From 10cc7db76bb3289079120206f021cbdd7841189e Mon Sep 17 00:00:00 2001 From: wanghongjun <1445693971@qq,com> Date: Tue, 24 Oct 2023 11:14:37 +0800 Subject: [PATCH] =?UTF-8?q?=E9=83=A8=E7=BD=B2=E5=88=B0git?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- framework/library/phpexcel/PHPExcel.php | 895 ++++++++++ .../library/phpexcel/PHPExcel/NamedRange.php | 246 +++ .../phpexcel/PHPExcel/ReferenceHelper.php | 918 ++++++++++ .../phpexcel/PHPExcel/Style/NumberFormat.php | 708 ++++++++ .../phpexcel/PHPExcel/Style/Protection.php | 207 +++ .../PHPExcel/Worksheet/PageMargins.php | 220 +++ .../phpexcel/PHPExcel/Worksheet/PageSetup.php | 798 +++++++++ .../PHPExcel/Worksheet/Protection.php | 545 ++++++ .../PHPExcel/Writer/Excel5/Parser.php | 1582 +++++++++++++++++ .../phpexcel/PHPExcel/Writer/OpenDocument.php | 190 ++ .../library/phpexcel/PHPExcel/Writer/PDF.php | 90 + web/common/permission.inc.php | 943 ++++++++++ .../kindeditor/plugins/code/prettify.css | 13 + .../kindeditor/plugins/code/prettify.js | 28 + .../plugins/image/images/refresh.png | Bin 0 -> 800 bytes .../plugins/multiimage/multiimage.js | 1384 ++++++++++++++ .../kindeditor/plugins/pagebreak/pagebreak.js | 27 + .../plugins/plainpaste/plainpaste.js | 41 + .../kindeditor/plugins/preview/preview.js | 31 + .../plugins/quickformat/quickformat.js | 81 + .../components/kindeditor/themes/qq/qq.css | 143 ++ .../components/tinymce/langs/readme.md | 3 + .../tinymce/plugins/advlist/plugin.min.js | 1 + .../tinymce/plugins/anchor/plugin.min.js | 1 + .../tinymce/plugins/autolink/plugin.min.js | 1 + .../tinymce/plugins/autoresize/plugin.min.js | 1 + .../tinymce/plugins/autosave/plugin.min.js | 1 + .../tinymce/plugins/bbcode/plugin.min.js | 1 + .../tinymce/plugins/charmap/plugin.min.js | 1 + .../tinymce/plugins/code/plugin.min.js | 1 + .../tinymce/plugins/contextmenu/plugin.min.js | 1 + .../plugins/directionality/plugin.min.js | 1 + .../tinymce/plugins/emoticons/plugin.min.js | 1 + .../tinymce/plugins/example/plugin.min.js | 1 + .../plugins/example_dependency/plugin.min.js | 1 + .../tinymce/plugins/fullpage/plugin.min.js | 1 + .../tinymce/plugins/fullscreen/plugin.min.js | 1 + .../tinymce/plugins/hr/plugin.min.js | 1 + .../tinymce/plugins/image/plugin.min.js | 48 + .../tinymce/plugins/importcss/plugin.min.js | 1 + .../plugins/insertdatetime/plugin.min.js | 1 + .../tinymce/plugins/layer/plugin.min.js | 1 + .../plugins/legacyoutput/plugin.min.js | 1 + .../tinymce/plugins/link/plugin.min.js | 1 + .../tinymce/plugins/lists/plugin.min.js | 1 + .../tinymce/plugins/media/plugin.min.js | 779 ++++++++ .../tinymce/plugins/multiimage/plugin.min.js | 38 + .../tinymce/plugins/nonbreaking/plugin.min.js | 1 + .../tinymce/plugins/noneditable/plugin.min.js | 1 + .../tinymce/plugins/pagebreak/plugin.min.js | 1 + .../tinymce/plugins/paste/plugin.min.js | 1 + .../tinymce/plugins/preview/plugin.min.js | 1 + .../tinymce/plugins/print/plugin.min.js | 1 + .../tinymce/plugins/save/plugin.min.js | 1 + .../plugins/searchreplace/plugin.min.js | 1 + .../plugins/spellchecker/plugin.min.js | 1 + .../tinymce/plugins/tabfocus/plugin.min.js | 1 + .../tinymce/plugins/table/plugin.min.js | 1 + .../tinymce/plugins/template/plugin.min.js | 1 + .../tinymce/plugins/textcolor/plugin.min.js | 1 + .../plugins/visualblocks/plugin.min.js | 1 + .../tinymce/plugins/visualchars/plugin.min.js | 1 + .../tinymce/plugins/wordcount/plugin.min.js | 1 + .../tinymce/skins/lightgray/fonts/readme.md | 1 + .../tinymce/skins/lightgray/img/object.gif | Bin 0 -> 152 bytes .../dialogs/attachment/images/progress.png | Bin 0 -> 1269 bytes .../emotion/images/neweditor-tab-bg.png | Bin 0 -> 216 bytes .../ueditor/dialogs/image/images/progress.png | Bin 0 -> 1269 bytes .../ueditor/dialogs/music/music.css | 1 + .../ueditor/dialogs/music/music.html | 32 + .../components/ueditor/dialogs/music/music.js | 192 ++ .../ueditor/dialogs/preview/preview.html | 40 + .../ueditor/dialogs/scrawl/images/redo.png | Bin 0 -> 454 bytes .../ueditor/dialogs/scrawl/images/redoH.png | Bin 0 -> 536 bytes .../ueditor/dialogs/template/images/pre0.png | Bin 0 -> 250 bytes .../ueditor/dialogs/template/images/pre1.png | Bin 0 -> 291 bytes .../ueditor/dialogs/template/images/pre2.png | Bin 0 -> 394 bytes .../ueditor/dialogs/template/images/pre3.png | Bin 0 -> 485 bytes .../ueditor/dialogs/template/images/pre4.png | Bin 0 -> 393 bytes .../dialogs/video/images/none_focus.jpg | Bin 0 -> 11546 bytes .../ueditor/dialogs/video/images/progress.png | Bin 0 -> 1269 bytes .../ueditor/lang/en/images/music.png | Bin 0 -> 91561 bytes .../ueditor/lang/zh-cn/images/music.png | Bin 0 -> 23106 bytes .../default/images/neweditor-tab-bg.png | Bin 0 -> 216 bytes .../themes/default/images/pagebreak.gif | Bin 0 -> 54 bytes .../highcharts/adapters/prototype-adapter.js | 15 + .../adapters/prototype-adapter.src.js | 316 ++++ .../highcharts/modules/no-data-to-display.js | 12 + .../modules/no-data-to-display.src.js | 128 ++ web/resource/components/webuploader/README.md | 26 + .../components/webuploader/progress.png | Bin 0 -> 1269 bytes web/resource/images/msg-tab-z25df2d.png | Bin 0 -> 1914 bytes web/resource/images/music-icon.png | Bin 0 -> 1386 bytes web/resource/images/noavatar_middle.gif | Bin 0 -> 3972 bytes web/resource/images/nopic-107.png | Bin 0 -> 1955 bytes web/resource/images/nopic-203.png | Bin 0 -> 11245 bytes web/resource/images/nopic-account.png | Bin 0 -> 290 bytes web/resource/images/nopic-module.png | Bin 0 -> 340 bytes web/resource/images/nopic-small.jpg | Bin 0 -> 9785 bytes web/resource/images/nopic-template.png | Bin 0 -> 142 bytes web/resource/images/nopic-user.png | Bin 0 -> 15456 bytes web/resource/images/nopic.jpg | Bin 0 -> 10262 bytes web/resource/images/nopic1.jpg | Bin 0 -> 11634 bytes web/resource/images/pen.png | Bin 0 -> 3408 bytes web/resource/images/player.jpg | Bin 0 -> 10990 bytes web/resource/images/radio-icon.png | Bin 0 -> 637 bytes web/resource/js/app/order.min.js | 1 + web/resource/js/lib/raty.min.js | 1 + web/source/account/post-user.ctrl.php | 532 ++++++ web/source/account/post.ctrl.php | 253 +++ web/source/system/optimize.ctrl.php | 79 + web/source/user/profile.ctrl.php | 450 +++++ web/themes/default/system/optimize.html | 49 + web/themes/default/user/post.html | 89 + web/themes/default/user/profile.html | 347 ++++ 115 files changed, 12560 insertions(+) create mode 100644 framework/library/phpexcel/PHPExcel.php create mode 100644 framework/library/phpexcel/PHPExcel/NamedRange.php create mode 100644 framework/library/phpexcel/PHPExcel/ReferenceHelper.php create mode 100644 framework/library/phpexcel/PHPExcel/Style/NumberFormat.php create mode 100644 framework/library/phpexcel/PHPExcel/Style/Protection.php create mode 100644 framework/library/phpexcel/PHPExcel/Worksheet/PageMargins.php create mode 100644 framework/library/phpexcel/PHPExcel/Worksheet/PageSetup.php create mode 100644 framework/library/phpexcel/PHPExcel/Worksheet/Protection.php create mode 100644 framework/library/phpexcel/PHPExcel/Writer/Excel5/Parser.php create mode 100644 framework/library/phpexcel/PHPExcel/Writer/OpenDocument.php create mode 100644 framework/library/phpexcel/PHPExcel/Writer/PDF.php create mode 100644 web/common/permission.inc.php create mode 100644 web/resource/components/kindeditor/plugins/code/prettify.css create mode 100644 web/resource/components/kindeditor/plugins/code/prettify.js create mode 100644 web/resource/components/kindeditor/plugins/image/images/refresh.png create mode 100644 web/resource/components/kindeditor/plugins/multiimage/multiimage.js create mode 100644 web/resource/components/kindeditor/plugins/pagebreak/pagebreak.js create mode 100644 web/resource/components/kindeditor/plugins/plainpaste/plainpaste.js create mode 100644 web/resource/components/kindeditor/plugins/preview/preview.js create mode 100644 web/resource/components/kindeditor/plugins/quickformat/quickformat.js create mode 100644 web/resource/components/kindeditor/themes/qq/qq.css create mode 100644 web/resource/components/tinymce/langs/readme.md create mode 100644 web/resource/components/tinymce/plugins/advlist/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/anchor/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/autolink/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/autoresize/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/autosave/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/bbcode/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/charmap/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/code/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/contextmenu/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/directionality/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/emoticons/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/example/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/example_dependency/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/fullpage/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/fullscreen/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/hr/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/image/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/importcss/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/insertdatetime/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/layer/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/legacyoutput/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/link/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/lists/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/media/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/multiimage/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/nonbreaking/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/noneditable/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/pagebreak/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/paste/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/preview/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/print/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/save/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/searchreplace/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/spellchecker/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/tabfocus/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/table/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/template/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/textcolor/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/visualblocks/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/visualchars/plugin.min.js create mode 100644 web/resource/components/tinymce/plugins/wordcount/plugin.min.js create mode 100644 web/resource/components/tinymce/skins/lightgray/fonts/readme.md create mode 100644 web/resource/components/tinymce/skins/lightgray/img/object.gif create mode 100644 web/resource/components/ueditor/dialogs/attachment/images/progress.png create mode 100644 web/resource/components/ueditor/dialogs/emotion/images/neweditor-tab-bg.png create mode 100644 web/resource/components/ueditor/dialogs/image/images/progress.png create mode 100644 web/resource/components/ueditor/dialogs/music/music.css create mode 100644 web/resource/components/ueditor/dialogs/music/music.html create mode 100644 web/resource/components/ueditor/dialogs/music/music.js create mode 100644 web/resource/components/ueditor/dialogs/preview/preview.html create mode 100644 web/resource/components/ueditor/dialogs/scrawl/images/redo.png create mode 100644 web/resource/components/ueditor/dialogs/scrawl/images/redoH.png create mode 100644 web/resource/components/ueditor/dialogs/template/images/pre0.png create mode 100644 web/resource/components/ueditor/dialogs/template/images/pre1.png create mode 100644 web/resource/components/ueditor/dialogs/template/images/pre2.png create mode 100644 web/resource/components/ueditor/dialogs/template/images/pre3.png create mode 100644 web/resource/components/ueditor/dialogs/template/images/pre4.png create mode 100644 web/resource/components/ueditor/dialogs/video/images/none_focus.jpg create mode 100644 web/resource/components/ueditor/dialogs/video/images/progress.png create mode 100644 web/resource/components/ueditor/lang/en/images/music.png create mode 100644 web/resource/components/ueditor/lang/zh-cn/images/music.png create mode 100644 web/resource/components/ueditor/themes/default/images/neweditor-tab-bg.png create mode 100644 web/resource/components/ueditor/themes/default/images/pagebreak.gif create mode 100644 web/resource/components/ueditor/third-party/highcharts/adapters/prototype-adapter.js create mode 100644 web/resource/components/ueditor/third-party/highcharts/adapters/prototype-adapter.src.js create mode 100644 web/resource/components/ueditor/third-party/highcharts/modules/no-data-to-display.js create mode 100644 web/resource/components/ueditor/third-party/highcharts/modules/no-data-to-display.src.js create mode 100644 web/resource/components/webuploader/README.md create mode 100644 web/resource/components/webuploader/progress.png create mode 100644 web/resource/images/msg-tab-z25df2d.png create mode 100644 web/resource/images/music-icon.png create mode 100644 web/resource/images/noavatar_middle.gif create mode 100644 web/resource/images/nopic-107.png create mode 100644 web/resource/images/nopic-203.png create mode 100644 web/resource/images/nopic-account.png create mode 100644 web/resource/images/nopic-module.png create mode 100644 web/resource/images/nopic-small.jpg create mode 100644 web/resource/images/nopic-template.png create mode 100644 web/resource/images/nopic-user.png create mode 100644 web/resource/images/nopic.jpg create mode 100644 web/resource/images/nopic1.jpg create mode 100644 web/resource/images/pen.png create mode 100644 web/resource/images/player.jpg create mode 100644 web/resource/images/radio-icon.png create mode 100644 web/resource/js/app/order.min.js create mode 100644 web/resource/js/lib/raty.min.js create mode 100644 web/source/account/post-user.ctrl.php create mode 100644 web/source/account/post.ctrl.php create mode 100644 web/source/system/optimize.ctrl.php create mode 100644 web/source/user/profile.ctrl.php create mode 100644 web/themes/default/system/optimize.html create mode 100644 web/themes/default/user/post.html create mode 100644 web/themes/default/user/profile.html diff --git a/framework/library/phpexcel/PHPExcel.php b/framework/library/phpexcel/PHPExcel.php new file mode 100644 index 0000000..abacb97 --- /dev/null +++ b/framework/library/phpexcel/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/framework/library/phpexcel/PHPExcel/NamedRange.php b/framework/library/phpexcel/PHPExcel/NamedRange.php new file mode 100644 index 0000000..9e7d41e --- /dev/null +++ b/framework/library/phpexcel/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/framework/library/phpexcel/PHPExcel/ReferenceHelper.php b/framework/library/phpexcel/PHPExcel/ReferenceHelper.php new file mode 100644 index 0000000..bf7771a --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/ReferenceHelper.php @@ -0,0 +1,918 @@ += ($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] = '/(? 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] = '/(? 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] = '/(? 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] = '/(? 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/framework/library/phpexcel/PHPExcel/Style/NumberFormat.php b/framework/library/phpexcel/PHPExcel/Style/NumberFormat.php new file mode 100644 index 0000000..a381f4f --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Style/NumberFormat.php @@ -0,0 +1,708 @@ +_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 + * + * + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getNumberFormat()->applyFromArray( + * array( + * 'code' => PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE + * ) + * ); + * + * + * @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: [$-] + // 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.'
'; + 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/framework/library/phpexcel/PHPExcel/Style/Protection.php b/framework/library/phpexcel/PHPExcel/Style/Protection.php new file mode 100644 index 0000000..a8f65ce --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Style/Protection.php @@ -0,0 +1,207 @@ +_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 + * + * + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getLocked()->applyFromArray( + * array( + * 'locked' => TRUE, + * 'hidden' => FALSE + * ) + * ); + * + * + * @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/framework/library/phpexcel/PHPExcel/Worksheet/PageMargins.php b/framework/library/phpexcel/PHPExcel/Worksheet/PageMargins.php new file mode 100644 index 0000000..339815d --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Worksheet/PageMargins.php @@ -0,0 +1,220 @@ +_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/framework/library/phpexcel/PHPExcel/Worksheet/PageSetup.php b/framework/library/phpexcel/PHPExcel/Worksheet/PageSetup.php new file mode 100644 index 0000000..1508eea --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Worksheet/PageSetup.php @@ -0,0 +1,798 @@ + + * 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) + * + * + * @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 all 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 all 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/framework/library/phpexcel/PHPExcel/Worksheet/Protection.php b/framework/library/phpexcel/PHPExcel/Worksheet/Protection.php new file mode 100644 index 0000000..e9d6bb6 --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Worksheet/Protection.php @@ -0,0 +1,545 @@ +_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/framework/library/phpexcel/PHPExcel/Writer/Excel5/Parser.php b/framework/library/phpexcel/PHPExcel/Writer/Excel5/Parser.php new file mode 100644 index 0000000..443fefc --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/Excel5/Parser.php @@ -0,0 +1,1582 @@ +=,;#()"{} + 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/framework/library/phpexcel/PHPExcel/Writer/OpenDocument.php b/framework/library/phpexcel/PHPExcel/Writer/OpenDocument.php new file mode 100644 index 0000000..912ba9d --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/OpenDocument.php @@ -0,0 +1,190 @@ +setPHPExcel($pPHPExcel); + + $writerPartsArray = array( + 'content' => 'PHPExcel_Writer_OpenDocument_Content', + 'meta' => 'PHPExcel_Writer_OpenDocument_Meta', + 'meta_inf' => 'PHPExcel_Writer_OpenDocument_MetaInf', + 'mimetype' => 'PHPExcel_Writer_OpenDocument_Mimetype', + 'settings' => 'PHPExcel_Writer_OpenDocument_Settings', + 'styles' => 'PHPExcel_Writer_OpenDocument_Styles', + 'thumbnails' => 'PHPExcel_Writer_OpenDocument_Thumbnails' + ); + + foreach ($writerPartsArray as $writer => $class) { + $this->writerParts[$writer] = new $class($this); + } + } + + /** + * 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) { + throw new PHPExcel_Writer_Exception('PHPExcel object unassigned.'); + } + + // 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; + } + } + + $objZip = $this->createZip($pFilename); + + $objZip->addFromString('META-INF/manifest.xml', $this->getWriterPart('meta_inf')->writeManifest()); + $objZip->addFromString('Thumbnails/thumbnail.png', $this->getWriterPart('thumbnails')->writeThumbnail()); + $objZip->addFromString('content.xml', $this->getWriterPart('content')->write()); + $objZip->addFromString('meta.xml', $this->getWriterPart('meta')->write()); + $objZip->addFromString('mimetype', $this->getWriterPart('mimetype')->write()); + $objZip->addFromString('settings.xml', $this->getWriterPart('settings')->write()); + $objZip->addFromString('styles.xml', $this->getWriterPart('styles')->write()); + + // 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); + } + } + + /** + * Create zip object + * + * @param string $pFilename + * @throws PHPExcel_Writer_Exception + * @return ZipArchive + */ + private function createZip($pFilename) + { + // 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."); + } + } + + return $objZip; + } + + /** + * 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; + } +} diff --git a/framework/library/phpexcel/PHPExcel/Writer/PDF.php b/framework/library/phpexcel/PHPExcel/Writer/PDF.php new file mode 100644 index 0000000..ed31195 --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/PDF.php @@ -0,0 +1,90 @@ +_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/web/common/permission.inc.php b/web/common/permission.inc.php new file mode 100644 index 0000000..7c77b29 --- /dev/null +++ b/web/common/permission.inc.php @@ -0,0 +1,943 @@ + + array ( + 'default' => '', + 'direct' => + array ( + 0 => 'auth', + 1 => 'welcome', + ), + 'vice_founder' => + array ( + 0 => 'account*', + ), + 'owner' => + array ( + 0 => 'account*', + ), + 'manager' => + array ( + 0 => 'common-info', + 1 => 'display', + 2 => 'manage', + 3 => 'post-step', + 4 => 'post-user', + 5 => 'post', + 6 => 'create', + ), + 'operator' => + array ( + 0 => 'common-info', + 1 => 'display', + 2 => 'manage', + 3 => 'post-step', + 4 => 'create', + ), + 'clerk' => + array ( + 0 => 'display', + ), + 'unbind_user' => + array ( + ), + ), + 'advertisement' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + ), + 'owner' => + array ( + ), + 'manager' => + array ( + ), + 'operator' => + array ( + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'article' => + array ( + 'default' => '', + 'direct' => + array ( + 0 => 'notice-show', + 1 => 'news-show', + ), + 'vice_founder' => + array ( + ), + 'owner' => + array ( + ), + 'manager' => + array ( + ), + 'operator' => + array ( + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'message' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'notice', + ), + 'owner' => + array ( + 0 => 'notice', + ), + 'manager' => + array ( + 0 => 'notice', + ), + 'operator' => + array ( + 0 => 'notice', + ), + 'clerk' => + array ( + 0 => 'notice', + ), + 'unbind_user' => + array ( + 0 => 'notice', + ), + ), + 'cloud' => + array ( + 'default' => 'touch', + 'direct' => + array ( + 0 => 'touch', + 1 => 'dock', + ), + 'vice_founder' => + array ( + ), + 'owner' => + array ( + ), + 'manager' => + array ( + ), + 'operator' => + array ( + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'cron' => + array ( + 'default' => '', + 'direct' => + array ( + 0 => 'entry', + ), + 'vice_founder' => + array ( + ), + 'owner' => + array ( + ), + 'manager' => + array ( + ), + 'operator' => + array ( + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'founder' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + ), + 'owner' => + array ( + ), + 'manager' => + array ( + ), + 'operator' => + array ( + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'help' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'help*', + ), + 'owner' => + array ( + 0 => 'help*', + ), + 'manager' => + array ( + 0 => 'help*', + ), + 'operator' => + array ( + 0 => 'help*', + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'home' => + array ( + 'default' => 'welcome', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'home*', + ), + 'owner' => + array ( + 0 => 'home*', + ), + 'manager' => + array ( + 0 => 'home*', + ), + 'operator' => + array ( + 0 => 'home*', + ), + 'clerk' => + array ( + 0 => 'welcome', + ), + 'unbind_user' => + array ( + ), + 'expired' => + array ( + 0 => 'welcome', + ), + ), + 'mc' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'mc*', + ), + 'owner' => + array ( + 0 => 'mc*', + ), + 'manager' => + array ( + 0 => 'chats', + 1 => 'fields', + 2 => 'group', + 3 => 'trade', + 4 => 'fans', + 5 => 'member', + 6 => 'message', + ), + 'operator' => + array ( + 0 => 'chats', + 1 => 'fields', + 2 => 'group', + 3 => 'trade', + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'module' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'module*', + ), + 'owner' => + array ( + 0 => 'manage-account', + 1 => 'manage-system', + 2 => 'permission', + 3 => 'display', + 4 => 'welcome', + 5 => 'link', + 6 => 'link-account', + 7 => 'shortcut', + 8 => 'plugin', + ), + 'manager' => + array ( + 0 => 'manage-account', + 1 => 'display', + 2 => 'welcome', + 3 => 'link', + 4 => 'link-account', + 5 => 'shortcut', + 6 => 'plugin', + ), + 'operator' => + array ( + 0 => 'manage-account', + 1 => 'display', + 2 => 'welcome', + 3 => 'link', + 4 => 'link-account', + 5 => 'shortcut', + 6 => 'plugin', + ), + 'clerk' => + array ( + 0 => 'display', + 1 => 'manage-account', + 2 => 'welcome', + 3 => 'link', + 4 => 'link-account', + 5 => 'shortcut', + 6 => 'plugin', + ), + 'unbind_user' => + array ( + ), + ), + 'platform' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'platform*', + ), + 'owner' => + array ( + 0 => 'platform*', + ), + 'manager' => + array ( + 0 => 'cover', + 1 => 'reply', + 2 => 'menu', + 3 => 'qr', + 4 => 'mass', + 5 => 'material', + 6 => 'material-post', + 7 => 'url2qr', + ), + 'operator' => + array ( + 0 => 'cover', + 1 => 'reply', + 2 => 'material', + 3 => 'material-post', + 4 => 'url2qr', + ), + 'clerk' => + array ( + 0 => 'reply', + 1 => 'cover', + 2 => 'material', + 3 => 'material-post', + ), + 'unbind_user' => + array ( + ), + ), + 'profile' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'profile*', + ), + 'owner' => + array ( + 0 => 'profile*', + ), + 'manager' => + array ( + 0 => 'remote', + 1 => 'passport', + 2 => 'tplnotice', + 3 => 'notify', + 4 => 'common', + 5 => 'payment', + 6 => 'refund', + 7 => 'module-link-uniacid', + 8 => 'bind-domain', + ), + 'operator' => + array ( + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + 0 => 'profile*', + ), + ), + 'site' => + array ( + 'default' => '', + 'direct' => + array ( + 0 => 'entry', + ), + 'vice_founder' => + array ( + 0 => 'site*', + ), + 'owner' => + array ( + 0 => 'site*', + ), + 'manager' => + array ( + 0 => 'editor', + 1 => 'article', + 2 => 'category', + 3 => 'style', + 4 => 'nav', + 5 => 'slide', + 6 => 'multi', + 7 => 'comment', + ), + 'operator' => + array ( + 0 => 'editor', + 1 => 'article', + 2 => 'category', + 3 => 'style', + 4 => 'nav', + 5 => 'slide', + ), + 'clerk' => + array ( + 0 => 'nav', + ), + 'unbind_user' => + array ( + ), + ), + 'statistics' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'statistics*', + ), + 'owner' => + array ( + 0 => 'statistics*', + ), + 'manager' => + array ( + 0 => 'app', + 1 => 'site', + 2 => 'setting', + 3 => 'fans', + ), + 'operator' => + array ( + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + ), + 'store' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'goods-buyer', + 1 => 'orders', + ), + 'owner' => + array ( + 0 => 'goods-buyer', + 1 => 'orders', + ), + 'manager' => + array ( + 0 => 'goods-buyer', + 1 => 'orders', + ), + 'operator' => + array ( + 0 => 'goods-buyer', + 1 => 'orders', + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + ), + 'expired' => + array ( + 0 => 'goods-buyer', + 1 => 'orders', + ), + ), + 'system' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'updatecache', + ), + 'owner' => + array ( + 0 => 'updatecache', + ), + 'manager' => + array ( + 0 => 'updatecache', + ), + 'operator' => + array ( + 0 => 'updatecache', + ), + 'clerk' => + array ( + 0 => 'updatecache', + ), + 'unbind_user' => + array ( + 0 => 'updatecache', + ), + 'expired' => + array ( + 0 => 'updatecache', + ), + ), + 'user' => + array ( + 'default' => 'display', + 'direct' => + array ( + 0 => 'login', + 1 => 'register', + 2 => 'logout', + 3 => 'find-password', + 4 => 'third-bind', + 5 => 'agreement-show', + ), + 'vice_founder' => + array ( + 0 => 'user*', + ), + 'owner' => + array ( + 0 => 'profile', + ), + 'manager' => + array ( + 0 => 'profile', + ), + 'operator' => + array ( + 0 => 'profile', + ), + 'clerk' => + array ( + 0 => 'profile', + ), + 'unbind_user' => + array ( + 0 => 'profile', + ), + 'expired' => + array ( + 0 => 'user*', + ), + ), + 'miniapp' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'miniapp*', + ), + 'owner' => + array ( + 0 => 'miniapp*', + ), + 'manager' => + array ( + 0 => 'display', + 1 => 'version', + 2 => 'post', + ), + 'operator' => + array ( + 0 => 'display', + 1 => 'version', + 2 => 'post', + ), + 'clerk' => + array ( + 0 => 'display', + 1 => 'version', + 2 => 'post', + ), + 'unbind_user' => + array ( + ), + ), + 'wxapp' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'wxapp*', + ), + 'owner' => + array ( + 0 => 'wxapp*', + ), + 'manager' => + array ( + 0 => 'display', + 1 => 'version', + 2 => 'post', + 3 => 'auth', + 4 => 'manage', + ), + 'operator' => + array ( + 0 => 'display', + 1 => 'version', + 2 => 'post', + 3 => 'auth', + ), + 'clerk' => + array ( + 0 => 'display', + ), + 'unbind_user' => + array ( + ), + ), + 'webapp' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'webapp*', + ), + 'owner' => + array ( + 0 => 'webapp*', + ), + 'manager' => + array ( + 0 => 'home', + 1 => 'manage', + ), + 'operator' => + array ( + 0 => 'home', + 1 => 'manage', + ), + 'clerk' => + array ( + 0 => 'home', + ), + 'unbind_user' => + array ( + ), + ), + 'phoneapp' => + array ( + 'default' => '', + 'direct' => + array ( + ), + 'vice_founder' => + array ( + 0 => 'phoneapp*', + ), + 'owner' => + array ( + 0 => 'phoneapp*', + ), + 'manager' => + array ( + 0 => 'display', + 1 => 'manage', + 2 => 'version', + ), + 'operator' => + array ( + 0 => 'display', + 1 => 'manage', + 2 => 'version', + ), + 'clerk' => + array ( + 0 => 'display', + ), + ), + 'utility' => + array ( + 'default' => '', + 'direct' => + array ( + 0 => 'verifycode', + 1 => 'code', + 2 => 'bindcall', + 3 => 'subscribe', + 4 => 'wxcode', + 5 => 'modules', + 6 => 'link', + 7 => 'visit', + 8 => 'file', + ), + 'vice_founder' => + array ( + 0 => 'user', + 1 => 'emulator', + 2 => 'file', + ), + 'owner' => + array ( + 0 => 'emulator', + 1 => 'file', + ), + 'manager' => + array ( + 0 => 'emulator', + 1 => 'file', + ), + 'operator' => + array ( + 0 => 'emulator', + 1 => 'file', + ), + 'clerk' => + array ( + 0 => 'emulator', + 1 => 'file', + ), + 'unbind_user' => + array ( + ), + ), + 'append' => + array ( + 0 => 'append*', + ), + 'see_more_info' => + array ( + 'founder' => + array ( + 0 => 'see_module_manage_system_except_installed', + 1 => 'see_module_manage_system_ugrade', + 2 => 'see_module_manage_system_stop', + 3 => 'see_module_manage_system_install', + 4 => 'see_module_manage_system_shopinfo', + 5 => 'see_module_manage_system_info_edit', + 6 => 'see_module_manage_system_detailinfo', + 7 => 'see_module_manage_system_group_add', + 8 => 'see_module_manage_system_welcome_support', + 9 => 'see_account_post_modules_tpl_edit_store_endtime', + 10 => 'see_account_manage_module_tpl_all_permission', + 11 => 'see_account_manage_sms_blance', + 12 => 'see_account_manage_users_edit_vicefounder', + 13 => 'see_account_manage_users_edit_owner', + 14 => 'see_account_manage_users_set_permission_for_manager', + 15 => 'see_account_manage_users_set_permission_for_operator', + 16 => 'see_account_manage_users_addmanager', + 17 => 'see_account_manage_users_delmanager', + 18 => 'see_account_manage_users_deloperator', + 19 => 'see_account_manage_users_adduser', + 20 => 'see_account_manage_users_add_viceuser', + 21 => 'see_account_manage_display', + 22 => 'see_account_manage_recycle', + 23 => 'see_account_manage_system_platform', + 24 => 'see_account_manage_expired_message', + 25 => 'see_permission_create_account_group', + 26 => 'see_permission_module_group', + 27 => 'see_permission_user_group', + 28 => 'see_permission_founder_group', + 29 => 'see_system_upgrade', + 30 => 'see_system_manage_clerk', + 31 => 'see_system_manage_vice_founder', + 32 => 'see_system_add_vice_founder', + 33 => 'see_notice_post', + 34 => 'see_message_official', + 35 => 'see_message_order', + 36 => 'see_message_register', + 37 => 'see_message_worker', + 38 => 'see_module_manage_system_newversion', + 39 => 'see_user_add_welcome_account', + 40 => 'see_user_edit_base_founder_name', + 41 => 'see_user_create_own_vice_founder', + 42 => 'see_user_profile_account_num', + 43 => 'see_user_profile_edit_username', + 44 => 'see_user_manage_display', + 45 => 'see_user_manage_founder', + 46 => 'see_user_manage_clerk', + 47 => 'see_user_manage_check', + 48 => 'see_user_manage_recycle', + 49 => 'see_user_manage_fields', + 50 => 'see_user_manage_expire', + 51 => 'see_workorder', + 52 => 'see_controller', + 53 => 'see_modules_deactivate', + ), + 'vice_founder' => + array ( + 0 => 'see_account_manage_users_adduser', + 1 => 'see_account_manage_users_edit_owner', + 2 => 'see_account_manage_users_set_permission_for_manager', + 3 => 'see_account_manage_users_set_permission_for_operator', + 4 => 'see_account_manage_users_deloperator', + 5 => 'see_account_manage_users_delmanager', + 6 => 'see_account_manage_display', + 7 => 'see_account_manage_recycle', + 8 => 'see_module_manage_system_group_add', + 9 => 'see_permission_create_account_group', + 10 => 'see_permission_module_group', + 11 => 'see_permission_user_group', + 12 => 'see_user_add_welcome_account', + 13 => 'see_user_profile_account_num', + 14 => 'see_user_manage_display', + 15 => 'see_user_manage_check', + 16 => 'see_user_manage_recycle', + 17 => 'see_controller', + ), + 'owner' => + array ( + 0 => 'see_account_manage_users_set_permission_for_manager', + 1 => 'see_account_manage_users_set_permission_for_operator', + 2 => 'see_account_manage_users_deloperator', + 3 => 'see_account_manage_users_delmanager', + 4 => 'see_account_manage_display', + 5 => 'see_account_manage_recycle', + 6 => 'see_modules_recharge', + 7 => 'see_user_add_welcome_account', + 8 => 'see_user_profile_account_num', + ), + 'manager' => + array ( + 0 => 'see_account_manage_users_set_permission_for_operator', + 1 => 'see_account_manage_users_deloperator', + 2 => 'see_account_manage_display', + 3 => 'see_user_profile_welcome', + 4 => 'see_user_add_welcome_account', + 5 => 'see_user_profile_account_num', + ), + 'operator' => + array ( + 0 => 'see_account_manage_display', + 1 => 'see_user_profile_welcome', + 2 => 'see_user_add_welcome_account', + 3 => 'see_user_profile_account_num', + ), + 'clerk' => + array ( + ), + 'unbind_user' => + array ( + 0 => 'see_user_profile_welcome', + ), + 'expired' => + array ( + ), + ), +); +return $we7_file_permission; \ No newline at end of file diff --git a/web/resource/components/kindeditor/plugins/code/prettify.css b/web/resource/components/kindeditor/plugins/code/prettify.css new file mode 100644 index 0000000..b8287e5 --- /dev/null +++ b/web/resource/components/kindeditor/plugins/code/prettify.css @@ -0,0 +1,13 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} + +pre.prettyprint { + border: 0; + border-left: 3px solid rgb(204, 204, 204); + margin-left: 2em; + padding: 0.5em; + font-size: 110%; + display: block; + font-family: "Consolas", "Monaco", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace; + margin: 1em 0px; + white-space: pre; +} diff --git a/web/resource/components/kindeditor/plugins/code/prettify.js b/web/resource/components/kindeditor/plugins/code/prettify.js new file mode 100644 index 0000000..eef5ad7 --- /dev/null +++ b/web/resource/components/kindeditor/plugins/code/prettify.js @@ -0,0 +1,28 @@ +var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= +[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), +l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, +q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, +"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), +a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} +for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], +H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ +I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), +["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", +/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), +["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", +hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= +!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p;XHLv^X{MWe`Tlinj{a@#N-#PzxnA+M}IA}100Yb>4X_(gy!}zoRE}P9-Gcn=d zkLP%hWjQ4)@@JM~+i8G(XAfenZNtG5HYNzd8%dOYyWMWnOnF3+72tRd!jUi}2NK|K@I&8)OF&qx6p4}p zNk|SR-ebsy13*!0YHDW7YT0sZYHEb3naQ_!H+||v`?BIuOy6N2+`4@WqS457TO^h) zm&>rVwN(K?sZ?EUrDdq93cY>3t8LL(cd1me(hdXzFq59yt*$=OA8Cm$X{rYHyV)7A z#X?cQ`YiyT&v&O(EP<};pb-roKY8>C?|NIBLs@#ZUja+Twe?j%i2xe~G);pCbMras zNLeT#2A>Qz9?$BUE+N?{W;%*H`IOjtzBJ zbcqY1Brc%;m;*rB&UK$%qceTbLcVYjRapQA4pnLuP|^uxzK1(Rn)UJR(iAxgof;y1uelRaG_g>g8*| zAi&Pe?eA0t^n1W zX4Kl&3PZywBhVa}N1wF+SVMXH*LDTK>)l&an7)3`#Be)-7DtoN3TR7cbNHakwn95Q eJ67C30R{j{$`Q#a2a=)y0000 +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + + +(function(K) { + +function KSWFUpload(options) { + this.init(options); +} +K.extend(KSWFUpload, { + init : function(options) { + var self = this; + options.afterError = options.afterError || function(str) { + alert(str); + }; + self.options = options; + self.progressbars = {}; + // template + self.div = K(options.container).html([ + '
', + '
', + '
', + '', + '
', + '
' + options.uploadDesc + '
', + '', + '', + '', + '
', + '
', + '
' + ].join('')); + self.bodyDiv = K('.ke-swfupload-body', self.div); + + function showError(itemDiv, msg) { + K('.ke-status > div', itemDiv).hide(); + K('.ke-message', itemDiv).addClass('ke-error').show().html(K.escape(msg)); + } + + var settings = { + debug : false, + upload_url : options.uploadUrl, + flash_url : options.flashUrl, + file_post_name : options.filePostName, + button_placeholder : K('.ke-swfupload-button > input', self.div)[0], + button_image_url: options.buttonImageUrl, + button_width: options.buttonWidth, + button_height: options.buttonHeight, + button_cursor : SWFUpload.CURSOR.HAND, + file_types : options.fileTypes, + file_types_description : options.fileTypesDesc, + file_upload_limit : options.fileUploadLimit, + file_size_limit : options.fileSizeLimit, + post_params : options.postParams, + file_queued_handler : function(file) { + file.url = self.options.fileIconUrl; + self.appendFile(file); + }, + file_queue_error_handler : function(file, errorCode, message) { + var errorName = ''; + switch (errorCode) { + case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED: + errorName = options.queueLimitExceeded; + break; + case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT: + errorName = options.fileExceedsSizeLimit; + break; + case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE: + errorName = options.zeroByteFile; + break; + case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE: + errorName = options.invalidFiletype; + break; + default: + errorName = options.unknownError; + break; + } + K.DEBUG && alert(errorName); + }, + upload_start_handler : function(file) { + var self = this; + var itemDiv = K('div[data-id="' + file.id + '"]', self.bodyDiv); + K('.ke-status > div', itemDiv).hide(); + K('.ke-progressbar', itemDiv).show(); + }, + upload_progress_handler : function(file, bytesLoaded, bytesTotal) { + var percent = Math.round(bytesLoaded * 100 / bytesTotal); + var progressbar = self.progressbars[file.id]; + progressbar.bar.css('width', Math.round(percent * 80 / 100) + 'px'); + progressbar.percent.html(percent + '%'); + }, + upload_error_handler : function(file, errorCode, message) { + if (file && file.filestatus == SWFUpload.FILE_STATUS.ERROR) { + var itemDiv = K('div[data-id="' + file.id + '"]', self.bodyDiv).eq(0); + showError(itemDiv, self.options.errorMessage); + } + }, + upload_success_handler : function(file, serverData) { + var itemDiv = K('div[data-id="' + file.id + '"]', self.bodyDiv).eq(0); + var data = {}; + try { + data = K.json(serverData); + } catch (e) { + self.options.afterError.call(this, '' + serverData + ''); + } + if (data.error !== 0) { + showError(itemDiv, K.DEBUG ? data.message : self.options.errorMessage); + return; + } + file.url = data.url; + K('.ke-img', itemDiv).attr('src', file.url).attr('data-status', file.filestatus).data('data', data); + K('.ke-status > div', itemDiv).hide(); + } + }; + self.swfu = new SWFUpload(settings); + + K('.ke-swfupload-startupload input', self.div).click(function() { + self.swfu.startUpload(); + }); + }, + getUrlList : function() { + var list = []; + K('.ke-img', self.bodyDiv).each(function() { + var img = K(this); + var status = img.attr('data-status'); + if (status == SWFUpload.FILE_STATUS.COMPLETE) { + list.push(img.data('data')); + } + }); + return list; + }, + removeFile : function(fileId) { + var self = this; + self.swfu.cancelUpload(fileId); + var itemDiv = K('div[data-id="' + fileId + '"]', self.bodyDiv); + K('.ke-photo', itemDiv).unbind(); + K('.ke-delete', itemDiv).unbind(); + itemDiv.remove(); + }, + removeFiles : function() { + var self = this; + K('.ke-item', self.bodyDiv).each(function() { + self.removeFile(K(this).attr('data-id')); + }); + }, + appendFile : function(file) { + var self = this; + var itemDiv = K('
'); + self.bodyDiv.append(itemDiv); + var photoDiv = K('
') + .mouseover(function(e) { + K(this).addClass('ke-on'); + }) + .mouseout(function(e) { + K(this).removeClass('ke-on'); + }); + itemDiv.append(photoDiv); + + var img = K('' + file.name + ''); + photoDiv.append(img); + K('').appendTo(photoDiv).click(function() { + self.removeFile(file.id); + }); + var statusDiv = K('
').appendTo(photoDiv); + // progressbar + K(['
', + '
', + '
0%
'].join('')).hide().appendTo(statusDiv); + // message + K('
' + self.options.pendingMessage + '
').appendTo(statusDiv); + + itemDiv.append('
' + file.name + '
'); + + self.progressbars[file.id] = { + bar : K('.ke-progressbar-bar-inner', photoDiv), + percent : K('.ke-progressbar-percent', photoDiv) + }; + }, + remove : function() { + this.removeFiles(); + this.swfu.destroy(); + this.div.html(''); + } +}); + +K.swfupload = function(element, options) { + return new KSWFUpload(element, options); +}; + +})(KindEditor); + +KindEditor.plugin('multiimage', function(K) { + var self = this, name = 'multiimage', + formatUploadUrl = K.undef(self.formatUploadUrl, true), + uploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'), + imgPath = self.pluginsPath + 'multiimage/images/', + imageSizeLimit = K.undef(self.imageSizeLimit, '1MB'), + imageFileTypes = K.undef(self.imageFileTypes, '*.jpg;*.gif;*.png'), + imageUploadLimit = K.undef(self.imageUploadLimit, 20), + filePostName = K.undef(self.filePostName, 'imgFile'), + lang = self.lang(name + '.'); + + self.plugin.multiImageDialog = function(options) { + var clickFn = options.clickFn, + uploadDesc = K.tmpl(lang.uploadDesc, {uploadLimit : imageUploadLimit, sizeLimit : imageSizeLimit}); + var html = [ + '
', + '
', + '
', + '
' + ].join(''); + var dialog = self.createDialog({ + name : name, + width : 650, + height : 510, + title : self.lang(name), + body : html, + previewBtn : { + name : lang.insertAll, + click : function(e) { + clickFn.call(self, swfupload.getUrlList()); + } + }, + yesBtn : { + name : lang.clearAll, + click : function(e) { + swfupload.removeFiles(); + } + }, + beforeRemove : function() { + // IE9 bugfix: https://github.com/kindsoft/kindeditor/issues/72 + if (!K.IE || K.V <= 8) { + swfupload.remove(); + } + } + }), + div = dialog.div; + + var swfupload = K.swfupload({ + container : K('.swfupload', div), + buttonImageUrl : imgPath + (self.langType == 'zh_CN' ? 'select-files-zh_CN.png' : 'select-files-en.png'), + buttonWidth : self.langType == 'zh_CN' ? 72 : 88, + buttonHeight : 23, + fileIconUrl : imgPath + 'image.png', + uploadDesc : uploadDesc, + startButtonValue : lang.startUpload, + uploadUrl : K.addParam(uploadJson, 'dir=image'), + flashUrl : imgPath + 'swfupload.swf', + filePostName : filePostName, + fileTypes : '*.jpg;*.jpeg;*.gif;*.png;*.bmp', + fileTypesDesc : 'Image Files', + fileUploadLimit : imageUploadLimit, + fileSizeLimit : imageSizeLimit, + postParams : K.undef(self.extraFileUploadParams, {}), + queueLimitExceeded : lang.queueLimitExceeded, + fileExceedsSizeLimit : lang.fileExceedsSizeLimit, + zeroByteFile : lang.zeroByteFile, + invalidFiletype : lang.invalidFiletype, + unknownError : lang.unknownError, + pendingMessage : lang.pending, + errorMessage : lang.uploadError, + afterError : function(html) { + self.errorDialog(html); + } + }); + + return dialog; + }; + self.clickToolbar(name, function() { + self.plugin.multiImageDialog({ + clickFn : function (urlList) { + if (urlList.length === 0) { + return; + } + K.each(urlList, function(i, data) { + if (self.afterUpload) { + self.afterUpload.call(self, data.url, data, 'multiimage'); + } + self.exec('insertimage', data.url, data.title, data.width, data.height, data.border, data.align); + }); + // Bugfix: [Firefox] 上传图片后,总是出现正在加载的样式,需要延迟执行hideDialog + setTimeout(function() { + self.hideDialog().focus(); + }, 0); + } + }); + }); +}); + + +/** + * SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com + * + * mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/, http://www.vinterwebb.se/ + * + * SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilz閚 and Mammon Media and is released under the MIT License: + * http://www.opensource.org/licenses/mit-license.php + * + * SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License: + * http://www.opensource.org/licenses/mit-license.php + * + */ + + +/* ******************* */ +/* Constructor & Init */ +/* ******************* */ + +(function() { + +window.SWFUpload = function (settings) { + this.initSWFUpload(settings); +}; + +SWFUpload.prototype.initSWFUpload = function (settings) { + try { + this.customSettings = {}; // A container where developers can place their own settings associated with this instance. + this.settings = settings; + this.eventQueue = []; + this.movieName = "KindEditor_SWFUpload_" + SWFUpload.movieCount++; + this.movieElement = null; + + + // Setup global control tracking + SWFUpload.instances[this.movieName] = this; + + // Load the settings. Load the Flash movie. + this.initSettings(); + this.loadFlash(); + this.displayDebugInfo(); + } catch (ex) { + delete SWFUpload.instances[this.movieName]; + throw ex; + } +}; + +/* *************** */ +/* Static Members */ +/* *************** */ +SWFUpload.instances = {}; +SWFUpload.movieCount = 0; +SWFUpload.version = "2.2.0 2009-03-25"; +SWFUpload.QUEUE_ERROR = { + QUEUE_LIMIT_EXCEEDED : -100, + FILE_EXCEEDS_SIZE_LIMIT : -110, + ZERO_BYTE_FILE : -120, + INVALID_FILETYPE : -130 +}; +SWFUpload.UPLOAD_ERROR = { + HTTP_ERROR : -200, + MISSING_UPLOAD_URL : -210, + IO_ERROR : -220, + SECURITY_ERROR : -230, + UPLOAD_LIMIT_EXCEEDED : -240, + UPLOAD_FAILED : -250, + SPECIFIED_FILE_ID_NOT_FOUND : -260, + FILE_VALIDATION_FAILED : -270, + FILE_CANCELLED : -280, + UPLOAD_STOPPED : -290 +}; +SWFUpload.FILE_STATUS = { + QUEUED : -1, + IN_PROGRESS : -2, + ERROR : -3, + COMPLETE : -4, + CANCELLED : -5 +}; +SWFUpload.BUTTON_ACTION = { + SELECT_FILE : -100, + SELECT_FILES : -110, + START_UPLOAD : -120 +}; +SWFUpload.CURSOR = { + ARROW : -1, + HAND : -2 +}; +SWFUpload.WINDOW_MODE = { + WINDOW : "window", + TRANSPARENT : "transparent", + OPAQUE : "opaque" +}; + +// Private: takes a URL, determines if it is relative and converts to an absolute URL +// using the current site. Only processes the URL if it can, otherwise returns the URL untouched +SWFUpload.completeURL = function(url) { + if (typeof(url) !== "string" || url.match(/^https?:\/\//i) || url.match(/^\//)) { + return url; + } + + var currentURL = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port : ""); + + var indexSlash = window.location.pathname.lastIndexOf("/"); + if (indexSlash <= 0) { + path = "/"; + } else { + path = window.location.pathname.substr(0, indexSlash) + "/"; + } + + return /*currentURL +*/ path + url; + +}; + + +/* ******************** */ +/* Instance Members */ +/* ******************** */ + +// Private: initSettings ensures that all the +// settings are set, getting a default value if one was not assigned. +SWFUpload.prototype.initSettings = function () { + this.ensureDefault = function (settingName, defaultValue) { + this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName]; + }; + + // Upload backend settings + this.ensureDefault("upload_url", ""); + this.ensureDefault("preserve_relative_urls", false); + this.ensureDefault("file_post_name", "Filedata"); + this.ensureDefault("post_params", {}); + this.ensureDefault("use_query_string", false); + this.ensureDefault("requeue_on_error", false); + this.ensureDefault("http_success", []); + this.ensureDefault("assume_success_timeout", 0); + + // File Settings + this.ensureDefault("file_types", "*.*"); + this.ensureDefault("file_types_description", "All Files"); + this.ensureDefault("file_size_limit", 0); // Default zero means "unlimited" + this.ensureDefault("file_upload_limit", 0); + this.ensureDefault("file_queue_limit", 0); + + // Flash Settings + this.ensureDefault("flash_url", "swfupload.swf"); + this.ensureDefault("prevent_swf_caching", true); + + // Button Settings + this.ensureDefault("button_image_url", ""); + this.ensureDefault("button_width", 1); + this.ensureDefault("button_height", 1); + this.ensureDefault("button_text", ""); + this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;"); + this.ensureDefault("button_text_top_padding", 0); + this.ensureDefault("button_text_left_padding", 0); + this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES); + this.ensureDefault("button_disabled", false); + this.ensureDefault("button_placeholder_id", ""); + this.ensureDefault("button_placeholder", null); + this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW); + this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW); + + // Debug Settings + this.ensureDefault("debug", false); + this.settings.debug_enabled = this.settings.debug; // Here to maintain v2 API + + // Event Handlers + this.settings.return_upload_start_handler = this.returnUploadStart; + this.ensureDefault("swfupload_loaded_handler", null); + this.ensureDefault("file_dialog_start_handler", null); + this.ensureDefault("file_queued_handler", null); + this.ensureDefault("file_queue_error_handler", null); + this.ensureDefault("file_dialog_complete_handler", null); + + this.ensureDefault("upload_start_handler", null); + this.ensureDefault("upload_progress_handler", null); + this.ensureDefault("upload_error_handler", null); + this.ensureDefault("upload_success_handler", null); + this.ensureDefault("upload_complete_handler", null); + + this.ensureDefault("debug_handler", this.debugMessage); + + this.ensureDefault("custom_settings", {}); + + // Other settings + this.customSettings = this.settings.custom_settings; + + // Update the flash url if needed + if (!!this.settings.prevent_swf_caching) { + this.settings.flash_url = this.settings.flash_url + (this.settings.flash_url.indexOf("?") < 0 ? "?" : "&") + "preventswfcaching=" + new Date().getTime(); + } + + if (!this.settings.preserve_relative_urls) { + //this.settings.flash_url = SWFUpload.completeURL(this.settings.flash_url); // Don't need to do this one since flash doesn't look at it + this.settings.upload_url = SWFUpload.completeURL(this.settings.upload_url); + this.settings.button_image_url = SWFUpload.completeURL(this.settings.button_image_url); + } + + delete this.ensureDefault; +}; + +// Private: loadFlash replaces the button_placeholder element with the flash movie. +SWFUpload.prototype.loadFlash = function () { + var targetElement, tempParent; + + // Make sure an element with the ID we are going to use doesn't already exist + if (document.getElementById(this.movieName) !== null) { + throw "ID " + this.movieName + " is already in use. The Flash Object could not be added"; + } + + // Get the element where we will be placing the flash movie + targetElement = document.getElementById(this.settings.button_placeholder_id) || this.settings.button_placeholder; + + if (targetElement == undefined) { + throw "Could not find the placeholder element: " + this.settings.button_placeholder_id; + } + + // Append the container and load the flash + tempParent = document.createElement("div"); + tempParent.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers) + targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement); + + // Fix IE Flash/Form bug + if (window[this.movieName] == undefined) { + window[this.movieName] = this.getMovieElement(); + } + +}; + +// Private: getFlashHTML generates the object tag needed to embed the flash in to the document +SWFUpload.prototype.getFlashHTML = function () { + // Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay + // Fix bug for IE9 + // http://www.kindsoft.net/view.php?bbsid=7&postid=5825&pagenum=1 + var classid = ''; + if (KindEditor.IE && KindEditor.V > 8) { + classid = ' classid = "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"'; + } + return ['', + '', + '', + '', + '', + '', + '', + ''].join(""); +}; + +// Private: getFlashVars builds the parameter string that will be passed +// to flash in the flashvars param. +SWFUpload.prototype.getFlashVars = function () { + // Build a string from the post param object + var paramString = this.buildParamString(); + var httpSuccessString = this.settings.http_success.join(","); + + // Build the parameter string + return ["movieName=", encodeURIComponent(this.movieName), + "&uploadURL=", encodeURIComponent(this.settings.upload_url), + "&useQueryString=", encodeURIComponent(this.settings.use_query_string), + "&requeueOnError=", encodeURIComponent(this.settings.requeue_on_error), + "&httpSuccess=", encodeURIComponent(httpSuccessString), + "&assumeSuccessTimeout=", encodeURIComponent(this.settings.assume_success_timeout), + "&params=", encodeURIComponent(paramString), + "&filePostName=", encodeURIComponent(this.settings.file_post_name), + "&fileTypes=", encodeURIComponent(this.settings.file_types), + "&fileTypesDescription=", encodeURIComponent(this.settings.file_types_description), + "&fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit), + "&fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit), + "&fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit), + "&debugEnabled=", encodeURIComponent(this.settings.debug_enabled), + "&buttonImageURL=", encodeURIComponent(this.settings.button_image_url), + "&buttonWidth=", encodeURIComponent(this.settings.button_width), + "&buttonHeight=", encodeURIComponent(this.settings.button_height), + "&buttonText=", encodeURIComponent(this.settings.button_text), + "&buttonTextTopPadding=", encodeURIComponent(this.settings.button_text_top_padding), + "&buttonTextLeftPadding=", encodeURIComponent(this.settings.button_text_left_padding), + "&buttonTextStyle=", encodeURIComponent(this.settings.button_text_style), + "&buttonAction=", encodeURIComponent(this.settings.button_action), + "&buttonDisabled=", encodeURIComponent(this.settings.button_disabled), + "&buttonCursor=", encodeURIComponent(this.settings.button_cursor) + ].join(""); +}; + +// Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload +// The element is cached after the first lookup +SWFUpload.prototype.getMovieElement = function () { + if (this.movieElement == undefined) { + this.movieElement = document.getElementById(this.movieName); + } + + if (this.movieElement === null) { + throw "Could not find Flash element"; + } + + return this.movieElement; +}; + +// Private: buildParamString takes the name/value pairs in the post_params setting object +// and joins them up in to a string formatted "name=value&name=value" +SWFUpload.prototype.buildParamString = function () { + var postParams = this.settings.post_params; + var paramStringPairs = []; + + if (typeof(postParams) === "object") { + for (var name in postParams) { + if (postParams.hasOwnProperty(name)) { + paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString())); + } + } + } + + return paramStringPairs.join("&"); +}; + +// Public: Used to remove a SWFUpload instance from the page. This method strives to remove +// all references to the SWF, and other objects so memory is properly freed. +// Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state. +// Credits: Major improvements provided by steffen +SWFUpload.prototype.destroy = function () { + try { + // Make sure Flash is done before we try to remove it + this.cancelUpload(null, false); + + + // Remove the SWFUpload DOM nodes + var movieElement = null; + movieElement = this.getMovieElement(); + + if (movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE + // Loop through all the movie's properties and remove all function references (DOM/JS IE 6/7 memory leak workaround) + for (var i in movieElement) { + try { + if (typeof(movieElement[i]) === "function") { + movieElement[i] = null; + } + } catch (ex1) {} + } + + // Remove the Movie Element from the page + try { + movieElement.parentNode.removeChild(movieElement); + } catch (ex) {} + } + + // Remove IE form fix reference + window[this.movieName] = null; + + // Destroy other references + SWFUpload.instances[this.movieName] = null; + delete SWFUpload.instances[this.movieName]; + + this.movieElement = null; + this.settings = null; + this.customSettings = null; + this.eventQueue = null; + this.movieName = null; + + + return true; + } catch (ex2) { + return false; + } +}; + + +// Public: displayDebugInfo prints out settings and configuration +// information about this SWFUpload instance. +// This function (and any references to it) can be deleted when placing +// SWFUpload in production. +SWFUpload.prototype.displayDebugInfo = function () { + this.debug( + [ + "---SWFUpload Instance Info---\n", + "Version: ", SWFUpload.version, "\n", + "Movie Name: ", this.movieName, "\n", + "Settings:\n", + "\t", "upload_url: ", this.settings.upload_url, "\n", + "\t", "flash_url: ", this.settings.flash_url, "\n", + "\t", "use_query_string: ", this.settings.use_query_string.toString(), "\n", + "\t", "requeue_on_error: ", this.settings.requeue_on_error.toString(), "\n", + "\t", "http_success: ", this.settings.http_success.join(", "), "\n", + "\t", "assume_success_timeout: ", this.settings.assume_success_timeout, "\n", + "\t", "file_post_name: ", this.settings.file_post_name, "\n", + "\t", "post_params: ", this.settings.post_params.toString(), "\n", + "\t", "file_types: ", this.settings.file_types, "\n", + "\t", "file_types_description: ", this.settings.file_types_description, "\n", + "\t", "file_size_limit: ", this.settings.file_size_limit, "\n", + "\t", "file_upload_limit: ", this.settings.file_upload_limit, "\n", + "\t", "file_queue_limit: ", this.settings.file_queue_limit, "\n", + "\t", "debug: ", this.settings.debug.toString(), "\n", + + "\t", "prevent_swf_caching: ", this.settings.prevent_swf_caching.toString(), "\n", + + "\t", "button_placeholder_id: ", this.settings.button_placeholder_id.toString(), "\n", + "\t", "button_placeholder: ", (this.settings.button_placeholder ? "Set" : "Not Set"), "\n", + "\t", "button_image_url: ", this.settings.button_image_url.toString(), "\n", + "\t", "button_width: ", this.settings.button_width.toString(), "\n", + "\t", "button_height: ", this.settings.button_height.toString(), "\n", + "\t", "button_text: ", this.settings.button_text.toString(), "\n", + "\t", "button_text_style: ", this.settings.button_text_style.toString(), "\n", + "\t", "button_text_top_padding: ", this.settings.button_text_top_padding.toString(), "\n", + "\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n", + "\t", "button_action: ", this.settings.button_action.toString(), "\n", + "\t", "button_disabled: ", this.settings.button_disabled.toString(), "\n", + + "\t", "custom_settings: ", this.settings.custom_settings.toString(), "\n", + "Event Handlers:\n", + "\t", "swfupload_loaded_handler assigned: ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n", + "\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n", + "\t", "file_queued_handler assigned: ", (typeof this.settings.file_queued_handler === "function").toString(), "\n", + "\t", "file_queue_error_handler assigned: ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n", + "\t", "upload_start_handler assigned: ", (typeof this.settings.upload_start_handler === "function").toString(), "\n", + "\t", "upload_progress_handler assigned: ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n", + "\t", "upload_error_handler assigned: ", (typeof this.settings.upload_error_handler === "function").toString(), "\n", + "\t", "upload_success_handler assigned: ", (typeof this.settings.upload_success_handler === "function").toString(), "\n", + "\t", "upload_complete_handler assigned: ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n", + "\t", "debug_handler assigned: ", (typeof this.settings.debug_handler === "function").toString(), "\n" + ].join("") + ); +}; + +/* Note: addSetting and getSetting are no longer used by SWFUpload but are included + the maintain v2 API compatibility +*/ +// Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used. +SWFUpload.prototype.addSetting = function (name, value, default_value) { + if (value == undefined) { + return (this.settings[name] = default_value); + } else { + return (this.settings[name] = value); + } +}; + +// Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found. +SWFUpload.prototype.getSetting = function (name) { + if (this.settings[name] != undefined) { + return this.settings[name]; + } + + return ""; +}; + + + +// Private: callFlash handles function calls made to the Flash element. +// Calls are made with a setTimeout for some functions to work around +// bugs in the ExternalInterface library. +SWFUpload.prototype.callFlash = function (functionName, argumentArray) { + argumentArray = argumentArray || []; + + var movieElement = this.getMovieElement(); + var returnValue, returnString; + + // Flash's method if calling ExternalInterface methods (code adapted from MooTools). + try { + returnString = movieElement.CallFunction('' + __flash__argumentsToXML(argumentArray, 0) + ''); + returnValue = eval(returnString); + } catch (ex) { + throw "Call to " + functionName + " failed"; + } + + // Unescape file post param values + if (returnValue != undefined && typeof returnValue.post === "object") { + returnValue = this.unescapeFilePostParams(returnValue); + } + + return returnValue; +}; + +/* ***************************** + -- Flash control methods -- + Your UI should use these + to operate SWFUpload + ***************************** */ + +// WARNING: this function does not work in Flash Player 10 +// Public: selectFile causes a File Selection Dialog window to appear. This +// dialog only allows 1 file to be selected. +SWFUpload.prototype.selectFile = function () { + this.callFlash("SelectFile"); +}; + +// WARNING: this function does not work in Flash Player 10 +// Public: selectFiles causes a File Selection Dialog window to appear/ This +// dialog allows the user to select any number of files +// Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names. +// If the selection name length is too long the dialog will fail in an unpredictable manner. There is no work-around +// for this bug. +SWFUpload.prototype.selectFiles = function () { + this.callFlash("SelectFiles"); +}; + + +// Public: startUpload starts uploading the first file in the queue unless +// the optional parameter 'fileID' specifies the ID +SWFUpload.prototype.startUpload = function (fileID) { + this.callFlash("StartUpload", [fileID]); +}; + +// Public: cancelUpload cancels any queued file. The fileID parameter may be the file ID or index. +// If you do not specify a fileID the current uploading file or first file in the queue is cancelled. +// If you do not want the uploadError event to trigger you can specify false for the triggerErrorEvent parameter. +SWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) { + if (triggerErrorEvent !== false) { + triggerErrorEvent = true; + } + this.callFlash("CancelUpload", [fileID, triggerErrorEvent]); +}; + +// Public: stopUpload stops the current upload and requeues the file at the beginning of the queue. +// If nothing is currently uploading then nothing happens. +SWFUpload.prototype.stopUpload = function () { + this.callFlash("StopUpload"); +}; + +/* ************************ + * Settings methods + * These methods change the SWFUpload settings. + * SWFUpload settings should not be changed directly on the settings object + * since many of the settings need to be passed to Flash in order to take + * effect. + * *********************** */ + +// Public: getStats gets the file statistics object. +SWFUpload.prototype.getStats = function () { + return this.callFlash("GetStats"); +}; + +// Public: setStats changes the SWFUpload statistics. You shouldn't need to +// change the statistics but you can. Changing the statistics does not +// affect SWFUpload accept for the successful_uploads count which is used +// by the upload_limit setting to determine how many files the user may upload. +SWFUpload.prototype.setStats = function (statsObject) { + this.callFlash("SetStats", [statsObject]); +}; + +// Public: getFile retrieves a File object by ID or Index. If the file is +// not found then 'null' is returned. +SWFUpload.prototype.getFile = function (fileID) { + if (typeof(fileID) === "number") { + return this.callFlash("GetFileByIndex", [fileID]); + } else { + return this.callFlash("GetFile", [fileID]); + } +}; + +// Public: addFileParam sets a name/value pair that will be posted with the +// file specified by the Files ID. If the name already exists then the +// exiting value will be overwritten. +SWFUpload.prototype.addFileParam = function (fileID, name, value) { + return this.callFlash("AddFileParam", [fileID, name, value]); +}; + +// Public: removeFileParam removes a previously set (by addFileParam) name/value +// pair from the specified file. +SWFUpload.prototype.removeFileParam = function (fileID, name) { + this.callFlash("RemoveFileParam", [fileID, name]); +}; + +// Public: setUploadUrl changes the upload_url setting. +SWFUpload.prototype.setUploadURL = function (url) { + this.settings.upload_url = url.toString(); + this.callFlash("SetUploadURL", [url]); +}; + +// Public: setPostParams changes the post_params setting +SWFUpload.prototype.setPostParams = function (paramsObject) { + this.settings.post_params = paramsObject; + this.callFlash("SetPostParams", [paramsObject]); +}; + +// Public: addPostParam adds post name/value pair. Each name can have only one value. +SWFUpload.prototype.addPostParam = function (name, value) { + this.settings.post_params[name] = value; + this.callFlash("SetPostParams", [this.settings.post_params]); +}; + +// Public: removePostParam deletes post name/value pair. +SWFUpload.prototype.removePostParam = function (name) { + delete this.settings.post_params[name]; + this.callFlash("SetPostParams", [this.settings.post_params]); +}; + +// Public: setFileTypes changes the file_types setting and the file_types_description setting +SWFUpload.prototype.setFileTypes = function (types, description) { + this.settings.file_types = types; + this.settings.file_types_description = description; + this.callFlash("SetFileTypes", [types, description]); +}; + +// Public: setFileSizeLimit changes the file_size_limit setting +SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) { + this.settings.file_size_limit = fileSizeLimit; + this.callFlash("SetFileSizeLimit", [fileSizeLimit]); +}; + +// Public: setFileUploadLimit changes the file_upload_limit setting +SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) { + this.settings.file_upload_limit = fileUploadLimit; + this.callFlash("SetFileUploadLimit", [fileUploadLimit]); +}; + +// Public: setFileQueueLimit changes the file_queue_limit setting +SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) { + this.settings.file_queue_limit = fileQueueLimit; + this.callFlash("SetFileQueueLimit", [fileQueueLimit]); +}; + +// Public: setFilePostName changes the file_post_name setting +SWFUpload.prototype.setFilePostName = function (filePostName) { + this.settings.file_post_name = filePostName; + this.callFlash("SetFilePostName", [filePostName]); +}; + +// Public: setUseQueryString changes the use_query_string setting +SWFUpload.prototype.setUseQueryString = function (useQueryString) { + this.settings.use_query_string = useQueryString; + this.callFlash("SetUseQueryString", [useQueryString]); +}; + +// Public: setRequeueOnError changes the requeue_on_error setting +SWFUpload.prototype.setRequeueOnError = function (requeueOnError) { + this.settings.requeue_on_error = requeueOnError; + this.callFlash("SetRequeueOnError", [requeueOnError]); +}; + +// Public: setHTTPSuccess changes the http_success setting +SWFUpload.prototype.setHTTPSuccess = function (http_status_codes) { + if (typeof http_status_codes === "string") { + http_status_codes = http_status_codes.replace(" ", "").split(","); + } + + this.settings.http_success = http_status_codes; + this.callFlash("SetHTTPSuccess", [http_status_codes]); +}; + +// Public: setHTTPSuccess changes the http_success setting +SWFUpload.prototype.setAssumeSuccessTimeout = function (timeout_seconds) { + this.settings.assume_success_timeout = timeout_seconds; + this.callFlash("SetAssumeSuccessTimeout", [timeout_seconds]); +}; + +// Public: setDebugEnabled changes the debug_enabled setting +SWFUpload.prototype.setDebugEnabled = function (debugEnabled) { + this.settings.debug_enabled = debugEnabled; + this.callFlash("SetDebugEnabled", [debugEnabled]); +}; + +// Public: setButtonImageURL loads a button image sprite +SWFUpload.prototype.setButtonImageURL = function (buttonImageURL) { + if (buttonImageURL == undefined) { + buttonImageURL = ""; + } + + this.settings.button_image_url = buttonImageURL; + this.callFlash("SetButtonImageURL", [buttonImageURL]); +}; + +// Public: setButtonDimensions resizes the Flash Movie and button +SWFUpload.prototype.setButtonDimensions = function (width, height) { + this.settings.button_width = width; + this.settings.button_height = height; + + var movie = this.getMovieElement(); + if (movie != undefined) { + movie.style.width = width + "px"; + movie.style.height = height + "px"; + } + + this.callFlash("SetButtonDimensions", [width, height]); +}; +// Public: setButtonText Changes the text overlaid on the button +SWFUpload.prototype.setButtonText = function (html) { + this.settings.button_text = html; + this.callFlash("SetButtonText", [html]); +}; +// Public: setButtonTextPadding changes the top and left padding of the text overlay +SWFUpload.prototype.setButtonTextPadding = function (left, top) { + this.settings.button_text_top_padding = top; + this.settings.button_text_left_padding = left; + this.callFlash("SetButtonTextPadding", [left, top]); +}; + +// Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button +SWFUpload.prototype.setButtonTextStyle = function (css) { + this.settings.button_text_style = css; + this.callFlash("SetButtonTextStyle", [css]); +}; +// Public: setButtonDisabled disables/enables the button +SWFUpload.prototype.setButtonDisabled = function (isDisabled) { + this.settings.button_disabled = isDisabled; + this.callFlash("SetButtonDisabled", [isDisabled]); +}; +// Public: setButtonAction sets the action that occurs when the button is clicked +SWFUpload.prototype.setButtonAction = function (buttonAction) { + this.settings.button_action = buttonAction; + this.callFlash("SetButtonAction", [buttonAction]); +}; + +// Public: setButtonCursor changes the mouse cursor displayed when hovering over the button +SWFUpload.prototype.setButtonCursor = function (cursor) { + this.settings.button_cursor = cursor; + this.callFlash("SetButtonCursor", [cursor]); +}; + +/* ******************************* + Flash Event Interfaces + These functions are used by Flash to trigger the various + events. + + All these functions a Private. + + Because the ExternalInterface library is buggy the event calls + are added to a queue and the queue then executed by a setTimeout. + This ensures that events are executed in a determinate order and that + the ExternalInterface bugs are avoided. +******************************* */ + +SWFUpload.prototype.queueEvent = function (handlerName, argumentArray) { + // Warning: Don't call this.debug inside here or you'll create an infinite loop + + if (argumentArray == undefined) { + argumentArray = []; + } else if (!(argumentArray instanceof Array)) { + argumentArray = [argumentArray]; + } + + var self = this; + if (typeof this.settings[handlerName] === "function") { + // Queue the event + this.eventQueue.push(function () { + this.settings[handlerName].apply(this, argumentArray); + }); + + // Execute the next queued event + setTimeout(function () { + self.executeNextEvent(); + }, 0); + + } else if (this.settings[handlerName] !== null) { + throw "Event handler " + handlerName + " is unknown or is not a function"; + } +}; + +// Private: Causes the next event in the queue to be executed. Since events are queued using a setTimeout +// we must queue them in order to garentee that they are executed in order. +SWFUpload.prototype.executeNextEvent = function () { + // Warning: Don't call this.debug inside here or you'll create an infinite loop + + var f = this.eventQueue ? this.eventQueue.shift() : null; + if (typeof(f) === "function") { + f.apply(this); + } +}; + +// Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have +// properties that contain characters that are not valid for JavaScript identifiers. To work around this +// the Flash Component escapes the parameter names and we must unescape again before passing them along. +SWFUpload.prototype.unescapeFilePostParams = function (file) { + var reg = /[$]([0-9a-f]{4})/i; + var unescapedPost = {}; + var uk; + + if (file != undefined) { + for (var k in file.post) { + if (file.post.hasOwnProperty(k)) { + uk = k; + var match; + while ((match = reg.exec(uk)) !== null) { + uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16))); + } + unescapedPost[uk] = file.post[k]; + } + } + + file.post = unescapedPost; + } + + return file; +}; + +// Private: Called by Flash to see if JS can call in to Flash (test if External Interface is working) +SWFUpload.prototype.testExternalInterface = function () { + try { + return this.callFlash("TestExternalInterface"); + } catch (ex) { + return false; + } +}; + +// Private: This event is called by Flash when it has finished loading. Don't modify this. +// Use the swfupload_loaded_handler event setting to execute custom code when SWFUpload has loaded. +SWFUpload.prototype.flashReady = function () { + // Check that the movie element is loaded correctly with its ExternalInterface methods defined + var movieElement = this.getMovieElement(); + + if (!movieElement) { + this.debug("Flash called back ready but the flash movie can't be found."); + return; + } + + this.cleanUp(movieElement); + + this.queueEvent("swfupload_loaded_handler"); +}; + +// Private: removes Flash added fuctions to the DOM node to prevent memory leaks in IE. +// This function is called by Flash each time the ExternalInterface functions are created. +SWFUpload.prototype.cleanUp = function (movieElement) { + // Pro-actively unhook all the Flash functions + try { + if (this.movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE + this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)"); + for (var key in movieElement) { + try { + if (typeof(movieElement[key]) === "function") { + movieElement[key] = null; + } + } catch (ex) { + } + } + } + } catch (ex1) { + + } + + // Fix Flashes own cleanup code so if the SWFMovie was removed from the page + // it doesn't display errors. + window["__flash__removeCallback"] = function (instance, name) { + try { + if (instance) { + instance[name] = null; + } + } catch (flashEx) { + + } + }; + +}; + + +/* This is a chance to do something before the browse window opens */ +SWFUpload.prototype.fileDialogStart = function () { + this.queueEvent("file_dialog_start_handler"); +}; + + +/* Called when a file is successfully added to the queue. */ +SWFUpload.prototype.fileQueued = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("file_queued_handler", file); +}; + + +/* Handle errors that occur when an attempt to queue a file fails. */ +SWFUpload.prototype.fileQueueError = function (file, errorCode, message) { + file = this.unescapeFilePostParams(file); + this.queueEvent("file_queue_error_handler", [file, errorCode, message]); +}; + +/* Called after the file dialog has closed and the selected files have been queued. + You could call startUpload here if you want the queued files to begin uploading immediately. */ +SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued, numFilesInQueue) { + this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued, numFilesInQueue]); +}; + +SWFUpload.prototype.uploadStart = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("return_upload_start_handler", file); +}; + +SWFUpload.prototype.returnUploadStart = function (file) { + var returnValue; + if (typeof this.settings.upload_start_handler === "function") { + file = this.unescapeFilePostParams(file); + returnValue = this.settings.upload_start_handler.call(this, file); + } else if (this.settings.upload_start_handler != undefined) { + throw "upload_start_handler must be a function"; + } + + // Convert undefined to true so if nothing is returned from the upload_start_handler it is + // interpretted as 'true'. + if (returnValue === undefined) { + returnValue = true; + } + + returnValue = !!returnValue; + + this.callFlash("ReturnUploadStart", [returnValue]); +}; + + + +SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]); +}; + +SWFUpload.prototype.uploadError = function (file, errorCode, message) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_error_handler", [file, errorCode, message]); +}; + +SWFUpload.prototype.uploadSuccess = function (file, serverData, responseReceived) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_success_handler", [file, serverData, responseReceived]); +}; + +SWFUpload.prototype.uploadComplete = function (file) { + file = this.unescapeFilePostParams(file); + this.queueEvent("upload_complete_handler", file); +}; + +/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the + internal debug console. You can override this event and have messages written where you want. */ +SWFUpload.prototype.debug = function (message) { + this.queueEvent("debug_handler", message); +}; + + +/* ********************************** + Debug Console + The debug console is a self contained, in page location + for debug message to be sent. The Debug Console adds + itself to the body if necessary. + + The console is automatically scrolled as messages appear. + + If you are using your own debug handler or when you deploy to production and + have debug disabled you can remove these functions to reduce the file size + and complexity. +********************************** */ + +// Private: debugMessage is the default debug_handler. If you want to print debug messages +// call the debug() function. When overriding the function your own function should +// check to see if the debug setting is true before outputting debug information. +SWFUpload.prototype.debugMessage = function (message) { + if (this.settings.debug) { + var exceptionMessage, exceptionValues = []; + + // Check for an exception object and print it nicely + if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string") { + for (var key in message) { + if (message.hasOwnProperty(key)) { + exceptionValues.push(key + ": " + message[key]); + } + } + exceptionMessage = exceptionValues.join("\n") || ""; + exceptionValues = exceptionMessage.split("\n"); + exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: "); + SWFUpload.Console.writeLine(exceptionMessage); + } else { + SWFUpload.Console.writeLine(message); + } + } +}; + +SWFUpload.Console = {}; +SWFUpload.Console.writeLine = function (message) { + var console, documentForm; + + try { + console = document.getElementById("SWFUpload_Console"); + + if (!console) { + documentForm = document.createElement("form"); + document.getElementsByTagName("body")[0].appendChild(documentForm); + + console = document.createElement("textarea"); + console.id = "SWFUpload_Console"; + console.style.fontFamily = "monospace"; + console.setAttribute("wrap", "off"); + console.wrap = "off"; + console.style.overflow = "auto"; + console.style.width = "700px"; + console.style.height = "350px"; + console.style.margin = "5px"; + documentForm.appendChild(console); + } + + console.value += message + "\n"; + + console.scrollTop = console.scrollHeight - console.clientHeight; + } catch (ex) { + alert("Exception: " + ex.name + " Message: " + ex.message); + } +}; + +})(); + +(function() { +/* + Queue Plug-in + + Features: + *Adds a cancelQueue() method for cancelling the entire queue. + *All queued files are uploaded when startUpload() is called. + *If false is returned from uploadComplete then the queue upload is stopped. + If false is not returned (strict comparison) then the queue upload is continued. + *Adds a QueueComplete event that is fired when all the queued files have finished uploading. + Set the event handler with the queue_complete_handler setting. + + */ + +if (typeof(SWFUpload) === "function") { + SWFUpload.queue = {}; + + SWFUpload.prototype.initSettings = (function (oldInitSettings) { + return function () { + if (typeof(oldInitSettings) === "function") { + oldInitSettings.call(this); + } + + this.queueSettings = {}; + + this.queueSettings.queue_cancelled_flag = false; + this.queueSettings.queue_upload_count = 0; + + this.queueSettings.user_upload_complete_handler = this.settings.upload_complete_handler; + this.queueSettings.user_upload_start_handler = this.settings.upload_start_handler; + this.settings.upload_complete_handler = SWFUpload.queue.uploadCompleteHandler; + this.settings.upload_start_handler = SWFUpload.queue.uploadStartHandler; + + this.settings.queue_complete_handler = this.settings.queue_complete_handler || null; + }; + })(SWFUpload.prototype.initSettings); + + SWFUpload.prototype.startUpload = function (fileID) { + this.queueSettings.queue_cancelled_flag = false; + this.callFlash("StartUpload", [fileID]); + }; + + SWFUpload.prototype.cancelQueue = function () { + this.queueSettings.queue_cancelled_flag = true; + this.stopUpload(); + + var stats = this.getStats(); + while (stats.files_queued > 0) { + this.cancelUpload(); + stats = this.getStats(); + } + }; + + SWFUpload.queue.uploadStartHandler = function (file) { + var returnValue; + if (typeof(this.queueSettings.user_upload_start_handler) === "function") { + returnValue = this.queueSettings.user_upload_start_handler.call(this, file); + } + + // To prevent upload a real "FALSE" value must be returned, otherwise default to a real "TRUE" value. + returnValue = (returnValue === false) ? false : true; + + this.queueSettings.queue_cancelled_flag = !returnValue; + + return returnValue; + }; + + SWFUpload.queue.uploadCompleteHandler = function (file) { + var user_upload_complete_handler = this.queueSettings.user_upload_complete_handler; + var continueUpload; + + if (file.filestatus === SWFUpload.FILE_STATUS.COMPLETE) { + this.queueSettings.queue_upload_count++; + } + + if (typeof(user_upload_complete_handler) === "function") { + continueUpload = (user_upload_complete_handler.call(this, file) === false) ? false : true; + } else if (file.filestatus === SWFUpload.FILE_STATUS.QUEUED) { + // If the file was stopped and re-queued don't restart the upload + continueUpload = false; + } else { + continueUpload = true; + } + + if (continueUpload) { + var stats = this.getStats(); + if (stats.files_queued > 0 && this.queueSettings.queue_cancelled_flag === false) { + this.startUpload(); + } else if (this.queueSettings.queue_cancelled_flag === false) { + this.queueEvent("queue_complete_handler", [this.queueSettings.queue_upload_count]); + this.queueSettings.queue_upload_count = 0; + } else { + this.queueSettings.queue_cancelled_flag = false; + this.queueSettings.queue_upload_count = 0; + } + } + }; +} + +})(); diff --git a/web/resource/components/kindeditor/plugins/pagebreak/pagebreak.js b/web/resource/components/kindeditor/plugins/pagebreak/pagebreak.js new file mode 100644 index 0000000..dfa883a --- /dev/null +++ b/web/resource/components/kindeditor/plugins/pagebreak/pagebreak.js @@ -0,0 +1,27 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('pagebreak', function(K) { + var self = this; + var name = 'pagebreak'; + var pagebreakHtml = K.undef(self.pagebreakHtml, '
'); + + self.clickToolbar(name, function() { + var cmd = self.cmd, range = cmd.range; + self.focus(); + var tail = self.newlineTag == 'br' || K.WEBKIT ? '' : ''; + self.insertHtml(pagebreakHtml + tail); + if (tail !== '') { + var p = K('#__kindeditor_tail_tag__', self.edit.doc); + range.selectNodeContents(p[0]); + p.removeAttr('id'); + cmd.select(); + } + }); +}); diff --git a/web/resource/components/kindeditor/plugins/plainpaste/plainpaste.js b/web/resource/components/kindeditor/plugins/plainpaste/plainpaste.js new file mode 100644 index 0000000..8f7bed8 --- /dev/null +++ b/web/resource/components/kindeditor/plugins/plainpaste/plainpaste.js @@ -0,0 +1,41 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('plainpaste', function(K) { + var self = this, name = 'plainpaste'; + self.clickToolbar(name, function() { + var lang = self.lang(name + '.'), + html = '
' + + '
' + lang.comment + '
' + + '' + + '
', + dialog = self.createDialog({ + name : name, + width : 450, + title : self.lang(name), + body : html, + yesBtn : { + name : self.lang('yes'), + click : function(e) { + var html = textarea.val(); + html = K.escape(html); + html = html.replace(/ {2}/g, '  '); + if (self.newlineTag == 'p') { + html = html.replace(/^/, '

').replace(/$/, '

').replace(/\n/g, '

'); + } else { + html = html.replace(/\n/g, '
$&'); + } + self.insertHtml(html).hideDialog().focus(); + } + } + }), + textarea = K('textarea', dialog.div); + textarea[0].focus(); + }); +}); diff --git a/web/resource/components/kindeditor/plugins/preview/preview.js b/web/resource/components/kindeditor/plugins/preview/preview.js new file mode 100644 index 0000000..ef6e2cf --- /dev/null +++ b/web/resource/components/kindeditor/plugins/preview/preview.js @@ -0,0 +1,31 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('preview', function(K) { + var self = this, name = 'preview', undefined; + self.clickToolbar(name, function() { + var lang = self.lang(name + '.'), + html = '

' + + '' + + '
', + dialog = self.createDialog({ + name : name, + width : 750, + title : self.lang(name), + body : html + }), + iframe = K('iframe', dialog.div), + doc = K.iframeDoc(iframe); + doc.open(); + doc.write(self.fullHtml()); + doc.close(); + K(doc.body).css('background-color', '#FFF'); + iframe[0].contentWindow.focus(); + }); +}); diff --git a/web/resource/components/kindeditor/plugins/quickformat/quickformat.js b/web/resource/components/kindeditor/plugins/quickformat/quickformat.js new file mode 100644 index 0000000..5b98c72 --- /dev/null +++ b/web/resource/components/kindeditor/plugins/quickformat/quickformat.js @@ -0,0 +1,81 @@ +/******************************************************************************* +* KindEditor - WYSIWYG HTML Editor for Internet +* Copyright (C) 2006-2011 kindsoft.net +* +* @author Roddy +* @site http://www.kindsoft.net/ +* @licence http://www.kindsoft.net/license.php +*******************************************************************************/ + +KindEditor.plugin('quickformat', function(K) { + var self = this, name = 'quickformat', + blockMap = K.toMap('blockquote,center,div,h1,h2,h3,h4,h5,h6,p'); + function getFirstChild(knode) { + var child = knode.first(); + while (child && child.first()) { + child = child.first(); + } + return child; + } + self.clickToolbar(name, function() { + self.focus(); + var doc = self.edit.doc, + range = self.cmd.range, + child = K(doc.body).first(), next, + nodeList = [], subList = [], + bookmark = range.createBookmark(true); + while(child) { + next = child.next(); + var firstChild = getFirstChild(child); + if (!firstChild || firstChild.name != 'img') { + if (blockMap[child.name]) { + child.html(child.html().replace(/^(\s| | )+/ig, '')); + child.css('text-indent', '2em'); + } else { + subList.push(child); + } + if (!next || (blockMap[next.name] || blockMap[child.name] && !blockMap[next.name])) { + if (subList.length > 0) { + nodeList.push(subList); + } + subList = []; + } + } + child = next; + } + K.each(nodeList, function(i, subList) { + var wrapper = K('

', doc); + subList[0].before(wrapper); + K.each(subList, function(i, knode) { + wrapper.append(knode); + }); + }); + range.moveToBookmark(bookmark); + self.addBookmark(); + }); +}); + +/** +-------------------------- +abcd
+1234
+ +to + +

+ abcd
+ 1234
+

+ +-------------------------- + +  abcd1233 +

1234

+ +to + +

abcd1233

+

1234

+ +-------------------------- +*/ \ No newline at end of file diff --git a/web/resource/components/kindeditor/themes/qq/qq.css b/web/resource/components/kindeditor/themes/qq/qq.css new file mode 100644 index 0000000..a45e08c --- /dev/null +++ b/web/resource/components/kindeditor/themes/qq/qq.css @@ -0,0 +1,143 @@ +/* container */ +.ke-container-qq { + display: block; + border: 1px solid #c3c3c3; + background-color: #FFF; + overflow: hidden; + margin: 0; + padding: 0; +} +/* toolbar */ +.ke-container-qq .ke-toolbar { + border-bottom: 1px solid #c3c3c3; + background-color: #FFFFFF; + padding: 2px 5px; + text-align: left; + overflow: hidden; + zoom: 1; +} +.ke-toolbar-icon-url { + background-image: url(editor.gif); + width:18px; + *xwidth:20px; + height:18px; + *xheight:20px; +} +.ke-icon-checked{ + background-image: url(../default/default.png); + width:16px; + height:16px; +} +.ke-container-qq .ke-icon-bold{ + background-position: 4px 1px; +} +.ke-container-qq .ke-icon-italic{ + background-position: -27px 1px; +} +.ke-container-qq .ke-icon-italic{ + background-position: -28px 1px; +} +.ke-container-qq .ke-icon-underline{ + background-position: -60px 1px; +} +.ke-container-qq .ke-icon-fontname{ + background-position: -95px 1px; +} +.ke-container-qq .ke-icon-fontsize{ + background-position: -128px 1px; +} +.ke-container-qq .ke-icon-forecolor{ + background-position: -159px 1px; +} +.ke-container-qq .ke-icon-hilitecolor{ + background-position: -190px 1px; +} +.ke-container-qq .ke-icon-plug-align{ + background-position: -223px 1px; +} +.plug-align-justifyleft{ + background-position: -350px 1px; +} +.plug-align-justifycenter{ + background-position: -382px 1px; +} +.plug-align-justifyright{ + background-position: -414px 1px; +} +.plug-order-insertorderedlist{ + background-position: -446px 1px; +} +.plug-order-insertunorderedlist{ + background-position: -477px 1px; +} +.plug-indent-indent{ + background-position: -513px 1px; +} +.plug-indent-outdent{ + background-position: -545px 1px; +} +.ke-container-qq .ke-icon-plug-order{ + background-position: -255px 1px; +} +.ke-container-qq .ke-icon-plug-indent{ + background-position: -287px 1px; +} +.ke-container-qq .ke-icon-link{ + background-position: -319px 1px; +} + +.ke-container-qq .ke-toolbar .ke-outline { + cursor: default; + padding:0px; + border:1px solid #fff; +} +.ke-container-qq .ke-toolbar .ke-on { + border-left:1px solid white; + border-top:1px solid white; + border-right:1px solid gray; + border-bottom:1px solid gray; + background-color: #FFFFFF; +} +.ke-container-qq .ke-toolbar .ke-selected { + border-left:1px solid gray; + border-top:1px solid gray; + border-right:1px solid white; + border-bottom:1px solid white; + background-color: #FFFFFF; +} +.ke-container-qq .ke-toolbar .ke-disabled { + cursor: default; +} + +.ke-colorpicker-qq{ + background:#fff; +} +/* statusbar */ +.ke-container-qq .ke-statusbar { + display:none; +} +/* menu */ +.ke-menu-qq { + border:1px solid #a6a6a6; + position:absolute; + background:#fff; + -moz-box-shadow:2px 2px 4px #DDDDDD; + z-index:999; + left:-400px; + top:-386px; + right:218px; + width:130px; +} +.ke-menu-qq .ke-menu-item { + padding:0px; + background:#fff; +} +.ke-menu-qq .ke-menu-item-on { + border:1px solid #000080;background:#FFEEC2;color:#036; +} +.ke-menu-qq .ke-toolbar .ke-selected { + border:1px solid #9a9afb; +} +.ke-menu-qq .ke-menu-item-left{ + width:auto; +} diff --git a/web/resource/components/tinymce/langs/readme.md b/web/resource/components/tinymce/langs/readme.md new file mode 100644 index 0000000..a52bf03 --- /dev/null +++ b/web/resource/components/tinymce/langs/readme.md @@ -0,0 +1,3 @@ +This is where language files should be placed. + +Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/ diff --git a/web/resource/components/tinymce/plugins/advlist/plugin.min.js b/web/resource/components/tinymce/plugins/advlist/plugin.min.js new file mode 100644 index 0000000..a4db7cc --- /dev/null +++ b/web/resource/components/tinymce/plugins/advlist/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("advlist",function(t){function e(t,e){var n=[];return tinymce.each(e.split(/[ ,]/),function(t){n.push({text:t.replace(/\-/g," ").replace(/\b\w/g,function(t){return t.toUpperCase()}),data:"default"==t?"":t})}),n}function n(e,n){var o,l=t.dom,a=t.selection;o=l.getParent(a.getNode(),"ol,ul"),o&&o.nodeName==e&&n!==!1||t.execCommand("UL"==e?"InsertUnorderedList":"InsertOrderedList"),n=n===!1?i[e]:n,i[e]=n,o=l.getParent(a.getNode(),"ol,ul"),o&&(l.setStyle(o,"listStyleType",n),o.removeAttribute("data-mce-style")),t.focus()}function o(e){var n=t.dom.getStyle(t.dom.getParent(t.selection.getNode(),"ol,ul"),"listStyleType")||"";e.control.items().each(function(t){t.active(t.settings.data===n)})}var l,a,i={};l=e("OL",t.getParam("advlist_number_styles","default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman")),a=e("UL",t.getParam("advlist_bullet_styles","default,circle,disc,square")),t.addButton("numlist",{type:"splitbutton",tooltip:"Numbered list",menu:l,onshow:o,onselect:function(t){n("OL",t.control.settings.data)},onclick:function(){n("OL",!1)}}),t.addButton("bullist",{type:"splitbutton",tooltip:"Bullet list",menu:a,onshow:o,onselect:function(t){n("UL",t.control.settings.data)},onclick:function(){n("UL",!1)}})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/anchor/plugin.min.js b/web/resource/components/tinymce/plugins/anchor/plugin.min.js new file mode 100644 index 0000000..058e686 --- /dev/null +++ b/web/resource/components/tinymce/plugins/anchor/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("anchor",function(n){function e(){var e=n.selection.getNode();n.windowManager.open({title:"Anchor",body:{type:"textbox",name:"name",size:40,label:"Name",value:e.name||e.id},onsubmit:function(e){n.execCommand("mceInsertContent",!1,n.dom.createHTML("a",{id:e.data.name}))}})}n.addButton("anchor",{icon:"anchor",tooltip:"Anchor",onclick:e,stateSelector:"a:not([href])"}),n.addMenuItem("anchor",{icon:"anchor",text:"Anchor",context:"insert",onclick:e})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/autolink/plugin.min.js b/web/resource/components/tinymce/plugins/autolink/plugin.min.js new file mode 100644 index 0000000..c49c679 --- /dev/null +++ b/web/resource/components/tinymce/plugins/autolink/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("autolink",function(t){function n(t){o(t,-1,"(",!0)}function e(t){o(t,0,"",!0)}function i(t){o(t,-1,"",!1)}function o(t,n,e){function i(t,n){if(0>n&&(n=0),3==t.nodeType){var e=t.data.length;n>e&&(n=e)}return n}function o(t,n){f.setStart(t,i(t,n))}function r(t,n){f.setEnd(t,i(t,n))}var f,d,a,s,c,l,u,g,h;if(f=t.selection.getRng(!0).cloneRange(),f.startOffset<5){if(g=f.endContainer.previousSibling,!g){if(!f.endContainer.firstChild||!f.endContainer.firstChild.nextSibling)return;g=f.endContainer.firstChild.nextSibling}if(h=g.length,o(g,h),r(g,h),f.endOffset<5)return;d=f.endOffset,s=g}else{if(s=f.endContainer,3!=s.nodeType&&s.firstChild){for(;3!=s.nodeType&&s.firstChild;)s=s.firstChild;3==s.nodeType&&(o(s,0),r(s,s.nodeValue.length))}d=1==f.endOffset?2:f.endOffset-1-n}a=d;do o(s,d>=2?d-2:0),r(s,d>=1?d-1:0),d-=1;while(" "!=f.toString()&&""!==f.toString()&&160!=f.toString().charCodeAt(0)&&d-2>=0&&f.toString()!=e);f.toString()==e||160==f.toString().charCodeAt(0)?(o(s,d),r(s,a),d+=1):0===f.startOffset?(o(s,0),r(s,a)):(o(s,d),r(s,a)),l=f.toString(),"."==l.charAt(l.length-1)&&r(s,a-1),l=f.toString(),u=l.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+\-]+@)(.+)$/i),u&&("www."==u[1]?u[1]="http://www.":/@$/.test(u[1])&&!/^mailto:/.test(u[1])&&(u[1]="mailto:"+u[1]),c=t.selection.getBookmark(),t.selection.setRng(f),t.execCommand("createlink",!1,u[1]+u[2]),t.selection.moveToBookmark(c),t.nodeChanged())}var r;return t.on("keydown",function(n){return 13==n.keyCode?i(t):void 0}),tinymce.Env.ie?void t.on("focus",function(){if(!r){r=!0;try{t.execCommand("AutoUrlDetect",!1,!0)}catch(n){}}}):(t.on("keypress",function(e){return 41==e.keyCode?n(t):void 0}),void t.on("keyup",function(n){return 32==n.keyCode?e(t):void 0}))}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/autoresize/plugin.min.js b/web/resource/components/tinymce/plugins/autoresize/plugin.min.js new file mode 100644 index 0000000..fed1d4f --- /dev/null +++ b/web/resource/components/tinymce/plugins/autoresize/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("autoresize",function(e){function t(){return e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen()}function i(n){var s,r,g,u,l,m,h,d,f=tinymce.DOM;if(r=e.getDoc()){if(g=r.body,u=r.documentElement,l=o.autoresize_min_height,!g||n&&"setcontent"===n.type&&n.initial||t())return void(g&&u&&(g.style.overflowY="auto",u.style.overflowY="auto"));h=e.dom.getStyle(g,"margin-top",!0),d=e.dom.getStyle(g,"margin-bottom",!0),m=g.offsetHeight+parseInt(h,10)+parseInt(d,10),(isNaN(m)||0>=m)&&(m=tinymce.Env.ie?g.scrollHeight:tinymce.Env.webkit&&0===g.clientHeight?0:g.offsetHeight),m>o.autoresize_min_height&&(l=m),o.autoresize_max_height&&m>o.autoresize_max_height?(l=o.autoresize_max_height,g.style.overflowY="auto",u.style.overflowY="auto"):(g.style.overflowY="hidden",u.style.overflowY="hidden",g.scrollTop=0),l!==a&&(s=l-a,f.setStyle(f.get(e.id+"_ifr"),"height",l+"px"),a=l,tinymce.isWebKit&&0>s&&i(n))}}function n(e,t,o){setTimeout(function(){i({}),e--?n(e,t,o):o&&o()},t)}var o=e.settings,a=0;e.settings.inline||(o.autoresize_min_height=parseInt(e.getParam("autoresize_min_height",e.getElement().offsetHeight),10),o.autoresize_max_height=parseInt(e.getParam("autoresize_max_height",0),10),e.on("init",function(){var t=e.getParam("autoresize_overflow_padding",1);e.dom.setStyles(e.getBody(),{paddingBottom:e.getParam("autoresize_bottom_margin",50),paddingLeft:t,paddingRight:t})}),e.on("nodechange setcontent keyup FullscreenStateChanged",i),e.getParam("autoresize_on_init",!0)&&e.on("init",function(){n(20,100,function(){n(5,1e3)})}),e.addCommand("mceAutoResize",i))}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/autosave/plugin.min.js b/web/resource/components/tinymce/plugins/autosave/plugin.min.js new file mode 100644 index 0000000..bb41975 --- /dev/null +++ b/web/resource/components/tinymce/plugins/autosave/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("autosave",function(e){function t(e,t){var n={s:1e3,m:6e4};return e=/^(\d+)([ms]?)$/.exec(""+(e||t)),(e[2]?n[e[2]]:1)*parseInt(e,10)}function n(){var e=parseInt(l.getItem(d+"time"),10)||0;return(new Date).getTime()-e>v.autosave_retention?(a(!1),!1):!0}function a(t){l.removeItem(d+"draft"),l.removeItem(d+"time"),t!==!1&&e.fire("RemoveDraft")}function r(){!c()&&e.isDirty()&&(l.setItem(d+"draft",e.getContent({format:"raw",no_events:!0})),l.setItem(d+"time",(new Date).getTime()),e.fire("StoreDraft"))}function o(){n()&&(e.setContent(l.getItem(d+"draft"),{format:"raw"}),e.fire("RestoreDraft"))}function i(){m||(setInterval(function(){e.removed||r()},v.autosave_interval),m=!0)}function s(){var t=this;t.disabled(!n()),e.on("StoreDraft RestoreDraft RemoveDraft",function(){t.disabled(!n())}),i()}function u(){e.undoManager.beforeChange(),o(),a(),e.undoManager.add()}function f(){var e;return tinymce.each(tinymce.editors,function(t){t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&t.getParam("autosave_ask_before_unload",!0)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))}),e}function c(t){var n=e.settings.forced_root_block;return t=tinymce.trim("undefined"==typeof t?e.getBody().innerHTML:t),""===t||new RegExp("^<"+n+"[^>]*>(( | |[ ]|]*>)+?|)|
$","i").test(t)}var d,m,v=e.settings,l=tinymce.util.LocalStorage;d=v.autosave_prefix||"tinymce-autosave-{path}{query}-{id}-",d=d.replace(/\{path\}/g,document.location.pathname),d=d.replace(/\{query\}/g,document.location.search),d=d.replace(/\{id\}/g,e.id),v.autosave_interval=t(v.autosave_interval,"30s"),v.autosave_retention=t(v.autosave_retention,"20m"),e.addButton("restoredraft",{title:"Restore last draft",onclick:u,onPostRender:s}),e.addMenuItem("restoredraft",{text:"Restore last draft",onclick:u,onPostRender:s,context:"file"}),e.settings.autosave_restore_when_empty!==!1&&(e.on("init",function(){n()&&c()&&o()}),e.on("saveContent",function(){a()})),window.onbeforeunload=f,this.hasDraft=n,this.storeDraft=r,this.restoreDraft=o,this.removeDraft=a,this.isEmpty=c}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/bbcode/plugin.min.js b/web/resource/components/tinymce/plugins/bbcode/plugin.min.js new file mode 100644 index 0000000..78c37cd --- /dev/null +++ b/web/resource/components/tinymce/plugins/bbcode/plugin.min.js @@ -0,0 +1 @@ +!function(){tinymce.create("tinymce.plugins.BBCodePlugin",{init:function(o){var e=this,t=o.getParam("bbcode_dialect","punbb").toLowerCase();o.on("beforeSetContent",function(o){o.content=e["_"+t+"_bbcode2html"](o.content)}),o.on("postProcess",function(o){o.set&&(o.content=e["_"+t+"_bbcode2html"](o.content)),o.get&&(o.content=e["_"+t+"_html2bbcode"](o.content))})},getInfo:function(){return{longname:"BBCode Plugin",author:"Moxiecode Systems AB",authorurl:"http://www.tinymce.com",infourl:"http://www.tinymce.com/wiki.php/Plugin:bbcode"}},_punbb_html2bbcode:function(o){function e(e,t){o=o.replace(e,t)}return o=tinymce.trim(o),e(/(.*?)<\/a>/gi,"[url=$1]$2[/url]"),e(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),e(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),e(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),e(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),e(/(.*?)<\/span>/gi,"[color=$1]$2[/color]"),e(/(.*?)<\/font>/gi,"[color=$1]$2[/color]"),e(/(.*?)<\/span>/gi,"[size=$1]$2[/size]"),e(/(.*?)<\/font>/gi,"$1"),e(//gi,"[img]$1[/img]"),e(/(.*?)<\/span>/gi,"[code]$1[/code]"),e(/(.*?)<\/span>/gi,"[quote]$1[/quote]"),e(/(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),e(/(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),e(/(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),e(/(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),e(/(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),e(/(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),e(/<\/(strong|b)>/gi,"[/b]"),e(/<(strong|b)>/gi,"[b]"),e(/<\/(em|i)>/gi,"[/i]"),e(/<(em|i)>/gi,"[i]"),e(/<\/u>/gi,"[/u]"),e(/(.*?)<\/span>/gi,"[u]$1[/u]"),e(//gi,"[u]"),e(/]*>/gi,"[quote]"),e(/<\/blockquote>/gi,"[/quote]"),e(/
/gi,"\n"),e(//gi,"\n"),e(/
/gi,"\n"),e(/

/gi,""),e(/<\/p>/gi,"\n"),e(/ |\u00a0/gi," "),e(/"/gi,'"'),e(/</gi,"<"),e(/>/gi,">"),e(/&/gi,"&"),o},_punbb_bbcode2html:function(o){function e(e,t){o=o.replace(e,t)}return o=tinymce.trim(o),e(/\n/gi,"
"),e(/\[b\]/gi,""),e(/\[\/b\]/gi,""),e(/\[i\]/gi,""),e(/\[\/i\]/gi,""),e(/\[u\]/gi,""),e(/\[\/u\]/gi,""),e(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'$2'),e(/\[url\](.*?)\[\/url\]/gi,'$1'),e(/\[img\](.*?)\[\/img\]/gi,''),e(/\[color=(.*?)\](.*?)\[\/color\]/gi,'$2'),e(/\[code\](.*?)\[\/code\]/gi,'$1 '),e(/\[quote.*?\](.*?)\[\/quote\]/gi,'$1 '),o}}),tinymce.PluginManager.add("bbcode",tinymce.plugins.BBCodePlugin)}(); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/charmap/plugin.min.js b/web/resource/components/tinymce/plugins/charmap/plugin.min.js new file mode 100644 index 0000000..46fce44 --- /dev/null +++ b/web/resource/components/tinymce/plugins/charmap/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("charmap",function(e){function a(){function a(e){for(;e;){if("TD"==e.nodeName)return e;e=e.parentNode}}var t,r,o,n;t='';var l=25;for(o=0;10>o;o++){for(t+="",r=0;l>r;r++){var s=i[o*l+r];t+='"}t+=""}t+="";var c={type:"container",html:t,onclick:function(a){var i=a.target;"TD"==i.tagName&&(i=i.firstChild),"DIV"==i.tagName&&(e.execCommand("mceInsertContent",!1,i.firstChild.data),a.ctrlKey||n.close())},onmouseover:function(e){var i=a(e.target);i&&n.find("#preview").text(i.firstChild.firstChild.data)}};n=e.windowManager.open({title:"Special character",spacing:10,padding:10,items:[c,{type:"label",name:"preview",text:" ",style:"font-size: 40px; text-align: center",border:1,minWidth:100,minHeight:80}],buttons:[{text:"Close",onclick:function(){n.close()}}]})}var i=[["160","no-break space"],["38","ampersand"],["34","quotation mark"],["162","cent sign"],["8364","euro sign"],["163","pound sign"],["165","yen sign"],["169","copyright sign"],["174","registered sign"],["8482","trade mark sign"],["8240","per mille sign"],["181","micro sign"],["183","middle dot"],["8226","bullet"],["8230","three dot leader"],["8242","minutes / feet"],["8243","seconds / inches"],["167","section sign"],["182","paragraph sign"],["223","sharp s / ess-zed"],["8249","single left-pointing angle quotation mark"],["8250","single right-pointing angle quotation mark"],["171","left pointing guillemet"],["187","right pointing guillemet"],["8216","left single quotation mark"],["8217","right single quotation mark"],["8220","left double quotation mark"],["8221","right double quotation mark"],["8218","single low-9 quotation mark"],["8222","double low-9 quotation mark"],["60","less-than sign"],["62","greater-than sign"],["8804","less-than or equal to"],["8805","greater-than or equal to"],["8211","en dash"],["8212","em dash"],["175","macron"],["8254","overline"],["164","currency sign"],["166","broken bar"],["168","diaeresis"],["161","inverted exclamation mark"],["191","turned question mark"],["710","circumflex accent"],["732","small tilde"],["176","degree sign"],["8722","minus sign"],["177","plus-minus sign"],["247","division sign"],["8260","fraction slash"],["215","multiplication sign"],["185","superscript one"],["178","superscript two"],["179","superscript three"],["188","fraction one quarter"],["189","fraction one half"],["190","fraction three quarters"],["402","function / florin"],["8747","integral"],["8721","n-ary sumation"],["8734","infinity"],["8730","square root"],["8764","similar to"],["8773","approximately equal to"],["8776","almost equal to"],["8800","not equal to"],["8801","identical to"],["8712","element of"],["8713","not an element of"],["8715","contains as member"],["8719","n-ary product"],["8743","logical and"],["8744","logical or"],["172","not sign"],["8745","intersection"],["8746","union"],["8706","partial differential"],["8704","for all"],["8707","there exists"],["8709","diameter"],["8711","backward difference"],["8727","asterisk operator"],["8733","proportional to"],["8736","angle"],["180","acute accent"],["184","cedilla"],["170","feminine ordinal indicator"],["186","masculine ordinal indicator"],["8224","dagger"],["8225","double dagger"],["192","A - grave"],["193","A - acute"],["194","A - circumflex"],["195","A - tilde"],["196","A - diaeresis"],["197","A - ring above"],["198","ligature AE"],["199","C - cedilla"],["200","E - grave"],["201","E - acute"],["202","E - circumflex"],["203","E - diaeresis"],["204","I - grave"],["205","I - acute"],["206","I - circumflex"],["207","I - diaeresis"],["208","ETH"],["209","N - tilde"],["210","O - grave"],["211","O - acute"],["212","O - circumflex"],["213","O - tilde"],["214","O - diaeresis"],["216","O - slash"],["338","ligature OE"],["352","S - caron"],["217","U - grave"],["218","U - acute"],["219","U - circumflex"],["220","U - diaeresis"],["221","Y - acute"],["376","Y - diaeresis"],["222","THORN"],["224","a - grave"],["225","a - acute"],["226","a - circumflex"],["227","a - tilde"],["228","a - diaeresis"],["229","a - ring above"],["230","ligature ae"],["231","c - cedilla"],["232","e - grave"],["233","e - acute"],["234","e - circumflex"],["235","e - diaeresis"],["236","i - grave"],["237","i - acute"],["238","i - circumflex"],["239","i - diaeresis"],["240","eth"],["241","n - tilde"],["242","o - grave"],["243","o - acute"],["244","o - circumflex"],["245","o - tilde"],["246","o - diaeresis"],["248","o slash"],["339","ligature oe"],["353","s - caron"],["249","u - grave"],["250","u - acute"],["251","u - circumflex"],["252","u - diaeresis"],["253","y - acute"],["254","thorn"],["255","y - diaeresis"],["913","Alpha"],["914","Beta"],["915","Gamma"],["916","Delta"],["917","Epsilon"],["918","Zeta"],["919","Eta"],["920","Theta"],["921","Iota"],["922","Kappa"],["923","Lambda"],["924","Mu"],["925","Nu"],["926","Xi"],["927","Omicron"],["928","Pi"],["929","Rho"],["931","Sigma"],["932","Tau"],["933","Upsilon"],["934","Phi"],["935","Chi"],["936","Psi"],["937","Omega"],["945","alpha"],["946","beta"],["947","gamma"],["948","delta"],["949","epsilon"],["950","zeta"],["951","eta"],["952","theta"],["953","iota"],["954","kappa"],["955","lambda"],["956","mu"],["957","nu"],["958","xi"],["959","omicron"],["960","pi"],["961","rho"],["962","final sigma"],["963","sigma"],["964","tau"],["965","upsilon"],["966","phi"],["967","chi"],["968","psi"],["969","omega"],["8501","alef symbol"],["982","pi symbol"],["8476","real part symbol"],["978","upsilon - hook symbol"],["8472","Weierstrass p"],["8465","imaginary part"],["8592","leftwards arrow"],["8593","upwards arrow"],["8594","rightwards arrow"],["8595","downwards arrow"],["8596","left right arrow"],["8629","carriage return"],["8656","leftwards double arrow"],["8657","upwards double arrow"],["8658","rightwards double arrow"],["8659","downwards double arrow"],["8660","left right double arrow"],["8756","therefore"],["8834","subset of"],["8835","superset of"],["8836","not a subset of"],["8838","subset of or equal to"],["8839","superset of or equal to"],["8853","circled plus"],["8855","circled times"],["8869","perpendicular"],["8901","dot operator"],["8968","left ceiling"],["8969","right ceiling"],["8970","left floor"],["8971","right floor"],["9001","left-pointing angle bracket"],["9002","right-pointing angle bracket"],["9674","lozenge"],["9824","black spade suit"],["9827","black club suit"],["9829","black heart suit"],["9830","black diamond suit"],["8194","en space"],["8195","em space"],["8201","thin space"],["8204","zero width non-joiner"],["8205","zero width joiner"],["8206","left-to-right mark"],["8207","right-to-left mark"],["173","soft hyphen"]];e.addButton("charmap",{icon:"charmap",tooltip:"Special character",onclick:a}),e.addMenuItem("charmap",{icon:"charmap",text:"Special character",onclick:a,context:"insert"})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/code/plugin.min.js b/web/resource/components/tinymce/plugins/code/plugin.min.js new file mode 100644 index 0000000..9e7e898 --- /dev/null +++ b/web/resource/components/tinymce/plugins/code/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("code",function(e){function o(){e.windowManager.open({title:"Source code",body:{type:"textbox",name:"code",multiline:!0,minWidth:e.getParam("code_dialog_width",600),minHeight:e.getParam("code_dialog_height",Math.min(tinymce.DOM.getViewPort().h-200,500)),value:e.getContent({source_view:!0}),spellcheck:!1,style:"direction: ltr; text-align: left"},onSubmit:function(o){e.focus(),e.undoManager.transact(function(){e.setContent(o.data.code)}),e.selection.setCursorLocation(),e.nodeChanged()}})}e.addCommand("mceCodeEditor",o),e.addButton("code",{icon:"code",tooltip:"Source code",onclick:o}),e.addMenuItem("code",{icon:"code",text:"Source code",context:"tools",onclick:o})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/contextmenu/plugin.min.js b/web/resource/components/tinymce/plugins/contextmenu/plugin.min.js new file mode 100644 index 0000000..66d034d --- /dev/null +++ b/web/resource/components/tinymce/plugins/contextmenu/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("contextmenu",function(e){var n,t=e.settings.contextmenu_never_use_native;e.on("contextmenu",function(i){var o;if(!i.ctrlKey||t){if(i.preventDefault(),o=e.settings.contextmenu||"link image multiimage inserttable | cell row column deletetable",n)n.show();else{var c=[];tinymce.each(o.split(/[ ,]/),function(n){var t=e.menuItems[n];"|"==n&&(t={text:n}),t&&(t.shortcut="",c.push(t))});for(var a=0;a'}),t+=""}),t+=""}var i=[["cool","cry","embarassed","foot-in-mouth"],["frown","innocent","kiss","laughing"],["money-mouth","sealed","smile","surprised"],["tongue-out","undecided","wink","yell"]];t.addButton("emoticons",{type:"panelbutton",panel:{role:"application",autohide:!0,html:a,onclick:function(e){var a=t.dom.getParent(e.target,"a");a&&(t.insertContent(''+a.getAttribute('),this.hide())}},tooltip:"Emoticons"})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/example/plugin.min.js b/web/resource/components/tinymce/plugins/example/plugin.min.js new file mode 100644 index 0000000..00a262e --- /dev/null +++ b/web/resource/components/tinymce/plugins/example/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("example",function(t,e){t.addButton("example",{text:"My button",icon:!1,onclick:function(){t.windowManager.open({title:"Example plugin",body:[{type:"textbox",name:"title",label:"Title"}],onsubmit:function(e){t.insertContent("Title: "+e.data.title)}})}}),t.addMenuItem("example",{text:"Example plugin",context:"tools",onclick:function(){t.windowManager.open({title:"TinyMCE site",url:e+"/dialog.html",width:600,height:400,buttons:[{text:"Insert",onclick:function(){var e=t.windowManager.getWindows()[0];t.insertContent(e.getContentWindow().document.getElementById("content").value),e.close()}},{text:"Close",onclick:"close"}]})}})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/example_dependency/plugin.min.js b/web/resource/components/tinymce/plugins/example_dependency/plugin.min.js new file mode 100644 index 0000000..e61bf47 --- /dev/null +++ b/web/resource/components/tinymce/plugins/example_dependency/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("example_dependency",function(){},["example"]); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/fullpage/plugin.min.js b/web/resource/components/tinymce/plugins/fullpage/plugin.min.js new file mode 100644 index 0000000..1da17c9 --- /dev/null +++ b/web/resource/components/tinymce/plugins/fullpage/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("fullpage",function(e){function t(){var t=n();e.windowManager.open({title:"Document properties",data:t,defaults:{type:"textbox",size:40},body:[{name:"title",label:"Title"},{name:"keywords",label:"Keywords"},{name:"description",label:"Description"},{name:"robots",label:"Robots"},{name:"author",label:"Author"},{name:"docencoding",label:"Encoding"}],onSubmit:function(e){l(tinymce.extend(t,e.data))}})}function n(){function t(e,t){var n=e.attr(t);return n||""}var n,l,a=i(),r={};return r.fontface=e.getParam("fullpage_default_fontface",""),r.fontsize=e.getParam("fullpage_default_fontsize",""),n=a.firstChild,7==n.type&&(r.xml_pi=!0,l=/encoding="([^"]+)"/.exec(n.value),l&&(r.docencoding=l[1])),n=a.getAll("#doctype")[0],n&&(r.doctype=""),n=a.getAll("title")[0],n&&n.firstChild&&(r.title=n.firstChild.value),s(a.getAll("meta"),function(e){var t,n=e.attr("name"),l=e.attr("http-equiv");n?r[n.toLowerCase()]=e.attr("content"):"Content-Type"==l&&(t=/charset\s*=\s*(.*)\s*/gi.exec(e.attr("content")),t&&(r.docencoding=t[1]))}),n=a.getAll("html")[0],n&&(r.langcode=t(n,"lang")||t(n,"xml:lang")),r.stylesheets=[],tinymce.each(a.getAll("link"),function(e){"stylesheet"==e.attr("rel")&&r.stylesheets.push(e.attr("href"))}),n=a.getAll("body")[0],n&&(r.langdir=t(n,"dir"),r.style=t(n,"style"),r.visited_color=t(n,"vlink"),r.link_color=t(n,"link"),r.active_color=t(n,"alink")),r}function l(t){function n(e,t,n){e.attr(t,n?n:void 0)}function l(e){r.firstChild?r.insert(e,r.firstChild):r.append(e)}var a,r,o,c,u,f=e.dom;a=i(),r=a.getAll("head")[0],r||(c=a.getAll("html")[0],r=new m("head",1),c.firstChild?c.insert(r,c.firstChild,!0):c.append(r)),c=a.firstChild,t.xml_pi?(u='version="1.0"',t.docencoding&&(u+=' encoding="'+t.docencoding+'"'),7!=c.type&&(c=new m("xml",7),a.insert(c,a.firstChild,!0)),c.value=u):c&&7==c.type&&c.remove(),c=a.getAll("#doctype")[0],t.doctype?(c||(c=new m("#doctype",10),t.xml_pi?a.insert(c,a.firstChild):l(c)),c.value=t.doctype.substring(9,t.doctype.length-1)):c&&c.remove(),c=null,s(a.getAll("meta"),function(e){"Content-Type"==e.attr("http-equiv")&&(c=e)}),t.docencoding?(c||(c=new m("meta",1),c.attr("http-equiv","Content-Type"),c.shortEnded=!0,l(c)),c.attr("content","text/html; charset="+t.docencoding)):c.remove(),c=a.getAll("title")[0],t.title?(c?c.empty():(c=new m("title",1),l(c)),c.append(new m("#text",3)).value=t.title):c&&c.remove(),s("keywords,description,author,copyright,robots".split(","),function(e){var n,i,r=a.getAll("meta"),o=t[e];for(n=0;n"))}function i(){return new tinymce.html.DomParser({validate:!1,root_name:"#document"}).parse(d)}function a(t){function n(e){return e.replace(/<\/?[A-Z]+/g,function(e){return e.toLowerCase()})}var l,a,o,m,u=t.content,f="",g=e.dom;if(!t.selection&&!("raw"==t.format&&d||t.source_view&&e.getParam("fullpage_hide_in_source_view"))){u=u.replace(/<(\/?)BODY/gi,"<$1body"),l=u.indexOf("",l),d=n(u.substring(0,l+1)),a=u.indexOf("\n"),o=i(),s(o.getAll("style"),function(e){e.firstChild&&(f+=e.firstChild.value)}),m=o.getAll("body")[0],m&&g.setAttribs(e.getBody(),{style:m.attr("style")||"",dir:m.attr("dir")||"",vLink:m.attr("vlink")||"",link:m.attr("link")||"",aLink:m.attr("alink")||""}),g.remove("fullpage_styles");var y=e.getDoc().getElementsByTagName("head")[0];f&&(g.add(y,"style",{id:"fullpage_styles"},f),m=g.get("fullpage_styles"),m.styleSheet&&(m.styleSheet.cssText=f));var h={};tinymce.each(y.getElementsByTagName("link"),function(e){"stylesheet"==e.rel&&e.getAttribute("data-mce-fullpage")&&(h[e.href]=e)}),tinymce.each(o.getAll("link"),function(e){var t=e.attr("href");h[t]||"stylesheet"!=e.attr("rel")||g.add(y,"link",{rel:"stylesheet",text:"text/css",href:t,"data-mce-fullpage":"1"}),delete h[t]}),tinymce.each(h,function(e){e.parentNode.removeChild(e)})}}function r(){var t,n="",l="";return e.getParam("fullpage_default_xml_pi")&&(n+='\n'),n+=e.getParam("fullpage_default_doctype",""),n+="\n\n\n",(t=e.getParam("fullpage_default_title"))&&(n+=""+t+"\n"),(t=e.getParam("fullpage_default_encoding"))&&(n+='\n'),(t=e.getParam("fullpage_default_font_family"))&&(l+="font-family: "+t+";"),(t=e.getParam("fullpage_default_font_size"))&&(l+="font-size: "+t+";"),(t=e.getParam("fullpage_default_text_color"))&&(l+="color: "+t+";"),n+="\n\n"}function o(t){t.selection||t.source_view&&e.getParam("fullpage_hide_in_source_view")||(t.content=tinymce.trim(d)+"\n"+tinymce.trim(t.content)+"\n"+tinymce.trim(c))}var d,c,s=tinymce.each,m=tinymce.html.Node;e.addCommand("mceFullPageProperties",t),e.addButton("fullpage",{title:"Document properties",cmd:"mceFullPageProperties"}),e.addMenuItem("fullpage",{text:"Document properties",cmd:"mceFullPageProperties",context:"file"}),e.on("BeforeSetContent",a),e.on("GetContent",o)}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/fullscreen/plugin.min.js b/web/resource/components/tinymce/plugins/fullscreen/plugin.min.js new file mode 100644 index 0000000..1bb1940 --- /dev/null +++ b/web/resource/components/tinymce/plugins/fullscreen/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("fullscreen",function(e){function t(){var e,t,n=window,i=document,l=i.body;return l.offsetWidth&&(e=l.offsetWidth,t=l.offsetHeight),n.innerWidth&&n.innerHeight&&(e=n.innerWidth,t=n.innerHeight),{w:e,h:t}}function n(){function n(){d.setStyle(a,"height",t().h-(h.clientHeight-a.clientHeight))}var u,h,a,f,m=document.body,g=document.documentElement;s=!s,h=e.getContainer(),u=h.style,a=e.getContentAreaContainer().firstChild,f=a.style,s?(i=f.width,l=f.height,f.width=f.height="100%",c=u.width,o=u.height,u.width=u.height="",d.addClass(m,"mce-fullscreen"),d.addClass(g,"mce-fullscreen"),d.addClass(h,"mce-fullscreen"),d.bind(window,"resize",n),n(),r=n):(f.width=i,f.height=l,c&&(u.width=c),o&&(u.height=o),d.removeClass(m,"mce-fullscreen"),d.removeClass(g,"mce-fullscreen"),d.removeClass(h,"mce-fullscreen"),d.unbind(window,"resize",r)),e.fire("FullscreenStateChanged",{state:s})}var i,l,r,c,o,s=!1,d=tinymce.DOM;return e.settings.inline?void 0:(e.on("init",function(){e.addShortcut("Ctrl+Alt+F","",n)}),e.on("remove",function(){r&&d.unbind(window,"resize",r)}),e.addCommand("mceFullScreen",n),e.addMenuItem("fullscreen",{text:"Fullscreen",shortcut:"Ctrl+Alt+F",selectable:!0,onClick:n,onPostRender:function(){var t=this;e.on("FullscreenStateChanged",function(e){t.active(e.state)})},context:"view"}),e.addButton("fullscreen",{tooltip:"Fullscreen",shortcut:"Ctrl+Alt+F",onClick:n,onPostRender:function(){var t=this;e.on("FullscreenStateChanged",function(e){t.active(e.state)})}}),{isFullscreen:function(){return s}})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/hr/plugin.min.js b/web/resource/components/tinymce/plugins/hr/plugin.min.js new file mode 100644 index 0000000..e5ff6f3 --- /dev/null +++ b/web/resource/components/tinymce/plugins/hr/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("hr",function(n){n.addCommand("InsertHorizontalRule",function(){n.execCommand("mceInsertContent",!1,"


")}),n.addButton("hr",{icon:"hr",tooltip:"Horizontal line",cmd:"InsertHorizontalRule"}),n.addMenuItem("hr",{icon:"hr",text:"Horizontal line",cmd:"InsertHorizontalRule",context:"insert"})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/image/plugin.min.js b/web/resource/components/tinymce/plugins/image/plugin.min.js new file mode 100644 index 0000000..7c6b3b6 --- /dev/null +++ b/web/resource/components/tinymce/plugins/image/plugin.min.js @@ -0,0 +1,48 @@ +tinymce.PluginManager.add('image', function(editor) { + function handleImageDialog() { + var dom = editor.dom; + var imgElm = editor.selection.getNode(); + require(['util'], function(u){ + var v = ''; + if (imgElm && imgElm.tagName.toLowerCase() == 'img') { + v = imgElm.src; + } + u.image(v, function(val){ + data = { + src: val.url, + alt: val.filename, + title: val.filename + }; + + if (!data["class"]) { + delete data["class"]; + } + + if (!imgElm || imgElm.tagName.toLowerCase() != 'img') { + data.id = '__mcenew'; + editor.focus(); + editor.selection.setContent(dom.createHTML('img', data)); + imgElm = dom.get('__mcenew'); + dom.setAttrib(imgElm, 'id', null); + } else { + dom.setAttribs(imgElm, data); + } + },'', {direct: true, multi : false} ); + }); + } + + editor.addButton('image', { + icon: 'image', + tooltip: 'Insert/edit image', + onclick: handleImageDialog, + stateSelector: 'img:not([data-mce-object],[data-mce-placeholder])' + }); + + editor.addMenuItem('image', { + icon: 'image', + text: 'Insert image', + onclick: handleImageDialog, + context: 'insert', + prependToContext: true + }); +}); diff --git a/web/resource/components/tinymce/plugins/importcss/plugin.min.js b/web/resource/components/tinymce/plugins/importcss/plugin.min.js new file mode 100644 index 0000000..5dd1d44 --- /dev/null +++ b/web/resource/components/tinymce/plugins/importcss/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("importcss",function(t){function e(t){return"string"==typeof t?function(e){return-1!==e.indexOf(t)}:t instanceof RegExp?function(e){return t.test(e)}:t}function n(e,n){function i(t,e){var c,o=t.href;if(o&&n(o,e)){s(t.imports,function(t){i(t,!0)});try{c=t.cssRules||t.rules}catch(a){}s(c,function(t){t.styleSheet?i(t.styleSheet,!0):t.selectorText&&s(t.selectorText.split(","),function(t){r.push(tinymce.trim(t))})})}}var r=[],c={};s(t.contentCSS,function(t){c[t]=!0}),n||(n=function(t,e){return e||c[t]});try{s(e.styleSheets,function(t){i(t)})}catch(o){}return r}function i(e){var n,i=/^(?:([a-z0-9\-_]+))?(\.[a-z0-9_\-\.]+)$/i.exec(e);if(i){var r=i[1],s=i[2].substr(1).split(".").join(" "),c=tinymce.makeMap("a,img");return i[1]?(n={title:e},t.schema.getTextBlockElements()[r]?n.block=r:t.schema.getBlockElements()[r]||c[r.toLowerCase()]?n.selector=r:n.inline=r):i[2]&&(n={inline:"span",title:e.substr(1),classes:s}),t.settings.importcss_merge_classes!==!1?n.classes=s:n.attributes={"class":s},n}}var r=this,s=tinymce.each;t.on("renderFormatsMenu",function(c){var o=t.settings,a={},l=o.importcss_selector_converter||i,f=e(o.importcss_selector_filter),m=c.control;t.settings.importcss_append||m.items().remove();var u=[];tinymce.each(o.importcss_groups,function(t){t=tinymce.extend({},t),t.filter=e(t.filter),u.push(t)}),s(n(c.doc||t.getDoc(),e(o.importcss_file_filter)),function(e){if(-1===e.indexOf(".mce-")&&!a[e]&&(!f||f(e))){var n,i=l.call(r,e);if(i){var s=i.name||tinymce.DOM.uniqueId();if(u)for(var c=0;c'+n+"";var i=e.dom.getParent(e.selection.getStart(),"time");if(i)return void e.dom.setOuterHTML(i,n)}e.insertContent(n)}var n,r,i="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),d="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),c="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),m="January February March April May June July August September October November December".split(" "),u=[];e.addCommand("mceInsertDate",function(){a(e.getParam("insertdatetime_dateformat",e.translate("%Y-%m-%d")))}),e.addCommand("mceInsertTime",function(){a(e.getParam("insertdatetime_timeformat",e.translate("%H:%M:%S")))}),e.addButton("insertdatetime",{type:"splitbutton",title:"Insert date/time",onclick:function(){a(n||r)},menu:u}),tinymce.each(e.settings.insertdatetime_formats||["%H:%M:%S","%Y-%m-%d","%I:%M:%S %p","%D"],function(e){r||(r=e),u.push({text:t(e),onclick:function(){n=e,a(e)}})}),e.addMenuItem("insertdatetime",{icon:"date",text:"Insert date/time",menu:u,context:"insert"})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/layer/plugin.min.js b/web/resource/components/tinymce/plugins/layer/plugin.min.js new file mode 100644 index 0000000..f100292 --- /dev/null +++ b/web/resource/components/tinymce/plugins/layer/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("layer",function(e){function t(e){do if(e.className&&-1!=e.className.indexOf("mceItemLayer"))return e;while(e=e.parentNode)}function o(t){var o=e.dom;tinymce.each(o.select("div,p",t),function(e){/^(absolute|relative|fixed)$/i.test(e.style.position)&&(e.hasVisual?o.addClass(e,"mceItemVisualAid"):o.removeClass(e,"mceItemVisualAid"),o.addClass(e,"mceItemLayer"))})}function d(o){var d,n,a=[],i=t(e.selection.getNode()),s=-1,l=-1;for(n=[],tinymce.walk(e.getBody(),function(e){1==e.nodeType&&/^(absolute|relative|static)$/i.test(e.style.position)&&n.push(e)},"childNodes"),d=0;ds&&n[d]==i&&(s=d);if(0>o){for(d=0;d-1?(n[s].style.zIndex=a[l],n[l].style.zIndex=a[s]):a[s]>0&&(n[s].style.zIndex=a[s]-1)}else{for(d=0;da[s]){l=d;break}l>-1?(n[s].style.zIndex=a[l],n[l].style.zIndex=a[s]):n[s].style.zIndex=a[s]+1}e.execCommand("mceRepaint")}function n(){var t=e.dom,o=t.getPos(t.getParent(e.selection.getNode(),"*")),d=e.getBody();e.dom.add(d,"div",{style:{position:"absolute",left:o.x,top:o.y>20?o.y:20,width:100,height:100},"class":"mceItemVisualAid mceItemLayer"},e.selection.getContent()||e.getLang("layer.content")),tinymce.Env.ie&&t.setHTML(d,d.innerHTML)}function a(){var o=t(e.selection.getNode());o||(o=e.dom.getParent(e.selection.getNode(),"DIV,P,IMG")),o&&("absolute"==o.style.position.toLowerCase()?(e.dom.setStyles(o,{position:"",left:"",top:"",width:"",height:""}),e.dom.removeClass(o,"mceItemVisualAid"),e.dom.removeClass(o,"mceItemLayer")):(o.style.left||(o.style.left="20px"),o.style.top||(o.style.top="20px"),o.style.width||(o.style.width=o.width?o.width+"px":"100px"),o.style.height||(o.style.height=o.height?o.height+"px":"100px"),o.style.position="absolute",e.dom.setAttrib(o,"data-mce-style",""),e.addVisual(e.getBody())),e.execCommand("mceRepaint"),e.nodeChanged())}e.addCommand("mceInsertLayer",n),e.addCommand("mceMoveForward",function(){d(1)}),e.addCommand("mceMoveBackward",function(){d(-1)}),e.addCommand("mceMakeAbsolute",function(){a()}),e.addButton("moveforward",{title:"layer.forward_desc",cmd:"mceMoveForward"}),e.addButton("movebackward",{title:"layer.backward_desc",cmd:"mceMoveBackward"}),e.addButton("absolute",{title:"layer.absolute_desc",cmd:"mceMakeAbsolute"}),e.addButton("insertlayer",{title:"layer.insertlayer_desc",cmd:"mceInsertLayer"}),e.on("init",function(){tinymce.Env.ie&&e.getDoc().execCommand("2D-Position",!1,!0)}),e.on("mouseup",function(o){var d=t(o.target);d&&e.dom.setAttrib(d,"data-mce-style","")}),e.on("mousedown",function(o){var d,n=o.target,a=e.getDoc();tinymce.Env.gecko&&(t(n)?"on"!==a.designMode&&(a.designMode="on",n=a.body,d=n.parentNode,d.removeChild(n),d.appendChild(n)):"on"==a.designMode&&(a.designMode="off"))}),e.on("NodeChange",o)}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/legacyoutput/plugin.min.js b/web/resource/components/tinymce/plugins/legacyoutput/plugin.min.js new file mode 100644 index 0000000..f77d8e8 --- /dev/null +++ b/web/resource/components/tinymce/plugins/legacyoutput/plugin.min.js @@ -0,0 +1 @@ +!function(e){e.on("AddEditor",function(e){e.editor.settings.inline_styles=!1}),e.PluginManager.add("legacyoutput",function(t){t.on("init",function(){var i="p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img",n=e.explode(t.settings.font_size_style_values),l=t.schema;t.formatter.register({alignleft:{selector:i,attributes:{align:"left"}},aligncenter:{selector:i,attributes:{align:"center"}},alignright:{selector:i,attributes:{align:"right"}},alignjustify:{selector:i,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:!0}],strikethrough:[{inline:"strike",remove:"all"},{inline:"span",styles:{textDecoration:"line-through"},exact:!0}],fontname:{inline:"font",attributes:{face:"%value"}},fontsize:{inline:"font",attributes:{size:function(t){return e.inArray(n,t.value)+1}}},forecolor:{inline:"font",attributes:{color:"%value"}},hilitecolor:{inline:"font",styles:{backgroundColor:"%value"}}}),e.each("b,i,u,strike".split(","),function(e){l.addValidElements(e+"[*]")}),l.getElementRule("font")||l.addValidElements("font[face|size|color|style]"),e.each(i.split(","),function(e){var t=l.getElementRule(e);t&&(t.attributes.align||(t.attributes.align={},t.attributesOrder.push("align")))})})})}(tinymce); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/link/plugin.min.js b/web/resource/components/tinymce/plugins/link/plugin.min.js new file mode 100644 index 0000000..75d5c6f --- /dev/null +++ b/web/resource/components/tinymce/plugins/link/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("link",function(t){function e(e){return function(){var n=t.settings.link_list;"string"==typeof n?tinymce.util.XHR.send({url:n,success:function(t){e(tinymce.util.JSON.parse(t))}}):"function"==typeof n?n(e):e(n)}}function n(e){function n(t){var e=d.find("#text");(!e.value()||t.lastControl&&e.value()==t.lastControl.text())&&e.value(t.control.text()),d.find("#href").value(t.control.value())}function l(){function n(e,l){return l=l||[],tinymce.each(e,function(e){var i={text:e.text||e.title};e.menu?i.menu=n(e.menu):i.value=t.convertURL(e.value||e.url,"href"),l.push(i)}),l}return n(e,[{text:"None",value:""}])}function i(e){return tinymce.each(e,function(e){e.textStyle=function(){return t.formatter.getCssText({inline:"a",classes:[e.value]})}}),e}function a(e,n,l){var i,a=[];return tinymce.each(t.settings[e]||l,function(t){var e={text:t.text||t.title,value:t.value};a.push(e),(b[n]===t.value||!i&&t.selected)&&(i=e)}),i&&!b[n]&&(b[n]=i.value,i.selected=!0),a}function r(e){var l=[];return tinymce.each(t.dom.select("a:not([href])"),function(t){var n=t.name||t.id;n&&l.push({text:n,value:"#"+n,selected:-1!=e.indexOf("#"+n)})}),l.length?(l.unshift({text:"None",value:""}),{name:"anchor",type:"listbox",label:"Anchors",values:l,onselect:n}):void 0}function o(){h&&h.value(t.convertURL(this.value(),"href")),!f&&0===b.text.length&&x&&this.parent().parent().find("#text")[0].value(this.value())}function s(t){var e=k.getContent();if(/]+>[^<]+<\/a>$/.test(e)||-1==e.indexOf("href=")))return!1;if(t){var n,l=t.childNodes;if(0===l.length)return!1;for(n=l.length-1;n>=0;n--)if(3!=l[n].nodeType)return!1}return!0}var u,c,f,d,x,v,h,g,m,p,y,b={},k=t.selection,w=t.dom;u=k.getNode(),c=w.getParent(u,"a[href]"),x=s(),b.text=f=c?c.innerText||c.textContent:k.getContent({format:"text"}),b.href=c?w.getAttrib(c,"href"):"",b.target=c?w.getAttrib(c,"target"):t.settings.default_link_target||null,b.rel=c?w.getAttrib(c,"rel"):null,b["class"]=c?w.getAttrib(c,"class"):null,b.title=c?w.getAttrib(c,"title"):"",x&&(v={name:"text",type:"textbox",size:40,label:"Text to display",onchange:function(){b.text=this.value()}}),e&&(h={type:"listbox",label:"Link list",values:l(),onselect:n,value:t.convertURL(b.href,"href"),onPostRender:function(){h=this}}),t.settings.target_list!==!1&&(m={name:"target",type:"listbox",label:"Target",values:a("target_list","target",[{text:"None",value:""},{text:"New window",value:"_blank"}])}),t.settings.rel_list&&(g={name:"rel",type:"listbox",label:"Rel",values:a("rel_list","rel",[{text:"None",value:""}])}),t.settings.link_class_list&&(p={name:"class",type:"listbox",label:"Class",values:i(a("link_class_list","class"))}),t.settings.link_title!==!1&&(y={name:"title",type:"textbox",label:"Title",value:b.title}),d=t.windowManager.open({title:"Insert link",data:b,body:[{name:"href",type:"filepicker",filetype:"file",size:40,autofocus:!0,label:"Url",onchange:o,onkeyup:o},v,y,r(b.href),h,g,m,p],onSubmit:function(e){function n(e,n){var l=t.selection.getRng();window.setTimeout(function(){t.windowManager.confirm(e,function(e){t.selection.setRng(l),n(e)})},0)}function l(){var e={href:i,target:b.target?b.target:null,rel:b.rel?b.rel:null,"class":b["class"]?b["class"]:null,title:b.title?b.title:null};c?(t.focus(),x&&b.text!=f&&("innerText"in c?c.innerText=b.text:c.textContent=b.text),w.setAttribs(c,e),k.select(c),t.undoManager.add()):x?t.insertContent(w.createHTML("a",e,w.encode(b.text))):t.execCommand("mceInsertLink",!1,e)}var i;return b=tinymce.extend(b,e.data),(i=b.href)?i.indexOf("@")>0&&-1==i.indexOf("//")&&-1==i.indexOf("mailto:")?void n("The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?",function(t){t&&(i="mailto:"+i),l()}):/^\s*www\./i.test(i)?void n("The URL you entered seems to be an external link. Do you want to add the required http:// prefix?",function(t){t&&(i="http://"+i),l()}):void l():void t.execCommand("unlink")}})}t.addButton("link",{icon:"link",tooltip:"Insert/edit link",shortcut:"Ctrl+K",onclick:e(n),stateSelector:"a[href]"}),t.addButton("unlink",{icon:"unlink",tooltip:"Remove link",cmd:"unlink",stateSelector:"a[href]"}),t.addShortcut("Ctrl+K","",e(n)),this.showDialog=n,t.addMenuItem("link",{icon:"link",text:"Insert link",shortcut:"Ctrl+K",onclick:e(n),stateSelector:"a[href]",context:"insert",prependToContext:!0})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/lists/plugin.min.js b/web/resource/components/tinymce/plugins/lists/plugin.min.js new file mode 100644 index 0000000..cf0e600 --- /dev/null +++ b/web/resource/components/tinymce/plugins/lists/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("lists",function(e){function t(e){return e&&/^(OL|UL|DL)$/.test(e.nodeName)}function n(e){return e.parentNode.firstChild==e}function r(e){return e.parentNode.lastChild==e}function a(t){return t&&!!e.schema.getTextBlockElements()[t.nodeName]}var o=this;e.on("init",function(){function i(e){function t(t){var r,a,o;a=e[t?"startContainer":"endContainer"],o=e[t?"startOffset":"endOffset"],1==a.nodeType&&(r=y.create("span",{"data-mce-type":"bookmark"}),a.hasChildNodes()?(o=Math.min(o,a.childNodes.length-1),t?a.insertBefore(r,a.childNodes[o]):y.insertAfter(r,a.childNodes[o])):a.appendChild(r),a=r,o=0),n[t?"startContainer":"endContainer"]=a,n[t?"startOffset":"endOffset"]=o}var n={};return t(!0),e.collapsed||t(),n}function d(e){function t(t){function n(e){for(var t=e.parentNode.firstChild,n=0;t;){if(t==e)return n;(1!=t.nodeType||"bookmark"!=t.getAttribute("data-mce-type"))&&n++,t=t.nextSibling}return-1}var r,a,o;r=o=e[t?"startContainer":"endContainer"],a=e[t?"startOffset":"endOffset"],r&&(1==r.nodeType&&(a=n(r),r=r.parentNode,y.remove(o)),e[t?"startContainer":"endContainer"]=r,e[t?"startOffset":"endOffset"]=a)}t(!0),t();var n=y.createRng();n.setStart(e.startContainer,e.startOffset),e.endContainer&&n.setEnd(e.endContainer,e.endOffset),k.setRng(n)}function s(t,n){var r,a,o,i=y.createFragment(),d=e.schema.getBlockElements();if(e.settings.forced_root_block&&(n=n||e.settings.forced_root_block),n&&(a=y.create(n),a.tagName===e.settings.forced_root_block&&y.setAttribs(a,e.settings.forced_root_block_attrs),i.appendChild(a)),t)for(;r=t.firstChild;){var s=r.nodeName;o||"SPAN"==s&&"bookmark"==r.getAttribute("data-mce-type")||(o=!0),d[s]?(i.appendChild(r),a=null):n?(a||(a=y.create(n),i.appendChild(a)),a.appendChild(r)):i.appendChild(r)}return e.settings.forced_root_block?o||tinymce.Env.ie&&!(tinymce.Env.ie>10)||a.appendChild(y.create("br",{"data-mce-bogus":"1"})):i.appendChild(y.create("br")),i}function f(){return tinymce.grep(k.getSelectedBlocks(),function(e){return/^(LI|DT|DD)$/.test(e.nodeName)})}function l(e,t,n){var r,a,o=y.select('span[data-mce-type="bookmark"]',e);n=n||s(t),r=y.createRng(),r.setStartAfter(t),r.setEndAfter(e),a=r.extractContents(),y.isEmpty(a)||y.insertAfter(a,e),y.insertAfter(n,e),y.isEmpty(t.parentNode)&&(tinymce.each(o,function(e){t.parentNode.parentNode.insertBefore(e,t.parentNode)}),y.remove(t.parentNode)),y.remove(t)}function c(e){var n,r;if(n=e.nextSibling,n&&t(n)&&n.nodeName==e.nodeName){for(;r=n.firstChild;)e.appendChild(r);y.remove(n)}if(n=e.previousSibling,n&&t(n)&&n.nodeName==e.nodeName){for(;r=n.firstChild;)e.insertBefore(r,e.firstChild);y.remove(n)}}function p(e){tinymce.each(tinymce.grep(y.select("ol,ul",e)),function(e){var n,r=e.parentNode;"LI"==r.nodeName&&r.firstChild==e&&(n=r.previousSibling,n&&"LI"==n.nodeName&&(n.appendChild(e),y.isEmpty(r)&&y.remove(r))),t(r)&&(n=r.previousSibling,n&&"LI"==n.nodeName&&n.appendChild(e))})}function m(e){function a(e){y.isEmpty(e)&&y.remove(e)}var o,i=e.parentNode,d=i.parentNode;return"DD"==e.nodeName?(y.rename(e,"DT"),!0):n(e)&&r(e)?("LI"==d.nodeName?(y.insertAfter(e,d),a(d),y.remove(i)):t(d)?y.remove(i,!0):(d.insertBefore(s(e),i),y.remove(i)),!0):n(e)?("LI"==d.nodeName?(y.insertAfter(e,d),e.appendChild(i),a(d)):t(d)?d.insertBefore(e,i):(d.insertBefore(s(e),i),y.remove(e)),!0):r(e)?("LI"==d.nodeName?y.insertAfter(e,d):t(d)?y.insertAfter(e,i):(y.insertAfter(s(e),i),y.remove(e)),!0):("LI"==d.nodeName?(i=d,o=s(e,"LI")):o=t(d)?s(e,"LI"):s(e),l(i,e,o),p(i.parentNode),!0)}function u(e){function n(n,r){var a;if(t(n)){for(;a=e.lastChild.firstChild;)r.appendChild(a);y.remove(n)}}var r,a;return"DT"==e.nodeName?(y.rename(e,"DD"),!0):(r=e.previousSibling,r&&t(r)?(r.appendChild(e),!0):r&&"LI"==r.nodeName&&t(r.lastChild)?(r.lastChild.appendChild(e),n(e.lastChild,r.lastChild),!0):(r=e.nextSibling,r&&t(r)?(r.insertBefore(e,r.firstChild),!0):r&&"LI"==r.nodeName&&t(e.lastChild)?!1:(r=e.previousSibling,r&&"LI"==r.nodeName?(a=y.create(e.parentNode.nodeName),r.appendChild(a),a.appendChild(e),n(e.lastChild,a),!0):!1)))}function h(){var t=f();if(t.length){for(var n=i(k.getRng(!0)),r=0;r0))return n;for(var a=new tinymce.dom.TreeWalker(e.startContainer);n=a[t?"next":"prev"]();)if(3==n.nodeType&&n.data.length>0)return n}function r(e,n){var r,a,o=e.parentNode;for(t(n.lastChild)&&(a=n.lastChild),r=n.lastChild,r&&"BR"==r.nodeName&&e.hasChildNodes()&&y.remove(r);r=e.firstChild;)n.appendChild(r);a&&n.appendChild(a),y.remove(e),y.isEmpty(o)&&y.remove(o)}if(k.isCollapsed()){var a=y.getParent(k.getStart(),"LI");if(a){var o=k.getRng(!0),s=y.getParent(n(o,e),"LI");if(s&&s!=a){var f=i(o);return e?r(s,a):r(a,s),d(f),!0}if(!s&&!e&&g(a.parentNode.nodeName))return!0}}},e.addCommand("Indent",function(){return h()?void 0:!0}),e.addCommand("Outdent",function(){return v()?void 0:!0}),e.addCommand("InsertUnorderedList",function(){N("UL")}),e.addCommand("InsertOrderedList",function(){N("OL")}),e.addCommand("InsertDefinitionList",function(){N("DL")}),e.addQueryStateHandler("InsertUnorderedList",L("UL")),e.addQueryStateHandler("InsertOrderedList",L("OL")),e.addQueryStateHandler("InsertDefinitionList",L("DL")),e.on("keydown",function(t){9==t.keyCode&&e.dom.getParent(e.selection.getStart(),"LI,DT,DD")&&(t.preventDefault(),t.shiftKey?v():h())})}),e.addButton("indent",{icon:"indent",title:"Increase indent",cmd:"Indent",onPostRender:function(){var t=this;e.on("nodechange",function(){for(var r=e.selection.getSelectedBlocks(),a=!1,o=0,i=r.length;!a&&i>o;o++){var d=r[o].nodeName;a="LI"==d&&n(r[o])||"UL"==d||"OL"==d||"DD"==d}t.disabled(a)})}}),e.on("keydown",function(e){e.keyCode==tinymce.util.VK.BACKSPACE?o.backspaceDelete()&&e.preventDefault():e.keyCode==tinymce.util.VK.DELETE&&o.backspaceDelete(!0)&&e.preventDefault()})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/media/plugin.min.js b/web/resource/components/tinymce/plugins/media/plugin.min.js new file mode 100644 index 0000000..cb1515c --- /dev/null +++ b/web/resource/components/tinymce/plugins/media/plugin.min.js @@ -0,0 +1,779 @@ +/** + * plugin.js + * + * Copyright, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +/*jshint maxlen:255 */ +/*eslint max-len:0 */ +/*global tinymce:true */ + +tinymce.PluginManager.add('media', function(editor, url) { + var urlPatterns = [ + {regex: /youtu\.be\/([\w\-.]+)/, type: 'iframe', w: '100%', h: '250px', url: '//www.youtube.com/embed/$1'}, + {regex: /youtube\.com(.+)v=([^&]+)/, type: 'iframe', w: '100%', h: '250px', url: '//www.youtube.com/embed/$2'}, + {regex: /vimeo\.com\/([0-9]+)/, type: 'iframe', w: '100%', h: '250px', url: '//player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc'}, + {regex: /vimeo\.com\/(.*)\/([0-9]+)/, type: "iframe", w: '100%', h: '250px', url: "//player.vimeo.com/video/$2?title=0&byline=0"}, + {regex: /maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/, type: 'iframe', w: '100%', h: '250px', url: '//maps.google.com/maps/ms?msid=$2&output=embed"'}, + {regex: /v\.youku\.com\/v_show\/id_([\w\-=]+)\.html/, type: 'iframe', w: '100%', h: '250px', url: '//player.youku.com/embed/$1'}, + {regex: /tudou\.com\/(listplay|albumplay)\/([\w\-=]+)\/([\w\-=]+)\.html/, type: 'iframe', w: '100%', h: '250px', url: '//www.tudou.com/programs/view/html5embed.action?type=0&code=$3&lcode='}, + {regex: /tudou\.com\/programs\/view\/([\w\-=]+)\//, type: 'iframe', w: '100%', h: '250px', url: '//www.tudou.com/programs/view/html5embed.action?type=0&code=$1&lcode='}, + {regex: /56\.com\/([\w\-=]+)\/v_([\w\-=]+)\.html/, type: 'iframe', w: '100%', h: '250px', url: '//www.56.com/iframe/$2"'}, + {regex: /v\.ku6\.com\/.+\/([\w\-=._]+)\.html.*$/, type: 'iframe', w: '100%', h: '250px', url: '//player.ku6.com/refer/$1/v.swf'} + ]; + + var embedChange = (tinymce.Env.ie && tinymce.Env.ie <= 8) ? 'onChange' : 'onInput'; + + function guessMime(url) { + if (url.indexOf('.mp3') != -1) { + return 'audio/mpeg'; + } + + if (url.indexOf('.wav') != -1) { + return 'audio/wav'; + } + + if (url.indexOf('.mp4') != -1) { + return 'video/mp4'; + } + + if (url.indexOf('.webm') != -1) { + return 'video/webm'; + } + + if (url.indexOf('.ogg') != -1) { + return 'video/ogg'; + } + + if (url.indexOf('.swf') != -1) { + return 'application/x-shockwave-flash'; + } + + return ''; + } + + function getVideoScriptMatch(src) { + var prefixes = editor.settings.media_scripts; + + if (prefixes) { + for (var i = 0; i < prefixes.length; i++) { + if (src.indexOf(prefixes[i].filter) !== -1) { + return prefixes[i]; + } + } + } + } + + function showDialog() { + var win, width, height, data; + + var generalFormItems = [ + { + name: 'source1', + type: 'filepicker', + filetype: 'media', + size: 40, + autofocus: true, + label: 'Source', + onchange: function(e) { + tinymce.each(e.meta, function(value, key) { + win.find('#' + key).value(value); + }); + } + } + ]; + + function recalcSize(e) { + var widthCtrl, heightCtrl, newWidth, newHeight; + + widthCtrl = win.find('#width')[0]; + heightCtrl = win.find('#height')[0]; + + newWidth = widthCtrl.value(); + newHeight = heightCtrl.value(); + + if (win.find('#constrain')[0].checked() && width && height && newWidth && newHeight) { + if (e.control == widthCtrl) { + newHeight = Math.round((newWidth / width) * newHeight); + heightCtrl.value(newHeight); + } else { + newWidth = Math.round((newHeight / height) * newWidth); + widthCtrl.value(newWidth); + } + } + + width = newWidth; + height = newHeight; + } + generalFormItems.push({type: 'label',text: '支持优酷、56、土豆、酷六',forId: ''}); + generalFormItems.push({type: 'label',text: '直接填写页面地址即可',forId: ''}); + generalFormItems.push({type: 'label',text: '其它视频请复制“通用代码”到内嵌中',forId: ''}); + if (editor.settings.media_alt_source !== false) { + generalFormItems.push({name: 'source2', type: 'filepicker', filetype: 'media', size: 40, label: 'Alternative source'}); + } + + if (editor.settings.media_poster !== false) { + generalFormItems.push({name: 'poster', type: 'filepicker', filetype: 'image', size: 40, label: 'Poster'}); + } + + if (editor.settings.media_dimensions !== false) { + generalFormItems.push({ + type: 'container', + label: 'Dimensions', + layout: 'flex', + align: 'center', + spacing: 5, + items: [ + {name: 'width', type: 'textbox', maxLength: 3, size: 3, onchange: recalcSize}, + {type: 'label', text: 'x'}, + {name: 'height', type: 'textbox', maxLength: 3, size: 3, onchange: recalcSize}, + {name: 'constrain', type: 'checkbox', checked: true, text: 'Constrain proportions'} + ] + }); + } + + data = getData(editor.selection.getNode()); + width = data.width; + height = data.height; + + var embedTextBox = { + id: 'mcemediasource', + type: 'textbox', + flex: 1, + name: 'embed', + value: getSource(), + multiline: true, + label: 'Source' + }; + + function updateValueOnChange() { + data = htmlToData(this.value()); + this.parent().parent().fromJSON(data); + } + + embedTextBox[embedChange] = updateValueOnChange; + + win = editor.windowManager.open({ + title: 'Insert/edit video', + data: data, + bodyType: 'tabpanel', + body: [ + { + title: 'General', + type: "form", + onShowTab: function() { + data = htmlToData(this.next().find('#embed').value()); + this.fromJSON(data); + }, + items: generalFormItems + }, + + { + title: 'Embed', + type: "panel", + layout: 'flex', + direction: 'column', + align: 'stretch', + padding: 10, + spacing: 10, + onShowTab: function() { + this.find('#embed').value(dataToHtml(this.parent().toJSON())); + }, + items: [ + { + type: 'label', + text: 'Paste your embed code below:', + forId: 'mcemediasource' + }, + embedTextBox + ] + } + ], + onSubmit: function() { + var beforeObjects, afterObjects, i, y; + + beforeObjects = editor.dom.select('img[data-mce-object]'); + editor.insertContent(dataToHtml(this.toJSON())); + afterObjects = editor.dom.select('img[data-mce-object]'); + + // Find new image placeholder so we can select it + for (i = 0; i < beforeObjects.length; i++) { + for (y = afterObjects.length - 1; y >= 0; y--) { + if (beforeObjects[i] == afterObjects[y]) { + afterObjects.splice(y, 1); + } + } + } + + editor.selection.select(afterObjects[0]); + editor.nodeChanged(); + } + }); + } + + function getSource() { + var elm = editor.selection.getNode(); + + if (elm.getAttribute('data-mce-object')) { + return editor.selection.getContent(); + } + } + + function dataToHtml(data) { + var html = ''; + if (!data.source1) { + tinymce.extend(data, htmlToData(data.embed)); + if (!data.source1) { + return ''; + } + } + + if (!data.source2) { + data.source2 = ''; + } + + if (!data.poster) { + data.poster = ''; + } + + data.source1 = editor.convertURL(data.source1, "source"); + data.source2 = editor.convertURL(data.source2, "source"); + data.source1mime = guessMime(data.source1); + data.source2mime = guessMime(data.source2); + data.poster = editor.convertURL(data.poster, "poster"); + data.flashPlayerUrl = editor.convertURL(url + '/moxieplayer.swf', "movie"); + + tinymce.each(urlPatterns, function(pattern) { + var match, i, url; + + if ((match = pattern.regex.exec(data.source1))) { + url = pattern.url; + + for (i = 0; match[i]; i++) { + /*jshint loopfunc:true*/ + /*eslint no-loop-func:0 */ + url = url.replace('$' + i, function() { + return match[i]; + }); + } + + data.source1 = url; + data.type = pattern.type; + data.width = data.width || pattern.w; + data.height = data.height || pattern.h; + } + }); + + if (data.embed) { + html = updateHtml(data.embed, data, true); + } else { + var videoScript = getVideoScriptMatch(data.source1); + if (videoScript) { + data.type = 'script'; + data.width = videoScript.width; + data.height = videoScript.height; + } + + data.width = data.width || 300; + data.height = data.height || 150; + + tinymce.each(data, function(value, key) { + data[key] = editor.dom.encode(value); + }); + + if (data.type == "iframe") { + html += ''; + } else if (data.source1mime == "application/x-shockwave-flash") { + html += ''; + + if (data.poster) { + html += ''; + } + + html += ''; + } else if (data.source1mime.indexOf('audio') != -1) { + if (editor.settings.audio_template_callback) { + html = editor.settings.audio_template_callback(data); + } else { + html += ( + '' + ); + } + } else if (data.type == "script") { + html += ''; + } else { + if (editor.settings.video_template_callback) { + html = editor.settings.video_template_callback(data); + } else { + html = ( + '' + ); + } + } + } + + return html; + } + + function htmlToData(html) { + var data = {}; + + new tinymce.html.SaxParser({ + validate: false, + allow_conditional_comments: true, + special: 'script,noscript', + start: function(name, attrs) { + if (!data.source1 && name == "param") { + data.source1 = attrs.map.movie; + } + + if (name == "iframe" || name == "object" || name == "embed" || name == "video" || name == "audio") { + if (!data.type) { + data.type = name; + } + + data = tinymce.extend(attrs.map, data); + } + + if (name == "script") { + var videoScript = getVideoScriptMatch(attrs.map.src); + if (!videoScript) { + return; + } + + data = { + type: "script", + source1: attrs.map.src, + width: videoScript.width, + height: videoScript.height + }; + } + + if (name == "source") { + if (!data.source1) { + data.source1 = attrs.map.src; + } else if (!data.source2) { + data.source2 = attrs.map.src; + } + } + + if (name == "img" && !data.poster) { + data.poster = attrs.map.src; + } + } + }).parse(html); + + data.source1 = data.source1 || data.src || data.data; + data.source2 = data.source2 || ''; + data.poster = data.poster || ''; + + return data; + } + + function getData(element) { + if (element.getAttribute('data-mce-object')) { + return htmlToData(editor.serializer.serialize(element, {selection: true})); + } + + return {}; + } + + function sanitize(html) { + if (editor.settings.media_filter_html === false) { + return html; + } + + var writer = new tinymce.html.Writer(); + + new tinymce.html.SaxParser({ + validate: false, + allow_conditional_comments: false, + special: 'script,noscript', + + comment: function(text) { + writer.comment(text); + }, + + cdata: function(text) { + writer.cdata(text); + }, + + text: function(text, raw) { + writer.text(text, raw); + }, + + start: function(name, attrs, empty) { + if (name == 'script' || name == 'noscript') { + return; + } + + for (var i = 0; i < attrs.length; i++) { + if (attrs[i].name.indexOf('on') === 0) { + return; + } + } + + writer.start(name, attrs, empty); + }, + + end: function(name) { + if (name == 'script' || name == 'noscript') { + return; + } + + writer.end(name); + } + }, new tinymce.html.Schema({})).parse(html); + + return writer.getContent(); + } + + function updateHtml(html, data, updateAll) { + var writer = new tinymce.html.Writer(); + var sourceCount = 0, hasImage; + + function setAttributes(attrs, updatedAttrs) { + var name, i, value, attr; + + for (name in updatedAttrs) { + value = "" + updatedAttrs[name]; + + if (attrs.map[name]) { + i = attrs.length; + while (i--) { + attr = attrs[i]; + + if (attr.name == name) { + if (value) { + attrs.map[name] = value; + attr.value = value; + } else { + delete attrs.map[name]; + attrs.splice(i, 1); + } + } + } + } else if (value) { + attrs.push({ + name: name, + value: value + }); + + attrs.map[name] = value; + } + } + } + + new tinymce.html.SaxParser({ + validate: false, + allow_conditional_comments: true, + special: 'script,noscript', + + comment: function(text) { + writer.comment(text); + }, + + cdata: function(text) { + writer.cdata(text); + }, + + text: function(text, raw) { + writer.text(text, raw); + }, + + start: function(name, attrs, empty) { + switch (name) { + case "video": + case "object": + case "embed": + case "img": + case "iframe": + setAttributes(attrs, { + style: 'width:'+data.width+'; height:'+data.height+';' + }); + break; + } + + if (updateAll) { + switch (name) { + case "video": + setAttributes(attrs, { + poster: data.poster, + src: "" + }); + + if (data.source2) { + setAttributes(attrs, { + src: "" + }); + } + break; + + case "iframe": + setAttributes(attrs, { + src: data.source1 + }); + break; + + case "source": + sourceCount++; + + if (sourceCount <= 2) { + setAttributes(attrs, { + src: data["source" + sourceCount], + type: data["source" + sourceCount + "mime"] + }); + + if (!data["source" + sourceCount]) { + return; + } + } + break; + + case "img": + if (!data.poster) { + return; + } + + hasImage = true; + break; + } + } + + writer.start(name, attrs, empty); + }, + + end: function(name) { + if (name == "video" && updateAll) { + for (var index = 1; index <= 2; index++) { + if (data["source" + index]) { + var attrs = []; + attrs.map = {}; + + if (sourceCount < index) { + setAttributes(attrs, { + src: data["source" + index], + type: data["source" + index + "mime"] + }); + + writer.start("source", attrs, true); + } + } + } + } + + if (data.poster && name == "object" && updateAll && !hasImage) { + var imgAttrs = []; + imgAttrs.map = {}; + + setAttributes(imgAttrs, { + src: data.poster, + width: data.width, + height: data.height + }); + + writer.start("img", imgAttrs, true); + } + + writer.end(name); + } + }, new tinymce.html.Schema({})).parse(html); + + return writer.getContent(); + } + + editor.on('ResolveName', function(e) { + var name; + + if (e.target.nodeType == 1 && (name = e.target.getAttribute("data-mce-object"))) { + e.name = name; + } + }); + + editor.on('preInit', function() { + // Make sure that any messy HTML is retained inside these + var specialElements = editor.schema.getSpecialElements(); + tinymce.each('video audio iframe object'.split(' '), function(name) { + specialElements[name] = new RegExp('<\/' + name + '[^>]*>', 'gi'); + }); + + // Allow elements + //editor.schema.addValidElements('object[id|style|width|height|classid|codebase|*],embed[id|style|width|height|type|src|*],video[*],audio[*]'); + + // Set allowFullscreen attribs as boolean + var boolAttrs = editor.schema.getBoolAttrs(); + tinymce.each('webkitallowfullscreen mozallowfullscreen allowfullscreen'.split(' '), function(name) { + boolAttrs[name] = {}; + }); + + // Converts iframe, video etc into placeholder images + editor.parser.addNodeFilter('iframe,video,audio,object,embed,script', function(nodes, name) { + var i = nodes.length, ai, node, placeHolder, attrName, attrValue, attribs, innerHtml; + var videoScript; + + while (i--) { + node = nodes[i]; + if (!node.parent) { + continue; + } + + if (node.name == 'script') { + videoScript = getVideoScriptMatch(node.attr('src')); + if (!videoScript) { + continue; + } + } + + placeHolder = new tinymce.html.Node('img', 1); + placeHolder.shortEnded = true; + + if (videoScript) { + if (videoScript.width) { + node.attr('width', videoScript.width.toString()); + } + + if (videoScript.height) { + node.attr('height', videoScript.height.toString()); + } + } + + // Prefix all attributes except width, height and style since we + // will add these to the placeholder + attribs = node.attributes; + ai = attribs.length; + while (ai--) { + attrName = attribs[ai].name; + attrValue = attribs[ai].value; + + if (attrName !== "width" && attrName !== "height" && attrName !== "style") { + if (attrName == "data" || attrName == "src") { + attrValue = editor.convertURL(attrValue, attrName); + } + + placeHolder.attr('data-mce-p-' + attrName, attrValue); + } + } + + // Place the inner HTML contents inside an escaped attribute + // This enables us to copy/paste the fake object + innerHtml = node.firstChild && node.firstChild.value; + if (innerHtml) { + placeHolder.attr("data-mce-html", escape(innerHtml)); + placeHolder.firstChild = null; + } + + placeHolder.attr({ + width: node.attr('width') || "300", + height: node.attr('height') || (name == "audio" ? "30" : "150"), + style: node.attr('style'), + src: tinymce.Env.transparentSrc, + "data-mce-object": name, + "class": "mce-object mce-object-" + name + }); + + node.replace(placeHolder); + } + }); + + // Replaces placeholder images with real elements for video, object, iframe etc + editor.serializer.addAttributeFilter('data-mce-object', function(nodes, name) { + var i = nodes.length, node, realElm, ai, attribs, innerHtml, innerNode, realElmName; + + while (i--) { + node = nodes[i]; + if (!node.parent) { + continue; + } + + realElmName = node.attr(name); + realElm = new tinymce.html.Node(realElmName, 1); + + // Add width/height to everything but audio + if (realElmName != "audio" && realElmName != "script") { + realElm.attr({ + width: node.attr('width'), + height: node.attr('height') + }); + } + + realElm.attr({ + style: node.attr('style') + }); + + // Unprefix all placeholder attributes + attribs = node.attributes; + ai = attribs.length; + while (ai--) { + var attrName = attribs[ai].name; + + if (attrName.indexOf('data-mce-p-') === 0) { + realElm.attr(attrName.substr(11), attribs[ai].value); + } + } + + if (realElmName == "script") { + realElm.attr('type', 'text/javascript'); + } + + // Inject innerhtml + innerHtml = node.attr('data-mce-html'); + if (innerHtml) { + innerNode = new tinymce.html.Node('#text', 3); + innerNode.raw = true; + innerNode.value = sanitize(unescape(innerHtml)); + realElm.append(innerNode); + } + + node.replace(realElm); + } + }); + }); + + editor.on('ObjectSelected', function(e) { + var objectType = e.target.getAttribute('data-mce-object'); + + if (objectType == "audio" || objectType == "script") { + e.preventDefault(); + } + }); + + editor.on('objectResized', function(e) { + var target = e.target, html; + + if (target.getAttribute('data-mce-object')) { + html = target.getAttribute('data-mce-html'); + if (html) { + html = unescape(html); + target.setAttribute('data-mce-html', escape( + updateHtml(html, { + width: e.width, + height: e.height + }) + )); + } + } + }); + + editor.addButton('media', { + tooltip: 'Insert/edit video', + onclick: showDialog, + stateSelector: ['img[data-mce-object=video]', 'img[data-mce-object=iframe]'] + }); + + editor.addMenuItem('media', { + icon: 'media', + text: 'Insert video', + onclick: showDialog, + context: 'insert', + prependToContext: true + }); +}); diff --git a/web/resource/components/tinymce/plugins/multiimage/plugin.min.js b/web/resource/components/tinymce/plugins/multiimage/plugin.min.js new file mode 100644 index 0000000..2a67636 --- /dev/null +++ b/web/resource/components/tinymce/plugins/multiimage/plugin.min.js @@ -0,0 +1,38 @@ +tinymce.PluginManager.add('multiimage', function(editor) { + function handleImageDialog() { + var dom = editor.dom; + var imgElm = editor.selection.getNode(); + require(['util'], function(u){ + var v = ''; + if (imgElm && imgElm.tagName.toLowerCase() == 'img') { + v = imgElm.src; + } + u.uploadMultiPictures(function(list){ + for(var i=0;i 
':" "),n.dom.setAttrib(n.dom.select("span.mce-nbsp"),"data-mce-bogus","1")}),n.addButton("nonbreaking",{title:"Insert nonbreaking space",cmd:"mceNonBreaking"}),n.addMenuItem("nonbreaking",{text:"Nonbreaking space",cmd:"mceNonBreaking",context:"insert"}),e){var a=+e>1?+e:3;n.on("keydown",function(e){if(9==e.keyCode){if(e.shiftKey)return;e.preventDefault();for(var t=0;a>t;t++)n.execCommand("mceNonBreaking")}})}}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/noneditable/plugin.min.js b/web/resource/components/tinymce/plugins/noneditable/plugin.min.js new file mode 100644 index 0000000..aa642de --- /dev/null +++ b/web/resource/components/tinymce/plugins/noneditable/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("noneditable",function(e){function t(e){var t;if(1===e.nodeType){if(t=e.getAttribute(u),t&&"inherit"!==t)return t;if(t=e.contentEditable,"inherit"!==t)return t}return null}function n(e){for(var n;e;){if(n=t(e))return"false"===n?e:null;e=e.parentNode}}function r(){function r(e){for(;e;){if(e.id===g)return e;e=e.parentNode}}function a(e){var t;if(e)for(t=new f(e,e),e=t.current();e;e=t.next())if(3===e.nodeType)return e}function i(n,r){var a,i;return"false"===t(n)&&u.isBlock(n)?void s.select(n):(i=u.createRng(),"true"===t(n)&&(n.firstChild||n.appendChild(e.getDoc().createTextNode(" ")),n=n.firstChild,r=!0),a=u.create("span",{id:g,"data-mce-bogus":!0},m),r?n.parentNode.insertBefore(a,n):u.insertAfter(a,n),i.setStart(a.firstChild,1),i.collapse(!0),s.setRng(i),a)}function o(e){var t,n,i,o;if(e)t=s.getRng(!0),t.setStartBefore(e),t.setEndBefore(e),n=a(e),n&&n.nodeValue.charAt(0)==m&&(n=n.deleteData(0,1)),u.remove(e,!0),s.setRng(t);else for(i=r(s.getStart());(e=u.get(g))&&e!==o;)i!==e&&(n=a(e),n&&n.nodeValue.charAt(0)==m&&(n=n.deleteData(0,1)),u.remove(e,!0)),o=e}function l(){function e(e,n){var r,a,i,o,l;if(r=d.startContainer,a=d.startOffset,3==r.nodeType){if(l=r.nodeValue.length,a>0&&l>a||(n?a==l:0===a))return}else{if(!(a0?a-1:a;r=r.childNodes[u],r.hasChildNodes()&&(r=r.firstChild)}for(i=new f(r,e);o=i[n?"prev":"next"]();){if(3===o.nodeType&&o.nodeValue.length>0)return;if("true"===t(o))return o}return e}var r,a,l,d,u;o(),l=s.isCollapsed(),r=n(s.getStart()),a=n(s.getEnd()),(r||a)&&(d=s.getRng(!0),l?(r=r||a,(u=e(r,!0))?i(u,!0):(u=e(r,!1))?i(u,!1):s.select(r)):(d=s.getRng(!0),r&&d.setStartBefore(r),a&&d.setEndAfter(a),s.setRng(d)))}function d(a){function i(e,t){for(;e=e[t?"previousSibling":"nextSibling"];)if(3!==e.nodeType||e.nodeValue.length>0)return e}function d(e,t){s.select(e),s.collapse(t)}function g(a){function i(e){for(var t=d;t;){if(t===e)return;t=t.parentNode}u.remove(e),l()}function o(){var r,o,l=e.schema.getNonEmptyElements();for(o=new tinymce.dom.TreeWalker(d,e.getBody());(r=a?o.prev():o.next())&&!l[r.nodeName.toLowerCase()]&&!(3===r.nodeType&&tinymce.trim(r.nodeValue).length>0);)if("false"===t(r))return i(r),!0;return n(r)?!0:!1}var f,d,c,g;if(s.isCollapsed()){if(f=s.getRng(!0),d=f.startContainer,c=f.startOffset,d=r(d)||d,g=n(d))return i(g),!1;if(3==d.nodeType&&(a?c>0:ch||h>124)&&h!=c.DELETE&&h!=c.BACKSPACE){if((tinymce.isMac?a.metaKey:a.ctrlKey)&&(67==h||88==h||86==h))return;if(a.preventDefault(),h==c.LEFT||h==c.RIGHT){var y=h==c.LEFT;if(e.dom.isBlock(m)){var T=y?m.previousSibling:m.nextSibling,C=new f(T,T),b=y?C.prev():C.next();d(b,!y)}else d(m,y)}}else if(h==c.LEFT||h==c.RIGHT||h==c.BACKSPACE||h==c.DELETE){if(p=r(v)){if(h==c.LEFT||h==c.BACKSPACE)if(m=i(p,!0),m&&"false"===t(m)){if(a.preventDefault(),h!=c.LEFT)return void u.remove(m);d(m,!0)}else o(p);if(h==c.RIGHT||h==c.DELETE)if(m=i(p),m&&"false"===t(m)){if(a.preventDefault(),h!=c.RIGHT)return void u.remove(m);d(m,!1)}else o(p)}if((h==c.BACKSPACE||h==c.DELETE)&&!g(h==c.BACKSPACE))return a.preventDefault(),!1}}var u=e.dom,s=e.selection,g="mce_noneditablecaret",m="";e.on("mousedown",function(n){var r=e.selection.getNode();"false"===t(r)&&r==n.target&&l()}),e.on("mouseup keyup",l),e.on("keydown",d)}function a(t){var n=l.length,r=t.content,a=tinymce.trim(o);if("raw"!=t.format){for(;n--;)r=r.replace(l[n],function(t){var n=arguments,i=n[n.length-2];return i>0&&'"'==r.charAt(i-1)?t:''+e.dom.encode("string"==typeof n[1]?n[1]:n[0])+""});t.content=r}}var i,o,l,f=tinymce.dom.TreeWalker,d="contenteditable",u="data-mce-"+d,c=tinymce.util.VK;i=" "+tinymce.trim(e.getParam("noneditable_editable_class","mceEditable"))+" ",o=" "+tinymce.trim(e.getParam("noneditable_noneditable_class","mceNonEditable"))+" ",l=e.getParam("noneditable_regexp"),l&&!l.length&&(l=[l]),e.on("PreInit",function(){r(),l&&e.on("BeforeSetContent",a),e.parser.addAttributeFilter("class",function(e){for(var t,n,r=e.length;r--;)n=e[r],t=" "+n.attr("class")+" ",-1!==t.indexOf(i)?n.attr(u,"true"):-1!==t.indexOf(o)&&n.attr(u,"false")}),e.serializer.addAttributeFilter(u,function(e){for(var t,n=e.length;n--;)t=e[n],l&&t.attr("data-mce-content")?(t.name="#text",t.type=3,t.raw=!0,t.value=t.attr("data-mce-content")):(t.attr(d,null),t.attr(u,null))}),e.parser.addAttributeFilter(d,function(e){for(var t,n=e.length;n--;)t=e[n],t.attr(u,t.attr(d)),t.attr(d,null)})}),e.on("drop",function(e){n(e.target)&&e.preventDefault()})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/pagebreak/plugin.min.js b/web/resource/components/tinymce/plugins/pagebreak/plugin.min.js new file mode 100644 index 0000000..e232c05 --- /dev/null +++ b/web/resource/components/tinymce/plugins/pagebreak/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("pagebreak",function(e){var a="mce-pagebreak",t=e.getParam("pagebreak_separator",""),n=new RegExp(t.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(e){return"\\"+e}),"gi"),r='';e.addCommand("mcePageBreak",function(){e.insertContent(e.settings.pagebreak_split_block?"

"+r+"

":r)}),e.addButton("pagebreak",{title:"Page break",cmd:"mcePageBreak"}),e.addMenuItem("pagebreak",{text:"Page break",icon:"pagebreak",cmd:"mcePageBreak",context:"insert"}),e.on("ResolveName",function(t){"IMG"==t.target.nodeName&&e.dom.hasClass(t.target,a)&&(t.name="pagebreak")}),e.on("click",function(t){t=t.target,"IMG"===t.nodeName&&e.dom.hasClass(t,a)&&e.selection.select(t)}),e.on("BeforeSetContent",function(e){e.content=e.content.replace(n,r)}),e.on("PreInit",function(){e.serializer.addNodeFilter("img",function(a){for(var n,r,c=a.length;c--;)if(n=a[c],r=n.attr("class"),r&&-1!==r.indexOf("mce-pagebreak")){var o=n.parent;if(e.schema.getBlockElements()[o.name]&&e.settings.pagebreak_split_block){o.type=3,o.value=t,o.raw=!0,n.remove();continue}n.type=3,n.value=t,n.raw=!0}})})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/paste/plugin.min.js b/web/resource/components/tinymce/plugins/paste/plugin.min.js new file mode 100644 index 0000000..52fa8bd --- /dev/null +++ b/web/resource/components/tinymce/plugins/paste/plugin.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";function n(e,t){for(var n,r=[],i=0;i]*>\s*|\s*<\/body[^>]*>[\s\S]*$/g,/|/g,[/\u00a0<\/span>/g,"\xa0"],/
$/i])}return{filter:r,innerText:i,trimHtml:o}}),r(f,[p,m,l],function(e,t,n){return function(r){function i(e){var t,n=r.dom;if(t=r.fire("BeforePastePreProcess",{content:e}),t=r.fire("PastePreProcess",t),e=t.content,!t.isDefaultPrevented()){if(r.hasEventListeners("PastePostProcess")&&!t.isDefaultPrevented()){var i=n.add(r.getBody(),"div",{style:"display:none"},e);t=r.fire("PastePostProcess",{node:i}),n.remove(i),e=t.node.innerHTML}t.isDefaultPrevented()||r.insertContent(e,{merge:r.settings.paste_merge_formats!==!1})}}function o(e){e=r.dom.encode(e).replace(/\r\n/g,"\n");var t=r.dom.getParent(r.selection.getStart(),r.dom.isBlock),o=r.settings.forced_root_block,a;o&&(a=r.dom.createHTML(o,r.settings.forced_root_block_attrs),a=a.substr(0,a.length-3)+">"),t&&/^(PRE|DIV)$/.test(t.nodeName)||!o?e=n.filter(e,[[/\n/g,"
"]]):(e=n.filter(e,[[/\n\n/g,"

"+a],[/^(.*<\/p>)(

)$/,a+"$1"],[/\n/g,"
"]]),-1!=e.indexOf("

")&&(e=a+e)),i(e)}function a(){var t=r.dom,n=r.getBody(),i=r.dom.getViewPort(r.getWin()),o=i.y,a=20,s;if(b=r.selection.getRng(),r.inline&&(s=r.selection.getScrollContainer(),s&&s.scrollTop>0&&(o=s.scrollTop)),b.getClientRects){var l=b.getClientRects();if(l.length)a=o+(l[0].top-t.getPos(n).y);else{a=o;var c=b.startContainer;c&&(3==c.nodeType&&c.parentNode!=n&&(c=c.parentNode),1==c.nodeType&&(a=t.getPos(c,s||n).y))}}y=t.add(r.getBody(),"div",{id:"mcepastebin",contentEditable:!0,"data-mce-bogus":"1",style:"position: absolute; top: "+a+"px;width: 10px; height: 10px; overflow: hidden; opacity: 0"},x),(e.ie||e.gecko)&&t.setStyle(y,"left","rtl"==t.getStyle(n,"direction",!0)?65535:-65535),t.bind(y,"beforedeactivate focusin focusout",function(e){e.stopPropagation()}),y.focus(),r.selection.select(y,!0)}function s(){if(y){for(var e;e=r.dom.get("mcepastebin");)r.dom.remove(e),r.dom.unbind(e);b&&r.selection.setRng(b)}y=b=null}function l(){var e=x,t,n;for(t=r.dom.select("div[id=mcepastebin]"),n=t.length;n--;){var i=t[n].innerHTML;e==x&&(e=""),i.length>e.length&&(e=i)}return e}function c(e){var t={};if(e&&e.types){var n=e.getData("Text");n&&n.length>0&&(t["text/plain"]=n);for(var r=0;r')},t.readAsDataURL(e.getAsFile()),!0}}if(!(!r.settings.paste_data_images||"text/html"in t||"text/plain"in t)&&e.clipboardData){var o=e.clipboardData.items;if(o)for(var a=0;a0}function h(e){return t.metaKeyPressed(e)&&86==e.keyCode||e.shiftKey&&45==e.keyCode}function g(){r.on("keydown",function(t){if(h(t)&&!t.isDefaultPrevented()){if(w=t.shiftKey&&86==t.keyCode,w&&e.webkit&&-1!=navigator.userAgent.indexOf("Version/"))return;if(t.stopImmediatePropagation(),C=(new Date).getTime(),e.ie&&w)return t.preventDefault(),void r.fire("paste",{ieFake:!0});s(),a()}}),r.on("keyup",function(e){h(e)&&!e.isDefaultPrevented()&&s()}),r.on("paste",function(t){var c=d(t),p=(new Date).getTime()-C<1e3,h="text"==v.pasteFormat||w;return w=!1,t.isDefaultPrevented()||f(t)?void s():u(t,c)?void s():(p||t.preventDefault(),!e.ie||p&&!t.ieFake||(a(),r.dom.bind(y,"paste",function(e){e.stopPropagation()}),r.getDoc().execCommand("Paste",!1,null),c["text/html"]=l()),void setTimeout(function(){var e;return m(c,"text/html")?e=c["text/html"]:(e=l(),e==x&&(h=!0)),e=n.trimHtml(l()),y&&y.firstChild&&"mcepastebin"===y.firstChild.id&&(h=!0),s(),h&&(e=m(c,"text/plain")&&-1==e.indexOf("

")?c["text/plain"]:n.innerText(e)),e==x?void(p||r.windowManager.alert("Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.")):void(h?o(e):i(e))},0))}),r.on("dragstart",function(e){if(e.dataTransfer.types)try{e.dataTransfer.setData("mce-internal",r.selection.getContent())}catch(t){}}),r.on("drop",function(e){var t=p(e);if(t&&!e.isDefaultPrevented()){var n=c(e.dataTransfer),a=n["mce-internal"]||n["text/html"]||n["text/plain"];a&&(e.preventDefault(),r.undoManager.transact(function(){n["mce-internal"]&&r.execCommand("Delete"),r.selection.setRng(t),n["text/html"]?i(a):o(a)}))}})}var v=this,y,b,C=0,x="%MCEPASTEBIN%",w;v.pasteHtml=i,v.pasteText=o,r.on("preInit",function(){g(),r.parser.addNodeFilter("img",function(t){if(!r.settings.paste_data_images)for(var n=t.length;n--;){var i=t[n].attributes.map.src;i&&0===i.indexOf("data:image")&&(t[n].attr("data-mce-object")||i===e.transparentSrc||t[n].remove())}})}),r.on("BeforeAddUndo",function(e){e.level.content&&(e.level.content=e.level.content.replace(/
]+>%MCEPASTEBIN%<\/div>/gi,""))})}}),r(h,[c,d,u,g,v,l],function(e,t,n,r,i,o){function a(e){return/l?n&&(n=n.parent.parent):(r=n,n=null)),n&&n.name==a?n.append(e):(r=r||n,n=new i(a,1),s>1&&n.attr("start",""+s),e.wrap(n)),e.name="li",t.value="";var c=t.next;c&&3==c.type&&(c.value=c.value.replace(/^\u00a0+/,"")),l>o&&r&&r.lastChild.append(n),o=l}for(var n,r,o=1,a=e.getAll("p"),s=0;s/gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/ /gi,"\xa0"],[/([\s\u00a0]*)<\/span>/gi,function(e,t){return t.length>0?t.replace(/./," ").slice(Math.floor(t.length/2)).split("").join("\xa0"):""}]]);var h=l.paste_word_valid_elements;h||(h="-strong/b,-em/i,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,-p/div,-table[width],-tr,-td[colspan|rowspan|width],-th,-thead,-tfoot,-tbody,-a[href|name],sub,sup,strike,br,del");var g=new n({valid_elements:h,valid_children:"-li[p]"});e.each(g.elements,function(e){e.attributes["class"]||(e.attributes["class"]={},e.attributesOrder.push("class")),e.attributes.style||(e.attributes.style={},e.attributesOrder.push("style"))});var v=new t({},g);v.addAttributeFilter("style",function(e){for(var t=e.length,n;t--;)n=e[t],n.attr("style",u(n,n.attr("style"))),"span"==n.name&&n.parent&&!n.attributes.length&&n.unwrap()}),v.addAttributeFilter("class",function(e){for(var t=e.length,n,r;t--;)n=e[t],r=n.attr("class"),/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(r)&&n.remove(),n.attr("class",null)}),v.addNodeFilter("del",function(e){for(var t=e.length;t--;)e[t].remove()}),v.addNodeFilter("a",function(e){for(var t=e.length,n,r,i;t--;)if(n=e[t],r=n.attr("href"),i=n.attr("name"),r&&-1!=r.indexOf("#_msocom_"))n.remove();else if(r&&0===r.indexOf("file://")&&(r=r.split("#")[1],r&&(r="#"+r)),r||i){if(i&&!/^_?(?:toc|edn|ftn)/i.test(i)){n.unwrap();continue}n.attr({href:r,name:i})}else n.unwrap()});var y=v.parse(f);d(y),c.content=new r({},g).serialize(y)}})}return s.isWordContent=a,s}),r(y,[p,c,h,l],function(e,t,n,r){return function(i){function o(e){i.on("BeforePastePreProcess",function(t){t.content=e(t.content)})}function a(e){if(!n.isWordContent(e))return e;var o=[];t.each(i.schema.getBlockElements(),function(e,t){o.push(t)});var a=new RegExp("(?:
 [\\s\\r\\n]+|
)*(<\\/?("+o.join("|")+")[^>]*>)(?:
 [\\s\\r\\n]+|
)*","g");return e=r.filter(e,[[a,"$1"]]),e=r.filter(e,[[/

/g,"

"],[/
/g," "],[/

/g,"
"]])}function s(e){if(n.isWordContent(e))return e;var t=i.settings.paste_webkit_styles;if(i.settings.paste_remove_styles_if_webkit===!1||"all"==t)return e;if(t&&(t=t.split(/[, ]/)),t){var r=i.dom,o=i.selection.getNode();e=e.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi,function(e,n,i,a){var s=r.parseStyle(i,"span"),l={};if("none"===t)return n+a;for(var c=0;c]+) style="([^"]*)"([^>]*>)/gi,"$1$3");return e=e.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi,function(e,t,n,r){return t+' style="'+n+'"'+r})}e.webkit&&o(s),e.ie&&o(a)}}),r(b,[C,f,h,y],function(e,t,n,r){var i;e.add("paste",function(e){function o(){"text"==s.pasteFormat?(this.active(!1),s.pasteFormat="html"):(s.pasteFormat="text",this.active(!0),i||(e.windowManager.alert("Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off."),i=!0))}var a=this,s,l=e.settings;a.clipboard=s=new t(e),a.quirks=new r(e),a.wordFilter=new n(e),e.settings.paste_as_text&&(a.clipboard.pasteFormat="text"),l.paste_preprocess&&e.on("PastePreProcess",function(e){l.paste_preprocess.call(a,a,e)}),l.paste_postprocess&&e.on("PastePostProcess",function(e){l.paste_postprocess.call(a,a,e)}),e.addCommand("mceInsertClipboardContent",function(e,t){t.content&&a.clipboard.pasteHtml(t.content),t.text&&a.clipboard.pasteText(t.text)}),e.paste_block_drop&&e.on("dragend dragover draggesture dragdrop drop drag",function(e){e.preventDefault(),e.stopPropagation()}),e.settings.paste_data_images||e.on("drop",function(e){var t=e.dataTransfer;t&&t.files&&t.files.length>0&&e.preventDefault()}),e.addButton("pastetext",{icon:"pastetext",tooltip:"Paste as text",onclick:o,active:"text"==a.clipboard.pasteFormat}),e.addMenuItem("pastetext",{text:"Paste as text",selectable:!0,active:s.pasteFormat,onclick:o})})}),a([l,h])}(this); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/preview/plugin.min.js b/web/resource/components/tinymce/plugins/preview/plugin.min.js new file mode 100644 index 0000000..23e70ac --- /dev/null +++ b/web/resource/components/tinymce/plugins/preview/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("preview",function(e){var t=e.settings,i=!tinymce.Env.ie;e.addCommand("mcePreview",function(){e.windowManager.open({title:"Preview",width:parseInt(e.getParam("plugin_preview_width","650"),10),height:parseInt(e.getParam("plugin_preview_height","500"),10),html:'",buttons:{text:"Close",onclick:function(){this.parent().parent().close()}},onPostRender:function(){var n,a="";a+='',tinymce.each(e.contentCSS,function(t){a+=''});var r=t.body_id||"tinymce";-1!=r.indexOf("=")&&(r=e.getParam("body_id","","hash"),r=r[e.id]||r);var d=t.body_class||"";-1!=d.indexOf("=")&&(d=e.getParam("body_class","","hash"),d=d[e.id]||"");var o=e.settings.directionality?' dir="'+e.settings.directionality+'"':"";if(n=""+a+'"+e.getContent()+"",i)this.getEl("body").firstChild.src="data:text/html;charset=utf-8,"+encodeURIComponent(n);else{var s=this.getEl("body").firstChild.contentWindow.document;s.open(),s.write(n),s.close()}}})}),e.addButton("preview",{title:"Preview",cmd:"mcePreview"}),e.addMenuItem("preview",{text:"Preview",cmd:"mcePreview",context:"view"})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/print/plugin.min.js b/web/resource/components/tinymce/plugins/print/plugin.min.js new file mode 100644 index 0000000..abc37b5 --- /dev/null +++ b/web/resource/components/tinymce/plugins/print/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("print",function(t){t.addCommand("mcePrint",function(){t.getWin().print()}),t.addButton("print",{title:"Print",cmd:"mcePrint"}),t.addShortcut("Ctrl+P","","mcePrint"),t.addMenuItem("print",{text:"Print",cmd:"mcePrint",icon:"print",shortcut:"Ctrl+P",context:"file"})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/save/plugin.min.js b/web/resource/components/tinymce/plugins/save/plugin.min.js new file mode 100644 index 0000000..07fcb1b --- /dev/null +++ b/web/resource/components/tinymce/plugins/save/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("save",function(e){function a(){var a;return a=tinymce.DOM.getParent(e.id,"form"),!e.getParam("save_enablewhendirty",!0)||e.isDirty()?(tinymce.triggerSave(),e.getParam("save_onsavecallback")?void(e.execCallback("save_onsavecallback",e)&&(e.startContent=tinymce.trim(e.getContent({format:"raw"})),e.nodeChanged())):void(a?(e.isNotDirty=!0,(!a.onsubmit||a.onsubmit())&&("function"==typeof a.submit?a.submit():e.windowManager.alert("Error: Form submit field collision.")),e.nodeChanged()):e.windowManager.alert("Error: No form element found."))):void 0}function n(){var a=tinymce.trim(e.startContent);return e.getParam("save_oncancelcallback")?void e.execCallback("save_oncancelcallback",e):(e.setContent(a),e.undoManager.clear(),void e.nodeChanged())}function t(){var a=this;e.on("nodeChange",function(){a.disabled(e.getParam("save_enablewhendirty",!0)&&!e.isDirty())})}e.addCommand("mceSave",a),e.addCommand("mceCancel",n),e.addButton("save",{icon:"save",text:"Save",cmd:"mceSave",disabled:!0,onPostRender:t}),e.addButton("cancel",{text:"Cancel",icon:!1,cmd:"mceCancel",disabled:!0,onPostRender:t}),e.addShortcut("ctrl+s","","mceSave")}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/searchreplace/plugin.min.js b/web/resource/components/tinymce/plugins/searchreplace/plugin.min.js new file mode 100644 index 0000000..367c6bd --- /dev/null +++ b/web/resource/components/tinymce/plugins/searchreplace/plugin.min.js @@ -0,0 +1 @@ +!function(){function e(e,t,n,a,r){function i(e,t){if(t=t||0,!e[0])throw"findAndReplaceDOMText cannot handle zero-length matches";var n=e.index;if(t>0){var a=e[t];if(!a)throw"Invalid capture group";n+=e[0].indexOf(a),e[0]=a}return[n,n+e[0].length,[e[0]]]}function d(e){var t;if(3===e.nodeType)return e.data;if(h[e.nodeName]&&!u[e.nodeName])return"";if(t="",(u[e.nodeName]||m[e.nodeName])&&(t+="\n"),e=e.firstChild)do t+=d(e);while(e=e.nextSibling);return t}function o(e,t,n){var a,r,i,d,o=[],l=0,c=e,s=t.shift(),f=0;e:for(;;){if((u[c.nodeName]||m[c.nodeName])&&l++,3===c.nodeType&&(!r&&c.length+l>=s[1]?(r=c,d=s[1]-l):a&&o.push(c),!a&&c.length+l>s[0]&&(a=c,i=s[0]-l),l+=c.length),a&&r){if(c=n({startNode:a,startNodeIndex:i,endNode:r,endNodeIndex:d,innerNodes:o,match:s[2],matchIndex:f}),l-=r.length-d,a=null,r=null,o=[],s=t.shift(),f++,!s)break}else{if((!h[c.nodeName]||u[c.nodeName])&&c.firstChild){c=c.firstChild;continue}if(c.nextSibling){c=c.nextSibling;continue}}for(;;){if(c.nextSibling){c=c.nextSibling;break}if(c.parentNode===e)break e;c=c.parentNode}}}function l(e){var t;if("function"!=typeof e){var n=e.nodeType?e:f.createElement(e);t=function(e,t){var a=n.cloneNode(!1);return a.setAttribute("data-mce-index",t),e&&a.appendChild(f.createTextNode(e)),a}}else t=e;return function(e){var n,a,r,i=e.startNode,d=e.endNode,o=e.matchIndex;if(i===d){var l=i;r=l.parentNode,e.startNodeIndex>0&&(n=f.createTextNode(l.data.substring(0,e.startNodeIndex)),r.insertBefore(n,l));var c=t(e.match[0],o);return r.insertBefore(c,l),e.endNodeIndexh;++h){var g=e.innerNodes[h],p=t(g.data,o);g.parentNode.replaceChild(p,g),u.push(p)}var x=t(d.data.substring(0,e.endNodeIndex),o);return r=i.parentNode,r.insertBefore(n,i),r.insertBefore(s,i),r.removeChild(i),r=d.parentNode,r.insertBefore(x,d),r.insertBefore(a,d),r.removeChild(d),x}}var c,s,f,u,h,m,g=[],p=0;if(f=t.ownerDocument,u=r.getBlockElements(),h=r.getWhiteSpaceElements(),m=r.getShortEndedElements(),s=d(t)){if(e.global)for(;c=e.exec(s);)g.push(i(c,a));else c=s.match(e),g.push(i(c,a));return g.length&&(p=g.length,o(t,g,l(n))),p}}function t(t){function n(){function e(){r.statusbar.find("#next").disabled(!d(s+1).length),r.statusbar.find("#prev").disabled(!d(s-1).length)}function n(){tinymce.ui.MessageBox.alert("Could not find the specified string.",function(){r.find("#find")[0].focus()})}var a={},r=tinymce.ui.Factory.create({type:"window",layout:"flex",pack:"center",align:"center",onClose:function(){t.focus(),c.done()},onSubmit:function(t){var i,o,l,f;return t.preventDefault(),o=r.find("#case").checked(),f=r.find("#words").checked(),l=r.find("#find").value(),l.length?a.text==l&&a.caseState==o&&a.wholeWord==f?0===d(s+1).length?void n():(c.next(),void e()):(i=c.find(l,o,f),i||n(),r.statusbar.items().slice(1).disabled(0===i),e(),void(a={text:l,caseState:o,wholeWord:f})):(c.done(!1),void r.statusbar.items().slice(1).disabled(!0))},buttons:[{text:"Find",onclick:function(){r.submit()}},{text:"Replace",disabled:!0,onclick:function(){c.replace(r.find("#replace").value())||(r.statusbar.items().slice(1).disabled(!0),s=-1,a={})}},{text:"Replace all",disabled:!0,onclick:function(){c.replace(r.find("#replace").value(),!0,!0),r.statusbar.items().slice(1).disabled(!0),a={}}},{type:"spacer",flex:1},{text:"Prev",name:"prev",disabled:!0,onclick:function(){c.prev(),e()}},{text:"Next",name:"next",disabled:!0,onclick:function(){c.next(),e()}}],title:"Find and replace",items:{type:"form",padding:20,labelGap:30,spacing:10,items:[{type:"textbox",name:"find",size:40,label:"Find",value:t.selection.getNode().src},{type:"textbox",name:"replace",size:40,label:"Replace with"},{type:"checkbox",name:"case",text:"Match case",label:" "},{type:"checkbox",name:"words",text:"Whole words",label:" "}]}}).renderTo().reflow()}function a(e){var t=e.getAttribute("data-mce-index");return"number"==typeof t?""+t:t}function r(n){var a,r;return r=t.dom.create("span",{"data-mce-bogus":1}),r.className="mce-match-marker",a=t.getBody(),c.done(!1),e(n,a,r,!1,t.schema)}function i(e){var t=e.parentNode;e.firstChild&&t.insertBefore(e.firstChild,e),e.parentNode.removeChild(e)}function d(e){var n,r=[];if(n=tinymce.toArray(t.getBody().getElementsByTagName("span")),n.length)for(var i=0;is&&f[o].setAttribute("data-mce-index",m-1)}return t.undoManager.add(),s=p,n?(g=d(p+1).length>0,c.next()):(g=d(p-1).length>0,c.prev()),!r&&g},c.done=function(e){var n,r,d,o;for(r=tinymce.toArray(t.getBody().getElementsByTagName("span")),n=0;n=d.end?(o=s,a=d.end-l):r&&c.push(s),!r&&s.length+l>d.start&&(r=s,i=d.start-l),l+=s.length),r&&o){if(s=n({startNode:r,startNodeIndex:i,endNode:o,endNodeIndex:a,innerNodes:c,match:d.text,matchIndex:u}),l-=o.length-a,r=null,o=null,c=[],d=t.shift(),u++,!d)break}else{if((!T[s.nodeName]||S[s.nodeName])&&s.firstChild){s=s.firstChild;continue}if(s.nextSibling){s=s.nextSibling;continue}}for(;;){if(s.nextSibling){s=s.nextSibling;break}if(s.parentNode===e)break e;s=s.parentNode}}}function i(e){function t(t,n){var r=w[n];r.stencil||(r.stencil=e(r));var o=r.stencil.cloneNode(!1);return o.setAttribute("data-mce-index",n),t&&o.appendChild(b.doc.createTextNode(t)),o}return function(e){var n,r,o,i=e.startNode,a=e.endNode,c=e.matchIndex,l=b.doc;if(i===a){var s=i;o=s.parentNode,e.startNodeIndex>0&&(n=l.createTextNode(s.data.substring(0,e.startNodeIndex)),o.insertBefore(n,s));var d=t(e.match,c);return o.insertBefore(d,s),e.endNodeIndexh;++h){var m=e.innerNodes[h],p=t(m.data,c);m.parentNode.replaceChild(p,m),f.push(p)}var v=t(a.data.substring(0,e.endNodeIndex),c);return o=i.parentNode,o.insertBefore(n,i),o.insertBefore(u,i),o.removeChild(i),o=a.parentNode,o.insertBefore(v,a),o.insertBefore(r,a),o.removeChild(a),v}}function a(e){var t=e.parentNode;t.insertBefore(e.firstChild,e),e.parentNode.removeChild(e)}function c(t){var n=e.getElementsByTagName("*"),r=[];t="number"==typeof t?""+t:null;for(var o=0;ot&&e(w[t],t)!==!1;t++);return this}function u(t){return w.length&&o(e,w,i(t)),this}function f(e,t){if(y&&e.global)for(;k=e.exec(y);)w.push(n(k,t));return this}function h(e){var t,n=c(e?l(e):null);for(t=n.length;t--;)a(n[t]);return this}function g(e){return w[e.getAttribute("data-mce-index")]}function m(e){return c(l(e))[0]}function p(e,t,n){return w.push({start:e,end:e+t,text:y.substr(e,t),data:n}),this}function v(e){var n=c(l(e)),r=t.dom.createRng();return r.setStartBefore(n[0]),r.setEndAfter(n[n.length-1]),r}function x(e,n){var r=v(e);return r.deleteContents(),n.length>0&&r.insertNode(t.dom.doc.createTextNode(n)),r}function N(){return w.splice(0,w.length),h(),this}var k,w=[],y,b=t.dom,S,T,B;return S=t.schema.getBlockElements(),T=t.schema.getWhiteSpaceElements(),B=t.schema.getShortEndedElements(),y=r(e),{text:y,matches:w,each:d,filter:s,reset:N,matchFromElement:g,elementFromMatch:m,find:f,add:p,wrap:u,unwrap:h,replace:x,rangeFromMatch:v,indexOf:l}}}),r(s,[l,d,u,f,h,g,m,p],function(e,t,n,r,o,i,a,c){t.add("spellchecker",function(t,l){function s(){return T.textMatcher||(T.textMatcher=new e(t.getBody(),t)),T.textMatcher}function d(e,t){var r=[];return n.each(t,function(e){r.push({selectable:!0,text:e.name,data:e.value})}),r}function u(e){for(var t in e)return!1;return!0}function f(e,i){var a=[],c=B[e];n.each(c,function(e){a.push({text:e,onclick:function(){t.insertContent(t.dom.encode(e)),t.dom.remove(i),v()}})}),a.push({text:"-"}),E&&a.push({text:"Add to Dictionary",onclick:function(){x(e,i)}}),a.push.apply(a,[{text:"Ignore",onclick:function(){N(e,i)}},{text:"Ignore all",onclick:function(){N(e,i,!0)}},{text:"Finish",onclick:k}]),I=new r({items:a,context:"contextmenu",onautohide:function(e){-1!=e.target.className.indexOf("spellchecker")&&e.preventDefault()},onhide:function(){I.remove(),I=null}}),I.renderTo(document.body);var l=o.DOM.getPos(t.getContentAreaContainer()),s=t.dom.getPos(i[0]),d=t.dom.getRoot();"BODY"==d.nodeName?(s.x-=d.ownerDocument.documentElement.scrollLeft||d.scrollLeft,s.y-=d.ownerDocument.documentElement.scrollTop||d.scrollTop):(s.x-=d.scrollLeft,s.y-=d.scrollTop),l.x+=s.x,l.y+=s.y,I.moveTo(l.x,l.y+i[0].offsetHeight)}function h(){return t.getParam("spellchecker_wordchar_pattern")||new RegExp('[^\\s!"#$%&()*+,-./:;<=>?@[\\]^_{|}`\xa7\xa9\xab\xae\xb1\xb6\xb7\xb8\xbb\xbc\xbd\xbe\xbf\xd7\xf7\xa4\u201d\u201c\u201e]+',"g")}function g(e,t,r,o){var s={method:e},d="";"spellcheck"==e&&(s.text=t,s.lang=M.spellchecker_language),"addToDictionary"==e&&(s.word=t),n.each(s,function(e,t){d&&(d+="&"),d+=t+"="+encodeURIComponent(e)}),i.send({url:new a(l).toAbsolute(M.spellchecker_rpc_url),type:"post",content_type:"application/x-www-form-urlencoded",data:d,success:function(e){e=c.parse(e),e?e.error?o(e.error):r(e):o("Sever response wasn't proper JSON.")},error:function(e,t){o("Spellchecker request error: "+t.status)}})}function m(e,t,n,r){var o=M.spellchecker_callback||g;o.call(T,e,t,n,r)}function p(){function e(e){var n;return e.words?(E=!!e.dictionary,n=e.words):n=e,t.setProgressState(!1),u(n)?(t.windowManager.alert("No misspellings found"),void(C=!1)):(B=n,s().find(h()).filter(function(e){return!!n[e.text]}).wrap(function(e){return t.dom.create("span",{"class":"mce-spellchecker-word","data-mce-bogus":1,"data-mce-word":e.text})}),void t.fire("SpellcheckStart"))}function n(e){t.windowManager.alert(e),t.setProgressState(!1),k()}return C?void k():(k(),C=!0,t.setProgressState(!0),m("spellcheck",s().text,e,n),void t.focus())}function v(){t.dom.select("span.mce-spellchecker-word").length||k()}function x(e,n){t.setProgressState(!0),m("addToDictionary",e,function(){t.setProgressState(!1),t.dom.remove(n,!0),v()},function(e){t.windowManager.alert(e),t.setProgressState(!1)})}function N(e,r,o){t.selection.collapse(),o?n.each(t.dom.select("span.mce-spellchecker-word"),function(n){n.getAttribute("data-mce-word")==e&&t.dom.remove(n,!0)}):t.dom.remove(r,!0),v()}function k(){s().reset(),T.textMatcher=null,C&&(C=!1,t.fire("SpellcheckEnd"))}function w(e){var t=e.getAttribute("data-mce-index");return"number"==typeof t?""+t:t}function y(e){var r,o=[];if(r=n.toArray(t.getBody().getElementsByTagName("span")),r.length)for(var i=0;i0){var o=t.dom.createRng();o.setStartBefore(r[0]),o.setEndAfter(r[r.length-1]),t.selection.setRng(o),f(n.getAttribute("data-mce-word"),r)}}}),t.addMenuItem("spellchecker",{text:"Spellcheck",context:"tools",onclick:p,selectable:!0,onPostRender:function(){var e=this;t.on("SpellcheckStart SpellcheckEnd",function(){e.active(C)})}});var _={tooltip:"Spellcheck",onclick:p,onPostRender:function(){var e=this;t.on("SpellcheckStart SpellcheckEnd",function(){e.active(C)})}};S.length>1&&(_.type="splitbutton",_.menu=S,_.onshow=b,_.onselect=function(e){M.spellchecker_language=e.control.settings.data}),t.addButton("spellchecker",_),t.addCommand("mceSpellCheck",p),t.on("remove",function(){I&&(I.remove(),I=null)}),t.on("change",v),this.getTextMatcher=s,this.getWordCharPattern=h,this.getLanguage=function(){return M.spellchecker_language},M.spellchecker_language=M.spellchecker_language||M.language||"en"})}),a([l,s])}(this); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/tabfocus/plugin.min.js b/web/resource/components/tinymce/plugins/tabfocus/plugin.min.js new file mode 100644 index 0000000..68fe35e --- /dev/null +++ b/web/resource/components/tinymce/plugins/tabfocus/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("tabfocus",function(e){function n(e){9!==e.keyCode||e.ctrlKey||e.altKey||e.metaKey||e.preventDefault()}function t(n){function t(n){function t(e){return"BODY"===e.nodeName||"hidden"!=e.type&&"none"!=e.style.display&&"hidden"!=e.style.visibility&&t(e.parentNode)}function r(e){return e.tabIndex||"INPUT"==e.nodeName||"TEXTAREA"==e.nodeName}function c(e){return!r(e)&&"-1"!=e.getAttribute("tabindex")&&t(e)}if(u=i.select(":input:enabled,*[tabindex]:not(iframe)"),o(u,function(n,t){return n.id==e.id?(a=t,!1):void 0}),n>0){for(d=a+1;d=0;d--)if(c(u[d]))return u[d];return null}var a,u,c,d;if(!(9!==n.keyCode||n.ctrlKey||n.altKey||n.metaKey)&&(c=r(e.getParam("tab_focus",e.getParam("tabfocus_elements",":prev,:next"))),1==c.length&&(c[1]=c[0],c[0]=":prev"),u=n.shiftKey?":prev"==c[0]?t(-1):i.get(c[0]):":next"==c[1]?t(1):i.get(c[1]))){var y=tinymce.get(u.id||u.name);u.id&&y?y.focus():window.setTimeout(function(){tinymce.Env.webkit||window.focus(),u.focus()},10),n.preventDefault()}}var i=tinymce.DOM,o=tinymce.each,r=tinymce.explode;e.on("init",function(){e.inline&&tinymce.DOM.setAttrib(e.getBody(),"tabIndex",null)}),e.on("keyup",n),tinymce.Env.gecko?e.on("keypress keydown",t):e.on("keydown",t)}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/table/plugin.min.js b/web/resource/components/tinymce/plugins/table/plugin.min.js new file mode 100644 index 0000000..4ee5cca --- /dev/null +++ b/web/resource/components/tinymce/plugins/table/plugin.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";function n(e,t){for(var n,o=[],a=0;a "+t+" tr",r);a(n,function(n,l){l+=e,a(H.select("> td, > th",n),function(e,n){var a,r,i,s;if(M[l])for(;M[l][n];)n++;for(i=o(e,"rowspan"),s=o(e,"colspan"),r=l;l+i>r;r++)for(M[r]||(M[r]=[]),a=n;n+s>a;a++)M[r][a]={part:t,real:r==l&&a==n,elm:e,rowspan:i,colspan:s};_=Math.max(_,n+1)})}),e+=n.length})}function s(e,t){return e=e.cloneNode(t),e.removeAttribute("id"),e}function c(e,t){var n;return n=M[t],n?n[e]:void 0}function d(e,t,n){e&&(n=parseInt(n,10),1===n?e.removeAttribute(t,1):e.setAttribute(t,n,1))}function u(e){return e&&(H.hasClass(e.elm,"mce-item-selected")||e==E)}function m(){var e=[];return a(r.rows,function(t){a(t.cells,function(n){return H.hasClass(n,"mce-item-selected")||E&&n==E.elm?(e.push(t),!1):void 0})}),e}function f(){var e=H.createRng();e.setStartAfter(r),e.setEndAfter(r),L.setRng(e),H.remove(r)}function g(t){var o,r={};return l.settings.table_clone_elements!==!1&&(r=e.makeMap((l.settings.table_clone_elements||"strong em b i span font h1 h2 h3 h4 h5 h6 p div").toUpperCase(),/[ ,]/)),e.walk(t,function(e){var l;return 3==e.nodeType?(a(H.getParents(e.parentNode,null,t).reverse(),function(e){r[e.nodeName]&&(e=s(e,!1),o?l&&l.appendChild(e):o=l=e,l=e)}),l&&(l.innerHTML=n.ie?" ":'
'),!1):void 0},"childNodes"),t=s(t,!1),d(t,"rowSpan",1),d(t,"colSpan",1),o?t.appendChild(o):(!n.ie||n.ie>10)&&(t.innerHTML='
'),t}function p(){var e=H.createRng(),t;return a(H.select("tr",r),function(e){0===e.cells.length&&H.remove(e)}),0===H.select("tr",r).length?(e.setStartBefore(r),e.setEndBefore(r),L.setRng(e),void H.remove(r)):(a(H.select("thead,tbody,tfoot",r),function(e){0===e.rows.length&&H.remove(e)}),i(),void(D&&(t=M[Math.min(M.length-1,D.y)],t&&(L.select(t[Math.min(t.length-1,D.x)].elm,!0),L.collapse(!0)))))}function h(e,t,n,o){var a,l,r,i,s;for(a=M[t][e].elm.parentNode,r=1;n>=r;r++)if(a=H.getNext(a,"tr")){for(l=e;l>=0;l--)if(s=M[t+r][l].elm,s.parentNode==a){for(i=1;o>=i;i++)H.insertAfter(g(s),s);break}if(-1==l)for(i=1;o>=i;i++)a.insertBefore(g(a.cells[0]),a.cells[0])}}function b(){a(M,function(e,t){a(e,function(e,n){var a,l,r;if(u(e)&&(e=e.elm,a=o(e,"colspan"),l=o(e,"rowspan"),a>1||l>1)){for(d(e,"rowSpan",1),d(e,"colSpan",1),r=0;a-1>r;r++)H.insertAfter(g(e),e);h(n,t,l-1,a)}})})}function v(t,n,o){var l,r,s,m,f,g,h,v,x,y,w;if(t?(l=T(t),r=l.x,s=l.y,m=r+(n-1),f=s+(o-1)):(D=I=null,a(M,function(e,t){a(e,function(e,n){u(e)&&(D||(D={x:n,y:t}),I={x:n,y:t})})}),D&&(r=D.x,s=D.y,m=I.x,f=I.y)),v=c(r,s),x=c(m,f),v&&x&&v.part==x.part){for(b(),i(),v=c(r,s).elm,d(v,"colSpan",m-r+1),d(v,"rowSpan",f-s+1),h=s;f>=h;h++)for(g=r;m>=g;g++)M[h]&&M[h][g]&&(t=M[h][g].elm,t!=v&&(y=e.grep(t.childNodes),a(y,function(e){v.appendChild(e)}),y.length&&(y=e.grep(v.childNodes),w=0,a(y,function(e){"BR"==e.nodeName&&H.getAttrib(e,"data-mce-bogus")&&w++0&&M[n-1][i]&&(p=M[n-1][i].elm,h=o(p,"rowSpan"),h>1)){d(p,"rowSpan",h+1);continue}}else if(h=o(l,"rowspan"),h>1){d(l,"rowSpan",h+1);continue}f=g(l),d(f,"colSpan",l.colSpan),m.appendChild(f),r=l}m.hasChildNodes()&&(e?c.parentNode.insertBefore(m,c):H.insertAfter(m,c))}}function y(e){var t,n;a(M,function(n){return a(n,function(n,o){return u(n)&&(t=o,e)?!1:void 0}),e?!t:void 0}),a(M,function(a,l){var r,i,s;a[t]&&(r=a[t].elm,r!=n&&(s=o(r,"colspan"),i=o(r,"rowspan"),1==s?e?(r.parentNode.insertBefore(g(r),r),h(t,l,i-1,s)):(H.insertAfter(g(r),r),h(t,l,i-1,s)):d(r,"colSpan",r.colSpan+1),n=r))})}function w(){var t=[];a(M,function(n){a(n,function(n,l){u(n)&&-1===e.inArray(t,l)&&(a(M,function(e){var t=e[l].elm,n;n=o(t,"colSpan"),n>1?d(t,"colSpan",n-1):H.remove(t)}),t.push(l))})}),p()}function C(){function e(e){var t,n;a(e.cells,function(e){var n=o(e,"rowSpan");n>1&&(d(e,"rowSpan",n-1),t=T(e),h(t.x,t.y,1,1))}),t=T(e.cells[0]),a(M[t.y],function(e){var t;e=e.elm,e!=n&&(t=o(e,"rowSpan"),1>=t?H.remove(e):d(e,"rowSpan",t-1),n=e)})}var t;t=m(),a(t.reverse(),function(t){e(t)}),p()}function R(){var e=m();return H.remove(e),p(),e}function N(){var e=m();return a(e,function(t,n){e[n]=s(t,!0)}),e}function S(e,t){var n=m(),o=n[t?0:n.length-1],l=o.cells.length;e&&(a(M,function(e){var t;return l=0,a(e,function(e){e.real&&(l+=e.colspan),e.elm.parentNode==o&&(t=1)}),t?!1:void 0}),t||e.reverse(),a(e,function(e){var n,a=e.cells.length,r;for(n=0;a>n;n++)r=e.cells[n],d(r,"colSpan",1),d(r,"rowSpan",1);for(n=a;l>n;n++)e.appendChild(g(e.cells[a-1]));for(n=l;a>n;n++)H.remove(e.cells[n]);t?o.parentNode.insertBefore(e,o):H.insertAfter(e,o)}),H.removeClass(H.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"))}function T(e){var t;return a(M,function(n,o){return a(n,function(n,a){return n.elm==e?(t={x:a,y:o},!1):void 0}),!t}),t}function P(e){D=T(e)}function A(){var e,t;return e=t=0,a(M,function(n,o){a(n,function(n,a){var l,r;u(n)&&(n=M[o][a],a>e&&(e=a),o>t&&(t=o),n.real&&(l=n.colspan-1,r=n.rowspan-1,l&&a+l>e&&(e=a+l),r&&o+r>t&&(t=o+r)))})}),{x:e,y:t}}function k(e){var t,n,o,a,l,r,i,s,c,d;if(I=T(e),D&&I){for(t=Math.min(D.x,I.x),n=Math.min(D.y,I.y),o=Math.max(D.x,I.x),a=Math.max(D.y,I.y),l=o,r=a,d=n;r>=d;d++)e=M[d][t],e.real||t-(e.colspan-1)=c;c++)e=M[n][c],e.real||n-(e.rowspan-1)=d;d++)for(c=t;o>=c;c++)e=M[d][c],e.real&&(i=e.colspan-1,s=e.rowspan-1,i&&c+i>l&&(l=c+i),s&&d+s>r&&(r=d+s));for(H.removeClass(H.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),d=n;r>=d;d++)for(c=t;l>=c;c++)M[d][c]&&H.addClass(M[d][c].elm,"mce-item-selected")}}function B(e,t){var n,o,a;n=T(e),o=n.y*_+n.x;do{if(o+=t,a=c(o%_,Math.floor(o/_)),!a)break;if(a.elm!=e)return L.select(a.elm,!0),H.isEmpty(a.elm)&&L.collapse(!0),!0}while(a.elm==e);return!1}var M,_,D,I,E,L=l.selection,H=L.dom;r=r||H.getParent(L.getStart(),"table"),i(),E=H.getParent(L.getStart(),"th,td"),E&&(D=T(E),I=A(),E=c(D.x,D.y)),e.extend(this,{deleteTable:f,split:b,merge:v,insertRow:x,insertCol:y,deleteCols:w,deleteRows:C,cutRows:R,copyRows:N,pasteRows:S,getPos:T,setStartCell:P,setEndCell:k,moveRelIdx:B,refresh:i})}}),o(u,[m,d,c],function(e,t,n){function o(e,t){return parseInt(e.getAttribute(t)||1,10)}var a=n.each;return function(n){function l(){function t(t){function l(e,o){var a=e?"previousSibling":"nextSibling",l=n.dom.getParent(o,"tr"),i=l[a];if(i)return h(n,o,i,e),t.preventDefault(),!0;var d=n.dom.getParent(l,"table"),u=l.parentNode,m=u.nodeName.toLowerCase();if("tbody"===m||m===(e?"tfoot":"thead")){var f=r(e,d,u,"tbody");if(null!==f)return s(e,f,o)}return c(e,l,a,d)}function r(e,t,o,a){var l=n.dom.select(">"+a,t),r=l.indexOf(o);if(e&&0===r||!e&&r===l.length-1)return i(e,t);if(-1===r){var s="thead"===o.tagName.toLowerCase()?0:l.length-1;return l[s]}return l[r+(e?-1:1)]}function i(e,t){var o=e?"thead":"tfoot",a=n.dom.select(">"+o,t);return 0!==a.length?a[0]:null}function s(e,o,a){var l=d(o,e);return l&&h(n,a,l,e),t.preventDefault(),!0}function c(e,o,a,r){var i=r[a];if(i)return u(i),!0;var s=n.dom.getParent(r,"td,th");if(s)return l(e,s,t);var c=d(o,!e);return u(c),t.preventDefault(),!1}function d(e,t){var o=e&&e[t?"lastChild":"firstChild"];return o&&"BR"===o.nodeName?n.dom.getParent(o,"td,th"):o}function u(e){n.selection.setCursorLocation(e,0)}function m(){return x==e.UP||x==e.DOWN}function f(e){var t=e.selection.getNode(),n=e.dom.getParent(t,"tr");return null!==n}function g(e){for(var t=0,n=e;n.previousSibling;)n=n.previousSibling,t+=o(n,"colspan");return t}function p(e,t){var n=0,l=0;return a(e.children,function(e,a){return n+=o(e,"colspan"),l=a,n>t?!1:void 0}),l}function h(e,t,o,a){var l=g(n.dom.getParent(t,"td,th")),r=p(o,l),i=o.childNodes[r],s=d(i,a);u(s||i)}function b(e){var t=n.selection.getNode(),o=n.dom.getParent(t,"td,th"),a=n.dom.getParent(e,"td,th");return o&&o!==a&&v(o,a)}function v(e,t){return n.dom.getParent(e,"TABLE")===n.dom.getParent(t,"TABLE")}var x=t.keyCode;if(m()&&f(n)){var y=n.selection.getNode();setTimeout(function(){b(y)&&l(!t.shiftKey&&x===e.UP,y,t)},0)}}n.on("KeyDown",function(e){t(e)})}function r(){function e(e,t){var n=t.ownerDocument,o=n.createRange(),a;return o.setStartBefore(t),o.setEnd(e.endContainer,e.endOffset),a=n.createElement("body"),a.appendChild(o.cloneContents()),0===a.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length}n.on("KeyDown",function(t){var o,a,l=n.dom;(37==t.keyCode||38==t.keyCode)&&(o=n.selection.getRng(),a=l.getParent(o.startContainer,"table"),a&&n.getBody().firstChild==a&&e(o,a)&&(o=l.createRng(),o.setStartBefore(a),o.setEndBefore(a),n.selection.setRng(o),t.preventDefault()))})}function i(){n.on("KeyDown SetContent VisualAid",function(){var e;for(e=n.getBody().lastChild;e;e=e.previousSibling)if(3==e.nodeType){if(e.nodeValue.length>0)break}else if(1==e.nodeType&&("BR"==e.tagName||!e.getAttribute("data-mce-bogus")))break;e&&"TABLE"==e.nodeName&&(n.settings.forced_root_block?n.dom.add(n.getBody(),n.settings.forced_root_block,n.settings.forced_root_block_attrs,t.ie&&t.ie<11?" ":'
'):n.dom.add(n.getBody(),"br",{"data-mce-bogus":"1"}))}),n.on("PreProcess",function(e){var t=e.node.lastChild;t&&("BR"==t.nodeName||1==t.childNodes.length&&("BR"==t.firstChild.nodeName||"\xa0"==t.firstChild.nodeValue))&&t.previousSibling&&"TABLE"==t.previousSibling.nodeName&&n.dom.remove(t)})}function s(){function e(e,t,n,o){var a=3,l=e.dom.getParent(t.startContainer,"TABLE"),r,i,s;return l&&(r=l.parentNode),i=t.startContainer.nodeType==a&&0===t.startOffset&&0===t.endOffset&&o&&("TR"==n.nodeName||n==r),s=("TD"==n.nodeName||"TH"==n.nodeName)&&!o,i||s}function t(){var t=n.selection.getRng(),o=n.selection.getNode(),a=n.dom.getParent(t.startContainer,"TD,TH");if(e(n,t,o,a)){a||(a=o);for(var l=a.lastChild;l.lastChild;)l=l.lastChild;3==l.nodeType&&(t.setEnd(l,l.data.length),n.selection.setRng(t))}}n.on("KeyDown",function(){t()}),n.on("MouseDown",function(e){2!=e.button&&t()})}function c(){n.on("keydown",function(t){if((t.keyCode==e.DELETE||t.keyCode==e.BACKSPACE)&&!t.isDefaultPrevented()){var o=n.dom.getParent(n.selection.getStart(),"table");if(o){for(var a=n.dom.select("td,th",o),l=a.length;l--;)if(!n.dom.hasClass(a[l],"mce-item-selected"))return;t.preventDefault(),n.execCommand("mceTableDelete")}}})}c(),t.webkit&&(l(),s()),t.gecko&&(r(),i()),t.ie>10&&(r(),i())}}),o(f,[s,g,c],function(e,t,n){return function(o){function a(){o.getBody().style.webkitUserSelect="",d&&(o.dom.removeClass(o.dom.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),d=!1)}function l(t){var n,a,l=t.target;if(s&&(i||l!=s)&&("TD"==l.nodeName||"TH"==l.nodeName)){a=r.getParent(l,"table"),a==c&&(i||(i=new e(o,a),i.setStartCell(s),o.getBody().style.webkitUserSelect="none"),i.setEndCell(l),d=!0),n=o.selection.getSel();try{n.removeAllRanges?n.removeAllRanges():n.empty()}catch(u){}t.preventDefault()}}var r=o.dom,i,s,c,d=!0;return o.on("MouseDown",function(e){2!=e.button&&(a(),s=r.getParent(e.target,"td,th"),c=r.getParent(s,"table"))}),o.on("mouseover",l),o.on("remove",function(){r.unbind(o.getDoc(),"mouseover",l)}),o.on("MouseUp",function(){function e(e,o){var l=new t(e,e);do{if(3==e.nodeType&&0!==n.trim(e.nodeValue).length)return void(o?a.setStart(e,0):a.setEnd(e,e.nodeValue.length));if("BR"==e.nodeName)return void(o?a.setStartBefore(e):a.setEndBefore(e))}while(e=o?l.next():l.prev())}var a,l=o.selection,d,u,m,f;if(s){if(i&&(o.getBody().style.webkitUserSelect=""),d=r.select("td.mce-item-selected,th.mce-item-selected"),d.length>0){a=r.createRng(),m=d[0],a.setStartBefore(m),a.setEndAfter(m),e(m,1),u=new t(m,r.getParent(d[0],"table"));do if("TD"==m.nodeName||"TH"==m.nodeName){if(!r.hasClass(m,"mce-item-selected"))break;f=m}while(m=u.next());e(f),l.setRng(a)}o.nodeChanged(),s=i=c=null}}),o.on("KeyUp Drop",function(){a(),s=i=c=null}),{clear:a}}}),o(p,[s,u,f,c,g,d,h],function(e,t,n,o,a,l,r){function i(a){function r(e){return e?e.replace(/px$/,""):""}function i(e){return/^[0-9]+$/.test(e)&&(e+="px"),e}function c(e){s("left center right".split(" "),function(t){a.formatter.remove("align"+t,{},e)})}function d(e){s("top middle bottom".split(" "),function(t){a.formatter.remove("valign"+t,{},e)})}function u(e,t){return o.each(t,function(t){t.textStyle=function(){return a.formatter.getCssText({block:e,classes:[t.value]})}}),t}function m(e,t,n,l){var r,i=[];return o.each(a.settings[t]||l,function(t){var o={text:t.text||t.title,value:t.value};i.push(o),(e[n]===t.value||!r&&t.selected)&&(r=o)}),r&&(e[n]=r.value,r.selected=!0),i}function f(){var e=a.dom,t,n,d,f,g;t=e.getParent(a.selection.getStart(),"table"),g={width:r(e.getStyle(t,"width")||e.getAttrib(t,"width")),height:r(e.getStyle(t,"height")||e.getAttrib(t,"height")),cellspacing:t?e.getAttrib(t,"cellspacing"):"",cellpadding:t?e.getAttrib(t,"cellpadding"):"",border:t?e.getAttrib(t,"border"):"",caption:!!e.select("caption",t)[0],"class":e.getAttrib(t,"class")},s("left center right".split(" "),function(e){a.formatter.matchNode(t,"align"+e)&&(g.align=e)}),t||(n={label:"Cols",name:"cols"},d={label:"Rows",name:"rows"}),a.settings.table_class_list&&(g["class"]&&(g["class"]=g["class"].replace(/\s*mce\-item\-table\s*/g,"")),f={name:"class",type:"listbox",label:"Class",values:u("table",m(g,"table_class_list","class"))}),a.windowManager.open({title:"Table properties",items:{type:"form",layout:"flex",direction:"column",labelGapCalc:"children",items:[{type:"form",labelGapCalc:!1,padding:0,layout:"grid",columns:2,data:g,defaults:{type:"textbox",maxWidth:50},items:[n,d,{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell spacing",name:"cellspacing"},{label:"Cell padding",name:"cellpadding"},{label:"Border",name:"border"},{label:"Caption",name:"caption",type:"checkbox"}]},{label:"Alignment",name:"align",type:"listbox",text:"None",values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},f]},onsubmit:function(){var n;g=o.extend(g,this.toJSON()),a.undoManager.transact(function(){t||(t=v(g.cols||1,g.rows||1)),a.dom.setAttribs(t,{cellspacing:g.cellspacing,cellpadding:g.cellpadding,border:g.border,"class":g["class"]}),a.dom.setStyles(t,{width:i(g.width),height:i(g.height)}),n=e.select("caption",t)[0],n&&!g.caption&&e.remove(n),!n&&g.caption&&(n=e.create("caption"),n.innerHTML=l.ie?"\xa0":'
',t.insertBefore(n,t.firstChild)),c(t),g.align&&a.formatter.apply("align"+g.align,{},t),a.focus(),a.addVisual()})}})}function g(e,t){a.windowManager.open({title:"Merge cells",body:[{label:"Cols",name:"cols",type:"textbox",value:"1",size:10},{label:"Rows",name:"rows",type:"textbox",value:"1",size:10}],onsubmit:function(){var n=this.toJSON();a.undoManager.transact(function(){e.merge(t,n.cols,n.rows)})}})}function p(){var e=a.dom,t,n,l,f=[];f=a.dom.select("td.mce-item-selected,th.mce-item-selected"),t=a.dom.getParent(a.selection.getStart(),"td,th"),!f.length&&t&&f.push(t),t=t||f[0],t&&(n={width:r(e.getStyle(t,"width")||e.getAttrib(t,"width")),height:r(e.getStyle(t,"height")||e.getAttrib(t,"height")),scope:e.getAttrib(t,"scope"),"class":e.getAttrib(t,"class")},n.type=t.nodeName.toLowerCase(),s("left center right".split(" "),function(e){a.formatter.matchNode(t,"align"+e)&&(n.align=e)}),s("top middle bottom".split(" "),function(e){a.formatter.matchNode(t,"valign"+e)&&(n.valign=e)}),a.settings.table_cell_class_list&&(l={name:"class",type:"listbox",label:"Class",values:u("td",m(n,"table_cell_class_list","class"))}),a.windowManager.open({title:"Cell properties",items:{type:"form",layout:"flex",direction:"column",labelGapCalc:"children",items:[{type:"form",data:n,layout:"grid",columns:2,labelGapCalc:!1,padding:0,defaults:{type:"textbox",maxWidth:50},items:[{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell type",name:"type",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"Cell",value:"td"},{text:"Header cell",value:"th"}]},{label:"Scope",name:"scope",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Row",value:"row"},{text:"Column",value:"col"},{text:"Row group",value:"rowgroup"},{text:"Column group",value:"colgroup"}]},{label:"H Align",name:"align",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},{label:"V Align",name:"valign",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Top",value:"top"},{text:"Middle",value:"middle"},{text:"Bottom",value:"bottom"}]}]},l]},onsubmit:function(){n=o.extend(n,this.toJSON()),a.undoManager.transact(function(){s(f,function(t){a.dom.setAttribs(t,{scope:n.scope,"class":n["class"]}),a.dom.setStyles(t,{width:i(n.width),height:i(n.height)}),n.type&&t.nodeName.toLowerCase()!=n.type&&(t=e.rename(t,n.type)),c(t),n.align&&a.formatter.apply("align"+n.align,{},t),d(t),n.valign&&a.formatter.apply("valign"+n.valign,{},t)}),a.focus()})}}))}function h(){var e=a.dom,t,n,l,d,f,g=[];t=a.dom.getParent(a.selection.getStart(),"table"),n=a.dom.getParent(a.selection.getStart(),"td,th"),s(t.rows,function(t){s(t.cells,function(o){return e.hasClass(o,"mce-item-selected")||o==n?(g.push(t),!1):void 0})}),l=g[0],l&&(f={height:r(e.getStyle(l,"height")||e.getAttrib(l,"height")),scope:e.getAttrib(l,"scope"),"class":e.getAttrib(l,"class")},f.type=l.parentNode.nodeName.toLowerCase(),s("left center right".split(" "),function(e){a.formatter.matchNode(l,"align"+e)&&(f.align=e)}),a.settings.table_row_class_list&&(d={name:"class",type:"listbox",label:"Class",values:u("tr",m(f,"table_row_class_list","class"))}),a.windowManager.open({title:"Row properties",items:{type:"form",data:f,columns:2,defaults:{type:"textbox"},items:[{type:"listbox",name:"type",label:"Row type",text:"None",maxWidth:null,values:[{text:"Header",value:"thead"},{text:"Body",value:"tbody"},{text:"Footer",value:"tfoot"}]},{type:"listbox",name:"align",label:"Alignment",text:"None",maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},{label:"Height",name:"height"},d]},onsubmit:function(){var t,n,l;f=o.extend(f,this.toJSON()),a.undoManager.transact(function(){var o=f.type;s(g,function(r){a.dom.setAttribs(r,{scope:f.scope,"class":f["class"]}),a.dom.setStyles(r,{height:i(f.height)}),o!=r.parentNode.nodeName.toLowerCase()&&(t=e.getParent(r,"table"),n=r.parentNode,l=e.select(o,t)[0],l||(l=e.create(o),t.firstChild?t.insertBefore(l,t.firstChild):t.appendChild(l)),l.appendChild(r),n.hasChildNodes()||e.remove(n)),c(r),f.align&&a.formatter.apply("align"+f.align,{},r)}),a.focus()})}}))}function b(e){return function(){a.execCommand(e)}}function v(e,t){var n,o,r;for(r='',n=0;t>n;n++){for(r+="",o=0;e>o;o++)r+="";r+=""}r+="
"+(l.ie?" ":"
")+"
",a.insertContent(r);var i=a.dom.get("__mce");return a.dom.setAttrib(i,"id",null),a.dom.setAttribs(i,a.settings.table_default_attributes||{}),a.dom.setStyles(i,a.settings.table_default_styles||{}),i}function x(e,t){function n(){e.disabled(!a.dom.getParent(a.selection.getStart(),t)),a.selection.selectorChanged(t,function(t){e.disabled(!t)})}a.initialized?n():a.on("init",n)}function y(){x(this,"table")}function w(){x(this,"td,th")}function C(){var e="";e='';for(var t=0;10>t;t++){e+="";for(var n=0;10>n;n++)e+='';e+=""}return e+="
",e+=''}function R(e,t,n){var o=n.getEl().getElementsByTagName("table")[0],l,r,i,s,c,d=n.isRtl()||"tl-tr"==n.parent().rel;for(o.nextSibling.innerHTML=e+1+" x "+(t+1),d&&(e=9-e),r=0;10>r;r++)for(l=0;10>l;l++)s=o.rows[r].childNodes[l].firstChild,c=(d?l>=e:e>=l)&&t>=r,a.dom.toggleClass(s,"mce-active",c),c&&(i=s);return i.parentNode}var N,S=this;a.settings.table_grid===!1?a.addMenuItem("inserttable",{text:"Insert table",icon:"table",context:"table",onclick:f}):a.addMenuItem("inserttable",{text:"Insert table",icon:"table",context:"table",ariaHideMenu:!0,onclick:function(e){e.aria&&(this.parent().hideAll(),e.stopImmediatePropagation(),f())},onshow:function(){R(0,0,this.menu.items()[0])},onhide:function(){var e=this.menu.items()[0].getEl().getElementsByTagName("a");a.dom.removeClass(e,"mce-active"),a.dom.addClass(e[0],"mce-active")},menu:[{type:"container",html:C(),onPostRender:function(){this.lastX=this.lastY=0},onmousemove:function(e){var t=e.target,n,o;"A"==t.tagName.toUpperCase()&&(n=parseInt(t.getAttribute("data-mce-x"),10),o=parseInt(t.getAttribute("data-mce-y"),10),(this.isRtl()||"tl-tr"==this.parent().rel)&&(n=9-n),(n!==this.lastX||o!==this.lastY)&&(R(n,o,e.control),this.lastX=n,this.lastY=o))},onkeydown:function(e){var t=this.lastX,n=this.lastY,o;switch(e.keyCode){case 37:t>0&&(t--,o=!0);break;case 39:o=!0,9>t&&t++;break;case 38:o=!0,n>0&&n--;break;case 40:o=!0,9>n&&n++}o&&(e.preventDefault(),e.stopPropagation(),R(t,n,e.control).focus(),this.lastX=t,this.lastY=n)},onclick:function(e){var t=this;"A"==e.target.tagName.toUpperCase()&&(e.preventDefault(),e.stopPropagation(),t.parent().cancel(),a.undoManager.transact(function(){v(t.lastX+1,t.lastY+1)}),a.addVisual())}}]}),a.addMenuItem("tableprops",{text:"Table properties",context:"table",onPostRender:y,onclick:f}),a.addMenuItem("deletetable",{text:"Delete table",context:"table",onPostRender:y,cmd:"mceTableDelete"}),a.addMenuItem("cell",{separator:"before",text:"Cell",context:"table",menu:[{text:"Cell properties",onclick:b("mceTableCellProps"),onPostRender:w},{text:"Merge cells",onclick:b("mceTableMergeCells"),onPostRender:w},{text:"Split cell",onclick:b("mceTableSplitCells"),onPostRender:w}]}),a.addMenuItem("row",{text:"Row",context:"table",menu:[{text:"Insert row before",onclick:b("mceTableInsertRowBefore"),onPostRender:w},{text:"Insert row after",onclick:b("mceTableInsertRowAfter"),onPostRender:w},{text:"Delete row",onclick:b("mceTableDeleteRow"),onPostRender:w},{text:"Row properties",onclick:b("mceTableRowProps"),onPostRender:w},{text:"-"},{text:"Cut row",onclick:b("mceTableCutRow"),onPostRender:w},{text:"Copy row",onclick:b("mceTableCopyRow"),onPostRender:w},{text:"Paste row before",onclick:b("mceTablePasteRowBefore"),onPostRender:w},{text:"Paste row after",onclick:b("mceTablePasteRowAfter"),onPostRender:w}]}),a.addMenuItem("column",{text:"Column",context:"table",menu:[{text:"Insert column before",onclick:b("mceTableInsertColBefore"),onPostRender:w},{text:"Insert column after",onclick:b("mceTableInsertColAfter"),onPostRender:w},{text:"Delete column",onclick:b("mceTableDeleteCol"),onPostRender:w}]});var T=[];s("inserttable tableprops deletetable | cell row column".split(" "),function(e){T.push("|"==e?{text:"-"}:a.menuItems[e])}),a.addButton("table",{type:"menubutton",title:"Table",menu:T}),l.isIE||a.on("click",function(e){e=e.target,"TABLE"===e.nodeName&&(a.selection.select(e),a.nodeChanged())}),S.quirks=new t(a),a.on("Init",function(){S.cellSelection=new n(a)}),s({mceTableSplitCells:function(e){e.split()},mceTableMergeCells:function(e){var t;t=a.dom.getParent(a.selection.getStart(),"th,td"),a.dom.select("td.mce-item-selected,th.mce-item-selected").length?e.merge():g(e,t)},mceTableInsertRowBefore:function(e){e.insertRow(!0)},mceTableInsertRowAfter:function(e){e.insertRow()},mceTableInsertColBefore:function(e){e.insertCol(!0)},mceTableInsertColAfter:function(e){e.insertCol()},mceTableDeleteCol:function(e){e.deleteCols()},mceTableDeleteRow:function(e){e.deleteRows()},mceTableCutRow:function(e){N=e.cutRows()},mceTableCopyRow:function(e){N=e.copyRows()},mceTablePasteRowBefore:function(e){e.pasteRows(N,!0)},mceTablePasteRowAfter:function(e){e.pasteRows(N)},mceTableDelete:function(e){e.deleteTable()}},function(t,n){a.addCommand(n,function(){var n=new e(a);n&&(t(n),a.execCommand("mceRepaint"),S.cellSelection.clear())})}),s({mceInsertTable:function(){f()},mceTableRowProps:h,mceTableCellProps:p},function(e,t){a.addCommand(t,function(t,n){e(n)})}),a.settings.table_tab_navigation!==!1&&a.on("keydown",function(t){var n,o,l;9==t.keyCode&&(n=a.dom.getParent(a.selection.getStart(),"th,td"),n&&(t.preventDefault(),o=new e(a),l=t.shiftKey?-1:1,a.undoManager.transact(function(){!o.moveRelIdx(n,l)&&l>0&&(o.insertRow(),o.refresh(),o.moveRelIdx(n,l))})))})}var s=o.each;r.add("table",i)}),r([])}(this); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/template/plugin.min.js b/web/resource/components/tinymce/plugins/template/plugin.min.js new file mode 100644 index 0000000..cee38af --- /dev/null +++ b/web/resource/components/tinymce/plugins/template/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("template",function(e){function t(t){return function(){var a=e.settings.templates;"string"==typeof a?tinymce.util.XHR.send({url:a,success:function(e){t(tinymce.util.JSON.parse(e))}}):t(a)}}function a(t){function a(t){function a(t){if(-1==t.indexOf("")){var a="";tinymce.each(e.contentCSS,function(t){a+=''}),t=""+a+""+t+""}t=r(t,"template_preview_replace_values");var l=n.find("iframe")[0].getEl().contentWindow.document;l.open(),l.write(t),l.close()}var c=t.control.value();c.url?tinymce.util.XHR.send({url:c.url,success:function(e){l=e,a(l)}}):(l=c.content,a(l)),n.find("#description")[0].text(t.control.value().description)}var n,l,i=[];return t&&0!==t.length?(tinymce.each(t,function(e){i.push({selected:!i.length,text:e.title,value:{url:e.url,content:e.content,description:e.description}})}),n=e.windowManager.open({title:"Insert template",layout:"flex",direction:"column",align:"stretch",padding:15,spacing:10,items:[{type:"form",flex:0,padding:0,items:[{type:"container",label:"Templates",items:{type:"listbox",label:"Templates",name:"template",values:i,onselect:a}}]},{type:"label",name:"description",label:"Description",text:" "},{type:"iframe",flex:1,border:1}],onsubmit:function(){c(!1,l)},width:e.getParam("template_popup_width",600),height:e.getParam("template_popup_height",500)}),void n.find("listbox")[0].fire("select")):void e.windowManager.alert("No templates defined")}function n(t,a){function n(e,t){if(e=""+e,e.length0&&(o=p.create("div",null),o.appendChild(s[0].cloneNode(!0))),i(p.select("*",o),function(t){c(t,e.getParam("template_cdate_classes","cdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_cdate_format",e.getLang("template.cdate_format")))),c(t,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_mdate_format",e.getLang("template.mdate_format")))),c(t,e.getParam("template_selected_content_classes","selcontent").replace(/\s+/g,"|"))&&(t.innerHTML=m)}),l(o),e.execCommand("mceInsertContent",!1,o.innerHTML),e.addVisual()}var i=tinymce.each;e.addCommand("mceInsertTemplate",c),e.addButton("template",{title:"Insert template",onclick:t(a)}),e.addMenuItem("template",{text:"Insert template",onclick:t(a),context:"insert"}),e.on("PreProcess",function(t){var a=e.dom;i(a.select("div",t.node),function(t){a.hasClass(t,"mceTmpl")&&(i(a.select("*",t),function(t){a.hasClass(t,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))&&(t.innerHTML=n(e.getParam("template_mdate_format",e.getLang("template.mdate_format"))))}),l(t))})})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/textcolor/plugin.min.js b/web/resource/components/tinymce/plugins/textcolor/plugin.min.js new file mode 100644 index 0000000..a42de76 --- /dev/null +++ b/web/resource/components/tinymce/plugins/textcolor/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("textcolor",function(e){function t(){var t,o,l=[];for(o=e.settings.textcolor_map||["000000","Black","993300","Burnt orange","333300","Dark olive","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","Red violet","C0C0C0","Silver","FF99CC","Pink","FFCC99","Peach","FFFF99","Light yellow","CCFFCC","Pale green","CCFFFF","Pale cyan","99CCFF","Light sky blue","CC99FF","Plum","FFFFFF","White"],t=0;t',a=o.length-1,c=e.settings.textcolor_rows||5,i=e.settings.textcolor_cols||8,F=0;c>F;F++){for(r+="",n=0;i>n;n++)d=F*i+n,d>a?r+="":(l=o[d],r+='
');r+=""}return r+=""}function l(t){var o,l=this.parent();(o=t.target.getAttribute("data-mce-color"))&&(this.lastId&&document.getElementById(this.lastId).setAttribute("aria-selected",!1),t.target.setAttribute("aria-selected",!0),this.lastId=t.target.id,l.hidePanel(),o="#"+o,l.color(o),e.execCommand(l.settings.selectcmd,!1,o))}function r(){var t=this;t._color&&e.execCommand(t.settings.selectcmd,!1,t._color)}e.addButton("forecolor",{type:"colorbutton",tooltip:"Text color",selectcmd:"ForeColor",panel:{role:"application",ariaRemember:!0,html:o,onclick:l},onclick:r}),e.addButton("backcolor",{type:"colorbutton",tooltip:"Background color",selectcmd:"HiliteColor",panel:{role:"application",ariaRemember:!0,html:o,onclick:l},onclick:r})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/visualblocks/plugin.min.js b/web/resource/components/tinymce/plugins/visualblocks/plugin.min.js new file mode 100644 index 0000000..8c48ed0 --- /dev/null +++ b/web/resource/components/tinymce/plugins/visualblocks/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("visualblocks",function(e,s){function o(){var s=this;s.active(a),e.on("VisualBlocks",function(){s.active(e.dom.hasClass(e.getBody(),"mce-visualblocks"))})}var l,t,a;window.NodeList&&(e.addCommand("mceVisualBlocks",function(){var o,c=e.dom;l||(l=c.uniqueId(),o=c.create("link",{id:l,rel:"stylesheet",href:s+"/css/visualblocks.css"}),e.getDoc().getElementsByTagName("head")[0].appendChild(o)),e.on("PreviewFormats AfterPreviewFormats",function(s){a&&c.toggleClass(e.getBody(),"mce-visualblocks","afterpreviewformats"==s.type)}),c.toggleClass(e.getBody(),"mce-visualblocks"),a=e.dom.hasClass(e.getBody(),"mce-visualblocks"),t&&t.active(c.hasClass(e.getBody(),"mce-visualblocks")),e.fire("VisualBlocks")}),e.addButton("visualblocks",{title:"Show blocks",cmd:"mceVisualBlocks",onPostRender:o}),e.addMenuItem("visualblocks",{text:"Show blocks",cmd:"mceVisualBlocks",onPostRender:o,selectable:!0,context:"view",prependToContext:!0}),e.on("init",function(){e.settings.visualblocks_default_state&&e.execCommand("mceVisualBlocks",!1,null,{skip_focus:!0})}),e.on("remove",function(){e.dom.removeClass(e.getBody(),"mce-visualblocks")}))}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/visualchars/plugin.min.js b/web/resource/components/tinymce/plugins/visualchars/plugin.min.js new file mode 100644 index 0000000..fc7e109 --- /dev/null +++ b/web/resource/components/tinymce/plugins/visualchars/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("visualchars",function(e){function a(a){var t,s,i,r,c,d,l=e.getBody(),m=e.selection;if(n=!n,o.state=n,e.fire("VisualChars",{state:n}),a&&(d=m.getBookmark()),n)for(s=[],tinymce.walk(l,function(e){3==e.nodeType&&e.nodeValue&&-1!=e.nodeValue.indexOf(" ")&&s.push(e)},"childNodes"),i=0;i$1'),c=e.dom.create("div",null,r);t=c.lastChild;)e.dom.insertAfter(t,s[i]);e.dom.remove(s[i])}else for(s=e.dom.select("span.mce-nbsp",l),i=s.length-1;i>=0;i--)e.dom.remove(s[i],1);m.moveToBookmark(d)}function t(){var a=this;e.on("VisualChars",function(e){a.active(e.state)})}var n,o=this;e.addCommand("mceVisualChars",a),e.addButton("visualchars",{title:"Show invisible characters",cmd:"mceVisualChars",onPostRender:t}),e.addMenuItem("visualchars",{text:"Show invisible characters",cmd:"mceVisualChars",onPostRender:t,selectable:!0,context:"view",prependToContext:!0}),e.on("beforegetcontent",function(e){n&&"raw"!=e.format&&!e.draft&&(n=!0,a(!1))})}); \ No newline at end of file diff --git a/web/resource/components/tinymce/plugins/wordcount/plugin.min.js b/web/resource/components/tinymce/plugins/wordcount/plugin.min.js new file mode 100644 index 0000000..c5f1788 --- /dev/null +++ b/web/resource/components/tinymce/plugins/wordcount/plugin.min.js @@ -0,0 +1 @@ +tinymce.PluginManager.add("wordcount",function(a){function b(){a.theme.panel.find("#wordcount").text(["Words: {0}",e.getCount()])}var c,d,e=this;c=a.getParam("wordcount_countregex",/[\w\u2019\x27\-\u00C0-\u1FFF]+/g),h=a.getParam("wordhcount_countregex",/[\u2E80-\u9FFF]{1}/g),d=a.getParam("wordcount_cleanregex",/[.(),;:!?%#$?\x27\x22_+=\\\/\-]*/g),a.on("init",function(){var c=a.theme.panel&&a.theme.panel.find("#statusbar")[0];c&&window.setTimeout(function(){c.insert({type:"label",name:"wordcount",text:["Words: {0}",e.getCount()],classes:"wordcount",disabled:a.settings.readonly},0),a.on("setcontent beforeaddundo",b),a.on("keyup",function(a){32==a.keyCode&&b()})},0)}),e.getCount=function(){var b=a.getContent({format:"raw"}),e=0;if(b){b=b.replace(/\.\.\./g," "),b=b.replace(/<.[^<>]*?>/g," "),b=b.replace(/ | /gi," "),b=b.replace(/(\w+)(&#?[a-z0-9]+;)+(\w+)/i,"$1$3"),b=b.replace(/&.+?;/g," "),b=b.replace(d,"");var f=b.match(c);f&&(e=f.length);var g=b.match(h);g&&(e+=g.length)}return e}}); \ No newline at end of file diff --git a/web/resource/components/tinymce/skins/lightgray/fonts/readme.md b/web/resource/components/tinymce/skins/lightgray/fonts/readme.md new file mode 100644 index 0000000..fa5d639 --- /dev/null +++ b/web/resource/components/tinymce/skins/lightgray/fonts/readme.md @@ -0,0 +1 @@ +Icons are generated and provided by the http://icomoon.io service. diff --git a/web/resource/components/tinymce/skins/lightgray/img/object.gif b/web/resource/components/tinymce/skins/lightgray/img/object.gif new file mode 100644 index 0000000000000000000000000000000000000000..cccd7f023fb80908cb33bb7d9604236cd21b7ae7 GIT binary patch literal 152 zcmV;J0B8S4Nk%w1VG#fg0J9GO<>lo+KR<78Z?v?uS65g4{r%Y3*xlXT%F4>`@9+2b z_ww@cot>Tk|Nk>HGXMYpA^8LW000jFEC2ui01*HU000C<(8)=wd#<&tyXIMjHBV`d zBSi|xsj3(;nD0kQ0aJq8eLH~x02P|t2!_J&Wqb%0io?#xD8U}fi7AzZCsS=07??9MLn2Bde0{8v^Kf6`()~Xj@TAnpKdC8`Lf!&sHg;q@=(~U%$M( zT(8_%FTW^V-_X+15@d#vkuFe$ZgFK^Nn(X=Ua>OF1ees}t-3#_`hBq$Z(46Le)Ln;eW^@CE2 z^Gl18f$@>14ATq@JNy=b6armi>cVAJd5X6R;MWawh(V&G(G=xXffXz1o@ zX=ZL{;B08&Z0-!x>zP+vl9-pA3bQv8XfIT+GhV$`&PAz-CHX}m`T04p6cCV+Uy@&( zkzb(T9Bihb;hUJ8nFkWk1Vs?Uzb>gonPsUdZbkXI3g8g7%EaOV0~10%hv-cqC)D(T zj?o7t52WM*69T3|5EGvGfgE`DNzDW1nId53*cQ_-&cMK^?CIhdQgN$ga=rIq1A(^5 zYKwg&`wo`WvF`u>{iFU|`!+wz>b#B?t8F4hxRm$~lz-tTH#6E8xZnKlv%`YRwvA{oKseqmK8(Gfx|> z#)dT+Zy!CGH{+89Q&m{rC!PyyIjq?Y9m+ziHPqr6qxfF`+2Qt=-KQ=fE8_j%1#Y2} z>NffN)P;AQIhrE)QQzeqbFS^A8(M1XGuQqTO<=fcH+M~2lzlL$Ao6teb6Mw<&;$U? C61Fb@ literal 0 HcmV?d00001 diff --git a/web/resource/components/ueditor/dialogs/emotion/images/neweditor-tab-bg.png b/web/resource/components/ueditor/dialogs/emotion/images/neweditor-tab-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..8f398b0958cdc5136a23b9745becc23a833aa325 GIT binary patch literal 216 zcmeAS@N?(olHy`uVBq!ia0vp^96&72!3HGF`uUCmDVAa<&kznEsNqQI0P;BtJR*x3 z7^L@rFypT63w8qqANLt@XPdKI8X22WQ%mvv4FO#q2N BK}7%n literal 0 HcmV?d00001 diff --git a/web/resource/components/ueditor/dialogs/image/images/progress.png b/web/resource/components/ueditor/dialogs/image/images/progress.png new file mode 100644 index 0000000000000000000000000000000000000000..717c4865c90a959c6a0e9ad1af9c777d900a2e9c GIT binary patch literal 1269 zcmeAS@N?(olHy`uVBq!ia0vp^f8U}fi7AzZCsS=07??9MLn2Bde0{8v^Kf6`()~Xj@TAnpKdC8`Lf!&sHg;q@=(~U%$M( zT(8_%FTW^V-_X+15@d#vkuFe$ZgFK^Nn(X=Ua>OF1ees}t-3#_`hBq$Z(46Le)Ln;eW^@CE2 z^Gl18f$@>14ATq@JNy=b6armi>cVAJd5X6R;MWawh(V&G(G=xXffXz1o@ zX=ZL{;B08&Z0-!x>zP+vl9-pA3bQv8XfIT+GhV$`&PAz-CHX}m`T04p6cCV+Uy@&( zkzb(T9Bihb;hUJ8nFkWk1Vs?Uzb>gonPsUdZbkXI3g8g7%EaOV0~10%hv-cqC)D(T zj?o7t52WM*69T3|5EGvGfgE`DNzDW1nId53*cQ_-&cMK^?CIhdQgN$ga=rIq1A(^5 zYKwg&`wo`WvF`u>{iFU|`!+wz>b#B?t8F4hxRm$~lz-tTH#6E8xZnKlv%`YRwvA{oKseqmK8(Gfx|> z#)dT+Zy!CGH{+89Q&m{rC!PyyIjq?Y9m+ziHPqr6qxfF`+2Qt=-KQ=fE8_j%1#Y2} z>NffN)P;AQIhrE)QQzeqbFS^A8(M1XGuQqTO<=fcH+M~2lzlL$Ao6teb6Mw<&;$U? C61Fb@ literal 0 HcmV?d00001 diff --git a/web/resource/components/ueditor/dialogs/music/music.css b/web/resource/components/ueditor/dialogs/music/music.css new file mode 100644 index 0000000..b2c6136 --- /dev/null +++ b/web/resource/components/ueditor/dialogs/music/music.css @@ -0,0 +1 @@ +.listPanel,.page,.resultBar{overflow:hidden}.m-h,.pageon{font-weight:700}.wrapper{margin:5px 10px}.searchBar{height:30px;padding:7px 0 3px;text-align:center}.searchBtn{font-size:13px;height:24px}.resultBar{width:460px;margin:5px auto;border:1px solid #CCC;border-radius:5px;box-shadow:2px 2px 5px #D3D6DA}.panelon{display:block}.paneloff{display:none}.page{width:220px;margin:20px auto}.pageoff,.pageon{float:right;width:24px;line-height:24px;height:24px;margin-right:5px;text-align:center}.pageon{background:0 0;border:none;color:#000}.pageoff{cursor:pointer;background-color:#fff;border:1px solid #E7ECF0;color:#2D64B3;text-decoration:none}.m-l,.m-m,.m-s,.m-t,.m-try-t,.m-z{float:left}.m-box{width:460px}.m-m{line-height:20px;height:20px}.m-h{height:24px;line-height:24px;padding-left:46px;background-color:#FAFAFA;border-bottom:1px solid #DAD8D8;font-size:12px;color:#333}.m-l{width:40px}.m-t{width:140px}.m-s{width:110px}.m-z{width:100px}.m-try-t{width:60px}.m-try,.m-trying{float:left;width:20px;height:20px}.m-try{background:url(http://static.tieba.baidu.com/tb/editor/images/try_music.gif) no-repeat}.m-trying{background:url(http://static.tieba.baidu.com/tb/editor/images/stop_music.gif) no-repeat}.loading{width:95px;height:7px;font-size:7px;margin:60px auto;background:url(http://static.tieba.baidu.com/tb/editor/images/loading.gif) no-repeat}.empty{width:300px;height:40px;padding:2px;margin:50px auto;line-height:40px;color:#069;text-align:center} \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/music/music.html b/web/resource/components/ueditor/dialogs/music/music.html new file mode 100644 index 0000000..e7ef04f --- /dev/null +++ b/web/resource/components/ueditor/dialogs/music/music.html @@ -0,0 +1,32 @@ + + + + + 插入音乐 + + + + +
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/music/music.js b/web/resource/components/ueditor/dialogs/music/music.js new file mode 100644 index 0000000..1c538bf --- /dev/null +++ b/web/resource/components/ueditor/dialogs/music/music.js @@ -0,0 +1,192 @@ +function Music() { + this.init(); +} +(function () { + var pages = [], + panels = [], + selectedItem = null; + Music.prototype = { + total:70, + pageSize:10, + dataUrl:"http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.search.common", + playerUrl:"http://box.baidu.com/widget/flash/bdspacesong.swf", + + init:function () { + var me = this; + domUtils.on($G("J_searchName"), "keyup", function (event) { + var e = window.event || event; + if (e.keyCode == 13) { + me.dosearch(); + } + }); + domUtils.on($G("J_searchBtn"), "click", function () { + me.dosearch(); + }); + }, + callback:function (data) { + var me = this; + me.data = data.song_list; + setTimeout(function () { + $G('J_resultBar').innerHTML = me._renderTemplate(data.song_list); + }, 300); + }, + dosearch:function () { + var me = this; + selectedItem = null; + var key = $G('J_searchName').value; + if (utils.trim(key) == "")return false; + key = encodeURIComponent(key); + me._sent(key); + }, + doselect:function (i) { + var me = this; + if (typeof i == 'object') { + selectedItem = i; + } else if (typeof i == 'number') { + selectedItem = me.data[i]; + } + }, + onpageclick:function (id) { + var me = this; + for (var i = 0; i < pages.length; i++) { + $G(pages[i]).className = 'pageoff'; + $G(panels[i]).className = 'paneloff'; + } + $G('page' + id).className = 'pageon'; + $G('panel' + id).className = 'panelon'; + }, + listenTest:function (elem) { + var me = this, + view = $G('J_preview'), + is_play_action = (elem.className == 'm-try'), + old_trying = me._getTryingElem(); + + if (old_trying) { + old_trying.className = 'm-try'; + view.innerHTML = ''; + } + if (is_play_action) { + elem.className = 'm-trying'; + view.innerHTML = me._buildMusicHtml(me._getUrl(true)); + } + }, + _sent:function (param) { + var me = this; + $G('J_resultBar').innerHTML = '
'; + + utils.loadFile(document, { + src:me.dataUrl + '&query=' + param + '&page_size=' + me.total + '&callback=music.callback&.r=' + Math.random(), + tag:"script", + type:"text/javascript", + defer:"defer" + }); + }, + _removeHtml:function (str) { + var reg = /<\s*\/?\s*[^>]*\s*>/gi; + return str.replace(reg, ""); + }, + _getUrl:function (isTryListen) { + var me = this; + var param = 'from=tiebasongwidget&url=&name=' + encodeURIComponent(me._removeHtml(selectedItem.title)) + '&artist=' + + encodeURIComponent(me._removeHtml(selectedItem.author)) + '&extra=' + + encodeURIComponent(me._removeHtml(selectedItem.album_title)) + + '&autoPlay='+isTryListen+'' + '&loop=true'; + return me.playerUrl + "?" + param; + }, + _getTryingElem:function () { + var s = $G('J_listPanel').getElementsByTagName('span'); + + for (var i = 0; i < s.length; i++) { + if (s[i].className == 'm-trying') + return s[i]; + } + return null; + }, + _buildMusicHtml:function (playerUrl) { + var html = ' 12) + return s.substring(0, 5) + '...'; + if (!s) s = " "; + return s; + }, + _rebuildData:function (data) { + var me = this, + newData = [], + d = me.pageSize, + itembox; + for (var i = 0; i < data.length; i++) { + if ((i + d) % d == 0) { + itembox = []; + newData.push(itembox) + } + itembox.push(data[i]); + } + return newData; + }, + _renderTemplate:function (data) { + var me = this; + if (data.length == 0)return '
' + lang.emptyTxt + '
'; + data = me._rebuildData(data); + var s = [], p = [], t = []; + s.push('
'); + p.push('
'); + for (var i = 0, tmpList; tmpList = data[i++];) { + panels.push('panel' + i); + pages.push('page' + i); + if (i == 1) { + s.push('
'); + if (data.length != 1) { + t.push('
' + (i ) + '
'); + } + } else { + s.push('
'); + t.push('
' + (i ) + '
'); + } + s.push('
'); + s.push('
' + lang.chapter + '' + lang.singer + + '' + lang.special + '' + lang.listenTest + '
'); + for (var j = 0, tmpObj; tmpObj = tmpList[j++];) { + s.push(''); + } + s.push('
'); + s.push('
'); + } + t.reverse(); + p.push(t.join('')); + s.push('
'); + p.push('
'); + return s.join('') + p.join(''); + }, + exec:function () { + var me = this; + if (selectedItem == null) return; + $G('J_preview').innerHTML = ""; + editor.execCommand('music', { + url:me._getUrl(false), + width:400, + height:95 + }); + } + }; +})(); + + + diff --git a/web/resource/components/ueditor/dialogs/preview/preview.html b/web/resource/components/ueditor/dialogs/preview/preview.html new file mode 100644 index 0000000..f6b433b --- /dev/null +++ b/web/resource/components/ueditor/dialogs/preview/preview.html @@ -0,0 +1,40 @@ + + + + + + + + + + +
+ +
+ + + \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/scrawl/images/redo.png b/web/resource/components/ueditor/dialogs/scrawl/images/redo.png new file mode 100644 index 0000000000000000000000000000000000000000..12cd9bbefc637c7c0a394d00e9d70333ac0f6ea5 GIT binary patch literal 454 zcmV;%0XhDOP)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUzL`g(JR5(v#U>Fi0G&GbsGc&WABFAQBW&H;lG7V%HSq6a&=p3^@!o0LWNZTU!fu9x(;+;T6gAK| zUX3q)K?dNALXZKDj*f0X1N4B{3W%M7*b|6-p|o>kWaLs-R#pQbUlE7}(JkW!3Wxx) wG!QERu?7%p1F;U22Ju1SAbF5FkorLa0CKM2R>lkau>b%707*qoM6N<$f*t~~2mk;8 literal 0 HcmV?d00001 diff --git a/web/resource/components/ueditor/dialogs/scrawl/images/redoH.png b/web/resource/components/ueditor/dialogs/scrawl/images/redoH.png new file mode 100644 index 0000000000000000000000000000000000000000..d9f33d38a3d11ce10447830ce409a0890ecad264 GIT binary patch literal 536 zcmV+z0_XjSP)LlRro!K@`S+vst67f)FhPH9;i)IZy=QifsP%Q^7=yx~FIm{DVqJh#8yN2on55 zK6niC-hAJD?=d5!lvD$)D)w6iOxq2aw)?eGO}w=Q({?4W2uyj7_3$nS0b08|CV^$s zcEc4Nn6?`Q=790%;vf4s`J3kd?(rXB%yX=pvVdv3pMkYfEM|mb9T>VsU5&ud zHR{zG?2nRrWd3EgfMHFMKLD%wc#k35+Fxy@XQ-Rrp?E*AqO06&F51~7BhBb9F%{CA zdmJPWQouxT{!<~+LW6%qD0@z^RN@x6tuTZA%{2bb;RZ0`Io4$$5UD%$(J!*|z&Fpa za?fuyZTGrH*P6~!{%Io9+`*3VLY0+{d|s}SVM0@>uRpF)fd0F8hF zgjKx=6b8R6tZy&P{3zz{+r)RSrIc5o-hmLJL6K@zgn|6H_V+Po~-c70vN1t=1+A%PQ29uxwx4>qZSNmg$Vo0WSSm;`Hl{Ww|6H_V+Po~-c6&>|-aSW-r_2!NtU#o%$i-Y0&su(f8j@G?~f`NtGer^@M zrYdIdrP)2_bk~ELr2i)^H(PkDy?QdpIbuVC@BX&$s!L5iRYqm|O_N&n@I;(N<+i7f+;9Z? Phk?P<)z4*}Q$iB}^elK+ literal 0 HcmV?d00001 diff --git a/web/resource/components/ueditor/dialogs/template/images/pre2.png b/web/resource/components/ueditor/dialogs/template/images/pre2.png new file mode 100644 index 0000000000000000000000000000000000000000..5a55672c1f9c4d41d5b5cf52d76bb2b7e7c6b186 GIT binary patch literal 394 zcmeAS@N?(olHy`uVBq!ia0vp^DM0MT!2~3?K3Qf5q$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~;1Ffi(Px;TbZ+h>KHoj_IVWAxIr&Fiabo)3x94Up%M35SEe^0#X9dS;F-9{&3Ljos=IM}2LB&w>e?K^KZ|9tHA z)W~h}eTfo>R&7s^?LYqdE7+t-Dv4L4H{``lKYf(JYIB0^>jrz9Khf>{)o!mlw-~mt za!)h6<9vO9zW09 gTfg@IqFVdQ&MBb@0QJAA?EnA( literal 0 HcmV?d00001 diff --git a/web/resource/components/ueditor/dialogs/template/images/pre3.png b/web/resource/components/ueditor/dialogs/template/images/pre3.png new file mode 100644 index 0000000000000000000000000000000000000000..d852d29f13bcf743e15df824901ab568123a5aae GIT binary patch literal 485 zcmVTEH>0M4JV5-1QxJ>b$K`ZPMW6ena#ScoGi+aGE}QBI9b2~7O)VofCVgI z0Sj2@r|V8tRYg%8l35(bVHm0eOOPtd@{r7;D7wSi^O|UT7k&b(?|avE4}m2@pKY0^ zX8{XXz`D@ra0V&khG!6NNY4Tm0v50s9T*)L9q3sISir&!aYH5D@CmFqjy=yiBr_3O zu`P1E)qr;HnlAuCCeD2n8T2!dey#!;npC;SpUiv|xYU?E`rwKTr@$H|hS bPXPu1`Qm#ITgjGb00000NkvXXu0mjf8+_C8 literal 0 HcmV?d00001 diff --git a/web/resource/components/ueditor/dialogs/template/images/pre4.png b/web/resource/components/ueditor/dialogs/template/images/pre4.png new file mode 100644 index 0000000000000000000000000000000000000000..0d7bc72ab99fe2c0ed9de1d89fd1c3e82ac3fd43 GIT binary patch literal 393 zcmeAS@N?(olHy`uVBq!ia0vp^DM0MT!2~3?K3Qf5q$EpRBT9nv(@M${i&7aJQ}UBi z6+Ckj(^G>|6H_V+Po~;1FfeL+x;TbZ+5xOQzYV@t-I~V=Oc$U@%9?>h?uf)>*!tD zz9*sh?!vZ&M%HQV5wX`#zTA@g`shVPPoZs!AO#y_jv5_v2~@eKa{lwdV71lh?Z-1u+JRxq;OXk;vd$@?2>^GKp!om* literal 0 HcmV?d00001 diff --git a/web/resource/components/ueditor/dialogs/video/images/none_focus.jpg b/web/resource/components/ueditor/dialogs/video/images/none_focus.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7c768dcb47aaa289135afd2bd0e8eb0b6ecb7536 GIT binary patch literal 11546 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 C61Fb@ literal 0 HcmV?d00001 diff --git a/web/resource/components/ueditor/lang/en/images/music.png b/web/resource/components/ueditor/lang/en/images/music.png new file mode 100644 index 0000000000000000000000000000000000000000..2f495fe92ffecdce42b74fd57dca2687414711fb GIT binary patch literal 91561 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 LNkvXXu0mjf3l)h% literal 0 HcmV?d00001 diff --git a/web/resource/components/ueditor/lang/zh-cn/images/music.png b/web/resource/components/ueditor/lang/zh-cn/images/music.png new file mode 100644 index 0000000000000000000000000000000000000000..354edebc341b43e56a5e809686e17c279125b026 GIT binary patch literal 23106 zcmV*UKwH0wP)KLZ*U+5Lu!Sk^o_Z5E4Meg@_7P6crJiNL9pw)e1;Xm069{HJUZAPk55R%$-RIA z6-eL&AQ0xu!e<4=008gy@A0LT~suv4>S3ILP<0Bm`DLLvaF4FK%)Nj?Pt*r}7;7Xa9z9H|HZjR63e zC`Tj$K)V27Re@400>HumpsYY5E(E}?0f1SyGDiY{y#)Yvj#!WnKwtoXnL;eg03bL5 z07D)V%>y7z1E4U{zu>7~aD})?0RX_umCct+(lZpemCzb@^6=o|A>zVpu|i=NDG+7} zl4`aK{0#b-!z=TL9Wt0BGO&T{GJWpjryhdijfaIQ&2!o}p04JRKYg3k&Tf zVxhe-O!X z{f;To;xw^bEES6JSc$k$B2CA6xl)ltA<32E66t?3@gJ7`36pmX0IY^jz)rRYwaaY4 ze(nJRiw;=Qb^t(r^DT@T3y}a2XEZW-_W%Hszxj_qD**t_m!#tW0KDiJT&R>6OvVTR z07RgHDzHHZ48atvzz&?j9lXF70$~P3Knx_nJP<+#`N z#-MZ2bTkiLfR>_b(HgWKJ%F~Nr_oF3b#wrIijHG|(J>BYjM-sajE6;FiC7vY#};Gd zST$CUHDeuEH+B^pz@B062qXfFfD`NpUW5?BY=V%GM_5c)L#QR}BeW8_2v-S%gfYS= zB9o|3v?Y2H`NVi)In3rTB8+ej^> zQ=~r95NVuDChL%G$=>7$vVg20myx%S50Foi`^m%Pw-h?Xh~i8Mq9jtJloCocWk2Nv zrJpiFnV_ms&8eQ$2&#xWpIS+6pmtC%Q-`S&GF4Q#^mhymh7E(qNMa}%YZ-ePrx>>xFPTiH1=E+A$W$=bG8>s^ zm=Bn5Rah$aDtr}@$`X}2l~$F0mFKEdRdZE8)p@E5RI61Ft6o-prbbn>P~)iy)E2AN zsU20jsWz_8Qg>31P|s0cqrPALg8E|(vWA65poU1JRAaZs8I2(p#xiB`SVGovRs-uS zYnV-9TeA7=Om+qP8+I>yOjAR1s%ETak!GFdam@h^# z)@rS0t$wXH+Irf)+G6c;?H29p+V6F6oj{!|o%K3xI`?%6x;DB|x`n#ibhIR?(H}Q3Gzd138Ei2)WAMz7W9Vy`X}HnwgyEn!VS)>mv$8&{hQn>w4zwy3R}t;BYlZQm5)6pty=DfLrs+A-|>>;~;Q z_F?uV_HFjh9n2gO9o9Q^JA86v({H5aB!kjoO6 zc9$1ZZKsN-Zl8L~mE{`ly3)1N^`o1+o7}D0ZPeY&J;i;i`%NyJ8_8Y6J?}yE@b_5a zam?eLr<8@mESk|3$_SkmS{wQ>%qC18))9_|&j{ZT zes8AvOzF(F2#DZEY>2oYX&IRp`F#{ADl)1r>QS^)ba8a|EY_^#S^HO&t^Rgqwv=MZThqqEWH8 zxJo>d=ABlR_Bh=;eM9Tw|Ih34~oTE|= zX_mAr*D$vzw@+p(E0Yc6dFE}(8oqt`+R{gE3x4zjX+Sb3_cYE^= zgB=w+-tUy`ytONMS8KgRef4hA?t0j zufM;t32jm~jUGrkaOInTZ`zyfns>EuS}G30LFK_G-==(f<51|K&cocp&EJ`SxAh3? zNO>#LI=^+SEu(FqJ)ynt=!~PC9bO$rzPJB=?=j6w@a-(u02P7 zaQ)#(uUl{HW%tYNS3ItC^iAtK(eKlL`f9+{bJzISE?u8_z3;~C8@FyI-5j_jy7l;W z_U#vU3hqqYU3!mrul&B+{ptt$59)uk{;_4iZQ%G|z+lhASr6|H35TBkl>gI*;nGLU zN7W-nBaM%pA0HbH8olyl&XeJ%vZoWz%6?Y=dFykl=imL}`%BMQ{Mhgd`HRoLu6e2R za__6DuR6yg#~-}Tc|Gx_{H@O0eebyMy5GmWADJlpK>kqk(fVV@r_fLLKIeS?{4e)} z^ZO;zpECde00d`2O+f$vv5tKEQIh}w03c&XQcVB=dL;k=fP(-4`Tqa_faw4Lbua(` z>RI+y?e7jKeZ#YO-CPhUwyK~#9!?7exA9M^p&_{vcV@Q5GqIB1jP=js}RM33N9aK%>!Dbyww4XI8%b<5gz8Gc&6Jkf1#k9f?9#R#sMK zR=zL4@B4i}v|Pmq00AHb0DyphAb%Fd007uu1|iA9?Il6^K%q;bV2Y^c)Rtf@*|3oH z^Yc;E0@Qv$isdl?V88$vz{8zC@)Gvni`l)3qqZ>E8%Wsg*#FRAG1VTH?jI!V1o~eb zxkI3feNKM_5{_xCV-)oW_7aYI3-0PA%+JK!6D)ZzW_P>z5Y4S_*%V6ah60v9eqZV?O zI#EX|<}^6pxaT3q6bti%y=2+`tN!oKw%haD-;129!DrdjGGve07RJo-?RDDJ7TTTP zwQWaFQL%ZSSa+Uh3tRC!Ylp>>gK3*b2g$4;}y&8R$Wv;Ijf^Zb0foZjo z6tMWnQjfjlRS&>4I~YxV)kl&sEpl86P>B`b5yZS|1#5Ex5sD&e09EF=U@TwF~NpTjisNb}d*a}n2 zbLXd}K&&DAKiEIE{XnP+DUg~9chg4=ha+gjpC>dj3PC*9p~i>AO-(I{~ycfGmbb@5MCm} zl7k@JHM|Pv1UaGv3&TE+2d^Rz5K>cns!f&dG3CyWfsUp8RQz!mEB+rJh2d_1Rs7Av zQ8)`Jh}{jsD`9J~0$v4+c^Eu3F{e6G8wOe3KD4rFxfn{O5 z+Q1YoILu{HLmildSj2%TO2wltz{uCjf}7Id5!{_>!Z6YPAb*|YzrkWsc!h;AA1T-q z6mL|=QE&h$NCA3RVA*_t4yy%GL|#|w822dj1Ko971Hl4+mip-kz{gmfglao{zQy zG|^$2%=Y*bFi@TM2K*GwAlMzYD;Uk_(L)@;keVH!#|O*g-z#c8;o6@quu7Ia8zZ=n5hU>i=HnqRv_rwQcW%H5u~v& z3gZ)Ll+;m*>ElkZv<`djA@O{J7-tTJC_6p@n>ts?r^s*?e)QO?jj-lz%zzgk_#o6~ zvJiXa#u!?-4YH7MS4^9juwrn~SolVU9SwCZ)tXvCL%@5%L>)?H|A{%CbBF*5>=n)T zVf7$}v2tugXd@7VW6H2%aL0l|8s~#>3<67qtwP`xs5Qzi4n%CCsw<%otN$N~t-6I0 zsxtx0a25(V{UCaWV}+C~0a-H475JyPyN5V(;fIH?I(MW3d&S(z2dIk1Wz@(|o|^=1 z$*z&@u>$dGi-$YdjbJpQBud9L#tUXjI0$BnyBo2?m=06242tsO*a|j**WfnHE7|OL z%Z|WKJWa4$#sn0Y6hhgeu8xH%_@PXxPYTOX6_%|*!ctK@m&h|(?3osa$?BF3M1r@D zcH7YkBNCKi6yPsgg4q#J=Yya)gY1Yq{=0~O3j4ok+G8cx`=XS@hla53+E~0D)qI47 zWR@$}>ku?b1Gh|KYvVPf9E3H*T&fAg!vRpjlGTb(OKOxy@qh-ePaz5EK+CCErqi`Y zDlEY}Qf!6PQW0WTj@8@>3blZv?hQ&PjwXwuAXPYk#Seh5)H-Z@GgQpwrT79ruyIVq zaH$S~_R;nqPin>&(WD`1W3((1^VAWP1<$nN~ZJW!aS@Gy?W1WDIb zs=2im9?2%KnnUTT+)t%;;n;K=Qtz@jC4LZEhK9T3^&SvO;TQ-G$5}s$0UWWMSVU^N zHd1gz3h2kvoig@QbPvz6+d5QC>NxfIhXsq_~IEs41aPN;3S!IcN?HDV3>KLFb#Z$5h!SJaByP07~ ziklxq~3tLBk?_kNO0|mnjnf~OT~9R2B=Dj zu;?p&pbv_Im#VZn9KuLlT_A-*YIhHZp?FOYG1gn8HdsMC6aX><8VVU{X+;(DI;n`Q z)@tsO-CVR9_wB}=Qhmv3)?H8Bk^{p%|K!=tAXwfbfvpl-#Uq1a!cr8)#cV)63t>W~ zWM52~FY^0FuK|Z@b|`!km9SJ*_#p>TGE^Hb2!f(`P)cKA7L?(5^^zYk!U~+<9Ajk* zceZWq&!Jvbt&Yl${JbkPD)$gt)>=ACj~dbI)ox8(v`DQOFg1~-0k z^^#VoCa9`^jOoP}F$%FKeT^8{)R-D>T5yQsuwTp{k0bzkK zzpLbij{spY7|Qnf2(09!MC~9#M^I!}SrnH+XJgrH9XUZ#8iI<=sBhsK7N_4uyQSIc zGgIcxL4vZmT4|oUz53eB`hPfg?~i_Z=QqAL{V!ji`!{Fry>xZu%a;@3&pp%K# z-CxUXB6Y19?Yn8KjVwlnZt@sH_9~8{8}j=~Q1`eg$gsA}R#t$Y2%^fjvSm369G+5n ztfbROzA1W&V>#xW7-w&IUYjXY*IKf>7TQw@YE4tZ>ruaJ>oHUbHKa7xawCU_l}wWg zr;tHgqbiTEFmTXp6k^Ty0k9IOE1=>Qks6n&L^Mv_lK?|@2wJT)?^}%}yRl$3=F9a3 zYvbrC&g0-n_SZkTMd~KT3W2pNXn?yxJ>4R;$P)=d8PAOYIvg{03UB-)x{#Qoc4lPR zM)X!;rGzalki;?q3oDew_U}D*DCmcWu(V5K2hV7t{*FKQyi{s0}eG&NtEYRsq z_e|(9^kD^Fa}2D{70H9Hn0TxhLQ;UR0F-H&v|=KrhBEj|COaZFlwCS%sYXmP@19w| zZ#P!#=AzxWXV&kTb=P~yBa4P$dtZ7-A-%OXxwSX7tv8iT>f|$Cy|MNe*H(ChHJbfr z$G63E_9zF{hk_%}Mxo6{2&{MzD>6F)D_(e{a6w9D#qTE&2V`LdXaY68h1G!#n61zV zJ{@z_9r&?S3ENjw+(Aa2+9DrAAz&)S9f1pTget-co6-rgnsU)?B+-4S#E39%1w}Zm zM2GahKR5rCAJ6^UcNbo|w({1U@?5Fb^f2Bq`Q-l%_9XTXrGIJf;1>?`|KZQ={9it^ z<@ZjFeSUY(r+4*lPPMX0oz9RF-|o6CP^X@%)Ih6y{RqX#cgJdcq{=C?yF@OuA}nVA zN3dYR*&_O+tOuwEjET80>uZmxOT>Z!e^`=2KhyQkjGnlNI{GjpDbj@(AnDXzrgqx2Yg{!=u~mIcLz>Jp}5V_BN7d{BJp z>avKie)IY5-O*1t2DTC`)cAqHNJy|jWH_qS=B}!h6WmaK|Atk`H!AdNR@T9IQKQZNTAh6m93jsI|(}@g2$GNU@UW4qNuKUq959pI;3T}NR3)U1UP8}9U9L3%D$n0bZGF8Key+PPi^_q zi{t;*p4s=b%m)rD)ji&5+bUpGJV|*=@%BK3n8dW{~)w)ptvNKNl0RMWm@Y5S)2n1x9&W` zy0Y|x4^{<$lmCrR?U34w!(yit@=$o!+*hVnU%IlyZ@}jKZ+>dWhDAQC;8T!{^Xdv@ zA+@a>tF+GJcxjLlOn%M*H5`!C zn(u9tHYlKPRxp07(i#xuZV&3q?9lWDh4)=rc_d~?VIjMRs|vJ*q$jycTc|qpu%y$k z89GvtX`|7Q`lM9eA1eeSur+R`wC9}^VF`b(+YHOsHP#aE_QWC&{< zVr)iSn84|&)bsCOU-{ORMQ+){oAX}`HUP;LG8`WQu)$UM0T5P94hz(c@IolH@Mhf) z!abn}&I{eREo(y{OT`ff+8_2iS7DGhA@=}04?G!wVlY&fXVgc7u&{Usi{felAz99< z`Lq@(=OBEgBmOun@j#ob(**Om3s{!7)u>B2EUexJy7tXdvoLgaIL|Th&#_D;bS2AU zMZH*LeWj_)R^1poBlTff@h}UQJQdan{DG&U%N%bAKW^B))m0s$L^q`OmCS<{u)V>n z4t4%_YJ?S8b(l-VdMu|M9~RTS8Fhq%4GtzK!ce11vr;V+GFXXV3S>@qY3JuaF(K1$ zUB3VQDM6&$-2257J0p!|-G)X=U;WZ^6lDl|L=Yox+I?uZN1BSI%~rG^sG;@&@~}LEAxboUToD$BmB{_= z#{8^ea)T8kzk%_u3r=4vPEEPWTg;956t4tAZa2ozsMn>{ekwjll~gJAbF|}RqFR>p z(_3y6WZ2D)w`U|A7LU$s>3-fwpG5U>vEm^z={m!!{8VnH$czdVpM@WiW~%by13<;L z4Go&Lisn~|R&2Y2uxwfWM7%lyrsJnc`QX)cz9_N^__0kK6>U~{L!(FdP#NyYLNenO zsKdoYEs`U@q&kZ<+WcFW7rsBWBtcjwcPptn)voBKPfxJe_pUE}i_`d#zuzyZZ*4v*6s)u^MgXN z!yrZ^uc1NK001aEwOR{$(&?TAcpk2M$cr+1At9%M3&6@JfYes3)Y|t+oX6^M#!#_U zLMl5HA;xLd^|jE6V7oBO@7O}OK}l~Cvz44liL^=3V;Px1hHK1OxBliG^ zRTem`juK>PpVdl*e7mKk#alBo2_19<2_5AUpkvn-YXeMKGMB7=kgT6PUVHTwa=b{* zFYT*>kLOhAnuDmm%^QVRl6zuxDk+i@UMS4v6vBUr??thPK@9NCOAFt>E{Jqn`o8$W z?)bxac-Vl-@l57?_uAs0UlI{k-*3OTTLpZ=@lJT#8x2892LNzgcYbkocyv@wLa7rG zQab1|G_A!$IBu(TW#;aVv2k&~1qkc=ubn>e!YQ)T2rA(oh8FQDH}5PAk8TOEk0o`; z=({}a`NF1065heHqwy{G8fPud{EA4 z?~}jy;pyjJI0aNkf|&5?vE{S)JS?E@bz-!hG4ctcE z!x#We%dS@)I&K08iEvR^%(p#Yd{*cat35jtH)rx?*LG?>`JvldjR6Q)x{d&$CAUMSfvec zSSa2?D2mmRtWDO(P2~m-0a*ZYVJn#Njmi1%U6UZJ-+J*0xhxk$(21GrM3(x_)x|%b zoabJ8dTZZrpL!w^?1-acKJhRIw`>`jFnxqMqq=*i~d+q+OacttPSm+T;{9sZ83)oM+r zTwGtDUsybNXrixBpy61^qh#7M^NTxo?*X5~T3IWdzczjN$T3D${5TU>AW3V$o!UTn z=#|+Hvrc&qgjA`)4CWHksrejH9EPnzyj_h(9b=FC1B|8hYaK<>l(PwOa?OP;!QuwA z(;8$6qnoAWmE~e-&2$JXQ#*IcXF0yelBA!aqN?w<}H| zkmug~>FHoIMm7!Ye{zqJFy6Z`Nsx#{EHjK3K6Tu6-KiVXi_5Fr3QxXxiWdG14SEa! zfJ@h=^hA2c_&EKob<}>f)`F_b!1j2r zAvGLlWl%GjNHkq{`tIWBmTl104hKkR4-?qlzPDKSV0dKIvF(}Z>9%aWZ%?5&S6nZ> zJ9#CW&0&B-Z|?BEJzcGNr3UrZ$6Y1-(0r~KB0Ek)jLdH-&Y~SC;l1;u%9NbLQuAW? zVN{~gm`kb>#z}PI-ASh90UUn%=%-#dHF4zVi5E}p-m@o@Nhb{B;QmkS-M9b53#Xnw za`fbj%=Eo1AoXkJrPc61`GvKP$OXXxbEhbfv$IQ)}cW%$cbjiCO z5FAmdR0FnarC2Pkmx?RP$aCFVC7}VCHft3_1J`G}dhlMR)l_-W)+eQix zJy)sPa51@X_hu4=Me5f3-o8gGn*jn^kxkoo&DGk9dYMwWw6%(#PD!8if1Z!!lL9y^EL@taoLjL*1 zJKwo-PXIXm|NPVYA_r~N#&=~1`pYZ#{_Nr%aRdIx&+JpVmQ+pj=yLpEd9Usi@>u}5 zcYi5c7$n}S0OJ@Mq_plj-!+M~{KRQ3U`Q1Ckm5z^gwwvv2=_LVtm_zv({k z`Cw+QM$t4QdZK+C#A)e#k$2gh>np;on zptaf>Us4Bf>zSUcKd@J7j)`6W)j$m-Kkt>5C-&?*eDJB@Rn)8}HE7f-w8|L>bf#$r zJQV$1+TMj`Q&ik&{x0ZTP4?=}-MbG?O!W8n2dC+-UAqq*p2(y#8$Qveu3dF(+hOxR zuuy5pNt}H>sd}x}tpeEQkLvYZyY~b<-GM_Bo#%%qcJA6u_D?30P9zcmdK&j%4c^rw zuy3ta3;Zcbkuy!J>cVo_aa>p`JE>%ncq87wF>5wpvE&3(yVeM{u<15G_CBmf`am*- z1yPoCPzAIDZ)%tJC4_Kj1dQ4I&o12l%l8G5Zd?Dq_{{!pNxO}uBmL$3^IyMkTe1N^ zw?A@lr_-ha6Vtp-tB%mZ4p~g|1#4S}^FI}IWJ9u~^*si1o7@+AXI}G+x2#dUtiEY3z+5-TvvR1nA!Q4}a zCg`&IHGCX6tVcYx;&5BCagRwNrSnMXBvK?pTQdKYBu&Y8oGCc0 zjptQ%r7*db;o#NU?`aO z4GeABF}{6lJe$w8Ya!HFKIj(m*1PA)lY!nW$7F%Jeto887F#S``Gx79piw&Ky4?{;_~Y9T8TJ- z=trOu-d$L1crZfQ=*1)GV*c0&GN087!Lts}M zpy|1kPE^9(zNL%a<`!0}s2n6D8$7?Tc8afTK;`~%1Rl-`sE!wqgE=Len z({Xi2z;&J8f!a?&!0}K_~$1OF}|})wR<5({oQ9nh>L0M>7BbSEuI|*X_Og z572uxpM>5-7{XFfdw&xVmJ^w%C7>i4H*q|d!!84{GcB>KV;z|z=db{W;Um<+hN`Ub zh$L^e1Byf?ben+XsY#%&RU8-?Jn_P*!%rW5{)JPACXPPuKR-Be^tqF#4on<f zEcMr8K#u|U=jS2J6>=E^GX84G zU%6D0XJesG)-E8>aa-qKT3OBI@-1lJRQF}0nXCZ&N4orHW^c{TOxu=4E~5#*Y(lNOxrW;O~C+fD%mM?)fTp^S+la-}(Bv zTjB9YqQUcNa1pUj=n!O-I7e2R~j2e!)|DFg^0t#>X-5B~VUYo`MijOdj~)H%4- zT5ama^wP@eFaBHy6fCW*F0ZUEudEgdeMb);Bv|a(BNNhCsxPK$%I4jBUg;OYm{WtLET{@4Uz^y(h$7#k0G#vi}+&XH%1bMR{N z>eR7kk0;Y0FzVGHP6__inE*2ZIbR=ubw`B@>EE} z1jN-U!ozR!__!mi!0(QtR6-|So)JQ^^2M!~>D?p`OV+$O0%66;kThj@DoC9tolZ>4 zKQEX+QcGwn)W%43X=sqpAgTCE_?D@%`3ez{=K7023WVKppvq(CmH7})gu2%0~n|k#}KQ3AJnE%_G zx-tFocVD@9`O12!yleNKaq2fYzqs=5g~>PHKKt&4$@i~b59V|Fpx7lK2xXu0CufOW{wQ@6<1dn7FDsH;1gGh#lqlFVW92u-?F{Ek-^anYMV8L2!acAlFL`G z508vCn@y?G9U!dE_oDi-dp=85GVNNU#{Is?dmGIrecwZ)rw+GB^>yE%;{UNmSgOvM;o zn=UUjb=B(+$SZ3ldYMS3Z+z=$PbR&(R=P4hcks}Jxby3^TD@Ll-itejBa<|S3poI| zIXhQ&YEll1-iAVd0c3d$KYac4lY94(Bnk5Bdlx1P14CQ4Z41B=x!k;WVRGA!@ebBV z7=wK|4!+69Z697WUH9~vceam@Z`rbqtS10jS8v|hI<^yJWM7b2i!o%3Hg5Xi=`;KG zALuI-f`$82KqIU`MZJ1sI#(DP9w=m@;1wCc3Q0)%2qE?jx`xfA@40`Wc7G26}XBWJa=$4(2Ny-|Mk95W{>7lEtS15l&3<#k;Tw!hhIPS4KG%yw>#v)L@7@JsNUvDs`X z0I+R4ShJ>S!SB$q!}eIpXO8CX%vUOvk&)3h`mn5~&t#2n9SyiJ4ufzSsOU{2$S%-K z$yw3zE4Z_nbiGzf>6m=?8?$q{Tt1af%d_nZ|w7eGSEy(q=Nop7X>`JxSbTP)j zCW{8>ESJl1y+_G+(NL#8a&RV7EU^cP7 zHwj4%u20X|P2d;}U^xqpB5ZRd>!qtV=K>i^`ng%7t>`(`S`{0HVbGzPH)rP>9_$z! z*H8yQEw7b(@_pi#Bs6&Q%`+I_@WBJbll{ZjJNSs;pm#4!Zr?H9S11rH%OR}5`V`E6 z)n5bGsGR&arML4r341j*K29uS0c(@M%}go*0JFE}2RCmE|G@;>-w#ipIpK#)U<`(@ z9!_4JLW%U)_&5OM6Ie&cv}{0HZ?1oAZ40Ju3ffBn|{k!O!{hiu44Sd%x}=&S=?01)MyMbs(e$>3E;>dD6* zVL5E~!)VM}yl@tTcrr@OTCaJbt`f(QLhyzS@E=^`ifVKv=mC#NAs z=4aq$3e+V47#b*S>g&lTAc^ZacAD_&Spy6*ZPl{|BwF)(6_$2EFPn#2ZKXH&wTQDPbL%m3^=s-?2(DhLxmn+ zWUNpKi_9l~Datx)vw2$`OkJx4-m7yLFJ;o{fq}sePik9$z^t_0;k(AR-Mc*}vRCw3 zL@tGnwjOO^- zA~4$G#}8p~&00{r{6rL|A|DOHWJPWFaF9 zrdskK7W)KUOvHD8=hEEQ-{Uvn$c~{e{le3d9@pw!N%IZ_C~f%Bsacclb{#=)vOV+a zjp}SVQ^52h=~qB<0AxeUGlvPlg}KP2vG?+ zgcVRu2q0s$KX>lV{Pi2thYnBl77Co6hyirZ&87@Oa;=mr*?g~RcM)&e-G#-udy6zI z4Hzrh0iV=6khAH!KYiyMXvW0RV*p?v&=J(V_Ms%cvxEi)l4ll9-<~fywPXAD5S;si zH{LmP8Var~0D+UmHhQF?|`1 z%RM@ewYa+8o)Tn4#$;8UKt6%VnR<6&@#^&( zyLRuPQ}6?Xg?$awHmyV^7tsHsLw%)U5rhnW5E4g$LReEbril(nrnOoC=i4-ywU09dx&sr4i3r+;lA z-^5o+z^hBt)iBbMzA9_yb?c%ri7$9@${gfv7Ztw@Y2OwUw!8WxAJ3SoBrT$ z9Z^}dLD6YOY_7{S=@myX1n{G4cmLg6*93&M=}W(OMC$lgdFbg@fCOPpP0!8VTWnY7 zv&0!$izck_@V-5T-W*X056~rP{+9G6+P@#uvfn;8IWRc%#NK@Y?h7!*joEfBA-(d1 zSL;cq0l;t zMQ6`XdKeBJp5Wpu7={r+8d`>-1Ay&Rnp#rV4Ne(O`qrv9&z{?{V{B;Crr@O>AIg3A zN2f`Ys78TP!fmDVh2fFWc2Tr%b9?!(PM>)GxuIMt0Alx-R#(a+cGhw;W-K9G1f2#q_WVbU@R> z&{lI8fO?A*D#{pz8Kv7Ni0I@HcxYV#f3e#X$FwaC?~>AJ7K`LkpyJv2PRskH6iSfeTK zF;`2ILS@4+G6tBX630RYPIq8?0(EY_e1$Pk12G2MvU~d^^DRoTtyP@hY6SonE?p@W z*Ph(FuUf5gSd8YpEYqqq+rnNh+mrAb72E9GNsul?*dvJ2wCr3@hFJNDvp>M0)k>wW zP^ecO`f3FLPwX7iH7#Jo$X$G;TB}wnS|U}c)u*QCUj50L@4tTLXBRG4To@b~edf6n zyPw>WebY`cTrXXm`RY3#2ncKV%fEaq z4t^AgDw;~ez&GF(AAfc2&c8czML<}?U;4#k^hhW|(Gb3X6!+g*Sgf~T)5s`ryaSR; zje+1rYSswC3YN?z+EAkDx^JJGbgH#u&mJe@AkEqkT`Wjz;4`7TR@MN5Sr%7TQ@H{S zaDuc3+C`O1005jl&#QqMBW!-)bSGOC+zA4}Wml@T(cvKgSXf#y za{Y#3V1WK4XbA2vuU?v(KKktOTCH~d>Xm`Pq5i?49-o;CpkffydTn~{+RWU6LlcEU zAvn;%36s*>OHR$qRbALVHjXIo6;d?o1X;6jIvm0yzbtA|W(R_@wBuvu!@?|MWvQ}H zqxt~TxuYSe@TA@dRM!Oa`9 zb8o+U{>`)Je*EU!J=xsOvF&;PYISdM>Fslqm#^J$TP*}0d7?Ld=$32 zS_I!m7JNsn?rtgN_2>%Ujwa~Hx^1D4ZCXPFNI`&nKZuIGqS={n83GA6-X5zJlC(BN z@l7vXnEsFNOmXXZW^DM&fBRXfeMzOzd4hm~ScK&%nwR|5)!Tpa=KDOt8XNxIUwRgC z921906$Bsl5!Qwut81mpH#>?FsUpm1o~~;buTIS`Ebe>iz~JBz5y*7eK6(4xWVW}! zAuQ;GpjP_xJ*H)!JwG|Vd(YU`QO#GZ2!i|3=`#Vs+E`rrE3cg3A%K$8D#`!c?vD@Ic!{c5`;_?!w|T&peY)>4BN+;NgkBzCx{5TV7hkZSQL? zolb8mycVY3;wW-0up*>ITGc=S-;Do`8pl_X<%;XE($HwWvh9G#0KC*Z2End7j zH9Ru9XYW1$D5$03O11X-nRoU*bzo?4h||!eB@n7cQ&>>F!-`uUQnwz%wyj()|5!{N zE1%0dww2H4ZL2eNEGw7K+rc!Kw=64{Z%=J@n$72J)5`Y>^K*I2vU+lP+qSZ~yklFr zT;8;-zTUiLS=oHvGOcVrPY{;4yUAxcvQLyw9sd(^{y;1g zuOgsZ=ZJOi#61$z*zJ)k+U} z-qTa9RLH9t|JCP@9vm4O^t=|yBMbJxYRSTGqquy3VR?1y)@_4>L*x@{^=3BBUr|iU zp1-&7?Dlcn;*X1ES^0dv(rDFI*4{mLzOT@qN~QoaLfFljTe@y^_T)ew0IuJdURf=s zQmJ~qE}hou^>iwgPNfbX_(X67v-$kunl;?lV>^`#SFV*y<|m(f9xx{RHlNSi!MWEf zKeAc>c?-0=i^aj-p0!f>^3`kmKCxfJEdU(=uHBgSJg-nFkmUyk2I=>@Ui&(7>B{xH zi%Yp&{u56fur15TCC0XAv+QmZ);7plFW)^@=@vXC5cg zbg3QPksAp+76IfFP_Ni)>!mwOs|OEFaNpW-Y{#*OM@ECqNoY`BTP2C0iG%vsSory{aBqHiWYjQ>ln%IAuT-nmYOPo*-CJ1PF*Y7}xJX*&+4GZqgG1S% zZy=UywdtfWQpf?o_k4tfF}U^Wx%1~!sr3G*4x}?_QFWC9XDs`On&V7OUC-unPww4^ z0Q6S9TCJWvKe_*@0|P@tz#fGGo*7~04#2U?H*elFEqmAQJ)5^~qt{<`9H(3yDD?K` zbH%mN2eWgo2c)qe1_>*K>-In{eg6Hah2_;PTet1nvnRMaF%Vd#HOn$PKLdbjwYIdf ziUAHCo@l3rJ;1LY%RE_9#Sk7|Kg184!|Lb}js>VQMN$VA>n0anPJz2e?AH=J_k2yw z6qQXsDS@bX9zac@5}F)ih51kEuv(_?VyCy9W6dn2A9)IW<$R)R^Q_b;q56X}Z5=-MF(jHG4ak&57^A7!Qw((kjw= z*=mAOG@WV-7K>%O?p7PEC-?4q;>o=rbNthvp6~6`4a2gmS_>{+pMHO8`r6HzMhmuV z-L`#fJlHnJg*V9@{yYD+CkPi406 z7=QZcv9>$RqMX@L9esdR&|02%@bJX&@CcdH0R7_o*ZK;DR4T>i{o5Ul+r!$(mTgZw zxo^wXZCqY%CYv=f`T3R7>u1hhxH{Enww~C#&tZ8z|`Rvl}_vQu?o)pV*YSTh|hnI0J(edd$L0b|7FzEV?04YcLGuRHuNbl730LV#wg z@y9t2D;U8r3xqgddmH`;-Xh#hC{MTz1X0}>$&!C@@#fcl#@nEdjgNf!?;ICRPhxUI zFvuWbWTv;|`|scS4{u#@TVBllc64mycYpafhYD%N0jU#Qr3PiuVaGJEp#iU8&O-5u z7B&`XA18RDTq*%THkUJ4#z%UfUDqXuk4T4D_%8JRM2c;QOesLr#~}p7pM_OtDOTF| zu<9ku&k9*ih~W_V@{$M~GTR+C$rpl~%_0Net~3BqnXB)=xZEwQ5zmJa@L} zxoHx zXSCZ1`k;1NMd!!KYCkMRe(A>sVM#mUa0N%5j?IGURyCxAqbelB6x{rPIHR}Z+vjh5 z?Ppg7gf;qypMOp|nA5`=Q(Yza!pN)Ncz5d0&R*|!AD(=2`xifVjC_jb*VFSVBnm6E zWHtkbX*W`}5lK4|MHL=|A0uD^4|)J}h6Rutc}|kur6B>IBBtI@`VmMmCw#+{_=45` zq-aiB)5m>ZBxvjM1BWCZ9et;Q<@YX_3mw7oQ|=*Zh1#RWR$P*f=(OTF^%^ow&#Uw`Ks?*1{FOL2?< z`E-l>UZH7U0dB3>Y>k){dkSbM@Y!=H#$?mSu(}?AN6J1n?BG)wf)1I2m@6(ih9hhn7TB1P_d7uX7TG|eAVs`HTKQxq5~&Ybuip=j5;rLH4x*BCxnZ=Q#b zu%y;1so`5{-Ik8zm?4@`(ON5!>2uo!=RFQ!4 zatL5VyoBNXpC?w@k-=)1jF`qRGAjdo6h>B$Ujoy2fE$ap( z(@8B#r4kiYTZ+qM4427bF~AZ0SFj!rWV|7pNlUXiSYTx2m7$8dQ7g1VlJqQ z3~(1c4IB#Hbdsvr-2D#DVlx;xj0Q4{CfyRm@n}MCP)DdRoig=y%=RUL}t z3zzJQg`8EsMSx)L6LVJOS^P3Uh!l7Py24q4uMmeengl@^ls551pRZGcFVf6?``#vn;Q~c@A zrtkfC|NeVFxHKJ~MIug<08a(zhW8V3IE$V-m2RmkT|>Y5nTf$%CZq!R@mlXQrLyp)JrGsBwH_wILZQl$pbN?Sz4`!tNPY^ zQ(t}Sa#!E$*v`#g{`^T0NFvb-6Y_Xt>dycA>O1j2G@UTM^vlm586OQ7UL&I{RJcT} zO^bsRq~I>*k{HVfCbk8hN}5CzIK(oiH3+2+SQ@E@B*;#+uVU_mFd7R92s6Z=r4Z&+ zHafY9Oh(v6N`6u_7Zd%dc8f= z$o)@$=lGHFQB|D)JtEP2SdwIK@frC6>fv-om5+wwvzW{ytaem!pX)Py5*<0FpN>@_ zgHDbfP#hw)g+MVlh)!{$xtq{^1@ZJsJEXriTXi6H$w6#yJ+RCajZ$fk6~}E!Jyvwy zoS4TT?Y7Ce-X;AR>ApMu`hz@DW~*2%#$~`e?DYh({SzMn!eW7s^m5L5vP7am^tuF> zc~7`iMyv$MjlIEEUA(>cm2bb{bzeR8_ddD*AAahP6fbo3xH7-|m2ba6dS|H~Nkji{ zpWXl8Jo5=d*FscR6yga&JXImuXH-l?7sr~zJ~+ae1uV7#A?sCoE~%ovI&>9Q%Z@U5 z6%IXOT9Ble1;y)EpmLT+=0jlVT4*;J@Z};ZB^@bBUm?mi)fMU_q9OUEkTYHrmiL0# z5}yX;Qsg{gFFg{3MdOh;%R6)`7R3ulv=tfu#f_`B&?nBeEf3>=`{Q#h;;QQM@3}qO z+IQeim~TFEdSKh|AN|)Sf9|QB(oY#1D*VIe_kZ;t|LWg9u*1+bd1}6(s(2JLh}nH8 zSJto`|Elx3(h$_@u*hvWwo-pYig!t-EO%D%`|;>OKOURc zC7sM3cdh^2DeMetdJHmG-^0=f-JD8}LA-6Z)?mdjcrF2I6=9QBN~k>*t@^^=rrW{L`O5c4F7a zr=Hxdw;GX%l|i7PNXO#TSS)0mB5FwiTS1(hSR95lF_l=)cy=hikCf}N6g-Y4rj=UC zjBu{IlA}f|ahWN)V$ozYO)MmZ$P;Ky3EvmTV;JJ0b7(~`UUg?1&mypF3lOsn^g5YT zdsZ<-LVY5VB}q6kq{g_+5OW+W97dyr`nJ$Zchw)p7d;oI3FM{ETfD1jRwXo4GR9>;0H8tZ9}!>oaV zC6Sja3TUyz9txH&`PZj=0OR0GcCqb28s$z;5vQ>9;?_@jUj!Q9JZHuWaokp1&PpZEZjT0ZCN(iCqkIGNXG)IF@xf}@bp)th^^6KpJ z`mg`#_hWvMzMk~&|H{dO+ehG|c%V>jB|b|Cs#cOXg2airZM6D^aTqR^+G?;`*HdX# z2qb20EC32AF^W*EazBh^7AhHp0ksq>UlMKnz64mBOjRey&6I#Fq~PGN65Odk77~cj z5MhyH8)K$cV34%)(H<#p70HIsOowI5yAxV6>BR>`_Jr)^PBwaf!+W6uYLN! zwqe`0FvgZ;ic`+-rqR^{YSd9eJWLRh%_J9ZE{2_mr&sjIkAVRZP(wOe03 zb7`?`iwma{#%K1A|H6UYyEYa4R2iV31Y-b}W&dEsNQ63!9iso+POm};q0W=ebN?-v zeoJRv)M~~5vhrJ`Xe_`hN&Y9xfnhb)pjQhh?Ce7EELU_XqN-{V zb-x=q0#S_jKvB0NVsQuxFKj?cs!OUhV=Qsu<0uXb$*Kb7iK+2~buqgFV+lE^J&JCF zR_w8wQ`|6@>8?-}Ih@5|9}WSvTCH+vz2&;4(%OkVTmRMH{nWqsrQ<)pZ~MV*oA!?m ze0Kl%=MV1u{lE3e|KsmI|Ak{uWL&3QT3@(#x3s=CfA{uUadrOg?c(ano!hromzQqe znq661ygfU!ym#iwpN=rf)1R+?y4rGdJ7Q`wMe3)60wZ=Vqo?mKJZ{ znq6I9x_f7?xVm!p&fNN1asKY@()!xH`8(xuX<=dBw9Lh&`;KF;EH70nPH}amUaPGa zR~z;E`g+lAHcO?omg|;F>#bIcLvz@}mT6)STbAizOxh5rI5MlNBz~dh3xu>L%;F|X z@OfD*!`NY_{8xjFa4v%%vpE^e9HH`#afI6f>JdFwro^)js;&Ymmlo&YQYCYmlx{1{ zZ@^5&qAH=p=|0^gz+$E_CqA|!I9jZ}R3S&s;e~`PM~dt)X{YyxkFfBAtwHP=ODd1V zB-;c?8c}tro`EYqi?5S}jkuSbGf^V}FGK{^B-6L_HjO z(liYa(vXG_(#dm8Lt6Wx>w4$8rqlB^>VY&3`76;hjsA$>^Dwm;Gz9DRF!AtK)~5%s zQrH3^m>((l5nB2b<2qD+G$cyTYWj)SC8g>Z=3#!AYRTe35i?3F6C!F66p9`Sm0YC= zOC?{1-wdgQLaA|2%3g&y>BA8g7C{#KWwj5Pw~83ak$|?41iR6^55otUW$byTRVKK@ zb=`8gh-naYQ0t~7FTQ4YH@X?TCEgUmn#)#b$Q9L?Uj{f+p<=c zmmJ$#U0JeiYjt(maqQKV<%(?=S5_*HQ!K7l9H+RtQgNKM;%c>0Szjww9A|y4NS@Pk zYSro*wS4=%D=Us|6<3!nfBi-OQ*6sxU0HT)dv&Efzgn%3PgyIjlC{&g4!S} zc(wB`O+(PeSp>cT;t4WPkY5jC2jlYWB?GCb+))E2mc_}p1xFNCuP=s(ifw*6kyuft zZIQr|?g0()+8Hl^g52&;OP@%^^{UG$MPIu}dtuB}1t4|MzREQg$?kzd4#sNrIZj%< z%2=59>iN8tci%va!^0Y=n^G*yK5xYMSOaHXu~3R&-sj)+&Z!)a$iGBH3s( zlF5|ox~X)!<+ak8jEB9RY!+jj&E}AXvbj9cw0v)`rt7)hUfs}pd;4_5AkFgf`CcQD z$mM%=!^q`>WsH1puWsnsT#igNU8ASDe4ael4Lz672k#>5A!{a|Le`nj_v(h8>+RKa zJ>T1lG%cIUgNAx~vKZq`Hrv8px~Io&x#@Je*=#10sYaubFcP&|)i8`&t*YyKrQ#q> zt5lr!-k|nRu*c$L@OOo#vCLt|oe$Xe`>2j7*As~2wj`fx$-7L_N}MHQa6BwgA-Rk; z4sF@CkDEjk#vw2ETOct7fkRbPB|ztXB1q|sH=uDd~-1M$|KcwBEoBO;5GM zsuyD-O%$byK1K*j96DmMEt2N)BE2QBPHi9t!2}0*3i}8xSU#8u)Ea{S#Nx05Sy0o+ zOEmXHkWoNL1uyw9sXd3htD_i-7)lsAyMk0mp~pcyhd0JbN0`(Dts-AATgZo__!?;JGjKR*hjMz8}t)qIpusW`f>SF07>Fsikxkx0}V^<*klZ`4!iwA*qsnVwdwmFdZP z7-w^N0O;-Q({;VCuV5q-h5ms=D%n3Un98JwHVvnHGJ~6jGuiB>khdo6C=k zZpr0)hetQ(^1UOQw*=GS(aq%5Y%afPcr0&K28zw%Z8`in&W(5OUNC46jh4$hCc->xh>o3&c_!y z2UJK0x1C&c=7*|FpsEKrU#W__*jEnAreRsXAHF*Q=6mNrZ1+6hbI6pW&c?($(i#I$ zBx*4IirCIZwwN@l;LEzw90SDqxF9UrO7l=U#QyboppODug|7m|gI7|770E_P8`a<# zs2te1dZf-Qm4YlBvuBIK2qxwAkh-}JoeaeV%p+MIuToLOVPYacXrm*Ds1OJbM2Tdz zLZXHv;Z=ySOM4tpmBX?jamKX2Inxg{D+0B-su0ddl2}hwCg2Cxi*XmRt?o7TUe#EteU2|1fa&7)Ez$%U^^x@+#{9s#-WFcrsJ$mDZvgJtW zOA=GJXl*(iQmOJ?G02-{B6Ukm%wa2}_QX^B1ANLt@XPdKI8X22WQ%mvv4FO#q2N BK}7%n literal 0 HcmV?d00001 diff --git a/web/resource/components/ueditor/themes/default/images/pagebreak.gif b/web/resource/components/ueditor/themes/default/images/pagebreak.gif new file mode 100644 index 0000000000000000000000000000000000000000..8d1cffd64af72709b1180b3b0a51bbfe30bcb8c6 GIT binary patch literal 54 zcmZ?wbhEHb8U}fi7AzZCsS=07??9MLn2Bde0{8v^Kf6`()~Xj@TAnpKdC8`Lf!&sHg;q@=(~U%$M( zT(8_%FTW^V-_X+15@d#vkuFe$ZgFK^Nn(X=Ua>OF1ees}t-3#_`hBq$Z(46Le)Ln;eW^@CE2 z^Gl18f$@>14ATq@JNy=b6armi>cVAJd5X6R;MWawh(V&G(G=xXffXz1o@ zX=ZL{;B08&Z0-!x>zP+vl9-pA3bQv8XfIT+GhV$`&PAz-CHX}m`T04p6cCV+Uy@&( zkzb(T9Bihb;hUJ8nFkWk1Vs?Uzb>gonPsUdZbkXI3g8g7%EaOV0~10%hv-cqC)D(T zj?o7t52WM*69T3|5EGvGfgE`DNzDW1nId53*cQ_-&cMK^?CIhdQgN$ga=rIq1A(^5 zYKwg&`wo`WvF`u>{iFU|`!+wz>b#B?t8F4hxRm$~lz-tTH#6E8xZnKlv%`YRwvA{oKseqmK8(Gfx|> z#)dT+Zy!CGH{+89Q&m{rC!PyyIjq?Y9m+ziHPqr6qxfF`+2Qt=-KQ=fE8_j%1#Y2} z>NffN)P;AQIhrE)QQzeqbFS^A8(M1XGuQqTO<=fcH+M~2lzlL$Ao6teb6Mw<&;$U? C61Fb@ literal 0 HcmV?d00001 diff --git a/web/resource/images/msg-tab-z25df2d.png b/web/resource/images/msg-tab-z25df2d.png new file mode 100644 index 0000000000000000000000000000000000000000..6a18531bbc8145417210ef77909ea7adbfe1cb34 GIT binary patch literal 1914 zcmV-=2Zi{FP) zO{gAM8OMJ&hH{Z2U4%<*FEPe6__->jQK1A0)XpJFp;g3>c)27ZQc4h!a2Jh>^UTf6dFQfw2Ewa~uQ@}&Oo3-L?;4$dghPBN+VY9vnyaK!g{Fl&%TfKlSuu2v5 zS_SI_s_H$2Z!?BL*vt=z$p7jylWo`my8@hzVM(CD+BUO-oe`1CZOblfat(HJC~N_! zs&^AMGX*;3u)I;j3t?sMzem?hAdY|1_R#w)EYE4yd z%movXwZZPIOS>mn5t)+u+uh1r7hzwi>L&?S7(z1gSM~BS5uOL`w%7T%aQ013rK%oP z)h{HLc^vo`;WGPpT)5DNs(K9gF0ihuuZzel^>Pt;5qNj62rawxJn$~y4&VjLh4oe( z;a7kMYoG5i=ot~&QPm^BvsU&c5&3sALRCEle7$9*r+{Zw^&G*Sea2p|*}R78$MP08 zf6NTgPl0o=cr1^BQNb$Rp8YT@D=TaDwN^McoBJxgzlH9r^nOa}Z-v}f;atOgmEOM{ z+*je;qlI(xxUa&wW0?CYoO`|WzTv(~@B6zi%PuwCm*v8GtC#yKoI6u`zf(BZa9^eO zY4=q)x72+V&Mmkvo7YhNSl(iy`-+d{F)+yPD=RB2>-K1LGA&MRS-#?#!QQ4#)*tLA zz{7)+Y4H|WV&fNttK)F@6~Rsbzb4!|0VZ5iRP{mNcXb#{i|{32J)Sw`si8Y38!7?$3-wpZiVOzs zj46wOI{>PBCva&A@RHSmFmfRY{Ig9T0KS}vWXH;?eQ~L`QJX$tht_G}H-y9Oy1hSb zWlvb$7wdpH)4Kuum2hwLDG~WrON6NElZ2DTe}Mby9m?8%a;fwfO3`+tHdZZT3hi&$&z%PMsi^v=P}VlgbCCNgz3+Bk*5jpm+h zYoF=>j(I$sDri&b{X!GPf$Y7v>1vw2k8p3>u+Og3RcFv{(`N;PBka;Xig2#8PIg~e zSy}s32Qc>)_xsxI6Vhke)?EAhMqvi78nD{YQ`5n~u^OHGO4ZG|udJ-Bte^v!`-=O0 z?e+=jGi__GeSD$Mz!d~mJ9=t57&um=b6=^tIro*7m6a7V$j{iotdoR)e!0)4CxD~C zS4HHxwuhE)Sf!KELMI4)j8i%dJXim{ya{{)_=v5sdJTVUrmB8}@RvmYAUvbtd0%QJy z!2R}$^_Hq$u@zk={29&H^!{4m+#vV0X28_1`8M}eecmp;ug3Rn0PCgq+mqZ^;aqlK z8MxBGTjRd$IeeqtSLuC!_fAp(u=XYQK2d`E+R23AxbpQYW07*qoM6N<$f*RB5 A9smFU literal 0 HcmV?d00001 diff --git a/web/resource/images/music-icon.png b/web/resource/images/music-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..135a2d472e58d85d041837adce257099e382d3f0 GIT binary patch literal 1386 zcmeAS@N?(olHy`uVBq!ia0vp^8X(NU1|)m_?Z^dEk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+nAI{vB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxOgGuk*h0bFQqR!T z(!$6@N5ROz&`jUJQs2--*TB%qz|zXVPyq^*fVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;NpiyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr7I$DAddqG{Q6U zQu51-HNkp(eXTt6ic1pnl2bihY?Xkf=w)W6SQ#6*S~?jz8XKCLnHd_oT3VQyI$O9o zIvF{e8Cg0SyTbIkS_bdgF4=1r+cnNz;&Z_1!iwHwO1>Sj*NprVE@iLX zc)`hFYscILoe%hT%;Q!!(CNN;=G~jT1pS&b2Ad}wp0l%D&-420Qftx265dB`j!mt! z;$r++bFcL7CY@>(KLf!T93}#n6L{Y+Mo(hYsW_P=Y{)q6fYHe&*Xhj@zouViy8P$k z8YPb-zE=Bwvy?wz6WLLg_=x5C)Zj=)NrT5fo{8Hun6aL$;IG>epP;+Nm!o9!lTN2! zNqLUuE2g`c`)RmU82-HS^4LN*vGfXECqW4pv38{k*<$-Y=f!OnlM;{kr{2APD$hH0 zzxJDRxx63Pxoe8{^En0u?OWtGN$9Q6?R$@A99`~dF6^|X*?XT>?78B?70rLAFMARZ ztvYdjLf@k$cSH`#Xcp-TG~W8AP-gM2$@qg;N}WiH!^Y*F*2_B1M9Zf$zC zH}&GX?Iom@Tpx`1M--JkYCHQ~SxTw--SIYcWa?u@$>h9W` z!eP6Y=K5dCQ)O!3(>(Fd?fl4V8S@{^XJBSn-PT@VU8BqgD*ZfN{an^LB{Ts5$87Z6 literal 0 HcmV?d00001 diff --git a/web/resource/images/noavatar_middle.gif b/web/resource/images/noavatar_middle.gif new file mode 100644 index 0000000000000000000000000000000000000000..7016d1155c6ada15a6e6ea67d971f428ea571920 GIT binary patch literal 3972 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 literal 0 HcmV?d00001 diff --git a/web/resource/images/nopic-107.png b/web/resource/images/nopic-107.png new file mode 100644 index 0000000000000000000000000000000000000000..526f91e209d49740c4d22b082e9e25c860bfd035 GIT binary patch literal 1955 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 literal 0 HcmV?d00001 diff --git a/web/resource/images/nopic-template.png b/web/resource/images/nopic-template.png new file mode 100644 index 0000000000000000000000000000000000000000..b913aa263031794f6b842268d9188af8da6ba279 GIT binary patch literal 142 zcmeAS@N?(olHy`uVBq!ia0vp^HXzKx3?xrnI^qbV_yc@GT)+SLb>_^OFJHf(J$v@y z!$)?)Qs046R-P`7Ar_~TC0LnR=dfOE;OyF>U?p%&U)REC$y5V|)Pp^V+Zlv6-CcZX p@g-*`DbwH9i@j$X^fWOtF@)P|vPSfZO#zz1;OXk;vd$@?2>=H_Fya6J literal 0 HcmV?d00001 diff --git a/web/resource/images/nopic-user.png b/web/resource/images/nopic-user.png new file mode 100644 index 0000000000000000000000000000000000000000..7e503b749ed8ca0b3de7647ee00c2629f08a836e GIT binary patch literal 15456 zcmeI3YitzP6~`wJ1!58v+C-s9nDIg+taNr}c6aQZ(Rvf?HQ1(W&|=3XD8TH@UGKo| z&ayLWuYp*oqz%;MA!H~u2nfQoA9&>fi3v(Rpg>asd5{MMMGc{9NJC-*q!ppy-r2XW z?JG-7zf^a$yEEsW`#*Q?@1A>hzRddhjdSiVnNmVg)cy5!z5qOXtnc_c;qRgCjSs`q zz45w*21QNynf1Mc>fJV(qQuKuQ>)qP|D~kpQM;__L10fsAo zc!?7wj;FJS&07MmJP9=<1$?u!!$GUc7BPQ0JJU6nYMg;rC1RF~gK&3aIya;oR+- zrb=$Wxp+}l8NuleGL^hbU}TQx8NR|9lIWgpLtGuA*1}X|RY@m4w4b~+&Qq;$qiwXyG zh6Er8K_}y^-~r>{T|q|V6*t3)E|*gjRHf39Sui-45yA``s!lUtHgy(d8O*hGNcPH;*hqa;oTdmz5Nv8Y5VgnDB zw|=wIVmB&Xh?f?-QE5Th9Mep%BRd+>T%@x8L8UZ|1@K`Hcq;_KDR@}48CA^JQXtam z(_o!9ta?=e=atr=juC|mM-vt~vcgO%6g`%u_jsliKJ>xoO*a3)Ic)pqtK^S)QJB$> z85M~|20?(}O@a&02k{bI2oStUaN+qNUV;k&f;R~+JRihMa3MhOCc%a0gLnxp1PI4T@Fu~9=Yx0&E(8ePB)IT=5HG=n0KuCC7oHE|CAbhE zc$475^Fh1>7Xk!t5?pvbh?n3(fZ$Dn3(p7f5?lxnyh(83`5<0`3ju;R2`)Sz#7l4? zK=39OS4rU&P7s6dZFayHG!GuQ@F0A-lUC{ieu`QNUkqKdmZEM9!t+-YmE zBkz82-}ZS|E_OZlxhd5Se6sZVZMP-+1Pu2`*|);E2P0(!sv}^b6m2-ws@1ckP(!ZTW7o$9{avTXW`} zxxVr2?ZfSBHV2mNYq@7a+3NnQNA??~{o|f!=%4(_zizpodvoWrd~@@yqy4|0n0)f) zrd2ch?7usCt81{mE_#0PftH)AE?yIj+n+vA)-&Usi<3ThVs7~}a{TREn^yNu{OJk4 z?C!F=Dem}V<0n;DuM@U*>1OYq4Se;VUfIx4o_yo8AKrXzM{-J=QC$ZeGS^e&D~$z7~j3?;Je@N>`N_L{GRw){oWT({eIEj$Gh4OESc68KHcvR z-A8@CZQ!@3UyfY!oceUxQ}0})zS;dz_pWvP;c4f(dZRzwm^XNJo4RG|&A+UR^@g50 zbak(`@BHD<27bO{&sVFx&f^rSCBx i8<+bGPP=}BdNFV`{P^4>uUqc`*Vi`s_E#_c)qendI~g|s literal 0 HcmV?d00001 diff --git a/web/resource/images/nopic.jpg b/web/resource/images/nopic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..260fefcf91f6cfb5d3c2d3b7f1584bf4cb8cf70f GIT binary patch literal 10262 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 U1_LPm8=U@E_5WD}n8^eG2On(oY5)KL literal 0 HcmV?d00001 diff --git a/web/resource/images/nopic1.jpg b/web/resource/images/nopic1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6d3c5458cb67c3ea421f64333887fb90d291992d GIT binary patch literal 11634 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 literal 0 HcmV?d00001 diff --git a/web/resource/images/radio-icon.png b/web/resource/images/radio-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5f190544dd2ce9c320368c2a1b015bc9942e2277 GIT binary patch literal 637 zcmeAS@N?(olHy`uVBq!ia0vp^8X(NU3?z3ec*Fy#(g2?jS0Fu;?toi=YCq6owUQve zV20`Jzl7hIYka%BIqF_zyP@pkHOm)T?|B!_o13b2^R(y8o`&Qj&I=369x*U5PV{tf z46!&pHS~H>ivdr`(sI5X$G*P#U!P>KbB-u;;)mw;k0+wuMn&DY|8!~S4bPjcp|3U` z4NXx!p|v^5%%_l3#pc{p0j>T@CXaQ?3afdq@Y-f(IlP~1aIo>)n>f4e4B}s&2q;>d zyIRa6AnUP@qpESqa>1K(WNyVzI&}Skyd1|r!L!@~`%5oc_G z+S&C7xHbQ3MnA~A?49{3{l?B6%?g4izRGS&)W2w9^g8PR=ZU{;PaU{ACmS>`JgNBB zS^Yx<*E^$~3(|Gi=efL?655eDwmqNsRloading

'),c=$("#order-remark-container")),$.get("./index.php?c=order&a=order&do=get_info",{id:a},function(d){if(console.log(d),d.errno)return void util.tips(d.message);var e=d,f=' ';c.html(f),c.find(".js-order-remark-post").off("click"),c.find(".js-order-remark-post").click(function(){var d=c.find('[name="admin_remark"]').val();$.post("./index.php?c=order&a=order&do=admin_remark",{id:a,admin_remark:d},function(a){console.log("admin-remark: ",a),a.errno?util.tips(a.message):(c.modal("hide"),$.isFunction(b)&&b(a),util.tips("订单修改备注操作成功!"))},"json")}),c.modal("show")},"json"),c},c.selectExpress=function(a,b){var c=$("#order-express-select-container");return 0==c.length&&($(document.body).append(''),c=$("#order-express-select-container")),$.get("./index.php?c=order&a=order&do=select_express",{id:a.id},function(d){if(d.errno)return void util.tips(d.message);var e=d,f=' ',c.html(f),c.find(".js-express-row").off("click"),c.find(".js-express-row").click(function(){$(this).find(":radio").get(0).checked=!0}),c.find(".js-express-submit").off("click"),c.find(".js-express-submit").on("click",function(){if(0==c.find("input[type='radio']:checked").length)return void util.tips("请选择快递公司.");var a=c.find("input[type='radio']:checked").parent().parent(),d={express:a.find(".js-express-cell").html(),post_fee:a.find(".js-fee-cell").html()};$.isFunction(b)&&b(d),c.modal("hide")}),c.modal("show")},"json"),c},c.editPayment=function(a,b){var d=$("#order-edit-payment-container");return 0==d.length&&($(document.body).append(''),d=$("#order-edit-payment-container")),d.empty(),$.get("./index.php?c=order&a=order&do=get_info",{id:a,items:!0},function(a){if(a.errno)return void util.tips(a.message);var e=a,f=' ';d.html(f),f=' 商品 单价/数量 小计(元) 涨价或减价 运费',$.each(e.items,function(a,b){f+='',f+=' ',f+='

'+b.name+"

"+b.specification+"

",f+='

¥'+b.price+"

x"+b.num+"

",f+=' ¥'+b.amount+"",1>a&&(f+='

 

',f+=' 免运费 | 选择快递'),f+=""}),$(".js-order-items").append(f);var g=0,h=function(){var a=$("input.js-order-post-fee").val(),b=$("input.js-order-adjust-fee").val(),c=parseFloat(e.total_fee),f=parseFloat(a),h=parseFloat(b);return g=f+h+c,0>f?($("input.js-order-post-fee").val("0.00"),valid=!1,void util.tips("快递费不能小于 0")):0>g?(valid=!1,g=0,h=0-c-f,$("input.js-order-adjust-fee").val(h),void util.tips("付款金额不能小于 0")):(d.find("span.js-order-post-fee").html(parseFloat(a).toFixed(2)),d.find("span.js-order-adjust-fee").html(parseFloat(h).toFixed(2)),void d.find("span.js-order-payment").html(parseFloat(g).toFixed(2)))};d.find(".js-post-fee-free").off("click"),d.find(".js-post-fee-free").on("click",function(){$("input.js-order-post-fee").val("0.00"),h()}),d.find(".js-order-fee").off("change"),d.find(".js-order-fee").change(function(){h()}),d.find(".js-order-select-express").off("change"),d.find(".js-order-select-express").click(function(){$modalobj=d,c.selectExpress(e,function(a){$modalobj.find("input.js-order-post-fee").val(parseFloat(a.post_fee).toFixed(2)),$modalobj.find('input[name="express"]').val(a.express),h()})}),d.find(".js-order-edit-payment-submit").off("click"),d.find(".js-order-edit-payment-submit").click(function(){!isNaN(g)&&g>=0?(postdata=util.serialize(d.find("input")),postdata.id=e.id,$.post("./index.php?c=order&a=order&do=edit_payment",postdata,function(a){a.errno?util.tips(a.message):($.isFunction(b)&&b(a),d.modal("hide"),util.tips("订单价格修改成功."))},"json")):util.tips("订单价格无法保存,请检查金额.")}),d.modal("show")},"json"),d},c.adminClose=function(a,b){var c=$("#order-cancel-container");if(0==c.length){var d='';$(document.body).append(d),c=$("#order-cancel-container")}c.find('input[name="cancel-reason"]').val(""),$.get("./index.php?c=order&a=order&do=get_info",{id:a},function(d){d.errno?util.tips(d.message):(c.find(".js-cancel-reason li a").off("click"),c.find(".js-cancel-reason li a").click(function(){var a=$(this).html();c.find('input[name="cancel-reason"]').val(a)}),c.find(".js-order-submit").off("click"),c.find(".js-order-submit").click(function(){var d=c.find('input[name="cancel-reason"]').val();null!=d&&d.length>0&&$.post("./index.php?c=order&a=order&do=admin_close",{id:a,cancel_reason:d},function(a){console.log(a),c.modal("hide"),a.errno?util.tips(a.message):($.isFunction(b)&&b(a),util.tips("取消订单成功."))},"json")}),c.find(".js-order-cancel").off("click"),c.find(".js-order-cancel").click(function(){c.modal("hide")}),c.modal("show"))},"json")},c.send=function(b,c){var d=$("#order-send-container");0==d.length&&($(document.body).append(''),d=$("#order-send-container")),$.get("./index.php?c=order&a=order&do=get_info",{id:b,items:!0,logistics:!0,exclude_refund:!0,present:!0},function(e){if(e.errno)util.tips(e.message);else{console.log(e);var f=e;for(var g in f.items)f.items[g].url=util.tomedia(f.items[g].thumb);var h="";h+='";var i='
';d.html(a.template(i)({order:f})),d.find(".js-order-send-cancel").off("click"),d.find(".js-order-send-cancel").click(function(){d.modal("hide")}),d.find(".js-order-send-submit").off("click"),d.find(".js-order-send-submit").click(function(){var a=d.find('input[name="express_no"]').val(),e=d.find('select[name="express"]').val();null!=a&&a.length>0?$.post("./index.php?c=order&a=order&do=send",{id:b,express_no:a,express:e},function(a){console.log(a),d.modal("hide"),a.errno?util.tips(a.message):($.isFunction(c)&&c(a),util.tips("订单发货成功."))},"json"):util.tips("快递单号不能为空")}),d.modal("show")}},"json")},c.editAddress=function(c,d){var e=$("#js-order-address-container");return 0==e.length&&($(document.body).append(''),e=$("#js-order-address-container")),$.get("./index.php?c=order&a=order&do=get_info",{id:c},function(c){if(console.log("order.editAddress: ",c),c.errno)util.tips(c.message);else{var f=c,g=' ';e.html(a.template(g)(f)),e.find(".js-order-address").each(function(){var a={};a.province=$(this).find(".js-province")[0],a.city=$(this).find(".js-city")[0],a.district=$(this).find(".js-district")[0];var c={};c.province=$(a.province).attr("data-value"),c.city=$(a.city).attr("data-value"),c.district=$(a.district).attr("data-value"),b.render(a,c,{withTitle:!0})}),e.find(".js-submit").click(function(){if(postdata=util.serialize(e.find("input, select, textarea")),""==postdata.realname)return util.tips("请填写收货人"),!1;if(""==postdata.mobile)return util.tips("请填写手机号"),!1;var a=/^1\d{10}$/;return a.test(postdata.mobile)?""==postdata.province?(util.tips("请选择省"),!1):""==postdata.city?(util.tips("请选择市"),!1):""==postdata.address?(util.tips("请填写详细地址"),!1):(postdata.id=f.id,void $.post("./index.php?c=order&a=order&do=edit_address",postdata,function(a){a.errno?util.tips(a.message):(e.modal("hide"),$.isFunction(d)&&d(a),util.tips("订单地址修改成功."))},"json")):(util.tips("填写手机号有误"),!1)}),e.modal("show")}},"json"),e},c.rank=function(a){$this=$(a);var b=$this.data("order-id"),c=$this.data("rank");$this.raty({cancel:!0,cancelOn:"cancel-custom-on.png",cancelOff:"cancel-custom-off.png",cancelPlace:"left",cancelHint:"重置",hints:["1","2","3","4","5"],number:6,path:"./resource/images/",starOff:"star-off-big.png",starOn:"star-on-big.png",starType:"img",size:16,score:c,targetKeep:!0,click:function(a){b&&$.post("./index.php?c=order&a=order&do=rank",{id:b,rank:a?a:0},function(a){a.errno||util.tips("修改成功!")},"json")}})},c}); \ No newline at end of file diff --git a/web/resource/js/lib/raty.min.js b/web/resource/js/lib/raty.min.js new file mode 100644 index 0000000..a5c9787 --- /dev/null +++ b/web/resource/js/lib/raty.min.js @@ -0,0 +1 @@ +!function(a){var b={init:function(c){return this.each(function(){var d=this,e=a(d).empty();d.opt=a.extend(!0,{},a.fn.raty.defaults,c),e.data("settings",d.opt),d.opt.number=b.between(d.opt.number,0,5),"/"!=d.opt.path.substring(d.opt.path.length-1,d.opt.path.length)&&(d.opt.path+="/"),"function"==typeof d.opt.score&&(d.opt.score=d.opt.score.call(d)),d.opt.score&&(d.opt.score=b.between(d.opt.score,0,d.opt.number));for(var f=1;f<=d.opt.number;f++)a("",{src:d.opt.path+(!d.opt.score||d.opt.score",{type:"hidden",name:d.opt.scoreName}).appendTo(d),d.opt.score&&d.opt.score>0&&(d.score.val(d.opt.score),b.roundStar.call(d,d.opt.score)),d.opt.iconRange&&b.fill.call(d,d.opt.score),b.setTarget.call(d,d.opt.score,d.opt.targetKeep);var g=d.opt.space?4:0,h=d.opt.width||d.opt.number*d.opt.size+d.opt.number*g;d.opt.cancel&&(d.cancel=a("",{src:d.opt.path+d.opt.cancelOff,alt:"x",title:d.opt.cancelHint,"class":"raty-cancel"}),"left"==d.opt.cancelPlace?e.prepend(" ").prepend(d.cancel):e.append(" ").append(d.cancel),h+=d.opt.size+g),d.opt.readOnly?(b.fixHint.call(d),d.cancel&&d.cancel.hide()):(e.css("cursor","pointer"),b.bindAction.call(d)),e.css("width",h)})},between:function(a,b,c){return Math.min(Math.max(parseFloat(a),b),c)},bindAction:function(){var c=this,d=a(c);d.mouseleave(function(){var a=c.score.val()||void 0;b.initialize.call(c,a),b.setTarget.call(c,a,c.opt.targetKeep),c.opt.mouseover&&c.opt.mouseover.call(c,a)});var e=c.opt.half?"mousemove":"mouseover";c.opt.cancel&&c.cancel.mouseenter(function(){a(this).attr("src",c.opt.path+c.opt.cancelOn),c.stars.attr("src",c.opt.path+c.opt.starOff),b.setTarget.call(c,null,!0),c.opt.mouseover&&c.opt.mouseover.call(c,null)}).mouseleave(function(){a(this).attr("src",c.opt.path+c.opt.cancelOff),c.opt.mouseover&&c.opt.mouseover.call(c,c.score.val()||null)}).click(function(a){c.score.removeAttr("value"),c.opt.click&&c.opt.click.call(c,null,a)}),c.stars.bind(e,function(e){var f=parseInt(this.alt,10);if(c.opt.half){var g=parseFloat((e.pageX-a(this).offset().left)/c.opt.size),h=g>.5?1:.5;f=parseFloat(this.alt)-1+h,b.fill.call(c,f),c.opt.precision&&(f=f-h+g),b.showHalf.call(c,f)}else b.fill.call(c,f);d.data("score",f),b.setTarget.call(c,f,!0),c.opt.mouseover&&c.opt.mouseover.call(c,f,e)}).click(function(a){c.score.val(c.opt.half||c.opt.precision?d.data("score"):this.alt),c.opt.click&&c.opt.click.call(c,c.score.val(),a)})},cancel:function(c){return a(this).each(function(){var d=this,e=a(d);return e.data("readonly")===!0?this:(c?b.click.call(d,null):b.score.call(d,null),void d.score.removeAttr("value"))})},click:function(c){return a(this).each(function(){return a(this).data("readonly")===!0?this:(b.initialize.call(this,c),this.opt.click?this.opt.click.call(this,c):b.error.call(this,'you must add the "click: function(score, evt) { }" callback.'),void b.setTarget.call(this,c,!0))})},error:function(b){a(this).html(b),a.error(b)},fill:function(a){for(var b,c,d,e=this,f=e.stars.length,g=0,h=1;f>=h;h++)b=e.stars.eq(h-1),e.opt.iconRange&&e.opt.iconRange.length>g?(c=e.opt.iconRange[g],d=e.opt.single?h==a?c.on||e.opt.starOn:c.off||e.opt.starOff:a>=h?c.on||e.opt.starOn:c.off||e.opt.starOff,h<=c.range&&b.attr("src",e.opt.path+d),h==c.range&&g++):(d=e.opt.single?h==a?e.opt.starOn:e.opt.starOff:a>=h?e.opt.starOn:e.opt.starOff,b.attr("src",e.opt.path+d))},fixHint:function(){var b=a(this),c=parseInt(this.score.val(),10),d=this.opt.noRatedMsg;!isNaN(c)&&c>0&&(d=c<=this.opt.hints.length&&null!==this.opt.hints[c-1]?this.opt.hints[c-1]:c),b.data("readonly",!0).css("cursor","default").attr("title",d),this.score.attr("readonly","readonly"),this.stars.attr("title",d)},getScore:function(){var b,c=[];return a(this).each(function(){b=this.score.val(),c.push(b?parseFloat(b):void 0)}),c.length>1?c:c[0]},readOnly:function(c){return this.each(function(){var d=a(this);return d.data("readonly")===c?this:(this.cancel&&(c?this.cancel.hide():this.cancel.show()),c?(d.unbind(),d.children("img").unbind(),b.fixHint.call(this)):(b.bindAction.call(this),b.unfixHint.call(this)),void d.data("readonly",c))})},reload:function(){return b.set.call(this,{})},roundStar:function(a){var b=(a-Math.floor(a)).toFixed(2);if(b>this.opt.round.down){var c=this.opt.starOn;b0&&.6>b&&this.stars.eq(Math.ceil(a)-1).attr("src",this.opt.path+this.opt.starHalf)},initialize:function(a){a=a?b.between(a,0,this.opt.number):0,b.fill.call(this,a),a>0&&(this.opt.halfShow&&b.roundStar.call(this,a),this.score.val(a))},unfixHint:function(){for(var b=0;bmodel('module'); +load()->model('system'); + +$dos = array('delete', 'edit', 'set_permission', 'save_permission', 'set_manager', 'module'); +$do = in_array($do, $dos) ? $do : 'edit'; + +$uniacid = intval($_GPC['uniacid']); +if (empty($uniacid)) { + if ($_W['isajax']) { + iajax(-1, '请选择要编辑的平台账号'); + } + itoast('请选择要编辑的平台账号', referer(), 'error'); +} +$state = permission_account_user_role($_W['uid'], $uniacid); +$role_permission = in_array($state, array(ACCOUNT_MANAGE_NAME_FOUNDER, ACCOUNT_MANAGE_NAME_OWNER, ACCOUNT_MANAGE_NAME_MANAGER, ACCOUNT_MANAGE_NAME_VICE_FOUNDER)); +if (!$role_permission) { + if ($_W['isajax']) { + iajax(-1, '无权限操作'); + } + itoast('无权限操作!', referer(), 'error'); +} +$founders = explode(',', $_W['config']['setting']['founder']); +$founder_info = pdo_getcolumn('users', array('uid' => current($founders)), 'username'); +$account = uni_fetch($uniacid); +$_W['breadcrumb'] = $account['name']; +$headimgsrc = tomedia('headimg_' . $account['acid'] . '.jpg'); +if (is_error($account)) { + itoast($account['message']); +} + +if ('edit' == $do) { + $account_belong_user = pdo_getcolumn('uni_account_users', array('uniacid' => $uniacid, 'role' => 'owner'), 'uid'); + $permissions = pdo_fetchall('SELECT id, uid, role FROM ' . tablename('uni_account_users') . " WHERE uniacid = '$uniacid' ORDER BY uid ASC, role DESC", array(), 'uid'); + if (!empty($permissions)) { + $member = pdo_fetchall('SELECT username, uid FROM ' . tablename('users') . ' WHERE uid IN (' . implode(',', array_keys($permissions)) . ')', array(), 'uid'); + if (!empty($member)) { + $operator = $manager = $owner = $vice_founder = array(); + foreach ($permissions as $key => $per_val) { + $per_val['isfounder'] = in_array($member[$key]['uid'], $founders) ? 1 : 0; + $per_val['username'] = $member[$key]['username'] ? $member[$key]['username'] : ''; + switch ($per_val['role']) { + case 'vice_founder': + $vice_founder = $per_val; + break; + case 'owner': + $owner = $per_val; + break; + case 'manager': + $manager[] = $per_val; + break; + case 'operator': + $operator[] = $per_val; + break; + default: + break; + } + } + } + } + if ($_W['isajax']) { + iajax(0, array( + 'founder_info' => $founder_info, + 'vice_founder' => empty($vice_founder) ? '' : $vice_founder, + 'owner' => empty($owner) ? '' : $owner, + 'manager' => empty($manager) ? '' : $manager, + 'operator' => empty($operator) ? '' : $operator, + 'create_user_url' => $_W['siteroot'] . 'web' . ltrim(url('user/create'), '.'), + )); + } + template('account/manage-users'); +} + +if ('delete' == $do) { + $uid = intval($_GPC['uid']); + if (empty($uid)) { + iajax(-1, '请选择要删除的用户!'); + } + $data = array( + 'uniacid' => $uniacid, + 'uid' => $uid, + ); + $exists = pdo_get('uni_account_users', array('uniacid' => $uniacid, 'uid' => $uid)); + if (empty($exists)) { + iajax(-1, '该平台账号下不存在该用户!'); + } + + if (ACCOUNT_MANAGE_NAME_MANAGER == $state && (ACCOUNT_MANAGE_NAME_OWNER == $exists['role'] || ACCOUNT_MANAGE_NAME_MANAGER == $exists['role'])) { + iajax(-1, '管理员不可操作其他管理员'); + } + $result = pdo_delete('uni_account_users', $data); + if ($result) { + if (ACCOUNT_MANAGE_NAME_OPERATOR == $exists['role']) { + pdo_delete('users_permission', $data); + } + pdo_delete('users_lastuse', $data); + pdo_delete('system_stat_visit', $data); + pdo_delete('users_operate_history', $data); + iajax(0, '删除成功!', referer()); + } else { + iajax(-1, '删除失败,请重试'); + } +} + +if ('set_manager' == $do) { + $username = safe_gpc_string($_GPC['username']); + $user = user_single(array('username' => $username)); + + if (!empty($user)) { + if (2 != $user['status']) { + iajax(3, '用户未通过审核或不存在!', ''); + } + + if (ACCOUNT_OPERATE_CLERK == $user['type']) { + iajax(-1, '该用户是应用操作员,不能成为账号的操作员!', ''); + } + + $addtype = intval($_GPC['addtype']); + if (ACCOUNT_MANAGE_TYPE_OWNER == $addtype) { + $user_end_time = user_end_time($user['uid']); + $account_end_time = 0 == $user_end_time ? 0 : strtotime($user_end_time); + pdo_update('account', array('endtime' => $account_end_time), array('uniacid' => $uniacid)); + } + + if (!in_array($addtype, array(ACCOUNT_MANAGE_TYPE_OPERATOR, ACCOUNT_MANAGE_TYPE_MANAGER, ACCOUNT_MANAGE_TYPE_OWNER, ACCOUNT_MANAGE_TYPE_VICE_FOUNDER))) { + iajax(-1, '添加使用者类型有误,只能添加操作员/管理员/主管理员/副创始人!'); + } + if (in_array($user['uid'], $founders)) { + if (ACCOUNT_MANAGE_TYPE_OWNER == $addtype) { + pdo_delete('uni_account_users', array('uniacid' => $uniacid, 'role' => ACCOUNT_MANAGE_NAME_OWNER)); + iajax(0, '修改成功!', ''); + } + iajax(1, '不可操作网站创始人!', ''); + } + if (ACCOUNT_MANAGE_TYPE_OWNER == $addtype && !in_array($_W['uid'], $founders)) { + $creat_limit = permission_user_account_num($user['uid']); + if ($creat_limit[TYPE_SIGN . '_limit'] <= 0) { + itoast(error(5, ACCOUNT_TYPE_NAME . '创建数量已达上限'), '', 'error'); + } + } + + $data = array( + 'uniacid' => $uniacid, + 'uid' => $user['uid'], + ); + + $exists = pdo_get('uni_account_users', $data); + if (empty($exists)) { + if (ACCOUNT_MANAGE_TYPE_OWNER == $addtype) { + if (ACCOUNT_MANAGE_NAME_MANAGER == $state) { + iajax(4, '管理员不可操作主管理员', ''); + } + $vice_founder = pdo_get('uni_account_users', array('uniacid' => $uniacid, 'role' => ACCOUNT_MANAGE_NAME_VICE_FOUNDER)); + if (!empty($vice_founder) && $user['owner_uid'] != $vice_founder['uid']) { + iajax(-1, '只能修改平台副创始人下的用户为主管理员!'); + } + $owner = pdo_get('uni_account_users', array('uniacid' => $uniacid, 'role' => 'owner')); + if (empty($owner)) { + $data['role'] = ACCOUNT_MANAGE_NAME_OWNER; + } else { + $result = pdo_update('uni_account_users', $data, array('id' => $owner['id'])); + if ($result) { + pdo_delete('users_permission', array('uniacid' => $uniacid, 'uid' => $user['uid'])); + cache_clean(cache_system_key('user_accounts')); + //cache_build_account_modules($uniacid, $user['uid']); + iajax(0, '修改成功!', ''); + } else { + iajax(1, '修改失败!', ''); + } + exit; + } + } elseif (ACCOUNT_MANAGE_TYPE_MANAGER == $addtype) { + if (ACCOUNT_MANAGE_NAME_MANAGER == $state) { + iajax(4, '管理员不可操作管理员', ''); + } + $data['role'] = ACCOUNT_MANAGE_NAME_MANAGER; + } elseif (ACCOUNT_MANAGE_TYPE_OPERATOR == $addtype) { + $data['role'] = ACCOUNT_MANAGE_NAME_OPERATOR; + } + pdo_delete('uni_account_users', array('uniacid' => $uniacid, 'uid' => $user['uid'])); + $result = pdo_insert('uni_account_users', $data); + + if ($result) { + if (ACCOUNT_MANAGE_TYPE_OWNER == $addtype) { + pdo_delete('users_permission', array('uniacid' => $uniacid, 'uid' => $user['uid'])); + } + if (in_array($addtype, array(ACCOUNT_MANAGE_TYPE_MANAGER, ACCOUNT_MANAGE_TYPE_OPERATOR))) { + permission_account_user_init($user['uid'], $uniacid); + } + cache_clean(cache_system_key('user_accounts')); + //cache_build_account_modules($uniacid, $user['uid']); + iajax(0, '添加成功!', ''); + } else { + iajax(1, '添加失败!', ''); + } + } else { + $permissions = table('users_permission')->getAllUserPermission($user['uid'], $uniacid); + $modulelist = uni_modules(); + if (!empty($permissions)) { + $i = 0; + foreach ($permissions as $permission) { + if ($i >= 3) { + break; + } + if (!in_array($permission['type'], array_keys($modulelist))) { + continue; + } + $module_info = module_fetch($permission['type']); + $modules_str .= $module_info['title'] . ','; + ++$i; + } + } + + if (empty($permissions) && !empty($exists)) { + if (ACCOUNT_MANAGE_NAME_OPERATOR == $exists['role']) { + $role_name = '操作员'; + } elseif (ACCOUNT_MANAGE_NAME_MANAGER == $exists['role']) { + $role_name = '管理员'; + } elseif (ACCOUNT_MANAGE_NAME_OWNER == $exists['role']) { + $role_name = '主管理员'; + } + + iajax(2, "添加平台使用者失败, " . $username . ", 已经是公众号的" . $role_name . ' ,请勿重复添加!', ''); + } else { + iajax(2, "添加平台使用者失败, " . $username . ", 已经是 " . rtrim($modules_str, ',') . '的应用操作员,请先取消其应用内操作员身份后再添加平台使用者!', ''); + } + } + } else { + iajax(-1, '用户不存在!', ''); + } +} + +if ('set_permission' == $do || 'save_permission' == $do) { + $uid = intval($_GPC['uid']); + $user = user_single(array('uid' => $uid)); + if (empty($user)) { + if ($_W['isajax']) { + iajax(-1, '您操作的用户不存在或是已经被删除'); + } + itoast('您操作的用户不存在或是已经被删除!', '', ''); + } + $role = permission_account_user_role($_W['uid'], $uniacid); + if (empty($role)) { + if ($_W['isajax']) { + iajax(-1, '此用户没有操作该统一公众号的权限,请选指派“管理员”或是“操作员”权限!'); + } + itoast('此用户没有操作该统一公众号的权限,请选指派“管理员”或是“操作员”权限!', '', ''); + } + $module_permission = permission_account_user_menu($uid, $uniacid, 'modules'); + + if ('all' == current($module_permission)) { + $module_permission_keys = array(); + $module_permission_all = 1; + } else { + $module_permission_keys = array_keys($module_permission); + $module_permission_all = 0; + } + $user_all_module_permission = table('users_permission')->getAllUserModulePermission($uid, $uniacid); + if ($account->supportVersion) { + $version_modules = array(); + $version_all = miniapp_version_all($uniacid); + if (!empty($version_all)) { + foreach ($version_all as $key => $version) { + if (!empty($version['modules'])) { + $version_modules = array_merge($version_modules, array_keys($version['modules'])); + } + } + } + foreach ($version_modules as $version_module) { + $module[$version_module] = module_fetch($version_module); + } + } else { + $module = uni_modules_by_uniacid($uniacid); + } + $user_modules_permissions = array(); + if (!empty($module)) { + foreach ($module as $module_name_key => $value) { + if (1 == $value['issystem']) { + unset($module[$module_name_key]); + continue; + } + if (!empty($user_all_module_permission[$module_name_key]['permission'])) { + $have_module_permission = explode('|', $user_all_module_permission[$module_name_key]['permission']); + } else { + $have_module_permission = array(); + } + $user_modules_permissions[$module_name_key] = array('module_title' => $value['title'], 'permission' => array()); + $permissions = module_permission_fetch($module_name_key); + if (empty($permissions)) { + $user_modules_permissions[$module_name_key]['permission'] = (in_array('all', $have_module_permission) || in_array('all', $module_permission)) ? array('all') : array(); + continue; + } + foreach ($permissions as $permission_info) { + $permission_info['checked'] = 0; + if (in_array($permission_info['permission'], $have_module_permission) || in_array('all', $have_module_permission) || in_array('all', $module_permission)) { + $permission_info['checked'] = 1; + } + $user_modules_permissions[$module_name_key]['permission'][] = $permission_info; + } + } + } + + foreach ($account_all_type_sign as $account_type_sign => $account_type_info) { + if (in_array($account['type'], $account_type_info['contain_type'])) { + $account_type = 'account' == $account_type_sign ? 'system' : $account_type_sign; + } + } + + $user_menu_permissions = permission_account_user_menu($uid, $uniacid, $account_type); + $menus = system_menu_permission_list($role); + + permission_account_user_init($user['uid'], $uniacid); + + if (in_array($account['type_sign'], array(ACCOUNT_TYPE_SIGN, WEBAPP_TYPE_SIGN))) { + $account_type_menu = ACCOUNT_TYPE_SIGN; + } elseif (in_array($account['type_sign'], array(ALIAPP_TYPE_SIGN, BAIDUAPP_TYPE_SIGN, TOUTIAOAPP_TYPE_SIGN))) { + $account_type_menu = WXAPP_TYPE_SIGN; + } else { + $account_type_menu = $account['type_sign']; + } + + if ('set_permission' == $do) { + if ($_W['isajax']) { + if (!empty($menus[$account_type_menu]) && !empty($menus[$account_type_menu]['section'])) { + foreach ($menus[$account_type_menu]['section'] as $section_key => &$section) { + if ($section_key == 'platform_module') { + unset($menus[$account_type_menu]['section']['platform_module']); + continue; + } + if (empty($section['menu'])) { + continue; + } + foreach ($section['menu'] as &$menu) { + + if (in_array($menu['permission_name'], $user_menu_permissions)) { + $menu['checked'] = 1; + } else { + $menu['checked'] = 0; + } + if (empty($menu['sub_permission'])) { + continue; + } + foreach ($menu['sub_permission'] as &$sub_permission) { + if (in_array($sub_permission['permission_name'], $user_menu_permissions)) { + $sub_permission['checked'] = 1; + } else { + $sub_permission['checked'] = 0; + } + } + unset($menu); + } + unset($sub_permission); + } + unset($section); + } + $result = array( + 'uni_modules_permission' => $user_modules_permissions, + 'menus' => $menus[$account_type_menu], + ); + iajax(0, $result); + } + template('account/set-permission'); + } +} + +if ('save_permission' == $do) { + $user_menu_permission_new = array(); + if (!empty($_GPC['menus'])) { + $all_menu_permission = permission_menu_name(); + foreach ($_GPC['menus'] as $permission_name) { + if (in_array($permission_name, $all_menu_permission)) { + $user_menu_permission_new[] = $permission_name; + } + } + $data = array( + 'type' => $account_type, + 'permission' => implode('|', $user_menu_permission_new), + ); + $result = permission_update_account_user($uid, $uniacid, $data); + if (is_error($result)) { + if ($_W['isajax']) { + iajax(-1, $result['message']); + } + itoast($result['message']); + } + } else { + $data = array( + 'type' => $account_type, + 'permission' => '|', + ); + $result = permission_update_account_user($uid, $uniacid, $data); + } + if (is_error($result)) { + if ($_W['isajax']) { + iajax(-1, $result['message']); + } + itoast($result['message']); + } + + + $permission_names = "'" . implode(array(PERMISSION_ACCOUNT, PERMISSION_WXAPP, PERMISSION_WEBAPP, PERMISSION_PHONEAPP, PERMISSION_ALIAPP, PERMISSION_BAIDUAPP, PERMISSION_TOUTIAOAPP, PERMISSION_SYSTEM), "','") . "'"; + pdo_query('DELETE FROM ' . tablename('users_permission') . ' WHERE uniacid = :uniacid AND uid = :uid AND type not in (' . $permission_names . ')', array(':uniacid' => $uniacid, ':uid' => $uid)); + + if (!empty($_GPC['module'])) { + $module_names = array(); + foreach ($_GPC['module'] as $module_val) { + $insert = array( + 'uniacid' => $uniacid, + 'uid' => $uid, + 'type' => $module_val, + ); + if (!empty($module[$module_val])) { + $module_names[] = $module_val; + } + if (1 == $_GPC[$module_val . '_select']) { + $insert['permission'] = 'all'; + pdo_insert('users_permission', $insert); + continue; + } else { + $data = array(); + foreach ($_GPC['module_' . $module_val] as $v) { + $data[] = $v; + } + if (!empty($data)) { + $insert['permission'] = implode('|', $data); + pdo_insert('users_permission', $insert); + } + } + } + $module_names = implode(',', $module_names); + pdo_query('DELETE FROM ' . tablename('users_operate_history') . ' WHERE uniacid = :uniacid AND uid = :uid AND module_name not in (:module_name)', array(':uniacid' => $uniacid, ':uid' => $uid, ':module_name' => $module_names)); + } else { + $module_all_permission_data = array( + 'uid' => $uid, + 'uniacid' => $uniacid, + 'type' => 'modules', + ); + $module_all_permission = pdo_get('users_permission', $module_all_permission_data); + if (empty($module_all_permission)) { + $module_all_permission_data['permission'] = 'none'; + pdo_insert('users_permission', $module_all_permission_data); + } + } + cache_delete(cache_system_key('permission', array('uniacid' => $uniacid, 'uid' => $uid))); + if ($_W['isajax']) { + iajax(0, '操作菜单权限成功!'); + } + itoast('操作菜单权限成功!', referer(), 'success'); +} + +if ('module' == $do) { + $uid = intval($_GPC['uid']); + $user = user_single($uid); + if (empty($user)) { + iajax(-1, '访问错误, 未找到指定操作用户.', ''); + } + $isfounder = user_is_founder($uid, true); + if ($isfounder) { + iajax(-1, '访问错误, 无法编辑站长.', ''); + } + $module_name = safe_gpc_string($_GPC['m']); + $module = pdo_fetch('SELECT * FROM ' . tablename('modules') . ' WHERE name = :m', array(':m' => $module_name)); + $purview = pdo_fetch('SELECT * FROM ' . tablename('users_permission') . ' WHERE uniacid = :aid AND uid = :uid AND type = :type', array(':aid' => $uniacid, ':uid' => $uid, ':type' => $module_name)); + $user_module_permissions = permission_account_user_menu($uid, $uniacid, 'modules'); + if (!empty($purview['permission'])) { + $purview['permission'] = explode('|', $purview['permission']); + } else { + $purview['permission'] = array(); + } + + $mineurl = array(); + $all = 0; + if (!empty($mods)) { + foreach ($mods as $mod) { + if ('all' == $mod['url']) { + $all = 1; + break; + } else { + $mineurl[] = $mod['url']; + } + } + } + $data = array(); + if ($module['settings']) { + $data[] = array('title' => '参数设置', 'permission' => $module_name . '_settings'); + } + if ($module['isrulefields']) { + $data[] = array('title' => '回复规则列表', 'permission' => $module_name . '_rule'); + } + $entries = module_entries($module_name); + if (!empty($entries['home'])) { + $data[] = array('title' => '微站首页导航', 'permission' => $module_name . '_home'); + } + if (!empty($entries['profile'])) { + $data[] = array('title' => '个人中心导航', 'permission' => $module_name . '_profile'); + } + if (!empty($entries['shortcut'])) { + $data[] = array('title' => '快捷菜单', 'permission' => $module_name . '_shortcut'); + } + if (!empty($entries['cover'])) { + foreach ($entries['cover'] as $cover) { + $data[] = array('title' => $cover['title'], 'permission' => $module_name . '_cover_' . $cover['do']); + } + } + if (!empty($entries['menu'])) { + foreach ($entries['menu'] as $menu) { + if (!empty($menu['multilevel'])) { + continue; + } + $data[] = array('title' => $menu['title'], 'permission' => $module_name . '_menu_' . $menu['do']); + } + } + unset($entries); + if (!empty($module['permissions'])) { + $module['permissions'] = (array)iunserializer($module['permissions']); + $data = array_merge($data, $module['permissions']); + } + foreach ($data as &$data_val) { + $data_val['checked'] = 0; + if (in_array($data_val['permission'], $purview['permission']) || in_array('all', $purview['permission']) || in_array('all', $user_module_permissions)) { + $data_val['checked'] = 1; + } + } + unset($data_val); + if (empty($data)) { + iajax(-1, '无子权限!', ''); + } else { + iajax(0, $data, ''); + } +} diff --git a/web/source/account/post.ctrl.php b/web/source/account/post.ctrl.php new file mode 100644 index 0000000..880ef33 --- /dev/null +++ b/web/source/account/post.ctrl.php @@ -0,0 +1,253 @@ +model('module'); +load()->model('cloud'); +load()->model('cache'); +load()->classs('weixin.platform'); +load()->model('utility'); +load()->func('file'); +$uniacid = intval($_GPC['uniacid']); +if (empty($uniacid)) { + $url = url('account/manage', array('account_type' => ACCOUNT_TYPE)); + if ($_W['isajax']) { + iajax(-1, '请选择要编辑的' . ACCOUNT_TYPE_NAME); + } + itoast('请选择要编辑的' . ACCOUNT_TYPE_NAME, $url, 'error'); +} +$account = uni_fetch($uniacid); +if (!$account) { + if ($_W['isajax']) { + iajax(-1, '无效的uniacid'); + } + itoast('无效的uniacid'); +} +$acid = $account['acid']; +$state = permission_account_user_role($_W['uid'], $uniacid); +$dos = array('base', 'sms', 'modules_tpl', 'edit_modules_tpl', 'operators'); +$role_permission = in_array($state, array(ACCOUNT_MANAGE_NAME_FOUNDER, ACCOUNT_MANAGE_NAME_OWNER, ACCOUNT_MANAGE_NAME_VICE_FOUNDER)); +if ($role_permission || $_W['isajax']) { + $do = in_array($do, $dos) ? $do : 'base'; +} elseif (ACCOUNT_MANAGE_NAME_MANAGER == $state) { + if (ACCOUNT_TYPE == ACCOUNT_TYPE_APP_NORMAL || ACCOUNT_TYPE == ACCOUNT_TYPE_APP_AUTH) { + header('Location: ' . url('wxapp/manage/display', array('uniacid' => $uniacid))); + exit; + } else { + $do = in_array($do, $dos) ? $do : 'modules_tpl'; + } +} else { + itoast('您是该公众号的操作员,无权限操作!', url('account/manage'), 'error'); +} + +$_W['breadcrumb'] = $account['name']; +if ('base' == $do) { + if (!$role_permission && !$_W['isajax']) { + itoast('无权限操作!', url('account/post/modules_tpl', array('uniacid' => $uniacid)), 'error'); + } + if ($_W['ispost'] && $_W['isajax']) { + if (!empty($_GPC['type'])) { + $type = safe_gpc_string($_GPC['type']); + } else { + iajax(-1, '参数错误!', ''); + } + $request_data = safe_gpc_string(trim($_GPC['request_data'])); + switch ($type) { + case 'qrcodeimgsrc': + case 'headimgsrc': + $imgsrc = safe_gpc_path($request_data); + $image_type = array( + 'qrcodeimgsrc' => 'qrcode', + 'headimgsrc' => 'logo', + ); + if (file_is_image($imgsrc)) { + $result = table('uni_account')->where('uniacid', $uniacid)->fill($image_type[$type], $imgsrc)->save(); + } else { + $result = ''; + } + break; + case 'name': + $uni_account = pdo_update('uni_account', array('name' => $request_data), array('uniacid' => $uniacid)); + $account_wechats = pdo_update($account->tablename, array('name' => $request_data), array('uniacid' => $uniacid)); + $result = ($uni_account && $account_wechats) ? true : false; + break; + case 'account': + $data = array('account' => $request_data); break; + case 'original': + $data = array('original' => $request_data); break; + case 'level': + $data = array('level' => intval($_GPC['request_data'])); break; + case 'appid': + if (!empty($request_data)) { + $hasAppid = uni_get_account_by_appid($request_data, $account['type'], $account['uniacid']); + if (!empty($hasAppid)) { + iajax(1, "{$hasAppid['key_title']}已被{$hasAppid['type_title']}[ {$hasAppid['name']} ]使用"); + } + } + $data = array('appid' => $request_data); break; + case 'key': + if (!empty($request_data) && !in_array($account['type_sign'], array(BAIDUAPP_TYPE_SIGN, TOUTIAOAPP_TYPE_SIGN))) { + $hasAppid = uni_get_account_by_appid($request_data, $account['type'], $account['uniacid']); + if (!empty($hasAppid)) { + iajax(1, "{$hasAppid['key_title']}已被{$hasAppid['type_title']}[ {$hasAppid['name']} ]使用"); + } + } + if ($account['key'] == $request_data) { + iajax(0, '修改成功!', referer()); + } + $data = array('key' => $request_data); break; + case 'secret': + if ($account['secret'] == $request_data) { + iajax(0, '修改成功!', referer()); + } + $data = array('secret' => $request_data); break; + case 'token': + $oauth = (array) uni_setting_load(array('oauth'), $uniacid); + if ($oauth['oauth'] == $acid && 4 != $account['level']) { + $acid = pdo_fetchcolumn('SELECT acid FROM ' . tablename('account_wechats') . " WHERE uniacid = :uniacid AND level = 4 AND secret != '' AND `key` != ''", array(':uniacid' => $uniacid)); + pdo_update('uni_settings', array('oauth' => iserializer(array('account' => $acid, 'host' => $oauth['oauth']['host']))), array('uniacid' => $uniacid)); + } + $data = array('token' => $request_data); + break; + case 'encodingaeskey': + $oauth = (array) uni_setting_load(array('oauth'), $uniacid); + if ($oauth['oauth'] == $acid && 4 != $account['level']) { + $acid = pdo_fetchcolumn('SELECT acid FROM ' . tablename('account_wechats') . " WHERE uniacid = :uniacid AND level = 4 AND secret != '' AND `key` != ''", array(':uniacid' => $uniacid)); + pdo_update('uni_settings', array('oauth' => iserializer(array('account' => $acid, 'host' => $oauth['oauth']['host']))), array('uniacid' => $uniacid)); + } + $data = array('encodingaeskey' => $request_data); + break; + case 'jointype': + if (in_array($account['type'], array(ACCOUNT_TYPE_OFFCIAL_NORMAL, ACCOUNT_TYPE_APP_NORMAL))) { + $result = true; + } else { + $change_type = array( + 'type' => 'account' == $account->typeSign ? ACCOUNT_TYPE_OFFCIAL_NORMAL : ACCOUNT_TYPE_APP_NORMAL, + ); + $update_type = pdo_update('account', $change_type, array('uniacid' => $uniacid)); + $result = $update_type ? true : false; + } + break; + case 'highest_visit': + if (user_is_vice_founder() || empty($_W['isfounder'])) { + iajax(1, '只有创始人可以修改!'); + } + $statistics_setting = (array) uni_setting_load(array('statistics'), $uniacid); + if (!empty($statistics_setting['statistics'])) { + $highest_visit = $statistics_setting['statistics']; + $highest_visit['founder'] = intval($_GPC['request_data']); + } else { + $highest_visit = array('founder' => intval($_GPC['request_data'])); + } + $result = pdo_update('uni_settings', array('statistics' => iserializer($highest_visit)), array('uniacid' => $uniacid)); + break; + case 'endtime': + $endtime = strtotime($_GPC['endtime']); + if ($endtime <= 0) { + iajax(1, '参数错误!'); + } + + if ($_W['isfounder']) { + $endtime = 1 != $_GPC['endtype'] ? $endtime : 0; + + } else { + $owner_id = pdo_getcolumn('uni_account_users', array('uniacid' => $uniacid, 'role' => 'owner'), 'uid'); + $user_endtime = pdo_getcolumn('users', array('uid' => $owner_id), 'endtime'); + + if ($user_endtime != USER_ENDTIME_GROUP_UNLIMIT_TYPE && $user_endtime != USER_ENDTIME_GROUP_EMPTY_TYPE && $user_endtime < $endtime && !empty($user_endtime)) { + iajax(1, '设置到期日期不能超过' . user_end_time($owner_id)); + } + } + $result = pdo_update('account', array('endtime' => $endtime), array('uniacid' => $uniacid)); + break; + case 'attachment_limit': + if (user_is_vice_founder() || empty($_W['isfounder'])) { + iajax(1, '只有创始人可以修改!'); + } + $has_uniacid = pdo_getcolumn('uni_settings', array('uniacid' => $uniacid), 'uniacid'); + if ($_GPC['request_data'] < 0) { + $attachment_limit = -1; + } else { + $attachment_limit = intval($_GPC['request_data']); + } + if (empty($has_uniacid)) { + $result = pdo_insert('uni_settings', array('attachment_limit' => $attachment_limit, 'uniacid' => $uniacid)); + } else { + $result = pdo_update('uni_settings', array('attachment_limit' => $attachment_limit), array('uniacid' => $uniacid)); + } + break; + } + if (!in_array($type, array('qrcodeimgsrc', 'headimgsrc', 'name', 'endtime', 'jointype', 'highest_visit', 'attachment_limit'))) { + $result = pdo_update($account->tablename, $data, array('uniacid' => $uniacid)); + } + if ($result) { + cache_delete(cache_system_key('uniaccount', array('uniacid' => $uniacid))); + cache_delete(cache_system_key('accesstoken', array('uniacid' => $uniacid))); + cache_delete(cache_system_key('statistics', array('uniacid' => $uniacid))); + iajax(0, '修改成功!', referer()); + } else { + iajax(1, '修改失败!', ''); + } + } + + if(!$_W['isadmin']){ + $owner_id = pdo_getcolumn('uni_account_users', array('uniacid' => $uniacid, 'role' => 'owner'), 'uid'); + $user_endtime = user_end_time($owner_id); + } + if ($_W['setting']['platform']['authstate']) { + $account_platform = new WeixinPlatform(); + $preauthcode = $account_platform->getPreauthCode(); + if (is_error($preauthcode)) { + if (40013 == $preauthcode['errno']) { + $url = '微信开放平台 appid 链接不成功,请检查修改后再试' . "去设置"; + } else { + $url = "{$preauthcode['message']}"; + } + + $authurl = array( + 'errno' => 1, + 'url' => $url, + ); + } else { + $authurl_type = $account['type'] == 4 ? ACCOUNT_PLATFORM_API_LOGIN_WXAPP : ACCOUNT_PLATFORM_API_LOGIN_ACCOUNT; + $callurl = $authurl_type == ACCOUNT_PLATFORM_API_LOGIN_WXAPP ? 'index.php?c=wxapp&a=auth&do=forward' : 'index.php?c=account&a=auth&do=forward'; + $authurl = array( + 'errno' => 0, + 'url' => sprintf(ACCOUNT_PLATFORM_API_LOGIN, $account_platform->appid, $preauthcode, urlencode($GLOBALS['_W']['siteroot'] . $callurl), $authurl_type), + ); + } + } + $account['start'] = date('Y-m-d', $account['starttime']); + $account['end'] = in_array($account['endtime'], array(USER_ENDTIME_GROUP_EMPTY_TYPE, USER_ENDTIME_GROUP_UNLIMIT_TYPE)) ? '永久' : date('Y-m-d', $account['endtime']); + $account['endtype'] = (in_array($account['endtime'], array(USER_ENDTIME_GROUP_EMPTY_TYPE, USER_ENDTIME_GROUP_UNLIMIT_TYPE)) || $account['endtime'] == 0) ? 1 : 2; + $uni_setting = (array) uni_setting_load(array('statistics', 'attachment_limit', 'attachment_size'), $uniacid); + $account['highest_visit'] = empty($uni_setting['statistics']['founder']) ? 0 : $uni_setting['statistics']['founder']; + + $attachment_limit = intval($uni_setting['attachment_limit']); + if (0 == $attachment_limit) { + $upload = setting_load('upload'); + $attachment_limit = empty($upload['upload']['attachment_limit']) ? 0 : intval($upload['upload']['attachment_limit']); + } + if ($attachment_limit <= 0) { + $attachment_limit = -1; + } + $account['attachment_limit'] = intval($attachment_limit); + $account['switchurl_full'] = $_W['siteroot'] . 'web/' . ltrim($account['switchurl'], './'); + $account['endtime'] = strlen($account['endtime']) == 10 ? $account['endtime'] : time(); + $account['headimgsrc'] = $account['logo']; + $account['qrcodeimgsrc'] = $account['qrcode']; + $account['switchurl_full'] = $_W['siteroot'] . 'web/' . ltrim($account['switchurl'], './'); + $account['siteurl'] = $account['type_sign'] != WXAPP_TYPE_SIGN ? $_W['siteroot'] : str_replace('http://', 'https://', $_W['siteroot']); + $account['service_url'] = $account['siteurl'] . 'api.php?id=' . $account['acid']; + $account['type_class'] = $account_all_type_sign[$account['type_sign']]['icon']; + $account['owner_endtime'] = $user_endtime; + $account['support_version'] = $account->supportVersion; + $uniaccount = array(); + $uniaccount = pdo_get('uni_account', array('uniacid' => $uniacid)); + + if ($_W['isajax']) { + iajax(0, $account); + } else { + template('account/manage-base'); + } +} diff --git a/web/source/system/optimize.ctrl.php b/web/source/system/optimize.ctrl.php new file mode 100644 index 0000000..9bdfadb --- /dev/null +++ b/web/source/system/optimize.ctrl.php @@ -0,0 +1,79 @@ +func('cache'); + +$dos = array('opcache'); +$do = in_array($do, $dos) ? $do : 'index'; + +if ('opcache' == $do) { + opcache_reset(); + if ($_W['isw7_request']) { + iajax(0, '清空缓存成功'); + } + itoast('清空缓存成功', url('system/optimize'), 'success'); +} else { + $cache_type = cache_type(); + $clear = array('url' => url('system/updatecache', array('do' => 'updatecache')), 'title' => '更新缓存'); + $extensions = array( + 'memcache' => array( + 'support' => extension_loaded('memcache'), + 'status' => 'memcache' == $cache_type, + 'clear' => $clear, + ), + 'redis' => array( + 'support' => extension_loaded('redis'), + 'status' => 'redis' == $cache_type, + 'clear' => $clear, + ), + 'opcache' => array( + 'support' => function_exists('opcache_get_configuration'), + 'status' => ini_get('opcache.enable') || ini_get('opcache.enable_cli'), + 'clear' => array( + 'url' => url('system/optimize/opcache'), + 'title' => '清空缓存', + ), + ), + ); + $slave = $_W['config']['db']; + $setting = $_W['config']['setting']; + + if ($extensions['memcache']['status']) { + $memobj = cache_memcache(); + if (!empty($memobj) && method_exists($memobj, 'getExtendedStats')) { + $status = $memobj->getExtendedStats(); + if (!empty($status)) { + foreach ($status as $server => $row) { + $data_status[] = '已用:' . round($row['bytes'] / 1048576, 2) . ' M / 共:' . round($row['limit_maxbytes'] / 1048576) . ' M'; + } + $extensions['memcache']['extra'] = ', ' . implode(', ', $data_status); + } + } + } + if ($extensions['redis']['status']) { + $redisobj = cache_redis(); + if (!empty($redisobj) && method_exists($redisobj, 'info')) { + $status = $redisobj->info(); + if (!empty($status)) { + $extensions['redis']['extra'] = '消耗峰值:' . round($status['used_memory_peak'] / 1048576, 2) . ' M/ 内存总量:' . round($status['used_memory'] / 1048576, 2) . ' M'; + } + } + } + if ($_W['isw7_request']) { + $message = array( + 'extensions' => $extensions, + 'slave_status' => $slave['slave_status'], + 'extensions' => $extensions, + 'session_setting' => array( + 'memcache' => $setting['memcache']['session'], + 'redis' => $setting['redis']['session'] + ), + 'slave_except_table' => !empty($slave['common']['slave_except_table']) ? $slave['common']['slave_except_table']: array(), + 'proxy_host' => !empty($setting['proxy']['host']) ? $setting['proxy']['host'] : '' + ); + iajax(0, $message); + } + template('system/optimize'); +} \ No newline at end of file diff --git a/web/source/user/profile.ctrl.php b/web/source/user/profile.ctrl.php new file mode 100644 index 0000000..38aede2 --- /dev/null +++ b/web/source/user/profile.ctrl.php @@ -0,0 +1,450 @@ +model('user'); +load()->func('file'); +load()->classs('oauth2/oauth2client'); +load()->model('setting'); + +$dos = array('base', 'post', 'bind', 'validate_mobile', 'bind_mobile', 'unbind', 'check_mobile_sms_code', 'change_mobile'); +$do = in_array($do, $dos) ? $do : 'base'; + +if ('post' == $do) { + $type = trim($_GPC['type']); + $extra_filed_key = safe_gpc_string($_GPC['extra_field_key']); + $extra_filed_val = safe_gpc_string($_GPC['extra_field_val']); + if ($_W['isfounder']) { + $uid = is_array($_GPC['uid']) ? 0 : intval($_GPC['uid']); + } else { + $uid = $_W['uid']; + } + if (empty($uid) || empty($type)) { + iajax(-1, '参数错误,请刷新后重试!', ''); + } + $user = user_single($uid); + if (empty($user)) { + iajax(-1, '用户不存在或已经被删除!', ''); + } + + if (USER_STATUS_CHECK == $user['status'] || USER_STATUS_BAN == $user['status']) { + iajax(-1, '访问错误,该用户未审核或者已被禁用,请先修改用户状态!', ''); + } + + $users_profile_exist = table('users_profile')->getByUid($uid); + if ('birth' == $type) { + if ($users_profile_exist['year'] == $_GPC['year'] && $users_profile_exist['month'] == $_GPC['month'] && $users_profile_exist['day'] == $_GPC['day']) { + iajax(0, '未作修改!', ''); + } + } elseif ('reside' == $type) { + if ($users_profile_exist['province'] == $_GPC['province'] && $users_profile_exist['city'] == $_GPC['city'] && $users_profile_exist['district'] == $_GPC['district']) { + iajax(0, '未作修改!', ''); + } + } else { + if (in_array($type, array('username', 'password', 'welcome_link'))) { + if ($user[$type] == $_GPC[$type] && 'password' != $type) { + iajax(0, '未做修改!', ''); + } + } else { + if ($users_profile_exist[$type] == $_GPC[$type] && empty($extra_filed_key)) { + iajax(0, '未作修改!', ''); + } + } + } + switch ($type) { + case 'avatar': + case 'realname': + case 'address': + case 'qq': + case 'mobile': + if ('mobile' == $type) { + $match = preg_match(REGULAR_MOBILE, trim($_GPC[$type])); + if (empty($match)) { + iajax(-1, '手机号不正确', ''); + } + $users_mobile = pdo_get('users_profile', array('mobile' => trim($_GPC[$type]), 'uid <>' => $uid)); + $bind_mobile = pdo_get('users_bind', array('bind_sign' => trim($_GPC[$type]), 'uid <>' => $uid)); + if (!empty($users_mobile) || !empty($bind_mobile)) { + iajax(-1, '手机号已存在,请联系管理员', ''); + } + } + if ($users_profile_exist) { + $result = pdo_update('users_profile', array($type => trim($_GPC[$type])), array('uid' => $uid)); + } else { + $data = array( + 'uid' => $uid, + 'createtime' => TIMESTAMP, + $type => safe_gpc_string($_GPC[$type]), + ); + $result = pdo_insert('users_profile', $data); + } + if ('mobile' == $type) { + $data = array( + 'uid' => $uid, + 'bind_sign' => trim($_GPC[$type]), + 'third_nickname' => trim($_GPC[$type]), + 'third_type' => USER_REGISTER_TYPE_MOBILE, + ); + $users_bind_exist = pdo_get('users_bind', array('uid' => $uid, 'third_type' => USER_REGISTER_TYPE_MOBILE)); + if ($users_bind_exist) { + $result_bind = pdo_update('users_bind', $data, array('uid' => $uid, 'third_type' => USER_REGISTER_TYPE_MOBILE)); + } else { + $result_bind = pdo_insert('users_bind', $data); + } + if (!$result_bind) { + iajax(-1, '操作失败,请联系管理员解决!', ''); + } + } + break; + case 'username': + if (!$_W['isadmin'] && $_W['uid'] != $user['owner_uid']) { + iajax(-1, '无权限修改,请联系网站创始人!'); + } + $username = safe_gpc_string($_GPC['username']); + $name_exist = pdo_get('users', array('username' => $username)); + if (!empty($name_exist)) { + iajax(-1, '用户名已存在,请更换其他用户名!', ''); + } + $result = pdo_update('users', array('username' => $username), array('uid' => $uid)); + break; + case 'vice_founder_name': + $userinfo = user_single(array('username' => safe_gpc_string($_GPC['vice_founder_name']))); + + if (empty($userinfo) || ACCOUNT_MANAGE_GROUP_VICE_FOUNDER != $userinfo['founder_groupid']) { + iajax(-1, '用户不存在或该用户不是副创始人', ''); + } + pdo_update('users', array('owner_uid' => $userinfo['uid']), array('uid' => $uid)); + $founder_own_user_table = table('users_founder_own_users'); + $founder_own_user_exists = $founder_own_user_table->getFounderByUid($uid); + + if (!empty($founder_own_user_exists)) { + $result = $founder_own_user_table->updateOwnUser($uid, $userinfo['uid']); + } else { + $result = $founder_own_user_table->addOwnUser($uid, $userinfo['uid']); + } + + + if ($result) { + $uni_account_users = table('uni_account_users'); + $synchronize_data = $uni_account_users->where(array('uid' => $uid, 'role' => 'owner'))->getall('uniacid'); + if (!empty($synchronize_data)) { + foreach ($synchronize_data as $k => $v) { + $founder_id = ''; + $founder_id = table('uni_account_users')->where(array('uniacid' => $k, 'role' => 'vice_founder'))->getcolumn('id'); + + if ($founder_id) { + $uni_account_result = table('uni_account_users')->where(array('id' => $founder_id))->fill(array('uid' => $userinfo['uid']))->save(); + } else { + $save_data = array( + 'uniacid' => $k, + 'uid' => $userinfo['uid'], + 'role' => 'vice_founder', + 'rank' => 0, + 'createtime' => 0 + ); + $uni_account_result = table('uni_account_users')->fill($save_data)->save(); + } + } + } + } + + break; + case 'remark': + $result = pdo_update('users', array('remark' => safe_gpc_string($_GPC['remark'])), array('uid' => $uid)); + break; + case 'welcome_link': + $welcome_link = intval($_GPC['welcome_link']); + $result = pdo_update('users', array('welcome_link' => $welcome_link), array('uid' => $uid)); + break; + case 'password': + if ($_GPC['newpwd'] !== $_GPC['renewpwd']) { + iajax(-1, '两次密码不一致!', ''); + } + $_GPC['newpwd'] = safe_gpc_string($_GPC['newpwd']); + $check_safe = safe_check_password($_GPC['newpwd']); + if (is_error($check_safe)) { + iajax(-1, $check_safe['message']); + } + + if (!$_W['isfounder'] && empty($user['register_type'])) { + $pwd = user_password($_GPC['oldpwd'], $uid); + $pwd_hash = user_password_hash($pwd, $uid); + if ($pwd_hash != $user['hash']) { + iajax(-1, '原密码不正确!', ''); + } + } + $newpwd = user_password($_GPC['newpwd'], $uid); + $newpwd_hash = user_password_hash($newpwd, $uid); + if ($newpwd_hash == $user['hash']) { + iajax(0, '未作修改!', ''); + } + $result = pdo_update('users', array('password' => $newpwd), array('uid' => $uid)); + break; + case 'endtime': + if (!$_W['isfounder']) { + iajax(-1, '无权限操作!'); + } + if (1 == $_GPC['endtype']) { + $endtime = 0; + } else { + $endtime = strtotime($_GPC['endtime']); + } + if (user_is_vice_founder() && !empty($_W['user']['endtime']) && ($endtime > $_W['user']['endtime'] || empty($endtime))) { + iajax(-1, '副创始人给用户设置的时间不能超过自己的到期时间'); + } + $result = pdo_update('users', array('endtime' => $endtime), array('uid' => $uid)); + pdo_update('users_profile', array('send_expire_status' => 0), array('uid' => $uid)); + $uni_account_user = pdo_getall('uni_account_users', array('uid' => $uid, 'role' => 'owner')); + if (!empty($uni_account_user)) { + foreach ($uni_account_user as $account) { + cache_delete(cache_system_key('uniaccount', array('uniacid' => $account['uniacid']))); + } + } + break; + case 'birth': + if ($users_profile_exist) { + $result = pdo_update('users_profile', array('birthyear' => intval($_GPC['year']), 'birthmonth' => intval($_GPC['month']), 'birthday' => intval($_GPC['day'])), array('uid' => $uid)); + } else { + $data = array( + 'uid' => $uid, + 'createtime' => TIMESTAMP, + 'birthyear' => intval($_GPC['year']), + 'birthmonth' => intval($_GPC['month']), + 'birthday' => intval($_GPC['day']), + ); + $result = pdo_insert('users_profile', $data); + } + break; + case 'reside': + $province = safe_gpc_string($_GPC['province']); + $city = safe_gpc_string($_GPC['city']); + $district = safe_gpc_string($_GPC['district']); + if ($users_profile_exist) { + $result = pdo_update('users_profile', array('resideprovince' => $province, 'residecity' => $city, 'residedist' => $district), array('uid' => $uid)); + } else { + $data = array( + 'uid' => $uid, + 'createtime' => TIMESTAMP, + 'resideprovince' => $province, + 'residecity' => $city, + 'residedist' => $district, + ); + $result = pdo_insert('users_profile', $data); + } + break; + default: + $allow_fields = array( + 'realname', 'nickname', 'avatar', 'qq', 'mobile', 'gender', 'birthyear', 'birthmonth', 'birthday', 'constellation', 'zodiac', 'idcard', 'studentid', 'grade', 'address', 'zipcode', 'nationality', 'resideprovince', 'residecity', 'residedist', 'graduateschool', 'company', 'education', 'occupation', 'position', 'revenue', 'affectivestatus', 'lookingfor', 'bloodtype', 'height', 'weight', 'alipay', 'msn', 'email', 'taobao', 'site', 'bio', 'interest', + ); + if (empty($extra_filed_key) || !in_array($extra_filed_key, $allow_fields)) { + iajax(-1, '参数错误', ''); + } + if ($users_profile_exist) { + $result = pdo_update('users_profile', array($extra_filed_key => $extra_filed_val), array('uid' => $uid)); + } else { + $data = array( + 'uid' => $uid, + $extra_filed_key => $extra_filed_val, + ); + $result = pdo_insert('users_profile', $data); + } + break; + } + if ($result) { + pdo_update('users_profile', array('edittime' => TIMESTAMP), array('uid' => $uid)); + $type == 'password' ? iajax(0, '修改成功,请重新登录!', url('user/login')) : iajax(0, '修改成功!', ''); + } else { + iajax(-1, '修改失败,请稍候重试!', ''); + } +} + +if ('base' == $do) { + $user_type = !empty($_GPC['user_type']) ? trim($_GPC['user_type']) : PERSONAL_BASE_TYPE; + $user = $_W['user']; + $user['last_visit'] = date('Y-m-d H:i:s', $user['lastvisit']); + $user['joindate'] = date('Y-m-d H:i:s', $user['joindate']); + $user['url'] = user_invite_register_url($_W['uid']); + + $profile = pdo_get('users_profile', array('uid' => $_W['uid'])); + $profile = user_detail_formate($profile); + + $redirect_urls = array( + array('id' => WELCOME_DISPLAY_TYPE, 'name' => '用户欢迎页'), + array('id' => PLATFORM_DISPLAY_TYPE, 'name' => '最后进入的平台或应用'), + ); + $support_login_urls = user_support_urls(); + + $lists = table('users_bind')->getAllByUid($_W['uid']); + $bind_qq = array(); + $bind_wechat = array(); + $bind_mobile = array(); + if (!empty($lists)) { + foreach ($lists as $list) { + switch ($list['third_type']) { + case USER_REGISTER_TYPE_QQ: + $bind_qq = $list; + break; + case USER_REGISTER_TYPE_WECHAT: + $bind_wechat = $list; + break; + case USER_REGISTER_TYPE_MOBILE: + $bind_mobile = $list; + break; + } + } + } + + $endtime = $user['endtime']; + if (USER_ENDTIME_GROUP_EMPTY_TYPE == $endtime || USER_ENDTIME_GROUP_UNLIMIT_TYPE == $endtime) { + $endtime = '永久'; + } else { + $endtime = date('Y-m-d', $endtime); + } + + $setting_sms_sign = setting_load('site_sms_sign'); + $bind_sign = !empty($setting_sms_sign['site_sms_sign']['register']) ? $setting_sms_sign['site_sms_sign']['register'] : ''; + + template('user/profile'); +} + +if ('bind' == $do) { + $setting_sms_sign = setting_load('site_sms_sign'); + $bind_sign = !empty($setting_sms_sign['site_sms_sign']['register']) ? $setting_sms_sign['site_sms_sign']['register'] : ''; + + $user = table('users')->getById($_W['uid']); + $user_profile = table('users_profile')->getByUid($_W['uid']); + + $bind_info = table('users_bind')->getAllByUid($_W['uid']); + + $signs = array_keys($bind_info); + + if (!empty($user['openid']) && !in_array($user['openid'], $signs)) { + pdo_insert('users_bind', array('uid' => $user['uid'], 'bind_sign' => $user['openid'], 'third_type' => $user['register_type'], 'third_nickname' => $user_profile['nickname'])); + } + + if (!empty($user_profile['mobile']) && !in_array($user_profile['mobile'], $signs)) { + pdo_insert('users_bind', array('uid' => $user_profile['uid'], 'bind_sign' => $user_profile['mobile'], 'third_type' => USER_REGISTER_TYPE_MOBILE, 'third_nickname' => $user_profile['mobile'])); + } + + $lists = table('users_bind')->getAllByUid($_W['uid']); + + $bind_qq = array(); + $bind_wechat = array(); + $bind_mobile = array(); + + if (!empty($lists)) { + foreach ($lists as $list) { + switch ($list['third_type']) { + case USER_REGISTER_TYPE_QQ: + $bind_qq = $list; + break; + case USER_REGISTER_TYPE_WECHAT: + $bind_wechat = $list; + break; + case USER_REGISTER_TYPE_MOBILE: + $bind_mobile = $list; + break; + } + } + } + + $support_login_urls = user_support_urls(); + + template('user/bind'); +} + +if (in_array($do, array('validate_mobile', 'bind_mobile')) || USER_REGISTER_TYPE_MOBILE == $_GPC['bind_type'] && 'unbind' == $do) { + $user_bind = table('users_bind')->getByTypeAndUid(USER_REGISTER_TYPE_MOBILE, $_W['uid']); + + $mobile = safe_gpc_string($_GPC['mobile']); + $type = trim($_GPC['type']); + + $mobile_exists = table('users_profile')->where('uid !=', $_W['uid'])->getByMobile($mobile); + if (empty($mobile)) { + iajax(-1, '手机号不能为空'); + } + if (!preg_match(REGULAR_MOBILE, $mobile)) { + iajax(-1, '手机号格式不正确'); + } + + if (!empty($type) && $mobile != $user_bind['bind_sign']) { + iajax(-1, '请输入已绑定的手机号'); + } + + if (empty($type) && !empty($mobile_exists)) { + iajax(-1, '手机号已存在'); + } +} +if ('validate_mobile' == $do) { + $user = array('username' => safe_gpc_string($_GPC['mobile'])); + $mobile_exists = user_check($user); + if ($mobile_exists) { + iajax(-1, '手机号已经存在'); + } + iajax(0, '本地校验成功'); +} + +if ('bind_mobile' == $do) { + if ($_W['isajax'] && $_W['ispost']) { + $bind_info = OAuth2Client::create('mobile')->bind(); + + $user = array('username' => safe_gpc_string($_GPC['mobile'])); + $mobile_exists = user_check($user); + if ($mobile_exists) { + iajax(-1, '手机号已经存在'); + } + + if (is_error($bind_info)) { + iajax(-1, $bind_info['message']); + } + iajax(0, '绑定成功', url('user/profile/bind')); + } else { + iajax(-1, '非法请求'); + } +} + +if ('change_mobile' == $do) { + $step = 1; + $bind_mobile = table('users_bind')->getByTypeAndUid(USER_REGISTER_TYPE_MOBILE, $_W['uid']); + $setting_sms_sign = setting_load('site_sms_sign'); + $bind_sign = !empty($setting_sms_sign['site_sms_sign']['register']) ? $setting_sms_sign['site_sms_sign']['register'] : ''; + template('user/change-mobile'); +} + +if ('check_mobile_sms_code' == $do) { + if ($_W['isajax'] && $_W['ispost']) { + $check_result = OAuth2Client::create('mobile')->paramValidate(); + if (is_error($check_result)) { + iajax(-1, $check_result['message']); + } + $check_authcode = authcode(safe_gpc_string($_GPC['mobile']), 'ENCODE'); + $message = array( + 'message' => '验证成功', + 'check_authcode' => $check_authcode + ); + iajax(0, $message); + } else { + iajax(-1, '非法请求'); + } +} + +if ('unbind' == $do) { + $types = array(1 => 'qq', 2 => 'wechat', 3 => 'mobile'); + if (!in_array($_GPC['bind_type'], array(USER_REGISTER_TYPE_QQ, USER_REGISTER_TYPE_WECHAT, USER_REGISTER_TYPE_MOBILE))) { + iajax(-1, '类型错误'); + } + $bind_type = $types[$_GPC['bind_type']]; + if ($_W['isajax'] && $_W['ispost']) { + $unbind_info = OAuth2Client::create($bind_type, $_W['setting']['thirdlogin'][$bind_type]['appid'], $_W['setting']['thirdlogin'][$bind_type]['appsecret'])->unbind(); + + if (is_error($unbind_info)) { + iajax(-1, $unbind_info['message']); + } + $settings = $_W['setting']['copyright']; + if ($_W['isadmin'] && $settings['login_verify_status']) { + $settings['login_verify_status'] = 0; + setting_save($settings, 'copyright'); + } + iajax(0, '解绑成功', url('user/profile/bind')); + } + iajax(-1, '非法请求'); +} \ No newline at end of file diff --git a/web/themes/default/system/optimize.html b/web/themes/default/system/optimize.html new file mode 100644 index 0000000..45845cb --- /dev/null +++ b/web/themes/default/system/optimize.html @@ -0,0 +1,49 @@ +{template 'common/header'} +
+
    +
    +
    + + + + + + + + + + + + {loop $extensions $key $extension} + + + + + + + {/loop} +
    内存接口PHP 扩展环境Config 设置
    {$key} + {if $extension['support']} + 支持 + {else} + 不支持 + {/if} + + {if $extension['status']} + 已开启 + {else} + 未开启 + {/if} + {if $key == 'opcache' && $extensions['eAccelerator']['status'] && $extensions['opcache']['status']} + eAccelerator 不可与 opcache同时开启 + {/if} + + {if $extension['status'] && $extension['clear']} + {$extension['clear']['title']} + {/if} + {$extension['extra']} +
    +
    +
    +
    +{template 'common/footer'} diff --git a/web/themes/default/user/post.html b/web/themes/default/user/post.html new file mode 100644 index 0000000..2d87a76 --- /dev/null +++ b/web/themes/default/user/post.html @@ -0,0 +1,89 @@ +{template 'common/header'} +
    + + +
    + +
    + +
    + +
    + + {if $is_used != 'used'} +
    + 用户名已经被注册! + 用户名不能为空! + 用户名必须为 3 到 30 个字符组成,包括汉字,大小写字母(不区分大小写) +
    + {/if} + + {if $is_used == 'used'} +
    不是系统用户
    + {/if} +
    +
    + + {if $is_used != 'used'} + +
    + +
    + + +
    请填写密码,最小长度为 8 个字符
    +
    +
    + + + +
    + +
    + +
    重复输入密码,确认正确输入
    +
    +
    + + {/if} + + +
    + +
    + +
    +
    + +
    + + +
    + +
    +
    +
    + + +{template 'common/footer'} + diff --git a/web/themes/default/user/profile.html b/web/themes/default/user/profile.html new file mode 100644 index 0000000..26f7546 --- /dev/null +++ b/web/themes/default/user/profile.html @@ -0,0 +1,347 @@ +{template 'common/header'} +
    + {if $_W['highest_role'] != 'founder'} +
    + +
    +

    +
    +
    + {/if} + {if $user_type=='' || $user_type == PERSONAL_BASE_TYPE} +
    + + + + + + + + + + + + + + + + + + + + + + + +
    账户设置
    头像
    用户{if permission_check_account_user('see_user_profile_edit_username')}{/if}
    密码******
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {if $_W['isadmin']} + + + + + + {/if} +
    基础信息
    真实姓名
    上次登录时间
    上次登录IP
    注册时间
    到期时间{$endtime}
    备注
    + + + {/if} + +
    + + +{if $user_type == PERSONAL_BIND_TYPE} + + + +{/if} +{template 'common/footer'} \ No newline at end of file