diff --git a/framework/library/phpexcel/PHPExcel/DocumentProperties.php b/framework/library/phpexcel/PHPExcel/DocumentProperties.php new file mode 100644 index 0000000..2a6370a --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/DocumentProperties.php @@ -0,0 +1,587 @@ +_lastModifiedBy = $this->_creator; + $this->_created = time(); + $this->_modified = time(); + } + + /** + * Get Creator + * + * @return string + */ + public function getCreator() { + return $this->_creator; + } + + /** + * Set Creator + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setCreator($pValue = '') { + $this->_creator = $pValue; + return $this; + } + + /** + * Get Last Modified By + * + * @return string + */ + public function getLastModifiedBy() { + return $this->_lastModifiedBy; + } + + /** + * Set Last Modified By + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setLastModifiedBy($pValue = '') { + $this->_lastModifiedBy = $pValue; + return $this; + } + + /** + * Get Created + * + * @return datetime + */ + public function getCreated() { + return $this->_created; + } + + /** + * Set Created + * + * @param datetime $pValue + * @return PHPExcel_DocumentProperties + */ + public function setCreated($pValue = null) { + if ($pValue === NULL) { + $pValue = time(); + } elseif (is_string($pValue)) { + if (is_numeric($pValue)) { + $pValue = intval($pValue); + } else { + $pValue = strtotime($pValue); + } + } + + $this->_created = $pValue; + return $this; + } + + /** + * Get Modified + * + * @return datetime + */ + public function getModified() { + return $this->_modified; + } + + /** + * Set Modified + * + * @param datetime $pValue + * @return PHPExcel_DocumentProperties + */ + public function setModified($pValue = null) { + if ($pValue === NULL) { + $pValue = time(); + } elseif (is_string($pValue)) { + if (is_numeric($pValue)) { + $pValue = intval($pValue); + } else { + $pValue = strtotime($pValue); + } + } + + $this->_modified = $pValue; + return $this; + } + + /** + * Get Title + * + * @return string + */ + public function getTitle() { + return $this->_title; + } + + /** + * Set Title + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setTitle($pValue = '') { + $this->_title = $pValue; + return $this; + } + + /** + * Get Description + * + * @return string + */ + public function getDescription() { + return $this->_description; + } + + /** + * Set Description + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setDescription($pValue = '') { + $this->_description = $pValue; + return $this; + } + + /** + * Get Subject + * + * @return string + */ + public function getSubject() { + return $this->_subject; + } + + /** + * Set Subject + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setSubject($pValue = '') { + $this->_subject = $pValue; + return $this; + } + + /** + * Get Keywords + * + * @return string + */ + public function getKeywords() { + return $this->_keywords; + } + + /** + * Set Keywords + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setKeywords($pValue = '') { + $this->_keywords = $pValue; + return $this; + } + + /** + * Get Category + * + * @return string + */ + public function getCategory() { + return $this->_category; + } + + /** + * Set Category + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setCategory($pValue = '') { + $this->_category = $pValue; + return $this; + } + + /** + * Get Company + * + * @return string + */ + public function getCompany() { + return $this->_company; + } + + /** + * Set Company + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setCompany($pValue = '') { + $this->_company = $pValue; + return $this; + } + + /** + * Get Manager + * + * @return string + */ + public function getManager() { + return $this->_manager; + } + + /** + * Set Manager + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setManager($pValue = '') { + $this->_manager = $pValue; + return $this; + } + + /** + * Get a List of Custom Property Names + * + * @return array of string + */ + public function getCustomProperties() { + return array_keys($this->_customProperties); + } + + /** + * Check if a Custom Property is defined + * + * @param string $propertyName + * @return boolean + */ + public function isCustomPropertySet($propertyName) { + return isset($this->_customProperties[$propertyName]); + } + + /** + * Get a Custom Property Value + * + * @param string $propertyName + * @return string + */ + public function getCustomPropertyValue($propertyName) { + if (isset($this->_customProperties[$propertyName])) { + return $this->_customProperties[$propertyName]['value']; + } + + } + + /** + * Get a Custom Property Type + * + * @param string $propertyName + * @return string + */ + public function getCustomPropertyType($propertyName) { + if (isset($this->_customProperties[$propertyName])) { + return $this->_customProperties[$propertyName]['type']; + } + + } + + /** + * Set a Custom Property + * + * @param string $propertyName + * @param mixed $propertyValue + * @param string $propertyType + * 'i' : Integer + * 'f' : Floating Point + * 's' : String + * 'd' : Date/Time + * 'b' : Boolean + * @return PHPExcel_DocumentProperties + */ + public function setCustomProperty($propertyName,$propertyValue='',$propertyType=NULL) { + if (($propertyType === NULL) || (!in_array($propertyType,array(self::PROPERTY_TYPE_INTEGER, + self::PROPERTY_TYPE_FLOAT, + self::PROPERTY_TYPE_STRING, + self::PROPERTY_TYPE_DATE, + self::PROPERTY_TYPE_BOOLEAN)))) { + if ($propertyValue === NULL) { + $propertyType = self::PROPERTY_TYPE_STRING; + } elseif (is_float($propertyValue)) { + $propertyType = self::PROPERTY_TYPE_FLOAT; + } elseif(is_int($propertyValue)) { + $propertyType = self::PROPERTY_TYPE_INTEGER; + } elseif (is_bool($propertyValue)) { + $propertyType = self::PROPERTY_TYPE_BOOLEAN; + } else { + $propertyType = self::PROPERTY_TYPE_STRING; + } + } + + $this->_customProperties[$propertyName] = array('value' => $propertyValue, 'type' => $propertyType); + return $this; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } + + public static function convertProperty($propertyValue,$propertyType) { + switch ($propertyType) { + case 'empty' : // Empty + return ''; + break; + case 'null' : // Null + return NULL; + break; + case 'i1' : // 1-Byte Signed Integer + case 'i2' : // 2-Byte Signed Integer + case 'i4' : // 4-Byte Signed Integer + case 'i8' : // 8-Byte Signed Integer + case 'int' : // Integer + return (int) $propertyValue; + break; + case 'ui1' : // 1-Byte Unsigned Integer + case 'ui2' : // 2-Byte Unsigned Integer + case 'ui4' : // 4-Byte Unsigned Integer + case 'ui8' : // 8-Byte Unsigned Integer + case 'uint' : // Unsigned Integer + return abs((int) $propertyValue); + break; + case 'r4' : // 4-Byte Real Number + case 'r8' : // 8-Byte Real Number + case 'decimal' : // Decimal + return (float) $propertyValue; + break; + case 'lpstr' : // LPSTR + case 'lpwstr' : // LPWSTR + case 'bstr' : // Basic String + return $propertyValue; + break; + case 'date' : // Date and Time + case 'filetime' : // File Time + return strtotime($propertyValue); + break; + case 'bool' : // Boolean + return ($propertyValue == 'true') ? True : False; + break; + case 'cy' : // Currency + case 'error' : // Error Status Code + case 'vector' : // Vector + case 'array' : // Array + case 'blob' : // Binary Blob + case 'oblob' : // Binary Blob Object + case 'stream' : // Binary Stream + case 'ostream' : // Binary Stream Object + case 'storage' : // Binary Storage + case 'ostorage' : // Binary Storage Object + case 'vstream' : // Binary Versioned Stream + case 'clsid' : // Class ID + case 'cf' : // Clipboard Data + return $propertyValue; + break; + } + return $propertyValue; + } + + public static function convertPropertyType($propertyType) { + switch ($propertyType) { + case 'i1' : // 1-Byte Signed Integer + case 'i2' : // 2-Byte Signed Integer + case 'i4' : // 4-Byte Signed Integer + case 'i8' : // 8-Byte Signed Integer + case 'int' : // Integer + case 'ui1' : // 1-Byte Unsigned Integer + case 'ui2' : // 2-Byte Unsigned Integer + case 'ui4' : // 4-Byte Unsigned Integer + case 'ui8' : // 8-Byte Unsigned Integer + case 'uint' : // Unsigned Integer + return self::PROPERTY_TYPE_INTEGER; + break; + case 'r4' : // 4-Byte Real Number + case 'r8' : // 8-Byte Real Number + case 'decimal' : // Decimal + return self::PROPERTY_TYPE_FLOAT; + break; + case 'empty' : // Empty + case 'null' : // Null + case 'lpstr' : // LPSTR + case 'lpwstr' : // LPWSTR + case 'bstr' : // Basic String + return self::PROPERTY_TYPE_STRING; + break; + case 'date' : // Date and Time + case 'filetime' : // File Time + return self::PROPERTY_TYPE_DATE; + break; + case 'bool' : // Boolean + return self::PROPERTY_TYPE_BOOLEAN; + break; + case 'cy' : // Currency + case 'error' : // Error Status Code + case 'vector' : // Vector + case 'array' : // Array + case 'blob' : // Binary Blob + case 'oblob' : // Binary Blob Object + case 'stream' : // Binary Stream + case 'ostream' : // Binary Stream Object + case 'storage' : // Binary Storage + case 'ostorage' : // Binary Storage Object + case 'vstream' : // Binary Versioned Stream + case 'clsid' : // Class ID + case 'cf' : // Clipboard Data + return self::PROPERTY_TYPE_UNKNOWN; + break; + } + return self::PROPERTY_TYPE_UNKNOWN; + } + +} diff --git a/framework/library/phpexcel/PHPExcel/DocumentSecurity.php b/framework/library/phpexcel/PHPExcel/DocumentSecurity.php new file mode 100644 index 0000000..e3e8378 --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/DocumentSecurity.php @@ -0,0 +1,218 @@ +_lockRevision = false; + $this->_lockStructure = false; + $this->_lockWindows = false; + $this->_revisionsPassword = ''; + $this->_workbookPassword = ''; + } + + /** + * Is some sort of dcument security enabled? + * + * @return boolean + */ + function isSecurityEnabled() { + return $this->_lockRevision || + $this->_lockStructure || + $this->_lockWindows; + } + + /** + * Get LockRevision + * + * @return boolean + */ + function getLockRevision() { + return $this->_lockRevision; + } + + /** + * Set LockRevision + * + * @param boolean $pValue + * @return PHPExcel_DocumentSecurity + */ + function setLockRevision($pValue = false) { + $this->_lockRevision = $pValue; + return $this; + } + + /** + * Get LockStructure + * + * @return boolean + */ + function getLockStructure() { + return $this->_lockStructure; + } + + /** + * Set LockStructure + * + * @param boolean $pValue + * @return PHPExcel_DocumentSecurity + */ + function setLockStructure($pValue = false) { + $this->_lockStructure = $pValue; + return $this; + } + + /** + * Get LockWindows + * + * @return boolean + */ + function getLockWindows() { + return $this->_lockWindows; + } + + /** + * Set LockWindows + * + * @param boolean $pValue + * @return PHPExcel_DocumentSecurity + */ + function setLockWindows($pValue = false) { + $this->_lockWindows = $pValue; + return $this; + } + + /** + * Get RevisionsPassword (hashed) + * + * @return string + */ + function getRevisionsPassword() { + return $this->_revisionsPassword; + } + + /** + * Set RevisionsPassword + * + * @param string $pValue + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @return PHPExcel_DocumentSecurity + */ + function setRevisionsPassword($pValue = '', $pAlreadyHashed = false) { + if (!$pAlreadyHashed) { + $pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue); + } + $this->_revisionsPassword = $pValue; + return $this; + } + + /** + * Get WorkbookPassword (hashed) + * + * @return string + */ + function getWorkbookPassword() { + return $this->_workbookPassword; + } + + /** + * Set WorkbookPassword + * + * @param string $pValue + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @return PHPExcel_DocumentSecurity + */ + function setWorkbookPassword($pValue = '', $pAlreadyHashed = false) { + if (!$pAlreadyHashed) { + $pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue); + } + $this->_workbookPassword = $pValue; + return $this; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/framework/library/phpexcel/PHPExcel/Exception.php b/framework/library/phpexcel/PHPExcel/Exception.php new file mode 100644 index 0000000..78c9521 --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Exception.php @@ -0,0 +1,52 @@ +line = $line; + $e->file = $file; + throw $e; + } +} diff --git a/framework/library/phpexcel/PHPExcel/HashTable.php b/framework/library/phpexcel/PHPExcel/HashTable.php new file mode 100644 index 0000000..100c7ec --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/HashTable.php @@ -0,0 +1,202 @@ +addFromSource($pSource); + } + } + + /** + * Add HashTable items from source + * + * @param PHPExcel_IComparable[] $pSource Source array to create HashTable from + * @throws PHPExcel_Exception + */ + public function addFromSource($pSource = null) { + // Check if an array was passed + if ($pSource == null) { + return; + } else if (!is_array($pSource)) { + throw new PHPExcel_Exception('Invalid array parameter passed.'); + } + + foreach ($pSource as $item) { + $this->add($item); + } + } + + /** + * Add HashTable item + * + * @param PHPExcel_IComparable $pSource Item to add + * @throws PHPExcel_Exception + */ + public function add(PHPExcel_IComparable $pSource = null) { + $hash = $pSource->getHashCode(); + if (!isset($this->_items[$hash])) { + $this->_items[$hash] = $pSource; + $this->_keyMap[count($this->_items) - 1] = $hash; + } + } + + /** + * Remove HashTable item + * + * @param PHPExcel_IComparable $pSource Item to remove + * @throws PHPExcel_Exception + */ + public function remove(PHPExcel_IComparable $pSource = null) { + $hash = $pSource->getHashCode(); + if (isset($this->_items[$hash])) { + unset($this->_items[$hash]); + + $deleteKey = -1; + foreach ($this->_keyMap as $key => $value) { + if ($deleteKey >= 0) { + $this->_keyMap[$key - 1] = $value; + } + + if ($value == $hash) { + $deleteKey = $key; + } + } + unset($this->_keyMap[count($this->_keyMap) - 1]); + } + } + + /** + * Clear HashTable + * + */ + public function clear() { + $this->_items = array(); + $this->_keyMap = array(); + } + + /** + * Count + * + * @return int + */ + public function count() { + return count($this->_items); + } + + /** + * Get index for hash code + * + * @param string $pHashCode + * @return int Index + */ + public function getIndexForHashCode($pHashCode = '') { + return array_search($pHashCode, $this->_keyMap); + } + + /** + * Get by index + * + * @param int $pIndex + * @return PHPExcel_IComparable + * + */ + public function getByIndex($pIndex = 0) { + if (isset($this->_keyMap[$pIndex])) { + return $this->getByHashCode( $this->_keyMap[$pIndex] ); + } + + return null; + } + + /** + * Get by hashcode + * + * @param string $pHashCode + * @return PHPExcel_IComparable + * + */ + public function getByHashCode($pHashCode = '') { + if (isset($this->_items[$pHashCode])) { + return $this->_items[$pHashCode]; + } + + return null; + } + + /** + * HashTable to array + * + * @return PHPExcel_IComparable[] + */ + public function toArray() { + return $this->_items; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } + } + } +} diff --git a/framework/library/phpexcel/PHPExcel/IComparable.php b/framework/library/phpexcel/PHPExcel/IComparable.php new file mode 100644 index 0000000..fb1c33c --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/IComparable.php @@ -0,0 +1,43 @@ +_fillType = NULL; + } + $this->_startColor = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_WHITE, $isSupervisor, $isConditional); + $this->_endColor = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_BLACK, $isSupervisor, $isConditional); + + // bind parent if we are a supervisor + if ($isSupervisor) { + $this->_startColor->bindParent($this, '_startColor'); + $this->_endColor->bindParent($this, '_endColor'); + } + } + + /** + * Get the shared style component for the currently active cell in currently active sheet. + * Only used for style supervisor + * + * @return PHPExcel_Style_Fill + */ + public function getSharedComponent() + { + return $this->_parent->getSharedComponent()->getFill(); + } + + /** + * Build style array from subcomponents + * + * @param array $array + * @return array + */ + public function getStyleArray($array) + { + return array('fill' => $array); + } + + /** + * Apply styles from array + * + * + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getFill()->applyFromArray( + * array( + * 'type' => PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR, + * 'rotation' => 0, + * 'startcolor' => array( + * 'rgb' => '000000' + * ), + * 'endcolor' => array( + * 'argb' => 'FFFFFFFF' + * ) + * ) + * ); + * + * + * @param array $pStyles Array containing style information + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Fill + */ + public function applyFromArray($pStyles = null) { + if (is_array($pStyles)) { + if ($this->_isSupervisor) { + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + } else { + if (array_key_exists('type', $pStyles)) { + $this->setFillType($pStyles['type']); + } + if (array_key_exists('rotation', $pStyles)) { + $this->setRotation($pStyles['rotation']); + } + if (array_key_exists('startcolor', $pStyles)) { + $this->getStartColor()->applyFromArray($pStyles['startcolor']); + } + if (array_key_exists('endcolor', $pStyles)) { + $this->getEndColor()->applyFromArray($pStyles['endcolor']); + } + if (array_key_exists('color', $pStyles)) { + $this->getStartColor()->applyFromArray($pStyles['color']); + } + } + } else { + throw new PHPExcel_Exception("Invalid style array passed."); + } + return $this; + } + + /** + * Get Fill Type + * + * @return string + */ + public function getFillType() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getFillType(); + } + return $this->_fillType; + } + + /** + * Set Fill Type + * + * @param string $pValue PHPExcel_Style_Fill fill type + * @return PHPExcel_Style_Fill + */ + public function setFillType($pValue = PHPExcel_Style_Fill::FILL_NONE) { + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('type' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_fillType = $pValue; + } + return $this; + } + + /** + * Get Rotation + * + * @return double + */ + public function getRotation() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getRotation(); + } + return $this->_rotation; + } + + /** + * Set Rotation + * + * @param double $pValue + * @return PHPExcel_Style_Fill + */ + public function setRotation($pValue = 0) { + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('rotation' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_rotation = $pValue; + } + return $this; + } + + /** + * Get Start Color + * + * @return PHPExcel_Style_Color + */ + public function getStartColor() { + return $this->_startColor; + } + + /** + * Set Start Color + * + * @param PHPExcel_Style_Color $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Fill + */ + public function setStartColor(PHPExcel_Style_Color $pValue = null) { + // make sure parameter is a real color and not a supervisor + $color = $pValue->getIsSupervisor() ? $pValue->getSharedComponent() : $pValue; + + if ($this->_isSupervisor) { + $styleArray = $this->getStartColor()->getStyleArray(array('argb' => $color->getARGB())); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_startColor = $color; + } + return $this; + } + + /** + * Get End Color + * + * @return PHPExcel_Style_Color + */ + public function getEndColor() { + return $this->_endColor; + } + + /** + * Set End Color + * + * @param PHPExcel_Style_Color $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Fill + */ + public function setEndColor(PHPExcel_Style_Color $pValue = null) { + // make sure parameter is a real color and not a supervisor + $color = $pValue->getIsSupervisor() ? $pValue->getSharedComponent() : $pValue; + + if ($this->_isSupervisor) { + $styleArray = $this->getEndColor()->getStyleArray(array('argb' => $color->getARGB())); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_endColor = $color; + } + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHashCode(); + } + return md5( + $this->getFillType() + . $this->getRotation() + . $this->getStartColor()->getHashCode() + . $this->getEndColor()->getHashCode() + . __CLASS__ + ); + } + +} diff --git a/framework/library/phpexcel/PHPExcel/Style/Font.php b/framework/library/phpexcel/PHPExcel/Style/Font.php new file mode 100644 index 0000000..33dca2a --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Style/Font.php @@ -0,0 +1,532 @@ +_name = NULL; + $this->_size = NULL; + $this->_bold = NULL; + $this->_italic = NULL; + $this->_superScript = NULL; + $this->_subScript = NULL; + $this->_underline = NULL; + $this->_strikethrough = NULL; + $this->_color = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_BLACK, $isSupervisor, $isConditional); + } else { + $this->_color = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_BLACK, $isSupervisor); + } + // bind parent if we are a supervisor + if ($isSupervisor) { + $this->_color->bindParent($this, '_color'); + } + } + + /** + * Get the shared style component for the currently active cell in currently active sheet. + * Only used for style supervisor + * + * @return PHPExcel_Style_Font + */ + public function getSharedComponent() + { + return $this->_parent->getSharedComponent()->getFont(); + } + + /** + * Build style array from subcomponents + * + * @param array $array + * @return array + */ + public function getStyleArray($array) + { + return array('font' => $array); + } + + /** + * Apply styles from array + * + * + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getFont()->applyFromArray( + * array( + * 'name' => 'Arial', + * 'bold' => TRUE, + * 'italic' => FALSE, + * 'underline' => PHPExcel_Style_Font::UNDERLINE_DOUBLE, + * 'strike' => FALSE, + * 'color' => array( + * 'rgb' => '808080' + * ) + * ) + * ); + * + * + * @param array $pStyles Array containing style information + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Font + */ + public function applyFromArray($pStyles = null) { + if (is_array($pStyles)) { + if ($this->_isSupervisor) { + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + } else { + if (array_key_exists('name', $pStyles)) { + $this->setName($pStyles['name']); + } + if (array_key_exists('bold', $pStyles)) { + $this->setBold($pStyles['bold']); + } + if (array_key_exists('italic', $pStyles)) { + $this->setItalic($pStyles['italic']); + } + if (array_key_exists('superScript', $pStyles)) { + $this->setSuperScript($pStyles['superScript']); + } + if (array_key_exists('subScript', $pStyles)) { + $this->setSubScript($pStyles['subScript']); + } + if (array_key_exists('underline', $pStyles)) { + $this->setUnderline($pStyles['underline']); + } + if (array_key_exists('strike', $pStyles)) { + $this->setStrikethrough($pStyles['strike']); + } + if (array_key_exists('color', $pStyles)) { + $this->getColor()->applyFromArray($pStyles['color']); + } + if (array_key_exists('size', $pStyles)) { + $this->setSize($pStyles['size']); + } + } + } else { + throw new PHPExcel_Exception("Invalid style array passed."); + } + return $this; + } + + /** + * Get Name + * + * @return string + */ + public function getName() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getName(); + } + return $this->_name; + } + + /** + * Set Name + * + * @param string $pValue + * @return PHPExcel_Style_Font + */ + public function setName($pValue = 'Calibri') { + if ($pValue == '') { + $pValue = 'Calibri'; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('name' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_name = $pValue; + } + return $this; + } + + /** + * Get Size + * + * @return double + */ + public function getSize() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getSize(); + } + return $this->_size; + } + + /** + * Set Size + * + * @param double $pValue + * @return PHPExcel_Style_Font + */ + public function setSize($pValue = 10) { + if ($pValue == '') { + $pValue = 10; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('size' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_size = $pValue; + } + return $this; + } + + /** + * Get Bold + * + * @return boolean + */ + public function getBold() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getBold(); + } + return $this->_bold; + } + + /** + * Set Bold + * + * @param boolean $pValue + * @return PHPExcel_Style_Font + */ + public function setBold($pValue = false) { + if ($pValue == '') { + $pValue = false; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('bold' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_bold = $pValue; + } + return $this; + } + + /** + * Get Italic + * + * @return boolean + */ + public function getItalic() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getItalic(); + } + return $this->_italic; + } + + /** + * Set Italic + * + * @param boolean $pValue + * @return PHPExcel_Style_Font + */ + public function setItalic($pValue = false) { + if ($pValue == '') { + $pValue = false; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('italic' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_italic = $pValue; + } + return $this; + } + + /** + * Get SuperScript + * + * @return boolean + */ + public function getSuperScript() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getSuperScript(); + } + return $this->_superScript; + } + + /** + * Set SuperScript + * + * @param boolean $pValue + * @return PHPExcel_Style_Font + */ + public function setSuperScript($pValue = false) { + if ($pValue == '') { + $pValue = false; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('superScript' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_superScript = $pValue; + $this->_subScript = !$pValue; + } + return $this; + } + + /** + * Get SubScript + * + * @return boolean + */ + public function getSubScript() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getSubScript(); + } + return $this->_subScript; + } + + /** + * Set SubScript + * + * @param boolean $pValue + * @return PHPExcel_Style_Font + */ + public function setSubScript($pValue = false) { + if ($pValue == '') { + $pValue = false; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('subScript' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_subScript = $pValue; + $this->_superScript = !$pValue; + } + return $this; + } + + /** + * Get Underline + * + * @return string + */ + public function getUnderline() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getUnderline(); + } + return $this->_underline; + } + + /** + * Set Underline + * + * @param string|boolean $pValue PHPExcel_Style_Font underline type + * If a boolean is passed, then TRUE equates to UNDERLINE_SINGLE, + * false equates to UNDERLINE_NONE + * @return PHPExcel_Style_Font + */ + public function setUnderline($pValue = self::UNDERLINE_NONE) { + if (is_bool($pValue)) { + $pValue = ($pValue) ? self::UNDERLINE_SINGLE : self::UNDERLINE_NONE; + } elseif ($pValue == '') { + $pValue = self::UNDERLINE_NONE; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('underline' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_underline = $pValue; + } + return $this; + } + + /** + * Get Strikethrough + * + * @return boolean + */ + public function getStrikethrough() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getStrikethrough(); + } + return $this->_strikethrough; + } + + /** + * Set Strikethrough + * + * @param boolean $pValue + * @return PHPExcel_Style_Font + */ + public function setStrikethrough($pValue = false) { + if ($pValue == '') { + $pValue = false; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('strike' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_strikethrough = $pValue; + } + return $this; + } + + /** + * Get Color + * + * @return PHPExcel_Style_Color + */ + public function getColor() { + return $this->_color; + } + + /** + * Set Color + * + * @param PHPExcel_Style_Color $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Font + */ + public function setColor(PHPExcel_Style_Color $pValue = null) { + // make sure parameter is a real color and not a supervisor + $color = $pValue->getIsSupervisor() ? $pValue->getSharedComponent() : $pValue; + + if ($this->_isSupervisor) { + $styleArray = $this->getColor()->getStyleArray(array('argb' => $color->getARGB())); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_color = $color; + } + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHashCode(); + } + return md5( + $this->_name + . $this->_size + . ($this->_bold ? 't' : 'f') + . ($this->_italic ? 't' : 'f') + . ($this->_superScript ? 't' : 'f') + . ($this->_subScript ? 't' : 'f') + . $this->_underline + . ($this->_strikethrough ? 't' : 'f') + . $this->_color->getHashCode() + . __CLASS__ + ); + } + +} diff --git a/framework/library/phpexcel/PHPExcel/Worksheet/Drawing.php b/framework/library/phpexcel/PHPExcel/Worksheet/Drawing.php new file mode 100644 index 0000000..45086ce --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Worksheet/Drawing.php @@ -0,0 +1,148 @@ +_path = ''; + + // Initialize parent + parent::__construct(); + } + + /** + * Get Filename + * + * @return string + */ + public function getFilename() { + return basename($this->_path); + } + + /** + * Get indexed filename (using image index) + * + * @return string + */ + public function getIndexedFilename() { + $fileName = $this->getFilename(); + $fileName = str_replace(' ', '_', $fileName); + return str_replace('.' . $this->getExtension(), '', $fileName) . $this->getImageIndex() . '.' . $this->getExtension(); + } + + /** + * Get Extension + * + * @return string + */ + public function getExtension() { + $exploded = explode(".", basename($this->_path)); + return $exploded[count($exploded) - 1]; + } + + /** + * Get Path + * + * @return string + */ + public function getPath() { + return $this->_path; + } + + /** + * Set Path + * + * @param string $pValue File path + * @param boolean $pVerifyFile Verify file + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_Drawing + */ + public function setPath($pValue = '', $pVerifyFile = true) { + if ($pVerifyFile) { + if (file_exists($pValue)) { + $this->_path = $pValue; + + if ($this->_width == 0 && $this->_height == 0) { + // Get width/height + list($this->_width, $this->_height) = getimagesize($pValue); + } + } else { + throw new PHPExcel_Exception("File $pValue not found!"); + } + } else { + $this->_path = $pValue; + } + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->_path + . parent::getHashCode() + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/framework/library/phpexcel/PHPExcel/Worksheet/HeaderFooter.php b/framework/library/phpexcel/PHPExcel/Worksheet/HeaderFooter.php new file mode 100644 index 0000000..ef118f2 --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Worksheet/HeaderFooter.php @@ -0,0 +1,465 @@ + + * Header/Footer Formatting Syntax taken from Office Open XML Part 4 - Markup Language Reference, page 1970: + * + * There are a number of formatting codes that can be written inline with the actual header / footer text, which + * affect the formatting in the header or footer. + * + * Example: This example shows the text "Center Bold Header" on the first line (center section), and the date on + * the second line (center section). + * &CCenter &"-,Bold"Bold&"-,Regular"Header_x000A_&D + * + * General Rules: + * There is no required order in which these codes must appear. + * + * The first occurrence of the following codes turns the formatting ON, the second occurrence turns it OFF again: + * - strikethrough + * - superscript + * - subscript + * Superscript and subscript cannot both be ON at same time. Whichever comes first wins and the other is ignored, + * while the first is ON. + * &L - code for "left section" (there are three header / footer locations, "left", "center", and "right"). When + * two or more occurrences of this section marker exist, the contents from all markers are concatenated, in the + * order of appearance, and placed into the left section. + * &P - code for "current page #" + * &N - code for "total pages" + * &font size - code for "text font size", where font size is a font size in points. + * &K - code for "text font color" + * RGB Color is specified as RRGGBB + * Theme Color is specifed as TTSNN where TT is the theme color Id, S is either "+" or "-" of the tint/shade + * value, NN is the tint/shade value. + * &S - code for "text strikethrough" on / off + * &X - code for "text super script" on / off + * &Y - code for "text subscript" on / off + * &C - code for "center section". When two or more occurrences of this section marker exist, the contents + * from all markers are concatenated, in the order of appearance, and placed into the center section. + * + * &D - code for "date" + * &T - code for "time" + * &G - code for "picture as background" + * &U - code for "text single underline" + * &E - code for "double underline" + * &R - code for "right section". When two or more occurrences of this section marker exist, the contents + * from all markers are concatenated, in the order of appearance, and placed into the right section. + * &Z - code for "this workbook's file path" + * &F - code for "this workbook's file name" + * &A - code for "sheet tab name" + * &+ - code for add to page #. + * &- - code for subtract from page #. + * &"font name,font type" - code for "text font name" and "text font type", where font name and font type + * are strings specifying the name and type of the font, separated by a comma. When a hyphen appears in font + * name, it means "none specified". Both of font name and font type can be localized values. + * &"-,Bold" - code for "bold font style" + * &B - also means "bold font style". + * &"-,Regular" - code for "regular font style" + * &"-,Italic" - code for "italic font style" + * &I - also means "italic font style" + * &"-,Bold Italic" code for "bold italic font style" + * &O - code for "outline style" + * &H - code for "shadow style" + * + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_HeaderFooter +{ + /* Header/footer image location */ + const IMAGE_HEADER_LEFT = 'LH'; + const IMAGE_HEADER_CENTER = 'CH'; + const IMAGE_HEADER_RIGHT = 'RH'; + const IMAGE_FOOTER_LEFT = 'LF'; + const IMAGE_FOOTER_CENTER = 'CF'; + const IMAGE_FOOTER_RIGHT = 'RF'; + + /** + * OddHeader + * + * @var string + */ + private $_oddHeader = ''; + + /** + * OddFooter + * + * @var string + */ + private $_oddFooter = ''; + + /** + * EvenHeader + * + * @var string + */ + private $_evenHeader = ''; + + /** + * EvenFooter + * + * @var string + */ + private $_evenFooter = ''; + + /** + * FirstHeader + * + * @var string + */ + private $_firstHeader = ''; + + /** + * FirstFooter + * + * @var string + */ + private $_firstFooter = ''; + + /** + * Different header for Odd/Even, defaults to false + * + * @var boolean + */ + private $_differentOddEven = false; + + /** + * Different header for first page, defaults to false + * + * @var boolean + */ + private $_differentFirst = false; + + /** + * Scale with document, defaults to true + * + * @var boolean + */ + private $_scaleWithDocument = true; + + /** + * Align with margins, defaults to true + * + * @var boolean + */ + private $_alignWithMargins = true; + + /** + * Header/footer images + * + * @var PHPExcel_Worksheet_HeaderFooterDrawing[] + */ + private $_headerFooterImages = array(); + + /** + * Create a new PHPExcel_Worksheet_HeaderFooter + */ + public function __construct() + { + } + + /** + * Get OddHeader + * + * @return string + */ + public function getOddHeader() { + return $this->_oddHeader; + } + + /** + * Set OddHeader + * + * @param string $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setOddHeader($pValue) { + $this->_oddHeader = $pValue; + return $this; + } + + /** + * Get OddFooter + * + * @return string + */ + public function getOddFooter() { + return $this->_oddFooter; + } + + /** + * Set OddFooter + * + * @param string $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setOddFooter($pValue) { + $this->_oddFooter = $pValue; + return $this; + } + + /** + * Get EvenHeader + * + * @return string + */ + public function getEvenHeader() { + return $this->_evenHeader; + } + + /** + * Set EvenHeader + * + * @param string $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setEvenHeader($pValue) { + $this->_evenHeader = $pValue; + return $this; + } + + /** + * Get EvenFooter + * + * @return string + */ + public function getEvenFooter() { + return $this->_evenFooter; + } + + /** + * Set EvenFooter + * + * @param string $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setEvenFooter($pValue) { + $this->_evenFooter = $pValue; + return $this; + } + + /** + * Get FirstHeader + * + * @return string + */ + public function getFirstHeader() { + return $this->_firstHeader; + } + + /** + * Set FirstHeader + * + * @param string $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setFirstHeader($pValue) { + $this->_firstHeader = $pValue; + return $this; + } + + /** + * Get FirstFooter + * + * @return string + */ + public function getFirstFooter() { + return $this->_firstFooter; + } + + /** + * Set FirstFooter + * + * @param string $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setFirstFooter($pValue) { + $this->_firstFooter = $pValue; + return $this; + } + + /** + * Get DifferentOddEven + * + * @return boolean + */ + public function getDifferentOddEven() { + return $this->_differentOddEven; + } + + /** + * Set DifferentOddEven + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setDifferentOddEven($pValue = false) { + $this->_differentOddEven = $pValue; + return $this; + } + + /** + * Get DifferentFirst + * + * @return boolean + */ + public function getDifferentFirst() { + return $this->_differentFirst; + } + + /** + * Set DifferentFirst + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setDifferentFirst($pValue = false) { + $this->_differentFirst = $pValue; + return $this; + } + + /** + * Get ScaleWithDocument + * + * @return boolean + */ + public function getScaleWithDocument() { + return $this->_scaleWithDocument; + } + + /** + * Set ScaleWithDocument + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setScaleWithDocument($pValue = true) { + $this->_scaleWithDocument = $pValue; + return $this; + } + + /** + * Get AlignWithMargins + * + * @return boolean + */ + public function getAlignWithMargins() { + return $this->_alignWithMargins; + } + + /** + * Set AlignWithMargins + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setAlignWithMargins($pValue = true) { + $this->_alignWithMargins = $pValue; + return $this; + } + + /** + * Add header/footer image + * + * @param PHPExcel_Worksheet_HeaderFooterDrawing $image + * @param string $location + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function addImage(PHPExcel_Worksheet_HeaderFooterDrawing $image = null, $location = self::IMAGE_HEADER_LEFT) { + $this->_headerFooterImages[$location] = $image; + return $this; + } + + /** + * Remove header/footer image + * + * @param string $location + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function removeImage($location = self::IMAGE_HEADER_LEFT) { + if (isset($this->_headerFooterImages[$location])) { + unset($this->_headerFooterImages[$location]); + } + return $this; + } + + /** + * Set header/footer images + * + * @param PHPExcel_Worksheet_HeaderFooterDrawing[] $images + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setImages($images) { + if (!is_array($images)) { + throw new PHPExcel_Exception('Invalid parameter!'); + } + + $this->_headerFooterImages = $images; + return $this; + } + + /** + * Get header/footer images + * + * @return PHPExcel_Worksheet_HeaderFooterDrawing[] + */ + public function getImages() { + // Sort array + $images = array(); + if (isset($this->_headerFooterImages[self::IMAGE_HEADER_LEFT])) $images[self::IMAGE_HEADER_LEFT] = $this->_headerFooterImages[self::IMAGE_HEADER_LEFT]; + if (isset($this->_headerFooterImages[self::IMAGE_HEADER_CENTER])) $images[self::IMAGE_HEADER_CENTER] = $this->_headerFooterImages[self::IMAGE_HEADER_CENTER]; + if (isset($this->_headerFooterImages[self::IMAGE_HEADER_RIGHT])) $images[self::IMAGE_HEADER_RIGHT] = $this->_headerFooterImages[self::IMAGE_HEADER_RIGHT]; + if (isset($this->_headerFooterImages[self::IMAGE_FOOTER_LEFT])) $images[self::IMAGE_FOOTER_LEFT] = $this->_headerFooterImages[self::IMAGE_FOOTER_LEFT]; + if (isset($this->_headerFooterImages[self::IMAGE_FOOTER_CENTER])) $images[self::IMAGE_FOOTER_CENTER] = $this->_headerFooterImages[self::IMAGE_FOOTER_CENTER]; + if (isset($this->_headerFooterImages[self::IMAGE_FOOTER_RIGHT])) $images[self::IMAGE_FOOTER_RIGHT] = $this->_headerFooterImages[self::IMAGE_FOOTER_RIGHT]; + $this->_headerFooterImages = $images; + + return $this->_headerFooterImages; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/framework/library/phpexcel/PHPExcel/Worksheet/HeaderFooterDrawing.php b/framework/library/phpexcel/PHPExcel/Worksheet/HeaderFooterDrawing.php new file mode 100644 index 0000000..512887e --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Worksheet/HeaderFooterDrawing.php @@ -0,0 +1,350 @@ +_path = ''; + $this->_name = ''; + $this->_offsetX = 0; + $this->_offsetY = 0; + $this->_width = 0; + $this->_height = 0; + $this->_resizeProportional = true; + } + + /** + * Get Name + * + * @return string + */ + public function getName() { + return $this->_name; + } + + /** + * Set Name + * + * @param string $pValue + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setName($pValue = '') { + $this->_name = $pValue; + return $this; + } + + /** + * Get OffsetX + * + * @return int + */ + public function getOffsetX() { + return $this->_offsetX; + } + + /** + * Set OffsetX + * + * @param int $pValue + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setOffsetX($pValue = 0) { + $this->_offsetX = $pValue; + return $this; + } + + /** + * Get OffsetY + * + * @return int + */ + public function getOffsetY() { + return $this->_offsetY; + } + + /** + * Set OffsetY + * + * @param int $pValue + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setOffsetY($pValue = 0) { + $this->_offsetY = $pValue; + return $this; + } + + /** + * Get Width + * + * @return int + */ + public function getWidth() { + return $this->_width; + } + + /** + * Set Width + * + * @param int $pValue + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setWidth($pValue = 0) { + // Resize proportional? + if ($this->_resizeProportional && $pValue != 0) { + $ratio = $this->_width / $this->_height; + $this->_height = round($ratio * $pValue); + } + + // Set width + $this->_width = $pValue; + + return $this; + } + + /** + * Get Height + * + * @return int + */ + public function getHeight() { + return $this->_height; + } + + /** + * Set Height + * + * @param int $pValue + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setHeight($pValue = 0) { + // Resize proportional? + if ($this->_resizeProportional && $pValue != 0) { + $ratio = $this->_width / $this->_height; + $this->_width = round($ratio * $pValue); + } + + // Set height + $this->_height = $pValue; + + return $this; + } + + /** + * Set width and height with proportional resize + * Example: + * + * $objDrawing->setResizeProportional(true); + * $objDrawing->setWidthAndHeight(160,120); + * + * + * @author Vincent@luo MSN:kele_100@hotmail.com + * @param int $width + * @param int $height + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setWidthAndHeight($width = 0, $height = 0) { + $xratio = $width / $this->_width; + $yratio = $height / $this->_height; + if ($this->_resizeProportional && !($width == 0 || $height == 0)) { + if (($xratio * $this->_height) < $height) { + $this->_height = ceil($xratio * $this->_height); + $this->_width = $width; + } else { + $this->_width = ceil($yratio * $this->_width); + $this->_height = $height; + } + } + return $this; + } + + /** + * Get ResizeProportional + * + * @return boolean + */ + public function getResizeProportional() { + return $this->_resizeProportional; + } + + /** + * Set ResizeProportional + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setResizeProportional($pValue = true) { + $this->_resizeProportional = $pValue; + return $this; + } + + /** + * Get Filename + * + * @return string + */ + public function getFilename() { + return basename($this->_path); + } + + /** + * Get Extension + * + * @return string + */ + public function getExtension() { + $parts = explode(".", basename($this->_path)); + return end($parts); + } + + /** + * Get Path + * + * @return string + */ + public function getPath() { + return $this->_path; + } + + /** + * Set Path + * + * @param string $pValue File path + * @param boolean $pVerifyFile Verify file + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setPath($pValue = '', $pVerifyFile = true) { + if ($pVerifyFile) { + if (file_exists($pValue)) { + $this->_path = $pValue; + + if ($this->_width == 0 && $this->_height == 0) { + // Get width/height + list($this->_width, $this->_height) = getimagesize($pValue); + } + } else { + throw new PHPExcel_Exception("File $pValue not found!"); + } + } else { + $this->_path = $pValue; + } + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->_path + . $this->_name + . $this->_offsetX + . $this->_offsetY + . $this->_width + . $this->_height + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/framework/library/phpexcel/PHPExcel/Writer/Excel2007.php b/framework/library/phpexcel/PHPExcel/Writer/Excel2007.php new file mode 100644 index 0000000..47de168 --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/Excel2007.php @@ -0,0 +1,472 @@ +setPHPExcel($pPHPExcel); + + $writerPartsArray = array( 'stringtable' => 'PHPExcel_Writer_Excel2007_StringTable', + 'contenttypes' => 'PHPExcel_Writer_Excel2007_ContentTypes', + 'docprops' => 'PHPExcel_Writer_Excel2007_DocProps', + 'rels' => 'PHPExcel_Writer_Excel2007_Rels', + 'theme' => 'PHPExcel_Writer_Excel2007_Theme', + 'style' => 'PHPExcel_Writer_Excel2007_Style', + 'workbook' => 'PHPExcel_Writer_Excel2007_Workbook', + 'worksheet' => 'PHPExcel_Writer_Excel2007_Worksheet', + 'drawing' => 'PHPExcel_Writer_Excel2007_Drawing', + 'comments' => 'PHPExcel_Writer_Excel2007_Comments', + 'chart' => 'PHPExcel_Writer_Excel2007_Chart', + ); + + // Initialise writer parts + // and Assign their parent IWriters + foreach ($writerPartsArray as $writer => $class) { + $this->_writerParts[$writer] = new $class($this); + } + + $hashTablesArray = array( '_stylesConditionalHashTable', '_fillHashTable', '_fontHashTable', + '_bordersHashTable', '_numFmtHashTable', '_drawingHashTable' + ); + + // Set HashTable variables + foreach ($hashTablesArray as $tableName) { + $this->$tableName = new PHPExcel_HashTable(); + } + } + + /** + * Get writer part + * + * @param string $pPartName Writer part name + * @return PHPExcel_Writer_Excel2007_WriterPart + */ + public function getWriterPart($pPartName = '') { + if ($pPartName != '' && isset($this->_writerParts[strtolower($pPartName)])) { + return $this->_writerParts[strtolower($pPartName)]; + } else { + return null; + } + } + + /** + * Save PHPExcel to file + * + * @param string $pFilename + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = null) + { + if ($this->_spreadSheet !== NULL) { + // garbage collect + $this->_spreadSheet->garbageCollect(); + + // If $pFilename is php://output or php://stdout, make it a temporary file... + $originalFilename = $pFilename; + if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') { + $pFilename = @tempnam(PHPExcel_Shared_File::sys_get_temp_dir(), 'phpxltmp'); + if ($pFilename == '') { + $pFilename = $originalFilename; + } + } + + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->setWriteDebugLog(FALSE); + $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType(); + PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); + + // Create string lookup table + $this->_stringTable = array(); + for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) { + $this->_stringTable = $this->getWriterPart('StringTable')->createStringTable($this->_spreadSheet->getSheet($i), $this->_stringTable); + } + + // Create styles dictionaries + $this->_stylesConditionalHashTable->addFromSource( $this->getWriterPart('Style')->allConditionalStyles($this->_spreadSheet) ); + $this->_fillHashTable->addFromSource( $this->getWriterPart('Style')->allFills($this->_spreadSheet) ); + $this->_fontHashTable->addFromSource( $this->getWriterPart('Style')->allFonts($this->_spreadSheet) ); + $this->_bordersHashTable->addFromSource( $this->getWriterPart('Style')->allBorders($this->_spreadSheet) ); + $this->_numFmtHashTable->addFromSource( $this->getWriterPart('Style')->allNumberFormats($this->_spreadSheet) ); + + // Create drawing dictionary + $this->_drawingHashTable->addFromSource( $this->getWriterPart('Drawing')->allDrawings($this->_spreadSheet) ); + + // Create new ZIP file and open it for writing + $zipClass = PHPExcel_Settings::getZipClass(); + $objZip = new $zipClass(); + + // Retrieve OVERWRITE and CREATE constants from the instantiated zip class + // This method of accessing constant values from a dynamic class should work with all appropriate versions of PHP + $ro = new ReflectionObject($objZip); + $zipOverWrite = $ro->getConstant('OVERWRITE'); + $zipCreate = $ro->getConstant('CREATE'); + + if (file_exists($pFilename)) { + unlink($pFilename); + } + // Try opening the ZIP file + if ($objZip->open($pFilename, $zipOverWrite) !== true) { + if ($objZip->open($pFilename, $zipCreate) !== true) { + throw new PHPExcel_Writer_Exception("Could not open " . $pFilename . " for writing."); + } + } + + // Add [Content_Types].xml to ZIP file + $objZip->addFromString('[Content_Types].xml', $this->getWriterPart('ContentTypes')->writeContentTypes($this->_spreadSheet, $this->_includeCharts)); + + // Add relationships to ZIP file + $objZip->addFromString('_rels/.rels', $this->getWriterPart('Rels')->writeRelationships($this->_spreadSheet)); + $objZip->addFromString('xl/_rels/workbook.xml.rels', $this->getWriterPart('Rels')->writeWorkbookRelationships($this->_spreadSheet)); + + // Add document properties to ZIP file + $objZip->addFromString('docProps/app.xml', $this->getWriterPart('DocProps')->writeDocPropsApp($this->_spreadSheet)); + $objZip->addFromString('docProps/core.xml', $this->getWriterPart('DocProps')->writeDocPropsCore($this->_spreadSheet)); + $customPropertiesPart = $this->getWriterPart('DocProps')->writeDocPropsCustom($this->_spreadSheet); + if ($customPropertiesPart !== NULL) { + $objZip->addFromString('docProps/custom.xml', $customPropertiesPart); + } + + // Add theme to ZIP file + $objZip->addFromString('xl/theme/theme1.xml', $this->getWriterPart('Theme')->writeTheme($this->_spreadSheet)); + + // Add string table to ZIP file + $objZip->addFromString('xl/sharedStrings.xml', $this->getWriterPart('StringTable')->writeStringTable($this->_stringTable)); + + // Add styles to ZIP file + $objZip->addFromString('xl/styles.xml', $this->getWriterPart('Style')->writeStyles($this->_spreadSheet)); + + // Add workbook to ZIP file + $objZip->addFromString('xl/workbook.xml', $this->getWriterPart('Workbook')->writeWorkbook($this->_spreadSheet, $this->_preCalculateFormulas)); + + $chartCount = 0; + // Add worksheets + for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) { + $objZip->addFromString('xl/worksheets/sheet' . ($i + 1) . '.xml', $this->getWriterPart('Worksheet')->writeWorksheet($this->_spreadSheet->getSheet($i), $this->_stringTable, $this->_includeCharts)); + if ($this->_includeCharts) { + $charts = $this->_spreadSheet->getSheet($i)->getChartCollection(); + if (count($charts) > 0) { + foreach($charts as $chart) { + $objZip->addFromString('xl/charts/chart' . ($chartCount + 1) . '.xml', $this->getWriterPart('Chart')->writeChart($chart)); + $chartCount++; + } + } + } + } + + $chartRef1 = $chartRef2 = 0; + // Add worksheet relationships (drawings, ...) + for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) { + + // Add relationships + $objZip->addFromString('xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeWorksheetRelationships($this->_spreadSheet->getSheet($i), ($i + 1), $this->_includeCharts)); + + $drawings = $this->_spreadSheet->getSheet($i)->getDrawingCollection(); + $drawingCount = count($drawings); + if ($this->_includeCharts) { + $chartCount = $this->_spreadSheet->getSheet($i)->getChartCount(); + } + + // Add drawing and image relationship parts + if (($drawingCount > 0) || ($chartCount > 0)) { + // Drawing relationships + $objZip->addFromString('xl/drawings/_rels/drawing' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeDrawingRelationships($this->_spreadSheet->getSheet($i),$chartRef1, $this->_includeCharts)); + + // Drawings + $objZip->addFromString('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPart('Drawing')->writeDrawings($this->_spreadSheet->getSheet($i),$chartRef2,$this->_includeCharts)); + } + + // Add comment relationship parts + if (count($this->_spreadSheet->getSheet($i)->getComments()) > 0) { + // VML Comments + $objZip->addFromString('xl/drawings/vmlDrawing' . ($i + 1) . '.vml', $this->getWriterPart('Comments')->writeVMLComments($this->_spreadSheet->getSheet($i))); + + // Comments + $objZip->addFromString('xl/comments' . ($i + 1) . '.xml', $this->getWriterPart('Comments')->writeComments($this->_spreadSheet->getSheet($i))); + } + + // Add header/footer relationship parts + if (count($this->_spreadSheet->getSheet($i)->getHeaderFooter()->getImages()) > 0) { + // VML Drawings + $objZip->addFromString('xl/drawings/vmlDrawingHF' . ($i + 1) . '.vml', $this->getWriterPart('Drawing')->writeVMLHeaderFooterImages($this->_spreadSheet->getSheet($i))); + + // VML Drawing relationships + $objZip->addFromString('xl/drawings/_rels/vmlDrawingHF' . ($i + 1) . '.vml.rels', $this->getWriterPart('Rels')->writeHeaderFooterDrawingRelationships($this->_spreadSheet->getSheet($i))); + + // Media + foreach ($this->_spreadSheet->getSheet($i)->getHeaderFooter()->getImages() as $image) { + $objZip->addFromString('xl/media/' . $image->getIndexedFilename(), file_get_contents($image->getPath())); + } + } + } + + // Add media + for ($i = 0; $i < $this->getDrawingHashTable()->count(); ++$i) { + if ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_Drawing) { + $imageContents = null; + $imagePath = $this->getDrawingHashTable()->getByIndex($i)->getPath(); + if (strpos($imagePath, 'zip://') !== false) { + $imagePath = substr($imagePath, 6); + $imagePathSplitted = explode('#', $imagePath); + + $imageZip = new ZipArchive(); + $imageZip->open($imagePathSplitted[0]); + $imageContents = $imageZip->getFromName($imagePathSplitted[1]); + $imageZip->close(); + unset($imageZip); + } else { + $imageContents = file_get_contents($imagePath); + } + + $objZip->addFromString('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents); + } else if ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_MemoryDrawing) { + ob_start(); + call_user_func( + $this->getDrawingHashTable()->getByIndex($i)->getRenderingFunction(), + $this->getDrawingHashTable()->getByIndex($i)->getImageResource() + ); + $imageContents = ob_get_contents(); + ob_end_clean(); + + $objZip->addFromString('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents); + } + } + + PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType); + PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->setWriteDebugLog($saveDebugLog); + + // Close file + if ($objZip->close() === false) { + throw new PHPExcel_Writer_Exception("Could not close zip file $pFilename."); + } + + // If a temporary file was used, copy it to the correct file stream + if ($originalFilename != $pFilename) { + if (copy($pFilename, $originalFilename) === false) { + throw new PHPExcel_Writer_Exception("Could not copy temporary zip file $pFilename to $originalFilename."); + } + @unlink($pFilename); + } + } else { + throw new PHPExcel_Writer_Exception("PHPExcel object unassigned."); + } + } + + /** + * Get PHPExcel object + * + * @return PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function getPHPExcel() { + if ($this->_spreadSheet !== null) { + return $this->_spreadSheet; + } else { + throw new PHPExcel_Writer_Exception("No PHPExcel assigned."); + } + } + + /** + * Set PHPExcel object + * + * @param PHPExcel $pPHPExcel PHPExcel object + * @throws PHPExcel_Writer_Exception + * @return PHPExcel_Writer_Excel2007 + */ + public function setPHPExcel(PHPExcel $pPHPExcel = null) { + $this->_spreadSheet = $pPHPExcel; + return $this; + } + + /** + * Get string table + * + * @return string[] + */ + public function getStringTable() { + return $this->_stringTable; + } + + /** + * Get PHPExcel_Style_Conditional HashTable + * + * @return PHPExcel_HashTable + */ + public function getStylesConditionalHashTable() { + return $this->_stylesConditionalHashTable; + } + + /** + * Get PHPExcel_Style_Fill HashTable + * + * @return PHPExcel_HashTable + */ + public function getFillHashTable() { + return $this->_fillHashTable; + } + + /** + * Get PHPExcel_Style_Font HashTable + * + * @return PHPExcel_HashTable + */ + public function getFontHashTable() { + return $this->_fontHashTable; + } + + /** + * Get PHPExcel_Style_Borders HashTable + * + * @return PHPExcel_HashTable + */ + public function getBordersHashTable() { + return $this->_bordersHashTable; + } + + /** + * Get PHPExcel_Style_NumberFormat HashTable + * + * @return PHPExcel_HashTable + */ + public function getNumFmtHashTable() { + return $this->_numFmtHashTable; + } + + /** + * Get PHPExcel_Worksheet_BaseDrawing HashTable + * + * @return PHPExcel_HashTable + */ + public function getDrawingHashTable() { + return $this->_drawingHashTable; + } + + /** + * Get Office2003 compatibility + * + * @return boolean + */ + public function getOffice2003Compatibility() { + return $this->_office2003compatibility; + } + + /** + * Set Office2003 compatibility + * + * @param boolean $pValue Office2003 compatibility? + * @return PHPExcel_Writer_Excel2007 + */ + public function setOffice2003Compatibility($pValue = false) { + $this->_office2003compatibility = $pValue; + return $this; + } + +} diff --git a/framework/library/phpexcel/PHPExcel/Writer/Excel2007/DocProps.php b/framework/library/phpexcel/PHPExcel/Writer/Excel2007/DocProps.php new file mode 100644 index 0000000..37cd54b --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/Excel2007/DocProps.php @@ -0,0 +1,272 @@ +getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Properties + $objWriter->startElement('Properties'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties'); + $objWriter->writeAttribute('xmlns:vt', 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); + + // Application + $objWriter->writeElement('Application', 'Microsoft Excel'); + + // DocSecurity + $objWriter->writeElement('DocSecurity', '0'); + + // ScaleCrop + $objWriter->writeElement('ScaleCrop', 'false'); + + // HeadingPairs + $objWriter->startElement('HeadingPairs'); + + // Vector + $objWriter->startElement('vt:vector'); + $objWriter->writeAttribute('size', '2'); + $objWriter->writeAttribute('baseType', 'variant'); + + // Variant + $objWriter->startElement('vt:variant'); + $objWriter->writeElement('vt:lpstr', 'Worksheets'); + $objWriter->endElement(); + + // Variant + $objWriter->startElement('vt:variant'); + $objWriter->writeElement('vt:i4', $pPHPExcel->getSheetCount()); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // TitlesOfParts + $objWriter->startElement('TitlesOfParts'); + + // Vector + $objWriter->startElement('vt:vector'); + $objWriter->writeAttribute('size', $pPHPExcel->getSheetCount()); + $objWriter->writeAttribute('baseType', 'lpstr'); + + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + $objWriter->writeElement('vt:lpstr', $pPHPExcel->getSheet($i)->getTitle()); + } + + $objWriter->endElement(); + + $objWriter->endElement(); + + // Company + $objWriter->writeElement('Company', $pPHPExcel->getProperties()->getCompany()); + + // Company + $objWriter->writeElement('Manager', $pPHPExcel->getProperties()->getManager()); + + // LinksUpToDate + $objWriter->writeElement('LinksUpToDate', 'false'); + + // SharedDoc + $objWriter->writeElement('SharedDoc', 'false'); + + // HyperlinksChanged + $objWriter->writeElement('HyperlinksChanged', 'false'); + + // AppVersion + $objWriter->writeElement('AppVersion', '12.0000'); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write docProps/core.xml to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeDocPropsCore(PHPExcel $pPHPExcel = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // cp:coreProperties + $objWriter->startElement('cp:coreProperties'); + $objWriter->writeAttribute('xmlns:cp', 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties'); + $objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + $objWriter->writeAttribute('xmlns:dcterms', 'http://purl.org/dc/terms/'); + $objWriter->writeAttribute('xmlns:dcmitype', 'http://purl.org/dc/dcmitype/'); + $objWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); + + // dc:creator + $objWriter->writeElement('dc:creator', $pPHPExcel->getProperties()->getCreator()); + + // cp:lastModifiedBy + $objWriter->writeElement('cp:lastModifiedBy', $pPHPExcel->getProperties()->getLastModifiedBy()); + + // dcterms:created + $objWriter->startElement('dcterms:created'); + $objWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF'); + $objWriter->writeRawData(date(DATE_W3C, $pPHPExcel->getProperties()->getCreated())); + $objWriter->endElement(); + + // dcterms:modified + $objWriter->startElement('dcterms:modified'); + $objWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF'); + $objWriter->writeRawData(date(DATE_W3C, $pPHPExcel->getProperties()->getModified())); + $objWriter->endElement(); + + // dc:title + $objWriter->writeElement('dc:title', $pPHPExcel->getProperties()->getTitle()); + + // dc:description + $objWriter->writeElement('dc:description', $pPHPExcel->getProperties()->getDescription()); + + // dc:subject + $objWriter->writeElement('dc:subject', $pPHPExcel->getProperties()->getSubject()); + + // cp:keywords + $objWriter->writeElement('cp:keywords', $pPHPExcel->getProperties()->getKeywords()); + + // cp:category + $objWriter->writeElement('cp:category', $pPHPExcel->getProperties()->getCategory()); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write docProps/custom.xml to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeDocPropsCustom(PHPExcel $pPHPExcel = null) + { + $customPropertyList = $pPHPExcel->getProperties()->getCustomProperties(); + if (empty($customPropertyList)) { + return; + } + + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // cp:coreProperties + $objWriter->startElement('Properties'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/officeDocument/2006/custom-properties'); + $objWriter->writeAttribute('xmlns:vt', 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); + + + foreach($customPropertyList as $key => $customProperty) { + $propertyValue = $pPHPExcel->getProperties()->getCustomPropertyValue($customProperty); + $propertyType = $pPHPExcel->getProperties()->getCustomPropertyType($customProperty); + + $objWriter->startElement('property'); + $objWriter->writeAttribute('fmtid', '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}'); + $objWriter->writeAttribute('pid', $key+2); + $objWriter->writeAttribute('name', $customProperty); + + switch($propertyType) { + case 'i' : + $objWriter->writeElement('vt:i4', $propertyValue); + break; + case 'f' : + $objWriter->writeElement('vt:r8', $propertyValue); + break; + case 'b' : + $objWriter->writeElement('vt:bool', ($propertyValue) ? 'true' : 'false'); + break; + case 'd' : + $objWriter->startElement('vt:filetime'); + $objWriter->writeRawData(date(DATE_W3C, $propertyValue)); + $objWriter->endElement(); + break; + default : + $objWriter->writeElement('vt:lpwstr', $propertyValue); + break; + } + + $objWriter->endElement(); + } + + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + +} diff --git a/framework/library/phpexcel/PHPExcel/Writer/Excel2007/Drawing.php b/framework/library/phpexcel/PHPExcel/Writer/Excel2007/Drawing.php new file mode 100644 index 0000000..d410c5d --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/Excel2007/Drawing.php @@ -0,0 +1,598 @@ +getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // xdr:wsDr + $objWriter->startElement('xdr:wsDr'); + $objWriter->writeAttribute('xmlns:xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing'); + $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); + + // Loop through images and write drawings + $i = 1; + $iterator = $pWorksheet->getDrawingCollection()->getIterator(); + while ($iterator->valid()) { + $this->_writeDrawing($objWriter, $iterator->current(), $i); + + $iterator->next(); + ++$i; + } + + if ($includeCharts) { + $chartCount = $pWorksheet->getChartCount(); + // Loop through charts and write the chart position + if ($chartCount > 0) { + for ($c = 0; $c < $chartCount; ++$c) { + $this->_writeChart($objWriter, $pWorksheet->getChartByIndex($c), $c+$i); + } + } + } + + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write drawings to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Chart $pChart + * @param int $pRelationId + * @throws PHPExcel_Writer_Exception + */ + public function _writeChart(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Chart $pChart = null, $pRelationId = -1) + { + $tl = $pChart->getTopLeftPosition(); + $tl['colRow'] = PHPExcel_Cell::coordinateFromString($tl['cell']); + $br = $pChart->getBottomRightPosition(); + $br['colRow'] = PHPExcel_Cell::coordinateFromString($br['cell']); + + $objWriter->startElement('xdr:twoCellAnchor'); + + $objWriter->startElement('xdr:from'); + $objWriter->writeElement('xdr:col', PHPExcel_Cell::columnIndexFromString($tl['colRow'][0]) - 1); + $objWriter->writeElement('xdr:colOff', PHPExcel_Shared_Drawing::pixelsToEMU($tl['xOffset'])); + $objWriter->writeElement('xdr:row', $tl['colRow'][1] - 1); + $objWriter->writeElement('xdr:rowOff', PHPExcel_Shared_Drawing::pixelsToEMU($tl['yOffset'])); + $objWriter->endElement(); + $objWriter->startElement('xdr:to'); + $objWriter->writeElement('xdr:col', PHPExcel_Cell::columnIndexFromString($br['colRow'][0]) - 1); + $objWriter->writeElement('xdr:colOff', PHPExcel_Shared_Drawing::pixelsToEMU($br['xOffset'])); + $objWriter->writeElement('xdr:row', $br['colRow'][1] - 1); + $objWriter->writeElement('xdr:rowOff', PHPExcel_Shared_Drawing::pixelsToEMU($br['yOffset'])); + $objWriter->endElement(); + + $objWriter->startElement('xdr:graphicFrame'); + $objWriter->writeAttribute('macro', ''); + $objWriter->startElement('xdr:nvGraphicFramePr'); + $objWriter->startElement('xdr:cNvPr'); + $objWriter->writeAttribute('name', 'Chart '.$pRelationId); + $objWriter->writeAttribute('id', 1025 * $pRelationId); + $objWriter->endElement(); + $objWriter->startElement('xdr:cNvGraphicFramePr'); + $objWriter->startElement('a:graphicFrameLocks'); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('xdr:xfrm'); + $objWriter->startElement('a:off'); + $objWriter->writeAttribute('x', '0'); + $objWriter->writeAttribute('y', '0'); + $objWriter->endElement(); + $objWriter->startElement('a:ext'); + $objWriter->writeAttribute('cx', '0'); + $objWriter->writeAttribute('cy', '0'); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('a:graphic'); + $objWriter->startElement('a:graphicData'); + $objWriter->writeAttribute('uri', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); + $objWriter->startElement('c:chart'); + $objWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); + $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + $objWriter->writeAttribute('r:id', 'rId'.$pRelationId); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('xdr:clientData'); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + /** + * Write drawings to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet_BaseDrawing $pDrawing + * @param int $pRelationId + * @throws PHPExcel_Writer_Exception + */ + public function _writeDrawing(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet_BaseDrawing $pDrawing = null, $pRelationId = -1) + { + if ($pRelationId >= 0) { + // xdr:oneCellAnchor + $objWriter->startElement('xdr:oneCellAnchor'); + // Image location + $aCoordinates = PHPExcel_Cell::coordinateFromString($pDrawing->getCoordinates()); + $aCoordinates[0] = PHPExcel_Cell::columnIndexFromString($aCoordinates[0]); + + // xdr:from + $objWriter->startElement('xdr:from'); + $objWriter->writeElement('xdr:col', $aCoordinates[0] - 1); + $objWriter->writeElement('xdr:colOff', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getOffsetX())); + $objWriter->writeElement('xdr:row', $aCoordinates[1] - 1); + $objWriter->writeElement('xdr:rowOff', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getOffsetY())); + $objWriter->endElement(); + + // xdr:ext + $objWriter->startElement('xdr:ext'); + $objWriter->writeAttribute('cx', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getWidth())); + $objWriter->writeAttribute('cy', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getHeight())); + $objWriter->endElement(); + + // xdr:pic + $objWriter->startElement('xdr:pic'); + + // xdr:nvPicPr + $objWriter->startElement('xdr:nvPicPr'); + + // xdr:cNvPr + $objWriter->startElement('xdr:cNvPr'); + $objWriter->writeAttribute('id', $pRelationId); + $objWriter->writeAttribute('name', $pDrawing->getName()); + $objWriter->writeAttribute('descr', $pDrawing->getDescription()); + $objWriter->endElement(); + + // xdr:cNvPicPr + $objWriter->startElement('xdr:cNvPicPr'); + + // a:picLocks + $objWriter->startElement('a:picLocks'); + $objWriter->writeAttribute('noChangeAspect', '1'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // xdr:blipFill + $objWriter->startElement('xdr:blipFill'); + + // a:blip + $objWriter->startElement('a:blip'); + $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + $objWriter->writeAttribute('r:embed', 'rId' . $pRelationId); + $objWriter->endElement(); + + // a:stretch + $objWriter->startElement('a:stretch'); + $objWriter->writeElement('a:fillRect', null); + $objWriter->endElement(); + + $objWriter->endElement(); + + // xdr:spPr + $objWriter->startElement('xdr:spPr'); + + // a:xfrm + $objWriter->startElement('a:xfrm'); + $objWriter->writeAttribute('rot', PHPExcel_Shared_Drawing::degreesToAngle($pDrawing->getRotation())); + $objWriter->endElement(); + + // a:prstGeom + $objWriter->startElement('a:prstGeom'); + $objWriter->writeAttribute('prst', 'rect'); + + // a:avLst + $objWriter->writeElement('a:avLst', null); + + $objWriter->endElement(); + +// // a:solidFill +// $objWriter->startElement('a:solidFill'); + +// // a:srgbClr +// $objWriter->startElement('a:srgbClr'); +// $objWriter->writeAttribute('val', 'FFFFFF'); + +///* SHADE +// // a:shade +// $objWriter->startElement('a:shade'); +// $objWriter->writeAttribute('val', '85000'); +// $objWriter->endElement(); +//*/ + +// $objWriter->endElement(); + +// $objWriter->endElement(); +/* + // a:ln + $objWriter->startElement('a:ln'); + $objWriter->writeAttribute('w', '88900'); + $objWriter->writeAttribute('cap', 'sq'); + + // a:solidFill + $objWriter->startElement('a:solidFill'); + + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', 'FFFFFF'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:miter + $objWriter->startElement('a:miter'); + $objWriter->writeAttribute('lim', '800000'); + $objWriter->endElement(); + + $objWriter->endElement(); +*/ + + if ($pDrawing->getShadow()->getVisible()) { + // a:effectLst + $objWriter->startElement('a:effectLst'); + + // a:outerShdw + $objWriter->startElement('a:outerShdw'); + $objWriter->writeAttribute('blurRad', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getShadow()->getBlurRadius())); + $objWriter->writeAttribute('dist', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getShadow()->getDistance())); + $objWriter->writeAttribute('dir', PHPExcel_Shared_Drawing::degreesToAngle($pDrawing->getShadow()->getDirection())); + $objWriter->writeAttribute('algn', $pDrawing->getShadow()->getAlignment()); + $objWriter->writeAttribute('rotWithShape', '0'); + + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', $pDrawing->getShadow()->getColor()->getRGB()); + + // a:alpha + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', $pDrawing->getShadow()->getAlpha() * 1000); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + } +/* + + // a:scene3d + $objWriter->startElement('a:scene3d'); + + // a:camera + $objWriter->startElement('a:camera'); + $objWriter->writeAttribute('prst', 'orthographicFront'); + $objWriter->endElement(); + + // a:lightRig + $objWriter->startElement('a:lightRig'); + $objWriter->writeAttribute('rig', 'twoPt'); + $objWriter->writeAttribute('dir', 't'); + + // a:rot + $objWriter->startElement('a:rot'); + $objWriter->writeAttribute('lat', '0'); + $objWriter->writeAttribute('lon', '0'); + $objWriter->writeAttribute('rev', '0'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); +*/ +/* + // a:sp3d + $objWriter->startElement('a:sp3d'); + + // a:bevelT + $objWriter->startElement('a:bevelT'); + $objWriter->writeAttribute('w', '25400'); + $objWriter->writeAttribute('h', '19050'); + $objWriter->endElement(); + + // a:contourClr + $objWriter->startElement('a:contourClr'); + + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', 'FFFFFF'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); +*/ + $objWriter->endElement(); + + $objWriter->endElement(); + + // xdr:clientData + $objWriter->writeElement('xdr:clientData', null); + + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } + + /** + * Write VML header/footer images to XML format + * + * @param PHPExcel_Worksheet $pWorksheet + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeVMLHeaderFooterImages(PHPExcel_Worksheet $pWorksheet = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Header/footer images + $images = $pWorksheet->getHeaderFooter()->getImages(); + + // xml + $objWriter->startElement('xml'); + $objWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml'); + $objWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office'); + $objWriter->writeAttribute('xmlns:x', 'urn:schemas-microsoft-com:office:excel'); + + // o:shapelayout + $objWriter->startElement('o:shapelayout'); + $objWriter->writeAttribute('v:ext', 'edit'); + + // o:idmap + $objWriter->startElement('o:idmap'); + $objWriter->writeAttribute('v:ext', 'edit'); + $objWriter->writeAttribute('data', '1'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // v:shapetype + $objWriter->startElement('v:shapetype'); + $objWriter->writeAttribute('id', '_x0000_t75'); + $objWriter->writeAttribute('coordsize', '21600,21600'); + $objWriter->writeAttribute('o:spt', '75'); + $objWriter->writeAttribute('o:preferrelative', 't'); + $objWriter->writeAttribute('path', 'm@4@5l@4@11@9@11@9@5xe'); + $objWriter->writeAttribute('filled', 'f'); + $objWriter->writeAttribute('stroked', 'f'); + + // v:stroke + $objWriter->startElement('v:stroke'); + $objWriter->writeAttribute('joinstyle', 'miter'); + $objWriter->endElement(); + + // v:formulas + $objWriter->startElement('v:formulas'); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'if lineDrawn pixelLineWidth 0'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum @0 1 0'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum 0 0 @1'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @2 1 2'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelWidth'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelHeight'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum @0 0 1'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @6 1 2'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelWidth'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum @8 21600 0'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelHeight'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum @10 21600 0'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // v:path + $objWriter->startElement('v:path'); + $objWriter->writeAttribute('o:extrusionok', 'f'); + $objWriter->writeAttribute('gradientshapeok', 't'); + $objWriter->writeAttribute('o:connecttype', 'rect'); + $objWriter->endElement(); + + // o:lock + $objWriter->startElement('o:lock'); + $objWriter->writeAttribute('v:ext', 'edit'); + $objWriter->writeAttribute('aspectratio', 't'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // Loop through images + foreach ($images as $key => $value) { + $this->_writeVMLHeaderFooterImage($objWriter, $key, $value); + } + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write VML comment to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pReference Reference + * @param PHPExcel_Worksheet_HeaderFooterDrawing $pImage Image + * @throws PHPExcel_Writer_Exception + */ + public function _writeVMLHeaderFooterImage(PHPExcel_Shared_XMLWriter $objWriter = null, $pReference = '', PHPExcel_Worksheet_HeaderFooterDrawing $pImage = null) + { + // Calculate object id + preg_match('{(\d+)}', md5($pReference), $m); + $id = 1500 + (substr($m[1], 0, 2) * 1); + + // Calculate offset + $width = $pImage->getWidth(); + $height = $pImage->getHeight(); + $marginLeft = $pImage->getOffsetX(); + $marginTop = $pImage->getOffsetY(); + + // v:shape + $objWriter->startElement('v:shape'); + $objWriter->writeAttribute('id', $pReference); + $objWriter->writeAttribute('o:spid', '_x0000_s' . $id); + $objWriter->writeAttribute('type', '#_x0000_t75'); + $objWriter->writeAttribute('style', "position:absolute;margin-left:{$marginLeft}px;margin-top:{$marginTop}px;width:{$width}px;height:{$height}px;z-index:1"); + + // v:imagedata + $objWriter->startElement('v:imagedata'); + $objWriter->writeAttribute('o:relid', 'rId' . $pReference); + $objWriter->writeAttribute('o:title', $pImage->getName()); + $objWriter->endElement(); + + // o:lock + $objWriter->startElement('o:lock'); + $objWriter->writeAttribute('v:ext', 'edit'); + $objWriter->writeAttribute('rotation', 't'); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + + /** + * Get an array of all drawings + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Worksheet_Drawing[] All drawings in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allDrawings(PHPExcel $pPHPExcel = null) + { + // Get an array of all drawings + $aDrawings = array(); + + // Loop through PHPExcel + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + // Loop through images and add to array + $iterator = $pPHPExcel->getSheet($i)->getDrawingCollection()->getIterator(); + while ($iterator->valid()) { + $aDrawings[] = $iterator->current(); + + $iterator->next(); + } + } + + return $aDrawings; + } +} diff --git a/framework/library/phpexcel/PHPExcel/Writer/Excel5.php b/framework/library/phpexcel/PHPExcel/Writer/Excel5.php new file mode 100644 index 0000000..26a52ae --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/Excel5.php @@ -0,0 +1,935 @@ +_phpExcel = $phpExcel; + + $this->_parser = new PHPExcel_Writer_Excel5_Parser(); + } + + /** + * Save PHPExcel to file + * + * @param string $pFilename + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = null) { + + // garbage collect + $this->_phpExcel->garbageCollect(); + + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE); + $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType(); + PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); + + // initialize colors array + $this->_colors = array(); + + // Initialise workbook writer + $this->_writerWorkbook = new PHPExcel_Writer_Excel5_Workbook($this->_phpExcel, + $this->_str_total, $this->_str_unique, $this->_str_table, + $this->_colors, $this->_parser); + + // Initialise worksheet writers + $countSheets = $this->_phpExcel->getSheetCount(); + for ($i = 0; $i < $countSheets; ++$i) { + $this->_writerWorksheets[$i] = new PHPExcel_Writer_Excel5_Worksheet($this->_str_total, $this->_str_unique, + $this->_str_table, $this->_colors, + $this->_parser, + $this->_preCalculateFormulas, + $this->_phpExcel->getSheet($i)); + } + + // build Escher objects. Escher objects for workbooks needs to be build before Escher object for workbook. + $this->_buildWorksheetEschers(); + $this->_buildWorkbookEscher(); + + // add 15 identical cell style Xfs + // for now, we use the first cellXf instead of cellStyleXf + $cellXfCollection = $this->_phpExcel->getCellXfCollection(); + for ($i = 0; $i < 15; ++$i) { + $this->_writerWorkbook->addXfWriter($cellXfCollection[0], true); + } + + // add all the cell Xfs + foreach ($this->_phpExcel->getCellXfCollection() as $style) { + $this->_writerWorkbook->addXfWriter($style, false); + } + + // add font from rich text eleemnts + for ($i = 0; $i < $countSheets; ++$i) { + foreach ($this->_writerWorksheets[$i]->_phpSheet->getCellCollection() as $cellID) { + $cell = $this->_writerWorksheets[$i]->_phpSheet->getCell($cellID); + $cVal = $cell->getValue(); + if ($cVal instanceof PHPExcel_RichText) { + $elements = $cVal->getRichTextElements(); + foreach ($elements as $element) { + if ($element instanceof PHPExcel_RichText_Run) { + $font = $element->getFont(); + $this->_writerWorksheets[$i]->_fntHashIndex[$font->getHashCode()] = $this->_writerWorkbook->_addFont($font); + } + } + } + } + } + + // initialize OLE file + $workbookStreamName = 'Workbook'; + $OLE = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs($workbookStreamName)); + + // Write the worksheet streams before the global workbook stream, + // because the byte sizes of these are needed in the global workbook stream + $worksheetSizes = array(); + for ($i = 0; $i < $countSheets; ++$i) { + $this->_writerWorksheets[$i]->close(); + $worksheetSizes[] = $this->_writerWorksheets[$i]->_datasize; + } + + // add binary data for global workbook stream + $OLE->append($this->_writerWorkbook->writeWorkbook($worksheetSizes)); + + // add binary data for sheet streams + for ($i = 0; $i < $countSheets; ++$i) { + $OLE->append($this->_writerWorksheets[$i]->getData()); + } + + $this->_documentSummaryInformation = $this->_writeDocumentSummaryInformation(); + // initialize OLE Document Summary Information + if(isset($this->_documentSummaryInformation) && !empty($this->_documentSummaryInformation)){ + $OLE_DocumentSummaryInformation = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs(chr(5) . 'DocumentSummaryInformation')); + $OLE_DocumentSummaryInformation->append($this->_documentSummaryInformation); + } + + $this->_summaryInformation = $this->_writeSummaryInformation(); + // initialize OLE Summary Information + if(isset($this->_summaryInformation) && !empty($this->_summaryInformation)){ + $OLE_SummaryInformation = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs(chr(5) . 'SummaryInformation')); + $OLE_SummaryInformation->append($this->_summaryInformation); + } + + // define OLE Parts + $arrRootData = array($OLE); + // initialize OLE Properties file + if(isset($OLE_SummaryInformation)){ + $arrRootData[] = $OLE_SummaryInformation; + } + // initialize OLE Extended Properties file + if(isset($OLE_DocumentSummaryInformation)){ + $arrRootData[] = $OLE_DocumentSummaryInformation; + } + + $root = new PHPExcel_Shared_OLE_PPS_Root(time(), time(), $arrRootData); + // save the OLE file + $res = $root->save($pFilename); + + PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); + } + + /** + * Set temporary storage directory + * + * @deprecated + * @param string $pValue Temporary storage directory + * @throws PHPExcel_Writer_Exception when directory does not exist + * @return PHPExcel_Writer_Excel5 + */ + public function setTempDir($pValue = '') { + return $this; + } + + /** + * Build the Worksheet Escher objects + * + */ + private function _buildWorksheetEschers() + { + // 1-based index to BstoreContainer + $blipIndex = 0; + $lastReducedSpId = 0; + $lastSpId = 0; + + foreach ($this->_phpExcel->getAllsheets() as $sheet) { + // sheet index + $sheetIndex = $sheet->getParent()->getIndex($sheet); + + $escher = null; + + // check if there are any shapes for this sheet + $filterRange = $sheet->getAutoFilter()->getRange(); + if (count($sheet->getDrawingCollection()) == 0 && empty($filterRange)) { + continue; + } + + // create intermediate Escher object + $escher = new PHPExcel_Shared_Escher(); + + // dgContainer + $dgContainer = new PHPExcel_Shared_Escher_DgContainer(); + + // set the drawing index (we use sheet index + 1) + $dgId = $sheet->getParent()->getIndex($sheet) + 1; + $dgContainer->setDgId($dgId); + $escher->setDgContainer($dgContainer); + + // spgrContainer + $spgrContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer(); + $dgContainer->setSpgrContainer($spgrContainer); + + // add one shape which is the group shape + $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); + $spContainer->setSpgr(true); + $spContainer->setSpType(0); + $spContainer->setSpId(($sheet->getParent()->getIndex($sheet) + 1) << 10); + $spgrContainer->addChild($spContainer); + + // add the shapes + + $countShapes[$sheetIndex] = 0; // count number of shapes (minus group shape), in sheet + + foreach ($sheet->getDrawingCollection() as $drawing) { + ++$blipIndex; + + ++$countShapes[$sheetIndex]; + + // add the shape + $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); + + // set the shape type + $spContainer->setSpType(0x004B); + // set the shape flag + $spContainer->setSpFlag(0x02); + + // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index) + $reducedSpId = $countShapes[$sheetIndex]; + $spId = $reducedSpId + | ($sheet->getParent()->getIndex($sheet) + 1) << 10; + $spContainer->setSpId($spId); + + // keep track of last reducedSpId + $lastReducedSpId = $reducedSpId; + + // keep track of last spId + $lastSpId = $spId; + + // set the BLIP index + $spContainer->setOPT(0x4104, $blipIndex); + + // set coordinates and offsets, client anchor + $coordinates = $drawing->getCoordinates(); + $offsetX = $drawing->getOffsetX(); + $offsetY = $drawing->getOffsetY(); + $width = $drawing->getWidth(); + $height = $drawing->getHeight(); + + $twoAnchor = PHPExcel_Shared_Excel5::oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height); + + $spContainer->setStartCoordinates($twoAnchor['startCoordinates']); + $spContainer->setStartOffsetX($twoAnchor['startOffsetX']); + $spContainer->setStartOffsetY($twoAnchor['startOffsetY']); + $spContainer->setEndCoordinates($twoAnchor['endCoordinates']); + $spContainer->setEndOffsetX($twoAnchor['endOffsetX']); + $spContainer->setEndOffsetY($twoAnchor['endOffsetY']); + + $spgrContainer->addChild($spContainer); + } + + // AutoFilters + if(!empty($filterRange)){ + $rangeBounds = PHPExcel_Cell::rangeBoundaries($filterRange); + $iNumColStart = $rangeBounds[0][0]; + $iNumColEnd = $rangeBounds[1][0]; + + $iInc = $iNumColStart; + while($iInc <= $iNumColEnd){ + ++$countShapes[$sheetIndex]; + + // create an Drawing Object for the dropdown + $oDrawing = new PHPExcel_Worksheet_BaseDrawing(); + // get the coordinates of drawing + $cDrawing = PHPExcel_Cell::stringFromColumnIndex($iInc - 1) . $rangeBounds[0][1]; + $oDrawing->setCoordinates($cDrawing); + $oDrawing->setWorksheet($sheet); + + // add the shape + $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); + // set the shape type + $spContainer->setSpType(0x00C9); + // set the shape flag + $spContainer->setSpFlag(0x01); + + // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index) + $reducedSpId = $countShapes[$sheetIndex]; + $spId = $reducedSpId + | ($sheet->getParent()->getIndex($sheet) + 1) << 10; + $spContainer->setSpId($spId); + + // keep track of last reducedSpId + $lastReducedSpId = $reducedSpId; + + // keep track of last spId + $lastSpId = $spId; + + $spContainer->setOPT(0x007F, 0x01040104); // Protection -> fLockAgainstGrouping + $spContainer->setOPT(0x00BF, 0x00080008); // Text -> fFitTextToShape + $spContainer->setOPT(0x01BF, 0x00010000); // Fill Style -> fNoFillHitTest + $spContainer->setOPT(0x01FF, 0x00080000); // Line Style -> fNoLineDrawDash + $spContainer->setOPT(0x03BF, 0x000A0000); // Group Shape -> fPrint + + // set coordinates and offsets, client anchor + $endCoordinates = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::stringFromColumnIndex($iInc - 1)); + $endCoordinates .= $rangeBounds[0][1] + 1; + + $spContainer->setStartCoordinates($cDrawing); + $spContainer->setStartOffsetX(0); + $spContainer->setStartOffsetY(0); + $spContainer->setEndCoordinates($endCoordinates); + $spContainer->setEndOffsetX(0); + $spContainer->setEndOffsetY(0); + + $spgrContainer->addChild($spContainer); + $iInc++; + } + } + + // identifier clusters, used for workbook Escher object + $this->_IDCLs[$dgId] = $lastReducedSpId; + + // set last shape index + $dgContainer->setLastSpId($lastSpId); + + // set the Escher object + $this->_writerWorksheets[$sheetIndex]->setEscher($escher); + } + } + + /** + * Build the Escher object corresponding to the MSODRAWINGGROUP record + */ + private function _buildWorkbookEscher() + { + $escher = null; + + // any drawings in this workbook? + $found = false; + foreach ($this->_phpExcel->getAllSheets() as $sheet) { + if (count($sheet->getDrawingCollection()) > 0) { + $found = true; + break; + } + } + + // nothing to do if there are no drawings + if (!$found) { + return; + } + + // if we reach here, then there are drawings in the workbook + $escher = new PHPExcel_Shared_Escher(); + + // dggContainer + $dggContainer = new PHPExcel_Shared_Escher_DggContainer(); + $escher->setDggContainer($dggContainer); + + // set IDCLs (identifier clusters) + $dggContainer->setIDCLs($this->_IDCLs); + + // this loop is for determining maximum shape identifier of all drawing + $spIdMax = 0; + $totalCountShapes = 0; + $countDrawings = 0; + + foreach ($this->_phpExcel->getAllsheets() as $sheet) { + $sheetCountShapes = 0; // count number of shapes (minus group shape), in sheet + + if (count($sheet->getDrawingCollection()) > 0) { + ++$countDrawings; + + foreach ($sheet->getDrawingCollection() as $drawing) { + ++$sheetCountShapes; + ++$totalCountShapes; + + $spId = $sheetCountShapes + | ($this->_phpExcel->getIndex($sheet) + 1) << 10; + $spIdMax = max($spId, $spIdMax); + } + } + } + + $dggContainer->setSpIdMax($spIdMax + 1); + $dggContainer->setCDgSaved($countDrawings); + $dggContainer->setCSpSaved($totalCountShapes + $countDrawings); // total number of shapes incl. one group shapes per drawing + + // bstoreContainer + $bstoreContainer = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer(); + $dggContainer->setBstoreContainer($bstoreContainer); + + // the BSE's (all the images) + foreach ($this->_phpExcel->getAllsheets() as $sheet) { + foreach ($sheet->getDrawingCollection() as $drawing) { + if ($drawing instanceof PHPExcel_Worksheet_Drawing) { + + $filename = $drawing->getPath(); + + list($imagesx, $imagesy, $imageFormat) = getimagesize($filename); + + switch ($imageFormat) { + + case 1: // GIF, not supported by BIFF8, we convert to PNG + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; + ob_start(); + imagepng(imagecreatefromgif($filename)); + $blipData = ob_get_contents(); + ob_end_clean(); + break; + + case 2: // JPEG + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG; + $blipData = file_get_contents($filename); + break; + + case 3: // PNG + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; + $blipData = file_get_contents($filename); + break; + + case 6: // Windows DIB (BMP), we convert to PNG + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; + ob_start(); + imagepng(PHPExcel_Shared_Drawing::imagecreatefrombmp($filename)); + $blipData = ob_get_contents(); + ob_end_clean(); + break; + + default: continue 2; + + } + + $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); + $blip->setData($blipData); + + $BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE(); + $BSE->setBlipType($blipType); + $BSE->setBlip($blip); + + $bstoreContainer->addBSE($BSE); + + } else if ($drawing instanceof PHPExcel_Worksheet_MemoryDrawing) { + + switch ($drawing->getRenderingFunction()) { + + case PHPExcel_Worksheet_MemoryDrawing::RENDERING_JPEG: + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG; + $renderingFunction = 'imagejpeg'; + break; + + case PHPExcel_Worksheet_MemoryDrawing::RENDERING_GIF: + case PHPExcel_Worksheet_MemoryDrawing::RENDERING_PNG: + case PHPExcel_Worksheet_MemoryDrawing::RENDERING_DEFAULT: + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; + $renderingFunction = 'imagepng'; + break; + + } + + ob_start(); + call_user_func($renderingFunction, $drawing->getImageResource()); + $blipData = ob_get_contents(); + ob_end_clean(); + + $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); + $blip->setData($blipData); + + $BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE(); + $BSE->setBlipType($blipType); + $BSE->setBlip($blip); + + $bstoreContainer->addBSE($BSE); + } + } + } + + // Set the Escher object + $this->_writerWorkbook->setEscher($escher); + } + + /** + * Build the OLE Part for DocumentSummary Information + * @return string + */ + private function _writeDocumentSummaryInformation(){ + + // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) + $data = pack('v', 0xFFFE); + // offset: 2; size: 2; + $data .= pack('v', 0x0000); + // offset: 4; size: 2; OS version + $data .= pack('v', 0x0106); + // offset: 6; size: 2; OS indicator + $data .= pack('v', 0x0002); + // offset: 8; size: 16 + $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00); + // offset: 24; size: 4; section count + $data .= pack('V', 0x0001); + + // offset: 28; size: 16; first section's class id: 02 d5 cd d5 9c 2e 1b 10 93 97 08 00 2b 2c f9 ae + $data .= pack('vvvvvvvv', 0xD502, 0xD5CD, 0x2E9C, 0x101B, 0x9793, 0x0008, 0x2C2B, 0xAEF9); + // offset: 44; size: 4; offset of the start + $data .= pack('V', 0x30); + + // SECTION + $dataSection = array(); + $dataSection_NumProps = 0; + $dataSection_Summary = ''; + $dataSection_Content = ''; + + // GKPIDDSI_CODEPAGE: CodePage + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x01), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x02), // 2 byte signed integer + 'data' => array('data' => 1252)); + $dataSection_NumProps++; + + // GKPIDDSI_CATEGORY : Category + if($this->_phpExcel->getProperties()->getCategory()){ + $dataProp = $this->_phpExcel->getProperties()->getCategory(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x02), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // GKPIDDSI_VERSION :Version of the application that wrote the property storage + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x17), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x03), + 'data' => array('pack' => 'V', 'data' => 0x000C0000)); + $dataSection_NumProps++; + // GKPIDDSI_SCALE : FALSE + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0B), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x0B), + 'data' => array('data' => false)); + $dataSection_NumProps++; + // GKPIDDSI_LINKSDIRTY : True if any of the values for the linked properties have changed outside of the application + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x10), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x0B), + 'data' => array('data' => false)); + $dataSection_NumProps++; + // GKPIDDSI_SHAREDOC : FALSE + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x13), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x0B), + 'data' => array('data' => false)); + $dataSection_NumProps++; + // GKPIDDSI_HYPERLINKSCHANGED : True if any of the values for the _PID_LINKS (hyperlink text) have changed outside of the application + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x16), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x0B), + 'data' => array('data' => false)); + $dataSection_NumProps++; + + // GKPIDDSI_DOCSPARTS + // MS-OSHARED p75 (2.3.3.2.2.1) + // Structure is VtVecUnalignedLpstrValue (2.3.3.1.9) + // cElements + $dataProp = pack('v', 0x0001); + $dataProp .= pack('v', 0x0000); + // array of UnalignedLpstr + // cch + $dataProp .= pack('v', 0x000A); + $dataProp .= pack('v', 0x0000); + // value + $dataProp .= 'Worksheet'.chr(0); + + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0D), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x101E), + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + + // GKPIDDSI_HEADINGPAIR + // VtVecHeadingPairValue + // cElements + $dataProp = pack('v', 0x0002); + $dataProp .= pack('v', 0x0000); + // Array of vtHeadingPair + // vtUnalignedString - headingString + // stringType + $dataProp .= pack('v', 0x001E); + // padding + $dataProp .= pack('v', 0x0000); + // UnalignedLpstr + // cch + $dataProp .= pack('v', 0x0013); + $dataProp .= pack('v', 0x0000); + // value + $dataProp .= 'Feuilles de calcul'; + // vtUnalignedString - headingParts + // wType : 0x0003 = 32 bit signed integer + $dataProp .= pack('v', 0x0300); + // padding + $dataProp .= pack('v', 0x0000); + // value + $dataProp .= pack('v', 0x0100); + $dataProp .= pack('v', 0x0000); + $dataProp .= pack('v', 0x0000); + $dataProp .= pack('v', 0x0000); + + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0C), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x100C), + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + + // 4 Section Length + // 4 Property count + // 8 * $dataSection_NumProps (8 = ID (4) + OffSet(4)) + $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8; + foreach ($dataSection as $dataProp){ + // Summary + $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']); + // Offset + $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset); + // DataType + $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']); + // Data + if($dataProp['type']['data'] == 0x02){ // 2 byte signed integer + $dataSection_Content .= pack('V', $dataProp['data']['data']); + + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x03){ // 4 byte signed integer + $dataSection_Content .= pack('V', $dataProp['data']['data']); + + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x0B){ // Boolean + if($dataProp['data']['data'] == false){ + $dataSection_Content .= pack('V', 0x0000); + } else { + $dataSection_Content .= pack('V', 0x0001); + } + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x1E){ // null-terminated string prepended by dword string length + // Null-terminated string + $dataProp['data']['data'] .= chr(0); + $dataProp['data']['length'] += 1; + // Complete the string with null string for being a %4 + $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4)==4 ? 0 : (4 - $dataProp['data']['length'] % 4)); + $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT); + + $dataSection_Content .= pack('V', $dataProp['data']['length']); + $dataSection_Content .= $dataProp['data']['data']; + + $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']); + } + elseif($dataProp['type']['data'] == 0x40){ // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + $dataSection_Content .= $dataProp['data']['data']; + + $dataSection_Content_Offset += 4 + 8; + } + else { + // Data Type Not Used at the moment + $dataSection_Content .= $dataProp['data']['data']; + + $dataSection_Content_Offset += 4 + $dataProp['data']['length']; + } + } + // Now $dataSection_Content_Offset contains the size of the content + + // section header + // offset: $secOffset; size: 4; section length + // + x Size of the content (summary + content) + $data .= pack('V', $dataSection_Content_Offset); + // offset: $secOffset+4; size: 4; property count + $data .= pack('V', $dataSection_NumProps); + // Section Summary + $data .= $dataSection_Summary; + // Section Content + $data .= $dataSection_Content; + + return $data; + } + + /** + * Build the OLE Part for Summary Information + * @return string + */ + private function _writeSummaryInformation(){ + // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) + $data = pack('v', 0xFFFE); + // offset: 2; size: 2; + $data .= pack('v', 0x0000); + // offset: 4; size: 2; OS version + $data .= pack('v', 0x0106); + // offset: 6; size: 2; OS indicator + $data .= pack('v', 0x0002); + // offset: 8; size: 16 + $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00); + // offset: 24; size: 4; section count + $data .= pack('V', 0x0001); + + // offset: 28; size: 16; first section's class id: e0 85 9f f2 f9 4f 68 10 ab 91 08 00 2b 27 b3 d9 + $data .= pack('vvvvvvvv', 0x85E0, 0xF29F, 0x4FF9, 0x1068, 0x91AB, 0x0008, 0x272B, 0xD9B3); + // offset: 44; size: 4; offset of the start + $data .= pack('V', 0x30); + + // SECTION + $dataSection = array(); + $dataSection_NumProps = 0; + $dataSection_Summary = ''; + $dataSection_Content = ''; + + // CodePage : CP-1252 + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x01), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x02), // 2 byte signed integer + 'data' => array('data' => 1252)); + $dataSection_NumProps++; + + // Title + if($this->_phpExcel->getProperties()->getTitle()){ + $dataProp = $this->_phpExcel->getProperties()->getTitle(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x02), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Subject + if($this->_phpExcel->getProperties()->getSubject()){ + $dataProp = $this->_phpExcel->getProperties()->getSubject(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x03), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Author (Creator) + if($this->_phpExcel->getProperties()->getCreator()){ + $dataProp = $this->_phpExcel->getProperties()->getCreator(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x04), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Keywords + if($this->_phpExcel->getProperties()->getKeywords()){ + $dataProp = $this->_phpExcel->getProperties()->getKeywords(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x05), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Comments (Description) + if($this->_phpExcel->getProperties()->getDescription()){ + $dataProp = $this->_phpExcel->getProperties()->getDescription(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x06), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Last Saved By (LastModifiedBy) + if($this->_phpExcel->getProperties()->getLastModifiedBy()){ + $dataProp = $this->_phpExcel->getProperties()->getLastModifiedBy(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x08), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Created Date/Time + if($this->_phpExcel->getProperties()->getCreated()){ + $dataProp = $this->_phpExcel->getProperties()->getCreated(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0C), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x40), // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + 'data' => array('data' => PHPExcel_Shared_OLE::LocalDate2OLE($dataProp))); + $dataSection_NumProps++; + } + // Modified Date/Time + if($this->_phpExcel->getProperties()->getModified()){ + $dataProp = $this->_phpExcel->getProperties()->getModified(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0D), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x40), // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + 'data' => array('data' => PHPExcel_Shared_OLE::LocalDate2OLE($dataProp))); + $dataSection_NumProps++; + } + // Security + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x13), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x03), // 4 byte signed integer + 'data' => array('data' => 0x00)); + $dataSection_NumProps++; + + + // 4 Section Length + // 4 Property count + // 8 * $dataSection_NumProps (8 = ID (4) + OffSet(4)) + $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8; + foreach ($dataSection as $dataProp){ + // Summary + $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']); + // Offset + $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset); + // DataType + $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']); + // Data + if($dataProp['type']['data'] == 0x02){ // 2 byte signed integer + $dataSection_Content .= pack('V', $dataProp['data']['data']); + + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x03){ // 4 byte signed integer + $dataSection_Content .= pack('V', $dataProp['data']['data']); + + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x1E){ // null-terminated string prepended by dword string length + // Null-terminated string + $dataProp['data']['data'] .= chr(0); + $dataProp['data']['length'] += 1; + // Complete the string with null string for being a %4 + $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4)==4 ? 0 : (4 - $dataProp['data']['length'] % 4)); + $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT); + + $dataSection_Content .= pack('V', $dataProp['data']['length']); + $dataSection_Content .= $dataProp['data']['data']; + + $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']); + } + elseif($dataProp['type']['data'] == 0x40){ // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + $dataSection_Content .= $dataProp['data']['data']; + + $dataSection_Content_Offset += 4 + 8; + } + else { + // Data Type Not Used at the moment + } + } + // Now $dataSection_Content_Offset contains the size of the content + + // section header + // offset: $secOffset; size: 4; section length + // + x Size of the content (summary + content) + $data .= pack('V', $dataSection_Content_Offset); + // offset: $secOffset+4; size: 4; property count + $data .= pack('V', $dataSection_NumProps); + // Section Summary + $data .= $dataSection_Summary; + // Section Content + $data .= $dataSection_Content; + + return $data; + } +} diff --git a/framework/library/phpexcel/PHPExcel/Writer/Excel5/Escher.php b/framework/library/phpexcel/PHPExcel/Writer/Excel5/Escher.php new file mode 100644 index 0000000..0624e04 --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/Excel5/Escher.php @@ -0,0 +1,537 @@ +_object = $object; + } + + /** + * Process the object to be written + */ + public function close() + { + // initialize + $this->_data = ''; + + switch (get_class($this->_object)) { + + case 'PHPExcel_Shared_Escher': + if ($dggContainer = $this->_object->getDggContainer()) { + $writer = new PHPExcel_Writer_Excel5_Escher($dggContainer); + $this->_data = $writer->close(); + } else if ($dgContainer = $this->_object->getDgContainer()) { + $writer = new PHPExcel_Writer_Excel5_Escher($dgContainer); + $this->_data = $writer->close(); + $this->_spOffsets = $writer->getSpOffsets(); + $this->_spTypes = $writer->getSpTypes(); + } + break; + + case 'PHPExcel_Shared_Escher_DggContainer': + // this is a container record + + // initialize + $innerData = ''; + + // write the dgg + $recVer = 0x0; + $recInstance = 0x0000; + $recType = 0xF006; + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + // dgg data + $dggData = + pack('VVVV' + , $this->_object->getSpIdMax() // maximum shape identifier increased by one + , $this->_object->getCDgSaved() + 1 // number of file identifier clusters increased by one + , $this->_object->getCSpSaved() + , $this->_object->getCDgSaved() // count total number of drawings saved + ); + + // add file identifier clusters (one per drawing) + $IDCLs = $this->_object->getIDCLs(); + + foreach ($IDCLs as $dgId => $maxReducedSpId) { + $dggData .= pack('VV', $dgId, $maxReducedSpId + 1); + } + + $header = pack('vvV', $recVerInstance, $recType, strlen($dggData)); + $innerData .= $header . $dggData; + + // write the bstoreContainer + if ($bstoreContainer = $this->_object->getBstoreContainer()) { + $writer = new PHPExcel_Writer_Excel5_Escher($bstoreContainer); + $innerData .= $writer->close(); + } + + // write the record + $recVer = 0xF; + $recInstance = 0x0000; + $recType = 0xF000; + $length = strlen($innerData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header . $innerData; + break; + + case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer': + // this is a container record + + // initialize + $innerData = ''; + + // treat the inner data + if ($BSECollection = $this->_object->getBSECollection()) { + foreach ($BSECollection as $BSE) { + $writer = new PHPExcel_Writer_Excel5_Escher($BSE); + $innerData .= $writer->close(); + } + } + + // write the record + $recVer = 0xF; + $recInstance = count($this->_object->getBSECollection()); + $recType = 0xF001; + $length = strlen($innerData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header . $innerData; + break; + + case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE': + // this is a semi-container record + + // initialize + $innerData = ''; + + // here we treat the inner data + if ($blip = $this->_object->getBlip()) { + $writer = new PHPExcel_Writer_Excel5_Escher($blip); + $innerData .= $writer->close(); + } + + // initialize + $data = ''; + + $btWin32 = $this->_object->getBlipType(); + $btMacOS = $this->_object->getBlipType(); + $data .= pack('CC', $btWin32, $btMacOS); + + $rgbUid = pack('VVVV', 0,0,0,0); // todo + $data .= $rgbUid; + + $tag = 0; + $size = strlen($innerData); + $cRef = 1; + $foDelay = 0; //todo + $unused1 = 0x0; + $cbName = 0x0; + $unused2 = 0x0; + $unused3 = 0x0; + $data .= pack('vVVVCCCC', $tag, $size, $cRef, $foDelay, $unused1, $cbName, $unused2, $unused3); + + $data .= $innerData; + + // write the record + $recVer = 0x2; + $recInstance = $this->_object->getBlipType(); + $recType = 0xF007; + $length = strlen($data); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header; + + $this->_data .= $data; + break; + + case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip': + // this is an atom record + + // write the record + switch ($this->_object->getParent()->getBlipType()) { + + case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG: + // initialize + $innerData = ''; + + $rgbUid1 = pack('VVVV', 0,0,0,0); // todo + $innerData .= $rgbUid1; + + $tag = 0xFF; // todo + $innerData .= pack('C', $tag); + + $innerData .= $this->_object->getData(); + + $recVer = 0x0; + $recInstance = 0x46A; + $recType = 0xF01D; + $length = strlen($innerData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header; + + $this->_data .= $innerData; + break; + + case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG: + // initialize + $innerData = ''; + + $rgbUid1 = pack('VVVV', 0,0,0,0); // todo + $innerData .= $rgbUid1; + + $tag = 0xFF; // todo + $innerData .= pack('C', $tag); + + $innerData .= $this->_object->getData(); + + $recVer = 0x0; + $recInstance = 0x6E0; + $recType = 0xF01E; + $length = strlen($innerData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header; + + $this->_data .= $innerData; + break; + + } + break; + + case 'PHPExcel_Shared_Escher_DgContainer': + // this is a container record + + // initialize + $innerData = ''; + + // write the dg + $recVer = 0x0; + $recInstance = $this->_object->getDgId(); + $recType = 0xF008; + $length = 8; + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + // number of shapes in this drawing (including group shape) + $countShapes = count($this->_object->getSpgrContainer()->getChildren()); + $innerData .= $header . pack('VV', $countShapes, $this->_object->getLastSpId()); + //$innerData .= $header . pack('VV', 0, 0); + + // write the spgrContainer + if ($spgrContainer = $this->_object->getSpgrContainer()) { + $writer = new PHPExcel_Writer_Excel5_Escher($spgrContainer); + $innerData .= $writer->close(); + + // get the shape offsets relative to the spgrContainer record + $spOffsets = $writer->getSpOffsets(); + $spTypes = $writer->getSpTypes(); + + // save the shape offsets relative to dgContainer + foreach ($spOffsets as & $spOffset) { + $spOffset += 24; // add length of dgContainer header data (8 bytes) plus dg data (16 bytes) + } + + $this->_spOffsets = $spOffsets; + $this->_spTypes = $spTypes; + } + + // write the record + $recVer = 0xF; + $recInstance = 0x0000; + $recType = 0xF002; + $length = strlen($innerData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header . $innerData; + break; + + case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer': + // this is a container record + + // initialize + $innerData = ''; + + // initialize spape offsets + $totalSize = 8; + $spOffsets = array(); + $spTypes = array(); + + // treat the inner data + foreach ($this->_object->getChildren() as $spContainer) { + $writer = new PHPExcel_Writer_Excel5_Escher($spContainer); + $spData = $writer->close(); + $innerData .= $spData; + + // save the shape offsets (where new shape records begin) + $totalSize += strlen($spData); + $spOffsets[] = $totalSize; + + $spTypes = array_merge($spTypes, $writer->getSpTypes()); + } + + // write the record + $recVer = 0xF; + $recInstance = 0x0000; + $recType = 0xF003; + $length = strlen($innerData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header . $innerData; + $this->_spOffsets = $spOffsets; + $this->_spTypes = $spTypes; + break; + + case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer': + // initialize + $data = ''; + + // build the data + + // write group shape record, if necessary? + if ($this->_object->getSpgr()) { + $recVer = 0x1; + $recInstance = 0x0000; + $recType = 0xF009; + $length = 0x00000010; + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $data .= $header . pack('VVVV', 0,0,0,0); + } + $this->_spTypes[] = ($this->_object->getSpType()); + + // write the shape record + $recVer = 0x2; + $recInstance = $this->_object->getSpType(); // shape type + $recType = 0xF00A; + $length = 0x00000008; + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $data .= $header . pack('VV', $this->_object->getSpId(), $this->_object->getSpgr() ? 0x0005 : 0x0A00); + + + // the options + if ($this->_object->getOPTCollection()) { + $optData = ''; + + $recVer = 0x3; + $recInstance = count($this->_object->getOPTCollection()); + $recType = 0xF00B; + foreach ($this->_object->getOPTCollection() as $property => $value) { + $optData .= pack('vV', $property, $value); + } + $length = strlen($optData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + $data .= $header . $optData; + } + + // the client anchor + if ($this->_object->getStartCoordinates()) { + $clientAnchorData = ''; + + $recVer = 0x0; + $recInstance = 0x0; + $recType = 0xF010; + + // start coordinates + list($column, $row) = PHPExcel_Cell::coordinateFromString($this->_object->getStartCoordinates()); + $c1 = PHPExcel_Cell::columnIndexFromString($column) - 1; + $r1 = $row - 1; + + // start offsetX + $startOffsetX = $this->_object->getStartOffsetX(); + + // start offsetY + $startOffsetY = $this->_object->getStartOffsetY(); + + // end coordinates + list($column, $row) = PHPExcel_Cell::coordinateFromString($this->_object->getEndCoordinates()); + $c2 = PHPExcel_Cell::columnIndexFromString($column) - 1; + $r2 = $row - 1; + + // end offsetX + $endOffsetX = $this->_object->getEndOffsetX(); + + // end offsetY + $endOffsetY = $this->_object->getEndOffsetY(); + + $clientAnchorData = pack('vvvvvvvvv', $this->_object->getSpFlag(), + $c1, $startOffsetX, $r1, $startOffsetY, + $c2, $endOffsetX, $r2, $endOffsetY); + + $length = strlen($clientAnchorData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + $data .= $header . $clientAnchorData; + } + + // the client data, just empty for now + if (!$this->_object->getSpgr()) { + $clientDataData = ''; + + $recVer = 0x0; + $recInstance = 0x0; + $recType = 0xF011; + + $length = strlen($clientDataData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + $data .= $header . $clientDataData; + } + + // write the record + $recVer = 0xF; + $recInstance = 0x0000; + $recType = 0xF004; + $length = strlen($data); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header . $data; + break; + + } + + return $this->_data; + } + + /** + * Gets the shape offsets + * + * @return array + */ + public function getSpOffsets() + { + return $this->_spOffsets; + } + + /** + * Gets the shape types + * + * @return array + */ + public function getSpTypes() + { + return $this->_spTypes; + } + + +} diff --git a/framework/library/phpexcel/PHPExcel/Writer/Excel5/Font.php b/framework/library/phpexcel/PHPExcel/Writer/Excel5/Font.php new file mode 100644 index 0000000..da1c9c1 --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/Excel5/Font.php @@ -0,0 +1,165 @@ +_colorIndex = 0x7FFF; + $this->_font = $font; + } + + /** + * Set the color index + * + * @param int $colorIndex + */ + public function setColorIndex($colorIndex) + { + $this->_colorIndex = $colorIndex; + } + + /** + * Get font record data + * + * @return string + */ + public function writeFont() + { + $font_outline = 0; + $font_shadow = 0; + + $icv = $this->_colorIndex; // Index to color palette + if ($this->_font->getSuperScript()) { + $sss = 1; + } else if ($this->_font->getSubScript()) { + $sss = 2; + } else { + $sss = 0; + } + $bFamily = 0; // Font family + $bCharSet = PHPExcel_Shared_Font::getCharsetFromFontName($this->_font->getName()); // Character set + + $record = 0x31; // Record identifier + $reserved = 0x00; // Reserved + $grbit = 0x00; // Font attributes + if ($this->_font->getItalic()) { + $grbit |= 0x02; + } + if ($this->_font->getStrikethrough()) { + $grbit |= 0x08; + } + if ($font_outline) { + $grbit |= 0x10; + } + if ($font_shadow) { + $grbit |= 0x20; + } + + $data = pack("vvvvvCCCC", + $this->_font->getSize() * 20, // Fontsize (in twips) + $grbit, + $icv, // Colour + self::_mapBold($this->_font->getBold()), // Font weight + $sss, // Superscript/Subscript + self::_mapUnderline($this->_font->getUnderline()), + $bFamily, + $bCharSet, + $reserved + ); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($this->_font->getName()); + + $length = strlen($data); + $header = pack("vv", $record, $length); + + return($header . $data); + } + + /** + * Map to BIFF5-BIFF8 codes for bold + * + * @param boolean $bold + * @return int + */ + private static function _mapBold($bold) { + if ($bold) { + return 0x2BC; // 700 = Bold font weight + } + return 0x190; // 400 = Normal font weight + } + + /** + * Map of BIFF2-BIFF8 codes for underline styles + * @static array of int + * + */ + private static $_mapUnderline = array( PHPExcel_Style_Font::UNDERLINE_NONE => 0x00, + PHPExcel_Style_Font::UNDERLINE_SINGLE => 0x01, + PHPExcel_Style_Font::UNDERLINE_DOUBLE => 0x02, + PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING => 0x21, + PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING => 0x22, + ); + /** + * Map underline + * + * @param string + * @return int + */ + private static function _mapUnderline($underline) { + if (isset(self::$_mapUnderline[$underline])) + return self::$_mapUnderline[$underline]; + return 0x00; + } + +} diff --git a/framework/library/phpexcel/PHPExcel/Writer/Exception.php b/framework/library/phpexcel/PHPExcel/Writer/Exception.php new file mode 100644 index 0000000..495c61e --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/Exception.php @@ -0,0 +1,52 @@ +line = $line; + $e->file = $file; + throw $e; + } +} diff --git a/framework/library/phpexcel/PHPExcel/Writer/HTML.php b/framework/library/phpexcel/PHPExcel/Writer/HTML.php new file mode 100644 index 0000000..af4635c --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/HTML.php @@ -0,0 +1,1527 @@ +_phpExcel = $phpExcel; + $this->_defaultFont = $this->_phpExcel->getDefaultStyle()->getFont(); + } + + /** + * Save PHPExcel to file + * + * @param string $pFilename + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = null) { + // garbage collect + $this->_phpExcel->garbageCollect(); + + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE); + $saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType(); + PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE); + + // Build CSS + $this->buildCSS(!$this->_useInlineCss); + + // Open file + $fileHandle = fopen($pFilename, 'wb+'); + if ($fileHandle === false) { + throw new PHPExcel_Writer_Exception("Could not open file $pFilename for writing."); + } + + // Write headers + fwrite($fileHandle, $this->generateHTMLHeader(!$this->_useInlineCss)); + + // Write navigation (tabs) + if ((!$this->_isPdf) && ($this->_generateSheetNavigationBlock)) { + fwrite($fileHandle, $this->generateNavigation()); + } + + // Write data + fwrite($fileHandle, $this->generateSheetData()); + + // Write footer + fwrite($fileHandle, $this->generateHTMLFooter()); + + // Close file + fclose($fileHandle); + + PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); + } + + /** + * Map VAlign + * + * @param string $vAlign Vertical alignment + * @return string + */ + private function _mapVAlign($vAlign) { + switch ($vAlign) { + case PHPExcel_Style_Alignment::VERTICAL_BOTTOM: return 'bottom'; + case PHPExcel_Style_Alignment::VERTICAL_TOP: return 'top'; + case PHPExcel_Style_Alignment::VERTICAL_CENTER: + case PHPExcel_Style_Alignment::VERTICAL_JUSTIFY: return 'middle'; + default: return 'baseline'; + } + } + + /** + * Map HAlign + * + * @param string $hAlign Horizontal alignment + * @return string|false + */ + private function _mapHAlign($hAlign) { + switch ($hAlign) { + case PHPExcel_Style_Alignment::HORIZONTAL_GENERAL: return false; + case PHPExcel_Style_Alignment::HORIZONTAL_LEFT: return 'left'; + case PHPExcel_Style_Alignment::HORIZONTAL_RIGHT: return 'right'; + case PHPExcel_Style_Alignment::HORIZONTAL_CENTER: + case PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS: return 'center'; + case PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY: return 'justify'; + default: return false; + } + } + + /** + * Map border style + * + * @param int $borderStyle Sheet index + * @return string + */ + private function _mapBorderStyle($borderStyle) { + switch ($borderStyle) { + case PHPExcel_Style_Border::BORDER_NONE: return 'none'; + case PHPExcel_Style_Border::BORDER_DASHDOT: return '1px dashed'; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT: return '1px dotted'; + case PHPExcel_Style_Border::BORDER_DASHED: return '1px dashed'; + case PHPExcel_Style_Border::BORDER_DOTTED: return '1px dotted'; + case PHPExcel_Style_Border::BORDER_DOUBLE: return '3px double'; + case PHPExcel_Style_Border::BORDER_HAIR: return '1px solid'; + case PHPExcel_Style_Border::BORDER_MEDIUM: return '2px solid'; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT: return '2px dashed'; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT: return '2px dotted'; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED: return '2px dashed'; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT: return '2px dashed'; + case PHPExcel_Style_Border::BORDER_THICK: return '3px solid'; + case PHPExcel_Style_Border::BORDER_THIN: return '1px solid'; + default: return '1px solid'; // map others to thin + } + } + + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } + + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Writer_HTML + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } + + /** + * Get sheet index + * + * @return boolean + */ + public function getGenerateSheetNavigationBlock() { + return $this->_generateSheetNavigationBlock; + } + + /** + * Set sheet index + * + * @param boolean $pValue Flag indicating whether the sheet navigation block should be generated or not + * @return PHPExcel_Writer_HTML + */ + public function setGenerateSheetNavigationBlock($pValue = true) { + $this->_generateSheetNavigationBlock = (bool) $pValue; + return $this; + } + + /** + * Write all sheets (resets sheetIndex to NULL) + */ + public function writeAllSheets() { + $this->_sheetIndex = null; + return $this; + } + + /** + * Generate HTML header + * + * @param boolean $pIncludeStyles Include styles? + * @return string + * @throws PHPExcel_Writer_Exception + */ + public function generateHTMLHeader($pIncludeStyles = false) { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } + + // Construct HTML + $properties = $this->_phpExcel->getProperties(); + $html = '' . PHP_EOL; + $html .= '' . PHP_EOL; + $html .= '' . PHP_EOL; + $html .= ' ' . PHP_EOL; + $html .= ' ' . PHP_EOL; + if ($properties->getTitle() > '') + $html .= ' ' . htmlspecialchars($properties->getTitle()) . '' . PHP_EOL; + + if ($properties->getCreator() > '') + $html .= ' ' . PHP_EOL; + if ($properties->getTitle() > '') + $html .= ' ' . PHP_EOL; + if ($properties->getDescription() > '') + $html .= ' ' . PHP_EOL; + if ($properties->getSubject() > '') + $html .= ' ' . PHP_EOL; + if ($properties->getKeywords() > '') + $html .= ' ' . PHP_EOL; + if ($properties->getCategory() > '') + $html .= ' ' . PHP_EOL; + if ($properties->getCompany() > '') + $html .= ' ' . PHP_EOL; + if ($properties->getManager() > '') + $html .= ' ' . PHP_EOL; + + if ($pIncludeStyles) { + $html .= $this->generateStyles(true); + } + + $html .= ' ' . PHP_EOL; + $html .= '' . PHP_EOL; + $html .= ' ' . PHP_EOL; + + // Return + return $html; + } + + /** + * Generate sheet data + * + * @return string + * @throws PHPExcel_Writer_Exception + */ + public function generateSheetData() { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } + + // Ensure that Spans have been calculated? + if (!$this->_spansAreCalculated) { + $this->_calculateSpans(); + } + + // Fetch sheets + $sheets = array(); + if (is_null($this->_sheetIndex)) { + $sheets = $this->_phpExcel->getAllSheets(); + } else { + $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex); + } + + // Construct HTML + $html = ''; + + // Loop all sheets + $sheetId = 0; + foreach ($sheets as $sheet) { + // Write table header + $html .= $this->_generateTableHeader($sheet); + + // Get worksheet dimension + $dimension = explode(':', $sheet->calculateWorksheetDimension()); + $dimension[0] = PHPExcel_Cell::coordinateFromString($dimension[0]); + $dimension[0][0] = PHPExcel_Cell::columnIndexFromString($dimension[0][0]) - 1; + $dimension[1] = PHPExcel_Cell::coordinateFromString($dimension[1]); + $dimension[1][0] = PHPExcel_Cell::columnIndexFromString($dimension[1][0]) - 1; + + // row min,max + $rowMin = $dimension[0][1]; + $rowMax = $dimension[1][1]; + + // calculate start of , + $tbodyStart = $rowMin; + $theadStart = $theadEnd = 0; // default: no no + if ($sheet->getPageSetup()->isRowsToRepeatAtTopSet()) { + $rowsToRepeatAtTop = $sheet->getPageSetup()->getRowsToRepeatAtTop(); + + // we can only support repeating rows that start at top row + if ($rowsToRepeatAtTop[0] == 1) { + $theadStart = $rowsToRepeatAtTop[0]; + $theadEnd = $rowsToRepeatAtTop[1]; + $tbodyStart = $rowsToRepeatAtTop[1] + 1; + } + } + + // Loop through cells + $row = $rowMin-1; + while($row++ < $rowMax) { + // ? + if ($row == $theadStart) { + $html .= ' ' . PHP_EOL; + } + + // ? + if ($row == $tbodyStart) { + $html .= ' ' . PHP_EOL; + } + + // Write row if there are HTML table cells in it + if ( !isset($this->_isSpannedRow[$sheet->getParent()->getIndex($sheet)][$row]) ) { + // Start a new rowData + $rowData = array(); + // Loop through columns + $column = $dimension[0][0] - 1; + while($column++ < $dimension[1][0]) { + // Cell exists? + if ($sheet->cellExistsByColumnAndRow($column, $row)) { + $rowData[$column] = $sheet->getCellByColumnAndRow($column, $row); + } else { + $rowData[$column] = ''; + } + } + $html .= $this->_generateRow($sheet, $rowData, $row - 1); + } + + // ? + if ($row == $theadEnd) { + $html .= ' ' . PHP_EOL; + } + } + $html .= $this->_extendRowsForChartsAndImages($sheet, $row); + + // Close table body. + $html .= ' ' . PHP_EOL; + + // Write table footer + $html .= $this->_generateTableFooter(); + + // Writing PDF? + if ($this->_isPdf) { + if (is_null($this->_sheetIndex) && $sheetId + 1 < $this->_phpExcel->getSheetCount()) { + $html .= '
'; + } + } + + // Next sheet + ++$sheetId; + } + + // Return + return $html; + } + + /** + * Generate sheet tabs + * + * @return string + * @throws PHPExcel_Writer_Exception + */ + public function generateNavigation() + { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } + + // Fetch sheets + $sheets = array(); + if (is_null($this->_sheetIndex)) { + $sheets = $this->_phpExcel->getAllSheets(); + } else { + $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex); + } + + // Construct HTML + $html = ''; + + // Only if there are more than 1 sheets + if (count($sheets) > 1) { + // Loop all sheets + $sheetId = 0; + + $html .= '' . PHP_EOL; + } + + return $html; + } + + private function _extendRowsForChartsAndImages(PHPExcel_Worksheet $pSheet, $row) { + $rowMax = $row; + $colMax = 'A'; + if ($this->_includeCharts) { + foreach ($pSheet->getChartCollection() as $chart) { + if ($chart instanceof PHPExcel_Chart) { + $chartCoordinates = $chart->getTopLeftPosition(); + $chartTL = PHPExcel_Cell::coordinateFromString($chartCoordinates['cell']); + $chartCol = PHPExcel_Cell::columnIndexFromString($chartTL[0]); + if ($chartTL[1] > $rowMax) { + $rowMax = $chartTL[1]; + if ($chartCol > PHPExcel_Cell::columnIndexFromString($colMax)) { + $colMax = $chartTL[0]; + } + } + } + } + } + + foreach ($pSheet->getDrawingCollection() as $drawing) { + if ($drawing instanceof PHPExcel_Worksheet_Drawing) { + $imageTL = PHPExcel_Cell::coordinateFromString($drawing->getCoordinates()); + $imageCol = PHPExcel_Cell::columnIndexFromString($imageTL[0]); + if ($imageTL[1] > $rowMax) { + $rowMax = $imageTL[1]; + if ($imageCol > PHPExcel_Cell::columnIndexFromString($colMax)) { + $colMax = $imageTL[0]; + } + } + } + } + $html = ''; + $colMax++; + while ($row < $rowMax) { + $html .= ''; + for ($col = 'A'; $col != $colMax; ++$col) { + $html .= ''; + $html .= $this->_writeImageInCell($pSheet, $col.$row); + if ($this->_includeCharts) { + $html .= $this->_writeChartInCell($pSheet, $col.$row); + } + $html .= ''; + } + ++$row; + $html .= ''; + } + return $html; + } + + + /** + * Generate image tag in cell + * + * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet + * @param string $coordinates Cell coordinates + * @return string + * @throws PHPExcel_Writer_Exception + */ + private function _writeImageInCell(PHPExcel_Worksheet $pSheet, $coordinates) { + // Construct HTML + $html = ''; + + // Write images + foreach ($pSheet->getDrawingCollection() as $drawing) { + if ($drawing instanceof PHPExcel_Worksheet_Drawing) { + if ($drawing->getCoordinates() == $coordinates) { + $filename = $drawing->getPath(); + + // Strip off eventual '.' + if (substr($filename, 0, 1) == '.') { + $filename = substr($filename, 1); + } + + // Prepend images root + $filename = $this->getImagesRoot() . $filename; + + // Strip off eventual '.' + if (substr($filename, 0, 1) == '.' && substr($filename, 0, 2) != './') { + $filename = substr($filename, 1); + } + + // Convert UTF8 data to PCDATA + $filename = htmlspecialchars($filename); + + $html .= PHP_EOL; + if ((!$this->_embedImages) || ($this->_isPdf)) { + $imageData = $filename; + } else { + $imageDetails = getimagesize($filename); + if ($fp = fopen($filename,"rb", 0)) { + $picture = fread($fp,filesize($filename)); + fclose($fp); + // base64 encode the binary data, then break it + // into chunks according to RFC 2045 semantics + $base64 = chunk_split(base64_encode($picture)); + $imageData = 'data:'.$imageDetails['mime'].';base64,' . $base64; + } else { + $imageData = $filename; + } + } + + $html .= '
'; + $html .= '' . PHP_EOL; + $html .= '
'; + } + } + } + + // Return + return $html; + } + + /** + * Generate chart tag in cell + * + * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet + * @param string $coordinates Cell coordinates + * @return string + * @throws PHPExcel_Writer_Exception + */ + private function _writeChartInCell(PHPExcel_Worksheet $pSheet, $coordinates) { + // Construct HTML + $html = ''; + + // Write charts + foreach ($pSheet->getChartCollection() as $chart) { + if ($chart instanceof PHPExcel_Chart) { + $chartCoordinates = $chart->getTopLeftPosition(); + if ($chartCoordinates['cell'] == $coordinates) { + $chartFileName = PHPExcel_Shared_File::sys_get_temp_dir().'/'.uniqid().'.png'; + if (!$chart->render($chartFileName)) { + return; + } + + $html .= PHP_EOL; + $imageDetails = getimagesize($chartFileName); + if ($fp = fopen($chartFileName,"rb", 0)) { + $picture = fread($fp,filesize($chartFileName)); + fclose($fp); + // base64 encode the binary data, then break it + // into chunks according to RFC 2045 semantics + $base64 = chunk_split(base64_encode($picture)); + $imageData = 'data:'.$imageDetails['mime'].';base64,' . $base64; + + $html .= '
'; + $html .= '' . PHP_EOL; + $html .= '
'; + + unlink($chartFileName); + } + } + } + } + + // Return + return $html; + } + + /** + * Generate CSS styles + * + * @param boolean $generateSurroundingHTML Generate surrounding HTML tags? () + * @return string + * @throws PHPExcel_Writer_Exception + */ + public function generateStyles($generateSurroundingHTML = true) { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } + + // Build CSS + $css = $this->buildCSS($generateSurroundingHTML); + + // Construct HTML + $html = ''; + + // Start styles + if ($generateSurroundingHTML) { + $html .= ' ' . PHP_EOL; + } + + // Return + return $html; + } + + /** + * Build CSS styles + * + * @param boolean $generateSurroundingHTML Generate surrounding HTML style? (html { }) + * @return array + * @throws PHPExcel_Writer_Exception + */ + public function buildCSS($generateSurroundingHTML = true) { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } + + // Cached? + if (!is_null($this->_cssStyles)) { + return $this->_cssStyles; + } + + // Ensure that spans have been calculated + if (!$this->_spansAreCalculated) { + $this->_calculateSpans(); + } + + // Construct CSS + $css = array(); + + // Start styles + if ($generateSurroundingHTML) { + // html { } + $css['html']['font-family'] = 'Calibri, Arial, Helvetica, sans-serif'; + $css['html']['font-size'] = '11pt'; + $css['html']['background-color'] = 'white'; + } + + + // table { } + $css['table']['border-collapse'] = 'collapse'; + if (!$this->_isPdf) { + $css['table']['page-break-after'] = 'always'; + } + + // .gridlines td { } + $css['.gridlines td']['border'] = '1px dotted black'; + + // .b {} + $css['.b']['text-align'] = 'center'; // BOOL + + // .e {} + $css['.e']['text-align'] = 'center'; // ERROR + + // .f {} + $css['.f']['text-align'] = 'right'; // FORMULA + + // .inlineStr {} + $css['.inlineStr']['text-align'] = 'left'; // INLINE + + // .n {} + $css['.n']['text-align'] = 'right'; // NUMERIC + + // .s {} + $css['.s']['text-align'] = 'left'; // STRING + + // Calculate cell style hashes + foreach ($this->_phpExcel->getCellXfCollection() as $index => $style) { + $css['td.style' . $index] = $this->_createCSSStyle( $style ); + } + + // Fetch sheets + $sheets = array(); + if (is_null($this->_sheetIndex)) { + $sheets = $this->_phpExcel->getAllSheets(); + } else { + $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex); + } + + // Build styles per sheet + foreach ($sheets as $sheet) { + // Calculate hash code + $sheetIndex = $sheet->getParent()->getIndex($sheet); + + // Build styles + // Calculate column widths + $sheet->calculateColumnWidths(); + + // col elements, initialize + $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn()) - 1; + $column = -1; + while($column++ < $highestColumnIndex) { + $this->_columnWidths[$sheetIndex][$column] = 42; // approximation + $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = '42pt'; + } + + // col elements, loop through columnDimensions and set width + foreach ($sheet->getColumnDimensions() as $columnDimension) { + if (($width = PHPExcel_Shared_Drawing::cellDimensionToPixels($columnDimension->getWidth(), $this->_defaultFont)) >= 0) { + $width = PHPExcel_Shared_Drawing::pixelsToPoints($width); + $column = PHPExcel_Cell::columnIndexFromString($columnDimension->getColumnIndex()) - 1; + $this->_columnWidths[$sheetIndex][$column] = $width; + $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = $width . 'pt'; + + if ($columnDimension->getVisible() === false) { + $css['table.sheet' . $sheetIndex . ' col.col' . $column]['visibility'] = 'collapse'; + $css['table.sheet' . $sheetIndex . ' col.col' . $column]['*display'] = 'none'; // target IE6+7 + } + } + } + + // Default row height + $rowDimension = $sheet->getDefaultRowDimension(); + + // table.sheetN tr { } + $css['table.sheet' . $sheetIndex . ' tr'] = array(); + + if ($rowDimension->getRowHeight() == -1) { + $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont()); + } else { + $pt_height = $rowDimension->getRowHeight(); + } + $css['table.sheet' . $sheetIndex . ' tr']['height'] = $pt_height . 'pt'; + if ($rowDimension->getVisible() === false) { + $css['table.sheet' . $sheetIndex . ' tr']['display'] = 'none'; + $css['table.sheet' . $sheetIndex . ' tr']['visibility'] = 'hidden'; + } + + // Calculate row heights + foreach ($sheet->getRowDimensions() as $rowDimension) { + $row = $rowDimension->getRowIndex() - 1; + + // table.sheetN tr.rowYYYYYY { } + $css['table.sheet' . $sheetIndex . ' tr.row' . $row] = array(); + + if ($rowDimension->getRowHeight() == -1) { + $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont()); + } else { + $pt_height = $rowDimension->getRowHeight(); + } + $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['height'] = $pt_height . 'pt'; + if ($rowDimension->getVisible() === false) { + $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['display'] = 'none'; + $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['visibility'] = 'hidden'; + } + } + } + + // Cache + if (is_null($this->_cssStyles)) { + $this->_cssStyles = $css; + } + + // Return + return $css; + } + + /** + * Create CSS style + * + * @param PHPExcel_Style $pStyle PHPExcel_Style + * @return array + */ + private function _createCSSStyle(PHPExcel_Style $pStyle) { + // Construct CSS + $css = ''; + + // Create CSS + $css = array_merge( + $this->_createCSSStyleAlignment($pStyle->getAlignment()) + , $this->_createCSSStyleBorders($pStyle->getBorders()) + , $this->_createCSSStyleFont($pStyle->getFont()) + , $this->_createCSSStyleFill($pStyle->getFill()) + ); + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Alignment) + * + * @param PHPExcel_Style_Alignment $pStyle PHPExcel_Style_Alignment + * @return array + */ + private function _createCSSStyleAlignment(PHPExcel_Style_Alignment $pStyle) { + // Construct CSS + $css = array(); + + // Create CSS + $css['vertical-align'] = $this->_mapVAlign($pStyle->getVertical()); + if ($textAlign = $this->_mapHAlign($pStyle->getHorizontal())) { + $css['text-align'] = $textAlign; + if(in_array($textAlign,array('left','right'))) + $css['padding-'.$textAlign] = (string)((int)$pStyle->getIndent() * 9).'px'; + } + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Font) + * + * @param PHPExcel_Style_Font $pStyle PHPExcel_Style_Font + * @return array + */ + private function _createCSSStyleFont(PHPExcel_Style_Font $pStyle) { + // Construct CSS + $css = array(); + + // Create CSS + if ($pStyle->getBold()) { + $css['font-weight'] = 'bold'; + } + if ($pStyle->getUnderline() != PHPExcel_Style_Font::UNDERLINE_NONE && $pStyle->getStrikethrough()) { + $css['text-decoration'] = 'underline line-through'; + } else if ($pStyle->getUnderline() != PHPExcel_Style_Font::UNDERLINE_NONE) { + $css['text-decoration'] = 'underline'; + } else if ($pStyle->getStrikethrough()) { + $css['text-decoration'] = 'line-through'; + } + if ($pStyle->getItalic()) { + $css['font-style'] = 'italic'; + } + + $css['color'] = '#' . $pStyle->getColor()->getRGB(); + $css['font-family'] = '\'' . $pStyle->getName() . '\''; + $css['font-size'] = $pStyle->getSize() . 'pt'; + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Borders) + * + * @param PHPExcel_Style_Borders $pStyle PHPExcel_Style_Borders + * @return array + */ + private function _createCSSStyleBorders(PHPExcel_Style_Borders $pStyle) { + // Construct CSS + $css = array(); + + // Create CSS + $css['border-bottom'] = $this->_createCSSStyleBorder($pStyle->getBottom()); + $css['border-top'] = $this->_createCSSStyleBorder($pStyle->getTop()); + $css['border-left'] = $this->_createCSSStyleBorder($pStyle->getLeft()); + $css['border-right'] = $this->_createCSSStyleBorder($pStyle->getRight()); + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Border) + * + * @param PHPExcel_Style_Border $pStyle PHPExcel_Style_Border + * @return string + */ + private function _createCSSStyleBorder(PHPExcel_Style_Border $pStyle) { + // Create CSS +// $css = $this->_mapBorderStyle($pStyle->getBorderStyle()) . ' #' . $pStyle->getColor()->getRGB(); + // Create CSS - add !important to non-none border styles for merged cells + $borderStyle = $this->_mapBorderStyle($pStyle->getBorderStyle()); + $css = $borderStyle . ' #' . $pStyle->getColor()->getRGB() . (($borderStyle == 'none') ? '' : ' !important'); + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Fill) + * + * @param PHPExcel_Style_Fill $pStyle PHPExcel_Style_Fill + * @return array + */ + private function _createCSSStyleFill(PHPExcel_Style_Fill $pStyle) { + // Construct HTML + $css = array(); + + // Create CSS + $value = $pStyle->getFillType() == PHPExcel_Style_Fill::FILL_NONE ? + 'white' : '#' . $pStyle->getStartColor()->getRGB(); + $css['background-color'] = $value; + + // Return + return $css; + } + + /** + * Generate HTML footer + */ + public function generateHTMLFooter() { + // Construct HTML + $html = ''; + $html .= ' ' . PHP_EOL; + $html .= '' . PHP_EOL; + + // Return + return $html; + } + + /** + * Generate table header + * + * @param PHPExcel_Worksheet $pSheet The worksheet for the table we are writing + * @return string + * @throws PHPExcel_Writer_Exception + */ + private function _generateTableHeader($pSheet) { + $sheetIndex = $pSheet->getParent()->getIndex($pSheet); + + // Construct HTML + $html = ''; + $html .= $this->_setMargins($pSheet); + + if (!$this->_useInlineCss) { + $gridlines = $pSheet->getShowGridLines() ? ' gridlines' : ''; + $html .= ' ' . PHP_EOL; + } else { + $style = isset($this->_cssStyles['table']) ? + $this->_assembleCSS($this->_cssStyles['table']) : ''; + + if ($this->_isPdf && $pSheet->getShowGridLines()) { + $html .= '
' . PHP_EOL; + } else { + $html .= '
' . PHP_EOL; + } + } + + // Write elements + $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($pSheet->getHighestColumn()) - 1; + $i = -1; + while($i++ < $highestColumnIndex) { + if (!$this->_isPdf) { + if (!$this->_useInlineCss) { + $html .= ' ' . PHP_EOL; + } else { + $style = isset($this->_cssStyles['table.sheet' . $sheetIndex . ' col.col' . $i]) ? + $this->_assembleCSS($this->_cssStyles['table.sheet' . $sheetIndex . ' col.col' . $i]) : ''; + $html .= ' ' . PHP_EOL; + } + } + } + + // Return + return $html; + } + + /** + * Generate table footer + * + * @throws PHPExcel_Writer_Exception + */ + private function _generateTableFooter() { + // Construct HTML + $html = ''; + $html .= '
' . PHP_EOL; + + // Return + return $html; + } + + /** + * Generate row + * + * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet + * @param array $pValues Array containing cells in a row + * @param int $pRow Row number (0-based) + * @return string + * @throws PHPExcel_Writer_Exception + */ + private function _generateRow(PHPExcel_Worksheet $pSheet, $pValues = null, $pRow = 0) { + if (is_array($pValues)) { + // Construct HTML + $html = ''; + + // Sheet index + $sheetIndex = $pSheet->getParent()->getIndex($pSheet); + + // DomPDF and breaks + if ($this->_isPdf && count($pSheet->getBreaks()) > 0) { + $breaks = $pSheet->getBreaks(); + + // check if a break is needed before this row + if (isset($breaks['A' . $pRow])) { + // close table: + $html .= $this->_generateTableFooter(); + + // insert page break + $html .= '
'; + + // open table again: + etc. + $html .= $this->_generateTableHeader($pSheet); + } + } + + // Write row start + if (!$this->_useInlineCss) { + $html .= ' ' . PHP_EOL; + } else { + $style = isset($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]) + ? $this->_assembleCSS($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]) : ''; + + $html .= ' ' . PHP_EOL; + } + + // Write cells + $colNum = 0; + foreach ($pValues as $cell) { + $coordinate = PHPExcel_Cell::stringFromColumnIndex($colNum) . ($pRow + 1); + + if (!$this->_useInlineCss) { + $cssClass = ''; + $cssClass = 'column' . $colNum; + } else { + $cssClass = array(); + if (isset($this->_cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum])) { + $this->_cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum]; + } + } + $colSpan = 1; + $rowSpan = 1; + + // initialize + $cellData = ' '; + + // PHPExcel_Cell + if ($cell instanceof PHPExcel_Cell) { + $cellData = ''; + if (is_null($cell->getParent())) { + $cell->attach($pSheet); + } + // Value + if ($cell->getValue() instanceof PHPExcel_RichText) { + // Loop through rich text elements + $elements = $cell->getValue()->getRichTextElements(); + foreach ($elements as $element) { + // Rich text start? + if ($element instanceof PHPExcel_RichText_Run) { + $cellData .= ''; + + if ($element->getFont()->getSuperScript()) { + $cellData .= ''; + } else if ($element->getFont()->getSubScript()) { + $cellData .= ''; + } + } + + // Convert UTF8 data to PCDATA + $cellText = $element->getText(); + $cellData .= htmlspecialchars($cellText); + + if ($element instanceof PHPExcel_RichText_Run) { + if ($element->getFont()->getSuperScript()) { + $cellData .= ''; + } else if ($element->getFont()->getSubScript()) { + $cellData .= ''; + } + + $cellData .= ''; + } + } + } else { + if ($this->_preCalculateFormulas) { + $cellData = PHPExcel_Style_NumberFormat::toFormattedString( + $cell->getCalculatedValue(), + $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(), + array($this, 'formatColor') + ); + } else { + $cellData = PHPExcel_Style_NumberFormat::ToFormattedString( + $cell->getValue(), + $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(), + array($this, 'formatColor') + ); + } + $cellData = htmlspecialchars($cellData); + if ($pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getFont()->getSuperScript()) { + $cellData = ''.$cellData.''; + } elseif ($pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getFont()->getSubScript()) { + $cellData = ''.$cellData.''; + } + } + + // Converts the cell content so that spaces occuring at beginning of each new line are replaced by   + // Example: " Hello\n to the world" is converted to "  Hello\n to the world" + $cellData = preg_replace("/(?m)(?:^|\\G) /", ' ', $cellData); + + // convert newline "\n" to '
' + $cellData = nl2br($cellData); + + // Extend CSS class? + if (!$this->_useInlineCss) { + $cssClass .= ' style' . $cell->getXfIndex(); + $cssClass .= ' ' . $cell->getDataType(); + } else { + if (isset($this->_cssStyles['td.style' . $cell->getXfIndex()])) { + $cssClass = array_merge($cssClass, $this->_cssStyles['td.style' . $cell->getXfIndex()]); + } + + // General horizontal alignment: Actual horizontal alignment depends on dataType + $sharedStyle = $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() ); + if ($sharedStyle->getAlignment()->getHorizontal() == PHPExcel_Style_Alignment::HORIZONTAL_GENERAL + && isset($this->_cssStyles['.' . $cell->getDataType()]['text-align'])) + { + $cssClass['text-align'] = $this->_cssStyles['.' . $cell->getDataType()]['text-align']; + } + } + } + + // Hyperlink? + if ($pSheet->hyperlinkExists($coordinate) && !$pSheet->getHyperlink($coordinate)->isInternal()) { + $cellData = '' . $cellData . ''; + } + + // Should the cell be written or is it swallowed by a rowspan or colspan? + $writeCell = ! ( isset($this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]) + && $this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum] ); + + // Colspan and Rowspan + $colspan = 1; + $rowspan = 1; + if (isset($this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum])) { + $spans = $this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]; + $rowSpan = $spans['rowspan']; + $colSpan = $spans['colspan']; + + // Also apply style from last cell in merge to fix borders - + // relies on !important for non-none border declarations in _createCSSStyleBorder + $endCellCoord = PHPExcel_Cell::stringFromColumnIndex($colNum + $colSpan - 1) . ($pRow + $rowSpan); + $cssClass .= ' style' . $pSheet->getCell($endCellCoord)->getXfIndex(); + } + + // Write + if ($writeCell) { + // Column start + $html .= ' _useInlineCss) { + $html .= ' class="' . $cssClass . '"'; + } else { + //** Necessary redundant code for the sake of PHPExcel_Writer_PDF ** + // We must explicitly write the width of the + $width = 0; + $i = $colNum - 1; + $e = $colNum + $colSpan - 1; + while($i++ < $e) { + if (isset($this->_columnWidths[$sheetIndex][$i])) { + $width += $this->_columnWidths[$sheetIndex][$i]; + } + } + $cssClass['width'] = $width . 'pt'; + + // We must also explicitly write the height of the + if (isset($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height'])) { + $height = $this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height']; + $cssClass['height'] = $height; + } + //** end of redundant code ** + + $html .= ' style="' . $this->_assembleCSS($cssClass) . '"'; + } + if ($colSpan > 1) { + $html .= ' colspan="' . $colSpan . '"'; + } + if ($rowSpan > 1) { + $html .= ' rowspan="' . $rowSpan . '"'; + } + $html .= '>'; + + // Image? + $html .= $this->_writeImageInCell($pSheet, $coordinate); + + // Chart? + if ($this->_includeCharts) { + $html .= $this->_writeChartInCell($pSheet, $coordinate); + } + + // Cell data + $html .= $cellData; + + // Column end + $html .= '' . PHP_EOL; + } + + // Next column + ++$colNum; + } + + // Write row end + $html .= ' ' . PHP_EOL; + + // Return + return $html; + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } + + /** + * Takes array where of CSS properties / values and converts to CSS string + * + * @param array + * @return string + */ + private function _assembleCSS($pValue = array()) + { + $pairs = array(); + foreach ($pValue as $property => $value) { + $pairs[] = $property . ':' . $value; + } + $string = implode('; ', $pairs); + + return $string; + } + + /** + * Get images root + * + * @return string + */ + public function getImagesRoot() { + return $this->_imagesRoot; + } + + /** + * Set images root + * + * @param string $pValue + * @return PHPExcel_Writer_HTML + */ + public function setImagesRoot($pValue = '.') { + $this->_imagesRoot = $pValue; + return $this; + } + + /** + * Get embed images + * + * @return boolean + */ + public function getEmbedImages() { + return $this->_embedImages; + } + + /** + * Set embed images + * + * @param boolean $pValue + * @return PHPExcel_Writer_HTML + */ + public function setEmbedImages($pValue = '.') { + $this->_embedImages = $pValue; + return $this; + } + + /** + * Get use inline CSS? + * + * @return boolean + */ + public function getUseInlineCss() { + return $this->_useInlineCss; + } + + /** + * Set use inline CSS? + * + * @param boolean $pValue + * @return PHPExcel_Writer_HTML + */ + public function setUseInlineCss($pValue = false) { + $this->_useInlineCss = $pValue; + return $this; + } + + /** + * Add color to formatted string as inline style + * + * @param string $pValue Plain formatted value without color + * @param string $pFormat Format code + * @return string + */ + public function formatColor($pValue, $pFormat) + { + // Color information, e.g. [Red] is always at the beginning + $color = null; // initialize + $matches = array(); + + $color_regex = '/^\\[[a-zA-Z]+\\]/'; + if (preg_match($color_regex, $pFormat, $matches)) { + $color = str_replace('[', '', $matches[0]); + $color = str_replace(']', '', $color); + $color = strtolower($color); + } + + // convert to PCDATA + $value = htmlspecialchars($pValue); + + // color span tag + if ($color !== null) { + $value = '' . $value . ''; + } + + return $value; + } + + /** + * Calculate information about HTML colspan and rowspan which is not always the same as Excel's + */ + private function _calculateSpans() + { + // Identify all cells that should be omitted in HTML due to cell merge. + // In HTML only the upper-left cell should be written and it should have + // appropriate rowspan / colspan attribute + $sheetIndexes = $this->_sheetIndex !== null ? + array($this->_sheetIndex) : range(0, $this->_phpExcel->getSheetCount() - 1); + + foreach ($sheetIndexes as $sheetIndex) { + $sheet = $this->_phpExcel->getSheet($sheetIndex); + + $candidateSpannedRow = array(); + + // loop through all Excel merged cells + foreach ($sheet->getMergeCells() as $cells) { + list($cells, ) = PHPExcel_Cell::splitRange($cells); + $first = $cells[0]; + $last = $cells[1]; + + list($fc, $fr) = PHPExcel_Cell::coordinateFromString($first); + $fc = PHPExcel_Cell::columnIndexFromString($fc) - 1; + + list($lc, $lr) = PHPExcel_Cell::coordinateFromString($last); + $lc = PHPExcel_Cell::columnIndexFromString($lc) - 1; + + // loop through the individual cells in the individual merge + $r = $fr - 1; + while($r++ < $lr) { + // also, flag this row as a HTML row that is candidate to be omitted + $candidateSpannedRow[$r] = $r; + + $c = $fc - 1; + while($c++ < $lc) { + if ( !($c == $fc && $r == $fr) ) { + // not the upper-left cell (should not be written in HTML) + $this->_isSpannedCell[$sheetIndex][$r][$c] = array( + 'baseCell' => array($fr, $fc), + ); + } else { + // upper-left is the base cell that should hold the colspan/rowspan attribute + $this->_isBaseCell[$sheetIndex][$r][$c] = array( + 'xlrowspan' => $lr - $fr + 1, // Excel rowspan + 'rowspan' => $lr - $fr + 1, // HTML rowspan, value may change + 'xlcolspan' => $lc - $fc + 1, // Excel colspan + 'colspan' => $lc - $fc + 1, // HTML colspan, value may change + ); + } + } + } + } + + // Identify which rows should be omitted in HTML. These are the rows where all the cells + // participate in a merge and the where base cells are somewhere above. + $countColumns = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn()); + foreach ($candidateSpannedRow as $rowIndex) { + if (isset($this->_isSpannedCell[$sheetIndex][$rowIndex])) { + if (count($this->_isSpannedCell[$sheetIndex][$rowIndex]) == $countColumns) { + $this->_isSpannedRow[$sheetIndex][$rowIndex] = $rowIndex; + }; + } + } + + // For each of the omitted rows we found above, the affected rowspans should be subtracted by 1 + if ( isset($this->_isSpannedRow[$sheetIndex]) ) { + foreach ($this->_isSpannedRow[$sheetIndex] as $rowIndex) { + $adjustedBaseCells = array(); + $c = -1; + $e = $countColumns - 1; + while($c++ < $e) { + $baseCell = $this->_isSpannedCell[$sheetIndex][$rowIndex][$c]['baseCell']; + + if ( !in_array($baseCell, $adjustedBaseCells) ) { + // subtract rowspan by 1 + --$this->_isBaseCell[$sheetIndex][ $baseCell[0] ][ $baseCell[1] ]['rowspan']; + $adjustedBaseCells[] = $baseCell; + } + } + } + } + + // TODO: Same for columns + } + + // We have calculated the spans + $this->_spansAreCalculated = true; + } + + private function _setMargins(PHPExcel_Worksheet $pSheet) { + $htmlPage = '@page { '; + $htmlBody = 'body { '; + + $left = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getLeft()) . 'in; '; + $htmlPage .= 'left-margin: ' . $left; + $htmlBody .= 'left-margin: ' . $left; + $right = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getRight()) . 'in; '; + $htmlPage .= 'right-margin: ' . $right; + $htmlBody .= 'right-margin: ' . $right; + $top = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getTop()) . 'in; '; + $htmlPage .= 'top-margin: ' . $top; + $htmlBody .= 'top-margin: ' . $top; + $bottom = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getBottom()) . 'in; '; + $htmlPage .= 'bottom-margin: ' . $bottom; + $htmlBody .= 'bottom-margin: ' . $bottom; + + $htmlPage .= "}\n"; + $htmlBody .= "}\n"; + + return "\n"; + } + +} diff --git a/framework/library/phpexcel/PHPExcel/Writer/PDF/DomPDF.php b/framework/library/phpexcel/PHPExcel/Writer/PDF/DomPDF.php new file mode 100644 index 0000000..2edc2d0 --- /dev/null +++ b/framework/library/phpexcel/PHPExcel/Writer/PDF/DomPDF.php @@ -0,0 +1,120 @@ +getSheetIndex())) { + $orientation = ($this->_phpExcel->getSheet(0)->getPageSetup()->getOrientation() + == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + $printPaperSize = $this->_phpExcel->getSheet(0)->getPageSetup()->getPaperSize(); + $printMargins = $this->_phpExcel->getSheet(0)->getPageMargins(); + } else { + $orientation = ($this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getOrientation() + == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + $printPaperSize = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getPaperSize(); + $printMargins = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageMargins(); + } + + // Override Page Orientation + if (!is_null($this->getOrientation())) { + $orientation = ($this->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT) + ? PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT + : $this->getOrientation(); + } + // Override Paper Size + if (!is_null($this->getPaperSize())) { + $printPaperSize = $this->getPaperSize(); + } + + if (isset(self::$_paperSizes[$printPaperSize])) { + $paperSize = self::$_paperSizes[$printPaperSize]; + } + + $orientation = ($orientation == 'L') ? 'landscape' : 'portrait'; + + // Create PDF + $pdf = new DOMPDF(); + $pdf->set_paper(strtolower($paperSize), $orientation); + + $pdf->load_html( + $this->generateHTMLHeader(FALSE) . + $this->generateSheetData() . + $this->generateHTMLFooter() + ); + $pdf->render(); + + // Write to file + fwrite($fileHandle, $pdf->output()); + + parent::restoreStateAfterSave($fileHandle); + } + +} diff --git a/web/common/frames.inc.php b/web/common/frames.inc.php new file mode 100644 index 0000000..d74ad2a --- /dev/null +++ b/web/common/frames.inc.php @@ -0,0 +1,183 @@ + '平台', + 'icon' => 'wi wi-platform-manage', + 'dimension' => 2, + 'url' => url('account/manage'), + 'section' => array( + 'account_manage' => array( + 'title' => '平台管理', + 'menu' => array( + 'account_manage_display' => array( + 'title' => '平台列表', + 'url' => url('account/manage'), + 'permission_name' => 'account_manage_display', + 'sub_permission' => array( + array( + 'title' => '帐号停用', + 'permission_name' => 'account_manage_stop', + ), + ), + ), + ), + ), + ), + 'founder' => true, +); + +$w7_system_menu['user_manage'] = array( + 'title' => '用户', + 'icon' => 'wi wi-user-group', + 'dimension' => 2, + 'url' => url('user/display'), + 'section' => array( + 'user_manage' => array( + 'title' => '用户管理', + 'menu' => array( + 'user_manage_display' => array( + 'title' => '普通用户', + 'url' => url('user/display'), + 'permission_name' => 'user_manage_display', + 'sub_permission' => array(), + ), + 'user_manage_recycle' => array( + 'title' => '回收站', + 'url' => url('user/display', array('type' => 'recycle')), + 'permission_name' => 'user_manage_recycle', + 'sub_permission' => array(), + ), + ), + ), + ), + 'founder' => true, +); + +$w7_system_menu['site'] = array( + 'title' => '设置', + 'menu-title' => '系统设置', + 'icon' => 'wi wi-system-info', + 'dimension' => 3, + 'url' => url('system/site'), + 'section' => array( + 'setting' => array( + 'title' => '设置', + 'menu' => array( + 'system_setting_site' => array( + 'title' => '站点设置', + 'url' => url('system/site'), + 'permission_name' => 'system_setting_site', + ), + 'system_setting_attachment' => array( + 'title' => '附件设置', + 'url' => url('system/attachment/remote'), + 'permission_name' => 'system_setting_attachment', + ), + ), + ), + 'utility' => array( + 'title' => '常用工具', + 'menu' => array( + 'system_utility_optimize' => array( + 'title' => '性能优化', + 'url' => url('system/optimize'), + 'permission_name' => 'system_utility_optimize', + ), + 'system_utility_check' => array( + 'title' => '系统检测', + 'url' => url('system/check'), + 'permission_name' => 'system_utility_check', + ), + ), + ), + ), + 'founder' => true, +); + +$w7_system_menu['cloud'] = array( + 'title' => '云服务', + 'menu-title' => '云服务中心', + 'icon' => 'wi wi-system-site', + 'dimension' => 3, + 'url' => url('cloud/auth/info'), + 'section' => array( + 'cloud_auth' => array( + 'title' => '云服务', + 'menu' => array( + 'cloud_auth_info' => array( + 'title' => '系统授权', + 'url' => url('cloud/auth/auth_info'), + 'permission_name' => 'cloud_auth_info', + ), + 'cloud_auth_upgrade' => array( + 'title' => '系统升级', + 'url' => url('cloud/auth/auth_upgrade'), + 'permission_name' => 'cloud_auth_upgrade', + ), + 'cloud_auth_upgrade_log' => array( + 'title' => '更新日志', + 'url' => url('cloud/auth/auth_upgrade_log'), + 'permission_name' => 'cloud_auth_upgrade_log', + ), + ), + ), + 'cloud_app' => array( + 'title' => '应用管理', + 'menu' => array( + 'cloud_app_info' => array( + 'title' => '应用信息', + 'url' => url('cloud/auth/app_info'), + 'permission_name' => 'cloud_app_info', + ), + 'cloud_app_pem' => array( + 'title' => '应用权限', + 'url' => url('cloud/auth/app_pem'), + 'permission_name' => 'cloud_app_pem', + ), + ), + ), + 'cloud_db' => array( + 'title' => '数据管理', + 'menu' => array( + 'cloud_dbm' => array( + 'title' => '数据管理', + 'url' => url('cloud/auth/db_m'), + 'permission_name' => 'cloud_dbm', + ), + 'cloud_db_sql' => array( + 'title' => '运行SQL', + 'url' => url('cloud/auth/db_sql'), + 'permission_name' => 'cloud_db_sql', + ), + ), + ), + 'cloud_set' => array( + 'title' => '系统设置', + 'menu' => array( + 'cloud_set_info' => array( + 'title' => '系统信息', + 'url' => url('cloud/auth/set_info'), + 'permission_name' => 'cloud_set_info', + ), + 'cloud_set_que' => array( + 'title' => '计划任务', + 'url' => url('cloud/auth/set_que'), + 'permission_name' => 'cloud_set_que', + ), + 'cloud_set_url' => array( + 'title' => '跳转域名', + 'url' => url('cloud/auth/set_url'), + 'permission_name' => 'cloud_set_url', + ), + ), + ), + ), + 'founder' => true, +); + +return $w7_system_menu; diff --git a/web/home.php b/web/home.php new file mode 100644 index 0000000..b0c2e61 --- /dev/null +++ b/web/home.php @@ -0,0 +1,30 @@ +i;)J(t,n=o[i++],e[n]);return t},Q=function(t){var e=R.call(this,t=S(t,!0));return!(this===V&&i(z,t)&&!i(D,t))&&(!(e||!i(this,t)||!i(z,t)||i(this,F)&&this[F][t])||e)},$=function(t,e){if(t=x(t),e=S(e,!0),t!==V||!i(z,e)||i(D,e)){var n=T(t,e);return!n||!i(z,e)||i(t,F)&&t[F][e]||(n.enumerable=!0),n}},Z=function(t){for(var e,n=_(x(t)),o=[],r=0;n.length>r;)i(z,e=n[r++])||e==F||e==c||o.push(e);return o},tt=function(t){for(var e,n=t===V,o=_(n?D:x(t)),r=[],s=0;o.length>s;)!i(z,e=o[s++])||n&&!i(V,e)||r.push(z[e]);return r};W||(a((M=function(){if(this instanceof M)throw TypeError("Symbol is not a constructor!");var t=f(arguments.length>0?arguments[0]:void 0),e=function(n){this===V&&e.call(D,n),i(this,F)&&i(this[F],t)&&(this[F][t]=!1),K(this,t,O(1,n))};return r&&G&&K(V,t,{configurable:!0,set:e}),U(t)}).prototype,"toString",function(){return this._k}),E.f=$,j.f=J,n(48).f=P.f=Z,n(29).f=Q,N.f=tt,r&&!n(18)&&a(V,"propertyIsEnumerable",Q,!0),d.f=function(t){return U(p(t))}),s(s.G+s.W+s.F*!W,{Symbol:M});for(var et="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),nt=0;et.length>nt;)p(et[nt++]);for(var ot=L(p.store),it=0;ot.length>it;)v(ot[it++]);s(s.S+s.F*!W,"Symbol",{for:function(t){return i(A,t+="")?A[t]:A[t]=M(t)},keyFor:function(t){if(!Y(t))throw TypeError(t+" is not a symbol!");for(var e in A)if(A[e]===t)return e},useSetter:function(){G=!0},useSimple:function(){G=!1}}),s(s.S+s.F*!W,"Object",{create:function(t,e){return void 0===e?k(t):X(k(t),e)},defineProperty:J,defineProperties:X,getOwnPropertyDescriptor:$,getOwnPropertyNames:Z,getOwnPropertySymbols:tt});var rt=u(function(){N.f(1)});s(s.S+s.F*rt,"Object",{getOwnPropertySymbols:function(t){return N.f(w(t))}}),H&&s(s.S+s.F*(!W||u(function(){var t=M();return"[null]"!=B([t])||"{}"!=B({a:t})||"{}"!=B(Object(t))})),"JSON",{stringify:function(t){for(var e,n,o=[t],i=1;arguments.length>i;)o.push(arguments[i++]);if(n=e=o[1],(b(e)||void 0!==t)&&!Y(t))return g(e)||(e=function(t,e){if("function"==typeof n&&(e=n.call(this,t,e)),!Y(e))return e}),o[1]=e,B.apply(H,o)}}),M.prototype[I]||n(4)(M.prototype,I,M.prototype.valueOf),h(M,"Symbol"),h(Math,"Math",!0),h(o.JSON,"JSON",!0)},function(t,e,n){var o=n(3);t.exports=function(t,e){if(!o(t))return t;var n,i;if(e&&"function"==typeof(n=t.toString)&&!o(i=n.call(t)))return i;if("function"==typeof(n=t.valueOf)&&!o(i=n.call(t)))return i;if(!e&&"function"==typeof(n=t.toString)&&!o(i=n.call(t)))return i;throw TypeError("Can't convert object to primitive value")}},function(t,e,n){var o=n(37);t.exports=function(t,e,n){if(o(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,o){return t.call(e,n,o)};case 3:return function(n,o,i){return t.call(e,n,o,i)}}return function(){return t.apply(e,arguments)}}},function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},function(t,e){t.exports=function(t){if(null==t)throw TypeError("Can't call method on "+t);return t}},function(t,e,n){"use strict";var o=n(7);t.exports=function(t,e){return!!t&&o(function(){e?t.call(null,function(){},1):t.call(null)})}},function(t,e,n){var o=n(5).f,i=n(8),r=n(1)("toStringTag");t.exports=function(t,e,n){t&&!i(t=n?t:t.prototype,r)&&o(t,r,{configurable:!0,value:e})}},function(t,e,n){var o=n(17)("keys"),i=n(14);t.exports=function(t){return o[t]||(o[t]=i(t))}},function(t,e){t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(t,e){e.f={}.propertyIsEnumerable},function(t,e,n){var o=n(12),i=n(65),r=n(28),s=n(27)("IE_PROTO"),a=function(){},c=function(){var t,e=n(36)("iframe"),o=r.length;for(e.style.display="none",n(66).appendChild(e),e.src="javascript:",(t=e.contentWindow.document).open(),t.write(" + + + +
+
+ + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + + + \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/emotion/emotion.js b/web/resource/components/ueditor/dialogs/emotion/emotion.js new file mode 100644 index 0000000..6e158a9 --- /dev/null +++ b/web/resource/components/ueditor/dialogs/emotion/emotion.js @@ -0,0 +1,186 @@ +window.onload = function () { + editor.setOpt({ + emotionLocalization:false + }); + + emotion.SmileyPath = editor.options.emotionLocalization === true ? 'images/' : "http://img.baidu.com/hi/"; + emotion.SmileyBox = createTabList( emotion.tabNum ); + emotion.tabExist = createArr( emotion.tabNum ); + + initImgName(); + initEvtHandler( "tabHeads" ); +}; + +function initImgName() { + for ( var pro in emotion.SmilmgName ) { + var tempName = emotion.SmilmgName[pro], + tempBox = emotion.SmileyBox[pro], + tempStr = ""; + + if ( tempBox.length ) return; + for ( var i = 1; i <= tempName[1]; i++ ) { + tempStr = tempName[0]; + if ( i < 10 ) tempStr = tempStr + '0'; + tempStr = tempStr + i + '.gif'; + tempBox.push( tempStr ); + } + } +} + +function initEvtHandler( conId ) { + var tabHeads = $G( conId ); + for ( var i = 0, j = 0; i < tabHeads.childNodes.length; i++ ) { + var tabObj = tabHeads.childNodes[i]; + if ( tabObj.nodeType == 1 ) { + domUtils.on( tabObj, "click", (function ( index ) { + return function () { + switchTab( index ); + }; + })( j ) ); + j++; + } + } + switchTab( 0 ); + $G( "tabIconReview" ).style.display = 'none'; +} + +function InsertSmiley( url, evt ) { + var obj = { + src:editor.options.emotionLocalization ? editor.options.UEDITOR_HOME_URL + "dialogs/emotion/" + url : url + }; + obj._src = obj.src; + editor.execCommand( 'insertimage', obj ); + if ( !evt.ctrlKey ) { + dialog.popup.hide(); + } +} + +function switchTab( index ) { + + autoHeight( index ); + if ( emotion.tabExist[index] == 0 ) { + emotion.tabExist[index] = 1; + createTab( 'tab' + index ); + } + //获取呈现元素句柄数组 + var tabHeads = $G( "tabHeads" ).getElementsByTagName( "span" ), + tabBodys = $G( "tabBodys" ).getElementsByTagName( "div" ), + i = 0, L = tabHeads.length; + //隐藏所有呈现元素 + for ( ; i < L; i++ ) { + tabHeads[i].className = ""; + tabBodys[i].style.display = "none"; + } + //显示对应呈现元素 + tabHeads[index].className = "focus"; + tabBodys[index].style.display = "block"; +} + +function autoHeight( index ) { + var iframe = dialog.getDom( "iframe" ), + parent = iframe.parentNode.parentNode; + switch ( index ) { + case 0: + iframe.style.height = "380px"; + parent.style.height = "392px"; + break; + case 1: + iframe.style.height = "220px"; + parent.style.height = "232px"; + break; + case 2: + iframe.style.height = "260px"; + parent.style.height = "272px"; + break; + case 3: + iframe.style.height = "300px"; + parent.style.height = "312px"; + break; + case 4: + iframe.style.height = "140px"; + parent.style.height = "152px"; + break; + case 5: + iframe.style.height = "260px"; + parent.style.height = "272px"; + break; + case 6: + iframe.style.height = "230px"; + parent.style.height = "242px"; + break; + default: + + } +} + + +function createTab( tabName ) { + var faceVersion = "?v=1.1", //版本号 + tab = $G( tabName ), //获取将要生成的Div句柄 + imagePath = emotion.SmileyPath + emotion.imageFolders[tabName], //获取显示表情和预览表情的路径 + positionLine = 11 / 2, //中间数 + iWidth = iHeight = 35, //图片长宽 + iColWidth = 3, //表格剩余空间的显示比例 + tableCss = emotion.imageCss[tabName], + cssOffset = emotion.imageCssOffset[tabName], + textHTML = ['
element because TCPDF + // does not recognize e.g.
element because TCPDF + // does not recognize e.g.
'], + i = 0, imgNum = emotion.SmileyBox[tabName].length, imgColNum = 11, faceImage, + sUrl, realUrl, posflag, offset, infor; + + for ( ; i < imgNum; ) { + textHTML.push( '' ); + for ( var j = 0; j < imgColNum; j++, i++ ) { + faceImage = emotion.SmileyBox[tabName][i]; + if ( faceImage ) { + sUrl = imagePath + faceImage + faceVersion; + realUrl = imagePath + faceImage; + posflag = j < positionLine ? 0 : 1; + offset = cssOffset * i * (-1) - 1; + infor = emotion.SmileyInfor[tabName][i]; + + textHTML.push( '' ); + } + textHTML.push( '' ); + } + textHTML.push( '
' ); + textHTML.push( '' ); + textHTML.push( '' ); + textHTML.push( '' ); + } else { + textHTML.push( '' ); + } + textHTML.push( '
' ); + textHTML = textHTML.join( "" ); + tab.innerHTML = textHTML; +} + +function over( td, srcPath, posFlag ) { + td.style.backgroundColor = "#ACCD3C"; + $G( 'faceReview' ).style.backgroundImage = "url(" + srcPath + ")"; + if ( posFlag == 1 ) $G( "tabIconReview" ).className = "show"; + $G( "tabIconReview" ).style.display = 'block'; +} + +function out( td ) { + td.style.backgroundColor = "transparent"; + var tabIconRevew = $G( "tabIconReview" ); + tabIconRevew.className = ""; + tabIconRevew.style.display = 'none'; +} + +function createTabList( tabNum ) { + var obj = {}; + for ( var i = 0; i < tabNum; i++ ) { + obj["tab" + i] = []; + } + return obj; +} + +function createArr( tabNum ) { + var arr = []; + for ( var i = 0; i < tabNum; i++ ) { + arr[i] = 0; + } + return arr; +} + diff --git a/web/resource/components/ueditor/dialogs/emotion/images/fface.gif b/web/resource/components/ueditor/dialogs/emotion/images/fface.gif new file mode 100644 index 0000000..0d8a6af Binary files /dev/null and b/web/resource/components/ueditor/dialogs/emotion/images/fface.gif differ diff --git a/web/resource/components/ueditor/dialogs/gmap/gmap.html b/web/resource/components/ueditor/dialogs/gmap/gmap.html new file mode 100644 index 0000000..c4cbfe6 --- /dev/null +++ b/web/resource/components/ueditor/dialogs/gmap/gmap.html @@ -0,0 +1,89 @@ + + + + + + + + + + +
+ + + + + + +
+
+
+ + + \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/help/help.css b/web/resource/components/ueditor/dialogs/help/help.css new file mode 100644 index 0000000..8e72827 --- /dev/null +++ b/web/resource/components/ueditor/dialogs/help/help.css @@ -0,0 +1 @@ +.wrapper{width:370px;margin:10px auto;zoom:1}.tabbody{height:360px}.tabbody .panel{width:100%;height:360px;position:absolute;background:#fff}.tabbody .panel h1{font-size:26px;margin:5px 0 0 5px}.tabbody .panel p{font-size:12px;margin:5px 0 0 5px}.tabbody table{width:90%;line-height:20px;margin:5px 0 0 5px}.tabbody table thead{font-weight:700;line-height:25px} \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/help/help.html b/web/resource/components/ueditor/dialogs/help/help.html new file mode 100644 index 0000000..9e50060 --- /dev/null +++ b/web/resource/components/ueditor/dialogs/help/help.html @@ -0,0 +1,82 @@ + + + + 帮助 + + + + + +
+
+ + +
+
+
+

UEditor

+

+

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ctrl+b
ctrl+c
ctrl+x
ctrl+v
ctrl+y
ctrl+z
ctrl+i
ctrl+u
ctrl+a
shift+enter
alt+z
+
+
+
+ + + \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/help/help.js b/web/resource/components/ueditor/dialogs/help/help.js new file mode 100644 index 0000000..9a2272e --- /dev/null +++ b/web/resource/components/ueditor/dialogs/help/help.js @@ -0,0 +1,56 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-9-26 + * Time: 下午1:06 + * To change this template use File | Settings | File Templates. + */ +/** + * tab点击处理事件 + * @param tabHeads + * @param tabBodys + * @param obj + */ +function clickHandler( tabHeads,tabBodys,obj ) { + //head样式更改 + for ( var k = 0, len = tabHeads.length; k < len; k++ ) { + tabHeads[k].className = ""; + } + obj.className = "focus"; + //body显隐 + var tabSrc = obj.getAttribute( "tabSrc" ); + for ( var j = 0, length = tabBodys.length; j < length; j++ ) { + var body = tabBodys[j], + id = body.getAttribute( "id" ); + body.onclick = function(){ + this.style.zoom = 1; + }; + if ( id != tabSrc ) { + body.style.zIndex = 1; + } else { + body.style.zIndex = 200; + } + } + +} + +/** + * TAB切换 + * @param tabParentId tab的父节点ID或者对象本身 + */ +function switchTab( tabParentId ) { + var tabElements = $G( tabParentId ).children, + tabHeads = tabElements[0].children, + tabBodys = tabElements[1].children; + + for ( var i = 0, length = tabHeads.length; i < length; i++ ) { + var head = tabHeads[i]; + if ( head.className === "focus" )clickHandler(tabHeads,tabBodys, head ); + head.onclick = function () { + clickHandler(tabHeads,tabBodys,this); + } + } +} +switchTab("helptab"); + +document.getElementById('version').innerHTML = parent.UE.version; \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/map/getscript.js b/web/resource/components/ueditor/dialogs/map/getscript.js new file mode 100644 index 0000000..594d363 --- /dev/null +++ b/web/resource/components/ueditor/dialogs/map/getscript.js @@ -0,0 +1,3 @@ +window.TILE_VERSION={"ditu":{"normal":{"version":"088","updateDate":"20171228"},"satellite":{"version":"009","updateDate":"20171228"},"normalTraffic":{"version":"081","updateDate":"20171228"},"satelliteTraffic":{"version":"083","updateDate":"20171228"},"mapJS":{"version":"104","updateDate":"20171228"},"satelliteStreet":{"version":"083","updateDate":"20171228"},"panoClick":{"version":"1033","updateDate":"20171225"},"panoUdt":{"version":"20171225","updateDate":"20171225"},"panoSwfAPI":{"version":"20150123","updateDate":"20150123"},"panoSwfPlace":{"version":"20141112","updateDate":"20141112"},"earthVector":{"version":"001","updateDate":"20171228"}},"webapp":{"high_normal":{"version":"001","updateDate":"20171228"},"lower_normal":{"version":"002","updateDate":"20171228"}},"api_for_mobile":{"vector":{"version":"002","updateDate":"20171228"},"vectorIcon":{"version":"002","updateDate":"20171228"}}};window.BMAP_AUTHENTIC_KEY="";(function(){var l=l||{version:"20080809",emptyFn:function(){}};(function(){l._log=[];var i=0;var aT={};l.BaseClass=function(aU){aT[(this.hashCode=(aU||l.BaseClass.guid()))]=this};l.BaseClass.guid=function(){return"mz_"+(i++).toString(36)};l.BaseClass.create=function(){var aU=new l.BaseClass();aU.decontrol();return aU};var e=l.instance=l.I=function(aU){return aT[aU]};l.BaseClass.prototype.dispose=function(){if(this.hashCode){delete aT[this.hashCode]}for(var aU in this){if(typeof this[aU]!="function"){delete this[aU]}}};l.BaseClass.prototype.getHashCode=function(){if(!this.hashCode){aT[(this.hashCode=l.BaseClass.guid())]=this}return this.hashCode};l.BaseClass.prototype.decontrol=function(){delete aT[this.hashCode]};l.BaseClass.prototype.toString=function(){return"[object "+(this._className||"Object")+"]"};l.BaseClass.prototype._wlog=function(aV,aW){var aU=l._log;if(aU.length>100){aU.reverse().length=50;aU.reverse()}aU[aU.length]="["+aV+"]["+(this._className||"Object")+" "+this.hashCode+"] "+aW}})();Function.prototype.inherits=function(aU,aT){var e,aV,aX=this.prototype,aW=function(){};aW.prototype=aU.prototype;aV=this.prototype=new aW();if(typeof(aT)=="string"){aV._className=aT}for(e in aX){aV[e]=aX[e]}this.prototype.constructor=aX.constructor;aX=aW=null;return aV};l.BaseEvent=function(e,i){this.type=e;this.returnValue=true;this.target=i||null;this.currentTarget=this.srcElement=null;this.cancelBubble=false;this.domEvent=null};l.BaseClass.prototype.addEventListener=function(aU,aT,i){if(typeof aT!="function"){return this._wlog("error","addEventListener:"+aT+" is not a function")}if(!this._listeners){this._listeners={}}var e=this._listeners,aV;if(typeof i=="string"&&i){if(/[^\w\-]/.test(i)){this._wlog("warning","nonstandard key:"+i)}else{aT.hashCode=i;aV=i}}if(aU.indexOf("on")!=0){aU="on"+aU}if(typeof e[aU]!="object"){e[aU]={}}aV=aV||l.BaseClass.guid();aT.hashCode=aV;if(e[aU][aV]){this._wlog("warning","repeat key:"+aV)}e[aU][aV]=aT};l.BaseClass.prototype.removeEventListener=function(aT,i){if(typeof i=="function"){i=i.hashCode}else{if(typeof i!="string"){return}}if(!this._listeners){this._listeners={}}if(aT.indexOf("on")!=0){aT="on"+aT}var e=this._listeners;if(!e[aT]){return}if(e[aT][i]){delete e[aT][i]}};l.BaseClass.prototype.dispatchEvent=function(aU){if(!this._listeners){this._listeners={}}var aT,e=this._listeners,aV=aU.type;aU.target=aU.srcElement=aU.target||aU.srcElement||this;aU.currentTarget=this;if(typeof this[aV]=="function"){this[aV](aU)}if(typeof e[aV]=="object"){for(aT in e[aV]){if(typeof e[aV][aT]=="function"){e[aV][aT].call(this,aU)}}}return aU.returnValue};l.BaseEvent.prototype.inherit=function(aV){var aU=this;this.domEvent=aV=window.event||aV;aU.clientX=aV.clientX||aV.pageX;aU.clientY=aV.clientY||aV.pageY;aU.offsetX=aV.offsetX||aV.layerX;aU.offsetY=aV.offsetY||aV.layerY;aU.screenX=aV.screenX;aU.screenY=aV.screenY;aU.ctrlKey=aV.ctrlKey||aV.metaKey;aU.shiftKey=aV.shiftKey;aU.altKey=aV.altKey;if(aV.touches){aU.touches=[];for(var aT=0;aT-1&&/Version\/(\d+(\.\d+)?)/.test(aT)){i=parseFloat(RegExp.$1)}}}}}if(aT.indexOf("Gecko")>-1&&aT.indexOf("KHTML")==-1&&/rv\:(\d+(\.\d+)?)/.test(aT)){aU=parseFloat(RegExp.$1)}if(/chrome\/(\d+\.\d)/i.test(aT)){aW=parseFloat(RegExp["\x241"])}return{ie:e,firefox:aY,gecko:aU,netscape:aX,opera:aV,safari:i,chrome:aW}})();window.FeBrowser=l.Browser;l.Dom={};l.Dom.createDom=function(i,e){if(l.isIE&&e&&e.name){i="<"+i+' name="'+l.String.escapeHTML(e.name)+'">'}var aT=document.createElement(i);if(e){l.Dom.setProperties(aT,e)}return aT};l.Dom.getOffset=function(aU){var aX=l.Dom.getOwnerDocument(aU);var aW=l.isGecko>0&&aX.getBoxObjectFor&&l.Dom.getStyle(aU,"position")=="absolute"&&(aU.style.top===""||aU.style.left==="");var aY={left:0,top:0};var i=(l.isIE&&!l.isStrict)?aX.body:aX.documentElement;if(aU==i){return aY}var aT=null;var aV;if(aU.getBoundingClientRect){aV=aU.getBoundingClientRect();aY.left=aV.left+Math.max(aX.documentElement.scrollLeft,aX.body.scrollLeft);aY.top=aV.top+Math.max(aX.documentElement.scrollTop,aX.body.scrollTop);aY.left-=aX.documentElement.clientLeft;aY.top-=aX.documentElement.clientTop;if(l.isIE&&!l.isStrict){aY.left-=2;aY.top-=2}}else{if(aX.getBoxObjectFor&&!aW){aV=aX.getBoxObjectFor(aU);var e=aX.getBoxObjectFor(i);aY.left=aV.screenX-e.screenX;aY.top=aV.screenY-e.screenY}else{aT=aU;do{aY.left+=aT.offsetLeft;aY.top+=aT.offsetTop;if(l.isWebkit>0&&l.Dom.getStyle(aT,"position")=="fixed"){aY.left+=aX.body.scrollLeft;aY.top+=aX.body.scrollTop;break}aT=aT.offsetParent}while(aT&&aT!=aU);if(l.isOpera>0||(l.isWebkit>0&&l.Dom.getStyle(aU,"position")=="absolute")){aY.top-=aX.body.offsetTop}aT=aU.offsetParent;while(aT&&aT!=aX.body){aY.left-=aT.scrollLeft;if(!l.isOpera||aT.tagName!="TR"){aY.top-=aT.scrollTop}aT=aT.offsetParent}}}return aY};l.Dom.getOwnerDocument=function(e){return e.nodeType==9?e:e.ownerDocument||e.document};l.Dom.setProperties=function(i,e){l.each(e,function(aU,aT){l.Dom._setProperty(i,aT,aU)})};l.Dom._setProperty=function(i,e,aT){if(e=="style"){i.style.cssText=aT}else{if(e=="class"){i.className=aT}else{if(e=="for"){i.htmlFor=aT}else{if(e in l.Dom._DIRECT_ATTRIBUTE_MAP){i.setAttribute(l.Dom._DIRECT_ATTRIBUTE_MAP[e],aT)}else{i[e]=aT}}}}};l.Dom._DIRECT_ATTRIBUTE_MAP={cellpadding:"cellPadding",cellspacing:"cellSpacing",colspan:"colSpan",rowspan:"rowSpan",valign:"vAlign",height:"height",width:"width",usemap:"useMap",frameborder:"frameBorder"};l.G=function(){for(var aT=[],aU=arguments.length-1;aU>-1;aU--){var aV=arguments[aU];aT[aU]=null;if(typeof aV=="object"&&aV&&aV.dom){aT[aU]=aV.dom}else{if((typeof aV=="object"&&aV&&aV.tagName)||aV==window||aV==document){aT[aU]=aV}else{if(typeof aV=="string"&&(aV=document.getElementById(aV))){aT[aU]=aV}}}}return aT.length<2?aT[0]:aT};l.ac=function(e,i){if(!(e=this.G(e))){return}i=this.trim(i);if(!new RegExp("(^| )"+i.replace(/(\W)/g,"\\$1")+"( |$)").test(e.className)){e.className=e.className.split(/\s+/).concat(i).join(" ")}};l.addClassName=l.ac;l.each=function(aW,e){if(typeof e!="function"){return aW}if(aW){if(aW.length===undefined){for(var aT in aW){e.call(aW[aT],aW[aT],aT)}}else{for(var aU=0,aV=aW.length;aU0&&!window.opera){/MSIE (\d+(\.\d+)?)/.test(navigator.userAgent);l.isIE=parseFloat(RegExp.$1)}})();l.rc=function(e,i){if(!(e=this.G(e))){return}i=this.trim(i);var aT=e.className.replace(new RegExp("(^| +)"+i.replace(/(\W)/g,"\\$1")+"( +|$)","g"),"$2");if(e.className!=aT){e.className=aT}};l.removeClassName=l.rc;l.show=function(){this.each(arguments,function(e){if(e=l.G(e)){e.style.display=""}})};l.trim=function(e){return e.replace(/(^[\s\t\xa0\u3000]+)|([\u3000\xa0\s\t]+$)/g,"")};var E=l.BaseClass;E.prototype.toString=function(){return this._className||""};var aw=l.BaseEvent;l.on=function(aT,i,e){if(!(aT=l.G(aT))){return aT}i=i.replace(/^on/,"").toLowerCase();if(aT.addEventListener){aT.addEventListener(i,e,false)}else{if(aT.attachEvent){aT.attachEvent("on"+i,e)}}return aT};l.un=function(aT,i,e){if(!(aT=l.G(aT))){return aT}i=i.replace(/^on/,"").toLowerCase();if(aT.removeEventListener){aT.removeEventListener(i,e,false)}else{if(aT.detachEvent){aT.detachEvent("on"+i,e)}}return aT};l.hc=function(aU,aT){if(!aU||!aU.className||typeof aU.className!="string"){return false}var i=-1;try{i=aU.className==aT||aU.className.search(new RegExp("(\\s|^)"+aT+"(\\s|$)"))}catch(aV){return false}return i>-1};if(typeof HTMLElement!="undefined"&&HTMLElement.prototype.__lookupGetter__&&!HTMLElement.prototype.__lookupGetter__("children")&&!window.opera){try{HTMLElement.prototype.__defineGetter__("children",function(){for(var aT=[],aU=0,aW,aV=0,e=this.childNodes.length;aV=i._endTime){if(typeof i._opts.render=="function"){i._opts.render(i._opts.transition(1))}if(typeof i._opts.finish=="function"){i._opts.finish()}return}i.schedule=i._opts.transition((e-i._beginTime)/i._opts.duration);if(typeof i._opts.render=="function"){i._opts.render(i.schedule)}if(!i.terminative){i._timer=setTimeout(function(){i._launch()},1000/i._opts.fps)}};aG.prototype.stop=function(e){this.terminative=true;if(this._timer){clearTimeout(this._timer)}if(e){this._endTime=this._beginTime;this._launch()}};aG.prototype.cancel=function(){if(this._timer){clearTimeout(this._timer)}this._endTime=this._beginTime;this.schedule=0};var k={linear:function(e){return e},reverse:function(e){return 1-e},easeInQuad:function(e){return e*e},easeInCubic:function(e){return Math.pow(e,3)},easeOutQuad:function(e){return -(e*(e-2))},easeOutCubic:function(e){return Math.pow((e-1),3)+1},easeInOutQuad:function(e){if(e<0.5){return e*e*2}else{return -2*(e-2)*e-1}return},easeInOutCubic:function(e){if(e<0.5){return Math.pow(e,3)*4}else{return Math.pow(e-1,3)*4+1}},easeInOutSine:function(e){return(1-Math.cos(Math.PI*e))/2}};function al(e){return e.style}function aR(aT,e){var i=al(aT);i.left=j(e[0]);i.top=j(e[1])}function B(aT,i){var e=al(aT);e.opacity=i;e.MozOpacity=i;e.KhtmlOpacity=i;e.filter="alpha(opacity="+(i*100)+")";e=null}function j(aT){if(typeof aT=="number"){return aT+"px"}else{if(typeof aT=="string"){var i=/"\\s","g"/;var aU=/"^\\d+(px|%)+$","i"/;var e=aT.replace(i,"");if(aU.exec(e)){return e}var aV=new RegExp("^\\d+$");if(aV.exec(e)){return e+"px"}return"0px"}}}function p(e){if(l.Browser.ie>0){e.unselectable="on";e.selectstart=function(){return false}}else{al(e).MozUserSelect="none"}}function aP(aT,e){var i=al(aT);i.width=j(e[0]);i.height=j(e[1])}function s(e){return e&&e.parentNode&&e.parentNode.nodeType!=11}function Z(i,e){i.insertAdjacentHTML("beforeEnd",e);return i.lastChild}function A(e){var i={left:0,top:0};while(e&&e.offsetParent){i.left+=e.offsetLeft;i.top+=e.offsetTop;e=e.offsetParent}return i}function ag(i){var i=window.event||i;i.stopPropagation?i.stopPropagation():i.cancelBubble=true}function D(i){var i=window.event||i;i.preventDefault?i.preventDefault():i.returnValue=false;return false}function aC(i){ag(i);return D(i)}function M(){var e=document.documentElement,i=document.body;if(e&&(e.scrollTop||e.scrollLeft)){return[e.scrollTop,e.scrollLeft]}else{if(i){return[i.scrollTop,i.scrollLeft]}else{return[0,0]}}}function o(aV){if(!aV){return}var aT=aV.attributes,aU,e,aW;if(aT){e=aT.length;for(aU=0;aU>4);a0=((aZ&15)<<4)|(aX>>2);aY=((aX&3)<<6)|aW;aT=aT+String.fromCharCode(a2);if(aX!=64){aT=aT+String.fromCharCode(a0)}if(aW!=64){aT=aT+String.fromCharCode(aY)}a2=a0=aY="";a1=aZ=aX=aW=""}while(aUi.maxX&&aV>=0){a2=this.offsetX}if(this.centerPoint.lat-this.height/2*aW<=i.minY&&aT>=0||this.centerPoint.lat+this.height/2*aW>i.maxY&&aT<0){a0=this.offsetY}this.centerPoint=new f(aY.lng+(this.offsetX-a2)*aW,aY.lat-(this.offsetY-a0)*aW);var aX=new aw("onreachbounds");this.dispatchEvent(aX)}a2=Math.round(a2);a0=Math.round(a0);this.offsetX=a2;this.offsetY=a0;this.platform.style.left=a2+"px";this.platform.style.top=a0+"px";this.maskLayer.style.left=-a2+"px";this.maskLayer.style.top=-a0+"px";if(this.divhs){this.divhs.style.left=-a2+"px";this.divhs.style.top=-a0+"px"}if(a3!=false){this.dispatchEvent(new aw("onmoving"))}},zoomTo:function(aX,i){if(typeof aX!="number"){return}var aW=aJ[this.mapType];if(!aW){return}aX=this._getProperZoom(aX).zoom;if(aX==this.zoomLevel){return}this.lastLevel=this.zoomLevel;if(i){this.temp._cPoint=i;this.temp._cPixel=this.pointToPixel(i)}else{if(this.getInfoWindow()){var aV=this.getInfoWindow().getPoint();this.temp._cPixel=this.pointToPixel(aV);this.temp._cPoint=aV}}if(i||this.temp.infoWin&&this.temp.infoWin.isOpen()){var aT=this.config.coordType==BMAP_COORD_LNGLAT?ar.convertLL2MC(this.temp._cPoint):this.temp._cPoint;var e=this.temp._cPixel;var aU=this.getZoomUnits(aX);this.centerPoint=new f(aT.lng+aU*(this.width/2-e.x),aT.lat-aU*(this.height/2-e.y))}this.dispatchEvent(new aw("onzoomstart"));this.dispatchEvent(new aw("onzoomstartcode"));this.zoomLevel=aX},zoomIn:function(e){this.zoomTo(this.zoomLevel+1,e)},zoomOut:function(e){this.zoomTo(this.zoomLevel-1,e)},panTo:function(i,aU,aV){if(!i||i.toString()!="Point"){return}var aT=this.pointToPixel(i);i=this.config.coordType==BMAP_COORD_LNGLAT?V.convertLL2MC(i):i;i=this.mapType==BMAP_PERSPECTIVE_MAP?V.convert2DTo3D(this.currentCity,i):i;var e=Math.round(this.width/2);var aW=Math.round(this.height/2);if(Math.abs(e-aT.x)>this.width||Math.abs(aW-aT.y)>this.height||aU==true){this._panTo(e-aT.x,aW-aT.y,i)}else{this._panBy(e-aT.x,aW-aT.y,{duration:aV})}},_panTo:function(i,e,aU){var aT=this.temp;if(aT.operating==true){return}if(aT.dragAni){aT.dragAni.stop();aT.dragAni=null;this.dispatchEvent(new aw("onmoveend"))}this.dispatchEvent(new aw("onmovestart"));this._setPlatformPosition(this.offsetX+i,this.offsetY+e,aU);this.dispatchEvent(new aw("onmoveend"))},panBy:function(i,e){i=Math.round(i)||0;e=Math.round(e)||0;if(Math.abs(i)<=this.width&&Math.abs(e)<=this.height&&!arguments[3]){this._panBy(i,e,{fps:arguments[2]})}else{this._panTo(i,e)}},_panBy:function(i,e,aV){if(this.temp.operating==true){return}aV=aV||{};this.dispatchEvent(new aw("onmovestart"));var aU=this,aT=aU.temp;aT.pl=aU.offsetX;aT.pt=aU.offsetY;if(aT.tlPan){aT.tlPan.cancel()}if(aT.dragAni){aT.dragAni.stop();aT.dragAni=null;this.dispatchEvent(new aw("onmoveend"))}aT.tlPan=new aG({fps:aV.fps||aU.config.fps,duration:aV.duration||aU.config.actionDuration,transition:aV.transition||k.easeInOutQuad,render:function(aW){this.terminative=aU.temp.operating;if(aU.temp.operating){return}aU._setPlatformPosition(aT.pl+Math.ceil(i*aW),aT.pt+Math.ceil(e*aW))},finish:function(aW){aU.dispatchEvent(new aw("onmoveend"));aU.temp.tlPan=false;if(aU.temp.stopArrow==true){aU.temp.stopArrow=false;if(aU.temp.arrow!=0){aU._arrow()}}}})},addControl:function(e){if(e&&av(e._i)){e._i(this);this.dispatchEvent(new aw("onaddcontrol",e))}},removeControl:function(e){if(e&&av(e.remove)){e.remove();this.dispatchEvent(new aw("onremovecontrol",e))}},addContextMenu:function(e){if(e&&e._type=="contextmenu"&&typeof e.initialize=="function"){e.initialize(this);this.dispatchEvent(new aw("onaddcontextmenu",e))}},removeContextMenu:function(e){if(e&&e._type=="contextmenu"&&typeof e.remove=="function"){this.dispatchEvent(new aw("onremovecontextmenu",e));e.remove()}},addOverlay:function(e){if(e&&av(e._i)){e._i(this);this.dispatchEvent(new aw("onaddoverlay",e))}},removeOverlay:function(e){if(e&&av(e.remove)){e.remove();this.dispatchEvent(new aw("onremoveoverlay",e))}},clearOverlays:function(){this.dispatchEvent(new aw("onclearoverlays"))},addTileLayer:function(e){for(var aU=0;aUe){aU=true;aT=e}return{zoom:aT,exceeded:aU}},getContainer:function(){return this.container},getZoomUnits:function(aT){var e=aJ[this.mapType];if(typeof e!="object"){return null}var i=aT||this.zoomLevel;return Math.pow(2,(e.zoomLevelMax-i))*e.baseUnits/e.tileSize},pointToPixel:function(i,aW,aU){if(!i){return}if(!aU){i=this.config.coordType==BMAP_COORD_LNGLAT?V.convertLL2MC(i):i;i=this.mapType==BMAP_PERSPECTIVE_MAP?V.convert2DTo3D(this.currentCity,i):i}var aT=this.getZoomUnits(aW);var e=Math.round((i.lng-this.centerPoint.lng)/aT+this.width/2);var aV=Math.round((this.centerPoint.lat-i.lat)/aT+this.height/2);return new aK(e,aV)},pixelToPoint:function(aW,aY,aT){if(!aW){return}var i=this.getZoomUnits(aY);var aV=this.centerPoint.lng+i*(aW.x-this.width/2);var aX=this.centerPoint.lat-i*(aW.y-this.height/2);var e=new f(aV,aX);if(!aT){if(this.mapType==BMAP_PERSPECTIVE_MAP){if(this.config.coordType==BMAP_COORD_LNGLAT){var aU=V.convert3DTo2D(this.currentCity,e);e=V.convertMC2LL(aU)}else{e=this.mapType==BMAP_PERSPECTIVE_MAP?V.convert3DTo2D(this.currentCity,e):e}}else{if(this.config.coordType==BMAP_COORD_LNGLAT){e=this.config.coordType==BMAP_COORD_LNGLAT?V.convertMC2LL(e):e}}}return e},pointToOverlayPixel:function(e,aU,i){var aT=this.pointToPixel(e,aU,i);if(!aT){return}aT.x-=this.offsetX;aT.y-=this.offsetY;return aT},overlayPixelToPoint:function(e,aT){if(!e){return}var i=new aK(e.x,e.y);i.x+=this.offsetX;i.y+=this.offsetY;return this.pixelToPoint(i,aT)},lnglatToMercator:function(i,aU){var e=new f(i,aU);var aT=V.convertLL2MC(e);return[aT.lng,aT.lat]},mercatorToLnglat:function(aT,i){if(isNaN(aT)||isNaN(i)){return[]}aT=parseFloat(aT);i=parseFloat(i);var aU=new f(aT,i);var e=V.convertMC2LL(aU);return[e.lng,e.lat]},getBounds:function(){if(!this.isLoaded()){return new y()}var e=arguments[0]||{},aT=e.margins||[0,0,0,0],aV=e.level||null,aU=this.pixelToPoint({x:aT[3],y:this.height-aT[2]},aV,true),i=this.pixelToPoint({x:this.width-aT[1],y:aT[0]},aV,true);if(this.config.coordType==BMAP_COORD_LNGLAT){aU=V.convertMC2LL(aU);i=V.convertMC2LL(i)}if(this.mapType==BMAP_PERSPECTIVE_MAP){aU=V.convert3DTo2D(this.currentCity,aU);i=V.convert3DTo2D(this.currentCity,i)}return new y(aU.lng,aU.lat,i.lng,i.lat)},setConfig:function(e){if(!e){return}for(var i in e){if(typeof this.config[i]==typeof e[i]){this.config[i]=e[i]}}},isLoaded:function(){return !!this.loaded},_getBestLevel:function(i,aT){var aX=aJ[this.mapType];if(!aX){return this.getZoom()}var aY=aT.margins||[10,10,10,10],aV=aT.zoomFactor||0,aZ=aY[1]+aY[3],aW=aY[0]+aY[2],e=aX.zoomLevelMin,a1=aX.zoomLevelMax;for(var aU=a1;aU>=e;aU--){var a0=this.getZoomUnits(aU);if((i.maxX-i.minX)/a0a1){aU=a1}return aU},getViewport:function(a3,aT){var a5={center:this.getCenter(),zoom:this.getZoom()};if(!a3||a3.length==0){return a5}aT=aT||{};var aX=[];var a1=[];if(this.config.coordType==BMAP_COORD_LNGLAT){for(var aY=0,aW=a3.length;aY=0;aY--){aU.extend(a1[aY])}if(aU.isEmpty()){return a5}var e=aU.getCenter();var a4=this._getBestLevel(aU,aT);if(aT.margins){var a0=aT.margins,aZ=(a0[1]-a0[3])/2,a2=(a0[0]-a0[2])/2,aV=this.getZoomUnits(a4);e.lng=e.lng+aV*aZ;e.lat=e.lat+aV*a2}if(this.mapType==BMAP_PERSPECTIVE_MAP){e=ar.convert3DTo2D(this.currentCity,e)}if(this.config.coordType==BMAP_COORD_LNGLAT){e=ar.convertMC2LL(e)}return{center:e,zoom:a4}},setViewport:function(i,aV){var e;if(i&&i.center){e=i}else{e=this.getViewport(i,aV)}aV=aV||{};var aT=aV.delay||200;if(e.zoom==this.zoomLevel&&aV.enableAnimation!=false){var aU=this;setTimeout(function(){aU.panTo(e.center,false,210)},aT)}else{this.centerAndZoom(e.center,e.zoom)}},addSpots:function(i,aU){if(!i||i.length==0){return}aU=aU||{};var aW=aU.zIndex||0,aV=typeof aU.enableMultiResponse=="undefined"?true:!!aU.enableMultiResponse;this.spotsPool=this.spotsPool||{};var e="sp"+(this.temp.spotsGuid++);this.spotsPool[e]={spots:i.slice(0),zIndex:aW,enableMultiResponse:aV};var aT=this;aq.load("hotspot",function(){aT._asyncRegister()});return e},getSpots:function(e){return this.spotsPool[e]&&this.spotsPool[e].spots||[]},removeSpots:function(e){if(!e||!this.spotsPool[e]){return}delete this.spotsPool[e]},clearSpots:function(){delete this.spotsPool},setBounds:function(e){aJ[this.mapType].bounds=new y(e.minX,e.minY,e.maxX,e.maxY)},getCoordType:function(){return this.config.coordType},getPanes:function(){return this._panes},getInfoWindow:function(){if(this.temp.infoWin&&this.temp.infoWin.isOpen()){return this.temp.infoWin}return null},getDistance:function(aT,e){if(!aT||!e){return}var i=0;if(this.config.coordType==BMAP_COORD_LNGLAT){i=V.getDistanceByLL(aT,e)}else{i=V.getDistanceByMC(aT,e)}return i},getOverlays:function(){var aV=[],aW=this._overlays,aU=this._customOverlays;if(aW){for(var aT in aW){if(aW[aT] instanceof aF){aV.push(aW[aT])}}}if(aU){for(var aT=0,e=aU.length;aT-1){return i[aT]}}return"bj"},setDefaultCursor:function(e){this.config.defaultCursor=e;if(this.platform){this.platform.style.cursor=this.config.defaultCursor}},getDefaultCursor:function(){return this.config.defaultCursor},setDraggingCursor:function(e){this.config.draggingCursor=e},getDraggingCursor:function(){return this.config.draggingCursor}});window.BMAP_API_VERSION="1.1";window.BMAP_NORMAL_MAP="B_NORMAL_MAP";window.BMAP_PERSPECTIVE_MAP="B_DIMENSIONAL_MAP";window.BMAP_COORD_LNGLAT=0;window.BMAP_COORD_MERCATOR=1;window.BMAP_SYS_DRAWER=0;window.BMAP_SVG_DRAWER=1;window.BMAP_VML_DRAWER=2;window.BMAP_CANVAS_DRAWER=3;window._addStat=function(aX,aW){if(!aX){return}aW=aW||{};var aV="";for(var aT in aW){aV=aV+"&"+aT+"="+encodeURIComponent(aW[aT])}var aY=function(i){if(!i){return}_addStat._sending=true;setTimeout(function(){_addStat._img.src="https://api.map.baidu.com/images/blank.gif?"+i.src},50)};var e=function(){var i=_addStat._reqQueue.shift();if(i){aY(i)}};var aU=(Math.random()*100000000).toFixed(0);if(_addStat._sending){_addStat._reqQueue.push({src:"t="+aU+"&code="+aX+aV})}else{aY({src:"t="+aU+"&code="+aX+aV})}if(!_addStat._binded){l.on(_addStat._img,"load",function(){_addStat._sending=false;e()});l.on(_addStat._img,"error",function(){_addStat._sending=false;e()});_addStat._binded=true}};window._addStat._reqQueue=[];window._addStat._img=new Image();var az=5000;_addStat(az,{"v":BMap.version});var aJ={B_NORMAL_MAP:{tileUrls:["http://online0.map.bdimg.com/tile/","http://online1.map.bdimg.com/tile/","http://online2.map.bdimg.com/tile/","http://online3.map.bdimg.com/tile/","http://online4.map.bdimg.com/tile/"],tileSize:256,baseUnits:256,zoomLevelMin:1,zoomLevelMax:18,errorUrl:aQ.imgPath+"bg.png",bounds:new y(-21364736,-10616832,23855104,15859712),imgExtend:"png"},B_DIMENSIONAL_MAP:{tileUrls:["https://d0.map.baidu.com/resource/mappic/","https://d1.map.baidu.com/resource/mappic/","https://d2.map.baidu.com/resource/mappic/","https://d3.map.baidu.com/resource/mappic/"],tileSize:256,baseUnits:256,zoomLevelMin:15,zoomLevelMax:20,errorUrl:aQ.imgPath+"bg.png",bounds:new y(-21364736,-10616832,23855104,15859712),imgExtend:"jpg",hotspotUrl:["https://d0.map.baidu.com/resource/js/map/","https://d1.map.baidu.com/resource/js/map/","https://d2.map.baidu.com/resource/js/map/","https://d3.map.baidu.com/resource/js/map/"],entityUrl:"https://d0.map.baidu.com/resource/js/entity/",citys:{bj:[new y(524288,9363456,727040,9474048),new y(12821123.68,4784960.94,12958550,4862821.56),2],gz:[new y(1048576,8857601,1157119,8949760),new y(12589292.4,2591556.62,12646784.64,2647562.86),1],sz:[new y(524288,9375745,668415,9474048),new y(12668344.21,2560434.57,12710864.02,2587497.06),14],sh:[new y(983040,8890369,1130495,8994816),new y(13507877.45,3640466.88,13537325.71,3658712.59),4]}},BMAP_CUSTOM_LAYER:{tileUrls:[""],tileSize:256,baseUnits:256,zoomLevelMin:1,zoomLevelMax:18,errorUrl:aQ.imgPath+"blank.gif",bounds:new y(-21364736,-10616832,23855104,15859712),imgExtend:"png"}};function m(){}l.extend(m,{num:{bj:{num:Math.sin(Math.PI/4),num2:Math.sin(Math.PI/6)},gz:{num:Math.sin(Math.PI/4),num2:Math.sin(Math.PI/4)},sz:{num:Math.sin(Math.PI/4),num2:Math.sin(Math.PI/4)},sh:{num:Math.sin(Math.PI/4),num2:Math.sin(Math.PI/4)}},correct_pts:{bj:[{j:116.305687,w:39.990912,utm_x:12947230.73,utm_y:4836903.65,x:630412,y:547340},{j:116.381837,w:40.000198,utm_x:12955707.8,utm_y:4838247.62,x:667412,y:561832},{j:116.430651,w:39.995216,utm_x:12961141.81,utm_y:4837526.55,x:686556,y:573372},{j:116.474111,w:39.976323,utm_x:12965979.81,utm_y:4834792.55,x:697152,y:586816},{j:116.280328,w:39.953159,utm_x:12944407.75,utm_y:4831441.53,x:603272,y:549976},{j:116.316117,w:39.952496,utm_x:12948391.8,utm_y:4831345.64,x:618504,y:557872},{j:116.350477,w:39.938107,utm_x:12952216.78,utm_y:4829264.65,x:627044,y:568220},{j:116.432025,w:39.947158,utm_x:12961294.76,utm_y:4830573.59,x:666280,y:584016},{j:116.46873,w:39.949516,utm_x:12965380.79,utm_y:4830914.63,x:683328,y:591444},{j:116.280077,w:39.913823,utm_x:12944379.8,utm_y:4825753.62,x:586150,y:558552},{j:116.308625,w:39.91374,utm_x:12947557.79,utm_y:4825741.62,x:598648,y:564732},{j:116.369853,w:39.912979,utm_x:12954373.73,utm_y:4825631.62,x:624561,y:578039},{j:116.433552,w:39.914694,utm_x:12961464.75,utm_y:4825879.53,x:652972,y:591348},{j:116.457034,w:39.914273,utm_x:12964078.78,utm_y:4825818.67,x:663028,y:596444},{j:116.490927,w:39.914127,utm_x:12967851.77,utm_y:4825797.57,x:677968,y:604188},{j:116.483839,w:39.877198,utm_x:12967062.73,utm_y:4820460.67,x:658596,y:610312},{j:116.405777,w:39.864461,utm_x:12958372.82,utm_y:4818620.62,x:619256,y:596088},{j:116.35345,w:39.859774,utm_x:12952547.74,utm_y:4817943.6,x:594633,y:585851},{j:116.403818,w:39.9141,utm_x:12958154.74,utm_y:4825793.66,x:639699,y:585226},{j:116.318111,w:39.891101,utm_x:12948613.78,utm_y:4822469.56,x:592856,y:571480},{j:116.413047,w:39.907238,utm_x:12959182.12,utm_y:4824801.76,x:640680,y:588704},{j:116.390843,w:39.906113,utm_x:12956710.35,utm_y:4824639.16,x:630620,y:584108},{j:116.446527,w:39.899438,utm_x:12962909.14,utm_y:4823674.4,x:651752,y:597416},{j:116.388665,w:39.95527,utm_x:12956467.9,utm_y:4831746.87,x:650656,y:572800},{j:116.398343,w:39.939704,utm_x:12957545.26,utm_y:4829495.6,x:648036,y:578452},{j:116.355101,w:39.973581,utm_x:12952731.53,utm_y:4834395.82,x:643268,y:560944},{j:116.380727,w:39.88464,utm_x:12955584.23,utm_y:4821535.94,x:616920,y:586496},{j:116.360843,w:39.946452,utm_x:12953370.73,utm_y:4830471.48,x:635293,y:568765},{j:116.340955,w:39.973421,utm_x:12951156.79,utm_y:4834372.67,x:638420,y:558632},{j:116.322585,w:40.023941,utm_x:12949111.83,utm_y:4841684.79,x:652135,y:543802},{j:116.356486,w:39.883341,utm_x:12952885.71,utm_y:4821348.24,x:606050,y:581443},{j:116.339592,w:39.992259,utm_x:12951005.06,utm_y:4837098.59,x:645664,y:554400},{j:116.3778,w:39.86392,utm_x:12955258.4,utm_y:4818542.48,x:606848,y:590328},{j:116.377354,w:39.964124,utm_x:12955208.75,utm_y:4833027.64,x:649911,y:568581},{j:116.361837,w:39.963897,utm_x:12953481.39,utm_y:4832994.8,x:643286,y:565175},{j:116.441397,w:39.939403,utm_x:12962338.06,utm_y:4829452.07,x:666772,y:587728},{j:116.359176,w:40.006631,utm_x:12953185.16,utm_y:4839178.78,x:660440,y:555411}],sz:[{j:113.88099,w:22.58884,utm_x:12677311.76,utm_y:2565810.52,x:569078,y:532290},{j:113.902002,w:22.566098,utm_x:12679650.83,utm_y:2563084.58,x:568318,y:545457},{j:113.869843,w:22.577711,utm_x:12676070.87,utm_y:2564476.5,x:561115,y:532494},{j:113.943387,w:22.555192,utm_x:12684257.84,utm_y:2561777.5,x:579437,y:558427},{j:113.899505,w:22.577052,utm_x:12679372.86,utm_y:2564397.51,x:571923,y:540181},{j:113.900376,w:22.596431,utm_x:12679469.82,utm_y:2566720.51,x:580142,y:535463},{j:113.92101,w:22.528931,utm_x:12681766.81,utm_y:2558630.58,x:560296,y:559780},{j:113.919672,w:22.517839,utm_x:12681617.86,utm_y:2557301.57,x:555296,y:562549},{j:113.938716,w:22.505569,utm_x:12683737.86,utm_y:2555831.55,x:557349,y:571072},{j:113.919203,w:22.483494,utm_x:12681565.66,utm_y:2553187.17,x:540853,y:572118},{j:113.942875,w:22.492046,utm_x:12684200.84,utm_y:2554211.57,x:553296,y:575994},{j:113.9567,w:22.530183,utm_x:12685739.85,utm_y:2558780.59,x:573378,y:568442},{j:113.989102,w:22.52697,utm_x:12689346.86,utm_y:2558395.61,x:584796,y:578728},{j:114.015467,w:22.533746,utm_x:12692281.83,utm_y:2559207.53,x:597126,y:584075},{j:113.972977,w:22.55702,utm_x:12687551.81,utm_y:2561996.58,x:591204,y:565924},{j:113.990368,w:22.561133,utm_x:12689487.79,utm_y:2562489.51,x:599240,y:569528},{j:114.143745,w:22.580535,utm_x:12706561.83,utm_y:2564815,x:663830,y:605622},{j:114.150374,w:22.557704,utm_x:12707299.77,utm_y:2562078.56,x:657016,y:613828},{j:114.106905,w:22.541858,utm_x:12702460.77,utm_y:2560179.58,x:634284,y:606528},{j:114.083927,w:22.535065,utm_x:12699902.85,utm_y:2559365.58,x:623132,y:602096},{j:114.049584,w:22.517997,utm_x:12696079.76,utm_y:2557320.5,x:603390,y:597564},{j:114.056304,w:22.542425,utm_x:12696827.84,utm_y:2560247.52,x:615980,y:592534},{j:114.051552,w:22.551321,utm_x:12696298.84,utm_y:2561313.59,x:617887,y:588719},{j:114.096377,w:22.559064,utm_x:12701288.79,utm_y:2562241.55,x:637568,y:598739},{j:114.135858,w:22.575851,utm_x:12705683.84,utm_y:2564253.55,x:659024,y:604806},{j:114.092029,w:22.575592,utm_x:12700804.77,utm_y:2564222.51,x:642776,y:592932},{j:114.054795,w:22.570617,utm_x:12696659.85,utm_y:2563626.21,x:626988,y:584142},{j:114.03075,w:22.553687,utm_x:12693983.15,utm_y:2561597.14,x:611068,y:582552},{j:114.074153,w:22.554124,utm_x:12698814.8,utm_y:2561649.51,x:627380,y:594008},{j:113.926721,w:22.546028,utm_x:12682402.56,utm_y:2560679.29,x:569340,y:556468},{j:113.938125,w:22.538296,utm_x:12683672.07,utm_y:2559752.74,x:570548,y:561748}],gz:[{j:113.335098,w:23.147289,utm_x:12616542.68,utm_y:2632892.7,x:1129109,y:1073920},{j:113.320932,w:23.146956,utm_x:12614965.71,utm_y:2632852.62,x:1125620,y:1071640},{j:113.321435,w:23.140119,utm_x:12615021.7,utm_y:2632029.65,x:1124032,y:1072882},{j:113.321471,w:23.119165,utm_x:12615025.71,utm_y:2629507.68,x:1118932,y:1076530},{j:113.340201,w:23.118616,utm_x:12617110.75,utm_y:2629441.61,x:1123238,y:1079667},{j:113.358068,w:23.116323,utm_x:12619099.71,utm_y:2629165.66,x:1126968,y:1083116},{j:113.357529,w:23.131271,utm_x:12619039.71,utm_y:2630964.68,x:1130508,y:1080440},{j:113.365811,w:23.150595,utm_x:12619961.67,utm_y:2633290.66,x:1137205,y:1078567},{j:113.294145,w:23.118467,utm_x:12611983.76,utm_y:2629423.68,x:1112245,y:1072043},{j:113.28615,w:23.121525,utm_x:12611093.75,utm_y:2629791.7,x:1110993,y:1070197},{j:113.307152,w:23.055497,utm_x:12613431.71,utm_y:2621847.21,x:1100144,y:1085123},{j:113.333445,w:23.052687,utm_x:12616358.66,utm_y:2621509.2,x:1105784,y:1089948},{j:113.347476,w:23.048755,utm_x:12617920.6,utm_y:2621036.24,x:1108099,y:1093064},{j:113.385774,w:23.036574,utm_x:12622183.96,utm_y:2619571.12,x:1113850,y:1101834},{j:113.364185,w:22.89798,utm_x:12619780.66,utm_y:2602910.64,x:1073186,y:1123374},{j:113.404577,w:22.906481,utm_x:12624277.13,utm_y:2603932.06,x:1084888,y:1128692},{j:113.430856,w:22.913156,utm_x:12627202.52,utm_y:2604734.12,x:1092892,y:1131761},{j:113.384554,w:22.933021,utm_x:12622048.15,utm_y:2607121.32,x:1086975,y:1120403},{j:113.263566,w:23.146333,utm_x:12608579.68,utm_y:2632777.63,x:1111742,y:1062098},{j:113.239213,w:23.152996,utm_x:12605868.69,utm_y:2633579.69,x:1107616,y:1056740},{j:113.253865,w:23.131628,utm_x:12607499.76,utm_y:2631007.65,x:1105912,y:1062966},{j:113.240767,w:23.088434,utm_x:12606041.68,utm_y:2625809.7,x:1092270,y:1068184},{j:113.279628,w:23.088284,utm_x:12610367.72,utm_y:2625791.65,x:1101412,y:1074883},{j:113.462271,w:23.107058,utm_x:12630699.66,utm_y:2628050.7,x:1148752,y:1101736},{j:113.401618,w:23.052957,utm_x:12623947.73,utm_y:2621541.68,x:1121925,y:1101535},{j:113.422504,w:23.05905,utm_x:12626272.77,utm_y:2622274.61,x:1128470,y:1104049},{j:113.362506,w:23.107149,utm_x:12619593.75,utm_y:2628061.65,x:1125835,y:1085505},{j:113.419629,w:23.143176,utm_x:12625952.73,utm_y:2632397.61,x:1148133,y:1089052},{j:113.23315,w:23.062251,utm_x:12605193.75,utm_y:2622659.67,x:1084184,y:1071368},{j:113.314525,w:23.101412,utm_x:12614252.48,utm_y:2627371.29,x:1113011,y:1078426},{j:113.307947,w:23.131369,utm_x:12613520.21,utm_y:2630976.47,x:1118622,y:1072198}],sh:[{j:121.524411,w:31.245875,utm_x:13528182.75,utm_y:3642354.51,x:1086581,y:1065728},{j:121.419229,w:31.244887,utm_x:13516473.81,utm_y:3642226.51,x:1032616,y:1029148},{j:121.405637,w:31.237871,utm_x:13514960.74,utm_y:3641317.54,x:1022724,y:1027244},{j:121.415348,w:31.222879,utm_x:13516041.78,utm_y:3639375.47,x:1018548,y:1036980},{j:121.422561,w:31.224261,utm_x:13516844.73,utm_y:3639554.48,x:1022976,y:1038908},{j:121.412581,w:31.204148,utm_x:13515733.75,utm_y:3636949.48,x:1006568,y:1043696},{j:121.443025,w:31.206202,utm_x:13519122.8,utm_y:3637215.49,x:1022656,y:1053704},{j:121.524061,w:31.246917,utm_x:13528143.79,utm_y:3642489.52,x:1082052,y:1064124},{j:121.529343,w:31.217769,utm_x:13528731.78,utm_y:3638713.59,x:1072696,y:1079064},{j:121.530268,w:31.210341,utm_x:13528834.75,utm_y:3637751.53,x:1068748,y:1082416},{j:121.511601,w:31.227303,utm_x:13526756.73,utm_y:3639948.53,x:1069276,y:1068716},{j:121.4966,w:31.243614,utm_x:13525086.81,utm_y:3642061.58,x:1071220,y:1056805},{j:121.485021,w:31.26138,utm_x:13523797.82,utm_y:3644363.54,x:1075708,y:1045540},{j:121.465114,w:31.278803,utm_x:13521581.76,utm_y:3646621.48,x:1073740,y:1031268},{j:121.454784,w:31.266566,utm_x:13520431.82,utm_y:3645035.58,x:1063591,y:1033191},{j:121.46851,w:31.24951,utm_x:13521959.81,utm_y:3642825.48,x:1060200,y:1044520},{j:121.446384,w:31.248422,utm_x:13519496.73,utm_y:3642684.51,x:1048784,y:1037750},{j:121.509499,w:31.246469,utm_x:13526522.73,utm_y:3642431.47,x:1079309,y:1060105},{j:121.481643,w:31.283943,utm_x:13523421.78,utm_y:3647287.68,x:1087096,y:1035304},{j:121.508054,w:31.280609,utm_x:13526361.87,utm_y:3646855.56,x:1098432,y:1045648},{j:121.493854,w:31.19121,utm_x:13524781.12,utm_y:3635274.07,x:1039624,y:1077288},{j:121.500079,w:31.185541,utm_x:13525474.09,utm_y:3634540.04,x:1039960,y:1081640},{j:121.484482,w:31.202846,utm_x:13523737.82,utm_y:3636780.87,x:1041388,y:1069232},{j:121.480877,w:31.189587,utm_x:13523336.51,utm_y:3635063.92,x:1032484,y:1073640},{j:121.502652,w:31.195209,utm_x:13525760.52,utm_y:3635791.9,x:1046384,y:1078728}]},getLnglatIndex:function(aV,aZ,aY){var aU=0;var aT=0;var a0=10000000,aX=1000000000;for(var aW=0;aW5000){aT._loadError(aT.objName,aU);clearInterval(aU.timer)}}},5)})}}aU.charset=aT.charset;aU.src=aT.url;document.getElementsByTagName("head")[0].appendChild(aU)},_loadData:function(aW,aT){var i=window[aW];var aV=new aw("onloaded");aV.data=i;for(var aU in aT.userData){if(!aV[aU]&&aT.userData[aU]){aV[aU]=aT.userData[aU]}}this.dispatchEvent(aV);aT.parentNode&&aT.parentNode.removeChild(aT);aT=null},_loadError:function(i,e){e.parentNode&&e.parentNode.removeChild(e);e=null}});var aI={request:function(i){var e=t("script",{src:i,type:"text/javascript",charset:"utf-8"});if(e.addEventListener){e.addEventListener("load",function(aU){var aT=aU.target;aT.parentNode.removeChild(aT)},false)}else{if(e.attachEvent){e.attachEvent("onreadystatechange",function(aU){var aT=window.event.srcElement;if(aT&&(aT.readyState=="loaded"||aT.readyState=="complete")){aT.parentNode.removeChild(aT)}})}}setTimeout(function(){document.getElementsByTagName("head")[0].appendChild(e);e=null},1)}};function aq(){}l.extend(aq,{Request:{INITIAL:-1,WAITING:0,COMPLETED:1},Dependency:{control:[],marker:[],poly:["marker"],infowindow:["marker"],hotspot:["poly"],menu:[],tools:["marker","poly"],oppc:[],opmb:[],"3dmap":["hotspot"]},preLoaded:{},Config:{_baseUrl:"https://api.map.baidu.com/getmodules?v=1.1",_timeout:5000},delayFlag:false,Module:{_modules:{},_arrMdls:[]},load:function(i,aU){var e=this.current(i);if(e._status==this.Request.COMPLETED){return}else{if(e._status==this.Request.INITIAL){this.combine(i);this.pushUniqueMdl(i);var aT=this;if(aT.delayFlag==false){aT.delayFlag=true;window.setTimeout(function(){var aV=aT.Config._baseUrl+"&mod="+aT.Module._arrMdls.join(",");aI.request(aV);aT.Module._arrMdls.length=0;aT.delayFlag=false},1)}e._status=this.Request.WAITING}e._callbacks.push(aU)}},combine:function(e){if(e&&this.Dependency[e]){var aU=this.Dependency[e];for(var aT=0;aT
");if(this._visible==false){this._container.style.display="none"}return this._container},_setPosition:function(){this.setAnchor(this._opts.anchor)},setAnchor:function(aU){if(this.anchorFixed||typeof aU!="number"||isNaN(aU)||aUBMAP_ANCHOR_BOTTOM_RIGHT){aU=this.defaultAnchor}this._opts=this._opts||{printable:false};this._opts.offset=this._opts.offset||this.defaultOffset;var aT=this._opts.anchor;this._opts.anchor=aU;if(!this._container){return}var aW=this._container;var e=this._opts.offset.width;var aV=this._opts.offset.height;aW.style.left=aW.style.top=aW.style.right=aW.style.bottom="auto";switch(aU){case BMAP_ANCHOR_TOP_LEFT:aW.style.top=aV+"px";aW.style.left=e+"px";break;case BMAP_ANCHOR_TOP_RIGHT:aW.style.top=aV+"px";aW.style.right=e+"px";break;case BMAP_ANCHOR_BOTTOM_LEFT:aW.style.bottom=aV+"px";aW.style.left=e+"px";break;case BMAP_ANCHOR_BOTTOM_RIGHT:aW.style.bottom=aV+"px";aW.style.right=e+"px";break;default:break}var i=["TL","TR","BL","BR"];l.rc(this._container,"anchor"+i[aT]);l.ac(this._container,"anchor"+i[aU])},getAnchor:function(){return this._opts.anchor},setOffset:function(e){if(!e||e&&e.toString()!="Size"){return}this._opts=this._opts||{printable:false};this._opts.offset=new X(e.width,e.height);if(!this._container){return}this.setAnchor(this._opts.anchor)},getOffset:function(){return this._opts.offset},getDom:function(){return this._container},show:function(){if(this._visible==true){return}this._visible=true;if(this._container){this._container.style.display=""}},hide:function(){if(this._visible==false){return}this._visible=false;if(this._container){this._container.style.display="none"}},isPrintable:function(){return !!this._opts.printable},isVisible:function(){if(!this._container&&!this._map){return false}return !!this._visible}});window.BMAP_ANCHOR_TOP_LEFT=0;window.BMAP_ANCHOR_TOP_RIGHT=1;window.BMAP_ANCHOR_BOTTOM_LEFT=2;window.BMAP_ANCHOR_BOTTOM_RIGHT=3;function K(e){P.call(this);e=e||{};this._opts={printable:false};l.extend(this._opts,e);this._copyrightCollection=[];this.defaultAnchor=BMAP_ANCHOR_BOTTOM_LEFT;this.defaultOffset=new X(5,2);this.setAnchor(e.anchor);this._canShow=true;this.blockInfoWindow=false;this._asyncLoadCode()}K.inherits(P,"CopyrightControl");l.extend(K.prototype,{initialize:function(e){this._map=e;return this._container},addCopyright:function(aU){if(!aU||typeof aU.id!="number"||isNaN(aU.id)){return}var e={minZoom:0,bounds:null,content:"",mapType:""};for(var aT in aU){e[aT]=aU[aT]}if(this._map){var aX=e.minZoom;if(aX==-1||aXaJ[this._map.mapType].zoomLevelMax){e.minZoom=aJ[this._map.mapType].zoomLevelMin}if(e.mapType!=""&&!aJ[e.mapType]){e.mapType=BMAP_NORMAL_MAP}}var aV=this.getCopyright(aU.id);if(aV){for(var aW in e){aV[aW]=e[aW]}}else{this._copyrightCollection.push(e)}},getCopyright:function(aU){for(var aT=0,e=this._copyrightCollection.length;aT0?e.width:150;e.height=e.height>0?e.height:150;this._opts.size=e},getSize:function(){if(this.isOpen()){return this._opts.size}else{return new X(this._btnWidth,this._btnHeight)}},isOpen:function(){return this._opts.isOpen},_asyncLoadCode:function(){var e=this;aq.load("control",function(){e._asyncDraw()})}});function T(e){P.call(this);e=e||{};this._opts={printable:false};this._opts=l.extend(l.extend(this._opts,{color:"black",unit:"metric"}),e);this.defaultAnchor=BMAP_ANCHOR_BOTTOM_LEFT;this.defaultOffset=new X(81,18);this.setAnchor(e.anchor);this._units={metric:{name:"metric",conv:1,incon:1000,u1:"\u7c73",u2:"\u516c\u91cc"},us:{name:"us",conv:3.2808,incon:5280,u1:"\u82f1\u5c3a",u2:"\u82f1\u91cc"}};if(!this._units[this._opts.unit]){this._opts.unit="metric"}this._asyncLoadCode()}window.BMAP_UNIT_METRIC="metric";window.BMAP_UNIT_IMPERIAL="us";T.inherits(P,"ScaleControl");l.extend(T.prototype,{initialize:function(e){this._map=e;return this._container},setUnit:function(e){this._opts.unit=this._units[e]&&this._units[e].name||this._opts.unit},getUnit:function(){return this._opts.unit},_asyncLoadCode:function(){var e=this;aq.load("control",function(){e._asyncDraw()})}});window.BMAP_NAVIGATION_CONTROL_LARGE=0;window.BMAP_NAVIGATION_CONTROL_SMALL=1;window.BMAP_NAVIGATION_CONTROL_PAN=2;window.BMAP_NAVIGATION_CONTROL_ZOOM=3;function H(e){P.call(this);e=e||{};this._opts={printable:false,showZoomInfo:true};l.extend(this._opts,e);this.defaultAnchor=BMAP_ANCHOR_TOP_LEFT;this.defaultOffset=new X(10,10);this.setAnchor(e.anchor);this.setType(e.type);this._asyncLoadCode()}H.inherits(P,"NavigationControl");l.extend(H.prototype,{initialize:function(e){this._map=e;return this._container},setType:function(e){if(typeof e=="number"&&e>=BMAP_NAVIGATION_CONTROL_LARGE&&e<=BMAP_NAVIGATION_CONTROL_ZOOM){this._opts.type=e}else{this._opts.type=BMAP_NAVIGATION_CONTROL_LARGE}},getType:function(){return this._opts.type},_asyncLoadCode:function(){var e=this;aq.load("control",function(){e._asyncDraw()})}});function ae(e){P.call(this);e=e||{};this._opts={printable:false};this.defaultAnchor=BMAP_ANCHOR_TOP_RIGHT;this.defaultOffset=new X(10,10);this.setAnchor(e.anchor);this._opts=l.extend(l.extend(this._opts,{offset:this.defaultOffset,enableSwitch:true}),e);this._asyncLoadCode()}ae.inherits(P,"MapTypeControl");l.extend(ae.prototype,{initialize:function(e){this._map=e;return this._container},select:function(e){},_asyncLoadCode:function(){var e=this;aq.load("control",function(){e._asyncDraw()})}});function g(i){E.call(this);this._opts={container:null,cursor:"default"};this._opts=l.extend(this._opts,i);this._type="contextmenu";this._map=null;this._container;this._shadow;this._left=0;this._top=0;this._items=[];this._rItems=[];this._dividers=[];this._enable=true;this.curPixel=null;this.curPoint=null;this._isOpen=false;var e=this;aq.load("menu",function(){e._draw()})}g.inherits(E,"ContextMenu");l.extend(g.prototype,{initialize:function(e){this._map=e},remove:function(){this._map=null},addItem:function(aU){if(!aU||aU._type!="menuitem"||aU._text==""||aU._width<=0){return}for(var aT=0,e=this._items.length;aTaT){this._items[aU]._dIndex--}}this._dividers.splice(aT,1)},getDom:function(){return this._container},show:function(){if(this._isOpen==true){return}this._isOpen=true},hide:function(){if(this._isOpen==false){return}this._isOpen=false},setCursor:function(e){if(!e){return}this._opts.cursor=e},getItem:function(e){return this._rItems[e]},enable:function(){this._enable=true},disable:function(){this._enable=false}});function L(aT,aU,i){if(!aT||!aU||typeof aU!="function"){return}E.call(this);this._opts={width:100,id:""};i=i||{};this._opts.width=(i.width*1)?i.width:100;this._opts.id=i.id?i.id:"";this._text=aT+"";this._callback=aU;this._map=null;this._type="menuitem";this._contextmenu=null;this._container=null;this._enabled=true;var e=this;aq.load("menu",function(){e._draw()})}L.inherits(E,"MenuItem");l.extend(L.prototype,{initialize:function(e,i){this._map=e;this._contextmenu=i},remove:function(){this._contextmenu=null;this._map=null},setText:function(e){if(!e){return}this._text=e+""},getDom:function(){return this._container},enable:function(){this._enabled=true},disable:function(){this._enabled=false}});function y(e,aU,aT,i){this.minX=e;this.minY=aU;this.maxX=aT;this.maxY=i}l.extend(y.prototype,{isEmpty:function(){var e="number";return(typeof(this.minX)!=e||typeof(this.minY)!=e||typeof(this.maxX)!=e||typeof(this.maxY)!=e)},equals:function(e){if(!e||e.toString()!="Bounds"){return}return(this.minX==e.minX&&this.minY==e.minY&&this.maxX==e.maxX&&this.maxY==e.maxY)},getMaxX:function(){return this.maxX},getMaxY:function(){return this.maxY},getMinX:function(){return this.minX},getMinY:function(){return this.minY},containsBounds:function(e){if(!e||e.toString()!="Bounds"){return}return(e.minX>this.minX&&e.maxXthis.minY&&e.maxYMath.max(this.minX,this.maxX)||Math.max(aT.minY,aT.maxY)Math.max(this.minY,this.maxY)){return null}var aV=Math.max(this.minX,aT.minX);var i=Math.min(this.maxX,aT.maxX);var aU=Math.max(this.minY,aT.minY);var e=Math.min(this.maxY,aT.maxY);return new y(aV,aU,i,e)},containsPoint:function(e){if(!e||e.toString()!="Point"){return}return(e.lng>=this.minX&&e.lng<=this.maxX&&e.lat>=this.minY&&e.lat<=this.maxY)},extend:function(e){if(!e||e.toString()!="Point"){return}var i=e.lng,aT=e.lat;if(!this.minX||this.minX>i){this.minX=i}if(!this.maxX||this.maxXaT){this.minY=aT}if(!this.maxY||this.maxYthis.minY&&i.lat=aW[aU].lat)&&(e.lat=aW[aT].lat)&&(e.lat0)?true:false},getQuad:function(e){return(e.lng>=0)?((e.lat>=0)?0:3):((e.lat>=0)?1:2)}};var aL={undo:1,redo:2,zoom:4,drag:8,move:16,mousewheel:32,toolbarOperation:64,stdMapCtrlDrag:128,dblclick:256};var ap={_map:null,_html:"
",_maskElement:null,_cursor:"default",inUse:false,show:function(e){if(!this._map){this._map=e}this.inUse=true;if(!this._maskElement){this._createMask(e)}this._maskElement.style.display="block"},_createMask:function(i){if(!this._map){this._map=i}if(!this._map){return}var e=this._maskElement=Z(this._map.container,this._html);l.on(e,"mouseup",function(aT){if(aT.button==2){aC(aT)}});l.on(e,"contextmenu",aC);e.style.display="none"},getDrawPoint:function(aU,aX,aV){aU=window.event||aU;var i=aU.layerX||aU.offsetX||0;var aW=aU.layerY||aU.offsetY||0;var aT=aU.target||aU.srcElement;if(aT!=ap.getDom(this._map)&&aX==true){while(aT&&aT!=this._map.container){if(!(aT.clientWidth==0&&aT.clientHeight==0&&aT.offsetParent&&aT.offsetParent.nodeName.toLowerCase()=="td")){i+=aT.offsetLeft;aW+=aT.offsetTop}aT=aT.offsetParent}}if(aT!=ap.getDom(this._map)&&aT!=this._map.container){return}if(typeof i==="undefined"||typeof aW==="undefined"){return}if(isNaN(i)||isNaN(aW)){return}if(aV){i=i+aV.x;aW=aW+aV.y}return this._map.pixelToPoint(new aK(i,aW))},hide:function(){if(!this._map){return}this.inUse=false;if(this._maskElement){this._maskElement.style.display="none"}},getDom:function(e){if(!this._maskElement){this._createMask(e)}return this._maskElement},setCursor:function(e){this._cursor=e||"default";if(this._maskElement){this._maskElement.style.cursor=this._cursor}}};function O(){this._type="overlay"}O.inherits(l.BaseClass,"Overlay");O.getZIndex=function(i,e){i=i*1;if(!i){return 0}if(e&&e==BMAP_COORD_MERCATOR){i=V.convertMC2LL(new BMap.Point(0,i)).lat}return(i*-100000)<<1};l.extend(O.prototype,{_i:function(e){if(!this.domElement&&av(this.initialize)){this.domElement=this.initialize(e);if(this.domElement){this.domElement.style.WebkitUserSelect="none"}}this.draw()},initialize:function(e){throw"initialize\u65b9\u6cd5\u672a\u5b9e\u73b0"},draw:function(){throw"draw\u65b9\u6cd5\u672a\u5b9e\u73b0"},remove:function(){if(this.domElement&&this.domElement.parentNode){this.domElement.parentNode.removeChild(this.domElement)}this.domElement=null;this.dispatchEvent(new aw("onremove"))},hide:function(){l.hide(this.domElement)},show:function(){l.show(this.domElement)},isVisible:function(){if(!this.domElement){return false}if(this.domElement.style.display=="none"||this.domElement.style.visibility=="hidden"){return false}return true},dispose:function(){l.BaseClass.prototype.decontrol.call(this)}});BMap.register(function(i){i.temp.overlayDiv=i.overlayDiv=e(i.platform,200);i._panes.floatPane=e(i.temp.overlayDiv,800);i._panes.markerMouseTarget=e(i.temp.overlayDiv,700);i._panes.floatShadow=e(i.temp.overlayDiv,600);i._panes.labelPane=e(i.temp.overlayDiv,500);i._panes.markerPane=e(i.temp.overlayDiv,400);i._panes.mapPane=e(i.temp.overlayDiv,200);function e(aT,aW){var aV=t("div"),aU=aV.style;aU.position="absolute";aU.top=aU.left=aU.width=aU.height="0";aU.zIndex=aW;aT.appendChild(aV);return aV}});function aF(){l.BaseClass.call(this);O.call(this);this._visible=true;this.infoWindow=null;this._dblclickTime=0}aF.inherits(O,"OverlayInternal");l.extend(aF.prototype,{initialize:function(e){this.map=e;l.BaseClass.call(this,this.hashCode);return null},draw:function(){},remove:function(){this.map=null;this.decontrol();O.prototype.remove.call(this)},hide:function(){if(this._visible==false){return}this._visible=false},show:function(){if(this._visible==true){return}this._visible=true},isVisible:function(){if(!this.domElement){return false}return !!this._visible},getDom:function(){return this.domElement},setConfig:function(i){i=i||{};for(var e in i){if(typeof(this._config[e])==typeof(i[e])){this._config[e]=i[e]}}},getPoint:function(){return this.point},setZIndex:function(e){this.zIndex=e},enableMassClear:function(){this._config.enableMassClear=true},disableMassClear:function(){this._config.enableMassClear=false}});function at(){this.map=null;this._overlays={};this._customOverlays=[]}BMap.register(function(i){var e=new at();e.map=i;i._overlays=e._overlays;i._customOverlays=e._customOverlays;i.addEventListener("load",function(aT){e.draw(aT)});i.addEventListener("moveend",function(aT){e.draw(aT)});if(l.Browser.ie&&l.Browser.ie<8||document.compatMode=="BackCompat"){i.addEventListener("zoomend",function(aT){setTimeout(function(){e.draw(aT)},20)})}else{i.addEventListener("zoomend",function(aT){e.draw(aT)})}i.addEventListener("maptypechange",function(aT){e.draw(aT)});i.addEventListener("addoverlay",function(aX){var aU=aX.target;if(aU instanceof aF){if(!e._overlays[aU.hashCode]){e._overlays[aU.hashCode]=aU}}else{var aW=false;for(var aV=0,aT=e._customOverlays.length;aV1){this._config.strokeOpacity=0.65}if(this._config.fillOpacity<0||this._config.fillOpacity>1){this._config.fillOpacity=0.65}if(this._config.strokeStyle!="solid"&&this._config.strokeStyle!="dashed"){this._config.strokeStyle="solid"}this.domElement=null;this._bounds=new BMap.Bounds(0,0,0,0);this._parseCache=[];this.vertexMarkers=[];this._temp={}}au.inherits(aF,"Graph");au.getGraphPoints=function(i){var e=[];if(!i){return e}if(typeof i=="string"){var aT=i.split(";");l.each(aT,function(aV){var aU=aV.split(",");e.push(new f(aU[0],aU[1]))})}if(i.constructor==Array&&i.length>0){e=i}return e};au.parseTolerance={0:[0.09,0.005,0.0001,0.00001],1:[9000,500,10,1]};l.extend(au.prototype,{initialize:function(e){this.map=e;return null},draw:function(){return;if(!this.domElement){return}if(this._drawer){this._drawer.setPath(this.domElement,this._getDisplayPixels(this.points))}},setPoints:function(e){this._parseCache.length=0;this.points=au.getGraphPoints(e).slice(0);this._calcBounds()},_calcBounds:function(){if(!this.points){return}var e=this;e._bounds=new y();l.each(this.points,function(i){e._bounds.extend(i)})},getPoints:function(){return this.points},setPointAt:function(i,e){if(!e||!this.points[i]){return}this._parseCache.length=0;this.points[i]=new f(e.lng,e.lat);this._calcBounds()},setStrokeColor:function(e){this._config.strokeColor=e},getStrokeColor:function(){return this._config.strokeColor},setStrokeWeight:function(e){if(e>0){this._config.strokeWeight=e}},getStrokeWeight:function(){return this._config.strokeWeight},setStrokeOpacity:function(e){if(!e||e>1||e<0){return}this._config.strokeOpacity=e},getStrokeOpacity:function(){return this._config.strokeOpacity},setFillOpacity:function(e){if(e>1||e<0){return}this._config.fillOpacity=e},getFillOpacity:function(){return this._config.fillOpacity},setStrokeStyle:function(e){if(e!="solid"&&e!="dashed"){return}this._config.strokeStyle=e},getStrokeStyle:function(){return this._config.strokeStyle},setFillColor:function(e){this._config.fillColor=e||""},getFillColor:function(){return this._config.fillColor},getBounds:function(){return this._bounds},remove:function(){if(this.map){this.map.removeEventListener("onmousemove",this._graphMouseEvent)}aF.prototype.remove.call(this);this._parseCache.length=0},enableEditing:function(){this._config.enableEditing=true},disableEditing:function(){this._config.enableEditing=false}});if(l.Browser.ie){l.on(document.body,"load",function(){if(document.namespaces&&!document.namespaces.olv){document.namespaces.add("olv","urn:schemas-microsoft-com:vml")}})}function aj(e){aF.call(this);this.map=null;this.domElement=null;this._config={width:0,height:0,offset:new X(0,0),opacity:1,background:"transparent",lineStroke:1,lineColor:"#000",lineStyle:"solid",point:null};this.setConfig(e);this.point=this._config.point}aj.inherits(aF,"Division");l.extend(aj.prototype,{_addDom:function(){var e=this._config;var aT=this.content;var i=['
');i.push(aT);i.push("
");this.domElement=Z(this.map.getPanes().markerMouseTarget,i.join(""))},initialize:function(e){this.map=e;this._addDom();if(this.domElement){l.on(this.domElement,"mousedown",function(i){ag(i)})}return this.domElement},draw:function(){var e=this.map.pointToOverlayPixel(this._config.point);this._config.offset=new X(-Math.round(this._config.width/2)-Math.round(this._config.lineStroke),-Math.round(this._config.height/2)-Math.round(this._config.lineStroke));this.domElement.style.left=e.x+this._config.offset.width+"px";this.domElement.style.top=e.y+this._config.offset.height+"px"},getPoint:function(){return this._config.point},_getPixel:function(e){return this.map.pointToPixel(this.getPoint())},setPoint:function(e){this._config.point=e;this.draw()},setDimension:function(e,i){this._config.width=Math.round(e);this._config.height=Math.round(i);if(this.domElement){this.domElement.style.width=this._config.width+"px";this.domElement.style.height=this._config.height+"px";this.draw()}}});function w(i,aT,aV){if(!i||!aT){return}this.imageUrl=i;this.size=aT;var aU=new X(Math.floor(aT.width/2),Math.floor(aT.height/2));var aW={offset:aU,imageOffset:new X(0,0)};aV=aV||{};for(var e in aV){if(typeof(aW[e])==typeof(aV[e])){aW[e]=aV[e]}}this.offset=aW.offset;this.imageOffset=aW.imageOffset;this.infoWindowOffset=aV.infoWindowOffset||this.offset;this.printImageUrl=aV.printImageUrl||""}var R=w.prototype;R.setImageUrl=function(e){if(!e){return}this.imageUrl=e};R.setPrintImageUrl=function(e){if(!e){return}this.printImageUrl=e};R.setSize=function(e){if(!e){return}this.size=new X(e.width,e.height)};R.setOffset=function(e){if(!e){return}this.offset=new X(e.width,e.height)};R.setImageOffset=function(e){if(!e){return}this.imageOffset=new X(e.width,e.height)};R.setInfoWindowOffset=function(e){if(!e){return}this.infoWindowOffset=new X(e.width,e.height)};R.toString=function(){return"Icon"};function ay(aT,i){l.BaseClass.call(this);this.content=aT;this.map=null;this._config={width:0,height:0,maxWidth:600,offset:new X(0,0),title:"",maxContent:"",enableMaximize:false,enableAutoPan:true,enableCloseOnClick:true,margin:[10,10,40,10],collisions:[[10,10],[10,10],[10,10],[10,10]],ifMaxScene:false,onClosing:function(){return true}};this.setConfig(i);if(this._config.width!=0){if(this._config.width<220){this._config.width=220}if(this._config.width>730){this._config.width=730}}if(this._config.height!=0){if(this._config.height<60){this._config.height=60}if(this._config.height>650){this._config.height=650}}if(this._config.maxWidth!=0){if(this._config.maxWidth<220){this._config.maxWidth=220}if(this._config.maxWidth>730){this._config.maxWidth=730}}this.isWinMax=false;this.IMG_PATH=aQ.imgPath;this.overlay=null;var e=this;aq.load("infowindow",function(){e._draw()})}ay.inherits(l.BaseClass,"InfoWindow");l.extend(ay.prototype,{setWidth:function(e){e=e*1;if(!e&&e!=0||isNaN(e)||e<0){return}if(e!=0){if(e<220){e=220}if(e>730){e=730}}this._config.width=e},setHeight:function(e){e=e*1;if(!e&&e!=0||isNaN(e)||e<0){return}if(e!=0){if(e<60){e=60}if(e>650){e=650}}this._config.height=e},setMaxWidth:function(e){e=e*1;if(!e&&e!=0||isNaN(e)||e<0){return}if(e!=0){if(e<220){e=220}if(e>730){e=730}}this._config.maxWidth=e},setTitle:function(e){this._config.title=e||""},setContent:function(e){this.content=e||""},setMaxContent:function(e){this._config.maxContent=e||""},redraw:function(){},enableAutoPan:function(){this._config.enableAutoPan=true},disableAutoPan:function(){this._config.enableAutoPan=false},enableCloseOnClick:function(){this._config.enableCloseOnClick=true},disableCloseOnClick:function(){this._config.enableCloseOnClick=false},enableMaximize:function(){this._config.enableMaximize=true},disableMaximize:function(){this._config.enableMaximize=false},show:function(){this._visible=true},hide:function(){this._visible=false},close:function(){this.hide()},dispose:function(){l.BaseClass.prototype.decontrol.call(this)},maximize:function(){this.isWinMax=true},restore:function(){this.isWinMax=false},setConfig:function(i){if(!i){return}for(var e in i){if(typeof(this._config[e])==typeof(i[e])){this._config[e]=i[e]}}},isVisible:function(){return this.isOpen()},isOpen:function(){return false},getPoint:function(){if(this.overlay&&this.overlay.getPoint){return this.overlay.getPoint()}},getOffset:function(){return this._config.offset},toString:function(){return"InfoWindow"}});C.prototype.openInfoWindow=function(aU,e){if(!aU||aU.toString()!="InfoWindow"||!e||e.toString()!="Point"){return}var i=this.temp;if(!i.marker){var aT=new w(aQ.imgPath+"blank.gif",{width:1,height:1});i.marker=new J(e,{icon:aT,width:1,height:1,offset:new X(0,0),infoWindowOffset:new X(0,0),clickable:false});i.marker._fromMap=1}else{i.marker.setPoint(e)}this.addOverlay(i.marker);i.marker.openInfoWindow(aU)};C.prototype.closeInfoWindow=function(){var e=this.temp.infoWin||this.temp._infoWin;if(e&&e.overlay){e.overlay.closeInfoWindow()}};aF.prototype.openInfoWindow=function(e){if(this.map){this.map.closeInfoWindow();e._visible=true;this.map.temp._infoWin=e;e.overlay=this;l.BaseClass.call(e,e.hashCode)}};aF.prototype.closeInfoWindow=function(){if(this.map&&this.map.temp._infoWin){this.map.temp._infoWin._visible=false;this.map.temp._infoWin.decontrol();this.map.temp._infoWin=null}};function q(aT,i){aF.call(this);this.content=aT;this.map=null;this.domElement=null;this._config={width:0,offset:new X(0,0),styles:{backgroundColor:"#fff",border:"1px solid #f00",padding:"1px",whiteSpace:"nowrap",font:"12px arial,simsun",zIndex:"80",MozUserSelect:"none"},point:null,enableMassClear:true,clickable:true};i=i||{};this.setConfig(i);if(this._config.width<0){this._config.width=0}this.point=this._config.point;var e=this;aq.load("marker",function(){e._draw()})}q.inherits(aF,"Label");l.extend(q.prototype,{setPoint:function(e){if(e&&e.toString()=="Point"&&!this.getMarker()){this.point=this._config.point=new f(e.lng,e.lat)}},setContent:function(e){this.content=e},setOpacity:function(e){if(e>=0&&e<=1){this._config.opacity=e}},setOffset:function(e){if(!e||e.toString()!="Size"){return}this._config.offset=new X(e.width,e.height)},getOffset:function(){return this._config.offset},setStyle:function(e){e=e||{};this._config.styles=l.extend(this._config.styles,e)},setStyles:function(e){return this.setStyle(e)},setTitle:function(e){this._config.title=e||""},getTitle:function(){return this._config.title},setMarker:function(e){this._marker=e;if(e){this.point=this._config.point=e.getPoint()}else{this.point=this._config.point=null}},getMarker:function(){return this._marker||null}});function J(e,aT){aF.call(this);aT=aT||{};this.point=e;this.map=null;this.domElement=null;this.iconDom=null;this.infoWindowDom=null;this.siblingElement=null;this.iconClassName="";this._config={offset:new X(0,0),opacity:1,icon:null,title:"",infoWindow:null,label:null,baseZIndex:0,clickable:true,zIndexFixed:false,isTop:false,enableMassClear:true,enableDragging:false,restrictDraggingArea:false};this.setConfig(aT);if(!aT.icon){this._config.icon=new BMap.Icon(aQ.imgPath+"marker_red.png",new X(23,25),{offset:new X(10,25),infoWindowOffset:new X(10,0)})}this._isDragging=false;var i=this;aq.load("marker",function(){i._draw()})}J.TOP_ZINDEX=O.getZIndex(-90)+1000000;J.DRAG_ZINDEX=J.TOP_ZINDEX+1000000;J.inherits(aF,"Marker");l.extend(J.prototype,{setIcon:function(e){if(e&&e.toString()=="Icon"){this._config.icon=e}},setIconClassName:function(e){if(this.iconDom){this.iconDom.className=e}},getIcon:function(){return this._config.icon},setLabel:function(e){if(e&&e.toString()=="Label"){this._config.label=e}},getLabel:function(){return this._config.label},enableDragging:function(e){this._config.enableDragging=true},disableDragging:function(){this._config.enableDragging=false},setPoint:function(e){if(e&&e.toString()=="Point"){this.point=this._config.point=new f(e.lng,e.lat)}},setTop:function(i,e){this._config.isTop=!!i;if(i){this._addi=e||0}},setTitle:function(e){this._config.title=e},getTitle:function(){return this._config.title||""},setOffset:function(e){if(e&&e.toString()=="Size"){this._config.offset=e}},getOffset:function(){return this._config.offset}});function c(e,aT){au.call(this,aT);aT=aT||{};this._config.fillOpacity=aT.fillOpacity?aT.fillOpacity:0.65;if(aT.fillColor==""){this._config.fillColor=""}else{this._config.fillColor=aT.fillColor?aT.fillColor:"#fff"}this.setPoints(e);var i=this;aq.load("poly",function(){i._draw()})}c.inherits(au,"Polygon");l.extend(c.prototype,{setPoints:function(i,e){this._userPoints=au.getGraphPoints(i).slice(0);var aT=au.getGraphPoints(i).slice(0);if(aT.length>1&&!aT[0].equals(aT[aT.length-1])){aT.push(new f(aT[0].lng,aT[0].lat))}au.prototype.setPoints.call(this,aT,e)},setPointAt:function(i,e){if(!this._userPoints[i]){return}this._userPoints[i]=new f(e.lng,e.lat);this.points[i]=new f(e.lng,e.lat);if(i==0&&!this.points[0].equals(this.points[this.points.length-1])){this.points[this.points.length-1]=new f(e.lng,e.lat)}this._calcBounds()},getPoints:function(){var e=this._userPoints;if(e.length==0){e=this.points}return e}});function ai(e,aT){au.call(this,aT);this.setPoints(e);var i=this;aq.load("poly",function(){i._draw()})}ai.inherits(au,"Polyline");function Y(i,e,aT){this.point=i;this.radius=Math.abs(e);c.call(this,[],aT)}Y.parseTolerance={0:[0.01,0.0001,0.00001,0.000004],1:[1000,10,1,0.4]};Y.inherits(c,"Circle");l.extend(Y.prototype,{initialize:function(e){this.map=e;this.points=this._getPerimeterPoints(this.point,this.radius);this._calcBounds();return null},getPoint:function(){return this.point},getCenter:function(){return this.point},setPoint:function(e,i){if(!e){return}this.point=e},setCenter:function(e,i){this.setPoint(e,i)},getRadius:function(){return this.radius},setRadius:function(e,i){this.radius=Math.abs(e)},_getPerimeterPoints:function(e,a0){if(!e||!a0||!this.map){return[]}var aT=this.map;var aX=e.lng,aV=e.lat;if(aT.config.coordType==BMAP_COORD_MERCATOR){var a6=ar.convertMC2LL(e);aX=a6.lng;aV=a6.lat}var a8=[];var a2=a0/6378800,aZ=(Math.PI/180)*aV,a5=(Math.PI/180)*aX;for(var aY=0;aY<360;aY+=9){var aW=(Math.PI/180)*aY,a3=Math.asin(Math.sin(aZ)*Math.cos(a2)+Math.cos(aZ)*Math.sin(a2)*Math.cos(aW)),a1=Math.atan2(Math.sin(aW)*Math.sin(a2)*Math.cos(aZ),Math.cos(a2)-Math.sin(aZ)*Math.sin(a3)),a4=((a5-a1+Math.PI)%(2*Math.PI))-Math.PI,a7=new f(a4*(180/Math.PI),a3*(180/Math.PI));if(aT.config.coordType==BMAP_COORD_LNGLAT){a8.push(a7)}else{a8.push(V.convertLL2MC(a7))}}var aU=a8[0];a8.push(new f(aU.lng,aU.lat));return a8}});function G(e,aT){c.call(this,e,aT);var i=this;aq.load("poly",function(){i._draw()})}G.inherits(c,"Rectangle");l.extend(G.prototype,{setPoints:function(aU){if(!aU){return}var aT=aU[0],e=aU[1];if(!aT||!e||aT.toString()!="Point"||e.toString()!="Point"){return}var aY=aT;var aW=e;var aX=new f(aY.lng,aW.lat);var aV=new f(aW.lng,aY.lat);var i=aT;this.points=[aY,aX,aW,aV,i];this._calcBounds()},getPoints:function(){return[this.points[0],this.points[2]]}});function aK(e,i){e=isNaN(e)?0:e;i=isNaN(i)?0:i;this.x=e;this.y=i}aK.prototype.equals=function(e){if(!e){return false}return e.x==this.x&&e.y==this.y};aK.prototype.toString=function(){return"Pixel"};function V(){}var ar=V;l.extend(V,{EARTHRADIUS:6370996.81,MCBAND:[12890594.86,8362377.87,5591021,3481989.83,1678043.12,0],LLBAND:[75,60,45,30,15,0],MC2LL:[[1.410526172116255e-8,0.00000898305509648872,-1.9939833816331,200.9824383106796,-187.2403703815547,91.6087516669843,-23.38765649603339,2.57121317296198,-0.03801003308653,17337981.2],[-7.435856389565537e-9,0.000008983055097726239,-0.78625201886289,96.32687599759846,-1.85204757529826,-59.36935905485877,47.40033549296737,-16.50741931063887,2.28786674699375,10260144.86],[-3.030883460898826e-8,0.00000898305509983578,0.30071316287616,59.74293618442277,7.357984074871,-25.38371002664745,13.45380521110908,-3.29883767235584,0.32710905363475,6856817.37],[-1.981981304930552e-8,0.000008983055099779535,0.03278182852591,40.31678527705744,0.65659298677277,-4.44255534477492,0.85341911805263,0.12923347998204,-0.04625736007561,4482777.06],[3.09191371068437e-9,0.000008983055096812155,0.00006995724062,23.10934304144901,-0.00023663490511,-0.6321817810242,-0.00663494467273,0.03430082397953,-0.00466043876332,2555164.4],[2.890871144776878e-9,0.000008983055095805407,-3.068298e-8,7.47137025468032,-0.00000353937994,-0.02145144861037,-0.00001234426596,0.00010322952773,-0.00000323890364,826088.5]],LL2MC:[[-0.0015702102444,111320.7020616939,1704480524535203,-10338987376042340,26112667856603880,-35149669176653700,26595700718403920,-10725012454188240,1800819912950474,82.5],[0.0008277824516172526,111320.7020463578,647795574.6671607,-4082003173.641316,10774905663.51142,-15171875531.51559,12053065338.62167,-5124939663.577472,913311935.9512032,67.5],[0.00337398766765,111320.7020202162,4481351.045890365,-23393751.19931662,79682215.47186455,-115964993.2797253,97236711.15602145,-43661946.33752821,8477230.501135234,52.5],[0.00220636496208,111320.7020209128,51751.86112841131,3796837.749470245,992013.7397791013,-1221952.21711287,1340652.697009075,-620943.6990984312,144416.9293806241,37.5],[-0.0003441963504368392,111320.7020576856,278.2353980772752,2485758.690035394,6070.750963243378,54821.18345352118,9540.606633304236,-2710.55326746645,1405.483844121726,22.5],[-0.0003218135878613132,111320.7020701615,0.00369383431289,823725.6402795718,0.46104986909093,2351.343141331292,1.58060784298199,8.77738589078284,0.37238884252424,7.45]],getDistanceByMC:function(aW,aU){if(typeof(aW)=="undefined"||typeof(aU)=="undefined"){return 0}var i,aV,e,aT;aW=this.convertMC2LL(aW);if(typeof(aW)=="undefined"){return 0}i=this.toRadians(aW.lng);aV=this.toRadians(aW.lat);aU=this.convertMC2LL(aU);if(typeof(aU)=="undefined"){return 0}e=this.toRadians(aU.lng);aT=this.toRadians(aU.lat);return this.getDistance(i,e,aV,aT)},getDistanceByLL:function(aW,aU){if(typeof(aW)=="undefined"||typeof(aU)=="undefined"){return 0}aW.lng=this.getLoop(aW.lng,-180,180);aW.lat=this.getRange(aW.lat,-74,74);aU.lng=this.getLoop(aU.lng,-180,180);aU.lat=this.getRange(aU.lat,-74,74);var i,e,aV,aT;i=this.toRadians(aW.lng);aV=this.toRadians(aW.lat);e=this.toRadians(aU.lng);aT=this.toRadians(aU.lat);return this.getDistance(i,e,aV,aT)},convertMC2LL:function(aT){var aU,aW;aU=new f(Math.abs(aT.lng),Math.abs(aT.lat));for(var aV=0;aV=this.MCBAND[aV]){aW=this.MC2LL[aV];break}}var e=this.convertor(aT,aW);var aT=new f(e.lng.toFixed(6),e.lat.toFixed(6));return aT},convertLL2MC:function(e){var aT,aV;e.lng=this.getLoop(e.lng,-180,180);e.lat=this.getRange(e.lat,-74,74);aT=new f(e.lng,e.lat);for(var aU=0;aU=this.LLBAND[aU]){aV=this.LL2MC[aU];break}}if(!aV){for(var aU=this.LLBAND.length-1;aU>=0;aU--){if(aT.lat<=-this.LLBAND[aU]){aV=this.LL2MC[aU];break}}}var aW=this.convertor(e,aV);var e=new f(aW.lng.toFixed(2),aW.lat.toFixed(2));return e},convertor:function(aT,aU){if(!aT||!aU){return}var e=aU[0]+aU[1]*Math.abs(aT.lng);var i=Math.abs(aT.lat)/aU[9];var aV=aU[2]+aU[3]*i+aU[4]*i*i+aU[5]*i*i*i+aU[6]*i*i*i*i+aU[7]*i*i*i*i*i+aU[8]*i*i*i*i*i*i;e*=(aT.lng<0?-1:1);aV*=(aT.lat<0?-1:1);return new f(e,aV)},getDistance:function(i,e,aU,aT){return this.EARTHRADIUS*Math.acos((Math.sin(aU)*Math.sin(aT)+Math.cos(aU)*Math.cos(aT)*Math.cos(e-i)))},toRadians:function(e){return Math.PI*e/180},toDegrees:function(e){return(180*e)/Math.PI},getRange:function(aT,i,e){if(i!=null){aT=Math.max(aT,i)}if(e!=null){aT=Math.min(aT,e)}return aT},getLoop:function(aT,i,e){while(aT>e){aT-=e-i}while(aT0){a8[aX.name]=aX;a8.push(aX.name)}var bb=a8.length-a4.bufferNumber;for(var a5=0;bb>0&&a50&&aU.isTransparentPng()==true){var ba=aX.src.toUpperCase();var a2=aX.img.style;var a3=a2.width;var bc=a2.height;var a9='position:absolute;FILTER: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="'+aX.src+'",sizingMethod=scale);';a2.cssText=a9;a2.width=a3;a2.height=bc;a2.left=aX.position[0]+"px";a2.top=aX.position[1]+"px"}}}var a7=new aw("onimagechange");a7.action="show";a7.tile=aX.name;a4.map.dispatchEvent(a7)};this.img.onerror=function(a3){if(!aX.mgr){return}var a1=aX.mgr;aX.error=true;var a2=aJ[aU.mapType];if(a2.errorUrl){aX.img.src=a2.errorUrl}if(!s(aX.img)){if(aU.tilesDiv){aU.tilesDiv.appendChild(aX.img)}}};if(FeBrowser.ie<=6&&FeBrowser.ie>0&&aU.isTransparentPng()==true){a0.src=aQ.imgPath+"blank.gif"}else{a0.src=i}a0=null;var aW=new aw("onimagebefore");aW.tile=aX.name;aZ.map.dispatchEvent(aW)}function aE(e){this.tileLayers=[];this.cacheDiv=null;this.map=e;this.bufferNumber=300;this.mapTiles=[];this.bufferTiles=[];this.slideMaxZoom=4;this.config=aJ[this.map.mapType];this.errorUrl=this.config.errorUrl;this.tileSize=this.config.tileSize;this.baseUnits=this.config.baseUnits;this.minZoomLevel=this.config.zoomLevelMin;this.maxZoomLevel=this.config.zoomLevelMax;this.tileURLs=this.config.tileUrls;this.imgNumber=0;this.temp={}}BMap.register(function(i){var e=i.tileMgr=new aE(i);i.addEventListener("dragstart",function(aT){e.dragStart(aT)});i.addEventListener("dragend",function(aT){e.dragEnd(aT)});i.addEventListener("click",function(aT){e.click(aT)});i.addEventListener("mousewheel",function(aT){e.mouseWheel(aT)});i.addEventListener("dblclick",function(aT){e.dblClick(aT)});i.addEventListener("rightdblclick",function(aT){e.dblClick(aT)});i.addEventListener("minuspress",function(aT){e.keypress(aT)});i.addEventListener("pluspress",function(aT){e.keypress(aT)});i.addEventListener("load",function(aT){e.loadTiles()});i.addEventListener("zoomstartcode",function(aT){e._zoom(aT)});i.addEventListener("moving",function(aT){e.mend(aT)});i.addEventListener("resize",function(aT){e.resizeMap(aT)});i.addEventListener("addtilelayer",function(aT){e.addTileLayer(aT)});i.addEventListener("removetilelayer",function(aT){e.removeTileLayer(aT)})});l.extend(aE.prototype,{addTileLayer:function(aU){var aT=this;var i=aU.target;aT.tileLayers.push(i);if(aT.map.loaded){aT.moveGridTiles(true)}},removeTileLayer:function(a0){var a1=this;var aY=a0.target;var aW=aY.mapType;var aV=a1.mapTiles;var a2=a1.bufferTiles;for(var aT in a2){var aU=aT.split("-")[1];if(aU==aW){delete a2[aT]}}for(var aT in aV){var aU=aT.split("-")[1];if(aU==aW){delete aV[aT]}}if(a1.zoomsDiv&&a1.zoomsDiv.parentNode){a1.zoomsDiv.parentNode.removeChild(a1.zoomsDiv);a1.zoomsDiv.innerHTML=""}for(var aZ=0,aX=a1.tileLayers.length;aZbj[0]||be<=bj[0]||aU>bj[1]||a4<=bj[1])){this.hideTile(bn,aW)}else{if(bj[2]!=bm.zoomLevel){this.hideTile(bn,aW)}else{if(bj[2]==bm.lastLevel){this.showTile(bj,[bk[0]*Math.pow(2,bm.zoomLevel-bm.lastLevel),bk[1]*Math.pow(2,bm.zoomLevel-bm.lastLevel)],bc,aW)}}}}var aY=-bm.offsetX+bm.width/2;var a6=-bm.offsetY+bm.height/2;aW.tilesDiv.style.left=Math.round(a0+aY)-bk[0]+"px";aW.tilesDiv.style.top=Math.round(aZ+a6)-bk[1]+"px";var e=[];this.imgTotalNumber=0;for(var bg=bh;bg
');i.style.display="";i.style.left=Math.ceil(-aT.offsetX+aT.width/2)+"px";i.style.top=Math.ceil(-aT.offsetY+aT.height/2)+"px";this.tilesDiv=i;this.map=aT},remove:function(){if(this.tilesDiv&&this.tilesDiv.parentNode){this.tilesDiv.innerHTML="";this.tilesDiv.parentNode.removeChild(this.tilesDiv)}delete this.tilesDiv},getCopyright:function(){return this.copyright},getMapType:function(){return this.mapType},setZIndex:function(e){this.zIndex=e;if(this.tilesDiv){this.tilesDiv.style.zIndex=e}}});function af(i,e,aT){this.bounds=i;this.content=e;this.mapType=aT}af.inherits(E,"Copyright");function aH(e){this._opts={};e=e||{};this._opts=l.extend(this._opts,e);if(this._opts.predictDate){if(this._opts.predictDate.weekday<1||this._opts.predictDate.weekday>7){this._opts.predictDate=1}if(this._opts.predictDate.hour<0||this._opts.predictDate.hour>23){this._opts.predictDate.hour=0}}this._tileUrl="https://its.map.baidu.com:8002/traffic/"}aH.prototype=new F();aH.prototype.initialize=function(e){F.prototype.initialize.call(this,e);this._map=e};aH.prototype.isTransparentPng=function(){return this._opts.transparentPng};aH.prototype.getTilesUrl=function(aX,i){var aY="";if(this._opts.predictDate){aY="HistoryService?day="+(this._opts.predictDate.weekday-1)+"&hour="+this._opts.predictDate.hour+"&t="+new Date().getTime()+"&"}else{aY="TrafficTileService?time="+new Date().getTime()+"&"}var aT=this._map,aZ=aX.x,aU=aX.y,aW=Math.floor(aZ/200),aV=Math.floor(aU/200),e=this._tileUrl+aY+"level="+i+"&x="+aZ+"&y="+aU;return e.replace(/-(\d+)/gi,"M$1")};function ao(e){E.call(this);if(!e){return}this._opts={};this._map=e}ao.inherits(E,"ToolbarItem");l.extend(ao.prototype,{open:function(){if(this._isOpen==true){return true}if(this._map._toolInUse){return false}this._map._toolInUse=true;this._isOpen=true;return true},close:function(){if(!this._isOpen){return}this._map._toolInUse=false;this._isOpen=false},_checkStr:function(e){if(!e){return""}return e.replace(//g,">")}});function ak(aT,i){ao.call(this,aT);this._opts=l.extend(l.extend(this._opts,{icon:null,iconFollow:false,followText:"",cursor:"pointer"}),i);this._isOpen=false;this._opts.followText=this._checkStr(this._opts.followText);this.followTitle=this._opts.followText;this.followMarker=null;this._overlays=[];var e=this;aq.load("tools",function(){e._draw()})}ak.inherits(ao,"PushpinTool");l.extend(ak.prototype,{setIcon:function(e){if(!e||e&&e.toString()!="Icon"){return}this._opts.icon=e},getIcon:function(){return this._opts.icon},setCursor:function(e){this._opts.cursor=e},getCursor:function(){return this._opts.cursor},clear:function(){for(var aT=0,e=this._overlays.length;aT1){this._opts.opacity=1}else{if(this._opts.opacity<0){this._opts.opacity=0}}if(this._opts.lineStyle!="solid"&&this._opts.lineStyle!="dashed"){this._opts.lineStyle="solid"}this._checked=false;this._drawing=null;this.followTitle=null;this._totalDis={};this._points=[];this._paths=[];this._dots=[];this._segDistance=[];this._overlays=[];this._units={metric:{name:"metric",conv:1,incon:1000,u1:"\u7c73",u2:"\u516c\u91cc"},us:{name:"us",conv:3.2808,incon:5279.856,u1:"\u82f1\u5c3a",u2:"\u82f1\u91cc"}};if(!this._units[this._opts.unit]){this._opts.unit="metric"}this._dLineColor="#ff6319";this._dLineStroke=3;this._dOpacity=0.8;this._dLineStyle="solid";this._dCursor=aQ.imgPath+"ruler.cur";if(this._opts.showResult){this._opts.followText="\u5355\u51fb\u786e\u5b9a\u8d77\u70b9"}this._followTextM="\u5355\u51fb\u786e\u5b9a\u5730\u70b9\uff0c\u53cc\u51fb\u7ed3\u675f";this._movingTimerId=null;if(this._opts.showResult){this.text="\u6d4b\u8ddd"}else{this.text="\u7ed8\u7ebf"}this._isOpen=false;var e=this;aq.load("tools",function(){e._draw()})}S.inherits(ao,"PolylineTItem");l.extend(S.prototype,{setLineColor:function(e){this._opts.lineColor=e},setLineStroke:function(e){if(Math.round(e)>0){this._opts.lineStroke=Math.round(e)}},setOpacity:function(e){if(e>=0&&e<=1){this._opts.opacity=e}},setLineStyle:function(e){if(e=="solid"||e=="dashed"){this._opts.lineStyle=e}},clear:function(){for(var aT=0,e=this._overlays.length;aT1?1:this._opts.opacity;if(this._opts.zoomTypeBMAP_ZOOM_OUT){this._opts.zoomType=BMAP_ZOOM_IN}this._isOpen=false;this._fDiv=null;this.followTitle=null;var e=this;aq.load("tools",function(){e._draw()})}n.inherits(ao,"DragAndZoomTool");l.extend(n.prototype,{setStrokeColor:function(e){if(typeof e=="string"){this._opts.strokeColor=e}},setLineStroke:function(e){if(typeof e=="number"&&Math.round(e)>0){this._opts.strokeWeight=Math.round(e)}},setLineStyle:function(e){if(e=="solid"||e=="dashed"){this._opts.style=e}},setOpacity:function(e){if(typeof e=="number"&&e>=0&&e<=1){this._opts.opacity=e}},setLineStyle:function(e){if(e=="solid"||e=="dashed"){this._opts.style=e}},setFillColor:function(e){this._opts.fillColor=e},setCursor:function(e){this._opts.cursor=e},getCursor:function(){return this._opts.cursor},toString:function(){return"DragAndZoomTool"}});function ad(){this._container=null}BMap.register(function(i){if(i.config.isOverviewMap){return}var e=new ad();i.container.insertAdjacentHTML("beforeEnd",e.render(i.config.defaultCursor));e._container=i.container.lastChild;i.temp.zoomer=e});ad.prototype.render=function(i){var e=['");return e.join("")};ad.prototype.action=function(aZ,a0){if(ad._timeline){return}var aY=this._container;if(!aY){return}var a7=a0;var aT=60;var a6=120;var a1=4/3,aV=Math.ceil((a7?aT:a6)/2),aW=Math.max(15,aV/a1),aX=aY.style;aX.width=aV*2+"px";aX.height=aW*2+"px";aX.visibility="visible";var a3=aY.children;if(a7){a3[0].style.backgroundPosition="0 0";a3[1].style.backgroundPosition="-7px 0";a3[2].style.backgroundPosition="0 -7px";a3[3].style.backgroundPosition="-7px -7px"}else{a3[0].style.backgroundPosition="-7px -7px";a3[1].style.backgroundPosition="0 -7px";a3[2].style.backgroundPosition="-7px 0";a3[3].style.backgroundPosition="0 0"}a3=null;var a5=aZ.x-aV;var a4=aZ.y-aW;if(isNaN(a5)||isNaN(a4)){return}aX.left=a5+"px";aX.top=a4+"px";var i=Math.ceil((a7?a6:aT)/2);var aU=Math.max(15,i/a1);i=i-aV;aU=Math.ceil(aU-aW);var a2=this;var e=a2._container.style;if(ad._timeline){ad._timeline.end()}ad._timeline=new aG({fps:20,duration:240,transition:k.easeInQuad,delay:100,render:function(a9){if(a9<0.1){return}var ba=Math.ceil(i*a9);var a8=Math.ceil(aU*a9);e.width=(aV+ba)*2+"px";e.height=(aW+a8)*2+"px";e.left=a5-ba+"px";e.top=a4-a8+"px"},finish:function(){ad._timeline=false;setTimeout(function(){aX.visibility="hidden"},300)}})};BMap.Map=C;BMap.MapType=aJ;BMap.Point=f;BMap.Pixel=aK;BMap.Size=X;BMap.Bounds=y;BMap.Area=x;BMap.TileLayer=F;BMap.Copyright=af;BMap.CoordTrans=m;BMap.Projection=V;BMap.Overlay=O;BMap.Label=q;BMap.Marker=J;BMap.Icon=w;BMap.Polyline=ai;BMap.Polygon=c;BMap.Rectangle=G;BMap.InfoWindow=ay;BMap.Circle=Y;BMap.Control=P;BMap.NavigationControl=H;BMap.OverviewMapControl=ah;BMap.CopyrightControl=K;BMap.ScaleControl=T;BMap.MapTypeControl=ae;BMap.PushpinTool=ak;BMap.DistanceTool=S;BMap.DragAndZoomTool=n;BMap.TrafficLayer=aH;BMap.ContextMenu=g;BMap.MenuItem=L;BMap.OperationMask=ap;BMap.register(function(e){if(e.config&&e.config.isOverviewMap){return}e.addEventListener("load",function(){if(e.temp.copyadded){return}e.temp.copyadded=true;var aU=new K({offset:new X(81,2),printable:true});var aT="© 2015 Baidu";if(e.getMapType()==BMAP_PERSPECTIVE_MAP){aT='© 2013 Baidu - Data © \u90fd\u5e02\u5708'}aU.addCopyright({content:aT,id:1});e.addEventListener("maptypechange",function(){var aV=e.getMapType();if(aV==BMAP_PERSPECTIVE_MAP){aU.addCopyright({id:1,content:'© 2013 Baidu - Data © \u90fd\u5e02\u5708'})}if(aV==BMAP_NORMAL_MAP){aU.addCopyright({id:1,content:"© 2013 Baidu"})}});e.addControl(aU);var i=new I();i._opts={printable:true};e.addControl(i);e.addEventListener("resize",function(){if(this.getSize().width>=220&&e.getSize().height>=100){i.show();aU.setOffset(new X(81,2))}else{i.hide();aU.setOffset(new X(4,2))}});if(e.getSize().width>=220&&e.getSize().height>=100){i.show()}else{i.hide();aU.setOffset(new X(4,2))}})});function I(e){this.defaultAnchor=BMAP_ANCHOR_BOTTOM_LEFT;this.defaultOffset=new X(1,0);this._useSmallImage=!!(l.Platform.ipad||l.Platform.iphone||l.Platform.android);this.IMG_URL=aQ.imgPath+(this._useSmallImage?"copyright_logo_s.png":"copyright_logo.png")}I.prototype=new P();I.prototype.initialize=function(i){this._map=i;var aT=t("div");aT.style.height="32px";var e=t("a",{title:"\u5230\u767e\u5ea6\u5730\u56fe\u9996\u9875",target:"_blank",href:"https://map.baidu.com/?sr=1"});e.style.outline="none";if(l.Browser.ie==6){e.innerHTML="
"}else{e.innerHTML=""}if(this._useSmallImage){aT.style.height="25px";e.href="#";e.innerHTML=""}aT.appendChild(e);i.getContainer().appendChild(aT);e=null;return aT};window.BMap.apiLoad();})(); + +(function(){var baidu=baidu||{version:"1-1-0"};baidu.event=baidu.event||{};baidu.event._unload=function(){var c=baidu.event._listeners,a=c.length,b=!!window.removeEventListener,e,d;while(a--){e=c[a];d=e[0];if(d.removeEventListener){d.removeEventListener(e[1],e[3],false)}else{if(d.detachEvent){d.detachEvent("on"+e[1],e[3])}}}if(b){window.removeEventListener("unload",baidu.event._unload,false)}else{window.detachEvent("onunload",baidu.event._unload)}};if(window.attachEvent){window.attachEvent("onunload",baidu.event._unload)}else{window.addEventListener("unload",baidu.event._unload,false)}baidu.event._listeners=baidu.event._listeners||[];baidu.event.un=function(c,d,f){if("string"==typeof c){c=baidu.dom.g(c)}d=d.replace(/^on/i,"");var b=baidu.event._listeners,a=b.length,g=!f,e;while(a--){e=b[a];if(e[1]===d&&e[0]===c&&(g||e[2]===f)){if(c.detachEvent){c.detachEvent("on"+d,e[3])}else{if(c.removeEventListener){c.removeEventListener(d,e[3],false)}}b.splice(a,1)}}return c};baidu.un=baidu.event.un;baidu.array=baidu.array||{};baidu.string=baidu.string||{};baidu.string.trim=function(a){return String(a).replace(new RegExp("(^[\\s\\t\\xa0\\u3000]+)|([\\u3000\\xa0\\s\\t]+\x24)","g"),"")};baidu.trim=baidu.string.trim;baidu.object=baidu.object||{};baidu.object.extend=function(c,a){for(var b in a){if(a.hasOwnProperty(b)){c[b]=a[b]}}};baidu.extend=baidu.object.extend;baidu.event.on=function(b,d,e){d=d.replace(/^on/i,"");if("string"==typeof b){b=baidu.dom.g(b)}var c=function(f){e.call(b,f)},a=baidu.event._listeners;a[a.length]=[b,d,e,c];if(b.attachEvent){b.attachEvent("on"+d,c)}else{if(b.addEventListener){b.addEventListener(d,c,false)}}return b};baidu.on=baidu.event.on;baidu.lang=baidu.lang||{};baidu.lang._instances=baidu.lang._instances||{};baidu.lang.instance=function(a){return baidu.lang._instances[a]||null};baidu.lang.inherits=function(g,e,d){var c,f,a=g.prototype,b=new Function();b.prototype=e.prototype;f=g.prototype=new b();for(c in a){f[c]=a[c]}g.prototype.constructor=g;g.superClass=e.prototype;if("string"==typeof d){f._className=d}};baidu.inherits=baidu.lang.inherits;baidu.dom=baidu.dom||{};baidu.dom.g=function(a){if("string"==typeof a||a instanceof String){return document.getElementById(a)}else{if(a&&a.nodeName&&(a.nodeType==1||a.nodeType==9)){return a}}return null};baidu.g=baidu.G=baidu.dom.g;baidu.lang._insCounter=baidu.lang._insCounter||1;baidu.lang.Class=function(a){this.guid=a||baidu.lang.Class.guid();baidu.lang._instances[this.guid]=this};baidu.lang.Class.guid=function(){return"TANGRAM__"+(baidu.lang._insCounter++).toString(36)};baidu.lang.Class.create=function(b){var d=new baidu.lang.Class();for(var a in b){d[a]=b[a]}return d};baidu.lang.Class.prototype.dispose=function(){if(this.guid){delete baidu.lang._instances[this.guid]}for(var a in this){if(typeof this[a]!="function"){delete this[a]}}};baidu.lang.Class.prototype.toString=function(){return this._className||"Object"};var CITY_TYPE_PROV=1;var CITY_TYPE_CITY=2;var CITY_TYPE_DIST=3;var RED_ICON_SIZE=new BMap.Size(23,25);var RED_ICON_OFFSET=new BMap.Size(9,25);var RED_ICON_INFOWND_OFFSET=new BMap.Size(9,0);function addSearchPoi(map,point,index,title,coordType){var pt=getPoiPoint(point,map.config.coordType,coordType);if(!pt){return}if(index<0||index>9){return}var ico=new BMap.Icon(API_URL+"img/markers.png",RED_ICON_SIZE,{offset:RED_ICON_OFFSET,imageOffset:new BMap.Size(0,-25*index),infoWindowOffset:RED_ICON_INFOWND_OFFSET});var mkr=new BMap.Marker(pt,{icon:ico});map.addOverlay(mkr);if(title){mkr.setTitle(title)}return mkr}function addCenterPoi(map,point,title,coordType){var pt=getPoiPoint(point,map.config.coordType,coordType);if(!pt){return}var ico=new BMap.Icon(API_URL+"img/markers.png",RED_ICON_SIZE,{offset:RED_ICON_OFFSET,imageOffset:new BMap.Size(0,-250),infoWindowOffset:RED_ICON_INFOWND_OFFSET});var mkr=new BMap.Marker(pt,{icon:ico});map.addOverlay(mkr);if(title){mkr.setTitle(title)}return mkr}function addSearchInBoundsPoi(map,point,title,coordType){var pt=getPoiPoint(point,map.config.coordType,coordType);if(!pt){return}var ico=new BMap.Icon(API_URL+"img/markers.png",RED_ICON_SIZE,{offset:RED_ICON_OFFSET,imageOffset:new BMap.Size(0,-300),infoWindowOffset:RED_ICON_INFOWND_OFFSET});var mkr=new BMap.Marker(pt,{icon:ico});map.addOverlay(mkr);if(title){mkr.setTitle(title)}return mkr}function getPoiPoint(point,mapCoordType,searchCoordType){var pts=[];var pt=null;if(point&&point.toString()=="Point"){pt=point}else{if(typeof point=="string"){pts=baidu.trim(point).split(",");if(pts.length<2){return}pts[0]=parseFloat(baidu.trim(pts[0]));pts[1]=parseFloat(baidu.trim(pts[1]))}else{pts=point.slice(0);if(pts.length<2){return}}pt=new BMap.Point(pts[0],pts[1])}pt=convertCoord(pt,searchCoordType,mapCoordType);return pt}window.BMAP_POI_TYPE_NORMAL=0;window.BMAP_POI_TYPE_BUSSTOP=1;window.BMAP_POI_TYPE_BUSLINE=2;window.BMAP_POI_TYPE_SUBSTOP=3;window.BMAP_POI_TYPE_SUBLINE=4;function createSearchInfoWnd(contents,opts){var title=contents.title;var addr=contents.addr;var tel=contents.tel;var uid=contents.uid||"";var url=contents.url;var poiType=contents.poiType||BMAP_POI_TYPE_NORMAL;opts=opts||{};if(!title){return null}var ntitle=title;if(poiType==BMAP_POI_TYPE_BUSSTOP){ntitle=ntitle+"-\u516c\u4ea4\u8f66\u7ad9"}else{if(poiType==BMAP_POI_TYPE_SUBSTOP){ntitle=ntitle+"-\u5730\u94c1\u7ad9"}}if(ntitle.replace(/[\u0100-\uffff]/g,"##").length>27){ntitle=ntitle.substring(0,13)+"…"}var thtml="

"+ntitle+"

";var htmls=[];htmls.push("
");if(addr){var addrTitle="\u5730\u5740\uff1a";if(poiType==BMAP_POI_TYPE_BUSSTOP||poiType==BMAP_POI_TYPE_SUBSTOP){addrTitle="\u8f66\u6b21\uff1a"}htmls.push('');htmls.push('");if(tel){htmls.push("")}htmls.push("
'+addrTitle+' ');htmls.push(addr+" 
\u7535\u8bdd\uff1a"+tel+"
")}else{if(tel){htmls.push('');htmls.push('
\u7535\u8bdd\uff1a'+tel+"
")}}htmls.push("
");var iw=new BMap.InfoWindow(htmls.join(""),{title:thtml,height:0,width:230,margin:[10,10,20,10]});return iw}var DEST_START=0;var DEST_END=1;function addDestPoi(map,point,title,type,coordType){var pt=getPoiPoint(point,map.config.coordType,coordType);if(!pt){return}var ico=new BMap.Icon(API_URL+"img/dest_markers.png",new BMap.Size(42,34),{offset:new BMap.Size(14,32),imageOffset:new BMap.Size(0,-34*type),infoWindowOffset:new BMap.Size(14,0)});var mkr=new BMap.Marker(pt,{icon:ico,baseZIndex:3500000});map.addOverlay(mkr);if(title){mkr.setTitle(title)}return mkr}var ROUTE_TYPE_DEFAULT=0;var ROUTE_TYPE_TRANSIT=1;function addLine(map,points,coordType){return addRoute(map,points,ROUTE_TYPE_TRANSIT,coordType)}function addRoute(map,points,type,coordType){var config=[{stroke:6,color:"#0030ff",opacity:0.45,style:"solid"},{stroke:6,color:"#0030ff",opacity:0.45,style:"solid"},{stroke:4,color:"#30a208",opacity:0.55,style:"dashed"},{stroke:5,color:"#0030ff",opacity:0.45,style:"solid"}];if(typeof type=="undefined"){type=0}if(!config[type]){return}var realPoints=[];var conf=config[type];if(map.config.coordType!=coordType){for(var i=0,l=points.length;i"];if(content){htmls.push("
"+content+"
")}htmls.push('');htmls.push('");htmls.push('
');if(curIndex==0){htmls.push('\u4e0a\u4e00\u6b65')}else{htmls.push('\u4e0a\u4e00\u6b65')}htmls.push("');if(curIndex==total+1){htmls.push('\u4e0b\u4e00\u6b65')}else{htmls.push('\u4e0b\u4e00\u6b65')}htmls.push("
");var iw=new BMap.InfoWindow(htmls.join(""),{title:"",height:0,width:220,margin:[10,10,20,10]});iw.addEventListener("open",function(){if(baidu.G("trans_prev")){baidu.on(baidu.G("trans_prev"),"click",function(){if(nextTransCbk&&typeof nextTransCbk=="function"){nextTransCbk(curIndex-1,obj)}})}if(baidu.G("trans_next")){baidu.on(baidu.G("trans_next"),"click",function(){if(nextTransCbk&&typeof nextTransCbk=="function"){nextTransCbk(curIndex+1,obj)}})}});return iw}function addTransPoi(map,point,type,title,coordType){var pt=getPoiPoint(point,map.config.coordType,coordType);if(!pt){return}type=type||BMAP_LINE_TYPE_BUS;var offsetY=-55;if(type==BMAP_LINE_TYPE_SUBWAY){offsetY=-76}var ico=new BMap.Icon(API_URL+"img/trans_icons.png",new BMap.Size(21,21),{imageOffset:new BMap.Size(0,offsetY),infoWindowOffset:new BMap.Size(10,0)});var mkr=new BMap.Marker(pt,{icon:ico});map.addOverlay(mkr);if(title){mkr.setTitle(title)}return mkr}function getInfoWindowDom(map){if(map&&map.infoWindowDoms&&map.infoWindowDoms.contentDiv){return map.infoWindowDoms.contentDiv.childNodes[0]}return null}var DataMgr={RawDispatcher:{},REQ_BASE_URL:"https://api.map.baidu.com/",request:function(cbk,params,userData,path){var timeStamp=(Math.random()*100000).toFixed(0);DataMgr.RawDispatcher["_cbk"+timeStamp]=function(json){userData=userData||{};cbk&&cbk(json,userData);delete DataMgr.RawDispatcher["_cbk"+timeStamp]};path=path||"";var reqParam=jsonToQuery(params,encodeURIComponent),me=this,key=window._key||"",script=create("script",{src:me.REQ_BASE_URL+path+"?"+reqParam+"&key="+key+"&ie=utf-8&oue=1&res=api&callback=BMap.DataMgr.RawDispatcher._cbk"+timeStamp});if(script.addEventListener){script.addEventListener("load",function(){script.parentNode.removeChild(script)},false)}else{if(script.attachEvent){script.attachEvent("onreadystatechange",function(e){var t=window.event.srcElement;if(t&&t.readyState=="loaded"){script.parentNode.removeChild(script)}})}}setTimeout(function(){document.getElementsByTagName("head")[0].appendChild(script)},1)}};mg("DataMgr",DataMgr);function BaseSearch(loc,opts){baidu.lang.Class.call(this);this._loc={};this.setLocation(loc);this._opts={coordType:BMAP_COORD_LNGLAT,renderOptions:{panel:null,map:null,autoViewport:true},onSearchComplete:function(){},onMarkersSet:function(){},onInfoHtmlSet:function(){},onResultsHtmlSet:function(){}};baidu.extend(this._opts,opts);this._opts.renderOptions.autoViewport=!!this._opts.renderOptions.autoViewport;this._opts.renderOptions.panel=baidu.G(this._opts.renderOptions.panel);this._setCoordType(this._opts.coordType)}baidu.inherits(BaseSearch,baidu.lang.Class);BaseSearch.CBK_SEARCH_COMPLETE=1;BaseSearch.CBK_MARKERS_SET=2;BaseSearch.CBK_INFO_HTML_SET=3;BaseSearch.CBK_POLYLINES_SET=4;BaseSearch.CBK_RESULTS_HTML_SET=5;BaseSearch._getPoiUrl=function(uid,ccode){if(uid){return MAP_URL+"?s="+encodeURIComponent("inf&uid="+uid+"&c="+ccode)+"&i=0&sr=1"}return""};BaseSearch._getLocType=function(loc){if(!loc){return LOC_TYPE_UNKNOWN}if(typeof loc=="string"){return LOC_TYPE_STRING}else{if(loc.constructor==BMap.Point){return LOC_TYPE_POINT}else{if(loc.constructor==BMap.Map){return LOC_TYPE_MAP}}}return LOC_TYPE_UNKNOWN};baidu.extend(BaseSearch.prototype,{getCoordType:function(){return this._opts.coordType},getResults:function(){return this._results},enableAutoViewport:function(){this._opts.renderOptions.autoViewport=true},disableAutoViewport:function(){this._opts.renderOptions.autoViewport=false},setLocation:function(loc){if(!loc){return}this._loc.src=loc},_getIdByLoc:function(loc,cbk){var locType=BaseSearch._getLocType(loc.src);if(locType==LOC_TYPE_UNKNOWN){return}var me=this;if(locType==LOC_TYPE_STRING){if(loc.curLocType==locType&&loc.curSrc==loc.src&&loc.curId){cbk&&cbk(loc.curId);return}loc.curLocType=locType;loc.curSrc=loc.src;DataMgr.request(function(json){if(json&&json.result&&json.result.type==RETURN_TYPE_CURRENT_CITY){me._loc.curId=json.content.code;cbk&&cbk(me._loc.curId)}},{qt:QUERY_TYPE_CURRENT_CITY,wd:loc.src})}else{var pt;var level=18;if(locType==LOC_TYPE_MAP){pt=loc.src.getCenter();level=loc.src.getZoom()}else{pt=loc.src}if(locType==loc.curLocType&&loc.curSrc.equals(pt)&&loc.curId){cbk&&cbk(loc.curId);return}if(locType==LOC_TYPE_MAP&&loc.src.config.coordType==BMAP_COORD_LNGLAT){pt=BMap.Projection.convertLL2MC(pt)}if(locType==LOC_TYPE_POINT&&this._opts.coordType==BMAP_COORD_LNGLAT){pt=BMap.Projection.convertLL2MC(pt)}loc.curLocType=locType;loc.curSrc=new BMap.Point(pt.lng,pt.lat);DataMgr.request(function(json){if(json&&json.result&&json.result.type==RETURN_TYPE_CENTER){me._loc.curId=json.content.uid;cbk&&cbk(me._loc.curId)}},{qt:QUERY_TYPE_CENTER,b:pt.lng+","+pt.lat+";"+pt.lng+","+pt.lat,l:level})}},setSearchCompleteCallback:function(cbk){this._opts.onSearchComplete=cbk||function(){}},setMarkersSetCallback:function(cbk){this._opts.onMarkersSet=cbk||function(){}},setInfoHtmlSetCallback:function(cbk){this._opts.onInfoHtmlSet=cbk||function(){}},setResultsHtmlSetCallback:function(cbk){this._opts.onResultsHtmlSet=cbk||function(){}},getStatus:function(){return this._status},_setStatus:function(code){if(typeof code=="number"){this._status=code}else{delete this._status}},_setCoordType:function(type){if(type===BMAP_COORD_LNGLAT||type===BMAP_COORD_MERCATOR){this._opts.coordType=type}else{this._opts.coordType=BMAP_COORD_LNGLAT}},_triggerCbk:function(cbkCode,d0,d1){var cbk;switch(cbkCode){case BaseSearch.CBK_SEARCH_COMPLETE:cbk=this._opts.onSearchComplete;break;case BaseSearch.CBK_MARKERS_SET:cbk=this._opts.onMarkersSet;break;case BaseSearch.CBK_POLYLINES_SET:cbk=this._opts.onPolylinesSet;break;case BaseSearch.CBK_INFO_HTML_SET:cbk=this._opts.onInfoHtmlSet;break;case BaseSearch.CBK_RESULTS_HTML_SET:cbk=this._opts.onResultsHtmlSet;break;default:break}cbk&&cbk(d0,d1)}});var LocalSearch=function(loc,opts){BaseSearch.call(this,loc,opts);opts=opts||{};opts.renderOptions=opts.renderOptions||{};this.setPageCapacity(opts.pageCapacity);if(typeof opts.renderOptions.selectFirstResult!="undefined"&&!opts.renderOptions.selectFirstResult){this.disableFirstResultSelection()}else{this.enableFirstResultSelection()}this._overlays=[];this._curIndex=-1};baidu.inherits(LocalSearch,BaseSearch,"LocalSearch");LocalSearch.DEFAULT_PAGE_CAPACITY=10;LocalSearch.MIN_PAGE_CAPACITY=1;LocalSearch.MAX_PAGE_CAPACITY=50;LocalSearch.DEFAULT_RADIUS=2000;LocalSearch.MAX_RADIUS=5000;LocalSearch.isReqDataMap=function(qt,type){if(!qt||typeof type=="undefined"){return false}if(qt==QUERY_TYPE_POI_SEARCH&&type!=RETURN_TYPE_POI_SEARCH&&type!=RETURN_TYPE_CITY_LIST&&type!=RETURN_TYPE_CURRENT_CITY&&type!=RETURN_TYPE_SPECIAL_REGION&&type!=RETURN_TYPE_NODATA_REGION){return false}if(qt==QUERY_TYPE_SEARCH_NEARBY&&type!=RETURN_TYPE_SEARCH_NEARBY){return false}if(qt==QUERY_TYPE_SEARCH_INBOUNDS&&type!=RETURN_TYPE_SEARCH_INBOUNDS){return false}return true};baidu.extend(LocalSearch.prototype,{search:function(keyword){if(!keyword){this.clearResults();this._setStatus(BMAP_STATUS_INVALID_REQUEST);this._triggerCbk(BaseSearch.CBK_SEARCH_COMPLETE);return}var opts=arguments[1]||{};var me=this;this._getIdByLoc(this._loc,function(id){id=id||1;var _opts={qt:QUERY_TYPE_POI_SEARCH,c:id,wd:keyword,rn:me.getPageCapacity(QUERY_TYPE_POI_SEARCH)};baidu.extend(_opts,opts.params);var ud={params:_opts,userKw:opts.userKw||keyword};baidu.extend(ud,opts);DataMgr.request(function(json,userData){me._rawDataCbk(json,userData)},_opts,ud)})},searchInBounds:function(keyword,bounds){if(!keyword||!bounds){this.clearResults();this._setStatus(BMAP_STATUS_INVALID_REQUEST);this._triggerCbk(BaseSearch.CBK_SEARCH_COMPLETE);return}var me=this;var opts=arguments[2]||{};this._getIdByLoc(this._loc,function(id){id=id||1;var pt1=new BMap.Point(bounds.minX,bounds.minY);var pt2=new BMap.Point(bounds.maxX,bounds.maxY);if(me._opts.coordType==BMAP_COORD_LNGLAT){pt1=BMap.Projection.convertLL2MC(pt1);pt2=BMap.Projection.convertLL2MC(pt2)}var bdstr="("+pt1.lng+","+pt1.lat+";"+pt2.lng+","+pt2.lat+")";var _opts={qt:QUERY_TYPE_SEARCH_INBOUNDS,c:id,wd:keyword,ar:bdstr,rn:me._opts.pageCapacity,l:18};baidu.extend(_opts,opts.params);var ud;if(opts&&opts.center&&opts.radius){ud={params:_opts,bounds:bounds,center:opts.center,radius:opts.radius,userKw:opts.userKw||keyword}}else{ud={params:_opts,bounds:bounds,userKw:opts.userKw||keyword}}DataMgr.request(function(json,userData){me._rawDataCbk(json,userData)},_opts,ud)})},searchNearby:function(keyword,center,radius){if(!keyword||!center||!(center instanceof BMap.Point)&&typeof center=="object"&&!center.uid){this.clearResults();this._setStatus(BMAP_STATUS_INVALID_REQUEST);this._triggerCbk(BaseSearch.CBK_SEARCH_COMPLETE);return}radius=radius||LocalSearch.DEFAULT_RADIUS;radius=radius<1?1:(radius>LocalSearch.MAX_RADIUS?LocalSearch.MAX_RADIUS:radius);var me=this;var opts=arguments[3]||{};if(center&¢er instanceof BMap.Point){var prjCenter;if(me._opts.coordType==BMAP_COORD_LNGLAT){prjCenter=BMap.Projection.convertLL2MC(center)}else{prjCenter=center}var prjPt1=new BMap.Point(prjCenter.lng-radius,prjCenter.lat-radius);var prjPt2=new BMap.Point(prjCenter.lng+radius,prjCenter.lat+radius);var pt1,pt2;if(me._opts.coordType==BMAP_COORD_LNGLAT){pt1=BMap.Projection.convertMC2LL(prjPt1);pt2=BMap.Projection.convertMC2LL(prjPt2)}else{pt1=prjPt1;pt2=prjPt2}var bounds=new BMap.Bounds(pt1.lng,pt1.lat,pt2.lng,pt2.lat);opts.center=center;opts.radius=radius;this.searchInBounds(keyword,bounds,opts);return}this._getIdByLoc(this._loc,function(id){id=id||1;var _opts={qt:QUERY_TYPE_SEARCH_NEARBY,c:id,wd:keyword,rn:me.getPageCapacity(QUERY_TYPE_SEARCH_NEARBY),uid:center.uid,r:radius};if(typeof center=="string"){_opts.qt=QUERY_TYPE_POI_SEARCH;_opts.wd=center+" "+keyword;delete _opts.r;delete _opts.uid}baidu.extend(_opts,opts.params);DataMgr.request(function(json,userData){me._rawDataCbk(json,userData)},_opts,{params:_opts,center:center,radius:radius,userKw:opts.userKw||keyword})})},_rawDataCbk:function(json,userData){var me=this;this.clearResults();me._json=json;this._ud=userData;var r=json.result;var qt=userData.params.qt;if(r.error!=0||!LocalSearch.isReqDataMap(qt,r.type)){var cc=json.current_city;this._results=new LocalResult({keyword:userData.userKw,city:cc.name,ccode:cc.code,pc:me.getPageCapacity(userData.params.qt),center:userData.center,radius:userData.radius,bounds:((userData.center&&userData.radius)?undefined:userData.bounds),moreUrl:this._getMoreUrl(userData,cc)});this._results._qt=userData.params.qt;this._setStatus(BMAP_STATUS_UNKNOWN_LOCATION);this._triggerCbk(BaseSearch.CBK_SEARCH_COMPLETE,this._results);this._renderList();return}me._processRaw(userData);me._renderMap();me._renderList();if(this._opts.renderOptions.selectFirstResult&&this._results&&this._results.getNumPois()>0){var me=this;setTimeout(function(){me._select(0)},240)}},_processRaw:function(userData){var r=this._json.result,c=this._json.content,cc=this._json.current_city,type=r.type,me=this,pageNum=r.page_num||0,total=0,count=0,results=[],points=[],cityList=[],count,total;if(type!=RETURN_TYPE_CITY_LIST&&type!=RETURN_TYPE_SPECIAL_REGION){count=r.count-(pageNum==0?(r.spec_dispnum||0):0);total=r.total<760?r.total:760;var start=pageNum==0?(r.spec_dispnum||0):0;if(type!=RETURN_TYPE_CURRENT_CITY){for(var i=start;i0){var me=this,map=this._opts.renderOptions.map,points=[];for(var i=0;i-1&&this._overlays[index]){var mkr=this._overlays[index];map.closeInfoWindow();var cur=this._results.getPoi(index);var iw=createSearchInfoWnd({title:cur.title,addr:cur.address,tel:cur.phoneNumber,url:cur.url,poiType:cur.type});var me=this;iw.addEventListener("close",function(){if(panel){if(typeof me._curIndex=="number"&&me._curIndex!=-1&&panel.getElementsByTagName("li")[me._curIndex]){panel.getElementsByTagName("li")[me._curIndex].style.backgroundColor=""}}me._curIndex=-1});iw.addEventListener("open",function(){me._triggerCbk(BaseSearch.CBK_INFO_HTML_SET,cur,getInfoWindowDom(map))});mkr.openInfoWindow(iw)}if(panel){if(typeof preIndex=="number"&&preIndex!=-1&&panel.getElementsByTagName("li")[preIndex]){panel.getElementsByTagName("li")[preIndex].style.backgroundColor=""}if(typeof index=="number"&&index!=-1&&panel.getElementsByTagName("li")[index]){panel.getElementsByTagName("li")[index].style.backgroundColor="#f0f0f0"}}this._curIndex=index},_clearOverlays:function(){for(var i=0,l=this._overlays.length;i1){var pg=new Page(paging,function(page){me.gotoPage(page-1)},{pageCount:me._results.getNumPages(),page:me._results.getPageIndex()+1,update:false})}resultsControl.appendChild(paging);resultsControl.appendChild(moreUrl);container.appendChild(resultsControl);this._opts.renderOptions.panel.appendChild(container);this._triggerCbk(BaseSearch.CBK_RESULTS_HTML_SET,container)}},_createItem:function(index){var r=this._results;if(!r||!r.getPoi(index)){return}var cur=r.getPoi(index);var kw=this._results.keyword;var item=create("li",{style:"margin:2px 0;padding:0 5px 0 3px;cursor:pointer;overflow:hidden;line-height:17px"});if(this._curIndex>-1&&index==this._curIndex){item.style.backgroundColor="#f0f0f0"}var offsetY=index==0?index+2+"px":"-"+(index*20-2)+"px";if(this._results.getCurrentNumPois()>LocalSearch.DEFAULT_PAGE_CAPACITY){offsetY="-218px"}var htmls=[" "];var regex=new RegExp(kw,"ig");var title=cur.title.replace(regex,"$&");if(cur.type==BMAP_POI_TYPE_BUSSTOP){title+="-\u516c\u4ea4\u8f66\u7ad9"}else{if(cur.type==BMAP_POI_TYPE_SUBSTOP){title+="-\u5730\u94c1\u7ad9"}}htmls.push(""+title+"");if(cur.address){htmls.push(" - "+cur.address.replace(regex,"$&")+"")}item.innerHTML=htmls.join("");var me=this;item.onclick=function(){me._select(index)};return item},_createCityItem:function(index){var item=create("li",{style:"margin:2px 0;padding:0 5px 0 3px;cursor:pointer;overflow:hidden;line-height:17px"});item._index=index;var clist=this._results.getCityList();item.innerHTML=""+clist[index].city+" (\u5171"+clist[index].numResults+"\u6761\u7ed3\u679c)";var me=this;item.onclick=function(){me.setLocation(me._results.getCityList()[index].city);me.search(me._results.keyword)};return item},clearResults:function(){delete this._json;delete this._status;delete this._results;delete this._ud;this._curIndex=-1;this._setStatus();this._clearOverlays();if(this._opts.renderOptions.panel){this._opts.renderOptions.panel.innerHTML=""}},gotoPage:function(pageNum){if(this._ud){if(typeof pageNum=="number"&&!isNaN(pageNum)&&pageNum>=0&&pageNum<=this._results.getNumPages()-1){this._ud.params.pn=pageNum;var qt=this._ud.params.qt;switch(qt){case QUERY_TYPE_POI_SEARCH:this.search(this._ud.params.wd,this._ud);break;case QUERY_TYPE_SEARCH_INBOUNDS:this.searchInBounds(this._ud.params.wd,this._ud.bounds,this._ud);break;case QUERY_TYPE_SEARCH_NEARBY:this.searchNearby(this._ud.params.wd,this._ud.center,this._ud.radius,this._ud);break;default:break}}else{this._setStatus(BMAP_STATUS_INVALID_REQUEST);this._triggerCbk(BaseSearch.CBK_SEARCH_COMPLETE)}}},enableFirstResultSelection:function(){this._opts.renderOptions.selectFirstResult=true},disableFirstResultSelection:function(){this._opts.renderOptions.selectFirstResult=false},setPageCapacity:function(cap){if(typeof cap=="number"&&!isNaN(cap)){this._opts.pageCapacity=cap<1?LocalSearch.DEFAULT_PAGE_CAPACITY:(cap>LocalSearch.MAX_PAGE_CAPACITY?LocalSearch.DEFAULT_PAGE_CAPACITY:cap)}else{this._opts.pageCapacity=LocalSearch.DEFAULT_PAGE_CAPACITY}},getPageCapacity:function(){if(!arguments[0]){return this._opts.pageCapacity}if(arguments[0]!=QUERY_TYPE_SEARCH_INBOUNDS){if(this._opts.pageCapacity<=LocalSearch.DEFAULT_PAGE_CAPACITY){return this._opts.pageCapacity}else{return LocalSearch.DEFAULT_PAGE_CAPACITY}}else{return this._opts.pageCapacity}},_getBestViewport:function(viewData){var renderOptions=this._opts.renderOptions,map=renderOptions.map;if(map){if(viewData.points){var pts=viewData.points;if(this._opts.coordType!=map.config.coordType){if(map.config.coordType==BMAP_COORD_MERCATOR){for(var i=0;i
");res.push(title);res.push("
");return res.join("")};baidu.extend(BaseRoute.prototype,{search:function(start,end){if(!start||!end){this.clearResults();this._setStatus(BMAP_STATUS_INVALID_REQUEST);this._triggerCbk(BaseSearch.CBK_SEARCH_COMPLETE);return false}return true},clearResults:function(){delete this._results;delete this._ud;delete this._json;delete this._boundsPoints;this._setStatus();if(this._opts.renderOptions.panel){this._opts.renderOptions.panel.innerHTML=""}if(this._opts.renderOptions.map){this._opts.renderOptions.map.closeInfoWindow()}this._clearOverlays();this._curIndex=-1},_formatDestQuery:function(dest){var ret;if(typeof dest=="string"){ret=[2,"","",dest,"",""]}else{if(dest instanceof BMap.Point){var pt=convertCoord(dest,this._opts.coordType,BMAP_COORD_MERCATOR);ret=[1,"",pt.lng+","+pt.lat,"","",""]}else{var pt=convertCoord(dest.point,this._opts.coordType,BMAP_COORD_MERCATOR);ret=[1,dest.uid,pt.lng+","+pt.lat,dest.title,"",""]}}return ret.join("$$")},setPolylinesSetCallback:function(cbk){this._opts.onPolylinesSet=cbk||function(){}}});function Route(opts){this._steps=opts.steps&&opts.steps.slice(0)||[];this._distance=opts.distance||0;this._index=opts.index||0;this._points=opts.points.slice(0);this._planIndex=opts.planIndex||0;this._rt=opts.rt;if(this._distance===0&&this._points.length>2){this._points.length=2}}baidu.extend(Route.prototype,{getNumSteps:function(){return this._steps.length},getStep:function(i){if(this._steps[i]){return this._steps[i]}},getDistance:function(format){if(format===false){return this._distance}else{return formatDistance(this._distance)}},getIndex:function(){return this._index},getPolyline:function(){return this._polyline},getPoints:function(){return this._points},getRouteType:function(){return this._rt},getPlanIndex:function(){return this._planIndex}});function RoutePlan(opts){this._routes=opts.routes.slice(0);this._distance=opts.distance||0;this._duration=opts.duration||0}baidu.extend(RoutePlan.prototype,{getRoute:function(i){if(this._routes[i]){return this._routes[i]}},getNumRoutes:function(){return this._routes.length},getDistance:function(format){if(format===false){return this._distance}else{return formatDistance(this._distance)}},getDuration:function(format){if(format===false){return this._duration}else{return formatTime(this._duration,"nav")}}});window.BMAP_TRANSIT_POLICY_LEAST_TIME=0;window.BMAP_TRANSIT_POLICY_LEAST_TRANSFER=2;window.BMAP_TRANSIT_POLICY_LEAST_WALKING=3;window.BMAP_LINE_TYPE_BUS=0;window.BMAP_LINE_TYPE_SUBWAY=1;window.BMAP_LINE_TYPE_FERRY=2;function TransitRoute(loc,opts){BaseRoute.call(this,loc,opts);opts=opts||{};this.setPolicy(opts.policy);this.setPageCapacity(opts.pageCapacity);this.QUERY_TYPE=QUERY_TYPE_TRANSIT;this.RETURN_TYPE=RETURN_TYPE_TRANSIT;this.ROUTE_TYPE=ROUTE_TYPE_TRANSIT;this._overlays=[];this._curIndex=-1}TransitRoute.MAX_PAGE_CAPACITY=5;TransitRoute.LINE_TYPE_MAPPING=[0,1,0,0,0,0,0,0,2,0,0,0,1,1,1];baidu.inherits(TransitRoute,BaseRoute,"TransitRoute");baidu.extend(TransitRoute.prototype,{setPolicy:function(policy){if(policy>=BMAP_TRANSIT_POLICY_LEAST_TIME&&policy<=BMAP_TRANSIT_POLICY_LEAST_WALKING){this._opts.policy=policy}else{this._opts.policy=BMAP_TRANSIT_POLICY_LEAST_TIME}},_internalSearch:function(sn,en,opt){var me=this;function getUidXyQuery(s){var a=s.split("$$"),type=a[0],pos=null;if(/^[0-2]$/.test(type)&&a.length>3){pos=a[parseInt(type)+1]}return pos}this._getIdByLoc(this._loc,function(id){if(!id){this._setStatus(BMAP_STATUS_INVALID_REQUEST);this._triggerCbk(BaseSearch.CBK_SEARCH_COMPLETE)}var start=getUidXyQuery(sn),end=getUidXyQuery(en);var params={qt:me.QUERY_TYPE,c:id,sn:sn,en:en,sy:me._opts.policy||0,brn:me._opts.pageCapacity};opt=opt||{};for(var key in opt){params[key]=opt[key]}DataMgr.request(function(json,userData){me._rawDataCbk(json,userData)},params,{start:start,end:end})})},search:function(start,end){if(BaseRoute.prototype.search.call(this,start,end)==true){var me=this;this._getIdByLoc(this._loc,function(id){if(!id){this._setStatus(BMAP_STATUS_INVALID_REQUEST);this._triggerCbk(BaseSearch.CBK_SEARCH_COMPLETE)}var params={qt:me.QUERY_TYPE,c:id,sn:me._formatDestQuery(start),en:me._formatDestQuery(end),sy:me._opts.policy||0,brn:me._opts.pageCapacity};DataMgr.request(function(json,userData){me._rawDataCbk(json,userData)},params,{start:start,end:end})})}},_rawDataCbk:function(json,userData){this.clearResults();this._json=json;var r=json.result;this._ud=userData;if(r.error!=0||r.type!=this.RETURN_TYPE){this._results=new TransitRouteResult({city:json.current_city.name,plans:[],policy:r.sy});this._setStatus(BMAP_STATUS_UNKNOWN_ROUTE);this._triggerCbk(BaseSearch.CBK_SEARCH_COMPLETE,this._results);return}this._processRaw();this._renderList();this._selectPlan(0)},_processRaw:function(){var r=this._json.result;var c=this._json.content;var cc=this._json.current_city;var start={};var end={};if(typeof this._ud.start=="object"&&!this._ud.start instanceof BMap.Point){baidu.extend(start,this._ud.start)}else{start.title=r.start.wd||"\u8d77\u70b9";start.uid=r.start.uid;start.url=BaseSearch._getPoiUrl(start.uid,cc.code);start.point=parseGeo(r.start.pt,true,this._opts.coordType).point;start.city=cc.name}if(typeof this._ud.end=="object"&&!this._ud.end instanceof BMap.Point){baidu.extend(end,this._ud.end)}else{end.title=r.end.wd||"\u7ec8\u70b9";end.uid=r.end.uid;end.url=BaseSearch._getPoiUrl(end.uid,cc.code);end.point=parseGeo(r.end.pt,true,this._opts.coordType).point;end.city=cc.name}var plans=[];this._boundsPoints=[];for(var i=0;i0){wRoutes.push(new Route({distance:stops[j].walk.distance,points:parseGeo(stops[j].walk.geo,true,this._opts.coordType).points,rt:BMAP_ROUTE_TYPE_WALKING,index:j,planIndex:i}))};dis+=stops[j].walk.distance;if(j==stops.length-2&&stops[j+1].walk.distance>0){wRoutes.push(new Route({distance:stops[j+1].walk.distance,points:parseGeo(stops[j+1].walk.geo,true,this._opts.coordType).points,rt:BMAP_ROUTE_TYPE_WALKING,index:j+1,planIndex:i}));dis+=stops[j+1].walk.distance}var lineGeo=parseGeo(lines[j].geo,true,this._opts.coordType);resLines.push(new Line({title:lines[j].name,uid:lines[j].uid,distance:lines[j].distance,points:lineGeo.points,stops:[onStop,offStop],type:this._getLineType(lines[j].type),numViaStops:lines[j].station_num}));var bpts=getPointsByBounds(lineGeo.bounds,this._opts.coordType,this._opts.renderOptions.map?this._opts.renderOptions.map.config.coordType:this._opts.coordType);this._boundsPoints[i].push(bpts[0],bpts[1]);dis+=lines[j].distance;if(stops[j].walk.distance){desc+="\u6b65\u884c\u7ea6"+formatDistance(stops[j].walk.distance)+"\uff0c\u5230\u8fbe"+onStop.title+"\uff0c"}desc+="\u4e58\u5750"+this._shortTitle(lines[j].name)+"\uff0c\u7ecf\u8fc7"+lines[j].station_num+"\u7ad9\uff0c\u5230\u8fbe"+offStop.title+"";if(j\u6b65\u884c\u7ea6"+formatDistance(stops[j+1].walk.distance)+"\uff0c\u5230\u8fbe"+stops[j+1].getOn.name+""}}}plans.push(new TransitRoutePlan({routes:wRoutes,distance:dis,duration:duration,lines:resLines,description:desc}))}var url=MAP_URL+"?s="+encodeURIComponent(this.QUERY_TYPE+"&c="+cc.code+"&sy="+r.sy+"&sn="+this._formatDestQuery(this._ud.start)+"&en="+this._formatDestQuery(this._ud.end)+"&sq="+(this._ud.start.title?this._ud.start.title:this._ud.start)+"&eq="+(this._ud.end.title?this._ud.end.title:this._ud.end))+"&sr=1";if(this._ud.start.toString()=="Point"&&this._ud.start.toString()=="Point"){url=""}this._results=new TransitRouteResult({city:cc.name,plans:plans,start:start,end:end,url:url,policy:r.sy});this._setStatus(BMAP_STATUS_SUCCESS);this._triggerCbk(BaseSearch.CBK_SEARCH_COMPLETE,this._results)},_shortTitle:function(title){return title.replace(/\(.*\)/,"")},_renderPlan:function(index){var map=this._opts.renderOptions.map;if(!map){return}var plan=this._results.getPlan(index);if(!plan){return}var startPoi=this._results.getStart();var endPoi=this._results.getEnd();var staMkr=addDestPoi(map,startPoi.point,startPoi.title,DEST_START,this._opts.coordType);startPoi.marker=staMkr;staMkr.addEventListener("click",function(){me._select(0)});this._overlays.push(staMkr);var endMkr=addDestPoi(map,endPoi.point,endPoi.title,DEST_END,this._opts.coordType);endPoi.marker=endMkr;this._overlays.push(endMkr);endMkr.addEventListener("click",function(){me._selectLast()});var startPt=convertCoord(startPoi.point,this._opts.coordType,map.config.coordType);var endPt=convertCoord(endPoi.point,this._opts.coordType,map.config.coordType);this._boundsPoints[index].push(startPt,endPt);var transPois=[];var me=this;for(var i=0,l=plan.getNumLines();i0){polyline=addRoute(map,route.getPoints(),route.getRouteType(),this._opts.coordType);route._polyline=polyline;this._overlays.push(polyline)}}var route=plan.getRoute(i);polyline=addRoute(map,route.getPoints(),route.getRouteType(),this._opts.coordType);route._polyline=polyline;this._overlays.push(polyline);var me=this;if(this._opts.renderOptions.autoViewport){map.setViewport(this._boundsPoints[index],{margins:[30,30,30,30]})}this._triggerCbk(BaseSearch.CBK_POLYLINES_SET,plan._lines,plan._routes);this._triggerCbk(BaseSearch.CBK_MARKERS_SET,[startPoi,endPoi],transPois)},_renderList:function(){if(this._opts.renderOptions.panel&&this._opts.renderOptions.panel.appendChild&&this._results&&this._results.getNumPlans()>0){var container=create("div",{style:"font-size:12px;font-family:arial,sans-serif;background:#fff"});var divSta=BaseRoute._genTitle(this._results.getStart().title,'Instance("'+this.guid+'")._select(0)',0);var tables=[""];for(var i=0,l=this._results.getNumPlans();i");tables.push("");tables.push("");tables.push("");tables.push("")}tables.push("
"+(i+1)+"."+plan.getDescription()+""+dis+" / "+dur+"
");var divEnd=BaseRoute._genTitle(this._results.getEnd().title,'Instance("'+this.guid+'")._selectLast()',1);var control="
";if(this._results.moreResultsUrl){control+="\u5230\u767e\u5ea6\u5730\u56fe\u67e5\u770b»"}control+=" 
";container.innerHTML=divSta+tables.join("")+divEnd+control;this._opts.renderOptions.panel.appendChild(container);this._triggerCbk(BaseSearch.CBK_RESULTS_HTML_SET,container)}},_select:function(index){var map=this._opts.renderOptions.map;if(map){var plan=this._results.getPlan(this._curIndex);if(!plan){return}var me=this;var total=plan.getNumLines()*2;if(index==0||index==total+1){var d=index===0?this._results.getStart():this._results.getEnd();var iw=createTransInfoWnd({content:""+d.title+"",total:total,curIndex:index,nextTransCbk:function(i){me._select(i)},type:TRANS_INFO_WND_TRANSIT});iw.addEventListener("open",function(){me._triggerCbk(BaseSearch.CBK_INFO_HTML_SET,d,getInfoWindowDom(map))});var oindex=index===0?0:1;this._overlays[oindex].openInfoWindow(iw)}else{var curLine=plan.getLine(Math.floor((index+1)/2)-1);var curStop;var desc;if(index%2===1){curStop=curLine.getGetOnStop();desc=""+curStop.title+"\u7ad9\u4e0a\u8f66"}else{curStop=curLine.getGetOffStop();desc=""+curStop.title+"\u7ad9\u4e0b\u8f66"}var iw=createTransInfoWnd({content:desc,total:total,curIndex:index,nextTransCbk:function(i){me._select(i)},type:TRANS_INFO_WND_TRANSIT});iw.addEventListener("open",function(){me._triggerCbk(BaseSearch.CBK_INFO_HTML_SET,curStop,getInfoWindowDom(map))});curStop.marker.openInfoWindow(iw)}}},_selectLast:function(){if(this._results&&this._curIndex>-1){var plan=this._results.getPlan(this._curIndex);if(!plan){return}var total=plan.getNumLines()*2;this._select(total+1)}},_selectPlan:function(index){if(!this._results&&!this._result.getPlan(index)){return}var plan=this._results.getPlan(index);var map=this._opts.renderOptions.map;if(map){map.closeInfoWindow();this._clearOverlays();this._renderPlan(index)}if(this._opts.renderOptions.panel){var table=this._opts.renderOptions.panel.getElementsByTagName("table")[0];if(!table){return}var trs=table.getElementsByTagName("tr");if(this._curIndex>=0&&trs[this._curIndex]){trs[this._curIndex].style.background=""}if(index>=0&&trs[index]){trs[index].style.background="#f0f0f0"}}this._curIndex=index},_clearOverlays:function(){for(var i=0;i=1&&cp<=TransitRoute.MAX_PAGE_CAPACITY){this._opts.pageCapacity=Math.round(cp)}else{this._opts.pageCapacity=TransitRoute.MAX_PAGE_CAPACITY}},toString:function(){return"TransitRoute"}});function TransitRoutePlan(opts){RoutePlan.call(this,opts);this._lines=opts.lines;this._description=opts.description;this._duration=opts.duration||0}baidu.inherits(TransitRoutePlan,RoutePlan,"TransitRoutePlan");baidu.extend(TransitRoutePlan.prototype,{getNumLines:function(){return this._lines.length},getLine:function(i){if(this._lines[i]){return this._lines[i]}},getDescription:function(includeHtml){if(includeHtml===false){return this._description.replace(/<(\/)?b>/g,"")}else{return this._description}},getDuration:function(format){if(format===false){return this._duration}else{return formatTime(this._duration,"bustime")}}});function Step(opts){this._point=opts.point;this._index=opts.index;this._description=opts.description;this._distance=opts.distance||0;this._routeIndex=opts.routeIndex||0;this._planIndex=opts.planIndex||0}baidu.extend(Step.prototype,{getPoint:function(){return this._point},getIndex:function(){return this._index},getDescription:function(includeHtml){if(includeHtml===false){return this._description.replace(/<\/?b>/g,"")}else{return this._description}},getDistance:function(format){if(format===false){return this._distance}else{return formatDistance(this._distance)}},getRouteIndex:function(){return this._routeIndex},getPlanIndex:function(){return this._planIndex}});var DWRoute=function(location,opts){BaseRoute.call(this,location,opts);this._overlays=[];this._curIndex=-1};DWRoute.ROAD_TYPE=["","\u73af\u5c9b","\u65e0\u5c5e\u6027\u9053\u8def","\u4e3b\u8def","\u9ad8\u901f\u8fde\u63a5\u8def","\u4ea4\u53c9\u70b9\u5185\u8def\u6bb5","\u8fde\u63a5\u9053\u8def","\u505c\u8f66\u573a\u5185\u90e8\u9053\u8def","\u670d\u52a1\u533a\u5185\u90e8\u9053\u8def","\u6865","\u6b65\u884c\u8857","\u8f85\u8def","\u531d\u9053","\u5168\u5c01\u95ed\u9053\u8def","\u672a\u5b9a\u4e49\u4ea4\u901a\u533a\u57df","POI\u8fde\u63a5\u8def","\u96a7\u9053","\u6b65\u884c\u9053","\u516c\u4ea4\u4e13\u7528\u9053","\u63d0\u524d\u53f3\u8f6c\u9053"];baidu.inherits(DWRoute,BaseRoute,"DWRoute");baidu.extend(DWRoute.prototype,{_internalSearch:function(sn,en,opt){var me=this;function getUidXyQuery(s){var a=s.split("$$"),type=a[0],pos=null;if(/^[0-2]$/.test(type)&&a.length>3){pos=a[parseInt(type)+1]}return pos}this._getIdByLoc(this._loc,function(id){id=id||1;var start=getUidXyQuery(sn),end=getUidXyQuery(en);var params={qt:me.QUERY_TYPE,c:id,sc:id,ec:id,sn:sn,en:en,sy:me._opts.policy||0};opt=opt||{};for(var key in opt){params[key]=opt[key]}DataMgr.request(function(json,userData){me._rawDataCbk(json,userData)},params,{start:start,end:end})})},search:function(start,end){if(BaseRoute.prototype.search.call(this,start,end)==true){var me=this;this._getIdByLoc(this._loc,function(id){id=id||1;var params={qt:me.QUERY_TYPE,c:id,sc:id,ec:id,sn:me._formatDestQuery(start),en:me._formatDestQuery(end),sy:me._opts.policy||0};DataMgr.request(function(json,userData){me._rawDataCbk(json,userData)},params,{start:start,end:end})})}},_rawDataCbk:function(json,userData){this.clearResults();this._json=json;var r=json.result;this._ud=userData;if(r.error!=0||r.type!=this.RETURN_TYPE){this._results=this._createResults({city:json.current_city.name,plans:[],policy:r.sy});this._setStatus(BMAP_STATUS_UNKNOWN_ROUTE);this._triggerCbk(BaseSearch.CBK_SEARCH_COMPLETE,this._results);return}this._processRaw();this._renderMap();this._renderList()},_processRaw:function(){var r=this._json.result;var c=this._json.content;var cc=this._json.current_city;var kps=c.kps;var rss=c.rss;var start={};var end={};if(typeof this._ud.start=="object"&&!this._ud.start instanceof BMap.Point){baidu.extend(start,this._ud.start)}else{start.title=r.start.wd||"\u8d77\u70b9";start.uid=r.start.uid;start.url=BaseSearch._getPoiUrl(start.uid,r.start_city.code);start.point=parseGeo(r.start.pt,true,this._opts.coordType).point;start.city=r.start_city.cname}if(typeof this._ud.end=="object"&&!this._ud.end instanceof BMap.Point){baidu.extend(end,this._ud.end)}else{end.title=r.end[0].wd||"\u7ec8\u70b9";end.uid=r.end[0].uid;if(end.uid=="null"){end.uid=""}end.url=BaseSearch._getPoiUrl(end.uid,r.end_city[0].code);end.point=parseGeo(r.end[0].pt,true,this._opts.coordType).point;end.city=r.end_city[0].cname}var steps=[];var polylinePoints=[];this._boundsPoints=[];for(var i=0,l=kps.length-1;i"+curKps.dr+"\uff0c"):"";var act=((rnm!=""&&pnm==rnm)?"\u7ee7\u7eed":"")+this._getRoadAct(curRss.t,curRss.n);var tips=this._getPoiInfo(curRss);var tic=this._getTicInfo(curKps);var ret=(rnm==nnm)?"":(this._getRetAct(nxtRss.t,nxtRss.n)+""+nnm+"");des=act+""+rnm+""+this._getRetType(curKps.rt)+disstr+"\uff0c"+tips+tic+dr;if(i==0){des="\u4ece\u8d77\u70b9\u5411"+this._getTurnType(curKps.ett||curKps.tt)+"\u51fa\u53d1"}else{if(i>0&&i"+this._getTurnType(curKps.ett||curKps.tt)+""+ret}else{des=des+"\u5230\u8fbe\u7ec8\u70b9"}}return des},_renderMap:function(){var map=this._opts.renderOptions.map;if(map&&this._results){var plan=this._results.getPlan(0);var route=plan.getRoute(0);var startPoi=this._results.getStart();var endPoi=this._results.getEnd();var me=this;var polyline=addRoute(map,route.getPoints(),route.getRouteType(),this._opts.coordType);route._polyline=polyline;this._overlays.push(polyline);var staMkr=addDestPoi(map,startPoi.point,startPoi.title,DEST_START,this._opts.coordType);startPoi.marker=staMkr;staMkr.addEventListener("click",function(){me._select(0)});this._overlays.push(staMkr);var endMkr=addDestPoi(map,endPoi.point,endPoi.title,DEST_END,this._opts.coordType);endPoi.marker=endMkr;this._overlays.push(endMkr);endMkr.addEventListener("click",function(){me._select(route.getNumSteps()+1)});if(this._opts.renderOptions.autoViewport){map.setViewport(this._boundsPoints,{margins:[30,30,30,30]})}this._triggerCbk(BaseSearch.CBK_POLYLINES_SET,plan._routes);this._triggerCbk(BaseSearch.CBK_MARKERS_SET,[startPoi,endPoi])}},_select:function(index){var preIndex=this._curIndex;if(this._opts.renderOptions.panel){var table=this._opts.renderOptions.panel.getElementsByTagName("table")[0];var trs=table.getElementsByTagName("tr");if(preIndex-1>=0&&trs[preIndex-1]){trs[preIndex-1].style.background=""}if(index-1>=0&&trs[index-1]){trs[index-1].style.background="#f0f0f0"}}var map=this._opts.renderOptions.map;if(map){var plan=this._results.getPlan(0);var route=plan.getRoute(0);var total=route.getNumSteps();var me=this;map.closeInfoWindow();if(index==0||index==total+1){var d=index===0?this._results.getStart():this._results.getEnd();var iw=createTransInfoWnd({content:""+d.title+"",total:total,curIndex:index,nextTransCbk:function(i){me._select(i)},type:this.TRANS_INFO_WND_TYPE});iw.addEventListener("open",function(){me._triggerCbk(BaseSearch.CBK_INFO_HTML_SET,d,getInfoWindowDom(map))});iw.addEventListener("close",function(){if(me._opts.renderOptions.panel){var table=me._opts.renderOptions.panel.getElementsByTagName("table")[0];var trs=table.getElementsByTagName("tr");if(me._curIndex-1>=0&&trs[me._curIndex-1]){trs[me._curIndex-1].style.background=""}}me._curIndex=-1});var oindex=index===0?1:2;this._overlays[oindex].openInfoWindow(iw)}else{var curStep=route.getStep(index-1);var iw=createTransInfoWnd({content:curStep.getDescription(),total:total,curIndex:index,nextTransCbk:function(i){me._select(i)},type:this.TRANS_INFO_WND_TYPE});iw.addEventListener("open",function(){me._triggerCbk(BaseSearch.CBK_INFO_HTML_SET,curStep,getInfoWindowDom(map))});iw.addEventListener("close",function(){if(me._opts.renderOptions.panel){var table=me._opts.renderOptions.panel.getElementsByTagName("table")[0];var trs=table.getElementsByTagName("tr");if(me._curIndex-1>=0&&trs[me._curIndex-1]){trs[me._curIndex-1].style.background=""}}me._curIndex=-1});var pt=convertCoord(curStep.getPoint(),this._opts.coordType,map.config.coordType);map.openInfoWindow(iw,pt)}}this._curIndex=index},_clearOverlays:function(){for(var i=0,l=this._overlays.length;i0){var plan=this._results.getPlan(0);var route=plan.getRoute(0);var container=create("div",{style:"font-size:12px;font-family:arial, sans-serif;background:#fff"});var divSta=BaseRoute._genTitle(this._results.getStart().title,'Instance("'+this.guid+'")._select(0)',0);var tables=[""];for(var i=0,l=route.getNumSteps();i");tables.push("");tables.push("");tables.push("")}tables.push("
"+(i+1)+"."+route.getStep(i).getDescription()+"
");var divEnd=BaseRoute._genTitle(this._results.getEnd().title,'Instance("'+this.guid+'")._select('+(route.getNumSteps()+1)+")",1);var control="
\u5168\u7a0b\uff1a"+plan.getDistance().replace(/(\d+(?:.\d+)?)/,"$1 ")+" / "+plan.getDuration().replace(/(\d+)/,"$1 ")+"";if(this._results.moreResultsUrl){control+="\u5230\u767e\u5ea6\u5730\u56fe\u67e5\u770b»"}control+=" 
";container.innerHTML=divSta+tables.join("")+divEnd+control;this._opts.renderOptions.panel.appendChild(container);this._triggerCbk(BaseSearch.CBK_RESULTS_HTML_SET,container)}},_getRoadName:function(roadType,roadName){if(roadName==""||!roadName){if(roadType==9||roadType==12||roadType==1||roadType==16){roadName=DWRoute.ROAD_TYPE[roadType]}}return roadName},_getPoiInfo:function(rss){var tips="";var poi=rss.poi;if(poi){var ps=this._getPsType(poi.ps)||"",pw=this._getPwType(poi.pw)||"";var ds=poi.pd<((rss.t==13||rss.t==4)?1000:50)?"":"\u7ea6"+formatDistance(poi.pd)+"\u540e";tips=pw+ps+""+poi.pn+""+ds+(ps==""?"":"\uff0c")}return tips},_getTicInfo:function(kps){var kiw=kps.iw;return !kps.ic?"":((this._getIwGo(kiw)||"")+""+kps.ic+""+(this._getIwTo(kiw)||""))},_getRoadAct:function(roadType,roadName){var act="\u6cbf";if(roadType==0||(!roadName&&roadType!=1&&roadType!=16&&roadType!=9&&roadType!=12)){act=""}return act},_getRetAct:function(roadType,roadName){var ret="\u8fdb\u5165";if(!roadName&&(roadType==9||roadType==12)){ret="\u4e0a"}else{if(roadType==0||(!roadName&&roadType!=1&&roadType!=16)){ret=""}}return ret},_getTaxiFare:function(){if(this._json&&this._json.content&&this._json.content.taxi){var taxiData=this._json.content.taxi;var result={distance:taxiData.dis,remark:taxiData.remark};if(taxiData.detail[0]){var dayFare=taxiData.detail[0];result.day={initialFare:parseFloat(dayFare.startPrice),unitFare:parseFloat(dayFare.kmPrice),totalFare:parseFloat(dayFare.totalPrice)}}if(taxiData.detail[1]){var nightFare=taxiData.detail[1];result.night={initialFare:parseFloat(nightFare.startPrice),unitFare:parseFloat(nightFare.kmPrice),totalFare:parseFloat(nightFare.totalPrice)}}return result}return null}});window.BMAP_DRIVING_POLICY_LEAST_TIME=0;window.BMAP_DRIVING_POLICY_LEAST_DISTANCE=1;window.BMAP_DRIVING_POLICY_AVOID_HIGHWAYS=2;function DrivingRoute(location,opts){DWRoute.call(this,location,opts);opts=opts||{};this.setPolicy(opts.policy);this.QUERY_TYPE=QUERY_TYPE_DRIVING;this.RETURN_TYPE=RETURN_TYPE_DRIVING;this.ROUTE_TYPE=BMAP_ROUTE_TYPE_DRIVING;this.TRANS_INFO_WND_TYPE=TRANS_INFO_WND_DRIVING}baidu.inherits(DrivingRoute,DWRoute,"DrivingRoute");DrivingRoute.TURN_TYPE=["","\u76f4\u884c","\u53f3\u524d\u65b9\u8f6c\u5f2f","\u53f3\u8f6c","\u53f3\u540e\u65b9\u8f6c\u5f2f","\u8c03\u5934","\u5de6\u540e\u65b9\u8f6c\u5f2f","\u5de6\u8f6c","\u5de6\u524d\u65b9\u8f6c\u5f2f","\u7a0d\u5411\u5de6\u8f6c","\u76f4\u884c","\u7a0d\u5411\u53f3\u8f6c","\u6b63\u5317\u65b9\u5411","\u4e1c\u5317\u65b9\u5411","\u6b63\u4e1c\u65b9\u5411","\u4e1c\u5357\u65b9\u5411","\u6b63\u5357\u65b9\u5411","\u897f\u5357\u65b9\u5411","\u6b63\u897f\u65b9\u5411","\u897f\u5317\u65b9\u5411"];DrivingRoute.RET_TYPE=["","\u4ece\u8d77\u70b9\u51fa\u53d1","\u5230\u8fbe\u76ee\u7684\u5730","\u9014\u7ecf\u70b9","\u884c\u9a76"];DrivingRoute.IWGO=["\u5728","\u4ece","\u4ece"];DrivingRoute.IWTO=["","","\u79bb\u5f00"];DrivingRoute.PWTYPE=["\u8fc7","\u5728"];DrivingRoute.PSTYPE=["\u5de6\u4fa7\u7684","\u53f3\u4fa7\u7684",""];DrivingRoute.DWTYPE=["","\u671d"];baidu.extend(DrivingRoute.prototype,{setPolicy:function(policy){if(policy>=BMAP_DRIVING_POLICY_LEAST_TIME&&policy<=BMAP_DRIVING_POLICY_AVOID_HIGHWAYS){this._opts.policy=policy}else{this._opts.policy=BMAP_DRIVING_POLICY_LEAST_TIME}},_createResults:function(opts){return new DrivingRouteResult(opts)},_getTurnType:function(tt){return DrivingRoute.TURN_TYPE[tt]},_getRetType:function(rt){return DrivingRoute.RET_TYPE[rt]},_getIwGo:function(i){return DrivingRoute.IWGO[i]},_getIwTo:function(i){return DrivingRoute.IWTO[i]},_getPwType:function(i){return DrivingRoute.PWTYPE[i]},_getPsType:function(i){return DrivingRoute.PSTYPE[i]},_getDwType:function(i){return DrivingRoute.DWTYPE[i]},toString:function(){return"DrivingRoute"}});function WalkingRoute(location,opts){DWRoute.call(this,location,opts);this.QUERY_TYPE=QUERY_TYPE_WALKING;this.RETURN_TYPE=RETURN_TYPE_WALKING;this.ROUTE_TYPE=BMAP_ROUTE_TYPE_WALKING;this.TRANS_INFO_WND_TYPE=TRANS_INFO_WND_WALKING}baidu.inherits(WalkingRoute,DWRoute,"WalkingRoute");WalkingRoute.TURN_TYPE=["","\u76f4\u8d70","\u5411\u53f3\u524d\u65b9\u8f6c","\u53f3\u8f6c","\u5411\u53f3\u540e\u65b9\u8f6c","\u5411\u540e\u8f6c","\u5411\u5de6\u540e\u65b9\u8f6c","\u5de6\u8f6c","\u5411\u5de6\u524d\u65b9\u8f6c","\u5de6\u8f6c\u7a7f\u8fc7\u9a6c\u8def\u5e76\u7ee7\u7eed\u5411\u524d","\u53f3\u8f6c\u7a7f\u8fc7\u9a6c\u8def\u5e76\u7ee7\u7eed\u5411\u524d","\u5de6\u8f6c\u7a7f\u8fc7\u9a6c\u8def\u5e76\u5f80\u56de\u8d70","\u53f3\u8f6c\u7a7f\u8fc7\u9a6c\u8def\u5e76\u5f80\u56de\u8d70","\u6b63\u5317\u65b9\u5411","\u4e1c\u5317\u65b9\u5411","\u6b63\u4e1c\u65b9\u5411","\u4e1c\u5357\u65b9\u5411","\u6b63\u5357\u65b9\u5411","\u897f\u5357\u65b9\u5411","\u6b63\u897f\u65b9\u5411","\u897f\u5317\u65b9\u5411","","","",""];WalkingRoute.RET_TYPE=["","\u4ece\u8d77\u70b9\u51fa\u53d1","\u5230\u8fbe\u76ee\u7684\u5730","\u9014\u7ecf\u70b9","\u8d70"];WalkingRoute.IWGO=["\u5728","\u4ece","\u4ece"];WalkingRoute.IWTO=["","","\u79bb\u5f00"];WalkingRoute.PWTYPE=["\u8fc7","\u5728"];WalkingRoute.PSTYPE=["\u5de6\u4fa7\u7684","\u53f3\u4fa7\u7684",""];WalkingRoute.DWTYPE=["","\u671d"];baidu.extend(WalkingRoute.prototype,{_createResults:function(opts){delete opts.url;return new WalkingRouteResult(opts)},_getTurnType:function(tt){return WalkingRoute.TURN_TYPE[tt]},_getRetType:function(rt){return WalkingRoute.RET_TYPE[rt]},_getIwGo:function(i){return WalkingRoute.IWGO[i]},_getIwTo:function(i){return WalkingRoute.IWTO[i]},_getPwType:function(i){return WalkingRoute.PWTYPE[i]},_getPsType:function(i){return WalkingRoute.PSTYPE[i]},_getDwType:function(i){return WalkingRoute.DWTYPE[i]},toString:function(){return"WalkingRoute"}});function Line(opts){this.title=opts.title;this.uid=opts.uid;this.type=opts.type;this._stops=opts.stops.slice(0);this._points=opts.points.slice(0);this._distance=opts.distance||0;this._numViaStops=opts.numViaStops||0}baidu.extend(Line.prototype,{getNumViaStops:function(){return this._numViaStops},getGetOnStop:function(){return this._stops[0]},getGetOffStop:function(){return this._stops[1]},getPoints:function(){return this._points},getPolyline:function(){return this._polyline},getDistance:function(format){if(format===false){return this._distance}else{return formatDistance(this._distance)}}});function Popup(opts){baidu.lang.Class.call(this);this.visible=false;this.config=opts;if(!this.config){return}this.config.addDom=this.config.addDom?baidu.G(this.config.addDom):document.body;if(opts.clickClose!=null&&opts.clickClose==false){this.config.clickClose=false}else{this.config.clickClose=true}this.connectDom=new Array()}baidu.extend(Popup.prototype,{render:function(){var config=this.config;this.main=create("div",{style:"position:absolute;z-index:20;width:390px;display:none;font-size:12px;font-family:arial,sans-serif"});this.popBox=create("div",{style:"border:1px solid #8ba4d8;z-index:2;position:absolute;width:100%;height:100%;background:#FFF;overflow:hidden"});this.main.appendChild(this.popBox);if(config.isTitle!=false){this.title=create("div",{style:"background:url("+API_URL+"img/popup_title.gif);height:24px;line-height:25px;font-size:12px;font-weight:bold;color:#6688cc;padding-left:7px"});this.popBox.appendChild(this.title)}this.content=create("div");this.popBox.appendChild(this.content);this.button=create("button",{style:"position:absolute;top:6px;right:4px;width:12px;height:12px;background:url("+API_URL+"img/popup_close.gif) no-repeat;border:0;cursor:pointer",id:"popup_close"});this.popBox.appendChild(this.button);this.shadow=create("div",{style:"width:100%; height:100%; background:#505050;border:1px solid #505050; position:absolute;left:2px; top:3px;z-index:1;opacity:0.4;filter:alpha(opacity=40)"});this.main.appendChild(this.shadow);this.config.addDom.appendChild(this.main);this.addConnectDom(this.main);this.initialize()},initialize:function(){var config=this.config;this.setTitle(config.title);this.setContent(config.content);this.setWidth(config.width);this.setHeight(config.height);this.show();var me=this;var popClose=function(e){var ee=e.srcElement||e.target;while(ee){var dom=me.connectDom;for(var i=0;i9){if(cityName==null){}if(e.type.indexOf("zoom")>0){if(me.ishide&&me.ishide==1){me.show();me.ishide=0}}me.removeMarker()}else{if(e.type.indexOf("zoom")>0){if(me.opened==1){me.ishide=1;me.addMarker()}}me.hide()}}}map.addEventListener("load",function(e){showMarker(e)});map.addEventListener("moveend",function(e){showMarker(e)});map.addEventListener("mapcontainerresize",function(e){showMarker(e)});map.addEventListener("dragend",function(e){showMarker(e)});map.addEventListener("zoomend",function(e){showMarker(e)});map.addEventListener("zoomstart",function(e){showMarker(e)});return div},bind:function(c){var me=this;c.onmousedown=function(){me.markers=[];this.style.backgroundPosition="0 -108px"};c.onclick=function(){me._toggle()}},setWeek:function(obj){for(var i=0;i<7;i++){baidu.G("week_"+this.hashCode+"_"+i).className="";if(baidu.G("week_"+this.hashCode+"_"+i)==obj){this.week=i;obj.className="on";baidu.G("font_"+this.hashCode).innerHTML="\u661f\u671f"+obj.innerHTML+" ";this.setForecast()}}},_genHtml:function(){var guid=this.hashCode;var weekName=["\u4e00","\u4e8c","\u4e09","\u56db","\u4e94","\u516d","\u65e5"];var htmls=['
'];htmls.push('
\u5b9e\u65f6\u8def\u51b5
');htmls.push('
\u5f53\u524d\u65f6\u95f4\uff1a ');htmls.push('');htmls.push('');htmls.push('\u67e5\u770b\u6d41\u91cf\u9884\u6d4b
");htmls.push('');htmls.push('');for(var i=0;i<7;i++){htmls.push('")}htmls.push("");htmls.push('');htmls.push('");htmls.push('
');return htmls.join("")},_launch:function(){var me=this;this._getTime();if(me.trafficTimer){clearInterval(me.trafficTimer)}me.trafficTimer=setInterval(function(){me._getTime()},TrafficControl.time);this.setBar();this.setBarTime(12)},_getTime:function(){if(this.type!="default"){return}var me=this;var aid=[{code:131,name:"beijing"},{code:289,name:"shanghai"},{code:257,name:"guangzhou"}];var k=true;var mType=BMap.MapType.B_LiveTraffic_MAP;this._getCityCode(function(code){for(var i=0;ithis.now){this.now=newTime;this.updateTile()}},updateTile:function(){this.addTrafficLay("B_LiveTraffic_MAP")},_getCityCode:function(cbk){var pt=this._map.getCenter();var level=this._map.getZoom();if(this._map.config.coordType==BMAP_COORD_LNGLAT){pt=BMap.Projection.convertLL2MC(pt)}DataMgr.request(function(json){if(json&&json.result&&json.result.type==RETURN_TYPE_CENTER){cbk&&cbk(json.content.uid)}},{qt:QUERY_TYPE_CENTER,b:pt.lng+","+pt.lat+";"+pt.lng+","+pt.lat,l:level})},setBar:function(){var me=this;var bt=baidu.G("bar_"+this.hashCode);function dragStart(){baidu.on(document,"onmousemove",dragIng);baidu.on(document,"onmouseup",dragEnd)}function dragIng(e){var x=e.clientX||e.x;var left=getPosition(baidu.G("bar_prev_"+me.hashCode)).left+9;var margin=x-left-4;if(margin<0){margin=0}if(margin>165){margin=165}if(FeBrowser.ie<=6&&FeBrowser.ie>0){bt.style.marginLeft=(margin*0.53)+"px"}else{bt.style.marginLeft=margin+"px"}baidu.G("timeBox_"+me.hashCode).style.marginLeft=(margin)+"px";me.setTimeBox()}function dragEnd(){baidu.un(document,"onmousemove",dragIng);baidu.un(document,"onmouseup",dragEnd);me.setForecast()}baidu.on(bt,"onmousedown",dragStart)},setBarTime:function(n){if(n<0){n=0}if(n>24){n=24}this.hour=n;var margin=n*(165/24);baidu.G("timeBox_"+this.hashCode).style.marginLeft=margin+"px";var bt=baidu.G("bar_"+this.hashCode);if(FeBrowser.ie<=6&&FeBrowser.ie>0){bt.style.marginLeft=(margin*0.53)+"px"}else{bt.style.marginLeft=margin+"px"}this.setTimeBox()},setTimeBox:function(){var box=baidu.G("timeBox_"+this.hashCode);var box2=baidu.G("time_"+this.hashCode);var margin=parseInt(box.style.marginLeft);var n=Math.ceil((margin-4)*24/165);this.hour=n;if(n<10){n="0"+n}box2.innerHTML=box.innerHTML=n+":00"},setBarBut:function(key){var box=baidu.G("timeBox_"+this.hashCode);var margin=parseInt(box.style.marginLeft);var n=Math.ceil((margin-4)*24/165);this.setBarTime(key=="next"?(n+1):(n-1));this.setForecast()},setForecast:function(){var hour=this.hour;if(hour==24){hour=0}var forecastUrl=[];var mForeType=BMap.MapType.B_ForecastTraffic_MAP;var mLiveType=BMap.MapType.B_LiveTraffic_MAP;for(var i=0;i-1){url+="&t="+t.getTime()}else{url+="?t="+t.getTime()}var _complete=function(){if(!script.readyState||script.readyState=="loaded"||script.readyState=="complete"){if(typeof(echo)=="function"){echo()}else{eval(echo)}}};if(isIe){script.onreadystatechange=_complete}else{script.onload=_complete}script.setAttribute("src",url)}function getBPoints(bounds){if(!bounds||bounds.length==0){return}var points=[];for(var i=0;i18){level=18}return level}var STAT_APPJS_EXECUTE=5100;window._addStat(STAT_APPJS_EXECUTE);window.BMAP_STATUS_SUCCESS=0;window.BMAP_STATUS_CITY_LIST=1;window.BMAP_STATUS_UNKNOWN_LOCATION=2;window.BMAP_STATUS_UNKNOWN_ROUTE=3;window.BMAP_STATUS_INVALID_KEY=4;window.BMAP_STATUS_INVALID_REQUEST=5;window.BMAP_STATUS_PERMISSION_DENIED=6;window.BMAP_STATUS_SERVICE_UNAVAILABLE=7;window.BMAP_STATUS_TIMEOUT=8;window.BMAP_ROUTE_TYPE_WALKING=2;window.BMAP_ROUTE_TYPE_DRIVING=3;var QUERY_TYPE_CURRENT_CITY="cur";var QUERY_TYPE_CENTER="cen";var QUERY_TYPE_POI_SEARCH="s";var QUERY_TYPE_SEARCH_INBOUNDS="bd";var QUERY_TYPE_SEARCH_NEARBY="nb";var QUERY_TYPE_TRANSIT="bt";var QUERY_TYPE_DRIVING="nav";var QUERY_TYPE_WALKING="walk";var QUERY_TYPE_GEOCODER="gc";var QUERY_TYPE_REVERSE_GEOCODER="rgc";var QUERY_TYPE_LOCALCITY="dec";var QUERY_TYPE_EXT="ext";var RETURN_TYPE_CURRENT_CITY=2;var RETURN_TYPE_CENTER=4;var RETURN_TYPE_CITY_LIST=7;var RETURN_TYPE_POI_SEARCH=11;var RETURN_TYPE_SEARCH_NEARBY=12;var RETURN_TYPE_TRANSIT=14;var RETURN_TYPE_DRIVING=20;var RETURN_TYPE_SEARCH_INBOUNDS=21;var RETURN_TYPE_SPECIAL_REGION=26;var RETURN_TYPE_NODATA_REGION=28;var RETURN_TYPE_WALKING=31;var RETURN_TYPE_GEOCODER=35;var RETURN_TYPE_REVERSE_GEOCODER=44;var LOC_TYPE_UNKNOWN=-1;var LOC_TYPE_MAP=0;var LOC_TYPE_POINT=1;var LOC_TYPE_STRING=2;var GEO_TYPE_AREA=0;var GEO_TYPE_LINE=1;var GEO_TYPE_POINT=2;var MAP_URL="https://map.baidu.com/";var API_URL="https://api.map.baidu.com/";function parseGeo(geo,usePoint,coordType){if(typeof geo!="string"||!geo){return}var temp=geo.split("|");var r;var bdpt0;var bdpt1;if(temp.length==1){r=decode_geo_diff(geo)}else{r=decode_geo_diff(temp[2]);bdpt0=decode_geo_diff(temp[0]);bdpt1=decode_geo_diff(temp[1]);if(!usePoint){return r}}var ret={type:r.geoType};if(usePoint){switch(ret.type){case GEO_TYPE_POINT:ret.point=new BMap.Point(r.geo[0][0],r.geo[0][1]);ret.points=[ret.point];if(typeof coordType=="number"&&coordType==BMAP_COORD_LNGLAT){var npt=BMap.Projection.convertMC2LL(ret.point);ret.point=npt;ret.points=[npt]}break;case GEO_TYPE_LINE:ret.points=[];var curGeo=r.geo[0];for(var i=0,l=curGeo.length-1;i_MAX_DELTA_){x=_MAX_DELTA_-x}if(y>_MAX_DELTA_){y=_MAX_DELTA_-y}ret.push(ret[l-2]+x);ret.push(ret[l-1]+y);return 0}function _char2num_(c){var n=c.charCodeAt(0);if(c>="A"&&c<="Z"){return n-"A".charCodeAt(0)}else{if(c>="a"&&c<="z"){return(26+n-"a".charCodeAt(0))}else{if(c>="0"&&c<="9"){return(52+n-"0".charCodeAt(0))}else{if(c=="+"){return 62}else{if(c=="/"){return 63}}}}}return -1}function formatDistance(dis){if(typeof dis=="string"){dis=parseFloat(dis)}var ret;if(!dis||dis<0){ret="0\u7c73"}else{if(dis<=10){ret="10\u7c73"}else{ret=dis<1000?Math.round(dis/10)*10+"\u7c73":(dis/1000).toFixed(1)+"\u516c\u91cc"}}if(ret=="1000\u7c73"){ret="1.0\u516c\u91cc"}return ret}function formatTime(seconds,mode){if(!seconds||isNaN(seconds)){return""}var stime="",m=60,d=m*24;var minutes=Math.ceil(seconds/m);if(mode=="bustime"){var a=minutes%10,b=parseInt(minutes/10);minutes=a!=0?(a>5?(++b*10):b?(b*10):5):minutes}var days=parseInt(minutes/d);minutes%=d;var hours=parseInt(minutes/m);minutes%=m;if(days>=1){stime+=days+"\u5929"}if(hours>=1){stime+=hours+"\u5c0f\u65f6"}if(minutes>=1){if(mode&&mode=="nav"&&days>=1){return stime}else{stime+=minutes+"\u5206\u949f"}}return stime}function convertCoord(point,fromCoord,toCoord){var ret=point;switch(fromCoord){case BMAP_COORD_MERCATOR:switch(toCoord){case BMAP_COORD_LNGLAT:ret=BMap.Projection.convertMC2LL(point);break;default:break}break;case BMAP_COORD_LNGLAT:switch(toCoord){case BMAP_COORD_MERCATOR:ret=BMap.Projection.convertLL2MC(point);break;default:break}break;default:break}return ret}function getPointsByBounds(bounds,fromCoordType,toCoordType){var pt0=new BMap.Point(bounds.minX,bounds.minY);var pt1=new BMap.Point(bounds.maxX,bounds.maxY);if(typeof fromCoordType!="undefined"&&typeof toCoordType!="undefined"){pt0=convertCoord(pt0,fromCoordType,toCoordType);pt1=convertCoord(pt1,fromCoordType,toCoordType)}return[pt0,pt1]}function parseGeoStr(str,coord){var pts=str.split(",");var pt=new BMap.Point(pts[0],pts[1]);return convertCoord(pt,BMAP_COORD_MERCATOR,coord)}window.Instance=baidu.lang.instance;function Page(container,callback,opts){baidu.lang.Class.call(this);if(!container){return}this.container=(typeof(container)=="object")?container:baidu.G(container);this.page=1;this.pageCount=100;this.argName="pg";this.pagecap=4;this.callback=callback;this.update=true;var _config={page:1,totalCount:100,pageCount:100,pagecap:4,argName:"pg",update:true};if(!opts){opts=_config}for(var p in opts){if(typeof(opts[p])!="undefined"){this[p]=opts[p]}}this.render()}baidu.extend(Page.prototype,{render:function(){this.initialize()},initialize:function(){this.checkPages();this.container.innerHTML=this.createHtml()},checkPages:function(){if(isNaN(parseInt(this.page))){this.page=1}if(isNaN(parseInt(this.pageCount))){this.pageCount=1}if(this.page<1){this.page=1}if(this.pageCount<1){this.pageCount=1}if(this.page>this.pageCount){this.page=this.pageCount}this.page=parseInt(this.page);this.pageCount=parseInt(this.pageCount)},getPage:function(){var args=location.search;var reg=new RegExp("[?&]?"+this.argName+"=([^&]*)[&$]?","gi");var chk=args.match(reg);this.page=RegExp.$1},createHtml:function(){var strHtml=[],prevPage=this.page-1,nextPage=this.page+1;strHtml.push('

');if(prevPage<1){}else{if(this.page>=this.pagecap){strHtml.push('\u9996\u9875")}strHtml.push('\u4e0a\u4e00\u9875')}if(this.pagethis.page+spt){var endPage=this.page+spt;var startPage=this.page-spt-mod}else{var endPage=this.pageCount;var startPage=this.page-spt-mod}}if(this.page>this.pageCount-this.pagecap&&this.page>=this.pagecap){var startPage=this.pageCount-this.pagecap+1;var endPage=this.pageCount}for(var i=startPage;i<=endPage;i++){if(i>0){if(i==this.page){strHtml.push(''+i+"")}else{if(i>=1&&i<=this.pageCount){strHtml.push('['+i+"]")}}}}if(nextPage>this.pageCount){}else{strHtml.push('\u4e0b\u4e00\u9875')}strHtml.push("

");return strHtml.join("")},toPage:function(page){var turnTo=page?page:1;if(typeof(this.callback)=="function"){this.callback(turnTo);this.page=turnTo}if(this.update){this.render()}}});mg("LocalSearch",LocalSearch);mg("TransitRoute",TransitRoute);mg("DrivingRoute",DrivingRoute);mg("WalkingRoute",WalkingRoute);mg("TrafficControl",TrafficControl);mg("Geocoder",Geocoder);mg("LocalCity",LocalCity);mg("Geolocation",Geolocation);mg("Boundary",Boundary);function Boundary(opts){this._opts={coordType:BMAP_COORD_LNGLAT};baidu.extend(this._opts,opts)}baidu.inherits(Boundary,baidu.lang.Class,"Boundary");baidu.extend(Boundary.prototype,{get:function(name,cbk){var results={};results.boundaries=[];var me=this;DataMgr.request(function(jsonUID){if(jsonUID&&jsonUID.content&&jsonUID.content.uid){var tempUID=jsonUID.content.uid;DataMgr.request(function(jsonBoundaries){if(jsonBoundaries&&jsonBoundaries.content&&jsonBoundaries.content.geo){if(name.indexOf("\u798f\u5efa")>-1||name.indexOf("\u6d59\u6c5f")>-1){var arrTemp=me._parseGeoSpecial(jsonBoundaries.content.geo);results.boundaries=arrTemp}else{var rs=parseGeo(jsonBoundaries.content.geo,false,me._opts.coordType);if(rs.geo&&rs.geo.length&&rs.geo.length>0){var l=rs.geo.length;for(i=0;i0){var ll=rec.length-1;var str=[];for(var j=0;j + + + + + + + +
+
+
+

+
    +
  • + +
  • +
  • + +
  • +
+
    +
  • + +
  • +
  • + +
  • +
+
+
+
+

+
    +
  • + +
  • +
  • + +
  • +
+
+
+
+

+
    +
  • + + +
  • +
+
+
+
+
+
+

+
+
+
+
+
+ + + \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/table/edittable.js b/web/resource/components/ueditor/dialogs/table/edittable.js new file mode 100644 index 0000000..11dbee7 --- /dev/null +++ b/web/resource/components/ueditor/dialogs/table/edittable.js @@ -0,0 +1,237 @@ +/** + * Created with JetBrains PhpStorm. + * User: xuheng + * Date: 12-12-19 + * Time: 下午4:55 + * To change this template use File | Settings | File Templates. + */ +(function () { + var title = $G("J_title"), + titleCol = $G("J_titleCol"), + caption = $G("J_caption"), + sorttable = $G("J_sorttable"), + autoSizeContent = $G("J_autoSizeContent"), + autoSizePage = $G("J_autoSizePage"), + tone = $G("J_tone"), + me, + preview = $G("J_preview"); + + var editTable = function () { + me = this; + me.init(); + }; + editTable.prototype = { + init:function () { + var colorPiker = new UE.ui.ColorPicker({ + editor:editor + }), + colorPop = new UE.ui.Popup({ + editor:editor, + content:colorPiker + }); + + title.checked = editor.queryCommandState("inserttitle") == -1; + titleCol.checked = editor.queryCommandState("inserttitlecol") == -1; + caption.checked = editor.queryCommandState("insertcaption") == -1; + sorttable.checked = editor.queryCommandState("enablesort") == 1; + + var enablesortState = editor.queryCommandState("enablesort"), + disablesortState = editor.queryCommandState("disablesort"); + + sorttable.checked = !!(enablesortState < 0 && disablesortState >=0); + sorttable.disabled = !!(enablesortState < 0 && disablesortState < 0); + sorttable.title = enablesortState < 0 && disablesortState < 0 ? lang.errorMsg:''; + + me.createTable(title.checked, titleCol.checked, caption.checked); + me.setAutoSize(); + me.setColor(me.getColor()); + + domUtils.on(title, "click", me.titleHanler); + domUtils.on(titleCol, "click", me.titleColHanler); + domUtils.on(caption, "click", me.captionHanler); + domUtils.on(sorttable, "click", me.sorttableHanler); + domUtils.on(autoSizeContent, "click", me.autoSizeContentHanler); + domUtils.on(autoSizePage, "click", me.autoSizePageHanler); + + domUtils.on(tone, "click", function () { + colorPop.showAnchor(tone); + }); + domUtils.on(document, 'mousedown', function () { + colorPop.hide(); + }); + colorPiker.addListener("pickcolor", function () { + me.setColor(arguments[1]); + colorPop.hide(); + }); + colorPiker.addListener("picknocolor", function () { + me.setColor(""); + colorPop.hide(); + }); + }, + + createTable:function (hasTitle, hasTitleCol, hasCaption) { + var arr = [], + sortSpan = '^'; + arr.push(""); + if (hasCaption) { + arr.push("") + } + if (hasTitle) { + arr.push(""); + if(hasTitleCol) { arr.push(""); } + for (var j = 0; j < 5; j++) { + arr.push(""); + } + arr.push(""); + } + for (var i = 0; i < 6; i++) { + arr.push(""); + if(hasTitleCol) { arr.push("") } + for (var k = 0; k < 5; k++) { + arr.push("") + } + arr.push(""); + } + arr.push("
" + lang.captionName + "
" + lang.titleName + "" + lang.titleName + "
" + lang.titleName + "" + lang.cellsName + "
"); + preview.innerHTML = arr.join(""); + this.updateSortSpan(); + }, + titleHanler:function () { + var example = $G("J_example"), + frg=document.createDocumentFragment(), + color = domUtils.getComputedStyle(domUtils.getElementsByTagName(example, "td")[0], "border-color"), + colCount = example.rows[0].children.length; + + if (title.checked) { + example.insertRow(0); + for (var i = 0, node; i < colCount; i++) { + node = document.createElement("th"); + node.innerHTML = lang.titleName; + frg.appendChild(node); + } + example.rows[0].appendChild(frg); + + } else { + domUtils.remove(example.rows[0]); + } + me.setColor(color); + me.updateSortSpan(); + }, + titleColHanler:function () { + var example = $G("J_example"), + color = domUtils.getComputedStyle(domUtils.getElementsByTagName(example, "td")[0], "border-color"), + colArr = example.rows, + colCount = colArr.length; + + if (titleCol.checked) { + for (var i = 0, node; i < colCount; i++) { + node = document.createElement("th"); + node.innerHTML = lang.titleName; + colArr[i].insertBefore(node, colArr[i].children[0]); + } + } else { + for (var i = 0; i < colCount; i++) { + domUtils.remove(colArr[i].children[0]); + } + } + me.setColor(color); + me.updateSortSpan(); + }, + captionHanler:function () { + var example = $G("J_example"); + if (caption.checked) { + var row = document.createElement('caption'); + row.innerHTML = lang.captionName; + example.insertBefore(row, example.firstChild); + } else { + domUtils.remove(domUtils.getElementsByTagName(example, 'caption')[0]); + } + }, + sorttableHanler:function(){ + me.updateSortSpan(); + }, + autoSizeContentHanler:function () { + var example = $G("J_example"); + example.removeAttribute("width"); + }, + autoSizePageHanler:function () { + var example = $G("J_example"); + var tds = example.getElementsByTagName(example, "td"); + utils.each(tds, function (td) { + td.removeAttribute("width"); + }); + example.setAttribute('width', '100%'); + }, + updateSortSpan: function(){ + var example = $G("J_example"), + row = example.rows[0]; + + var spans = domUtils.getElementsByTagName(example,"span"); + utils.each(spans,function(span){ + span.parentNode.removeChild(span); + }); + if (sorttable.checked) { + utils.each(row.cells, function(cell, i){ + var span = document.createElement("span"); + span.innerHTML = "^"; + cell.appendChild(span); + }); + } + }, + getColor:function () { + var start = editor.selection.getStart(), color, + cell = domUtils.findParentByTagName(start, ["td", "th", "caption"], true); + color = cell && domUtils.getComputedStyle(cell, "border-color"); + if (!color) color = "#DDDDDD"; + return color; + }, + setColor:function (color) { + var example = $G("J_example"), + arr = domUtils.getElementsByTagName(example, "td").concat( + domUtils.getElementsByTagName(example, "th"), + domUtils.getElementsByTagName(example, "caption") + ); + + tone.value = color; + utils.each(arr, function (node) { + node.style.borderColor = color; + }); + + }, + setAutoSize:function () { + var me = this; + autoSizePage.checked = true; + me.autoSizePageHanler(); + } + }; + + new editTable; + + dialog.onok = function () { + editor.__hasEnterExecCommand = true; + + var checks = { + title:"inserttitle deletetitle", + titleCol:"inserttitlecol deletetitlecol", + caption:"insertcaption deletecaption", + sorttable:"enablesort disablesort" + }; + editor.fireEvent('saveScene'); + for(var i in checks){ + var cmds = checks[i].split(" "), + input = $G("J_" + i); + if(input["checked"]){ + editor.queryCommandState(cmds[0])!=-1 &&editor.execCommand(cmds[0]); + }else{ + editor.queryCommandState(cmds[1])!=-1 &&editor.execCommand(cmds[1]); + } + } + + editor.execCommand("edittable", tone.value); + autoSizeContent.checked ?editor.execCommand('adaptbytext') : ""; + autoSizePage.checked ? editor.execCommand("adaptbywindow") : ""; + editor.fireEvent('saveScene'); + + editor.__hasEnterExecCommand = false; + }; +})(); \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/table/edittd.html b/web/resource/components/ueditor/dialogs/table/edittd.html new file mode 100644 index 0000000..49a52f7 --- /dev/null +++ b/web/resource/components/ueditor/dialogs/table/edittd.html @@ -0,0 +1,61 @@ + + + + + + + + +
+ + +
+ + + \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/table/edittip.html b/web/resource/components/ueditor/dialogs/table/edittip.html new file mode 100644 index 0000000..954f7bb --- /dev/null +++ b/web/resource/components/ueditor/dialogs/table/edittip.html @@ -0,0 +1,33 @@ + + + + 表格删除提示 + + + + +
+
+ +
+
+ +
+
+ + + \ No newline at end of file diff --git a/web/resource/components/ueditor/dialogs/video/images/file-icons.gif b/web/resource/components/ueditor/dialogs/video/images/file-icons.gif new file mode 100644 index 0000000..d8c02c2 Binary files /dev/null and b/web/resource/components/ueditor/dialogs/video/images/file-icons.gif differ diff --git a/web/resource/components/ueditor/dialogs/video/images/file-icons.png b/web/resource/components/ueditor/dialogs/video/images/file-icons.png new file mode 100644 index 0000000..3ff82c8 Binary files /dev/null and b/web/resource/components/ueditor/dialogs/video/images/file-icons.png differ diff --git a/web/resource/components/ueditor/dialogs/wordimage/fClipboard_ueditor.swf b/web/resource/components/ueditor/dialogs/wordimage/fClipboard_ueditor.swf new file mode 100644 index 0000000..ac5d27f Binary files /dev/null and b/web/resource/components/ueditor/dialogs/wordimage/fClipboard_ueditor.swf differ diff --git a/web/resource/components/ueditor/lang/en/en.js b/web/resource/components/ueditor/lang/en/en.js new file mode 100644 index 0000000..c7e22f5 --- /dev/null +++ b/web/resource/components/ueditor/lang/en/en.js @@ -0,0 +1,684 @@ +/** + * Created with JetBrains PhpStorm. + * User: taoqili + * Date: 12-6-12 + * Time: 下午6:57 + * To change this template use File | Settings | File Templates. + */ +UE.I18N['en'] = { + 'labelMap':{ + 'anchor':'Anchor', 'undo':'Undo', 'redo':'Redo', 'bold':'Bold', 'indent':'Indent', 'snapscreen':'SnapScreen', + 'italic':'Italic', 'underline':'Underline', 'strikethrough':'Strikethrough', 'subscript':'SubScript','fontborder':'text border', + 'superscript':'SuperScript', 'formatmatch':'Format Match', 'source':'Source', 'blockquote':'BlockQuote', + 'pasteplain':'PastePlain', 'selectall':'SelectAll', 'print':'Print', 'preview':'Preview', + 'horizontal':'Horizontal', 'removeformat':'RemoveFormat', 'time':'Time', 'date':'Date', + 'unlink':'Unlink', 'insertrow':'InsertRow', 'insertcol':'InsertCol', 'mergeright':'MergeRight', 'mergedown':'MergeDown', + 'deleterow':'DeleteRow', 'deletecol':'DeleteCol', 'splittorows':'SplitToRows','insertcode':'insert code', + 'splittocols':'SplitToCols', 'splittocells':'SplitToCells','deletecaption':'DeleteCaption','inserttitle':'InsertTitle', + 'mergecells':'MergeCells', 'deletetable':'DeleteTable', 'cleardoc':'Clear', 'insertparagraphbeforetable':"InsertParagraphBeforeTable", + 'fontfamily':'FontFamily', 'fontsize':'FontSize', 'paragraph':'Paragraph','simpleupload':'Single Image','insertimage':'Multi Image','edittable':'Edit Table', 'edittd':'Edit Td','link':'Link', + 'emotion':'Emotion', 'spechars':'Spechars', 'searchreplace':'SearchReplace', 'map':'BaiduMap', 'gmap':'GoogleMap', + 'insertvideo':'Video', 'help':'Help', 'justifyleft':'JustifyLeft', 'justifyright':'JustifyRight', 'justifycenter':'JustifyCenter', + 'justifyjustify':'Justify', 'forecolor':'FontColor', 'backcolor':'BackColor', 'insertorderedlist':'OL', + 'insertunorderedlist':'UL', 'fullscreen':'FullScreen', 'directionalityltr':'EnterFromLeft', 'directionalityrtl':'EnterFromRight', + 'rowspacingtop':'RowSpacingTop', 'rowspacingbottom':'RowSpacingBottom', 'pagebreak':'PageBreak', 'insertframe':'Iframe', 'imagenone':'Default', + 'imageleft':'ImageLeft', 'imageright':'ImageRight', 'attachment':'Attachment', 'imagecenter':'ImageCenter', 'wordimage':'WordImage', + 'lineheight':'LineHeight','edittip':'EditTip','customstyle':'CustomStyle', 'scrawl':'Scrawl', 'autotypeset':'AutoTypeset', + 'webapp':'WebAPP', 'touppercase':'UpperCase', 'tolowercase':'LowerCase','template':'Template','background':'Background','inserttable':'InsertTable', + 'music':'Music', 'charts': 'charts','drafts': 'Load from Drafts' + }, + 'insertorderedlist':{ + 'num':'1,2,3...', + 'num1':'1),2),3)...', + 'num2':'(1),(2),(3)...', + 'cn':'一,二,三....', + 'cn1':'一),二),三)....', + 'cn2':'(一),(二),(三)....', + 'decimal':'1,2,3...', + 'lower-alpha':'a,b,c...', + 'lower-roman':'i,ii,iii...', + 'upper-alpha':'A,B,C...', + 'upper-roman':'I,II,III...' + }, + 'insertunorderedlist':{ + 'circle':'○ Circle', + 'disc':'● Circle dot', + 'square':'■ Rectangle ', + 'dash' :'- Dash', + 'dot' : '。dot' + }, + 'paragraph':{'p':'Paragraph', 'h1':'Title 1', 'h2':'Title 2', 'h3':'Title 3', 'h4':'Title 4', 'h5':'Title 5', 'h6':'Title 6'}, + 'fontfamily':{ + 'songti':'Sim Sun', + 'kaiti':'Sim Kai', + 'heiti':'Sim Hei', + 'lishu':'Sim Li', + 'yahei': 'Microsoft YaHei', + 'andaleMono':'Andale Mono', + 'arial': 'Arial', + 'arialBlack':'Arial Black', + 'comicSansMs':'Comic Sans MS', + 'impact':'Impact', + 'timesNewRoman':'Times New Roman' + }, + 'customstyle':{ + 'tc':'Title center', + 'tl':'Title left', + 'im':'Important', + 'hi':'Highlight' + }, + 'autoupload': { + 'exceedSizeError': 'File Size Exceed', + 'exceedTypeError': 'File Type Not Allow', + 'jsonEncodeError': 'Server Return Format Error', + 'loading':"loading...", + 'loadError':"load error", + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + }, + 'simpleupload':{ + 'exceedSizeError': 'File Size Exceed', + 'exceedTypeError': 'File Type Not Allow', + 'jsonEncodeError': 'Server Return Format Error', + 'loading':"loading...", + 'loadError':"load error", + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + }, + 'elementPathTip':"Path", + 'wordCountTip':"Word Count", + 'wordCountMsg':'{#count} characters entered,{#leave} left. ', + 'wordOverFlowMsg':'The number of characters has exceeded allowable maximum values, the server may refuse to save!', + 'ok':"OK", + 'cancel':"Cancel", + 'closeDialog':"closeDialog", + 'tableDrag':"You must import the file uiUtils.js before drag! ", + 'autofloatMsg':"The plugin AutoFloat depends on EditorUI!", + 'loadconfigError': 'Get server config error.', + 'loadconfigFormatError': 'Server config format error.', + 'loadconfigHttpError': 'Get server config http error.', + 'snapScreen_plugin':{ + 'browserMsg':"Only IE supported!", + 'callBackErrorMsg':"The callback data is wrong,please check the config!", + 'uploadErrorMsg':"Upload error,please check your server environment! " + }, + 'insertcode':{ + 'as3':'ActionScript 3', + 'bash':'Bash/Shell', + 'cpp':'C/C++', + 'css':'CSS', + 'cf':'ColdFusion', + 'c#':'C#', + 'delphi':'Delphi', + 'diff':'Diff', + 'erlang':'Erlang', + 'groovy':'Groovy', + 'html':'HTML', + 'java':'Java', + 'jfx':'JavaFX', + 'js':'JavaScript', + 'pl':'Perl', + 'php':'PHP', + 'plain':'Plain Text', + 'ps':'PowerShell', + 'python':'Python', + 'ruby':'Ruby', + 'scala':'Scala', + 'sql':'SQL', + 'vb':'Visual Basic', + 'xml':'XML' + }, + 'confirmClear':"Do you confirm to clear the Document?", + 'contextMenu':{ + 'delete':"Delete", + 'selectall':"Select all", + 'deletecode':"Delete Code", + 'cleardoc':"Clear Document", + 'confirmclear':"Do you confirm to clear the Document?", + 'unlink':"Unlink", + 'paragraph':"Paragraph", + 'edittable':"Table property", + 'aligncell':'Align cell', + 'aligntable':'Table alignment', + 'tableleft':'Left float', + 'tablecenter':'Center', + 'tableright':'Right float', + 'aligntd':'Cell alignment', + 'edittd':"Cell property", + 'setbordervisible':'set table edge visible', + 'table':"Table", + 'justifyleft':'Justify Left', + 'justifyright':'Justify Right', + 'justifycenter':'Justify Center', + 'justifyjustify':'Default', + 'deletetable':"Delete table", + 'insertparagraphbefore':"InsertedBeforeLine", + 'insertparagraphafter':'InsertedAfterLine', + 'inserttable':'Insert table', + 'insertcaption':'Insert caption', + 'deletecaption':'Delete Caption', + 'inserttitle':'Insert Title', + 'deletetitle':'Delete Title', + 'inserttitlecol':'Insert Title Col', + 'deletetitlecol':'Delete Title Col', + 'averageDiseRow':'AverageDise Row', + 'averageDisCol':'AverageDis Col', + 'deleterow':"Delete row", + 'deletecol':"Delete col", + 'insertrow':"Insert row", + 'insertcol':"Insert col", + 'insertrownext':'Insert Row Next', + 'insertcolnext':'Insert Col Next', + 'mergeright':"Merge right", + 'mergeleft':"Merge left", + 'mergedown':"Merge down", + 'mergecells':"Merge cells", + 'splittocells':"Split to cells", + 'splittocols':"Split to Cols", + 'splittorows':"Split to Rows", + 'tablesort':'Table sorting', + 'enablesort':'Sorting Enable', + 'disablesort':'Sorting Disable', + 'reversecurrent':'Reverse current', + 'orderbyasc':'Order By ASCII', + 'reversebyasc':'Reverse By ASCII', + 'orderbynum':'Order By Num', + 'reversebynum':'Reverse By Num', + 'borderbk':'Border shading', + 'setcolor':'interlaced color', + 'unsetcolor':'Cancel interlacedcolor', + 'setbackground':'Background interlaced', + 'unsetbackground':'Cancel Bk interlaced', + 'redandblue':'Blue and red', + 'threecolorgradient':'Three-color gradient', + 'copy':"Copy(Ctrl + c)", + 'copymsg':"Browser does not support. Please use 'Ctrl + c' instead!", + 'paste':"Paste(Ctrl + v)", + 'pastemsg':"Browser does not support. Please use 'Ctrl + v' instead!" + }, + 'copymsg': "Browser does not support. Please use 'Ctrl + c' instead!", + 'pastemsg': "Browser does not support. Please use 'Ctrl + v' instead!", + 'anthorMsg':"Link", + 'clearColor':'Clear', + 'standardColor':'Standard color', + 'themeColor':'Theme color', + 'property':'Property', + 'default':'Default', + 'modify':'Modify', + 'justifyleft':'Justify Left', + 'justifyright':'Justify Right', + 'justifycenter':'Justify Center', + 'justify':'Default', + 'clear':'Clear', + 'anchorMsg':'Anchor', + 'delete':'Delete', + 'clickToUpload':"Click to upload", + 'unset':'Language hasn\'t been set!', + 't_row':'row', + 't_col':'col', + 'pasteOpt':'Paste Option', + 'pasteSourceFormat':"Keep Source Formatting", + 'tagFormat':'Keep tag', + 'pasteTextFormat':'Keep Text only', + 'more':'More', + 'autoTypeSet':{ + 'mergeLine':"Merge empty line", + 'delLine':"Del empty line", + 'removeFormat':"Remove format", + 'indent':"Indent", + 'alignment':"Alignment", + 'imageFloat':"Image float", + 'removeFontsize':"Remove font size", + 'removeFontFamily':"Remove fontFamily", + 'removeHtml':"Remove redundant HTML code", + 'pasteFilter':"Paste filter", + 'run':"Done", + 'symbol':'Symbol Conversion', + 'bdc2sb':'Full-width to Half-width', + 'tobdc':'Half-width to Full-width' + }, + + 'background':{ + 'static':{ + 'lang_background_normal':'Normal', + 'lang_background_local':'Online', + 'lang_background_set':'Background Set', + 'lang_background_none':'No Background', + 'lang_background_colored':'Colored Background', + 'lang_background_color':'Color Set', + 'lang_background_netimg':'Net-Image', + 'lang_background_align':'Align Type', + 'lang_background_position':'Position', + 'repeatType':{'options':["Center", "Repeat-x", "Repeat-y", "Tile","Custom"]} + }, + 'noUploadImage':"No pictures has been uploaded!", + 'toggleSelect':'Change the active state by click!\n Image Size: ' + }, + //===============dialog i18N======================= + 'insertimage':{ + 'static':{ + 'lang_tab_remote':"Insert", + 'lang_tab_upload':"Local", + 'lang_tab_online':"Manager", + 'lang_tab_search':"Search", + 'lang_input_url':"Address:", + 'lang_input_size':"Size:", + 'lang_input_width':"Width", + 'lang_input_height':"Height", + 'lang_input_border':"Border:", + 'lang_input_vhspace':"Margins:", + 'lang_input_title':"Title:", + 'lang_input_align':'Image Float Style:', + 'lang_imgLoading':"Loading...", + 'lang_start_upload':"Start Upload", + 'lock':{'title':"Lock rate"}, + 'searchType':{'title':"ImageType", 'options':["News", "Wallpaper", "emotions", "photo"]}, + 'searchTxt':{'value':"Enter the search keyword!"}, + 'searchBtn':{'value':"Search"}, + 'searchReset':{'value':"Clear"}, + 'noneAlign':{'title':'None Float'}, + 'leftAlign':{'title':'Left Float'}, + 'rightAlign':{'title':'Right Float'}, + 'centerAlign':{'title':'Center In A Line'} + }, + 'uploadSelectFile':'Select File', + 'uploadAddFile':'Add File', + 'uploadStart':'Start Upload', + 'uploadPause':'Pause Upload', + 'uploadContinue':'Continue Upload', + 'uploadRetry':'Retry Upload', + 'uploadDelete':'Delete', + 'uploadTurnLeft':'Turn Left', + 'uploadTurnRight':'Turn Right', + 'uploadPreview':'Doing Preview', + 'uploadNoPreview':'Can Not Preview', + 'updateStatusReady': 'Selected _ pictures, total _KB.', + 'updateStatusConfirm': '_ uploaded successfully and _ upload failed', + 'updateStatusFinish': 'Total _ pictures (_KB), _ uploaded successfully', + 'updateStatusError': ' and _ upload failed', + 'errorNotSupport': 'WebUploader does not support the browser you are using. Please upgrade your browser or flash player', + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + 'errorExceedSize':'File Size Exceed', + 'errorFileType':'File Type Not Allow', + 'errorInterrupt':'File Upload Interrupted', + 'errorUploadRetry':'Upload Error, Please Retry.', + 'errorHttp':'Http Error', + 'errorServerUpload':'Server Result Error.', + 'remoteLockError':"Cannot Lock the Proportion between width and height", + 'numError':"Please enter the correct Num. e.g 123,400", + 'imageUrlError':"The image format may be wrong!", + 'imageLoadError':"Error,please check the network or URL!", + 'searchRemind':"Enter the search keyword!", + 'searchLoading':"Image is loading,please wait...", + 'searchRetry':" Sorry,can't find the image,please try again!" + }, + 'attachment':{ + 'static':{ + 'lang_tab_upload': 'Upload', + 'lang_tab_online': 'Online', + 'lang_start_upload':"Start upload", + 'lang_drop_remind':"You can drop files here, a single maximum of 300 files" + }, + 'uploadSelectFile':'Select File', + 'uploadAddFile':'Add File', + 'uploadStart':'Start Upload', + 'uploadPause':'Pause Upload', + 'uploadContinue':'Continue Upload', + 'uploadRetry':'Retry Upload', + 'uploadDelete':'Delete', + 'uploadTurnLeft':'Turn Left', + 'uploadTurnRight':'Turn Right', + 'uploadPreview':'Doing Preview', + 'updateStatusReady': 'Selected _ files, total _KB.', + 'updateStatusConfirm': '_ uploaded successfully and _ upload failed', + 'updateStatusFinish': 'Total _ files (_KB), _ uploaded successfully', + 'updateStatusError': ' and _ upload failed', + 'errorNotSupport': 'WebUploader does not support the browser you are using. Please upgrade your browser or flash player', + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + 'errorExceedSize':'File Size Exceed', + 'errorFileType':'File Type Not Allow', + 'errorInterrupt':'File Upload Interrupted', + 'errorUploadRetry':'Upload Error, Please Retry.', + 'errorHttp':'Http Error', + 'errorServerUpload':'Server Result Error.' + }, + + 'insertvideo':{ + 'static':{ + 'lang_tab_insertV':"Video", + 'lang_tab_searchV':"Search", + 'lang_tab_uploadV':"Upload", + 'lang_video_url':" URL ", + 'lang_video_size':"Video Size", + 'lang_videoW':"Width", + 'lang_videoH':"Height", + 'lang_alignment':"Alignment", + 'videoSearchTxt':{'value':"Enter the search keyword!"}, + 'videoType':{'options':["All", "Hot", "Entertainment", "Funny", "Sports", "Science", "variety"]}, + 'videoSearchBtn':{'value':"Search in Baidu"}, + 'videoSearchReset':{'value':"Clear result"}, + + 'lang_input_fileStatus':' No file uploaded!', + 'startUpload':{'style':"background:url(upload.png) no-repeat;"}, + + 'lang_upload_size':"Video Size", + 'lang_upload_width':"Width", + 'lang_upload_height':"Height", + 'lang_upload_alignment':"Alignment", + 'lang_format_advice':"Recommends mp4 format." + }, + 'numError':"Please enter the correct Num. e.g 123,400", + 'floatLeft':"Float left", + 'floatRight':"Float right", + 'default':"Default", + 'block':"Display in block", + 'urlError':"The video url format may be wrong!", + 'loading':"  The video is loading, please wait…", + 'clickToSelect':"Click to select", + 'goToSource':'Visit source video ', + 'noVideo':"    Sorry,can't find the video,please try again!", + + 'browseFiles':'Open files', + 'uploadSuccess':'Upload Successful!', + 'delSuccessFile':'Remove from the success of the queue', + 'delFailSaveFile':'Remove the save failed file', + 'statusPrompt':' file(s) uploaded! ', + 'flashVersionError':'The current Flash version is too low, please update FlashPlayer,then try again!', + 'flashLoadingError':'The Flash failed loading! Please check the path or network state', + 'fileUploadReady':'Wait for uploading...', + 'delUploadQueue':'Remove from the uploading queue ', + 'limitPrompt1':'Can not choose more than single', + 'limitPrompt2':'file(s)!Please choose again!', + 'delFailFile':'Remove failure file', + 'fileSizeLimit':'File size exceeds the limit!', + 'emptyFile':'Can not upload an empty file!', + 'fileTypeError':'File type error!', + 'unknownError':'Unknown error!', + 'fileUploading':'Uploading,please wait...', + 'cancelUpload':'Cancel upload', + 'netError':'Network error', + 'failUpload':'Upload failed', + 'serverIOError':'Server IO error!', + 'noAuthority':'No Permission!', + 'fileNumLimit':'Upload limit to the number', + 'failCheck':'Authentication fails, the upload is skipped!', + 'fileCanceling':'Cancel, please wait...', + 'stopUploading':'Upload has stopped...', + + 'uploadSelectFile':'Select File', + 'uploadAddFile':'Add File', + 'uploadStart':'Start Upload', + 'uploadPause':'Pause Upload', + 'uploadContinue':'Continue Upload', + 'uploadRetry':'Retry Upload', + 'uploadDelete':'Delete', + 'uploadTurnLeft':'Turn Left', + 'uploadTurnRight':'Turn Right', + 'uploadPreview':'Doing Preview', + 'updateStatusReady': 'Selected _ files, total _KB.', + 'updateStatusConfirm': '_ uploaded successfully and _ upload failed', + 'updateStatusFinish': 'Total _ files (_KB), _ uploaded successfully', + 'updateStatusError': ' and _ upload failed', + 'errorNotSupport': 'WebUploader does not support the browser you are using. Please upgrade your browser or flash player', + 'errorLoadConfig': 'Server config not loaded, upload can not work.', + 'errorExceedSize':'File Size Exceed', + 'errorFileType':'File Type Not Allow', + 'errorInterrupt':'File Upload Interrupted', + 'errorUploadRetry':'Upload Error, Please Retry.', + 'errorHttp':'Http Error', + 'errorServerUpload':'Server Result Error.' + }, + 'webapp':{ + 'tip1':"This function provided by Baidu APP,please apply for baidu APPKey webmaster first!", + 'tip2':"And then open the file ueditor.config.js to set it! ", + 'applyFor':"APPLY FOR", + 'anthorApi':"Baidu API" + }, + 'template':{ + 'static':{ + 'lang_template_bkcolor':'Background Color', + 'lang_template_clear' : 'Keep Content', + 'lang_template_select':'Select Template' + }, + 'blank':"Blank", + 'blog':"Blog", + 'resume':"Resume", + 'richText':"Rich Text", + 'scrPapers':"Scientific Papers" + }, + scrawl:{ + 'static':{ + 'lang_input_previousStep':"Previous", + 'lang_input_nextsStep':"Next", + 'lang_input_clear':'Clear', + 'lang_input_addPic':'AddImage', + 'lang_input_ScalePic':'ScaleImage', + 'lang_input_removePic':'RemoveImage', + 'J_imgTxt':{title:'Add background image'} + }, + 'noScarwl':"No paint, a white paper...", + 'scrawlUpLoading':"Image is uploading, please wait...", + 'continueBtn':"Try again", + 'imageError':"Image failed to load!", + 'backgroundUploading':'Image is uploading,please wait...' + }, + 'music':{ + 'static':{ + 'lang_input_tips':"Input singer/song/album, search you interested in music!", + 'J_searchBtn':{value:'Search songs'} + }, + 'emptyTxt':'Not search to the relevant music results, please change a keyword try.', + 'chapter':'Songs', + 'singer':'Singer', + 'special':'Album', + 'listenTest':'Audition' + }, + anchor:{ + 'static':{ + 'lang_input_anchorName':'Anchor Name:' + } + }, + 'charts':{ + 'static':{ + 'lang_data_source':'Data source:', + 'lang_chart_format': 'Chart format:', + 'lang_data_align': 'Align', + 'lang_chart_align_same': 'Consistent with the X-axis Y-axis', + 'lang_chart_align_reverse': 'X-axis Y-axis opposite', + 'lang_chart_title': 'Title', + 'lang_chart_main_title': 'main title:', + 'lang_chart_sub_title': 'sub title:', + 'lang_chart_x_title': 'X-axis title:', + 'lang_chart_y_title': 'Y-axis title:', + 'lang_chart_tip': 'Prompt', + 'lang_cahrt_tip_prefix': 'prefix:', + 'lang_cahrt_tip_description': '仅饼图有效, 当鼠标移动到饼图中相应的块上时,提示框内的文字的前缀', + 'lang_chart_data_unit': 'Unit', + 'lang_chart_data_unit_title': 'unit:', + 'lang_chart_data_unit_description': '显示在每个数据点上的数据的单位, 比如: 温度的单位 ℃', + 'lang_chart_type': 'Chart type:', + 'lang_prev_btn': 'Previous', + 'lang_next_btn': 'Next' + } + }, + emotion:{ + 'static':{ + 'lang_input_choice':'Choice', + 'lang_input_Tuzki':'Tuzki', + 'lang_input_lvdouwa':'LvDouWa', + 'lang_input_BOBO':'BOBO', + 'lang_input_babyCat':'BabyCat', + 'lang_input_bubble':'Bubble', + 'lang_input_youa':'YouA' + } + }, + gmap:{ + 'static':{ + 'lang_input_address':'Address:', + 'lang_input_search':'Search', + 'address':{value:"Beijing"} + }, + searchError:'Unable to locate the address!' + }, + help:{ + 'static':{ + 'lang_input_about':'About', + 'lang_input_shortcuts':'Shortcuts', + 'lang_input_introduction':"UEditor is developed by Baidu Co.ltd. It is lightweight, customizable , focusing on user experience and etc. , UEditor is based on open source BSD license , allowing free use and redistribution.", + 'lang_Txt_shortcuts':'Shortcuts', + 'lang_Txt_func':'Function', + 'lang_Txt_bold':'Bold', + 'lang_Txt_copy':'Copy', + 'lang_Txt_cut':'Cut', + 'lang_Txt_Paste':'Paste', + 'lang_Txt_undo':'Undo', + 'lang_Txt_redo':'Redo', + 'lang_Txt_italic':'Italic', + 'lang_Txt_underline':'Underline', + 'lang_Txt_selectAll':'Select All', + 'lang_Txt_visualEnter':'Submit', + 'lang_Txt_fullscreen':'Fullscreen' + } + }, + insertframe:{ + 'static':{ + 'lang_input_address':'Address:', + 'lang_input_width':'Width:', + 'lang_input_height':'height:', + 'lang_input_isScroll':'Enable scrollbars:', + 'lang_input_frameborder':'Show frame border:', + 'lang_input_alignMode':'Alignment:', + 'align':{title:"Alignment", options:["Default", "Left", "Right", "Center"]} + }, + 'enterAddress':'Please enter an address!' + }, + link:{ + 'static':{ + 'lang_input_text':'Text:', + 'lang_input_url':'URL:', + 'lang_input_title':'Title:', + 'lang_input_target':'open in new window:' + }, + 'validLink':'Supports only effective when a link is selected', + 'httpPrompt':'The hyperlink you enter should start with "http|https|ftp://"!' + }, + map:{ + 'static':{ + lang_city:"City", + lang_address:"Address", + city:{value:"Beijing"}, + lang_search:"Search", + lang_dynamicmap:"Dynamic map" + }, + cityMsg:"Please enter the city name!", + errorMsg:"Can't find the place!" + }, + searchreplace:{ + 'static':{ + lang_tab_search:"Search", + lang_tab_replace:"Replace", + lang_search1:"Search", + lang_search2:"Search", + lang_replace:"Replace", + lang_searchReg:'Support regular expression ,which starts and ends with a slash ,for example "/expression/"', + lang_searchReg1:'Support regular expression ,which starts and ends with a slash ,for example "/expression/"', + lang_case_sensitive1:"Case sense", + lang_case_sensitive2:"Case sense", + nextFindBtn:{value:"Next"}, + preFindBtn:{value:"Preview"}, + nextReplaceBtn:{value:"Next"}, + preReplaceBtn:{value:"Preview"}, + repalceBtn:{value:"Replace"}, + repalceAllBtn:{value:"Replace all"} + }, + getEnd:"Has the search to the bottom!", + getStart:"Has the search to the top!", + countMsg:"Altogether replaced {#count} character(s)!" + }, + snapscreen:{ + 'static':{ + lang_showMsg:"You should install the UEditor screenshots program first!", + lang_download:"Download!", + lang_step1:"Step1:Download the program and then run it", + lang_step2:"Step2:After complete install,try to click the button again" + } + }, + spechars:{ + 'static':{}, + tsfh:"Special", + lmsz:"Roman", + szfh:"Numeral", + rwfh:"Japanese", + xlzm:"The Greek", + ewzm:"Russian", + pyzm:"Phonetic", + yyyb:"English", + zyzf:"Others" + }, + 'edittable':{ + 'static':{ + 'lang_tableStyle':'Table style', + 'lang_insertCaption':'Add table header row', + 'lang_insertTitle':'Add table title row', + 'lang_insertTitleCol':'Add table title col', + 'lang_tableSize':'Automatically adjust table size', + 'lang_autoSizeContent':'Adaptive by form text', + 'lang_orderbycontent':"Table of contents sortable", + 'lang_autoSizePage':'Page width adaptive', + 'lang_example':'Example', + 'lang_borderStyle':'Table Border', + 'lang_color':'Color:' + }, + captionName:'Caption', + titleName:'Title', + cellsName:'text', + errorMsg:'There are merged cells, can not sort.' + }, + 'edittip':{ + 'static':{ + lang_delRow:'Delete entire row', + lang_delCol:'Delete entire col' + } + }, + 'edittd':{ + 'static':{ + lang_tdBkColor:'Background Color:' + } + }, + 'formula':{ + 'static':{ + } + }, + wordimage:{ + 'static':{ + lang_resave:"The re-save step", + uploadBtn:{src:"upload.png", alt:"Upload"}, + clipboard:{style:"background: url(copy.png) -153px -1px no-repeat;"}, + lang_step:" 1. Click top button to copy the url and then open the dialog to paste it. 2. Open after choose photos uploaded process." + }, + fileType:"Image", + flashError:"Flash initialization failed!", + netError:"Network error! Please try again!", + copySuccess:"URL has been copied!", + + 'flashI18n':{ + lang:encodeURI( '{"UploadingState":"totalNum: ${a},uploadComplete: ${b}", "BeforeUpload":"waitingNum: ${a}", "ExceedSize":"Size exceed${a}", "ErrorInPreview":"Preview failed", "DefaultDescription":"Description", "LoadingImage":"Loading..."}' ), + uploadingTF:encodeURI( '{"font":"Arial", "size":12, "color":"0x000", "bold":"true", "italic":"false", "underline":"false"}' ), + imageTF:encodeURI( '{"font":"Arial", "size":11, "color":"red", "bold":"false", "italic":"false", "underline":"false"}' ), + textEncoding:"utf-8", + addImageSkinURL:"addImage.png", + allDeleteBtnUpSkinURL:"allDeleteBtnUpSkin.png", + allDeleteBtnHoverSkinURL:"allDeleteBtnHoverSkin.png", + rotateLeftBtnEnableSkinURL:"rotateLeftEnable.png", + rotateLeftBtnDisableSkinURL:"rotateLeftDisable.png", + rotateRightBtnEnableSkinURL:"rotateRightEnable.png", + rotateRightBtnDisableSkinURL:"rotateRightDisable.png", + deleteBtnEnableSkinURL:"deleteEnable.png", + deleteBtnDisableSkinURL:"deleteDisable.png", + backgroundURL:'', + listBackgroundURL:'', + buttonURL:'button.png' + } + }, + 'autosave': { + 'success':'Local conservation success' + } +}; diff --git a/web/resource/components/ueditor/themes/default/images/filescan.png b/web/resource/components/ueditor/themes/default/images/filescan.png new file mode 100644 index 0000000..1d27158 Binary files /dev/null and b/web/resource/components/ueditor/themes/default/images/filescan.png differ diff --git a/web/resource/components/ueditor/themes/default/images/highlighted.gif b/web/resource/components/ueditor/themes/default/images/highlighted.gif new file mode 100644 index 0000000..9272b49 Binary files /dev/null and b/web/resource/components/ueditor/themes/default/images/highlighted.gif differ diff --git a/web/resource/components/ueditor/third-party/highcharts/highcharts-more.js b/web/resource/components/ueditor/third-party/highcharts/highcharts-more.js new file mode 100644 index 0000000..85af9f5 --- /dev/null +++ b/web/resource/components/ueditor/third-party/highcharts/highcharts-more.js @@ -0,0 +1,50 @@ +/* + Highcharts JS v3.0.6 (2013-10-04) + + (c) 2009-2013 Torstein Hønsi + + License: www.highcharts.com/license +*/ +(function(j,C){function J(a,b,c){this.init.call(this,a,b,c)}function K(a,b,c){a.call(this,b,c);if(this.chart.polar)this.closeSegment=function(a){var c=this.xAxis.center;a.push("L",c[0],c[1])},this.closedStacks=!0}function L(a,b){var c=this.chart,d=this.options.animation,g=this.group,f=this.markerGroup,e=this.xAxis.center,i=c.plotLeft,n=c.plotTop;if(c.polar){if(c.renderer.isSVG)if(d===!0&&(d={}),b){if(c={translateX:e[0]+i,translateY:e[1]+n,scaleX:0.001,scaleY:0.001},g.attr(c),f)f.attrSetters=g.attrSetters, +f.attr(c)}else c={translateX:i,translateY:n,scaleX:1,scaleY:1},g.animate(c,d),f&&f.animate(c,d),this.animate=null}else a.call(this,b)}var P=j.arrayMin,Q=j.arrayMax,s=j.each,F=j.extend,p=j.merge,R=j.map,r=j.pick,v=j.pInt,m=j.getOptions().plotOptions,h=j.seriesTypes,x=j.extendClass,M=j.splat,o=j.wrap,N=j.Axis,u=j.Tick,z=j.Series,q=h.column.prototype,t=Math,D=t.round,A=t.floor,S=t.max,w=function(){};F(J.prototype,{init:function(a,b,c){var d=this,g=d.defaultOptions;d.chart=b;if(b.angular)g.background= +{};d.options=a=p(g,a);(a=a.background)&&s([].concat(M(a)).reverse(),function(a){var b=a.backgroundColor,a=p(d.defaultBackgroundOptions,a);if(b)a.backgroundColor=b;a.color=a.backgroundColor;c.options.plotBands.unshift(a)})},defaultOptions:{center:["50%","50%"],size:"85%",startAngle:0},defaultBackgroundOptions:{shape:"circle",borderWidth:1,borderColor:"silver",backgroundColor:{linearGradient:{x1:0,y1:0,x2:0,y2:1},stops:[[0,"#FFF"],[1,"#DDD"]]},from:Number.MIN_VALUE,innerRadius:0,to:Number.MAX_VALUE, +outerRadius:"105%"}});var G=N.prototype,u=u.prototype,T={getOffset:w,redraw:function(){this.isDirty=!1},render:function(){this.isDirty=!1},setScale:w,setCategories:w,setTitle:w},O={isRadial:!0,defaultRadialGaugeOptions:{labels:{align:"center",x:0,y:null},minorGridLineWidth:0,minorTickInterval:"auto",minorTickLength:10,minorTickPosition:"inside",minorTickWidth:1,plotBands:[],tickLength:10,tickPosition:"inside",tickWidth:2,title:{rotation:0},zIndex:2},defaultRadialXOptions:{gridLineWidth:1,labels:{align:null, +distance:15,x:0,y:null},maxPadding:0,minPadding:0,plotBands:[],showLastLabel:!1,tickLength:0},defaultRadialYOptions:{gridLineInterpolation:"circle",labels:{align:"right",x:-3,y:-2},plotBands:[],showLastLabel:!1,title:{x:4,text:null,rotation:90}},setOptions:function(a){this.options=p(this.defaultOptions,this.defaultRadialOptions,a)},getOffset:function(){G.getOffset.call(this);this.chart.axisOffset[this.side]=0},getLinePath:function(a,b){var c=this.center,b=r(b,c[2]/2-this.offset);return this.chart.renderer.symbols.arc(this.left+ +c[0],this.top+c[1],b,b,{start:this.startAngleRad,end:this.endAngleRad,open:!0,innerR:0})},setAxisTranslation:function(){G.setAxisTranslation.call(this);if(this.center&&(this.transA=this.isCircular?(this.endAngleRad-this.startAngleRad)/(this.max-this.min||1):this.center[2]/2/(this.max-this.min||1),this.isXAxis))this.minPixelPadding=this.transA*this.minPointOffset+(this.reversed?(this.endAngleRad-this.startAngleRad)/4:0)},beforeSetTickPositions:function(){this.autoConnect&&(this.max+=this.categories&& +1||this.pointRange||this.closestPointRange||0)},setAxisSize:function(){G.setAxisSize.call(this);if(this.isRadial)this.center=this.pane.center=h.pie.prototype.getCenter.call(this.pane),this.len=this.width=this.height=this.isCircular?this.center[2]*(this.endAngleRad-this.startAngleRad)/2:this.center[2]/2},getPosition:function(a,b){if(!this.isCircular)b=this.translate(a),a=this.min;return this.postTranslate(this.translate(a),r(b,this.center[2]/2)-this.offset)},postTranslate:function(a,b){var c=this.chart, +d=this.center,a=this.startAngleRad+a;return{x:c.plotLeft+d[0]+Math.cos(a)*b,y:c.plotTop+d[1]+Math.sin(a)*b}},getPlotBandPath:function(a,b,c){var d=this.center,g=this.startAngleRad,f=d[2]/2,e=[r(c.outerRadius,"100%"),c.innerRadius,r(c.thickness,10)],i=/%$/,n,l=this.isCircular;this.options.gridLineInterpolation==="polygon"?d=this.getPlotLinePath(a).concat(this.getPlotLinePath(b,!0)):(l||(e[0]=this.translate(a),e[1]=this.translate(b)),e=R(e,function(a){i.test(a)&&(a=v(a,10)*f/100);return a}),c.shape=== +"circle"||!l?(a=-Math.PI/2,b=Math.PI*1.5,n=!0):(a=g+this.translate(a),b=g+this.translate(b)),d=this.chart.renderer.symbols.arc(this.left+d[0],this.top+d[1],e[0],e[0],{start:a,end:b,innerR:r(e[1],e[0]-e[2]),open:n}));return d},getPlotLinePath:function(a,b){var c=this.center,d=this.chart,g=this.getPosition(a),f,e,i;this.isCircular?i=["M",c[0]+d.plotLeft,c[1]+d.plotTop,"L",g.x,g.y]:this.options.gridLineInterpolation==="circle"?(a=this.translate(a))&&(i=this.getLinePath(0,a)):(f=d.xAxis[0],i=[],a=this.translate(a), +c=f.tickPositions,f.autoConnect&&(c=c.concat([c[0]])),b&&(c=[].concat(c).reverse()),s(c,function(c,b){e=f.getPosition(c,a);i.push(b?"L":"M",e.x,e.y)}));return i},getTitlePosition:function(){var a=this.center,b=this.chart,c=this.options.title;return{x:b.plotLeft+a[0]+(c.x||0),y:b.plotTop+a[1]-{high:0.5,middle:0.25,low:0}[c.align]*a[2]+(c.y||0)}}};o(G,"init",function(a,b,c){var k;var d=b.angular,g=b.polar,f=c.isX,e=d&&f,i,n;n=b.options;var l=c.pane||0;if(d){if(F(this,e?T:O),i=!f)this.defaultRadialOptions= +this.defaultRadialGaugeOptions}else if(g)F(this,O),this.defaultRadialOptions=(i=f)?this.defaultRadialXOptions:p(this.defaultYAxisOptions,this.defaultRadialYOptions);a.call(this,b,c);if(!e&&(d||g)){a=this.options;if(!b.panes)b.panes=[];this.pane=(k=b.panes[l]=b.panes[l]||new J(M(n.pane)[l],b,this),l=k);l=l.options;b.inverted=!1;n.chart.zoomType=null;this.startAngleRad=b=(l.startAngle-90)*Math.PI/180;this.endAngleRad=n=(r(l.endAngle,l.startAngle+360)-90)*Math.PI/180;this.offset=a.offset||0;if((this.isCircular= +i)&&c.max===C&&n-b===2*Math.PI)this.autoConnect=!0}});o(u,"getPosition",function(a,b,c,d,g){var f=this.axis;return f.getPosition?f.getPosition(c):a.call(this,b,c,d,g)});o(u,"getLabelPosition",function(a,b,c,d,g,f,e,i,n){var l=this.axis,k=f.y,h=f.align,j=(l.translate(this.pos)+l.startAngleRad+Math.PI/2)/Math.PI*180%360;l.isRadial?(a=l.getPosition(this.pos,l.center[2]/2+r(f.distance,-25)),f.rotation==="auto"?d.attr({rotation:j}):k===null&&(k=v(d.styles.lineHeight)*0.9-d.getBBox().height/2),h===null&& +(h=l.isCircular?j>20&&j<160?"left":j>200&&j<340?"right":"center":"center",d.attr({align:h})),a.x+=f.x,a.y+=k):a=a.call(this,b,c,d,g,f,e,i,n);return a});o(u,"getMarkPath",function(a,b,c,d,g,f,e){var i=this.axis;i.isRadial?(a=i.getPosition(this.pos,i.center[2]/2+d),b=["M",b,c,"L",a.x,a.y]):b=a.call(this,b,c,d,g,f,e);return b});m.arearange=p(m.area,{lineWidth:1,marker:null,threshold:null,tooltip:{pointFormat:'{series.name}: {point.low} - {point.high}
'}, +trackByArea:!0,dataLabels:{verticalAlign:null,xLow:0,xHigh:0,yLow:0,yHigh:0}});h.arearange=j.extendClass(h.area,{type:"arearange",pointArrayMap:["low","high"],toYData:function(a){return[a.low,a.high]},pointValKey:"low",getSegments:function(){var a=this;s(a.points,function(b){if(!a.options.connectNulls&&(b.low===null||b.high===null))b.y=null;else if(b.low===null&&b.high!==null)b.y=b.high});z.prototype.getSegments.call(this)},translate:function(){var a=this.yAxis;h.area.prototype.translate.apply(this); +s(this.points,function(b){var c=b.low,d=b.high,g=b.plotY;d===null&&c===null?b.y=null:c===null?(b.plotLow=b.plotY=null,b.plotHigh=a.translate(d,0,1,0,1)):d===null?(b.plotLow=g,b.plotHigh=null):(b.plotLow=g,b.plotHigh=a.translate(d,0,1,0,1))})},getSegmentPath:function(a){var b,c=[],d=a.length,g=z.prototype.getSegmentPath,f,e;e=this.options;var i=e.step;for(b=HighchartsAdapter.grep(a,function(a){return a.plotLow!==null});d--;)f=a[d],f.plotHigh!==null&&c.push({plotX:f.plotX,plotY:f.plotHigh});a=g.call(this, +b);if(i)i===!0&&(i="left"),e.step={left:"right",center:"center",right:"left"}[i];c=g.call(this,c);e.step=i;e=[].concat(a,c);c[0]="L";this.areaPath=this.areaPath.concat(a,c);return e},drawDataLabels:function(){var a=this.data,b=a.length,c,d=[],g=z.prototype,f=this.options.dataLabels,e,i=this.chart.inverted;if(f.enabled||this._hasPointLabels){for(c=b;c--;)e=a[c],e.y=e.high,e.plotY=e.plotHigh,d[c]=e.dataLabel,e.dataLabel=e.dataLabelUpper,e.below=!1,i?(f.align="left",f.x=f.xHigh):f.y=f.yHigh;g.drawDataLabels.apply(this, +arguments);for(c=b;c--;)e=a[c],e.dataLabelUpper=e.dataLabel,e.dataLabel=d[c],e.y=e.low,e.plotY=e.plotLow,e.below=!0,i?(f.align="right",f.x=f.xLow):f.y=f.yLow;g.drawDataLabels.apply(this,arguments)}},alignDataLabel:h.column.prototype.alignDataLabel,getSymbol:h.column.prototype.getSymbol,drawPoints:w});m.areasplinerange=p(m.arearange);h.areasplinerange=x(h.arearange,{type:"areasplinerange",getPointSpline:h.spline.prototype.getPointSpline});m.columnrange=p(m.column,m.arearange,{lineWidth:1,pointRange:null}); +h.columnrange=x(h.arearange,{type:"columnrange",translate:function(){var a=this,b=a.yAxis,c;q.translate.apply(a);s(a.points,function(d){var g=d.shapeArgs,f=a.options.minPointLength,e;d.plotHigh=c=b.translate(d.high,0,1,0,1);d.plotLow=d.plotY;e=c;d=d.plotY-c;d{series.name}
Maximum: {point.high}
Upper quartile: {point.q3}
Median: {point.median}
Lower quartile: {point.q1}
Minimum: {point.low}
'},whiskerLength:"50%",whiskerWidth:2});h.boxplot=x(h.column,{type:"boxplot",pointArrayMap:["low","q1","median","q3","high"], +toYData:function(a){return[a.low,a.q1,a.median,a.q3,a.high]},pointValKey:"high",pointAttrToOptions:{fill:"fillColor",stroke:"color","stroke-width":"lineWidth"},drawDataLabels:w,translate:function(){var a=this.yAxis,b=this.pointArrayMap;h.column.prototype.translate.apply(this);s(this.points,function(c){s(b,function(b){c[b]!==null&&(c[b+"Plot"]=a.translate(c[b],0,1,0,1))})})},drawPoints:function(){var a=this,b=a.points,c=a.options,d=a.chart.renderer,g,f,e,i,n,l,k,h,j,m,o,H,p,E,I,q,w,t,v,u,z,y,x=a.doQuartiles!== +!1,B=parseInt(a.options.whiskerLength,10)/100;s(b,function(b){j=b.graphic;z=b.shapeArgs;o={};E={};q={};y=b.color||a.color;if(b.plotY!==C)if(g=b.pointAttr[b.selected?"selected":""],w=z.width,t=A(z.x),v=t+w,u=D(w/2),f=A(x?b.q1Plot:b.lowPlot),e=A(x?b.q3Plot:b.lowPlot),i=A(b.highPlot),n=A(b.lowPlot),o.stroke=b.stemColor||c.stemColor||y,o["stroke-width"]=r(b.stemWidth,c.stemWidth,c.lineWidth),o.dashstyle=b.stemDashStyle||c.stemDashStyle,E.stroke=b.whiskerColor||c.whiskerColor||y,E["stroke-width"]=r(b.whiskerWidth, +c.whiskerWidth,c.lineWidth),q.stroke=b.medianColor||c.medianColor||y,q["stroke-width"]=r(b.medianWidth,c.medianWidth,c.lineWidth),k=o["stroke-width"]%2/2,h=t+u+k,m=["M",h,e,"L",h,i,"M",h,f,"L",h,n,"z"],x&&(k=g["stroke-width"]%2/2,h=A(h)+k,f=A(f)+k,e=A(e)+k,t+=k,v+=k,H=["M",t,e,"L",t,f,"L",v,f,"L",v,e,"L",t,e,"z"]),B&&(k=E["stroke-width"]%2/2,i+=k,n+=k,p=["M",h-u*B,i,"L",h+u*B,i,"M",h-u*B,n,"L",h+u*B,n]),k=q["stroke-width"]%2/2,l=D(b.medianPlot)+k,I=["M",t,l,"L",v,l,"z"],j)b.stem.animate({d:m}),B&& +b.whiskers.animate({d:p}),x&&b.box.animate({d:H}),b.medianShape.animate({d:I});else{b.graphic=j=d.g().add(a.group);b.stem=d.path(m).attr(o).add(j);if(B)b.whiskers=d.path(p).attr(E).add(j);if(x)b.box=d.path(H).attr(g).add(j);b.medianShape=d.path(I).attr(q).add(j)}})}});m.errorbar=p(m.boxplot,{color:"#000000",grouping:!1,linkedTo:":previous",tooltip:{pointFormat:m.arearange.tooltip.pointFormat},whiskerWidth:null});h.errorbar=x(h.boxplot,{type:"errorbar",pointArrayMap:["low","high"],toYData:function(a){return[a.low, +a.high]},pointValKey:"high",doQuartiles:!1,getColumnMetrics:function(){return this.linkedParent&&this.linkedParent.columnMetrics||h.column.prototype.getColumnMetrics.call(this)}});m.waterfall=p(m.column,{lineWidth:1,lineColor:"#333",dashStyle:"dot",borderColor:"#333"});h.waterfall=x(h.column,{type:"waterfall",upColorProp:"fill",pointArrayMap:["low","y"],pointValKey:"y",init:function(a,b){b.stacking=!0;h.column.prototype.init.call(this,a,b)},translate:function(){var a=this.options,b=this.yAxis,c,d, +g,f,e,i,n,l,k;c=a.threshold;a=a.borderWidth%2/2;h.column.prototype.translate.apply(this);l=c;g=this.points;for(d=0,c=g.length;d0&&!a.color)a.pointAttr=d,a.color=c})},getGraphPath:function(){var a=this.data,b=a.length,c=D(this.options.lineWidth+this.options.borderWidth)%2/2,d=[],g,f,e;for(e=1;e0?(i[f]-a)/(b-a):0.5,h.push(t.ceil(c+e*(d-c))/2);this.radii=h},animate:function(a){var b=this.options.animation;if(!a)s(this.points,function(a){var d=a.graphic,a=a.shapeArgs;d&&a&&(d.attr("r",1),d.animate({r:a.r},b))}),this.animate=null},translate:function(){var a,b=this.data,c,d,g=this.radii;h.scatter.prototype.translate.call(this);for(a=b.length;a--;)c=b[a],d=g?g[a]:0,c.negative=c.z<(this.options.zThreshold||0),d>=this.minPxSize/2?(c.shapeType= +"circle",c.shapeArgs={x:c.plotX,y:c.plotY,r:d},c.dlBox={x:c.plotX-d,y:c.plotY-d,width:2*d,height:2*d}):c.shapeArgs=c.plotY=c.dlBox=C},drawLegendSymbol:function(a,b){var c=v(a.itemStyle.fontSize)/2;b.legendSymbol=this.chart.renderer.circle(c,a.baseline-c,c).attr({zIndex:3}).add(b.legendGroup);b.legendSymbol.isMarker=!0},drawPoints:h.column.prototype.drawPoints,alignDataLabel:h.column.prototype.alignDataLabel});N.prototype.beforePadding=function(){var a=this,b=this.len,c=this.chart,d=0,g=b,f=this.isXAxis, +e=f?"xData":"yData",i=this.min,h={},j=t.min(c.plotWidth,c.plotHeight),k=Number.MAX_VALUE,m=-Number.MAX_VALUE,o=this.max-i,p=b/o,q=[];this.tickPositions&&(s(this.series,function(b){var c=b.options;if(b.type==="bubble"&&b.visible&&(a.allowZoomOutside=!0,q.push(b),f))s(["minSize","maxSize"],function(a){var b=c[a],d=/%$/.test(b),b=v(b);h[a]=d?j*b/100:b}),b.minPxSize=h.minSize,b=b.zData,b.length&&(k=t.min(k,t.max(P(b),c.displayNegative===!1?c.zThreshold:-Number.MAX_VALUE)),m=t.max(m,Q(b)))}),s(q,function(a){var b= +a[e],c=b.length,j;f&&a.getRadii(k,m,h.minSize,h.maxSize);if(o>0)for(;c--;)j=a.radii[c],d=Math.min((b[c]-i)*p-j,d),g=Math.max((b[c]-i)*p+j,g)}),q.length&&o>0&&r(this.options.min,this.userMin)===C&&r(this.options.max,this.userMax)===C&&(g-=b,p*=(b+d-g)/b,this.min+=d/p,this.max+=g/p))};var y=z.prototype,m=j.Pointer.prototype;y.toXY=function(a){var b,c=this.chart;b=a.plotX;var d=a.plotY;a.rectPlotX=b;a.rectPlotY=d;a.clientX=(b/Math.PI*180+this.xAxis.pane.options.startAngle)%360;b=this.xAxis.postTranslate(a.plotX, +this.yAxis.len-d);a.plotX=a.polarPlotX=b.x-c.plotLeft;a.plotY=a.polarPlotY=b.y-c.plotTop};y.orderTooltipPoints=function(a){if(this.chart.polar&&(a.sort(function(a,c){return a.clientX-c.clientX}),a[0]))a[0].wrappedClientX=a[0].clientX+360,a.push(a[0])};o(h.area.prototype,"init",K);o(h.areaspline.prototype,"init",K);o(h.spline.prototype,"getPointSpline",function(a,b,c,d){var g,f,e,i,h,j,k;if(this.chart.polar){g=c.plotX;f=c.plotY;a=b[d-1];e=b[d+1];this.connectEnds&&(a||(a=b[b.length-2]),e||(e=b[1])); +if(a&&e)i=a.plotX,h=a.plotY,b=e.plotX,j=e.plotY,i=(1.5*g+i)/2.5,h=(1.5*f+h)/2.5,e=(1.5*g+b)/2.5,k=(1.5*f+j)/2.5,b=Math.sqrt(Math.pow(i-g,2)+Math.pow(h-f,2)),j=Math.sqrt(Math.pow(e-g,2)+Math.pow(k-f,2)),i=Math.atan2(h-f,i-g),h=Math.atan2(k-f,e-g),k=Math.PI/2+(i+h)/2,Math.abs(i-k)>Math.PI/2&&(k-=Math.PI),i=g+Math.cos(k)*b,h=f+Math.sin(k)*b,e=g+Math.cos(Math.PI+k)*j,k=f+Math.sin(Math.PI+k)*j,c.rightContX=e,c.rightContY=k;d?(c=["C",a.rightContX||a.plotX,a.rightContY||a.plotY,i||g,h||f,g,f],a.rightContX= +a.rightContY=null):c=["M",g,f]}else c=a.call(this,b,c,d);return c});o(y,"translate",function(a){a.call(this);if(this.chart.polar&&!this.preventPostTranslate)for(var a=this.points,b=a.length;b--;)this.toXY(a[b])});o(y,"getSegmentPath",function(a,b){var c=this.points;if(this.chart.polar&&this.options.connectEnds!==!1&&b[b.length-1]===c[c.length-1]&&c[0].y!==null)this.connectEnds=!0,b=[].concat(b,[c[0]]);return a.call(this,b)});o(y,"animate",L);o(q,"animate",L);o(y,"setTooltipPoints",function(a,b){this.chart.polar&& +F(this.xAxis,{tooltipLen:360});return a.call(this,b)});o(q,"translate",function(a){var b=this.xAxis,c=this.yAxis.len,d=b.center,g=b.startAngleRad,f=this.chart.renderer,e,h;this.preventPostTranslate=!0;a.call(this);if(b.isRadial){b=this.points;for(h=b.length;h--;)e=b[h],a=e.barX+g,e.shapeType="path",e.shapeArgs={d:f.symbols.arc(d[0],d[1],c-e.plotY,null,{start:a,end:a+e.pointWidth,innerR:c-r(e.yBottom,c)})},this.toXY(e)}});o(q,"alignDataLabel",function(a,b,c,d,g,f){if(this.chart.polar){a=b.rectPlotX/ +Math.PI*180;if(d.align===null)d.align=a>20&&a<160?"left":a>200&&a<340?"right":"center";if(d.verticalAlign===null)d.verticalAlign=a<45||a>315?"bottom":a>135&&a<225?"top":"middle";y.alignDataLabel.call(this,b,c,d,g,f)}else a.call(this,b,c,d,g,f)});o(m,"getIndex",function(a,b){var c,d=this.chart,g;d.polar?(g=d.xAxis[0].center,c=b.chartX-g[0]-d.plotLeft,d=b.chartY-g[1]-d.plotTop,c=180-Math.round(Math.atan2(c,d)/Math.PI*180)):c=a.call(this,b);return c});o(m,"getCoordinates",function(a,b){var c=this.chart, +d={xAxis:[],yAxis:[]};c.polar?s(c.axes,function(a){var f=a.isXAxis,e=a.center,h=b.chartX-e[0]-c.plotLeft,e=b.chartY-e[1]-c.plotTop;d[f?"xAxis":"yAxis"].push({axis:a,value:a.translate(f?Math.PI-Math.atan2(h,e):Math.sqrt(Math.pow(h,2)+Math.pow(e,2)),!0)})}):d=a.call(this,b);return d})})(Highcharts); diff --git a/web/resource/components/ueditor/third-party/highcharts/highcharts-more.src.js b/web/resource/components/ueditor/third-party/highcharts/highcharts-more.src.js new file mode 100644 index 0000000..39d4941 --- /dev/null +++ b/web/resource/components/ueditor/third-party/highcharts/highcharts-more.src.js @@ -0,0 +1,2430 @@ +// ==ClosureCompiler== +// @compilation_level SIMPLE_OPTIMIZATIONS + +/** + * @license Highcharts JS v3.0.6 (2013-10-04) + * + * (c) 2009-2013 Torstein Hønsi + * + * License: www.highcharts.com/license + */ + +// JSLint options: +/*global Highcharts, HighchartsAdapter, document, window, navigator, setInterval, clearInterval, clearTimeout, setTimeout, location, jQuery, $, console */ + +(function (Highcharts, UNDEFINED) { +var arrayMin = Highcharts.arrayMin, + arrayMax = Highcharts.arrayMax, + each = Highcharts.each, + extend = Highcharts.extend, + merge = Highcharts.merge, + map = Highcharts.map, + pick = Highcharts.pick, + pInt = Highcharts.pInt, + defaultPlotOptions = Highcharts.getOptions().plotOptions, + seriesTypes = Highcharts.seriesTypes, + extendClass = Highcharts.extendClass, + splat = Highcharts.splat, + wrap = Highcharts.wrap, + Axis = Highcharts.Axis, + Tick = Highcharts.Tick, + Series = Highcharts.Series, + colProto = seriesTypes.column.prototype, + math = Math, + mathRound = math.round, + mathFloor = math.floor, + mathMax = math.max, + noop = function () {};/** + * The Pane object allows options that are common to a set of X and Y axes. + * + * In the future, this can be extended to basic Highcharts and Highstock. + */ +function Pane(options, chart, firstAxis) { + this.init.call(this, options, chart, firstAxis); +} + +// Extend the Pane prototype +extend(Pane.prototype, { + + /** + * Initiate the Pane object + */ + init: function (options, chart, firstAxis) { + var pane = this, + backgroundOption, + defaultOptions = pane.defaultOptions; + + pane.chart = chart; + + // Set options + if (chart.angular) { // gauges + defaultOptions.background = {}; // gets extended by this.defaultBackgroundOptions + } + pane.options = options = merge(defaultOptions, options); + + backgroundOption = options.background; + + // To avoid having weighty logic to place, update and remove the backgrounds, + // push them to the first axis' plot bands and borrow the existing logic there. + if (backgroundOption) { + each([].concat(splat(backgroundOption)).reverse(), function (config) { + var backgroundColor = config.backgroundColor; // if defined, replace the old one (specific for gradients) + config = merge(pane.defaultBackgroundOptions, config); + if (backgroundColor) { + config.backgroundColor = backgroundColor; + } + config.color = config.backgroundColor; // due to naming in plotBands + firstAxis.options.plotBands.unshift(config); + }); + } + }, + + /** + * The default options object + */ + defaultOptions: { + // background: {conditional}, + center: ['50%', '50%'], + size: '85%', + startAngle: 0 + //endAngle: startAngle + 360 + }, + + /** + * The default background options + */ + defaultBackgroundOptions: { + shape: 'circle', + borderWidth: 1, + borderColor: 'silver', + backgroundColor: { + linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, + stops: [ + [0, '#FFF'], + [1, '#DDD'] + ] + }, + from: Number.MIN_VALUE, // corrected to axis min + innerRadius: 0, + to: Number.MAX_VALUE, // corrected to axis max + outerRadius: '105%' + } + +}); +var axisProto = Axis.prototype, + tickProto = Tick.prototype; + +/** + * Augmented methods for the x axis in order to hide it completely, used for the X axis in gauges + */ +var hiddenAxisMixin = { + getOffset: noop, + redraw: function () { + this.isDirty = false; // prevent setting Y axis dirty + }, + render: function () { + this.isDirty = false; // prevent setting Y axis dirty + }, + setScale: noop, + setCategories: noop, + setTitle: noop +}; + +/** + * Augmented methods for the value axis + */ +/*jslint unparam: true*/ +var radialAxisMixin = { + isRadial: true, + + /** + * The default options extend defaultYAxisOptions + */ + defaultRadialGaugeOptions: { + labels: { + align: 'center', + x: 0, + y: null // auto + }, + minorGridLineWidth: 0, + minorTickInterval: 'auto', + minorTickLength: 10, + minorTickPosition: 'inside', + minorTickWidth: 1, + plotBands: [], + tickLength: 10, + tickPosition: 'inside', + tickWidth: 2, + title: { + rotation: 0 + }, + zIndex: 2 // behind dials, points in the series group + }, + + // Circular axis around the perimeter of a polar chart + defaultRadialXOptions: { + gridLineWidth: 1, // spokes + labels: { + align: null, // auto + distance: 15, + x: 0, + y: null // auto + }, + maxPadding: 0, + minPadding: 0, + plotBands: [], + showLastLabel: false, + tickLength: 0 + }, + + // Radial axis, like a spoke in a polar chart + defaultRadialYOptions: { + gridLineInterpolation: 'circle', + labels: { + align: 'right', + x: -3, + y: -2 + }, + plotBands: [], + showLastLabel: false, + title: { + x: 4, + text: null, + rotation: 90 + } + }, + + /** + * Merge and set options + */ + setOptions: function (userOptions) { + + this.options = merge( + this.defaultOptions, + this.defaultRadialOptions, + userOptions + ); + + }, + + /** + * Wrap the getOffset method to return zero offset for title or labels in a radial + * axis + */ + getOffset: function () { + // Call the Axis prototype method (the method we're in now is on the instance) + axisProto.getOffset.call(this); + + // Title or label offsets are not counted + this.chart.axisOffset[this.side] = 0; + }, + + + /** + * Get the path for the axis line. This method is also referenced in the getPlotLinePath + * method. + */ + getLinePath: function (lineWidth, radius) { + var center = this.center; + radius = pick(radius, center[2] / 2 - this.offset); + + return this.chart.renderer.symbols.arc( + this.left + center[0], + this.top + center[1], + radius, + radius, + { + start: this.startAngleRad, + end: this.endAngleRad, + open: true, + innerR: 0 + } + ); + }, + + /** + * Override setAxisTranslation by setting the translation to the difference + * in rotation. This allows the translate method to return angle for + * any given value. + */ + setAxisTranslation: function () { + + // Call uber method + axisProto.setAxisTranslation.call(this); + + // Set transA and minPixelPadding + if (this.center) { // it's not defined the first time + if (this.isCircular) { + + this.transA = (this.endAngleRad - this.startAngleRad) / + ((this.max - this.min) || 1); + + + } else { + this.transA = (this.center[2] / 2) / ((this.max - this.min) || 1); + } + + if (this.isXAxis) { + this.minPixelPadding = this.transA * this.minPointOffset + + (this.reversed ? (this.endAngleRad - this.startAngleRad) / 4 : 0); // ??? + } + } + }, + + /** + * In case of auto connect, add one closestPointRange to the max value right before + * tickPositions are computed, so that ticks will extend passed the real max. + */ + beforeSetTickPositions: function () { + if (this.autoConnect) { + this.max += (this.categories && 1) || this.pointRange || this.closestPointRange || 0; // #1197, #2260 + } + }, + + /** + * Override the setAxisSize method to use the arc's circumference as length. This + * allows tickPixelInterval to apply to pixel lengths along the perimeter + */ + setAxisSize: function () { + + axisProto.setAxisSize.call(this); + + if (this.isRadial) { + + // Set the center array + this.center = this.pane.center = seriesTypes.pie.prototype.getCenter.call(this.pane); + + this.len = this.width = this.height = this.isCircular ? + this.center[2] * (this.endAngleRad - this.startAngleRad) / 2 : + this.center[2] / 2; + } + }, + + /** + * Returns the x, y coordinate of a point given by a value and a pixel distance + * from center + */ + getPosition: function (value, length) { + if (!this.isCircular) { + length = this.translate(value); + value = this.min; + } + + return this.postTranslate( + this.translate(value), + pick(length, this.center[2] / 2) - this.offset + ); + }, + + /** + * Translate from intermediate plotX (angle), plotY (axis.len - radius) to final chart coordinates. + */ + postTranslate: function (angle, radius) { + + var chart = this.chart, + center = this.center; + + angle = this.startAngleRad + angle; + + return { + x: chart.plotLeft + center[0] + Math.cos(angle) * radius, + y: chart.plotTop + center[1] + Math.sin(angle) * radius + }; + + }, + + /** + * Find the path for plot bands along the radial axis + */ + getPlotBandPath: function (from, to, options) { + var center = this.center, + startAngleRad = this.startAngleRad, + fullRadius = center[2] / 2, + radii = [ + pick(options.outerRadius, '100%'), + options.innerRadius, + pick(options.thickness, 10) + ], + percentRegex = /%$/, + start, + end, + open, + isCircular = this.isCircular, // X axis in a polar chart + ret; + + // Polygonal plot bands + if (this.options.gridLineInterpolation === 'polygon') { + ret = this.getPlotLinePath(from).concat(this.getPlotLinePath(to, true)); + + // Circular grid bands + } else { + + // Plot bands on Y axis (radial axis) - inner and outer radius depend on to and from + if (!isCircular) { + radii[0] = this.translate(from); + radii[1] = this.translate(to); + } + + // Convert percentages to pixel values + radii = map(radii, function (radius) { + if (percentRegex.test(radius)) { + radius = (pInt(radius, 10) * fullRadius) / 100; + } + return radius; + }); + + // Handle full circle + if (options.shape === 'circle' || !isCircular) { + start = -Math.PI / 2; + end = Math.PI * 1.5; + open = true; + } else { + start = startAngleRad + this.translate(from); + end = startAngleRad + this.translate(to); + } + + + ret = this.chart.renderer.symbols.arc( + this.left + center[0], + this.top + center[1], + radii[0], + radii[0], + { + start: start, + end: end, + innerR: pick(radii[1], radii[0] - radii[2]), + open: open + } + ); + } + + return ret; + }, + + /** + * Find the path for plot lines perpendicular to the radial axis. + */ + getPlotLinePath: function (value, reverse) { + var axis = this, + center = axis.center, + chart = axis.chart, + end = axis.getPosition(value), + xAxis, + xy, + tickPositions, + ret; + + // Spokes + if (axis.isCircular) { + ret = ['M', center[0] + chart.plotLeft, center[1] + chart.plotTop, 'L', end.x, end.y]; + + // Concentric circles + } else if (axis.options.gridLineInterpolation === 'circle') { + value = axis.translate(value); + if (value) { // a value of 0 is in the center + ret = axis.getLinePath(0, value); + } + // Concentric polygons + } else { + xAxis = chart.xAxis[0]; + ret = []; + value = axis.translate(value); + tickPositions = xAxis.tickPositions; + if (xAxis.autoConnect) { + tickPositions = tickPositions.concat([tickPositions[0]]); + } + // Reverse the positions for concatenation of polygonal plot bands + if (reverse) { + tickPositions = [].concat(tickPositions).reverse(); + } + + each(tickPositions, function (pos, i) { + xy = xAxis.getPosition(pos, value); + ret.push(i ? 'L' : 'M', xy.x, xy.y); + }); + + } + return ret; + }, + + /** + * Find the position for the axis title, by default inside the gauge + */ + getTitlePosition: function () { + var center = this.center, + chart = this.chart, + titleOptions = this.options.title; + + return { + x: chart.plotLeft + center[0] + (titleOptions.x || 0), + y: chart.plotTop + center[1] - ({ high: 0.5, middle: 0.25, low: 0 }[titleOptions.align] * + center[2]) + (titleOptions.y || 0) + }; + } + +}; +/*jslint unparam: false*/ + +/** + * Override axisProto.init to mix in special axis instance functions and function overrides + */ +wrap(axisProto, 'init', function (proceed, chart, userOptions) { + var axis = this, + angular = chart.angular, + polar = chart.polar, + isX = userOptions.isX, + isHidden = angular && isX, + isCircular, + startAngleRad, + endAngleRad, + options, + chartOptions = chart.options, + paneIndex = userOptions.pane || 0, + pane, + paneOptions; + + // Before prototype.init + if (angular) { + extend(this, isHidden ? hiddenAxisMixin : radialAxisMixin); + isCircular = !isX; + if (isCircular) { + this.defaultRadialOptions = this.defaultRadialGaugeOptions; + } + + } else if (polar) { + //extend(this, userOptions.isX ? radialAxisMixin : radialAxisMixin); + extend(this, radialAxisMixin); + isCircular = isX; + this.defaultRadialOptions = isX ? this.defaultRadialXOptions : merge(this.defaultYAxisOptions, this.defaultRadialYOptions); + + } + + // Run prototype.init + proceed.call(this, chart, userOptions); + + if (!isHidden && (angular || polar)) { + options = this.options; + + // Create the pane and set the pane options. + if (!chart.panes) { + chart.panes = []; + } + this.pane = pane = chart.panes[paneIndex] = chart.panes[paneIndex] || new Pane( + splat(chartOptions.pane)[paneIndex], + chart, + axis + ); + paneOptions = pane.options; + + + // Disable certain features on angular and polar axes + chart.inverted = false; + chartOptions.chart.zoomType = null; + + // Start and end angle options are + // given in degrees relative to top, while internal computations are + // in radians relative to right (like SVG). + this.startAngleRad = startAngleRad = (paneOptions.startAngle - 90) * Math.PI / 180; + this.endAngleRad = endAngleRad = (pick(paneOptions.endAngle, paneOptions.startAngle + 360) - 90) * Math.PI / 180; + this.offset = options.offset || 0; + + this.isCircular = isCircular; + + // Automatically connect grid lines? + if (isCircular && userOptions.max === UNDEFINED && endAngleRad - startAngleRad === 2 * Math.PI) { + this.autoConnect = true; + } + } + +}); + +/** + * Add special cases within the Tick class' methods for radial axes. + */ +wrap(tickProto, 'getPosition', function (proceed, horiz, pos, tickmarkOffset, old) { + var axis = this.axis; + + return axis.getPosition ? + axis.getPosition(pos) : + proceed.call(this, horiz, pos, tickmarkOffset, old); +}); + +/** + * Wrap the getLabelPosition function to find the center position of the label + * based on the distance option + */ +wrap(tickProto, 'getLabelPosition', function (proceed, x, y, label, horiz, labelOptions, tickmarkOffset, index, step) { + var axis = this.axis, + optionsY = labelOptions.y, + ret, + align = labelOptions.align, + angle = ((axis.translate(this.pos) + axis.startAngleRad + Math.PI / 2) / Math.PI * 180) % 360; + + if (axis.isRadial) { + ret = axis.getPosition(this.pos, (axis.center[2] / 2) + pick(labelOptions.distance, -25)); + + // Automatically rotated + if (labelOptions.rotation === 'auto') { + label.attr({ + rotation: angle + }); + + // Vertically centered + } else if (optionsY === null) { + optionsY = pInt(label.styles.lineHeight) * 0.9 - label.getBBox().height / 2; + + } + + // Automatic alignment + if (align === null) { + if (axis.isCircular) { + if (angle > 20 && angle < 160) { + align = 'left'; // right hemisphere + } else if (angle > 200 && angle < 340) { + align = 'right'; // left hemisphere + } else { + align = 'center'; // top or bottom + } + } else { + align = 'center'; + } + label.attr({ + align: align + }); + } + + ret.x += labelOptions.x; + ret.y += optionsY; + + } else { + ret = proceed.call(this, x, y, label, horiz, labelOptions, tickmarkOffset, index, step); + } + return ret; +}); + +/** + * Wrap the getMarkPath function to return the path of the radial marker + */ +wrap(tickProto, 'getMarkPath', function (proceed, x, y, tickLength, tickWidth, horiz, renderer) { + var axis = this.axis, + endPoint, + ret; + + if (axis.isRadial) { + endPoint = axis.getPosition(this.pos, axis.center[2] / 2 + tickLength); + ret = [ + 'M', + x, + y, + 'L', + endPoint.x, + endPoint.y + ]; + } else { + ret = proceed.call(this, x, y, tickLength, tickWidth, horiz, renderer); + } + return ret; +});/* + * The AreaRangeSeries class + * + */ + +/** + * Extend the default options with map options + */ +defaultPlotOptions.arearange = merge(defaultPlotOptions.area, { + lineWidth: 1, + marker: null, + threshold: null, + tooltip: { + pointFormat: '{series.name}: {point.low} - {point.high}
' + }, + trackByArea: true, + dataLabels: { + verticalAlign: null, + xLow: 0, + xHigh: 0, + yLow: 0, + yHigh: 0 + } +}); + +/** + * Add the series type + */ +seriesTypes.arearange = Highcharts.extendClass(seriesTypes.area, { + type: 'arearange', + pointArrayMap: ['low', 'high'], + toYData: function (point) { + return [point.low, point.high]; + }, + pointValKey: 'low', + + /** + * Extend getSegments to force null points if the higher value is null. #1703. + */ + getSegments: function () { + var series = this; + + each(series.points, function (point) { + if (!series.options.connectNulls && (point.low === null || point.high === null)) { + point.y = null; + } else if (point.low === null && point.high !== null) { + point.y = point.high; + } + }); + Series.prototype.getSegments.call(this); + }, + + /** + * Translate data points from raw values x and y to plotX and plotY + */ + translate: function () { + var series = this, + yAxis = series.yAxis; + + seriesTypes.area.prototype.translate.apply(series); + + // Set plotLow and plotHigh + each(series.points, function (point) { + + var low = point.low, + high = point.high, + plotY = point.plotY; + + if (high === null && low === null) { + point.y = null; + } else if (low === null) { + point.plotLow = point.plotY = null; + point.plotHigh = yAxis.translate(high, 0, 1, 0, 1); + } else if (high === null) { + point.plotLow = plotY; + point.plotHigh = null; + } else { + point.plotLow = plotY; + point.plotHigh = yAxis.translate(high, 0, 1, 0, 1); + } + }); + }, + + /** + * Extend the line series' getSegmentPath method by applying the segment + * path to both lower and higher values of the range + */ + getSegmentPath: function (segment) { + + var lowSegment, + highSegment = [], + i = segment.length, + baseGetSegmentPath = Series.prototype.getSegmentPath, + point, + linePath, + lowerPath, + options = this.options, + step = options.step, + higherPath; + + // Remove nulls from low segment + lowSegment = HighchartsAdapter.grep(segment, function (point) { + return point.plotLow !== null; + }); + + // Make a segment with plotX and plotY for the top values + while (i--) { + point = segment[i]; + if (point.plotHigh !== null) { + highSegment.push({ + plotX: point.plotX, + plotY: point.plotHigh + }); + } + } + + // Get the paths + lowerPath = baseGetSegmentPath.call(this, lowSegment); + if (step) { + if (step === true) { + step = 'left'; + } + options.step = { left: 'right', center: 'center', right: 'left' }[step]; // swap for reading in getSegmentPath + } + higherPath = baseGetSegmentPath.call(this, highSegment); + options.step = step; + + // Create a line on both top and bottom of the range + linePath = [].concat(lowerPath, higherPath); + + // For the area path, we need to change the 'move' statement into 'lineTo' or 'curveTo' + higherPath[0] = 'L'; // this probably doesn't work for spline + this.areaPath = this.areaPath.concat(lowerPath, higherPath); + + return linePath; + }, + + /** + * Extend the basic drawDataLabels method by running it for both lower and higher + * values. + */ + drawDataLabels: function () { + + var data = this.data, + length = data.length, + i, + originalDataLabels = [], + seriesProto = Series.prototype, + dataLabelOptions = this.options.dataLabels, + point, + inverted = this.chart.inverted; + + if (dataLabelOptions.enabled || this._hasPointLabels) { + + // Step 1: set preliminary values for plotY and dataLabel and draw the upper labels + i = length; + while (i--) { + point = data[i]; + + // Set preliminary values + point.y = point.high; + point.plotY = point.plotHigh; + + // Store original data labels and set preliminary label objects to be picked up + // in the uber method + originalDataLabels[i] = point.dataLabel; + point.dataLabel = point.dataLabelUpper; + + // Set the default offset + point.below = false; + if (inverted) { + dataLabelOptions.align = 'left'; + dataLabelOptions.x = dataLabelOptions.xHigh; + } else { + dataLabelOptions.y = dataLabelOptions.yHigh; + } + } + seriesProto.drawDataLabels.apply(this, arguments); // #1209 + + // Step 2: reorganize and handle data labels for the lower values + i = length; + while (i--) { + point = data[i]; + + // Move the generated labels from step 1, and reassign the original data labels + point.dataLabelUpper = point.dataLabel; + point.dataLabel = originalDataLabels[i]; + + // Reset values + point.y = point.low; + point.plotY = point.plotLow; + + // Set the default offset + point.below = true; + if (inverted) { + dataLabelOptions.align = 'right'; + dataLabelOptions.x = dataLabelOptions.xLow; + } else { + dataLabelOptions.y = dataLabelOptions.yLow; + } + } + seriesProto.drawDataLabels.apply(this, arguments); + } + + }, + + alignDataLabel: seriesTypes.column.prototype.alignDataLabel, + + getSymbol: seriesTypes.column.prototype.getSymbol, + + drawPoints: noop +});/** + * The AreaSplineRangeSeries class + */ + +defaultPlotOptions.areasplinerange = merge(defaultPlotOptions.arearange); + +/** + * AreaSplineRangeSeries object + */ +seriesTypes.areasplinerange = extendClass(seriesTypes.arearange, { + type: 'areasplinerange', + getPointSpline: seriesTypes.spline.prototype.getPointSpline +});/** + * The ColumnRangeSeries class + */ +defaultPlotOptions.columnrange = merge(defaultPlotOptions.column, defaultPlotOptions.arearange, { + lineWidth: 1, + pointRange: null +}); + +/** + * ColumnRangeSeries object + */ +seriesTypes.columnrange = extendClass(seriesTypes.arearange, { + type: 'columnrange', + /** + * Translate data points from raw values x and y to plotX and plotY + */ + translate: function () { + var series = this, + yAxis = series.yAxis, + plotHigh; + + colProto.translate.apply(series); + + // Set plotLow and plotHigh + each(series.points, function (point) { + var shapeArgs = point.shapeArgs, + minPointLength = series.options.minPointLength, + heightDifference, + height, + y; + + point.plotHigh = plotHigh = yAxis.translate(point.high, 0, 1, 0, 1); + point.plotLow = point.plotY; + + // adjust shape + y = plotHigh; + height = point.plotY - plotHigh; + + if (height < minPointLength) { + heightDifference = (minPointLength - height); + height += heightDifference; + y -= heightDifference / 2; + } + shapeArgs.height = height; + shapeArgs.y = y; + }); + }, + trackerGroups: ['group', 'dataLabels'], + drawGraph: noop, + pointAttrToOptions: colProto.pointAttrToOptions, + drawPoints: colProto.drawPoints, + drawTracker: colProto.drawTracker, + animate: colProto.animate, + getColumnMetrics: colProto.getColumnMetrics +}); +/* + * The GaugeSeries class + */ + + + +/** + * Extend the default options + */ +defaultPlotOptions.gauge = merge(defaultPlotOptions.line, { + dataLabels: { + enabled: true, + y: 15, + borderWidth: 1, + borderColor: 'silver', + borderRadius: 3, + style: { + fontWeight: 'bold' + }, + verticalAlign: 'top', + zIndex: 2 + }, + dial: { + // radius: '80%', + // backgroundColor: 'black', + // borderColor: 'silver', + // borderWidth: 0, + // baseWidth: 3, + // topWidth: 1, + // baseLength: '70%' // of radius + // rearLength: '10%' + }, + pivot: { + //radius: 5, + //borderWidth: 0 + //borderColor: 'silver', + //backgroundColor: 'black' + }, + tooltip: { + headerFormat: '' + }, + showInLegend: false +}); + +/** + * Extend the point object + */ +var GaugePoint = Highcharts.extendClass(Highcharts.Point, { + /** + * Don't do any hover colors or anything + */ + setState: function (state) { + this.state = state; + } +}); + + +/** + * Add the series type + */ +var GaugeSeries = { + type: 'gauge', + pointClass: GaugePoint, + + // chart.angular will be set to true when a gauge series is present, and this will + // be used on the axes + angular: true, + drawGraph: noop, + fixedBox: true, + trackerGroups: ['group', 'dataLabels'], + + /** + * Calculate paths etc + */ + translate: function () { + + var series = this, + yAxis = series.yAxis, + options = series.options, + center = yAxis.center; + + series.generatePoints(); + + each(series.points, function (point) { + + var dialOptions = merge(options.dial, point.dial), + radius = (pInt(pick(dialOptions.radius, 80)) * center[2]) / 200, + baseLength = (pInt(pick(dialOptions.baseLength, 70)) * radius) / 100, + rearLength = (pInt(pick(dialOptions.rearLength, 10)) * radius) / 100, + baseWidth = dialOptions.baseWidth || 3, + topWidth = dialOptions.topWidth || 1, + rotation = yAxis.startAngleRad + yAxis.translate(point.y, null, null, null, true); + + // Handle the wrap option + if (options.wrap === false) { + rotation = Math.max(yAxis.startAngleRad, Math.min(yAxis.endAngleRad, rotation)); + } + rotation = rotation * 180 / Math.PI; + + point.shapeType = 'path'; + point.shapeArgs = { + d: dialOptions.path || [ + 'M', + -rearLength, -baseWidth / 2, + 'L', + baseLength, -baseWidth / 2, + radius, -topWidth / 2, + radius, topWidth / 2, + baseLength, baseWidth / 2, + -rearLength, baseWidth / 2, + 'z' + ], + translateX: center[0], + translateY: center[1], + rotation: rotation + }; + + // Positions for data label + point.plotX = center[0]; + point.plotY = center[1]; + }); + }, + + /** + * Draw the points where each point is one needle + */ + drawPoints: function () { + + var series = this, + center = series.yAxis.center, + pivot = series.pivot, + options = series.options, + pivotOptions = options.pivot, + renderer = series.chart.renderer; + + each(series.points, function (point) { + + var graphic = point.graphic, + shapeArgs = point.shapeArgs, + d = shapeArgs.d, + dialOptions = merge(options.dial, point.dial); // #1233 + + if (graphic) { + graphic.animate(shapeArgs); + shapeArgs.d = d; // animate alters it + } else { + point.graphic = renderer[point.shapeType](shapeArgs) + .attr({ + stroke: dialOptions.borderColor || 'none', + 'stroke-width': dialOptions.borderWidth || 0, + fill: dialOptions.backgroundColor || 'black', + rotation: shapeArgs.rotation // required by VML when animation is false + }) + .add(series.group); + } + }); + + // Add or move the pivot + if (pivot) { + pivot.animate({ // #1235 + translateX: center[0], + translateY: center[1] + }); + } else { + series.pivot = renderer.circle(0, 0, pick(pivotOptions.radius, 5)) + .attr({ + 'stroke-width': pivotOptions.borderWidth || 0, + stroke: pivotOptions.borderColor || 'silver', + fill: pivotOptions.backgroundColor || 'black' + }) + .translate(center[0], center[1]) + .add(series.group); + } + }, + + /** + * Animate the arrow up from startAngle + */ + animate: function (init) { + var series = this; + + if (!init) { + each(series.points, function (point) { + var graphic = point.graphic; + + if (graphic) { + // start value + graphic.attr({ + rotation: series.yAxis.startAngleRad * 180 / Math.PI + }); + + // animate + graphic.animate({ + rotation: point.shapeArgs.rotation + }, series.options.animation); + } + }); + + // delete this function to allow it only once + series.animate = null; + } + }, + + render: function () { + this.group = this.plotGroup( + 'group', + 'series', + this.visible ? 'visible' : 'hidden', + this.options.zIndex, + this.chart.seriesGroup + ); + seriesTypes.pie.prototype.render.call(this); + this.group.clip(this.chart.clipRect); + }, + + setData: seriesTypes.pie.prototype.setData, + drawTracker: seriesTypes.column.prototype.drawTracker +}; +seriesTypes.gauge = Highcharts.extendClass(seriesTypes.line, GaugeSeries);/* **************************************************************************** + * Start Box plot series code * + *****************************************************************************/ + +// Set default options +defaultPlotOptions.boxplot = merge(defaultPlotOptions.column, { + fillColor: '#FFFFFF', + lineWidth: 1, + //medianColor: null, + medianWidth: 2, + states: { + hover: { + brightness: -0.3 + } + }, + //stemColor: null, + //stemDashStyle: 'solid' + //stemWidth: null, + threshold: null, + tooltip: { + pointFormat: '{series.name}
' + + 'Maximum: {point.high}
' + + 'Upper quartile: {point.q3}
' + + 'Median: {point.median}
' + + 'Lower quartile: {point.q1}
' + + 'Minimum: {point.low}
' + + }, + //whiskerColor: null, + whiskerLength: '50%', + whiskerWidth: 2 +}); + +// Create the series object +seriesTypes.boxplot = extendClass(seriesTypes.column, { + type: 'boxplot', + pointArrayMap: ['low', 'q1', 'median', 'q3', 'high'], // array point configs are mapped to this + toYData: function (point) { // return a plain array for speedy calculation + return [point.low, point.q1, point.median, point.q3, point.high]; + }, + pointValKey: 'high', // defines the top of the tracker + + /** + * One-to-one mapping from options to SVG attributes + */ + pointAttrToOptions: { // mapping between SVG attributes and the corresponding options + fill: 'fillColor', + stroke: 'color', + 'stroke-width': 'lineWidth' + }, + + /** + * Disable data labels for box plot + */ + drawDataLabels: noop, + + /** + * Translate data points from raw values x and y to plotX and plotY + */ + translate: function () { + var series = this, + yAxis = series.yAxis, + pointArrayMap = series.pointArrayMap; + + seriesTypes.column.prototype.translate.apply(series); + + // do the translation on each point dimension + each(series.points, function (point) { + each(pointArrayMap, function (key) { + if (point[key] !== null) { + point[key + 'Plot'] = yAxis.translate(point[key], 0, 1, 0, 1); + } + }); + }); + }, + + /** + * Draw the data points + */ + drawPoints: function () { + var series = this, //state = series.state, + points = series.points, + options = series.options, + chart = series.chart, + renderer = chart.renderer, + pointAttr, + q1Plot, + q3Plot, + highPlot, + lowPlot, + medianPlot, + crispCorr, + crispX, + graphic, + stemPath, + stemAttr, + boxPath, + whiskersPath, + whiskersAttr, + medianPath, + medianAttr, + width, + left, + right, + halfWidth, + shapeArgs, + color, + doQuartiles = series.doQuartiles !== false, // error bar inherits this series type but doesn't do quartiles + whiskerLength = parseInt(series.options.whiskerLength, 10) / 100; + + + each(points, function (point) { + + graphic = point.graphic; + shapeArgs = point.shapeArgs; // the box + stemAttr = {}; + whiskersAttr = {}; + medianAttr = {}; + color = point.color || series.color; + + if (point.plotY !== UNDEFINED) { + + pointAttr = point.pointAttr[point.selected ? 'selected' : '']; + + // crisp vector coordinates + width = shapeArgs.width; + left = mathFloor(shapeArgs.x); + right = left + width; + halfWidth = mathRound(width / 2); + //crispX = mathRound(left + halfWidth) + crispCorr; + q1Plot = mathFloor(doQuartiles ? point.q1Plot : point.lowPlot);// + crispCorr; + q3Plot = mathFloor(doQuartiles ? point.q3Plot : point.lowPlot);// + crispCorr; + highPlot = mathFloor(point.highPlot);// + crispCorr; + lowPlot = mathFloor(point.lowPlot);// + crispCorr; + + // Stem attributes + stemAttr.stroke = point.stemColor || options.stemColor || color; + stemAttr['stroke-width'] = pick(point.stemWidth, options.stemWidth, options.lineWidth); + stemAttr.dashstyle = point.stemDashStyle || options.stemDashStyle; + + // Whiskers attributes + whiskersAttr.stroke = point.whiskerColor || options.whiskerColor || color; + whiskersAttr['stroke-width'] = pick(point.whiskerWidth, options.whiskerWidth, options.lineWidth); + + // Median attributes + medianAttr.stroke = point.medianColor || options.medianColor || color; + medianAttr['stroke-width'] = pick(point.medianWidth, options.medianWidth, options.lineWidth); + + + // The stem + crispCorr = (stemAttr['stroke-width'] % 2) / 2; + crispX = left + halfWidth + crispCorr; + stemPath = [ + // stem up + 'M', + crispX, q3Plot, + 'L', + crispX, highPlot, + + // stem down + 'M', + crispX, q1Plot, + 'L', + crispX, lowPlot, + 'z' + ]; + + // The box + if (doQuartiles) { + crispCorr = (pointAttr['stroke-width'] % 2) / 2; + crispX = mathFloor(crispX) + crispCorr; + q1Plot = mathFloor(q1Plot) + crispCorr; + q3Plot = mathFloor(q3Plot) + crispCorr; + left += crispCorr; + right += crispCorr; + boxPath = [ + 'M', + left, q3Plot, + 'L', + left, q1Plot, + 'L', + right, q1Plot, + 'L', + right, q3Plot, + 'L', + left, q3Plot, + 'z' + ]; + } + + // The whiskers + if (whiskerLength) { + crispCorr = (whiskersAttr['stroke-width'] % 2) / 2; + highPlot = highPlot + crispCorr; + lowPlot = lowPlot + crispCorr; + whiskersPath = [ + // High whisker + 'M', + crispX - halfWidth * whiskerLength, + highPlot, + 'L', + crispX + halfWidth * whiskerLength, + highPlot, + + // Low whisker + 'M', + crispX - halfWidth * whiskerLength, + lowPlot, + 'L', + crispX + halfWidth * whiskerLength, + lowPlot + ]; + } + + // The median + crispCorr = (medianAttr['stroke-width'] % 2) / 2; + medianPlot = mathRound(point.medianPlot) + crispCorr; + medianPath = [ + 'M', + left, + medianPlot, + 'L', + right, + medianPlot, + 'z' + ]; + + // Create or update the graphics + if (graphic) { // update + + point.stem.animate({ d: stemPath }); + if (whiskerLength) { + point.whiskers.animate({ d: whiskersPath }); + } + if (doQuartiles) { + point.box.animate({ d: boxPath }); + } + point.medianShape.animate({ d: medianPath }); + + } else { // create new + point.graphic = graphic = renderer.g() + .add(series.group); + + point.stem = renderer.path(stemPath) + .attr(stemAttr) + .add(graphic); + + if (whiskerLength) { + point.whiskers = renderer.path(whiskersPath) + .attr(whiskersAttr) + .add(graphic); + } + if (doQuartiles) { + point.box = renderer.path(boxPath) + .attr(pointAttr) + .add(graphic); + } + point.medianShape = renderer.path(medianPath) + .attr(medianAttr) + .add(graphic); + } + } + }); + + } + + +}); + +/* **************************************************************************** + * End Box plot series code * + *****************************************************************************/ +/* **************************************************************************** + * Start error bar series code * + *****************************************************************************/ + +// 1 - set default options +defaultPlotOptions.errorbar = merge(defaultPlotOptions.boxplot, { + color: '#000000', + grouping: false, + linkedTo: ':previous', + tooltip: { + pointFormat: defaultPlotOptions.arearange.tooltip.pointFormat + }, + whiskerWidth: null +}); + +// 2 - Create the series object +seriesTypes.errorbar = extendClass(seriesTypes.boxplot, { + type: 'errorbar', + pointArrayMap: ['low', 'high'], // array point configs are mapped to this + toYData: function (point) { // return a plain array for speedy calculation + return [point.low, point.high]; + }, + pointValKey: 'high', // defines the top of the tracker + doQuartiles: false, + + /** + * Get the width and X offset, either on top of the linked series column + * or standalone + */ + getColumnMetrics: function () { + return (this.linkedParent && this.linkedParent.columnMetrics) || + seriesTypes.column.prototype.getColumnMetrics.call(this); + } +}); + +/* **************************************************************************** + * End error bar series code * + *****************************************************************************/ +/* **************************************************************************** + * Start Waterfall series code * + *****************************************************************************/ + +// 1 - set default options +defaultPlotOptions.waterfall = merge(defaultPlotOptions.column, { + lineWidth: 1, + lineColor: '#333', + dashStyle: 'dot', + borderColor: '#333' +}); + + +// 2 - Create the series object +seriesTypes.waterfall = extendClass(seriesTypes.column, { + type: 'waterfall', + + upColorProp: 'fill', + + pointArrayMap: ['low', 'y'], + + pointValKey: 'y', + + /** + * Init waterfall series, force stacking + */ + init: function (chart, options) { + // force stacking + options.stacking = true; + + seriesTypes.column.prototype.init.call(this, chart, options); + }, + + + /** + * Translate data points from raw values + */ + translate: function () { + var series = this, + options = series.options, + axis = series.yAxis, + len, + i, + points, + point, + shapeArgs, + stack, + y, + previousY, + stackPoint, + threshold = options.threshold, + crispCorr = (options.borderWidth % 2) / 2; + + // run column series translate + seriesTypes.column.prototype.translate.apply(this); + + previousY = threshold; + points = series.points; + + for (i = 0, len = points.length; i < len; i++) { + // cache current point object + point = points[i]; + shapeArgs = point.shapeArgs; + + // get current stack + stack = series.getStack(i); + stackPoint = stack.points[series.index]; + + // override point value for sums + if (isNaN(point.y)) { + point.y = series.yData[i]; + } + + // up points + y = mathMax(previousY, previousY + point.y) + stackPoint[0]; + shapeArgs.y = axis.translate(y, 0, 1); + + + // sum points + if (point.isSum || point.isIntermediateSum) { + shapeArgs.y = axis.translate(stackPoint[1], 0, 1); + shapeArgs.height = axis.translate(stackPoint[0], 0, 1) - shapeArgs.y; + + // if it's not the sum point, update previous stack end position + } else { + previousY += stack.total; + } + + // negative points + if (shapeArgs.height < 0) { + shapeArgs.y += shapeArgs.height; + shapeArgs.height *= -1; + } + + point.plotY = shapeArgs.y = mathRound(shapeArgs.y) - crispCorr; + shapeArgs.height = mathRound(shapeArgs.height); + point.yBottom = shapeArgs.y + shapeArgs.height; + } + }, + + /** + * Call default processData then override yData to reflect waterfall's extremes on yAxis + */ + processData: function (force) { + var series = this, + options = series.options, + yData = series.yData, + points = series.points, + point, + dataLength = yData.length, + threshold = options.threshold || 0, + subSum, + sum, + dataMin, + dataMax, + y, + i; + + sum = subSum = dataMin = dataMax = threshold; + + for (i = 0; i < dataLength; i++) { + y = yData[i]; + point = points && points[i] ? points[i] : {}; + + if (y === "sum" || point.isSum) { + yData[i] = sum; + } else if (y === "intermediateSum" || point.isIntermediateSum) { + yData[i] = subSum; + subSum = threshold; + } else { + sum += y; + subSum += y; + } + dataMin = Math.min(sum, dataMin); + dataMax = Math.max(sum, dataMax); + } + + Series.prototype.processData.call(this, force); + + // Record extremes + series.dataMin = dataMin; + series.dataMax = dataMax; + }, + + /** + * Return y value or string if point is sum + */ + toYData: function (pt) { + if (pt.isSum) { + return "sum"; + } else if (pt.isIntermediateSum) { + return "intermediateSum"; + } + + return pt.y; + }, + + /** + * Postprocess mapping between options and SVG attributes + */ + getAttribs: function () { + seriesTypes.column.prototype.getAttribs.apply(this, arguments); + + var series = this, + options = series.options, + stateOptions = options.states, + upColor = options.upColor || series.color, + hoverColor = Highcharts.Color(upColor).brighten(0.1).get(), + seriesDownPointAttr = merge(series.pointAttr), + upColorProp = series.upColorProp; + + seriesDownPointAttr[''][upColorProp] = upColor; + seriesDownPointAttr.hover[upColorProp] = stateOptions.hover.upColor || hoverColor; + seriesDownPointAttr.select[upColorProp] = stateOptions.select.upColor || upColor; + + each(series.points, function (point) { + if (point.y > 0 && !point.color) { + point.pointAttr = seriesDownPointAttr; + point.color = upColor; + } + }); + }, + + /** + * Draw columns' connector lines + */ + getGraphPath: function () { + + var data = this.data, + length = data.length, + lineWidth = this.options.lineWidth + this.options.borderWidth, + normalizer = mathRound(lineWidth) % 2 / 2, + path = [], + M = 'M', + L = 'L', + prevArgs, + pointArgs, + i, + d; + + for (i = 1; i < length; i++) { + pointArgs = data[i].shapeArgs; + prevArgs = data[i - 1].shapeArgs; + + d = [ + M, + prevArgs.x + prevArgs.width, prevArgs.y + normalizer, + L, + pointArgs.x, prevArgs.y + normalizer + ]; + + if (data[i - 1].y < 0) { + d[2] += prevArgs.height; + d[5] += prevArgs.height; + } + + path = path.concat(d); + } + + return path; + }, + + /** + * Extremes are recorded in processData + */ + getExtremes: noop, + + /** + * Return stack for given index + */ + getStack: function (i) { + var axis = this.yAxis, + stacks = axis.stacks, + key = this.stackKey; + + if (this.processedYData[i] < this.options.threshold) { + key = '-' + key; + } + + return stacks[key][i]; + }, + + drawGraph: Series.prototype.drawGraph +}); + +/* **************************************************************************** + * End Waterfall series code * + *****************************************************************************/ +/* **************************************************************************** + * Start Bubble series code * + *****************************************************************************/ + +// 1 - set default options +defaultPlotOptions.bubble = merge(defaultPlotOptions.scatter, { + dataLabels: { + inside: true, + style: { + color: 'white', + textShadow: '0px 0px 3px black' + }, + verticalAlign: 'middle' + }, + // displayNegative: true, + marker: { + // fillOpacity: 0.5, + lineColor: null, // inherit from series.color + lineWidth: 1 + }, + minSize: 8, + maxSize: '20%', + // negativeColor: null, + tooltip: { + pointFormat: '({point.x}, {point.y}), Size: {point.z}' + }, + turboThreshold: 0, + zThreshold: 0 +}); + +// 2 - Create the series object +seriesTypes.bubble = extendClass(seriesTypes.scatter, { + type: 'bubble', + pointArrayMap: ['y', 'z'], + trackerGroups: ['group', 'dataLabelsGroup'], + + /** + * Mapping between SVG attributes and the corresponding options + */ + pointAttrToOptions: { + stroke: 'lineColor', + 'stroke-width': 'lineWidth', + fill: 'fillColor' + }, + + /** + * Apply the fillOpacity to all fill positions + */ + applyOpacity: function (fill) { + var markerOptions = this.options.marker, + fillOpacity = pick(markerOptions.fillOpacity, 0.5); + + // When called from Legend.colorizeItem, the fill isn't predefined + fill = fill || markerOptions.fillColor || this.color; + + if (fillOpacity !== 1) { + fill = Highcharts.Color(fill).setOpacity(fillOpacity).get('rgba'); + } + return fill; + }, + + /** + * Extend the convertAttribs method by applying opacity to the fill + */ + convertAttribs: function () { + var obj = Series.prototype.convertAttribs.apply(this, arguments); + + obj.fill = this.applyOpacity(obj.fill); + + return obj; + }, + + /** + * Get the radius for each point based on the minSize, maxSize and each point's Z value. This + * must be done prior to Series.translate because the axis needs to add padding in + * accordance with the point sizes. + */ + getRadii: function (zMin, zMax, minSize, maxSize) { + var len, + i, + pos, + zData = this.zData, + radii = [], + zRange; + + // Set the shape type and arguments to be picked up in drawPoints + for (i = 0, len = zData.length; i < len; i++) { + zRange = zMax - zMin; + pos = zRange > 0 ? // relative size, a number between 0 and 1 + (zData[i] - zMin) / (zMax - zMin) : + 0.5; + radii.push(math.ceil(minSize + pos * (maxSize - minSize)) / 2); + } + this.radii = radii; + }, + + /** + * Perform animation on the bubbles + */ + animate: function (init) { + var animation = this.options.animation; + + if (!init) { // run the animation + each(this.points, function (point) { + var graphic = point.graphic, + shapeArgs = point.shapeArgs; + + if (graphic && shapeArgs) { + // start values + graphic.attr('r', 1); + + // animate + graphic.animate({ + r: shapeArgs.r + }, animation); + } + }); + + // delete this function to allow it only once + this.animate = null; + } + }, + + /** + * Extend the base translate method to handle bubble size + */ + translate: function () { + + var i, + data = this.data, + point, + radius, + radii = this.radii; + + // Run the parent method + seriesTypes.scatter.prototype.translate.call(this); + + // Set the shape type and arguments to be picked up in drawPoints + i = data.length; + + while (i--) { + point = data[i]; + radius = radii ? radii[i] : 0; // #1737 + + // Flag for negativeColor to be applied in Series.js + point.negative = point.z < (this.options.zThreshold || 0); + + if (radius >= this.minPxSize / 2) { + // Shape arguments + point.shapeType = 'circle'; + point.shapeArgs = { + x: point.plotX, + y: point.plotY, + r: radius + }; + + // Alignment box for the data label + point.dlBox = { + x: point.plotX - radius, + y: point.plotY - radius, + width: 2 * radius, + height: 2 * radius + }; + } else { // below zThreshold + point.shapeArgs = point.plotY = point.dlBox = UNDEFINED; // #1691 + } + } + }, + + /** + * Get the series' symbol in the legend + * + * @param {Object} legend The legend object + * @param {Object} item The series (this) or point + */ + drawLegendSymbol: function (legend, item) { + var radius = pInt(legend.itemStyle.fontSize) / 2; + + item.legendSymbol = this.chart.renderer.circle( + radius, + legend.baseline - radius, + radius + ).attr({ + zIndex: 3 + }).add(item.legendGroup); + item.legendSymbol.isMarker = true; + + }, + + drawPoints: seriesTypes.column.prototype.drawPoints, + alignDataLabel: seriesTypes.column.prototype.alignDataLabel +}); + +/** + * Add logic to pad each axis with the amount of pixels + * necessary to avoid the bubbles to overflow. + */ +Axis.prototype.beforePadding = function () { + var axis = this, + axisLength = this.len, + chart = this.chart, + pxMin = 0, + pxMax = axisLength, + isXAxis = this.isXAxis, + dataKey = isXAxis ? 'xData' : 'yData', + min = this.min, + extremes = {}, + smallestSize = math.min(chart.plotWidth, chart.plotHeight), + zMin = Number.MAX_VALUE, + zMax = -Number.MAX_VALUE, + range = this.max - min, + transA = axisLength / range, + activeSeries = []; + + // Handle padding on the second pass, or on redraw + if (this.tickPositions) { + each(this.series, function (series) { + + var seriesOptions = series.options, + zData; + + if (series.type === 'bubble' && series.visible) { + + // Correction for #1673 + axis.allowZoomOutside = true; + + // Cache it + activeSeries.push(series); + + if (isXAxis) { // because X axis is evaluated first + + // For each series, translate the size extremes to pixel values + each(['minSize', 'maxSize'], function (prop) { + var length = seriesOptions[prop], + isPercent = /%$/.test(length); + + length = pInt(length); + extremes[prop] = isPercent ? + smallestSize * length / 100 : + length; + + }); + series.minPxSize = extremes.minSize; + + // Find the min and max Z + zData = series.zData; + if (zData.length) { // #1735 + zMin = math.min( + zMin, + math.max( + arrayMin(zData), + seriesOptions.displayNegative === false ? seriesOptions.zThreshold : -Number.MAX_VALUE + ) + ); + zMax = math.max(zMax, arrayMax(zData)); + } + } + } + }); + + each(activeSeries, function (series) { + + var data = series[dataKey], + i = data.length, + radius; + + if (isXAxis) { + series.getRadii(zMin, zMax, extremes.minSize, extremes.maxSize); + } + + if (range > 0) { + while (i--) { + radius = series.radii[i]; + pxMin = Math.min(((data[i] - min) * transA) - radius, pxMin); + pxMax = Math.max(((data[i] - min) * transA) + radius, pxMax); + } + } + }); + + if (activeSeries.length && range > 0 && pick(this.options.min, this.userMin) === UNDEFINED && pick(this.options.max, this.userMax) === UNDEFINED) { + pxMax -= axisLength; + transA *= (axisLength + pxMin - pxMax) / axisLength; + this.min += pxMin / transA; + this.max += pxMax / transA; + } + } +}; + +/* **************************************************************************** + * End Bubble series code * + *****************************************************************************/ +/** + * Extensions for polar charts. Additionally, much of the geometry required for polar charts is + * gathered in RadialAxes.js. + * + */ + +var seriesProto = Series.prototype, + pointerProto = Highcharts.Pointer.prototype; + + + +/** + * Translate a point's plotX and plotY from the internal angle and radius measures to + * true plotX, plotY coordinates + */ +seriesProto.toXY = function (point) { + var xy, + chart = this.chart, + plotX = point.plotX, + plotY = point.plotY; + + // Save rectangular plotX, plotY for later computation + point.rectPlotX = plotX; + point.rectPlotY = plotY; + + // Record the angle in degrees for use in tooltip + point.clientX = ((plotX / Math.PI * 180) + this.xAxis.pane.options.startAngle) % 360; + + // Find the polar plotX and plotY + xy = this.xAxis.postTranslate(point.plotX, this.yAxis.len - plotY); + point.plotX = point.polarPlotX = xy.x - chart.plotLeft; + point.plotY = point.polarPlotY = xy.y - chart.plotTop; +}; + +/** + * Order the tooltip points to get the mouse capture ranges correct. #1915. + */ +seriesProto.orderTooltipPoints = function (points) { + if (this.chart.polar) { + points.sort(function (a, b) { + return a.clientX - b.clientX; + }); + + // Wrap mouse tracking around to capture movement on the segment to the left + // of the north point (#1469, #2093). + if (points[0]) { + points[0].wrappedClientX = points[0].clientX + 360; + points.push(points[0]); + } + } +}; + + +/** + * Add some special init logic to areas and areasplines + */ +function initArea(proceed, chart, options) { + proceed.call(this, chart, options); + if (this.chart.polar) { + + /** + * Overridden method to close a segment path. While in a cartesian plane the area + * goes down to the threshold, in the polar chart it goes to the center. + */ + this.closeSegment = function (path) { + var center = this.xAxis.center; + path.push( + 'L', + center[0], + center[1] + ); + }; + + // Instead of complicated logic to draw an area around the inner area in a stack, + // just draw it behind + this.closedStacks = true; + } +} +wrap(seriesTypes.area.prototype, 'init', initArea); +wrap(seriesTypes.areaspline.prototype, 'init', initArea); + + +/** + * Overridden method for calculating a spline from one point to the next + */ +wrap(seriesTypes.spline.prototype, 'getPointSpline', function (proceed, segment, point, i) { + + var ret, + smoothing = 1.5, // 1 means control points midway between points, 2 means 1/3 from the point, 3 is 1/4 etc; + denom = smoothing + 1, + plotX, + plotY, + lastPoint, + nextPoint, + lastX, + lastY, + nextX, + nextY, + leftContX, + leftContY, + rightContX, + rightContY, + distanceLeftControlPoint, + distanceRightControlPoint, + leftContAngle, + rightContAngle, + jointAngle; + + + if (this.chart.polar) { + + plotX = point.plotX; + plotY = point.plotY; + lastPoint = segment[i - 1]; + nextPoint = segment[i + 1]; + + // Connect ends + if (this.connectEnds) { + if (!lastPoint) { + lastPoint = segment[segment.length - 2]; // not the last but the second last, because the segment is already connected + } + if (!nextPoint) { + nextPoint = segment[1]; + } + } + + // find control points + if (lastPoint && nextPoint) { + + lastX = lastPoint.plotX; + lastY = lastPoint.plotY; + nextX = nextPoint.plotX; + nextY = nextPoint.plotY; + leftContX = (smoothing * plotX + lastX) / denom; + leftContY = (smoothing * plotY + lastY) / denom; + rightContX = (smoothing * plotX + nextX) / denom; + rightContY = (smoothing * plotY + nextY) / denom; + distanceLeftControlPoint = Math.sqrt(Math.pow(leftContX - plotX, 2) + Math.pow(leftContY - plotY, 2)); + distanceRightControlPoint = Math.sqrt(Math.pow(rightContX - plotX, 2) + Math.pow(rightContY - plotY, 2)); + leftContAngle = Math.atan2(leftContY - plotY, leftContX - plotX); + rightContAngle = Math.atan2(rightContY - plotY, rightContX - plotX); + jointAngle = (Math.PI / 2) + ((leftContAngle + rightContAngle) / 2); + + + // Ensure the right direction, jointAngle should be in the same quadrant as leftContAngle + if (Math.abs(leftContAngle - jointAngle) > Math.PI / 2) { + jointAngle -= Math.PI; + } + + // Find the corrected control points for a spline straight through the point + leftContX = plotX + Math.cos(jointAngle) * distanceLeftControlPoint; + leftContY = plotY + Math.sin(jointAngle) * distanceLeftControlPoint; + rightContX = plotX + Math.cos(Math.PI + jointAngle) * distanceRightControlPoint; + rightContY = plotY + Math.sin(Math.PI + jointAngle) * distanceRightControlPoint; + + // Record for drawing in next point + point.rightContX = rightContX; + point.rightContY = rightContY; + + } + + + // moveTo or lineTo + if (!i) { + ret = ['M', plotX, plotY]; + } else { // curve from last point to this + ret = [ + 'C', + lastPoint.rightContX || lastPoint.plotX, + lastPoint.rightContY || lastPoint.plotY, + leftContX || plotX, + leftContY || plotY, + plotX, + plotY + ]; + lastPoint.rightContX = lastPoint.rightContY = null; // reset for updating series later + } + + + } else { + ret = proceed.call(this, segment, point, i); + } + return ret; +}); + +/** + * Extend translate. The plotX and plotY values are computed as if the polar chart were a + * cartesian plane, where plotX denotes the angle in radians and (yAxis.len - plotY) is the pixel distance from + * center. + */ +wrap(seriesProto, 'translate', function (proceed) { + + // Run uber method + proceed.call(this); + + // Postprocess plot coordinates + if (this.chart.polar && !this.preventPostTranslate) { + var points = this.points, + i = points.length; + while (i--) { + // Translate plotX, plotY from angle and radius to true plot coordinates + this.toXY(points[i]); + } + } +}); + +/** + * Extend getSegmentPath to allow connecting ends across 0 to provide a closed circle in + * line-like series. + */ +wrap(seriesProto, 'getSegmentPath', function (proceed, segment) { + + var points = this.points; + + // Connect the path + if (this.chart.polar && this.options.connectEnds !== false && + segment[segment.length - 1] === points[points.length - 1] && points[0].y !== null) { + this.connectEnds = true; // re-used in splines + segment = [].concat(segment, [points[0]]); + } + + // Run uber method + return proceed.call(this, segment); + +}); + + +function polarAnimate(proceed, init) { + var chart = this.chart, + animation = this.options.animation, + group = this.group, + markerGroup = this.markerGroup, + center = this.xAxis.center, + plotLeft = chart.plotLeft, + plotTop = chart.plotTop, + attribs; + + // Specific animation for polar charts + if (chart.polar) { + + // Enable animation on polar charts only in SVG. In VML, the scaling is different, plus animation + // would be so slow it would't matter. + if (chart.renderer.isSVG) { + + if (animation === true) { + animation = {}; + } + + // Initialize the animation + if (init) { + + // Scale down the group and place it in the center + attribs = { + translateX: center[0] + plotLeft, + translateY: center[1] + plotTop, + scaleX: 0.001, // #1499 + scaleY: 0.001 + }; + + group.attr(attribs); + if (markerGroup) { + markerGroup.attrSetters = group.attrSetters; + markerGroup.attr(attribs); + } + + // Run the animation + } else { + attribs = { + translateX: plotLeft, + translateY: plotTop, + scaleX: 1, + scaleY: 1 + }; + group.animate(attribs, animation); + if (markerGroup) { + markerGroup.animate(attribs, animation); + } + + // Delete this function to allow it only once + this.animate = null; + } + } + + // For non-polar charts, revert to the basic animation + } else { + proceed.call(this, init); + } +} + +// Define the animate method for both regular series and column series and their derivatives +wrap(seriesProto, 'animate', polarAnimate); +wrap(colProto, 'animate', polarAnimate); + + +/** + * Throw in a couple of properties to let setTooltipPoints know we're indexing the points + * in degrees (0-360), not plot pixel width. + */ +wrap(seriesProto, 'setTooltipPoints', function (proceed, renew) { + + if (this.chart.polar) { + extend(this.xAxis, { + tooltipLen: 360 // degrees are the resolution unit of the tooltipPoints array + }); + } + + // Run uber method + return proceed.call(this, renew); +}); + + +/** + * Extend the column prototype's translate method + */ +wrap(colProto, 'translate', function (proceed) { + + var xAxis = this.xAxis, + len = this.yAxis.len, + center = xAxis.center, + startAngleRad = xAxis.startAngleRad, + renderer = this.chart.renderer, + start, + points, + point, + i; + + this.preventPostTranslate = true; + + // Run uber method + proceed.call(this); + + // Postprocess plot coordinates + if (xAxis.isRadial) { + points = this.points; + i = points.length; + while (i--) { + point = points[i]; + start = point.barX + startAngleRad; + point.shapeType = 'path'; + point.shapeArgs = { + d: renderer.symbols.arc( + center[0], + center[1], + len - point.plotY, + null, + { + start: start, + end: start + point.pointWidth, + innerR: len - pick(point.yBottom, len) + } + ) + }; + this.toXY(point); // provide correct plotX, plotY for tooltip + } + } +}); + + +/** + * Align column data labels outside the columns. #1199. + */ +wrap(colProto, 'alignDataLabel', function (proceed, point, dataLabel, options, alignTo, isNew) { + + if (this.chart.polar) { + var angle = point.rectPlotX / Math.PI * 180, + align, + verticalAlign; + + // Align nicely outside the perimeter of the columns + if (options.align === null) { + if (angle > 20 && angle < 160) { + align = 'left'; // right hemisphere + } else if (angle > 200 && angle < 340) { + align = 'right'; // left hemisphere + } else { + align = 'center'; // top or bottom + } + options.align = align; + } + if (options.verticalAlign === null) { + if (angle < 45 || angle > 315) { + verticalAlign = 'bottom'; // top part + } else if (angle > 135 && angle < 225) { + verticalAlign = 'top'; // bottom part + } else { + verticalAlign = 'middle'; // left or right + } + options.verticalAlign = verticalAlign; + } + + seriesProto.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew); + } else { + proceed.call(this, point, dataLabel, options, alignTo, isNew); + } + +}); + +/** + * Extend the mouse tracker to return the tooltip position index in terms of + * degrees rather than pixels + */ +wrap(pointerProto, 'getIndex', function (proceed, e) { + var ret, + chart = this.chart, + center, + x, + y; + + if (chart.polar) { + center = chart.xAxis[0].center; + x = e.chartX - center[0] - chart.plotLeft; + y = e.chartY - center[1] - chart.plotTop; + + ret = 180 - Math.round(Math.atan2(x, y) / Math.PI * 180); + + } else { + + // Run uber method + ret = proceed.call(this, e); + } + return ret; +}); + +/** + * Extend getCoordinates to prepare for polar axis values + */ +wrap(pointerProto, 'getCoordinates', function (proceed, e) { + var chart = this.chart, + ret = { + xAxis: [], + yAxis: [] + }; + + if (chart.polar) { + + each(chart.axes, function (axis) { + var isXAxis = axis.isXAxis, + center = axis.center, + x = e.chartX - center[0] - chart.plotLeft, + y = e.chartY - center[1] - chart.plotTop; + + ret[isXAxis ? 'xAxis' : 'yAxis'].push({ + axis: axis, + value: axis.translate( + isXAxis ? + Math.PI - Math.atan2(x, y) : // angle + Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)), // distance from center + true + ) + }); + }); + + } else { + ret = proceed.call(this, e); + } + + return ret; +}); +}(Highcharts)); diff --git a/web/resource/components/ueditor/third-party/highcharts/highcharts.js b/web/resource/components/ueditor/third-party/highcharts/highcharts.js new file mode 100644 index 0000000..f8edd5f --- /dev/null +++ b/web/resource/components/ueditor/third-party/highcharts/highcharts.js @@ -0,0 +1,283 @@ +/* + Highcharts JS v3.0.6 (2013-10-04) + + (c) 2009-2013 Torstein Hønsi + + License: www.highcharts.com/license +*/ +(function(){function r(a,b){var c;a||(a={});for(c in b)a[c]=b[c];return a}function x(){var a,b=arguments.length,c={},d=function(a,b){var c,h;typeof a!=="object"&&(a={});for(h in b)b.hasOwnProperty(h)&&(c=b[h],a[h]=c&&typeof c==="object"&&Object.prototype.toString.call(c)!=="[object Array]"&&typeof c.nodeType!=="number"?d(a[h]||{},c):b[h]);return a};for(a=0;a3?c.length%3:0;return e+(g?c.substr(0,g)+d:"")+c.substr(g).replace(/(\d{3})(?=\d)/g,"$1"+d)+(f?b+N(a-c).toFixed(f).slice(2):"")}function Ba(a,b){return Array((b||2)+1-String(a).length).join(0)+a}function mb(a,b,c){var d=a[b];a[b]=function(){var a=Array.prototype.slice.call(arguments);a.unshift(d);return c.apply(this,a)}}function Ca(a,b){for(var c="{",d=!1, +e,f,g,h,i,j=[];(c=a.indexOf(c))!==-1;){e=a.slice(0,c);if(d){f=e.split(":");g=f.shift().split(".");i=g.length;e=b;for(h=0;h-1?h.thousandsSep:"")):e=Xa(f,e)}j.push(e);a=a.slice(c+1);c=(d=!d)?"}":"{"}j.push(a);return j.join("")}function nb(a){return R.pow(10,P(R.log(a)/R.LN10))}function ob(a,b,c,d){var e,c=o(c,1);e=a/c;b||(b=[1,2,2.5,5,10],d&&d.allowDecimals=== +!1&&(c===1?b=[1,2,5,10]:c<=0.1&&(b=[1/c])));for(d=0;d=D[pb]&&(i.setMilliseconds(0),i.setSeconds(j>=D[Ya]?0:k*P(i.getSeconds()/k)));if(j>=D[Ya])i[Fb](j>=D[Qa]?0:k*P(i[qb]()/k));if(j>=D[Qa])i[Gb](j>=D[ua]?0:k*P(i[rb]()/k));if(j>=D[ua])i[sb](j>=D[Ra]?1:k*P(i[Sa]()/k));j>=D[Ra]&&(i[Hb](j>=D[Da]?0:k*P(i[$a]()/k)),h=i[ab]());j>=D[Da]&&(h-=h%k,i[Ib](h));if(j===D[Za])i[sb](i[Sa]()-i[tb]()+o(d,1));b=1;h=i[ab]();for(var d= +i.getTime(),l=i[$a](),m=i[Sa](),p=g?0:(864E5+i.getTimezoneOffset()*6E4)%864E5;dc&&(c=a[b]);return c}function Ka(a,b){for(var c in a)a[c]&&a[c]!==b&&a[c].destroy&&a[c].destroy(),delete a[c]}function Ta(a){cb||(cb=U(Ea));a&&cb.appendChild(a);cb.innerHTML=""}function ka(a,b){var c="Highcharts error #"+a+": www.highcharts.com/errors/"+a;if(b)throw c;else O.console&&console.log(c)}function ia(a){return parseFloat(a.toPrecision(14))} +function La(a,b){Fa=o(a,b.animation)}function Lb(){var a=M.global.useUTC,b=a?"getUTC":"get",c=a?"setUTC":"set";bb=a?Date.UTC:function(a,b,c,g,h,i){return(new Date(a,b,o(c,1),o(g,0),o(h,0),o(i,0))).getTime()};qb=b+"Minutes";rb=b+"Hours";tb=b+"Day";Sa=b+"Date";$a=b+"Month";ab=b+"FullYear";Fb=c+"Minutes";Gb=c+"Hours";sb=c+"Date";Hb=c+"Month";Ib=c+"FullYear"}function wa(){}function Ma(a,b,c,d){this.axis=a;this.pos=b;this.type=c||"";this.isNew=!0;!c&&!d&&this.addLabel()}function vb(a,b){this.axis=a;if(b)this.options= +b,this.id=b.id}function Mb(a,b,c,d,e,f){var g=a.chart.inverted;this.axis=a;this.isNegative=c;this.options=b;this.x=d;this.total=null;this.points={};this.stack=e;this.percent=f==="percent";this.alignOptions={align:b.align||(g?c?"left":"right":"center"),verticalAlign:b.verticalAlign||(g?"middle":c?"bottom":"top"),y:o(b.y,g?4:c?14:-6),x:o(b.x,g?c?-6:6:0)};this.textAlign=b.textAlign||(g?c?"right":"left":"center")}function db(){this.init.apply(this,arguments)}function wb(){this.init.apply(this,arguments)} +function xb(a,b){this.init(a,b)}function eb(a,b){this.init(a,b)}function yb(){this.init.apply(this,arguments)}var w,y=document,O=window,R=Math,t=R.round,P=R.floor,xa=R.ceil,s=R.max,I=R.min,N=R.abs,V=R.cos,ca=R.sin,ya=R.PI,Ua=ya*2/360,oa=navigator.userAgent,Nb=O.opera,ta=/msie/i.test(oa)&&!Nb,fb=y.documentMode===8,gb=/AppleWebKit/.test(oa),hb=/Firefox/.test(oa),Ob=/(Mobile|Android|Windows Phone)/.test(oa),za="http://www.w3.org/2000/svg",Z=!!y.createElementNS&&!!y.createElementNS(za,"svg").createSVGRect, +Ub=hb&&parseInt(oa.split("Firefox/")[1],10)<4,$=!Z&&!ta&&!!y.createElement("canvas").getContext,Va,ib=y.documentElement.ontouchstart!==w,Pb={},zb=0,cb,M,Xa,Fa,Ab,D,pa=function(){},Ga=[],Ea="div",S="none",Qb="rgba(192,192,192,"+(Z?1.0E-4:0.002)+")",Db="millisecond",pb="second",Ya="minute",Qa="hour",ua="day",Za="week",Ra="month",Da="year",Rb="stroke-width",bb,qb,rb,tb,Sa,$a,ab,Fb,Gb,sb,Hb,Ib,W={};O.Highcharts=O.Highcharts?ka(16,!0):{};Xa=function(a,b,c){if(!u(b)||isNaN(b))return"Invalid date";var a= +o(a,"%Y-%m-%d %H:%M:%S"),d=new Date(b),e,f=d[rb](),g=d[tb](),h=d[Sa](),i=d[$a](),j=d[ab](),k=M.lang,l=k.weekdays,d=r({a:l[g].substr(0,3),A:l[g],d:Ba(h),e:h,b:k.shortMonths[i],B:k.months[i],m:Ba(i+1),y:j.toString().substr(2,2),Y:j,H:Ba(f),I:Ba(f%12||12),l:f%12||12,M:Ba(d[qb]()),p:f<12?"AM":"PM",P:f<12?"am":"pm",S:Ba(d.getSeconds()),L:Ba(t(b%1E3),3)},Highcharts.dateFormats);for(e in d)for(;a.indexOf("%"+e)!==-1;)a=a.replace("%"+e,typeof d[e]==="function"?d[e](b):d[e]);return c?a.substr(0,1).toUpperCase()+ +a.substr(1):a};Jb.prototype={wrapColor:function(a){if(this.color>=a)this.color=0},wrapSymbol:function(a){if(this.symbol>=a)this.symbol=0}};D=function(){for(var a=0,b=arguments,c=b.length,d={};a-1,f=e?7:3,g,b=b.split(" "),c=[].concat(c),h,i,j=function(a){for(g=a.length;g--;)a[g]==="M"&&a.splice(g+1,0,a[g+1],a[g+2],a[g+1],a[g+2])};e&& +(j(b),j(c));a.isArea&&(h=b.splice(b.length-6,6),i=c.splice(c.length-6,6));if(d<=c.length/f&&b.length===c.length)for(;d--;)c=[].concat(c).splice(0,f).concat(c);a.shift=0;if(b.length)for(a=c.length;b.length{point.key}
',pointFormat:'{series.name}: {point.y}
',shadow:!0,snap:Ob?25:10,style:{color:"#333333",cursor:"default", +fontSize:"12px",padding:"8px",whiteSpace:"nowrap"}},credits:{enabled:!0,text:"Highcharts.com",href:"http://www.highcharts.com",position:{align:"right",x:-10,verticalAlign:"bottom",y:-5},style:{cursor:"pointer",color:"#909090",fontSize:"9px"}}};var Y=M.plotOptions,X=Y.line;Lb();var ra=function(a){var b=[],c,d;(function(a){a&&a.stops?d=Na(a.stops,function(a){return ra(a[1])}):(c=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/.exec(a))?b=[C(c[1]),C(c[2]), +C(c[3]),parseFloat(c[4],10)]:(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(a))?b=[C(c[1],16),C(c[2],16),C(c[3],16),1]:(c=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(a))&&(b=[C(c[1]),C(c[2]),C(c[3]),1])})(a);return{get:function(c){var f;d?(f=x(a),f.stops=[].concat(f.stops),n(d,function(a,b){f.stops[b]=[f.stops[b][0],a.get(c)]})):f=b&&!isNaN(b[0])?c==="rgb"?"rgb("+b[0]+","+b[1]+","+b[2]+")":c==="a"?b[3]:"rgba("+b.join(",")+")":a;return f},brighten:function(a){if(d)n(d, +function(b){b.brighten(a)});else if(sa(a)&&a!==0){var c;for(c=0;c<3;c++)b[c]+=C(a*255),b[c]<0&&(b[c]=0),b[c]>255&&(b[c]=255)}return this},rgba:b,setOpacity:function(a){b[3]=a;return this}}};wa.prototype={init:function(a,b){this.element=b==="span"?U(b):y.createElementNS(za,b);this.renderer=a;this.attrSetters={}},opacity:1,animate:function(a,b,c){b=o(b,Fa,!0);Wa(this);if(b){b=x(b);if(c)b.complete=c;Bb(this,a,b)}else this.attr(a),c&&c()},attr:function(a,b){var c,d,e,f,g=this.element,h=g.nodeName.toLowerCase(), +i=this.renderer,j,k=this.attrSetters,l=this.shadows,m,p,q=this;ea(a)&&u(b)&&(c=a,a={},a[c]=b);if(ea(a))c=a,h==="circle"?c={x:"cx",y:"cy"}[c]||c:c==="strokeWidth"&&(c="stroke-width"),q=v(g,c)||this[c]||0,c!=="d"&&c!=="visibility"&&c!=="fill"&&(q=parseFloat(q));else{for(c in a)if(j=!1,d=a[c],e=k[c]&&k[c].call(this,d,c),e!==!1){e!==w&&(d=e);if(c==="d")d&&d.join&&(d=d.join(" ")),/(NaN| {2}|^$)/.test(d)&&(d="M 0 0");else if(c==="x"&&h==="text")for(e=0;e1100)&&b.call(d,a)}):d["on"+a]=b;return this},setRadialReference:function(a){this.element.radialReference=a;return this},translate:function(a,b){return this.attr({translateX:a,translateY:b})},invert:function(){this.inverted=!0;this.updateTransform();return this},htmlCss:function(a){var b=this.element;if(b=a&&b.tagName==="SPAN"&&a.width)delete a.width,this.textWidth=b,this.updateTransform();this.styles=r(this.styles,a);K(this.element,a);return this},htmlGetBBox:function(){var a= +this.element,b=this.bBox;if(!b){if(a.nodeName==="text")a.style.position="absolute";b=this.bBox={x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}}return b},htmlUpdateTransform:function(){if(this.added){var a=this.renderer,b=this.element,c=this.translateX||0,d=this.translateY||0,e=this.x||0,f=this.y||0,g=this.textAlign||"left",h={left:0,center:0.5,right:1}[g],i=g&&g!=="left",j=this.shadows;K(b,{marginLeft:c,marginTop:d});j&&n(j,function(a){K(a,{marginLeft:c+1,marginTop:d+1})}); +this.inverted&&n(b.childNodes,function(c){a.invertChild(c,b)});if(b.tagName==="SPAN"){var k,l,j=this.rotation,m;k=0;var p=1,q=0,ba;m=C(this.textWidth);var A=this.xCorr||0,L=this.yCorr||0,Sb=[j,g,b.innerHTML,this.textWidth].join(",");if(Sb!==this.cTT){u(j)&&(k=j*Ua,p=V(k),q=ca(k),this.setSpanRotation(j,q,p));k=o(this.elemWidth,b.offsetWidth);l=o(this.elemHeight,b.offsetHeight);if(k>m&&/[ \-]/.test(b.textContent||b.innerText))K(b,{width:m+"px",display:"block",whiteSpace:"normal"}),k=m;m=a.fontMetrics(b.style.fontSize).b; +A=p<0&&-k;L=q<0&&-l;ba=p*q<0;A+=q*m*(ba?1-h:h);L-=p*m*(j?ba?h:1-h:1);i&&(A-=k*h*(p<0?-1:1),j&&(L-=l*h*(q<0?-1:1)),K(b,{textAlign:g}));this.xCorr=A;this.yCorr=L}K(b,{left:e+A+"px",top:f+L+"px"});if(gb)l=b.offsetHeight;this.cTT=Sb}}else this.alignOnAdd=!0},setSpanRotation:function(a){var b={};b[ta?"-ms-transform":gb?"-webkit-transform":hb?"MozTransform":Nb?"-o-transform":""]=b.transform="rotate("+a+"deg)";K(this.element,b)},updateTransform:function(){var a=this.translateX||0,b=this.translateY||0,c= +this.scaleX,d=this.scaleY,e=this.inverted,f=this.rotation;e&&(a+=this.attr("width"),b+=this.attr("height"));a=["translate("+a+","+b+")"];e?a.push("rotate(90) scale(-1,1)"):f&&a.push("rotate("+f+" "+(this.x||0)+" "+(this.y||0)+")");(u(c)||u(d))&&a.push("scale("+o(c,1)+" "+o(d,1)+")");a.length&&v(this.element,"transform",a.join(" "))},toFront:function(){var a=this.element;a.parentNode.appendChild(a);return this},align:function(a,b,c){var d,e,f,g,h={};e=this.renderer;f=e.alignedObjects;if(a){if(this.alignOptions= +a,this.alignByTranslate=b,!c||ea(c))this.alignTo=d=c||"renderer",ga(f,this),f.push(this),c=null}else a=this.alignOptions,b=this.alignByTranslate,d=this.alignTo;c=o(c,e[d],e);d=a.align;e=a.verticalAlign;f=(c.x||0)+(a.x||0);g=(c.y||0)+(a.y||0);if(d==="right"||d==="center")f+=(c.width-(a.width||0))/{right:1,center:2}[d];h[b?"translateX":"x"]=t(f);if(e==="bottom"||e==="middle")g+=(c.height-(a.height||0))/({bottom:1,middle:2}[e]||1);h[b?"translateY":"y"]=t(g);this[this.placed?"animate":"attr"](h);this.placed= +!0;this.alignAttr=h;return this},getBBox:function(){var a=this.bBox,b=this.renderer,c,d=this.rotation;c=this.element;var e=this.styles,f=d*Ua;if(!a){if(c.namespaceURI===za||b.forExport){try{a=c.getBBox?r({},c.getBBox()):{width:c.offsetWidth,height:c.offsetHeight}}catch(g){}if(!a||a.width<0)a={width:0,height:0}}else a=this.htmlGetBBox();if(b.isSVG){b=a.width;c=a.height;if(ta&&e&&e.fontSize==="11px"&&c.toPrecision(3)==="22.7")a.height=c=14;if(d)a.width=N(c*ca(f))+N(b*V(f)),a.height=N(c*V(f))+N(b*ca(f))}this.bBox= +a}return a},show:function(){return this.attr({visibility:"visible"})},hide:function(){return this.attr({visibility:"hidden"})},fadeOut:function(a){var b=this;b.animate({opacity:0},{duration:a||150,complete:function(){b.hide()}})},add:function(a){var b=this.renderer,c=a||b,d=c.element||b.box,e=d.childNodes,f=this.element,g=v(f,"zIndex"),h;if(a)this.parentGroup=a;this.parentInverted=a&&a.inverted;this.textStr!==void 0&&b.buildText(this);if(g)c.handleZ=!0,g=C(g);if(c.handleZ)for(c=0;cg||!u(g)&&u(b))){d.insertBefore(f,a);h=!0;break}h||d.appendChild(f);this.added=!0;z(this,"add");return this},safeRemoveChild:function(a){var b=a.parentNode;b&&b.removeChild(a)},destroy:function(){var a=this,b=a.element||{},c=a.shadows,d=a.renderer.isSVG&&b.nodeName==="SPAN"&&b.parentNode,e,f;b.onclick=b.onmouseout=b.onmouseover=b.onmousemove=b.point=null;Wa(a);if(a.clipPath)a.clipPath=a.clipPath.destroy();if(a.stops){for(f=0;f/g,'').replace(/<(i|em)>/g,'').replace(//g,"").split(//g),f=b.childNodes,g=/style="([^"]+)"/,h=/href="(http[^"]+)"/,i=v(b,"x"),j=a.styles,k=j&&j.width&&C(j.width),l=j&&j.lineHeight,m=f.length;m--;)b.removeChild(f[m]);k&&!a.added&&this.box.appendChild(b);e[e.length-1]===""&&e.pop();n(e,function(e,f){var m,o=0,e=e.replace(//g, +"|||");m=e.split("|||");n(m,function(e){if(e!==""||m.length===1){var p={},n=y.createElementNS(za,"tspan"),s;g.test(e)&&(s=e.match(g)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),v(n,"style",s));h.test(e)&&!d&&(v(n,"onclick",'location.href="'+e.match(h)[1]+'"'),K(n,{cursor:"pointer"}));e=(e.replace(/<(.|\n)*?>/g,"")||" ").replace(/</g,"<").replace(/>/g,">");if(e!==" "&&(n.appendChild(y.createTextNode(e)),o?p.dx=0:p.x=i,v(n,p),!o&&f&&(!Z&&d&&K(n,{display:"block"}),v(n,"dy",l||c.fontMetrics(/px$/.test(n.style.fontSize)? +n.style.fontSize:j.fontSize).h,gb&&n.offsetHeight)),b.appendChild(n),o++,k))for(var e=e.replace(/([^\^])-/g,"$1- ").split(" "),u,t,p=a._clipHeight,E=[],w=C(l||16),B=1;e.length||E.length;)delete a.bBox,u=a.getBBox(),t=u.width,u=t>k,!u||e.length===1?(e=E,E=[],e.length&&(B++,p&&B*w>p?(e=["..."],a.attr("title",a.textStr)):(n=y.createElementNS(za,"tspan"),v(n,{dy:w,x:i}),s&&v(n,"style",s),b.appendChild(n),t>k&&(k=t)))):(n.removeChild(n.firstChild),E.unshift(e.pop())),e.length&&n.appendChild(y.createTextNode(e.join(" ").replace(/- /g, +"-")))}})})},button:function(a,b,c,d,e,f,g,h){var i=this.label(a,b,c,null,null,null,null,null,"button"),j=0,k,l,m,p,q,n,a={x1:0,y1:0,x2:0,y2:1},e=x({"stroke-width":1,stroke:"#CCCCCC",fill:{linearGradient:a,stops:[[0,"#FEFEFE"],[1,"#F6F6F6"]]},r:2,padding:5,style:{color:"black"}},e);m=e.style;delete e.style;f=x(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#FFF"],[1,"#ACF"]]}},f);p=f.style;delete f.style;g=x(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#9BD"],[1,"#CDF"]]}},g);q=g.style; +delete g.style;h=x(e,{style:{color:"#CCC"}},h);n=h.style;delete h.style;J(i.element,ta?"mouseover":"mouseenter",function(){j!==3&&i.attr(f).css(p)});J(i.element,ta?"mouseout":"mouseleave",function(){j!==3&&(k=[e,f,g][j],l=[m,p,q][j],i.attr(k).css(l))});i.setState=function(a){(i.state=j=a)?a===2?i.attr(g).css(q):a===3&&i.attr(h).css(n):i.attr(e).css(m)};return i.on("click",function(){j!==3&&d.call(i)}).attr(e).css(r({cursor:"default"},m))},crispLine:function(a,b){a[1]===a[4]&&(a[1]=a[4]=t(a[1])-b% +2/2);a[2]===a[5]&&(a[2]=a[5]=t(a[2])+b%2/2);return a},path:function(a){var b={fill:S};Ia(a)?b.d=a:T(a)&&r(b,a);return this.createElement("path").attr(b)},circle:function(a,b,c){a=T(a)?a:{x:a,y:b,r:c};return this.createElement("circle").attr(a)},arc:function(a,b,c,d,e,f){if(T(a))b=a.y,c=a.r,d=a.innerR,e=a.start,f=a.end,a=a.x;a=this.symbol("arc",a||0,b||0,c||0,c||0,{innerR:d||0,start:e||0,end:f||0});a.r=c;return a},rect:function(a,b,c,d,e,f){e=T(a)?a.r:e;e=this.createElement("rect").attr({rx:e,ry:e, +fill:S});return e.attr(T(a)?a:e.crisp(f,a,b,s(c,0),s(d,0)))},setSize:function(a,b,c){var d=this.alignedObjects,e=d.length;this.width=a;this.height=b;for(this.boxWrapper[o(c,!0)?"animate":"attr"]({width:a,height:b});e--;)d[e].align()},g:function(a){var b=this.createElement("g");return u(a)?b.attr({"class":"highcharts-"+a}):b},image:function(a,b,c,d,e){var f={preserveAspectRatio:S};arguments.length>1&&r(f,{x:b,y:c,width:d,height:e});f=this.createElement("image").attr(f);f.element.setAttributeNS?f.element.setAttributeNS("http://www.w3.org/1999/xlink", +"href",a):f.element.setAttribute("hc-svg-href",a);return f},symbol:function(a,b,c,d,e,f){var g,h=this.symbols[a],h=h&&h(t(b),t(c),d,e,f),i=/^url\((.*?)\)$/,j,k;if(h)g=this.path(h),r(g,{symbolName:a,x:b,y:c,width:d,height:e}),f&&r(g,f);else if(i.test(a))k=function(a,b){a.element&&(a.attr({width:b[0],height:b[1]}),a.alignByTranslate||a.translate(t((d-b[0])/2),t((e-b[1])/2)))},j=a.match(i)[1],a=Pb[j],g=this.image(j).attr({x:b,y:c}),g.isImg=!0,a?k(g,a):(g.attr({width:0,height:0}),U("img",{onload:function(){k(g, +Pb[j]=[this.width,this.height])},src:j}));return g},symbols:{circle:function(a,b,c,d){var e=0.166*c;return["M",a+c/2,b,"C",a+c+e,b,a+c+e,b+d,a+c/2,b+d,"C",a-e,b+d,a-e,b,a+c/2,b,"Z"]},square:function(a,b,c,d){return["M",a,b,"L",a+c,b,a+c,b+d,a,b+d,"Z"]},triangle:function(a,b,c,d){return["M",a+c/2,b,"L",a+c,b+d,a,b+d,"Z"]},"triangle-down":function(a,b,c,d){return["M",a,b,"L",a+c,b,a+c/2,b+d,"Z"]},diamond:function(a,b,c,d){return["M",a+c/2,b,"L",a+c,b+d/2,a+c/2,b+d,a,b+d/2,"Z"]},arc:function(a,b,c,d, +e){var f=e.start,c=e.r||c||d,g=e.end-0.001,d=e.innerR,h=e.open,i=V(f),j=ca(f),k=V(g),g=ca(g),e=e.end-f');if(b)c=e||b==="span"||b==="img"?c.join(""):a.prepVML(c),this.element= +U(c);this.renderer=a;this.attrSetters={}},add:function(a){var b=this.renderer,c=this.element,d=b.box,d=a?a.element||a:d;a&&a.inverted&&b.invertChild(c,d);d.appendChild(c);this.added=!0;this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform();z(this,"add");return this},updateTransform:wa.prototype.htmlUpdateTransform,setSpanRotation:function(a,b,c){K(this.element,{filter:a?["progid:DXImageTransform.Microsoft.Matrix(M11=",c,", M12=",-b,", M21=",b,", M22=",c,", sizingMethod='auto expand')"].join(""): +S})},pathToVML:function(a){for(var b=a.length,c=[],d;b--;)if(sa(a[b]))c[b]=t(a[b]*10)-5;else if(a[b]==="Z")c[b]="x";else if(c[b]=a[b],a.isArc&&(a[b]==="wa"||a[b]==="at"))d=a[b]==="wa"?1:-1,c[b+5]===c[b+7]&&(c[b+7]-=d),c[b+6]===c[b+8]&&(c[b+8]-=d);return c.join(" ")||"x"},attr:function(a,b){var c,d,e,f=this.element||{},g=f.style,h=f.nodeName,i=this.renderer,j=this.symbolName,k,l=this.shadows,m,p=this.attrSetters,q=this;ea(a)&&u(b)&&(c=a,a={},a[c]=b);if(ea(a))c=a,q=c==="strokeWidth"||c==="stroke-width"? +this.strokeweight:this[c];else for(c in a)if(d=a[c],m=!1,e=p[c]&&p[c].call(this,d,c),e!==!1&&d!==null){e!==w&&(d=e);if(j&&/^(x|y|r|start|end|width|height|innerR|anchorX|anchorY)/.test(c))k||(this.symbolAttr(a),k=!0),m=!0;else if(c==="d"){d=d||[];this.d=d.join(" ");f.path=d=this.pathToVML(d);if(l)for(e=l.length;e--;)l[e].path=l[e].cutOff?this.cutOffPath(d,l[e].cutOff):d;m=!0}else if(c==="visibility"){if(l)for(e=l.length;e--;)l[e].style[c]=d;h==="DIV"&&(d=d==="hidden"?"-999em":0,fb||(g[c]=d?"visible": +"hidden"),c="top");g[c]=d;m=!0}else if(c==="zIndex")d&&(g[c]=d),m=!0;else if(qa(c,["x","y","width","height"])!==-1)this[c]=d,c==="x"||c==="y"?c={x:"left",y:"top"}[c]:d=s(0,d),this.updateClipping?(this[c]=d,this.updateClipping()):g[c]=d,m=!0;else if(c==="class"&&h==="DIV")f.className=d;else if(c==="stroke")d=i.color(d,f,c),c="strokecolor";else if(c==="stroke-width"||c==="strokeWidth")f.stroked=d?!0:!1,c="strokeweight",this[c]=d,sa(d)&&(d+="px");else if(c==="dashstyle")(f.getElementsByTagName("stroke")[0]|| +U(i.prepVML([""]),null,null,f))[c]=d||"solid",this.dashstyle=d,m=!0;else if(c==="fill")if(h==="SPAN")g.color=d;else{if(h!=="IMG")f.filled=d!==S?!0:!1,d=i.color(d,f,c,this),c="fillcolor"}else if(c==="opacity")m=!0;else if(h==="shape"&&c==="rotation")this[c]=f.style[c]=d,f.style.left=-t(ca(d*Ua)+1)+"px",f.style.top=t(V(d*Ua))+"px";else if(c==="translateX"||c==="translateY"||c==="rotation")this[c]=d,this.updateTransform(),m=!0;else if(c==="text")this.bBox=null,f.innerHTML=d,m=!0;m||(fb?f[c]= +d:v(f,c,d))}return q},clip:function(a){var b=this,c;a?(c=a.members,ga(c,b),c.push(b),b.destroyClip=function(){ga(c,b)},a=a.getCSS(b)):(b.destroyClip&&b.destroyClip(),a={clip:fb?"inherit":"rect(auto)"});return b.css(a)},css:wa.prototype.htmlCss,safeRemoveChild:function(a){a.parentNode&&Ta(a)},destroy:function(){this.destroyClip&&this.destroyClip();return wa.prototype.destroy.apply(this)},on:function(a,b){this.element["on"+a]=function(){var a=O.event;a.target=a.srcElement;b(a)};return this},cutOffPath:function(a, +b){var c,a=a.split(/[ ,]/);c=a.length;if(c===9||c===11)a[c-4]=a[c-2]=C(a[c-2])-10*b;return a.join(" ")},shadow:function(a,b,c){var d=[],e,f=this.element,g=this.renderer,h,i=f.style,j,k=f.path,l,m,p,q;k&&typeof k.value!=="string"&&(k="x");m=k;if(a){p=o(a.width,3);q=(a.opacity||0.15)/p;for(e=1;e<=3;e++){l=p*2+1-2*e;c&&(m=this.cutOffPath(k.value,l+0.5));j=[''];h=U(g.prepVML(j),null, +{left:C(i.left)+o(a.offsetX,1),top:C(i.top)+o(a.offsetY,1)});if(c)h.cutOff=l+1;j=[''];U(g.prepVML(j),null,null,h);b?b.element.appendChild(h):f.parentNode.insertBefore(h,f);d.push(h)}this.shadows=d}return this}};F=ha(wa,F);var ma={Element:F,isIE8:oa.indexOf("MSIE 8.0")>-1,init:function(a,b,c){var d,e;this.alignedObjects=[];d=this.createElement(Ea);e=d.element;e.style.position="relative";a.appendChild(d.element);this.isVML=!0;this.box=e;this.boxWrapper= +d;this.setSize(b,c,!1);y.namespaces.hcv||(y.namespaces.add("hcv","urn:schemas-microsoft-com:vml"),(y.styleSheets.length?y.styleSheets[0]:y.createStyleSheet()).cssText+="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } ")},isHidden:function(){return!this.box.offsetWidth},clipRect:function(a,b,c,d){var e=this.createElement(),f=T(a);return r(e,{members:[],left:(f?a.x:a)+1,top:(f?a.y:b)+1,width:(f?a.width:c)-1,height:(f?a.height:d)-1,getCSS:function(a){var b= +a.element,c=b.nodeName,a=a.inverted,d=this.top-(c==="shape"?b.offsetTop:0),e=this.left,b=e+this.width,f=d+this.height,d={clip:"rect("+t(a?e:d)+"px,"+t(a?f:b)+"px,"+t(a?b:f)+"px,"+t(a?d:e)+"px)"};!a&&fb&&c==="DIV"&&r(d,{width:b+"px",height:f+"px"});return d},updateClipping:function(){n(e.members,function(a){a.css(e.getCSS(a))})}})},color:function(a,b,c,d){var e=this,f,g=/^rgba/,h,i,j=S;a&&a.linearGradient?i="gradient":a&&a.radialGradient&&(i="pattern");if(i){var k,l,m=a.linearGradient||a.radialGradient, +p,q,o,A,L,s="",a=a.stops,u,t=[],w=function(){h=[''];U(e.prepVML(h),null,null,b)};p=a[0];u=a[a.length-1];p[0]>0&&a.unshift([0,p[1]]);u[0]<1&&a.push([1,u[1]]);n(a,function(a,b){g.test(a[1])?(f=ra(a[1]),k=f.get("rgb"),l=f.get("a")):(k=a[1],l=1);t.push(a[0]*100+"% "+k);b?(o=l,A=k):(q=l,L=k)});if(c==="fill")if(i==="gradient")c=m.x1||m[0]||0,a=m.y1||m[1]||0,p=m.x2||m[2]||0,m=m.y2||m[3]||0,s='angle="'+ +(90-R.atan((m-a)/(p-c))*180/ya)+'"',w();else{var j=m.r,r=j*2,E=j*2,H=m.cx,B=m.cy,x=b.radialReference,v,j=function(){x&&(v=d.getBBox(),H+=(x[0]-v.x)/v.width-0.5,B+=(x[1]-v.y)/v.height-0.5,r*=x[2]/v.width,E*=x[2]/v.height);s='src="'+M.global.VMLRadialGradientURL+'" size="'+r+","+E+'" origin="0.5,0.5" position="'+H+","+B+'" color2="'+L+'" ';w()};d.added?j():J(d,"add",j);j=A}else j=k}else if(g.test(a)&&b.tagName!=="IMG")f=ra(a),h=["<",c,' opacity="',f.get("a"),'"/>'],U(this.prepVML(h),null,null,b),j= +f.get("rgb");else{j=b.getElementsByTagName(c);if(j.length)j[0].opacity=1,j[0].type="solid";j=a}return j},prepVML:function(a){var b=this.isIE8,a=a.join("");b?(a=a.replace("/>",' xmlns="urn:schemas-microsoft-com:vml" />'),a=a.indexOf('style="')===-1?a.replace("/>",' style="display:inline-block;behavior:url(#default#VML);" />'):a.replace('style="','style="display:inline-block;behavior:url(#default#VML);')):a=a.replace("<","1&&f.attr({x:b,y:c,width:d,height:e});return f},rect:function(a,b,c,d,e,f){var g=this.symbol("rect");g.r= +T(a)?a.r:e;return g.attr(T(a)?a:g.crisp(f,a,b,s(c,0),s(d,0)))},invertChild:function(a,b){var c=b.style;K(a,{flip:"x",left:C(c.width)-1,top:C(c.height)-1,rotation:-90})},symbols:{arc:function(a,b,c,d,e){var f=e.start,g=e.end,h=e.r||c||d,c=e.innerR,d=V(f),i=ca(f),j=V(g),k=ca(g);if(g-f===0)return["x"];f=["wa",a-h,b-h,a+h,b+h,a+h*d,b+h*i,a+h*j,b+h*k];e.open&&!c&&f.push("e","M",a,b);f.push("at",a-c,b-c,a+c,b+c,a+c*j,b+c*k,a+c*d,b+c*i,"x","e");f.isArc=!0;return f},circle:function(a,b,c,d,e){e&&(c=d=2*e.r); +e&&e.isCircle&&(a-=c/2,b-=d/2);return["wa",a,b,a+c,b+d,a+c,b+d/2,a+c,b+d/2,"e"]},rect:function(a,b,c,d,e){var f=a+c,g=b+d,h;!u(e)||!e.r?f=Ha.prototype.symbols.square.apply(0,arguments):(h=I(e.r,c,d),f=["M",a+h,b,"L",f-h,b,"wa",f-2*h,b,f,b+2*h,f-h,b,f,b+h,"L",f,g-h,"wa",f-2*h,g-2*h,f,g,f,g-h,f-h,g,"L",a+h,g,"wa",a,g-2*h,a+2*h,g,a+h,g,a,g-h,"L",a,b+h,"wa",a,b,a+2*h,b+2*h,a,b+h,a+h,b,"x","e"]);return f}}};Highcharts.VMLRenderer=F=function(){this.init.apply(this,arguments)};F.prototype=x(Ha.prototype, +ma);Va=F}var Tb;if($)Highcharts.CanVGRenderer=F=function(){za="http://www.w3.org/1999/xhtml"},F.prototype.symbols={},Tb=function(){function a(){var a=b.length,d;for(d=0;dj&&(c=!1)):h+k>m&&(h=m-k,d&&h+l0&&b.height>0){f=x({align:c&&k&&"center",x:c?!k&&4:10,verticalAlign:!c&&k&&"middle",y:c?k?16:10:k?6:-4,rotation:c&&!k&&90},f);if(!g)a.label=g=w.text(f.text,0,0,f.useHTML).attr({align:f.textAlign||f.align,rotation:f.rotation,zIndex:L}).css(f.style).add();b=[q[1],q[4],o(q[6],q[1])];q=[q[2],q[5],o(q[7],q[2])];c=Ja(b);k=Ja(q);g.align(f,!1,{x:c,y:k,width:va(b)-c,height:va(q)-k});g.show()}else g&&g.hide();return a}, +destroy:function(){ga(this.axis.plotLinesAndBands,this);delete this.axis;Ka(this)}};Mb.prototype={destroy:function(){Ka(this,this.axis)},render:function(a){var b=this.options,c=b.format,c=c?Ca(c,this):b.formatter.call(this);this.label?this.label.attr({text:c,visibility:"hidden"}):this.label=this.axis.chart.renderer.text(c,0,0,b.useHTML).css(b.style).attr({align:this.textAlign,rotation:b.rotation,visibility:"hidden"}).add(a)},setOffset:function(a,b){var c=this.axis,d=c.chart,e=d.inverted,f=this.isNegative, +g=c.translate(this.percent?100:this.total,0,0,0,1),c=c.translate(0),c=N(g-c),h=d.xAxis[0].translate(this.x)+a,i=d.plotHeight,f={x:e?f?g:g-c:h,y:e?i-h-b:f?i-g-c:i-g,width:e?c:b,height:e?b:c};if(e=this.label)e.align(this.alignOptions,null,f),f=e.alignAttr,e.attr({visibility:this.options.crop===!1||d.isInsidePlot(f.x,f.y)?Z?"inherit":"visible":"hidden"})}};db.prototype={defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b", +month:"%b '%y",year:"%Y"},endOnTick:!1,gridLineColor:"#C0C0C0",labels:G,lineColor:"#C0D0E0",lineWidth:1,minPadding:0.01,maxPadding:0.01,minorGridLineColor:"#E0E0E0",minorGridLineWidth:1,minorTickColor:"#A0A0A0",minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:!1,tickColor:"#C0D0E0",tickLength:5,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",tickWidth:1,title:{align:"middle",style:{color:"#4d759e",fontWeight:"bold"}},type:"linear"},defaultYAxisOptions:{endOnTick:!0, +gridLineWidth:1,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8,y:3},lineWidth:0,maxPadding:0.05,minPadding:0.05,startOnTick:!0,tickWidth:0,title:{rotation:270,text:"Values"},stackLabels:{enabled:!1,formatter:function(){return Aa(this.total,-1)},style:G.style}},defaultLeftAxisOptions:{labels:{x:-8,y:null},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:8,y:null},title:{rotation:90}},defaultBottomAxisOptions:{labels:{x:0,y:14},title:{rotation:0}},defaultTopAxisOptions:{labels:{x:0,y:-5}, +title:{rotation:0}},init:function(a,b){var c=b.isX;this.horiz=a.inverted?!c:c;this.xOrY=(this.isXAxis=c)?"x":"y";this.opposite=b.opposite;this.side=this.horiz?this.opposite?0:2:this.opposite?1:3;this.setOptions(b);var d=this.options,e=d.type;this.labelFormatter=d.labels.formatter||this.defaultLabelFormatter;this.userOptions=b;this.minPixelPadding=0;this.chart=a;this.reversed=d.reversed;this.zoomEnabled=d.zoomEnabled!==!1;this.categories=d.categories||e==="category";this.isLog=e==="logarithmic";this.isDatetimeAxis= +e==="datetime";this.isLinked=u(d.linkedTo);this.tickmarkOffset=this.categories&&d.tickmarkPlacement==="between"?0.5:0;this.ticks={};this.minorTicks={};this.plotLinesAndBands=[];this.alternateBands={};this.len=0;this.minRange=this.userMinRange=d.minRange||d.maxZoom;this.range=d.range;this.offset=d.offset||0;this.stacks={};this.oldStacks={};this.stackExtremes={};this.min=this.max=null;var f,d=this.options.events;qa(this,a.axes)===-1&&(a.axes.push(this),a[c?"xAxis":"yAxis"].push(this));this.series=this.series|| +[];if(a.inverted&&c&&this.reversed===w)this.reversed=!0;this.removePlotLine=this.removePlotBand=this.removePlotBandOrLine;for(f in d)J(this,f,d[f]);if(this.isLog)this.val2lin=na,this.lin2val=fa},setOptions:function(a){this.options=x(this.defaultOptions,this.isXAxis?{}:this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions,this.defaultLeftAxisOptions][this.side],x(M[this.isXAxis?"xAxis":"yAxis"],a))},update:function(a,b){var c=this.chart,a=c.options[this.xOrY+ +"Axis"][this.options.index]=x(this.userOptions,a);this.destroy(!0);this._addedPlotLB=this.userMin=this.userMax=w;this.init(c,r(a,{events:w}));c.isDirtyBox=!0;o(b,!0)&&c.redraw()},remove:function(a){var b=this.chart,c=this.xOrY+"Axis";n(this.series,function(a){a.remove(!1)});ga(b.axes,this);ga(b[c],this);b.options[c].splice(this.options.index,1);n(b[c],function(a,b){a.options.index=b});this.destroy();b.isDirtyBox=!0;o(a,!0)&&b.redraw()},defaultLabelFormatter:function(){var a=this.axis,b=this.value, +c=a.categories,d=this.dateTimeLabelFormat,e=M.lang.numericSymbols,f=e&&e.length,g,h=a.options.labels.format,a=a.isLog?b:a.tickInterval;if(h)g=Ca(h,this);else if(c)g=b;else if(d)g=Xa(d,b);else if(f&&a>=1E3)for(;f--&&g===w;)c=Math.pow(1E3,f+1),a>=c&&e[f]!==null&&(g=Aa(b/c,-1)+e[f]);g===w&&(g=b>=1E3?Aa(b,0):Aa(b,-1));return g},getSeriesExtremes:function(){var a=this,b=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=null;a.stackExtremes={};a.buildStacks();n(a.series,function(c){if(c.visible||!b.options.chart.ignoreHiddenSeries){var d; +d=c.options.threshold;var e;a.hasVisibleSeries=!0;a.isLog&&d<=0&&(d=null);if(a.isXAxis){if(d=c.xData,d.length)a.dataMin=I(o(a.dataMin,d[0]),Ja(d)),a.dataMax=s(o(a.dataMax,d[0]),va(d))}else{c.getExtremes();e=c.dataMax;c=c.dataMin;if(u(c)&&u(e))a.dataMin=I(o(a.dataMin,c),c),a.dataMax=s(o(a.dataMax,e),e);if(u(d))if(a.dataMin>=d)a.dataMin=d,a.ignoreMinPadding=!0;else if(a.dataMaxf+this.width)m=!0}else if(c=f,i=l-this.right,hg+this.height)m=!0;return m&&!d?null:e.renderer.crispLine(["M",c,h,"L",i,j],b||0)},getPlotBandPath:function(a,b){var c=this.getPlotLinePath(b),d=this.getPlotLinePath(a);d&&c?d.push(c[4], +c[5],c[1],c[2]):d=null;return d},getLinearTickPositions:function(a,b,c){for(var d,b=ia(P(b/a)*a),c=ia(xa(c/a)*a),e=[];b<=c;){e.push(b);b=ia(b+a);if(b===d)break;d=b}return e},getLogTickPositions:function(a,b,c,d){var e=this.options,f=this.len,g=[];if(!d)this._minorAutoInterval=null;if(a>=0.5)a=t(a),g=this.getLinearTickPositions(a,b,c);else if(a>=0.08)for(var f=P(b),h,i,j,k,l,e=a>0.3?[1,2,4]:a>0.15?[1,2,4,6,8]:[1,2,3,4,5,6,7,8,9];fb&&(!d|| +k<=c)&&g.push(k),k>c&&(l=!0),k=j}else if(b=fa(b),c=fa(c),a=e[d?"minorTickInterval":"tickInterval"],a=o(a==="auto"?null:a,this._minorAutoInterval,(c-b)*(e.tickPixelInterval/(d?5:1))/((d?f/this.tickPositions.length:f)||1)),a=ob(a,null,nb(a)),g=Na(this.getLinearTickPositions(a,b,c),na),!d)this._minorAutoInterval=a/5;if(!d)this.tickInterval=a;return g},getMinorTickPositions:function(){var a=this.options,b=this.tickPositions,c=this.minorTickInterval,d=[],e;if(this.isLog){e=b.length;for(a=1;a=this.minRange,f,g,h,i,j;if(this.isXAxis&&this.minRange===w&&!this.isLog)u(a.min)||u(a.max)?this.minRange=null:(n(this.series,function(a){i=a.xData;for(g=j=a.xIncrement?1:i.length- +1;g>0;g--)if(h=i[g]-i[g-1],f===w||hb&&(g=0);c=s(c,g);e=s(e,ea(h)?0:g/2);f=s(f,h==="on"?0:g);!a.noSharedTooltip&&u(l)&&(d=u(d)?I(d,l):l)}),g=this.ordinalSlope&&d?this.ordinalSlope/d:1,this.minPointOffset=e*=g,this.pointRangePadding=f*=g,this.pointRange=I(c,b),this.closestPointRange=d;if(a)this.oldTransA=h;this.translationSlope=this.transA=h=this.len/(b+f||1);this.transB=this.horiz?this.left:this.bottom;this.minPixelPadding=h*e},setTickPositions:function(a){var b=this,c= +b.chart,d=b.options,e=b.isLog,f=b.isDatetimeAxis,g=b.isXAxis,h=b.isLinked,i=b.options.tickPositioner,j=d.maxPadding,k=d.minPadding,l=d.tickInterval,m=d.minTickInterval,p=d.tickPixelInterval,q,ba=b.categories;h?(b.linkedParent=c[g?"xAxis":"yAxis"][d.linkedTo],c=b.linkedParent.getExtremes(),b.min=o(c.min,c.dataMin),b.max=o(c.max,c.dataMax),d.type!==b.linkedParent.options.type&&ka(11,1)):(b.min=o(b.userMin,d.min,b.dataMin),b.max=o(b.userMax,d.max,b.dataMax));if(e)!a&&I(b.min,o(b.dataMin,b.min))<=0&& +ka(10,1),b.min=ia(na(b.min)),b.max=ia(na(b.max));if(b.range&&(b.userMin=b.min=s(b.min,b.max-b.range),b.userMax=b.max,a))b.range=null;b.beforePadding&&b.beforePadding();b.adjustForMinRange();if(!ba&&!b.usePercentage&&!h&&u(b.min)&&u(b.max)&&(c=b.max-b.min)){if(!u(d.min)&&!u(b.userMin)&&k&&(b.dataMin<0||!b.ignoreMinPadding))b.min-=c*k;if(!u(d.max)&&!u(b.userMax)&&j&&(b.dataMax>0||!b.ignoreMaxPadding))b.max+=c*j}b.min===b.max||b.min===void 0||b.max===void 0?b.tickInterval=1:h&&!l&&p===b.linkedParent.options.tickPixelInterval? +b.tickInterval=b.linkedParent.tickInterval:(b.tickInterval=o(l,ba?1:(b.max-b.min)*p/s(b.len,p)),!u(l)&&b.lens(2*b.len,200)&&ka(19,!0),a=f?(b.getNonLinearTimeTicks||Eb)(Cb(b.tickInterval,d.units),b.min,b.max,d.startOfWeek,b.ordinalPositions,b.closestPointRange,!0):e?b.getLogTickPositions(b.tickInterval, +b.min,b.max):b.getLinearTickPositions(b.tickInterval,b.min,b.max),q&&a.splice(1,a.length-2),b.tickPositions=a;if(!h)e=a[0],f=a[a.length-1],h=b.minPointOffset||0,d.startOnTick?b.min=e:b.min-h>e&&a.shift(),d.endOnTick?b.max=f:b.max+h(b[d]||0)&&this.options.alignTicks!== +!1)b[d]=c.length;a.maxTicks=b},adjustTickAmount:function(){var a=this._maxTicksKey,b=this.tickPositions,c=this.chart.maxTicks;if(c&&c[a]&&!this.isDatetimeAxis&&!this.categories&&!this.isLinked&&this.options.alignTicks!==!1){var d=this.tickAmount,e=b.length;this.tickAmount=a=c[a];if(e=this.dataMax&&(b=w));this.displayBtn=a!==w||b!==w;this.setExtremes(a, +b,!1,w,{trigger:"zoom"});return!0},setAxisSize:function(){var a=this.chart,b=this.options,c=b.offsetLeft||0,d=b.offsetRight||0,e=this.horiz,f,g;this.left=g=o(b.left,a.plotLeft+c);this.top=f=o(b.top,a.plotTop);this.width=c=o(b.width,a.plotWidth-c+d);this.height=b=o(b.height,a.plotHeight);this.bottom=a.chartHeight-b-f;this.right=a.chartWidth-c-g;this.len=s(e?c:b,0);this.pos=e?g:f},getExtremes:function(){var a=this.isLog;return{min:a?ia(fa(this.min)):this.min,max:a?ia(fa(this.max)):this.max,dataMin:this.dataMin, +dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,c=b?fa(this.min):this.min,b=b?fa(this.max):this.max;c>a||a===null?a=c:b15&&a<165?"right":a>195&&a<345?"left":"center"},getOffset:function(){var a=this,b=a.chart,c=b.renderer,d=a.options,e=a.tickPositions,f=a.ticks,g=a.horiz,h=a.side,i=b.inverted?[1,0,3,2][h]:h,j,k=0,l,m=0,p=d.title,q=d.labels,ba=0,A=b.axisOffset,L=b.clipOffset,t=[-1,1,1,-1][h],r,v=1,x=o(q.maxStaggerLines,5),la,E,H,B;a.hasData=j=a.hasVisibleSeries||u(a.min)&&u(a.max)&&!!e;a.showAxis=b=j||o(d.showEmpty,!0);a.staggerLines=a.horiz&&q.staggerLines; +if(!a.axisGroup)a.gridGroup=c.g("grid").attr({zIndex:d.gridZIndex||1}).add(),a.axisGroup=c.g("axis").attr({zIndex:d.zIndex||2}).add(),a.labelGroup=c.g("axis-labels").attr({zIndex:q.zIndex||7}).add();if(j||a.isLinked){a.labelAlign=o(q.align||a.autoLabelAlign(q.rotation));n(e,function(b){f[b]?f[b].addLabel():f[b]=new Ma(a,b)});if(a.horiz&&!a.staggerLines&&x&&!q.rotation){for(r=a.reversed?[].concat(e).reverse():e;v1)a.staggerLines=v}n(e,function(b){if(h===0||h===2||{1:"left",3:"right"}[h]===a.labelAlign)ba=s(f[b].getLabelSize(),ba)});if(a.staggerLines)ba*=a.staggerLines,a.labelOffset=ba}else for(r in f)f[r].destroy(),delete f[r];if(p&&p.text&&p.enabled!==!1){if(!a.axisTitle)a.axisTitle=c.text(p.text,0,0,p.useHTML).attr({zIndex:7,rotation:p.rotation||0,align:p.textAlign||{low:"left",middle:"center",high:"right"}[p.align]}).css(p.style).add(a.axisGroup), +a.axisTitle.isNew=!0;if(b)k=a.axisTitle.getBBox()[g?"height":"width"],m=o(p.margin,g?5:10),l=p.offset;a.axisTitle[b?"show":"hide"]()}a.offset=t*o(d.offset,A[h]);a.axisTitleMargin=o(l,ba+m+(h!==2&&ba&&t*d.labels[g?"y":"x"]));A[h]=s(A[h],a.axisTitleMargin+k+t*a.offset);L[i]=s(L[i],P(d.lineWidth/2)*2)},getLinePath:function(a){var b=this.chart,c=this.opposite,d=this.offset,e=this.horiz,f=this.left+(c?this.width:0)+d,d=b.chartHeight-this.bottom-(c?this.height:0)+d;c&&(a*=-1);return b.renderer.crispLine(["M", +e?this.left:f,e?d:this.top,"L",e?b.chartWidth-this.right:f,e?d:b.chartHeight-this.bottom],a)},getTitlePosition:function(){var a=this.horiz,b=this.left,c=this.top,d=this.len,e=this.options.title,f=a?b:c,g=this.opposite,h=this.offset,i=C(e.style.fontSize||12),d={low:f+(a?0:d),middle:f+d/2,high:f+(a?d:0)}[e.align],b=(a?c+this.height:b)+(a?1:-1)*(g?-1:1)*this.axisTitleMargin+(this.side===2?i:0);return{x:a?d:b+(g?this.width:0)+h+(e.x||0),y:a?b-(g?this.height:0)+h:d+(e.y||0)}},render:function(){var a=this, +b=a.chart,c=b.renderer,d=a.options,e=a.isLog,f=a.isLinked,g=a.tickPositions,h=a.axisTitle,i=a.stacks,j=a.ticks,k=a.minorTicks,l=a.alternateBands,m=d.stackLabels,p=d.alternateGridColor,q=a.tickmarkOffset,o=d.lineWidth,A,s=b.hasRendered&&u(a.oldMin)&&!isNaN(a.oldMin);A=a.hasData;var t=a.showAxis,r,v;n([j,k,l],function(a){for(var b in a)a[b].isActive=!1});if(A||f)if(a.minorTickInterval&&!a.categories&&n(a.getMinorTickPositions(),function(b){k[b]||(k[b]=new Ma(a,b,"minor"));s&&k[b].isNew&&k[b].render(null, +!0);k[b].render(null,!1,1)}),g.length&&(n(g.slice(1).concat([g[0]]),function(b,c){c=c===g.length-1?0:c+1;if(!f||b>=a.min&&b<=a.max)j[b]||(j[b]=new Ma(a,b)),s&&j[b].isNew&&j[b].render(c,!0),j[b].render(c,!1,1)}),q&&a.min===0&&(j[-1]||(j[-1]=new Ma(a,-1,null,!0)),j[-1].render(-1))),p&&n(g,function(b,c){if(c%2===0&&b1||N(b-f.y)>1))clearTimeout(this.tooltipTimeout),this.tooltipTimeout=setTimeout(function(){e&&e.move(a,b,c,d)},32)},hide:function(){var a=this,b;clearTimeout(this.hideTimer);if(!this.isHidden)b=this.chart.hoverPoints,this.hideTimer=setTimeout(function(){a.label.fadeOut();a.isHidden=!0},o(this.options.hideDelay,500)),b&&n(b,function(a){a.setState()}),this.chart.hoverPoints= +null},hideCrosshairs:function(){n(this.crosshairs,function(a){a&&a.hide()})},getAnchor:function(a,b){var c,d=this.chart,e=d.inverted,f=d.plotTop,g=0,h=0,i,a=ja(a);c=a[0].tooltipPos;this.followPointer&&b&&(b.chartX===w&&(b=d.pointer.normalize(b)),c=[b.chartX-d.plotLeft,b.chartY-f]);c||(n(a,function(a){i=a.series.yAxis;g+=a.plotX;h+=(a.plotLow?(a.plotLow+a.plotHigh)/2:a.plotY)+(!e&&i?i.top-f:0)}),g/=a.length,h/=a.length,c=[e?d.plotWidth-h:g,this.shared&&!e&&a.length>1&&b?b.chartY-f:e?d.plotHeight-g: +h]);return Na(c,t)},getPosition:function(a,b,c){var d=this.chart,e=d.plotLeft,f=d.plotTop,g=d.plotWidth,h=d.plotHeight,i=o(this.options.distance,12),j=c.plotX,c=c.plotY,d=j+e+(d.inverted?i:-a-i),k=c-b+f+15,l;d<7&&(d=e+s(j,0)+i);d+a>e+g&&(d-=d+a-(e+g),k=c-b+f-i,l=!0);k=k&&c<=k+b&&(k=c+f+i));k+b>f+h&&(k=s(f,f+h-b-i));return{x:d,y:k}},defaultFormatter:function(a){var b=this.points||ja(this),c=b[0].series,d;d=[c.tooltipHeaderFormatter(b[0])];n(b,function(a){c=a.series;d.push(c.tooltipFormatter&& +c.tooltipFormatter(a)||a.point.tooltipFormatter(c.tooltipOptions.pointFormat))});d.push(a.options.footerFormat||"");return d.join("")},refresh:function(a,b){var c=this.chart,d=this.label,e=this.options,f,g,h={},i,j=[];i=e.formatter||this.defaultFormatter;var h=c.hoverPoints,k,l=e.crosshairs,m=this.shared;clearTimeout(this.hideTimer);this.followPointer=ja(a)[0].series.tooltipOptions.followPointer;g=this.getAnchor(a,b);f=g[0];g=g[1];m&&(!a.series||!a.series.noSharedTooltip)?(c.hoverPoints=a,h&&n(h, +function(a){a.setState()}),n(a,function(a){a.setState("hover");j.push(a.getLabelConfig())}),h={x:a[0].category,y:a[0].y},h.points=j,a=a[0]):h=a.getLabelConfig();i=i.call(h,this);h=a.series;i===!1?this.hide():(this.isHidden&&(Wa(d),d.attr("opacity",1).show()),d.attr({text:i}),k=e.borderColor||a.color||h.color||"#606060",d.attr({stroke:k}),this.updatePosition({plotX:f,plotY:g}),this.isHidden=!1);if(l){l=ja(l);for(d=l.length;d--;)if(m=a.series,e=m[d?"yAxis":"xAxis"],l[d]&&e)if(h=d?o(a.stackY,a.y):a.x, +e.isLog&&(h=na(h)),d===1&&m.modifyValue&&(h=m.modifyValue(h)),e=e.getPlotLinePath(h,1),this.crosshairs[d])this.crosshairs[d].attr({d:e,visibility:"visible"});else{h={"stroke-width":l[d].width||1,stroke:l[d].color||"#C0C0C0",zIndex:l[d].zIndex||2};if(l[d].dashStyle)h.dashstyle=l[d].dashStyle;this.crosshairs[d]=c.renderer.path(e).attr(h).add()}}z(c,"tooltipRefresh",{text:i,x:f+c.plotLeft,y:g+c.plotTop,borderColor:k})},updatePosition:function(a){var b=this.chart,c=this.label,c=(this.options.positioner|| +this.getPosition).call(this,c.width,c.height,a);this.move(t(c.x),t(c.y),a.plotX+b.plotLeft,a.plotY+b.plotTop)}};xb.prototype={init:function(a,b){var c=b.chart,d=c.events,e=$?"":c.zoomType,c=a.inverted,f;this.options=b;this.chart=a;this.zoomX=f=/x/.test(e);this.zoomY=e=/y/.test(e);this.zoomHor=f&&!c||e&&c;this.zoomVert=e&&!c||f&&c;this.runChartClick=d&&!!d.click;this.pinchDown=[];this.lastValidTouch={};if(b.tooltip.enabled)a.tooltip=new wb(a,b.tooltip);this.setDOMEvents()},normalize:function(a,b){var c, +d,a=a||O.event;if(!a.target)a.target=a.srcElement;a=Xb(a);d=a.touches?a.touches.item(0):a;if(!b)this.chartPosition=b=Wb(this.chart.container);d.pageX===w?(c=s(a.x,a.clientX-b.left),d=a.y):(c=d.pageX-b.left,d=d.pageY-b.top);return r(a,{chartX:t(c),chartY:t(d)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};n(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c,value:c.toValue(a[c.horiz?"chartX":"chartY"])})});return b},getIndex:function(a){var b=this.chart;return b.inverted? +b.plotHeight+b.plotTop-a.chartY:a.chartX-b.plotLeft},runPointActions:function(a){var b=this.chart,c=b.series,d=b.tooltip,e,f=b.hoverPoint,g=b.hoverSeries,h,i,j=b.chartWidth,k=this.getIndex(a);if(d&&this.options.tooltip.shared&&(!g||!g.noSharedTooltip)){e=[];h=c.length;for(i=0;i +j&&e.splice(h,1);if(e.length&&e[0].clientX!==this.hoverX)d.refresh(e,a),this.hoverX=e[0].clientX}if(g&&g.tracker){if((b=g.tooltipPoints[k])&&b!==f)b.onMouseOver(a)}else d&&d.followPointer&&!d.isHidden&&(a=d.getAnchor([{}],a),d.updatePosition({plotX:a[0],plotY:a[1]}))},reset:function(a){var b=this.chart,c=b.hoverSeries,d=b.hoverPoint,e=b.tooltip,b=e&&e.shared?b.hoverPoints:d;(a=a&&e&&b)&&ja(b)[0].plotX===w&&(a=!1);if(a)e.refresh(b);else{if(d)d.onMouseOut();if(c)c.onMouseOut();e&&(e.hide(),e.hideCrosshairs()); +this.hoverX=null}},scaleGroups:function(a,b){var c=this.chart,d;n(c.series,function(e){d=a||e.getPlotBox();e.xAxis&&e.xAxis.zoomEnabled&&(e.group.attr(d),e.markerGroup&&(e.markerGroup.attr(d),e.markerGroup.clip(b?c.clipRect:null)),e.dataLabelsGroup&&e.dataLabelsGroup.attr(d))});c.clipRect.attr(b||c.clipBox)},pinchTranslateDirection:function(a,b,c,d,e,f,g){var h=this.chart,i=a?"x":"y",j=a?"X":"Y",k="chart"+j,l=a?"width":"height",m=h["plot"+(a?"Left":"Top")],p,q,o=1,n=h.inverted,s=h.bounds[a?"h":"v"], +t=b.length===1,u=b[0][k],r=c[0][k],w=!t&&b[1][k],v=!t&&c[1][k],x,c=function(){!t&&N(u-w)>20&&(o=N(r-v)/N(u-w));q=(m-r)/o+u;p=h["plot"+(a?"Width":"Height")]/o};c();b=q;bs.max&&(b=s.max-p,x=!0);x?(r-=0.8*(r-g[i][0]),t||(v-=0.8*(v-g[i][1])),c()):g[i]=[r,v];n||(f[i]=q-m,f[l]=p);f=n?1/o:o;e[l]=p;e[i]=b;d[n?a?"scaleY":"scaleX":"scale"+j]=o;d["translate"+j]=f*m+(r-f*u)},pinch:function(a){var b=this,c=b.chart,d=b.pinchDown,e=c.tooltip&&c.tooltip.options.followTouchMove,f=a.touches, +g=f.length,h=b.lastValidTouch,i=b.zoomHor||b.pinchHor,j=b.zoomVert||b.pinchVert,k=i||j,l=b.selectionMarker,m={},p=g===1&&(b.inClass(a.target,"highcharts-tracker")&&c.runTrackerClick||c.runChartClick),q={};(k||e)&&!p&&a.preventDefault();Na(f,function(a){return b.normalize(a)});if(a.type==="touchstart")n(f,function(a,b){d[b]={chartX:a.chartX,chartY:a.chartY}}),h.x=[d[0].chartX,d[1]&&d[1].chartX],h.y=[d[0].chartY,d[1]&&d[1].chartY],n(c.axes,function(a){if(a.zoomEnabled){var b=c.bounds[a.horiz?"h":"v"], +d=a.minPixelPadding,e=a.toPixels(a.dataMin),f=a.toPixels(a.dataMax),g=I(e,f),e=s(e,f);b.min=I(a.pos,g-d);b.max=s(a.pos+a.len,e+d)}});else if(d.length){if(!l)b.selectionMarker=l=r({destroy:pa},c.plotBox);i&&b.pinchTranslateDirection(!0,d,f,m,l,q,h);j&&b.pinchTranslateDirection(!1,d,f,m,l,q,h);b.hasPinched=k;b.scaleGroups(m,q);!k&&e&&g===1&&this.runPointActions(b.normalize(a))}},dragStart:function(a){var b=this.chart;b.mouseIsDown=a.type;b.cancelClick=!1;b.mouseDownX=this.mouseDownX=a.chartX;b.mouseDownY= +this.mouseDownY=a.chartY},drag:function(a){var b=this.chart,c=b.options.chart,d=a.chartX,e=a.chartY,f=this.zoomHor,g=this.zoomVert,h=b.plotLeft,i=b.plotTop,j=b.plotWidth,k=b.plotHeight,l,m=this.mouseDownX,p=this.mouseDownY;dh+j&&(d=h+j);ei+k&&(e=i+k);this.hasDragged=Math.sqrt(Math.pow(m-d,2)+Math.pow(p-e,2));if(this.hasDragged>10){l=b.isInsidePlot(m-h,p-i);if(b.hasCartesianSeries&&(this.zoomX||this.zoomY)&&l&&!this.selectionMarker)this.selectionMarker=b.renderer.rect(h,i,f?1:j,g? +1:k,0).attr({fill:c.selectionMarkerFill||"rgba(69,114,167,0.25)",zIndex:7}).add();this.selectionMarker&&f&&(d-=m,this.selectionMarker.attr({width:N(d),x:(d>0?0:d)+m}));this.selectionMarker&&g&&(d=e-p,this.selectionMarker.attr({height:N(d),y:(d>0?0:d)+p}));l&&!this.selectionMarker&&c.panning&&b.pan(a,c.panning)}},drop:function(a){var b=this.chart,c=this.hasPinched;if(this.selectionMarker){var d={xAxis:[],yAxis:[],originalEvent:a.originalEvent||a},e=this.selectionMarker,f=e.x,g=e.y,h;if(this.hasDragged|| +c)n(b.axes,function(a){if(a.zoomEnabled){var b=a.horiz,c=a.toValue(b?f:g),b=a.toValue(b?f+e.width:g+e.height);!isNaN(c)&&!isNaN(b)&&(d[a.xOrY+"Axis"].push({axis:a,min:I(c,b),max:s(c,b)}),h=!0)}}),h&&z(b,"selection",d,function(a){b.zoom(r(a,c?{animation:!1}:null))});this.selectionMarker=this.selectionMarker.destroy();c&&this.scaleGroups()}if(b)K(b.container,{cursor:b._cursor}),b.cancelClick=this.hasDragged>10,b.mouseIsDown=this.hasDragged=this.hasPinched=!1,this.pinchDown=[]},onContainerMouseDown:function(a){a= +this.normalize(a);a.preventDefault&&a.preventDefault();this.dragStart(a)},onDocumentMouseUp:function(a){this.drop(a)},onDocumentMouseMove:function(a){var b=this.chart,c=this.chartPosition,d=b.hoverSeries,a=this.normalize(a,c);c&&d&&!this.inClass(a.target,"highcharts-tracker")&&!b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)&&this.reset()},onContainerMouseLeave:function(){this.reset();this.chartPosition=null},onContainerMouseMove:function(a){var b=this.chart,a=this.normalize(a);a.returnValue= +!1;b.mouseIsDown==="mousedown"&&this.drag(a);(this.inClass(a.target,"highcharts-tracker")||b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop))&&!b.openMenu&&this.runPointActions(a)},inClass:function(a,b){for(var c;a;){if(c=v(a,"class"))if(c.indexOf(b)!==-1)return!0;else if(c.indexOf("highcharts-container")!==-1)return!1;a=a.parentNode}},onTrackerMouseOut:function(a){var b=this.chart.hoverSeries;if(b&&!b.options.stickyTracking&&!this.inClass(a.toElement||a.relatedTarget,"highcharts-tooltip"))b.onMouseOut()}, +onContainerClick:function(a){var b=this.chart,c=b.hoverPoint,d=b.plotLeft,e=b.plotTop,f=b.inverted,g,h,i,a=this.normalize(a);a.cancelBubble=!0;if(!b.cancelClick)c&&this.inClass(a.target,"highcharts-tracker")?(g=this.chartPosition,h=c.plotX,i=c.plotY,r(c,{pageX:g.left+d+(f?b.plotWidth-i:h),pageY:g.top+e+(f?b.plotHeight-h:i)}),z(c.series,"click",r(a,{point:c})),b.hoverPoint&&c.firePointEvent("click",a)):(r(a,this.getCoordinates(a)),b.isInsidePlot(a.chartX-d,a.chartY-e)&&z(b,"click",a))},onContainerTouchStart:function(a){var b= +this.chart;a.touches.length===1?(a=this.normalize(a),b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)?(this.runPointActions(a),this.pinch(a)):this.reset()):a.touches.length===2&&this.pinch(a)},onContainerTouchMove:function(a){(a.touches.length===1||a.touches.length===2)&&this.pinch(a)},onDocumentTouchEnd:function(a){this.drop(a)},setDOMEvents:function(){var a=this,b=a.chart.container,c;this._events=c=[[b,"onmousedown","onContainerMouseDown"],[b,"onmousemove","onContainerMouseMove"],[b,"onclick", +"onContainerClick"],[b,"mouseleave","onContainerMouseLeave"],[y,"mousemove","onDocumentMouseMove"],[y,"mouseup","onDocumentMouseUp"]];ib&&c.push([b,"ontouchstart","onContainerTouchStart"],[b,"ontouchmove","onContainerTouchMove"],[y,"touchend","onDocumentTouchEnd"]);n(c,function(b){a["_"+b[2]]=function(c){a[b[2]](c)};b[1].indexOf("on")===0?b[0][b[1]]=a["_"+b[2]]:J(b[0],b[1],a["_"+b[2]])})},destroy:function(){var a=this;n(a._events,function(b){b[1].indexOf("on")===0?b[0][b[1]]=null:aa(b[0],b[1],a["_"+ +b[2]])});delete a._events;clearInterval(a.tooltipTimeout)}};eb.prototype={init:function(a,b){var c=this,d=b.itemStyle,e=o(b.padding,8),f=b.itemMarginTop||0;this.options=b;if(b.enabled)c.baseline=C(d.fontSize)+3+f,c.itemStyle=d,c.itemHiddenStyle=x(d,b.itemHiddenStyle),c.itemMarginTop=f,c.padding=e,c.initialItemX=e,c.initialItemY=e-5,c.maxItemWidth=0,c.chart=a,c.itemHeight=0,c.lastLineHeight=0,c.render(),J(c.chart,"endResize",function(){c.positionCheckboxes()})},colorizeItem:function(a,b){var c=this.options, +d=a.legendItem,e=a.legendLine,f=a.legendSymbol,g=this.itemHiddenStyle.color,c=b?c.itemStyle.color:g,h=b?a.color:g,g=a.options&&a.options.marker,i={stroke:h,fill:h},j;d&&d.css({fill:c,color:c});e&&e.attr({stroke:h});if(f){if(g&&f.isMarker)for(j in g=a.convertAttribs(g),g)d=g[j],d!==w&&(i[j]=d);f.attr(i)}},positionItem:function(a){var b=this.options,c=b.symbolPadding,b=!b.rtl,d=a._legendItemPos,e=d[0],d=d[1],f=a.checkbox;a.legendGroup&&a.legendGroup.translate(b?e:this.legendWidth-e-2*c-4,d);if(f)f.x= +e,f.y=d},destroyItem:function(a){var b=a.checkbox;n(["legendItem","legendLine","legendSymbol","legendGroup"],function(b){a[b]&&(a[b]=a[b].destroy())});b&&Ta(a.checkbox)},destroy:function(){var a=this.group,b=this.box;if(b)this.box=b.destroy();if(a)this.group=a.destroy()},positionCheckboxes:function(a){var b=this.group.alignAttr,c,d=this.clipHeight||this.legendHeight;if(b)c=b.translateY,n(this.allItems,function(e){var f=e.checkbox,g;f&&(g=c+f.y+(a||0)+3,K(f,{left:b.translateX+e.legendItemWidth+f.x- +20+"px",top:g+"px",display:g>c-6&&g(p||c.chartWidth-2*k-A))b.itemX=A,b.itemY+=n+b.lastLineHeight+q,b.lastLineHeight=0;b.maxItemWidth=s(b.maxItemWidth,e);b.lastItemY=n+b.itemY+q;b.lastLineHeight=s(g,b.lastLineHeight);a._legendItemPos=[b.itemX,b.itemY];f?b.itemX+=e:(b.itemY+=n+g+q,b.lastLineHeight=g);b.offsetWidth= +p||s((f?b.itemX-A-l:e)+k,b.offsetWidth)},render:function(){var a=this,b=a.chart,c=b.renderer,d=a.group,e,f,g,h,i=a.box,j=a.options,k=a.padding,l=j.borderWidth,m=j.backgroundColor;a.itemX=a.initialItemX;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;if(!d)a.group=d=c.g("legend").attr({zIndex:7}).add(),a.contentGroup=c.g().attr({zIndex:1}).add(d),a.scrollGroup=c.g().add(a.contentGroup);a.renderTitle();e=[];n(b.series,function(a){var b=a.options;b.showInLegend&&!u(b.linkedTo)&&(e=e.concat(a.legendItems|| +(b.legendType==="point"?a.data:a)))});Kb(e,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});j.reversed&&e.reverse();a.allItems=e;a.display=f=!!e.length;n(e,function(b){a.renderItem(b)});g=j.width||a.offsetWidth;h=a.lastItemY+a.lastLineHeight+a.titleHeight;h=a.handleOverflow(h);if(l||m){g+=k;h+=k;if(i){if(g>0&&h>0)i[i.isNew?"attr":"animate"](i.crisp(null,null,null,g,h)),i.isNew=!1}else a.box=i=c.rect(0,0,g,h,j.borderRadius,l||0).attr({stroke:j.borderColor, +"stroke-width":l||0,fill:m||S}).add(d).shadow(j.shadow),i.isNew=!0;i[f?"show":"hide"]()}a.legendWidth=g;a.legendHeight=h;n(e,function(b){a.positionItem(b)});f&&d.align(r({width:g,height:h},j),!0,"spacingBox");b.isResizing||this.positionCheckboxes()},handleOverflow:function(a){var b=this,c=this.chart,d=c.renderer,e=this.options,f=e.y,f=c.spacingBox.height+(e.verticalAlign==="top"?-f:f)-this.padding,g=e.maxHeight,h=this.clipRect,i=e.navigation,j=o(i.animation,!0),k=i.arrowSize||12,l=this.nav;e.layout=== +"horizontal"&&(f/=2);g&&(f=I(f,g));if(a>f&&!e.useHTML){this.clipHeight=c=f-20-this.titleHeight;this.pageCount=xa(a/c);this.currentPage=o(this.currentPage,1);this.fullHeight=a;if(!h)h=b.clipRect=d.clipRect(0,0,9999,0),b.contentGroup.clip(h);h.attr({height:c});if(!l)this.nav=l=d.g().attr({zIndex:1}).add(this.group),this.up=d.symbol("triangle",0,0,k,k).on("click",function(){b.scroll(-1,j)}).add(l),this.pager=d.text("",15,10).css(i.style).add(l),this.down=d.symbol("triangle-down",0,0,k,k).on("click", +function(){b.scroll(1,j)}).add(l);b.scroll(0);a=f}else if(l)h.attr({height:c.chartHeight}),l.hide(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0;return a},scroll:function(a,b){var c=this.pageCount,d=this.currentPage+a,e=this.clipHeight,f=this.options.navigation,g=f.activeColor,h=f.inactiveColor,f=this.pager,i=this.padding;d>c&&(d=c);if(d>0)b!==w&&La(b,this.chart),this.nav.attr({translateX:i,translateY:e+7+this.titleHeight,visibility:"visible"}),this.up.attr({fill:d===1?h:g}).css({cursor:d=== +1?"default":"pointer"}),f.attr({text:d+"/"+this.pageCount}),this.down.attr({x:18+this.pager.getBBox().width,fill:d===c?h:g}).css({cursor:d===c?"default":"pointer"}),e=-I(e*(d-1),this.fullHeight-e+i)+1,this.scrollGroup.animate({translateY:e}),f.attr({text:d+"/"+c}),this.currentPage=d,this.positionCheckboxes(e)}};/Trident.*?11\.0/.test(oa)&&mb(eb.prototype,"positionItem",function(a,b){var c=this;setTimeout(function(){a.call(c,b)})});yb.prototype={init:function(a,b){var c,d=a.series;a.series=null;c= +x(M,a);c.series=a.series=d;d=c.chart;this.margin=this.splashArray("margin",d);this.spacing=this.splashArray("spacing",d);var e=d.events;this.bounds={h:{},v:{}};this.callback=b;this.isResizing=0;this.options=c;this.axes=[];this.series=[];this.hasCartesianSeries=d.showAxes;var f=this,g;f.index=Ga.length;Ga.push(f);d.reflow!==!1&&J(f,"load",function(){f.initReflow()});if(e)for(g in e)J(f,g,e[g]);f.xAxis=[];f.yAxis=[];f.animation=$?!1:o(d.animation,!0);f.pointCount=0;f.counters=new Jb;f.firstRender()}, +initSeries:function(a){var b=this.options.chart;(b=W[a.type||b.type||b.defaultSeriesType])||ka(17,!0);b=new b;b.init(this,a);return b},addSeries:function(a,b,c){var d,e=this;a&&(b=o(b,!0),z(e,"addSeries",{options:a},function(){d=e.initSeries(a);e.isDirtyLegend=!0;e.linkSeries();b&&e.redraw(c)}));return d},addAxis:function(a,b,c,d){var e=b?"xAxis":"yAxis",f=this.options;new db(this,x(a,{index:this[e].length,isX:b}));f[e]=ja(f[e]||{});f[e].push(a);o(c,!0)&&this.redraw(d)},isInsidePlot:function(a,b, +c){var d=c?b:a,a=c?a:b;return d>=0&&d<=this.plotWidth&&a>=0&&a<=this.plotHeight},adjustTickAmounts:function(){this.options.chart.alignTicks!==!1&&n(this.axes,function(a){a.adjustTickAmount()});this.maxTicks=null},redraw:function(a){var b=this.axes,c=this.series,d=this.pointer,e=this.legend,f=this.isDirtyLegend,g,h,i=this.isDirtyBox,j=c.length,k=j,l=this.renderer,m=l.isHidden(),p=[];La(a,this);m&&this.cloneRenderTo();for(this.layOutTitles();k--;)if(a=c[k],a.options.stacking&&(g=!0,a.isDirty)){h=!0; +break}if(h)for(k=j;k--;)if(a=c[k],a.options.stacking)a.isDirty=!0;n(c,function(a){a.isDirty&&a.options.legendType==="point"&&(f=!0)});if(f&&e.options.enabled)e.render(),this.isDirtyLegend=!1;g&&this.getStacks();if(this.hasCartesianSeries){if(!this.isResizing)this.maxTicks=null,n(b,function(a){a.setScale()});this.adjustTickAmounts();this.getMargins();n(b,function(a){a.isDirty&&(i=!0)});n(b,function(a){if(a.isDirtyExtremes)a.isDirtyExtremes=!1,p.push(function(){z(a,"afterSetExtremes",r(a.eventArgs, +a.getExtremes()));delete a.eventArgs});(i||g)&&a.redraw()})}i&&this.drawChartBox();n(c,function(a){a.isDirty&&a.visible&&(!a.isCartesian||a.xAxis)&&a.redraw()});d&&d.reset&&d.reset(!0);l.draw();z(this,"redraw");m&&this.cloneRenderTo(!0);n(p,function(a){a.call()})},showLoading:function(a){var b=this.options,c=this.loadingDiv,d=b.loading;if(!c)this.loadingDiv=c=U(Ea,{className:"highcharts-loading"},r(d.style,{zIndex:10,display:S}),this.container),this.loadingSpan=U("span",null,d.labelStyle,c);this.loadingSpan.innerHTML= +a||b.lang.loading;if(!this.loadingShown)K(c,{opacity:0,display:"",left:this.plotLeft+"px",top:this.plotTop+"px",width:this.plotWidth+"px",height:this.plotHeight+"px"}),Bb(c,{opacity:d.style.opacity},{duration:d.showDuration||0}),this.loadingShown=!0},hideLoading:function(){var a=this.options,b=this.loadingDiv;b&&Bb(b,{opacity:0},{duration:a.loading.hideDuration||100,complete:function(){K(b,{display:S})}});this.loadingShown=!1},get:function(a){var b=this.axes,c=this.series,d,e;for(d=0;dI(k.dataMin,k.min)&&i=18&&a<=25&&(a=15);c&&(c.css({width:(d.width||f)+"px"}).align(r({y:a+e.margin},d),!1,"spacingBox"),!d.floating&&!d.verticalAlign&&(a=xa(a+c.getBBox().height)));this.titleOffset= +a},getChartSize:function(){var a=this.options.chart,b=this.renderToClone||this.renderTo;this.containerWidth=jb(b,"width");this.containerHeight=jb(b,"height");this.chartWidth=s(0,a.width||this.containerWidth||600);this.chartHeight=s(0,o(a.height,this.containerHeight>19?this.containerHeight:400))},cloneRenderTo:function(a){var b=this.renderToClone,c=this.container;a?b&&(this.renderTo.appendChild(c),Ta(b),delete this.renderToClone):(c&&c.parentNode===this.renderTo&&this.renderTo.removeChild(c),this.renderToClone= +b=this.renderTo.cloneNode(0),K(b,{position:"absolute",top:"-9999px",display:"block"}),y.body.appendChild(b),c&&b.appendChild(c))},getContainer:function(){var a,b=this.options.chart,c,d,e;this.renderTo=a=b.renderTo;e="highcharts-"+zb++;if(ea(a))this.renderTo=a=y.getElementById(a);a||ka(13,!0);c=C(v(a,"data-highcharts-chart"));!isNaN(c)&&Ga[c]&&Ga[c].destroy();v(a,"data-highcharts-chart",this.index);a.innerHTML="";a.offsetWidth||this.cloneRenderTo();this.getChartSize();c=this.chartWidth;d=this.chartHeight; +this.container=a=U(Ea,{className:"highcharts-container"+(b.className?" "+b.className:""),id:e},r({position:"relative",overflow:"hidden",width:c+"px",height:d+"px",textAlign:"left",lineHeight:"normal",zIndex:0,"-webkit-tap-highlight-color":"rgba(0,0,0,0)"},b.style),this.renderToClone||a);this._cursor=a.style.cursor;this.renderer=b.forExport?new Ha(a,c,d,!0):new Va(a,c,d);$&&this.renderer.create(this,a,c,d)},getMargins:function(){var a=this.spacing,b,c=this.legend,d=this.margin,e=this.options.legend, +f=o(e.margin,10),g=e.x,h=e.y,i=e.align,j=e.verticalAlign,k=this.titleOffset;this.resetMargins();b=this.axisOffset;if(k&&!u(d[0]))this.plotTop=s(this.plotTop,k+this.options.title.margin+a[0]);if(c.display&&!e.floating)if(i==="right"){if(!u(d[1]))this.marginRight=s(this.marginRight,c.legendWidth-g+f+a[1])}else if(i==="left"){if(!u(d[3]))this.plotLeft=s(this.plotLeft,c.legendWidth+g+f+a[3])}else if(j==="top"){if(!u(d[0]))this.plotTop=s(this.plotTop,c.legendHeight+h+f+a[0])}else if(j==="bottom"&&!u(d[2]))this.marginBottom= +s(this.marginBottom,c.legendHeight-h+f+a[2]);this.extraBottomMargin&&(this.marginBottom+=this.extraBottomMargin);this.extraTopMargin&&(this.plotTop+=this.extraTopMargin);this.hasCartesianSeries&&n(this.axes,function(a){a.getOffset()});u(d[3])||(this.plotLeft+=b[3]);u(d[0])||(this.plotTop+=b[0]);u(d[2])||(this.marginBottom+=b[2]);u(d[1])||(this.marginRight+=b[1]);this.setChartSize()},initReflow:function(){function a(a){var g=c.width||jb(d,"width"),h=c.height||jb(d,"height"),a=a?a.target:O;if(!b.hasUserSize&& +g&&h&&(a===O||a===y)){if(g!==b.containerWidth||h!==b.containerHeight)clearTimeout(e),b.reflowTimeout=e=setTimeout(function(){if(b.container)b.setSize(g,h,!1),b.hasUserSize=null},100);b.containerWidth=g;b.containerHeight=h}}var b=this,c=b.options.chart,d=b.renderTo,e;b.reflow=a;J(O,"resize",a);J(b,"destroy",function(){aa(O,"resize",a)})},setSize:function(a,b,c){var d=this,e,f,g;d.isResizing+=1;g=function(){d&&z(d,"endResize",null,function(){d.isResizing-=1})};La(c,d);d.oldChartHeight=d.chartHeight; +d.oldChartWidth=d.chartWidth;if(u(a))d.chartWidth=e=s(0,t(a)),d.hasUserSize=!!e;if(u(b))d.chartHeight=f=s(0,t(b));K(d.container,{width:e+"px",height:f+"px"});d.setChartSize(!0);d.renderer.setSize(e,f,c);d.maxTicks=null;n(d.axes,function(a){a.isDirty=!0;a.setScale()});n(d.series,function(a){a.isDirty=!0});d.isDirtyLegend=!0;d.isDirtyBox=!0;d.getMargins();d.redraw(c);d.oldChartHeight=null;z(d,"resize");Fa===!1?g():setTimeout(g,Fa&&Fa.duration||500)},setChartSize:function(a){var b=this.inverted,c=this.renderer, +d=this.chartWidth,e=this.chartHeight,f=this.options.chart,g=this.spacing,h=this.clipOffset,i,j,k,l;this.plotLeft=i=t(this.plotLeft);this.plotTop=j=t(this.plotTop);this.plotWidth=k=s(0,t(d-i-this.marginRight));this.plotHeight=l=s(0,t(e-j-this.marginBottom));this.plotSizeX=b?l:k;this.plotSizeY=b?k:l;this.plotBorderWidth=f.plotBorderWidth||0;this.spacingBox=c.spacingBox={x:g[3],y:g[0],width:d-g[3]-g[1],height:e-g[0]-g[2]};this.plotBox=c.plotBox={x:i,y:j,width:k,height:l};d=2*P(this.plotBorderWidth/2); +b=xa(s(d,h[3])/2);c=xa(s(d,h[0])/2);this.clipBox={x:b,y:c,width:P(this.plotSizeX-s(d,h[1])/2-b),height:P(this.plotSizeY-s(d,h[2])/2-c)};a||n(this.axes,function(a){a.setAxisSize();a.setAxisTranslation()})},resetMargins:function(){var a=this.spacing,b=this.margin;this.plotTop=o(b[0],a[0]);this.marginRight=o(b[1],a[1]);this.marginBottom=o(b[2],a[2]);this.plotLeft=o(b[3],a[3]);this.axisOffset=[0,0,0,0];this.clipOffset=[0,0,0,0]},drawChartBox:function(){var a=this.options.chart,b=this.renderer,c=this.chartWidth, +d=this.chartHeight,e=this.chartBackground,f=this.plotBackground,g=this.plotBorder,h=this.plotBGImage,i=a.borderWidth||0,j=a.backgroundColor,k=a.plotBackgroundColor,l=a.plotBackgroundImage,m=a.plotBorderWidth||0,p,q=this.plotLeft,o=this.plotTop,n=this.plotWidth,s=this.plotHeight,t=this.plotBox,u=this.clipRect,r=this.clipBox;p=i+(a.shadow?8:0);if(i||j)if(e)e.animate(e.crisp(null,null,null,c-p,d-p));else{e={fill:j||S};if(i)e.stroke=a.borderColor,e["stroke-width"]=i;this.chartBackground=b.rect(p/2,p/ +2,c-p,d-p,a.borderRadius,i).attr(e).add().shadow(a.shadow)}if(k)f?f.animate(t):this.plotBackground=b.rect(q,o,n,s,0).attr({fill:k}).add().shadow(a.plotShadow);if(l)h?h.animate(t):this.plotBGImage=b.image(l,q,o,n,s).add();u?u.animate({width:r.width,height:r.height}):this.clipRect=b.clipRect(r);if(m)g?g.animate(g.crisp(null,q,o,n,s)):this.plotBorder=b.rect(q,o,n,s,0,-m).attr({stroke:a.plotBorderColor,"stroke-width":m,zIndex:1}).add();this.isDirtyBox=!1},propFromSeries:function(){var a=this,b=a.options.chart, +c,d=a.options.series,e,f;n(["inverted","angular","polar"],function(g){c=W[b.type||b.defaultSeriesType];f=a[g]||b[g]||c&&c.prototype[g];for(e=d&&d.length;!f&&e--;)(c=W[d[e].type])&&c.prototype[g]&&(f=!0);a[g]=f})},linkSeries:function(){var a=this,b=a.series;n(b,function(a){a.linkedSeries.length=0});n(b,function(b){var d=b.options.linkedTo;if(ea(d)&&(d=d===":previous"?a.series[b.index-1]:a.get(d)))d.linkedSeries.push(b),b.linkedParent=d})},render:function(){var a=this,b=a.axes,c=a.renderer,d=a.options, +e=d.labels,f=d.credits,g;a.setTitle();a.legend=new eb(a,d.legend);a.getStacks();n(b,function(a){a.setScale()});a.getMargins();a.maxTicks=null;n(b,function(a){a.setTickPositions(!0);a.setMaxTicks()});a.adjustTickAmounts();a.getMargins();a.drawChartBox();a.hasCartesianSeries&&n(b,function(a){a.render()});if(!a.seriesGroup)a.seriesGroup=c.g("series-group").attr({zIndex:3}).add();n(a.series,function(a){a.translate();a.setTooltipPoints();a.render()});e.items&&n(e.items,function(b){var d=r(e.style,b.style), +f=C(d.left)+a.plotLeft,g=C(d.top)+a.plotTop+12;delete d.left;delete d.top;c.text(b.html,f,g).attr({zIndex:2}).css(d).add()});if(f.enabled&&!a.credits)g=f.href,a.credits=c.text(f.text,0,0).on("click",function(){if(g)location.href=g}).attr({align:f.position.align,zIndex:8}).css(f.style).add().align(f.position);a.hasRendered=!0},destroy:function(){var a=this,b=a.axes,c=a.series,d=a.container,e,f=d&&d.parentNode;z(a,"destroy");Ga[a.index]=w;a.renderTo.removeAttribute("data-highcharts-chart");aa(a);for(e= +b.length;e--;)b[e]=b[e].destroy();for(e=c.length;e--;)c[e]=c[e].destroy();n("title,subtitle,chartBackground,plotBackground,plotBGImage,plotBorder,seriesGroup,clipRect,credits,pointer,scroller,rangeSelector,legend,resetZoomButton,tooltip,renderer".split(","),function(b){var c=a[b];c&&c.destroy&&(a[b]=c.destroy())});if(d)d.innerHTML="",aa(d),f&&Ta(d);for(e in a)delete a[e]},isReadyToRender:function(){var a=this;return!Z&&O==O.top&&y.readyState!=="complete"||$&&!O.canvg?($?Tb.push(function(){a.firstRender()}, +a.options.global.canvasToolsURL):y.attachEvent("onreadystatechange",function(){y.detachEvent("onreadystatechange",a.firstRender);y.readyState==="complete"&&a.firstRender()}),!1):!0},firstRender:function(){var a=this,b=a.options,c=a.callback;if(a.isReadyToRender())a.getContainer(),z(a,"init"),a.resetMargins(),a.setChartSize(),a.propFromSeries(),a.getAxes(),n(b.series||[],function(b){a.initSeries(b)}),a.linkSeries(),z(a,"beforeRender"),a.pointer=new xb(a,b),a.render(),a.renderer.draw(),c&&c.apply(a, +[a]),n(a.callbacks,function(b){b.apply(a,[a])}),a.cloneRenderTo(!0),z(a,"load")},splashArray:function(a,b){var c=b[a],c=T(c)?c:[c,c,c,c];return[o(b[a+"Top"],c[0]),o(b[a+"Right"],c[1]),o(b[a+"Bottom"],c[2]),o(b[a+"Left"],c[3])]}};yb.prototype.callbacks=[];var Pa=function(){};Pa.prototype={init:function(a,b,c){this.series=a;this.applyOptions(b,c);this.pointAttr={};if(a.options.colorByPoint&&(b=a.options.colors||a.chart.options.colors,this.color=this.color||b[a.colorCounter++],a.colorCounter===b.length))a.colorCounter= +0;a.chart.pointCount++;return this},applyOptions:function(a,b){var c=this.series,d=c.pointValKey,a=Pa.prototype.optionsToObject.call(this,a);r(this,a);this.options=this.options?r(this.options,a):a;if(d)this.y=this[d];if(this.x===w&&c)this.x=b===w?c.autoIncrement():b;return this},optionsToObject:function(a){var b,c=this.series,d=c.pointArrayMap||["y"],e=d.length,f=0,g=0;if(typeof a==="number"||a===null)b={y:a};else if(Ia(a)){b={};if(a.length>e){c=typeof a[0];if(c==="string")b.name=a[0];else if(c=== +"number")b.x=a[0];f++}for(;ga+1&&b.push(d.slice(a+1,g)),a=g):g===e-1&&b.push(d.slice(a+1,g+1))});this.segments=b},setOptions:function(a){var b=this.chart.options,c=b.plotOptions,d=c[this.type];this.userOptions=a;a=x(d,c.series, +a);this.tooltipOptions=x(b.tooltip,a.tooltip);d.marker===null&&delete a.marker;return a},getColor:function(){var a=this.options,b=this.userOptions,c=this.chart.options.colors,d=this.chart.counters,e;e=a.color||Y[this.type].color;if(!e&&!a.colorByPoint)u(b._colorIndex)?a=b._colorIndex:(b._colorIndex=d.color,a=d.color++),e=c[a];this.color=e;d.wrapColor(c.length)},getSymbol:function(){var a=this.userOptions,b=this.options.marker,c=this.chart,d=c.options.symbols,c=c.counters;this.symbol=b.symbol;if(!this.symbol)u(a._symbolIndex)? +a=a._symbolIndex:(a._symbolIndex=c.symbol,a=c.symbol++),this.symbol=d[a];if(/^url/.test(this.symbol))b.radius=0;c.wrapSymbol(d.length)},drawLegendSymbol:function(a){var b=this.options,c=b.marker,d=a.options,e;e=d.symbolWidth;var f=this.chart.renderer,g=this.legendGroup,a=a.baseline-t(f.fontMetrics(d.itemStyle.fontSize).b*0.3);if(b.lineWidth){d={"stroke-width":b.lineWidth};if(b.dashStyle)d.dashstyle=b.dashStyle;this.legendLine=f.path(["M",0,a,"L",e,a]).attr(d).add(g)}if(c&&c.enabled)b=c.radius,this.legendSymbol= +e=f.symbol(this.symbol,e/2-b,a-b,2*b,2*b).add(g),e.isMarker=!0},addPoint:function(a,b,c,d){var e=this.options,f=this.data,g=this.graph,h=this.area,i=this.chart,j=this.xData,k=this.yData,l=this.zData,m=this.names,p=g&&g.shift||0,q=e.data,s;La(d,i);c&&n([g,h,this.graphNeg,this.areaNeg],function(a){if(a)a.shift=p+1});if(h)h.isArea=!0;b=o(b,!0);d={series:this};this.pointClass.prototype.applyOptions.apply(d,[a]);g=d.x;h=j.length;if(this.requireSorting&&gg;)h--;j.splice(h,0,g); +k.splice(h,0,this.toYData?this.toYData(d):d.y);l.splice(h,0,d.z);if(m)m[g]=d.name;q.splice(h,0,a);s&&(this.data.splice(h,0,null),this.processData());e.legendType==="point"&&this.generatePoints();c&&(f[0]&&f[0].remove?f[0].remove(!1):(f.shift(),j.shift(),k.shift(),l.shift(),q.shift()));this.isDirtyData=this.isDirty=!0;b&&(this.getAttribs(),i.redraw())},setData:function(a,b){var c=this.points,d=this.options,e=this.chart,f=null,g=this.xAxis,h=g&&g.categories&&!g.categories.length?[]:null,i;this.xIncrement= +null;this.pointRange=g&&g.categories?1:d.pointRange;this.colorCounter=0;var j=[],k=[],l=[],m=a?a.length:[];i=o(d.turboThreshold,1E3);var p=this.pointArrayMap,p=p&&p.length,q=!!this.toYData;if(i&&m>i){for(i=0;f===null&&ij||this.forceCrop))if(a=h.min,h=h.max,b[d-1]h)b=[],c=[];else if(b[0]h)e=this.cropData(this.xData,this.yData,a,h),b=e.xData,c=e.yData,e=e.start, +f=!0;for(h=b.length-1;h>=0;h--)d=b[h]-b[h-1],d>0&&(g===w||d=c){f=s(0,i-h);break}for(;id){g=i+h;break}return{xData:a.slice(f,g),yData:b.slice(f,g),start:f,end:g}},generatePoints:function(){var a=this.options.data, +b=this.data,c,d=this.processedXData,e=this.processedYData,f=this.pointClass,g=d.length,h=this.cropStart||0,i,j=this.hasGroupedData,k,l=[],m;if(!b&&!j)b=[],b.length=a.length,b=this.data=b;for(m=0;m0),j=this.getExtremesFromAll||this.cropped||(b[l+1]||j)>=h&&(b[l-1]||j)<=g,i&&j)if(i=k.length)for(;i--;)k[i]!==null&&(e[f++]=k[i]);else e[f++]=k;this.dataMin=o(void 0,Ja(e));this.dataMax=o(void 0,va(e))},translate:function(){this.processedXData|| +this.processData();this.generatePoints();for(var a=this.options,b=a.stacking,c=this.xAxis,d=c.categories,e=this.yAxis,f=this.points,g=f.length,h=!!this.modifyValue,i=a.pointPlacement,j=i==="between"||sa(i),k=a.threshold,a=0;a=f.min&&c<=f.max){h=b[i+1];c=d===w?0:d+1;for(d=b[i+1]?I(s(0,P((e.clientX+(h?h.wrappedClientX||h.clientX:g))/2)),g):g;c>=0&&c<=d;)j[c++]=e}this.tooltipPoints=j}},tooltipHeaderFormatter:function(a){var b=this.tooltipOptions,c=b.xDateFormat, +d=b.dateTimeLabelFormats,e=this.xAxis,f=e&&e.options.type==="datetime",b=b.headerFormat,e=e&&e.closestPointRange,g;if(f&&!c)if(e)for(g in D){if(D[g]>=e){c=d[g];break}}else c=d.day;f&&c&&sa(a.key)&&(b=b.replace("{point.key}","{point.key:"+c+"}"));return Ca(b,{point:a,series:this})},onMouseOver:function(){var a=this.chart,b=a.hoverSeries;if(b&&b!==this)b.onMouseOut();this.options.events.mouseOver&&z(this,"mouseOver");this.setState("hover");a.hoverSeries=this},onMouseOut:function(){var a=this.options, +b=this.chart,c=b.tooltip,d=b.hoverPoint;if(d)d.onMouseOut();this&&a.events.mouseOut&&z(this,"mouseOut");c&&!a.stickyTracking&&(!c.shared||this.noSharedTooltip)&&c.hide();this.setState();b.hoverSeries=null},animate:function(a){var b=this,c=b.chart,d=c.renderer,e;e=b.options.animation;var f=c.clipBox,g=c.inverted,h;if(e&&!T(e))e=Y[b.type].animation;h="_sharedClip"+e.duration+e.easing;if(a)a=c[h],e=c[h+"m"],a||(c[h]=a=d.clipRect(r(f,{width:0})),c[h+"m"]=e=d.clipRect(-99,g?-c.plotLeft:-c.plotTop,99,g? +c.chartWidth:c.chartHeight)),b.group.clip(a),b.markerGroup.clip(e),b.sharedClipKey=h;else{if(a=c[h])a.animate({width:c.plotSizeX},e),c[h+"m"].animate({width:c.plotSizeX+99},e);b.animate=null;b.animationTimeout=setTimeout(function(){b.afterAnimate()},e.duration)}},afterAnimate:function(){var a=this.chart,b=this.sharedClipKey,c=this.group;c&&this.options.clip!==!1&&(c.clip(a.clipRect),this.markerGroup.clip());setTimeout(function(){b&&a[b]&&(a[b]=a[b].destroy(),a[b+"m"]=a[b+"m"].destroy())},100)},drawPoints:function(){var a, +b=this.points,c=this.chart,d,e,f,g,h,i,j,k,l=this.options.marker,m,p=this.markerGroup;if(l.enabled||this._hasPointMarkers)for(f=b.length;f--;)if(g=b[f],d=P(g.plotX),e=g.plotY,k=g.graphic,i=g.marker||{},a=l.enabled&&i.enabled===w||i.enabled,m=c.isInsidePlot(t(d),e,c.inverted),a&&e!==w&&!isNaN(e)&&g.y!==null)if(a=g.pointAttr[g.selected?"select":""],h=a.r,i=o(i.symbol,this.symbol),j=i.indexOf("url")===0,k)k.attr({visibility:m?Z?"inherit":"visible":"hidden"}).animate(r({x:d-h,y:e-h},k.symbolName?{width:2* +h,height:2*h}:{}));else{if(m&&(h>0||j))g.graphic=c.renderer.symbol(i,d-h,e-h,2*h,2*h).attr(a).add(p)}else if(k)g.graphic=k.destroy()},convertAttribs:function(a,b,c,d){var e=this.pointAttrToOptions,f,g,h={},a=a||{},b=b||{},c=c||{},d=d||{};for(f in e)g=e[f],h[f]=o(a[g],b[f],c[f],d[f]);return h},getAttribs:function(){var a=this,b=a.options,c=Y[a.type].marker?b.marker:b,d=c.states,e=d.hover,f,g=a.color,h={stroke:g,fill:g},i=a.points||[],j=[],k,l=a.pointAttrToOptions,m=b.negativeColor,p=c.lineColor,q; +b.marker?(e.radius=e.radius||c.radius+2,e.lineWidth=e.lineWidth||c.lineWidth+1):e.color=e.color||ra(e.color||g).brighten(e.brightness).get();j[""]=a.convertAttribs(c,h);n(["hover","select"],function(b){j[b]=a.convertAttribs(d[b],j[""])});a.pointAttr=j;for(g=i.length;g--;){h=i[g];if((c=h.options&&h.options.marker||h.options)&&c.enabled===!1)c.radius=0;if(h.negative&&m)h.color=h.fillColor=m;f=b.colorByPoint||h.color;if(h.options)for(q in l)u(c[l[q]])&&(f=!0);if(f){c=c||{};k=[];d=c.states||{};f=d.hover= +d.hover||{};if(!b.marker)f.color=ra(f.color||h.color).brighten(f.brightness||e.brightness).get();k[""]=a.convertAttribs(r({color:h.color,fillColor:h.color,lineColor:p===null?h.color:w},c),j[""]);k.hover=a.convertAttribs(d.hover,j.hover,k[""]);k.select=a.convertAttribs(d.select,j.select,k[""])}else k=j;h.pointAttr=k}},update:function(a,b){var c=this.chart,d=this.type,e=W[d].prototype,f,a=x(this.userOptions,{animation:!1,index:this.index,pointStart:this.xData[0]},{data:this.options.data},a);this.remove(!1); +for(f in e)e.hasOwnProperty(f)&&(this[f]=w);r(this,W[a.type||d].prototype);this.init(c,a);o(b,!0)&&c.redraw(!1)},destroy:function(){var a=this,b=a.chart,c=/AppleWebKit\/533/.test(oa),d,e,f=a.data||[],g,h,i;z(a,"destroy");aa(a);n(["xAxis","yAxis"],function(b){if(i=a[b])ga(i.series,a),i.isDirty=i.forceRedraw=!0,i.stacks={}});a.legendItem&&a.chart.legend.destroyItem(a);for(e=f.length;e--;)(g=f[e])&&g.destroy&&g.destroy();a.points=null;clearTimeout(a.animationTimeout);n("area,graph,dataLabelsGroup,group,markerGroup,tracker,graphNeg,areaNeg,posClip,negClip".split(","), +function(b){a[b]&&(d=c&&b==="group"?"hide":"destroy",a[b][d]())});if(b.hoverSeries===a)b.hoverSeries=null;ga(b.series,a);for(h in a)delete a[h]},drawDataLabels:function(){var a=this,b=a.options.dataLabels,c=a.points,d,e,f,g;if(b.enabled||a._hasPointLabels)a.dlProcessOptions&&a.dlProcessOptions(b),g=a.plotGroup("dataLabelsGroup","data-labels",a.visible?"visible":"hidden",b.zIndex||6),e=b,n(c,function(c){var i,j=c.dataLabel,k,l,m=c.connector,p=!0;d=c.options&&c.options.dataLabels;i=o(d&&d.enabled,e.enabled); +if(j&&!i)c.dataLabel=j.destroy();else if(i){b=x(e,d);i=b.rotation;k=c.getLabelConfig();f=b.format?Ca(b.format,k):b.formatter.call(k,b);b.style.color=o(b.color,b.style.color,a.color,"black");if(j)if(u(f))j.attr({text:f}),p=!1;else{if(c.dataLabel=j=j.destroy(),m)c.connector=m.destroy()}else if(u(f)){j={fill:b.backgroundColor,stroke:b.borderColor,"stroke-width":b.borderWidth,r:b.borderRadius||0,rotation:i,padding:b.padding,zIndex:1};for(l in j)j[l]===w&&delete j[l];j=c.dataLabel=a.chart.renderer[i?"text": +"label"](f,0,-999,null,null,null,b.useHTML).attr(j).css(b.style).add(g).shadow(b.shadow)}j&&a.alignDataLabel(c,j,b,null,p)}})},alignDataLabel:function(a,b,c,d,e){var f=this.chart,g=f.inverted,h=o(a.plotX,-999),i=o(a.plotY,-999),j=b.getBBox();if(a=this.visible&&f.isInsidePlot(a.plotX,a.plotY,g))d=r({x:g?f.plotWidth-i:h,y:t(g?f.plotHeight-h:i),width:0,height:0},d),r(c,{width:j.width,height:j.height}),c.rotation?(g={align:c.align,x:d.x+c.x+d.width/2,y:d.y+c.y+d.height/2},b[e?"attr":"animate"](g)):(b.align(c, +null,d),g=b.alignAttr,o(c.overflow,"justify")==="justify"?this.justifyDataLabel(b,c,g,j,d,e):o(c.crop,!0)&&(a=f.isInsidePlot(g.x,g.y)&&f.isInsidePlot(g.x+j.width,g.y+j.height)));a||b.attr({y:-999})},justifyDataLabel:function(a,b,c,d,e,f){var g=this.chart,h=b.align,i=b.verticalAlign,j,k;j=c.x;if(j<0)h==="right"?b.align="left":b.x=-j,k=!0;j=c.x+d.width;if(j>g.plotWidth)h==="left"?b.align="right":b.x=g.plotWidth-j,k=!0;j=c.y;if(j<0)i==="bottom"?b.verticalAlign="top":b.y=-j,k=!0;j=c.y+d.height;if(j>g.plotHeight)i=== +"top"?b.verticalAlign="bottom":b.y=g.plotHeight-j,k=!0;if(k)a.placed=!f,a.align(b,null,e)},getSegmentPath:function(a){var b=this,c=[],d=b.options.step;n(a,function(e,f){var g=e.plotX,h=e.plotY,i;b.getPointSpline?c.push.apply(c,b.getPointSpline(a,e,f)):(c.push(f?"L":"M"),d&&f&&(i=a[f-1],d==="right"?c.push(i.plotX,h):d==="center"?c.push((i.plotX+g)/2,i.plotY,(i.plotX+g)/2,h):c.push(g,i.plotY)),c.push(e.plotX,e.plotY))});return c},getGraphPath:function(){var a=this,b=[],c,d=[];n(a.segments,function(e){c= +a.getSegmentPath(e);e.length>1?b=b.concat(c):d.push(e[0])});a.singlePoints=d;return a.graphPath=b},drawGraph:function(){var a=this,b=this.options,c=[["graph",b.lineColor||this.color]],d=b.lineWidth,e=b.dashStyle,f=this.getGraphPath(),g=b.negativeColor;g&&c.push(["graphNeg",g]);n(c,function(c,g){var j=c[0],k=a[j];if(k)Wa(k),k.animate({d:f});else if(d&&f.length)k={stroke:c[1],"stroke-width":d,zIndex:1},e?k.dashstyle=e:k["stroke-linecap"]=k["stroke-linejoin"]="round",a[j]=a.chart.renderer.path(f).attr(k).add(a.group).shadow(!g&& +b.shadow)})},clipNeg:function(){var a=this.options,b=this.chart,c=b.renderer,d=a.negativeColor||a.negativeFillColor,e,f=this.graph,g=this.area,h=this.posClip,i=this.negClip;e=b.chartWidth;var j=b.chartHeight,k=s(e,j),l=this.yAxis;if(d&&(f||g)){d=t(l.toPixels(a.threshold||0,!0));a={x:0,y:0,width:k,height:d};k={x:0,y:d,width:k,height:k};if(b.inverted)a.height=k.y=b.plotWidth-d,c.isVML&&(a={x:b.plotWidth-d-b.plotLeft,y:0,width:e,height:j},k={x:d+b.plotLeft-e,y:0,width:b.plotLeft+d,height:e});l.reversed? +(b=k,e=a):(b=a,e=k);h?(h.animate(b),i.animate(e)):(this.posClip=h=c.clipRect(b),this.negClip=i=c.clipRect(e),f&&this.graphNeg&&(f.clip(h),this.graphNeg.clip(i)),g&&(g.clip(h),this.areaNeg.clip(i)))}},invertGroups:function(){function a(){var a={width:b.yAxis.len,height:b.xAxis.len};n(["group","markerGroup"],function(c){b[c]&&b[c].attr(a).invert()})}var b=this,c=b.chart;if(b.xAxis)J(c,"resize",a),J(b,"destroy",function(){aa(c,"resize",a)}),a(),b.invertGroups=a},plotGroup:function(a,b,c,d,e){var f=this[a], +g=!f;g&&(this[a]=f=this.chart.renderer.g(b).attr({visibility:c,zIndex:d||0.1}).add(e));f[g?"attr":"animate"](this.getPlotBox());return f},getPlotBox:function(){return{translateX:this.xAxis?this.xAxis.left:this.chart.plotLeft,translateY:this.yAxis?this.yAxis.top:this.chart.plotTop,scaleX:1,scaleY:1}},render:function(){var a=this.chart,b,c=this.options,d=c.animation&&!!this.animate&&a.renderer.isSVG,e=this.visible?"visible":"hidden",f=c.zIndex,g=this.hasRendered,h=a.seriesGroup;b=this.plotGroup("group", +"series",e,f,h);this.markerGroup=this.plotGroup("markerGroup","markers",e,f,h);d&&this.animate(!0);this.getAttribs();b.inverted=this.isCartesian?a.inverted:!1;this.drawGraph&&(this.drawGraph(),this.clipNeg());this.drawDataLabels();this.drawPoints();this.options.enableMouseTracking!==!1&&this.drawTracker();a.inverted&&this.invertGroups();c.clip!==!1&&!this.sharedClipKey&&!g&&b.clip(a.clipRect);d?this.animate():g||this.afterAnimate();this.isDirty=this.isDirtyData=!1;this.hasRendered=!0},redraw:function(){var a= +this.chart,b=this.isDirtyData,c=this.group,d=this.xAxis,e=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:o(d&&d.left,a.plotLeft),translateY:o(e&&e.top,a.plotTop)}));this.translate();this.setTooltipPoints(!0);this.render();b&&z(this,"updatedData")},setState:function(a){var b=this.options,c=this.graph,d=this.graphNeg,e=b.states,b=b.lineWidth,a=a||"";if(this.state!==a)this.state=a,e[a]&&e[a].enabled===!1||(a&&(b=e[a].lineWidth||b+1),c&&!c.dashstyle&& +(a={"stroke-width":b},c.attr(a),d&&d.attr(a)))},setVisible:function(a,b){var c=this,d=c.chart,e=c.legendItem,f,g=d.options.chart.ignoreHiddenSeries,h=c.visible;f=(c.visible=a=c.userOptions.visible=a===w?!h:a)?"show":"hide";n(["group","dataLabelsGroup","markerGroup","tracker"],function(a){if(c[a])c[a][f]()});if(d.hoverSeries===c)c.onMouseOut();e&&d.legend.colorizeItem(c,a);c.isDirty=!0;c.options.stacking&&n(d.series,function(a){if(a.options.stacking&&a.visible)a.isDirty=!0});n(c.linkedSeries,function(b){b.setVisible(a, +!1)});if(g)d.isDirtyBox=!0;b!==!1&&d.redraw();z(c,f)},show:function(){this.setVisible(!0)},hide:function(){this.setVisible(!1)},select:function(a){this.selected=a=a===w?!this.selected:a;if(this.checkbox)this.checkbox.checked=a;z(this,a?"select":"unselect")},drawTracker:function(){var a=this,b=a.options,c=b.trackByArea,d=[].concat(c?a.areaPath:a.graphPath),e=d.length,f=a.chart,g=f.pointer,h=f.renderer,i=f.options.tooltip.snap,j=a.tracker,k=b.cursor,l=k&&{cursor:k},k=a.singlePoints,m,p=function(){if(f.hoverSeries!== +a)a.onMouseOver()};if(e&&!c)for(m=e+1;m--;)d[m]==="M"&&d.splice(m+1,0,d[m+1]-i,d[m+2],"L"),(m&&d[m]==="M"||m===e)&&d.splice(m,0,"L",d[m-2]+i,d[m-1]);for(m=0;m=0;d--)g=o(a[d].yBottom,f),da&&i>e?(i=s(a,e),k=2*e-i):ig&&k>e?(k=s(g,e),i=2*e-k):kf?b-f:e-(d.translate(a.y,0,1,0,1)<=e?f:0)));a.barX=n;a.pointWidth=g;b=N(n)<0.5;u=t(n+u)+j;n=t(n)+j;u-=n;w=N(r)<0.5;c=t(r+c)+k;r=t(r)+k;c-=r;b&&(n+=1,u-=1);w&&(r-= +1,c+=1);a.shapeType="rect";a.shapeArgs={x:n,y:r,width:u,height:c}})},getSymbol:pa,drawLegendSymbol:G.prototype.drawLegendSymbol,drawGraph:pa,drawPoints:function(){var a=this,b=a.options,c=a.chart.renderer,d;n(a.points,function(e){var f=e.plotY,g=e.graphic;if(f!==w&&!isNaN(f)&&e.y!==null)d=e.shapeArgs,g?(Wa(g),g.animate(x(d))):e.graphic=c[e.shapeType](d).attr(e.pointAttr[e.selected?"select":""]).add(a.group).shadow(b.shadow,null,b.stacking&&!b.borderRadius);else if(g)e.graphic=g.destroy()})},drawTracker:function(){var a= +this,b=a.chart,c=b.pointer,d=a.options.cursor,e=d&&{cursor:d},f=function(c){var d=c.target,e;if(b.hoverSeries!==a)a.onMouseOver();for(;d&&!e;)e=d.point,d=d.parentNode;if(e!==w&&e!==b.hoverPoint)e.onMouseOver(c)};n(a.points,function(a){if(a.graphic)a.graphic.element.point=a;if(a.dataLabel)a.dataLabel.element.point=a});if(!a._hasTracking)n(a.trackerGroups,function(b){if(a[b]&&(a[b].addClass("highcharts-tracker").on("mouseover",f).on("mouseout",function(a){c.onTrackerMouseOut(a)}).css(e),ib))a[b].on("touchstart", +f)}),a._hasTracking=!0},alignDataLabel:function(a,b,c,d,e){var f=this.chart,g=f.inverted,h=a.dlBox||a.shapeArgs,i=a.below||a.plotY>o(this.translatedThreshold,f.plotSizeY),j=o(c.inside,!!this.options.stacking);if(h&&(d=x(h),g&&(d={x:f.plotWidth-d.y-d.height,y:f.plotHeight-d.x-d.width,width:d.height,height:d.width}),!j))g?(d.x+=i?0:d.width,d.width=0):(d.y+=i?d.height:0,d.height=0);c.align=o(c.align,!g||j?"center":i?"right":"left");c.verticalAlign=o(c.verticalAlign,g||j?"middle":i?"top":"bottom");Q.prototype.alignDataLabel.call(this, +a,b,c,d,e)},animate:function(a){var b=this.yAxis,c=this.options,d=this.chart.inverted,e={};if(Z)a?(e.scaleY=0.001,a=I(b.pos+b.len,s(b.pos,b.toPixels(c.threshold))),d?e.translateX=a-b.len:e.translateY=a,this.group.attr(e)):(e.scaleY=1,e[d?"translateX":"translateY"]=b.pos,this.group.animate(e,this.options.animation),this.animate=null)},remove:function(){var a=this,b=a.chart;b.hasRendered&&n(b.series,function(b){if(b.type===a.type)b.isDirty=!0});Q.prototype.remove.apply(a,arguments)}});W.column=F;Y.bar= +x(Y.column);ma=ha(F,{type:"bar",inverted:!0});W.bar=ma;Y.scatter=x(X,{lineWidth:0,tooltip:{headerFormat:'{series.name}
',pointFormat:"x: {point.x}
y: {point.y}
",followPointer:!0},stickyTracking:!1});ma=ha(Q,{type:"scatter",sorted:!1,requireSorting:!1,noSharedTooltip:!0,trackerGroups:["markerGroup"],drawTracker:F.prototype.drawTracker,setTooltipPoints:pa});W.scatter=ma;Y.pie=x(X,{borderColor:"#FFFFFF",borderWidth:1, +center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30,enabled:!0,formatter:function(){return this.point.name}},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,states:{hover:{brightness:0.1,shadow:!1}},stickyTracking:!1,tooltip:{followPointer:!0}});X={type:"pie",isCartesian:!1,pointClass:ha(Pa,{init:function(){Pa.prototype.init.apply(this,arguments);var a=this,b;if(a.y<0)a.y=null;r(a,{visible:a.visible!==!1,name:o(a.name,"Slice")});b=function(b){a.slice(b.type=== +"select")};J(a,"select",b);J(a,"unselect",b);return a},setVisible:function(a){var b=this,c=b.series,d=c.chart,e;b.visible=b.options.visible=a=a===w?!b.visible:a;c.options.data[qa(b,c.data)]=b.options;e=a?"show":"hide";n(["graphic","dataLabel","connector","shadowGroup"],function(a){if(b[a])b[a][e]()});b.legendItem&&d.legend.colorizeItem(b,a);if(!c.isDirty&&c.options.ignoreHiddenPoint)c.isDirty=!0,d.redraw()},slice:function(a,b,c){var d=this.series;La(c,d.chart);o(b,!0);this.sliced=this.options.sliced= +a=u(a)?a:!this.sliced;d.options.data[qa(this,d.data)]=this.options;a=a?this.slicedTranslation:{translateX:0,translateY:0};this.graphic.animate(a);this.shadowGroup&&this.shadowGroup.animate(a)}}),requireSorting:!1,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color"},getColor:pa,animate:function(a){var b=this,c=b.points,d=b.startAngleRad;if(!a)n(c,function(a){var c=a.graphic,a=a.shapeArgs;c&&(c.attr({r:b.center[3]/ +2,start:d,end:d}),c.animate({r:a.r,start:a.start,end:a.end},b.options.animation))}),b.animate=null},setData:function(a,b){Q.prototype.setData.call(this,a,!1);this.processData();this.generatePoints();o(b,!0)&&this.chart.redraw()},generatePoints:function(){var a,b=0,c,d,e,f=this.options.ignoreHiddenPoint;Q.prototype.generatePoints.call(this);c=this.points;d=c.length;for(a=0;a0?e.y/b*100:0,e.total=b},getCenter:function(){var a= +this.options,b=this.chart,c=2*(a.slicedOffset||0),d,e=b.plotWidth-2*c,f=b.plotHeight-2*c,b=a.center,a=[o(b[0],"50%"),o(b[1],"50%"),a.size||"100%",a.innerSize||0],g=I(e,f),h;return Na(a,function(a,b){h=/%$/.test(a);d=b<2||b===2&&h;return(h?[e,f,g,g][b]*C(a)/100:a)+(d?c:0)})},translate:function(a){this.generatePoints();var b=0,c=this.options,d=c.slicedOffset,e=d+c.borderWidth,f,g,h,i=c.startAngle||0,j=this.startAngleRad=ya/180*(i-90),i=(this.endAngleRad=ya/180*((c.endAngle||i+360)-90))-j,k=this.points, +l=c.dataLabels.distance,c=c.ignoreHiddenPoint,m,n=k.length,o;if(!a)this.center=a=this.getCenter();this.getX=function(b,c){h=R.asin((b-a[1])/(a[2]/2+l));return a[0]+(c?-1:1)*V(h)*(a[2]/2+l)};for(m=0;m0.75*i&&(h-=2*ya);o.slicedTranslation={translateX:t(V(h)*d),translateY:t(ca(h)*d)};f=V(h)*a[2]/2;g=ca(h)*a[2]/2;o.tooltipPos= +[a[0]+f*0.7,a[1]+g*0.7];o.half=h<-ya/2||h>ya/2?1:0;o.angle=h;e=I(e,l/2);o.labelPos=[a[0]+f+V(h)*l,a[1]+g+ca(h)*l,a[0]+f+V(h)*e,a[1]+g+ca(h)*e,a[0]+f,a[1]+g,l<0?"center":o.half?"right":"left",h]}},setTooltipPoints:pa,drawGraph:null,drawPoints:function(){var a=this,b=a.chart.renderer,c,d,e=a.options.shadow,f,g;if(e&&!a.shadowGroup)a.shadowGroup=b.g("shadow").add(a.group);n(a.points,function(h){d=h.graphic;g=h.shapeArgs;f=h.shadowGroup;if(e&&!f)f=h.shadowGroup=b.g("shadow").add(a.shadowGroup);c=h.sliced? +h.slicedTranslation:{translateX:0,translateY:0};f&&f.attr(c);d?d.animate(r(g,c)):h.graphic=d=b.arc(g).setRadialReference(a.center).attr(h.pointAttr[h.selected?"select":""]).attr({"stroke-linejoin":"round"}).attr(c).add(a.group).shadow(e,f);h.visible===!1&&h.setVisible(!1)})},sortByAngle:function(a,b){a.sort(function(a,d){return a.angle!==void 0&&(d.angle-a.angle)*b})},drawDataLabels:function(){var a=this,b=a.data,c,d=a.chart,e=a.options.dataLabels,f=o(e.connectorPadding,10),g=o(e.connectorWidth,1), +h=d.plotWidth,d=d.plotHeight,i,j,k=o(e.softConnector,!0),l=e.distance,m=a.center,p=m[2]/2,q=m[1],u=l>0,r,w,v,x,C=[[],[]],y,z,E,H,B,D=[0,0,0,0],I=function(a,b){return b.y-a.y};if(a.visible&&(e.enabled||a._hasPointLabels)){Q.prototype.drawDataLabels.apply(a);n(b,function(a){a.dataLabel&&C[a.half].push(a)});for(H=0;!x&&b[H];)x=b[H]&&b[H].dataLabel&&(b[H].dataLabel.getBBox().height||21),H++;for(H=2;H--;){var b=[],K=[],G=C[H],J=G.length,F;a.sortByAngle(G,H-0.5);if(l>0){for(B=q-p-l;B<=q+p+l;B+=x)b.push(B); +w=b.length;if(J>w){c=[].concat(G);c.sort(I);for(B=J;B--;)c[B].rank=B;for(B=J;B--;)G[B].rank>=w&&G.splice(B,1);J=G.length}for(B=0;B0){if(w=K.pop(),F=w.i,z=w.y,c>z&&b[F+1]!==null||ch-f&&(D[1]=s(t(y+w-h+f),D[1])),z-x/2<0?D[0]=s(t(-z+x/2),D[0]):z+x/2>d&&(D[2]=s(t(z+x/2-d),D[2]))}}if(va(D)===0||this.verifyDataLabelOverflow(D))this.placeDataLabels(),u&&g&&n(this.points,function(b){i=b.connector;v=b.labelPos;if((r=b.dataLabel)&& +r._pos)E=r._attr.visibility,y=r.connX,z=r.connY,j=k?["M",y+(v[6]==="left"?5:-5),z,"C",y,z,2*v[2]-v[4],2*v[3]-v[5],v[2],v[3],"L",v[4],v[5]]:["M",y+(v[6]==="left"?5:-5),z,"L",v[2],v[3],"L",v[4],v[5]],i?(i.animate({d:j}),i.attr("visibility",E)):b.connector=i=a.chart.renderer.path(j).attr({"stroke-width":g,stroke:e.connectorColor||b.color||"#606060",visibility:E}).add(a.group);else if(i)b.connector=i.destroy()})}},verifyDataLabelOverflow:function(a){var b=this.center,c=this.options,d=c.center,e=c=c.minSize|| +80,f;d[0]!==null?e=s(b[2]-s(a[1],a[3]),c):(e=s(b[2]-a[1]-a[3],c),b[0]+=(a[3]-a[1])/2);d[1]!==null?e=s(I(e,b[2]-s(a[0],a[2])),c):(e=s(I(e,b[2]-a[0]-a[2]),c),b[1]+=(a[0]-a[2])/2);e
/g, '
') + .split(//g), + childNodes = textNode.childNodes, + styleRegex = /style="([^"]+)"/, + hrefRegex = /href="(http[^"]+)"/, + parentX = attr(textNode, 'x'), + textStyles = wrapper.styles, + width = textStyles && textStyles.width && pInt(textStyles.width), + textLineHeight = textStyles && textStyles.lineHeight, + i = childNodes.length; + + /// remove old text + while (i--) { + textNode.removeChild(childNodes[i]); + } + + if (width && !wrapper.added) { + this.box.appendChild(textNode); // attach it to the DOM to read offset width + } + + // remove empty line at end + if (lines[lines.length - 1] === '') { + lines.pop(); + } + + // build the lines + each(lines, function (line, lineNo) { + var spans, spanNo = 0; + + line = line.replace(//g, '|||'); + spans = line.split('|||'); + + each(spans, function (span) { + if (span !== '' || spans.length === 1) { + var attributes = {}, + tspan = doc.createElementNS(SVG_NS, 'tspan'), + spanStyle; // #390 + if (styleRegex.test(span)) { + spanStyle = span.match(styleRegex)[1].replace(/(;| |^)color([ :])/, '$1fill$2'); + attr(tspan, 'style', spanStyle); + } + if (hrefRegex.test(span) && !forExport) { // Not for export - #1529 + attr(tspan, 'onclick', 'location.href=\"' + span.match(hrefRegex)[1] + '\"'); + css(tspan, { cursor: 'pointer' }); + } + + span = (span.replace(/<(.|\n)*?>/g, '') || ' ') + .replace(/</g, '<') + .replace(/>/g, '>'); + + // Nested tags aren't supported, and cause crash in Safari (#1596) + if (span !== ' ') { + + // add the text node + tspan.appendChild(doc.createTextNode(span)); + + if (!spanNo) { // first span in a line, align it to the left + attributes.x = parentX; + } else { + attributes.dx = 0; // #16 + } + + // add attributes + attr(tspan, attributes); + + // first span on subsequent line, add the line height + if (!spanNo && lineNo) { + + // allow getting the right offset height in exporting in IE + if (!hasSVG && forExport) { + css(tspan, { display: 'block' }); + } + + // Set the line height based on the font size of either + // the text element or the tspan element + attr( + tspan, + 'dy', + textLineHeight || renderer.fontMetrics( + /px$/.test(tspan.style.fontSize) ? + tspan.style.fontSize : + textStyles.fontSize + ).h, + // Safari 6.0.2 - too optimized for its own good (#1539) + // TODO: revisit this with future versions of Safari + isWebKit && tspan.offsetHeight + ); + } + + // Append it + textNode.appendChild(tspan); + + spanNo++; + + // check width and apply soft breaks + if (width) { + var words = span.replace(/([^\^])-/g, '$1- ').split(' '), // #1273 + tooLong, + actualWidth, + clipHeight = wrapper._clipHeight, + rest = [], + dy = pInt(textLineHeight || 16), + softLineNo = 1, + bBox; + + while (words.length || rest.length) { + delete wrapper.bBox; // delete cache + bBox = wrapper.getBBox(); + actualWidth = bBox.width; + tooLong = actualWidth > width; + if (!tooLong || words.length === 1) { // new line needed + words = rest; + rest = []; + if (words.length) { + softLineNo++; + + if (clipHeight && softLineNo * dy > clipHeight) { + words = ['...']; + wrapper.attr('title', wrapper.textStr); + } else { + + tspan = doc.createElementNS(SVG_NS, 'tspan'); + attr(tspan, { + dy: dy, + x: parentX + }); + if (spanStyle) { // #390 + attr(tspan, 'style', spanStyle); + } + textNode.appendChild(tspan); + + if (actualWidth > width) { // a single word is pressing it out + width = actualWidth; + } + } + } + } else { // append to existing line tspan + tspan.removeChild(tspan.firstChild); + rest.unshift(words.pop()); + } + if (words.length) { + tspan.appendChild(doc.createTextNode(words.join(' ').replace(/- /g, '-'))); + } + } + } + } + } + }); + }); + }, + + /** + * Create a button with preset states + * @param {String} text + * @param {Number} x + * @param {Number} y + * @param {Function} callback + * @param {Object} normalState + * @param {Object} hoverState + * @param {Object} pressedState + */ + button: function (text, x, y, callback, normalState, hoverState, pressedState, disabledState) { + var label = this.label(text, x, y, null, null, null, null, null, 'button'), + curState = 0, + stateOptions, + stateStyle, + normalStyle, + hoverStyle, + pressedStyle, + disabledStyle, + STYLE = 'style', + verticalGradient = { x1: 0, y1: 0, x2: 0, y2: 1 }; + + // Normal state - prepare the attributes + normalState = merge({ + 'stroke-width': 1, + stroke: '#CCCCCC', + fill: { + linearGradient: verticalGradient, + stops: [ + [0, '#FEFEFE'], + [1, '#F6F6F6'] + ] + }, + r: 2, + padding: 5, + style: { + color: 'black' + } + }, normalState); + normalStyle = normalState[STYLE]; + delete normalState[STYLE]; + + // Hover state + hoverState = merge(normalState, { + stroke: '#68A', + fill: { + linearGradient: verticalGradient, + stops: [ + [0, '#FFF'], + [1, '#ACF'] + ] + } + }, hoverState); + hoverStyle = hoverState[STYLE]; + delete hoverState[STYLE]; + + // Pressed state + pressedState = merge(normalState, { + stroke: '#68A', + fill: { + linearGradient: verticalGradient, + stops: [ + [0, '#9BD'], + [1, '#CDF'] + ] + } + }, pressedState); + pressedStyle = pressedState[STYLE]; + delete pressedState[STYLE]; + + // Disabled state + disabledState = merge(normalState, { + style: { + color: '#CCC' + } + }, disabledState); + disabledStyle = disabledState[STYLE]; + delete disabledState[STYLE]; + + // Add the events. IE9 and IE10 need mouseover and mouseout to funciton (#667). + addEvent(label.element, isIE ? 'mouseover' : 'mouseenter', function () { + if (curState !== 3) { + label.attr(hoverState) + .css(hoverStyle); + } + }); + addEvent(label.element, isIE ? 'mouseout' : 'mouseleave', function () { + if (curState !== 3) { + stateOptions = [normalState, hoverState, pressedState][curState]; + stateStyle = [normalStyle, hoverStyle, pressedStyle][curState]; + label.attr(stateOptions) + .css(stateStyle); + } + }); + + label.setState = function (state) { + label.state = curState = state; + if (!state) { + label.attr(normalState) + .css(normalStyle); + } else if (state === 2) { + label.attr(pressedState) + .css(pressedStyle); + } else if (state === 3) { + label.attr(disabledState) + .css(disabledStyle); + } + }; + + return label + .on('click', function () { + if (curState !== 3) { + callback.call(label); + } + }) + .attr(normalState) + .css(extend({ cursor: 'default' }, normalStyle)); + }, + + /** + * Make a straight line crisper by not spilling out to neighbour pixels + * @param {Array} points + * @param {Number} width + */ + crispLine: function (points, width) { + // points format: [M, 0, 0, L, 100, 0] + // normalize to a crisp line + if (points[1] === points[4]) { + // Substract due to #1129. Now bottom and left axis gridlines behave the same. + points[1] = points[4] = mathRound(points[1]) - (width % 2 / 2); + } + if (points[2] === points[5]) { + points[2] = points[5] = mathRound(points[2]) + (width % 2 / 2); + } + return points; + }, + + + /** + * Draw a path + * @param {Array} path An SVG path in array form + */ + path: function (path) { + var attr = { + fill: NONE + }; + if (isArray(path)) { + attr.d = path; + } else if (isObject(path)) { // attributes + extend(attr, path); + } + return this.createElement('path').attr(attr); + }, + + /** + * Draw and return an SVG circle + * @param {Number} x The x position + * @param {Number} y The y position + * @param {Number} r The radius + */ + circle: function (x, y, r) { + var attr = isObject(x) ? + x : + { + x: x, + y: y, + r: r + }; + + return this.createElement('circle').attr(attr); + }, + + /** + * Draw and return an arc + * @param {Number} x X position + * @param {Number} y Y position + * @param {Number} r Radius + * @param {Number} innerR Inner radius like used in donut charts + * @param {Number} start Starting angle + * @param {Number} end Ending angle + */ + arc: function (x, y, r, innerR, start, end) { + var arc; + + if (isObject(x)) { + y = x.y; + r = x.r; + innerR = x.innerR; + start = x.start; + end = x.end; + x = x.x; + } + + // Arcs are defined as symbols for the ability to set + // attributes in attr and animate + arc = this.symbol('arc', x || 0, y || 0, r || 0, r || 0, { + innerR: innerR || 0, + start: start || 0, + end: end || 0 + }); + arc.r = r; // #959 + return arc; + }, + + /** + * Draw and return a rectangle + * @param {Number} x Left position + * @param {Number} y Top position + * @param {Number} width + * @param {Number} height + * @param {Number} r Border corner radius + * @param {Number} strokeWidth A stroke width can be supplied to allow crisp drawing + */ + rect: function (x, y, width, height, r, strokeWidth) { + + r = isObject(x) ? x.r : r; + + var wrapper = this.createElement('rect').attr({ + rx: r, + ry: r, + fill: NONE + }); + return wrapper.attr( + isObject(x) ? + x : + // do not crispify when an object is passed in (as in column charts) + wrapper.crisp(strokeWidth, x, y, mathMax(width, 0), mathMax(height, 0)) + ); + }, + + /** + * Resize the box and re-align all aligned elements + * @param {Object} width + * @param {Object} height + * @param {Boolean} animate + * + */ + setSize: function (width, height, animate) { + var renderer = this, + alignedObjects = renderer.alignedObjects, + i = alignedObjects.length; + + renderer.width = width; + renderer.height = height; + + renderer.boxWrapper[pick(animate, true) ? 'animate' : 'attr']({ + width: width, + height: height + }); + + while (i--) { + alignedObjects[i].align(); + } + }, + + /** + * Create a group + * @param {String} name The group will be given a class name of 'highcharts-{name}'. + * This can be used for styling and scripting. + */ + g: function (name) { + var elem = this.createElement('g'); + return defined(name) ? elem.attr({ 'class': PREFIX + name }) : elem; + }, + + /** + * Display an image + * @param {String} src + * @param {Number} x + * @param {Number} y + * @param {Number} width + * @param {Number} height + */ + image: function (src, x, y, width, height) { + var attribs = { + preserveAspectRatio: NONE + }, + elemWrapper; + + // optional properties + if (arguments.length > 1) { + extend(attribs, { + x: x, + y: y, + width: width, + height: height + }); + } + + elemWrapper = this.createElement('image').attr(attribs); + + // set the href in the xlink namespace + if (elemWrapper.element.setAttributeNS) { + elemWrapper.element.setAttributeNS('http://www.w3.org/1999/xlink', + 'href', src); + } else { + // could be exporting in IE + // using href throws "not supported" in ie7 and under, requries regex shim to fix later + elemWrapper.element.setAttribute('hc-svg-href', src); + } + + return elemWrapper; + }, + + /** + * Draw a symbol out of pre-defined shape paths from the namespace 'symbol' object. + * + * @param {Object} symbol + * @param {Object} x + * @param {Object} y + * @param {Object} radius + * @param {Object} options + */ + symbol: function (symbol, x, y, width, height, options) { + + var obj, + + // get the symbol definition function + symbolFn = this.symbols[symbol], + + // check if there's a path defined for this symbol + path = symbolFn && symbolFn( + mathRound(x), + mathRound(y), + width, + height, + options + ), + + imageElement, + imageRegex = /^url\((.*?)\)$/, + imageSrc, + imageSize, + centerImage; + + if (path) { + + obj = this.path(path); + // expando properties for use in animate and attr + extend(obj, { + symbolName: symbol, + x: x, + y: y, + width: width, + height: height + }); + if (options) { + extend(obj, options); + } + + + // image symbols + } else if (imageRegex.test(symbol)) { + + // On image load, set the size and position + centerImage = function (img, size) { + if (img.element) { // it may be destroyed in the meantime (#1390) + img.attr({ + width: size[0], + height: size[1] + }); + + if (!img.alignByTranslate) { // #185 + img.translate( + mathRound((width - size[0]) / 2), // #1378 + mathRound((height - size[1]) / 2) + ); + } + } + }; + + imageSrc = symbol.match(imageRegex)[1]; + imageSize = symbolSizes[imageSrc]; + + // Ireate the image synchronously, add attribs async + obj = this.image(imageSrc) + .attr({ + x: x, + y: y + }); + obj.isImg = true; + + if (imageSize) { + centerImage(obj, imageSize); + } else { + // Initialize image to be 0 size so export will still function if there's no cached sizes. + // + obj.attr({ width: 0, height: 0 }); + + // Create a dummy JavaScript image to get the width and height. Due to a bug in IE < 8, + // the created element must be assigned to a variable in order to load (#292). + imageElement = createElement('img', { + onload: function () { + centerImage(obj, symbolSizes[imageSrc] = [this.width, this.height]); + }, + src: imageSrc + }); + } + } + + return obj; + }, + + /** + * An extendable collection of functions for defining symbol paths. + */ + symbols: { + 'circle': function (x, y, w, h) { + var cpw = 0.166 * w; + return [ + M, x + w / 2, y, + 'C', x + w + cpw, y, x + w + cpw, y + h, x + w / 2, y + h, + 'C', x - cpw, y + h, x - cpw, y, x + w / 2, y, + 'Z' + ]; + }, + + 'square': function (x, y, w, h) { + return [ + M, x, y, + L, x + w, y, + x + w, y + h, + x, y + h, + 'Z' + ]; + }, + + 'triangle': function (x, y, w, h) { + return [ + M, x + w / 2, y, + L, x + w, y + h, + x, y + h, + 'Z' + ]; + }, + + 'triangle-down': function (x, y, w, h) { + return [ + M, x, y, + L, x + w, y, + x + w / 2, y + h, + 'Z' + ]; + }, + 'diamond': function (x, y, w, h) { + return [ + M, x + w / 2, y, + L, x + w, y + h / 2, + x + w / 2, y + h, + x, y + h / 2, + 'Z' + ]; + }, + 'arc': function (x, y, w, h, options) { + var start = options.start, + radius = options.r || w || h, + end = options.end - 0.001, // to prevent cos and sin of start and end from becoming equal on 360 arcs (related: #1561) + innerRadius = options.innerR, + open = options.open, + cosStart = mathCos(start), + sinStart = mathSin(start), + cosEnd = mathCos(end), + sinEnd = mathSin(end), + longArc = options.end - start < mathPI ? 0 : 1; + + return [ + M, + x + radius * cosStart, + y + radius * sinStart, + 'A', // arcTo + radius, // x radius + radius, // y radius + 0, // slanting + longArc, // long or short arc + 1, // clockwise + x + radius * cosEnd, + y + radius * sinEnd, + open ? M : L, + x + innerRadius * cosEnd, + y + innerRadius * sinEnd, + 'A', // arcTo + innerRadius, // x radius + innerRadius, // y radius + 0, // slanting + longArc, // long or short arc + 0, // clockwise + x + innerRadius * cosStart, + y + innerRadius * sinStart, + + open ? '' : 'Z' // close + ]; + } + }, + + /** + * Define a clipping rectangle + * @param {String} id + * @param {Number} x + * @param {Number} y + * @param {Number} width + * @param {Number} height + */ + clipRect: function (x, y, width, height) { + var wrapper, + id = PREFIX + idCounter++, + + clipPath = this.createElement('clipPath').attr({ + id: id + }).add(this.defs); + + wrapper = this.rect(x, y, width, height, 0).add(clipPath); + wrapper.id = id; + wrapper.clipPath = clipPath; + + return wrapper; + }, + + + /** + * Take a color and return it if it's a string, make it a gradient if it's a + * gradient configuration object. Prior to Highstock, an array was used to define + * a linear gradient with pixel positions relative to the SVG. In newer versions + * we change the coordinates to apply relative to the shape, using coordinates + * 0-1 within the shape. To preserve backwards compatibility, linearGradient + * in this definition is an object of x1, y1, x2 and y2. + * + * @param {Object} color The color or config object + */ + color: function (color, elem, prop) { + var renderer = this, + colorObject, + regexRgba = /^rgba/, + gradName, + gradAttr, + gradients, + gradientObject, + stops, + stopColor, + stopOpacity, + radialReference, + n, + id, + key = []; + + // Apply linear or radial gradients + if (color && color.linearGradient) { + gradName = 'linearGradient'; + } else if (color && color.radialGradient) { + gradName = 'radialGradient'; + } + + if (gradName) { + gradAttr = color[gradName]; + gradients = renderer.gradients; + stops = color.stops; + radialReference = elem.radialReference; + + // Keep < 2.2 kompatibility + if (isArray(gradAttr)) { + color[gradName] = gradAttr = { + x1: gradAttr[0], + y1: gradAttr[1], + x2: gradAttr[2], + y2: gradAttr[3], + gradientUnits: 'userSpaceOnUse' + }; + } + + // Correct the radial gradient for the radial reference system + if (gradName === 'radialGradient' && radialReference && !defined(gradAttr.gradientUnits)) { + gradAttr = merge(gradAttr, { + cx: (radialReference[0] - radialReference[2] / 2) + gradAttr.cx * radialReference[2], + cy: (radialReference[1] - radialReference[2] / 2) + gradAttr.cy * radialReference[2], + r: gradAttr.r * radialReference[2], + gradientUnits: 'userSpaceOnUse' + }); + } + + // Build the unique key to detect whether we need to create a new element (#1282) + for (n in gradAttr) { + if (n !== 'id') { + key.push(n, gradAttr[n]); + } + } + for (n in stops) { + key.push(stops[n]); + } + key = key.join(','); + + // Check if a gradient object with the same config object is created within this renderer + if (gradients[key]) { + id = gradients[key].id; + + } else { + + // Set the id and create the element + gradAttr.id = id = PREFIX + idCounter++; + gradients[key] = gradientObject = renderer.createElement(gradName) + .attr(gradAttr) + .add(renderer.defs); + + + // The gradient needs to keep a list of stops to be able to destroy them + gradientObject.stops = []; + each(stops, function (stop) { + var stopObject; + if (regexRgba.test(stop[1])) { + colorObject = Color(stop[1]); + stopColor = colorObject.get('rgb'); + stopOpacity = colorObject.get('a'); + } else { + stopColor = stop[1]; + stopOpacity = 1; + } + stopObject = renderer.createElement('stop').attr({ + offset: stop[0], + 'stop-color': stopColor, + 'stop-opacity': stopOpacity + }).add(gradientObject); + + // Add the stop element to the gradient + gradientObject.stops.push(stopObject); + }); + } + + // Return the reference to the gradient object + return 'url(' + renderer.url + '#' + id + ')'; + + // Webkit and Batik can't show rgba. + } else if (regexRgba.test(color)) { + colorObject = Color(color); + attr(elem, prop + '-opacity', colorObject.get('a')); + + return colorObject.get('rgb'); + + + } else { + // Remove the opacity attribute added above. Does not throw if the attribute is not there. + elem.removeAttribute(prop + '-opacity'); + + return color; + } + + }, + + + /** + * Add text to the SVG object + * @param {String} str + * @param {Number} x Left position + * @param {Number} y Top position + * @param {Boolean} useHTML Use HTML to render the text + */ + text: function (str, x, y, useHTML) { + + // declare variables + var renderer = this, + defaultChartStyle = defaultOptions.chart.style, + fakeSVG = useCanVG || (!hasSVG && renderer.forExport), + wrapper; + + if (useHTML && !renderer.forExport) { + return renderer.html(str, x, y); + } + + x = mathRound(pick(x, 0)); + y = mathRound(pick(y, 0)); + + wrapper = renderer.createElement('text') + .attr({ + x: x, + y: y, + text: str + }) + .css({ + fontFamily: defaultChartStyle.fontFamily, + fontSize: defaultChartStyle.fontSize + }); + + // Prevent wrapping from creating false offsetWidths in export in legacy IE (#1079, #1063) + if (fakeSVG) { + wrapper.css({ + position: ABSOLUTE + }); + } + + wrapper.x = x; + wrapper.y = y; + return wrapper; + }, + + + /** + * Create HTML text node. This is used by the VML renderer as well as the SVG + * renderer through the useHTML option. + * + * @param {String} str + * @param {Number} x + * @param {Number} y + */ + html: function (str, x, y) { + var defaultChartStyle = defaultOptions.chart.style, + wrapper = this.createElement('span'), + attrSetters = wrapper.attrSetters, + element = wrapper.element, + renderer = wrapper.renderer; + + // Text setter + attrSetters.text = function (value) { + if (value !== element.innerHTML) { + delete this.bBox; + } + element.innerHTML = value; + return false; + }; + + // Various setters which rely on update transform + attrSetters.x = attrSetters.y = attrSetters.align = function (value, key) { + if (key === 'align') { + key = 'textAlign'; // Do not overwrite the SVGElement.align method. Same as VML. + } + wrapper[key] = value; + wrapper.htmlUpdateTransform(); + return false; + }; + + // Set the default attributes + wrapper.attr({ + text: str, + x: mathRound(x), + y: mathRound(y) + }) + .css({ + position: ABSOLUTE, + whiteSpace: 'nowrap', + fontFamily: defaultChartStyle.fontFamily, + fontSize: defaultChartStyle.fontSize + }); + + // Use the HTML specific .css method + wrapper.css = wrapper.htmlCss; + + // This is specific for HTML within SVG + if (renderer.isSVG) { + wrapper.add = function (svgGroupWrapper) { + + var htmlGroup, + container = renderer.box.parentNode, + parentGroup, + parents = []; + + // Create a mock group to hold the HTML elements + if (svgGroupWrapper) { + htmlGroup = svgGroupWrapper.div; + if (!htmlGroup) { + + // Read the parent chain into an array and read from top down + parentGroup = svgGroupWrapper; + while (parentGroup) { + + parents.push(parentGroup); + + // Move up to the next parent group + parentGroup = parentGroup.parentGroup; + } + + // Ensure dynamically updating position when any parent is translated + each(parents.reverse(), function (parentGroup) { + var htmlGroupStyle; + + // Create a HTML div and append it to the parent div to emulate + // the SVG group structure + htmlGroup = parentGroup.div = parentGroup.div || createElement(DIV, { + className: attr(parentGroup.element, 'class') + }, { + position: ABSOLUTE, + left: (parentGroup.translateX || 0) + PX, + top: (parentGroup.translateY || 0) + PX + }, htmlGroup || container); // the top group is appended to container + + // Shortcut + htmlGroupStyle = htmlGroup.style; + + // Set listeners to update the HTML div's position whenever the SVG group + // position is changed + extend(parentGroup.attrSetters, { + translateX: function (value) { + htmlGroupStyle.left = value + PX; + }, + translateY: function (value) { + htmlGroupStyle.top = value + PX; + }, + visibility: function (value, key) { + htmlGroupStyle[key] = value; + } + }); + }); + + } + } else { + htmlGroup = container; + } + + htmlGroup.appendChild(element); + + // Shared with VML: + wrapper.added = true; + if (wrapper.alignOnAdd) { + wrapper.htmlUpdateTransform(); + } + + return wrapper; + }; + } + return wrapper; + }, + + /** + * Utility to return the baseline offset and total line height from the font size + */ + fontMetrics: function (fontSize) { + fontSize = pInt(fontSize || 11); + + // Empirical values found by comparing font size and bounding box height. + // Applies to the default font family. http://jsfiddle.net/highcharts/7xvn7/ + var lineHeight = fontSize < 24 ? fontSize + 4 : mathRound(fontSize * 1.2), + baseline = mathRound(lineHeight * 0.8); + + return { + h: lineHeight, + b: baseline + }; + }, + + /** + * Add a label, a text item that can hold a colored or gradient background + * as well as a border and shadow. + * @param {string} str + * @param {Number} x + * @param {Number} y + * @param {String} shape + * @param {Number} anchorX In case the shape has a pointer, like a flag, this is the + * coordinates it should be pinned to + * @param {Number} anchorY + * @param {Boolean} baseline Whether to position the label relative to the text baseline, + * like renderer.text, or to the upper border of the rectangle. + * @param {String} className Class name for the group + */ + label: function (str, x, y, shape, anchorX, anchorY, useHTML, baseline, className) { + + var renderer = this, + wrapper = renderer.g(className), + text = renderer.text('', 0, 0, useHTML) + .attr({ + zIndex: 1 + }), + //.add(wrapper), + box, + bBox, + alignFactor = 0, + padding = 3, + paddingLeft = 0, + width, + height, + wrapperX, + wrapperY, + crispAdjust = 0, + deferredAttr = {}, + baselineOffset, + attrSetters = wrapper.attrSetters, + needsBox; + + /** + * This function runs after the label is added to the DOM (when the bounding box is + * available), and after the text of the label is updated to detect the new bounding + * box and reflect it in the border box. + */ + function updateBoxSize() { + var boxX, + boxY, + style = text.element.style; + + bBox = (width === undefined || height === undefined || wrapper.styles.textAlign) && + text.getBBox(); + wrapper.width = (width || bBox.width || 0) + 2 * padding + paddingLeft; + wrapper.height = (height || bBox.height || 0) + 2 * padding; + + // update the label-scoped y offset + baselineOffset = padding + renderer.fontMetrics(style && style.fontSize).b; + + if (needsBox) { + + // create the border box if it is not already present + if (!box) { + boxX = mathRound(-alignFactor * padding); + boxY = baseline ? -baselineOffset : 0; + + wrapper.box = box = shape ? + renderer.symbol(shape, boxX, boxY, wrapper.width, wrapper.height) : + renderer.rect(boxX, boxY, wrapper.width, wrapper.height, 0, deferredAttr[STROKE_WIDTH]); + box.add(wrapper); + } + + // apply the box attributes + if (!box.isImg) { // #1630 + box.attr(merge({ + width: wrapper.width, + height: wrapper.height + }, deferredAttr)); + } + deferredAttr = null; + } + } + + /** + * This function runs after setting text or padding, but only if padding is changed + */ + function updateTextPadding() { + var styles = wrapper.styles, + textAlign = styles && styles.textAlign, + x = paddingLeft + padding * (1 - alignFactor), + y; + + // determin y based on the baseline + y = baseline ? 0 : baselineOffset; + + // compensate for alignment + if (defined(width) && (textAlign === 'center' || textAlign === 'right')) { + x += { center: 0.5, right: 1 }[textAlign] * (width - bBox.width); + } + + // update if anything changed + if (x !== text.x || y !== text.y) { + text.attr({ + x: x, + y: y + }); + } + + // record current values + text.x = x; + text.y = y; + } + + /** + * Set a box attribute, or defer it if the box is not yet created + * @param {Object} key + * @param {Object} value + */ + function boxAttr(key, value) { + if (box) { + box.attr(key, value); + } else { + deferredAttr[key] = value; + } + } + + function getSizeAfterAdd() { + text.add(wrapper); + wrapper.attr({ + text: str, // alignment is available now + x: x, + y: y + }); + + if (box && defined(anchorX)) { + wrapper.attr({ + anchorX: anchorX, + anchorY: anchorY + }); + } + } + + /** + * After the text element is added, get the desired size of the border box + * and add it before the text in the DOM. + */ + addEvent(wrapper, 'add', getSizeAfterAdd); + + /* + * Add specific attribute setters. + */ + + // only change local variables + attrSetters.width = function (value) { + width = value; + return false; + }; + attrSetters.height = function (value) { + height = value; + return false; + }; + attrSetters.padding = function (value) { + if (defined(value) && value !== padding) { + padding = value; + updateTextPadding(); + } + return false; + }; + attrSetters.paddingLeft = function (value) { + if (defined(value) && value !== paddingLeft) { + paddingLeft = value; + updateTextPadding(); + } + return false; + }; + + + // change local variable and set attribue as well + attrSetters.align = function (value) { + alignFactor = { left: 0, center: 0.5, right: 1 }[value]; + return false; // prevent setting text-anchor on the group + }; + + // apply these to the box and the text alike + attrSetters.text = function (value, key) { + text.attr(key, value); + updateBoxSize(); + updateTextPadding(); + return false; + }; + + // apply these to the box but not to the text + attrSetters[STROKE_WIDTH] = function (value, key) { + needsBox = true; + crispAdjust = value % 2 / 2; + boxAttr(key, value); + return false; + }; + attrSetters.stroke = attrSetters.fill = attrSetters.r = function (value, key) { + if (key === 'fill') { + needsBox = true; + } + boxAttr(key, value); + return false; + }; + attrSetters.anchorX = function (value, key) { + anchorX = value; + boxAttr(key, value + crispAdjust - wrapperX); + return false; + }; + attrSetters.anchorY = function (value, key) { + anchorY = value; + boxAttr(key, value - wrapperY); + return false; + }; + + // rename attributes + attrSetters.x = function (value) { + wrapper.x = value; // for animation getter + value -= alignFactor * ((width || bBox.width) + padding); + wrapperX = mathRound(value); + + wrapper.attr('translateX', wrapperX); + return false; + }; + attrSetters.y = function (value) { + wrapperY = wrapper.y = mathRound(value); + wrapper.attr('translateY', wrapperY); + return false; + }; + + // Redirect certain methods to either the box or the text + var baseCss = wrapper.css; + return extend(wrapper, { + /** + * Pick up some properties and apply them to the text instead of the wrapper + */ + css: function (styles) { + if (styles) { + var textStyles = {}; + styles = merge(styles); // create a copy to avoid altering the original object (#537) + each(['fontSize', 'fontWeight', 'fontFamily', 'color', 'lineHeight', 'width', 'textDecoration', 'textShadow'], function (prop) { + if (styles[prop] !== UNDEFINED) { + textStyles[prop] = styles[prop]; + delete styles[prop]; + } + }); + text.css(textStyles); + } + return baseCss.call(wrapper, styles); + }, + /** + * Return the bounding box of the box, not the group + */ + getBBox: function () { + return { + width: bBox.width + 2 * padding, + height: bBox.height + 2 * padding, + x: bBox.x - padding, + y: bBox.y - padding + }; + }, + /** + * Apply the shadow to the box + */ + shadow: function (b) { + if (box) { + box.shadow(b); + } + return wrapper; + }, + /** + * Destroy and release memory. + */ + destroy: function () { + removeEvent(wrapper, 'add', getSizeAfterAdd); + + // Added by button implementation + removeEvent(wrapper.element, 'mouseenter'); + removeEvent(wrapper.element, 'mouseleave'); + + if (text) { + text = text.destroy(); + } + if (box) { + box = box.destroy(); + } + // Call base implementation to destroy the rest + SVGElement.prototype.destroy.call(wrapper); + + // Release local pointers (#1298) + wrapper = renderer = updateBoxSize = updateTextPadding = boxAttr = getSizeAfterAdd = null; + } + }); + } +}; // end SVGRenderer + + +// general renderer +Renderer = SVGRenderer; + + +/* **************************************************************************** + * * + * START OF INTERNET EXPLORER <= 8 SPECIFIC CODE * + * * + * For applications and websites that don't need IE support, like platform * + * targeted mobile apps and web apps, this code can be removed. * + * * + *****************************************************************************/ + +/** + * @constructor + */ +var VMLRenderer, VMLElement; +if (!hasSVG && !useCanVG) { + +/** + * The VML element wrapper. + */ +Highcharts.VMLElement = VMLElement = { + + /** + * Initialize a new VML element wrapper. It builds the markup as a string + * to minimize DOM traffic. + * @param {Object} renderer + * @param {Object} nodeName + */ + init: function (renderer, nodeName) { + var wrapper = this, + markup = ['<', nodeName, ' filled="f" stroked="f"'], + style = ['position: ', ABSOLUTE, ';'], + isDiv = nodeName === DIV; + + // divs and shapes need size + if (nodeName === 'shape' || isDiv) { + style.push('left:0;top:0;width:1px;height:1px;'); + } + style.push('visibility: ', isDiv ? HIDDEN : VISIBLE); + + markup.push(' style="', style.join(''), '"/>'); + + // create element with default attributes and style + if (nodeName) { + markup = isDiv || nodeName === 'span' || nodeName === 'img' ? + markup.join('') + : renderer.prepVML(markup); + wrapper.element = createElement(markup); + } + + wrapper.renderer = renderer; + wrapper.attrSetters = {}; + }, + + /** + * Add the node to the given parent + * @param {Object} parent + */ + add: function (parent) { + var wrapper = this, + renderer = wrapper.renderer, + element = wrapper.element, + box = renderer.box, + inverted = parent && parent.inverted, + + // get the parent node + parentNode = parent ? + parent.element || parent : + box; + + + // if the parent group is inverted, apply inversion on all children + if (inverted) { // only on groups + renderer.invertChild(element, parentNode); + } + + // append it + parentNode.appendChild(element); + + // align text after adding to be able to read offset + wrapper.added = true; + if (wrapper.alignOnAdd && !wrapper.deferUpdateTransform) { + wrapper.updateTransform(); + } + + // fire an event for internal hooks + fireEvent(wrapper, 'add'); + + return wrapper; + }, + + /** + * VML always uses htmlUpdateTransform + */ + updateTransform: SVGElement.prototype.htmlUpdateTransform, + + /** + * Set the rotation of a span with oldIE's filter + */ + setSpanRotation: function (rotation, sintheta, costheta) { + // Adjust for alignment and rotation. Rotation of useHTML content is not yet implemented + // but it can probably be implemented for Firefox 3.5+ on user request. FF3.5+ + // has support for CSS3 transform. The getBBox method also needs to be updated + // to compensate for the rotation, like it currently does for SVG. + // Test case: http://highcharts.com/tests/?file=text-rotation + css(this.element, { + filter: rotation ? ['progid:DXImageTransform.Microsoft.Matrix(M11=', costheta, + ', M12=', -sintheta, ', M21=', sintheta, ', M22=', costheta, + ', sizingMethod=\'auto expand\')'].join('') : NONE + }); + }, + + /** + * Converts a subset of an SVG path definition to its VML counterpart. Takes an array + * as the parameter and returns a string. + */ + pathToVML: function (value) { + // convert paths + var i = value.length, + path = [], + clockwise; + + while (i--) { + + // Multiply by 10 to allow subpixel precision. + // Substracting half a pixel seems to make the coordinates + // align with SVG, but this hasn't been tested thoroughly + if (isNumber(value[i])) { + path[i] = mathRound(value[i] * 10) - 5; + } else if (value[i] === 'Z') { // close the path + path[i] = 'x'; + } else { + path[i] = value[i]; + + // When the start X and end X coordinates of an arc are too close, + // they are rounded to the same value above. In this case, substract 1 from the end X + // position. #760, #1371. + if (value.isArc && (value[i] === 'wa' || value[i] === 'at')) { + clockwise = value[i] === 'wa' ? 1 : -1; // #1642 + if (path[i + 5] === path[i + 7]) { + path[i + 7] -= clockwise; + } + // Start and end Y (#1410) + if (path[i + 6] === path[i + 8]) { + path[i + 8] -= clockwise; + } + } + } + } + // Loop up again to handle path shortcuts (#2132) + /*while (i++ < path.length) { + if (path[i] === 'H') { // horizontal line to + path[i] = 'L'; + path.splice(i + 2, 0, path[i - 1]); + } else if (path[i] === 'V') { // vertical line to + path[i] = 'L'; + path.splice(i + 1, 0, path[i - 2]); + } + }*/ + return path.join(' ') || 'x'; + }, + + /** + * Get or set attributes + */ + attr: function (hash, val) { + var wrapper = this, + key, + value, + i, + result, + element = wrapper.element || {}, + elemStyle = element.style, + nodeName = element.nodeName, + renderer = wrapper.renderer, + symbolName = wrapper.symbolName, + hasSetSymbolSize, + shadows = wrapper.shadows, + skipAttr, + attrSetters = wrapper.attrSetters, + ret = wrapper; + + // single key-value pair + if (isString(hash) && defined(val)) { + key = hash; + hash = {}; + hash[key] = val; + } + + // used as a getter, val is undefined + if (isString(hash)) { + key = hash; + if (key === 'strokeWidth' || key === 'stroke-width') { + ret = wrapper.strokeweight; + } else { + ret = wrapper[key]; + } + + // setter + } else { + for (key in hash) { + value = hash[key]; + skipAttr = false; + + // check for a specific attribute setter + result = attrSetters[key] && attrSetters[key].call(wrapper, value, key); + + if (result !== false && value !== null) { // #620 + + if (result !== UNDEFINED) { + value = result; // the attribute setter has returned a new value to set + } + + + // prepare paths + // symbols + if (symbolName && /^(x|y|r|start|end|width|height|innerR|anchorX|anchorY)/.test(key)) { + // if one of the symbol size affecting parameters are changed, + // check all the others only once for each call to an element's + // .attr() method + if (!hasSetSymbolSize) { + wrapper.symbolAttr(hash); + + hasSetSymbolSize = true; + } + skipAttr = true; + + } else if (key === 'd') { + value = value || []; + wrapper.d = value.join(' '); // used in getter for animation + + element.path = value = wrapper.pathToVML(value); + + // update shadows + if (shadows) { + i = shadows.length; + while (i--) { + shadows[i].path = shadows[i].cutOff ? this.cutOffPath(value, shadows[i].cutOff) : value; + } + } + skipAttr = true; + + // handle visibility + } else if (key === 'visibility') { + + // let the shadow follow the main element + if (shadows) { + i = shadows.length; + while (i--) { + shadows[i].style[key] = value; + } + } + + // Instead of toggling the visibility CSS property, move the div out of the viewport. + // This works around #61 and #586 + if (nodeName === 'DIV') { + value = value === HIDDEN ? '-999em' : 0; + + // In order to redraw, IE7 needs the div to be visible when tucked away + // outside the viewport. So the visibility is actually opposite of + // the expected value. This applies to the tooltip only. + if (!docMode8) { + elemStyle[key] = value ? VISIBLE : HIDDEN; + } + key = 'top'; + } + elemStyle[key] = value; + skipAttr = true; + + // directly mapped to css + } else if (key === 'zIndex') { + + if (value) { + elemStyle[key] = value; + } + skipAttr = true; + + // x, y, width, height + } else if (inArray(key, ['x', 'y', 'width', 'height']) !== -1) { + + wrapper[key] = value; // used in getter + + if (key === 'x' || key === 'y') { + key = { x: 'left', y: 'top' }[key]; + } else { + value = mathMax(0, value); // don't set width or height below zero (#311) + } + + // clipping rectangle special + if (wrapper.updateClipping) { + wrapper[key] = value; // the key is now 'left' or 'top' for 'x' and 'y' + wrapper.updateClipping(); + } else { + // normal + elemStyle[key] = value; + } + + skipAttr = true; + + // class name + } else if (key === 'class' && nodeName === 'DIV') { + // IE8 Standards mode has problems retrieving the className + element.className = value; + + // stroke + } else if (key === 'stroke') { + + value = renderer.color(value, element, key); + + key = 'strokecolor'; + + // stroke width + } else if (key === 'stroke-width' || key === 'strokeWidth') { + element.stroked = value ? true : false; + key = 'strokeweight'; + wrapper[key] = value; // used in getter, issue #113 + if (isNumber(value)) { + value += PX; + } + + // dashStyle + } else if (key === 'dashstyle') { + var strokeElem = element.getElementsByTagName('stroke')[0] || + createElement(renderer.prepVML(['']), null, null, element); + strokeElem[key] = value || 'solid'; + wrapper.dashstyle = value; /* because changing stroke-width will change the dash length + and cause an epileptic effect */ + skipAttr = true; + + // fill + } else if (key === 'fill') { + + if (nodeName === 'SPAN') { // text color + elemStyle.color = value; + } else if (nodeName !== 'IMG') { // #1336 + element.filled = value !== NONE ? true : false; + + value = renderer.color(value, element, key, wrapper); + + key = 'fillcolor'; + } + + // opacity: don't bother - animation is too slow and filters introduce artifacts + } else if (key === 'opacity') { + /*css(element, { + opacity: value + });*/ + skipAttr = true; + + // rotation on VML elements + } else if (nodeName === 'shape' && key === 'rotation') { + + wrapper[key] = element.style[key] = value; // style is for #1873 + + // Correction for the 1x1 size of the shape container. Used in gauge needles. + element.style.left = -mathRound(mathSin(value * deg2rad) + 1) + PX; + element.style.top = mathRound(mathCos(value * deg2rad)) + PX; + + // translation for animation + } else if (key === 'translateX' || key === 'translateY' || key === 'rotation') { + wrapper[key] = value; + wrapper.updateTransform(); + + skipAttr = true; + + // text for rotated and non-rotated elements + } else if (key === 'text') { + this.bBox = null; + element.innerHTML = value; + skipAttr = true; + } + + + if (!skipAttr) { + if (docMode8) { // IE8 setAttribute bug + element[key] = value; + } else { + attr(element, key, value); + } + } + + } + } + } + return ret; + }, + + /** + * Set the element's clipping to a predefined rectangle + * + * @param {String} id The id of the clip rectangle + */ + clip: function (clipRect) { + var wrapper = this, + clipMembers, + cssRet; + + if (clipRect) { + clipMembers = clipRect.members; + erase(clipMembers, wrapper); // Ensure unique list of elements (#1258) + clipMembers.push(wrapper); + wrapper.destroyClip = function () { + erase(clipMembers, wrapper); + }; + cssRet = clipRect.getCSS(wrapper); + + } else { + if (wrapper.destroyClip) { + wrapper.destroyClip(); + } + cssRet = { clip: docMode8 ? 'inherit' : 'rect(auto)' }; // #1214 + } + + return wrapper.css(cssRet); + + }, + + /** + * Set styles for the element + * @param {Object} styles + */ + css: SVGElement.prototype.htmlCss, + + /** + * Removes a child either by removeChild or move to garbageBin. + * Issue 490; in VML removeChild results in Orphaned nodes according to sIEve, discardElement does not. + */ + safeRemoveChild: function (element) { + // discardElement will detach the node from its parent before attaching it + // to the garbage bin. Therefore it is important that the node is attached and have parent. + if (element.parentNode) { + discardElement(element); + } + }, + + /** + * Extend element.destroy by removing it from the clip members array + */ + destroy: function () { + if (this.destroyClip) { + this.destroyClip(); + } + + return SVGElement.prototype.destroy.apply(this); + }, + + /** + * Add an event listener. VML override for normalizing event parameters. + * @param {String} eventType + * @param {Function} handler + */ + on: function (eventType, handler) { + // simplest possible event model for internal use + this.element['on' + eventType] = function () { + var evt = win.event; + evt.target = evt.srcElement; + handler(evt); + }; + return this; + }, + + /** + * In stacked columns, cut off the shadows so that they don't overlap + */ + cutOffPath: function (path, length) { + + var len; + + path = path.split(/[ ,]/); + len = path.length; + + if (len === 9 || len === 11) { + path[len - 4] = path[len - 2] = pInt(path[len - 2]) - 10 * length; + } + return path.join(' '); + }, + + /** + * Apply a drop shadow by copying elements and giving them different strokes + * @param {Boolean|Object} shadowOptions + */ + shadow: function (shadowOptions, group, cutOff) { + var shadows = [], + i, + element = this.element, + renderer = this.renderer, + shadow, + elemStyle = element.style, + markup, + path = element.path, + strokeWidth, + modifiedPath, + shadowWidth, + shadowElementOpacity; + + // some times empty paths are not strings + if (path && typeof path.value !== 'string') { + path = 'x'; + } + modifiedPath = path; + + if (shadowOptions) { + shadowWidth = pick(shadowOptions.width, 3); + shadowElementOpacity = (shadowOptions.opacity || 0.15) / shadowWidth; + for (i = 1; i <= 3; i++) { + + strokeWidth = (shadowWidth * 2) + 1 - (2 * i); + + // Cut off shadows for stacked column items + if (cutOff) { + modifiedPath = this.cutOffPath(path.value, strokeWidth + 0.5); + } + + markup = ['']; + + shadow = createElement(renderer.prepVML(markup), + null, { + left: pInt(elemStyle.left) + pick(shadowOptions.offsetX, 1), + top: pInt(elemStyle.top) + pick(shadowOptions.offsetY, 1) + } + ); + if (cutOff) { + shadow.cutOff = strokeWidth + 1; + } + + // apply the opacity + markup = ['']; + createElement(renderer.prepVML(markup), null, null, shadow); + + + // insert it + if (group) { + group.element.appendChild(shadow); + } else { + element.parentNode.insertBefore(shadow, element); + } + + // record it + shadows.push(shadow); + + } + + this.shadows = shadows; + } + return this; + + } +}; +VMLElement = extendClass(SVGElement, VMLElement); + +/** + * The VML renderer + */ +var VMLRendererExtension = { // inherit SVGRenderer + + Element: VMLElement, + isIE8: userAgent.indexOf('MSIE 8.0') > -1, + + + /** + * Initialize the VMLRenderer + * @param {Object} container + * @param {Number} width + * @param {Number} height + */ + init: function (container, width, height) { + var renderer = this, + boxWrapper, + box; + + renderer.alignedObjects = []; + + boxWrapper = renderer.createElement(DIV); + box = boxWrapper.element; + box.style.position = RELATIVE; // for freeform drawing using renderer directly + container.appendChild(boxWrapper.element); + + + // generate the containing box + renderer.isVML = true; + renderer.box = box; + renderer.boxWrapper = boxWrapper; + + + renderer.setSize(width, height, false); + + // The only way to make IE6 and IE7 print is to use a global namespace. However, + // with IE8 the only way to make the dynamic shapes visible in screen and print mode + // seems to be to add the xmlns attribute and the behaviour style inline. + if (!doc.namespaces.hcv) { + + doc.namespaces.add('hcv', 'urn:schemas-microsoft-com:vml'); + + // Setup default CSS (#2153) + (doc.styleSheets.length ? doc.styleSheets[0] : doc.createStyleSheet()).cssText += + 'hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke' + + '{ behavior:url(#default#VML); display: inline-block; } '; + + } + }, + + + /** + * Detect whether the renderer is hidden. This happens when one of the parent elements + * has display: none + */ + isHidden: function () { + return !this.box.offsetWidth; + }, + + /** + * Define a clipping rectangle. In VML it is accomplished by storing the values + * for setting the CSS style to all associated members. + * + * @param {Number} x + * @param {Number} y + * @param {Number} width + * @param {Number} height + */ + clipRect: function (x, y, width, height) { + + // create a dummy element + var clipRect = this.createElement(), + isObj = isObject(x); + + // mimic a rectangle with its style object for automatic updating in attr + return extend(clipRect, { + members: [], + left: (isObj ? x.x : x) + 1, + top: (isObj ? x.y : y) + 1, + width: (isObj ? x.width : width) - 1, + height: (isObj ? x.height : height) - 1, + getCSS: function (wrapper) { + var element = wrapper.element, + nodeName = element.nodeName, + isShape = nodeName === 'shape', + inverted = wrapper.inverted, + rect = this, + top = rect.top - (isShape ? element.offsetTop : 0), + left = rect.left, + right = left + rect.width, + bottom = top + rect.height, + ret = { + clip: 'rect(' + + mathRound(inverted ? left : top) + 'px,' + + mathRound(inverted ? bottom : right) + 'px,' + + mathRound(inverted ? right : bottom) + 'px,' + + mathRound(inverted ? top : left) + 'px)' + }; + + // issue 74 workaround + if (!inverted && docMode8 && nodeName === 'DIV') { + extend(ret, { + width: right + PX, + height: bottom + PX + }); + } + return ret; + }, + + // used in attr and animation to update the clipping of all members + updateClipping: function () { + each(clipRect.members, function (member) { + member.css(clipRect.getCSS(member)); + }); + } + }); + + }, + + + /** + * Take a color and return it if it's a string, make it a gradient if it's a + * gradient configuration object, and apply opacity. + * + * @param {Object} color The color or config object + */ + color: function (color, elem, prop, wrapper) { + var renderer = this, + colorObject, + regexRgba = /^rgba/, + markup, + fillType, + ret = NONE; + + // Check for linear or radial gradient + if (color && color.linearGradient) { + fillType = 'gradient'; + } else if (color && color.radialGradient) { + fillType = 'pattern'; + } + + + if (fillType) { + + var stopColor, + stopOpacity, + gradient = color.linearGradient || color.radialGradient, + x1, + y1, + x2, + y2, + opacity1, + opacity2, + color1, + color2, + fillAttr = '', + stops = color.stops, + firstStop, + lastStop, + colors = [], + addFillNode = function () { + // Add the fill subnode. When colors attribute is used, the meanings of opacity and o:opacity2 + // are reversed. + markup = ['']; + createElement(renderer.prepVML(markup), null, null, elem); + }; + + // Extend from 0 to 1 + firstStop = stops[0]; + lastStop = stops[stops.length - 1]; + if (firstStop[0] > 0) { + stops.unshift([ + 0, + firstStop[1] + ]); + } + if (lastStop[0] < 1) { + stops.push([ + 1, + lastStop[1] + ]); + } + + // Compute the stops + each(stops, function (stop, i) { + if (regexRgba.test(stop[1])) { + colorObject = Color(stop[1]); + stopColor = colorObject.get('rgb'); + stopOpacity = colorObject.get('a'); + } else { + stopColor = stop[1]; + stopOpacity = 1; + } + + // Build the color attribute + colors.push((stop[0] * 100) + '% ' + stopColor); + + // Only start and end opacities are allowed, so we use the first and the last + if (!i) { + opacity1 = stopOpacity; + color2 = stopColor; + } else { + opacity2 = stopOpacity; + color1 = stopColor; + } + }); + + // Apply the gradient to fills only. + if (prop === 'fill') { + + // Handle linear gradient angle + if (fillType === 'gradient') { + x1 = gradient.x1 || gradient[0] || 0; + y1 = gradient.y1 || gradient[1] || 0; + x2 = gradient.x2 || gradient[2] || 0; + y2 = gradient.y2 || gradient[3] || 0; + fillAttr = 'angle="' + (90 - math.atan( + (y2 - y1) / // y vector + (x2 - x1) // x vector + ) * 180 / mathPI) + '"'; + + addFillNode(); + + // Radial (circular) gradient + } else { + + var r = gradient.r, + sizex = r * 2, + sizey = r * 2, + cx = gradient.cx, + cy = gradient.cy, + radialReference = elem.radialReference, + bBox, + applyRadialGradient = function () { + if (radialReference) { + bBox = wrapper.getBBox(); + cx += (radialReference[0] - bBox.x) / bBox.width - 0.5; + cy += (radialReference[1] - bBox.y) / bBox.height - 0.5; + sizex *= radialReference[2] / bBox.width; + sizey *= radialReference[2] / bBox.height; + } + fillAttr = 'src="' + defaultOptions.global.VMLRadialGradientURL + '" ' + + 'size="' + sizex + ',' + sizey + '" ' + + 'origin="0.5,0.5" ' + + 'position="' + cx + ',' + cy + '" ' + + 'color2="' + color2 + '" '; + + addFillNode(); + }; + + // Apply radial gradient + if (wrapper.added) { + applyRadialGradient(); + } else { + // We need to know the bounding box to get the size and position right + addEvent(wrapper, 'add', applyRadialGradient); + } + + // The fill element's color attribute is broken in IE8 standards mode, so we + // need to set the parent shape's fillcolor attribute instead. + ret = color1; + } + + // Gradients are not supported for VML stroke, return the first color. #722. + } else { + ret = stopColor; + } + + // if the color is an rgba color, split it and add a fill node + // to hold the opacity component + } else if (regexRgba.test(color) && elem.tagName !== 'IMG') { + + colorObject = Color(color); + + markup = ['<', prop, ' opacity="', colorObject.get('a'), '"/>']; + createElement(this.prepVML(markup), null, null, elem); + + ret = colorObject.get('rgb'); + + + } else { + var propNodes = elem.getElementsByTagName(prop); // 'stroke' or 'fill' node + if (propNodes.length) { + propNodes[0].opacity = 1; + propNodes[0].type = 'solid'; + } + ret = color; + } + + return ret; + }, + + /** + * Take a VML string and prepare it for either IE8 or IE6/IE7. + * @param {Array} markup A string array of the VML markup to prepare + */ + prepVML: function (markup) { + var vmlStyle = 'display:inline-block;behavior:url(#default#VML);', + isIE8 = this.isIE8; + + markup = markup.join(''); + + if (isIE8) { // add xmlns and style inline + markup = markup.replace('/>', ' xmlns="urn:schemas-microsoft-com:vml" />'); + if (markup.indexOf('style="') === -1) { + markup = markup.replace('/>', ' style="' + vmlStyle + '" />'); + } else { + markup = markup.replace('style="', 'style="' + vmlStyle); + } + + } else { // add namespace + markup = markup.replace('<', ' 1) { + obj.attr({ + x: x, + y: y, + width: width, + height: height + }); + } + return obj; + }, + + /** + * VML uses a shape for rect to overcome bugs and rotation problems + */ + rect: function (x, y, width, height, r, strokeWidth) { + + var wrapper = this.symbol('rect'); + wrapper.r = isObject(x) ? x.r : r; + + //return wrapper.attr(wrapper.crisp(strokeWidth, x, y, mathMax(width, 0), mathMax(height, 0))); + return wrapper.attr( + isObject(x) ? + x : + // do not crispify when an object is passed in (as in column charts) + wrapper.crisp(strokeWidth, x, y, mathMax(width, 0), mathMax(height, 0)) + ); + }, + + /** + * In the VML renderer, each child of an inverted div (group) is inverted + * @param {Object} element + * @param {Object} parentNode + */ + invertChild: function (element, parentNode) { + var parentStyle = parentNode.style; + css(element, { + flip: 'x', + left: pInt(parentStyle.width) - 1, + top: pInt(parentStyle.height) - 1, + rotation: -90 + }); + }, + + /** + * Symbol definitions that override the parent SVG renderer's symbols + * + */ + symbols: { + // VML specific arc function + arc: function (x, y, w, h, options) { + var start = options.start, + end = options.end, + radius = options.r || w || h, + innerRadius = options.innerR, + cosStart = mathCos(start), + sinStart = mathSin(start), + cosEnd = mathCos(end), + sinEnd = mathSin(end), + ret; + + if (end - start === 0) { // no angle, don't show it. + return ['x']; + } + + ret = [ + 'wa', // clockwise arc to + x - radius, // left + y - radius, // top + x + radius, // right + y + radius, // bottom + x + radius * cosStart, // start x + y + radius * sinStart, // start y + x + radius * cosEnd, // end x + y + radius * sinEnd // end y + ]; + + if (options.open && !innerRadius) { + ret.push( + 'e', + M, + x,// - innerRadius, + y// - innerRadius + ); + } + + ret.push( + 'at', // anti clockwise arc to + x - innerRadius, // left + y - innerRadius, // top + x + innerRadius, // right + y + innerRadius, // bottom + x + innerRadius * cosEnd, // start x + y + innerRadius * sinEnd, // start y + x + innerRadius * cosStart, // end x + y + innerRadius * sinStart, // end y + 'x', // finish path + 'e' // close + ); + + ret.isArc = true; + return ret; + + }, + // Add circle symbol path. This performs significantly faster than v:oval. + circle: function (x, y, w, h, wrapper) { + + if (wrapper) { + w = h = 2 * wrapper.r; + } + + // Center correction, #1682 + if (wrapper && wrapper.isCircle) { + x -= w / 2; + y -= h / 2; + } + + // Return the path + return [ + 'wa', // clockwisearcto + x, // left + y, // top + x + w, // right + y + h, // bottom + x + w, // start x + y + h / 2, // start y + x + w, // end x + y + h / 2, // end y + //'x', // finish path + 'e' // close + ]; + }, + /** + * Add rectangle symbol path which eases rotation and omits arcsize problems + * compared to the built-in VML roundrect shape + * + * @param {Number} left Left position + * @param {Number} top Top position + * @param {Number} r Border radius + * @param {Object} options Width and height + */ + + rect: function (left, top, width, height, options) { + + var right = left + width, + bottom = top + height, + ret, + r; + + // No radius, return the more lightweight square + if (!defined(options) || !options.r) { + ret = SVGRenderer.prototype.symbols.square.apply(0, arguments); + + // Has radius add arcs for the corners + } else { + + r = mathMin(options.r, width, height); + ret = [ + M, + left + r, top, + + L, + right - r, top, + 'wa', + right - 2 * r, top, + right, top + 2 * r, + right - r, top, + right, top + r, + + L, + right, bottom - r, + 'wa', + right - 2 * r, bottom - 2 * r, + right, bottom, + right, bottom - r, + right - r, bottom, + + L, + left + r, bottom, + 'wa', + left, bottom - 2 * r, + left + 2 * r, bottom, + left + r, bottom, + left, bottom - r, + + L, + left, top + r, + 'wa', + left, top, + left + 2 * r, top + 2 * r, + left, top + r, + left + r, top, + + + 'x', + 'e' + ]; + } + return ret; + } + } +}; +Highcharts.VMLRenderer = VMLRenderer = function () { + this.init.apply(this, arguments); +}; +VMLRenderer.prototype = merge(SVGRenderer.prototype, VMLRendererExtension); + + // general renderer + Renderer = VMLRenderer; +} + +/* **************************************************************************** + * * + * END OF INTERNET EXPLORER <= 8 SPECIFIC CODE * + * * + *****************************************************************************/ +/* **************************************************************************** + * * + * START OF ANDROID < 3 SPECIFIC CODE. THIS CAN BE REMOVED IF YOU'RE NOT * + * TARGETING THAT SYSTEM. * + * * + *****************************************************************************/ +var CanVGRenderer, + CanVGController; + +if (useCanVG) { + /** + * The CanVGRenderer is empty from start to keep the source footprint small. + * When requested, the CanVGController downloads the rest of the source packaged + * together with the canvg library. + */ + Highcharts.CanVGRenderer = CanVGRenderer = function () { + // Override the global SVG namespace to fake SVG/HTML that accepts CSS + SVG_NS = 'http://www.w3.org/1999/xhtml'; + }; + + /** + * Start with an empty symbols object. This is needed when exporting is used (exporting.src.js will add a few symbols), but + * the implementation from SvgRenderer will not be merged in until first render. + */ + CanVGRenderer.prototype.symbols = {}; + + /** + * Handles on demand download of canvg rendering support. + */ + CanVGController = (function () { + // List of renderering calls + var deferredRenderCalls = []; + + /** + * When downloaded, we are ready to draw deferred charts. + */ + function drawDeferred() { + var callLength = deferredRenderCalls.length, + callIndex; + + // Draw all pending render calls + for (callIndex = 0; callIndex < callLength; callIndex++) { + deferredRenderCalls[callIndex](); + } + // Clear the list + deferredRenderCalls = []; + } + + return { + push: function (func, scriptLocation) { + // Only get the script once + if (deferredRenderCalls.length === 0) { + getScript(scriptLocation, drawDeferred); + } + // Register render call + deferredRenderCalls.push(func); + } + }; + }()); + + Renderer = CanVGRenderer; +} // end CanVGRenderer + +/* **************************************************************************** + * * + * END OF ANDROID < 3 SPECIFIC CODE * + * * + *****************************************************************************/ + +/** + * The Tick class + */ +function Tick(axis, pos, type, noLabel) { + this.axis = axis; + this.pos = pos; + this.type = type || ''; + this.isNew = true; + + if (!type && !noLabel) { + this.addLabel(); + } +} + +Tick.prototype = { + /** + * Write the tick label + */ + addLabel: function () { + var tick = this, + axis = tick.axis, + options = axis.options, + chart = axis.chart, + horiz = axis.horiz, + categories = axis.categories, + names = axis.series[0] && axis.series[0].names, + pos = tick.pos, + labelOptions = options.labels, + str, + tickPositions = axis.tickPositions, + width = (horiz && categories && + !labelOptions.step && !labelOptions.staggerLines && + !labelOptions.rotation && + chart.plotWidth / tickPositions.length) || + (!horiz && (chart.margin[3] || chart.chartWidth * 0.33)), // #1580, #1931 + isFirst = pos === tickPositions[0], + isLast = pos === tickPositions[tickPositions.length - 1], + css, + attr, + value = categories ? + pick(categories[pos], names && names[pos], pos) : + pos, + label = tick.label, + tickPositionInfo = tickPositions.info, + dateTimeLabelFormat; + + // Set the datetime label format. If a higher rank is set for this position, use that. If not, + // use the general format. + if (axis.isDatetimeAxis && tickPositionInfo) { + dateTimeLabelFormat = options.dateTimeLabelFormats[tickPositionInfo.higherRanks[pos] || tickPositionInfo.unitName]; + } + + // set properties for access in render method + tick.isFirst = isFirst; + tick.isLast = isLast; + + // get the string + str = axis.labelFormatter.call({ + axis: axis, + chart: chart, + isFirst: isFirst, + isLast: isLast, + dateTimeLabelFormat: dateTimeLabelFormat, + value: axis.isLog ? correctFloat(lin2log(value)) : value + }); + + // prepare CSS + css = width && { width: mathMax(1, mathRound(width - 2 * (labelOptions.padding || 10))) + PX }; + css = extend(css, labelOptions.style); + + // first call + if (!defined(label)) { + attr = { + align: axis.labelAlign + }; + if (isNumber(labelOptions.rotation)) { + attr.rotation = labelOptions.rotation; + } + if (width && labelOptions.ellipsis) { + attr._clipHeight = axis.len / tickPositions.length; + } + + tick.label = + defined(str) && labelOptions.enabled ? + chart.renderer.text( + str, + 0, + 0, + labelOptions.useHTML + ) + .attr(attr) + // without position absolute, IE export sometimes is wrong + .css(css) + .add(axis.labelGroup) : + null; + + // update + } else if (label) { + label.attr({ + text: str + }) + .css(css); + } + }, + + /** + * Get the offset height or width of the label + */ + getLabelSize: function () { + var label = this.label, + axis = this.axis; + return label ? + ((this.labelBBox = label.getBBox()))[axis.horiz ? 'height' : 'width'] : + 0; + }, + + /** + * Find how far the labels extend to the right and left of the tick's x position. Used for anti-collision + * detection with overflow logic. + */ + getLabelSides: function () { + var bBox = this.labelBBox, // assume getLabelSize has run at this point + axis = this.axis, + options = axis.options, + labelOptions = options.labels, + width = bBox.width, + leftSide = width * { left: 0, center: 0.5, right: 1 }[axis.labelAlign] - labelOptions.x; + + return [-leftSide, width - leftSide]; + }, + + /** + * Handle the label overflow by adjusting the labels to the left and right edge, or + * hide them if they collide into the neighbour label. + */ + handleOverflow: function (index, xy) { + var show = true, + axis = this.axis, + chart = axis.chart, + isFirst = this.isFirst, + isLast = this.isLast, + x = xy.x, + reversed = axis.reversed, + tickPositions = axis.tickPositions; + + if (isFirst || isLast) { + + var sides = this.getLabelSides(), + leftSide = sides[0], + rightSide = sides[1], + plotLeft = chart.plotLeft, + plotRight = plotLeft + axis.len, + neighbour = axis.ticks[tickPositions[index + (isFirst ? 1 : -1)]], + neighbourEdge = neighbour && neighbour.label.xy && neighbour.label.xy.x + neighbour.getLabelSides()[isFirst ? 0 : 1]; + + if ((isFirst && !reversed) || (isLast && reversed)) { + // Is the label spilling out to the left of the plot area? + if (x + leftSide < plotLeft) { + + // Align it to plot left + x = plotLeft - leftSide; + + // Hide it if it now overlaps the neighbour label + if (neighbour && x + rightSide > neighbourEdge) { + show = false; + } + } + + } else { + // Is the label spilling out to the right of the plot area? + if (x + rightSide > plotRight) { + + // Align it to plot right + x = plotRight - rightSide; + + // Hide it if it now overlaps the neighbour label + if (neighbour && x + leftSide < neighbourEdge) { + show = false; + } + + } + } + + // Set the modified x position of the label + xy.x = x; + } + return show; + }, + + /** + * Get the x and y position for ticks and labels + */ + getPosition: function (horiz, pos, tickmarkOffset, old) { + var axis = this.axis, + chart = axis.chart, + cHeight = (old && chart.oldChartHeight) || chart.chartHeight; + + return { + x: horiz ? + axis.translate(pos + tickmarkOffset, null, null, old) + axis.transB : + axis.left + axis.offset + (axis.opposite ? ((old && chart.oldChartWidth) || chart.chartWidth) - axis.right - axis.left : 0), + + y: horiz ? + cHeight - axis.bottom + axis.offset - (axis.opposite ? axis.height : 0) : + cHeight - axis.translate(pos + tickmarkOffset, null, null, old) - axis.transB + }; + + }, + + /** + * Get the x, y position of the tick label + */ + getLabelPosition: function (x, y, label, horiz, labelOptions, tickmarkOffset, index, step) { + var axis = this.axis, + transA = axis.transA, + reversed = axis.reversed, + staggerLines = axis.staggerLines, + baseline = axis.chart.renderer.fontMetrics(labelOptions.style.fontSize).b, + rotation = labelOptions.rotation; + + x = x + labelOptions.x - (tickmarkOffset && horiz ? + tickmarkOffset * transA * (reversed ? -1 : 1) : 0); + y = y + labelOptions.y - (tickmarkOffset && !horiz ? + tickmarkOffset * transA * (reversed ? 1 : -1) : 0); + + // Correct for rotation (#1764) + if (rotation && axis.side === 2) { + y -= baseline - baseline * mathCos(rotation * deg2rad); + } + + // Vertically centered + if (!defined(labelOptions.y) && !rotation) { // #1951 + y += baseline - label.getBBox().height / 2; + } + + // Correct for staggered labels + if (staggerLines) { + y += (index / (step || 1) % staggerLines) * (axis.labelOffset / staggerLines); + } + + return { + x: x, + y: y + }; + }, + + /** + * Extendible method to return the path of the marker + */ + getMarkPath: function (x, y, tickLength, tickWidth, horiz, renderer) { + return renderer.crispLine([ + M, + x, + y, + L, + x + (horiz ? 0 : -tickLength), + y + (horiz ? tickLength : 0) + ], tickWidth); + }, + + /** + * Put everything in place + * + * @param index {Number} + * @param old {Boolean} Use old coordinates to prepare an animation into new position + */ + render: function (index, old, opacity) { + var tick = this, + axis = tick.axis, + options = axis.options, + chart = axis.chart, + renderer = chart.renderer, + horiz = axis.horiz, + type = tick.type, + label = tick.label, + pos = tick.pos, + labelOptions = options.labels, + gridLine = tick.gridLine, + gridPrefix = type ? type + 'Grid' : 'grid', + tickPrefix = type ? type + 'Tick' : 'tick', + gridLineWidth = options[gridPrefix + 'LineWidth'], + gridLineColor = options[gridPrefix + 'LineColor'], + dashStyle = options[gridPrefix + 'LineDashStyle'], + tickLength = options[tickPrefix + 'Length'], + tickWidth = options[tickPrefix + 'Width'] || 0, + tickColor = options[tickPrefix + 'Color'], + tickPosition = options[tickPrefix + 'Position'], + gridLinePath, + mark = tick.mark, + markPath, + step = labelOptions.step, + attribs, + show = true, + tickmarkOffset = axis.tickmarkOffset, + xy = tick.getPosition(horiz, pos, tickmarkOffset, old), + x = xy.x, + y = xy.y, + reverseCrisp = ((horiz && x === axis.pos + axis.len) || (!horiz && y === axis.pos)) ? -1 : 1, // #1480, #1687 + staggerLines = axis.staggerLines; + + this.isActive = true; + + // create the grid line + if (gridLineWidth) { + gridLinePath = axis.getPlotLinePath(pos + tickmarkOffset, gridLineWidth * reverseCrisp, old, true); + + if (gridLine === UNDEFINED) { + attribs = { + stroke: gridLineColor, + 'stroke-width': gridLineWidth + }; + if (dashStyle) { + attribs.dashstyle = dashStyle; + } + if (!type) { + attribs.zIndex = 1; + } + if (old) { + attribs.opacity = 0; + } + tick.gridLine = gridLine = + gridLineWidth ? + renderer.path(gridLinePath) + .attr(attribs).add(axis.gridGroup) : + null; + } + + // If the parameter 'old' is set, the current call will be followed + // by another call, therefore do not do any animations this time + if (!old && gridLine && gridLinePath) { + gridLine[tick.isNew ? 'attr' : 'animate']({ + d: gridLinePath, + opacity: opacity + }); + } + } + + // create the tick mark + if (tickWidth && tickLength) { + + // negate the length + if (tickPosition === 'inside') { + tickLength = -tickLength; + } + if (axis.opposite) { + tickLength = -tickLength; + } + + markPath = tick.getMarkPath(x, y, tickLength, tickWidth * reverseCrisp, horiz, renderer); + + if (mark) { // updating + mark.animate({ + d: markPath, + opacity: opacity + }); + } else { // first time + tick.mark = renderer.path( + markPath + ).attr({ + stroke: tickColor, + 'stroke-width': tickWidth, + opacity: opacity + }).add(axis.axisGroup); + } + } + + // the label is created on init - now move it into place + if (label && !isNaN(x)) { + label.xy = xy = tick.getLabelPosition(x, y, label, horiz, labelOptions, tickmarkOffset, index, step); + + // Apply show first and show last. If the tick is both first and last, it is + // a single centered tick, in which case we show the label anyway (#2100). + if ((tick.isFirst && !tick.isLast && !pick(options.showFirstLabel, 1)) || + (tick.isLast && !tick.isFirst && !pick(options.showLastLabel, 1))) { + show = false; + + // Handle label overflow and show or hide accordingly + } else if (!staggerLines && horiz && labelOptions.overflow === 'justify' && !tick.handleOverflow(index, xy)) { + show = false; + } + + // apply step + if (step && index % step) { + // show those indices dividable by step + show = false; + } + + // Set the new position, and show or hide + if (show && !isNaN(xy.y)) { + xy.opacity = opacity; + label[tick.isNew ? 'attr' : 'animate'](xy); + tick.isNew = false; + } else { + label.attr('y', -9999); // #1338 + } + } + }, + + /** + * Destructor for the tick prototype + */ + destroy: function () { + destroyObjectProperties(this, this.axis); + } +}; + +/** + * The object wrapper for plot lines and plot bands + * @param {Object} options + */ +function PlotLineOrBand(axis, options) { + this.axis = axis; + + if (options) { + this.options = options; + this.id = options.id; + } +} + +PlotLineOrBand.prototype = { + + /** + * Render the plot line or plot band. If it is already existing, + * move it. + */ + render: function () { + var plotLine = this, + axis = plotLine.axis, + horiz = axis.horiz, + halfPointRange = (axis.pointRange || 0) / 2, + options = plotLine.options, + optionsLabel = options.label, + label = plotLine.label, + width = options.width, + to = options.to, + from = options.from, + isBand = defined(from) && defined(to), + value = options.value, + dashStyle = options.dashStyle, + svgElem = plotLine.svgElem, + path = [], + addEvent, + eventType, + xs, + ys, + x, + y, + color = options.color, + zIndex = options.zIndex, + events = options.events, + attribs, + renderer = axis.chart.renderer; + + // logarithmic conversion + if (axis.isLog) { + from = log2lin(from); + to = log2lin(to); + value = log2lin(value); + } + + // plot line + if (width) { + path = axis.getPlotLinePath(value, width); + attribs = { + stroke: color, + 'stroke-width': width + }; + if (dashStyle) { + attribs.dashstyle = dashStyle; + } + } else if (isBand) { // plot band + + // keep within plot area + from = mathMax(from, axis.min - halfPointRange); + to = mathMin(to, axis.max + halfPointRange); + + path = axis.getPlotBandPath(from, to, options); + attribs = { + fill: color + }; + if (options.borderWidth) { + attribs.stroke = options.borderColor; + attribs['stroke-width'] = options.borderWidth; + } + } else { + return; + } + // zIndex + if (defined(zIndex)) { + attribs.zIndex = zIndex; + } + + // common for lines and bands + if (svgElem) { + if (path) { + svgElem.animate({ + d: path + }, null, svgElem.onGetPath); + } else { + svgElem.hide(); + svgElem.onGetPath = function () { + svgElem.show(); + }; + } + } else if (path && path.length) { + plotLine.svgElem = svgElem = renderer.path(path) + .attr(attribs).add(); + + // events + if (events) { + addEvent = function (eventType) { + svgElem.on(eventType, function (e) { + events[eventType].apply(plotLine, [e]); + }); + }; + for (eventType in events) { + addEvent(eventType); + } + } + } + + // the plot band/line label + if (optionsLabel && defined(optionsLabel.text) && path && path.length && axis.width > 0 && axis.height > 0) { + // apply defaults + optionsLabel = merge({ + align: horiz && isBand && 'center', + x: horiz ? !isBand && 4 : 10, + verticalAlign : !horiz && isBand && 'middle', + y: horiz ? isBand ? 16 : 10 : isBand ? 6 : -4, + rotation: horiz && !isBand && 90 + }, optionsLabel); + + // add the SVG element + if (!label) { + plotLine.label = label = renderer.text( + optionsLabel.text, + 0, + 0, + optionsLabel.useHTML + ) + .attr({ + align: optionsLabel.textAlign || optionsLabel.align, + rotation: optionsLabel.rotation, + zIndex: zIndex + }) + .css(optionsLabel.style) + .add(); + } + + // get the bounding box and align the label + xs = [path[1], path[4], pick(path[6], path[1])]; + ys = [path[2], path[5], pick(path[7], path[2])]; + x = arrayMin(xs); + y = arrayMin(ys); + + label.align(optionsLabel, false, { + x: x, + y: y, + width: arrayMax(xs) - x, + height: arrayMax(ys) - y + }); + label.show(); + + } else if (label) { // move out of sight + label.hide(); + } + + // chainable + return plotLine; + }, + + /** + * Remove the plot line or band + */ + destroy: function () { + // remove it from the lookup + erase(this.axis.plotLinesAndBands, this); + + delete this.axis; + destroyObjectProperties(this); + } +}; +/** + * The class for stack items + */ +function StackItem(axis, options, isNegative, x, stackOption, stacking) { + + var inverted = axis.chart.inverted; + + this.axis = axis; + + // Tells if the stack is negative + this.isNegative = isNegative; + + // Save the options to be able to style the label + this.options = options; + + // Save the x value to be able to position the label later + this.x = x; + + // Initialize total value + this.total = null; + + // This will keep each points' extremes stored by series.index + this.points = {}; + + // Save the stack option on the series configuration object, and whether to treat it as percent + this.stack = stackOption; + this.percent = stacking === 'percent'; + + // The align options and text align varies on whether the stack is negative and + // if the chart is inverted or not. + // First test the user supplied value, then use the dynamic. + this.alignOptions = { + align: options.align || (inverted ? (isNegative ? 'left' : 'right') : 'center'), + verticalAlign: options.verticalAlign || (inverted ? 'middle' : (isNegative ? 'bottom' : 'top')), + y: pick(options.y, inverted ? 4 : (isNegative ? 14 : -6)), + x: pick(options.x, inverted ? (isNegative ? -6 : 6) : 0) + }; + + this.textAlign = options.textAlign || (inverted ? (isNegative ? 'right' : 'left') : 'center'); +} + +StackItem.prototype = { + destroy: function () { + destroyObjectProperties(this, this.axis); + }, + + /** + * Renders the stack total label and adds it to the stack label group. + */ + render: function (group) { + var options = this.options, + formatOption = options.format, + str = formatOption ? + format(formatOption, this) : + options.formatter.call(this); // format the text in the label + + // Change the text to reflect the new total and set visibility to hidden in case the serie is hidden + if (this.label) { + this.label.attr({text: str, visibility: HIDDEN}); + // Create new label + } else { + this.label = + this.axis.chart.renderer.text(str, 0, 0, options.useHTML) // dummy positions, actual position updated with setOffset method in columnseries + .css(options.style) // apply style + .attr({ + align: this.textAlign, // fix the text-anchor + rotation: options.rotation, // rotation + visibility: HIDDEN // hidden until setOffset is called + }) + .add(group); // add to the labels-group + } + }, + + /** + * Sets the offset that the stack has from the x value and repositions the label. + */ + setOffset: function (xOffset, xWidth) { + var stackItem = this, + axis = stackItem.axis, + chart = axis.chart, + inverted = chart.inverted, + neg = this.isNegative, // special treatment is needed for negative stacks + y = axis.translate(this.percent ? 100 : this.total, 0, 0, 0, 1), // stack value translated mapped to chart coordinates + yZero = axis.translate(0), // stack origin + h = mathAbs(y - yZero), // stack height + x = chart.xAxis[0].translate(this.x) + xOffset, // stack x position + plotHeight = chart.plotHeight, + stackBox = { // this is the box for the complete stack + x: inverted ? (neg ? y : y - h) : x, + y: inverted ? plotHeight - x - xWidth : (neg ? (plotHeight - y - h) : plotHeight - y), + width: inverted ? h : xWidth, + height: inverted ? xWidth : h + }, + label = this.label, + alignAttr; + + if (label) { + label.align(this.alignOptions, null, stackBox); // align the label to the box + + // Set visibility (#678) + alignAttr = label.alignAttr; + label.attr({ + visibility: this.options.crop === false || chart.isInsidePlot(alignAttr.x, alignAttr.y) ? + (hasSVG ? 'inherit' : VISIBLE) : + HIDDEN + }); + } + } +}; +/** + * Create a new axis object + * @param {Object} chart + * @param {Object} options + */ +function Axis() { + this.init.apply(this, arguments); +} + +Axis.prototype = { + + /** + * Default options for the X axis - the Y axis has extended defaults + */ + defaultOptions: { + // allowDecimals: null, + // alternateGridColor: null, + // categories: [], + dateTimeLabelFormats: { + millisecond: '%H:%M:%S.%L', + second: '%H:%M:%S', + minute: '%H:%M', + hour: '%H:%M', + day: '%e. %b', + week: '%e. %b', + month: '%b \'%y', + year: '%Y' + }, + endOnTick: false, + gridLineColor: '#C0C0C0', + // gridLineDashStyle: 'solid', + // gridLineWidth: 0, + // reversed: false, + + labels: defaultLabelOptions, + // { step: null }, + lineColor: '#C0D0E0', + lineWidth: 1, + //linkedTo: null, + //max: undefined, + //min: undefined, + minPadding: 0.01, + maxPadding: 0.01, + //minRange: null, + minorGridLineColor: '#E0E0E0', + // minorGridLineDashStyle: null, + minorGridLineWidth: 1, + minorTickColor: '#A0A0A0', + //minorTickInterval: null, + minorTickLength: 2, + minorTickPosition: 'outside', // inside or outside + //minorTickWidth: 0, + //opposite: false, + //offset: 0, + //plotBands: [{ + // events: {}, + // zIndex: 1, + // labels: { align, x, verticalAlign, y, style, rotation, textAlign } + //}], + //plotLines: [{ + // events: {} + // dashStyle: {} + // zIndex: + // labels: { align, x, verticalAlign, y, style, rotation, textAlign } + //}], + //reversed: false, + // showFirstLabel: true, + // showLastLabel: true, + startOfWeek: 1, + startOnTick: false, + tickColor: '#C0D0E0', + //tickInterval: null, + tickLength: 5, + tickmarkPlacement: 'between', // on or between + tickPixelInterval: 100, + tickPosition: 'outside', + tickWidth: 1, + title: { + //text: null, + align: 'middle', // low, middle or high + //margin: 0 for horizontal, 10 for vertical axes, + //rotation: 0, + //side: 'outside', + style: { + color: '#4d759e', + //font: defaultFont.replace('normal', 'bold') + fontWeight: 'bold' + } + //x: 0, + //y: 0 + }, + type: 'linear' // linear, logarithmic or datetime + }, + + /** + * This options set extends the defaultOptions for Y axes + */ + defaultYAxisOptions: { + endOnTick: true, + gridLineWidth: 1, + tickPixelInterval: 72, + showLastLabel: true, + labels: { + x: -8, + y: 3 + }, + lineWidth: 0, + maxPadding: 0.05, + minPadding: 0.05, + startOnTick: true, + tickWidth: 0, + title: { + rotation: 270, + text: 'Values' + }, + stackLabels: { + enabled: false, + //align: dynamic, + //y: dynamic, + //x: dynamic, + //verticalAlign: dynamic, + //textAlign: dynamic, + //rotation: 0, + formatter: function () { + return numberFormat(this.total, -1); + }, + style: defaultLabelOptions.style + } + }, + + /** + * These options extend the defaultOptions for left axes + */ + defaultLeftAxisOptions: { + labels: { + x: -8, + y: null + }, + title: { + rotation: 270 + } + }, + + /** + * These options extend the defaultOptions for right axes + */ + defaultRightAxisOptions: { + labels: { + x: 8, + y: null + }, + title: { + rotation: 90 + } + }, + + /** + * These options extend the defaultOptions for bottom axes + */ + defaultBottomAxisOptions: { + labels: { + x: 0, + y: 14 + // overflow: undefined, + // staggerLines: null + }, + title: { + rotation: 0 + } + }, + /** + * These options extend the defaultOptions for left axes + */ + defaultTopAxisOptions: { + labels: { + x: 0, + y: -5 + // overflow: undefined + // staggerLines: null + }, + title: { + rotation: 0 + } + }, + + /** + * Initialize the axis + */ + init: function (chart, userOptions) { + + + var isXAxis = userOptions.isX, + axis = this; + + // Flag, is the axis horizontal + axis.horiz = chart.inverted ? !isXAxis : isXAxis; + + // Flag, isXAxis + axis.isXAxis = isXAxis; + axis.xOrY = isXAxis ? 'x' : 'y'; + + + axis.opposite = userOptions.opposite; // needed in setOptions + axis.side = axis.horiz ? + (axis.opposite ? 0 : 2) : // top : bottom + (axis.opposite ? 1 : 3); // right : left + + axis.setOptions(userOptions); + + + var options = this.options, + type = options.type, + isDatetimeAxis = type === 'datetime'; + + axis.labelFormatter = options.labels.formatter || axis.defaultLabelFormatter; // can be overwritten by dynamic format + + + // Flag, stagger lines or not + axis.userOptions = userOptions; + + //axis.axisTitleMargin = UNDEFINED,// = options.title.margin, + axis.minPixelPadding = 0; + //axis.ignoreMinPadding = UNDEFINED; // can be set to true by a column or bar series + //axis.ignoreMaxPadding = UNDEFINED; + + axis.chart = chart; + axis.reversed = options.reversed; + axis.zoomEnabled = options.zoomEnabled !== false; + + // Initial categories + axis.categories = options.categories || type === 'category'; + + // Elements + //axis.axisGroup = UNDEFINED; + //axis.gridGroup = UNDEFINED; + //axis.axisTitle = UNDEFINED; + //axis.axisLine = UNDEFINED; + + // Shorthand types + axis.isLog = type === 'logarithmic'; + axis.isDatetimeAxis = isDatetimeAxis; + + // Flag, if axis is linked to another axis + axis.isLinked = defined(options.linkedTo); + // Linked axis. + //axis.linkedParent = UNDEFINED; + + // Tick positions + //axis.tickPositions = UNDEFINED; // array containing predefined positions + // Tick intervals + //axis.tickInterval = UNDEFINED; + //axis.minorTickInterval = UNDEFINED; + + axis.tickmarkOffset = (axis.categories && options.tickmarkPlacement === 'between') ? 0.5 : 0; + + // Major ticks + axis.ticks = {}; + // Minor ticks + axis.minorTicks = {}; + //axis.tickAmount = UNDEFINED; + + // List of plotLines/Bands + axis.plotLinesAndBands = []; + + // Alternate bands + axis.alternateBands = {}; + + // Axis metrics + //axis.left = UNDEFINED; + //axis.top = UNDEFINED; + //axis.width = UNDEFINED; + //axis.height = UNDEFINED; + //axis.bottom = UNDEFINED; + //axis.right = UNDEFINED; + //axis.transA = UNDEFINED; + //axis.transB = UNDEFINED; + //axis.oldTransA = UNDEFINED; + axis.len = 0; + //axis.oldMin = UNDEFINED; + //axis.oldMax = UNDEFINED; + //axis.oldUserMin = UNDEFINED; + //axis.oldUserMax = UNDEFINED; + //axis.oldAxisLength = UNDEFINED; + axis.minRange = axis.userMinRange = options.minRange || options.maxZoom; + axis.range = options.range; + axis.offset = options.offset || 0; + + + // Dictionary for stacks + axis.stacks = {}; + axis.oldStacks = {}; + + // Dictionary for stacks max values + axis.stackExtremes = {}; + + // Min and max in the data + //axis.dataMin = UNDEFINED, + //axis.dataMax = UNDEFINED, + + // The axis range + axis.max = null; + axis.min = null; + + // User set min and max + //axis.userMin = UNDEFINED, + //axis.userMax = UNDEFINED, + + // Run Axis + + var eventType, + events = axis.options.events; + + // Register + if (inArray(axis, chart.axes) === -1) { // don't add it again on Axis.update() + chart.axes.push(axis); + chart[isXAxis ? 'xAxis' : 'yAxis'].push(axis); + } + + axis.series = axis.series || []; // populated by Series + + // inverted charts have reversed xAxes as default + if (chart.inverted && isXAxis && axis.reversed === UNDEFINED) { + axis.reversed = true; + } + + axis.removePlotBand = axis.removePlotBandOrLine; + axis.removePlotLine = axis.removePlotBandOrLine; + + + // register event listeners + for (eventType in events) { + addEvent(axis, eventType, events[eventType]); + } + + // extend logarithmic axis + if (axis.isLog) { + axis.val2lin = log2lin; + axis.lin2val = lin2log; + } + }, + + /** + * Merge and set options + */ + setOptions: function (userOptions) { + this.options = merge( + this.defaultOptions, + this.isXAxis ? {} : this.defaultYAxisOptions, + [this.defaultTopAxisOptions, this.defaultRightAxisOptions, + this.defaultBottomAxisOptions, this.defaultLeftAxisOptions][this.side], + merge( + defaultOptions[this.isXAxis ? 'xAxis' : 'yAxis'], // if set in setOptions (#1053) + userOptions + ) + ); + }, + + /** + * Update the axis with a new options structure + */ + update: function (newOptions, redraw) { + var chart = this.chart; + + newOptions = chart.options[this.xOrY + 'Axis'][this.options.index] = merge(this.userOptions, newOptions); + + this.destroy(true); + this._addedPlotLB = this.userMin = this.userMax = UNDEFINED; // #1611, #2306 + + this.init(chart, extend(newOptions, { events: UNDEFINED })); + + chart.isDirtyBox = true; + if (pick(redraw, true)) { + chart.redraw(); + } + }, + + /** + * Remove the axis from the chart + */ + remove: function (redraw) { + var chart = this.chart, + key = this.xOrY + 'Axis'; // xAxis or yAxis + + // Remove associated series + each(this.series, function (series) { + series.remove(false); + }); + + // Remove the axis + erase(chart.axes, this); + erase(chart[key], this); + chart.options[key].splice(this.options.index, 1); + each(chart[key], function (axis, i) { // Re-index, #1706 + axis.options.index = i; + }); + this.destroy(); + chart.isDirtyBox = true; + + if (pick(redraw, true)) { + chart.redraw(); + } + }, + + /** + * The default label formatter. The context is a special config object for the label. + */ + defaultLabelFormatter: function () { + var axis = this.axis, + value = this.value, + categories = axis.categories, + dateTimeLabelFormat = this.dateTimeLabelFormat, + numericSymbols = defaultOptions.lang.numericSymbols, + i = numericSymbols && numericSymbols.length, + multi, + ret, + formatOption = axis.options.labels.format, + + // make sure the same symbol is added for all labels on a linear axis + numericSymbolDetector = axis.isLog ? value : axis.tickInterval; + + if (formatOption) { + ret = format(formatOption, this); + + } else if (categories) { + ret = value; + + } else if (dateTimeLabelFormat) { // datetime axis + ret = dateFormat(dateTimeLabelFormat, value); + + } else if (i && numericSymbolDetector >= 1000) { + // Decide whether we should add a numeric symbol like k (thousands) or M (millions). + // If we are to enable this in tooltip or other places as well, we can move this + // logic to the numberFormatter and enable it by a parameter. + while (i-- && ret === UNDEFINED) { + multi = Math.pow(1000, i + 1); + if (numericSymbolDetector >= multi && numericSymbols[i] !== null) { + ret = numberFormat(value / multi, -1) + numericSymbols[i]; + } + } + } + + if (ret === UNDEFINED) { + if (value >= 1000) { // add thousands separators + ret = numberFormat(value, 0); + + } else { // small numbers + ret = numberFormat(value, -1); + } + } + + return ret; + }, + + /** + * Get the minimum and maximum for the series of each axis + */ + getSeriesExtremes: function () { + var axis = this, + chart = axis.chart; + + axis.hasVisibleSeries = false; + + // reset dataMin and dataMax in case we're redrawing + axis.dataMin = axis.dataMax = null; + + // reset cached stacking extremes + axis.stackExtremes = {}; + + axis.buildStacks(); + + // loop through this axis' series + each(axis.series, function (series) { + + if (series.visible || !chart.options.chart.ignoreHiddenSeries) { + + var seriesOptions = series.options, + xData, + threshold = seriesOptions.threshold, + seriesDataMin, + seriesDataMax; + + axis.hasVisibleSeries = true; + + // Validate threshold in logarithmic axes + if (axis.isLog && threshold <= 0) { + threshold = null; + } + + // Get dataMin and dataMax for X axes + if (axis.isXAxis) { + xData = series.xData; + if (xData.length) { + axis.dataMin = mathMin(pick(axis.dataMin, xData[0]), arrayMin(xData)); + axis.dataMax = mathMax(pick(axis.dataMax, xData[0]), arrayMax(xData)); + } + + // Get dataMin and dataMax for Y axes, as well as handle stacking and processed data + } else { + + // Get this particular series extremes + series.getExtremes(); + seriesDataMax = series.dataMax; + seriesDataMin = series.dataMin; + + // Get the dataMin and dataMax so far. If percentage is used, the min and max are + // always 0 and 100. If seriesDataMin and seriesDataMax is null, then series + // doesn't have active y data, we continue with nulls + if (defined(seriesDataMin) && defined(seriesDataMax)) { + axis.dataMin = mathMin(pick(axis.dataMin, seriesDataMin), seriesDataMin); + axis.dataMax = mathMax(pick(axis.dataMax, seriesDataMax), seriesDataMax); + } + + // Adjust to threshold + if (defined(threshold)) { + if (axis.dataMin >= threshold) { + axis.dataMin = threshold; + axis.ignoreMinPadding = true; + } else if (axis.dataMax < threshold) { + axis.dataMax = threshold; + axis.ignoreMaxPadding = true; + } + } + } + } + }); + }, + + /** + * Translate from axis value to pixel position on the chart, or back + * + */ + translate: function (val, backwards, cvsCoord, old, handleLog, pointPlacement) { + var axis = this, + axisLength = axis.len, + sign = 1, + cvsOffset = 0, + localA = old ? axis.oldTransA : axis.transA, + localMin = old ? axis.oldMin : axis.min, + returnValue, + minPixelPadding = axis.minPixelPadding, + postTranslate = (axis.options.ordinal || (axis.isLog && handleLog)) && axis.lin2val; + + if (!localA) { + localA = axis.transA; + } + + // In vertical axes, the canvas coordinates start from 0 at the top like in + // SVG. + if (cvsCoord) { + sign *= -1; // canvas coordinates inverts the value + cvsOffset = axisLength; + } + + // Handle reversed axis + if (axis.reversed) { + sign *= -1; + cvsOffset -= sign * axisLength; + } + + // From pixels to value + if (backwards) { // reverse translation + + val = val * sign + cvsOffset; + val -= minPixelPadding; + returnValue = val / localA + localMin; // from chart pixel to value + if (postTranslate) { // log and ordinal axes + returnValue = axis.lin2val(returnValue); + } + + // From value to pixels + } else { + if (postTranslate) { // log and ordinal axes + val = axis.val2lin(val); + } + if (pointPlacement === 'between') { + pointPlacement = 0.5; + } + returnValue = sign * (val - localMin) * localA + cvsOffset + (sign * minPixelPadding) + + (isNumber(pointPlacement) ? localA * pointPlacement * axis.pointRange : 0); + } + + return returnValue; + }, + + /** + * Utility method to translate an axis value to pixel position. + * @param {Number} value A value in terms of axis units + * @param {Boolean} paneCoordinates Whether to return the pixel coordinate relative to the chart + * or just the axis/pane itself. + */ + toPixels: function (value, paneCoordinates) { + return this.translate(value, false, !this.horiz, null, true) + (paneCoordinates ? 0 : this.pos); + }, + + /* + * Utility method to translate a pixel position in to an axis value + * @param {Number} pixel The pixel value coordinate + * @param {Boolean} paneCoordiantes Whether the input pixel is relative to the chart or just the + * axis/pane itself. + */ + toValue: function (pixel, paneCoordinates) { + return this.translate(pixel - (paneCoordinates ? 0 : this.pos), true, !this.horiz, null, true); + }, + + /** + * Create the path for a plot line that goes from the given value on + * this axis, across the plot to the opposite side + * @param {Number} value + * @param {Number} lineWidth Used for calculation crisp line + * @param {Number] old Use old coordinates (for resizing and rescaling) + */ + getPlotLinePath: function (value, lineWidth, old, force) { + var axis = this, + chart = axis.chart, + axisLeft = axis.left, + axisTop = axis.top, + x1, + y1, + x2, + y2, + translatedValue = axis.translate(value, null, null, old), + cHeight = (old && chart.oldChartHeight) || chart.chartHeight, + cWidth = (old && chart.oldChartWidth) || chart.chartWidth, + skip, + transB = axis.transB; + + x1 = x2 = mathRound(translatedValue + transB); + y1 = y2 = mathRound(cHeight - translatedValue - transB); + + if (isNaN(translatedValue)) { // no min or max + skip = true; + + } else if (axis.horiz) { + y1 = axisTop; + y2 = cHeight - axis.bottom; + if (x1 < axisLeft || x1 > axisLeft + axis.width) { + skip = true; + } + } else { + x1 = axisLeft; + x2 = cWidth - axis.right; + + if (y1 < axisTop || y1 > axisTop + axis.height) { + skip = true; + } + } + return skip && !force ? + null : + chart.renderer.crispLine([M, x1, y1, L, x2, y2], lineWidth || 0); + }, + + /** + * Create the path for a plot band + */ + getPlotBandPath: function (from, to) { + + var toPath = this.getPlotLinePath(to), + path = this.getPlotLinePath(from); + + if (path && toPath) { + path.push( + toPath[4], + toPath[5], + toPath[1], + toPath[2] + ); + } else { // outside the axis area + path = null; + } + + return path; + }, + + /** + * Set the tick positions of a linear axis to round values like whole tens or every five. + */ + getLinearTickPositions: function (tickInterval, min, max) { + var pos, + lastPos, + roundedMin = correctFloat(mathFloor(min / tickInterval) * tickInterval), + roundedMax = correctFloat(mathCeil(max / tickInterval) * tickInterval), + tickPositions = []; + + // Populate the intermediate values + pos = roundedMin; + while (pos <= roundedMax) { + + // Place the tick on the rounded value + tickPositions.push(pos); + + // Always add the raw tickInterval, not the corrected one. + pos = correctFloat(pos + tickInterval); + + // If the interval is not big enough in the current min - max range to actually increase + // the loop variable, we need to break out to prevent endless loop. Issue #619 + if (pos === lastPos) { + break; + } + + // Record the last value + lastPos = pos; + } + return tickPositions; + }, + + /** + * Set the tick positions of a logarithmic axis + */ + getLogTickPositions: function (interval, min, max, minor) { + var axis = this, + options = axis.options, + axisLength = axis.len, + // Since we use this method for both major and minor ticks, + // use a local variable and return the result + positions = []; + + // Reset + if (!minor) { + axis._minorAutoInterval = null; + } + + // First case: All ticks fall on whole logarithms: 1, 10, 100 etc. + if (interval >= 0.5) { + interval = mathRound(interval); + positions = axis.getLinearTickPositions(interval, min, max); + + // Second case: We need intermediary ticks. For example + // 1, 2, 4, 6, 8, 10, 20, 40 etc. + } else if (interval >= 0.08) { + var roundedMin = mathFloor(min), + intermediate, + i, + j, + len, + pos, + lastPos, + break2; + + if (interval > 0.3) { + intermediate = [1, 2, 4]; + } else if (interval > 0.15) { // 0.2 equals five minor ticks per 1, 10, 100 etc + intermediate = [1, 2, 4, 6, 8]; + } else { // 0.1 equals ten minor ticks per 1, 10, 100 etc + intermediate = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + } + + for (i = roundedMin; i < max + 1 && !break2; i++) { + len = intermediate.length; + for (j = 0; j < len && !break2; j++) { + pos = log2lin(lin2log(i) * intermediate[j]); + + if (pos > min && (!minor || lastPos <= max)) { // #1670 + positions.push(lastPos); + } + + if (lastPos > max) { + break2 = true; + } + lastPos = pos; + } + } + + // Third case: We are so deep in between whole logarithmic values that + // we might as well handle the tick positions like a linear axis. For + // example 1.01, 1.02, 1.03, 1.04. + } else { + var realMin = lin2log(min), + realMax = lin2log(max), + tickIntervalOption = options[minor ? 'minorTickInterval' : 'tickInterval'], + filteredTickIntervalOption = tickIntervalOption === 'auto' ? null : tickIntervalOption, + tickPixelIntervalOption = options.tickPixelInterval / (minor ? 5 : 1), + totalPixelLength = minor ? axisLength / axis.tickPositions.length : axisLength; + + interval = pick( + filteredTickIntervalOption, + axis._minorAutoInterval, + (realMax - realMin) * tickPixelIntervalOption / (totalPixelLength || 1) + ); + + interval = normalizeTickInterval( + interval, + null, + getMagnitude(interval) + ); + + positions = map(axis.getLinearTickPositions( + interval, + realMin, + realMax + ), log2lin); + + if (!minor) { + axis._minorAutoInterval = interval / 5; + } + } + + // Set the axis-level tickInterval variable + if (!minor) { + axis.tickInterval = interval; + } + return positions; + }, + + /** + * Return the minor tick positions. For logarithmic axes, reuse the same logic + * as for major ticks. + */ + getMinorTickPositions: function () { + var axis = this, + options = axis.options, + tickPositions = axis.tickPositions, + minorTickInterval = axis.minorTickInterval, + minorTickPositions = [], + pos, + i, + len; + + if (axis.isLog) { + len = tickPositions.length; + for (i = 1; i < len; i++) { + minorTickPositions = minorTickPositions.concat( + axis.getLogTickPositions(minorTickInterval, tickPositions[i - 1], tickPositions[i], true) + ); + } + } else if (axis.isDatetimeAxis && options.minorTickInterval === 'auto') { // #1314 + minorTickPositions = minorTickPositions.concat( + getTimeTicks( + normalizeTimeTickInterval(minorTickInterval), + axis.min, + axis.max, + options.startOfWeek + ) + ); + if (minorTickPositions[0] < axis.min) { + minorTickPositions.shift(); + } + } else { + for (pos = axis.min + (tickPositions[0] - axis.min) % minorTickInterval; pos <= axis.max; pos += minorTickInterval) { + minorTickPositions.push(pos); + } + } + return minorTickPositions; + }, + + /** + * Adjust the min and max for the minimum range. Keep in mind that the series data is + * not yet processed, so we don't have information on data cropping and grouping, or + * updated axis.pointRange or series.pointRange. The data can't be processed until + * we have finally established min and max. + */ + adjustForMinRange: function () { + var axis = this, + options = axis.options, + min = axis.min, + max = axis.max, + zoomOffset, + spaceAvailable = axis.dataMax - axis.dataMin >= axis.minRange, + closestDataRange, + i, + distance, + xData, + loopLength, + minArgs, + maxArgs; + + // Set the automatic minimum range based on the closest point distance + if (axis.isXAxis && axis.minRange === UNDEFINED && !axis.isLog) { + + if (defined(options.min) || defined(options.max)) { + axis.minRange = null; // don't do this again + + } else { + + // Find the closest distance between raw data points, as opposed to + // closestPointRange that applies to processed points (cropped and grouped) + each(axis.series, function (series) { + xData = series.xData; + loopLength = series.xIncrement ? 1 : xData.length - 1; + for (i = loopLength; i > 0; i--) { + distance = xData[i] - xData[i - 1]; + if (closestDataRange === UNDEFINED || distance < closestDataRange) { + closestDataRange = distance; + } + } + }); + axis.minRange = mathMin(closestDataRange * 5, axis.dataMax - axis.dataMin); + } + } + + // if minRange is exceeded, adjust + if (max - min < axis.minRange) { + var minRange = axis.minRange; + zoomOffset = (minRange - max + min) / 2; + + // if min and max options have been set, don't go beyond it + minArgs = [min - zoomOffset, pick(options.min, min - zoomOffset)]; + if (spaceAvailable) { // if space is available, stay within the data range + minArgs[2] = axis.dataMin; + } + min = arrayMax(minArgs); + + maxArgs = [min + minRange, pick(options.max, min + minRange)]; + if (spaceAvailable) { // if space is availabe, stay within the data range + maxArgs[2] = axis.dataMax; + } + + max = arrayMin(maxArgs); + + // now if the max is adjusted, adjust the min back + if (max - min < minRange) { + minArgs[0] = max - minRange; + minArgs[1] = pick(options.min, max - minRange); + min = arrayMax(minArgs); + } + } + + // Record modified extremes + axis.min = min; + axis.max = max; + }, + + /** + * Update translation information + */ + setAxisTranslation: function (saveOld) { + var axis = this, + range = axis.max - axis.min, + pointRange = 0, + closestPointRange, + minPointOffset = 0, + pointRangePadding = 0, + linkedParent = axis.linkedParent, + ordinalCorrection, + transA = axis.transA; + + // adjust translation for padding + if (axis.isXAxis) { + if (linkedParent) { + minPointOffset = linkedParent.minPointOffset; + pointRangePadding = linkedParent.pointRangePadding; + + } else { + each(axis.series, function (series) { + var seriesPointRange = series.pointRange, + pointPlacement = series.options.pointPlacement, + seriesClosestPointRange = series.closestPointRange; + + if (seriesPointRange > range) { // #1446 + seriesPointRange = 0; + } + pointRange = mathMax(pointRange, seriesPointRange); + + // minPointOffset is the value padding to the left of the axis in order to make + // room for points with a pointRange, typically columns. When the pointPlacement option + // is 'between' or 'on', this padding does not apply. + minPointOffset = mathMax( + minPointOffset, + isString(pointPlacement) ? 0 : seriesPointRange / 2 + ); + + // Determine the total padding needed to the length of the axis to make room for the + // pointRange. If the series' pointPlacement is 'on', no padding is added. + pointRangePadding = mathMax( + pointRangePadding, + pointPlacement === 'on' ? 0 : seriesPointRange + ); + + // Set the closestPointRange + if (!series.noSharedTooltip && defined(seriesClosestPointRange)) { + closestPointRange = defined(closestPointRange) ? + mathMin(closestPointRange, seriesClosestPointRange) : + seriesClosestPointRange; + } + }); + } + + // Record minPointOffset and pointRangePadding + ordinalCorrection = axis.ordinalSlope && closestPointRange ? axis.ordinalSlope / closestPointRange : 1; // #988, #1853 + axis.minPointOffset = minPointOffset = minPointOffset * ordinalCorrection; + axis.pointRangePadding = pointRangePadding = pointRangePadding * ordinalCorrection; + + // pointRange means the width reserved for each point, like in a column chart + axis.pointRange = mathMin(pointRange, range); + + // closestPointRange means the closest distance between points. In columns + // it is mostly equal to pointRange, but in lines pointRange is 0 while closestPointRange + // is some other value + axis.closestPointRange = closestPointRange; + } + + // Secondary values + if (saveOld) { + axis.oldTransA = transA; + } + axis.translationSlope = axis.transA = transA = axis.len / ((range + pointRangePadding) || 1); + axis.transB = axis.horiz ? axis.left : axis.bottom; // translation addend + axis.minPixelPadding = transA * minPointOffset; + }, + + /** + * Set the tick positions to round values and optionally extend the extremes + * to the nearest tick + */ + setTickPositions: function (secondPass) { + var axis = this, + chart = axis.chart, + options = axis.options, + isLog = axis.isLog, + isDatetimeAxis = axis.isDatetimeAxis, + isXAxis = axis.isXAxis, + isLinked = axis.isLinked, + tickPositioner = axis.options.tickPositioner, + maxPadding = options.maxPadding, + minPadding = options.minPadding, + length, + linkedParentExtremes, + tickIntervalOption = options.tickInterval, + minTickIntervalOption = options.minTickInterval, + tickPixelIntervalOption = options.tickPixelInterval, + tickPositions, + keepTwoTicksOnly, + categories = axis.categories; + + // linked axis gets the extremes from the parent axis + if (isLinked) { + axis.linkedParent = chart[isXAxis ? 'xAxis' : 'yAxis'][options.linkedTo]; + linkedParentExtremes = axis.linkedParent.getExtremes(); + axis.min = pick(linkedParentExtremes.min, linkedParentExtremes.dataMin); + axis.max = pick(linkedParentExtremes.max, linkedParentExtremes.dataMax); + if (options.type !== axis.linkedParent.options.type) { + error(11, 1); // Can't link axes of different type + } + } else { // initial min and max from the extreme data values + axis.min = pick(axis.userMin, options.min, axis.dataMin); + axis.max = pick(axis.userMax, options.max, axis.dataMax); + } + + if (isLog) { + if (!secondPass && mathMin(axis.min, pick(axis.dataMin, axis.min)) <= 0) { // #978 + error(10, 1); // Can't plot negative values on log axis + } + axis.min = correctFloat(log2lin(axis.min)); // correctFloat cures #934 + axis.max = correctFloat(log2lin(axis.max)); + } + + // handle zoomed range + if (axis.range) { + axis.userMin = axis.min = mathMax(axis.min, axis.max - axis.range); // #618 + axis.userMax = axis.max; + if (secondPass) { + axis.range = null; // don't use it when running setExtremes + } + } + + // Hook for adjusting this.min and this.max. Used by bubble series. + if (axis.beforePadding) { + axis.beforePadding(); + } + + // adjust min and max for the minimum range + axis.adjustForMinRange(); + + // Pad the values to get clear of the chart's edges. To avoid tickInterval taking the padding + // into account, we do this after computing tick interval (#1337). + if (!categories && !axis.usePercentage && !isLinked && defined(axis.min) && defined(axis.max)) { + length = axis.max - axis.min; + if (length) { + if (!defined(options.min) && !defined(axis.userMin) && minPadding && (axis.dataMin < 0 || !axis.ignoreMinPadding)) { + axis.min -= length * minPadding; + } + if (!defined(options.max) && !defined(axis.userMax) && maxPadding && (axis.dataMax > 0 || !axis.ignoreMaxPadding)) { + axis.max += length * maxPadding; + } + } + } + + // get tickInterval + if (axis.min === axis.max || axis.min === undefined || axis.max === undefined) { + axis.tickInterval = 1; + } else if (isLinked && !tickIntervalOption && + tickPixelIntervalOption === axis.linkedParent.options.tickPixelInterval) { + axis.tickInterval = axis.linkedParent.tickInterval; + } else { + axis.tickInterval = pick( + tickIntervalOption, + categories ? // for categoried axis, 1 is default, for linear axis use tickPix + 1 : + // don't let it be more than the data range + (axis.max - axis.min) * tickPixelIntervalOption / mathMax(axis.len, tickPixelIntervalOption) + ); + // For squished axes, set only two ticks + if (!defined(tickIntervalOption) && axis.len < tickPixelIntervalOption && !this.isRadial) { + keepTwoTicksOnly = true; + axis.tickInterval /= 4; // tick extremes closer to the real values + } + } + + // Now we're finished detecting min and max, crop and group series data. This + // is in turn needed in order to find tick positions in ordinal axes. + if (isXAxis && !secondPass) { + each(axis.series, function (series) { + series.processData(axis.min !== axis.oldMin || axis.max !== axis.oldMax); + }); + } + + // set the translation factor used in translate function + axis.setAxisTranslation(true); + + // hook for ordinal axes and radial axes + if (axis.beforeSetTickPositions) { + axis.beforeSetTickPositions(); + } + + // hook for extensions, used in Highstock ordinal axes + if (axis.postProcessTickInterval) { + axis.tickInterval = axis.postProcessTickInterval(axis.tickInterval); + } + + // In column-like charts, don't cramp in more ticks than there are points (#1943) + if (axis.pointRange) { + axis.tickInterval = mathMax(axis.pointRange, axis.tickInterval); + } + + // Before normalizing the tick interval, handle minimum tick interval. This applies only if tickInterval is not defined. + if (!tickIntervalOption && axis.tickInterval < minTickIntervalOption) { + axis.tickInterval = minTickIntervalOption; + } + + // for linear axes, get magnitude and normalize the interval + if (!isDatetimeAxis && !isLog) { // linear + if (!tickIntervalOption) { + axis.tickInterval = normalizeTickInterval(axis.tickInterval, null, getMagnitude(axis.tickInterval), options); + } + } + + // get minorTickInterval + axis.minorTickInterval = options.minorTickInterval === 'auto' && axis.tickInterval ? + axis.tickInterval / 5 : options.minorTickInterval; + + // find the tick positions + axis.tickPositions = tickPositions = options.tickPositions ? + [].concat(options.tickPositions) : // Work on a copy (#1565) + (tickPositioner && tickPositioner.apply(axis, [axis.min, axis.max])); + if (!tickPositions) { + + // Too many ticks + if (!axis.ordinalPositions && (axis.max - axis.min) / axis.tickInterval > mathMax(2 * axis.len, 200)) { + error(19, true); + } + + if (isDatetimeAxis) { + tickPositions = (axis.getNonLinearTimeTicks || getTimeTicks)( + normalizeTimeTickInterval(axis.tickInterval, options.units), + axis.min, + axis.max, + options.startOfWeek, + axis.ordinalPositions, + axis.closestPointRange, + true + ); + } else if (isLog) { + tickPositions = axis.getLogTickPositions(axis.tickInterval, axis.min, axis.max); + } else { + tickPositions = axis.getLinearTickPositions(axis.tickInterval, axis.min, axis.max); + } + if (keepTwoTicksOnly) { + tickPositions.splice(1, tickPositions.length - 2); + } + + axis.tickPositions = tickPositions; + } + + if (!isLinked) { + + // reset min/max or remove extremes based on start/end on tick + var roundedMin = tickPositions[0], + roundedMax = tickPositions[tickPositions.length - 1], + minPointOffset = axis.minPointOffset || 0, + singlePad; + + if (options.startOnTick) { + axis.min = roundedMin; + } else if (axis.min - minPointOffset > roundedMin) { + tickPositions.shift(); + } + + if (options.endOnTick) { + axis.max = roundedMax; + } else if (axis.max + minPointOffset < roundedMax) { + tickPositions.pop(); + } + + // When there is only one point, or all points have the same value on this axis, then min + // and max are equal and tickPositions.length is 1. In this case, add some padding + // in order to center the point, but leave it with one tick. #1337. + if (tickPositions.length === 1) { + singlePad = 0.001; // The lowest possible number to avoid extra padding on columns + axis.min -= singlePad; + axis.max += singlePad; + } + } + }, + + /** + * Set the max ticks of either the x and y axis collection + */ + setMaxTicks: function () { + + var chart = this.chart, + maxTicks = chart.maxTicks || {}, + tickPositions = this.tickPositions, + key = this._maxTicksKey = [this.xOrY, this.pos, this.len].join('-'); + + if (!this.isLinked && !this.isDatetimeAxis && tickPositions && tickPositions.length > (maxTicks[key] || 0) && this.options.alignTicks !== false) { + maxTicks[key] = tickPositions.length; + } + chart.maxTicks = maxTicks; + }, + + /** + * When using multiple axes, adjust the number of ticks to match the highest + * number of ticks in that group + */ + adjustTickAmount: function () { + var axis = this, + chart = axis.chart, + key = axis._maxTicksKey, + tickPositions = axis.tickPositions, + maxTicks = chart.maxTicks; + + if (maxTicks && maxTicks[key] && !axis.isDatetimeAxis && !axis.categories && !axis.isLinked && axis.options.alignTicks !== false) { // only apply to linear scale + var oldTickAmount = axis.tickAmount, + calculatedTickAmount = tickPositions.length, + tickAmount; + + // set the axis-level tickAmount to use below + axis.tickAmount = tickAmount = maxTicks[key]; + + if (calculatedTickAmount < tickAmount) { + while (tickPositions.length < tickAmount) { + tickPositions.push(correctFloat( + tickPositions[tickPositions.length - 1] + axis.tickInterval + )); + } + axis.transA *= (calculatedTickAmount - 1) / (tickAmount - 1); + axis.max = tickPositions[tickPositions.length - 1]; + + } + if (defined(oldTickAmount) && tickAmount !== oldTickAmount) { + axis.isDirty = true; + } + } + }, + + /** + * Set the scale based on data min and max, user set min and max or options + * + */ + setScale: function () { + var axis = this, + stacks = axis.stacks, + type, + i, + isDirtyData, + isDirtyAxisLength; + + axis.oldMin = axis.min; + axis.oldMax = axis.max; + axis.oldAxisLength = axis.len; + + // set the new axisLength + axis.setAxisSize(); + //axisLength = horiz ? axisWidth : axisHeight; + isDirtyAxisLength = axis.len !== axis.oldAxisLength; + + // is there new data? + each(axis.series, function (series) { + if (series.isDirtyData || series.isDirty || + series.xAxis.isDirty) { // when x axis is dirty, we need new data extremes for y as well + isDirtyData = true; + } + }); + + // do we really need to go through all this? + if (isDirtyAxisLength || isDirtyData || axis.isLinked || axis.forceRedraw || + axis.userMin !== axis.oldUserMin || axis.userMax !== axis.oldUserMax) { + + // reset stacks + if (!axis.isXAxis) { + for (type in stacks) { + delete stacks[type]; + } + } + + axis.forceRedraw = false; + + // get data extremes if needed + axis.getSeriesExtremes(); + + // get fixed positions based on tickInterval + axis.setTickPositions(); + + // record old values to decide whether a rescale is necessary later on (#540) + axis.oldUserMin = axis.userMin; + axis.oldUserMax = axis.userMax; + + // Mark as dirty if it is not already set to dirty and extremes have changed. #595. + if (!axis.isDirty) { + axis.isDirty = isDirtyAxisLength || axis.min !== axis.oldMin || axis.max !== axis.oldMax; + } + } else if (!axis.isXAxis) { + if (axis.oldStacks) { + stacks = axis.stacks = axis.oldStacks; + } + + // reset stacks + for (type in stacks) { + for (i in stacks[type]) { + stacks[type][i].cum = stacks[type][i].total; + } + } + } + + // Set the maximum tick amount + axis.setMaxTicks(); + }, + + /** + * Set the extremes and optionally redraw + * @param {Number} newMin + * @param {Number} newMax + * @param {Boolean} redraw + * @param {Boolean|Object} animation Whether to apply animation, and optionally animation + * configuration + * @param {Object} eventArguments + * + */ + setExtremes: function (newMin, newMax, redraw, animation, eventArguments) { + var axis = this, + chart = axis.chart; + + redraw = pick(redraw, true); // defaults to true + + // Extend the arguments with min and max + eventArguments = extend(eventArguments, { + min: newMin, + max: newMax + }); + + // Fire the event + fireEvent(axis, 'setExtremes', eventArguments, function () { // the default event handler + + axis.userMin = newMin; + axis.userMax = newMax; + axis.eventArgs = eventArguments; + + // Mark for running afterSetExtremes + axis.isDirtyExtremes = true; + + // redraw + if (redraw) { + chart.redraw(animation); + } + }); + }, + + /** + * Overridable method for zooming chart. Pulled out in a separate method to allow overriding + * in stock charts. + */ + zoom: function (newMin, newMax) { + + // Prevent pinch zooming out of range. Check for defined is for #1946. + if (!this.allowZoomOutside) { + if (defined(this.dataMin) && newMin <= this.dataMin) { + newMin = UNDEFINED; + } + if (defined(this.dataMax) && newMax >= this.dataMax) { + newMax = UNDEFINED; + } + } + + // In full view, displaying the reset zoom button is not required + this.displayBtn = newMin !== UNDEFINED || newMax !== UNDEFINED; + + // Do it + this.setExtremes( + newMin, + newMax, + false, + UNDEFINED, + { trigger: 'zoom' } + ); + return true; + }, + + /** + * Update the axis metrics + */ + setAxisSize: function () { + var chart = this.chart, + options = this.options, + offsetLeft = options.offsetLeft || 0, + offsetRight = options.offsetRight || 0, + horiz = this.horiz, + width, + height, + top, + left; + + // Expose basic values to use in Series object and navigator + this.left = left = pick(options.left, chart.plotLeft + offsetLeft); + this.top = top = pick(options.top, chart.plotTop); + this.width = width = pick(options.width, chart.plotWidth - offsetLeft + offsetRight); + this.height = height = pick(options.height, chart.plotHeight); + this.bottom = chart.chartHeight - height - top; + this.right = chart.chartWidth - width - left; + + // Direction agnostic properties + this.len = mathMax(horiz ? width : height, 0); // mathMax fixes #905 + this.pos = horiz ? left : top; // distance from SVG origin + }, + + /** + * Get the actual axis extremes + */ + getExtremes: function () { + var axis = this, + isLog = axis.isLog; + + return { + min: isLog ? correctFloat(lin2log(axis.min)) : axis.min, + max: isLog ? correctFloat(lin2log(axis.max)) : axis.max, + dataMin: axis.dataMin, + dataMax: axis.dataMax, + userMin: axis.userMin, + userMax: axis.userMax + }; + }, + + /** + * Get the zero plane either based on zero or on the min or max value. + * Used in bar and area plots + */ + getThreshold: function (threshold) { + var axis = this, + isLog = axis.isLog; + + var realMin = isLog ? lin2log(axis.min) : axis.min, + realMax = isLog ? lin2log(axis.max) : axis.max; + + if (realMin > threshold || threshold === null) { + threshold = realMin; + } else if (realMax < threshold) { + threshold = realMax; + } + + return axis.translate(threshold, 0, 1, 0, 1); + }, + + addPlotBand: function (options) { + this.addPlotBandOrLine(options, 'plotBands'); + }, + + addPlotLine: function (options) { + this.addPlotBandOrLine(options, 'plotLines'); + }, + + /** + * Add a plot band or plot line after render time + * + * @param options {Object} The plotBand or plotLine configuration object + */ + addPlotBandOrLine: function (options, coll) { + var obj = new PlotLineOrBand(this, options).render(), + userOptions = this.userOptions; + + if (obj) { // #2189 + // Add it to the user options for exporting and Axis.update + if (coll) { + userOptions[coll] = userOptions[coll] || []; + userOptions[coll].push(options); + } + this.plotLinesAndBands.push(obj); + } + + return obj; + }, + + /** + * Compute auto alignment for the axis label based on which side the axis is on + * and the given rotation for the label + */ + autoLabelAlign: function (rotation) { + var ret, + angle = (pick(rotation, 0) - (this.side * 90) + 720) % 360; + + if (angle > 15 && angle < 165) { + ret = 'right'; + } else if (angle > 195 && angle < 345) { + ret = 'left'; + } else { + ret = 'center'; + } + return ret; + }, + + /** + * Render the tick labels to a preliminary position to get their sizes + */ + getOffset: function () { + var axis = this, + chart = axis.chart, + renderer = chart.renderer, + options = axis.options, + tickPositions = axis.tickPositions, + ticks = axis.ticks, + horiz = axis.horiz, + side = axis.side, + invertedSide = chart.inverted ? [1, 0, 3, 2][side] : side, + hasData, + showAxis, + titleOffset = 0, + titleOffsetOption, + titleMargin = 0, + axisTitleOptions = options.title, + labelOptions = options.labels, + labelOffset = 0, // reset + axisOffset = chart.axisOffset, + clipOffset = chart.clipOffset, + directionFactor = [-1, 1, 1, -1][side], + n, + i, + autoStaggerLines = 1, + maxStaggerLines = pick(labelOptions.maxStaggerLines, 5), + sortedPositions, + lastRight, + overlap, + pos, + bBox, + x, + w, + lineNo; + + // For reuse in Axis.render + axis.hasData = hasData = (axis.hasVisibleSeries || (defined(axis.min) && defined(axis.max) && !!tickPositions)); + axis.showAxis = showAxis = hasData || pick(options.showEmpty, true); + + // Set/reset staggerLines + axis.staggerLines = axis.horiz && labelOptions.staggerLines; + + // Create the axisGroup and gridGroup elements on first iteration + if (!axis.axisGroup) { + axis.gridGroup = renderer.g('grid') + .attr({ zIndex: options.gridZIndex || 1 }) + .add(); + axis.axisGroup = renderer.g('axis') + .attr({ zIndex: options.zIndex || 2 }) + .add(); + axis.labelGroup = renderer.g('axis-labels') + .attr({ zIndex: labelOptions.zIndex || 7 }) + .add(); + } + + if (hasData || axis.isLinked) { + + // Set the explicit or automatic label alignment + axis.labelAlign = pick(labelOptions.align || axis.autoLabelAlign(labelOptions.rotation)); + + each(tickPositions, function (pos) { + if (!ticks[pos]) { + ticks[pos] = new Tick(axis, pos); + } else { + ticks[pos].addLabel(); // update labels depending on tick interval + } + }); + + // Handle automatic stagger lines + if (axis.horiz && !axis.staggerLines && maxStaggerLines && !labelOptions.rotation) { + sortedPositions = axis.reversed ? [].concat(tickPositions).reverse() : tickPositions; + while (autoStaggerLines < maxStaggerLines) { + lastRight = []; + overlap = false; + + for (i = 0; i < sortedPositions.length; i++) { + pos = sortedPositions[i]; + bBox = ticks[pos].label && ticks[pos].label.getBBox(); + w = bBox ? bBox.width : 0; + lineNo = i % autoStaggerLines; + + if (w) { + x = axis.translate(pos); // don't handle log + if (lastRight[lineNo] !== UNDEFINED && x < lastRight[lineNo]) { + overlap = true; + } + lastRight[lineNo] = x + w; + } + } + if (overlap) { + autoStaggerLines++; + } else { + break; + } + } + + if (autoStaggerLines > 1) { + axis.staggerLines = autoStaggerLines; + } + } + + + each(tickPositions, function (pos) { + // left side must be align: right and right side must have align: left for labels + if (side === 0 || side === 2 || { 1: 'left', 3: 'right' }[side] === axis.labelAlign) { + + // get the highest offset + labelOffset = mathMax( + ticks[pos].getLabelSize(), + labelOffset + ); + } + + }); + if (axis.staggerLines) { + labelOffset *= axis.staggerLines; + axis.labelOffset = labelOffset; + } + + + } else { // doesn't have data + for (n in ticks) { + ticks[n].destroy(); + delete ticks[n]; + } + } + + if (axisTitleOptions && axisTitleOptions.text && axisTitleOptions.enabled !== false) { + if (!axis.axisTitle) { + axis.axisTitle = renderer.text( + axisTitleOptions.text, + 0, + 0, + axisTitleOptions.useHTML + ) + .attr({ + zIndex: 7, + rotation: axisTitleOptions.rotation || 0, + align: + axisTitleOptions.textAlign || + { low: 'left', middle: 'center', high: 'right' }[axisTitleOptions.align] + }) + .css(axisTitleOptions.style) + .add(axis.axisGroup); + axis.axisTitle.isNew = true; + } + + if (showAxis) { + titleOffset = axis.axisTitle.getBBox()[horiz ? 'height' : 'width']; + titleMargin = pick(axisTitleOptions.margin, horiz ? 5 : 10); + titleOffsetOption = axisTitleOptions.offset; + } + + // hide or show the title depending on whether showEmpty is set + axis.axisTitle[showAxis ? 'show' : 'hide'](); + } + + // handle automatic or user set offset + axis.offset = directionFactor * pick(options.offset, axisOffset[side]); + + axis.axisTitleMargin = + pick(titleOffsetOption, + labelOffset + titleMargin + + (side !== 2 && labelOffset && directionFactor * options.labels[horiz ? 'y' : 'x']) + ); + + axisOffset[side] = mathMax( + axisOffset[side], + axis.axisTitleMargin + titleOffset + directionFactor * axis.offset + ); + clipOffset[invertedSide] = mathMax(clipOffset[invertedSide], mathFloor(options.lineWidth / 2) * 2); + }, + + /** + * Get the path for the axis line + */ + getLinePath: function (lineWidth) { + var chart = this.chart, + opposite = this.opposite, + offset = this.offset, + horiz = this.horiz, + lineLeft = this.left + (opposite ? this.width : 0) + offset, + lineTop = chart.chartHeight - this.bottom - (opposite ? this.height : 0) + offset; + + if (opposite) { + lineWidth *= -1; // crispify the other way - #1480, #1687 + } + + return chart.renderer.crispLine([ + M, + horiz ? + this.left : + lineLeft, + horiz ? + lineTop : + this.top, + L, + horiz ? + chart.chartWidth - this.right : + lineLeft, + horiz ? + lineTop : + chart.chartHeight - this.bottom + ], lineWidth); + }, + + /** + * Position the title + */ + getTitlePosition: function () { + // compute anchor points for each of the title align options + var horiz = this.horiz, + axisLeft = this.left, + axisTop = this.top, + axisLength = this.len, + axisTitleOptions = this.options.title, + margin = horiz ? axisLeft : axisTop, + opposite = this.opposite, + offset = this.offset, + fontSize = pInt(axisTitleOptions.style.fontSize || 12), + + // the position in the length direction of the axis + alongAxis = { + low: margin + (horiz ? 0 : axisLength), + middle: margin + axisLength / 2, + high: margin + (horiz ? axisLength : 0) + }[axisTitleOptions.align], + + // the position in the perpendicular direction of the axis + offAxis = (horiz ? axisTop + this.height : axisLeft) + + (horiz ? 1 : -1) * // horizontal axis reverses the margin + (opposite ? -1 : 1) * // so does opposite axes + this.axisTitleMargin + + (this.side === 2 ? fontSize : 0); + + return { + x: horiz ? + alongAxis : + offAxis + (opposite ? this.width : 0) + offset + + (axisTitleOptions.x || 0), // x + y: horiz ? + offAxis - (opposite ? this.height : 0) + offset : + alongAxis + (axisTitleOptions.y || 0) // y + }; + }, + + /** + * Render the axis + */ + render: function () { + var axis = this, + chart = axis.chart, + renderer = chart.renderer, + options = axis.options, + isLog = axis.isLog, + isLinked = axis.isLinked, + tickPositions = axis.tickPositions, + axisTitle = axis.axisTitle, + stacks = axis.stacks, + ticks = axis.ticks, + minorTicks = axis.minorTicks, + alternateBands = axis.alternateBands, + stackLabelOptions = options.stackLabels, + alternateGridColor = options.alternateGridColor, + tickmarkOffset = axis.tickmarkOffset, + lineWidth = options.lineWidth, + linePath, + hasRendered = chart.hasRendered, + slideInTicks = hasRendered && defined(axis.oldMin) && !isNaN(axis.oldMin), + hasData = axis.hasData, + showAxis = axis.showAxis, + from, + to; + + // Mark all elements inActive before we go over and mark the active ones + each([ticks, minorTicks, alternateBands], function (coll) { + var pos; + for (pos in coll) { + coll[pos].isActive = false; + } + }); + + // If the series has data draw the ticks. Else only the line and title + if (hasData || isLinked) { + + // minor ticks + if (axis.minorTickInterval && !axis.categories) { + each(axis.getMinorTickPositions(), function (pos) { + if (!minorTicks[pos]) { + minorTicks[pos] = new Tick(axis, pos, 'minor'); + } + + // render new ticks in old position + if (slideInTicks && minorTicks[pos].isNew) { + minorTicks[pos].render(null, true); + } + + minorTicks[pos].render(null, false, 1); + }); + } + + // Major ticks. Pull out the first item and render it last so that + // we can get the position of the neighbour label. #808. + if (tickPositions.length) { // #1300 + each(tickPositions.slice(1).concat([tickPositions[0]]), function (pos, i) { + + // Reorganize the indices + i = (i === tickPositions.length - 1) ? 0 : i + 1; + + // linked axes need an extra check to find out if + if (!isLinked || (pos >= axis.min && pos <= axis.max)) { + + if (!ticks[pos]) { + ticks[pos] = new Tick(axis, pos); + } + + // render new ticks in old position + if (slideInTicks && ticks[pos].isNew) { + ticks[pos].render(i, true); + } + + ticks[pos].render(i, false, 1); + } + + }); + // In a categorized axis, the tick marks are displayed between labels. So + // we need to add a tick mark and grid line at the left edge of the X axis. + if (tickmarkOffset && axis.min === 0) { + if (!ticks[-1]) { + ticks[-1] = new Tick(axis, -1, null, true); + } + ticks[-1].render(-1); + } + + } + + // alternate grid color + if (alternateGridColor) { + each(tickPositions, function (pos, i) { + if (i % 2 === 0 && pos < axis.max) { + if (!alternateBands[pos]) { + alternateBands[pos] = new PlotLineOrBand(axis); + } + from = pos + tickmarkOffset; // #949 + to = tickPositions[i + 1] !== UNDEFINED ? tickPositions[i + 1] + tickmarkOffset : axis.max; + alternateBands[pos].options = { + from: isLog ? lin2log(from) : from, + to: isLog ? lin2log(to) : to, + color: alternateGridColor + }; + alternateBands[pos].render(); + alternateBands[pos].isActive = true; + } + }); + } + + // custom plot lines and bands + if (!axis._addedPlotLB) { // only first time + each((options.plotLines || []).concat(options.plotBands || []), function (plotLineOptions) { + axis.addPlotBandOrLine(plotLineOptions); + }); + axis._addedPlotLB = true; + } + + } // end if hasData + + // Remove inactive ticks + each([ticks, minorTicks, alternateBands], function (coll) { + var pos, + i, + forDestruction = [], + delay = globalAnimation ? globalAnimation.duration || 500 : 0, + destroyInactiveItems = function () { + i = forDestruction.length; + while (i--) { + // When resizing rapidly, the same items may be destroyed in different timeouts, + // or the may be reactivated + if (coll[forDestruction[i]] && !coll[forDestruction[i]].isActive) { + coll[forDestruction[i]].destroy(); + delete coll[forDestruction[i]]; + } + } + + }; + + for (pos in coll) { + + if (!coll[pos].isActive) { + // Render to zero opacity + coll[pos].render(pos, false, 0); + coll[pos].isActive = false; + forDestruction.push(pos); + } + } + + // When the objects are finished fading out, destroy them + if (coll === alternateBands || !chart.hasRendered || !delay) { + destroyInactiveItems(); + } else if (delay) { + setTimeout(destroyInactiveItems, delay); + } + }); + + // Static items. As the axis group is cleared on subsequent calls + // to render, these items are added outside the group. + // axis line + if (lineWidth) { + linePath = axis.getLinePath(lineWidth); + if (!axis.axisLine) { + axis.axisLine = renderer.path(linePath) + .attr({ + stroke: options.lineColor, + 'stroke-width': lineWidth, + zIndex: 7 + }) + .add(axis.axisGroup); + } else { + axis.axisLine.animate({ d: linePath }); + } + + // show or hide the line depending on options.showEmpty + axis.axisLine[showAxis ? 'show' : 'hide'](); + } + + if (axisTitle && showAxis) { + + axisTitle[axisTitle.isNew ? 'attr' : 'animate']( + axis.getTitlePosition() + ); + axisTitle.isNew = false; + } + + // Stacked totals: + if (stackLabelOptions && stackLabelOptions.enabled) { + var stackKey, oneStack, stackCategory, + stackTotalGroup = axis.stackTotalGroup; + + // Create a separate group for the stack total labels + if (!stackTotalGroup) { + axis.stackTotalGroup = stackTotalGroup = + renderer.g('stack-labels') + .attr({ + visibility: VISIBLE, + zIndex: 6 + }) + .add(); + } + + // plotLeft/Top will change when y axis gets wider so we need to translate the + // stackTotalGroup at every render call. See bug #506 and #516 + stackTotalGroup.translate(chart.plotLeft, chart.plotTop); + + // Render each stack total + for (stackKey in stacks) { + oneStack = stacks[stackKey]; + for (stackCategory in oneStack) { + oneStack[stackCategory].render(stackTotalGroup); + } + } + } + // End stacked totals + + axis.isDirty = false; + }, + + /** + * Remove a plot band or plot line from the chart by id + * @param {Object} id + */ + removePlotBandOrLine: function (id) { + var plotLinesAndBands = this.plotLinesAndBands, + options = this.options, + userOptions = this.userOptions, + i = plotLinesAndBands.length; + while (i--) { + if (plotLinesAndBands[i].id === id) { + plotLinesAndBands[i].destroy(); + } + } + each([options.plotLines || [], userOptions.plotLines || [], options.plotBands || [], userOptions.plotBands || []], function (arr) { + i = arr.length; + while (i--) { + if (arr[i].id === id) { + erase(arr, arr[i]); + } + } + }); + + }, + + /** + * Update the axis title by options + */ + setTitle: function (newTitleOptions, redraw) { + this.update({ title: newTitleOptions }, redraw); + }, + + /** + * Redraw the axis to reflect changes in the data or axis extremes + */ + redraw: function () { + var axis = this, + chart = axis.chart, + pointer = chart.pointer; + + // hide tooltip and hover states + if (pointer.reset) { + pointer.reset(true); + } + + // render the axis + axis.render(); + + // move plot lines and bands + each(axis.plotLinesAndBands, function (plotLine) { + plotLine.render(); + }); + + // mark associated series as dirty and ready for redraw + each(axis.series, function (series) { + series.isDirty = true; + }); + + }, + + /** + * Build the stacks from top down + */ + buildStacks: function () { + var series = this.series, + i = series.length; + if (!this.isXAxis) { + while (i--) { + series[i].setStackedPoints(); + } + // Loop up again to compute percent stack + if (this.usePercentage) { + for (i = 0; i < series.length; i++) { + series[i].setPercentStacks(); + } + } + } + }, + + /** + * Set new axis categories and optionally redraw + * @param {Array} categories + * @param {Boolean} redraw + */ + setCategories: function (categories, redraw) { + this.update({ categories: categories }, redraw); + }, + + /** + * Destroys an Axis instance. + */ + destroy: function (keepEvents) { + var axis = this, + stacks = axis.stacks, + stackKey, + plotLinesAndBands = axis.plotLinesAndBands, + i; + + // Remove the events + if (!keepEvents) { + removeEvent(axis); + } + + // Destroy each stack total + for (stackKey in stacks) { + destroyObjectProperties(stacks[stackKey]); + + stacks[stackKey] = null; + } + + // Destroy collections + each([axis.ticks, axis.minorTicks, axis.alternateBands], function (coll) { + destroyObjectProperties(coll); + }); + i = plotLinesAndBands.length; + while (i--) { // #1975 + plotLinesAndBands[i].destroy(); + } + + // Destroy local variables + each(['stackTotalGroup', 'axisLine', 'axisGroup', 'gridGroup', 'labelGroup', 'axisTitle'], function (prop) { + if (axis[prop]) { + axis[prop] = axis[prop].destroy(); + } + }); + } + + +}; // end Axis + +/** + * The tooltip object + * @param {Object} chart The chart instance + * @param {Object} options Tooltip options + */ +function Tooltip() { + this.init.apply(this, arguments); +} + +Tooltip.prototype = { + + init: function (chart, options) { + + var borderWidth = options.borderWidth, + style = options.style, + padding = pInt(style.padding); + + // Save the chart and options + this.chart = chart; + this.options = options; + + // Keep track of the current series + //this.currentSeries = UNDEFINED; + + // List of crosshairs + this.crosshairs = []; + + // Current values of x and y when animating + this.now = { x: 0, y: 0 }; + + // The tooltip is initially hidden + this.isHidden = true; + + + // create the label + this.label = chart.renderer.label('', 0, 0, options.shape, null, null, options.useHTML, null, 'tooltip') + .attr({ + padding: padding, + fill: options.backgroundColor, + 'stroke-width': borderWidth, + r: options.borderRadius, + zIndex: 8 + }) + .css(style) + .css({ padding: 0 }) // Remove it from VML, the padding is applied as an attribute instead (#1117) + .add() + .attr({ y: -999 }); // #2301 + + // When using canVG the shadow shows up as a gray circle + // even if the tooltip is hidden. + if (!useCanVG) { + this.label.shadow(options.shadow); + } + + // Public property for getting the shared state. + this.shared = options.shared; + }, + + /** + * Destroy the tooltip and its elements. + */ + destroy: function () { + each(this.crosshairs, function (crosshair) { + if (crosshair) { + crosshair.destroy(); + } + }); + + // Destroy and clear local variables + if (this.label) { + this.label = this.label.destroy(); + } + clearTimeout(this.hideTimer); + clearTimeout(this.tooltipTimeout); + }, + + /** + * Provide a soft movement for the tooltip + * + * @param {Number} x + * @param {Number} y + * @private + */ + move: function (x, y, anchorX, anchorY) { + var tooltip = this, + now = tooltip.now, + animate = tooltip.options.animation !== false && !tooltip.isHidden; + + // get intermediate values for animation + extend(now, { + x: animate ? (2 * now.x + x) / 3 : x, + y: animate ? (now.y + y) / 2 : y, + anchorX: animate ? (2 * now.anchorX + anchorX) / 3 : anchorX, + anchorY: animate ? (now.anchorY + anchorY) / 2 : anchorY + }); + + // move to the intermediate value + tooltip.label.attr(now); + + + // run on next tick of the mouse tracker + if (animate && (mathAbs(x - now.x) > 1 || mathAbs(y - now.y) > 1)) { + + // never allow two timeouts + clearTimeout(this.tooltipTimeout); + + // set the fixed interval ticking for the smooth tooltip + this.tooltipTimeout = setTimeout(function () { + // The interval function may still be running during destroy, so check that the chart is really there before calling. + if (tooltip) { + tooltip.move(x, y, anchorX, anchorY); + } + }, 32); + + } + }, + + /** + * Hide the tooltip + */ + hide: function () { + var tooltip = this, + hoverPoints; + + clearTimeout(this.hideTimer); // disallow duplicate timers (#1728, #1766) + if (!this.isHidden) { + hoverPoints = this.chart.hoverPoints; + + this.hideTimer = setTimeout(function () { + tooltip.label.fadeOut(); + tooltip.isHidden = true; + }, pick(this.options.hideDelay, 500)); + + // hide previous hoverPoints and set new + if (hoverPoints) { + each(hoverPoints, function (point) { + point.setState(); + }); + } + + this.chart.hoverPoints = null; + } + }, + + /** + * Hide the crosshairs + */ + hideCrosshairs: function () { + each(this.crosshairs, function (crosshair) { + if (crosshair) { + crosshair.hide(); + } + }); + }, + + /** + * Extendable method to get the anchor position of the tooltip + * from a point or set of points + */ + getAnchor: function (points, mouseEvent) { + var ret, + chart = this.chart, + inverted = chart.inverted, + plotTop = chart.plotTop, + plotX = 0, + plotY = 0, + yAxis; + + points = splat(points); + + // Pie uses a special tooltipPos + ret = points[0].tooltipPos; + + // When tooltip follows mouse, relate the position to the mouse + if (this.followPointer && mouseEvent) { + if (mouseEvent.chartX === UNDEFINED) { + mouseEvent = chart.pointer.normalize(mouseEvent); + } + ret = [ + mouseEvent.chartX - chart.plotLeft, + mouseEvent.chartY - plotTop + ]; + } + // When shared, use the average position + if (!ret) { + each(points, function (point) { + yAxis = point.series.yAxis; + plotX += point.plotX; + plotY += (point.plotLow ? (point.plotLow + point.plotHigh) / 2 : point.plotY) + + (!inverted && yAxis ? yAxis.top - plotTop : 0); // #1151 + }); + + plotX /= points.length; + plotY /= points.length; + + ret = [ + inverted ? chart.plotWidth - plotY : plotX, + this.shared && !inverted && points.length > 1 && mouseEvent ? + mouseEvent.chartY - plotTop : // place shared tooltip next to the mouse (#424) + inverted ? chart.plotHeight - plotX : plotY + ]; + } + + return map(ret, mathRound); + }, + + /** + * Place the tooltip in a chart without spilling over + * and not covering the point it self. + */ + getPosition: function (boxWidth, boxHeight, point) { + + // Set up the variables + var chart = this.chart, + plotLeft = chart.plotLeft, + plotTop = chart.plotTop, + plotWidth = chart.plotWidth, + plotHeight = chart.plotHeight, + distance = pick(this.options.distance, 12), + pointX = point.plotX, + pointY = point.plotY, + x = pointX + plotLeft + (chart.inverted ? distance : -boxWidth - distance), + y = pointY - boxHeight + plotTop + 15, // 15 means the point is 15 pixels up from the bottom of the tooltip + alignedRight; + + // It is too far to the left, adjust it + if (x < 7) { + x = plotLeft + mathMax(pointX, 0) + distance; + } + + // Test to see if the tooltip is too far to the right, + // if it is, move it back to be inside and then up to not cover the point. + if ((x + boxWidth) > (plotLeft + plotWidth)) { + x -= (x + boxWidth) - (plotLeft + plotWidth); + y = pointY - boxHeight + plotTop - distance; + alignedRight = true; + } + + // If it is now above the plot area, align it to the top of the plot area + if (y < plotTop + 5) { + y = plotTop + 5; + + // If the tooltip is still covering the point, move it below instead + if (alignedRight && pointY >= y && pointY <= (y + boxHeight)) { + y = pointY + plotTop + distance; // below + } + } + + // Now if the tooltip is below the chart, move it up. It's better to cover the + // point than to disappear outside the chart. #834. + if (y + boxHeight > plotTop + plotHeight) { + y = mathMax(plotTop, plotTop + plotHeight - boxHeight - distance); // below + } + + return {x: x, y: y}; + }, + + /** + * In case no user defined formatter is given, this will be used. Note that the context + * here is an object holding point, series, x, y etc. + */ + defaultFormatter: function (tooltip) { + var items = this.points || splat(this), + series = items[0].series, + s; + + // build the header + s = [series.tooltipHeaderFormatter(items[0])]; + + // build the values + each(items, function (item) { + series = item.series; + s.push((series.tooltipFormatter && series.tooltipFormatter(item)) || + item.point.tooltipFormatter(series.tooltipOptions.pointFormat)); + }); + + // footer + s.push(tooltip.options.footerFormat || ''); + + return s.join(''); + }, + + /** + * Refresh the tooltip's text and position. + * @param {Object} point + */ + refresh: function (point, mouseEvent) { + var tooltip = this, + chart = tooltip.chart, + label = tooltip.label, + options = tooltip.options, + x, + y, + anchor, + textConfig = {}, + text, + pointConfig = [], + formatter = options.formatter || tooltip.defaultFormatter, + hoverPoints = chart.hoverPoints, + borderColor, + crosshairsOptions = options.crosshairs, + shared = tooltip.shared, + currentSeries; + + clearTimeout(this.hideTimer); + + // get the reference point coordinates (pie charts use tooltipPos) + tooltip.followPointer = splat(point)[0].series.tooltipOptions.followPointer; + anchor = tooltip.getAnchor(point, mouseEvent); + x = anchor[0]; + y = anchor[1]; + + // shared tooltip, array is sent over + if (shared && !(point.series && point.series.noSharedTooltip)) { + + // hide previous hoverPoints and set new + + chart.hoverPoints = point; + if (hoverPoints) { + each(hoverPoints, function (point) { + point.setState(); + }); + } + + each(point, function (item) { + item.setState(HOVER_STATE); + + pointConfig.push(item.getLabelConfig()); + }); + + textConfig = { + x: point[0].category, + y: point[0].y + }; + textConfig.points = pointConfig; + point = point[0]; + + // single point tooltip + } else { + textConfig = point.getLabelConfig(); + } + text = formatter.call(textConfig, tooltip); + + // register the current series + currentSeries = point.series; + + // update the inner HTML + if (text === false) { + this.hide(); + } else { + + // show it + if (tooltip.isHidden) { + stop(label); + label.attr('opacity', 1).show(); + } + + // update text + label.attr({ + text: text + }); + + // set the stroke color of the box + borderColor = options.borderColor || point.color || currentSeries.color || '#606060'; + label.attr({ + stroke: borderColor + }); + + tooltip.updatePosition({ plotX: x, plotY: y }); + + this.isHidden = false; + } + + // crosshairs + if (crosshairsOptions) { + crosshairsOptions = splat(crosshairsOptions); // [x, y] + + var path, + i = crosshairsOptions.length, + attribs, + axis, + val, + series; + + while (i--) { + series = point.series; + axis = series[i ? 'yAxis' : 'xAxis']; + if (crosshairsOptions[i] && axis) { + val = i ? pick(point.stackY, point.y) : point.x; // #814 + if (axis.isLog) { // #1671 + val = log2lin(val); + } + if (i === 1 && series.modifyValue) { // #1205, #2316 + val = series.modifyValue(val); + } + + path = axis.getPlotLinePath( + val, + 1 + ); + + if (tooltip.crosshairs[i]) { + tooltip.crosshairs[i].attr({ d: path, visibility: VISIBLE }); + } else { + attribs = { + 'stroke-width': crosshairsOptions[i].width || 1, + stroke: crosshairsOptions[i].color || '#C0C0C0', + zIndex: crosshairsOptions[i].zIndex || 2 + }; + if (crosshairsOptions[i].dashStyle) { + attribs.dashstyle = crosshairsOptions[i].dashStyle; + } + tooltip.crosshairs[i] = chart.renderer.path(path) + .attr(attribs) + .add(); + } + } + } + } + fireEvent(chart, 'tooltipRefresh', { + text: text, + x: x + chart.plotLeft, + y: y + chart.plotTop, + borderColor: borderColor + }); + }, + + /** + * Find the new position and perform the move + */ + updatePosition: function (point) { + var chart = this.chart, + label = this.label, + pos = (this.options.positioner || this.getPosition).call( + this, + label.width, + label.height, + point + ); + + // do the move + this.move( + mathRound(pos.x), + mathRound(pos.y), + point.plotX + chart.plotLeft, + point.plotY + chart.plotTop + ); + } +}; +/** + * The mouse tracker object. All methods starting with "on" are primary DOM event handlers. + * Subsequent methods should be named differently from what they are doing. + * @param {Object} chart The Chart instance + * @param {Object} options The root options object + */ +function Pointer(chart, options) { + this.init(chart, options); +} + +Pointer.prototype = { + /** + * Initialize Pointer + */ + init: function (chart, options) { + + var chartOptions = options.chart, + chartEvents = chartOptions.events, + zoomType = useCanVG ? '' : chartOptions.zoomType, + inverted = chart.inverted, + zoomX, + zoomY; + + // Store references + this.options = options; + this.chart = chart; + + // Zoom status + this.zoomX = zoomX = /x/.test(zoomType); + this.zoomY = zoomY = /y/.test(zoomType); + this.zoomHor = (zoomX && !inverted) || (zoomY && inverted); + this.zoomVert = (zoomY && !inverted) || (zoomX && inverted); + + // Do we need to handle click on a touch device? + this.runChartClick = chartEvents && !!chartEvents.click; + + this.pinchDown = []; + this.lastValidTouch = {}; + + if (options.tooltip.enabled) { + chart.tooltip = new Tooltip(chart, options.tooltip); + } + + this.setDOMEvents(); + }, + + /** + * Add crossbrowser support for chartX and chartY + * @param {Object} e The event object in standard browsers + */ + normalize: function (e, chartPosition) { + var chartX, + chartY, + ePos; + + // common IE normalizing + e = e || win.event; + if (!e.target) { + e.target = e.srcElement; + } + + // Framework specific normalizing (#1165) + e = washMouseEvent(e); + + // iOS + ePos = e.touches ? e.touches.item(0) : e; + + // Get mouse position + if (!chartPosition) { + this.chartPosition = chartPosition = offset(this.chart.container); + } + + // chartX and chartY + if (ePos.pageX === UNDEFINED) { // IE < 9. #886. + chartX = mathMax(e.x, e.clientX - chartPosition.left); // #2005, #2129: the second case is + // for IE10 quirks mode within framesets + chartY = e.y; + } else { + chartX = ePos.pageX - chartPosition.left; + chartY = ePos.pageY - chartPosition.top; + } + + return extend(e, { + chartX: mathRound(chartX), + chartY: mathRound(chartY) + }); + }, + + /** + * Get the click position in terms of axis values. + * + * @param {Object} e A pointer event + */ + getCoordinates: function (e) { + var coordinates = { + xAxis: [], + yAxis: [] + }; + + each(this.chart.axes, function (axis) { + coordinates[axis.isXAxis ? 'xAxis' : 'yAxis'].push({ + axis: axis, + value: axis.toValue(e[axis.horiz ? 'chartX' : 'chartY']) + }); + }); + return coordinates; + }, + + /** + * Return the index in the tooltipPoints array, corresponding to pixel position in + * the plot area. + */ + getIndex: function (e) { + var chart = this.chart; + return chart.inverted ? + chart.plotHeight + chart.plotTop - e.chartY : + e.chartX - chart.plotLeft; + }, + + /** + * With line type charts with a single tracker, get the point closest to the mouse. + * Run Point.onMouseOver and display tooltip for the point or points. + */ + runPointActions: function (e) { + var pointer = this, + chart = pointer.chart, + series = chart.series, + tooltip = chart.tooltip, + point, + points, + hoverPoint = chart.hoverPoint, + hoverSeries = chart.hoverSeries, + i, + j, + distance = chart.chartWidth, + index = pointer.getIndex(e), + anchor; + + // shared tooltip + if (tooltip && pointer.options.tooltip.shared && !(hoverSeries && hoverSeries.noSharedTooltip)) { + points = []; + + // loop over all series and find the ones with points closest to the mouse + i = series.length; + for (j = 0; j < i; j++) { + if (series[j].visible && + series[j].options.enableMouseTracking !== false && + !series[j].noSharedTooltip && series[j].tooltipPoints.length) { + point = series[j].tooltipPoints[index]; + if (point && point.series) { // not a dummy point, #1544 + point._dist = mathAbs(index - point.clientX); + distance = mathMin(distance, point._dist); + points.push(point); + } + } + } + // remove furthest points + i = points.length; + while (i--) { + if (points[i]._dist > distance) { + points.splice(i, 1); + } + } + // refresh the tooltip if necessary + if (points.length && (points[0].clientX !== pointer.hoverX)) { + tooltip.refresh(points, e); + pointer.hoverX = points[0].clientX; + } + } + + // separate tooltip and general mouse events + if (hoverSeries && hoverSeries.tracker) { // only use for line-type series with common tracker + + // get the point + point = hoverSeries.tooltipPoints[index]; + + // a new point is hovered, refresh the tooltip + if (point && point !== hoverPoint) { + + // trigger the events + point.onMouseOver(e); + + } + + } else if (tooltip && tooltip.followPointer && !tooltip.isHidden) { + anchor = tooltip.getAnchor([{}], e); + tooltip.updatePosition({ plotX: anchor[0], plotY: anchor[1] }); + } + }, + + + + /** + * Reset the tracking by hiding the tooltip, the hover series state and the hover point + * + * @param allowMove {Boolean} Instead of destroying the tooltip altogether, allow moving it if possible + */ + reset: function (allowMove) { + var pointer = this, + chart = pointer.chart, + hoverSeries = chart.hoverSeries, + hoverPoint = chart.hoverPoint, + tooltip = chart.tooltip, + tooltipPoints = tooltip && tooltip.shared ? chart.hoverPoints : hoverPoint; + + // Narrow in allowMove + allowMove = allowMove && tooltip && tooltipPoints; + + // Check if the points have moved outside the plot area, #1003 + if (allowMove && splat(tooltipPoints)[0].plotX === UNDEFINED) { + allowMove = false; + } + + // Just move the tooltip, #349 + if (allowMove) { + tooltip.refresh(tooltipPoints); + + // Full reset + } else { + + if (hoverPoint) { + hoverPoint.onMouseOut(); + } + + if (hoverSeries) { + hoverSeries.onMouseOut(); + } + + if (tooltip) { + tooltip.hide(); + tooltip.hideCrosshairs(); + } + + pointer.hoverX = null; + + } + }, + + /** + * Scale series groups to a certain scale and translation + */ + scaleGroups: function (attribs, clip) { + + var chart = this.chart, + seriesAttribs; + + // Scale each series + each(chart.series, function (series) { + seriesAttribs = attribs || series.getPlotBox(); // #1701 + if (series.xAxis && series.xAxis.zoomEnabled) { + series.group.attr(seriesAttribs); + if (series.markerGroup) { + series.markerGroup.attr(seriesAttribs); + series.markerGroup.clip(clip ? chart.clipRect : null); + } + if (series.dataLabelsGroup) { + series.dataLabelsGroup.attr(seriesAttribs); + } + } + }); + + // Clip + chart.clipRect.attr(clip || chart.clipBox); + }, + + /** + * Run translation operations for each direction (horizontal and vertical) independently + */ + pinchTranslateDirection: function (horiz, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch) { + var chart = this.chart, + xy = horiz ? 'x' : 'y', + XY = horiz ? 'X' : 'Y', + sChartXY = 'chart' + XY, + wh = horiz ? 'width' : 'height', + plotLeftTop = chart['plot' + (horiz ? 'Left' : 'Top')], + selectionWH, + selectionXY, + clipXY, + scale = 1, + inverted = chart.inverted, + bounds = chart.bounds[horiz ? 'h' : 'v'], + singleTouch = pinchDown.length === 1, + touch0Start = pinchDown[0][sChartXY], + touch0Now = touches[0][sChartXY], + touch1Start = !singleTouch && pinchDown[1][sChartXY], + touch1Now = !singleTouch && touches[1][sChartXY], + outOfBounds, + transformScale, + scaleKey, + setScale = function () { + if (!singleTouch && mathAbs(touch0Start - touch1Start) > 20) { // Don't zoom if fingers are too close on this axis + scale = mathAbs(touch0Now - touch1Now) / mathAbs(touch0Start - touch1Start); + } + + clipXY = ((plotLeftTop - touch0Now) / scale) + touch0Start; + selectionWH = chart['plot' + (horiz ? 'Width' : 'Height')] / scale; + }; + + // Set the scale, first pass + setScale(); + + selectionXY = clipXY; // the clip position (x or y) is altered if out of bounds, the selection position is not + + // Out of bounds + if (selectionXY < bounds.min) { + selectionXY = bounds.min; + outOfBounds = true; + } else if (selectionXY + selectionWH > bounds.max) { + selectionXY = bounds.max - selectionWH; + outOfBounds = true; + } + + // Is the chart dragged off its bounds, determined by dataMin and dataMax? + if (outOfBounds) { + + // Modify the touchNow position in order to create an elastic drag movement. This indicates + // to the user that the chart is responsive but can't be dragged further. + touch0Now -= 0.8 * (touch0Now - lastValidTouch[xy][0]); + if (!singleTouch) { + touch1Now -= 0.8 * (touch1Now - lastValidTouch[xy][1]); + } + + // Set the scale, second pass to adapt to the modified touchNow positions + setScale(); + + } else { + lastValidTouch[xy] = [touch0Now, touch1Now]; + } + + + // Set geometry for clipping, selection and transformation + if (!inverted) { // TODO: implement clipping for inverted charts + clip[xy] = clipXY - plotLeftTop; + clip[wh] = selectionWH; + } + scaleKey = inverted ? (horiz ? 'scaleY' : 'scaleX') : 'scale' + XY; + transformScale = inverted ? 1 / scale : scale; + + selectionMarker[wh] = selectionWH; + selectionMarker[xy] = selectionXY; + transform[scaleKey] = scale; + transform['translate' + XY] = (transformScale * plotLeftTop) + (touch0Now - (transformScale * touch0Start)); + }, + + /** + * Handle touch events with two touches + */ + pinch: function (e) { + + var self = this, + chart = self.chart, + pinchDown = self.pinchDown, + followTouchMove = chart.tooltip && chart.tooltip.options.followTouchMove, + touches = e.touches, + touchesLength = touches.length, + lastValidTouch = self.lastValidTouch, + zoomHor = self.zoomHor || self.pinchHor, + zoomVert = self.zoomVert || self.pinchVert, + hasZoom = zoomHor || zoomVert, + selectionMarker = self.selectionMarker, + transform = {}, + fireClickEvent = touchesLength === 1 && ((self.inClass(e.target, PREFIX + 'tracker') && + chart.runTrackerClick) || chart.runChartClick), + clip = {}; + + // On touch devices, only proceed to trigger click if a handler is defined + if ((hasZoom || followTouchMove) && !fireClickEvent) { + e.preventDefault(); + } + + // Normalize each touch + map(touches, function (e) { + return self.normalize(e); + }); + + // Register the touch start position + if (e.type === 'touchstart') { + each(touches, function (e, i) { + pinchDown[i] = { chartX: e.chartX, chartY: e.chartY }; + }); + lastValidTouch.x = [pinchDown[0].chartX, pinchDown[1] && pinchDown[1].chartX]; + lastValidTouch.y = [pinchDown[0].chartY, pinchDown[1] && pinchDown[1].chartY]; + + // Identify the data bounds in pixels + each(chart.axes, function (axis) { + if (axis.zoomEnabled) { + var bounds = chart.bounds[axis.horiz ? 'h' : 'v'], + minPixelPadding = axis.minPixelPadding, + min = axis.toPixels(axis.dataMin), + max = axis.toPixels(axis.dataMax), + absMin = mathMin(min, max), + absMax = mathMax(min, max); + + // Store the bounds for use in the touchmove handler + bounds.min = mathMin(axis.pos, absMin - minPixelPadding); + bounds.max = mathMax(axis.pos + axis.len, absMax + minPixelPadding); + } + }); + + // Event type is touchmove, handle panning and pinching + } else if (pinchDown.length) { // can be 0 when releasing, if touchend fires first + + + // Set the marker + if (!selectionMarker) { + self.selectionMarker = selectionMarker = extend({ + destroy: noop + }, chart.plotBox); + } + + + + if (zoomHor) { + self.pinchTranslateDirection(true, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch); + } + if (zoomVert) { + self.pinchTranslateDirection(false, pinchDown, touches, transform, selectionMarker, clip, lastValidTouch); + } + + self.hasPinched = hasZoom; + + // Scale and translate the groups to provide visual feedback during pinching + self.scaleGroups(transform, clip); + + // Optionally move the tooltip on touchmove + if (!hasZoom && followTouchMove && touchesLength === 1) { + this.runPointActions(self.normalize(e)); + } + } + }, + + /** + * Start a drag operation + */ + dragStart: function (e) { + var chart = this.chart; + + // Record the start position + chart.mouseIsDown = e.type; + chart.cancelClick = false; + chart.mouseDownX = this.mouseDownX = e.chartX; + chart.mouseDownY = this.mouseDownY = e.chartY; + }, + + /** + * Perform a drag operation in response to a mousemove event while the mouse is down + */ + drag: function (e) { + + var chart = this.chart, + chartOptions = chart.options.chart, + chartX = e.chartX, + chartY = e.chartY, + zoomHor = this.zoomHor, + zoomVert = this.zoomVert, + plotLeft = chart.plotLeft, + plotTop = chart.plotTop, + plotWidth = chart.plotWidth, + plotHeight = chart.plotHeight, + clickedInside, + size, + mouseDownX = this.mouseDownX, + mouseDownY = this.mouseDownY; + + // If the mouse is outside the plot area, adjust to cooordinates + // inside to prevent the selection marker from going outside + if (chartX < plotLeft) { + chartX = plotLeft; + } else if (chartX > plotLeft + plotWidth) { + chartX = plotLeft + plotWidth; + } + + if (chartY < plotTop) { + chartY = plotTop; + } else if (chartY > plotTop + plotHeight) { + chartY = plotTop + plotHeight; + } + + // determine if the mouse has moved more than 10px + this.hasDragged = Math.sqrt( + Math.pow(mouseDownX - chartX, 2) + + Math.pow(mouseDownY - chartY, 2) + ); + if (this.hasDragged > 10) { + clickedInside = chart.isInsidePlot(mouseDownX - plotLeft, mouseDownY - plotTop); + + // make a selection + if (chart.hasCartesianSeries && (this.zoomX || this.zoomY) && clickedInside) { + if (!this.selectionMarker) { + this.selectionMarker = chart.renderer.rect( + plotLeft, + plotTop, + zoomHor ? 1 : plotWidth, + zoomVert ? 1 : plotHeight, + 0 + ) + .attr({ + fill: chartOptions.selectionMarkerFill || 'rgba(69,114,167,0.25)', + zIndex: 7 + }) + .add(); + } + } + + // adjust the width of the selection marker + if (this.selectionMarker && zoomHor) { + size = chartX - mouseDownX; + this.selectionMarker.attr({ + width: mathAbs(size), + x: (size > 0 ? 0 : size) + mouseDownX + }); + } + // adjust the height of the selection marker + if (this.selectionMarker && zoomVert) { + size = chartY - mouseDownY; + this.selectionMarker.attr({ + height: mathAbs(size), + y: (size > 0 ? 0 : size) + mouseDownY + }); + } + + // panning + if (clickedInside && !this.selectionMarker && chartOptions.panning) { + chart.pan(e, chartOptions.panning); + } + } + }, + + /** + * On mouse up or touch end across the entire document, drop the selection. + */ + drop: function (e) { + var chart = this.chart, + hasPinched = this.hasPinched; + + if (this.selectionMarker) { + var selectionData = { + xAxis: [], + yAxis: [], + originalEvent: e.originalEvent || e + }, + selectionBox = this.selectionMarker, + selectionLeft = selectionBox.x, + selectionTop = selectionBox.y, + runZoom; + // a selection has been made + if (this.hasDragged || hasPinched) { + + // record each axis' min and max + each(chart.axes, function (axis) { + if (axis.zoomEnabled) { + var horiz = axis.horiz, + selectionMin = axis.toValue((horiz ? selectionLeft : selectionTop)), + selectionMax = axis.toValue((horiz ? selectionLeft + selectionBox.width : selectionTop + selectionBox.height)); + + if (!isNaN(selectionMin) && !isNaN(selectionMax)) { // #859 + selectionData[axis.xOrY + 'Axis'].push({ + axis: axis, + min: mathMin(selectionMin, selectionMax), // for reversed axes, + max: mathMax(selectionMin, selectionMax) + }); + runZoom = true; + } + } + }); + if (runZoom) { + fireEvent(chart, 'selection', selectionData, function (args) { + chart.zoom(extend(args, hasPinched ? { animation: false } : null)); + }); + } + + } + this.selectionMarker = this.selectionMarker.destroy(); + + // Reset scaling preview + if (hasPinched) { + this.scaleGroups(); + } + } + + // Reset all + if (chart) { // it may be destroyed on mouse up - #877 + css(chart.container, { cursor: chart._cursor }); + chart.cancelClick = this.hasDragged > 10; // #370 + chart.mouseIsDown = this.hasDragged = this.hasPinched = false; + this.pinchDown = []; + } + }, + + onContainerMouseDown: function (e) { + + e = this.normalize(e); + + // issue #295, dragging not always working in Firefox + if (e.preventDefault) { + e.preventDefault(); + } + + this.dragStart(e); + }, + + + + onDocumentMouseUp: function (e) { + this.drop(e); + }, + + /** + * Special handler for mouse move that will hide the tooltip when the mouse leaves the plotarea. + * Issue #149 workaround. The mouseleave event does not always fire. + */ + onDocumentMouseMove: function (e) { + var chart = this.chart, + chartPosition = this.chartPosition, + hoverSeries = chart.hoverSeries; + + e = this.normalize(e, chartPosition); + + // If we're outside, hide the tooltip + if (chartPosition && hoverSeries && !this.inClass(e.target, 'highcharts-tracker') && + !chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) { + this.reset(); + } + }, + + /** + * When mouse leaves the container, hide the tooltip. + */ + onContainerMouseLeave: function () { + this.reset(); + this.chartPosition = null; // also reset the chart position, used in #149 fix + }, + + // The mousemove, touchmove and touchstart event handler + onContainerMouseMove: function (e) { + + var chart = this.chart; + + // normalize + e = this.normalize(e); + + // #295 + e.returnValue = false; + + + if (chart.mouseIsDown === 'mousedown') { + this.drag(e); + } + + // Show the tooltip and run mouse over events (#977) + if ((this.inClass(e.target, 'highcharts-tracker') || + chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) && !chart.openMenu) { + this.runPointActions(e); + } + }, + + /** + * Utility to detect whether an element has, or has a parent with, a specific + * class name. Used on detection of tracker objects and on deciding whether + * hovering the tooltip should cause the active series to mouse out. + */ + inClass: function (element, className) { + var elemClassName; + while (element) { + elemClassName = attr(element, 'class'); + if (elemClassName) { + if (elemClassName.indexOf(className) !== -1) { + return true; + } else if (elemClassName.indexOf(PREFIX + 'container') !== -1) { + return false; + } + } + element = element.parentNode; + } + }, + + onTrackerMouseOut: function (e) { + var series = this.chart.hoverSeries; + if (series && !series.options.stickyTracking && !this.inClass(e.toElement || e.relatedTarget, PREFIX + 'tooltip')) { + series.onMouseOut(); + } + }, + + onContainerClick: function (e) { + var chart = this.chart, + hoverPoint = chart.hoverPoint, + plotLeft = chart.plotLeft, + plotTop = chart.plotTop, + inverted = chart.inverted, + chartPosition, + plotX, + plotY; + + e = this.normalize(e); + e.cancelBubble = true; // IE specific + + if (!chart.cancelClick) { + + // On tracker click, fire the series and point events. #783, #1583 + if (hoverPoint && this.inClass(e.target, PREFIX + 'tracker')) { + chartPosition = this.chartPosition; + plotX = hoverPoint.plotX; + plotY = hoverPoint.plotY; + + // add page position info + extend(hoverPoint, { + pageX: chartPosition.left + plotLeft + + (inverted ? chart.plotWidth - plotY : plotX), + pageY: chartPosition.top + plotTop + + (inverted ? chart.plotHeight - plotX : plotY) + }); + + // the series click event + fireEvent(hoverPoint.series, 'click', extend(e, { + point: hoverPoint + })); + + // the point click event + if (chart.hoverPoint) { // it may be destroyed (#1844) + hoverPoint.firePointEvent('click', e); + } + + // When clicking outside a tracker, fire a chart event + } else { + extend(e, this.getCoordinates(e)); + + // fire a click event in the chart + if (chart.isInsidePlot(e.chartX - plotLeft, e.chartY - plotTop)) { + fireEvent(chart, 'click', e); + } + } + + + } + }, + + onContainerTouchStart: function (e) { + var chart = this.chart; + + if (e.touches.length === 1) { + + e = this.normalize(e); + + if (chart.isInsidePlot(e.chartX - chart.plotLeft, e.chartY - chart.plotTop)) { + + // Prevent the click pseudo event from firing unless it is set in the options + /*if (!chart.runChartClick) { + e.preventDefault(); + }*/ + + // Run mouse events and display tooltip etc + this.runPointActions(e); + + this.pinch(e); + + } else { + // Hide the tooltip on touching outside the plot area (#1203) + this.reset(); + } + + } else if (e.touches.length === 2) { + this.pinch(e); + } + }, + + onContainerTouchMove: function (e) { + if (e.touches.length === 1 || e.touches.length === 2) { + this.pinch(e); + } + }, + + onDocumentTouchEnd: function (e) { + this.drop(e); + }, + + /** + * Set the JS DOM events on the container and document. This method should contain + * a one-to-one assignment between methods and their handlers. Any advanced logic should + * be moved to the handler reflecting the event's name. + */ + setDOMEvents: function () { + + var pointer = this, + container = pointer.chart.container, + events; + + this._events = events = [ + [container, 'onmousedown', 'onContainerMouseDown'], + [container, 'onmousemove', 'onContainerMouseMove'], + [container, 'onclick', 'onContainerClick'], + [container, 'mouseleave', 'onContainerMouseLeave'], + [doc, 'mousemove', 'onDocumentMouseMove'], + [doc, 'mouseup', 'onDocumentMouseUp'] + ]; + + if (hasTouch) { + events.push( + [container, 'ontouchstart', 'onContainerTouchStart'], + [container, 'ontouchmove', 'onContainerTouchMove'], + [doc, 'touchend', 'onDocumentTouchEnd'] + ); + } + + each(events, function (eventConfig) { + + // First, create the callback function that in turn calls the method on Pointer + pointer['_' + eventConfig[2]] = function (e) { + pointer[eventConfig[2]](e); + }; + + // Now attach the function, either as a direct property or through addEvent + if (eventConfig[1].indexOf('on') === 0) { + eventConfig[0][eventConfig[1]] = pointer['_' + eventConfig[2]]; + } else { + addEvent(eventConfig[0], eventConfig[1], pointer['_' + eventConfig[2]]); + } + }); + + + }, + + /** + * Destroys the Pointer object and disconnects DOM events. + */ + destroy: function () { + var pointer = this; + + // Release all DOM events + each(pointer._events, function (eventConfig) { + if (eventConfig[1].indexOf('on') === 0) { + eventConfig[0][eventConfig[1]] = null; // delete breaks oldIE + } else { + removeEvent(eventConfig[0], eventConfig[1], pointer['_' + eventConfig[2]]); + } + }); + delete pointer._events; + + // memory and CPU leak + clearInterval(pointer.tooltipTimeout); + } +}; +/** + * The overview of the chart's series + */ +function Legend(chart, options) { + this.init(chart, options); +} + +Legend.prototype = { + + /** + * Initialize the legend + */ + init: function (chart, options) { + + var legend = this, + itemStyle = options.itemStyle, + padding = pick(options.padding, 8), + itemMarginTop = options.itemMarginTop || 0; + + this.options = options; + + if (!options.enabled) { + return; + } + + legend.baseline = pInt(itemStyle.fontSize) + 3 + itemMarginTop; // used in Series prototype + legend.itemStyle = itemStyle; + legend.itemHiddenStyle = merge(itemStyle, options.itemHiddenStyle); + legend.itemMarginTop = itemMarginTop; + legend.padding = padding; + legend.initialItemX = padding; + legend.initialItemY = padding - 5; // 5 is the number of pixels above the text + legend.maxItemWidth = 0; + legend.chart = chart; + legend.itemHeight = 0; + legend.lastLineHeight = 0; + + // Render it + legend.render(); + + // move checkboxes + addEvent(legend.chart, 'endResize', function () { + legend.positionCheckboxes(); + }); + + }, + + /** + * Set the colors for the legend item + * @param {Object} item A Series or Point instance + * @param {Object} visible Dimmed or colored + */ + colorizeItem: function (item, visible) { + var legend = this, + options = legend.options, + legendItem = item.legendItem, + legendLine = item.legendLine, + legendSymbol = item.legendSymbol, + hiddenColor = legend.itemHiddenStyle.color, + textColor = visible ? options.itemStyle.color : hiddenColor, + symbolColor = visible ? item.color : hiddenColor, + markerOptions = item.options && item.options.marker, + symbolAttr = { + stroke: symbolColor, + fill: symbolColor + }, + key, + val; + + if (legendItem) { + legendItem.css({ fill: textColor, color: textColor }); // color for #1553, oldIE + } + if (legendLine) { + legendLine.attr({ stroke: symbolColor }); + } + + if (legendSymbol) { + + // Apply marker options + if (markerOptions && legendSymbol.isMarker) { // #585 + markerOptions = item.convertAttribs(markerOptions); + for (key in markerOptions) { + val = markerOptions[key]; + if (val !== UNDEFINED) { + symbolAttr[key] = val; + } + } + } + + legendSymbol.attr(symbolAttr); + } + }, + + /** + * Position the legend item + * @param {Object} item A Series or Point instance + */ + positionItem: function (item) { + var legend = this, + options = legend.options, + symbolPadding = options.symbolPadding, + ltr = !options.rtl, + legendItemPos = item._legendItemPos, + itemX = legendItemPos[0], + itemY = legendItemPos[1], + checkbox = item.checkbox; + + if (item.legendGroup) { + item.legendGroup.translate( + ltr ? itemX : legend.legendWidth - itemX - 2 * symbolPadding - 4, + itemY + ); + } + + if (checkbox) { + checkbox.x = itemX; + checkbox.y = itemY; + } + }, + + /** + * Destroy a single legend item + * @param {Object} item The series or point + */ + destroyItem: function (item) { + var checkbox = item.checkbox; + + // destroy SVG elements + each(['legendItem', 'legendLine', 'legendSymbol', 'legendGroup'], function (key) { + if (item[key]) { + item[key] = item[key].destroy(); + } + }); + + if (checkbox) { + discardElement(item.checkbox); + } + }, + + /** + * Destroys the legend. + */ + destroy: function () { + var legend = this, + legendGroup = legend.group, + box = legend.box; + + if (box) { + legend.box = box.destroy(); + } + + if (legendGroup) { + legend.group = legendGroup.destroy(); + } + }, + + /** + * Position the checkboxes after the width is determined + */ + positionCheckboxes: function (scrollOffset) { + var alignAttr = this.group.alignAttr, + translateY, + clipHeight = this.clipHeight || this.legendHeight; + + if (alignAttr) { + translateY = alignAttr.translateY; + each(this.allItems, function (item) { + var checkbox = item.checkbox, + top; + + if (checkbox) { + top = (translateY + checkbox.y + (scrollOffset || 0) + 3); + css(checkbox, { + left: (alignAttr.translateX + item.legendItemWidth + checkbox.x - 20) + PX, + top: top + PX, + display: top > translateY - 6 && top < translateY + clipHeight - 6 ? '' : NONE + }); + } + }); + } + }, + + /** + * Render the legend title on top of the legend + */ + renderTitle: function () { + var options = this.options, + padding = this.padding, + titleOptions = options.title, + titleHeight = 0, + bBox; + + if (titleOptions.text) { + if (!this.title) { + this.title = this.chart.renderer.label(titleOptions.text, padding - 3, padding - 4, null, null, null, null, null, 'legend-title') + .attr({ zIndex: 1 }) + .css(titleOptions.style) + .add(this.group); + } + bBox = this.title.getBBox(); + titleHeight = bBox.height; + this.offsetWidth = bBox.width; // #1717 + this.contentGroup.attr({ translateY: titleHeight }); + } + this.titleHeight = titleHeight; + }, + + /** + * Render a single specific legend item + * @param {Object} item A series or point + */ + renderItem: function (item) { + var legend = this, + chart = legend.chart, + renderer = chart.renderer, + options = legend.options, + horizontal = options.layout === 'horizontal', + symbolWidth = options.symbolWidth, + symbolPadding = options.symbolPadding, + itemStyle = legend.itemStyle, + itemHiddenStyle = legend.itemHiddenStyle, + padding = legend.padding, + itemDistance = horizontal ? pick(options.itemDistance, 8) : 0, + ltr = !options.rtl, + itemHeight, + widthOption = options.width, + itemMarginBottom = options.itemMarginBottom || 0, + itemMarginTop = legend.itemMarginTop, + initialItemX = legend.initialItemX, + bBox, + itemWidth, + li = item.legendItem, + series = item.series || item, + itemOptions = series.options, + showCheckbox = itemOptions.showCheckbox, + useHTML = options.useHTML; + + if (!li) { // generate it once, later move it + + // Generate the group box + // A group to hold the symbol and text. Text is to be appended in Legend class. + item.legendGroup = renderer.g('legend-item') + .attr({ zIndex: 1 }) + .add(legend.scrollGroup); + + // Draw the legend symbol inside the group box + series.drawLegendSymbol(legend, item); + + // Generate the list item text and add it to the group + item.legendItem = li = renderer.text( + options.labelFormat ? format(options.labelFormat, item) : options.labelFormatter.call(item), + ltr ? symbolWidth + symbolPadding : -symbolPadding, + legend.baseline, + useHTML + ) + .css(merge(item.visible ? itemStyle : itemHiddenStyle)) // merge to prevent modifying original (#1021) + .attr({ + align: ltr ? 'left' : 'right', + zIndex: 2 + }) + .add(item.legendGroup); + + // Set the events on the item group, or in case of useHTML, the item itself (#1249) + (useHTML ? li : item.legendGroup).on('mouseover', function () { + item.setState(HOVER_STATE); + li.css(legend.options.itemHoverStyle); + }) + .on('mouseout', function () { + li.css(item.visible ? itemStyle : itemHiddenStyle); + item.setState(); + }) + .on('click', function (event) { + var strLegendItemClick = 'legendItemClick', + fnLegendItemClick = function () { + item.setVisible(); + }; + + // Pass over the click/touch event. #4. + event = { + browserEvent: event + }; + + // click the name or symbol + if (item.firePointEvent) { // point + item.firePointEvent(strLegendItemClick, event, fnLegendItemClick); + } else { + fireEvent(item, strLegendItemClick, event, fnLegendItemClick); + } + }); + + // Colorize the items + legend.colorizeItem(item, item.visible); + + // add the HTML checkbox on top + if (itemOptions && showCheckbox) { + item.checkbox = createElement('input', { + type: 'checkbox', + checked: item.selected, + defaultChecked: item.selected // required by IE7 + }, options.itemCheckboxStyle, chart.container); + + addEvent(item.checkbox, 'click', function (event) { + var target = event.target; + fireEvent(item, 'checkboxClick', { + checked: target.checked + }, + function () { + item.select(); + } + ); + }); + } + } + + // calculate the positions for the next line + bBox = li.getBBox(); + + itemWidth = item.legendItemWidth = + options.itemWidth || symbolWidth + symbolPadding + bBox.width + itemDistance + + (showCheckbox ? 20 : 0); + legend.itemHeight = itemHeight = bBox.height; + + // if the item exceeds the width, start a new line + if (horizontal && legend.itemX - initialItemX + itemWidth > + (widthOption || (chart.chartWidth - 2 * padding - initialItemX))) { + legend.itemX = initialItemX; + legend.itemY += itemMarginTop + legend.lastLineHeight + itemMarginBottom; + legend.lastLineHeight = 0; // reset for next line + } + + // If the item exceeds the height, start a new column + /*if (!horizontal && legend.itemY + options.y + itemHeight > chart.chartHeight - spacingTop - spacingBottom) { + legend.itemY = legend.initialItemY; + legend.itemX += legend.maxItemWidth; + legend.maxItemWidth = 0; + }*/ + + // Set the edge positions + legend.maxItemWidth = mathMax(legend.maxItemWidth, itemWidth); + legend.lastItemY = itemMarginTop + legend.itemY + itemMarginBottom; + legend.lastLineHeight = mathMax(itemHeight, legend.lastLineHeight); // #915 + + // cache the position of the newly generated or reordered items + item._legendItemPos = [legend.itemX, legend.itemY]; + + // advance + if (horizontal) { + legend.itemX += itemWidth; + + } else { + legend.itemY += itemMarginTop + itemHeight + itemMarginBottom; + legend.lastLineHeight = itemHeight; + } + + // the width of the widest item + legend.offsetWidth = widthOption || mathMax( + (horizontal ? legend.itemX - initialItemX - itemDistance : itemWidth) + padding, + legend.offsetWidth + ); + }, + + /** + * Render the legend. This method can be called both before and after + * chart.render. If called after, it will only rearrange items instead + * of creating new ones. + */ + render: function () { + var legend = this, + chart = legend.chart, + renderer = chart.renderer, + legendGroup = legend.group, + allItems, + display, + legendWidth, + legendHeight, + box = legend.box, + options = legend.options, + padding = legend.padding, + legendBorderWidth = options.borderWidth, + legendBackgroundColor = options.backgroundColor; + + legend.itemX = legend.initialItemX; + legend.itemY = legend.initialItemY; + legend.offsetWidth = 0; + legend.lastItemY = 0; + + if (!legendGroup) { + legend.group = legendGroup = renderer.g('legend') + .attr({ zIndex: 7 }) + .add(); + legend.contentGroup = renderer.g() + .attr({ zIndex: 1 }) // above background + .add(legendGroup); + legend.scrollGroup = renderer.g() + .add(legend.contentGroup); + } + + legend.renderTitle(); + + // add each series or point + allItems = []; + each(chart.series, function (serie) { + var seriesOptions = serie.options; + + if (!seriesOptions.showInLegend || defined(seriesOptions.linkedTo)) { + return; + } + + // use points or series for the legend item depending on legendType + allItems = allItems.concat( + serie.legendItems || + (seriesOptions.legendType === 'point' ? + serie.data : + serie) + ); + }); + + // sort by legendIndex + stableSort(allItems, function (a, b) { + return ((a.options && a.options.legendIndex) || 0) - ((b.options && b.options.legendIndex) || 0); + }); + + // reversed legend + if (options.reversed) { + allItems.reverse(); + } + + legend.allItems = allItems; + legend.display = display = !!allItems.length; + + // render the items + each(allItems, function (item) { + legend.renderItem(item); + }); + + // Draw the border + legendWidth = options.width || legend.offsetWidth; + legendHeight = legend.lastItemY + legend.lastLineHeight + legend.titleHeight; + + + legendHeight = legend.handleOverflow(legendHeight); + + if (legendBorderWidth || legendBackgroundColor) { + legendWidth += padding; + legendHeight += padding; + + if (!box) { + legend.box = box = renderer.rect( + 0, + 0, + legendWidth, + legendHeight, + options.borderRadius, + legendBorderWidth || 0 + ).attr({ + stroke: options.borderColor, + 'stroke-width': legendBorderWidth || 0, + fill: legendBackgroundColor || NONE + }) + .add(legendGroup) + .shadow(options.shadow); + box.isNew = true; + + } else if (legendWidth > 0 && legendHeight > 0) { + box[box.isNew ? 'attr' : 'animate']( + box.crisp(null, null, null, legendWidth, legendHeight) + ); + box.isNew = false; + } + + // hide the border if no items + box[display ? 'show' : 'hide'](); + } + + legend.legendWidth = legendWidth; + legend.legendHeight = legendHeight; + + // Now that the legend width and height are established, put the items in the + // final position + each(allItems, function (item) { + legend.positionItem(item); + }); + + // 1.x compatibility: positioning based on style + /*var props = ['left', 'right', 'top', 'bottom'], + prop, + i = 4; + while (i--) { + prop = props[i]; + if (options.style[prop] && options.style[prop] !== 'auto') { + options[i < 2 ? 'align' : 'verticalAlign'] = prop; + options[i < 2 ? 'x' : 'y'] = pInt(options.style[prop]) * (i % 2 ? -1 : 1); + } + }*/ + + if (display) { + legendGroup.align(extend({ + width: legendWidth, + height: legendHeight + }, options), true, 'spacingBox'); + } + + if (!chart.isResizing) { + this.positionCheckboxes(); + } + }, + + /** + * Set up the overflow handling by adding navigation with up and down arrows below the + * legend. + */ + handleOverflow: function (legendHeight) { + var legend = this, + chart = this.chart, + renderer = chart.renderer, + pageCount, + options = this.options, + optionsY = options.y, + alignTop = options.verticalAlign === 'top', + spaceHeight = chart.spacingBox.height + (alignTop ? -optionsY : optionsY) - this.padding, + maxHeight = options.maxHeight, + clipHeight, + clipRect = this.clipRect, + navOptions = options.navigation, + animation = pick(navOptions.animation, true), + arrowSize = navOptions.arrowSize || 12, + nav = this.nav; + + // Adjust the height + if (options.layout === 'horizontal') { + spaceHeight /= 2; + } + if (maxHeight) { + spaceHeight = mathMin(spaceHeight, maxHeight); + } + + // Reset the legend height and adjust the clipping rectangle + if (legendHeight > spaceHeight && !options.useHTML) { + + this.clipHeight = clipHeight = spaceHeight - 20 - this.titleHeight; + this.pageCount = pageCount = mathCeil(legendHeight / clipHeight); + this.currentPage = pick(this.currentPage, 1); + this.fullHeight = legendHeight; + + // Only apply clipping if needed. Clipping causes blurred legend in PDF export (#1787) + if (!clipRect) { + clipRect = legend.clipRect = renderer.clipRect(0, 0, 9999, 0); + legend.contentGroup.clip(clipRect); + } + clipRect.attr({ + height: clipHeight + }); + + // Add navigation elements + if (!nav) { + this.nav = nav = renderer.g().attr({ zIndex: 1 }).add(this.group); + this.up = renderer.symbol('triangle', 0, 0, arrowSize, arrowSize) + .on('click', function () { + legend.scroll(-1, animation); + }) + .add(nav); + this.pager = renderer.text('', 15, 10) + .css(navOptions.style) + .add(nav); + this.down = renderer.symbol('triangle-down', 0, 0, arrowSize, arrowSize) + .on('click', function () { + legend.scroll(1, animation); + }) + .add(nav); + } + + // Set initial position + legend.scroll(0); + + legendHeight = spaceHeight; + + } else if (nav) { + clipRect.attr({ + height: chart.chartHeight + }); + nav.hide(); + this.scrollGroup.attr({ + translateY: 1 + }); + this.clipHeight = 0; // #1379 + } + + return legendHeight; + }, + + /** + * Scroll the legend by a number of pages + * @param {Object} scrollBy + * @param {Object} animation + */ + scroll: function (scrollBy, animation) { + var pageCount = this.pageCount, + currentPage = this.currentPage + scrollBy, + clipHeight = this.clipHeight, + navOptions = this.options.navigation, + activeColor = navOptions.activeColor, + inactiveColor = navOptions.inactiveColor, + pager = this.pager, + padding = this.padding, + scrollOffset; + + // When resizing while looking at the last page + if (currentPage > pageCount) { + currentPage = pageCount; + } + + if (currentPage > 0) { + + if (animation !== UNDEFINED) { + setAnimation(animation, this.chart); + } + + this.nav.attr({ + translateX: padding, + translateY: clipHeight + 7 + this.titleHeight, + visibility: VISIBLE + }); + this.up.attr({ + fill: currentPage === 1 ? inactiveColor : activeColor + }) + .css({ + cursor: currentPage === 1 ? 'default' : 'pointer' + }); + pager.attr({ + text: currentPage + '/' + this.pageCount + }); + this.down.attr({ + x: 18 + this.pager.getBBox().width, // adjust to text width + fill: currentPage === pageCount ? inactiveColor : activeColor + }) + .css({ + cursor: currentPage === pageCount ? 'default' : 'pointer' + }); + + scrollOffset = -mathMin(clipHeight * (currentPage - 1), this.fullHeight - clipHeight + padding) + 1; + this.scrollGroup.animate({ + translateY: scrollOffset + }); + pager.attr({ + text: currentPage + '/' + pageCount + }); + + + this.currentPage = currentPage; + this.positionCheckboxes(scrollOffset); + } + + } + +}; + +// Workaround for #2030, horizontal legend items not displaying in IE11 Preview. +// TODO: When IE11 is released, check again for this bug, and remove the fix +// or make a better one. +if (/Trident.*?11\.0/.test(userAgent)) { + wrap(Legend.prototype, 'positionItem', function (proceed, item) { + var legend = this; + setTimeout(function () { + proceed.call(legend, item); + }); + }); +} + +/** + * The chart class + * @param {Object} options + * @param {Function} callback Function to run when the chart has loaded + */ +function Chart() { + this.init.apply(this, arguments); +} + +Chart.prototype = { + + /** + * Initialize the chart + */ + init: function (userOptions, callback) { + + // Handle regular options + var options, + seriesOptions = userOptions.series; // skip merging data points to increase performance + + userOptions.series = null; + options = merge(defaultOptions, userOptions); // do the merge + options.series = userOptions.series = seriesOptions; // set back the series data + + var optionsChart = options.chart; + + // Create margin & spacing array + this.margin = this.splashArray('margin', optionsChart); + this.spacing = this.splashArray('spacing', optionsChart); + + var chartEvents = optionsChart.events; + + //this.runChartClick = chartEvents && !!chartEvents.click; + this.bounds = { h: {}, v: {} }; // Pixel data bounds for touch zoom + + this.callback = callback; + this.isResizing = 0; + this.options = options; + //chartTitleOptions = UNDEFINED; + //chartSubtitleOptions = UNDEFINED; + + this.axes = []; + this.series = []; + this.hasCartesianSeries = optionsChart.showAxes; + //this.axisOffset = UNDEFINED; + //this.maxTicks = UNDEFINED; // handle the greatest amount of ticks on grouped axes + //this.inverted = UNDEFINED; + //this.loadingShown = UNDEFINED; + //this.container = UNDEFINED; + //this.chartWidth = UNDEFINED; + //this.chartHeight = UNDEFINED; + //this.marginRight = UNDEFINED; + //this.marginBottom = UNDEFINED; + //this.containerWidth = UNDEFINED; + //this.containerHeight = UNDEFINED; + //this.oldChartWidth = UNDEFINED; + //this.oldChartHeight = UNDEFINED; + + //this.renderTo = UNDEFINED; + //this.renderToClone = UNDEFINED; + + //this.spacingBox = UNDEFINED + + //this.legend = UNDEFINED; + + // Elements + //this.chartBackground = UNDEFINED; + //this.plotBackground = UNDEFINED; + //this.plotBGImage = UNDEFINED; + //this.plotBorder = UNDEFINED; + //this.loadingDiv = UNDEFINED; + //this.loadingSpan = UNDEFINED; + + var chart = this, + eventType; + + // Add the chart to the global lookup + chart.index = charts.length; + charts.push(chart); + + // Set up auto resize + if (optionsChart.reflow !== false) { + addEvent(chart, 'load', function () { + chart.initReflow(); + }); + } + + // Chart event handlers + if (chartEvents) { + for (eventType in chartEvents) { + addEvent(chart, eventType, chartEvents[eventType]); + } + } + + chart.xAxis = []; + chart.yAxis = []; + + // Expose methods and variables + chart.animation = useCanVG ? false : pick(optionsChart.animation, true); + chart.pointCount = 0; + chart.counters = new ChartCounters(); + + chart.firstRender(); + }, + + /** + * Initialize an individual series, called internally before render time + */ + initSeries: function (options) { + var chart = this, + optionsChart = chart.options.chart, + type = options.type || optionsChart.type || optionsChart.defaultSeriesType, + series, + constr = seriesTypes[type]; + + // No such series type + if (!constr) { + error(17, true); + } + + series = new constr(); + series.init(this, options); + return series; + }, + + /** + * Add a series dynamically after time + * + * @param {Object} options The config options + * @param {Boolean} redraw Whether to redraw the chart after adding. Defaults to true. + * @param {Boolean|Object} animation Whether to apply animation, and optionally animation + * configuration + * + * @return {Object} series The newly created series object + */ + addSeries: function (options, redraw, animation) { + var series, + chart = this; + + if (options) { + redraw = pick(redraw, true); // defaults to true + + fireEvent(chart, 'addSeries', { options: options }, function () { + series = chart.initSeries(options); + + chart.isDirtyLegend = true; // the series array is out of sync with the display + chart.linkSeries(); + if (redraw) { + chart.redraw(animation); + } + }); + } + + return series; + }, + + /** + * Add an axis to the chart + * @param {Object} options The axis option + * @param {Boolean} isX Whether it is an X axis or a value axis + */ + addAxis: function (options, isX, redraw, animation) { + var key = isX ? 'xAxis' : 'yAxis', + chartOptions = this.options, + axis; + + /*jslint unused: false*/ + axis = new Axis(this, merge(options, { + index: this[key].length, + isX: isX + })); + /*jslint unused: true*/ + + // Push the new axis options to the chart options + chartOptions[key] = splat(chartOptions[key] || {}); + chartOptions[key].push(options); + + if (pick(redraw, true)) { + this.redraw(animation); + } + }, + + /** + * Check whether a given point is within the plot area + * + * @param {Number} plotX Pixel x relative to the plot area + * @param {Number} plotY Pixel y relative to the plot area + * @param {Boolean} inverted Whether the chart is inverted + */ + isInsidePlot: function (plotX, plotY, inverted) { + var x = inverted ? plotY : plotX, + y = inverted ? plotX : plotY; + + return x >= 0 && + x <= this.plotWidth && + y >= 0 && + y <= this.plotHeight; + }, + + /** + * Adjust all axes tick amounts + */ + adjustTickAmounts: function () { + if (this.options.chart.alignTicks !== false) { + each(this.axes, function (axis) { + axis.adjustTickAmount(); + }); + } + this.maxTicks = null; + }, + + /** + * Redraw legend, axes or series based on updated data + * + * @param {Boolean|Object} animation Whether to apply animation, and optionally animation + * configuration + */ + redraw: function (animation) { + var chart = this, + axes = chart.axes, + series = chart.series, + pointer = chart.pointer, + legend = chart.legend, + redrawLegend = chart.isDirtyLegend, + hasStackedSeries, + hasDirtyStacks, + isDirtyBox = chart.isDirtyBox, // todo: check if it has actually changed? + seriesLength = series.length, + i = seriesLength, + serie, + renderer = chart.renderer, + isHiddenChart = renderer.isHidden(), + afterRedraw = []; + + setAnimation(animation, chart); + + if (isHiddenChart) { + chart.cloneRenderTo(); + } + + // Adjust title layout (reflow multiline text) + chart.layOutTitles(); + + // link stacked series + while (i--) { + serie = series[i]; + + if (serie.options.stacking) { + hasStackedSeries = true; + + if (serie.isDirty) { + hasDirtyStacks = true; + break; + } + } + } + if (hasDirtyStacks) { // mark others as dirty + i = seriesLength; + while (i--) { + serie = series[i]; + if (serie.options.stacking) { + serie.isDirty = true; + } + } + } + + // handle updated data in the series + each(series, function (serie) { + if (serie.isDirty) { // prepare the data so axis can read it + if (serie.options.legendType === 'point') { + redrawLegend = true; + } + } + }); + + // handle added or removed series + if (redrawLegend && legend.options.enabled) { // series or pie points are added or removed + // draw legend graphics + legend.render(); + + chart.isDirtyLegend = false; + } + + // reset stacks + if (hasStackedSeries) { + chart.getStacks(); + } + + + if (chart.hasCartesianSeries) { + if (!chart.isResizing) { + + // reset maxTicks + chart.maxTicks = null; + + // set axes scales + each(axes, function (axis) { + axis.setScale(); + }); + } + + chart.adjustTickAmounts(); + chart.getMargins(); + + // If one axis is dirty, all axes must be redrawn (#792, #2169) + each(axes, function (axis) { + if (axis.isDirty) { + isDirtyBox = true; + } + }); + + // redraw axes + each(axes, function (axis) { + + // Fire 'afterSetExtremes' only if extremes are set + if (axis.isDirtyExtremes) { // #821 + axis.isDirtyExtremes = false; + afterRedraw.push(function () { // prevent a recursive call to chart.redraw() (#1119) + fireEvent(axis, 'afterSetExtremes', extend(axis.eventArgs, axis.getExtremes())); // #747, #751 + delete axis.eventArgs; + }); + } + + if (isDirtyBox || hasStackedSeries) { + axis.redraw(); + } + }); + + + } + // the plot areas size has changed + if (isDirtyBox) { + chart.drawChartBox(); + } + + + // redraw affected series + each(series, function (serie) { + if (serie.isDirty && serie.visible && + (!serie.isCartesian || serie.xAxis)) { // issue #153 + serie.redraw(); + } + }); + + // move tooltip or reset + if (pointer && pointer.reset) { + pointer.reset(true); + } + + // redraw if canvas + renderer.draw(); + + // fire the event + fireEvent(chart, 'redraw'); // jQuery breaks this when calling it from addEvent. Overwrites chart.redraw + + if (isHiddenChart) { + chart.cloneRenderTo(true); + } + + // Fire callbacks that are put on hold until after the redraw + each(afterRedraw, function (callback) { + callback.call(); + }); + }, + + + + /** + * Dim the chart and show a loading text or symbol + * @param {String} str An optional text to show in the loading label instead of the default one + */ + showLoading: function (str) { + var chart = this, + options = chart.options, + loadingDiv = chart.loadingDiv; + + var loadingOptions = options.loading; + + // create the layer at the first call + if (!loadingDiv) { + chart.loadingDiv = loadingDiv = createElement(DIV, { + className: PREFIX + 'loading' + }, extend(loadingOptions.style, { + zIndex: 10, + display: NONE + }), chart.container); + + chart.loadingSpan = createElement( + 'span', + null, + loadingOptions.labelStyle, + loadingDiv + ); + + } + + // update text + chart.loadingSpan.innerHTML = str || options.lang.loading; + + // show it + if (!chart.loadingShown) { + css(loadingDiv, { + opacity: 0, + display: '', + left: chart.plotLeft + PX, + top: chart.plotTop + PX, + width: chart.plotWidth + PX, + height: chart.plotHeight + PX + }); + animate(loadingDiv, { + opacity: loadingOptions.style.opacity + }, { + duration: loadingOptions.showDuration || 0 + }); + chart.loadingShown = true; + } + }, + + /** + * Hide the loading layer + */ + hideLoading: function () { + var options = this.options, + loadingDiv = this.loadingDiv; + + if (loadingDiv) { + animate(loadingDiv, { + opacity: 0 + }, { + duration: options.loading.hideDuration || 100, + complete: function () { + css(loadingDiv, { display: NONE }); + } + }); + } + this.loadingShown = false; + }, + + /** + * Get an axis, series or point object by id. + * @param id {String} The id as given in the configuration options + */ + get: function (id) { + var chart = this, + axes = chart.axes, + series = chart.series; + + var i, + j, + points; + + // search axes + for (i = 0; i < axes.length; i++) { + if (axes[i].options.id === id) { + return axes[i]; + } + } + + // search series + for (i = 0; i < series.length; i++) { + if (series[i].options.id === id) { + return series[i]; + } + } + + // search points + for (i = 0; i < series.length; i++) { + points = series[i].points || []; + for (j = 0; j < points.length; j++) { + if (points[j].id === id) { + return points[j]; + } + } + } + return null; + }, + + /** + * Create the Axis instances based on the config options + */ + getAxes: function () { + var chart = this, + options = this.options, + xAxisOptions = options.xAxis = splat(options.xAxis || {}), + yAxisOptions = options.yAxis = splat(options.yAxis || {}), + optionsArray, + axis; + + // make sure the options are arrays and add some members + each(xAxisOptions, function (axis, i) { + axis.index = i; + axis.isX = true; + }); + + each(yAxisOptions, function (axis, i) { + axis.index = i; + }); + + // concatenate all axis options into one array + optionsArray = xAxisOptions.concat(yAxisOptions); + + each(optionsArray, function (axisOptions) { + axis = new Axis(chart, axisOptions); + }); + + chart.adjustTickAmounts(); + }, + + + /** + * Get the currently selected points from all series + */ + getSelectedPoints: function () { + var points = []; + each(this.series, function (serie) { + points = points.concat(grep(serie.points || [], function (point) { + return point.selected; + })); + }); + return points; + }, + + /** + * Get the currently selected series + */ + getSelectedSeries: function () { + return grep(this.series, function (serie) { + return serie.selected; + }); + }, + + /** + * Generate stacks for each series and calculate stacks total values + */ + getStacks: function () { + var chart = this; + + // reset stacks for each yAxis + each(chart.yAxis, function (axis) { + if (axis.stacks && axis.hasVisibleSeries) { + axis.oldStacks = axis.stacks; + } + }); + + each(chart.series, function (series) { + if (series.options.stacking && (series.visible === true || chart.options.chart.ignoreHiddenSeries === false)) { + series.stackKey = series.type + pick(series.options.stack, ''); + } + }); + }, + + /** + * Display the zoom button + */ + showResetZoom: function () { + var chart = this, + lang = defaultOptions.lang, + btnOptions = chart.options.chart.resetZoomButton, + theme = btnOptions.theme, + states = theme.states, + alignTo = btnOptions.relativeTo === 'chart' ? null : 'plotBox'; + + this.resetZoomButton = chart.renderer.button(lang.resetZoom, null, null, function () { chart.zoomOut(); }, theme, states && states.hover) + .attr({ + align: btnOptions.position.align, + title: lang.resetZoomTitle + }) + .add() + .align(btnOptions.position, false, alignTo); + + }, + + /** + * Zoom out to 1:1 + */ + zoomOut: function () { + var chart = this; + fireEvent(chart, 'selection', { resetSelection: true }, function () { + chart.zoom(); + }); + }, + + /** + * Zoom into a given portion of the chart given by axis coordinates + * @param {Object} event + */ + zoom: function (event) { + var chart = this, + hasZoomed, + pointer = chart.pointer, + displayButton = false, + resetZoomButton; + + // If zoom is called with no arguments, reset the axes + if (!event || event.resetSelection) { + each(chart.axes, function (axis) { + hasZoomed = axis.zoom(); + }); + } else { // else, zoom in on all axes + each(event.xAxis.concat(event.yAxis), function (axisData) { + var axis = axisData.axis, + isXAxis = axis.isXAxis; + + // don't zoom more than minRange + if (pointer[isXAxis ? 'zoomX' : 'zoomY'] || pointer[isXAxis ? 'pinchX' : 'pinchY']) { + hasZoomed = axis.zoom(axisData.min, axisData.max); + if (axis.displayBtn) { + displayButton = true; + } + } + }); + } + + // Show or hide the Reset zoom button + resetZoomButton = chart.resetZoomButton; + if (displayButton && !resetZoomButton) { + chart.showResetZoom(); + } else if (!displayButton && isObject(resetZoomButton)) { + chart.resetZoomButton = resetZoomButton.destroy(); + } + + + // Redraw + if (hasZoomed) { + chart.redraw( + pick(chart.options.chart.animation, event && event.animation, chart.pointCount < 100) // animation + ); + } + }, + + /** + * Pan the chart by dragging the mouse across the pane. This function is called + * on mouse move, and the distance to pan is computed from chartX compared to + * the first chartX position in the dragging operation. + */ + pan: function (e, panning) { + + var chart = this, + hoverPoints = chart.hoverPoints, + doRedraw; + + // remove active points for shared tooltip + if (hoverPoints) { + each(hoverPoints, function (point) { + point.setState(); + }); + } + + each(panning === 'xy' ? [1, 0] : [1], function (isX) { // xy is used in maps + var mousePos = e[isX ? 'chartX' : 'chartY'], + axis = chart[isX ? 'xAxis' : 'yAxis'][0], + startPos = chart[isX ? 'mouseDownX' : 'mouseDownY'], + halfPointRange = (axis.pointRange || 0) / 2, + extremes = axis.getExtremes(), + newMin = axis.toValue(startPos - mousePos, true) + halfPointRange, + newMax = axis.toValue(startPos + chart[isX ? 'plotWidth' : 'plotHeight'] - mousePos, true) - halfPointRange; + + if (axis.series.length && newMin > mathMin(extremes.dataMin, extremes.min) && newMax < mathMax(extremes.dataMax, extremes.max)) { + axis.setExtremes(newMin, newMax, false, false, { trigger: 'pan' }); + doRedraw = true; + } + + chart[isX ? 'mouseDownX' : 'mouseDownY'] = mousePos; // set new reference for next run + }); + + if (doRedraw) { + chart.redraw(false); + } + css(chart.container, { cursor: 'move' }); + }, + + /** + * Show the title and subtitle of the chart + * + * @param titleOptions {Object} New title options + * @param subtitleOptions {Object} New subtitle options + * + */ + setTitle: function (titleOptions, subtitleOptions) { + var chart = this, + options = chart.options, + chartTitleOptions, + chartSubtitleOptions; + + chartTitleOptions = options.title = merge(options.title, titleOptions); + chartSubtitleOptions = options.subtitle = merge(options.subtitle, subtitleOptions); + + // add title and subtitle + each([ + ['title', titleOptions, chartTitleOptions], + ['subtitle', subtitleOptions, chartSubtitleOptions] + ], function (arr) { + var name = arr[0], + title = chart[name], + titleOptions = arr[1], + chartTitleOptions = arr[2]; + + if (title && titleOptions) { + chart[name] = title = title.destroy(); // remove old + } + + if (chartTitleOptions && chartTitleOptions.text && !title) { + chart[name] = chart.renderer.text( + chartTitleOptions.text, + 0, + 0, + chartTitleOptions.useHTML + ) + .attr({ + align: chartTitleOptions.align, + 'class': PREFIX + name, + zIndex: chartTitleOptions.zIndex || 4 + }) + .css(chartTitleOptions.style) + .add(); + } + }); + chart.layOutTitles(); + }, + + /** + * Lay out the chart titles and cache the full offset height for use in getMargins + */ + layOutTitles: function () { + var titleOffset = 0, + title = this.title, + subtitle = this.subtitle, + options = this.options, + titleOptions = options.title, + subtitleOptions = options.subtitle, + autoWidth = this.spacingBox.width - 44; // 44 makes room for default context button + + if (title) { + title + .css({ width: (titleOptions.width || autoWidth) + PX }) + .align(extend({ y: 15 }, titleOptions), false, 'spacingBox'); + + if (!titleOptions.floating && !titleOptions.verticalAlign) { + titleOffset = title.getBBox().height; + + // Adjust for browser consistency + backwards compat after #776 fix + if (titleOffset >= 18 && titleOffset <= 25) { + titleOffset = 15; + } + } + } + if (subtitle) { + subtitle + .css({ width: (subtitleOptions.width || autoWidth) + PX }) + .align(extend({ y: titleOffset + titleOptions.margin }, subtitleOptions), false, 'spacingBox'); + + if (!subtitleOptions.floating && !subtitleOptions.verticalAlign) { + titleOffset = mathCeil(titleOffset + subtitle.getBBox().height); + } + } + + this.titleOffset = titleOffset; // used in getMargins + }, + + /** + * Get chart width and height according to options and container size + */ + getChartSize: function () { + var chart = this, + optionsChart = chart.options.chart, + renderTo = chart.renderToClone || chart.renderTo; + + // get inner width and height from jQuery (#824) + chart.containerWidth = adapterRun(renderTo, 'width'); + chart.containerHeight = adapterRun(renderTo, 'height'); + + chart.chartWidth = mathMax(0, optionsChart.width || chart.containerWidth || 600); // #1393, 1460 + chart.chartHeight = mathMax(0, pick(optionsChart.height, + // the offsetHeight of an empty container is 0 in standard browsers, but 19 in IE7: + chart.containerHeight > 19 ? chart.containerHeight : 400)); + }, + + /** + * Create a clone of the chart's renderTo div and place it outside the viewport to allow + * size computation on chart.render and chart.redraw + */ + cloneRenderTo: function (revert) { + var clone = this.renderToClone, + container = this.container; + + // Destroy the clone and bring the container back to the real renderTo div + if (revert) { + if (clone) { + this.renderTo.appendChild(container); + discardElement(clone); + delete this.renderToClone; + } + + // Set up the clone + } else { + if (container && container.parentNode === this.renderTo) { + this.renderTo.removeChild(container); // do not clone this + } + this.renderToClone = clone = this.renderTo.cloneNode(0); + css(clone, { + position: ABSOLUTE, + top: '-9999px', + display: 'block' // #833 + }); + doc.body.appendChild(clone); + if (container) { + clone.appendChild(container); + } + } + }, + + /** + * Get the containing element, determine the size and create the inner container + * div to hold the chart + */ + getContainer: function () { + var chart = this, + container, + optionsChart = chart.options.chart, + chartWidth, + chartHeight, + renderTo, + indexAttrName = 'data-highcharts-chart', + oldChartIndex, + containerId; + + chart.renderTo = renderTo = optionsChart.renderTo; + containerId = PREFIX + idCounter++; + + if (isString(renderTo)) { + chart.renderTo = renderTo = doc.getElementById(renderTo); + } + + // Display an error if the renderTo is wrong + if (!renderTo) { + error(13, true); + } + + // If the container already holds a chart, destroy it + oldChartIndex = pInt(attr(renderTo, indexAttrName)); + if (!isNaN(oldChartIndex) && charts[oldChartIndex]) { + charts[oldChartIndex].destroy(); + } + + // Make a reference to the chart from the div + attr(renderTo, indexAttrName, chart.index); + + // remove previous chart + renderTo.innerHTML = ''; + + // If the container doesn't have an offsetWidth, it has or is a child of a node + // that has display:none. We need to temporarily move it out to a visible + // state to determine the size, else the legend and tooltips won't render + // properly + if (!renderTo.offsetWidth) { + chart.cloneRenderTo(); + } + + // get the width and height + chart.getChartSize(); + chartWidth = chart.chartWidth; + chartHeight = chart.chartHeight; + + // create the inner container + chart.container = container = createElement(DIV, { + className: PREFIX + 'container' + + (optionsChart.className ? ' ' + optionsChart.className : ''), + id: containerId + }, extend({ + position: RELATIVE, + overflow: HIDDEN, // needed for context menu (avoid scrollbars) and + // content overflow in IE + width: chartWidth + PX, + height: chartHeight + PX, + textAlign: 'left', + lineHeight: 'normal', // #427 + zIndex: 0, // #1072 + '-webkit-tap-highlight-color': 'rgba(0,0,0,0)' + }, optionsChart.style), + chart.renderToClone || renderTo + ); + + // cache the cursor (#1650) + chart._cursor = container.style.cursor; + + chart.renderer = + optionsChart.forExport ? // force SVG, used for SVG export + new SVGRenderer(container, chartWidth, chartHeight, true) : + new Renderer(container, chartWidth, chartHeight); + + if (useCanVG) { + // If we need canvg library, extend and configure the renderer + // to get the tracker for translating mouse events + chart.renderer.create(chart, container, chartWidth, chartHeight); + } + }, + + /** + * Calculate margins by rendering axis labels in a preliminary position. Title, + * subtitle and legend have already been rendered at this stage, but will be + * moved into their final positions + */ + getMargins: function () { + var chart = this, + spacing = chart.spacing, + axisOffset, + legend = chart.legend, + margin = chart.margin, + legendOptions = chart.options.legend, + legendMargin = pick(legendOptions.margin, 10), + legendX = legendOptions.x, + legendY = legendOptions.y, + align = legendOptions.align, + verticalAlign = legendOptions.verticalAlign, + titleOffset = chart.titleOffset; + + chart.resetMargins(); + axisOffset = chart.axisOffset; + + // Adjust for title and subtitle + if (titleOffset && !defined(margin[0])) { + chart.plotTop = mathMax(chart.plotTop, titleOffset + chart.options.title.margin + spacing[0]); + } + + // Adjust for legend + if (legend.display && !legendOptions.floating) { + if (align === 'right') { // horizontal alignment handled first + if (!defined(margin[1])) { + chart.marginRight = mathMax( + chart.marginRight, + legend.legendWidth - legendX + legendMargin + spacing[1] + ); + } + } else if (align === 'left') { + if (!defined(margin[3])) { + chart.plotLeft = mathMax( + chart.plotLeft, + legend.legendWidth + legendX + legendMargin + spacing[3] + ); + } + + } else if (verticalAlign === 'top') { + if (!defined(margin[0])) { + chart.plotTop = mathMax( + chart.plotTop, + legend.legendHeight + legendY + legendMargin + spacing[0] + ); + } + + } else if (verticalAlign === 'bottom') { + if (!defined(margin[2])) { + chart.marginBottom = mathMax( + chart.marginBottom, + legend.legendHeight - legendY + legendMargin + spacing[2] + ); + } + } + } + + // adjust for scroller + if (chart.extraBottomMargin) { + chart.marginBottom += chart.extraBottomMargin; + } + if (chart.extraTopMargin) { + chart.plotTop += chart.extraTopMargin; + } + + // pre-render axes to get labels offset width + if (chart.hasCartesianSeries) { + each(chart.axes, function (axis) { + axis.getOffset(); + }); + } + + if (!defined(margin[3])) { + chart.plotLeft += axisOffset[3]; + } + if (!defined(margin[0])) { + chart.plotTop += axisOffset[0]; + } + if (!defined(margin[2])) { + chart.marginBottom += axisOffset[2]; + } + if (!defined(margin[1])) { + chart.marginRight += axisOffset[1]; + } + + chart.setChartSize(); + + }, + + /** + * Add the event handlers necessary for auto resizing + * + */ + initReflow: function () { + var chart = this, + optionsChart = chart.options.chart, + renderTo = chart.renderTo, + reflowTimeout; + + function reflow(e) { + var width = optionsChart.width || adapterRun(renderTo, 'width'), + height = optionsChart.height || adapterRun(renderTo, 'height'), + target = e ? e.target : win; // #805 - MooTools doesn't supply e + + // Width and height checks for display:none. Target is doc in IE8 and Opera, + // win in Firefox, Chrome and IE9. + if (!chart.hasUserSize && width && height && (target === win || target === doc)) { + + if (width !== chart.containerWidth || height !== chart.containerHeight) { + clearTimeout(reflowTimeout); + chart.reflowTimeout = reflowTimeout = setTimeout(function () { + if (chart.container) { // It may have been destroyed in the meantime (#1257) + chart.setSize(width, height, false); + chart.hasUserSize = null; + } + }, 100); + } + chart.containerWidth = width; + chart.containerHeight = height; + } + } + chart.reflow = reflow; + addEvent(win, 'resize', reflow); + addEvent(chart, 'destroy', function () { + removeEvent(win, 'resize', reflow); + }); + }, + + /** + * Resize the chart to a given width and height + * @param {Number} width + * @param {Number} height + * @param {Object|Boolean} animation + */ + setSize: function (width, height, animation) { + var chart = this, + chartWidth, + chartHeight, + fireEndResize; + + // Handle the isResizing counter + chart.isResizing += 1; + fireEndResize = function () { + if (chart) { + fireEvent(chart, 'endResize', null, function () { + chart.isResizing -= 1; + }); + } + }; + + // set the animation for the current process + setAnimation(animation, chart); + + chart.oldChartHeight = chart.chartHeight; + chart.oldChartWidth = chart.chartWidth; + if (defined(width)) { + chart.chartWidth = chartWidth = mathMax(0, mathRound(width)); + chart.hasUserSize = !!chartWidth; + } + if (defined(height)) { + chart.chartHeight = chartHeight = mathMax(0, mathRound(height)); + } + + css(chart.container, { + width: chartWidth + PX, + height: chartHeight + PX + }); + chart.setChartSize(true); + chart.renderer.setSize(chartWidth, chartHeight, animation); + + // handle axes + chart.maxTicks = null; + each(chart.axes, function (axis) { + axis.isDirty = true; + axis.setScale(); + }); + + // make sure non-cartesian series are also handled + each(chart.series, function (serie) { + serie.isDirty = true; + }); + + chart.isDirtyLegend = true; // force legend redraw + chart.isDirtyBox = true; // force redraw of plot and chart border + + chart.getMargins(); + + chart.redraw(animation); + + + chart.oldChartHeight = null; + fireEvent(chart, 'resize'); + + // fire endResize and set isResizing back + // If animation is disabled, fire without delay + if (globalAnimation === false) { + fireEndResize(); + } else { // else set a timeout with the animation duration + setTimeout(fireEndResize, (globalAnimation && globalAnimation.duration) || 500); + } + }, + + /** + * Set the public chart properties. This is done before and after the pre-render + * to determine margin sizes + */ + setChartSize: function (skipAxes) { + var chart = this, + inverted = chart.inverted, + renderer = chart.renderer, + chartWidth = chart.chartWidth, + chartHeight = chart.chartHeight, + optionsChart = chart.options.chart, + spacing = chart.spacing, + clipOffset = chart.clipOffset, + clipX, + clipY, + plotLeft, + plotTop, + plotWidth, + plotHeight, + plotBorderWidth; + + chart.plotLeft = plotLeft = mathRound(chart.plotLeft); + chart.plotTop = plotTop = mathRound(chart.plotTop); + chart.plotWidth = plotWidth = mathMax(0, mathRound(chartWidth - plotLeft - chart.marginRight)); + chart.plotHeight = plotHeight = mathMax(0, mathRound(chartHeight - plotTop - chart.marginBottom)); + + chart.plotSizeX = inverted ? plotHeight : plotWidth; + chart.plotSizeY = inverted ? plotWidth : plotHeight; + + chart.plotBorderWidth = optionsChart.plotBorderWidth || 0; + + // Set boxes used for alignment + chart.spacingBox = renderer.spacingBox = { + x: spacing[3], + y: spacing[0], + width: chartWidth - spacing[3] - spacing[1], + height: chartHeight - spacing[0] - spacing[2] + }; + chart.plotBox = renderer.plotBox = { + x: plotLeft, + y: plotTop, + width: plotWidth, + height: plotHeight + }; + + plotBorderWidth = 2 * mathFloor(chart.plotBorderWidth / 2); + clipX = mathCeil(mathMax(plotBorderWidth, clipOffset[3]) / 2); + clipY = mathCeil(mathMax(plotBorderWidth, clipOffset[0]) / 2); + chart.clipBox = { + x: clipX, + y: clipY, + width: mathFloor(chart.plotSizeX - mathMax(plotBorderWidth, clipOffset[1]) / 2 - clipX), + height: mathFloor(chart.plotSizeY - mathMax(plotBorderWidth, clipOffset[2]) / 2 - clipY) + }; + + if (!skipAxes) { + each(chart.axes, function (axis) { + axis.setAxisSize(); + axis.setAxisTranslation(); + }); + } + }, + + /** + * Initial margins before auto size margins are applied + */ + resetMargins: function () { + var chart = this, + spacing = chart.spacing, + margin = chart.margin; + + chart.plotTop = pick(margin[0], spacing[0]); + chart.marginRight = pick(margin[1], spacing[1]); + chart.marginBottom = pick(margin[2], spacing[2]); + chart.plotLeft = pick(margin[3], spacing[3]); + chart.axisOffset = [0, 0, 0, 0]; // top, right, bottom, left + chart.clipOffset = [0, 0, 0, 0]; + }, + + /** + * Draw the borders and backgrounds for chart and plot area + */ + drawChartBox: function () { + var chart = this, + optionsChart = chart.options.chart, + renderer = chart.renderer, + chartWidth = chart.chartWidth, + chartHeight = chart.chartHeight, + chartBackground = chart.chartBackground, + plotBackground = chart.plotBackground, + plotBorder = chart.plotBorder, + plotBGImage = chart.plotBGImage, + chartBorderWidth = optionsChart.borderWidth || 0, + chartBackgroundColor = optionsChart.backgroundColor, + plotBackgroundColor = optionsChart.plotBackgroundColor, + plotBackgroundImage = optionsChart.plotBackgroundImage, + plotBorderWidth = optionsChart.plotBorderWidth || 0, + mgn, + bgAttr, + plotLeft = chart.plotLeft, + plotTop = chart.plotTop, + plotWidth = chart.plotWidth, + plotHeight = chart.plotHeight, + plotBox = chart.plotBox, + clipRect = chart.clipRect, + clipBox = chart.clipBox; + + // Chart area + mgn = chartBorderWidth + (optionsChart.shadow ? 8 : 0); + + if (chartBorderWidth || chartBackgroundColor) { + if (!chartBackground) { + + bgAttr = { + fill: chartBackgroundColor || NONE + }; + if (chartBorderWidth) { // #980 + bgAttr.stroke = optionsChart.borderColor; + bgAttr['stroke-width'] = chartBorderWidth; + } + chart.chartBackground = renderer.rect(mgn / 2, mgn / 2, chartWidth - mgn, chartHeight - mgn, + optionsChart.borderRadius, chartBorderWidth) + .attr(bgAttr) + .add() + .shadow(optionsChart.shadow); + + } else { // resize + chartBackground.animate( + chartBackground.crisp(null, null, null, chartWidth - mgn, chartHeight - mgn) + ); + } + } + + + // Plot background + if (plotBackgroundColor) { + if (!plotBackground) { + chart.plotBackground = renderer.rect(plotLeft, plotTop, plotWidth, plotHeight, 0) + .attr({ + fill: plotBackgroundColor + }) + .add() + .shadow(optionsChart.plotShadow); + } else { + plotBackground.animate(plotBox); + } + } + if (plotBackgroundImage) { + if (!plotBGImage) { + chart.plotBGImage = renderer.image(plotBackgroundImage, plotLeft, plotTop, plotWidth, plotHeight) + .add(); + } else { + plotBGImage.animate(plotBox); + } + } + + // Plot clip + if (!clipRect) { + chart.clipRect = renderer.clipRect(clipBox); + } else { + clipRect.animate({ + width: clipBox.width, + height: clipBox.height + }); + } + + // Plot area border + if (plotBorderWidth) { + if (!plotBorder) { + chart.plotBorder = renderer.rect(plotLeft, plotTop, plotWidth, plotHeight, 0, -plotBorderWidth) + .attr({ + stroke: optionsChart.plotBorderColor, + 'stroke-width': plotBorderWidth, + zIndex: 1 + }) + .add(); + } else { + plotBorder.animate( + plotBorder.crisp(null, plotLeft, plotTop, plotWidth, plotHeight) + ); + } + } + + // reset + chart.isDirtyBox = false; + }, + + /** + * Detect whether a certain chart property is needed based on inspecting its options + * and series. This mainly applies to the chart.invert property, and in extensions to + * the chart.angular and chart.polar properties. + */ + propFromSeries: function () { + var chart = this, + optionsChart = chart.options.chart, + klass, + seriesOptions = chart.options.series, + i, + value; + + + each(['inverted', 'angular', 'polar'], function (key) { + + // The default series type's class + klass = seriesTypes[optionsChart.type || optionsChart.defaultSeriesType]; + + // Get the value from available chart-wide properties + value = ( + chart[key] || // 1. it is set before + optionsChart[key] || // 2. it is set in the options + (klass && klass.prototype[key]) // 3. it's default series class requires it + ); + + // 4. Check if any the chart's series require it + i = seriesOptions && seriesOptions.length; + while (!value && i--) { + klass = seriesTypes[seriesOptions[i].type]; + if (klass && klass.prototype[key]) { + value = true; + } + } + + // Set the chart property + chart[key] = value; + }); + + }, + + /** + * Link two or more series together. This is done initially from Chart.render, + * and after Chart.addSeries and Series.remove. + */ + linkSeries: function () { + var chart = this, + chartSeries = chart.series; + + // Reset links + each(chartSeries, function (series) { + series.linkedSeries.length = 0; + }); + + // Apply new links + each(chartSeries, function (series) { + var linkedTo = series.options.linkedTo; + if (isString(linkedTo)) { + if (linkedTo === ':previous') { + linkedTo = chart.series[series.index - 1]; + } else { + linkedTo = chart.get(linkedTo); + } + if (linkedTo) { + linkedTo.linkedSeries.push(series); + series.linkedParent = linkedTo; + } + } + }); + }, + + /** + * Render all graphics for the chart + */ + render: function () { + var chart = this, + axes = chart.axes, + renderer = chart.renderer, + options = chart.options; + + var labels = options.labels, + credits = options.credits, + creditsHref; + + // Title + chart.setTitle(); + + + // Legend + chart.legend = new Legend(chart, options.legend); + + chart.getStacks(); // render stacks + + // Get margins by pre-rendering axes + // set axes scales + each(axes, function (axis) { + axis.setScale(); + }); + + chart.getMargins(); + + chart.maxTicks = null; // reset for second pass + each(axes, function (axis) { + axis.setTickPositions(true); // update to reflect the new margins + axis.setMaxTicks(); + }); + chart.adjustTickAmounts(); + chart.getMargins(); // second pass to check for new labels + + + // Draw the borders and backgrounds + chart.drawChartBox(); + + + // Axes + if (chart.hasCartesianSeries) { + each(axes, function (axis) { + axis.render(); + }); + } + + // The series + if (!chart.seriesGroup) { + chart.seriesGroup = renderer.g('series-group') + .attr({ zIndex: 3 }) + .add(); + } + each(chart.series, function (serie) { + serie.translate(); + serie.setTooltipPoints(); + serie.render(); + }); + + // Labels + if (labels.items) { + each(labels.items, function (label) { + var style = extend(labels.style, label.style), + x = pInt(style.left) + chart.plotLeft, + y = pInt(style.top) + chart.plotTop + 12; + + // delete to prevent rewriting in IE + delete style.left; + delete style.top; + + renderer.text( + label.html, + x, + y + ) + .attr({ zIndex: 2 }) + .css(style) + .add(); + + }); + } + + // Credits + if (credits.enabled && !chart.credits) { + creditsHref = credits.href; + chart.credits = renderer.text( + credits.text, + 0, + 0 + ) + .on('click', function () { + if (creditsHref) { + location.href = creditsHref; + } + }) + .attr({ + align: credits.position.align, + zIndex: 8 + }) + .css(credits.style) + .add() + .align(credits.position); + } + + // Set flag + chart.hasRendered = true; + + }, + + /** + * Clean up memory usage + */ + destroy: function () { + var chart = this, + axes = chart.axes, + series = chart.series, + container = chart.container, + i, + parentNode = container && container.parentNode; + + // fire the chart.destoy event + fireEvent(chart, 'destroy'); + + // Delete the chart from charts lookup array + charts[chart.index] = UNDEFINED; + chart.renderTo.removeAttribute('data-highcharts-chart'); + + // remove events + removeEvent(chart); + + // ==== Destroy collections: + // Destroy axes + i = axes.length; + while (i--) { + axes[i] = axes[i].destroy(); + } + + // Destroy each series + i = series.length; + while (i--) { + series[i] = series[i].destroy(); + } + + // ==== Destroy chart properties: + each(['title', 'subtitle', 'chartBackground', 'plotBackground', 'plotBGImage', + 'plotBorder', 'seriesGroup', 'clipRect', 'credits', 'pointer', 'scroller', + 'rangeSelector', 'legend', 'resetZoomButton', 'tooltip', 'renderer'], function (name) { + var prop = chart[name]; + + if (prop && prop.destroy) { + chart[name] = prop.destroy(); + } + }); + + // remove container and all SVG + if (container) { // can break in IE when destroyed before finished loading + container.innerHTML = ''; + removeEvent(container); + if (parentNode) { + discardElement(container); + } + + } + + // clean it all up + for (i in chart) { + delete chart[i]; + } + + }, + + + /** + * VML namespaces can't be added until after complete. Listening + * for Perini's doScroll hack is not enough. + */ + isReadyToRender: function () { + var chart = this; + + // Note: in spite of JSLint's complaints, win == win.top is required + /*jslint eqeq: true*/ + if ((!hasSVG && (win == win.top && doc.readyState !== 'complete')) || (useCanVG && !win.canvg)) { + /*jslint eqeq: false*/ + if (useCanVG) { + // Delay rendering until canvg library is downloaded and ready + CanVGController.push(function () { chart.firstRender(); }, chart.options.global.canvasToolsURL); + } else { + doc.attachEvent('onreadystatechange', function () { + doc.detachEvent('onreadystatechange', chart.firstRender); + if (doc.readyState === 'complete') { + chart.firstRender(); + } + }); + } + return false; + } + return true; + }, + + /** + * Prepare for first rendering after all data are loaded + */ + firstRender: function () { + var chart = this, + options = chart.options, + callback = chart.callback; + + // Check whether the chart is ready to render + if (!chart.isReadyToRender()) { + return; + } + + // Create the container + chart.getContainer(); + + // Run an early event after the container and renderer are established + fireEvent(chart, 'init'); + + + chart.resetMargins(); + chart.setChartSize(); + + // Set the common chart properties (mainly invert) from the given series + chart.propFromSeries(); + + // get axes + chart.getAxes(); + + // Initialize the series + each(options.series || [], function (serieOptions) { + chart.initSeries(serieOptions); + }); + + chart.linkSeries(); + + // Run an event after axes and series are initialized, but before render. At this stage, + // the series data is indexed and cached in the xData and yData arrays, so we can access + // those before rendering. Used in Highstock. + fireEvent(chart, 'beforeRender'); + + // depends on inverted and on margins being set + chart.pointer = new Pointer(chart, options); + + chart.render(); + + // add canvas + chart.renderer.draw(); + // run callbacks + if (callback) { + callback.apply(chart, [chart]); + } + each(chart.callbacks, function (fn) { + fn.apply(chart, [chart]); + }); + + + // If the chart was rendered outside the top container, put it back in + chart.cloneRenderTo(true); + + fireEvent(chart, 'load'); + + }, + + /** + * Creates arrays for spacing and margin from given options. + */ + splashArray: function (target, options) { + var oVar = options[target], + tArray = isObject(oVar) ? oVar : [oVar, oVar, oVar, oVar]; + + return [pick(options[target + 'Top'], tArray[0]), + pick(options[target + 'Right'], tArray[1]), + pick(options[target + 'Bottom'], tArray[2]), + pick(options[target + 'Left'], tArray[3])]; + } +}; // end Chart + +// Hook for exporting module +Chart.prototype.callbacks = []; +/** + * The Point object and prototype. Inheritable and used as base for PiePoint + */ +var Point = function () {}; +Point.prototype = { + + /** + * Initialize the point + * @param {Object} series The series object containing this point + * @param {Object} options The data in either number, array or object format + */ + init: function (series, options, x) { + + var point = this, + colors; + point.series = series; + point.applyOptions(options, x); + point.pointAttr = {}; + + if (series.options.colorByPoint) { + colors = series.options.colors || series.chart.options.colors; + point.color = point.color || colors[series.colorCounter++]; + // loop back to zero + if (series.colorCounter === colors.length) { + series.colorCounter = 0; + } + } + + series.chart.pointCount++; + return point; + }, + /** + * Apply the options containing the x and y data and possible some extra properties. + * This is called on point init or from point.update. + * + * @param {Object} options + */ + applyOptions: function (options, x) { + var point = this, + series = point.series, + pointValKey = series.pointValKey; + + options = Point.prototype.optionsToObject.call(this, options); + + // copy options directly to point + extend(point, options); + point.options = point.options ? extend(point.options, options) : options; + + // For higher dimension series types. For instance, for ranges, point.y is mapped to point.low. + if (pointValKey) { + point.y = point[pointValKey]; + } + + // If no x is set by now, get auto incremented value. All points must have an + // x value, however the y value can be null to create a gap in the series + if (point.x === UNDEFINED && series) { + point.x = x === UNDEFINED ? series.autoIncrement() : x; + } + + return point; + }, + + /** + * Transform number or array configs into objects + */ + optionsToObject: function (options) { + var ret, + series = this.series, + pointArrayMap = series.pointArrayMap || ['y'], + valueCount = pointArrayMap.length, + firstItemType, + i = 0, + j = 0; + + if (typeof options === 'number' || options === null) { + ret = { y: options }; + + } else if (isArray(options)) { + ret = {}; + // with leading x value + if (options.length > valueCount) { + firstItemType = typeof options[0]; + if (firstItemType === 'string') { + ret.name = options[0]; + } else if (firstItemType === 'number') { + ret.x = options[0]; + } + i++; + } + while (j < valueCount) { + ret[pointArrayMap[j++]] = options[i++]; + } + } else if (typeof options === 'object') { + ret = options; + + // This is the fastest way to detect if there are individual point dataLabels that need + // to be considered in drawDataLabels. These can only occur in object configs. + if (options.dataLabels) { + series._hasPointLabels = true; + } + + // Same approach as above for markers + if (options.marker) { + series._hasPointMarkers = true; + } + } + return ret; + }, + + /** + * Destroy a point to clear memory. Its reference still stays in series.data. + */ + destroy: function () { + var point = this, + series = point.series, + chart = series.chart, + hoverPoints = chart.hoverPoints, + prop; + + chart.pointCount--; + + if (hoverPoints) { + point.setState(); + erase(hoverPoints, point); + if (!hoverPoints.length) { + chart.hoverPoints = null; + } + + } + if (point === chart.hoverPoint) { + point.onMouseOut(); + } + + // remove all events + if (point.graphic || point.dataLabel) { // removeEvent and destroyElements are performance expensive + removeEvent(point); + point.destroyElements(); + } + + if (point.legendItem) { // pies have legend items + chart.legend.destroyItem(point); + } + + for (prop in point) { + point[prop] = null; + } + + + }, + + /** + * Destroy SVG elements associated with the point + */ + destroyElements: function () { + var point = this, + props = ['graphic', 'dataLabel', 'dataLabelUpper', 'group', 'connector', 'shadowGroup'], + prop, + i = 6; + while (i--) { + prop = props[i]; + if (point[prop]) { + point[prop] = point[prop].destroy(); + } + } + }, + + /** + * Return the configuration hash needed for the data label and tooltip formatters + */ + getLabelConfig: function () { + var point = this; + return { + x: point.category, + y: point.y, + key: point.name || point.category, + series: point.series, + point: point, + percentage: point.percentage, + total: point.total || point.stackTotal + }; + }, + + /** + * Toggle the selection status of a point + * @param {Boolean} selected Whether to select or unselect the point. + * @param {Boolean} accumulate Whether to add to the previous selection. By default, + * this happens if the control key (Cmd on Mac) was pressed during clicking. + */ + select: function (selected, accumulate) { + var point = this, + series = point.series, + chart = series.chart; + + selected = pick(selected, !point.selected); + + // fire the event with the defalut handler + point.firePointEvent(selected ? 'select' : 'unselect', { accumulate: accumulate }, function () { + point.selected = point.options.selected = selected; + series.options.data[inArray(point, series.data)] = point.options; + + point.setState(selected && SELECT_STATE); + + // unselect all other points unless Ctrl or Cmd + click + if (!accumulate) { + each(chart.getSelectedPoints(), function (loopPoint) { + if (loopPoint.selected && loopPoint !== point) { + loopPoint.selected = loopPoint.options.selected = false; + series.options.data[inArray(loopPoint, series.data)] = loopPoint.options; + loopPoint.setState(NORMAL_STATE); + loopPoint.firePointEvent('unselect'); + } + }); + } + }); + }, + + /** + * Runs on mouse over the point + */ + onMouseOver: function (e) { + var point = this, + series = point.series, + chart = series.chart, + tooltip = chart.tooltip, + hoverPoint = chart.hoverPoint; + + // set normal state to previous series + if (hoverPoint && hoverPoint !== point) { + hoverPoint.onMouseOut(); + } + + // trigger the event + point.firePointEvent('mouseOver'); + + // update the tooltip + if (tooltip && (!tooltip.shared || series.noSharedTooltip)) { + tooltip.refresh(point, e); + } + + // hover this + point.setState(HOVER_STATE); + chart.hoverPoint = point; + }, + + /** + * Runs on mouse out from the point + */ + onMouseOut: function () { + var chart = this.series.chart, + hoverPoints = chart.hoverPoints; + + if (!hoverPoints || inArray(this, hoverPoints) === -1) { // #887 + this.firePointEvent('mouseOut'); + + this.setState(); + chart.hoverPoint = null; + } + }, + + /** + * Extendable method for formatting each point's tooltip line + * + * @return {String} A string to be concatenated in to the common tooltip text + */ + tooltipFormatter: function (pointFormat) { + + // Insert options for valueDecimals, valuePrefix, and valueSuffix + var series = this.series, + seriesTooltipOptions = series.tooltipOptions, + valueDecimals = pick(seriesTooltipOptions.valueDecimals, ''), + valuePrefix = seriesTooltipOptions.valuePrefix || '', + valueSuffix = seriesTooltipOptions.valueSuffix || ''; + + // Loop over the point array map and replace unformatted values with sprintf formatting markup + each(series.pointArrayMap || ['y'], function (key) { + key = '{point.' + key; // without the closing bracket + if (valuePrefix || valueSuffix) { + pointFormat = pointFormat.replace(key + '}', valuePrefix + key + '}' + valueSuffix); + } + pointFormat = pointFormat.replace(key + '}', key + ':,.' + valueDecimals + 'f}'); + }); + + return format(pointFormat, { + point: this, + series: this.series + }); + }, + + /** + * Update the point with new options (typically x/y data) and optionally redraw the series. + * + * @param {Object} options Point options as defined in the series.data array + * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call + * @param {Boolean|Object} animation Whether to apply animation, and optionally animation + * configuration + * + */ + update: function (options, redraw, animation) { + var point = this, + series = point.series, + graphic = point.graphic, + i, + data = series.data, + chart = series.chart, + seriesOptions = series.options; + + redraw = pick(redraw, true); + + // fire the event with a default handler of doing the update + point.firePointEvent('update', { options: options }, function () { + + point.applyOptions(options); + + // update visuals + if (isObject(options)) { + series.getAttribs(); + if (graphic) { + if (options.marker && options.marker.symbol) { + point.graphic = graphic.destroy(); + } else { + graphic.attr(point.pointAttr[point.state || '']); + } + } + } + + // record changes in the parallel arrays + i = inArray(point, data); + series.xData[i] = point.x; + series.yData[i] = series.toYData ? series.toYData(point) : point.y; + series.zData[i] = point.z; + seriesOptions.data[i] = point.options; + + // redraw + series.isDirty = series.isDirtyData = true; + if (!series.fixedBox && series.hasCartesianSeries) { // #1906, #2320 + chart.isDirtyBox = true; + } + + if (seriesOptions.legendType === 'point') { // #1831, #1885 + chart.legend.destroyItem(point); + } + if (redraw) { + chart.redraw(animation); + } + }); + }, + + /** + * Remove a point and optionally redraw the series and if necessary the axes + * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call + * @param {Boolean|Object} animation Whether to apply animation, and optionally animation + * configuration + */ + remove: function (redraw, animation) { + var point = this, + series = point.series, + points = series.points, + chart = series.chart, + i, + data = series.data; + + setAnimation(animation, chart); + redraw = pick(redraw, true); + + // fire the event with a default handler of removing the point + point.firePointEvent('remove', null, function () { + + // splice all the parallel arrays + i = inArray(point, data); + if (data.length === points.length) { + points.splice(i, 1); + } + data.splice(i, 1); + series.options.data.splice(i, 1); + series.xData.splice(i, 1); + series.yData.splice(i, 1); + series.zData.splice(i, 1); + + point.destroy(); + + + // redraw + series.isDirty = true; + series.isDirtyData = true; + if (redraw) { + chart.redraw(); + } + }); + + + }, + + /** + * Fire an event on the Point object. Must not be renamed to fireEvent, as this + * causes a name clash in MooTools + * @param {String} eventType + * @param {Object} eventArgs Additional event arguments + * @param {Function} defaultFunction Default event handler + */ + firePointEvent: function (eventType, eventArgs, defaultFunction) { + var point = this, + series = this.series, + seriesOptions = series.options; + + // load event handlers on demand to save time on mouseover/out + if (seriesOptions.point.events[eventType] || (point.options && point.options.events && point.options.events[eventType])) { + this.importEvents(); + } + + // add default handler if in selection mode + if (eventType === 'click' && seriesOptions.allowPointSelect) { + defaultFunction = function (event) { + // Control key is for Windows, meta (= Cmd key) for Mac, Shift for Opera + point.select(null, event.ctrlKey || event.metaKey || event.shiftKey); + }; + } + + fireEvent(this, eventType, eventArgs, defaultFunction); + }, + /** + * Import events from the series' and point's options. Only do it on + * demand, to save processing time on hovering. + */ + importEvents: function () { + if (!this.hasImportedEvents) { + var point = this, + options = merge(point.series.options.point, point.options), + events = options.events, + eventType; + + point.events = events; + + for (eventType in events) { + addEvent(point, eventType, events[eventType]); + } + this.hasImportedEvents = true; + + } + }, + + /** + * Set the point's state + * @param {String} state + */ + setState: function (state) { + var point = this, + plotX = point.plotX, + plotY = point.plotY, + series = point.series, + stateOptions = series.options.states, + markerOptions = defaultPlotOptions[series.type].marker && series.options.marker, + normalDisabled = markerOptions && !markerOptions.enabled, + markerStateOptions = markerOptions && markerOptions.states[state], + stateDisabled = markerStateOptions && markerStateOptions.enabled === false, + stateMarkerGraphic = series.stateMarkerGraphic, + pointMarker = point.marker || {}, + chart = series.chart, + radius, + newSymbol, + pointAttr = point.pointAttr; + + state = state || NORMAL_STATE; // empty string + + if ( + // already has this state + state === point.state || + // selected points don't respond to hover + (point.selected && state !== SELECT_STATE) || + // series' state options is disabled + (stateOptions[state] && stateOptions[state].enabled === false) || + // point marker's state options is disabled + (state && (stateDisabled || (normalDisabled && !markerStateOptions.enabled))) + + ) { + return; + } + + // apply hover styles to the existing point + if (point.graphic) { + radius = markerOptions && point.graphic.symbolName && pointAttr[state].r; + point.graphic.attr(merge( + pointAttr[state], + radius ? { // new symbol attributes (#507, #612) + x: plotX - radius, + y: plotY - radius, + width: 2 * radius, + height: 2 * radius + } : {} + )); + } else { + // if a graphic is not applied to each point in the normal state, create a shared + // graphic for the hover state + if (state && markerStateOptions) { + radius = markerStateOptions.radius; + newSymbol = pointMarker.symbol || series.symbol; + + // If the point has another symbol than the previous one, throw away the + // state marker graphic and force a new one (#1459) + if (stateMarkerGraphic && stateMarkerGraphic.currentSymbol !== newSymbol) { + stateMarkerGraphic = stateMarkerGraphic.destroy(); + } + + // Add a new state marker graphic + if (!stateMarkerGraphic) { + series.stateMarkerGraphic = stateMarkerGraphic = chart.renderer.symbol( + newSymbol, + plotX - radius, + plotY - radius, + 2 * radius, + 2 * radius + ) + .attr(pointAttr[state]) + .add(series.markerGroup); + stateMarkerGraphic.currentSymbol = newSymbol; + + // Move the existing graphic + } else { + stateMarkerGraphic.attr({ // #1054 + x: plotX - radius, + y: plotY - radius + }); + } + } + + if (stateMarkerGraphic) { + stateMarkerGraphic[state && chart.isInsidePlot(plotX, plotY) ? 'show' : 'hide'](); + } + } + + point.state = state; + } +}; + +/** + * @classDescription The base function which all other series types inherit from. The data in the series is stored + * in various arrays. + * + * - First, series.options.data contains all the original config options for + * each point whether added by options or methods like series.addPoint. + * - Next, series.data contains those values converted to points, but in case the series data length + * exceeds the cropThreshold, or if the data is grouped, series.data doesn't contain all the points. It + * only contains the points that have been created on demand. + * - Then there's series.points that contains all currently visible point objects. In case of cropping, + * the cropped-away points are not part of this array. The series.points array starts at series.cropStart + * compared to series.data and series.options.data. If however the series data is grouped, these can't + * be correlated one to one. + * - series.xData and series.processedXData contain clean x values, equivalent to series.data and series.points. + * - series.yData and series.processedYData contain clean x values, equivalent to series.data and series.points. + * + * @param {Object} chart + * @param {Object} options + */ +var Series = function () {}; + +Series.prototype = { + + isCartesian: true, + type: 'line', + pointClass: Point, + sorted: true, // requires the data to be sorted + requireSorting: true, + pointAttrToOptions: { // mapping between SVG attributes and the corresponding options + stroke: 'lineColor', + 'stroke-width': 'lineWidth', + fill: 'fillColor', + r: 'radius' + }, + colorCounter: 0, + init: function (chart, options) { + var series = this, + eventType, + events, + chartSeries = chart.series; + + series.chart = chart; + series.options = options = series.setOptions(options); // merge with plotOptions + series.linkedSeries = []; + + // bind the axes + series.bindAxes(); + + // set some variables + extend(series, { + name: options.name, + state: NORMAL_STATE, + pointAttr: {}, + visible: options.visible !== false, // true by default + selected: options.selected === true // false by default + }); + + // special + if (useCanVG) { + options.animation = false; + } + + // register event listeners + events = options.events; + for (eventType in events) { + addEvent(series, eventType, events[eventType]); + } + if ( + (events && events.click) || + (options.point && options.point.events && options.point.events.click) || + options.allowPointSelect + ) { + chart.runTrackerClick = true; + } + + series.getColor(); + series.getSymbol(); + + // set the data + series.setData(options.data, false); + + // Mark cartesian + if (series.isCartesian) { + chart.hasCartesianSeries = true; + } + + // Register it in the chart + chartSeries.push(series); + series._i = chartSeries.length - 1; + + // Sort series according to index option (#248, #1123) + stableSort(chartSeries, function (a, b) { + return pick(a.options.index, a._i) - pick(b.options.index, a._i); + }); + each(chartSeries, function (series, i) { + series.index = i; + series.name = series.name || 'Series ' + (i + 1); + }); + + }, + + /** + * Set the xAxis and yAxis properties of cartesian series, and register the series + * in the axis.series array + */ + bindAxes: function () { + var series = this, + seriesOptions = series.options, + chart = series.chart, + axisOptions; + + if (series.isCartesian) { + + each(['xAxis', 'yAxis'], function (AXIS) { // repeat for xAxis and yAxis + + each(chart[AXIS], function (axis) { // loop through the chart's axis objects + + axisOptions = axis.options; + + // apply if the series xAxis or yAxis option mathches the number of the + // axis, or if undefined, use the first axis + if ((seriesOptions[AXIS] === axisOptions.index) || + (seriesOptions[AXIS] !== UNDEFINED && seriesOptions[AXIS] === axisOptions.id) || + (seriesOptions[AXIS] === UNDEFINED && axisOptions.index === 0)) { + + // register this series in the axis.series lookup + axis.series.push(series); + + // set this series.xAxis or series.yAxis reference + series[AXIS] = axis; + + // mark dirty for redraw + axis.isDirty = true; + } + }); + + // The series needs an X and an Y axis + if (!series[AXIS]) { + error(18, true); + } + + }); + } + }, + + + /** + * Return an auto incremented x value based on the pointStart and pointInterval options. + * This is only used if an x value is not given for the point that calls autoIncrement. + */ + autoIncrement: function () { + var series = this, + options = series.options, + xIncrement = series.xIncrement; + + xIncrement = pick(xIncrement, options.pointStart, 0); + + series.pointInterval = pick(series.pointInterval, options.pointInterval, 1); + + series.xIncrement = xIncrement + series.pointInterval; + return xIncrement; + }, + + /** + * Divide the series data into segments divided by null values. + */ + getSegments: function () { + var series = this, + lastNull = -1, + segments = [], + i, + points = series.points, + pointsLength = points.length; + + if (pointsLength) { // no action required for [] + + // if connect nulls, just remove null points + if (series.options.connectNulls) { + i = pointsLength; + while (i--) { + if (points[i].y === null) { + points.splice(i, 1); + } + } + if (points.length) { + segments = [points]; + } + + // else, split on null points + } else { + each(points, function (point, i) { + if (point.y === null) { + if (i > lastNull + 1) { + segments.push(points.slice(lastNull + 1, i)); + } + lastNull = i; + } else if (i === pointsLength - 1) { // last value + segments.push(points.slice(lastNull + 1, i + 1)); + } + }); + } + } + + // register it + series.segments = segments; + }, + + /** + * Set the series options by merging from the options tree + * @param {Object} itemOptions + */ + setOptions: function (itemOptions) { + var chart = this.chart, + chartOptions = chart.options, + plotOptions = chartOptions.plotOptions, + typeOptions = plotOptions[this.type], + options; + + this.userOptions = itemOptions; + + options = merge( + typeOptions, + plotOptions.series, + itemOptions + ); + + // the tooltip options are merged between global and series specific options + this.tooltipOptions = merge(chartOptions.tooltip, options.tooltip); + + // Delte marker object if not allowed (#1125) + if (typeOptions.marker === null) { + delete options.marker; + } + + return options; + + }, + /** + * Get the series' color + */ + getColor: function () { + var options = this.options, + userOptions = this.userOptions, + defaultColors = this.chart.options.colors, + counters = this.chart.counters, + color, + colorIndex; + + color = options.color || defaultPlotOptions[this.type].color; + + if (!color && !options.colorByPoint) { + if (defined(userOptions._colorIndex)) { // after Series.update() + colorIndex = userOptions._colorIndex; + } else { + userOptions._colorIndex = counters.color; + colorIndex = counters.color++; + } + color = defaultColors[colorIndex]; + } + + this.color = color; + counters.wrapColor(defaultColors.length); + }, + /** + * Get the series' symbol + */ + getSymbol: function () { + var series = this, + userOptions = series.userOptions, + seriesMarkerOption = series.options.marker, + chart = series.chart, + defaultSymbols = chart.options.symbols, + counters = chart.counters, + symbolIndex; + + series.symbol = seriesMarkerOption.symbol; + if (!series.symbol) { + if (defined(userOptions._symbolIndex)) { // after Series.update() + symbolIndex = userOptions._symbolIndex; + } else { + userOptions._symbolIndex = counters.symbol; + symbolIndex = counters.symbol++; + } + series.symbol = defaultSymbols[symbolIndex]; + } + + // don't substract radius in image symbols (#604) + if (/^url/.test(series.symbol)) { + seriesMarkerOption.radius = 0; + } + counters.wrapSymbol(defaultSymbols.length); + }, + + /** + * Get the series' symbol in the legend. This method should be overridable to create custom + * symbols through Highcharts.seriesTypes[type].prototype.drawLegendSymbols. + * + * @param {Object} legend The legend object + */ + drawLegendSymbol: function (legend) { + + var options = this.options, + markerOptions = options.marker, + radius, + legendOptions = legend.options, + legendSymbol, + symbolWidth = legendOptions.symbolWidth, + renderer = this.chart.renderer, + legendItemGroup = this.legendGroup, + verticalCenter = legend.baseline - mathRound(renderer.fontMetrics(legendOptions.itemStyle.fontSize).b * 0.3), + attr; + + // Draw the line + if (options.lineWidth) { + attr = { + 'stroke-width': options.lineWidth + }; + if (options.dashStyle) { + attr.dashstyle = options.dashStyle; + } + this.legendLine = renderer.path([ + M, + 0, + verticalCenter, + L, + symbolWidth, + verticalCenter + ]) + .attr(attr) + .add(legendItemGroup); + } + + // Draw the marker + if (markerOptions && markerOptions.enabled) { + radius = markerOptions.radius; + this.legendSymbol = legendSymbol = renderer.symbol( + this.symbol, + (symbolWidth / 2) - radius, + verticalCenter - radius, + 2 * radius, + 2 * radius + ) + .add(legendItemGroup); + legendSymbol.isMarker = true; + } + }, + + /** + * Add a point dynamically after chart load time + * @param {Object} options Point options as given in series.data + * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call + * @param {Boolean} shift If shift is true, a point is shifted off the start + * of the series as one is appended to the end. + * @param {Boolean|Object} animation Whether to apply animation, and optionally animation + * configuration + */ + addPoint: function (options, redraw, shift, animation) { + var series = this, + seriesOptions = series.options, + data = series.data, + graph = series.graph, + area = series.area, + chart = series.chart, + xData = series.xData, + yData = series.yData, + zData = series.zData, + names = series.names, + currentShift = (graph && graph.shift) || 0, + dataOptions = seriesOptions.data, + point, + isInTheMiddle, + x, + i; + + setAnimation(animation, chart); + + // Make graph animate sideways + if (shift) { + each([graph, area, series.graphNeg, series.areaNeg], function (shape) { + if (shape) { + shape.shift = currentShift + 1; + } + }); + } + if (area) { + area.isArea = true; // needed in animation, both with and without shift + } + + // Optional redraw, defaults to true + redraw = pick(redraw, true); + + // Get options and push the point to xData, yData and series.options. In series.generatePoints + // the Point instance will be created on demand and pushed to the series.data array. + point = { series: series }; + series.pointClass.prototype.applyOptions.apply(point, [options]); + x = point.x; + + // Get the insertion point + i = xData.length; + if (series.requireSorting && x < xData[i - 1]) { + isInTheMiddle = true; + while (i && xData[i - 1] > x) { + i--; + } + } + + xData.splice(i, 0, x); + yData.splice(i, 0, series.toYData ? series.toYData(point) : point.y); + zData.splice(i, 0, point.z); + if (names) { + names[x] = point.name; + } + dataOptions.splice(i, 0, options); + + if (isInTheMiddle) { + series.data.splice(i, 0, null); + series.processData(); + } + + // Generate points to be added to the legend (#1329) + if (seriesOptions.legendType === 'point') { + series.generatePoints(); + } + + // Shift the first point off the parallel arrays + // todo: consider series.removePoint(i) method + if (shift) { + if (data[0] && data[0].remove) { + data[0].remove(false); + } else { + data.shift(); + xData.shift(); + yData.shift(); + zData.shift(); + dataOptions.shift(); + } + } + + // redraw + series.isDirty = true; + series.isDirtyData = true; + if (redraw) { + series.getAttribs(); // #1937 + chart.redraw(); + } + }, + + /** + * Replace the series data with a new set of data + * @param {Object} data + * @param {Object} redraw + */ + setData: function (data, redraw) { + var series = this, + oldData = series.points, + options = series.options, + chart = series.chart, + firstPoint = null, + xAxis = series.xAxis, + names = xAxis && xAxis.categories && !xAxis.categories.length ? [] : null, + i; + + // reset properties + series.xIncrement = null; + series.pointRange = xAxis && xAxis.categories ? 1 : options.pointRange; + + series.colorCounter = 0; // for series with colorByPoint (#1547) + + // parallel arrays + var xData = [], + yData = [], + zData = [], + dataLength = data ? data.length : [], + turboThreshold = pick(options.turboThreshold, 1000), + pt, + pointArrayMap = series.pointArrayMap, + valueCount = pointArrayMap && pointArrayMap.length, + hasToYData = !!series.toYData; + + // In turbo mode, only one- or twodimensional arrays of numbers are allowed. The + // first value is tested, and we assume that all the rest are defined the same + // way. Although the 'for' loops are similar, they are repeated inside each + // if-else conditional for max performance. + if (turboThreshold && dataLength > turboThreshold) { + + // find the first non-null point + i = 0; + while (firstPoint === null && i < dataLength) { + firstPoint = data[i]; + i++; + } + + + if (isNumber(firstPoint)) { // assume all points are numbers + var x = pick(options.pointStart, 0), + pointInterval = pick(options.pointInterval, 1); + + for (i = 0; i < dataLength; i++) { + xData[i] = x; + yData[i] = data[i]; + x += pointInterval; + } + series.xIncrement = x; + } else if (isArray(firstPoint)) { // assume all points are arrays + if (valueCount) { // [x, low, high] or [x, o, h, l, c] + for (i = 0; i < dataLength; i++) { + pt = data[i]; + xData[i] = pt[0]; + yData[i] = pt.slice(1, valueCount + 1); + } + } else { // [x, y] + for (i = 0; i < dataLength; i++) { + pt = data[i]; + xData[i] = pt[0]; + yData[i] = pt[1]; + } + } + } else { + error(12); // Highcharts expects configs to be numbers or arrays in turbo mode + } + } else { + for (i = 0; i < dataLength; i++) { + if (data[i] !== UNDEFINED) { // stray commas in oldIE + pt = { series: series }; + series.pointClass.prototype.applyOptions.apply(pt, [data[i]]); + xData[i] = pt.x; + yData[i] = hasToYData ? series.toYData(pt) : pt.y; + zData[i] = pt.z; + if (names && pt.name) { + names[pt.x] = pt.name; // #2046 + } + } + } + } + + // Forgetting to cast strings to numbers is a common caveat when handling CSV or JSON + if (isString(yData[0])) { + error(14, true); + } + + series.data = []; + series.options.data = data; + series.xData = xData; + series.yData = yData; + series.zData = zData; + series.names = names; + + // destroy old points + i = (oldData && oldData.length) || 0; + while (i--) { + if (oldData[i] && oldData[i].destroy) { + oldData[i].destroy(); + } + } + + // reset minRange (#878) + if (xAxis) { + xAxis.minRange = xAxis.userMinRange; + } + + // redraw + series.isDirty = series.isDirtyData = chart.isDirtyBox = true; + if (pick(redraw, true)) { + chart.redraw(false); + } + }, + + /** + * Remove a series and optionally redraw the chart + * + * @param {Boolean} redraw Whether to redraw the chart or wait for an explicit call + * @param {Boolean|Object} animation Whether to apply animation, and optionally animation + * configuration + */ + + remove: function (redraw, animation) { + var series = this, + chart = series.chart; + redraw = pick(redraw, true); + + if (!series.isRemoving) { /* prevent triggering native event in jQuery + (calling the remove function from the remove event) */ + series.isRemoving = true; + + // fire the event with a default handler of removing the point + fireEvent(series, 'remove', null, function () { + + + // destroy elements + series.destroy(); + + + // redraw + chart.isDirtyLegend = chart.isDirtyBox = true; + chart.linkSeries(); + + if (redraw) { + chart.redraw(animation); + } + }); + + } + series.isRemoving = false; + }, + + /** + * Process the data by cropping away unused data points if the series is longer + * than the crop threshold. This saves computing time for lage series. + */ + processData: function (force) { + var series = this, + processedXData = series.xData, // copied during slice operation below + processedYData = series.yData, + dataLength = processedXData.length, + croppedData, + cropStart = 0, + cropped, + distance, + closestPointRange, + xAxis = series.xAxis, + i, // loop variable + options = series.options, + cropThreshold = options.cropThreshold, + isCartesian = series.isCartesian; + + // If the series data or axes haven't changed, don't go through this. Return false to pass + // the message on to override methods like in data grouping. + if (isCartesian && !series.isDirty && !xAxis.isDirty && !series.yAxis.isDirty && !force) { + return false; + } + + + // optionally filter out points outside the plot area + if (isCartesian && series.sorted && (!cropThreshold || dataLength > cropThreshold || series.forceCrop)) { + var min = xAxis.min, + max = xAxis.max; + + // it's outside current extremes + if (processedXData[dataLength - 1] < min || processedXData[0] > max) { + processedXData = []; + processedYData = []; + + // only crop if it's actually spilling out + } else if (processedXData[0] < min || processedXData[dataLength - 1] > max) { + croppedData = this.cropData(series.xData, series.yData, min, max); + processedXData = croppedData.xData; + processedYData = croppedData.yData; + cropStart = croppedData.start; + cropped = true; + } + } + + + // Find the closest distance between processed points + for (i = processedXData.length - 1; i >= 0; i--) { + distance = processedXData[i] - processedXData[i - 1]; + if (distance > 0 && (closestPointRange === UNDEFINED || distance < closestPointRange)) { + closestPointRange = distance; + + // Unsorted data is not supported by the line tooltip, as well as data grouping and + // navigation in Stock charts (#725) and width calculation of columns (#1900) + } else if (distance < 0 && series.requireSorting) { + error(15); + } + } + + // Record the properties + series.cropped = cropped; // undefined or true + series.cropStart = cropStart; + series.processedXData = processedXData; + series.processedYData = processedYData; + + if (options.pointRange === null) { // null means auto, as for columns, candlesticks and OHLC + series.pointRange = closestPointRange || 1; + } + series.closestPointRange = closestPointRange; + + }, + + /** + * Iterate over xData and crop values between min and max. Returns object containing crop start/end + * cropped xData with corresponding part of yData, dataMin and dataMax within the cropped range + */ + cropData: function (xData, yData, min, max) { + var dataLength = xData.length, + cropStart = 0, + cropEnd = dataLength, + cropShoulder = pick(this.cropShoulder, 1), // line-type series need one point outside + i; + + // iterate up to find slice start + for (i = 0; i < dataLength; i++) { + if (xData[i] >= min) { + cropStart = mathMax(0, i - cropShoulder); + break; + } + } + + // proceed to find slice end + for (; i < dataLength; i++) { + if (xData[i] > max) { + cropEnd = i + cropShoulder; + break; + } + } + + return { + xData: xData.slice(cropStart, cropEnd), + yData: yData.slice(cropStart, cropEnd), + start: cropStart, + end: cropEnd + }; + }, + + + /** + * Generate the data point after the data has been processed by cropping away + * unused points and optionally grouped in Highcharts Stock. + */ + generatePoints: function () { + var series = this, + options = series.options, + dataOptions = options.data, + data = series.data, + dataLength, + processedXData = series.processedXData, + processedYData = series.processedYData, + pointClass = series.pointClass, + processedDataLength = processedXData.length, + cropStart = series.cropStart || 0, + cursor, + hasGroupedData = series.hasGroupedData, + point, + points = [], + i; + + if (!data && !hasGroupedData) { + var arr = []; + arr.length = dataOptions.length; + data = series.data = arr; + } + + for (i = 0; i < processedDataLength; i++) { + cursor = cropStart + i; + if (!hasGroupedData) { + if (data[cursor]) { + point = data[cursor]; + } else if (dataOptions[cursor] !== UNDEFINED) { // #970 + data[cursor] = point = (new pointClass()).init(series, dataOptions[cursor], processedXData[i]); + } + points[i] = point; + } else { + // splat the y data in case of ohlc data array + points[i] = (new pointClass()).init(series, [processedXData[i]].concat(splat(processedYData[i]))); + } + } + + // Hide cropped-away points - this only runs when the number of points is above cropThreshold, or when + // swithching view from non-grouped data to grouped data (#637) + if (data && (processedDataLength !== (dataLength = data.length) || hasGroupedData)) { + for (i = 0; i < dataLength; i++) { + if (i === cropStart && !hasGroupedData) { // when has grouped data, clear all points + i += processedDataLength; + } + if (data[i]) { + data[i].destroyElements(); + data[i].plotX = UNDEFINED; // #1003 + } + } + } + + series.data = data; + series.points = points; + }, + + /** + * Adds series' points value to corresponding stack + */ + setStackedPoints: function () { + if (!this.options.stacking || (this.visible !== true && this.chart.options.chart.ignoreHiddenSeries !== false)) { + return; + } + + var series = this, + xData = series.processedXData, + yData = series.processedYData, + stackedYData = [], + yDataLength = yData.length, + seriesOptions = series.options, + threshold = seriesOptions.threshold, + stackOption = seriesOptions.stack, + stacking = seriesOptions.stacking, + stackKey = series.stackKey, + negKey = '-' + stackKey, + negStacks = series.negStacks, + yAxis = series.yAxis, + stacks = yAxis.stacks, + oldStacks = yAxis.oldStacks, + isNegative, + stack, + other, + key, + i, + x, + y; + + // loop over the non-null y values and read them into a local array + for (i = 0; i < yDataLength; i++) { + x = xData[i]; + y = yData[i]; + + // Read stacked values into a stack based on the x value, + // the sign of y and the stack key. Stacking is also handled for null values (#739) + isNegative = negStacks && y < threshold; + key = isNegative ? negKey : stackKey; + + // Create empty object for this stack if it doesn't exist yet + if (!stacks[key]) { + stacks[key] = {}; + } + + // Initialize StackItem for this x + if (!stacks[key][x]) { + if (oldStacks[key] && oldStacks[key][x]) { + stacks[key][x] = oldStacks[key][x]; + stacks[key][x].total = null; + } else { + stacks[key][x] = new StackItem(yAxis, yAxis.options.stackLabels, isNegative, x, stackOption, stacking); + } + } + + // If the StackItem doesn't exist, create it first + stack = stacks[key][x]; + stack.points[series.index] = [stack.cum || 0]; + + // Add value to the stack total + if (stacking === 'percent') { + + // Percent stacked column, totals are the same for the positive and negative stacks + other = isNegative ? stackKey : negKey; + if (negStacks && stacks[other] && stacks[other][x]) { + other = stacks[other][x]; + stack.total = other.total = mathMax(other.total, stack.total) + mathAbs(y) || 0; + + // Percent stacked areas + } else { + stack.total += mathAbs(y) || 0; + } + } else { + stack.total += y || 0; + } + + stack.cum = (stack.cum || 0) + (y || 0); + + stack.points[series.index].push(stack.cum); + stackedYData[i] = stack.cum; + + } + + if (stacking === 'percent') { + yAxis.usePercentage = true; + } + + this.stackedYData = stackedYData; // To be used in getExtremes + + // Reset old stacks + yAxis.oldStacks = {}; + }, + + /** + * Iterate over all stacks and compute the absolute values to percent + */ + setPercentStacks: function () { + var series = this, + stackKey = series.stackKey, + stacks = series.yAxis.stacks; + + each([stackKey, '-' + stackKey], function (key) { + var i = series.xData.length, + x, + stack, + pointExtremes, + totalFactor; + + while (i--) { + x = series.xData[i]; + stack = stacks[key] && stacks[key][x]; + pointExtremes = stack && stack.points[series.index]; + if (pointExtremes) { + totalFactor = stack.total ? 100 / stack.total : 0; + pointExtremes[0] = correctFloat(pointExtremes[0] * totalFactor); // Y bottom value + pointExtremes[1] = correctFloat(pointExtremes[1] * totalFactor); // Y value + series.stackedYData[i] = pointExtremes[1]; + } + } + }); + }, + + /** + * Calculate Y extremes for visible data + */ + getExtremes: function () { + var xAxis = this.xAxis, + yAxis = this.yAxis, + xData = this.processedXData, + yData = this.stackedYData || this.processedYData, + yDataLength = yData.length, + activeYData = [], + activeCounter = 0, + xExtremes = xAxis.getExtremes(), // #2117, need to compensate for log X axis + xMin = xExtremes.min, + xMax = xExtremes.max, + validValue, + withinRange, + dataMin, + dataMax, + x, + y, + i, + j; + + for (i = 0; i < yDataLength; i++) { + + x = xData[i]; + y = yData[i]; + + // For points within the visible range, including the first point outside the + // visible range, consider y extremes + validValue = y !== null && y !== UNDEFINED && (!yAxis.isLog || (y.length || y > 0)); + withinRange = this.getExtremesFromAll || this.cropped || ((xData[i + 1] || x) >= xMin && + (xData[i - 1] || x) <= xMax); + + if (validValue && withinRange) { + + j = y.length; + if (j) { // array, like ohlc or range data + while (j--) { + if (y[j] !== null) { + activeYData[activeCounter++] = y[j]; + } + } + } else { + activeYData[activeCounter++] = y; + } + } + } + this.dataMin = pick(dataMin, arrayMin(activeYData)); + this.dataMax = pick(dataMax, arrayMax(activeYData)); + }, + + /** + * Translate data points from raw data values to chart specific positioning data + * needed later in drawPoints, drawGraph and drawTracker. + */ + translate: function () { + if (!this.processedXData) { // hidden series + this.processData(); + } + this.generatePoints(); + var series = this, + options = series.options, + stacking = options.stacking, + xAxis = series.xAxis, + categories = xAxis.categories, + yAxis = series.yAxis, + points = series.points, + dataLength = points.length, + hasModifyValue = !!series.modifyValue, + i, + pointPlacement = options.pointPlacement, + dynamicallyPlaced = pointPlacement === 'between' || isNumber(pointPlacement), + threshold = options.threshold; + + + // Translate each point + for (i = 0; i < dataLength; i++) { + var point = points[i], + xValue = point.x, + yValue = point.y, + yBottom = point.low, + stack = yAxis.stacks[(series.negStacks && yValue < threshold ? '-' : '') + series.stackKey], + pointStack, + stackValues; + + // Discard disallowed y values for log axes + if (yAxis.isLog && yValue <= 0) { + point.y = yValue = null; + } + + // Get the plotX translation + point.plotX = xAxis.translate(xValue, 0, 0, 0, 1, pointPlacement, this.type === 'flags'); // Math.round fixes #591 + + + // Calculate the bottom y value for stacked series + if (stacking && series.visible && stack && stack[xValue]) { + + pointStack = stack[xValue]; + stackValues = pointStack.points[series.index]; + yBottom = stackValues[0]; + yValue = stackValues[1]; + + if (yBottom === 0) { + yBottom = pick(threshold, yAxis.min); + } + if (yAxis.isLog && yBottom <= 0) { // #1200, #1232 + yBottom = null; + } + + point.percentage = stacking === 'percent' && yValue; + point.total = point.stackTotal = pointStack.total; + point.stackY = yValue; + + // Place the stack label + pointStack.setOffset(series.pointXOffset || 0, series.barW || 0); + + } + + // Set translated yBottom or remove it + point.yBottom = defined(yBottom) ? + yAxis.translate(yBottom, 0, 1, 0, 1) : + null; + + // general hook, used for Highstock compare mode + if (hasModifyValue) { + yValue = series.modifyValue(yValue, point); + } + + // Set the the plotY value, reset it for redraws + point.plotY = (typeof yValue === 'number' && yValue !== Infinity) ? + //mathRound(yAxis.translate(yValue, 0, 1, 0, 1) * 10) / 10 : // Math.round fixes #591 + yAxis.translate(yValue, 0, 1, 0, 1) : + UNDEFINED; + + // Set client related positions for mouse tracking + point.clientX = dynamicallyPlaced ? xAxis.translate(xValue, 0, 0, 0, 1) : point.plotX; // #1514 + + point.negative = point.y < (threshold || 0); + + // some API data + point.category = categories && categories[point.x] !== UNDEFINED ? + categories[point.x] : point.x; + + + } + + // now that we have the cropped data, build the segments + series.getSegments(); + }, + /** + * Memoize tooltip texts and positions + */ + setTooltipPoints: function (renew) { + var series = this, + points = [], + pointsLength, + low, + high, + xAxis = series.xAxis, + xExtremes = xAxis && xAxis.getExtremes(), + axisLength = xAxis ? (xAxis.tooltipLen || xAxis.len) : series.chart.plotSizeX, // tooltipLen and tooltipPosName used in polar + point, + pointX, + nextPoint, + i, + tooltipPoints = []; // a lookup array for each pixel in the x dimension + + // don't waste resources if tracker is disabled + if (series.options.enableMouseTracking === false) { + return; + } + + // renew + if (renew) { + series.tooltipPoints = null; + } + + // concat segments to overcome null values + each(series.segments || series.points, function (segment) { + points = points.concat(segment); + }); + + // Reverse the points in case the X axis is reversed + if (xAxis && xAxis.reversed) { + points = points.reverse(); + } + + // Polar needs additional shaping + if (series.orderTooltipPoints) { + series.orderTooltipPoints(points); + } + + // Assign each pixel position to the nearest point + pointsLength = points.length; + for (i = 0; i < pointsLength; i++) { + point = points[i]; + pointX = point.x; + if (pointX >= xExtremes.min && pointX <= xExtremes.max) { // #1149 + nextPoint = points[i + 1]; + + // Set this range's low to the last range's high plus one + low = high === UNDEFINED ? 0 : high + 1; + // Now find the new high + high = points[i + 1] ? + mathMin(mathMax(0, mathFloor( // #2070 + (point.clientX + (nextPoint ? (nextPoint.wrappedClientX || nextPoint.clientX) : axisLength)) / 2 + )), axisLength) : + axisLength; + + while (low >= 0 && low <= high) { + tooltipPoints[low++] = point; + } + } + } + series.tooltipPoints = tooltipPoints; + }, + + /** + * Format the header of the tooltip + */ + tooltipHeaderFormatter: function (point) { + var series = this, + tooltipOptions = series.tooltipOptions, + xDateFormat = tooltipOptions.xDateFormat, + dateTimeLabelFormats = tooltipOptions.dateTimeLabelFormats, + xAxis = series.xAxis, + isDateTime = xAxis && xAxis.options.type === 'datetime', + headerFormat = tooltipOptions.headerFormat, + closestPointRange = xAxis && xAxis.closestPointRange, + n; + + // Guess the best date format based on the closest point distance (#568) + if (isDateTime && !xDateFormat) { + if (closestPointRange) { + for (n in timeUnits) { + if (timeUnits[n] >= closestPointRange) { + xDateFormat = dateTimeLabelFormats[n]; + break; + } + } + } else { + xDateFormat = dateTimeLabelFormats.day; + } + } + + // Insert the header date format if any + if (isDateTime && xDateFormat && isNumber(point.key)) { + headerFormat = headerFormat.replace('{point.key}', '{point.key:' + xDateFormat + '}'); + } + + return format(headerFormat, { + point: point, + series: series + }); + }, + + /** + * Series mouse over handler + */ + onMouseOver: function () { + var series = this, + chart = series.chart, + hoverSeries = chart.hoverSeries; + + // set normal state to previous series + if (hoverSeries && hoverSeries !== series) { + hoverSeries.onMouseOut(); + } + + // trigger the event, but to save processing time, + // only if defined + if (series.options.events.mouseOver) { + fireEvent(series, 'mouseOver'); + } + + // hover this + series.setState(HOVER_STATE); + chart.hoverSeries = series; + }, + + /** + * Series mouse out handler + */ + onMouseOut: function () { + // trigger the event only if listeners exist + var series = this, + options = series.options, + chart = series.chart, + tooltip = chart.tooltip, + hoverPoint = chart.hoverPoint; + + // trigger mouse out on the point, which must be in this series + if (hoverPoint) { + hoverPoint.onMouseOut(); + } + + // fire the mouse out event + if (series && options.events.mouseOut) { + fireEvent(series, 'mouseOut'); + } + + + // hide the tooltip + if (tooltip && !options.stickyTracking && (!tooltip.shared || series.noSharedTooltip)) { + tooltip.hide(); + } + + // set normal state + series.setState(); + chart.hoverSeries = null; + }, + + /** + * Animate in the series + */ + animate: function (init) { + var series = this, + chart = series.chart, + renderer = chart.renderer, + clipRect, + markerClipRect, + animation = series.options.animation, + clipBox = chart.clipBox, + inverted = chart.inverted, + sharedClipKey; + + // Animation option is set to true + if (animation && !isObject(animation)) { + animation = defaultPlotOptions[series.type].animation; + } + sharedClipKey = '_sharedClip' + animation.duration + animation.easing; + + // Initialize the animation. Set up the clipping rectangle. + if (init) { + + // If a clipping rectangle with the same properties is currently present in the chart, use that. + clipRect = chart[sharedClipKey]; + markerClipRect = chart[sharedClipKey + 'm']; + if (!clipRect) { + chart[sharedClipKey] = clipRect = renderer.clipRect( + extend(clipBox, { width: 0 }) + ); + + chart[sharedClipKey + 'm'] = markerClipRect = renderer.clipRect( + -99, // include the width of the first marker + inverted ? -chart.plotLeft : -chart.plotTop, + 99, + inverted ? chart.chartWidth : chart.chartHeight + ); + } + series.group.clip(clipRect); + series.markerGroup.clip(markerClipRect); + series.sharedClipKey = sharedClipKey; + + // Run the animation + } else { + clipRect = chart[sharedClipKey]; + if (clipRect) { + clipRect.animate({ + width: chart.plotSizeX + }, animation); + chart[sharedClipKey + 'm'].animate({ + width: chart.plotSizeX + 99 + }, animation); + } + + // Delete this function to allow it only once + series.animate = null; + + // Call the afterAnimate function on animation complete (but don't overwrite the animation.complete option + // which should be available to the user). + series.animationTimeout = setTimeout(function () { + series.afterAnimate(); + }, animation.duration); + } + }, + + /** + * This runs after animation to land on the final plot clipping + */ + afterAnimate: function () { + var chart = this.chart, + sharedClipKey = this.sharedClipKey, + group = this.group; + + if (group && this.options.clip !== false) { + group.clip(chart.clipRect); + this.markerGroup.clip(); // no clip + } + + // Remove the shared clipping rectancgle when all series are shown + setTimeout(function () { + if (sharedClipKey && chart[sharedClipKey]) { + chart[sharedClipKey] = chart[sharedClipKey].destroy(); + chart[sharedClipKey + 'm'] = chart[sharedClipKey + 'm'].destroy(); + } + }, 100); + }, + + /** + * Draw the markers + */ + drawPoints: function () { + var series = this, + pointAttr, + points = series.points, + chart = series.chart, + plotX, + plotY, + i, + point, + radius, + symbol, + isImage, + graphic, + options = series.options, + seriesMarkerOptions = options.marker, + pointMarkerOptions, + enabled, + isInside, + markerGroup = series.markerGroup; + + if (seriesMarkerOptions.enabled || series._hasPointMarkers) { + + i = points.length; + while (i--) { + point = points[i]; + plotX = mathFloor(point.plotX); // #1843 + plotY = point.plotY; + graphic = point.graphic; + pointMarkerOptions = point.marker || {}; + enabled = (seriesMarkerOptions.enabled && pointMarkerOptions.enabled === UNDEFINED) || pointMarkerOptions.enabled; + isInside = chart.isInsidePlot(mathRound(plotX), plotY, chart.inverted); // #1858 + + // only draw the point if y is defined + if (enabled && plotY !== UNDEFINED && !isNaN(plotY) && point.y !== null) { + + // shortcuts + pointAttr = point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE]; + radius = pointAttr.r; + symbol = pick(pointMarkerOptions.symbol, series.symbol); + isImage = symbol.indexOf('url') === 0; + + if (graphic) { // update + graphic + .attr({ // Since the marker group isn't clipped, each individual marker must be toggled + visibility: isInside ? (hasSVG ? 'inherit' : VISIBLE) : HIDDEN + }) + .animate(extend({ + x: plotX - radius, + y: plotY - radius + }, graphic.symbolName ? { // don't apply to image symbols #507 + width: 2 * radius, + height: 2 * radius + } : {})); + } else if (isInside && (radius > 0 || isImage)) { + point.graphic = graphic = chart.renderer.symbol( + symbol, + plotX - radius, + plotY - radius, + 2 * radius, + 2 * radius + ) + .attr(pointAttr) + .add(markerGroup); + } + + } else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + } + } + + }, + + /** + * Convert state properties from API naming conventions to SVG attributes + * + * @param {Object} options API options object + * @param {Object} base1 SVG attribute object to inherit from + * @param {Object} base2 Second level SVG attribute object to inherit from + */ + convertAttribs: function (options, base1, base2, base3) { + var conversion = this.pointAttrToOptions, + attr, + option, + obj = {}; + + options = options || {}; + base1 = base1 || {}; + base2 = base2 || {}; + base3 = base3 || {}; + + for (attr in conversion) { + option = conversion[attr]; + obj[attr] = pick(options[option], base1[attr], base2[attr], base3[attr]); + } + return obj; + }, + + /** + * Get the state attributes. Each series type has its own set of attributes + * that are allowed to change on a point's state change. Series wide attributes are stored for + * all series, and additionally point specific attributes are stored for all + * points with individual marker options. If such options are not defined for the point, + * a reference to the series wide attributes is stored in point.pointAttr. + */ + getAttribs: function () { + var series = this, + seriesOptions = series.options, + normalOptions = defaultPlotOptions[series.type].marker ? seriesOptions.marker : seriesOptions, + stateOptions = normalOptions.states, + stateOptionsHover = stateOptions[HOVER_STATE], + pointStateOptionsHover, + seriesColor = series.color, + normalDefaults = { + stroke: seriesColor, + fill: seriesColor + }, + points = series.points || [], // #927 + i, + point, + seriesPointAttr = [], + pointAttr, + pointAttrToOptions = series.pointAttrToOptions, + hasPointSpecificOptions, + negativeColor = seriesOptions.negativeColor, + defaultLineColor = normalOptions.lineColor, + key; + + // series type specific modifications + if (seriesOptions.marker) { // line, spline, area, areaspline, scatter + + // if no hover radius is given, default to normal radius + 2 + stateOptionsHover.radius = stateOptionsHover.radius || normalOptions.radius + 2; + stateOptionsHover.lineWidth = stateOptionsHover.lineWidth || normalOptions.lineWidth + 1; + + } else { // column, bar, pie + + // if no hover color is given, brighten the normal color + stateOptionsHover.color = stateOptionsHover.color || + Color(stateOptionsHover.color || seriesColor) + .brighten(stateOptionsHover.brightness).get(); + } + + // general point attributes for the series normal state + seriesPointAttr[NORMAL_STATE] = series.convertAttribs(normalOptions, normalDefaults); + + // HOVER_STATE and SELECT_STATE states inherit from normal state except the default radius + each([HOVER_STATE, SELECT_STATE], function (state) { + seriesPointAttr[state] = + series.convertAttribs(stateOptions[state], seriesPointAttr[NORMAL_STATE]); + }); + + // set it + series.pointAttr = seriesPointAttr; + + + // Generate the point-specific attribute collections if specific point + // options are given. If not, create a referance to the series wide point + // attributes + i = points.length; + while (i--) { + point = points[i]; + normalOptions = (point.options && point.options.marker) || point.options; + if (normalOptions && normalOptions.enabled === false) { + normalOptions.radius = 0; + } + + if (point.negative && negativeColor) { + point.color = point.fillColor = negativeColor; + } + + hasPointSpecificOptions = seriesOptions.colorByPoint || point.color; // #868 + + // check if the point has specific visual options + if (point.options) { + for (key in pointAttrToOptions) { + if (defined(normalOptions[pointAttrToOptions[key]])) { + hasPointSpecificOptions = true; + } + } + } + + // a specific marker config object is defined for the individual point: + // create it's own attribute collection + if (hasPointSpecificOptions) { + normalOptions = normalOptions || {}; + pointAttr = []; + stateOptions = normalOptions.states || {}; // reassign for individual point + pointStateOptionsHover = stateOptions[HOVER_STATE] = stateOptions[HOVER_STATE] || {}; + + // Handle colors for column and pies + if (!seriesOptions.marker) { // column, bar, point + // if no hover color is given, brighten the normal color + pointStateOptionsHover.color = + Color(pointStateOptionsHover.color || point.color) + .brighten(pointStateOptionsHover.brightness || + stateOptionsHover.brightness).get(); + + } + + // normal point state inherits series wide normal state + pointAttr[NORMAL_STATE] = series.convertAttribs(extend({ + color: point.color, // #868 + fillColor: point.color, // Individual point color or negative color markers (#2219) + lineColor: defaultLineColor === null ? point.color : UNDEFINED // Bubbles take point color, line markers use white + }, normalOptions), seriesPointAttr[NORMAL_STATE]); + + // inherit from point normal and series hover + pointAttr[HOVER_STATE] = series.convertAttribs( + stateOptions[HOVER_STATE], + seriesPointAttr[HOVER_STATE], + pointAttr[NORMAL_STATE] + ); + + // inherit from point normal and series hover + pointAttr[SELECT_STATE] = series.convertAttribs( + stateOptions[SELECT_STATE], + seriesPointAttr[SELECT_STATE], + pointAttr[NORMAL_STATE] + ); + + + // no marker config object is created: copy a reference to the series-wide + // attribute collection + } else { + pointAttr = seriesPointAttr; + } + + point.pointAttr = pointAttr; + + } + + }, + /** + * Update the series with a new set of options + */ + update: function (newOptions, redraw) { + var chart = this.chart, + // must use user options when changing type because this.options is merged + // in with type specific plotOptions + oldOptions = this.userOptions, + oldType = this.type, + proto = seriesTypes[oldType].prototype, + n; + + // Do the merge, with some forced options + newOptions = merge(oldOptions, { + animation: false, + index: this.index, + pointStart: this.xData[0] // when updating after addPoint + }, { data: this.options.data }, newOptions); + + // Destroy the series and reinsert methods from the type prototype + this.remove(false); + for (n in proto) { // Overwrite series-type specific methods (#2270) + if (proto.hasOwnProperty(n)) { + this[n] = UNDEFINED; + } + } + extend(this, seriesTypes[newOptions.type || oldType].prototype); + + + this.init(chart, newOptions); + if (pick(redraw, true)) { + chart.redraw(false); + } + }, + + /** + * Clear DOM objects and free up memory + */ + destroy: function () { + var series = this, + chart = series.chart, + issue134 = /AppleWebKit\/533/.test(userAgent), + destroy, + i, + data = series.data || [], + point, + prop, + axis; + + // add event hook + fireEvent(series, 'destroy'); + + // remove all events + removeEvent(series); + + // erase from axes + each(['xAxis', 'yAxis'], function (AXIS) { + axis = series[AXIS]; + if (axis) { + erase(axis.series, series); + axis.isDirty = axis.forceRedraw = true; + axis.stacks = {}; // Rebuild stacks when updating (#2229) + } + }); + + // remove legend items + if (series.legendItem) { + series.chart.legend.destroyItem(series); + } + + // destroy all points with their elements + i = data.length; + while (i--) { + point = data[i]; + if (point && point.destroy) { + point.destroy(); + } + } + series.points = null; + + // Clear the animation timeout if we are destroying the series during initial animation + clearTimeout(series.animationTimeout); + + // destroy all SVGElements associated to the series + each(['area', 'graph', 'dataLabelsGroup', 'group', 'markerGroup', 'tracker', + 'graphNeg', 'areaNeg', 'posClip', 'negClip'], function (prop) { + if (series[prop]) { + + // issue 134 workaround + destroy = issue134 && prop === 'group' ? + 'hide' : + 'destroy'; + + series[prop][destroy](); + } + }); + + // remove from hoverSeries + if (chart.hoverSeries === series) { + chart.hoverSeries = null; + } + erase(chart.series, series); + + // clear all members + for (prop in series) { + delete series[prop]; + } + }, + + /** + * Draw the data labels + */ + drawDataLabels: function () { + + var series = this, + seriesOptions = series.options, + options = seriesOptions.dataLabels, + points = series.points, + pointOptions, + generalOptions, + str, + dataLabelsGroup; + + if (options.enabled || series._hasPointLabels) { + + // Process default alignment of data labels for columns + if (series.dlProcessOptions) { + series.dlProcessOptions(options); + } + + // Create a separate group for the data labels to avoid rotation + dataLabelsGroup = series.plotGroup( + 'dataLabelsGroup', + 'data-labels', + series.visible ? VISIBLE : HIDDEN, + options.zIndex || 6 + ); + + // Make the labels for each point + generalOptions = options; + each(points, function (point) { + + var enabled, + dataLabel = point.dataLabel, + labelConfig, + attr, + name, + rotation, + connector = point.connector, + isNew = true; + + // Determine if each data label is enabled + pointOptions = point.options && point.options.dataLabels; + enabled = pick(pointOptions && pointOptions.enabled, generalOptions.enabled); // #2282 + + + // If the point is outside the plot area, destroy it. #678, #820 + if (dataLabel && !enabled) { + point.dataLabel = dataLabel.destroy(); + + // Individual labels are disabled if the are explicitly disabled + // in the point options, or if they fall outside the plot area. + } else if (enabled) { + + // Create individual options structure that can be extended without + // affecting others + options = merge(generalOptions, pointOptions); + + rotation = options.rotation; + + // Get the string + labelConfig = point.getLabelConfig(); + str = options.format ? + format(options.format, labelConfig) : + options.formatter.call(labelConfig, options); + + // Determine the color + options.style.color = pick(options.color, options.style.color, series.color, 'black'); + + + // update existing label + if (dataLabel) { + + if (defined(str)) { + dataLabel + .attr({ + text: str + }); + isNew = false; + + } else { // #1437 - the label is shown conditionally + point.dataLabel = dataLabel = dataLabel.destroy(); + if (connector) { + point.connector = connector.destroy(); + } + } + + // create new label + } else if (defined(str)) { + attr = { + //align: align, + fill: options.backgroundColor, + stroke: options.borderColor, + 'stroke-width': options.borderWidth, + r: options.borderRadius || 0, + rotation: rotation, + padding: options.padding, + zIndex: 1 + }; + // Remove unused attributes (#947) + for (name in attr) { + if (attr[name] === UNDEFINED) { + delete attr[name]; + } + } + + dataLabel = point.dataLabel = series.chart.renderer[rotation ? 'text' : 'label']( // labels don't support rotation + str, + 0, + -999, + null, + null, + null, + options.useHTML + ) + .attr(attr) + .css(options.style) + .add(dataLabelsGroup) + .shadow(options.shadow); + + } + + if (dataLabel) { + // Now the data label is created and placed at 0,0, so we need to align it + series.alignDataLabel(point, dataLabel, options, null, isNew); + } + } + }); + } + }, + + /** + * Align each individual data label + */ + alignDataLabel: function (point, dataLabel, options, alignTo, isNew) { + var chart = this.chart, + inverted = chart.inverted, + plotX = pick(point.plotX, -999), + plotY = pick(point.plotY, -999), + bBox = dataLabel.getBBox(), + visible = this.visible && chart.isInsidePlot(point.plotX, point.plotY, inverted), + alignAttr; // the final position; + + if (visible) { + + // The alignment box is a singular point + alignTo = extend({ + x: inverted ? chart.plotWidth - plotY : plotX, + y: mathRound(inverted ? chart.plotHeight - plotX : plotY), + width: 0, + height: 0 + }, alignTo); + + // Add the text size for alignment calculation + extend(options, { + width: bBox.width, + height: bBox.height + }); + + // Allow a hook for changing alignment in the last moment, then do the alignment + if (options.rotation) { // Fancy box alignment isn't supported for rotated text + alignAttr = { + align: options.align, + x: alignTo.x + options.x + alignTo.width / 2, + y: alignTo.y + options.y + alignTo.height / 2 + }; + dataLabel[isNew ? 'attr' : 'animate'](alignAttr); + } else { + dataLabel.align(options, null, alignTo); + alignAttr = dataLabel.alignAttr; + + // Handle justify or crop + if (pick(options.overflow, 'justify') === 'justify') { // docs: overflow: justify, also crop only applies when not justify + this.justifyDataLabel(dataLabel, options, alignAttr, bBox, alignTo, isNew); + + } else if (pick(options.crop, true)) { + // Now check that the data label is within the plot area + visible = chart.isInsidePlot(alignAttr.x, alignAttr.y) && chart.isInsidePlot(alignAttr.x + bBox.width, alignAttr.y + bBox.height); + + } + } + } + + // Show or hide based on the final aligned position + if (!visible) { + dataLabel.attr({ y: -999 }); + } + + }, + + /** + * If data labels fall partly outside the plot area, align them back in, in a way that + * doesn't hide the point. + */ + justifyDataLabel: function (dataLabel, options, alignAttr, bBox, alignTo, isNew) { + var chart = this.chart, + align = options.align, + verticalAlign = options.verticalAlign, + off, + justified; + + // Off left + off = alignAttr.x; + if (off < 0) { + if (align === 'right') { + options.align = 'left'; + } else { + options.x = -off; + } + justified = true; + } + + // Off right + off = alignAttr.x + bBox.width; + if (off > chart.plotWidth) { + if (align === 'left') { + options.align = 'right'; + } else { + options.x = chart.plotWidth - off; + } + justified = true; + } + + // Off top + off = alignAttr.y; + if (off < 0) { + if (verticalAlign === 'bottom') { + options.verticalAlign = 'top'; + } else { + options.y = -off; + } + justified = true; + } + + // Off bottom + off = alignAttr.y + bBox.height; + if (off > chart.plotHeight) { + if (verticalAlign === 'top') { + options.verticalAlign = 'bottom'; + } else { + options.y = chart.plotHeight - off; + } + justified = true; + } + + if (justified) { + dataLabel.placed = !isNew; + dataLabel.align(options, null, alignTo); + } + }, + + /** + * Return the graph path of a segment + */ + getSegmentPath: function (segment) { + var series = this, + segmentPath = [], + step = series.options.step; + + // build the segment line + each(segment, function (point, i) { + + var plotX = point.plotX, + plotY = point.plotY, + lastPoint; + + if (series.getPointSpline) { // generate the spline as defined in the SplineSeries object + segmentPath.push.apply(segmentPath, series.getPointSpline(segment, point, i)); + + } else { + + // moveTo or lineTo + segmentPath.push(i ? L : M); + + // step line? + if (step && i) { + lastPoint = segment[i - 1]; + if (step === 'right') { + segmentPath.push( + lastPoint.plotX, + plotY + ); + + } else if (step === 'center') { + segmentPath.push( + (lastPoint.plotX + plotX) / 2, + lastPoint.plotY, + (lastPoint.plotX + plotX) / 2, + plotY + ); + + } else { + segmentPath.push( + plotX, + lastPoint.plotY + ); + } + } + + // normal line to next point + segmentPath.push( + point.plotX, + point.plotY + ); + } + }); + + return segmentPath; + }, + + /** + * Get the graph path + */ + getGraphPath: function () { + var series = this, + graphPath = [], + segmentPath, + singlePoints = []; // used in drawTracker + + // Divide into segments and build graph and area paths + each(series.segments, function (segment) { + + segmentPath = series.getSegmentPath(segment); + + // add the segment to the graph, or a single point for tracking + if (segment.length > 1) { + graphPath = graphPath.concat(segmentPath); + } else { + singlePoints.push(segment[0]); + } + }); + + // Record it for use in drawGraph and drawTracker, and return graphPath + series.singlePoints = singlePoints; + series.graphPath = graphPath; + + return graphPath; + + }, + + /** + * Draw the actual graph + */ + drawGraph: function () { + var series = this, + options = this.options, + props = [['graph', options.lineColor || this.color]], + lineWidth = options.lineWidth, + dashStyle = options.dashStyle, + graphPath = this.getGraphPath(), + negativeColor = options.negativeColor; + + if (negativeColor) { + props.push(['graphNeg', negativeColor]); + } + + // draw the graph + each(props, function (prop, i) { + var graphKey = prop[0], + graph = series[graphKey], + attribs; + + if (graph) { + stop(graph); // cancel running animations, #459 + graph.animate({ d: graphPath }); + + } else if (lineWidth && graphPath.length) { // #1487 + attribs = { + stroke: prop[1], + 'stroke-width': lineWidth, + zIndex: 1 // #1069 + }; + if (dashStyle) { + attribs.dashstyle = dashStyle; + } else { + attribs['stroke-linecap'] = attribs['stroke-linejoin'] = 'round'; + } + + series[graphKey] = series.chart.renderer.path(graphPath) + .attr(attribs) + .add(series.group) + .shadow(!i && options.shadow); + } + }); + }, + + /** + * Clip the graphs into the positive and negative coloured graphs + */ + clipNeg: function () { + var options = this.options, + chart = this.chart, + renderer = chart.renderer, + negativeColor = options.negativeColor || options.negativeFillColor, + translatedThreshold, + posAttr, + negAttr, + graph = this.graph, + area = this.area, + posClip = this.posClip, + negClip = this.negClip, + chartWidth = chart.chartWidth, + chartHeight = chart.chartHeight, + chartSizeMax = mathMax(chartWidth, chartHeight), + yAxis = this.yAxis, + above, + below; + + if (negativeColor && (graph || area)) { + translatedThreshold = mathRound(yAxis.toPixels(options.threshold || 0, true)); + above = { + x: 0, + y: 0, + width: chartSizeMax, + height: translatedThreshold + }; + below = { + x: 0, + y: translatedThreshold, + width: chartSizeMax, + height: chartSizeMax + }; + + if (chart.inverted) { + + above.height = below.y = chart.plotWidth - translatedThreshold; + if (renderer.isVML) { + above = { + x: chart.plotWidth - translatedThreshold - chart.plotLeft, + y: 0, + width: chartWidth, + height: chartHeight + }; + below = { + x: translatedThreshold + chart.plotLeft - chartWidth, + y: 0, + width: chart.plotLeft + translatedThreshold, + height: chartWidth + }; + } + } + + if (yAxis.reversed) { + posAttr = below; + negAttr = above; + } else { + posAttr = above; + negAttr = below; + } + + if (posClip) { // update + posClip.animate(posAttr); + negClip.animate(negAttr); + } else { + + this.posClip = posClip = renderer.clipRect(posAttr); + this.negClip = negClip = renderer.clipRect(negAttr); + + if (graph && this.graphNeg) { + graph.clip(posClip); + this.graphNeg.clip(negClip); + } + + if (area) { + area.clip(posClip); + this.areaNeg.clip(negClip); + } + } + } + }, + + /** + * Initialize and perform group inversion on series.group and series.markerGroup + */ + invertGroups: function () { + var series = this, + chart = series.chart; + + // Pie, go away (#1736) + if (!series.xAxis) { + return; + } + + // A fixed size is needed for inversion to work + function setInvert() { + var size = { + width: series.yAxis.len, + height: series.xAxis.len + }; + + each(['group', 'markerGroup'], function (groupName) { + if (series[groupName]) { + series[groupName].attr(size).invert(); + } + }); + } + + addEvent(chart, 'resize', setInvert); // do it on resize + addEvent(series, 'destroy', function () { + removeEvent(chart, 'resize', setInvert); + }); + + // Do it now + setInvert(); // do it now + + // On subsequent render and redraw, just do setInvert without setting up events again + series.invertGroups = setInvert; + }, + + /** + * General abstraction for creating plot groups like series.group, series.dataLabelsGroup and + * series.markerGroup. On subsequent calls, the group will only be adjusted to the updated plot size. + */ + plotGroup: function (prop, name, visibility, zIndex, parent) { + var group = this[prop], + isNew = !group; + + // Generate it on first call + if (isNew) { + this[prop] = group = this.chart.renderer.g(name) + .attr({ + visibility: visibility, + zIndex: zIndex || 0.1 // IE8 needs this + }) + .add(parent); + } + // Place it on first and subsequent (redraw) calls + group[isNew ? 'attr' : 'animate'](this.getPlotBox()); + return group; + }, + + /** + * Get the translation and scale for the plot area of this series + */ + getPlotBox: function () { + return { + translateX: this.xAxis ? this.xAxis.left : this.chart.plotLeft, + translateY: this.yAxis ? this.yAxis.top : this.chart.plotTop, + scaleX: 1, // #1623 + scaleY: 1 + }; + }, + + /** + * Render the graph and markers + */ + render: function () { + var series = this, + chart = series.chart, + group, + options = series.options, + animation = options.animation, + doAnimation = animation && !!series.animate && + chart.renderer.isSVG, // this animation doesn't work in IE8 quirks when the group div is hidden, + // and looks bad in other oldIE + visibility = series.visible ? VISIBLE : HIDDEN, + zIndex = options.zIndex, + hasRendered = series.hasRendered, + chartSeriesGroup = chart.seriesGroup; + + // the group + group = series.plotGroup( + 'group', + 'series', + visibility, + zIndex, + chartSeriesGroup + ); + + series.markerGroup = series.plotGroup( + 'markerGroup', + 'markers', + visibility, + zIndex, + chartSeriesGroup + ); + + // initiate the animation + if (doAnimation) { + series.animate(true); + } + + // cache attributes for shapes + series.getAttribs(); + + // SVGRenderer needs to know this before drawing elements (#1089, #1795) + group.inverted = series.isCartesian ? chart.inverted : false; + + // draw the graph if any + if (series.drawGraph) { + series.drawGraph(); + series.clipNeg(); + } + + // draw the data labels (inn pies they go before the points) + series.drawDataLabels(); + + // draw the points + series.drawPoints(); + + + // draw the mouse tracking area + if (series.options.enableMouseTracking !== false) { + series.drawTracker(); + } + + // Handle inverted series and tracker groups + if (chart.inverted) { + series.invertGroups(); + } + + // Initial clipping, must be defined after inverting groups for VML + if (options.clip !== false && !series.sharedClipKey && !hasRendered) { + group.clip(chart.clipRect); + } + + // Run the animation + if (doAnimation) { + series.animate(); + } else if (!hasRendered) { + series.afterAnimate(); + } + + series.isDirty = series.isDirtyData = false; // means data is in accordance with what you see + // (See #322) series.isDirty = series.isDirtyData = false; // means data is in accordance with what you see + series.hasRendered = true; + }, + + /** + * Redraw the series after an update in the axes. + */ + redraw: function () { + var series = this, + chart = series.chart, + wasDirtyData = series.isDirtyData, // cache it here as it is set to false in render, but used after + group = series.group, + xAxis = series.xAxis, + yAxis = series.yAxis; + + // reposition on resize + if (group) { + if (chart.inverted) { + group.attr({ + width: chart.plotWidth, + height: chart.plotHeight + }); + } + + group.animate({ + translateX: pick(xAxis && xAxis.left, chart.plotLeft), + translateY: pick(yAxis && yAxis.top, chart.plotTop) + }); + } + + series.translate(); + series.setTooltipPoints(true); + + series.render(); + if (wasDirtyData) { + fireEvent(series, 'updatedData'); + } + }, + + /** + * Set the state of the graph + */ + setState: function (state) { + var series = this, + options = series.options, + graph = series.graph, + graphNeg = series.graphNeg, + stateOptions = options.states, + lineWidth = options.lineWidth, + attribs; + + state = state || NORMAL_STATE; + + if (series.state !== state) { + series.state = state; + + if (stateOptions[state] && stateOptions[state].enabled === false) { + return; + } + + if (state) { + lineWidth = stateOptions[state].lineWidth || lineWidth + 1; + } + + if (graph && !graph.dashstyle) { // hover is turned off for dashed lines in VML + attribs = { + 'stroke-width': lineWidth + }; + // use attr because animate will cause any other animation on the graph to stop + graph.attr(attribs); + if (graphNeg) { + graphNeg.attr(attribs); + } + } + } + }, + + /** + * Set the visibility of the graph + * + * @param vis {Boolean} True to show the series, false to hide. If UNDEFINED, + * the visibility is toggled. + */ + setVisible: function (vis, redraw) { + var series = this, + chart = series.chart, + legendItem = series.legendItem, + showOrHide, + ignoreHiddenSeries = chart.options.chart.ignoreHiddenSeries, + oldVisibility = series.visible; + + // if called without an argument, toggle visibility + series.visible = vis = series.userOptions.visible = vis === UNDEFINED ? !oldVisibility : vis; + showOrHide = vis ? 'show' : 'hide'; + + // show or hide elements + each(['group', 'dataLabelsGroup', 'markerGroup', 'tracker'], function (key) { + if (series[key]) { + series[key][showOrHide](); + } + }); + + + // hide tooltip (#1361) + if (chart.hoverSeries === series) { + series.onMouseOut(); + } + + + if (legendItem) { + chart.legend.colorizeItem(series, vis); + } + + + // rescale or adapt to resized chart + series.isDirty = true; + // in a stack, all other series are affected + if (series.options.stacking) { + each(chart.series, function (otherSeries) { + if (otherSeries.options.stacking && otherSeries.visible) { + otherSeries.isDirty = true; + } + }); + } + + // show or hide linked series + each(series.linkedSeries, function (otherSeries) { + otherSeries.setVisible(vis, false); + }); + + if (ignoreHiddenSeries) { + chart.isDirtyBox = true; + } + if (redraw !== false) { + chart.redraw(); + } + + fireEvent(series, showOrHide); + }, + + /** + * Show the graph + */ + show: function () { + this.setVisible(true); + }, + + /** + * Hide the graph + */ + hide: function () { + this.setVisible(false); + }, + + + /** + * Set the selected state of the graph + * + * @param selected {Boolean} True to select the series, false to unselect. If + * UNDEFINED, the selection state is toggled. + */ + select: function (selected) { + var series = this; + // if called without an argument, toggle + series.selected = selected = (selected === UNDEFINED) ? !series.selected : selected; + + if (series.checkbox) { + series.checkbox.checked = selected; + } + + fireEvent(series, selected ? 'select' : 'unselect'); + }, + + /** + * Draw the tracker object that sits above all data labels and markers to + * track mouse events on the graph or points. For the line type charts + * the tracker uses the same graphPath, but with a greater stroke width + * for better control. + */ + drawTracker: function () { + var series = this, + options = series.options, + trackByArea = options.trackByArea, + trackerPath = [].concat(trackByArea ? series.areaPath : series.graphPath), + trackerPathLength = trackerPath.length, + chart = series.chart, + pointer = chart.pointer, + renderer = chart.renderer, + snap = chart.options.tooltip.snap, + tracker = series.tracker, + cursor = options.cursor, + css = cursor && { cursor: cursor }, + singlePoints = series.singlePoints, + singlePoint, + i, + onMouseOver = function () { + if (chart.hoverSeries !== series) { + series.onMouseOver(); + } + }; + + // Extend end points. A better way would be to use round linecaps, + // but those are not clickable in VML. + if (trackerPathLength && !trackByArea) { + i = trackerPathLength + 1; + while (i--) { + if (trackerPath[i] === M) { // extend left side + trackerPath.splice(i + 1, 0, trackerPath[i + 1] - snap, trackerPath[i + 2], L); + } + if ((i && trackerPath[i] === M) || i === trackerPathLength) { // extend right side + trackerPath.splice(i, 0, L, trackerPath[i - 2] + snap, trackerPath[i - 1]); + } + } + } + + // handle single points + for (i = 0; i < singlePoints.length; i++) { + singlePoint = singlePoints[i]; + trackerPath.push(M, singlePoint.plotX - snap, singlePoint.plotY, + L, singlePoint.plotX + snap, singlePoint.plotY); + } + + + + // draw the tracker + if (tracker) { + tracker.attr({ d: trackerPath }); + + } else { // create + + series.tracker = renderer.path(trackerPath) + .attr({ + 'stroke-linejoin': 'round', // #1225 + visibility: series.visible ? VISIBLE : HIDDEN, + stroke: TRACKER_FILL, + fill: trackByArea ? TRACKER_FILL : NONE, + 'stroke-width' : options.lineWidth + (trackByArea ? 0 : 2 * snap), + zIndex: 2 + }) + .add(series.group); + + // The tracker is added to the series group, which is clipped, but is covered + // by the marker group. So the marker group also needs to capture events. + each([series.tracker, series.markerGroup], function (tracker) { + tracker.addClass(PREFIX + 'tracker') + .on('mouseover', onMouseOver) + .on('mouseout', function (e) { pointer.onTrackerMouseOut(e); }) + .css(css); + + if (hasTouch) { + tracker.on('touchstart', onMouseOver); + } + }); + } + + } + +}; // end Series prototype + + +/** + * LineSeries object + */ +var LineSeries = extendClass(Series); +seriesTypes.line = LineSeries; + +/** + * Set the default options for area + */ +defaultPlotOptions.area = merge(defaultSeriesOptions, { + threshold: 0 + // trackByArea: false, + // lineColor: null, // overrides color, but lets fillColor be unaltered + // fillOpacity: 0.75, + // fillColor: null +}); + +/** + * AreaSeries object + */ +var AreaSeries = extendClass(Series, { + type: 'area', + + /** + * For stacks, don't split segments on null values. Instead, draw null values with + * no marker. Also insert dummy points for any X position that exists in other series + * in the stack. + */ + getSegments: function () { + var segments = [], + segment = [], + keys = [], + xAxis = this.xAxis, + yAxis = this.yAxis, + stack = yAxis.stacks[this.stackKey], + pointMap = {}, + plotX, + plotY, + points = this.points, + connectNulls = this.options.connectNulls, + val, + i, + x; + + if (this.options.stacking && !this.cropped) { // cropped causes artefacts in Stock, and perf issue + // Create a map where we can quickly look up the points by their X value. + for (i = 0; i < points.length; i++) { + pointMap[points[i].x] = points[i]; + } + + // Sort the keys (#1651) + for (x in stack) { + keys.push(+x); + } + keys.sort(function (a, b) { + return a - b; + }); + + each(keys, function (x) { + if (connectNulls && (!pointMap[x] || pointMap[x].y === null)) { // #1836 + return; + + // The point exists, push it to the segment + } else if (pointMap[x]) { + segment.push(pointMap[x]); + + // There is no point for this X value in this series, so we + // insert a dummy point in order for the areas to be drawn + // correctly. + } else { + plotX = xAxis.translate(x); + val = stack[x].percent ? (stack[x].total ? stack[x].cum * 100 / stack[x].total : 0) : stack[x].cum; // #1991 + plotY = yAxis.toPixels(val, true); + segment.push({ + y: null, + plotX: plotX, + clientX: plotX, + plotY: plotY, + yBottom: plotY, + onMouseOver: noop + }); + } + }); + + if (segment.length) { + segments.push(segment); + } + + } else { + Series.prototype.getSegments.call(this); + segments = this.segments; + } + + this.segments = segments; + }, + + /** + * Extend the base Series getSegmentPath method by adding the path for the area. + * This path is pushed to the series.areaPath property. + */ + getSegmentPath: function (segment) { + + var segmentPath = Series.prototype.getSegmentPath.call(this, segment), // call base method + areaSegmentPath = [].concat(segmentPath), // work on a copy for the area path + i, + options = this.options, + segLength = segmentPath.length, + translatedThreshold = this.yAxis.getThreshold(options.threshold), // #2181 + yBottom; + + if (segLength === 3) { // for animation from 1 to two points + areaSegmentPath.push(L, segmentPath[1], segmentPath[2]); + } + if (options.stacking && !this.closedStacks) { + + // Follow stack back. Todo: implement areaspline. A general solution could be to + // reverse the entire graphPath of the previous series, though may be hard with + // splines and with series with different extremes + for (i = segment.length - 1; i >= 0; i--) { + + yBottom = pick(segment[i].yBottom, translatedThreshold); + + // step line? + if (i < segment.length - 1 && options.step) { + areaSegmentPath.push(segment[i + 1].plotX, yBottom); + } + + areaSegmentPath.push(segment[i].plotX, yBottom); + } + + } else { // follow zero line back + this.closeSegment(areaSegmentPath, segment, translatedThreshold); + } + this.areaPath = this.areaPath.concat(areaSegmentPath); + return segmentPath; + }, + + /** + * Extendable method to close the segment path of an area. This is overridden in polar + * charts. + */ + closeSegment: function (path, segment, translatedThreshold) { + path.push( + L, + segment[segment.length - 1].plotX, + translatedThreshold, + L, + segment[0].plotX, + translatedThreshold + ); + }, + + /** + * Draw the graph and the underlying area. This method calls the Series base + * function and adds the area. The areaPath is calculated in the getSegmentPath + * method called from Series.prototype.drawGraph. + */ + drawGraph: function () { + + // Define or reset areaPath + this.areaPath = []; + + // Call the base method + Series.prototype.drawGraph.apply(this); + + // Define local variables + var series = this, + areaPath = this.areaPath, + options = this.options, + negativeColor = options.negativeColor, + negativeFillColor = options.negativeFillColor, + props = [['area', this.color, options.fillColor]]; // area name, main color, fill color + + if (negativeColor || negativeFillColor) { + props.push(['areaNeg', negativeColor, negativeFillColor]); + } + + each(props, function (prop) { + var areaKey = prop[0], + area = series[areaKey]; + + // Create or update the area + if (area) { // update + area.animate({ d: areaPath }); + + } else { // create + series[areaKey] = series.chart.renderer.path(areaPath) + .attr({ + fill: pick( + prop[2], + Color(prop[1]).setOpacity(pick(options.fillOpacity, 0.75)).get() + ), + zIndex: 0 // #1069 + }).add(series.group); + } + }); + }, + + /** + * Get the series' symbol in the legend + * + * @param {Object} legend The legend object + * @param {Object} item The series (this) or point + */ + drawLegendSymbol: function (legend, item) { + + item.legendSymbol = this.chart.renderer.rect( + 0, + legend.baseline - 11, + legend.options.symbolWidth, + 12, + 2 + ).attr({ + zIndex: 3 + }).add(item.legendGroup); + + } +}); + +seriesTypes.area = AreaSeries;/** + * Set the default options for spline + */ +defaultPlotOptions.spline = merge(defaultSeriesOptions); + +/** + * SplineSeries object + */ +var SplineSeries = extendClass(Series, { + type: 'spline', + + /** + * Get the spline segment from a given point's previous neighbour to the given point + */ + getPointSpline: function (segment, point, i) { + var smoothing = 1.5, // 1 means control points midway between points, 2 means 1/3 from the point, 3 is 1/4 etc + denom = smoothing + 1, + plotX = point.plotX, + plotY = point.plotY, + lastPoint = segment[i - 1], + nextPoint = segment[i + 1], + leftContX, + leftContY, + rightContX, + rightContY, + ret; + + // find control points + if (lastPoint && nextPoint) { + + var lastX = lastPoint.plotX, + lastY = lastPoint.plotY, + nextX = nextPoint.plotX, + nextY = nextPoint.plotY, + correction; + + leftContX = (smoothing * plotX + lastX) / denom; + leftContY = (smoothing * plotY + lastY) / denom; + rightContX = (smoothing * plotX + nextX) / denom; + rightContY = (smoothing * plotY + nextY) / denom; + + // have the two control points make a straight line through main point + correction = ((rightContY - leftContY) * (rightContX - plotX)) / + (rightContX - leftContX) + plotY - rightContY; + + leftContY += correction; + rightContY += correction; + + // to prevent false extremes, check that control points are between + // neighbouring points' y values + if (leftContY > lastY && leftContY > plotY) { + leftContY = mathMax(lastY, plotY); + rightContY = 2 * plotY - leftContY; // mirror of left control point + } else if (leftContY < lastY && leftContY < plotY) { + leftContY = mathMin(lastY, plotY); + rightContY = 2 * plotY - leftContY; + } + if (rightContY > nextY && rightContY > plotY) { + rightContY = mathMax(nextY, plotY); + leftContY = 2 * plotY - rightContY; + } else if (rightContY < nextY && rightContY < plotY) { + rightContY = mathMin(nextY, plotY); + leftContY = 2 * plotY - rightContY; + } + + // record for drawing in next point + point.rightContX = rightContX; + point.rightContY = rightContY; + + } + + // Visualize control points for debugging + /* + if (leftContX) { + this.chart.renderer.circle(leftContX + this.chart.plotLeft, leftContY + this.chart.plotTop, 2) + .attr({ + stroke: 'red', + 'stroke-width': 1, + fill: 'none' + }) + .add(); + this.chart.renderer.path(['M', leftContX + this.chart.plotLeft, leftContY + this.chart.plotTop, + 'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop]) + .attr({ + stroke: 'red', + 'stroke-width': 1 + }) + .add(); + this.chart.renderer.circle(rightContX + this.chart.plotLeft, rightContY + this.chart.plotTop, 2) + .attr({ + stroke: 'green', + 'stroke-width': 1, + fill: 'none' + }) + .add(); + this.chart.renderer.path(['M', rightContX + this.chart.plotLeft, rightContY + this.chart.plotTop, + 'L', plotX + this.chart.plotLeft, plotY + this.chart.plotTop]) + .attr({ + stroke: 'green', + 'stroke-width': 1 + }) + .add(); + } + */ + + // moveTo or lineTo + if (!i) { + ret = [M, plotX, plotY]; + } else { // curve from last point to this + ret = [ + 'C', + lastPoint.rightContX || lastPoint.plotX, + lastPoint.rightContY || lastPoint.plotY, + leftContX || plotX, + leftContY || plotY, + plotX, + plotY + ]; + lastPoint.rightContX = lastPoint.rightContY = null; // reset for updating series later + } + return ret; + } +}); +seriesTypes.spline = SplineSeries; + +/** + * Set the default options for areaspline + */ +defaultPlotOptions.areaspline = merge(defaultPlotOptions.area); + +/** + * AreaSplineSeries object + */ +var areaProto = AreaSeries.prototype, + AreaSplineSeries = extendClass(SplineSeries, { + type: 'areaspline', + closedStacks: true, // instead of following the previous graph back, follow the threshold back + + // Mix in methods from the area series + getSegmentPath: areaProto.getSegmentPath, + closeSegment: areaProto.closeSegment, + drawGraph: areaProto.drawGraph, + drawLegendSymbol: areaProto.drawLegendSymbol + }); +seriesTypes.areaspline = AreaSplineSeries; + +/** + * Set the default options for column + */ +defaultPlotOptions.column = merge(defaultSeriesOptions, { + borderColor: '#FFFFFF', + borderWidth: 1, + borderRadius: 0, + //colorByPoint: undefined, + groupPadding: 0.2, + //grouping: true, + marker: null, // point options are specified in the base options + pointPadding: 0.1, + //pointWidth: null, + minPointLength: 0, + cropThreshold: 50, // when there are more points, they will not animate out of the chart on xAxis.setExtremes + pointRange: null, // null means auto, meaning 1 in a categorized axis and least distance between points if not categories + states: { + hover: { + brightness: 0.1, + shadow: false + }, + select: { + color: '#C0C0C0', + borderColor: '#000000', + shadow: false + } + }, + dataLabels: { + align: null, // auto + verticalAlign: null, // auto + y: null + }, + stickyTracking: false, + threshold: 0 +}); + +/** + * ColumnSeries object + */ +var ColumnSeries = extendClass(Series, { + type: 'column', + pointAttrToOptions: { // mapping between SVG attributes and the corresponding options + stroke: 'borderColor', + 'stroke-width': 'borderWidth', + fill: 'color', + r: 'borderRadius' + }, + cropShoulder: 0, + trackerGroups: ['group', 'dataLabelsGroup'], + negStacks: true, // use separate negative stacks, unlike area stacks where a negative + // point is substracted from previous (#1910) + + /** + * Initialize the series + */ + init: function () { + Series.prototype.init.apply(this, arguments); + + var series = this, + chart = series.chart; + + // if the series is added dynamically, force redraw of other + // series affected by a new column + if (chart.hasRendered) { + each(chart.series, function (otherSeries) { + if (otherSeries.type === series.type) { + otherSeries.isDirty = true; + } + }); + } + }, + + /** + * Return the width and x offset of the columns adjusted for grouping, groupPadding, pointPadding, + * pointWidth etc. + */ + getColumnMetrics: function () { + + var series = this, + options = series.options, + xAxis = series.xAxis, + yAxis = series.yAxis, + reversedXAxis = xAxis.reversed, + stackKey, + stackGroups = {}, + columnIndex, + columnCount = 0; + + // Get the total number of column type series. + // This is called on every series. Consider moving this logic to a + // chart.orderStacks() function and call it on init, addSeries and removeSeries + if (options.grouping === false) { + columnCount = 1; + } else { + each(series.chart.series, function (otherSeries) { + var otherOptions = otherSeries.options, + otherYAxis = otherSeries.yAxis; + if (otherSeries.type === series.type && otherSeries.visible && + yAxis.len === otherYAxis.len && yAxis.pos === otherYAxis.pos) { // #642, #2086 + if (otherOptions.stacking) { + stackKey = otherSeries.stackKey; + if (stackGroups[stackKey] === UNDEFINED) { + stackGroups[stackKey] = columnCount++; + } + columnIndex = stackGroups[stackKey]; + } else if (otherOptions.grouping !== false) { // #1162 + columnIndex = columnCount++; + } + otherSeries.columnIndex = columnIndex; + } + }); + } + + var categoryWidth = mathMin( + mathAbs(xAxis.transA) * (xAxis.ordinalSlope || options.pointRange || xAxis.closestPointRange || 1), + xAxis.len // #1535 + ), + groupPadding = categoryWidth * options.groupPadding, + groupWidth = categoryWidth - 2 * groupPadding, + pointOffsetWidth = groupWidth / columnCount, + optionPointWidth = options.pointWidth, + pointPadding = defined(optionPointWidth) ? (pointOffsetWidth - optionPointWidth) / 2 : + pointOffsetWidth * options.pointPadding, + pointWidth = pick(optionPointWidth, pointOffsetWidth - 2 * pointPadding), // exact point width, used in polar charts + colIndex = (reversedXAxis ? + columnCount - (series.columnIndex || 0) : // #1251 + series.columnIndex) || 0, + pointXOffset = pointPadding + (groupPadding + colIndex * + pointOffsetWidth - (categoryWidth / 2)) * + (reversedXAxis ? -1 : 1); + + // Save it for reading in linked series (Error bars particularly) + return (series.columnMetrics = { + width: pointWidth, + offset: pointXOffset + }); + + }, + + /** + * Translate each point to the plot area coordinate system and find shape positions + */ + translate: function () { + var series = this, + chart = series.chart, + options = series.options, + borderWidth = options.borderWidth, + yAxis = series.yAxis, + threshold = options.threshold, + translatedThreshold = series.translatedThreshold = yAxis.getThreshold(threshold), + minPointLength = pick(options.minPointLength, 5), + metrics = series.getColumnMetrics(), + pointWidth = metrics.width, + seriesBarW = series.barW = mathCeil(mathMax(pointWidth, 1 + 2 * borderWidth)), // rounded and postprocessed for border width + pointXOffset = series.pointXOffset = metrics.offset, + xCrisp = -(borderWidth % 2 ? 0.5 : 0), + yCrisp = borderWidth % 2 ? 0.5 : 1; + + if (chart.renderer.isVML && chart.inverted) { + yCrisp += 1; + } + + Series.prototype.translate.apply(series); + + // record the new values + each(series.points, function (point) { + var yBottom = pick(point.yBottom, translatedThreshold), + plotY = mathMin(mathMax(-999 - yBottom, point.plotY), yAxis.len + 999 + yBottom), // Don't draw too far outside plot area (#1303, #2241) + barX = point.plotX + pointXOffset, + barW = seriesBarW, + barY = mathMin(plotY, yBottom), + right, + bottom, + fromTop, + fromLeft, + barH = mathMax(plotY, yBottom) - barY; + + // Handle options.minPointLength + if (mathAbs(barH) < minPointLength) { + if (minPointLength) { + barH = minPointLength; + barY = + mathRound(mathAbs(barY - translatedThreshold) > minPointLength ? // stacked + yBottom - minPointLength : // keep position + translatedThreshold - (yAxis.translate(point.y, 0, 1, 0, 1) <= translatedThreshold ? minPointLength : 0)); // use exact yAxis.translation (#1485) + } + } + + // Cache for access in polar + point.barX = barX; + point.pointWidth = pointWidth; + + + // Round off to obtain crisp edges + fromLeft = mathAbs(barX) < 0.5; + right = mathRound(barX + barW) + xCrisp; + barX = mathRound(barX) + xCrisp; + barW = right - barX; + + fromTop = mathAbs(barY) < 0.5; + bottom = mathRound(barY + barH) + yCrisp; + barY = mathRound(barY) + yCrisp; + barH = bottom - barY; + + // Top and left edges are exceptions + if (fromLeft) { + barX += 1; + barW -= 1; + } + if (fromTop) { + barY -= 1; + barH += 1; + } + + // Register shape type and arguments to be used in drawPoints + point.shapeType = 'rect'; + point.shapeArgs = { + x: barX, + y: barY, + width: barW, + height: barH + }; + }); + + }, + + getSymbol: noop, + + /** + * Use a solid rectangle like the area series types + */ + drawLegendSymbol: AreaSeries.prototype.drawLegendSymbol, + + + /** + * Columns have no graph + */ + drawGraph: noop, + + /** + * Draw the columns. For bars, the series.group is rotated, so the same coordinates + * apply for columns and bars. This method is inherited by scatter series. + * + */ + drawPoints: function () { + var series = this, + options = series.options, + renderer = series.chart.renderer, + shapeArgs; + + + // draw the columns + each(series.points, function (point) { + var plotY = point.plotY, + graphic = point.graphic; + + if (plotY !== UNDEFINED && !isNaN(plotY) && point.y !== null) { + shapeArgs = point.shapeArgs; + + if (graphic) { // update + stop(graphic); + graphic.animate(merge(shapeArgs)); + + } else { + point.graphic = graphic = renderer[point.shapeType](shapeArgs) + .attr(point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE]) + .add(series.group) + .shadow(options.shadow, null, options.stacking && !options.borderRadius); + } + + } else if (graphic) { + point.graphic = graphic.destroy(); // #1269 + } + }); + }, + + /** + * Add tracking event listener to the series group, so the point graphics + * themselves act as trackers + */ + drawTracker: function () { + var series = this, + chart = series.chart, + pointer = chart.pointer, + cursor = series.options.cursor, + css = cursor && { cursor: cursor }, + onMouseOver = function (e) { + var target = e.target, + point; + + if (chart.hoverSeries !== series) { + series.onMouseOver(); + } + while (target && !point) { + point = target.point; + target = target.parentNode; + } + if (point !== UNDEFINED && point !== chart.hoverPoint) { // undefined on graph in scatterchart + point.onMouseOver(e); + } + }; + + // Add reference to the point + each(series.points, function (point) { + if (point.graphic) { + point.graphic.element.point = point; + } + if (point.dataLabel) { + point.dataLabel.element.point = point; + } + }); + + // Add the event listeners, we need to do this only once + if (!series._hasTracking) { + each(series.trackerGroups, function (key) { + if (series[key]) { // we don't always have dataLabelsGroup + series[key] + .addClass(PREFIX + 'tracker') + .on('mouseover', onMouseOver) + .on('mouseout', function (e) { pointer.onTrackerMouseOut(e); }) + .css(css); + if (hasTouch) { + series[key].on('touchstart', onMouseOver); + } + } + }); + series._hasTracking = true; + } + }, + + /** + * Override the basic data label alignment by adjusting for the position of the column + */ + alignDataLabel: function (point, dataLabel, options, alignTo, isNew) { + var chart = this.chart, + inverted = chart.inverted, + dlBox = point.dlBox || point.shapeArgs, // data label box for alignment + below = point.below || (point.plotY > pick(this.translatedThreshold, chart.plotSizeY)), + inside = pick(options.inside, !!this.options.stacking); // draw it inside the box? + + // Align to the column itself, or the top of it + if (dlBox) { // Area range uses this method but not alignTo + alignTo = merge(dlBox); + if (inverted) { + alignTo = { + x: chart.plotWidth - alignTo.y - alignTo.height, + y: chart.plotHeight - alignTo.x - alignTo.width, + width: alignTo.height, + height: alignTo.width + }; + } + + // Compute the alignment box + if (!inside) { + if (inverted) { + alignTo.x += below ? 0 : alignTo.width; + alignTo.width = 0; + } else { + alignTo.y += below ? alignTo.height : 0; + alignTo.height = 0; + } + } + } + + // When alignment is undefined (typically columns and bars), display the individual + // point below or above the point depending on the threshold + options.align = pick( + options.align, + !inverted || inside ? 'center' : below ? 'right' : 'left' + ); + options.verticalAlign = pick( + options.verticalAlign, + inverted || inside ? 'middle' : below ? 'top' : 'bottom' + ); + + // Call the parent method + Series.prototype.alignDataLabel.call(this, point, dataLabel, options, alignTo, isNew); + }, + + + /** + * Animate the column heights one by one from zero + * @param {Boolean} init Whether to initialize the animation or run it + */ + animate: function (init) { + var series = this, + yAxis = this.yAxis, + options = series.options, + inverted = this.chart.inverted, + attr = {}, + translatedThreshold; + + if (hasSVG) { // VML is too slow anyway + if (init) { + attr.scaleY = 0.001; + translatedThreshold = mathMin(yAxis.pos + yAxis.len, mathMax(yAxis.pos, yAxis.toPixels(options.threshold))); + if (inverted) { + attr.translateX = translatedThreshold - yAxis.len; + } else { + attr.translateY = translatedThreshold; + } + series.group.attr(attr); + + } else { // run the animation + + attr.scaleY = 1; + attr[inverted ? 'translateX' : 'translateY'] = yAxis.pos; + series.group.animate(attr, series.options.animation); + + // delete this function to allow it only once + series.animate = null; + } + } + }, + + /** + * Remove this series from the chart + */ + remove: function () { + var series = this, + chart = series.chart; + + // column and bar series affects other series of the same type + // as they are either stacked or grouped + if (chart.hasRendered) { + each(chart.series, function (otherSeries) { + if (otherSeries.type === series.type) { + otherSeries.isDirty = true; + } + }); + } + + Series.prototype.remove.apply(series, arguments); + } +}); +seriesTypes.column = ColumnSeries; +/** + * Set the default options for bar + */ +defaultPlotOptions.bar = merge(defaultPlotOptions.column); +/** + * The Bar series class + */ +var BarSeries = extendClass(ColumnSeries, { + type: 'bar', + inverted: true +}); +seriesTypes.bar = BarSeries; + +/** + * Set the default options for scatter + */ +defaultPlotOptions.scatter = merge(defaultSeriesOptions, { + lineWidth: 0, + tooltip: { + headerFormat: '{series.name}
', + pointFormat: 'x: {point.x}
y: {point.y}
', + followPointer: true + }, + stickyTracking: false +}); + +/** + * The scatter series class + */ +var ScatterSeries = extendClass(Series, { + type: 'scatter', + sorted: false, + requireSorting: false, + noSharedTooltip: true, + trackerGroups: ['markerGroup'], + + drawTracker: ColumnSeries.prototype.drawTracker, + + setTooltipPoints: noop +}); +seriesTypes.scatter = ScatterSeries; + +/** + * Set the default options for pie + */ +defaultPlotOptions.pie = merge(defaultSeriesOptions, { + borderColor: '#FFFFFF', + borderWidth: 1, + center: [null, null], + clip: false, + colorByPoint: true, // always true for pies + dataLabels: { + // align: null, + // connectorWidth: 1, + // connectorColor: point.color, + // connectorPadding: 5, + distance: 30, + enabled: true, + formatter: function () { + return this.point.name; + } + // softConnector: true, + //y: 0 + }, + ignoreHiddenPoint: true, + //innerSize: 0, + legendType: 'point', + marker: null, // point options are specified in the base options + size: null, + showInLegend: false, + slicedOffset: 10, + states: { + hover: { + brightness: 0.1, + shadow: false + } + }, + stickyTracking: false, + tooltip: { + followPointer: true + } +}); + +/** + * Extended point object for pies + */ +var PiePoint = extendClass(Point, { + /** + * Initiate the pie slice + */ + init: function () { + + Point.prototype.init.apply(this, arguments); + + var point = this, + toggleSlice; + + // Disallow negative values (#1530) + if (point.y < 0) { + point.y = null; + } + + //visible: options.visible !== false, + extend(point, { + visible: point.visible !== false, + name: pick(point.name, 'Slice') + }); + + // add event listener for select + toggleSlice = function (e) { + point.slice(e.type === 'select'); + }; + addEvent(point, 'select', toggleSlice); + addEvent(point, 'unselect', toggleSlice); + + return point; + }, + + /** + * Toggle the visibility of the pie slice + * @param {Boolean} vis Whether to show the slice or not. If undefined, the + * visibility is toggled + */ + setVisible: function (vis) { + var point = this, + series = point.series, + chart = series.chart, + method; + + // if called without an argument, toggle visibility + point.visible = point.options.visible = vis = vis === UNDEFINED ? !point.visible : vis; + series.options.data[inArray(point, series.data)] = point.options; // update userOptions.data + + method = vis ? 'show' : 'hide'; + + // Show and hide associated elements + each(['graphic', 'dataLabel', 'connector', 'shadowGroup'], function (key) { + if (point[key]) { + point[key][method](); + } + }); + + if (point.legendItem) { + chart.legend.colorizeItem(point, vis); + } + + // Handle ignore hidden slices + if (!series.isDirty && series.options.ignoreHiddenPoint) { + series.isDirty = true; + chart.redraw(); + } + }, + + /** + * Set or toggle whether the slice is cut out from the pie + * @param {Boolean} sliced When undefined, the slice state is toggled + * @param {Boolean} redraw Whether to redraw the chart. True by default. + */ + slice: function (sliced, redraw, animation) { + var point = this, + series = point.series, + chart = series.chart, + translation; + + setAnimation(animation, chart); + + // redraw is true by default + redraw = pick(redraw, true); + + // if called without an argument, toggle + point.sliced = point.options.sliced = sliced = defined(sliced) ? sliced : !point.sliced; + series.options.data[inArray(point, series.data)] = point.options; // update userOptions.data + + translation = sliced ? point.slicedTranslation : { + translateX: 0, + translateY: 0 + }; + + point.graphic.animate(translation); + + if (point.shadowGroup) { + point.shadowGroup.animate(translation); + } + + } +}); + +/** + * The Pie series class + */ +var PieSeries = { + type: 'pie', + isCartesian: false, + pointClass: PiePoint, + requireSorting: false, + noSharedTooltip: true, + trackerGroups: ['group', 'dataLabelsGroup'], + pointAttrToOptions: { // mapping between SVG attributes and the corresponding options + stroke: 'borderColor', + 'stroke-width': 'borderWidth', + fill: 'color' + }, + + /** + * Pies have one color each point + */ + getColor: noop, + + /** + * Animate the pies in + */ + animate: function (init) { + var series = this, + points = series.points, + startAngleRad = series.startAngleRad; + + if (!init) { + each(points, function (point) { + var graphic = point.graphic, + args = point.shapeArgs; + + if (graphic) { + // start values + graphic.attr({ + r: series.center[3] / 2, // animate from inner radius (#779) + start: startAngleRad, + end: startAngleRad + }); + + // animate + graphic.animate({ + r: args.r, + start: args.start, + end: args.end + }, series.options.animation); + } + }); + + // delete this function to allow it only once + series.animate = null; + } + }, + + /** + * Extend the basic setData method by running processData and generatePoints immediately, + * in order to access the points from the legend. + */ + setData: function (data, redraw) { + Series.prototype.setData.call(this, data, false); + this.processData(); + this.generatePoints(); + if (pick(redraw, true)) { + this.chart.redraw(); + } + }, + + /** + * Extend the generatePoints method by adding total and percentage properties to each point + */ + generatePoints: function () { + var i, + total = 0, + points, + len, + point, + ignoreHiddenPoint = this.options.ignoreHiddenPoint; + + Series.prototype.generatePoints.call(this); + + // Populate local vars + points = this.points; + len = points.length; + + // Get the total sum + for (i = 0; i < len; i++) { + point = points[i]; + total += (ignoreHiddenPoint && !point.visible) ? 0 : point.y; + } + this.total = total; + + // Set each point's properties + for (i = 0; i < len; i++) { + point = points[i]; + point.percentage = total > 0 ? (point.y / total) * 100 : 0; + point.total = total; + } + + }, + + /** + * Get the center of the pie based on the size and center options relative to the + * plot area. Borrowed by the polar and gauge series types. + */ + getCenter: function () { + + var options = this.options, + chart = this.chart, + slicingRoom = 2 * (options.slicedOffset || 0), + handleSlicingRoom, + plotWidth = chart.plotWidth - 2 * slicingRoom, + plotHeight = chart.plotHeight - 2 * slicingRoom, + centerOption = options.center, + positions = [pick(centerOption[0], '50%'), pick(centerOption[1], '50%'), options.size || '100%', options.innerSize || 0], + smallestSize = mathMin(plotWidth, plotHeight), + isPercent; + + return map(positions, function (length, i) { + isPercent = /%$/.test(length); + handleSlicingRoom = i < 2 || (i === 2 && isPercent); + return (isPercent ? + // i == 0: centerX, relative to width + // i == 1: centerY, relative to height + // i == 2: size, relative to smallestSize + // i == 4: innerSize, relative to smallestSize + [plotWidth, plotHeight, smallestSize, smallestSize][i] * + pInt(length) / 100 : + length) + (handleSlicingRoom ? slicingRoom : 0); + }); + }, + + /** + * Do translation for pie slices + */ + translate: function (positions) { + this.generatePoints(); + + var series = this, + cumulative = 0, + precision = 1000, // issue #172 + options = series.options, + slicedOffset = options.slicedOffset, + connectorOffset = slicedOffset + options.borderWidth, + start, + end, + angle, + startAngle = options.startAngle || 0, + startAngleRad = series.startAngleRad = mathPI / 180 * (startAngle - 90), + endAngleRad = series.endAngleRad = mathPI / 180 * ((options.endAngle || (startAngle + 360)) - 90), // docs + circ = endAngleRad - startAngleRad, //2 * mathPI, + points = series.points, + radiusX, // the x component of the radius vector for a given point + radiusY, + labelDistance = options.dataLabels.distance, + ignoreHiddenPoint = options.ignoreHiddenPoint, + i, + len = points.length, + point; + + // Get positions - either an integer or a percentage string must be given. + // If positions are passed as a parameter, we're in a recursive loop for adjusting + // space for data labels. + if (!positions) { + series.center = positions = series.getCenter(); + } + + // utility for getting the x value from a given y, used for anticollision logic in data labels + series.getX = function (y, left) { + + angle = math.asin((y - positions[1]) / (positions[2] / 2 + labelDistance)); + + return positions[0] + + (left ? -1 : 1) * + (mathCos(angle) * (positions[2] / 2 + labelDistance)); + }; + + // Calculate the geometry for each point + for (i = 0; i < len; i++) { + + point = points[i]; + + // set start and end angle + start = startAngleRad + (cumulative * circ); + if (!ignoreHiddenPoint || point.visible) { + cumulative += point.percentage / 100; + } + end = startAngleRad + (cumulative * circ); + + // set the shape + point.shapeType = 'arc'; + point.shapeArgs = { + x: positions[0], + y: positions[1], + r: positions[2] / 2, + innerR: positions[3] / 2, + start: mathRound(start * precision) / precision, + end: mathRound(end * precision) / precision + }; + + // center for the sliced out slice + angle = (end + start) / 2; + if (angle > 0.75 * circ) { + angle -= 2 * mathPI; + } + point.slicedTranslation = { + translateX: mathRound(mathCos(angle) * slicedOffset), + translateY: mathRound(mathSin(angle) * slicedOffset) + }; + + // set the anchor point for tooltips + radiusX = mathCos(angle) * positions[2] / 2; + radiusY = mathSin(angle) * positions[2] / 2; + point.tooltipPos = [ + positions[0] + radiusX * 0.7, + positions[1] + radiusY * 0.7 + ]; + + point.half = angle < -mathPI / 2 || angle > mathPI / 2 ? 1 : 0; + point.angle = angle; + + // set the anchor point for data labels + connectorOffset = mathMin(connectorOffset, labelDistance / 2); // #1678 + point.labelPos = [ + positions[0] + radiusX + mathCos(angle) * labelDistance, // first break of connector + positions[1] + radiusY + mathSin(angle) * labelDistance, // a/a + positions[0] + radiusX + mathCos(angle) * connectorOffset, // second break, right outside pie + positions[1] + radiusY + mathSin(angle) * connectorOffset, // a/a + positions[0] + radiusX, // landing point for connector + positions[1] + radiusY, // a/a + labelDistance < 0 ? // alignment + 'center' : + point.half ? 'right' : 'left', // alignment + angle // center angle + ]; + + } + }, + + setTooltipPoints: noop, + drawGraph: null, + + /** + * Draw the data points + */ + drawPoints: function () { + var series = this, + chart = series.chart, + renderer = chart.renderer, + groupTranslation, + //center, + graphic, + //group, + shadow = series.options.shadow, + shadowGroup, + shapeArgs; + + if (shadow && !series.shadowGroup) { + series.shadowGroup = renderer.g('shadow') + .add(series.group); + } + + // draw the slices + each(series.points, function (point) { + graphic = point.graphic; + shapeArgs = point.shapeArgs; + shadowGroup = point.shadowGroup; + + // put the shadow behind all points + if (shadow && !shadowGroup) { + shadowGroup = point.shadowGroup = renderer.g('shadow') + .add(series.shadowGroup); + } + + // if the point is sliced, use special translation, else use plot area traslation + groupTranslation = point.sliced ? point.slicedTranslation : { + translateX: 0, + translateY: 0 + }; + + //group.translate(groupTranslation[0], groupTranslation[1]); + if (shadowGroup) { + shadowGroup.attr(groupTranslation); + } + + // draw the slice + if (graphic) { + graphic.animate(extend(shapeArgs, groupTranslation)); + } else { + point.graphic = graphic = renderer.arc(shapeArgs) + .setRadialReference(series.center) + .attr( + point.pointAttr[point.selected ? SELECT_STATE : NORMAL_STATE] + ) + .attr({ 'stroke-linejoin': 'round' }) + .attr(groupTranslation) + .add(series.group) + .shadow(shadow, shadowGroup); + } + + // detect point specific visibility + if (point.visible === false) { + point.setVisible(false); + } + + }); + + }, + + /** + * Utility for sorting data labels + */ + sortByAngle: function (points, sign) { + points.sort(function (a, b) { + return a.angle !== undefined && (b.angle - a.angle) * sign; + }); + }, + + /** + * Override the base drawDataLabels method by pie specific functionality + */ + drawDataLabels: function () { + var series = this, + data = series.data, + point, + chart = series.chart, + options = series.options.dataLabels, + connectorPadding = pick(options.connectorPadding, 10), + connectorWidth = pick(options.connectorWidth, 1), + plotWidth = chart.plotWidth, + plotHeight = chart.plotHeight, + connector, + connectorPath, + softConnector = pick(options.softConnector, true), + distanceOption = options.distance, + seriesCenter = series.center, + radius = seriesCenter[2] / 2, + centerY = seriesCenter[1], + outside = distanceOption > 0, + dataLabel, + dataLabelWidth, + labelPos, + labelHeight, + halves = [// divide the points into right and left halves for anti collision + [], // right + [] // left + ], + x, + y, + visibility, + rankArr, + i, + j, + overflow = [0, 0, 0, 0], // top, right, bottom, left + sort = function (a, b) { + return b.y - a.y; + }; + + // get out if not enabled + if (!series.visible || (!options.enabled && !series._hasPointLabels)) { + return; + } + + // run parent method + Series.prototype.drawDataLabels.apply(series); + + // arrange points for detection collision + each(data, function (point) { + if (point.dataLabel) { // it may have been cancelled in the base method (#407) + halves[point.half].push(point); + } + }); + + // assume equal label heights + i = 0; + while (!labelHeight && data[i]) { // #1569 + labelHeight = data[i] && data[i].dataLabel && (data[i].dataLabel.getBBox().height || 21); // 21 is for #968 + i++; + } + + /* Loop over the points in each half, starting from the top and bottom + * of the pie to detect overlapping labels. + */ + i = 2; + while (i--) { + + var slots = [], + slotsLength, + usedSlots = [], + points = halves[i], + pos, + length = points.length, + slotIndex; + + // Sort by angle + series.sortByAngle(points, i - 0.5); + + // Only do anti-collision when we are outside the pie and have connectors (#856) + if (distanceOption > 0) { + + // build the slots + for (pos = centerY - radius - distanceOption; pos <= centerY + radius + distanceOption; pos += labelHeight) { + slots.push(pos); + + // visualize the slot + /* + var slotX = series.getX(pos, i) + chart.plotLeft - (i ? 100 : 0), + slotY = pos + chart.plotTop; + if (!isNaN(slotX)) { + chart.renderer.rect(slotX, slotY - 7, 100, labelHeight, 1) + .attr({ + 'stroke-width': 1, + stroke: 'silver' + }) + .add(); + chart.renderer.text('Slot '+ (slots.length - 1), slotX, slotY + 4) + .attr({ + fill: 'silver' + }).add(); + } + */ + } + slotsLength = slots.length; + + // if there are more values than available slots, remove lowest values + if (length > slotsLength) { + // create an array for sorting and ranking the points within each quarter + rankArr = [].concat(points); + rankArr.sort(sort); + j = length; + while (j--) { + rankArr[j].rank = j; + } + j = length; + while (j--) { + if (points[j].rank >= slotsLength) { + points.splice(j, 1); + } + } + length = points.length; + } + + // The label goes to the nearest open slot, but not closer to the edge than + // the label's index. + for (j = 0; j < length; j++) { + + point = points[j]; + labelPos = point.labelPos; + + var closest = 9999, + distance, + slotI; + + // find the closest slot index + for (slotI = 0; slotI < slotsLength; slotI++) { + distance = mathAbs(slots[slotI] - labelPos[1]); + if (distance < closest) { + closest = distance; + slotIndex = slotI; + } + } + + // if that slot index is closer to the edges of the slots, move it + // to the closest appropriate slot + if (slotIndex < j && slots[j] !== null) { // cluster at the top + slotIndex = j; + } else if (slotsLength < length - j + slotIndex && slots[j] !== null) { // cluster at the bottom + slotIndex = slotsLength - length + j; + while (slots[slotIndex] === null) { // make sure it is not taken + slotIndex++; + } + } else { + // Slot is taken, find next free slot below. In the next run, the next slice will find the + // slot above these, because it is the closest one + while (slots[slotIndex] === null) { // make sure it is not taken + slotIndex++; + } + } + + usedSlots.push({ i: slotIndex, y: slots[slotIndex] }); + slots[slotIndex] = null; // mark as taken + } + // sort them in order to fill in from the top + usedSlots.sort(sort); + } + + // now the used slots are sorted, fill them up sequentially + for (j = 0; j < length; j++) { + + var slot, naturalY; + + point = points[j]; + labelPos = point.labelPos; + dataLabel = point.dataLabel; + visibility = point.visible === false ? HIDDEN : VISIBLE; + naturalY = labelPos[1]; + + if (distanceOption > 0) { + slot = usedSlots.pop(); + slotIndex = slot.i; + + // if the slot next to currrent slot is free, the y value is allowed + // to fall back to the natural position + y = slot.y; + if ((naturalY > y && slots[slotIndex + 1] !== null) || + (naturalY < y && slots[slotIndex - 1] !== null)) { + y = naturalY; + } + + } else { + y = naturalY; + } + + // get the x - use the natural x position for first and last slot, to prevent the top + // and botton slice connectors from touching each other on either side + x = options.justify ? + seriesCenter[0] + (i ? -1 : 1) * (radius + distanceOption) : + series.getX(slotIndex === 0 || slotIndex === slots.length - 1 ? naturalY : y, i); + + + // Record the placement and visibility + dataLabel._attr = { + visibility: visibility, + align: labelPos[6] + }; + dataLabel._pos = { + x: x + options.x + + ({ left: connectorPadding, right: -connectorPadding }[labelPos[6]] || 0), + y: y + options.y - 10 // 10 is for the baseline (label vs text) + }; + dataLabel.connX = x; + dataLabel.connY = y; + + + // Detect overflowing data labels + if (this.options.size === null) { + dataLabelWidth = dataLabel.width; + // Overflow left + if (x - dataLabelWidth < connectorPadding) { + overflow[3] = mathMax(mathRound(dataLabelWidth - x + connectorPadding), overflow[3]); + + // Overflow right + } else if (x + dataLabelWidth > plotWidth - connectorPadding) { + overflow[1] = mathMax(mathRound(x + dataLabelWidth - plotWidth + connectorPadding), overflow[1]); + } + + // Overflow top + if (y - labelHeight / 2 < 0) { + overflow[0] = mathMax(mathRound(-y + labelHeight / 2), overflow[0]); + + // Overflow left + } else if (y + labelHeight / 2 > plotHeight) { + overflow[2] = mathMax(mathRound(y + labelHeight / 2 - plotHeight), overflow[2]); + } + } + } // for each point + } // for each half + + // Do not apply the final placement and draw the connectors until we have verified + // that labels are not spilling over. + if (arrayMax(overflow) === 0 || this.verifyDataLabelOverflow(overflow)) { + + // Place the labels in the final position + this.placeDataLabels(); + + // Draw the connectors + if (outside && connectorWidth) { + each(this.points, function (point) { + connector = point.connector; + labelPos = point.labelPos; + dataLabel = point.dataLabel; + + if (dataLabel && dataLabel._pos) { + visibility = dataLabel._attr.visibility; + x = dataLabel.connX; + y = dataLabel.connY; + connectorPath = softConnector ? [ + M, + x + (labelPos[6] === 'left' ? 5 : -5), y, // end of the string at the label + 'C', + x, y, // first break, next to the label + 2 * labelPos[2] - labelPos[4], 2 * labelPos[3] - labelPos[5], + labelPos[2], labelPos[3], // second break + L, + labelPos[4], labelPos[5] // base + ] : [ + M, + x + (labelPos[6] === 'left' ? 5 : -5), y, // end of the string at the label + L, + labelPos[2], labelPos[3], // second break + L, + labelPos[4], labelPos[5] // base + ]; + + if (connector) { + connector.animate({ d: connectorPath }); + connector.attr('visibility', visibility); + + } else { + point.connector = connector = series.chart.renderer.path(connectorPath).attr({ + 'stroke-width': connectorWidth, + stroke: options.connectorColor || point.color || '#606060', + visibility: visibility + }) + .add(series.group); + } + } else if (connector) { + point.connector = connector.destroy(); + } + }); + } + } + }, + + /** + * Verify whether the data labels are allowed to draw, or we should run more translation and data + * label positioning to keep them inside the plot area. Returns true when data labels are ready + * to draw. + */ + verifyDataLabelOverflow: function (overflow) { + + var center = this.center, + options = this.options, + centerOption = options.center, + minSize = options.minSize || 80, + newSize = minSize, + ret; + + // Handle horizontal size and center + if (centerOption[0] !== null) { // Fixed center + newSize = mathMax(center[2] - mathMax(overflow[1], overflow[3]), minSize); + + } else { // Auto center + newSize = mathMax( + center[2] - overflow[1] - overflow[3], // horizontal overflow + minSize + ); + center[0] += (overflow[3] - overflow[1]) / 2; // horizontal center + } + + // Handle vertical size and center + if (centerOption[1] !== null) { // Fixed center + newSize = mathMax(mathMin(newSize, center[2] - mathMax(overflow[0], overflow[2])), minSize); + + } else { // Auto center + newSize = mathMax( + mathMin( + newSize, + center[2] - overflow[0] - overflow[2] // vertical overflow + ), + minSize + ); + center[1] += (overflow[0] - overflow[2]) / 2; // vertical center + } + + // If the size must be decreased, we need to run translate and drawDataLabels again + if (newSize < center[2]) { + center[2] = newSize; + this.translate(center); + each(this.points, function (point) { + if (point.dataLabel) { + point.dataLabel._pos = null; // reset + } + }); + this.drawDataLabels(); + + // Else, return true to indicate that the pie and its labels is within the plot area + } else { + ret = true; + } + return ret; + }, + + /** + * Perform the final placement of the data labels after we have verified that they + * fall within the plot area. + */ + placeDataLabels: function () { + each(this.points, function (point) { + var dataLabel = point.dataLabel, + _pos; + + if (dataLabel) { + _pos = dataLabel._pos; + if (_pos) { + dataLabel.attr(dataLabel._attr); + dataLabel[dataLabel.moved ? 'animate' : 'attr'](_pos); + dataLabel.moved = true; + } else if (dataLabel) { + dataLabel.attr({ y: -999 }); + } + } + }); + }, + + alignDataLabel: noop, + + /** + * Draw point specific tracker objects. Inherit directly from column series. + */ + drawTracker: ColumnSeries.prototype.drawTracker, + + /** + * Use a simple symbol from column prototype + */ + drawLegendSymbol: AreaSeries.prototype.drawLegendSymbol, + + /** + * Pies don't have point marker symbols + */ + getSymbol: noop + +}; +PieSeries = extendClass(Series, PieSeries); +seriesTypes.pie = PieSeries; + + +// global variables +extend(Highcharts, { + + // Constructors + Axis: Axis, + Chart: Chart, + Color: Color, + Legend: Legend, + Pointer: Pointer, + Point: Point, + Tick: Tick, + Tooltip: Tooltip, + Renderer: Renderer, + Series: Series, + SVGElement: SVGElement, + SVGRenderer: SVGRenderer, + + // Various + arrayMin: arrayMin, + arrayMax: arrayMax, + charts: charts, + dateFormat: dateFormat, + format: format, + pathAnim: pathAnim, + getOptions: getOptions, + hasBidiBug: hasBidiBug, + isTouchDevice: isTouchDevice, + numberFormat: numberFormat, + seriesTypes: seriesTypes, + setOptions: setOptions, + addEvent: addEvent, + removeEvent: removeEvent, + createElement: createElement, + discardElement: discardElement, + css: css, + each: each, + extend: extend, + map: map, + merge: merge, + pick: pick, + splat: splat, + extendClass: extendClass, + pInt: pInt, + wrap: wrap, + svg: hasSVG, + canvas: useCanVG, + vml: !hasSVG && !useCanVG, + product: PRODUCT, + version: VERSION +}); +}()); diff --git a/web/resource/components/ueditor/third-party/highcharts/modules/drilldown.js b/web/resource/components/ueditor/third-party/highcharts/modules/drilldown.js new file mode 100644 index 0000000..1df1acc --- /dev/null +++ b/web/resource/components/ueditor/third-party/highcharts/modules/drilldown.js @@ -0,0 +1,11 @@ +(function(e){function q(b,a,c){return"rgba("+[Math.round(b[0]+(a[0]-b[0])*c),Math.round(b[1]+(a[1]-b[1])*c),Math.round(b[2]+(a[2]-b[2])*c),b[3]+(a[3]-b[3])*c].join(",")+")"}var m=function(){},j=e.getOptions(),g=e.each,n=e.extend,o=e.wrap,h=e.Chart,i=e.seriesTypes,k=i.pie,l=i.column,r=HighchartsAdapter.fireEvent;n(j.lang,{drillUpText:"◁ Back to {series.name}"});j.drilldown={activeAxisLabelStyle:{cursor:"pointer",color:"#039",fontWeight:"bold",textDecoration:"underline"},activeDataLabelStyle:{cursor:"pointer", +color:"#039",fontWeight:"bold",textDecoration:"underline"},animation:{duration:500},drillUpButton:{position:{align:"right",x:-10,y:10}}};e.SVGRenderer.prototype.Element.prototype.fadeIn=function(){this.attr({opacity:0.1,visibility:"visible"}).animate({opacity:1},{duration:250})};h.prototype.drilldownLevels=[];h.prototype.addSeriesAsDrilldown=function(b,a){var c=b.series,d=c.xAxis,f=c.yAxis,e;e=b.color||c.color;var g,a=n({color:e},a);g=HighchartsAdapter.inArray(this,c.points);this.drilldownLevels.push({seriesOptions:c.userOptions, +shapeArgs:b.shapeArgs,bBox:b.graphic.getBBox(),color:e,newSeries:a,pointOptions:c.options.data[g],pointIndex:g,oldExtremes:{xMin:d&&d.userMin,xMax:d&&d.userMax,yMin:f&&f.userMin,yMax:f&&f.userMax}});e=this.addSeries(a,!1);if(d)d.oldPos=d.pos,d.userMin=d.userMax=null,f.userMin=f.userMax=null;if(c.type===e.type)e.animate=e.animateDrilldown||m,e.options.animation=!0;c.remove(!1);this.redraw();this.showDrillUpButton()};h.prototype.getDrilldownBackText=function(){return this.options.lang.drillUpText.replace("{series.name}", +this.drilldownLevels[this.drilldownLevels.length-1].seriesOptions.name)};h.prototype.showDrillUpButton=function(){var b=this,a=this.getDrilldownBackText(),c=b.options.drilldown.drillUpButton;this.drillUpButton?this.drillUpButton.attr({text:a}).align():this.drillUpButton=this.renderer.button(a,null,null,function(){b.drillUp()}).attr(n({align:c.position.align,zIndex:9},c.theme)).add().align(c.position,!1,c.relativeTo||"plotBox")};h.prototype.drillUp=function(){var b=this.drilldownLevels.pop(),a=this.series[0], +c=b.oldExtremes,d=this.addSeries(b.seriesOptions,!1);r(this,"drillup",{seriesOptions:b.seriesOptions});if(d.type===a.type)d.drilldownLevel=b,d.animate=d.animateDrillupTo||m,d.options.animation=!0,a.animateDrillupFrom&&a.animateDrillupFrom(b);a.remove(!1);d.xAxis&&(d.xAxis.setExtremes(c.xMin,c.xMax,!1),d.yAxis.setExtremes(c.yMin,c.yMax,!1));this.redraw();this.drilldownLevels.length===0?this.drillUpButton=this.drillUpButton.destroy():this.drillUpButton.attr({text:this.getDrilldownBackText()}).align()}; +k.prototype.animateDrilldown=function(b){var a=this.chart.drilldownLevels[this.chart.drilldownLevels.length-1],c=this.chart.options.drilldown.animation,d=a.shapeArgs,f=d.start,s=(d.end-f)/this.points.length,h=e.Color(a.color).rgba;b||g(this.points,function(a,b){var g=e.Color(a.color).rgba;a.graphic.attr(e.merge(d,{start:f+b*s,end:f+(b+1)*s})).animate(a.shapeArgs,e.merge(c,{step:function(a,d){d.prop==="start"&&this.attr({fill:q(h,g,d.pos)})}}))})};k.prototype.animateDrillupTo=l.prototype.animateDrillupTo= +function(b){if(!b){var a=this,c=a.drilldownLevel;g(this.points,function(a){a.graphic.hide();a.dataLabel&&a.dataLabel.hide();a.connector&&a.connector.hide()});setTimeout(function(){g(a.points,function(a,b){var e=b===c.pointIndex?"show":"fadeIn";a.graphic[e]();if(a.dataLabel)a.dataLabel[e]();if(a.connector)a.connector[e]()})},Math.max(this.chart.options.drilldown.animation.duration-50,0));this.animate=m}};l.prototype.animateDrilldown=function(b){var a=this.chart.drilldownLevels[this.chart.drilldownLevels.length- +1].shapeArgs,c=this.chart.options.drilldown.animation;b||(a.x+=this.xAxis.oldPos-this.xAxis.pos,g(this.points,function(b){b.graphic.attr(a).animate(b.shapeArgs,c)}))};l.prototype.animateDrillupFrom=k.prototype.animateDrillupFrom=function(b){var a=this.chart.options.drilldown.animation,c=this.group;delete this.group;g(this.points,function(d){var f=d.graphic,g=e.Color(d.color).rgba;delete d.graphic;f.animate(b.shapeArgs,e.merge(a,{step:function(a,c){c.prop==="start"&&this.attr({fill:q(g,e.Color(b.color).rgba, +c.pos)})},complete:function(){f.destroy();c&&(c=c.destroy())}}))})};e.Point.prototype.doDrilldown=function(){for(var b=this.series.chart,a=b.options.drilldown,c=a.series.length,d;c--&&!d;)a.series[c].id===this.drilldown&&(d=a.series[c]);r(b,"drilldown",{point:this,seriesOptions:d});d&&b.addSeriesAsDrilldown(this,d)};o(e.Point.prototype,"init",function(b,a,c,d){var f=b.call(this,a,c,d),b=a.chart,a=(a=a.xAxis&&a.xAxis.ticks[d])&&a.label;if(f.drilldown){if(e.addEvent(f,"click",function(){f.doDrilldown()}), +a){if(!a._basicStyle)a._basicStyle=a.element.getAttribute("style");a.addClass("highcharts-drilldown-axis-label").css(b.options.drilldown.activeAxisLabelStyle).on("click",function(){f.doDrilldown&&f.doDrilldown()})}}else a&&a._basicStyle&&a.element.setAttribute("style",a._basicStyle);return f});o(e.Series.prototype,"drawDataLabels",function(b){var a=this.chart.options.drilldown.activeDataLabelStyle;b.call(this);g(this.points,function(b){if(b.drilldown&&b.dataLabel)b.dataLabel.attr({"class":"highcharts-drilldown-data-label"}).css(a).on("click", +function(){b.doDrilldown()})})});l.prototype.supportsDrilldown=!0;k.prototype.supportsDrilldown=!0;var p,j=function(b){b.call(this);g(this.points,function(a){a.drilldown&&a.graphic&&a.graphic.attr({"class":"highcharts-drilldown-point"}).css({cursor:"pointer"})})};for(p in i)i[p].prototype.supportsDrilldown&&o(i[p].prototype,"drawTracker",j)})(Highcharts); diff --git a/web/resource/components/ueditor/third-party/highcharts/modules/drilldown.src.js b/web/resource/components/ueditor/third-party/highcharts/modules/drilldown.src.js new file mode 100644 index 0000000..558aed4 --- /dev/null +++ b/web/resource/components/ueditor/third-party/highcharts/modules/drilldown.src.js @@ -0,0 +1,447 @@ +/** + * Highcharts Drilldown plugin + * + * Author: Torstein Honsi + * Last revision: 2013-02-18 + * License: MIT License + * + * Demo: http://jsfiddle.net/highcharts/Vf3yT/ + */ + +/*global HighchartsAdapter*/ +(function (H) { + + "use strict"; + + var noop = function () {}, + defaultOptions = H.getOptions(), + each = H.each, + extend = H.extend, + wrap = H.wrap, + Chart = H.Chart, + seriesTypes = H.seriesTypes, + PieSeries = seriesTypes.pie, + ColumnSeries = seriesTypes.column, + fireEvent = HighchartsAdapter.fireEvent; + + // Utilities + function tweenColors(startColor, endColor, pos) { + var rgba = [ + Math.round(startColor[0] + (endColor[0] - startColor[0]) * pos), + Math.round(startColor[1] + (endColor[1] - startColor[1]) * pos), + Math.round(startColor[2] + (endColor[2] - startColor[2]) * pos), + startColor[3] + (endColor[3] - startColor[3]) * pos + ]; + return 'rgba(' + rgba.join(',') + ')'; + } + + // Add language + extend(defaultOptions.lang, { + drillUpText: '◁ Back to {series.name}' + }); + defaultOptions.drilldown = { + activeAxisLabelStyle: { + cursor: 'pointer', + color: '#039', + fontWeight: 'bold', + textDecoration: 'underline' + }, + activeDataLabelStyle: { + cursor: 'pointer', + color: '#039', + fontWeight: 'bold', + textDecoration: 'underline' + }, + animation: { + duration: 500 + }, + drillUpButton: { + position: { + align: 'right', + x: -10, + y: 10 + } + // relativeTo: 'plotBox' + // theme + } + }; + + /** + * A general fadeIn method + */ + H.SVGRenderer.prototype.Element.prototype.fadeIn = function () { + this + .attr({ + opacity: 0.1, + visibility: 'visible' + }) + .animate({ + opacity: 1 + }, { + duration: 250 + }); + }; + + // Extend the Chart prototype + Chart.prototype.drilldownLevels = []; + + Chart.prototype.addSeriesAsDrilldown = function (point, ddOptions) { + var oldSeries = point.series, + xAxis = oldSeries.xAxis, + yAxis = oldSeries.yAxis, + newSeries, + color = point.color || oldSeries.color, + pointIndex, + level; + + ddOptions = extend({ + color: color + }, ddOptions); + pointIndex = HighchartsAdapter.inArray(this, oldSeries.points); + level = { + seriesOptions: oldSeries.userOptions, + shapeArgs: point.shapeArgs, + bBox: point.graphic.getBBox(), + color: color, + newSeries: ddOptions, + pointOptions: oldSeries.options.data[pointIndex], + pointIndex: pointIndex, + oldExtremes: { + xMin: xAxis && xAxis.userMin, + xMax: xAxis && xAxis.userMax, + yMin: yAxis && yAxis.userMin, + yMax: yAxis && yAxis.userMax + } + }; + + this.drilldownLevels.push(level); + + newSeries = this.addSeries(ddOptions, false); + if (xAxis) { + xAxis.oldPos = xAxis.pos; + xAxis.userMin = xAxis.userMax = null; + yAxis.userMin = yAxis.userMax = null; + } + + // Run fancy cross-animation on supported and equal types + if (oldSeries.type === newSeries.type) { + newSeries.animate = newSeries.animateDrilldown || noop; + newSeries.options.animation = true; + } + + oldSeries.remove(false); + + this.redraw(); + this.showDrillUpButton(); + }; + + Chart.prototype.getDrilldownBackText = function () { + var lastLevel = this.drilldownLevels[this.drilldownLevels.length - 1]; + + return this.options.lang.drillUpText.replace('{series.name}', lastLevel.seriesOptions.name); + + }; + + Chart.prototype.showDrillUpButton = function () { + var chart = this, + backText = this.getDrilldownBackText(), + buttonOptions = chart.options.drilldown.drillUpButton; + + + if (!this.drillUpButton) { + this.drillUpButton = this.renderer.button( + backText, + null, + null, + function () { + chart.drillUp(); + } + ) + .attr(extend({ + align: buttonOptions.position.align, + zIndex: 9 + }, buttonOptions.theme)) + .add() + .align(buttonOptions.position, false, buttonOptions.relativeTo || 'plotBox'); + } else { + this.drillUpButton.attr({ + text: backText + }) + .align(); + } + }; + + Chart.prototype.drillUp = function () { + var chart = this, + level = chart.drilldownLevels.pop(), + oldSeries = chart.series[0], + oldExtremes = level.oldExtremes, + newSeries = chart.addSeries(level.seriesOptions, false); + + fireEvent(chart, 'drillup', { seriesOptions: level.seriesOptions }); + + if (newSeries.type === oldSeries.type) { + newSeries.drilldownLevel = level; + newSeries.animate = newSeries.animateDrillupTo || noop; + newSeries.options.animation = true; + + if (oldSeries.animateDrillupFrom) { + oldSeries.animateDrillupFrom(level); + } + } + + oldSeries.remove(false); + + // Reset the zoom level of the upper series + if (newSeries.xAxis) { + newSeries.xAxis.setExtremes(oldExtremes.xMin, oldExtremes.xMax, false); + newSeries.yAxis.setExtremes(oldExtremes.yMin, oldExtremes.yMax, false); + } + + + this.redraw(); + + if (this.drilldownLevels.length === 0) { + this.drillUpButton = this.drillUpButton.destroy(); + } else { + this.drillUpButton.attr({ + text: this.getDrilldownBackText() + }) + .align(); + } + }; + + PieSeries.prototype.animateDrilldown = function (init) { + var level = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1], + animationOptions = this.chart.options.drilldown.animation, + animateFrom = level.shapeArgs, + start = animateFrom.start, + angle = animateFrom.end - start, + startAngle = angle / this.points.length, + startColor = H.Color(level.color).rgba; + + if (!init) { + each(this.points, function (point, i) { + var endColor = H.Color(point.color).rgba; + + /*jslint unparam: true*/ + point.graphic + .attr(H.merge(animateFrom, { + start: start + i * startAngle, + end: start + (i + 1) * startAngle + })) + .animate(point.shapeArgs, H.merge(animationOptions, { + step: function (val, fx) { + if (fx.prop === 'start') { + this.attr({ + fill: tweenColors(startColor, endColor, fx.pos) + }); + } + } + })); + /*jslint unparam: false*/ + }); + } + }; + + + /** + * When drilling up, keep the upper series invisible until the lower series has + * moved into place + */ + PieSeries.prototype.animateDrillupTo = + ColumnSeries.prototype.animateDrillupTo = function (init) { + if (!init) { + var newSeries = this, + level = newSeries.drilldownLevel; + + each(this.points, function (point) { + point.graphic.hide(); + if (point.dataLabel) { + point.dataLabel.hide(); + } + if (point.connector) { + point.connector.hide(); + } + }); + + + // Do dummy animation on first point to get to complete + setTimeout(function () { + each(newSeries.points, function (point, i) { + // Fade in other points + var verb = i === level.pointIndex ? 'show' : 'fadeIn'; + point.graphic[verb](); + if (point.dataLabel) { + point.dataLabel[verb](); + } + if (point.connector) { + point.connector[verb](); + } + }); + }, Math.max(this.chart.options.drilldown.animation.duration - 50, 0)); + + // Reset + this.animate = noop; + } + + }; + + ColumnSeries.prototype.animateDrilldown = function (init) { + var animateFrom = this.chart.drilldownLevels[this.chart.drilldownLevels.length - 1].shapeArgs, + animationOptions = this.chart.options.drilldown.animation; + + if (!init) { + + animateFrom.x += (this.xAxis.oldPos - this.xAxis.pos); + + each(this.points, function (point) { + point.graphic + .attr(animateFrom) + .animate(point.shapeArgs, animationOptions); + }); + } + + }; + + /** + * When drilling up, pull out the individual point graphics from the lower series + * and animate them into the origin point in the upper series. + */ + ColumnSeries.prototype.animateDrillupFrom = + PieSeries.prototype.animateDrillupFrom = + function (level) { + var animationOptions = this.chart.options.drilldown.animation, + group = this.group; + + delete this.group; + each(this.points, function (point) { + var graphic = point.graphic, + startColor = H.Color(point.color).rgba; + + delete point.graphic; + + /*jslint unparam: true*/ + graphic.animate(level.shapeArgs, H.merge(animationOptions, { + + step: function (val, fx) { + if (fx.prop === 'start') { + this.attr({ + fill: tweenColors(startColor, H.Color(level.color).rgba, fx.pos) + }); + } + }, + complete: function () { + graphic.destroy(); + if (group) { + group = group.destroy(); + } + } + })); + /*jslint unparam: false*/ + }); + }; + + H.Point.prototype.doDrilldown = function () { + var series = this.series, + chart = series.chart, + drilldown = chart.options.drilldown, + i = drilldown.series.length, + seriesOptions; + + while (i-- && !seriesOptions) { + if (drilldown.series[i].id === this.drilldown) { + seriesOptions = drilldown.series[i]; + } + } + + // Fire the event. If seriesOptions is undefined, the implementer can check for + // seriesOptions, and call addSeriesAsDrilldown async if necessary. + fireEvent(chart, 'drilldown', { + point: this, + seriesOptions: seriesOptions + }); + + if (seriesOptions) { + chart.addSeriesAsDrilldown(this, seriesOptions); + } + + }; + + wrap(H.Point.prototype, 'init', function (proceed, series, options, x) { + var point = proceed.call(this, series, options, x), + chart = series.chart, + tick = series.xAxis && series.xAxis.ticks[x], + tickLabel = tick && tick.label; + + if (point.drilldown) { + + // Add the click event to the point label + H.addEvent(point, 'click', function () { + point.doDrilldown(); + }); + + // Make axis labels clickable + if (tickLabel) { + if (!tickLabel._basicStyle) { + tickLabel._basicStyle = tickLabel.element.getAttribute('style'); + } + tickLabel + .addClass('highcharts-drilldown-axis-label') + .css(chart.options.drilldown.activeAxisLabelStyle) + .on('click', function () { + if (point.doDrilldown) { + point.doDrilldown(); + } + }); + + } + } else if (tickLabel && tickLabel._basicStyle) { + tickLabel.element.setAttribute('style', tickLabel._basicStyle); + } + + return point; + }); + + wrap(H.Series.prototype, 'drawDataLabels', function (proceed) { + var css = this.chart.options.drilldown.activeDataLabelStyle; + + proceed.call(this); + + each(this.points, function (point) { + if (point.drilldown && point.dataLabel) { + point.dataLabel + .attr({ + 'class': 'highcharts-drilldown-data-label' + }) + .css(css) + .on('click', function () { + point.doDrilldown(); + }); + } + }); + }); + + // Mark the trackers with a pointer + ColumnSeries.prototype.supportsDrilldown = true; + PieSeries.prototype.supportsDrilldown = true; + var type, + drawTrackerWrapper = function (proceed) { + proceed.call(this); + each(this.points, function (point) { + if (point.drilldown && point.graphic) { + point.graphic + .attr({ + 'class': 'highcharts-drilldown-point' + }) + .css({ cursor: 'pointer' }); + } + }); + }; + for (type in seriesTypes) { + if (seriesTypes[type].prototype.supportsDrilldown) { + wrap(seriesTypes[type].prototype, 'drawTracker', drawTrackerWrapper); + } + } + +}(Highcharts)); diff --git a/web/resource/components/ueditor/third-party/highcharts/modules/exporting.js b/web/resource/components/ueditor/third-party/highcharts/modules/exporting.js new file mode 100644 index 0000000..8ec202c --- /dev/null +++ b/web/resource/components/ueditor/third-party/highcharts/modules/exporting.js @@ -0,0 +1,22 @@ +/* + Highcharts JS v3.0.6 (2013-10-04) + Exporting module + + (c) 2010-2013 Torstein Hønsi + + License: www.highcharts.com/license +*/ +(function(f){var A=f.Chart,t=f.addEvent,C=f.removeEvent,k=f.createElement,n=f.discardElement,u=f.css,o=f.merge,r=f.each,p=f.extend,D=Math.max,j=document,B=window,E=f.isTouchDevice,F=f.Renderer.prototype.symbols,x=f.getOptions(),y;p(x.lang,{printChart:"Print chart",downloadPNG:"Download PNG image",downloadJPEG:"Download JPEG image",downloadPDF:"Download PDF document",downloadSVG:"Download SVG vector image",contextButtonTitle:"Chart context menu"});x.navigation={menuStyle:{border:"1px solid #A0A0A0", +background:"#FFFFFF",padding:"5px 0"},menuItemStyle:{padding:"0 10px",background:"none",color:"#303030",fontSize:E?"14px":"11px"},menuItemHoverStyle:{background:"#4572A5",color:"#FFFFFF"},buttonOptions:{symbolFill:"#E0E0E0",symbolSize:14,symbolStroke:"#666",symbolStrokeWidth:3,symbolX:12.5,symbolY:10.5,align:"right",buttonSpacing:3,height:22,theme:{fill:"white",stroke:"none"},verticalAlign:"top",width:24}};x.exporting={type:"image/png",url:"http://export.highcharts.com/",buttons:{contextButton:{menuClassName:"highcharts-contextmenu", +symbol:"menu",_titleKey:"contextButtonTitle",menuItems:[{textKey:"printChart",onclick:function(){this.print()}},{separator:!0},{textKey:"downloadPNG",onclick:function(){this.exportChart()}},{textKey:"downloadJPEG",onclick:function(){this.exportChart({type:"image/jpeg"})}},{textKey:"downloadPDF",onclick:function(){this.exportChart({type:"application/pdf"})}},{textKey:"downloadSVG",onclick:function(){this.exportChart({type:"image/svg+xml"})}}]}}};f.post=function(c,a){var d,b;b=k("form",{method:"post", +action:c,enctype:"multipart/form-data"},{display:"none"},j.body);for(d in a)k("input",{type:"hidden",name:d,value:a[d]},null,b);b.submit();n(b)};p(A.prototype,{getSVG:function(c){var a=this,d,b,z,h,g=o(a.options,c);if(!j.createElementNS)j.createElementNS=function(a,b){return j.createElement(b)};c=k("div",null,{position:"absolute",top:"-9999em",width:a.chartWidth+"px",height:a.chartHeight+"px"},j.body);b=a.renderTo.style.width;h=a.renderTo.style.height;b=g.exporting.sourceWidth||g.chart.width||/px$/.test(b)&& +parseInt(b,10)||600;h=g.exporting.sourceHeight||g.chart.height||/px$/.test(h)&&parseInt(h,10)||400;p(g.chart,{animation:!1,renderTo:c,forExport:!0,width:b,height:h});g.exporting.enabled=!1;g.series=[];r(a.series,function(a){z=o(a.options,{animation:!1,showCheckbox:!1,visible:a.visible});z.isInternal||g.series.push(z)});d=new f.Chart(g,a.callback);r(["xAxis","yAxis"],function(b){r(a[b],function(a,c){var g=d[b][c],f=a.getExtremes(),h=f.userMin,f=f.userMax;g&&(h!==void 0||f!==void 0)&&g.setExtremes(h, +f,!0,!1)})});b=d.container.innerHTML;g=null;d.destroy();n(c);b=b.replace(/zIndex="[^"]+"/g,"").replace(/isShadow="[^"]+"/g,"").replace(/symbolName="[^"]+"/g,"").replace(/jQuery[0-9]+="[^"]+"/g,"").replace(/url\([^#]+#/g,"url(#").replace(/.*?$/,"").replace(/ /g," ").replace(/­/g,"­").replace(//g,'xlink:href="$1"/>').replace(/id=([^" >]+)/g,'id="$1"').replace(/class=([^" >]+)/g,'class="$1"').replace(/ transform /g," ").replace(/:(path|rect)/g,"$1").replace(/style="([^"]+)"/g,function(a){return a.toLowerCase()});return b=b.replace(/(url\(#highcharts-[0-9]+)"/g,"$1").replace(/"/g,"'")},exportChart:function(c,a){var c=c||{},d=this.options.exporting,d=this.getSVG(o({chart:{borderRadius:0}},d.chartOptions,a,{exporting:{sourceWidth:c.sourceWidth|| +d.sourceWidth,sourceHeight:c.sourceHeight||d.sourceHeight}})),c=o(this.options.exporting,c);f.post(c.url,{filename:c.filename||"chart",type:c.type,width:c.width||0,scale:c.scale||2,svg:d})},print:function(){var c=this,a=c.container,d=[],b=a.parentNode,f=j.body,h=f.childNodes;if(!c.isPrinting)c.isPrinting=!0,r(h,function(a,b){if(a.nodeType===1)d[b]=a.style.display,a.style.display="none"}),f.appendChild(a),B.focus(),B.print(),setTimeout(function(){b.appendChild(a);r(h,function(a,b){if(a.nodeType=== +1)a.style.display=d[b]});c.isPrinting=!1},1E3)},contextMenu:function(c,a,d,b,f,h,g){var e=this,j=e.options.navigation,q=j.menuItemStyle,l=e.chartWidth,m=e.chartHeight,o="cache-"+c,i=e[o],s=D(f,h),v,w,n;if(!i)e[o]=i=k("div",{className:c},{position:"absolute",zIndex:1E3,padding:s+"px"},e.container),v=k("div",null,p({MozBoxShadow:"3px 3px 10px #888",WebkitBoxShadow:"3px 3px 10px #888",boxShadow:"3px 3px 10px #888"},j.menuStyle),i),w=function(){u(i,{display:"none"});g&&g.setState(0);e.openMenu=!1},t(i, +"mouseleave",function(){n=setTimeout(w,500)}),t(i,"mouseenter",function(){clearTimeout(n)}),t(document,"mousedown",function(a){e.pointer.inClass(a.target,c)||w()}),r(a,function(a){if(a){var b=a.separator?k("hr",null,null,v):k("div",{onmouseover:function(){u(this,j.menuItemHoverStyle)},onmouseout:function(){u(this,q)},onclick:function(){w();a.onclick.apply(e,arguments)},innerHTML:a.text||e.options.lang[a.textKey]},p({cursor:"pointer"},q),v);e.exportDivElements.push(b)}}),e.exportDivElements.push(v, +i),e.exportMenuWidth=i.offsetWidth,e.exportMenuHeight=i.offsetHeight;a={display:"block"};d+e.exportMenuWidth>l?a.right=l-d-f-s+"px":a.left=d-s+"px";b+h+e.exportMenuHeight>m&&g.alignOptions.verticalAlign!=="top"?a.bottom=m-b-s+"px":a.top=b+h-s+"px";u(i,a);e.openMenu=!0},addButton:function(c){var a=this,d=a.renderer,b=o(a.options.navigation.buttonOptions,c),j=b.onclick,h=b.menuItems,g,e,k={stroke:b.symbolStroke,fill:b.symbolFill},q=b.symbolSize||12;if(!a.btnCount)a.btnCount=0;if(!a.exportDivElements)a.exportDivElements= +[],a.exportSVGElements=[];if(b.enabled!==!1){var l=b.theme,m=l.states,n=m&&m.hover,m=m&&m.select,i;delete l.states;j?i=function(){j.apply(a,arguments)}:h&&(i=function(){a.contextMenu(e.menuClassName,h,e.translateX,e.translateY,e.width,e.height,e);e.setState(2)});b.text&&b.symbol?l.paddingLeft=f.pick(l.paddingLeft,25):b.text||p(l,{width:b.width,height:b.height,padding:0});e=d.button(b.text,0,0,i,l,n,m).attr({title:a.options.lang[b._titleKey],"stroke-linecap":"round"});e.menuClassName=c.menuClassName|| +"highcharts-menu-"+a.btnCount++;b.symbol&&(g=d.symbol(b.symbol,b.symbolX-q/2,b.symbolY-q/2,q,q).attr(p(k,{"stroke-width":b.symbolStrokeWidth||1,zIndex:1})).add(e));e.add().align(p(b,{width:e.width,x:f.pick(b.x,y)}),!0,"spacingBox");y+=(e.width+b.buttonSpacing)*(b.align==="right"?-1:1);a.exportSVGElements.push(e,g)}},destroyExport:function(c){var c=c.target,a,d;for(a=0;a
重新上传失败图片或忽略')):(a=d.getStats(),b="共"+fileCount+"张("+c.formatSize(fileSize)+"),已上传"+a.successNum+"张",a.uploadFailNum&&(b+=",失败"+a.uploadFailNum+"张")),m.html(b)}function h(a){var b;if(a!==state){switch(n.removeClass("state-"+state),n.addClass("state-"+a),state=a,state){case"pedding":o.removeClass("element-invisible"),k.hide(),d.refresh();break;case"ready":o.addClass("element-invisible"),k.show(),d.refresh();break;case"uploading":p.show(),n.text("暂停上传");break;case"paused":p.hide(),n.text("确定使用");break;case"confirm":if(p.hide(),n.text("确定使用").addClass("disabled"),b=d.getStats(),b.successNum&&!b.uploadFailNum)return void h("finish");break;case"finish":if(n.removeClass("disabled"),b=d.getStats(),b.successNum){if(d.uploadedFiles.length>0)return i.finish(d.uploadedFiles),void d.resetUploader()}else state="done",location.reload()}g()}}var i=this;i.modalobj.find("#li_upload a").html("上传图片"),i.modalobj.find(".modal-body").append(this.buildHtml().uploaderDialog);var j=a("#uploader"),k=a('').appendTo(j.find(".queueList")),l=j.find(".statusBar"),m=l.find(".info"),n=j.find(".uploadBtn"),o=j.find(".placeholder"),p=l.find(".progress").hide();j.find(".btn-primary");fileCount=0,fileSize=0,ratio=window.devicePixelRatio||1,thumbnailWidth=110*ratio,thumbnailHeight=110*ratio,state="pedding",percentages={},supportTransition=function(){var a=document.createElement("p").style,b="transition"in a||"WebkitTransition"in a||"MozTransition"in a||"msTransition"in a||"OTransition"in a;return a=null,b}(),d;var q={pick:{id:"#filePicker",label:"点击选择图片",multiple:!0},dnd:"#dndArea",paste:"#uploader",swf:"./resource/componets/webuploader/Uploader.swf",server:"./index.php?c=utility&a=file&do=upload&type=image",chunked:!1,compress:!1,accept:{title:"Images",extensions:"gif,jpg,jpeg,bmp,png",mimeTypes:"image/*"},fileNumLimit:30,fileSizeLimit:4194304,fileSingleSizeLimit:125829120,auto:!1};q=a.extend({},q,i.options.uploader),q.pick.multiple=i.options.multiple,d=c.create(q),d.uploadedFiles=[],d.addButton({id:"#filePicker2",label:"+",multiple:i.options.multiple}),accept=0,d.resetUploader=function(){fileCount=0,fileSize=0,accept=0,d.uploadedFiles=[],a.each(d.getFiles(),function(a,b){e(b)}),d.refresh(),d.reset(),n.removeClass("disabled"),h("pedding")},d.onUploadProgress=function(b,c){var d=a("#"+b.id),e=d.find(".progress span");e.css("width",100*c+"%"),percentages[b.id][1]=c,fileid=b.id,f()},d.onFileQueued=function(a){fileCount++,fileSize+=a.size,1===fileCount&&(o.addClass("element-invisible"),l.show()),b(a),h("ready"),f()},d.onFileDequeued=function(a){fileCount--,fileSize-=a.size,fileCount||h("pedding"),e(a),f()},d.on("all",function(a){switch(a){case"uploadFinished":h("confirm");break;case"startUpload":h("uploading");break;case"stopUpload":h("paused")}}),d.on("uploadSuccess",function(b,c){return c.message?(alert(c.message),void d.resetUploader()):void(c.attachment&&(accept++,d.uploadedFiles.push(c),a("#"+b.id).append(''+c.width+"x"+c.height+""),a(".accept").text("成功上传 "+accept+" 张图片")))}),d.onError=function(a){return"Q_EXCEED_SIZE_LIMIT"==a?void alert("错误信息: 图片大于 "+c.formatSize(q.fileSizeLimit)+" 无法上传."):"F_DUPLICATE"==a?void alert("错误信息: 不能重复上传图片."):void alert("Eroor: "+a)},n.on("click",function(){return a(this).hasClass("disabled")?!1:void("ready"===state?d.upload():"paused"===state?d.upload():"uploading"===state&&d.stop())}),m.on("click",".retry",function(){d.retry()}),m.on("click",".ignore",function(){}),n.addClass("state-"+state),f()},initAudioUploader:function(){function b(b){var e=a('
  • '+b.name+'

  • '),f=a('
    删除
    ').appendTo(e),g=e.find("p.progress span"),h=e.find("p.imgWrap"),j=a('

    '),l=function(a){switch(a){case"exceed_size":text="文件大小超出";break;case"interrupt":text="上传暂停";break;default:text="上传失败,请重试"}j.text(text).appendTo(e)};"invalid"===b.getStatus()?l(b.statusText):(h.text(c.formatSize(b.size)+" kb"),percentages[b.id]=[b.size,0],b.rotation=0),b.on("statuschange",function(a,c){"progress"===c?g.hide().width(0):"queued"===c&&(e.off("mouseenter mouseleave"),f.remove()),"error"===a||"invalid"===a?(l(b.statusText),percentages[b.id][1]=1):"interrupt"===a?l("interrupt"):"queued"===a?percentages[b.id][1]=0:"progress"===a&&j.remove(),e.removeClass("state-"+c).addClass("state-"+a)}),e.on("mouseenter",function(){f.stop().animate({height:30})}),e.on("mouseleave",function(){f.stop().animate({height:0})}),f.on("click","span",function(){var c,e=a(this).index();switch(e){case 0:return void d.removeFile(b);case 1:b.rotation+=90;break;case 2:b.rotation-=90}supportTransition?(c="rotate("+b.rotation+"deg)",h.css({"-webkit-transform":c,"-mos-transform":c,"-o-transform":c,transform:c})):h.css("filter","progid:DXImageTransform.Microsoft.BasicImage(rotation="+~~(b.rotation/90%4+4)%4+")")}),i.options.multiple&&k.find(".fileinput-button").show(),e.insertBefore(k.find(".fileinput-button"))}function e(b){var c=a("#"+b.id);delete percentages[b.id],f(),c.off().find(".file-panel").off().end().remove()}function f(){var b,c=0,d=0,e=p.children();a.each(percentages,function(a,b){d+=b[0],c+=b[0]*b[1]}),b=d?c/d:0,e.eq(0).text(Math.round(100*b)+"%"),e.eq(1).css("width",Math.round(100*b)+"%"),g()}function g(){var a,b="";"ready"===state?b="选中"+fileCount+"个音频,共"+c.formatSize(fileSize)+"。":"confirm"===state?(a=d.getStats(),a.uploadFailNum&&(b="已上传"+a.successNum+"个音频,"+a.uploadFailNum+'个音频上传失败,重新上传失败音频文件或忽略')):(a=d.getStats(),b="共"+fileCount+"张("+c.formatSize(fileSize)+"),已上传"+a.successNum+"个",a.uploadFailNum&&(b+=",失败"+a.uploadFailNum+"个")),m.html(b)}function h(a){var b;if(a!==state){switch(n.removeClass("state-"+state),n.addClass("state-"+a),state=a,state){case"pedding":o.removeClass("element-invisible"),k.hide(),d.refresh();break;case"ready":o.addClass("element-invisible"),k.show(),d.refresh();break;case"uploading":p.show(),n.text("暂停上传");break;case"paused":p.show(),n.text("继续上传");break;case"confirm":if(p.hide(),n.text("确定使用").addClass("disabled"),b=d.getStats(),b.successNum&&!b.uploadFailNum)return void h("finish");break;case"finish":if(n.removeClass("disabled"),b=d.getStats(),b.successNum){if(d.uploadedFiles.length>0)return i.finish(d.uploadedFiles),void d.resetUploader()}else state="done",location.reload()}g()}}var i=this;i.modalobj.find("#li_upload a").html("上传音频"),i.modalobj.find(".modal-body").append(this.buildHtml().uploaderDialog);var j=a("#uploader"),k=a('').appendTo(j.find(".queueList")),l=j.find(".statusBar"),m=l.find(".info"),n=j.find(".uploadBtn"),o=j.find(".placeholder"),p=l.find(".progress").hide();j.find(".btn-primary");fileCount=0,fileSize=0,ratio=window.devicePixelRatio||1,state="pedding",percentages={},supportTransition=function(){var a=document.createElement("p").style,b="transition"in a||"WebkitTransition"in a||"MozTransition"in a||"msTransition"in a||"OTransition"in a;return a=null,b}(),d;var q={pick:{id:"#filePicker",label:"点击选择音频",multiple:!0},dnd:"#dndArea",paste:"#uploader",swf:"./resource/componets/webuploader/Uploader.swf",server:"./index.php?c=utility&a=file&do=upload&type=audio",chunked:!1,compress:!1,accept:{title:"Audios",extensions:"mp3,wma,wav,amr",mimeTypes:"audio/*"},fileNumLimit:30,fileSizeLimit:6291456,fileSingleSizeLimit:125829120,auto:!1};q=a.extend({},q,i.options.uploader),a("#dndArea p").html("最大支持 "+c.formatSize(q.fileSizeLimit)+" MB 以内的语音 ("+q.accept.extensions+" 格式)"),q.pick.multiple=i.options.multiple,d=c.create(q),d.uploadedFiles=[],d.addButton({id:"#filePicker2",label:"+",multiple:i.options.multiple}),accept=0,d.resetUploader=function(){fileCount=0,fileSize=0,accept=0,d.uploadedFiles=[],a.each(d.getFiles(),function(a,b){e(b)}),d.refresh(),d.reset(),n.removeClass("disabled"),h("pedding")},d.onUploadProgress=function(b,c){var d=a("#"+b.id),e=d.find(".progress span");e.css("width",100*c+"%"),percentages[b.id][1]=c,fileid=b.id,f()},d.onFileQueued=function(a){fileCount++,fileSize+=a.size,1===fileCount&&(o.addClass("element-invisible"),l.show()),b(a),h("ready"),f()},d.onFileDequeued=function(a){fileCount--,fileSize-=a.size,fileCount||h("pedding"),e(a),f()},d.on("all",function(a){switch(a){case"uploadFinished":h("confirm");break;case"startUpload":h("uploading");break;case"stopUpload":h("paused")}}),d.on("uploadSuccess",function(b,c){return c.error?(alert(c.message),d.resetUploader(),!1):void(c.attachment&&(accept++,d.uploadedFiles.push(c),a("#"+b.id).append(''+c.width+"x"+c.height+""),a(".accept").text("成功上传 "+accept+" 个音频")))}),d.onError=function(a){return"Q_EXCEED_SIZE_LIMIT"==a?void alert("错误信息: 音频大于 "+c.formatSize(q.fileSizeLimit)+" 无法上传."):"F_DUPLICATE"==a?void alert("错误信息: 不能重复上传音频."):void alert("Eroor: "+a)},n.on("click",function(){return a(this).hasClass("disabled")?!1:void("ready"===state?d.upload():"paused"===state?d.upload():"uploading"===state&&d.stop())}),m.on("click",".retry",function(){d.retry()}),m.on("click",".ignore",function(){}),n.addClass("state-"+state),f()},finish:function(b){var c=this;a.isFunction(c.options.callback)&&(0==c.options.multiple?c.options.callback(b[0]):c.options.callback(b),c.modalobj.modal("hide"))},buildHtml:function(){var a={};return a.mainDialog='',a.remoteDialog='
    \n
    \n
    \n
    \n \n \n
    \n \n
    \n
    \n
    \n
    \n \n
    ',a.localDialog='
    \n
    \n \n
    ",a.uploaderDialog='
    \n
    \n
    \n
    \n
    xx
    \n'+(this.options.multiple?'

    或将照片拖到这里,单次最多可选30张

    \n':'

    或将照片拖到这里

    \n')+'
    \n
    \n
    \n
    \n
    \n 0%\n \n
    \n
    \n
    \n
    \n
    \n
    确定使用
    \n \n
    \n
    \n
    \n
    ',a.localDialogLi='
      \n<%var items = _.sortBy(items, function(item) {return -item.id;});%><%_.each(items, function(item) {%> \n
    • \n
      \n
      \n
      \n
      \n
    • \n<%});%>\n
    ',a.localAudioDialog='
    \n
    \n \n \n \n \n \n \n \n \n \n \n
    标题创建时间\n
    \n \n \n \n \n
    \n
    \n \n
    ",a.localAudioDialogLi='<%var items = _.sortBy(items, function(item) {return -item.id;});%><%_.each(items, function(item) {%> \n\n <%=item.filename%>\n <%=item.createtime%>\n \n \n \n \n \n \n\n<%});%>\n',a}};return d}); \ No newline at end of file diff --git a/web/resource/js/lib/district-wechat.js b/web/resource/js/lib/district-wechat.js new file mode 100644 index 0000000..08b5990 --- /dev/null +++ b/web/resource/js/lib/district-wechat.js @@ -0,0 +1 @@ +define(function(){var s=[{title:"四川",cities:[{title:"凉山"},{title:"资阳"},{title:"成都"},{title:"自贡"},{title:"泸州"},{title:"攀枝花"},{title:"绵阳"},{title:"德阳"},{title:"遂宁"},{title:"广元"},{title:"乐山"},{title:"内江"},{title:"南充"},{title:"宜宾"},{title:"眉山"},{title:"达州"},{title:"广安"},{title:"巴中"},{title:"雅安"},{title:"甘孜"},{title:"阿坝"}]},{title:"重庆",cities:[{title:"酉阳"},{title:"彭水"},{title:"合川"},{title:"永川"},{title:"江津"},{title:"南川"},{title:"铜梁"},{title:"大足"},{title:"荣昌"},{title:"璧山"},{title:"长寿"},{title:"綦江"},{title:"潼南"},{title:"梁平"},{title:"城口"},{title:"石柱"},{title:"秀山"},{title:"万州"},{title:"渝中"},{title:"涪陵"},{title:"江北"},{title:"大渡口"},{title:"九龙坡"},{title:"沙坪坝"},{title:"北碚"},{title:"南岸"},{title:"黔江"},{title:"巫溪"},{title:"双桥"},{title:"万盛"},{title:"巴南"},{title:"渝北"},{title:"忠县"},{title:"武隆"},{title:"垫江"},{title:"丰都"},{title:"巫山"},{title:"奉节"},{title:"云阳"},{title:"开县"}]},{title:"陕西",cities:[{title:"商洛"},{title:"西安"},{title:"宝鸡"},{title:"铜川"},{title:"渭南"},{title:"咸阳"},{title:"汉中"},{title:"延安"},{title:"安康"},{title:"榆林"}]},{title:"甘肃",cities:[{title:"定西"},{title:"庆阳"},{title:"陇南"},{title:"甘南"},{title:"临夏"},{title:"兰州"},{title:"金昌"},{title:"嘉峪关"},{title:"天水"},{title:"白银"},{title:"张掖"},{title:"武威"},{title:"酒泉"},{title:"平凉"}]},{title:"青海",cities:[{title:"海南"},{title:"果洛"},{title:"玉树"},{title:"海东"},{title:"海北"},{title:"黄南"},{title:"海西"},{title:"西宁"}]},{title:"宁夏",cities:[{title:"银川"},{title:"吴忠"},{title:"石嘴山"},{title:"中卫"},{title:"固原"}]},{title:"云南",cities:[{title:"红河"},{title:"文山"},{title:"楚雄"},{title:"怒江"},{title:"德宏"},{title:"西双版纳"},{title:"大理"},{title:"迪庆"},{title:"昆明"},{title:"曲靖"},{title:"保山"},{title:"玉溪"},{title:"丽江"},{title:"昭通"},{title:"临沧"},{title:"普洱"}]},{title:"澳门",cities:[{title:"None"}]},{title:"贵州",cities:[{title:"毕节"},{title:"黔东南"},{title:"黔南"},{title:"铜仁"},{title:"黔西南"},{title:"贵阳"},{title:"遵义"},{title:"六盘水"},{title:"安顺"}]},{title:"香港",cities:[{title:"None"}]},{title:"辽宁",cities:[{title:"盘锦"},{title:"辽阳"},{title:"朝阳"},{title:"铁岭"},{title:"葫芦岛"},{title:"沈阳"},{title:"鞍山"},{title:"大连"},{title:"本溪"},{title:"抚顺"},{title:"锦州"},{title:"丹东"},{title:"阜新"},{title:"营口"}]},{title:"吉林",cities:[{title:"延边"},{title:"长春"},{title:"四平"},{title:"吉林"},{title:"通化"},{title:"辽源"},{title:"松原"},{title:"白山"},{title:"白城"}]},{title:"黑龙江",cities:[{title:"黑河"},{title:"牡丹江"},{title:"哈尔滨"},{title:"大兴安岭"},{title:"鸡西"},{title:"齐齐哈尔"},{title:"双鸭山"},{title:"鹤岗"},{title:"伊春"},{title:"大庆"},{title:"七台河"},{title:"佳木斯"}]},{title:"黑龙江 ",cities:[{title:"绥化"}]},{title:"海南",cities:[{title:"乐东"},{title:"昌江"},{title:"白沙"},{title:"西沙"},{title:"琼中"},{title:"保亭"},{title:"陵水"},{title:"中沙"},{title:"南沙"},{title:"海口"},{title:"三亚"},{title:"五指山"},{title:"儋州"},{title:"琼海"},{title:"文昌"},{title:"东方"},{title:"万宁"},{title:"定安"},{title:"屯昌"},{title:"澄迈"},{title:"临高"}]},{title:"广东",cities:[{title:"揭阳"},{title:"中山"},{title:"广州"},{title:"深圳"},{title:"韶关"},{title:"汕头"},{title:"珠海"},{title:"江门"},{title:"佛山"},{title:"茂名"},{title:"湛江"},{title:"惠州"},{title:"肇庆"},{title:"汕尾"},{title:"梅州"},{title:"阳江"},{title:"河源"},{title:"东莞"},{title:"清远"},{title:"潮州"},{title:"云浮"}]},{title:"广西",cities:[{title:"贺州"},{title:"百色"},{title:"来宾"},{title:"河池"},{title:"崇左"},{title:"南宁"},{title:"桂林"},{title:"柳州"},{title:"北海"},{title:"梧州"},{title:"钦州"},{title:"防城港"},{title:"玉林"},{title:"贵港"}]},{title:"湖北",cities:[{title:"黄冈"},{title:"荆州"},{title:"随州"},{title:"咸宁"},{title:"神农架"},{title:"恩施"},{title:"武汉"},{title:"十堰"},{title:"黄石"},{title:"宜昌"},{title:"鄂州"},{title:"襄樊"},{title:"孝感"},{title:"荆门"},{title:"潜江"},{title:"仙桃"},{title:"天门"}]},{title:"湖南",cities:[{title:"永州"},{title:"郴州"},{title:"娄底"},{title:"怀化"},{title:"湘西"},{title:"长沙"},{title:"湘潭"},{title:"株洲"},{title:"邵阳"},{title:"衡阳"},{title:"常德"},{title:"岳阳"},{title:"益阳"},{title:"张家界"}]},{title:"河南",cities:[{title:"漯河"},{title:"许昌"},{title:"南阳"},{title:"三门峡"},{title:"信阳"},{title:"商丘"},{title:"驻马店"},{title:"周口"},{title:"济源"},{title:"郑州"},{title:"洛阳"},{title:"开封"},{title:"安阳"},{title:"平顶山"},{title:"新乡"},{title:"鹤壁"},{title:"濮阳"},{title:"焦作"}]},{title:"台湾",cities:[{title:"屏东县"},{title:"澎湖县"},{title:"台东县"},{title:"花莲县"},{title:"台北市"},{title:"基隆市"},{title:"高雄市"},{title:"台南市"},{title:"台中市"},{title:"嘉义市"},{title:"新竹市"},{title:"宜兰县"},{title:"台北县"},{title:"新竹县"},{title:"桃园县"},{title:"台中县"},{title:"苗栗县"},{title:"南投县"},{title:"彰化县"},{title:"嘉义县"},{title:"云林县"},{title:"高雄县"},{title:"台南县"}]},{title:"北京",cities:[{title:"房山"},{title:"大兴"},{title:"顺义"},{title:"通州"},{title:"昌平"},{title:"密云"},{title:"平谷"},{title:"延庆"},{title:"东城"},{title:"怀柔"},{title:"崇文"},{title:"西城"},{title:"朝阳"},{title:"宣武"},{title:"石景山"},{title:"丰台"},{title:"门头沟"},{title:"海淀"}]},{title:"河北",cities:[{title:"衡水"},{title:"廊坊"},{title:"石家庄"},{title:"秦皇岛"},{title:"唐山"},{title:"邢台"},{title:"邯郸"},{title:"张家口"},{title:"保定"},{title:"沧州"},{title:"承德"}]},{title:"天津",cities:[{title:"西青"},{title:"东丽"},{title:"北辰"},{title:"津南"},{title:"宁河"},{title:"武清"},{title:"静海"},{title:"宝坻"},{title:"和平"},{title:"河西"},{title:"河东"},{title:"河北"},{title:"南开"},{title:"塘沽"},{title:"红桥"},{title:"大港"},{title:"汉沽"},{title:"蓟县"}]},{title:"内蒙古",cities:[{title:"锡林郭勒"},{title:"兴安"},{title:"阿拉善"},{title:"呼和浩特"},{title:"乌海"},{title:"包头"},{title:"通辽"},{title:"赤峰"},{title:"呼伦贝尔"},{title:"鄂尔多斯"},{title:"乌兰察布"},{title:"巴彦淖尔"}]},{title:"山西",cities:[{title:"吕梁"},{title:"临汾"},{title:"太原"},{title:"阳泉"},{title:"大同"},{title:"晋城"},{title:"长治"},{title:"晋中"},{title:"朔州"},{title:"忻州"},{title:"运城"}]},{title:"浙江",cities:[{title:"丽水"},{title:"台州"},{title:"杭州"},{title:"温州"},{title:"宁波"},{title:"湖州"},{title:"嘉兴"},{title:"金华"},{title:"绍兴"},{title:"舟山"},{title:"衢州"}]},{title:"江苏",cities:[{title:"镇江"},{title:"扬州"},{title:"宿迁"},{title:"泰州"},{title:"南京"},{title:"徐州"},{title:"无锡"},{title:"苏州"},{title:"常州"},{title:"连云港"},{title:"南通"},{title:"盐城"},{title:"淮安"}]},{title:"上海",cities:[{title:"杨浦"},{title:"南汇"},{title:"宝山"},{title:"闵行"},{title:"浦东新"},{title:"嘉定"},{title:"松江"},{title:"金山"},{title:"崇明"},{title:"奉贤"},{title:"青浦"},{title:"黄浦"},{title:"卢湾"},{title:"长宁"},{title:"徐汇"},{title:"普陀"},{title:"静安"},{title:"虹口"},{title:"闸北"}]},{title:"山东",cities:[{title:"日照"},{title:"威海"},{title:"临沂"},{title:"莱芜"},{title:"聊城"},{title:"德州"},{title:"菏泽"},{title:"滨州"},{title:"济南"},{title:"淄博"},{title:"青岛"},{title:"东营"},{title:"枣庄"},{title:"潍坊"},{title:"烟台"},{title:"泰安"},{title:"济宁"}]},{title:"江西",cities:[{title:"上饶"},{title:"抚州"},{title:"南昌"},{title:"萍乡"},{title:"景德镇"},{title:"新余"},{title:"九江"},{title:"赣州"},{title:"鹰潭"},{title:"宜春"},{title:"吉安"}]},{title:"福建",cities:[{title:"福州"},{title:"莆田"},{title:"厦门"},{title:"泉州"},{title:"三明"},{title:"南平"},{title:"漳州"},{title:"宁德"},{title:"龙岩"}]},{title:"安徽",cities:[{title:"滁州"},{title:"黄山"},{title:"宿州"},{title:"阜阳"},{title:"六安"},{title:"巢湖"},{title:"池州"},{title:"亳州"},{title:"宣城"},{title:"合肥"},{title:"蚌埠"},{title:"芜湖"},{title:"马鞍山"},{title:"淮南"},{title:"铜陵"},{title:"淮北"},{title:"安庆"}]},{title:"西藏",cities:[{title:"那曲"},{title:"阿里"},{title:"林芝"},{title:"昌都"},{title:"山南"},{title:"日喀则"},{title:"拉萨"}]},{title:"新疆",cities:[{title:"博尔塔拉"},{title:"吐鲁番"},{title:"哈密"},{title:"昌吉"},{title:"和田"},{title:"喀什"},{title:"克孜勒苏"},{title:"巴音郭楞"},{title:"阿克苏"},{title:"伊犁"},{title:"塔城"},{title:"乌鲁木齐"},{title:"阿勒泰"},{title:"克拉玛依"},{title:"石河子"},{title:"图木舒克"},{title:"阿拉尔"},{title:"五家渠"}]}],t={};function i(n,t,l){if(!n.city)return!1;n.city.options.length=0,l.withTitle&&n.city.options.add(new Option("市",""));var i=n.province.options[n.province.options.selectedIndex],e=$(i).attr("pid");e&&$.each(s[e].cities,function(t,c){if("北京市"!=c.title&&"上海市"!=c.title&&"天津市"!=c.title&&"重庆市"!=c.title||!l.wechat){if(l.wechat){var i=c.title.indexOf("市");-1xp||t<-xp}function ft(t){this._target=t.target,this._life=t.life||1e3,this._delay=t.delay||0,this._initialized=!1,this.loop=null!=t.loop&&t.loop,this.gap=t.gap||0,this.easing=t.easing||"Linear",this.onframe=t.onframe,this.ondestroy=t.ondestroy,this.onrestart=t.onrestart,this._pausedTime=0,this._paused=!1}function pt(t){return(t=Math.round(t))<0?0:t>255?255:t}function gt(t){return(t=Math.round(t))<0?0:t>360?360:t}function mt(t){return t<0?0:t>1?1:t}function vt(t){return pt(t.length&&"%"===t.charAt(t.length-1)?parseFloat(t)/100*255:parseInt(t,10))}function yt(t){return mt(t.length&&"%"===t.charAt(t.length-1)?parseFloat(t)/100:parseFloat(t))}function xt(t,e,n){return n<0?n+=1:n>1&&(n-=1),6*n<1?t+(e-t)*n*6:2*n<1?e:3*n<2?t+(e-t)*(2/3-n)*6:t}function _t(t,e,n){return t+(e-t)*n}function wt(t,e,n,i,r){return t[0]=e,t[1]=n,t[2]=i,t[3]=r,t}function bt(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t}function St(t,e){Pp&&bt(Pp,e),Pp=kp.put(t,Pp||e.slice())}function Mt(t,e){if(t){e=e||[];var n=kp.get(t);if(n)return bt(e,n);var i=(t+="").replace(/ /g,"").toLowerCase();if(i in Dp)return bt(e,Dp[i]),St(t,e),e;if("#"!==i.charAt(0)){var r=i.indexOf("("),o=i.indexOf(")");if(-1!==r&&o+1===i.length){var a=i.substr(0,r),s=i.substr(r+1,o-(r+1)).split(","),l=1;switch(a){case"rgba":if(4!==s.length)return void wt(e,0,0,0,1);l=yt(s.pop());case"rgb":return 3!==s.length?void wt(e,0,0,0,1):(wt(e,vt(s[0]),vt(s[1]),vt(s[2]),l),St(t,e),e);case"hsla":return 4!==s.length?void wt(e,0,0,0,1):(s[3]=yt(s[3]),It(s,e),St(t,e),e);case"hsl":return 3!==s.length?void wt(e,0,0,0,1):(It(s,e),St(t,e),e);default:return}}wt(e,0,0,0,1)}else{if(4===i.length)return(h=parseInt(i.substr(1),16))>=0&&h<=4095?(wt(e,(3840&h)>>4|(3840&h)>>8,240&h|(240&h)>>4,15&h|(15&h)<<4,1),St(t,e),e):void wt(e,0,0,0,1);if(7===i.length){var h=parseInt(i.substr(1),16);return h>=0&&h<=16777215?(wt(e,(16711680&h)>>16,(65280&h)>>8,255&h,1),St(t,e),e):void wt(e,0,0,0,1)}}}}function It(t,e){var n=(parseFloat(t[0])%360+360)%360/360,i=yt(t[1]),r=yt(t[2]),o=r<=.5?r*(i+1):r+i-r*i,a=2*r-o;return e=e||[],wt(e,pt(255*xt(a,o,n+1/3)),pt(255*xt(a,o,n)),pt(255*xt(a,o,n-1/3)),1),4===t.length&&(e[3]=t[3]),e}function Tt(t){if(t){var e,n,i=t[0]/255,r=t[1]/255,o=t[2]/255,a=Math.min(i,r,o),s=Math.max(i,r,o),l=s-a,h=(s+a)/2;if(0===l)e=0,n=0;else{n=h<.5?l/(s+a):l/(2-s-a);var u=((s-i)/6+l/2)/l,c=((s-r)/6+l/2)/l,d=((s-o)/6+l/2)/l;i===s?e=d-c:r===s?e=1/3+u-d:o===s&&(e=2/3+c-u),e<0&&(e+=1),e>1&&(e-=1)}var f=[360*e,n,h];return null!=t[3]&&f.push(t[3]),f}}function Ct(t,e){var n=Mt(t);if(n){for(var i=0;i<3;i++)n[i]=e<0?n[i]*(1-e)|0:(255-n[i])*e+n[i]|0;return Lt(n,4===n.length?"rgba":"rgb")}}function At(t){var e=Mt(t);if(e)return((1<<24)+(e[0]<<16)+(e[1]<<8)+ +e[2]).toString(16).slice(1)}function Dt(t,e,n){if(e&&e.length&&t>=0&&t<=1){n=n||[];var i=t*(e.length-1),r=Math.floor(i),o=Math.ceil(i),a=e[r],s=e[o],l=i-r;return n[0]=pt(_t(a[0],s[0],l)),n[1]=pt(_t(a[1],s[1],l)),n[2]=pt(_t(a[2],s[2],l)),n[3]=mt(_t(a[3],s[3],l)),n}}function kt(t,e,n){if(e&&e.length&&t>=0&&t<=1){var i=t*(e.length-1),r=Math.floor(i),o=Math.ceil(i),a=Mt(e[r]),s=Mt(e[o]),l=i-r,h=Lt([pt(_t(a[0],s[0],l)),pt(_t(a[1],s[1],l)),pt(_t(a[2],s[2],l)),mt(_t(a[3],s[3],l))],"rgba");return n?{color:h,leftIndex:r,rightIndex:o,value:i}:h}}function Pt(t,e){if((t=Mt(t))&&null!=e)return t[3]=mt(e),Lt(t,"rgba")}function Lt(t,e){if(t&&t.length){var n=t[0]+","+t[1]+","+t[2];return"rgba"!==e&&"hsva"!==e&&"hsla"!==e||(n+=","+t[3]),e+"("+n+")"}}function Ot(t,e){return t[e]}function zt(t,e,n){t[e]=n}function Et(t,e,n){return(e-t)*n+t}function Rt(t,e,n){return n>.5?e:t}function Nt(t,e,n,i,r){var o=t.length;if(1==r)for(s=0;sr)t.length=r;else for(a=i;a=0&&!(m[n]<=e);n--);n=Math.min(n,h-2)}else{for(n=k;ne);n++);n=Math.min(n-1,h-2)}k=n,P=e;var i=m[n+1]-m[n];if(0!==i)if(I=(e-m[n])/i,l)if(C=v[n],T=v[0===n?n:n-1],A=v[n>h-2?h-1:n+1],D=v[n>h-3?h-1:n+2],d)Ft(T,C,A,D,I,I*I,I*I*I,a(t,r),g);else{if(f)o=Ft(T,C,A,D,I,I*I,I*I*I,L,1),o=Wt(L);else{if(p)return Rt(C,A,I);o=Gt(T,C,A,D,I,I*I,I*I*I)}s(t,r,o)}else if(d)Nt(v[n],v[n+1],I,a(t,r),g);else{var o;if(f)Nt(v[n],v[n+1],I,L,1),o=Wt(L);else{if(p)return Rt(v[n],v[n+1],I);o=Et(v[n],v[n+1],I)}s(t,r,o)}},ondestroy:n});return e&&"spline"!==e&&(O.easing=e),O}}}function Xt(t,e,n,i){n<0&&(t+=n,n=-n),i<0&&(e+=i,i=-i),this.x=t,this.y=e,this.width=n,this.height=i}function jt(t){for(var e=0;t>=jp;)e|=1&t,t>>=1;return t+e}function Yt(t,e,n,i){var r=e+1;if(r===n)return 1;if(i(t[r++],t[e])<0){for(;r=0;)r++;return r-e}function qt(t,e,n){for(n--;e>>1])<0?l=o:s=o+1;var h=i-s;switch(h){case 3:t[s+3]=t[s+2];case 2:t[s+2]=t[s+1];case 1:t[s+1]=t[s];break;default:for(;h>0;)t[s+h]=t[s+h-1],h--}t[s]=a}}function Kt(t,e,n,i,r,o){var a=0,s=0,l=1;if(o(t,e[n+r])>0){for(s=i-r;l0;)a=l,(l=1+(l<<1))<=0&&(l=s);l>s&&(l=s),a+=r,l+=r}else{for(s=r+1;ls&&(l=s);var h=a;a=r-l,l=r-h}for(a++;a>>1);o(t,e[n+u])>0?a=u+1:l=u}return l}function Qt(t,e,n,i,r,o){var a=0,s=0,l=1;if(o(t,e[n+r])<0){for(s=r+1;ls&&(l=s);var h=a;a=r-l,l=r-h}else{for(s=i-r;l=0;)a=l,(l=1+(l<<1))<=0&&(l=s);l>s&&(l=s),a+=r,l+=r}for(a++;a>>1);o(t,e[n+u])<0?l=u:a=u+1}return l}function Jt(t,e){function n(n){var s=o[n],h=a[n],u=o[n+1],c=a[n+1];a[n]=h+c,n===l-3&&(o[n+1]=o[n+2],a[n+1]=a[n+2]),l--;var d=Qt(t[u],t,s,h,0,e);s+=d,0!==(h-=d)&&0!==(c=Kt(t[s+h-1],t,u,c,c-1,e))&&(h<=c?i(s,h,u,c):r(s,h,u,c))}function i(n,i,r,o){var a=0;for(a=0;a=Yp||f>=Yp);if(p)break;g<0&&(g=0),g+=2}if((s=g)<1&&(s=1),1===i){for(a=0;a=0;a--)t[f+a]=t[d+a];if(0===i){v=!0;break}}if(t[c--]=h[u--],1==--o){v=!0;break}if(0!=(m=o-Kt(t[l],h,0,o,o-1,e))){for(o-=m,f=(c-=m)+1,d=(u-=m)+1,a=0;a=Yp||m>=Yp);if(v)break;p<0&&(p=0),p+=2}if((s=p)<1&&(s=1),1===o){for(f=(c-=i)+1,d=(l-=i)+1,a=i-1;a>=0;a--)t[f+a]=t[d+a];t[c]=h[u]}else{if(0===o)throw new Error;for(d=c-(o-1),a=0;a=0;a--)t[f+a]=t[d+a];t[c]=h[u]}else for(d=c-(o-1),a=0;a1;){var t=l-2;if(t>=1&&a[t-1]<=a[t]+a[t+1]||t>=2&&a[t-2]<=a[t]+a[t-1])a[t-1]a[t+1])break;n(t)}},this.forceMergeRuns=function(){for(;l>1;){var t=l-2;t>0&&a[t-1]s&&(l=s),$t(t,n,n+l,n+o,e),o=l}a.pushRun(n,o),a.mergeRuns(),r-=o,n+=o}while(0!==r);a.forceMergeRuns()}}function ee(t,e){return t.zlevel===e.zlevel?t.z===e.z?t.z2-e.z2:t.z-e.z:t.zlevel-e.zlevel}function ne(t,e,n){var i=null==e.x?0:e.x,r=null==e.x2?1:e.x2,o=null==e.y?0:e.y,a=null==e.y2?0:e.y2;return e.global||(i=i*n.width+n.x,r=r*n.width+n.x,o=o*n.height+n.y,a=a*n.height+n.y),t.createLinearGradient(i,o,r,a)}function ie(t,e,n){var i=n.width,r=n.height,o=Math.min(i,r),a=null==e.x?.5:e.x,s=null==e.y?.5:e.y,l=null==e.r?.5:e.r;return e.global||(a=a*i+n.x,s=s*r+n.y,l*=o),t.createRadialGradient(a,s,0,a,s,l)}function re(){return!1}function oe(t,e,n){var i=ep(),r=e.getWidth(),o=e.getHeight(),a=i.style;return a&&(a.position="absolute",a.left=0,a.top=0,a.width=r+"px",a.height=o+"px",i.setAttribute("data-zr-dom-id",t)),i.width=r*n,i.height=o*n,i}function ae(t){if("string"==typeof t){var e=ag.get(t);return e&&e.image}return t}function se(t,e,n,i,r){if(t){if("string"==typeof t){if(e&&e.__zrImageSrc===t||!n)return e;var o=ag.get(t),a={hostEl:n,cb:i,cbPayload:r};return o?!he(e=o.image)&&o.pending.push(a):(!e&&(e=new Image),e.onload=le,ag.put(t,e.__cachedImgObj={image:e,pending:[a]}),e.src=e.__zrImageSrc=t),e}return t}return e}function le(){var t=this.__cachedImgObj;this.onload=this.__cachedImgObj=null;for(var e=0;ehg&&(lg=0,sg={}),lg++,sg[n]=r,r}function ce(t,e,n,i,r,o,a){return o?fe(t,e,n,i,r,o,a):de(t,e,n,i,r,a)}function de(t,e,n,i,r,o){var a=Se(t,e,r,o),s=ue(t,e);r&&(s+=r[1]+r[3]);var l=a.outerHeight,h=new Xt(pe(0,s,n),ge(0,l,i),s,l);return h.lineHeight=a.lineHeight,h}function fe(t,e,n,i,r,o,a){var s=Me(t,{rich:o,truncate:a,font:e,textAlign:n,textPadding:r}),l=s.outerWidth,h=s.outerHeight;return new Xt(pe(0,l,n),ge(0,h,i),l,h)}function pe(t,e,n){return"right"===n?t-=e:"center"===n&&(t-=e/2),t}function ge(t,e,n){return"middle"===n?t-=e/2:"bottom"===n&&(t-=e),t}function me(t,e,n){var i=e.x,r=e.y,o=e.height,a=e.width,s=o/2,l="left",h="top";switch(t){case"left":i-=n,r+=s,l="right",h="middle";break;case"right":i+=n+a,r+=s,h="middle";break;case"top":i+=a/2,r-=n,l="center",h="bottom";break;case"bottom":i+=a/2,r+=o+n,l="center";break;case"inside":i+=a/2,r+=s,l="center",h="middle";break;case"insideLeft":i+=n,r+=s,h="middle";break;case"insideRight":i+=a-n,r+=s,l="right",h="middle";break;case"insideTop":i+=a/2,r+=n,l="center";break;case"insideBottom":i+=a/2,r+=o-n,l="center",h="bottom";break;case"insideTopLeft":i+=n,r+=n;break;case"insideTopRight":i+=a-n,r+=n,l="right";break;case"insideBottomLeft":i+=n,r+=o-n,h="bottom";break;case"insideBottomRight":i+=a-n,r+=o-n,l="right",h="bottom"}return{x:i,y:r,textAlign:l,textVerticalAlign:h}}function ve(t,e,n,i,r){if(!e)return"";var o=(t+"").split("\n");r=ye(e,n,i,r);for(var a=0,s=o.length;a=a;l++)s-=a;var h=ue(n);return h>s&&(n="",h=0),s=t-h,i.ellipsis=n,i.ellipsisWidth=h,i.contentWidth=s,i.containerWidth=t,i}function xe(t,e){var n=e.containerWidth,i=e.font,r=e.contentWidth;if(!n)return"";var o=ue(t,i);if(o<=n)return t;for(var a=0;;a++){if(o<=r||a>=e.maxIterations){t+=e.ellipsis;break}var s=0===a?_e(t,r,e.ascCharWidth,e.cnCharWidth):o>0?Math.floor(t.length*r/o):0;o=ue(t=t.substr(0,s),i)}return""===t&&(t=e.placeholder),t}function _e(t,e,n,i){for(var r=0,o=0,a=t.length;ol)t="",o=[];else if(null!=h)for(var u=ye(h-(n?n[1]+n[3]:0),e,i.ellipsis,{minChar:i.minChar,placeholder:i.placeholder}),c=0,d=o.length;cr&&Ie(n,t.substring(r,o)),Ie(n,i[2],i[1]),r=ug.lastIndex}rf)return{lines:[],width:0,height:0};P.textWidth=ue(P.text,_);var b=y.textWidth,S=null==b||"auto"===b;if("string"==typeof b&&"%"===b.charAt(b.length-1))P.percentWidth=b,h.push(P),b=0;else{if(S){b=P.textWidth;var M=y.textBackgroundColor,I=M&&M.image;I&&he(I=ae(I))&&(b=Math.max(b,I.width*w/I.height))}var T=x?x[1]+x[3]:0;b+=T;var D=null!=d?d-m:null;null!=D&&Dl&&(n*=l/(c=n+i),i*=l/c),r+o>l&&(r*=l/(c=r+o),o*=l/c),i+r>h&&(i*=h/(c=i+r),r*=h/c),n+o>h&&(n*=h/(c=n+o),o*=h/c),t.moveTo(a+n,s),t.lineTo(a+l-i,s),0!==i&&t.quadraticCurveTo(a+l,s,a+l,s+i),t.lineTo(a+l,s+h-r),0!==r&&t.quadraticCurveTo(a+l,s+h,a+l-r,s+h),t.lineTo(a+o,s+h),0!==o&&t.quadraticCurveTo(a,s+h,a,s+h-o),t.lineTo(a,s+n),0!==n&&t.quadraticCurveTo(a,s,a+n,s)}function Ae(t){return De(t),d(t.rich,De),t}function De(t){if(t){t.font=Te(t);var e=t.textAlign;"middle"===e&&(e="center"),t.textAlign=null==e||fg[e]?e:"left";var n=t.textVerticalAlign||t.textBaseline;"center"===n&&(n="middle"),t.textVerticalAlign=null==n||pg[n]?n:"top",t.textPadding&&(t.textPadding=k(t.textPadding))}}function ke(t,e,n,i,r){i.rich?Le(t,e,n,i,r):Pe(t,e,n,i,r)}function Pe(t,e,n,i,r){var o=Fe(e,"font",i.font||cg),a=i.textPadding,s=t.__textCotentBlock;s&&!t.__dirty||(s=t.__textCotentBlock=Se(n,o,a,i.truncate));var l=s.outerHeight,h=s.lines,u=s.lineHeight,c=Ve(l,i,r),d=c.baseX,f=c.baseY,p=c.textAlign,g=c.textVerticalAlign;ze(e,i,r,d,f);var m=ge(f,l,g),v=d,y=m,x=Re(i);if(x||a){var _=ue(n,o);a&&(_+=a[1]+a[3]);var w=pe(d,_,p);x&&Ne(t,e,i,w,m,_,l),a&&(v=Ze(d,p,a),y+=a[0])}Fe(e,"textAlign",p||"left"),Fe(e,"textBaseline","middle"),Fe(e,"shadowBlur",i.textShadowBlur||0),Fe(e,"shadowColor",i.textShadowColor||"transparent"),Fe(e,"shadowOffsetX",i.textShadowOffsetX||0),Fe(e,"shadowOffsetY",i.textShadowOffsetY||0),y+=u/2;var b=i.textStrokeWidth,S=Ge(i.textStroke,b),M=He(i.textFill);S&&(Fe(e,"lineWidth",b),Fe(e,"strokeStyle",S)),M&&Fe(e,"fillStyle",M);for(var I=0;I=0&&"right"===(_=b[D]).textAlign;)Ee(t,e,_,i,M,v,A,"right"),I-=_.width,A-=_.width,D--;for(C+=(o-(C-m)-(y-A)-I)/2;T<=D;)Ee(t,e,_=b[T],i,M,v,C+_.width/2,"center"),C+=_.width,T++;v+=M}}function ze(t,e,n,i,r){if(n&&e.textRotation){var o=e.textOrigin;"center"===o?(i=n.width/2+n.x,r=n.height/2+n.y):o&&(i=o[0]+n.x,r=o[1]+n.y),t.translate(i,r),t.rotate(-e.textRotation),t.translate(-i,-r)}}function Ee(t,e,n,i,r,o,a,s){var l=i.rich[n.styleName]||{},h=n.textVerticalAlign,u=o+r/2;"top"===h?u=o+n.height/2:"bottom"===h&&(u=o+r-n.height/2),!n.isLineHolder&&Re(l)&&Ne(t,e,l,"right"===s?a-n.width:"center"===s?a-n.width/2:a,u-n.height/2,n.width,n.height);var c=n.textPadding;c&&(a=Ze(a,s,c),u-=n.height/2-c[2]-n.textHeight/2),Fe(e,"shadowBlur",A(l.textShadowBlur,i.textShadowBlur,0)),Fe(e,"shadowColor",l.textShadowColor||i.textShadowColor||"transparent"),Fe(e,"shadowOffsetX",A(l.textShadowOffsetX,i.textShadowOffsetX,0)),Fe(e,"shadowOffsetY",A(l.textShadowOffsetY,i.textShadowOffsetY,0)),Fe(e,"textAlign",s),Fe(e,"textBaseline","middle"),Fe(e,"font",n.font||cg);var d=Ge(l.textStroke||i.textStroke,p),f=He(l.textFill||i.textFill),p=C(l.textStrokeWidth,i.textStrokeWidth);d&&(Fe(e,"lineWidth",p),Fe(e,"strokeStyle",d),e.strokeText(n.text,a,u)),f&&(Fe(e,"fillStyle",f),e.fillText(n.text,a,u))}function Re(t){return t.textBackgroundColor||t.textBorderWidth&&t.textBorderColor}function Ne(t,e,n,i,r,o,a){var s=n.textBackgroundColor,l=n.textBorderWidth,h=n.textBorderColor,u=_(s);if(Fe(e,"shadowBlur",n.textBoxShadowBlur||0),Fe(e,"shadowColor",n.textBoxShadowColor||"transparent"),Fe(e,"shadowOffsetX",n.textBoxShadowOffsetX||0),Fe(e,"shadowOffsetY",n.textBoxShadowOffsetY||0),u||l&&h){e.beginPath();var c=n.textBorderRadius;c?Ce(e,{x:i,y:r,width:o,height:a,r:c}):e.rect(i,r,o,a),e.closePath()}if(u)Fe(e,"fillStyle",s),e.fill();else if(w(s)){var d=s.image;(d=se(d,null,t,Be,s))&&he(d)&&e.drawImage(d,i,r,o,a)}l&&h&&(Fe(e,"lineWidth",l),Fe(e,"strokeStyle",h),e.stroke())}function Be(t,e){e.image=t}function Ve(t,e,n){var i=e.x||0,r=e.y||0,o=e.textAlign,a=e.textVerticalAlign;if(n){var s=e.textPosition;if(s instanceof Array)i=n.x+We(s[0],n.width),r=n.y+We(s[1],n.height);else{var l=me(s,n,e.textDistance);i=l.x,r=l.y,o=o||l.textAlign,a=a||l.textVerticalAlign}var h=e.textOffset;h&&(i+=h[0],r+=h[1])}return{baseX:i,baseY:r,textAlign:o,textVerticalAlign:a}}function Fe(t,e,n){return t[e]=Kp(t,e,n),t[e]}function Ge(t,e){return null==t||e<=0||"transparent"===t||"none"===t?null:t.image||t.colorStops?"#000":t}function He(t){return null==t||"none"===t?null:t.image||t.colorStops?"#000":t}function We(t,e){return"string"==typeof t?t.lastIndexOf("%")>=0?parseFloat(t)/100*e:parseFloat(t):t}function Ze(t,e,n){return"right"===e?t-n[1]:"center"===e?t+n[3]/2-n[1]/2:t+n[3]}function Ue(t,e){return null!=t&&(t||e.textBackgroundColor||e.textBorderWidth&&e.textBorderColor||e.textPadding)}function Xe(t){t=t||{},Hp.call(this,t);for(var e in t)t.hasOwnProperty(e)&&"style"!==e&&(this[e]=t[e]);this.style=new Jp(t.style,this),this._rect=null,this.__clipPaths=[]}function je(t){Xe.call(this,t)}function Ye(t){return parseInt(t,10)}function qe(t){return!!t&&(!!t.__builtin__||"function"==typeof t.resize&&"function"==typeof t.refresh)}function $e(t,e,n){return vg.copy(t.getBoundingRect()),t.transform&&vg.applyTransform(t.transform),yg.width=e,yg.height=n,!vg.intersect(yg)}function Ke(t,e){if(t==e)return!1;if(!t||!e||t.length!==e.length)return!0;for(var n=0;n=0){var r="touchend"!=i?e.targetTouches[0]:e.changedTouches[0];r&&en(t,r,e,n)}else en(t,e,e,n),e.zrDelta=e.wheelDelta?e.wheelDelta/120:-(e.detail||0)/3;var o=e.button;return null==e.which&&void 0!==o&&wg.test(e.type)&&(e.which=1&o?1:2&o?3:4&o?2:0),e}function on(t,e,n){_g?t.addEventListener(e,n):t.attachEvent("on"+e,n)}function an(t,e,n){_g?t.removeEventListener(e,n):t.detachEvent("on"+e,n)}function sn(t){return t.which>1}function ln(t){var e=t[1][0]-t[0][0],n=t[1][1]-t[0][1];return Math.sqrt(e*e+n*n)}function hn(t){return[(t[0][0]+t[1][0])/2,(t[0][1]+t[1][1])/2]}function un(t){return"mousewheel"===t&&Zf.browser.firefox?"DOMMouseScroll":t}function cn(t,e,n){var i=t._gestureMgr;"start"===n&&i.clear();var r=i.recognize(e,t.handler.findHover(e.zrX,e.zrY,null).target,t.dom);if("end"===n&&i.clear(),r){var o=r.type;e.gestureEvent=o,t.handler.dispatchToElement({target:r.target},o,r.event)}}function dn(t){t._touching=!0,clearTimeout(t._touchTimer),t._touchTimer=setTimeout(function(){t._touching=!1},700)}function fn(t){var e=t.pointerType;return"pen"===e||"touch"===e}function pn(t){function e(t,e){return function(){if(!e._touching)return t.apply(e,arguments)}}d(Cg,function(e){t._handlers[e]=m(kg[e],t)}),d(Dg,function(e){t._handlers[e]=m(kg[e],t)}),d(Tg,function(n){t._handlers[n]=e(kg[n],t)})}function gn(t){function e(e,n){d(e,function(e){on(t,un(e),n._handlers[e])},n)}dp.call(this),this.dom=t,this._touching=!1,this._touchTimer,this._gestureMgr=new Mg,this._handlers={},pn(this),Zf.pointerEventsSupported?e(Dg,this):(Zf.touchEventsSupported&&e(Cg,this),e(Tg,this))}function mn(t,e){var n=new Eg(Hf(),t,e);return zg[n.id]=n,n}function vn(t,e){Og[t]=e}function yn(t){delete zg[t]}function xn(t){return t instanceof Array?t:null==t?[]:[t]}function _n(t,e,n){if(t){t[e]=t[e]||{},t.emphasis=t.emphasis||{},t.emphasis[e]=t.emphasis[e]||{};for(var i=0,r=n.length;i=n.length&&n.push({option:t})}}),n}function Mn(t){var e=R();Ng(t,function(t,n){var i=t.exist;i&&e.set(i.id,t)}),Ng(t,function(t,n){var i=t.option;P(!i||null==i.id||!e.get(i.id)||e.get(i.id)===t,"id duplicates: "+(i&&i.id)),i&&null!=i.id&&e.set(i.id,t),!t.keyInfo&&(t.keyInfo={})}),Ng(t,function(t,n){var i=t.exist,r=t.option,o=t.keyInfo;if(Bg(r)){if(o.name=null!=r.name?r.name+"":i?i.name:Fg,i)o.id=i.id;else if(null!=r.id)o.id=r.id+"";else{var a=0;do{o.id="\0"+o.name+"\0"+a++}while(e.get(o.id))}e.set(o.id,t)}})}function In(t){return Bg(t)&&t.id&&0===(t.id+"").indexOf("\0_ec_\0")}function Tn(t,e){return null!=e.dataIndexInside?e.dataIndexInside:null!=e.dataIndex?y(e.dataIndex)?f(e.dataIndex,function(e){return t.indexOfRawIndex(e)}):t.indexOfRawIndex(e.dataIndex):null!=e.name?y(e.name)?f(e.name,function(e){return t.indexOfName(e)}):t.indexOfName(e.name):void 0}function Cn(){var t="__\0ec_inner_"+Hg+++"_"+Math.random().toFixed(5);return function(e){return e[t]||(e[t]={})}}function An(t,e,n){if(_(e)){var i={};i[e+"Index"]=0,e=i}var r=n&&n.defaultMainType;!r||Dn(e,r+"Index")||Dn(e,r+"Id")||Dn(e,r+"Name")||(e[r+"Index"]=0);var o={};return Ng(e,function(i,r){var i=e[r];if("dataIndex"!==r&&"dataIndexInside"!==r){var a=r.match(/^(\w+)(Index|Id|Name)$/)||[],s=a[1],h=(a[2]||"").toLowerCase();if(!(!s||!h||null==i||"index"===h&&"none"===i||n&&n.includeMainTypes&&l(n.includeMainTypes,s)<0)){var u={mainType:s};"index"===h&&"all"===i||(u[h]=i);var c=t.queryComponents(u);o[s+"Models"]=c,o[s+"Model"]=c[0]}}else o[r]=i}),o}function Dn(t,e){return t&&t.hasOwnProperty(e)}function kn(t,e,n){t.setAttribute?t.setAttribute(e,n):t[e]=n}function Pn(t,e){return t.getAttribute?t.getAttribute(e):t[e]}function Ln(t){var e={main:"",sub:""};return t&&(t=t.split(Wg),e.main=t[0]||"",e.sub=t[1]||""),e}function On(t){P(/^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(t),'componentType "'+t+'" illegal')}function zn(t,e){t.$constructor=t,t.extend=function(t){var e=this,n=function(){t.$constructor?t.$constructor.apply(this,arguments):e.apply(this,arguments)};return o(n.prototype,t),n.extend=this.extend,n.superCall=Rn,n.superApply=Nn,h(n,this),n.superClass=e,n}}function En(t){var e=["__\0is_clz",Ug++,Math.random().toFixed(3)].join("_");t.prototype[e]=!0,t.isInstance=function(t){return!(!t||!t[e])}}function Rn(t,e){var n=D(arguments,2);return this.superClass.prototype[e].apply(t,n)}function Nn(t,e,n){return this.superClass.prototype[e].apply(t,n)}function Bn(t,e){function n(t){var e=i[t.main];return e&&e[Zg]||((e=i[t.main]={})[Zg]=!0),e}e=e||{};var i={};if(t.registerClass=function(t,e){return e&&(On(e),(e=Ln(e)).sub?e.sub!==Zg&&(n(e)[e.sub]=t):i[e.main]=t),t},t.getClass=function(t,e,n){var r=i[t];if(r&&r[Zg]&&(r=e?r[e]:null),n&&!r)throw new Error(e?"Component "+t+"."+(e||"")+" not exists. Load it first.":t+".type should be specified.");return r},t.getClassesByMainType=function(t){t=Ln(t);var e=[],n=i[t.main];return n&&n[Zg]?d(n,function(t,n){n!==Zg&&e.push(t)}):e.push(n),e},t.hasClass=function(t){return t=Ln(t),!!i[t.main]},t.getAllClassMainTypes=function(){var t=[];return d(i,function(e,n){t.push(n)}),t},t.hasSubTypes=function(t){t=Ln(t);var e=i[t.main];return e&&e[Zg]},t.parseClassType=Ln,e.registerWhenExtend){var r=t.extend;r&&(t.extend=function(e){var n=r.call(this,e);return t.registerClass(n,e.type)})}return t}function Vn(t){return t>-Jg&&tJg||t<-Jg}function Gn(t,e,n,i,r){var o=1-r;return o*o*(o*t+3*r*e)+r*r*(r*i+3*o*n)}function Hn(t,e,n,i,r){var o=1-r;return 3*(((e-t)*o+2*(n-e)*r)*o+(i-n)*r*r)}function Wn(t,e,n,i,r,o){var a=i+3*(e-n)-t,s=3*(n-2*e+t),l=3*(e-t),h=t-r,u=s*s-3*a*l,c=s*l-9*a*h,d=l*l-3*s*h,f=0;if(Vn(u)&&Vn(c))Vn(s)?o[0]=0:(M=-l/s)>=0&&M<=1&&(o[f++]=M);else{var p=c*c-4*u*d;if(Vn(p)){var g=c/u,m=-g/2;(M=-s/a+g)>=0&&M<=1&&(o[f++]=M),m>=0&&m<=1&&(o[f++]=m)}else if(p>0){var v=Qg(p),y=u*s+1.5*a*(-c+v),x=u*s+1.5*a*(-c-v);(M=(-s-((y=y<0?-Kg(-y,nm):Kg(y,nm))+(x=x<0?-Kg(-x,nm):Kg(x,nm))))/(3*a))>=0&&M<=1&&(o[f++]=M)}else{var _=(2*u*s-3*a*c)/(2*Qg(u*u*u)),w=Math.acos(_)/3,b=Qg(u),S=Math.cos(w),M=(-s-2*b*S)/(3*a),m=(-s+b*(S+em*Math.sin(w)))/(3*a),I=(-s+b*(S-em*Math.sin(w)))/(3*a);M>=0&&M<=1&&(o[f++]=M),m>=0&&m<=1&&(o[f++]=m),I>=0&&I<=1&&(o[f++]=I)}}return f}function Zn(t,e,n,i,r){var o=6*n-12*e+6*t,a=9*e+3*i-3*t-9*n,s=3*e-3*t,l=0;if(Vn(a))Fn(o)&&(c=-s/o)>=0&&c<=1&&(r[l++]=c);else{var h=o*o-4*a*s;if(Vn(h))r[0]=-o/(2*a);else if(h>0){var u=Qg(h),c=(-o+u)/(2*a),d=(-o-u)/(2*a);c>=0&&c<=1&&(r[l++]=c),d>=0&&d<=1&&(r[l++]=d)}}return l}function Un(t,e,n,i,r,o){var a=(e-t)*r+t,s=(n-e)*r+e,l=(i-n)*r+n,h=(s-a)*r+a,u=(l-s)*r+s,c=(u-h)*r+h;o[0]=t,o[1]=a,o[2]=h,o[3]=c,o[4]=c,o[5]=u,o[6]=l,o[7]=i}function Xn(t,e,n,i,r,o,a,s,l,h,u){var c,d,f,p,g,m=.005,v=1/0;im[0]=l,im[1]=h;for(var y=0;y<1;y+=.05)rm[0]=Gn(t,n,r,a,y),rm[1]=Gn(e,i,o,s,y),(p=hp(im,rm))=0&&p=0&&c<=1&&(r[l++]=c);else{var h=a*a-4*o*s;if(Vn(h))(c=-a/(2*o))>=0&&c<=1&&(r[l++]=c);else if(h>0){var u=Qg(h),c=(-a+u)/(2*o),d=(-a-u)/(2*o);c>=0&&c<=1&&(r[l++]=c),d>=0&&d<=1&&(r[l++]=d)}}return l}function $n(t,e,n){var i=t+n-2*e;return 0===i?.5:(t-e)/i}function Kn(t,e,n,i,r){var o=(e-t)*i+t,a=(n-e)*i+e,s=(a-o)*i+o;r[0]=t,r[1]=o,r[2]=s,r[3]=s,r[4]=a,r[5]=n}function Qn(t,e,n,i,r,o,a,s,l){var h,u=.005,c=1/0;im[0]=a,im[1]=s;for(var d=0;d<1;d+=.05)rm[0]=jn(t,n,r,d),rm[1]=jn(e,i,o,d),(m=hp(im,rm))=0&&m1e-4)return s[0]=t-n,s[1]=e-i,l[0]=t+n,void(l[1]=e+i);if(cm[0]=hm(r)*n+t,cm[1]=lm(r)*i+e,dm[0]=hm(o)*n+t,dm[1]=lm(o)*i+e,h(s,cm,dm),u(l,cm,dm),(r%=um)<0&&(r+=um),(o%=um)<0&&(o+=um),r>o&&!a?o+=um:rr&&(fm[0]=hm(f)*n+t,fm[1]=lm(f)*i+e,h(s,fm,s),u(l,fm,l))}function ri(t,e,n,i,r,o,a){if(0===r)return!1;var s=r,l=0,h=t;if(a>e+s&&a>i+s||at+s&&o>n+s||oe+c&&u>i+c&&u>o+c&&u>s+c||ut+c&&h>n+c&&h>r+c&&h>a+c||he+h&&l>i+h&&l>o+h||lt+h&&s>n+h&&s>r+h||sn||u+hr&&(r+=km);var d=Math.atan2(l,s);return d<0&&(d+=km),d>=i&&d<=r||d+km>=i&&d+km<=r}function hi(t,e,n,i,r,o){if(o>e&&o>i||or?a:0}function ui(t,e){return Math.abs(t-e)e&&h>i&&h>o&&h>s||h1&&ci(),c=Gn(e,i,o,s,Em[0]),p>1&&(d=Gn(e,i,o,s,Em[1]))),2==p?me&&s>i&&s>o||s=0&&h<=1){for(var u=0,c=jn(e,i,o,h),d=0;dn||s<-n)return 0;h=Math.sqrt(n*n-s*s);zm[0]=-h,zm[1]=h;var l=Math.abs(i-r);if(l<1e-4)return 0;if(l%Lm<1e-4){i=0,r=Lm;p=o?1:-1;return a>=zm[0]+t&&a<=zm[1]+t?p:0}if(o){var h=i;i=si(r),r=si(h)}else i=si(i),r=si(r);i>r&&(r+=Lm);for(var u=0,c=0;c<2;c++){var d=zm[c];if(d+t>a){var f=Math.atan2(s,d),p=o?1:-1;f<0&&(f=Lm+f),(f>=i&&f<=r||f+Lm>=i&&f+Lm<=r)&&(f>Math.PI/2&&f<1.5*Math.PI&&(p=-p),u+=p)}}return u}function gi(t,e,n,i,r){for(var o=0,a=0,s=0,l=0,h=0,u=0;u1&&(n||(o+=hi(a,s,l,h,i,r))),1==u&&(l=a=t[u],h=s=t[u+1]),c){case Pm.M:a=l=t[u++],s=h=t[u++];break;case Pm.L:if(n){if(ri(a,s,t[u],t[u+1],e,i,r))return!0}else o+=hi(a,s,t[u],t[u+1],i,r)||0;a=t[u++],s=t[u++];break;case Pm.C:if(n){if(oi(a,s,t[u++],t[u++],t[u++],t[u++],t[u],t[u+1],e,i,r))return!0}else o+=di(a,s,t[u++],t[u++],t[u++],t[u++],t[u],t[u+1],i,r)||0;a=t[u++],s=t[u++];break;case Pm.Q:if(n){if(ai(a,s,t[u++],t[u++],t[u],t[u+1],e,i,r))return!0}else o+=fi(a,s,t[u++],t[u++],t[u],t[u+1],i,r)||0;a=t[u++],s=t[u++];break;case Pm.A:var d=t[u++],f=t[u++],p=t[u++],g=t[u++],m=t[u++],v=t[u++],y=(t[u++],1-t[u++]),x=Math.cos(m)*p+d,_=Math.sin(m)*g+f;u>1?o+=hi(a,s,x,_,i,r):(l=x,h=_);var w=(i-d)*g/p+d;if(n){if(li(d,f,g,m,m+v,y,e,w,r))return!0}else o+=pi(d,f,g,m,m+v,y,w,r);a=Math.cos(m+v)*p+d,s=Math.sin(m+v)*g+f;break;case Pm.R:l=a=t[u++],h=s=t[u++];var x=l+t[u++],_=h+t[u++];if(n){if(ri(l,h,x,h,e,i,r)||ri(x,h,x,_,e,i,r)||ri(x,_,l,_,e,i,r)||ri(l,_,l,h,e,i,r))return!0}else o+=hi(x,h,x,_,i,r),o+=hi(l,_,l,h,i,r);break;case Pm.Z:if(n){if(ri(a,s,l,h,e,i,r))return!0}else o+=hi(a,s,l,h,i,r);a=l,s=h}}return n||ui(s,h)||(o+=hi(a,s,l,h,i,r)||0),0!==o}function mi(t,e,n){return gi(t,0,!1,e,n)}function vi(t,e,n,i){return gi(t,e,!0,n,i)}function yi(t){Xe.call(this,t),this.path=null}function xi(t,e,n,i,r,o,a,s,l,h,u){var c=l*(Ym/180),d=jm(c)*(t-n)/2+Xm(c)*(e-i)/2,f=-1*Xm(c)*(t-n)/2+jm(c)*(e-i)/2,p=d*d/(a*a)+f*f/(s*s);p>1&&(a*=Um(p),s*=Um(p));var g=(r===o?-1:1)*Um((a*a*(s*s)-a*a*(f*f)-s*s*(d*d))/(a*a*(f*f)+s*s*(d*d)))||0,m=g*a*f/s,v=g*-s*d/a,y=(t+n)/2+jm(c)*m-Xm(c)*v,x=(e+i)/2+Xm(c)*m+jm(c)*v,_=Km([1,0],[(d-m)/a,(f-v)/s]),w=[(d-m)/a,(f-v)/s],b=[(-1*d-m)/a,(-1*f-v)/s],S=Km(w,b);$m(w,b)<=-1&&(S=Ym),$m(w,b)>=1&&(S=0),0===o&&S>0&&(S-=2*Ym),1===o&&S<0&&(S+=2*Ym),u.addData(h,y,x,a,s,_,S,c,o)}function _i(t){if(!t)return[];var e,n=t.replace(/-/g," -").replace(/ /g," ").replace(/ /g,",").replace(/,,/g,",");for(e=0;e0&&""===f[0]&&f.shift();for(var p=0;p=2){if(r&&"spline"!==r){var o=ov(i,r,n,e.smoothConstraint);t.moveTo(i[0][0],i[0][1]);for(var a=i.length,s=0;s<(n?a:a-1);s++){var l=o[2*s],h=o[2*s+1],u=i[(s+1)%a];t.bezierCurveTo(l[0],l[1],h[0],h[1],u[0],u[1])}}else{"spline"===r&&(i=rv(i,n)),t.moveTo(i[0][0],i[0][1]);for(var s=1,c=i.length;s=0)&&(i={textFill:null,textStroke:t.textStroke,textStrokeWidth:t.textStrokeWidth},t.textFill="#fff",null==t.textStroke&&(t.textStroke=n.autoColor,null==t.textStrokeWidth&&(t.textStrokeWidth=2))),i}function nr(t){var e=t.insideRollback;e&&(t.textFill=e.textFill,t.textStroke=e.textStroke,t.textStrokeWidth=e.textStrokeWidth)}function ir(t,e){var n=e||e.getModel("textStyle");return L([t.fontStyle||n&&n.getShallow("fontStyle")||"",t.fontWeight||n&&n.getShallow("fontWeight")||"",(t.fontSize||n&&n.getShallow("fontSize")||12)+"px",t.fontFamily||n&&n.getShallow("fontFamily")||"sans-serif"].join(" "))}function rr(t,e,n,i,r,o){if("function"==typeof r&&(o=r,r=null),i&&i.isAnimationEnabled()){var a=t?"Update":"",s=i.getShallow("animationDuration"+a),l=i.getShallow("animationEasing"+a),h=i.getShallow("animationDelay"+a);"function"==typeof h&&(h=h(r,i.getAnimationDelayParams?i.getAnimationDelayParams(e,r):null)),"function"==typeof s&&(s=s(r)),s>0?e.animateTo(n,s,h||0,l,o,!!o):(e.stopAnimation(),e.attr(n),o&&o())}else e.stopAnimation(),e.attr(n),o&&o()}function or(t,e,n,i,r){rr(!0,t,e,n,i,r)}function ar(t,e,n,i,r){rr(!1,t,e,n,i,r)}function sr(t,e){for(var n=ot([]);t&&t!==e;)st(n,t.getLocalTransform(),n),t=t.parent;return n}function lr(t,e,n){return e&&!c(e)&&(e=_p.getLocalTransform(e)),n&&(e=ct([],e)),$([],t,e)}function hr(t,e,n){var i=0===e[4]||0===e[5]||0===e[0]?1:Math.abs(2*e[4]/e[0]),r=0===e[4]||0===e[5]||0===e[2]?1:Math.abs(2*e[4]/e[2]),o=["left"===t?-i:"right"===t?i:0,"top"===t?-r:"bottom"===t?r:0];return o=lr(o,e,n),Math.abs(o[0])>Math.abs(o[1])?o[0]>0?"right":"left":o[1]>0?"bottom":"top"}function ur(t,e,n,i){function r(t){var e={position:F(t.position),rotation:t.rotation};return t.shape&&(e.shape=o({},t.shape)),e}if(t&&e){var a=function(t){var e={};return t.traverse(function(t){!t.isGroup&&t.anid&&(e[t.anid]=t)}),e}(t);e.traverse(function(t){if(!t.isGroup&&t.anid){var e=a[t.anid];if(e){var i=r(t);t.attr(r(e)),or(t,i,n,t.dataIndex)}}})}}function cr(t,e){return f(t,function(t){var n=t[0];n=xv(n,e.x),n=_v(n,e.x+e.width);var i=t[1];return i=xv(i,e.y),i=_v(i,e.y+e.height),[n,i]})}function dr(t,e,n){var i=(e=o({rectHover:!0},e)).style={strokeNoScale:!0};if(n=n||{x:-1,y:-1,width:2,height:2},t)return 0===t.indexOf("image://")?(i.image=t.slice(8),a(i,n),new je(e)):Di(t.replace("path://",""),e,n,"center")}function fr(t,e,n){this.parentModel=e,this.ecModel=n,this.option=t}function pr(t,e,n){for(var i=0;i0){if(t<=e[0])return n[0];if(t>=e[1])return n[1]}else{if(t>=e[0])return n[0];if(t<=e[1])return n[1]}else{if(t===e[0])return n[0];if(t===e[1])return n[1]}return(t-e[0])/r*o+n[0]}function xr(t,e){switch(t){case"center":case"middle":t="50%";break;case"left":case"top":t="0%";break;case"right":case"bottom":t="100%"}return"string"==typeof t?vr(t).match(/%$/)?parseFloat(t)/100*e:parseFloat(t):null==t?NaN:+t}function _r(t,e,n){return null==e&&(e=10),e=Math.min(Math.max(0,e),20),t=(+t).toFixed(e),n?t:+t}function wr(t){return t.sort(function(t,e){return t-e}),t}function br(t){if(t=+t,isNaN(t))return 0;for(var e=1,n=0;Math.round(t*e)/e!==t;)e*=10,n++;return n}function Sr(t){var e=t.toString(),n=e.indexOf("e");if(n>0){var i=+e.slice(n+1);return i<0?-i:0}var r=e.indexOf(".");return r<0?0:e.length-1-r}function Mr(t,e){var n=Math.log,i=Math.LN10,r=Math.floor(n(t[1]-t[0])/i),o=Math.round(n(Math.abs(e[1]-e[0]))/i),a=Math.min(Math.max(-r+o,0),20);return isFinite(a)?a:20}function Ir(t,e,n){if(!t[e])return 0;var i=p(t,function(t,e){return t+(isNaN(e)?0:e)},0);if(0===i)return 0;for(var r=Math.pow(10,n),o=f(t,function(t){return(isNaN(t)?0:t)/i*r*100}),a=100*r,s=f(o,function(t){return Math.floor(t)}),l=p(s,function(t,e){return t+e},0),h=f(o,function(t,e){return t-s[e]});lu&&(u=h[d],c=d);++s[c],h[c]=0,++l}return s[e]/r}function Tr(t){var e=2*Math.PI;return(t%e+e)%e}function Cr(t){return t>-kv&&t=-20?+t.toFixed(i<0?-i:0):t}function Lr(t){return isNaN(t)?"-":(t=(t+"").split("."))[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g,"$1,")+(t.length>1?"."+t[1]:"")}function Or(t,e){return t=(t||"").toLowerCase().replace(/-(.)/g,function(t,e){return e.toUpperCase()}),e&&t&&(t=t.charAt(0).toUpperCase()+t.slice(1)),t}function zr(t){return String(t).replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function Er(t,e,n){y(e)||(e=[e]);var i=e.length;if(!i)return"";for(var r=e[0].$vars||[],o=0;o':'':""}function Nr(t,e,n){"week"!==t&&"month"!==t&&"quarter"!==t&&"half-year"!==t&&"year"!==t||(t="MM-dd\nyyyy");var i=Ar(e),r=n?"UTC":"",o=i["get"+r+"FullYear"](),a=i["get"+r+"Month"]()+1,s=i["get"+r+"Date"](),l=i["get"+r+"Hours"](),h=i["get"+r+"Minutes"](),u=i["get"+r+"Seconds"]();return t=t.replace("MM",Rv(a)).replace("M",a).replace("yyyy",o).replace("yy",o%100).replace("dd",Rv(s)).replace("d",s).replace("hh",Rv(l)).replace("h",l).replace("mm",Rv(h)).replace("m",h).replace("ss",Rv(u)).replace("s",u)}function Br(t){return t?t.charAt(0).toUpperCase()+t.substr(1):t}function Vr(t,e,n,i,r){var o=0,a=0;null==i&&(i=1/0),null==r&&(r=1/0);var s=0;e.eachChild(function(l,h){var u,c,d=l.position,f=l.getBoundingRect(),p=e.childAt(h+1),g=p&&p.getBoundingRect();if("horizontal"===t){var m=f.width+(g?-g.x+f.x:0);(u=o+m)>i||l.newline?(o=0,u=m,a+=s+n,s=f.height):s=Math.max(s,f.height)}else{var v=f.height+(g?-g.y+f.y:0);(c=a+v)>r||l.newline?(o+=s+n,a=0,c=v,s=f.width):s=Math.max(s,f.width)}l.newline||(d[0]=o,d[1]=a,"horizontal"===t?o=u+n:a=c+n)})}function Fr(t,e,n){n=Ov(n||0);var i=e.width,r=e.height,o=xr(t.left,i),a=xr(t.top,r),s=xr(t.right,i),l=xr(t.bottom,r),h=xr(t.width,i),u=xr(t.height,r),c=n[2]+n[0],d=n[1]+n[3],f=t.aspect;switch(isNaN(h)&&(h=i-s-d-o),isNaN(u)&&(u=r-l-c-a),null!=f&&(isNaN(h)&&isNaN(u)&&(f>i/r?h=.8*i:u=.8*r),isNaN(h)&&(h=f*u),isNaN(u)&&(u=h/f)),isNaN(o)&&(o=i-s-h-d),isNaN(a)&&(a=r-l-u-c),t.left||t.right){case"center":o=i/2-h/2-n[3];break;case"right":o=i-h-d}switch(t.top||t.bottom){case"middle":case"center":a=r/2-u/2-n[0];break;case"bottom":a=r-u-c}o=o||0,a=a||0,isNaN(h)&&(h=i-d-o-(s||0)),isNaN(u)&&(u=r-c-a-(l||0));var p=new Xt(o+n[3],a+n[0],h,u);return p.margin=n,p}function Gr(t,e,n,i,r){var o=!r||!r.hv||r.hv[0],s=!r||!r.hv||r.hv[1],l=r&&r.boundingMode||"all";if(o||s){var h;if("raw"===l)h="group"===t.type?new Xt(0,0,+e.width||0,+e.height||0):t.getBoundingRect();else if(h=t.getBoundingRect(),t.needLocalTransform()){var u=t.getLocalTransform();(h=h.clone()).applyTransform(u)}e=Fr(a({width:h.width,height:h.height},e),n,i);var c=t.position,d=o?e.x-h.x:0,f=s?e.y-h.y:0;t.attr("position","raw"===l?[d,f]:[c[0]+d,c[1]+f])}}function Hr(t,e,n){function i(n,i){var a={},l=0,h={},u=0;if(Fv(n,function(e){h[e]=t[e]}),Fv(n,function(t){r(e,t)&&(a[t]=h[t]=e[t]),o(a,t)&&l++,o(h,t)&&u++}),s[i])return o(e,n[1])?h[n[2]]=null:o(e,n[2])&&(h[n[1]]=null),h;if(2!==u&&l){if(l>=2)return a;for(var c=0;ce)return t[i];return t[n-1]}function Xr(t){var e=t.get("coordinateSystem"),n={coordSysName:e,coordSysDims:[],axisMap:R(),categoryAxisMap:R()},i=Kv[e];if(i)return i(t,n,n.axisMap,n.categoryAxisMap),n}function jr(t){return"category"===t.get("type")}function Yr(t){this.fromDataset=t.fromDataset,this.data=t.data||(t.sourceFormat===ey?{}:[]),this.sourceFormat=t.sourceFormat||ny,this.seriesLayoutBy=t.seriesLayoutBy||ry,this.dimensionsDefine=t.dimensionsDefine,this.encodeDefine=t.encodeDefine&&R(t.encodeDefine),this.startIndex=t.startIndex||0,this.dimensionsDetectCount=t.dimensionsDetectCount}function qr(t){var e=t.option.source,n=ny;if(S(e))n=iy;else if(y(e))for(var i=0,r=e.length;i=e:"max"===n?t<=e:t===e}function wo(t,e){return t.join(",")===e.join(",")}function bo(t,e){cy(e=e||{},function(e,n){if(null!=e){var i=t[n];if(Xv.hasClass(n)){e=xn(e);var r=Sn(i=xn(i),e);t[n]=fy(r,function(t){return t.option&&t.exist?py(t.exist,t.option,!0):t.exist||t.option})}else t[n]=py(i,e,!0)}})}function So(t){var e=t&&t.itemStyle;if(e)for(var n=0,r=yy.length;ne.outputData.count()&&e.model.getRawData().cloneShallow(e.outputData)}function Ko(t,e){d(t.CHANGABLE_METHODS,function(n){t.wrapMethod(n,v(Qo,e))})}function Qo(t){var e=Jo(t);e&&e.setOutputEnd(this.count())}function Jo(t){var e=(t.ecModel||{}).scheduler,n=e&&e.getPipeline(t.uid);if(n){var i=n.currentTask;if(i){var r=i.agentStubMap;r&&(i=r.get(t.uid))}return i}}function ta(){this.group=new Xp,this.uid=mr("viewChart"),this.renderTask=Wo({plan:ia,reset:ra}),this.renderTask.context={view:this}}function ea(t,e){if(t&&(t.trigger(e),"group"===t.type))for(var n=0;n=0?i():c=setTimeout(i,-o),h=r};return d.clear=function(){c&&(clearTimeout(c),c=null)},d.debounceNextCall=function(t){l=t},d}function sa(t,e,n,i){var r=t[e];if(r){var o=r[By]||r,a=r[Fy];if(r[Vy]!==n||a!==i){if(null==n||!i)return t[e]=o;(r=t[e]=aa(o,n,"debounce"===i))[By]=o,r[Fy]=i,r[Vy]=n}return r}}function la(t,e){var n=t[e];n&&n[By]&&(t[e]=n[By])}function ha(t,e){this.ecInstance=t,this.api=e,this.unfinished,this._stageTaskMap=R()}function ua(t,e,n,i,r){function o(t,e){return t.setDirty&&(!t.dirtyMap||t.dirtyMap.get(e.__pipeline.id))}r=r||{};var a;d(e,function(e,s){if(!r.visualType||r.visualType===e.visualType){var l=t._stageTaskMap.get(e.uid),h=l.seriesTaskMap,u=l.overallTask;if(u){var c,d=u.agentStubMap;d.each(function(t){o(r,t)&&(t.dirty(),c=!0)}),c&&u.dirty(),Xy(u,i);var f=t.getPerformArgs(u,r.block);d.each(function(t){t.perform(f)}),a|=u.perform(f)}else h&&h.each(function(s,l){o(r,s)&&s.dirty();var h=t.getPerformArgs(s,r.block);h.skip=!e.performRawSeries&&n.isSeriesFiltered(s.context.model),Xy(s,i),a|=s.perform(h)})}}),t.unfinished|=a}function ca(t,e,n,i,r){function o(n){var o=n.uid,s=a.get(o)||a.set(o,Wo({plan:va,reset:ya,count:_a}));s.context={model:n,ecModel:i,api:r,useClearVisual:e.isVisual&&!e.isLayout,plan:e.plan,reset:e.reset,scheduler:t},wa(t,n,s)}var a=n.seriesTaskMap||(n.seriesTaskMap=R()),s=e.seriesType,l=e.getTargetSeries;e.createOnAllSeries?i.eachRawSeries(o):s?i.eachRawSeriesByType(s,o):l&&l(i,r).each(o);var h=t._pipelineMap;a.each(function(t,e){h.get(e)||(t.dispose(),a.removeKey(e))})}function da(t,e,n,i,r){function o(e){var n=e.uid,i=s.get(n)||s.set(n,Wo({reset:pa,onDirty:ma}));i.context={model:e,overallProgress:u,isOverallFilter:c},i.agent=a,i.__block=u,wa(t,e,i)}var a=n.overallTask=n.overallTask||Wo({reset:fa});a.context={ecModel:i,api:r,overallReset:e.overallReset,scheduler:t};var s=a.agentStubMap=a.agentStubMap||R(),l=e.seriesType,h=e.getTargetSeries,u=!0,c=e.isOverallFilter;l?i.eachRawSeriesByType(l,o):h?h(i,r).each(o):(u=!1,d(i.getSeries(),o));var f=t._pipelineMap;s.each(function(t,e){f.get(e)||(t.dispose(),s.removeKey(e))})}function fa(t){t.overallReset(t.ecModel,t.api,t.payload)}function pa(t,e){return t.overallProgress&&ga}function ga(){this.agent.dirty(),this.getDownstream().dirty()}function ma(){this.agent&&this.agent.dirty()}function va(t){return t.plan&&t.plan(t.model,t.ecModel,t.api,t.payload)}function ya(t){if(t.useClearVisual&&t.data.clearAllVisual(),(t.resetDefines=xn(t.reset(t.model,t.ecModel,t.api,t.payload))).length)return xa}function xa(t,e){for(var n=e.data,i=e.resetDefines,r=0;re.get("hoverLayerThreshold")&&!Zf.node&&n.traverse(function(t){t.isGroup||(t.useHoverLayer=!0)})}function Wa(t,e){var n=t.get("blendMode")||null;e.group.traverse(function(t){t.isGroup||t.style.blend!==n&&t.setStyle("blend",n),t.eachPendingDisplayable&&t.eachPendingDisplayable(function(t){t.setStyle("blend",n)})})}function Za(t,e){var n=t.get("z"),i=t.get("zlevel");e.group.traverse(function(t){"group"!==t.type&&(null!=n&&(t.z=n),null!=i&&(t.zlevel=i))})}function Ua(t){var e=t._coordSysMgr;return o(new go(t),{getCoordinateSystems:m(e.getCoordinateSystems,e),getComponentByElement:function(e){for(;e;){var n=e.__ecComponentInfo;if(null!=n)return t._model.getComponent(n.mainType,n.index);e=e.parent}}})}function Xa(t){function e(t,e){for(var i=0;i65535?e:n}function ps(t){var e=t.constructor;return e===Array?t.slice():new e(t)}function gs(t,e){d(Vx.concat(e.__wrappedMethods||[]),function(n){e.hasOwnProperty(n)&&(t[n]=e[n])}),t.__wrappedMethods=e.__wrappedMethods}function ms(t){return t}function vs(t){return t=0?this._indices[t]:-1}function ys(t,e){var n=t._idList[e];return null==n&&(n=t._getIdFromStore(e)),null==n&&(n=Nx+e),n}function xs(t){return y(t)||(t=[t]),t}function _s(t,e){var n=t.dimensions,i=new Fx(f(n,t.getDimensionInfo,t),t.hostModel);gs(i,t);for(var r=i._storage={},o=t._storage,a=0;a=0?ws(o[s]):o[s])}return i}function ws(t){for(var e=new Array(t.length),n=0;ni&&(a=r.interval=i);var s=r.intervalPrecision=zs(a);return Rs(r.niceTickExtent=[jx(Math.ceil(t[0]/a)*a,s),jx(Math.floor(t[1]/a)*a,s)],t),r}function zs(t){return Sr(t)+2}function Es(t,e,n){t[e]=Math.max(Math.min(t[e],n[1]),n[0])}function Rs(t,e){!isFinite(t[0])&&(t[0]=e[0]),!isFinite(t[1])&&(t[1]=e[1]),Es(t,0,e),Es(t,1,e),t[0]>t[1]&&(t[0]=t[1])}function Ns(t,e,n,i){var r=[];if(!t)return r;e[0]1e4)return[];return e[1]>(r.length?r[r.length-1]:n[1])&&r.push(e[1]),r}function Bs(t){return t.get("stack")||$x+t.seriesIndex}function Vs(t){return t.dim+t.index}function Fs(t,e){return Gs(f(t,function(t){var e=t.getData(),n=t.coordinateSystem.getBaseAxis(),i=n.getExtent(),r="category"===n.type?n.getBandWidth():Math.abs(i[1]-i[0])/e.count();return{bandWidth:r,barWidth:xr(t.get("barWidth"),r),barMaxWidth:xr(t.get("barMaxWidth"),r),barGap:t.get("barGap"),barCategoryGap:t.get("barCategoryGap"),axisKey:Vs(n),stackId:Bs(t)}}),e)}function Gs(t,e){var n={};d(t,function(t,e){var i=t.axisKey,r=t.bandWidth,o=n[i]||{bandWidth:r,remainedWidth:r,autoWidthCount:0,categoryGap:"20%",gap:"30%",stacks:{}},a=o.stacks;n[i]=o;var s=t.stackId;a[s]||o.autoWidthCount++,a[s]=a[s]||{width:0,maxWidth:0};var l=t.barWidth;l&&!a[s].width&&(a[s].width=l,l=Math.min(o.remainedWidth,l),o.remainedWidth-=l);var h=t.barMaxWidth;h&&(a[s].maxWidth=h);var u=t.barGap;null!=u&&(o.gap=u);var c=t.barCategoryGap;null!=c&&(o.categoryGap=c)});var i={};return d(n,function(t,e){i[e]={};var n=t.stacks,r=t.bandWidth,o=xr(t.categoryGap,r),a=xr(t.gap,1),s=t.remainedWidth,l=t.autoWidthCount,h=(s-o)/(l+(l-1)*a);h=Math.max(h,0),d(n,function(t,e){var n=t.maxWidth;n&&n0&&s>0&&!l&&(a=0),a<0&&s<0&&!h&&(s=0));var c=e.ecModel;if(c){var d=g(c.getSeriesByType("bar"),function(t){return t.getBaseAxis()===e.axis}).length>0;if(("time"===o||"interval"===o)&&d){var f=Zs(a,s,e);a=f.min,s=f.max}}return[a,s]}function Zs(t,e,n){var i=n.ecModel,r=n.axis.getExtent(),o=r[1]-r[0],a=Fs(g(i.getSeriesByType("bar"),function(t){return!i.isSeriesFiltered(t)&&t.coordinateSystem&&"cartesian2d"===t.coordinateSystem.type}))[n.axis.dim+n.axis.index];if(void 0===a)return{min:t,max:e};var s=1/0;d(a,function(t){s=Math.min(t.offset,s)});var l=-1/0;d(a,function(t){l=Math.max(t.offset+t.width,l)});var h=Math.abs(s)+l,u=e-t,c=u/(1-(s+l)/o)-u;return e+=c*(l/h),t-=c*(s/h),{min:t,max:e}}function Us(t,e){var n=Ws(t,e),i=null!=e.getMin(),r=null!=e.getMax(),o=e.get("splitNumber");"log"===t.type&&(t.base=e.get("logBase"));var a=t.type;t.setExtent(n[0],n[1]),t.niceExtent({splitNumber:o,fixMin:i,fixMax:r,minInterval:"interval"===a||"time"===a?e.get("minInterval"):null,maxInterval:"interval"===a||"time"===a?e.get("maxInterval"):null});var s=e.get("interval");null!=s&&t.setInterval&&t.setInterval(s)}function Xs(t,e){if(e=e||t.get("type"))switch(e){case"category":return new Xx(t.getOrdinalMeta?t.getOrdinalMeta():t.getCategories(),[1/0,-1/0]);case"value":return new qx;default:return(Ds.getClass(e)||qx).create(t)}}function js(t,e,n,i,r){var o,a=0,s=0,l=(i-r)/180*Math.PI,h=1;e.length>40&&(h=Math.floor(e.length/40));for(var u=0;u1?h:(a+1)*h-1}function Ys(t,e){var n=t.scale,i=n.getTicksLabels(),r=n.getTicks();return"string"==typeof e?(e=function(t){return function(e){return t.replace("{value}",null!=e?e:"")}}(e),f(i,e)):"function"==typeof e?f(r,function(n,i){return e(qs(t,n),i)},this):i}function qs(t,e){return"category"===t.type?t.scale.getLabel(e):e}function $s(t,e){if("image"!==this.type){var n=this.style,i=this.shape;i&&"line"===i.symbolType?n.stroke=t:this.__isEmptyBrush?(n.stroke=t,n.fill=e||"#fff"):(n.fill&&(n.fill=t),n.stroke&&(n.stroke=t)),this.dirty(!1)}}function Ks(t,e,n,i,r,o,a){var s=0===t.indexOf("empty");s&&(t=t.substr(5,1).toLowerCase()+t.substr(6));var l;return l=0===t.indexOf("image://")?ki(t.slice(8),new Xt(e,n,i,r),a?"center":"cover"):0===t.indexOf("path://")?Di(t.slice(7),{},new Xt(e,n,i,r),a?"center":"cover"):new x_({shape:{symbolType:t,x:e,y:n,width:i,height:r}}),l.__isEmptyBrush=s,l.setColor=$s,l.setColor(o),l}function Qs(t,e){return Math.abs(t-e)>1^-(1&s),l=l>>1^-(1&l),r=s+=r,o=l+=o,i.push([s/n,l/n])}return i}function il(t,e){var n=(t[1]-t[0])/e/2;t[0]+=n,t[1]-=n}function rl(t,e){var n=t.mapDimension("defaultedLabel",!0),i=n.length;if(1===i)return Go(t,e,n[0]);if(i){for(var r=[],o=0;o=0?1:-1}function fl(t,e,n){for(var i,r=t.getBaseAxis(),o=t.getOtherAxis(r),a=r.onZero?0:o.scale.getExtent()[0],s=o.dim,l="x"===s||"radius"===s?1:0,h=e.stackedOn,u=e.get(s,n);h&&dl(h.get(s,n))===dl(u);){i=h;break}var c=[];return c[l]=e.get(r.dim,n),c[1-l]=i?i.get(s,n,!0):a,t.dataToPoint(c)}function pl(t,e){var n=[];return e.diff(t).add(function(t){n.push({cmd:"+",idx:t})}).update(function(t,e){n.push({cmd:"=",idx:e,idx1:t})}).remove(function(t){n.push({cmd:"-",idx:t})}).execute(),n}function gl(t){return isNaN(t[0])||isNaN(t[1])}function ml(t,e,n,i,r,o,a,s,l,h,u){for(var c=0,d=n,f=0;f=r||d<0)break;if(gl(p)){if(u){d+=o;continue}break}if(d===n)t[o>0?"moveTo":"lineTo"](p[0],p[1]),B_(F_,p);else if(l>0){var g=d+o,m=e[g];if(u)for(;m&&gl(e[g]);)m=e[g+=o];var v=.5,y=e[c];if(!(m=e[g])||gl(m))B_(G_,p);else{gl(m)&&!u&&(m=p),W(V_,m,y);var x,_;if("x"===h||"y"===h){var w="x"===h?0:1;x=Math.abs(p[w]-y[w]),_=Math.abs(p[w]-m[w])}else x=lp(p,y),_=lp(p,m);N_(G_,p,V_,-l*(1-(v=_/(_+x))))}E_(F_,F_,s),R_(F_,F_,a),E_(G_,G_,s),R_(G_,G_,a),t.bezierCurveTo(F_[0],F_[1],G_[0],G_[1],p[0],p[1]),N_(F_,p,V_,l*v)}else t.lineTo(p[0],p[1]);c=d,d+=o}return f}function vl(t,e){var n=[1/0,1/0],i=[-1/0,-1/0];if(e)for(var r=0;ri[0]&&(i[0]=o[0]),o[1]>i[1]&&(i[1]=o[1])}return{min:e?n:i,max:e?i:n}}function yl(t,e){if(t.length===e.length){for(var n=0;ne[0]?1:-1;e[0]+=i*n,e[1]-=i*n}return e}function wl(t){return t>=0?1:-1}function bl(t,e,n,i){var r=e.getBaseAxis(),o=e.getOtherAxis(r),a=0,s=o.scale.getExtent();"start"===i?a=s[0]:"end"===i?a=s[1]:(s=o.scale.getExtent())[0]>0?a=s[0]:s[1]<0&&(a=s[1]);var l=o.dim,h="x"===l||"radius"===l?1:0,u=n.mapDimension(l);return n.mapArray(u?[u]:[],function(t,i){for(var o,s=n.stackedOn;s&&wl(s.get(u,i))===wl(t);){o=s;break}var l=[];return l[h]=n.get(r.dim,i),l[1-h]=o?o.get(u,i,!0):a,e.dataToPoint(l)},!0)}function Sl(t,e,n){var i=_l(t.getAxis("x")),r=_l(t.getAxis("y")),o=t.getBaseAxis().isHorizontal(),a=Math.min(i[0],i[1]),s=Math.min(r[0],r[1]),l=Math.max(i[0],i[1])-a,h=Math.max(r[0],r[1])-s,u=n.get("lineStyle.width")||2,c=n.get("clipOverflow")?u/2:Math.max(l,h);o?(s-=c,h+=2*c):(a-=c,l+=2*c);var d=new lv({shape:{x:a,y:s,width:l,height:h}});return e&&(d.shape[o?"width":"height"]=0,ar(d,{shape:{width:l,height:h}},n)),d}function Ml(t,e,n){var i=t.getAngleAxis(),r=t.getRadiusAxis().getExtent(),o=i.getExtent(),a=Math.PI/180,s=new nv({shape:{cx:t.cx,cy:t.cy,r0:r[0],r:r[1],startAngle:-o[0]*a,endAngle:-o[1]*a,clockwise:i.inverse}});return e&&(s.shape.endAngle=-o[0]*a,ar(s,{shape:{endAngle:-o[1]*a}},n)),s}function Il(t,e,n){return"polar"===t.type?Ml(t,e,n):Sl(t,e,n)}function Tl(t,e,n){for(var i=e.getBaseAxis(),r="x"===i.dim||"radius"===i.dim?0:1,o=[],a=0;a=0;r--)if(n[r].dimension<2){i=n[r];break}if(i&&"cartesian2d"===e.type){var o=i.dimension,a=t.dimensions[o],s=e.getAxis(a),l=f(i.stops,function(t){return{coord:s.toGlobalCoord(s.dataToCoord(t.value)),color:t.color}}),h=l.length,u=i.outerColors.slice();h&&l[0].coord>l[h-1].coord&&(l.reverse(),u.reverse());var c=l[0].coord-10,p=l[h-1].coord+10,g=p-c;if(g<.001)return"transparent";d(l,function(t){t.offset=(t.coord-c)/g}),l.push({offset:h?l[h-1].offset:.5,color:u[1]||"transparent"}),l.unshift({offset:h?l[0].offset:.5,color:u[0]||"transparent"});var m=new gv(0,0,0,0,l,!0);return m[a]=c,m[a+"2"]=p,m}}}function Al(t){return this._axes[t]}function Dl(t){Y_.call(this,t)}function kl(t,e){return e.type||(e.data?"category":"value")}function Pl(t,e,n){return t.getCoordSysModel()===e}function Ll(t,e){var n=e*Math.PI/180,i=t.plain(),r=i.width,o=i.height,a=r*Math.cos(n)+o*Math.sin(n),s=r*Math.sin(n)+o*Math.cos(n);return new Xt(i.x,i.y,a,s)}function Ol(t){var e,n=t.model,i=n.get("axisLabel.show")?n.getFormattedLabels():[],r=n.getModel("axisLabel"),o=1,a=i.length;a>40&&(o=Math.ceil(a/40));for(var s=0;si[1],l="start"===e&&!s||"start"!==e&&s;return Cr(a-sw/2)?(o=l?"bottom":"top",r="center"):Cr(a-1.5*sw)?(o=l?"top":"bottom",r="center"):(o="middle",r=a<1.5*sw&&a>sw/2?l?"left":"right":l?"right":"left"),{rotation:a,textAlign:r,textVerticalAlign:o}}function Hl(t){var e=t.get("tooltip");return t.get("silent")||!(t.get("triggerEvent")||e&&e.show)}function Wl(t,e,n){var i=t.get("axisLabel.showMinLabel"),r=t.get("axisLabel.showMaxLabel");e=e||[],n=n||[];var o=e[0],a=e[1],s=e[e.length-1],l=e[e.length-2],h=n[0],u=n[1],c=n[n.length-1],d=n[n.length-2];!1===i?(Zl(o),Zl(h)):Ul(o,a)&&(i?(Zl(a),Zl(u)):(Zl(o),Zl(h))),!1===r?(Zl(s),Zl(c)):Ul(l,s)&&(r?(Zl(l),Zl(d)):(Zl(s),Zl(c)))}function Zl(t){t&&(t.ignore=!0)}function Ul(t,e,n){var i=t&&t.getBoundingRect().clone(),r=e&&e.getBoundingRect().clone();if(i&&r){var o=ot([]);return ht(o,o,-t.rotation),i.applyTransform(st([],o,t.getLocalTransform())),r.applyTransform(st([],o,e.getLocalTransform())),i.intersect(r)}}function Xl(t){return"middle"===t||"center"===t}function jl(t,e,n){var i=e.axis;if(e.get("axisTick.show")&&!i.scale.isBlank()){for(var r=e.getModel("axisTick"),o=r.getModel("lineStyle"),s=r.get("length"),l=dw(r,n.labelInterval),h=i.getTicksCoords(r.get("alignWithLabel")),u=i.scale.getTicks(),c=e.get("axisLabel.showMinLabel"),d=e.get("axisLabel.showMaxLabel"),f=[],p=[],g=t._transform,m=[],v=h.length,y=0;y=0||t===e}function eh(t){var e=nh(t);if(e){var n=e.axisPointerModel,i=e.axis.scale,r=n.option,o=n.get("status"),a=n.get("value");null!=a&&(a=i.parse(a));var s=rh(n);null==o&&(r.status=s?"show":"hide");var l=i.getExtent().slice();l[0]>l[1]&&l.reverse(),(null==a||a>l[1])&&(a=l[1]),a0?"bottom":"top":r.width>0?"left":"right";l||hh(t.style,d,i,h,o,n,p),Yi(t,d)}function ph(t,e){var n=t.get(Mw)||0;return Math.min(n,Math.abs(e.width),Math.abs(e.height))}function gh(t,e,n,i){var r=e.getData(),o=this.dataIndex,a=r.getName(o),s=e.get("selectedOffset");i.dispatchAction({type:"pieToggleSelect",from:t,name:a,seriesId:e.id}),r.each(function(t){mh(r.getItemGraphicEl(t),r.getItemLayout(t),e.isSelected(r.getName(t)),s,n)})}function mh(t,e,n,i,r){var o=(e.startAngle+e.endAngle)/2,a=Math.cos(o),s=Math.sin(o),l=n?i:0,h=[a*l,s*l];r?t.animate().when(200,{position:h}).start("bounceOut"):t.attr("position",h)}function vh(t,e){function n(){o.ignore=o.hoverIgnore,a.ignore=a.hoverIgnore}function i(){o.ignore=o.normalIgnore,a.ignore=a.normalIgnore}Xp.call(this);var r=new nv({z2:2}),o=new sv,a=new Qm;this.add(r),this.add(o),this.add(a),this.updateData(t,e,!0),this.on("emphasis",n).on("normal",i).on("mouseover",n).on("mouseout",i)}function yh(t,e,n,i,r,o,a){function s(e,n){for(var i=e;i>=0&&(t[i].y-=n,!(i>0&&t[i].y>t[i-1].y+t[i-1].height));i--);}function l(t,e,n,i,r,o){for(var a=e?Number.MAX_VALUE:0,s=0,l=t.length;s=a&&(d=a-10),!e&&d<=a&&(d=a+10),t[s].x=n+d*o,a=d}}t.sort(function(t,e){return t.y-e.y});for(var h,u=0,c=t.length,d=[],f=[],p=0;pe&&o+1t[o].y+t[o].height)return void s(o,i/2);s(n-1,i/2)}(p,c,-h),u=t[p].y+t[p].height;a-u<0&&s(c-1,u-a);for(p=0;p=n?f.push(t[p]):d.push(t[p]);l(d,!1,e,n,i,r),l(f,!0,e,n,i,r)}function xh(t,e,n,i,r,o){for(var a=[],s=[],l=0;l=0&&s<0)&&(a=p,s=f,r=h,o.length=0),Bw(u,function(t){o.push({seriesIndex:e.seriesIndex,dataIndexInside:t,dataIndex:e.getData().getRawIndex(t)})}))}}),{payloadBatch:o,snapToValue:r}}function kh(t,e,n,i){t[e.key]={value:n,payloadBatch:i}}function Ph(t,e,n,i){var r=n.payloadBatch,o=e.axis,a=o.model,s=e.axisPointerModel;if(e.triggerTooltip&&r.length){var l=e.coordSys.model,h=oh(l),u=t.map[h];u||(u=t.map[h]={coordSysId:l.id,coordSysIndex:l.componentIndex,coordSysType:l.type,coordSysMainType:l.mainType,dataByAxis:[]},t.list.push(u)),u.dataByAxis.push({axisDim:o.dim,axisIndex:a.componentIndex,axisType:a.type,axisId:a.id,value:i,valueLabelOpt:{precision:s.get("label.precision"),formatter:s.get("label.formatter")},seriesDataIndices:r.slice()})}}function Lh(t,e,n){var i=n.axesInfo=[];Bw(e,function(e,n){var r=e.axisPointerModel.option,o=t[n];o?(!e.useHandle&&(r.status="show"),r.value=o.value,r.seriesDataIndices=(o.payloadBatch||[]).slice()):!e.useHandle&&(r.status="hide"),"show"===r.status&&i.push({axisDim:e.axis.dim,axisIndex:e.axis.model.componentIndex,value:r.value})})}function Oh(t,e,n,i){if(!Nh(e)&&t.list.length){var r=((t.list[0].dataByAxis[0]||{}).seriesDataIndices||[])[0]||{};i({type:"showTip",escapeConnect:!0,x:e[0],y:e[1],tooltipOption:n.tooltipOption,position:n.position,dataIndexInside:r.dataIndexInside,dataIndex:r.dataIndex,seriesIndex:r.seriesIndex,dataByCoordSys:t.list})}else i({type:"hideTip"})}function zh(t,e,n){var i=n.getZr(),r=Fw(i).axisPointerLastHighlights||{},o=Fw(i).axisPointerLastHighlights={};Bw(t,function(t,e){var n=t.axisPointerModel.option;"show"===n.status&&Bw(n.seriesDataIndices,function(t){var e=t.seriesIndex+" | "+t.dataIndex;o[e]=t})});var a=[],s=[];d(r,function(t,e){!o[e]&&s.push(t)}),d(o,function(t,e){!r[e]&&a.push(t)}),s.length&&n.dispatchAction({type:"downplay",escapeConnect:!0,batch:s}),a.length&&n.dispatchAction({type:"highlight",escapeConnect:!0,batch:a})}function Eh(t,e){for(var n=0;n<(t||[]).length;n++){var i=t[n];if(e.axis.dim===i.axisDim&&e.axis.model.componentIndex===i.axisIndex)return i}}function Rh(t){var e=t.axis.model,n={},i=n.axisDim=t.axis.dim;return n.axisIndex=n[i+"AxisIndex"]=e.componentIndex,n.axisName=n[i+"AxisName"]=e.name,n.axisId=n[i+"AxisId"]=e.id,n}function Nh(t){return!t||null==t[0]||isNaN(t[0])||null==t[1]||isNaN(t[1])}function Bh(t,e,n){if(!Zf.node){var i=e.getZr();Gw(i).records||(Gw(i).records={}),Vh(i,e),(Gw(i).records[t]||(Gw(i).records[t]={})).handler=n}}function Vh(t,e){function n(n,i){t.on(n,function(n){var r=Wh(e);Hw(Gw(t).records,function(t){t&&i(t,n,r.dispatchAction)}),Fh(r.pendings,e)})}Gw(t).initialized||(Gw(t).initialized=!0,n("click",v(Hh,"click")),n("mousemove",v(Hh,"mousemove")),n("globalout",Gh))}function Fh(t,e){var n,i=t.showTip.length,r=t.hideTip.length;i?n=t.showTip[i-1]:r&&(n=t.hideTip[r-1]),n&&(n.dispatchAction=null,e.dispatchAction(n))}function Gh(t,e,n){t.handler("leave",null,n)}function Hh(t,e,n,i){e.handler(t,n,i)}function Wh(t){var e={showTip:[],hideTip:[]},n=function(i){var r=e[i.type];r?r.push(i):(i.dispatchAction=n,t.dispatchAction(i))};return{dispatchAction:n,pendings:e}}function Zh(t,e){if(!Zf.node){var n=e.getZr();(Gw(n).records||{})[t]&&(Gw(n).records[t]=null)}}function Uh(){}function Xh(t,e,n,i){jh(Zw(n).lastProp,i)||(Zw(n).lastProp=i,e?or(n,i,t):(n.stopAnimation(),n.attr(i)))}function jh(t,e){if(w(t)&&w(e)){var n=!0;return d(e,function(e,i){n=n&&jh(t[i],e)}),!!n}return t===e}function Yh(t,e){t[e.get("label.show")?"show":"hide"]()}function qh(t){return{position:t.position.slice(),rotation:t.rotation||0}}function $h(t,e,n){var i=e.get("z"),r=e.get("zlevel");t&&t.traverse(function(t){"group"!==t.type&&(null!=i&&(t.z=i),null!=r&&(t.zlevel=r),t.silent=n)})}function Kh(t){var e,n=t.get("type"),i=t.getModel(n+"Style");return"line"===n?(e=i.getLineStyle()).fill=null:"shadow"===n&&((e=i.getAreaStyle()).stroke=null),e}function Qh(t,e,n,i,r){var o=tu(n.get("value"),e.axis,e.ecModel,n.get("seriesDataIndices"),{precision:n.get("label.precision"),formatter:n.get("label.formatter")}),a=n.getModel("label"),s=Ov(a.get("padding")||0),l=a.getFont(),h=ce(o,l),u=r.position,c=h.width+s[1]+s[3],d=h.height+s[0]+s[2],f=r.align;"right"===f&&(u[0]-=c),"center"===f&&(u[0]-=c/2);var p=r.verticalAlign;"bottom"===p&&(u[1]-=d),"middle"===p&&(u[1]-=d/2),Jh(u,c,d,i);var g=a.get("backgroundColor");g&&"auto"!==g||(g=e.get("axisLine.lineStyle.color")),t.label={shape:{x:0,y:0,width:c,height:d,r:a.get("borderRadius")},position:u.slice(),style:{text:o,textFont:l,textFill:a.getTextColor(),textPosition:"inside",fill:g,stroke:a.get("borderColor")||"transparent",lineWidth:a.get("borderWidth")||0,shadowBlur:a.get("shadowBlur"),shadowColor:a.get("shadowColor"),shadowOffsetX:a.get("shadowOffsetX"),shadowOffsetY:a.get("shadowOffsetY")},z2:10}}function Jh(t,e,n,i){var r=i.getWidth(),o=i.getHeight();t[0]=Math.min(t[0]+e,r)-e,t[1]=Math.min(t[1]+n,o)-n,t[0]=Math.max(t[0],0),t[1]=Math.max(t[1],0)}function tu(t,e,n,i,r){var o=e.scale.getLabel(t,{precision:r.precision}),a=r.formatter;if(a){var s={value:qs(e,t),seriesData:[]};d(i,function(t){var e=n.getSeriesByIndex(t.seriesIndex),i=t.dataIndexInside,r=e&&e.getDataParams(i);r&&s.seriesData.push(r)}),_(a)?o=a.replace("{value}",o):x(a)&&(o=a(s))}return o}function eu(t,e,n){var i=rt();return ht(i,i,n.rotation),lt(i,i,n.position),lr([t.dataToCoord(e),(n.labelOffset||0)+(n.labelDirection||1)*(n.labelMargin||0)],i)}function nu(t,e,n,i,r,o){var a=lw.innerTextLayout(n.rotation,0,n.labelDirection);n.labelMargin=r.get("label.margin"),Qh(e,i,r,o,{position:eu(i.axis,t,n),align:a.textAlign,verticalAlign:a.textVerticalAlign})}function iu(t,e,n){return n=n||0,{x1:t[n],y1:t[1-n],x2:e[n],y2:e[1-n]}}function ru(t,e,n){return n=n||0,{x:t[n],y:t[1-n],width:e[n],height:e[1-n]}}function ou(t,e){var n={};return n[e.dim+"AxisIndex"]=e.index,t.getCartesian(n)}function au(t){return"x"===t.dim?0:1}function su(t){var e="left "+t+"s cubic-bezier(0.23, 1, 0.32, 1),top "+t+"s cubic-bezier(0.23, 1, 0.32, 1)";return f(Kw,function(t){return t+"transition:"+e}).join(";")}function lu(t){var e=[],n=t.get("fontSize"),i=t.getTextColor();return i&&e.push("color:"+i),e.push("font:"+t.getFont()),n&&e.push("line-height:"+Math.round(3*n/2)+"px"),qw(["decoration","align"],function(n){var i=t.get(n);i&&e.push("text-"+n+":"+i)}),e.join(";")}function hu(t){var e=[],n=t.get("transitionDuration"),i=t.get("backgroundColor"),r=t.getModel("textStyle"),o=t.get("padding");return n&&e.push(su(n)),i&&(Zf.canvasSupported?e.push("background-Color:"+i):(e.push("background-Color:#"+At(i)),e.push("filter:alpha(opacity=70)"))),qw(["width","color","radius"],function(n){var i="border-"+n,r=$w(i),o=t.get(r);null!=o&&e.push(i+":"+o+("color"===n?"":"px"))}),e.push(lu(r)),null!=o&&e.push("padding:"+Ov(o).join("px ")+"px"),e.join(";")+";"}function uu(t,e){if(Zf.wxa)return null;var n=document.createElement("div"),i=this._zr=e.getZr();this.el=n,this._x=e.getWidth()/2,this._y=e.getHeight()/2,t.appendChild(n),this._container=t,this._show=!1,this._hideTimeout;var r=this;n.onmouseenter=function(){r._enterable&&(clearTimeout(r._hideTimeout),r._show=!0),r._inContent=!0},n.onmousemove=function(e){if(e=e||window.event,!r._enterable){var n=i.handler;rn(t,e,!0),n.dispatch("mousemove",e)}},n.onmouseleave=function(){r._enterable&&r._show&&r.hideLater(r._hideDelay),r._inContent=!1}}function cu(t){for(var e=t.pop();t.length;){var n=t.pop();n&&(fr.isInstance(n)&&(n=n.get("tooltip",!0)),"string"==typeof n&&(n={formatter:n}),e=new fr(n,e,e.ecModel))}return e}function du(t,e){return t.dispatchAction||m(e.dispatchAction,e)}function fu(t,e,n,i,r,o,a){var s=gu(n),l=s.width,h=s.height;return null!=o&&(t+l+o>i?t-=l+o:t+=o),null!=a&&(e+h+a>r?e-=h+a:e+=a),[t,e]}function pu(t,e,n,i,r){var o=gu(n),a=o.width,s=o.height;return t=Math.min(t+a,i)-a,e=Math.min(e+s,r)-s,t=Math.max(t,0),e=Math.max(e,0),[t,e]}function gu(t){var e=t.clientWidth,n=t.clientHeight;if(document.defaultView&&document.defaultView.getComputedStyle){var i=document.defaultView.getComputedStyle(t);i&&(e+=parseInt(i.paddingLeft,10)+parseInt(i.paddingRight,10)+parseInt(i.borderLeftWidth,10)+parseInt(i.borderRightWidth,10),n+=parseInt(i.paddingTop,10)+parseInt(i.paddingBottom,10)+parseInt(i.borderTopWidth,10)+parseInt(i.borderBottomWidth,10))}return{width:e,height:n}}function mu(t,e,n){var i=n[0],r=n[1],o=0,a=0,s=e.width,l=e.height;switch(t){case"inside":o=e.x+s/2-i/2,a=e.y+l/2-r/2;break;case"top":o=e.x+s/2-i/2,a=e.y-r-5;break;case"bottom":o=e.x+s/2-i/2,a=e.y+l+5;break;case"left":o=e.x-i-5,a=e.y+l/2-r/2;break;case"right":o=e.x+s+5,a=e.y+l/2-r/2}return[o,a]}function vu(t){return"center"===t||"middle"===t}function yu(t,e,n){var i,r={},o="toggleSelected"===t;return n.eachComponent("legend",function(n){o&&null!=i?n[i?"select":"unSelect"](e.name):(n[t](e.name),i=n.isSelected(e.name)),d(n.getData(),function(t){var e=t.get("name");if("\n"!==e&&""!==e){var i=n.isSelected(e);r.hasOwnProperty(e)?r[e]=r[e]&&i:r[e]=i}})}),{name:e.name,selected:r}}function xu(t,e,n){var i=e.getBoxLayoutParams(),r=e.get("padding"),o={width:n.getWidth(),height:n.getHeight()},a=Fr(i,o,r);Wv(e.get("orient"),t,e.get("itemGap"),a.width,a.height),Gr(t,i,o,r)}function _u(t,e){var n=Ov(e.get("padding")),i=e.getItemStyle(["color","opacity"]);return i.fill=e.get("backgroundColor"),t=new lv({shape:{x:t.x-n[3],y:t.y-n[0],width:t.width+n[1]+n[3],height:t.height+n[0]+n[2],r:e.get("borderRadius")},style:i,silent:!0,z2:-1})}function wu(t,e){e.dispatchAction({type:"legendToggleSelect",name:t})}function bu(t,e,n){var i=n.getZr().storage.getDisplayList()[0];i&&i.useHoverLayer||t.get("legendHoverLink")&&n.dispatchAction({type:"highlight",seriesName:t.name,name:e})}function Su(t,e,n){var i=n.getZr().storage.getDisplayList()[0];i&&i.useHoverLayer||t.get("legendHoverLink")&&n.dispatchAction({type:"downplay",seriesName:t.name,name:e})}function Mu(t,e,n){var i=[1,1];i[t.getOrient().index]=0,Hr(e,n,{type:"box",ignoreSize:i})}function Iu(t){_n(t,"label",["show"])}function Tu(t){return!(isNaN(parseFloat(t.x))&&isNaN(parseFloat(t.y)))}function Cu(t){return!isNaN(parseFloat(t.x))&&!isNaN(parseFloat(t.y))}function Au(t,e,n){var i=-1;do{i=Math.max(br(t.get(e,n)),i),t=t.stackedOn}while(t);return i}function Du(t,e,n,i,r,o){var a=[],s=Eu(e,i,t),l=e.indicesOfNearest(i,s,!0)[0];a[r]=e.get(n,l,!0),a[o]=e.get(i,l,!0);var h=Au(e,i,l);return(h=Math.min(h,20))>=0&&(a[o]=+a[o].toFixed(h)),a}function ku(t,e){var i=t.getData(),r=t.coordinateSystem;if(e&&!Cu(e)&&!y(e.coord)&&r){var o=r.dimensions,a=Pu(e,i,r,t);if((e=n(e)).type&&vb[e.type]&&a.baseAxis&&a.valueAxis){var s=gb(o,a.baseAxis.dim),l=gb(o,a.valueAxis.dim);e.coord=vb[e.type](i,a.baseDataDim,a.valueDataDim,s,l),e.value=e.coord[l]}else{for(var h=[null!=e.xAxis?e.xAxis:e.radiusAxis,null!=e.yAxis?e.yAxis:e.angleAxis],u=0;u<2;u++)vb[h[u]]&&(h[u]=Eu(i,i.mapDimension(o[u]),h[u]));e.coord=h}}return e}function Pu(t,e,n,i){var r={};return null!=t.valueIndex||null!=t.valueDim?(r.valueDataDim=null!=t.valueIndex?e.getDimension(t.valueIndex):t.valueDim,r.valueAxis=n.getAxis(Lu(i,r.valueDataDim)),r.baseAxis=n.getOtherAxis(r.valueAxis),r.baseDataDim=e.mapDimension(r.baseAxis.dim)):(r.baseAxis=i.getBaseAxis(),r.valueAxis=n.getOtherAxis(r.baseAxis),r.baseDataDim=e.mapDimension(r.baseAxis.dim),r.valueDataDim=e.mapDimension(r.valueAxis.dim)),r}function Lu(t,e){var n=t.getData(),i=n.dimensions;e=n.getDimension(e);for(var r=0;r=0}function sc(t,e,n){function i(t,e){return l(e.nodes,t)>=0}function r(t,i){var r=!1;return e(function(e){d(n(t,e)||[],function(t){i.records[e.name][t]&&(r=!0)})}),r}function o(t,i){i.nodes.push(t),e(function(e){d(n(t,e)||[],function(t){i.records[e.name][t]=!0})})}return function(n){var a={nodes:[],records:{}};if(e(function(t){a.records[t.name]={}}),!n)return a;o(n,a);var s;do{s=!1,t(function(t){!i(t,a)&&r(t,a)&&(o(t,a),s=!0)})}while(s);return a}}function lc(t,e,n){var i=[1/0,-1/0];return kb(n,function(t){var n=t.getData();n&&kb(n.mapDimension(e,!0),function(t){var e=n.getApproximateExtent(t);e[0]i[1]&&(i[1]=e[1])})}),i[1]0?0:NaN);var a=n.getMax(!0);return null!=a&&"dataMax"!==a&&"function"!=typeof a?e[1]=a:r&&(e[1]=o>0?o-1:NaN),n.get("scale",!0)||(e[0]>0&&(e[0]=0),e[1]<0&&(e[1]=0)),e}function uc(t,e){var n=t.getAxisModel(),i=t._percentWindow,r=t._valueWindow;if(i){var o=Mr(r,[0,500]);o=Math.min(o,20);var a=e||0===i[0]&&100===i[1];n.setRange(a?null:+r[0].toFixed(o),a?null:+r[1].toFixed(o))}}function cc(t){var e=t._minMaxSpan={},n=t._dataZoomModel;kb(["min","max"],function(i){e[i+"Span"]=n.get(i+"Span");var r=n.get(i+"ValueSpan");if(null!=r&&(e[i+"ValueSpan"]=r,null!=(r=t.getAxisModel().axis.scale.parse(r)))){var o=t._dataExtent;e[i+"Span"]=yr(o[0]+r,o,[0,100],!0)}})}function dc(t){var e={};return Ob(["start","end","startValue","endValue","throttle"],function(n){t.hasOwnProperty(n)&&(e[n]=t[n])}),e}function fc(t,e){var n=t._rangePropMode,i=t.get("rangeMode");Ob([["start","startValue"],["end","endValue"]],function(t,r){var o=null!=e[t[0]],a=null!=e[t[1]];o&&!a?n[r]="percent":!o&&a?n[r]="value":i?n[r]=i[r]:o&&(n[r]="percent")})}function pc(t,e){var n=t[e]-t[1-e];return{span:Math.abs(n),sign:n>0?-1:n<0?1:e?-1:1}}function gc(t,e){return Math.min(e[1],Math.max(e[0],t))}function mc(t){return{x:"y",y:"x",radius:"angle",angle:"radius"}[t]}function vc(t){return"vertical"===t?"ns-resize":"ew-resize"}function yc(t,e,n){wc(t)[e]=n}function xc(t,e,n){var i=wc(t);i[e]===n&&(i[e]=null)}function _c(t,e){return!!wc(t)[e]}function wc(t){return t[jb]||(t[jb]={})}function bc(t){this.pointerChecker,this._zr=t,this._opt={};var e=m,i=e(Sc,this),r=e(Mc,this),o=e(Ic,this),s=e(Tc,this),l=e(Cc,this);dp.call(this),this.setPointerChecker=function(t){this.pointerChecker=t},this.enable=function(e,h){this.disable(),this._opt=a(n(h)||{},{zoomOnMouseWheel:!0,moveOnMouseMove:!0,preventDefaultMouseMove:!0}),null==e&&(e=!0),!0!==e&&"move"!==e&&"pan"!==e||(t.on("mousedown",i),t.on("mousemove",r),t.on("mouseup",o)),!0!==e&&"scale"!==e&&"zoom"!==e||(t.on("mousewheel",s),t.on("pinch",l))},this.disable=function(){t.off("mousedown",i),t.off("mousemove",r),t.off("mouseup",o),t.off("mousewheel",s),t.off("pinch",l)},this.dispose=this.disable,this.isDragging=function(){return this._dragging},this.isPinching=function(){return this._pinching}}function Sc(t){if(!(sn(t)||t.target&&t.target.draggable)){var e=t.offsetX,n=t.offsetY;this.pointerChecker&&this.pointerChecker(t,e,n)&&(this._x=e,this._y=n,this._dragging=!0)}}function Mc(t){if(!sn(t)&&Dc(this,"moveOnMouseMove",t)&&this._dragging&&"pinch"!==t.gestureEvent&&!_c(this._zr,"globalPan")){var e=t.offsetX,n=t.offsetY,i=this._x,r=this._y,o=e-i,a=n-r;this._x=e,this._y=n,this._opt.preventDefaultMouseMove&&bg(t.event),this.trigger("pan",o,a,i,r,e,n)}}function Ic(t){sn(t)||(this._dragging=!1)}function Tc(t){if(Dc(this,"zoomOnMouseWheel",t)&&0!==t.wheelDelta){var e=t.wheelDelta>0?1.1:1/1.1;Ac.call(this,t,e,t.offsetX,t.offsetY)}}function Cc(t){if(!_c(this._zr,"globalPan")){var e=t.pinchScale>1?1.1:1/1.1;Ac.call(this,t,e,t.pinchX,t.pinchY)}}function Ac(t,e,n,i){this.pointerChecker&&this.pointerChecker(t,n,i)&&(bg(t.event),this.trigger("zoom",e,n,i))}function Dc(t,e,n){var i=t._opt[e];return i&&(!_(i)||n.event[i+"Key"])}function kc(t,e){var n=zc(t),i=e.dataZoomId,r=e.coordId;d(n,function(t,n){var o=t.dataZoomInfos;o[i]&&l(e.allCoordIds,r)<0&&(delete o[i],t.count--)}),Rc(n);var o=n[r];o||((o=n[r]={coordId:r,dataZoomInfos:{},count:0}).controller=Ec(t,o),o.dispatchAction=v(Fc,t)),!o.dataZoomInfos[i]&&o.count++,o.dataZoomInfos[i]=e;var a=Gc(o.dataZoomInfos);o.controller.enable(a.controlType,a.opt),o.controller.setPointerChecker(e.containsPoint),sa(o,"dispatchAction",e.throttleRate,"fixRate")}function Pc(t,e){var n=zc(t);d(n,function(t){t.controller.dispose();var n=t.dataZoomInfos;n[e]&&(delete n[e],t.count--)}),Rc(n)}function Lc(t,e){if(t&&"dataZoom"===t.type&&t.batch)for(var n=0,i=t.batch.length;ni["type_"+e]&&(e=r),o(n,t.roamControllerOpt)}),{controlType:e,opt:n}}function Hc(t,e){Jb[t]=e}function Wc(t){return Jb[t]}function Zc(t){return 0===t.indexOf("my")}function Uc(t){this.model=t}function Xc(t){this.model=t}function jc(t){var e={},n=[],i=[];return t.eachRawSeries(function(t){var r=t.coordinateSystem;if(!r||"cartesian2d"!==r.type&&"polar"!==r.type)n.push(t);else{var o=r.getBaseAxis();if("category"===o.type){var a=o.dim+"_"+o.index;e[a]||(e[a]={categoryAxis:o,valueAxis:r.getOtherAxis(o),series:[]},i.push({axisDim:o.dim,axisIndex:o.index})),e[a].series.push(t)}else n.push(t)}}),{seriesGroupByCategoryAxis:e,other:n,meta:i}}function Yc(t){var e=[];return d(t,function(t,n){var i=t.categoryAxis,r=t.valueAxis.dim,o=[" "].concat(f(t.series,function(t){return t.name})),a=[i.model.getCategories()];d(t.series,function(t){a.push(t.getRawData().mapArray(r,function(t){return t}))});for(var s=[o.join(lS)],l=0;l=0)return!0}function Jc(t){for(var e=t.split(/\n+/g),n=[],i=f(Kc(e.shift()).split(hS),function(t){return{name:t,data:[]}}),r=0;rvS}function yd(t){var e=t.length-1;return e<0&&(e=0),[t[0],t[e]]}function xd(t,e,n,i){var r=new Xp;return r.add(new lv({name:"main",style:Sd(n),silent:!0,draggable:!0,cursor:"move",drift:uS(t,e,r,"nswe"),ondragend:uS(md,e,{isEnd:!0})})),cS(i,function(n){r.add(new lv({name:n,style:{opacity:0},draggable:!0,silent:!0,invisible:!0,drift:uS(t,e,r,n),ondragend:uS(md,e,{isEnd:!0})}))}),r}function _d(t,e,n,i){var r=i.brushStyle.lineWidth||0,o=pS(r,yS),a=n[0][0],s=n[1][0],l=a-r/2,h=s-r/2,u=n[0][1],c=n[1][1],d=u-o+r/2,f=c-o+r/2,p=u-a,g=c-s,m=p+r,v=g+r;bd(t,e,"main",a,s,p,g),i.transformable&&(bd(t,e,"w",l,h,o,v),bd(t,e,"e",d,h,o,v),bd(t,e,"n",l,h,m,o),bd(t,e,"s",l,f,m,o),bd(t,e,"nw",l,h,o,o),bd(t,e,"ne",d,h,o,o),bd(t,e,"sw",l,f,o,o),bd(t,e,"se",d,f,o,o))}function wd(t,e){var n=e.__brushOption,i=n.transformable,r=e.childAt(0);r.useStyle(Sd(n)),r.attr({silent:!i,cursor:i?"move":"default"}),cS(["w","e","n","s","se","sw","ne","nw"],function(n){var r=e.childOfName(n),o=Td(t,n);r&&r.attr({silent:!i,invisible:!i,cursor:i?wS[o]+"-resize":null})})}function bd(t,e,n,i,r,o,a){var s=e.childOfName(n);s&&s.setShape(Pd(kd(t,e,[[i,r],[i+o,r+a]])))}function Sd(t){return a({strokeNoScale:!0},t.brushStyle)}function Md(t,e,n,i){var r=[fS(t,n),fS(e,i)],o=[pS(t,n),pS(e,i)];return[[r[0],o[0]],[r[1],o[1]]]}function Id(t){return sr(t.group)}function Td(t,e){if(e.length>1)return("e"===(i=[Td(t,(e=e.split(""))[0]),Td(t,e[1])])[0]||"w"===i[0])&&i.reverse(),i.join("");var n={left:"w",right:"e",top:"n",bottom:"s"},i=hr({w:"left",e:"right",n:"top",s:"bottom"}[e],Id(t));return n[i]}function Cd(t,e,n,i,r,o,a,s){var l=i.__brushOption,h=t(l.range),u=Dd(n,o,a);cS(r.split(""),function(t){var e=_S[t];h[e[0]][e[1]]+=u[e[0]]}),l.range=e(Md(h[0][0],h[1][0],h[0][1],h[1][1])),cd(n,i),md(n,{isEnd:!1})}function Ad(t,e,n,i,r){var o=e.__brushOption.range,a=Dd(t,n,i);cS(o,function(t){t[0]+=a[0],t[1]+=a[1]}),cd(t,e),md(t,{isEnd:!1})}function Dd(t,e,n){var i=t.group,r=i.transformCoordToLocal(e,n),o=i.transformCoordToLocal(0,0);return[r[0]-o[0],r[1]-o[1]]}function kd(t,e,i){var r=pd(t,e);return r&&!0!==r?r.clipPath(i,t._transform):n(i)}function Pd(t){var e=fS(t[0][0],t[1][0]),n=fS(t[0][1],t[1][1]);return{x:e,y:n,width:pS(t[0][0],t[1][0])-e,height:pS(t[0][1],t[1][1])-n}}function Ld(t,e,n){if(t._brushType){var i=t._zr,r=t._covers,o=fd(t,e,n);if(!t._dragging)for(var a=0;a=0)&&t(o,i,r)})}function Ud(t){return t[0]>t[1]&&t.reverse(),t}function Xd(t,e){return An(t,e,{includeMainTypes:PS})}function jd(t,e,n,i){var r=n.getAxis(["x","y"][t]),o=Ud(f([0,1],function(t){return e?r.coordToData(r.toLocalCoord(i[t])):r.toGlobalCoord(r.dataToCoord(i[t]))})),a=[];return a[t]=o,a[1-t]=[NaN,NaN],{values:o,xyMinMax:a}}function Yd(t,e,n,i){return[e[0]-i[t]*n[0],e[1]-i[t]*n[1]]}function qd(t,e){var n=$d(t),i=$d(e),r=[n[0]/i[0],n[1]/i[1]];return isNaN(r[0])&&(r[0]=1),isNaN(r[1])&&(r[1]=1),r}function $d(t){return t?[t[0][1]-t[0][0],t[1][1]-t[1][0]]:[NaN,NaN]}function Kd(t,e){var n=ef(t);BS(e,function(e,i){for(var r=n.length-1;r>=0&&!n[r][i];r--);if(r<0){var o=t.queryComponents({mainType:"dataZoom",subType:"select",id:i})[0];if(o){var a=o.getPercentRange();n[0][i]={dataZoomId:i,start:a[0],end:a[1]}}}}),n.push(e)}function Qd(t){var e=ef(t),n=e[e.length-1];e.length>1&&e.pop();var i={};return BS(n,function(t,n){for(var r=e.length-1;r>=0;r--)if(t=e[r][n]){i[n]=t;break}}),i}function Jd(t){t[VS]=null}function tf(t){return ef(t).length}function ef(t){var e=t[VS];return e||(e=t[VS]=[{}]),e}function nf(t,e,n){(this._brushController=new rd(n.getZr())).on("brush",m(this._onBrush,this)).mount(),this._isZoomActive}function rf(t){var e={};return d(["xAxisIndex","yAxisIndex"],function(n){e[n]=t[n],null==e[n]&&(e[n]="all"),(!1===e[n]||"none"===e[n])&&(e[n]=[])}),e}function of(t,e){t.setIconStatus("back",tf(e)>1?"emphasis":"normal")}function af(t,e,n,i,r){var o=n._isZoomActive;i&&"takeGlobalCursor"===i.type&&(o="dataZoomSelect"===i.key&&i.dataZoomSelectActive),n._isZoomActive=o,t.setIconStatus("zoom",o?"emphasis":"normal");var a=new Zd(rf(t.option),e,{include:["grid"]});n._brushController.setPanels(a.makePanelOpts(r,function(t){return t.xAxisDeclared&&!t.yAxisDeclared?"lineX":!t.xAxisDeclared&&t.yAxisDeclared?"lineY":"rect"})).enableBrush(!!o&&{brushType:"auto",brushStyle:{lineWidth:0,fill:"rgba(0,0,0,0.2)"}})}function sf(t){this.model=t}function lf(t){return XS(t)}function hf(){if(!qS&&$S){qS=!0;var t=$S.styleSheets;t.length<31?$S.createStyleSheet().addRule(".zrvml","behavior:url(#default#VML)"):t[0].addRule(".zrvml","behavior:url(#default#VML)")}}function uf(t){return parseInt(t,10)}function cf(t,e){hf(),this.root=t,this.storage=e;var n=document.createElement("div"),i=document.createElement("div");n.style.cssText="display:inline-block;overflow:hidden;position:relative;width:300px;height:150px;",i.style.cssText="position:absolute;left:0;top:0;",t.appendChild(n),this._vmlRoot=i,this._vmlViewport=n,this.resize();var r=e.delFromStorage,o=e.addToStorage;e.delFromStorage=function(t){r.call(e,t),t&&t.onRemove&&t.onRemove(i)},e.addToStorage=function(t){t.onAdd&&t.onAdd(i),o.call(e,t)},this._firstPaint=!0}function df(t){return function(){Fp('In IE8.0 VML mode painter not support method "'+t+'"')}}function ff(t){return document.createElementNS(kM,t)}function pf(t){return zM(1e4*t)/1e4}function gf(t){return t-FM}function mf(t,e){var n=e?t.textFill:t.fill;return null!=n&&n!==OM}function vf(t,e){var n=e?t.textStroke:t.stroke;return null!=n&&n!==OM}function yf(t,e){e&&xf(t,"transform","matrix("+LM.call(e,",")+")")}function xf(t,e,n){(!n||"linear"!==n.type&&"radial"!==n.type)&&t.setAttribute(e,n)}function _f(t,e,n){t.setAttributeNS("http://www.w3.org/1999/xlink",e,n)}function wf(t,e,n){if(mf(e,n)){var i=n?e.textFill:e.fill;i="transparent"===i?OM:i,"none"!==t.getAttribute("clip-path")&&i===OM&&(i="rgba(0, 0, 0, 0.002)"),xf(t,"fill",i),xf(t,"fill-opacity",e.opacity)}else xf(t,"fill",OM);if(vf(e,n)){var r=n?e.textStroke:e.stroke;xf(t,"stroke",r="transparent"===r?OM:r),xf(t,"stroke-width",(n?e.textStrokeWidth:e.lineWidth)/(!n&&e.strokeNoScale?e.host.getLineScale():1)),xf(t,"paint-order",n?"stroke":"fill"),xf(t,"stroke-opacity",e.opacity),e.lineDash?(xf(t,"stroke-dasharray",e.lineDash.join(",")),xf(t,"stroke-dashoffset",zM(e.lineDashOffset||0))):xf(t,"stroke-dasharray",""),e.lineCap&&xf(t,"stroke-linecap",e.lineCap),e.lineJoin&&xf(t,"stroke-linejoin",e.lineJoin),e.miterLimit&&xf(t,"stroke-miterlimit",e.miterLimit)}else xf(t,"stroke",OM)}function bf(t){for(var e=[],n=t.data,i=t.len(),r=0;r=BM||!gf(g)&&(d>-NM&&d<0||d>NM)==!!p;var y=pf(s+h*RM(c)),x=pf(l+u*EM(c));m&&(d=p?BM-1e-4:1e-4-BM,v=!0,9===r&&e.push("M",y,x));var _=pf(s+h*RM(c+d)),w=pf(l+u*EM(c+d));e.push("A",pf(h),pf(u),zM(f*VM),+v,+p,_,w);break;case PM.Z:o="Z";break;case PM.R:var _=pf(n[r++]),w=pf(n[r++]),b=pf(n[r++]),S=pf(n[r++]);e.push("M",_,w,"L",_+b,w,"L",_+b,w+S,"L",_,w+S,"L",_,w)}o&&e.push(o);for(var M=0;M=11)}}(navigator.userAgent),Uf={"[object Function]":1,"[object RegExp]":1,"[object Date]":1,"[object Error]":1,"[object CanvasGradient]":1,"[object CanvasPattern]":1,"[object Image]":1,"[object Canvas]":1},Xf={"[object Int8Array]":1,"[object Uint8Array]":1,"[object Uint8ClampedArray]":1,"[object Int16Array]":1,"[object Uint16Array]":1,"[object Int32Array]":1,"[object Uint32Array]":1,"[object Float32Array]":1,"[object Float64Array]":1},jf=Object.prototype.toString,Yf=Array.prototype,qf=Yf.forEach,$f=Yf.filter,Kf=Yf.slice,Qf=Yf.map,Jf=Yf.reduce,tp={},ep=function(){return tp.createCanvas()};tp.createCanvas=function(){return document.createElement("canvas")};var np,ip="__ec_primitive__";E.prototype={constructor:E,get:function(t){return this.hasOwnProperty(t)?this[t]:null},set:function(t,e){return this[t]=e},each:function(t,e){void 0!==e&&(t=m(t,e));for(var n in this)this.hasOwnProperty(n)&&t(this[n],n)},removeKey:function(t){delete this[t]}};var rp=(Object.freeze||Object)({$override:e,clone:n,merge:i,mergeAll:r,extend:o,defaults:a,createCanvas:ep,getContext:s,indexOf:l,inherits:h,mixin:u,isArrayLike:c,each:d,map:f,reduce:p,filter:g,find:function(t,e,n){if(t&&e)for(var i=0,r=t.length;i3&&(e=cp.call(e,1));for(var i=this._$handlers[t],r=i.length,o=0;o4&&(e=cp.call(e,1,e.length-1));for(var i=e[e.length-1],r=this._$handlers[t],o=r.length,a=0;a=0;o--){var a;if(i[o]!==n&&!i[o].ignore&&(a=it(i[o],t,e))&&(!r.topTarget&&(r.topTarget=i[o]),a!==fp)){r.target=i[o];break}}return r}},d(["click","mousedown","mouseup","mousewheel","dblclick","contextmenu"],function(t){gp.prototype[t]=function(e){var n=this.findHover(e.zrX,e.zrY),i=n.target;if("mousedown"===t)this._downEl=i,this._downPoint=[e.zrX,e.zrY],this._upEl=i;else if("mouseup"===t)this._upEl=i;else if("click"===t){if(this._downEl!==this._upEl||!this._downPoint||lp(this._downPoint,[e.zrX,e.zrY])>4)return;this._downPoint=null}this.dispatchToElement(n,t,e)}}),u(gp,dp),u(gp,J);var mp="undefined"==typeof Float32Array?Array:Float32Array,vp=(Object.freeze||Object)({create:rt,identity:ot,copy:at,mul:st,translate:lt,rotate:ht,scale:ut,invert:ct,clone:function(t){var e=rt();return at(e,t),e}}),yp=ot,xp=5e-5,_p=function(t){(t=t||{}).position||(this.position=[0,0]),null==t.rotation&&(this.rotation=0),t.scale||(this.scale=[1,1]),this.origin=this.origin||null},wp=_p.prototype;wp.transform=null,wp.needLocalTransform=function(){return dt(this.rotation)||dt(this.position[0])||dt(this.position[1])||dt(this.scale[0]-1)||dt(this.scale[1]-1)},wp.updateTransform=function(){var t=this.parent,e=t&&t.transform,n=this.needLocalTransform(),i=this.transform;n||e?(i=i||rt(),n?this.getLocalTransform(i):yp(i),e&&(n?st(i,t.transform,i):at(i,t.transform)),this.transform=i,this.invTransform=this.invTransform||rt(),ct(this.invTransform,i)):i&&yp(i)},wp.getLocalTransform=function(t){return _p.getLocalTransform(this,t)},wp.setTransform=function(t){var e=this.transform,n=t.dpr||1;e?t.setTransform(n*e[0],n*e[1],n*e[2],n*e[3],n*e[4],n*e[5]):t.setTransform(n,0,0,n,0,0)},wp.restoreTransform=function(t){var e=t.dpr||1;t.setTransform(e,0,0,e,0,0)};var bp=[];wp.decomposeTransform=function(){if(this.transform){var t=this.parent,e=this.transform;t&&t.transform&&(st(bp,t.invTransform,e),e=bp);var n=e[0]*e[0]+e[1]*e[1],i=e[2]*e[2]+e[3]*e[3],r=this.position,o=this.scale;dt(n-1)&&(n=Math.sqrt(n)),dt(i-1)&&(i=Math.sqrt(i)),e[0]<0&&(n=-n),e[3]<0&&(i=-i),r[0]=e[4],r[1]=e[5],o[0]=n,o[1]=i,this.rotation=Math.atan2(-e[1]/i,e[0]/n)}},wp.getGlobalScale=function(){var t=this.transform;if(!t)return[1,1];var e=Math.sqrt(t[0]*t[0]+t[1]*t[1]),n=Math.sqrt(t[2]*t[2]+t[3]*t[3]);return t[0]<0&&(e=-e),t[3]<0&&(n=-n),[e,n]},wp.transformCoordToLocal=function(t,e){var n=[t,e],i=this.invTransform;return i&&$(n,n,i),n},wp.transformCoordToGlobal=function(t,e){var n=[t,e],i=this.transform;return i&&$(n,n,i),n},_p.getLocalTransform=function(t,e){yp(e=e||[]);var n=t.origin,i=t.scale||[1,1],r=t.rotation||0,o=t.position||[0,0];return n&&(e[4]-=n[0],e[5]-=n[1]),ut(e,e,i),r&&ht(e,e,r),n&&(e[4]+=n[0],e[5]+=n[1]),e[4]+=o[0],e[5]+=o[1],e};var Sp={linear:function(t){return t},quadraticIn:function(t){return t*t},quadraticOut:function(t){return t*(2-t)},quadraticInOut:function(t){return(t*=2)<1?.5*t*t:-.5*(--t*(t-2)-1)},cubicIn:function(t){return t*t*t},cubicOut:function(t){return--t*t*t+1},cubicInOut:function(t){return(t*=2)<1?.5*t*t*t:.5*((t-=2)*t*t+2)},quarticIn:function(t){return t*t*t*t},quarticOut:function(t){return 1- --t*t*t*t},quarticInOut:function(t){return(t*=2)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2)},quinticIn:function(t){return t*t*t*t*t},quinticOut:function(t){return--t*t*t*t*t+1},quinticInOut:function(t){return(t*=2)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2)},sinusoidalIn:function(t){return 1-Math.cos(t*Math.PI/2)},sinusoidalOut:function(t){return Math.sin(t*Math.PI/2)},sinusoidalInOut:function(t){return.5*(1-Math.cos(Math.PI*t))},exponentialIn:function(t){return 0===t?0:Math.pow(1024,t-1)},exponentialOut:function(t){return 1===t?1:1-Math.pow(2,-10*t)},exponentialInOut:function(t){return 0===t?0:1===t?1:(t*=2)<1?.5*Math.pow(1024,t-1):.5*(2-Math.pow(2,-10*(t-1)))},circularIn:function(t){return 1-Math.sqrt(1-t*t)},circularOut:function(t){return Math.sqrt(1- --t*t)},circularInOut:function(t){return(t*=2)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},elasticIn:function(t){var e,n=.1;return 0===t?0:1===t?1:(!n||n<1?(n=1,e=.1):e=.4*Math.asin(1/n)/(2*Math.PI),-n*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/.4))},elasticOut:function(t){var e,n=.1;return 0===t?0:1===t?1:(!n||n<1?(n=1,e=.1):e=.4*Math.asin(1/n)/(2*Math.PI),n*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/.4)+1)},elasticInOut:function(t){var e,n=.1;return 0===t?0:1===t?1:(!n||n<1?(n=1,e=.1):e=.4*Math.asin(1/n)/(2*Math.PI),(t*=2)<1?n*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/.4)*-.5:n*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/.4)*.5+1)},backIn:function(t){var e=1.70158;return t*t*((e+1)*t-e)},backOut:function(t){var e=1.70158;return--t*t*((e+1)*t+e)+1},backInOut:function(t){var e=2.5949095;return(t*=2)<1?t*t*((e+1)*t-e)*.5:.5*((t-=2)*t*((e+1)*t+e)+2)},bounceIn:function(t){return 1-Sp.bounceOut(1-t)},bounceOut:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},bounceInOut:function(t){return t<.5?.5*Sp.bounceIn(2*t):.5*Sp.bounceOut(2*t-1)+.5}};ft.prototype={constructor:ft,step:function(t,e){if(this._initialized||(this._startTime=t+this._delay,this._initialized=!0),this._paused)this._pausedTime+=e;else{var n=(t-this._startTime-this._pausedTime)/this._life;if(!(n<0)){n=Math.min(n,1);var i=this.easing,r="string"==typeof i?Sp[i]:i,o="function"==typeof r?r(n):n;return this.fire("frame",o),1==n?this.loop?(this.restart(t),"restart"):(this._needsRemove=!0,"destroy"):null}}},restart:function(t){var e=(t-this._startTime-this._pausedTime)%this._life;this._startTime=t-e+this.gap,this._pausedTime=0,this._needsRemove=!1},fire:function(t,e){this[t="on"+t]&&this[t](this._target,e)},pause:function(){this._paused=!0},resume:function(){this._paused=!1}};var Mp=function(){this.head=null,this.tail=null,this._len=0},Ip=Mp.prototype;Ip.insert=function(t){var e=new Tp(t);return this.insertEntry(e),e},Ip.insertEntry=function(t){this.head?(this.tail.next=t,t.prev=this.tail,t.next=null,this.tail=t):this.head=this.tail=t,this._len++},Ip.remove=function(t){var e=t.prev,n=t.next;e?e.next=n:this.head=n,n?n.prev=e:this.tail=e,t.next=t.prev=null,this._len--},Ip.len=function(){return this._len},Ip.clear=function(){this.head=this.tail=null,this._len=0};var Tp=function(t){this.value=t,this.next,this.prev},Cp=function(t){this._list=new Mp,this._map={},this._maxSize=t||10,this._lastRemovedEntry=null},Ap=Cp.prototype;Ap.put=function(t,e){var n=this._list,i=this._map,r=null;if(null==i[t]){var o=n.len(),a=this._lastRemovedEntry;if(o>=this._maxSize&&o>0){var s=n.head;n.remove(s),delete i[s.key],r=s.value,this._lastRemovedEntry=s}a?a.value=e:a=new Tp(e),a.key=t,n.insertEntry(a),i[t]=a}return r},Ap.get=function(t){var e=this._map[t],n=this._list;if(null!=e)return e!==n.tail&&(n.remove(e),n.insertEntry(e)),e.value},Ap.clear=function(){this._list.clear(),this._map={}};var Dp={transparent:[0,0,0,0],aliceblue:[240,248,255,1],antiquewhite:[250,235,215,1],aqua:[0,255,255,1],aquamarine:[127,255,212,1],azure:[240,255,255,1],beige:[245,245,220,1],bisque:[255,228,196,1],black:[0,0,0,1],blanchedalmond:[255,235,205,1],blue:[0,0,255,1],blueviolet:[138,43,226,1],brown:[165,42,42,1],burlywood:[222,184,135,1],cadetblue:[95,158,160,1],chartreuse:[127,255,0,1],chocolate:[210,105,30,1],coral:[255,127,80,1],cornflowerblue:[100,149,237,1],cornsilk:[255,248,220,1],crimson:[220,20,60,1],cyan:[0,255,255,1],darkblue:[0,0,139,1],darkcyan:[0,139,139,1],darkgoldenrod:[184,134,11,1],darkgray:[169,169,169,1],darkgreen:[0,100,0,1],darkgrey:[169,169,169,1],darkkhaki:[189,183,107,1],darkmagenta:[139,0,139,1],darkolivegreen:[85,107,47,1],darkorange:[255,140,0,1],darkorchid:[153,50,204,1],darkred:[139,0,0,1],darksalmon:[233,150,122,1],darkseagreen:[143,188,143,1],darkslateblue:[72,61,139,1],darkslategray:[47,79,79,1],darkslategrey:[47,79,79,1],darkturquoise:[0,206,209,1],darkviolet:[148,0,211,1],deeppink:[255,20,147,1],deepskyblue:[0,191,255,1],dimgray:[105,105,105,1],dimgrey:[105,105,105,1],dodgerblue:[30,144,255,1],firebrick:[178,34,34,1],floralwhite:[255,250,240,1],forestgreen:[34,139,34,1],fuchsia:[255,0,255,1],gainsboro:[220,220,220,1],ghostwhite:[248,248,255,1],gold:[255,215,0,1],goldenrod:[218,165,32,1],gray:[128,128,128,1],green:[0,128,0,1],greenyellow:[173,255,47,1],grey:[128,128,128,1],honeydew:[240,255,240,1],hotpink:[255,105,180,1],indianred:[205,92,92,1],indigo:[75,0,130,1],ivory:[255,255,240,1],khaki:[240,230,140,1],lavender:[230,230,250,1],lavenderblush:[255,240,245,1],lawngreen:[124,252,0,1],lemonchiffon:[255,250,205,1],lightblue:[173,216,230,1],lightcoral:[240,128,128,1],lightcyan:[224,255,255,1],lightgoldenrodyellow:[250,250,210,1],lightgray:[211,211,211,1],lightgreen:[144,238,144,1],lightgrey:[211,211,211,1],lightpink:[255,182,193,1],lightsalmon:[255,160,122,1],lightseagreen:[32,178,170,1],lightskyblue:[135,206,250,1],lightslategray:[119,136,153,1],lightslategrey:[119,136,153,1],lightsteelblue:[176,196,222,1],lightyellow:[255,255,224,1],lime:[0,255,0,1],limegreen:[50,205,50,1],linen:[250,240,230,1],magenta:[255,0,255,1],maroon:[128,0,0,1],mediumaquamarine:[102,205,170,1],mediumblue:[0,0,205,1],mediumorchid:[186,85,211,1],mediumpurple:[147,112,219,1],mediumseagreen:[60,179,113,1],mediumslateblue:[123,104,238,1],mediumspringgreen:[0,250,154,1],mediumturquoise:[72,209,204,1],mediumvioletred:[199,21,133,1],midnightblue:[25,25,112,1],mintcream:[245,255,250,1],mistyrose:[255,228,225,1],moccasin:[255,228,181,1],navajowhite:[255,222,173,1],navy:[0,0,128,1],oldlace:[253,245,230,1],olive:[128,128,0,1],olivedrab:[107,142,35,1],orange:[255,165,0,1],orangered:[255,69,0,1],orchid:[218,112,214,1],palegoldenrod:[238,232,170,1],palegreen:[152,251,152,1],paleturquoise:[175,238,238,1],palevioletred:[219,112,147,1],papayawhip:[255,239,213,1],peachpuff:[255,218,185,1],peru:[205,133,63,1],pink:[255,192,203,1],plum:[221,160,221,1],powderblue:[176,224,230,1],purple:[128,0,128,1],red:[255,0,0,1],rosybrown:[188,143,143,1],royalblue:[65,105,225,1],saddlebrown:[139,69,19,1],salmon:[250,128,114,1],sandybrown:[244,164,96,1],seagreen:[46,139,87,1],seashell:[255,245,238,1],sienna:[160,82,45,1],silver:[192,192,192,1],skyblue:[135,206,235,1],slateblue:[106,90,205,1],slategray:[112,128,144,1],slategrey:[112,128,144,1],snow:[255,250,250,1],springgreen:[0,255,127,1],steelblue:[70,130,180,1],tan:[210,180,140,1],teal:[0,128,128,1],thistle:[216,191,216,1],tomato:[255,99,71,1],turquoise:[64,224,208,1],violet:[238,130,238,1],wheat:[245,222,179,1],white:[255,255,255,1],whitesmoke:[245,245,245,1],yellow:[255,255,0,1],yellowgreen:[154,205,50,1]},kp=new Cp(20),Pp=null,Lp=Dt,Op=kt,zp=(Object.freeze||Object)({parse:Mt,lift:Ct,toHex:At,fastLerp:Dt,fastMapToColor:Lp,lerp:kt,mapToColor:Op,modifyHSL:function(t,e,n,i){if(t=Mt(t))return t=Tt(t),null!=e&&(t[0]=gt(e)),null!=n&&(t[1]=yt(n)),null!=i&&(t[2]=yt(i)),Lt(It(t),"rgba")},modifyAlpha:Pt,stringify:Lt}),Ep=Array.prototype.slice,Rp=function(t,e,n,i){this._tracks={},this._target=t,this._loop=e||!1,this._getter=n||Ot,this._setter=i||zt,this._clipCount=0,this._delay=0,this._doneList=[],this._onframeList=[],this._clipList=[]};Rp.prototype={when:function(t,e){var n=this._tracks;for(var i in e)if(e.hasOwnProperty(i)){if(!n[i]){n[i]=[];var r=this._getter(this._target,i);if(null==r)continue;0!==t&&n[i].push({time:0,value:Ht(r)})}n[i].push({time:t,value:e[i]})}return this},during:function(t){return this._onframeList.push(t),this},pause:function(){for(var t=0;t0&&this.animate(t,!1).when(null==i?500:i,o).delay(r||0),this}};var Hp=function(t){_p.call(this,t),dp.call(this,t),Gp.call(this,t),this.id=t.id||Hf()};Hp.prototype={type:"element",name:"",__zr:null,ignore:!1,clipPath:null,isGroup:!1,drift:function(t,e){switch(this.draggable){case"horizontal":e=0;break;case"vertical":t=0}var n=this.transform;n||(n=this.transform=[1,0,0,1,0,0]),n[4]+=t,n[5]+=e,this.decomposeTransform(),this.dirty(!1)},beforeUpdate:function(){},afterUpdate:function(){},update:function(){this.updateTransform()},traverse:function(t,e){},attrKV:function(t,e){if("position"===t||"scale"===t||"origin"===t){if(e){var n=this[t];n||(n=this[t]=[]),n[0]=e[0],n[1]=e[1]}}else this[t]=e},hide:function(){this.ignore=!0,this.__zr&&this.__zr.refresh()},show:function(){this.ignore=!1,this.__zr&&this.__zr.refresh()},attr:function(t,e){if("string"==typeof t)this.attrKV(t,e);else if(w(t))for(var n in t)t.hasOwnProperty(n)&&this.attrKV(n,t[n]);return this.dirty(!1),this},setClipPath:function(t){var e=this.__zr;e&&t.addSelfToZr(e),this.clipPath&&this.clipPath!==t&&this.removeClipPath(),this.clipPath=t,t.__zr=e,t.__clipTarget=this,this.dirty(!1)},removeClipPath:function(){var t=this.clipPath;t&&(t.__zr&&t.removeSelfFromZr(t.__zr),t.__zr=null,t.__clipTarget=null,this.clipPath=null,this.dirty(!1))},addSelfToZr:function(t){this.__zr=t;var e=this.animators;if(e)for(var n=0;n=n.x&&t<=n.x+n.width&&e>=n.y&&e<=n.y+n.height},clone:function(){return new Xt(this.x,this.y,this.width,this.height)},copy:function(t){this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height},plain:function(){return{x:this.x,y:this.y,width:this.width,height:this.height}}},Xt.create=function(t){return new Xt(t.x,t.y,t.width,t.height)};var Xp=function(t){t=t||{},Hp.call(this,t);for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e]);this._children=[],this.__storage=null,this.__dirty=!0};Xp.prototype={constructor:Xp,isGroup:!0,type:"group",silent:!1,children:function(){return this._children.slice()},childAt:function(t){return this._children[t]},childOfName:function(t){for(var e=this._children,n=0;n=0&&(n.splice(i,0,t),this._doAdd(t))}return this},_doAdd:function(t){t.parent&&t.parent.remove(t),t.parent=this;var e=this.__storage,n=this.__zr;e&&e!==t.__storage&&(e.addToStorage(t),t instanceof Xp&&t.addChildrenToStorage(e)),n&&n.refresh()},remove:function(t){var e=this.__zr,n=this.__storage,i=this._children,r=l(i,t);return r<0?this:(i.splice(r,1),t.parent=null,n&&(n.delFromStorage(t),t instanceof Xp&&t.delChildrenFromStorage(n)),e&&e.refresh(),this)},removeAll:function(){var t,e,n=this._children,i=this.__storage;for(e=0;e=0&&(this.delFromStorage(t),this._roots.splice(r,1),t instanceof Xp&&t.delChildrenFromStorage(this))}},addToStorage:function(t){return t&&(t.__storage=this,t.dirty(!1)),this},delFromStorage:function(t){return t&&(t.__storage=null),this},dispose:function(){this._renderList=this._roots=null},displayableSortFunc:ee};var $p={shadowBlur:1,shadowOffsetX:1,shadowOffsetY:1,textShadowBlur:1,textShadowOffsetX:1,textShadowOffsetY:1,textBoxShadowBlur:1,textBoxShadowOffsetX:1,textBoxShadowOffsetY:1},Kp=function(t,e,n){return $p.hasOwnProperty(e)?n*=t.dpr:n},Qp=[["shadowBlur",0],["shadowOffsetX",0],["shadowOffsetY",0],["shadowColor","#000"],["lineCap","butt"],["lineJoin","miter"],["miterLimit",10]],Jp=function(t,e){this.extendFrom(t,!1),this.host=e};Jp.prototype={constructor:Jp,host:null,fill:"#000",stroke:null,opacity:1,lineDash:null,lineDashOffset:0,shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,lineWidth:1,strokeNoScale:!1,text:null,font:null,textFont:null,fontStyle:null,fontWeight:null,fontSize:null,fontFamily:null,textTag:null,textFill:"#000",textStroke:null,textWidth:null,textHeight:null,textStrokeWidth:0,textLineHeight:null,textPosition:"inside",textRect:null,textOffset:null,textAlign:null,textVerticalAlign:null,textDistance:5,textShadowColor:"transparent",textShadowBlur:0,textShadowOffsetX:0,textShadowOffsetY:0,textBoxShadowColor:"transparent",textBoxShadowBlur:0,textBoxShadowOffsetX:0,textBoxShadowOffsetY:0,transformText:!1,textRotation:0,textOrigin:null,textBackgroundColor:null,textBorderColor:null,textBorderWidth:0,textBorderRadius:0,textPadding:null,rich:null,truncate:null,blend:null,bind:function(t,e,n){for(var i=this,r=n&&n.style,o=!r,a=0;a0},extendFrom:function(t,e){if(t)for(var n in t)!t.hasOwnProperty(n)||!0!==e&&(!1===e?this.hasOwnProperty(n):null==t[n])||(this[n]=t[n])},set:function(t,e){"string"==typeof t?this[t]=e:this.extendFrom(t,!0)},clone:function(){var t=new this.constructor;return t.extendFrom(this,!0),t},getGradient:function(t,e,n){for(var i=("radial"===e.type?ie:ne)(t,e,n),r=e.colorStops,o=0;o=0&&n.splice(i,1),t.__hoverMir=null},clearHover:function(t){for(var e=this._hoverElements,n=0;n15)break}s.__drawIndex=g,s.__drawIndex0&&t>i[0]){for(a=0;at);a++);o=n[i[a]]}if(i.splice(a+1,0,t),n[t]=e,!e.virtual)if(o){var l=o.dom;l.nextSibling?s.insertBefore(e.dom,l.nextSibling):s.appendChild(e.dom)}else s.firstChild?s.insertBefore(e.dom,s.firstChild):s.appendChild(e.dom)}else Fp("Layer of zlevel "+t+" is not valid")},eachLayer:function(t,e){var n,i,r=this._zlevelList;for(i=0;i0?.01:0),this._needsManuallyCompositing),o.__builtin__||Fp("ZLevel "+s+" has been used by unkown layer "+o.id),o!==n&&(o.__used=!0,o.__startIndex!==r&&(o.__dirty=!0),o.__startIndex=r,o.incremental?o.__drawIndex=-1:o.__drawIndex=r,e(r),n=o),a.__dirty&&(o.__dirty=!0,o.incremental&&o.__drawIndex<0&&(o.__drawIndex=r))}e(r),this.eachBuiltinLayer(function(t,e){!t.__used&&t.getElementCount()>0&&(t.__dirty=!0,t.__startIndex=t.__endIndex=t.__drawIndex=0),t.__dirty&&t.__drawIndex<0&&(t.__drawIndex=t.__startIndex)})},clear:function(){return this.eachBuiltinLayer(this._clearLayer),this},_clearLayer:function(t){t.clear()},configLayer:function(t,e){if(e){var n=this._layerConfig;n[t]?i(n[t],e,!0):n[t]=e;for(var r=0;r=0&&this._clips.splice(e,1)},removeAnimator:function(t){for(var e=t.getClips(),n=0;n1&&i&&i.length>1){var o=ln(i)/ln(r);!isFinite(o)&&(o=1),e.pinchScale=o;var a=hn(i);return e.pinchX=a[0],e.pinchY=a[1],{type:"pinch",target:t[0].target,event:e}}}}},Tg=["click","dblclick","mousewheel","mouseout","mouseup","mousedown","mousemove","contextmenu"],Cg=["touchstart","touchend","touchmove"],Ag={pointerdown:1,pointerup:1,pointermove:1,pointerout:1},Dg=f(Tg,function(t){var e=t.replace("mouse","pointer");return Ag[e]?e:t}),kg={mousemove:function(t){t=rn(this.dom,t),this.trigger("mousemove",t)},mouseout:function(t){var e=(t=rn(this.dom,t)).toElement||t.relatedTarget;if(e!=this.dom)for(;e&&9!=e.nodeType;){if(e===this.dom)return;e=e.parentNode}this.trigger("mouseout",t)},touchstart:function(t){(t=rn(this.dom,t)).zrByTouch=!0,this._lastTouchMoment=new Date,cn(this,t,"start"),kg.mousemove.call(this,t),kg.mousedown.call(this,t),dn(this)},touchmove:function(t){(t=rn(this.dom,t)).zrByTouch=!0,cn(this,t,"change"),kg.mousemove.call(this,t),dn(this)},touchend:function(t){(t=rn(this.dom,t)).zrByTouch=!0,cn(this,t,"end"),kg.mouseup.call(this,t),+new Date-this._lastTouchMoment<300&&kg.click.call(this,t),dn(this)},pointerdown:function(t){kg.mousedown.call(this,t)},pointermove:function(t){fn(t)||kg.mousemove.call(this,t)},pointerup:function(t){kg.mouseup.call(this,t)},pointerout:function(t){fn(t)||kg.mouseout.call(this,t)}};d(["click","mousedown","mouseup","mousewheel","dblclick","contextmenu"],function(t){kg[t]=function(e){e=rn(this.dom,e),this.trigger(t,e)}});var Pg=gn.prototype;Pg.dispose=function(){for(var t=Tg.concat(Cg),e=0;e=0||i&&l(i,a)<0)){var s=e.getShallow(a);null!=s&&(r[t[o][0]]=s)}}return r}},jg=Xg([["lineWidth","width"],["stroke","color"],["opacity"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"]]),Yg={getLineStyle:function(t){var e=jg(this,t),n=this.getLineDash(e.lineWidth);return n&&(e.lineDash=n),e},getLineDash:function(t){null==t&&(t=1);var e=this.get("type"),n=Math.max(t,2),i=4*t;return"solid"===e||null==e?null:"dashed"===e?[i,i]:[n,n]}},qg=Xg([["fill","color"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["opacity"],["shadowColor"]]),$g={getAreaStyle:function(t,e){return qg(this,t,e)}},Kg=Math.pow,Qg=Math.sqrt,Jg=1e-8,tm=1e-4,em=Qg(3),nm=1/3,im=B(),rm=B(),om=B(),am=Math.min,sm=Math.max,lm=Math.sin,hm=Math.cos,um=2*Math.PI,cm=B(),dm=B(),fm=B(),pm=[],gm=[],mm={M:1,L:2,C:3,Q:4,A:5,Z:6,R:7},vm=[],ym=[],xm=[],_m=[],wm=Math.min,bm=Math.max,Sm=Math.cos,Mm=Math.sin,Im=Math.sqrt,Tm=Math.abs,Cm="undefined"!=typeof Float32Array,Am=function(t){this._saveData=!t,this._saveData&&(this.data=[]),this._ctx=null};Am.prototype={constructor:Am,_xi:0,_yi:0,_x0:0,_y0:0,_ux:0,_uy:0,_len:0,_lineDash:null,_dashOffset:0,_dashIdx:0,_dashSum:0,setScale:function(t,e){this._ux=Tm(1/Bp/t)||0,this._uy=Tm(1/Bp/e)||0},getContext:function(){return this._ctx},beginPath:function(t){return this._ctx=t,t&&t.beginPath(),t&&(this.dpr=t.dpr),this._saveData&&(this._len=0),this._lineDash&&(this._lineDash=null,this._dashOffset=0),this},moveTo:function(t,e){return this.addData(mm.M,t,e),this._ctx&&this._ctx.moveTo(t,e),this._x0=t,this._y0=e,this._xi=t,this._yi=e,this},lineTo:function(t,e){var n=Tm(t-this._xi)>this._ux||Tm(e-this._yi)>this._uy||this._len<5;return this.addData(mm.L,t,e),this._ctx&&n&&(this._needsDash()?this._dashedLineTo(t,e):this._ctx.lineTo(t,e)),n&&(this._xi=t,this._yi=e),this},bezierCurveTo:function(t,e,n,i,r,o){return this.addData(mm.C,t,e,n,i,r,o),this._ctx&&(this._needsDash()?this._dashedBezierTo(t,e,n,i,r,o):this._ctx.bezierCurveTo(t,e,n,i,r,o)),this._xi=r,this._yi=o,this},quadraticCurveTo:function(t,e,n,i){return this.addData(mm.Q,t,e,n,i),this._ctx&&(this._needsDash()?this._dashedQuadraticTo(t,e,n,i):this._ctx.quadraticCurveTo(t,e,n,i)),this._xi=n,this._yi=i,this},arc:function(t,e,n,i,r,o){return this.addData(mm.A,t,e,n,n,i,r-i,0,o?0:1),this._ctx&&this._ctx.arc(t,e,n,i,r,o),this._xi=Sm(r)*n+t,this._yi=Mm(r)*n+t,this},arcTo:function(t,e,n,i,r){return this._ctx&&this._ctx.arcTo(t,e,n,i,r),this},rect:function(t,e,n,i){return this._ctx&&this._ctx.rect(t,e,n,i),this.addData(mm.R,t,e,n,i),this},closePath:function(){this.addData(mm.Z);var t=this._ctx,e=this._x0,n=this._y0;return t&&(this._needsDash()&&this._dashedLineTo(e,n),t.closePath()),this._xi=e,this._yi=n,this},fill:function(t){t&&t.fill(),this.toStatic()},stroke:function(t){t&&t.stroke(),this.toStatic()},setLineDash:function(t){if(t instanceof Array){this._lineDash=t,this._dashIdx=0;for(var e=0,n=0;ne.length&&(this._expandData(),e=this.data);for(var n=0;n0&&f<=t||u<0&&f>=t||0==u&&(c>0&&p<=e||c<0&&p>=e);)f+=u*(n=a[i=this._dashIdx]),p+=c*n,this._dashIdx=(i+1)%g,u>0&&fl||c>0&&ph||s[i%2?"moveTo":"lineTo"](u>=0?wm(f,t):bm(f,t),c>=0?wm(p,e):bm(p,e));u=f-t,c=p-e,this._dashOffset=-Im(u*u+c*c)},_dashedBezierTo:function(t,e,n,i,r,o){var a,s,l,h,u,c=this._dashSum,d=this._dashOffset,f=this._lineDash,p=this._ctx,g=this._xi,m=this._yi,v=Gn,y=0,x=this._dashIdx,_=f.length,w=0;for(d<0&&(d=c+d),d%=c,a=0;a<1;a+=.1)s=v(g,t,n,r,a+.1)-v(g,t,n,r,a),l=v(m,e,i,o,a+.1)-v(m,e,i,o,a),y+=Im(s*s+l*l);for(;x<_&&!((w+=f[x])>d);x++);for(a=(w-d)/y;a<=1;)h=v(g,t,n,r,a),u=v(m,e,i,o,a),x%2?p.moveTo(h,u):p.lineTo(h,u),a+=f[x]/y,x=(x+1)%_;x%2!=0&&p.lineTo(r,o),s=r-h,l=o-u,this._dashOffset=-Im(s*s+l*l)},_dashedQuadraticTo:function(t,e,n,i){var r=n,o=i;n=(n+2*t)/3,i=(i+2*e)/3,t=(this._xi+2*t)/3,e=(this._yi+2*e)/3,this._dashedBezierTo(t,e,n,i,r,o)},toStatic:function(){var t=this.data;t instanceof Array&&(t.length=this._len,Cm&&(this.data=new Float32Array(t)))},getBoundingRect:function(){vm[0]=vm[1]=xm[0]=xm[1]=Number.MAX_VALUE,ym[0]=ym[1]=_m[0]=_m[1]=-Number.MAX_VALUE;for(var t=this.data,e=0,n=0,i=0,r=0,o=0;ol||Tm(a-r)>h||c===u-1)&&(t.lineTo(o,a),i=o,r=a);break;case mm.C:t.bezierCurveTo(s[c++],s[c++],s[c++],s[c++],s[c++],s[c++]),i=s[c-2],r=s[c-1];break;case mm.Q:t.quadraticCurveTo(s[c++],s[c++],s[c++],s[c++]),i=s[c-2],r=s[c-1];break;case mm.A:var f=s[c++],p=s[c++],g=s[c++],m=s[c++],v=s[c++],y=s[c++],x=s[c++],_=s[c++],w=g>m?g:m,b=g>m?1:g/m,S=g>m?m/g:1,M=v+y;Math.abs(g-m)>.001?(t.translate(f,p),t.rotate(x),t.scale(b,S),t.arc(0,0,w,v,M,1-_),t.scale(1/b,1/S),t.rotate(-x),t.translate(-f,-p)):t.arc(f,p,w,v,M,1-_),1==c&&(e=Sm(v)*g+f,n=Mm(v)*m+p),i=Sm(M)*g+f,r=Mm(M)*m+p;break;case mm.R:e=i=s[c],n=r=s[c+1],t.rect(s[c++],s[c++],s[c++],s[c++]);break;case mm.Z:t.closePath(),i=e,r=n}}}},Am.CMD=mm;var Dm=2*Math.PI,km=2*Math.PI,Pm=Am.CMD,Lm=2*Math.PI,Om=1e-4,zm=[-1,-1,-1],Em=[-1,-1],Rm=ig.prototype.getCanvasPattern,Nm=Math.abs,Bm=new Am(!0);yi.prototype={constructor:yi,type:"path",__dirtyPath:!0,strokeContainThreshold:5,brush:function(t,e){var n=this.style,i=this.path||Bm,r=n.hasStroke(),o=n.hasFill(),a=n.fill,s=n.stroke,l=o&&!!a.colorStops,h=r&&!!s.colorStops,u=o&&!!a.image,c=r&&!!s.image;if(n.bind(t,this,e),this.setTransform(t),this.__dirty){var d;l&&(d=d||this.getBoundingRect(),this._fillGradient=n.getGradient(t,a,d)),h&&(d=d||this.getBoundingRect(),this._strokeGradient=n.getGradient(t,s,d))}l?t.fillStyle=this._fillGradient:u&&(t.fillStyle=Rm.call(a,t)),h?t.strokeStyle=this._strokeGradient:c&&(t.strokeStyle=Rm.call(s,t));var f=n.lineDash,p=n.lineDashOffset,g=!!t.setLineDash,m=this.getGlobalScale();i.setScale(m[0],m[1]),this.__dirtyPath||f&&!g&&r?(i.beginPath(t),f&&!g&&(i.setLineDash(f),i.setLineDashOffset(p)),this.buildPath(i,this.shape,!1),this.path&&(this.__dirtyPath=!1)):(t.beginPath(),this.path.rebuildPath(t)),o&&i.fill(t),f&&g&&(t.setLineDash(f),t.lineDashOffset=p),r&&i.stroke(t),f&&g&&t.setLineDash([]),null!=n.text&&(this.restoreTransform(t),this.drawRectText(t,this.getBoundingRect()))},buildPath:function(t,e,n){},createPathProxy:function(){this.path=new Am},getBoundingRect:function(){var t=this._rect,e=this.style,n=!t;if(n){var i=this.path;i||(i=this.path=new Am),this.__dirtyPath&&(i.beginPath(),this.buildPath(i,this.shape,!1)),t=i.getBoundingRect()}if(this._rect=t,e.hasStroke()){var r=this._rectWithStroke||(this._rectWithStroke=t.clone());if(this.__dirty||n){r.copy(t);var o=e.lineWidth,a=e.strokeNoScale?this.getLineScale():1;e.hasFill()||(o=Math.max(o,this.strokeContainThreshold||4)),a>1e-10&&(r.width+=o/a,r.height+=o/a,r.x-=o/a/2,r.y-=o/a/2)}return r}return t},contain:function(t,e){var n=this.transformCoordToLocal(t,e),i=this.getBoundingRect(),r=this.style;if(t=n[0],e=n[1],i.contain(t,e)){var o=this.path.data;if(r.hasStroke()){var a=r.lineWidth,s=r.strokeNoScale?this.getLineScale():1;if(s>1e-10&&(r.hasFill()||(a=Math.max(a,this.strokeContainThreshold)),vi(o,a/s,t,e)))return!0}if(r.hasFill())return mi(o,t,e)}return!1},dirty:function(t){null==t&&(t=!0),t&&(this.__dirtyPath=t,this._rect=null),this.__dirty=!0,this.__zr&&this.__zr.refresh(),this.__clipTarget&&this.__clipTarget.dirty()},animateShape:function(t){return this.animate("shape",t)},attrKV:function(t,e){"shape"===t?(this.setShape(e),this.__dirtyPath=!0,this._rect=null):Xe.prototype.attrKV.call(this,t,e)},setShape:function(t,e){var n=this.shape;if(n){if(w(t))for(var i in t)t.hasOwnProperty(i)&&(n[i]=t[i]);else n[t]=e;this.dirty(!0)}return this},getLineScale:function(){var t=this.transform;return t&&Nm(t[0]-1)>1e-10&&Nm(t[3]-1)>1e-10?Math.sqrt(Nm(t[0]*t[3]-t[2]*t[1])):1}},yi.extend=function(t){var e=function(e){yi.call(this,e),t.style&&this.style.extendFrom(t.style,!1);var n=t.shape;if(n){this.shape=this.shape||{};var i=this.shape;for(var r in n)!i.hasOwnProperty(r)&&n.hasOwnProperty(r)&&(i[r]=n[r])}t.init&&t.init.call(this,e)};h(e,yi);for(var n in t)"style"!==n&&"shape"!==n&&(e.prototype[n]=t[n]);return e},h(yi,Xe);var Vm=Am.CMD,Fm=[[],[],[]],Gm=Math.sqrt,Hm=Math.atan2,Wm=function(t,e){var n,i,r,o,a,s,l=t.data,h=Vm.M,u=Vm.C,c=Vm.L,d=Vm.R,f=Vm.A,p=Vm.Q;for(r=0,o=0;r=11?function(){var e,n=this.__clipPaths,i=this.style;if(n)for(var r=0;rn-2?n-1:c+1],h=t[c>n-3?n-1:c+2]);var p=d*d,g=d*p;i.push([Mi(s[0],f[0],l[0],h[0],d,p,g),Mi(s[1],f[1],l[1],h[1],d,p,g)])}return i},ov=function(t,e,n,i){var r,o,a,s,l=[],h=[],u=[],c=[];if(i){a=[1/0,1/0],s=[-1/0,-1/0];for(var d=0,f=t.length;d=n&&o>=r)return{x:n,y:r,width:i-n,height:o-r}},createIcon:dr,Group:Xp,Image:je,Text:Qm,Circle:Jm,Sector:nv,Ring:iv,Polygon:av,Polyline:sv,Rect:lv,Line:hv,BezierCurve:cv,Arc:dv,IncrementalDisplayable:Ci,CompoundPath:fv,LinearGradient:gv,RadialGradient:mv,BoundingRect:Xt}),Sv=["textStyle","color"],Mv={getTextColor:function(t){var e=this.ecModel;return this.getShallow("color")||(!t&&e?e.get(Sv):null)},getFont:function(){return ir({fontStyle:this.getShallow("fontStyle"),fontWeight:this.getShallow("fontWeight"),fontSize:this.getShallow("fontSize"),fontFamily:this.getShallow("fontFamily")},this.ecModel)},getTextRect:function(t){return ce(t,this.getFont(),this.getShallow("align"),this.getShallow("verticalAlign")||this.getShallow("baseline"),this.getShallow("padding"),this.getShallow("rich"),this.getShallow("truncateText"))}},Iv=Xg([["fill","color"],["stroke","borderColor"],["lineWidth","borderWidth"],["opacity"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"],["textPosition"],["textAlign"]]),Tv={getItemStyle:function(t,e){var n=Iv(this,t,e),i=this.getBorderLineDash();return i&&(n.lineDash=i),n},getBorderLineDash:function(){var t=this.get("borderType");return"solid"===t||null==t?null:"dashed"===t?[5,5]:[1,1]}},Cv=u,Av=Cn();fr.prototype={constructor:fr,init:null,mergeOption:function(t){i(this.option,t,!0)},get:function(t,e){return null==t?this.option:pr(this.option,this.parsePath(t),!e&&gr(this,t))},getShallow:function(t,e){var n=this.option,i=null==n?n:n[t],r=!e&&gr(this,t);return null==i&&r&&(i=r.getShallow(t)),i},getModel:function(t,e){var n,i=null==t?this.option:pr(this.option,t=this.parsePath(t));return e=e||(n=gr(this,t))&&n.getModel(t),new fr(i,e,this.ecModel)},isEmpty:function(){return null==this.option},restoreData:function(){},clone:function(){return new(0,this.constructor)(n(this.option))},setReadOnly:function(t){},parsePath:function(t){return"string"==typeof t&&(t=t.split(".")),t},customizeGetParent:function(t){Av(this).getParent=t},isAnimationEnabled:function(){if(!Zf.node){if(null!=this.option.animation)return!!this.option.animation;if(this.parentModel)return this.parentModel.isAnimationEnabled()}}},zn(fr),En(fr),Cv(fr,Yg),Cv(fr,$g),Cv(fr,Mv),Cv(fr,Tv);var Dv=0,kv=1e-4,Pv=/^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d\d)(?::(\d\d)(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/,Lv=(Object.freeze||Object)({linearMap:yr,parsePercent:xr,round:_r,asc:wr,getPrecision:br,getPrecisionSafe:Sr,getPixelPrecision:Mr,getPercentWithPrecision:Ir,MAX_SAFE_INTEGER:9007199254740991,remRadian:Tr,isRadianAroundZero:Cr,parseDate:Ar,quantity:Dr,nice:Pr,reformIntervals:function(t){function e(t,n,i){return t.interval[i]=0}}),Ov=k,zv=["a","b","c","d","e","f","g"],Ev=function(t,e){return"{"+t+(null==e?"":e)+"}"},Rv=function(t){return t<10?"0"+t:t},Nv=ve,Bv=ce,Vv=(Object.freeze||Object)({addCommas:Lr,toCamelCase:Or,normalizeCssArray:Ov,encodeHTML:zr,formatTpl:Er,formatTplSimple:function(t,e,n){return d(e,function(e,i){t=t.replace("{"+i+"}",n?zr(e):e)}),t},getTooltipMarker:Rr,formatTime:Nr,capitalFirst:Br,truncateText:Nv,getTextRect:Bv}),Fv=d,Gv=["left","right","top","bottom","width","height"],Hv=[["width","left","right"],["height","top","bottom"]],Wv=Vr,Zv=(v(Vr,"vertical"),v(Vr,"horizontal"),{getBoxLayoutParams:function(){return{left:this.get("left"),top:this.get("top"),right:this.get("right"),bottom:this.get("bottom"),width:this.get("width"),height:this.get("height")}}}),Uv=Cn(),Xv=fr.extend({type:"component",id:"",name:"",mainType:"",subType:"",componentIndex:0,defaultOption:null,ecModel:null,dependentModels:[],uid:null,layoutMode:null,$constructor:function(t,e,n,i){fr.call(this,t,e,n,i),this.uid=mr("ec_cpt_model")},init:function(t,e,n,i){this.mergeDefaultAndTheme(t,n)},mergeDefaultAndTheme:function(t,e){var n=this.layoutMode,r=n?Wr(t):{};i(t,e.getTheme().get(this.mainType)),i(t,this.getDefaultOption()),n&&Hr(t,r,n)},mergeOption:function(t,e){i(this.option,t,!0);var n=this.layoutMode;n&&Hr(this.option,t,n)},optionUpdated:function(t,e){},getDefaultOption:function(){var t=Uv(this);if(!t.defaultOption){for(var e=[],n=this.constructor;n;){var r=n.prototype.defaultOption;r&&e.push(r),n=n.superClass}for(var o={},a=e.length-1;a>=0;a--)o=i(o,e[a],!0);t.defaultOption=o}return t.defaultOption},getReferringComponents:function(t){return this.ecModel.queryComponents({mainType:t,index:this.get(t+"Index",!0),id:this.get(t+"Id",!0)})}});Bn(Xv,{registerWhenExtend:!0}),function(t){var e={};t.registerSubTypeDefaulter=function(t,n){t=Ln(t),e[t.main]=n},t.determineSubType=function(n,i){var r=i.type;if(!r){var o=Ln(n).main;t.hasSubTypes(n)&&e[o]&&(r=e[o](i))}return r}}(Xv),function(t,e){function n(t){var n={},o=[];return d(t,function(a){var s=i(n,a),h=r(s.originalDeps=e(a),t);s.entryCount=h.length,0===s.entryCount&&o.push(a),d(h,function(t){l(s.predecessor,t)<0&&s.predecessor.push(t);var e=i(n,t);l(e.successor,t)<0&&e.successor.push(a)})}),{graph:n,noEntryList:o}}function i(t,e){return t[e]||(t[e]={predecessor:[],successor:[]}),t[e]}function r(t,e){var n=[];return d(t,function(t){l(e,t)>=0&&n.push(t)}),n}t.topologicalTravel=function(t,e,i,r){function o(t){s[t].entryCount--,0===s[t].entryCount&&l.push(t)}if(t.length){var a=n(e),s=a.graph,l=a.noEntryList,h={};for(d(t,function(t){h[t]=!0});l.length;){var u=l.pop(),c=s[u],f=!!h[u];f&&(i.call(r,u,c.originalDeps.slice()),delete h[u]),d(c.successor,f?function(t){h[t]=!0,o(t)}:o)}d(h,function(){throw new Error("Circle dependency may exists")})}}}(Xv,function(t){var e=[];return d(Xv.getClassesByMainType(t),function(t){e=e.concat(t.prototype.dependencies||[])}),e=f(e,function(t){return Ln(t).main}),"dataset"!==t&&l(e,"dataset")<=0&&e.unshift("dataset"),e}),u(Xv,Zv);var jv="";"undefined"!=typeof navigator&&(jv=navigator.platform||"");var Yv={color:["#c23531","#2f4554","#61a0a8","#d48265","#91c7ae","#749f83","#ca8622","#bda29a","#6e7074","#546570","#c4ccd3"],gradientColor:["#f6efa6","#d88273","#bf444c"],textStyle:{fontFamily:jv.match(/^Win/)?"Microsoft YaHei":"sans-serif",fontSize:12,fontStyle:"normal",fontWeight:"normal"},blendMode:null,animation:"auto",animationDuration:1e3,animationDurationUpdate:300,animationEasing:"exponentialOut",animationEasingUpdate:"cubicOut",animationThreshold:2e3,progressiveThreshold:3e3,progressive:400,hoverLayerThreshold:3e3,useUTC:!1},qv=Cn(),$v={clearColorPalette:function(){qv(this).colorIdx=0,qv(this).colorNameMap={}},getColorFromPalette:function(t,e,n){var i=qv(e=e||this),r=i.colorIdx||0,o=i.colorNameMap=i.colorNameMap||{};if(o.hasOwnProperty(t))return o[t];var a=xn(this.get("color",!0)),s=this.get("colorLayer",!0),l=null!=n&&s?Ur(s,n):a;if((l=l||a)&&l.length){var h=l[r];return t&&(o[t]=h),i.colorIdx=(r+1)%l.length,h}}},Kv={cartesian2d:function(t,e,n,i){var r=t.getReferringComponents("xAxis")[0],o=t.getReferringComponents("yAxis")[0];e.coordSysDims=["x","y"],n.set("x",r),n.set("y",o),jr(r)&&(i.set("x",r),e.firstCategoryDimIndex=0),jr(o)&&(i.set("y",o),e.firstCategoryDimIndex=1)},singleAxis:function(t,e,n,i){var r=t.getReferringComponents("singleAxis")[0];e.coordSysDims=["single"],n.set("single",r),jr(r)&&(i.set("single",r),e.firstCategoryDimIndex=0)},polar:function(t,e,n,i){var r=t.getReferringComponents("polar")[0],o=r.findAxisModel("radiusAxis"),a=r.findAxisModel("angleAxis");e.coordSysDims=["radius","angle"],n.set("radius",o),n.set("angle",a),jr(o)&&(i.set("radius",o),e.firstCategoryDimIndex=0),jr(a)&&(i.set("angle",a),e.firstCategoryDimIndex=1)},geo:function(t,e,n,i){e.coordSysDims=["lng","lat"]},parallel:function(t,e,n,i){var r=t.ecModel,o=r.getComponent("parallel",t.get("parallelIndex")),a=e.coordSysDims=o.dimensions.slice();d(o.parallelAxisIndex,function(t,o){var s=r.getComponent("parallelAxis",t),l=a[o];n.set(l,s),jr(s)&&null==e.firstCategoryDimIndex&&(i.set(l,s),e.firstCategoryDimIndex=o)})}},Qv="original",Jv="arrayRows",ty="objectRows",ey="keyedColumns",ny="unknown",iy="typedArray",ry="column",oy="row";Yr.seriesDataToSource=function(t){return new Yr({data:t,sourceFormat:S(t)?iy:Qv,fromDataset:!1})},En(Yr);var ay=Cn(),sy="\0_ec_inner",ly=fr.extend({constructor:ly,init:function(t,e,n,i){n=n||{},this.option=null,this._theme=new fr(n),this._optionManager=i},setOption:function(t,e){P(!(sy in t),"please use chart.getOption()"),this._optionManager.setOption(t,e),this.resetOption(null)},resetOption:function(t){var e=!1,n=this._optionManager;if(!t||"recreate"===t){var i=n.mountOption("recreate"===t);this.option&&"recreate"!==t?(this.restoreData(),this.mergeOption(i)):ho.call(this,i),e=!0}if("timeline"!==t&&"media"!==t||this.restoreData(),!t||"recreate"===t||"timeline"===t){var r=n.getTimelineOption(this);r&&(this.mergeOption(r),e=!0)}if(!t||"recreate"===t||"media"===t){var o=n.getMediaOption(this,this._api);o.length&&d(o,function(t){this.mergeOption(t,e=!0)},this)}return e},mergeOption:function(t){var e=this.option,r=this._componentsMap,a=[];Kr(this),d(t,function(t,r){null!=t&&(Xv.hasClass(r)?r&&a.push(r):e[r]=null==e[r]?n(t):i(e[r],t,!0))}),Xv.topologicalTravel(a,Xv.getAllClassMainTypes(),function(n,i){var a=xn(t[n]),s=Sn(r.get(n),a);Mn(s),d(s,function(t,e){var i=t.option;w(i)&&(t.keyInfo.mainType=n,t.keyInfo.subType=co(n,i,t.exist))});var l=uo(r,i);e[n]=[],r.set(n,[]),d(s,function(t,i){var a=t.exist,s=t.option;if(P(w(s)||a,"Empty component definition"),s){var h=Xv.getClass(n,t.keyInfo.subType,!0);if(a&&a instanceof h)a.name=t.keyInfo.name,a.mergeOption(s,this),a.optionUpdated(s,!1);else{var u=o({dependentModels:l,componentIndex:i},t.keyInfo);o(a=new h(s,this,this,u),u),a.init(s,this,this,u),a.optionUpdated(null,!0)}}else a.mergeOption({},this),a.optionUpdated({},!1);r.get(n)[i]=a,e[n][i]=a.option},this),"series"===n&&fo(this,r.get("series"))},this),this._seriesIndicesMap=R(this._seriesIndices=this._seriesIndices||[])},getOption:function(){var t=n(this.option);return d(t,function(e,n){if(Xv.hasClass(n)){for(var i=(e=xn(e)).length-1;i>=0;i--)In(e[i])&&e.splice(i,1);t[n]=e}}),delete t[sy],t},getTheme:function(){return this._theme},getComponent:function(t,e){var n=this._componentsMap.get(t);if(n)return n[e||0]},queryComponents:function(t){var e=t.mainType;if(!e)return[];var n=t.index,i=t.id,r=t.name,o=this._componentsMap.get(e);if(!o||!o.length)return[];var a;if(null!=n)y(n)||(n=[n]),a=g(f(n,function(t){return o[t]}),function(t){return!!t});else if(null!=i){var s=y(i);a=g(o,function(t){return s&&l(i,t.id)>=0||!s&&t.id===i})}else if(null!=r){var h=y(r);a=g(o,function(t){return h&&l(r,t.name)>=0||!h&&t.name===r})}else a=o.slice();return po(a,t)},findComponents:function(t){var e=t.query,n=t.mainType,i=function(t){var e=n+"Index",i=n+"Id",r=n+"Name";return!t||null==t[e]&&null==t[i]&&null==t[r]?null:{mainType:n,index:t[e],id:t[i],name:t[r]}}(e);return function(e){return t.filter?g(e,t.filter):e}(po(i?this.queryComponents(i):this._componentsMap.get(n),t))},eachComponent:function(t,e,n){var i=this._componentsMap;"function"==typeof t?(n=e,e=t,i.each(function(t,i){d(t,function(t,r){e.call(n,i,t,r)})})):_(t)?d(i.get(t),e,n):w(t)&&d(this.findComponents(t),e,n)},getSeriesByName:function(t){return g(this._componentsMap.get("series"),function(e){return e.name===t})},getSeriesByIndex:function(t){return this._componentsMap.get("series")[t]},getSeriesByType:function(t){return g(this._componentsMap.get("series"),function(e){return e.subType===t})},getSeries:function(){return this._componentsMap.get("series").slice()},getSeriesCount:function(){return this._componentsMap.get("series").length},eachSeries:function(t,e){d(this._seriesIndices,function(n){var i=this._componentsMap.get("series")[n];t.call(e,i,n)},this)},eachRawSeries:function(t,e){d(this._componentsMap.get("series"),t,e)},eachSeriesByType:function(t,e,n){d(this._seriesIndices,function(i){var r=this._componentsMap.get("series")[i];r.subType===t&&e.call(n,r,i)},this)},eachRawSeriesByType:function(t,e,n){return d(this.getSeriesByType(t),e,n)},isSeriesFiltered:function(t){return null==this._seriesIndicesMap.get(t.componentIndex)},getCurrentSeriesIndices:function(){return(this._seriesIndices||[]).slice()},filterSeries:function(t,e){fo(this,g(this._componentsMap.get("series"),t,e))},restoreData:function(t){var e=this._componentsMap;fo(this,e.get("series"));var n=[];e.each(function(t,e){n.push(e)}),Xv.topologicalTravel(n,Xv.getAllClassMainTypes(),function(n,i){d(e.get(n),function(e){("series"!==n||!so(e,t))&&e.restoreData()})})}});u(ly,$v);var hy=["getDom","getZr","getWidth","getHeight","getDevicePixelRatio","dispatchAction","isDisposed","on","off","getDataURL","getConnectedDataURL","getModel","getOption","getViewOfComponentModel","getViewOfSeriesModel"],uy={};mo.prototype={constructor:mo,create:function(t,e){var n=[];d(uy,function(i,r){var o=i.create(t,e);n=n.concat(o||[])}),this._coordinateSystems=n},update:function(t,e){d(this._coordinateSystems,function(n){n.update&&n.update(t,e)})},getCoordinateSystems:function(){return this._coordinateSystems.slice()}},mo.register=function(t,e){uy[t]=e},mo.get=function(t){return uy[t]};var cy=d,dy=n,fy=f,py=i,gy=/^(min|max)?(.+)$/;vo.prototype={constructor:vo,setOption:function(t,e){t&&d(xn(t.series),function(t){t&&t.data&&S(t.data)&&O(t.data)}),t=dy(t,!0);var n=this._optionBackup,i=yo.call(this,t,e,!n);this._newBaseOption=i.baseOption,n?(bo(n.baseOption,i.baseOption),i.timelineOptions.length&&(n.timelineOptions=i.timelineOptions),i.mediaList.length&&(n.mediaList=i.mediaList),i.mediaDefault&&(n.mediaDefault=i.mediaDefault)):this._optionBackup=i},mountOption:function(t){var e=this._optionBackup;return this._timelineOptions=fy(e.timelineOptions,dy),this._mediaList=fy(e.mediaList,dy),this._mediaDefault=dy(e.mediaDefault),this._currentMediaIndices=[],dy(t?e.baseOption:this._newBaseOption)},getTimelineOption:function(t){var e,n=this._timelineOptions;if(n.length){var i=t.getComponent("timeline");i&&(e=dy(n[i.getCurrentIndex()],!0))}return e},getMediaOption:function(t){var e=this._api.getWidth(),n=this._api.getHeight(),i=this._mediaList,r=this._mediaDefault,o=[],a=[];if(!i.length&&!r)return a;for(var s=0,l=i.length;s1||l&&!a?function(n){function i(t,n){var i=r.getDimensionInfo(n);if(i&&!1!==i.otherDims.tooltip){var o=i.type,l=Rr({color:h,type:"subItem"}),u=(a?l+zr(i.displayName||"-")+": ":"")+zr("ordinal"===o?t+"":"time"===o?e?"":Nr("yyyy/MM/dd hh:mm:ss",t):Lr(t));u&&s.push(u)}}var a=p(n,function(t,e,n){var i=r.getDimensionInfo(n);return t|=i&&!1!==i.tooltip&&null!=i.displayName},0),s=[];return o.length?d(o,function(e){i(Go(r,t,e),e)}):d(n,i),(a?"
    ":"")+s.join(a?"
    ":", ")}(s):i(a?Go(r,t,o[0]):l?s[0]:s),c=Rr(h),f=r.getName(t),g=this.name;return g===Fg&&(g=""),g=g?zr(g)+(e?": ":"
    "):"",e?c+g+u:g+c+(f?zr(f)+": "+u:u)},isAnimationEnabled:function(){if(Zf.node)return!1;var t=this.getShallow("animation");return t&&this.getData().count()>this.getShallow("animationThreshold")&&(t=!1),t},restoreData:function(){this.dataTask.dirty()},getColorFromPalette:function(t,e,n){var i=this.ecModel,r=$v.getColorFromPalette.call(this,t,e,n);return r||(r=i.getColorFromPalette(t,e,n)),r},coordDimToDataDim:function(t){return this.getRawData().mapDimension(t,!0)},getProgressive:function(){return this.get("progressive")},getProgressiveThreshold:function(){return this.get("progressiveThreshold")},getAxisTooltipData:null,getTooltipPosition:null,pipeTask:null,preventIncremental:null,pipelineContext:null});u(Py,Ay),u(Py,$v);var Ly=function(){this.group=new Xp,this.uid=mr("viewComponent")};Ly.prototype={constructor:Ly,init:function(t,e){},render:function(t,e,n,i){},dispose:function(){}};var Oy=Ly.prototype;Oy.updateView=Oy.updateLayout=Oy.updateVisual=function(t,e,n,i){},zn(Ly),Bn(Ly,{registerWhenExtend:!0});var zy=function(){var t=Cn();return function(e){var n=t(e),i=e.pipelineContext,r=n.large,o=n.incrementalRender,a=n.large=i.large,s=n.incrementalRender=i.incrementalRender;return(r^a||o^s)&&"reset"}},Ey=Cn(),Ry=zy();ta.prototype={type:"chart",init:function(t,e){},render:function(t,e,n,i){},highlight:function(t,e,n,i){na(t.getData(),i,"emphasis")},downplay:function(t,e,n,i){na(t.getData(),i,"normal")},remove:function(t,e){this.group.removeAll()},dispose:function(){},incrementalPrepareRender:null,incrementalRender:null,updateTransform:null};var Ny=ta.prototype;Ny.updateView=Ny.updateLayout=Ny.updateVisual=function(t,e,n,i){this.render(t,e,n,i)},zn(ta),Bn(ta,{registerWhenExtend:!0}),ta.markUpdateMethod=function(t,e){Ey(t).updateMethod=e};var By="\0__throttleOriginMethod",Vy="\0__throttleRate",Fy="\0__throttleType",Gy={createOnAllSeries:!0,performRawSeries:!0,reset:function(t,e){var n=t.getData(),i=(t.visualColorAccessPath||"itemStyle.color").split("."),r=t.get(i)||t.getColorFromPalette(t.get("name"),null,e.getSeriesCount());if(n.setVisual("color",r),!e.isSeriesFiltered(t)){"function"!=typeof r||r instanceof pv||n.each(function(e){n.setItemVisual(e,"color",r(t.getDataParams(e)))});return{dataEach:n.hasItemOption?function(t,e){var n=t.getItemModel(e).get(i,!0);null!=n&&t.setItemVisual(e,"color",n)}:null}}}},Hy={toolbox:{brush:{title:{rect:"矩形选择",polygon:"圈选",lineX:"横向选择",lineY:"纵向选择",keep:"保持选择",clear:"清除选择"}},dataView:{title:"数据视图",lang:["数据视图","关闭","刷新"]},dataZoom:{title:{zoom:"区域缩放",back:"区域缩放还原"}},magicType:{title:{line:"切换为折线图",bar:"切换为柱状图",stack:"切换为堆叠",tiled:"切换为平铺"}},restore:{title:"还原"},saveAsImage:{title:"保存为图片",lang:["右键另存为图片"]}},series:{typeNames:{pie:"饼图",bar:"柱状图",line:"折线图",scatter:"散点图",effectScatter:"涟漪散点图",radar:"雷达图",tree:"树图",treemap:"矩形树图",boxplot:"箱型图",candlestick:"K线图",k:"K线图",heatmap:"热力图",map:"地图",parallel:"平行坐标图",lines:"线图",graph:"关系图",sankey:"桑基图",funnel:"漏斗图",gauge:"仪表盘图",pictorialBar:"象形柱图",themeRiver:"主题河流图",sunburst:"旭日图"}},aria:{general:{withTitle:"这是一个关于“{title}”的图表。",withoutTitle:"这是一个图表,"},series:{single:{prefix:"",withName:"图表类型是{seriesType},表示{seriesName}。",withoutName:"图表类型是{seriesType}。"},multiple:{prefix:"它由{seriesCount}个图表系列组成。",withName:"第{seriesId}个系列是一个表示{seriesName}的{seriesType},",withoutName:"第{seriesId}个系列是一个{seriesType},",separator:{middle:";",end:"。"}}},data:{allData:"其数据是——",partialData:"其中,前{displayCnt}项是——",withName:"{name}的数据是{value}",withoutName:"{value}",separator:{middle:",",end:""}}}},Wy=function(t,e){function n(t,e){if("string"!=typeof t)return t;var n=t;return d(e,function(t,e){n=n.replace(new RegExp("\\{\\s*"+e+"\\s*\\}","g"),t)}),n}function i(t){var e=o.get(t);if(null==e){for(var n=t.split("."),i=Hy.aria,r=0;r1?"series.multiple.prefix":"series.single.prefix"),{seriesCount:a}),e.eachSeries(function(t,e){if(e1?"multiple":"single")+".";o=n(o=i(s?h+"withName":h+"withoutName"),{seriesId:t.seriesIndex,seriesName:t.get("name"),seriesType:r(t.subType)});var c=t.getData();window.data=c,c.count()>l?o+=n(i("data.partialData"),{displayCnt:l}):o+=i("data.allData");for(var d=[],p=0;pn.bockIndex?n.step:null}}},Uy.getPipeline=function(t){return this._pipelineMap.get(t)},Uy.updateStreamModes=function(t,e){var n=this._pipelineMap.get(t.uid),i=t.getData().count(),r=n.progressiveEnabled&&e.incrementalPrepareRender&&i>=n.threshold,o=t.get("large")&&i>=t.get("largeThreshold");t.pipelineContext=n.context={incrementalRender:r,large:o}},Uy.restorePipelines=function(t){var e=this,n=e._pipelineMap=R();t.eachSeries(function(t){var i=t.getProgressive(),r=t.uid;n.set(r,{id:r,head:null,tail:null,threshold:t.getProgressiveThreshold(),progressiveEnabled:i&&!(t.preventIncremental&&t.preventIncremental()),bockIndex:-1,step:i||700,count:0}),wa(e,t,t.dataTask)})},Uy.prepareStageTasks=function(t,e){var n=this._stageTaskMap,i=this.ecInstance.getModel(),r=this.api;d(t,function(t){var e=n.get(t.uid)||n.set(t.uid,[]);t.reset&&ca(this,t,e,i,r),t.overallReset&&da(this,t,e,i,r)},this)},Uy.prepareView=function(t,e,n,i){var r=t.renderTask,o=r.context;o.model=e,o.ecModel=n,o.api=i,r.__block=!t.incrementalPrepareRender,wa(this,e,r)},Uy.performDataProcessorTasks=function(t,e,n){ua(this,t,e,n,{block:!0})},Uy.performVisualTasks=function(t,e,n,i){ua(this,t,e,n,i)},Uy.performSeriesTasks=function(t){var e;t.eachSeries(function(t){e|=t.dataTask.perform()}),this.unfinished|=e},Uy.plan=function(){this._pipelineMap.each(function(t){var e=t.tail;do{if(e.__block){t.bockIndex=e.__idxInPipeline;break}e=e.getUpstream()}while(e)})};var Xy=Uy.updatePayload=function(t,e){"remain"!==e&&(t.context.payload=e)};ha.wrapStageHandler=function(t,e){return x(t)&&(t={overallReset:t,seriesType:ba(t)}),t.uid=mr("stageHandler"),e&&(t.visualType=e),t};var jy,Yy={},qy={};Sa(Yy,ly),Sa(qy,go),Yy.eachSeriesByType=Yy.eachRawSeriesByType=function(t){jy=t},Yy.eachComponent=function(t){"series"===t.mainType&&t.subType&&(jy=t.subType)};var $y=["#37A2DA","#32C5E9","#67E0E3","#9FE6B8","#FFDB5C","#ff9f7f","#fb7293","#E062AE","#E690D1","#e7bcf3","#9d96f5","#8378EA","#96BFFF"],Ky={color:$y,colorLayer:[["#37A2DA","#ffd85c","#fd7b5f"],["#37A2DA","#67E0E3","#FFDB5C","#ff9f7f","#E062AE","#9d96f5"],["#37A2DA","#32C5E9","#9FE6B8","#FFDB5C","#ff9f7f","#fb7293","#e7bcf3","#8378EA","#96BFFF"],$y]},Qy=["#dd6b66","#759aa0","#e69d87","#8dc1a9","#ea7e53","#eedd78","#73a373","#73b9bc","#7289ab","#91ca8c","#f49f42"],Jy={color:Qy,backgroundColor:"#333",tooltip:{axisPointer:{lineStyle:{color:"#eee"},crossStyle:{color:"#eee"}}},legend:{textStyle:{color:"#eee"}},textStyle:{color:"#eee"},title:{textStyle:{color:"#eee"}},toolbox:{iconStyle:{normal:{borderColor:"#eee"}}},dataZoom:{textStyle:{color:"#eee"}},visualMap:{textStyle:{color:"#eee"}},timeline:{lineStyle:{color:"#eee"},itemStyle:{normal:{color:Qy[1]}},label:{normal:{textStyle:{color:"#eee"}}},controlStyle:{normal:{color:"#eee",borderColor:"#eee"}}},timeAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},logAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},valueAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},categoryAxis:{axisLine:{lineStyle:{color:"#eee"}},axisTick:{lineStyle:{color:"#eee"}},axisLabel:{textStyle:{color:"#eee"}},splitLine:{lineStyle:{type:"dashed",color:"#aaa"}},splitArea:{areaStyle:{color:"#eee"}}},line:{symbol:"circle"},graph:{color:Qy},gauge:{title:{textStyle:{color:"#eee"}}},candlestick:{itemStyle:{normal:{color:"#FD1050",color0:"#0CF49B",borderColor:"#FD1050",borderColor0:"#0CF49B"}}}};Jy.categoryAxis.splitLine.show=!1;var tx=P,ex=d,nx=x,ix=w,rx=Xv.parseClassType,ox={zrender:"4.0.1"},ax=1e3,sx=1e3,lx=3e3,hx={PROCESSOR:{FILTER:ax,STATISTIC:5e3},VISUAL:{LAYOUT:sx,GLOBAL:2e3,CHART:lx,COMPONENT:4e3,BRUSH:5e3}},ux="__flagInMainProcess",cx="__optionUpdated",dx=/^[a-zA-Z0-9_]+$/;Ia.prototype.on=Ma("on"),Ia.prototype.off=Ma("off"),Ia.prototype.one=Ma("one"),u(Ia,dp);var fx=Ta.prototype;fx._onframe=function(){if(!this._disposed){var t=this._scheduler;if(this[cx]){var e=this[cx].silent;this[ux]=!0,Aa(this),px.update.call(this),this[ux]=!1,this[cx]=!1,Oa.call(this,e),za.call(this,e)}else if(t.unfinished){var n=1,i=this._model;this._api;t.unfinished=!1;do{var r=+new Date;t.performSeriesTasks(i),t.performDataProcessorTasks(yx,i),Pa(this,i),t.performVisualTasks(bx,i),Fa(this,this._model,0,"remain"),n-=+new Date-r}while(n>0&&t.unfinished);t.unfinished||(this._zr&&this._zr.flush(),this.trigger("finished"))}}},fx.getDom=function(){return this._dom},fx.getZr=function(){return this._zr},fx.setOption=function(t,e,n){var i;if(ix(e)&&(n=e.lazyUpdate,i=e.silent,e=e.notMerge),this[ux]=!0,!this._model||e){var r=new vo(this._api),o=this._theme,a=this._model=new ly(null,null,o,r);a.scheduler=this._scheduler,a.init(null,null,o,r)}this._model.setOption(t,xx),n?(this[cx]={silent:i},this[ux]=!1):(Aa(this),px.update.call(this),this._zr.flush(),this[cx]=!1,this[ux]=!1,Oa.call(this,i),za.call(this,i))},fx.setTheme=function(){console.log("ECharts#setTheme() is DEPRECATED in ECharts 3.0")},fx.getModel=function(){return this._model},fx.getOption=function(){return this._model&&this._model.getOption()},fx.getWidth=function(){return this._zr.getWidth()},fx.getHeight=function(){return this._zr.getHeight()},fx.getDevicePixelRatio=function(){return this._zr.painter.dpr||window.devicePixelRatio||1},fx.getRenderedCanvas=function(t){if(Zf.canvasSupported){(t=t||{}).pixelRatio=t.pixelRatio||1,t.backgroundColor=t.backgroundColor||this._model.get("backgroundColor");var e=this._zr;return d(e.storage.getDisplayList(),function(t){t.stopAnimation(!0)}),e.painter.getRenderedCanvas(t)}},fx.getSvgDataUrl=function(){if(Zf.svgSupported){var t=this._zr;return d(t.storage.getDisplayList(),function(t){t.stopAnimation(!0)}),t.painter.pathToSvg()}},fx.getDataURL=function(t){var e=(t=t||{}).excludeComponents,n=this._model,i=[],r=this;ex(e,function(t){n.eachComponent({mainType:t},function(t){var e=r._componentsMap[t.__viewId];e.group.ignore||(i.push(e),e.group.ignore=!0)})});var o="svg"===this._zr.painter.getType()?this.getSvgDataUrl():this.getRenderedCanvas(t).toDataURL("image/"+(t&&t.type||"png"));return ex(i,function(t){t.group.ignore=!1}),o},fx.getConnectedDataURL=function(t){if(Zf.canvasSupported){var e=this.group,i=Math.min,r=Math.max;if(Tx[e]){var o=1/0,a=1/0,s=-1/0,l=-1/0,h=[],u=t&&t.pixelRatio||1;d(Ix,function(u,c){if(u.group===e){var d=u.getRenderedCanvas(n(t)),f=u.getDom().getBoundingClientRect();o=i(f.left,o),a=i(f.top,a),s=r(f.right,s),l=r(f.bottom,l),h.push({dom:d,left:f.left,top:f.top})}});var c=(s*=u)-(o*=u),f=(l*=u)-(a*=u),p=ep();p.width=c,p.height=f;var g=mn(p);return ex(h,function(t){var e=new je({style:{x:t.left*u-o,y:t.top*u-a,image:t.dom}});g.add(e)}),g.refreshImmediately(),p.toDataURL("image/"+(t&&t.type||"png"))}return this.getDataURL(t)}},fx.convertToPixel=v(Ca,"convertToPixel"),fx.convertFromPixel=v(Ca,"convertFromPixel"),fx.containPixel=function(t,e){var n;return t=An(this._model,t),d(t,function(t,i){i.indexOf("Models")>=0&&d(t,function(t){var r=t.coordinateSystem;if(r&&r.containPoint)n|=!!r.containPoint(e);else if("seriesModels"===i){var o=this._chartsMap[t.__viewId];o&&o.containPoint&&(n|=o.containPoint(e,t))}},this)},this),!!n},fx.getVisual=function(t,e){var n=(t=An(this._model,t,{defaultMainType:"series"})).seriesModel.getData(),i=t.hasOwnProperty("dataIndexInside")?t.dataIndexInside:t.hasOwnProperty("dataIndex")?n.indexOfRawIndex(t.dataIndex):null;return null!=i?n.getItemVisual(i,e):n.getVisual(e)},fx.getViewOfComponentModel=function(t){return this._componentsMap[t.__viewId]},fx.getViewOfSeriesModel=function(t){return this._chartsMap[t.__viewId]};var px={prepareAndUpdate:function(t){Aa(this),px.update.call(this,t)},update:function(t){var e=this._model,n=this._api,i=this._zr,r=this._coordSysMgr,o=this._scheduler;if(e){e.restoreData(t),o.performSeriesTasks(e),r.create(e,n),o.performDataProcessorTasks(yx,e,t),Pa(this,e),Ra(e),r.update(e,n),Na(e),o.performVisualTasks(bx,e,t),Ba(this,e,n,t);var a=e.get("backgroundColor")||"transparent",s=i.painter;if(s.isSingleCanvas&&s.isSingleCanvas())i.configLayer(0,{clearColor:a});else{if(!Zf.canvasSupported){var l=Mt(a);a=Lt(l,"rgb"),0===l[3]&&(a="transparent")}a.colorStops||a.image?(i.configLayer(0,{clearColor:a}),this.__hasGradientOrPatternBg=!0,this._dom.style.background="transparent"):(this.__hasGradientOrPatternBg&&i.configLayer(0,{clearColor:null}),this.__hasGradientOrPatternBg=!1,this._dom.style.background=a)}Ga(e,n)}},updateTransform:function(t){var e=this._model,n=this,i=this._api;if(e){var r=[];e.eachComponent(function(o,a){var s=n.getViewOfComponentModel(a);if(s&&s.__alive)if(s.updateTransform){var l=s.updateTransform(a,e,i,t);l&&l.update&&r.push(s)}else r.push(s)});var o=R();e.eachSeries(function(r){var a=n._chartsMap[r.__viewId];if(a.updateTransform){var s=a.updateTransform(r,e,i,t);s&&s.update&&o.set(r.uid,1)}else o.set(r.uid,1)}),Na(e),this._scheduler.performVisualTasks(bx,e,t,{setDirty:!0,dirtyMap:o}),Fa(n,e,0,t,o),Ga(e,this._api)}},updateView:function(t){var e=this._model;e&&(ta.markUpdateMethod(t,"updateView"),Na(e),this._scheduler.performVisualTasks(bx,e,t,{setDirty:!0}),Ba(this,this._model,this._api,t),Ga(e,this._api))},updateVisual:function(t){px.update.call(this,t)},updateLayout:function(t){px.update.call(this,t)}};fx.resize=function(t){this._zr.resize(t);var e=this._model;this._loadingFX&&this._loadingFX.resize(),e&&ka(this,e.resetOption("media"),t&&t.silent)},fx.showLoading=function(t,e){if(ix(t)&&(e=t,t=""),t=t||"default",this.hideLoading(),Mx[t]){var n=Mx[t](this._api,e),i=this._zr;this._loadingFX=n,i.add(n)}},fx.hideLoading=function(){this._loadingFX&&this._zr.remove(this._loadingFX),this._loadingFX=null},fx.makeActionFromEvent=function(t){var e=o({},t);return e.type=vx[t.type],e},fx.dispatchAction=function(t,e){ix(e)||(e={silent:!!e}),mx[t.type]&&this._model&&(this[ux]?this._pendingActions.push(t):(La.call(this,t,e.silent),e.flush?this._zr.flush(!0):!1!==e.flush&&Zf.browser.weChat&&this._throttledZrFlush(),Oa.call(this,e.silent),za.call(this,e.silent)))},fx.appendData=function(t){var e=t.seriesIndex;this.getModel().getSeriesByIndex(e).appendData(t),this._scheduler.unfinished=!0},fx.on=Ma("on"),fx.off=Ma("off"),fx.one=Ma("one");var gx=["click","dblclick","mouseover","mouseout","mousemove","mousedown","mouseup","globalout","contextmenu"];fx._initEvents=function(){ex(gx,function(t){this._zr.on(t,function(e){var n,i=this.getModel(),r=e.target;if("globalout"===t)n={};else if(r&&null!=r.dataIndex){var a=r.dataModel||i.getSeriesByIndex(r.seriesIndex);n=a&&a.getDataParams(r.dataIndex,r.dataType)||{}}else r&&r.eventData&&(n=o({},r.eventData));n&&(n.event=e,n.type=t,this.trigger(t,n))},this)},this),ex(vx,function(t,e){this._messageCenter.on(e,function(t){this.trigger(e,t)},this)},this)},fx.isDisposed=function(){return this._disposed},fx.clear=function(){this.setOption({series:[]},!0)},fx.dispose=function(){if(!this._disposed){this._disposed=!0,kn(this.getDom(),Dx,"");var t=this._api,e=this._model;ex(this._componentsViews,function(n){n.dispose(e,t)}),ex(this._chartsViews,function(n){n.dispose(e,t)}),this._zr.dispose(),delete Ix[this.id]}},u(Ta,dp);var mx={},vx={},yx=[],xx=[],_x=[],bx=[],Sx={},Mx={},Ix={},Tx={},Cx=new Date-0,Ax=new Date-0,Dx="_echarts_instance_",kx={},Px=ja;ts(2e3,Gy),$a(by),ns("default",function(t,e){a(e=e||{},{text:"loading",color:"#c23531",textColor:"#000",maskColor:"rgba(255, 255, 255, 0.8)",zlevel:0});var n=new lv({style:{fill:e.maskColor},zlevel:e.zlevel,z:1e4}),i=new dv({shape:{startAngle:-Zy/2,endAngle:-Zy/2+.1,r:10},style:{stroke:e.color,lineCap:"round",lineWidth:5},zlevel:e.zlevel,z:10001}),r=new lv({style:{fill:"none",text:e.text,textPosition:"right",textDistance:10,textFill:e.textColor},zlevel:e.zlevel,z:10001});i.animateShape(!0).when(1e3,{endAngle:3*Zy/2}).start("circularInOut"),i.animateShape(!0).when(1e3,{startAngle:3*Zy/2}).delay(300).start("circularInOut");var o=new Xp;return o.add(i),o.add(r),o.add(n),o.resize=function(){var e=t.getWidth()/2,o=t.getHeight()/2;i.setShape({cx:e,cy:o});var a=i.shape.r;r.setShape({x:e-a,y:o-a,width:2*a,height:2*a}),n.setShape({x:0,y:0,width:t.getWidth(),height:t.getHeight()})},o.resize(),o}),Qa({type:"highlight",event:"highlight",update:"highlight"},N),Qa({type:"downplay",event:"downplay",update:"downplay"},N),qa("light",Ky),qa("dark",Jy);var Lx={};ls.prototype={constructor:ls,add:function(t){return this._add=t,this},update:function(t){return this._update=t,this},remove:function(t){return this._remove=t,this},execute:function(){var t=this._old,e=this._new,n={},i=[],r=[];for(hs(t,{},i,"_oldKeyGetter",this),hs(e,n,r,"_newKeyGetter",this),o=0;o=e)){for(var n,i=this._chunkSize,r=this._rawData,o=this._storage,a=this.dimensions,s=this._dimensionInfos,l=this._nameList,h=this._idList,u=this._rawExtent,c=this._nameRepeatCount={},d=this._chunkCount,f=d-1,p=0;pu[I][1]&&(u[I][1]=C)}if(!r.pure){var A=l[_];w&&!A&&(null!=n?A=this._getNameFromStore(_):null!=w.name&&(l[_]=A=w.name));var D=null==w?null:w.id;null==D&&null!=A&&(c[A]=c[A]||0,D=A,c[A]>0&&(D+="__ec__"+c[A]),c[A]++),null!=D&&(h[_]=D)}}!r.persistent&&r.clean&&r.clean(),this._rawCount=this._count=e,this._extent={}}},Gx._getNameFromStore=function(t){var e=this._nameDimIdx;if(null!=e){var n=this._chunkSize,i=Math.floor(t/n),r=t%n,o=this.dimensions[e],a=this._dimensionInfos[o].ordinalMeta;if(a)return a.categories[t];var s=this._storage[o][i];return s&&s[r]}},Gx._getIdFromStore=function(t){var e=this._idDimIdx;if(null!=e){var n=this._chunkSize,i=Math.floor(t/n),r=t%n,o=this.dimensions[e],a=this._dimensionInfos[o].ordinalMeta;if(a)return a.categories[t];var s=this._storage[o][i];return s&&s[r]}},Gx.count=function(){return this._count},Gx.getIndices=function(){if(this._indices)return new(t=this._indices.constructor)(this._indices.buffer,0,this._count);for(var t=fs(this),e=new t(this.count()),n=0;n=0&&e=0&&h>0||a<=0&&h<0)&&(a+=h),l=l.stackedOn}}return a},Gx._getFast=function(t,e){var n=Math.floor(e/this._chunkSize),i=e%this._chunkSize;return this._storage[t][n][i]},Gx.getValues=function(t,e,n){var i=[];y(t)||(n=e,e=t,t=this.dimensions);for(var r=0,o=t.length;rl&&(l=u)}return r=[s,l],this._extent[a]=r,r},Gx.getApproximateExtent=function(t,e){return t=this.getDimension(t),this._approximateExtent[t]||this.getDataExtent(t,e)},Gx.setApproximateExtent=function(t,e,n){e=this.getDimension(e),this._approximateExtent[e]=t.slice()},Gx.isStacked=function(t){var e=this._dimensionInfos[t];return e&&e.stackable&&this.stackedOn},Gx.getSum=function(t,e){var n=0;if(this._storage[t])for(var i=0,r=this.count();i=this._rawCount||t<0)return-1;var e=this._indices,n=e[t];if(null!=n&&nt))return o;r=o-1}}return-1},Gx.indicesOfNearest=function(t,e,n,i){var r=[];if(!this._storage[t])return r;null==i&&(i=1/0);for(var o=Number.MAX_VALUE,a=-1,s=0,l=this.count();s=0&&a<0)&&(o=u,a=h,r.length=0),r.push(s))}return r},Gx.getRawIndex=ms,Gx.getRawDataItem=function(t){if(this._rawData.persistent)return this._rawData.getItem(this.getRawIndex(t));for(var e=[],n=0;n=h&&b<=u&&(a[s++]=d),d++;c=!0}else if(2===r){for(var f=this._storage[l],y=this._storage[n[1]],x=t[n[1]][0],_=t[n[1]][1],p=0;p=h&&b<=u&&S>=x&&S<=_&&(a[s++]=d),d++}c=!0}}if(!c)if(1===r){e=e||this.isStacked(l);for(v=0;v=h&&b<=u&&(a[s++]=I)}}else for(v=0;vt[T][1])&&(M=!1)}M&&(a[s++]=this.getRawIndex(v))}return sh-f&&(s=h-f,a.length=s);for(var p=0;p=e[0]&&t<=e[1]},Ds.prototype.normalize=function(t){var e=this._extent;return e[1]===e[0]?.5:(t-e[0])/(e[1]-e[0])},Ds.prototype.scale=function(t){var e=this._extent;return t*(e[1]-e[0])+e[0]},Ds.prototype.unionExtent=function(t){var e=this._extent;t[0]e[1]&&(e[1]=t[1])},Ds.prototype.unionExtentFromData=function(t,e){this.unionExtent(t.getApproximateExtent(e,!0))},Ds.prototype.getExtent=function(){return this._extent.slice()},Ds.prototype.setExtent=function(t,e){var n=this._extent;isNaN(t)||(n[0]=t),isNaN(e)||(n[1]=e)},Ds.prototype.getTicksLabels=function(){for(var t=[],e=this.getTicks(),n=0;ne[1]&&(e[1]=t[1]),qx.prototype.setExtent.call(this,e[0],e[1])},getInterval:function(){return this._interval},setInterval:function(t){this._interval=t,this._niceExtent=this._extent.slice(),this._intervalPrecision=zs(t)},getTicks:function(){return Ns(this._interval,this._extent,this._niceExtent,this._intervalPrecision)},getTicksLabels:function(){for(var t=[],e=this.getTicks(),n=0;n>>1;t[r][1]n&&(o=n);var a=n_.length,s=t_(n_,o,0,a),l=n_[Math.min(s,a-1)],h=l[1];"year"===l[0]&&(h*=Pr(r/h/t,!0));var u=this.getSetting("useUTC")?0:60*new Date(+i[0]||+i[1]).getTimezoneOffset()*1e3,c=[Math.round(Qx((i[0]-u)/h)*h+u),Math.round(Jx((i[1]-u)/h)*h+u)];Rs(c,i),this._stepLvl=l,this._interval=h,this._niceExtent=c},parse:function(t){return+Ar(t)}});d(["contain","normalize"],function(t){e_.prototype[t]=function(e){return Kx[t].call(this,this.parse(e))}});var n_=[["hh:mm:ss",1e3],["hh:mm:ss",5e3],["hh:mm:ss",1e4],["hh:mm:ss",15e3],["hh:mm:ss",3e4],["hh:mm\nMM-dd",6e4],["hh:mm\nMM-dd",3e5],["hh:mm\nMM-dd",6e5],["hh:mm\nMM-dd",9e5],["hh:mm\nMM-dd",18e5],["hh:mm\nMM-dd",36e5],["hh:mm\nMM-dd",72e5],["hh:mm\nMM-dd",216e5],["hh:mm\nMM-dd",432e5],["MM-dd\nyyyy",864e5],["MM-dd\nyyyy",1728e5],["MM-dd\nyyyy",2592e5],["MM-dd\nyyyy",3456e5],["MM-dd\nyyyy",432e6],["MM-dd\nyyyy",5184e5],["week",6048e5],["MM-dd\nyyyy",864e6],["week",12096e5],["week",18144e5],["month",26784e5],["week",36288e5],["month",53568e5],["week",36288e5],["quarter",8208e6],["month",107136e5],["month",13392e6],["half-year",16416e6],["month",214272e5],["month",26784e6],["year",32832e6]];e_.create=function(t){return new e_({useUTC:t.ecModel.get("useUTC")})};var i_=Ds.prototype,r_=qx.prototype,o_=Sr,a_=_r,s_=Math.floor,l_=Math.ceil,h_=Math.pow,u_=Math.log,c_=Ds.extend({type:"log",base:10,$constructor:function(){Ds.apply(this,arguments),this._originalScale=new qx},getTicks:function(){var t=this._originalScale,e=this._extent,n=t.getExtent();return f(r_.getTicks.call(this),function(i){var r=_r(h_(this.base,i));return r=i===e[0]&&t.__fixMin?Hs(r,n[0]):r,r=i===e[1]&&t.__fixMax?Hs(r,n[1]):r},this)},getLabel:r_.getLabel,scale:function(t){return t=i_.scale.call(this,t),h_(this.base,t)},setExtent:function(t,e){var n=this.base;t=u_(t)/u_(n),e=u_(e)/u_(n),r_.setExtent.call(this,t,e)},getExtent:function(){var t=this.base,e=i_.getExtent.call(this);e[0]=h_(t,e[0]),e[1]=h_(t,e[1]);var n=this._originalScale,i=n.getExtent();return n.__fixMin&&(e[0]=Hs(e[0],i[0])),n.__fixMax&&(e[1]=Hs(e[1],i[1])),e},unionExtent:function(t){this._originalScale.unionExtent(t);var e=this.base;t[0]=u_(t[0])/u_(e),t[1]=u_(t[1])/u_(e),i_.unionExtent.call(this,t)},unionExtentFromData:function(t,e){this.unionExtent(t.getApproximateExtent(e,!0,function(t){return t>0}))},niceTicks:function(t){t=t||10;var e=this._extent,n=e[1]-e[0];if(!(n===1/0||n<=0)){var i=Dr(n);for(t/n*i<=.5&&(i*=10);!isNaN(i)&&Math.abs(i)<1&&Math.abs(i)>0;)i*=10;var r=[_r(l_(e[0]/i)*i),_r(s_(e[1]/i)*i)];this._interval=i,this._niceExtent=r}},niceExtent:function(t){r_.niceExtent.call(this,t);var e=this._originalScale;e.__fixMin=t.fixMin,e.__fixMax=t.fixMax}});d(["contain","normalize"],function(t){c_.prototype[t]=function(e){return e=u_(e)/u_(this.base),i_[t].call(this,e)}}),c_.create=function(){return new c_};var d_={getFormattedLabels:function(){return Ys(this.axis,this.get("axisLabel.formatter"))},getMin:function(t){var e=this.option,n=t||null==e.rangeStart?e.min:e.rangeStart;return this.axis&&null!=n&&"dataMin"!==n&&"function"!=typeof n&&!I(n)&&(n=this.axis.scale.parse(n)),n},getMax:function(t){var e=this.option,n=t||null==e.rangeEnd?e.max:e.rangeEnd;return this.axis&&null!=n&&"dataMax"!==n&&"function"!=typeof n&&!I(n)&&(n=this.axis.scale.parse(n)),n},getNeedCrossZero:function(){var t=this.option;return null==t.rangeStart&&null==t.rangeEnd&&!t.scale},getCoordSysModel:N,setRange:function(t,e){this.option.rangeStart=t,this.option.rangeEnd=e},resetRange:function(){this.option.rangeStart=this.option.rangeEnd=null}},f_=Ai({type:"triangle",shape:{cx:0,cy:0,width:0,height:0},buildPath:function(t,e){var n=e.cx,i=e.cy,r=e.width/2,o=e.height/2;t.moveTo(n,i-o),t.lineTo(n+r,i+o),t.lineTo(n-r,i+o),t.closePath()}}),p_=Ai({type:"diamond",shape:{cx:0,cy:0,width:0,height:0},buildPath:function(t,e){var n=e.cx,i=e.cy,r=e.width/2,o=e.height/2;t.moveTo(n,i-o),t.lineTo(n+r,i),t.lineTo(n,i+o),t.lineTo(n-r,i),t.closePath()}}),g_=Ai({type:"pin",shape:{x:0,y:0,width:0,height:0},buildPath:function(t,e){var n=e.x,i=e.y,r=e.width/5*3,o=Math.max(r,e.height),a=r/2,s=a*a/(o-a),l=i-o+a+s,h=Math.asin(s/a),u=Math.cos(h)*a,c=Math.sin(h),d=Math.cos(h),f=.6*a,p=.7*a;t.moveTo(n-u,l+s),t.arc(n,l,a,Math.PI-h,2*Math.PI+h),t.bezierCurveTo(n+u-c*f,l+s+d*f,n,i-p,n,i),t.bezierCurveTo(n,i-p,n-u+c*f,l+s+d*f,n-u,l+s),t.closePath()}}),m_=Ai({type:"arrow",shape:{x:0,y:0,width:0,height:0},buildPath:function(t,e){var n=e.height,i=e.width,r=e.x,o=e.y,a=i/3*2;t.moveTo(r,o),t.lineTo(r+a,o+n),t.lineTo(r,o+n/4*3),t.lineTo(r-a,o+n),t.lineTo(r,o),t.closePath()}}),v_={line:function(t,e,n,i,r){r.x1=t,r.y1=e+i/2,r.x2=t+n,r.y2=e+i/2},rect:function(t,e,n,i,r){r.x=t,r.y=e,r.width=n,r.height=i},roundRect:function(t,e,n,i,r){r.x=t,r.y=e,r.width=n,r.height=i,r.r=Math.min(n,i)/4},square:function(t,e,n,i,r){var o=Math.min(n,i);r.x=t,r.y=e,r.width=o,r.height=o},circle:function(t,e,n,i,r){r.cx=t+n/2,r.cy=e+i/2,r.r=Math.min(n,i)/2},diamond:function(t,e,n,i,r){r.cx=t+n/2,r.cy=e+i/2,r.width=n,r.height=i},pin:function(t,e,n,i,r){r.x=t+n/2,r.y=e+i/2,r.width=n,r.height=i},arrow:function(t,e,n,i,r){r.x=t+n/2,r.y=e+i/2,r.width=n,r.height=i},triangle:function(t,e,n,i,r){r.cx=t+n/2,r.cy=e+i/2,r.width=n,r.height=i}},y_={};d({line:hv,rect:lv,roundRect:lv,square:lv,circle:Jm,diamond:p_,pin:g_,arrow:m_,triangle:f_},function(t,e){y_[e]=new t});var x_=Ai({type:"symbol",shape:{symbolType:"",x:0,y:0,width:0,height:0},beforeBrush:function(){var t=this.style;"pin"===this.shape.symbolType&&"inside"===t.textPosition&&(t.textPosition=["50%","40%"],t.textAlign="center",t.textVerticalAlign="middle")},buildPath:function(t,e,n){var i=e.symbolType,r=y_[i];"none"!==e.symbolType&&(r||(r=y_[i="rect"]),v_[i](e.x,e.y,e.width,e.height,r.shape),r.buildPath(t,r.shape,n))}}),__=(Object.freeze||Object)({createList:function(t){return Is(t.getSource(),t)},getLayoutRect:Fr,createScale:function(t,e){var n=e;fr.isInstance(e)||u(n=new fr(e),d_);var i=Xs(n);return i.setExtent(t[0],t[1]),Us(i,n),i},mixinAxisModelCommonMethods:function(t){u(t,d_)},completeDimensions:bs,createDimensions:Wx,createSymbol:Ks}),w_=1e-8;tl.prototype={constructor:tl,properties:null,getBoundingRect:function(){var t=this._rect;if(t)return t;for(var e=Number.MAX_VALUE,n=[e,e],i=[-e,-e],r=[],o=[],a=this.geometries,s=0;s0}),function(t){var e=t.properties,n=t.geometry,i=n.coordinates,r=[];"Polygon"===n.type&&r.push({type:"polygon",exterior:i[0],interiors:i.slice(1)}),"MultiPolygon"===n.type&&d(i,function(t){t[0]&&r.push({type:"polygon",exterior:t[0],interiors:t.slice(1)})});var o=new tl(e.name,r,e.cp);return o.properties=e,o})},S_=yr,M_=[0,1],I_=function(t,e,n){this.dim=t,this.scale=e,this._extent=n||[0,0],this.inverse=!1,this.onBand=!1,this._labelInterval};I_.prototype={constructor:I_,contain:function(t){var e=this._extent,n=Math.min(e[0],e[1]),i=Math.max(e[0],e[1]);return t>=n&&t<=i},containData:function(t){return this.contain(this.dataToCoord(t))},getExtent:function(){return this._extent.slice()},getPixelPrecision:function(t){return Mr(t||this.scale.getExtent(),this._extent)},setExtent:function(t,e){var n=this._extent;n[0]=t,n[1]=e},dataToCoord:function(t,e){var n=this._extent,i=this.scale;return t=i.normalize(t),this.onBand&&"ordinal"===i.type&&il(n=n.slice(),i.count()),S_(t,M_,n,e)},coordToData:function(t,e){var n=this._extent,i=this.scale;this.onBand&&"ordinal"===i.type&&il(n=n.slice(),i.count());var r=S_(t,n,M_,e);return this.scale.scale(r)},pointToData:function(t,e){},getTicksCoords:function(t){if(this.onBand&&!t){for(var e=this.getBands(),n=[],i=0;i0&&gl(n[r-1]);r--);for(;i0&&gl(n[o-1]);o--);for(;r=0){var a=r.getItemGraphicEl(o);if(!a){var s=r.getItemLayout(o);if(!s)return;(a=new sl(r,o)).position=s,a.setZ(t.get("zlevel"),t.get("z")),a.ignore=isNaN(s[0])||isNaN(s[1]),a.__temp=!0,r.setItemGraphicEl(o,a),a.stopSymbolAnimation(!0),this.group.add(a)}a.highlight()}else ta.prototype.highlight.call(this,t,e,n,i)},downplay:function(t,e,n,i){var r=t.getData(),o=Tn(r,i);if(null!=o&&o>=0){var a=r.getItemGraphicEl(o);a&&(a.__temp?(r.setItemGraphicEl(o,null),this.group.remove(a)):a.downplay())}else ta.prototype.downplay.call(this,t,e,n,i)},_newPolyline:function(t){var e=this._polyline;return e&&this._lineGroup.remove(e),e=new H_({shape:{points:t},silent:!0,z2:10}),this._lineGroup.add(e),this._polyline=e,e},_newPolygon:function(t,e){var n=this._polygon;return n&&this._lineGroup.remove(n),n=new W_({shape:{points:t,stackedOnPoints:e},silent:!0}),this._lineGroup.add(n),this._polygon=n,n},_getSymbolIgnoreFunc:function(t,e){var n=e.getAxesByScale("ordinal")[0];if(n&&n.isLabelIgnored)return m(n.isLabelIgnored,n)},_updateAnimation:function(t,e,n,i,r){var o=this._polyline,a=this._polygon,s=t.hostModel,l=z_(this._data,t,this._stackedOnPoints,e,this._coordSys,n),h=l.current,u=l.stackedOnCurrent,c=l.next,d=l.stackedOnNext;r&&(h=Tl(l.current,n,r),u=Tl(l.stackedOnCurrent,n,r),c=Tl(l.next,n,r),d=Tl(l.stackedOnNext,n,r)),o.shape.__points=l.current,o.shape.points=h,or(o,{shape:{points:c}},s),a&&(a.setShape({points:h,stackedOnPoints:u}),or(a,{shape:{points:c,stackedOnPoints:d}},s));for(var f=[],p=l.status,g=0;ge&&(e=t[n]);return e},min:function(t){for(var e=1/0,n=0;ne[1]&&e.reverse(),e},getOtherAxis:function(){this.grid.getOtherAxis()},isLabelIgnored:function(t){if("category"===this.type){var e=this.getLabelInterval();return"function"==typeof e&&!e(t,this.scale.getLabel(t))||t%(e+1)}},pointToData:function(t,e){return this.coordToData(this.toLocalCoord(t["x"===this.dim?0:1]),e)},toLocalCoord:null,toGlobalCoord:null},h(q_,I_);var $_={show:!0,zlevel:0,z:0,inverse:!1,name:"",nameLocation:"end",nameRotate:null,nameTruncate:{maxWidth:null,ellipsis:"...",placeholder:"."},nameTextStyle:{},nameGap:15,silent:!1,triggerEvent:!1,tooltip:{show:!1},axisPointer:{},axisLine:{show:!0,onZero:!0,onZeroAxisIndex:null,lineStyle:{color:"#333",width:1,type:"solid"},symbol:["none","none"],symbolSize:[10,15]},axisTick:{show:!0,inside:!1,length:5,lineStyle:{width:1}},axisLabel:{show:!0,inside:!1,rotate:0,showMinLabel:null,showMaxLabel:null,margin:8,fontSize:12},splitLine:{show:!0,lineStyle:{color:["#ccc"],width:1,type:"solid"}},splitArea:{show:!1,areaStyle:{color:["rgba(250,250,250,0.3)","rgba(200,200,200,0.3)"]}}},K_={};K_.categoryAxis=i({boundaryGap:!0,deduplication:null,splitLine:{show:!1},axisTick:{alignWithLabel:!1,interval:"auto"},axisLabel:{interval:"auto"}},$_),K_.valueAxis=i({boundaryGap:[0,0],splitNumber:5},$_),K_.timeAxis=a({scale:!0,min:"dataMin",max:"dataMax"},K_.valueAxis),K_.logAxis=a({scale:!0,logBase:10},K_.valueAxis);var Q_=["value","category","time","log"],J_=function(t,e,n,o){d(Q_,function(a){e.extend({type:t+"Axis."+a,mergeDefaultAndTheme:function(e,r){var o=this.layoutMode,s=o?Wr(e):{};i(e,r.getTheme().get(a+"Axis")),i(e,this.getDefaultOption()),e.type=n(t,e),o&&Hr(e,s,o)},optionUpdated:function(){"category"===this.option.type&&(this.__ordinalMeta=ks.createByAxisModel(this))},getCategories:function(){if("category"===this.option.type)return this.__ordinalMeta.categories},getOrdinalMeta:function(){return this.__ordinalMeta},defaultOption:r([{},K_[a+"Axis"],o],!0)})}),Xv.registerSubTypeDefaulter(t+"Axis",v(n,t))},tw=Xv.extend({type:"cartesian2dAxis",axis:null,init:function(){tw.superApply(this,"init",arguments),this.resetRange()},mergeOption:function(){tw.superApply(this,"mergeOption",arguments),this.resetRange()},restoreData:function(){tw.superApply(this,"restoreData",arguments),this.resetRange()},getCoordSysModel:function(){return this.ecModel.queryComponents({mainType:"grid",index:this.option.gridIndex,id:this.option.gridId})[0]}});i(tw.prototype,d_);var ew={offset:0};J_("x",tw,kl,ew),J_("y",tw,kl,ew),Xv.extend({type:"grid",dependencies:["xAxis","yAxis"],layoutMode:"box",coordinateSystem:null,defaultOption:{show:!1,zlevel:0,z:0,left:"10%",top:60,right:"10%",bottom:60,containLabel:!1,backgroundColor:"rgba(0,0,0,0)",borderWidth:1,borderColor:"#ccc"}});var nw=d,iw=function(t){var e=t.scale.getExtent(),n=e[0],i=e[1];return!(n>0&&i>0||n<0&&i<0)},rw=Us,ow=zl.prototype;ow.type="grid",ow.axisPointerEnabled=!0,ow.getRect=function(){return this._rect},ow.update=function(t,e){var n=this._axesMap;this._updateScale(t,this.model),nw(n.x,function(t){rw(t.scale,t.model)}),nw(n.y,function(t){rw(t.scale,t.model)}),nw(n.x,function(t){El(n,"y",t)}),nw(n.y,function(t){El(n,"x",t)}),this.resize(this.model,e)},ow.resize=function(t,e,n){function i(){nw(o,function(t){var e=t.isHorizontal(),n=e?[0,r.width]:[0,r.height],i=t.inverse?1:0;t.setExtent(n[i],n[1-i]),Nl(t,e?r.x:r.y)})}var r=Fr(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()});this._rect=r;var o=this._axesList;i(),!n&&t.get("containLabel")&&(nw(o,function(t){if(!t.model.get("axisLabel.inside")){var e=Ol(t);if(e){var n=t.isHorizontal()?"height":"width",i=t.model.get("axisLabel.margin");r[n]-=e[n]+i,"top"===t.position?r.y+=e.height+i:"left"===t.position&&(r.x+=e.width+i)}}}),i())},ow.getAxis=function(t,e){var n=this._axesMap[t];if(null!=n){if(null==e)for(var i in n)if(n.hasOwnProperty(i))return n[i];return n[e]}},ow.getAxes=function(){return this._axesList.slice()},ow.getCartesian=function(t,e){if(null!=t&&null!=e){var n="x"+t+"y"+e;return this._coordsMap[n]}w(t)&&(e=t.yAxisIndex,t=t.xAxisIndex);for(var i=0,r=this._coordsList;ih[1]?-1:1,c=["start"===r?h[0]-u*l:"end"===r?h[1]+u*l:(h[0]+h[1])/2,Xl(r)?t.labelOffset+a*l:0],d=e.get("nameRotate");null!=d&&(d=d*sw/180);var f;Xl(r)?i=uw(t.rotation,null!=d?d:t.rotation,a):(i=Gl(t,r,d||0,h),null!=(f=t.axisNameAvailableWidth)&&(f=Math.abs(f/Math.sin(i.rotation)),!isFinite(f)&&(f=null)));var p=s.getFont(),g=e.get("nameTruncate",!0)||{},m=g.ellipsis,v=T(t.nameTruncateMaxWidth,g.maxWidth,f),y=null!=m&&null!=v?Nv(n,v,p,m,{minChar:2,placeholder:g.placeholder}):n,x=e.get("tooltip",!0),_=e.mainType,w={componentType:_,name:n,$vars:["name"]};w[_+"Index"]=e.componentIndex;var b=new Qm({anid:"name",__fullText:n,__truncatedText:y,position:c,rotation:i.rotation,silent:Hl(e),z2:1,tooltip:x&&x.show?o({content:n,formatter:function(){return n},formatterParams:w},x):null});$i(b.style,s,{text:y,textFont:p,textFill:s.getTextColor()||e.get("axisLine.lineStyle.color"),textAlign:i.textAlign,textVerticalAlign:i.textVerticalAlign}),e.get("triggerEvent")&&(b.eventData=Fl(e),b.eventData.targetType="axisName",b.eventData.name=n),this._dumbGroup.add(b),b.updateTransform(),this.group.add(b),b.decomposeTransform()}}},uw=lw.innerTextLayout=function(t,e,n){var i,r,o=Tr(e-t);return Cr(o)?(r=n>0?"top":"bottom",i="center"):Cr(o-sw)?(r=n>0?"bottom":"top",i="center"):(r="middle",i=o>0&&o0?"right":"left":n>0?"left":"right"),{rotation:o,textAlign:i,textVerticalAlign:r}},cw=lw.ifIgnoreOnTick=function(t,e,n,i,r,o){if(0===e&&r||e===i-1&&o)return!1;var a,s=t.scale;return"ordinal"===s.type&&("function"==typeof n?(a=s.getTicks()[e],!n(a,s.getLabel(a))):e%(n+1))},dw=lw.getInterval=function(t,e){var n=t.get("interval");return null!=n&&"auto"!=n||(n=e),n},fw=d,pw=v,gw=rs({type:"axis",_axisPointer:null,axisPointerClass:null,render:function(t,e,n,i){this.axisPointerClass&&eh(t),gw.superApply(this,"render",arguments),ah(this,t,0,n,0,!0)},updateAxisPointer:function(t,e,n,i,r){ah(this,t,0,n,0,!1)},remove:function(t,e){var n=this._axisPointer;n&&n.remove(e),gw.superApply(this,"remove",arguments)},dispose:function(t,e){sh(this,e),gw.superApply(this,"dispose",arguments)}}),mw=[];gw.registerAxisPointerClass=function(t,e){mw[t]=e},gw.getAxisPointerClass=function(t){return t&&mw[t]};var vw=lw.ifIgnoreOnTick,yw=lw.getInterval,xw=["axisLine","axisTickLabel","axisName"],_w=["splitArea","splitLine"],ww=gw.extend({type:"cartesianAxis",axisPointerClass:"CartesianAxisPointer",render:function(t,e,n,i){this.group.removeAll();var r=this._axisGroup;if(this._axisGroup=new Xp,this.group.add(this._axisGroup),t.get("show")){var o=t.getCoordSysModel(),a=lh(o,t),s=new lw(t,a);d(xw,s.add,s),this._axisGroup.add(s.getGroup()),d(_w,function(e){t.get(e+".show")&&this["_"+e](t,o,a.labelInterval)},this),ur(r,this._axisGroup,t),ww.superCall(this,"render",t,e,n,i)}},_splitLine:function(t,e,n){var i=t.axis;if(!i.scale.isBlank()){var r=t.getModel("splitLine"),o=r.getModel("lineStyle"),s=o.get("color"),l=yw(r,n);s=y(s)?s:[s];for(var h=e.coordinateSystem.getRect(),u=i.isHorizontal(),c=0,d=i.getTicksCoords(),f=i.scale.getTicks(),p=t.get("axisLabel.showMinLabel"),g=t.get("axisLabel.showMaxLabel"),m=[],v=[],x=o.getLineStyle(),_=0;_1){var c;"string"==typeof r?c=X_[r]:"function"==typeof r&&(c=r),c&&t.setData(i.downSample(s.dim,1/u,c,j_))}}}}}("line")),Py.extend({type:"series.__base_bar__",getInitialData:function(t,e){return Is(this.getSource(),this)},getMarkerPosition:function(t){var e=this.coordinateSystem;if(e){var n=e.dataToPoint(e.clampData(t)),i=this.getData(),r=i.getLayout("offset"),o=i.getLayout("size");return n[e.getBaseAxis().isHorizontal()?0:1]+=r+o/2,n}return[NaN,NaN]},defaultOption:{zlevel:0,z:2,coordinateSystem:"cartesian2d",legendHoverLink:!0,barMinHeight:0,barMinAngle:0,itemStyle:{},emphasis:{}}}).extend({type:"series.bar",dependencies:["grid","polar"],brushSelector:"rect"});var bw=Xg([["fill","color"],["stroke","borderColor"],["lineWidth","borderWidth"],["stroke","barBorderColor"],["lineWidth","barBorderWidth"],["opacity"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"]]),Sw={getBarItemStyle:function(t){var e=bw(this,t);if(this.getBorderLineDash){var n=this.getBorderLineDash();n&&(e.lineDash=n)}return e}},Mw=["itemStyle","barBorderWidth"];o(fr.prototype,Sw),as({type:"bar",render:function(t,e,n){var i=t.get("coordinateSystem");return"cartesian2d"!==i&&"polar"!==i||this._render(t,e,n),this.group},dispose:N,_render:function(t,e,n){var i,r=this.group,o=t.getData(),a=this._data,s=t.coordinateSystem,l=s.getBaseAxis();"cartesian2d"===s.type?i=l.isHorizontal():"polar"===s.type&&(i="angle"===l.dim);var h=t.isAnimationEnabled()?t:null;o.diff(a).add(function(e){if(o.hasValue(e)){var n=o.getItemModel(e),a=Tw[s.type](o,e,n),l=Iw[s.type](o,e,n,a,i,h);o.setItemGraphicEl(e,l),r.add(l),fh(l,o,e,n,a,t,i,"polar"===s.type)}}).update(function(e,n){var l=a.getItemGraphicEl(n);if(o.hasValue(e)){var u=o.getItemModel(e),c=Tw[s.type](o,e,u);l?or(l,{shape:c},h,e):l=Iw[s.type](o,e,u,c,i,h,!0),o.setItemGraphicEl(e,l),r.add(l),fh(l,o,e,u,c,t,i,"polar"===s.type)}else r.remove(l)}).remove(function(t){var e=a.getItemGraphicEl(t);"cartesian2d"===s.type?e&&ch(t,h,e):e&&dh(t,h,e)}).execute(),this._data=o},remove:function(t,e){var n=this.group,i=this._data;t.get("animation")?i&&i.eachItemGraphicEl(function(e){"sector"===e.type?dh(e.dataIndex,t,e):ch(e.dataIndex,t,e)}):n.removeAll()}});var Iw={cartesian2d:function(t,e,n,i,r,a,s){var l=new lv({shape:o({},i)});if(a){var h=l.shape,u=r?"height":"width",c={};h[u]=0,c[u]=i[u],bv[s?"updateProps":"initProps"](l,{shape:c},a,e)}return l},polar:function(t,e,n,i,r,a,s){var l=new nv({shape:o({},i)});if(a){var h=l.shape,u=r?"r":"endAngle",c={};h[u]=r?0:i.startAngle,c[u]=i[u],bv[s?"updateProps":"initProps"](l,{shape:c},a,e)}return l}},Tw={cartesian2d:function(t,e,n){var i=t.getItemLayout(e),r=ph(n,i),o=i.width>0?1:-1,a=i.height>0?1:-1;return{x:i.x+o*r/2,y:i.y+a*r/2,width:i.width-o*r,height:i.height-a*r}},polar:function(t,e,n){var i=t.getItemLayout(e);return{cx:i.cx,cy:i.cy,r0:i.r0,r:i.r,startAngle:i.startAngle,endAngle:i.endAngle}}};Ja(v(function(t,e,n){var i=Fs(g(e.getSeriesByType(t),function(t){return!e.isSeriesFiltered(t)&&t.coordinateSystem&&"cartesian2d"===t.coordinateSystem.type})),r={},o={};e.eachSeriesByType(t,function(t){if("cartesian2d"===t.coordinateSystem.type){var e=t.getData(),n=t.coordinateSystem,a=n.getBaseAxis(),s=Bs(t),l=i[Vs(a)][s],h=l.offset,u=l.width,c=n.getOtherAxis(a),d=t.get("barMinHeight")||0,f=a.onZero?c.toGlobalCoord(c.dataToCoord(0)):c.getGlobalExtent()[0],p=[e.mapDimension("x"),e.mapDimension("y")],g=e.mapArray(p,function(t,e){return n.dataToPoint([t,e])},!0);r[s]=r[s]||[],o[s]=o[s]||[],e.setLayout({offset:h,size:u}),e.each(e.mapDimension(c.dim),function(t,n){if(!isNaN(t)){r[s][n]||(r[s][n]={p:f,n:f},o[s][n]={p:f,n:f});var i,a,l,p,m=t>=0?"p":"n",v=g[n],y=r[s][n][m],x=o[s][n][m];c.isHorizontal()?(i=y,a=v[1]+h,l=v[0]-x,p=u,o[s][n][m]+=l,Math.abs(l)0&&"scale"!==h){var d=r.getItemLayout(0),f=Math.max(n.getWidth(),n.getHeight())/2,p=m(a.removeClipPath,a);a.setClipPath(this._createClipPath(d.cx,d.cy,f,d.startAngle,d.clockwise,p,t))}this._data=r}},dispose:function(){},_createClipPath:function(t,e,n,i,r,o,a){var s=new nv({shape:{cx:t,cy:e,r0:0,r:n,startAngle:i,endAngle:i,clockwise:r}});return ar(s,{shape:{endAngle:i+(r?1:-1)*Math.PI*2}},a,o),s},containPoint:function(t,e){var n=e.getData().getItemLayout(0);if(n){var i=t[0]-n.cx,r=t[1]-n.cy,o=Math.sqrt(i*i+r*r);return o<=n.r&&o>=n.r0}}});var Pw=function(t,e,n,i){var r,o,a=t.getData(),s=[],l=!1;a.each(function(n){var i,h,u,c,d=a.getItemLayout(n),f=a.getItemModel(n),p=f.getModel("label"),g=p.get("position")||f.get("emphasis.label.position"),m=f.getModel("labelLine"),v=m.get("length"),y=m.get("length2"),x=(d.startAngle+d.endAngle)/2,_=Math.cos(x),w=Math.sin(x);r=d.cx,o=d.cy;var b="inside"===g||"inner"===g;if("center"===g)i=d.cx,h=d.cy,c="center";else{var S=(b?(d.r+d.r0)/2*_:d.r*_)+r,M=(b?(d.r+d.r0)/2*w:d.r*w)+o;if(i=S+3*_,h=M+3*w,!b){var I=S+_*(v+e-d.r),T=M+w*(v+e-d.r),C=I+(_<0?-1:1)*y,A=T;i=C+(_<0?-5:5),h=A,u=[[S,M],[I,T],[C,A]]}c=b?"center":_>0?"left":"right"}var D=p.getFont(),k=p.get("rotate")?_<0?-x+Math.PI:-x:0,P=ce(t.getFormattedLabel(n,"normal")||a.getName(n),D,c,"top");l=!!k,d.label={x:i,y:h,position:g,height:P.height,len:v,len2:y,linePoints:u,textAlign:c,verticalAlign:"middle",rotation:k,inside:b},b||s.push(d.label)}),!l&&t.get("avoidLabelOverlap")&&xh(s,r,o,e,n,i)},Lw=2*Math.PI,Ow=Math.PI/180;!function(t,e){d(e,function(e){e.update="updateView",Qa(e,function(n,i){var r={};return i.eachComponent({mainType:"series",subType:t,query:n},function(t){t[e.method]&&t[e.method](n.name,n.dataIndex);var i=t.getData();i.each(function(e){var n=i.getName(e);r[n]=t.isSelected(n)||!1})}),{name:n.name,selected:r}})})}("pie",[{type:"pieToggleSelect",event:"pieselectchanged",method:"toggleSelected"},{type:"pieSelect",event:"pieselected",method:"select"},{type:"pieUnSelect",event:"pieunselected",method:"unSelect"}]),ts(function(t){return{getTargetSeries:function(e){var n={},i=R();return e.eachSeriesByType(t,function(t){t.__paletteScope=n,i.set(t.uid,t)}),i},reset:function(t,e){var n=t.getRawData(),i={},r=t.getData();r.each(function(t){var e=r.getRawIndex(t);i[e]=t}),n.each(function(e){var o=i[e],a=null!=o&&r.getItemVisual(o,"color",!0);if(a)n.setItemVisual(e,"color",a);else{var s=n.getItemModel(e).get("itemStyle.color")||t.getColorFromPalette(n.getName(e),t.__paletteScope,n.count());n.setItemVisual(e,"color",s),null!=o&&r.setItemVisual(o,"color",s)}})}}}("pie")),Ja(v(function(t,e,n,i){e.eachSeriesByType(t,function(t){var e=t.getData(),i=e.mapDimension("value"),r=t.get("center"),o=t.get("radius");y(o)||(o=[0,o]),y(r)||(r=[r,r]);var a=n.getWidth(),s=n.getHeight(),l=Math.min(a,s),h=xr(r[0],a),u=xr(r[1],s),c=xr(o[0],l/2),d=xr(o[1],l/2),f=-t.get("startAngle")*Ow,p=t.get("minAngle")*Ow,g=0;e.each(i,function(t){!isNaN(t)&&g++});var m=e.getSum(i),v=Math.PI/(m||g)*2,x=t.get("clockwise"),_=t.get("roseType"),w=t.get("stillShowZeroSum"),b=e.getDataExtent(i);b[0]=0;var S=Lw,M=0,I=f,T=x?1:-1;if(e.each(i,function(t,n){var i;if(isNaN(t))e.setItemLayout(n,{angle:NaN,startAngle:NaN,endAngle:NaN,clockwise:x,cx:h,cy:u,r0:c,r:_?NaN:d});else{(i="area"!==_?0===m&&w?v:t*v:Lw/g)=0;s--){var l=2*s,h=i[l]-o/2,u=i[l+1]-a/2;if(t>=h&&e>=u&&t<=h+o&&e<=u+a)return s}return-1}}),Ew=_h.prototype;Ew.isPersistent=function(){return!this._incremental},Ew.updateData=function(t){this.group.removeAll();var e=new zw({rectHover:!0,cursor:"default"});e.setShape({points:t.getLayout("symbolPoints")}),this._setCommon(e,t),this.group.add(e),this._incremental=null},Ew.updateLayout=function(t){if(!this._incremental){var e=t.getLayout("symbolPoints");this.group.eachChild(function(t){if(null!=t.startIndex){var n=2*(t.endIndex-t.startIndex),i=4*t.startIndex*2;e=new Float32Array(e.buffer,i,n)}t.setShape("points",e)})}},Ew.incrementalPrepareUpdate=function(t){this.group.removeAll(),this._clearIncremental(),t.count()>2e6?(this._incremental||(this._incremental=new Ci({silent:!0})),this.group.add(this._incremental)):this._incremental=null},Ew.incrementalUpdate=function(t,e){var n;this._incremental?(n=new zw,this._incremental.addDisplayable(n,!0)):((n=new zw({rectHover:!0,cursor:"default",startIndex:t.start,endIndex:t.end})).incremental=!0,this.group.add(n)),n.setShape({points:e.getLayout("symbolPoints")}),this._setCommon(n,e,!!this._incremental)},Ew._setCommon=function(t,e,n){var i=e.hostModel,r=e.getVisual("symbolSize");t.setShape("size",r instanceof Array?r:[r,r]),t.symbolProxy=Ks(e.getVisual("symbol"),0,0,0,0),t.setColor=t.symbolProxy.setColor;var o=t.shape.size[0]<4;t.useStyle(i.getModel("itemStyle").getItemStyle(o?["color","shadowBlur","shadowColor"]:["color"]));var a=e.getVisual("color");a&&t.setColor(a),n||(t.seriesIndex=i.seriesIndex,t.on("mousemove",function(e){t.dataIndex=null;var n=t.findDataIndex(e.offsetX,e.offsetY);n>=0&&(t.dataIndex=n+(t.startIndex||0))}))},Ew.remove=function(){this._clearIncremental(),this._incremental=null,this.group.removeAll()},Ew._clearIncremental=function(){var t=this._incremental;t&&t.clearDisplaybles()},as({type:"scatter",render:function(t,e,n){var i=t.getData();this._updateSymbolDraw(i,t).updateData(i),this._finished=!0},incrementalPrepareRender:function(t,e,n){var i=t.getData();this._updateSymbolDraw(i,t).incrementalPrepareUpdate(i),this._finished=!1},incrementalRender:function(t,e,n){this._symbolDraw.incrementalUpdate(t,e.getData()),this._finished=t.end===e.getData().count()},updateTransform:function(t,e,n){var i=t.getData();if(this.group.dirty(),!this._finished||i.count()>1e4||!this._symbolDraw.isPersistent())return{update:!0};var r=U_().reset(t);r.progress&&r.progress({start:0,end:i.count()},i),this._symbolDraw.updateLayout(i)},_updateSymbolDraw:function(t,e){var n=this._symbolDraw,i=e.pipelineContext.large;return n&&i===this._isLargeDraw||(n&&n.remove(),n=this._symbolDraw=i?new _h:new hl,this._isLargeDraw=i,this.group.removeAll()),this.group.add(n.group),n},remove:function(t,e){this._symbolDraw&&this._symbolDraw.remove(!0),this._symbolDraw=null},dispose:function(){}}),ts(Z_("scatter","circle")),Ja(U_("scatter")),$a(function(t){var e=t.graphic;y(e)?e[0]&&e[0].elements?t.graphic=[t.graphic[0]]:t.graphic=[{elements:e}]:e&&!e.elements&&(t.graphic=[{elements:[e]}])});var Rw=is({type:"graphic",defaultOption:{elements:[],parentId:null},_elOptionsToUpdate:null,mergeOption:function(t){var e=this.option.elements;this.option.elements=null,Rw.superApply(this,"mergeOption",arguments),this.option.elements=e},optionUpdated:function(t,e){var n=this.option,i=(e?n:t).elements,r=n.elements=e?[]:n.elements,o=[];this._flatten(i,o);var a=Sn(r,o);Mn(a);var s=this._elOptionsToUpdate=[];d(a,function(t,e){var n=t.option;n&&(s.push(n),Ih(t,n),Th(r,e,n),Ch(r[e],n))},this);for(var l=r.length-1;l>=0;l--)null==r[l]?r.splice(l,1):delete r[l].$action},_flatten:function(t,e,n){d(t,function(t){if(t){n&&(t.parentOption=n),e.push(t);var i=t.children;"group"===t.type&&i&&this._flatten(i,e,t),delete t.children}},this)},useElOptionsToUpdate:function(){var t=this._elOptionsToUpdate;return this._elOptionsToUpdate=null,t}});rs({type:"graphic",init:function(t,e){this._elMap=R(),this._lastGraphicModel},render:function(t,e,n){t!==this._lastGraphicModel&&this._clear(),this._lastGraphicModel=t,this._updateElements(t,n),this._relocate(t,n)},_updateElements:function(t,e){var n=t.useElOptionsToUpdate();if(n){var i=this._elMap,r=this.group;d(n,function(t){var e=t.$action,n=t.id,o=i.get(n),a=t.parentId,s=null!=a?i.get(a):r;if("text"===t.type){var l=t.style;t.hv&&t.hv[1]&&(l.textVerticalAlign=l.textBaseline=null),!l.hasOwnProperty("textFill")&&l.fill&&(l.textFill=l.fill),!l.hasOwnProperty("textStroke")&&l.stroke&&(l.textStroke=l.stroke)}var h=Sh(t);e&&"merge"!==e?"replace"===e?(bh(o,i),wh(n,s,h,i)):"remove"===e&&bh(o,i):o?o.attr(h):wh(n,s,h,i);var u=i.get(n);u&&(u.__ecGraphicWidth=t.width,u.__ecGraphicHeight=t.height)})}},_relocate:function(t,e){for(var n=t.option.elements,i=this.group,r=this._elMap,o=n.length-1;o>=0;o--){var a=n[o],s=r.get(a.id);if(s){var l=s.parent;Gr(s,a,l===i?{width:e.getWidth(),height:e.getHeight()}:{width:l.__ecGraphicWidth||0,height:l.__ecGraphicHeight||0},null,{hv:a.hv,boundingMode:a.bounding})}}},_clear:function(){var t=this._elMap;t.each(function(e){bh(e,t)}),this._elMap=R()},dispose:function(){this._clear()}});var Nw=function(t,e){var n,i=[],r=t.seriesIndex;if(null==r||!(n=e.getSeriesByIndex(r)))return{point:[]};var o=n.getData(),a=Tn(o,t);if(null==a||a<0||y(a))return{point:[]};var s=o.getItemGraphicEl(a),l=n.coordinateSystem;if(n.getTooltipPosition)i=n.getTooltipPosition(a)||[];else if(l&&l.dataToPoint)i=l.dataToPoint(o.getValues(f(l.dimensions,function(t){return o.mapDimension(t)}),a,!0))||[];else if(s){var h=s.getBoundingRect().clone();h.applyTransform(s.transform),i=[h.x+h.width/2,h.y+h.height/2]}return{point:i,el:s}},Bw=d,Vw=v,Fw=Cn(),Gw=(is({type:"axisPointer",coordSysAxesInfo:null,defaultOption:{show:"auto",triggerOn:null,zlevel:0,z:50,type:"line",snap:!1,triggerTooltip:!0,value:null,status:null,link:[],animation:null,animationDurationUpdate:200,lineStyle:{color:"#aaa",width:1,type:"solid"},shadowStyle:{color:"rgba(150,150,150,0.3)"},label:{show:!0,formatter:null,precision:"auto",margin:3,color:"#fff",padding:[5,7,5,7],backgroundColor:"auto",borderColor:null,borderWidth:0,shadowBlur:3,shadowColor:"#aaa"},handle:{show:!1,icon:"M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7v-1.2h6.6z M13.3,22H6.7v-1.2h6.6z M13.3,19.6H6.7v-1.2h6.6z",size:45,margin:50,color:"#333",shadowBlur:3,shadowColor:"#aaa",shadowOffsetX:0,shadowOffsetY:2,throttle:40}}}),Cn()),Hw=d,Ww=rs({type:"axisPointer",render:function(t,e,n){var i=e.getComponent("tooltip"),r=t.get("triggerOn")||i&&i.get("triggerOn")||"mousemove|click";Bh("axisPointer",n,function(t,e,n){"none"!==r&&("leave"===t||r.indexOf(t)>=0)&&n({type:"updateAxisPointer",currTrigger:t,x:e&&e.offsetX,y:e&&e.offsetY})})},remove:function(t,e){Zh(e.getZr(),"axisPointer"),Ww.superApply(this._model,"remove",arguments)},dispose:function(t,e){Zh("axisPointer",e),Ww.superApply(this._model,"dispose",arguments)}}),Zw=Cn(),Uw=n,Xw=m;(Uh.prototype={_group:null,_lastGraphicKey:null,_handle:null,_dragging:!1,_lastValue:null,_lastStatus:null,_payloadInfo:null,animationThreshold:15,render:function(t,e,n,i){var r=e.get("value"),o=e.get("status");if(this._axisModel=t,this._axisPointerModel=e,this._api=n,i||this._lastValue!==r||this._lastStatus!==o){this._lastValue=r,this._lastStatus=o;var a=this._group,s=this._handle;if(!o||"hide"===o)return a&&a.hide(),void(s&&s.hide());a&&a.show(),s&&s.show();var l={};this.makeElOption(l,r,t,e,n);var h=l.graphicKey;h!==this._lastGraphicKey&&this.clear(n),this._lastGraphicKey=h;var u=this._moveAnimation=this.determineAnimation(t,e);if(a){var c=v(Xh,e,u);this.updatePointerEl(a,l,c,e),this.updateLabelEl(a,l,c,e)}else a=this._group=new Xp,this.createPointerEl(a,l,t,e),this.createLabelEl(a,l,t,e),n.getZr().add(a);$h(a,e,!0),this._renderHandle(r)}},remove:function(t){this.clear(t)},dispose:function(t){this.clear(t)},determineAnimation:function(t,e){var n=e.get("animation"),i=t.axis,r="category"===i.type,o=e.get("snap");if(!o&&!r)return!1;if("auto"===n||null==n){var a=this.animationThreshold;if(r&&i.getBandWidth()>a)return!0;if(o){var s=nh(t).seriesDataCount,l=i.getExtent();return Math.abs(l[0]-l[1])/s>a}return!1}return!0===n},makeElOption:function(t,e,n,i,r){},createPointerEl:function(t,e,n,i){var r=e.pointer;if(r){var o=Zw(t).pointerEl=new bv[r.type](Uw(e.pointer));t.add(o)}},createLabelEl:function(t,e,n,i){if(e.label){var r=Zw(t).labelEl=new lv(Uw(e.label));t.add(r),Yh(r,i)}},updatePointerEl:function(t,e,n){var i=Zw(t).pointerEl;i&&(i.setStyle(e.pointer.style),n(i,{shape:e.pointer.shape}))},updateLabelEl:function(t,e,n,i){var r=Zw(t).labelEl;r&&(r.setStyle(e.label.style),n(r,{shape:e.label.shape,position:e.label.position}),Yh(r,i))},_renderHandle:function(t){if(!this._dragging&&this.updateHandleTransform){var e=this._axisPointerModel,n=this._api.getZr(),i=this._handle,r=e.getModel("handle"),o=e.get("status");if(!r.get("show")||!o||"hide"===o)return i&&n.remove(i),void(this._handle=null);var a;this._handle||(a=!0,i=this._handle=dr(r.get("icon"),{cursor:"move",draggable:!0,onmousemove:function(t){bg(t.event)},onmousedown:Xw(this._onHandleDragMove,this,0,0),drift:Xw(this._onHandleDragMove,this),ondragend:Xw(this._onHandleDragEnd,this)}),n.add(i)),$h(i,e,!1);var s=["color","borderColor","borderWidth","opacity","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY"];i.setStyle(r.getItemStyle(null,s));var l=r.get("size");y(l)||(l=[l,l]),i.attr("scale",[l[0]/2,l[1]/2]),sa(this,"_doDispatchAxisPointer",r.get("throttle")||0,"fixRate"),this._moveHandleToValue(t,a)}},_moveHandleToValue:function(t,e){Xh(this._axisPointerModel,!e&&this._moveAnimation,this._handle,qh(this.getHandleTransform(t,this._axisModel,this._axisPointerModel)))},_onHandleDragMove:function(t,e){var n=this._handle;if(n){this._dragging=!0;var i=this.updateHandleTransform(qh(n),[t,e],this._axisModel,this._axisPointerModel);this._payloadInfo=i,n.stopAnimation(),n.attr(qh(i)),Zw(n).lastProp=null,this._doDispatchAxisPointer()}},_doDispatchAxisPointer:function(){if(this._handle){var t=this._payloadInfo,e=this._axisModel;this._api.dispatchAction({type:"updateAxisPointer",x:t.cursorPoint[0],y:t.cursorPoint[1],tooltipOption:t.tooltipOption,axesInfo:[{axisDim:e.axis.dim,axisIndex:e.componentIndex}]})}},_onHandleDragEnd:function(t){if(this._dragging=!1,this._handle){var e=this._axisPointerModel.get("value");this._moveHandleToValue(e),this._api.dispatchAction({type:"hideTip"})}},getHandleTransform:null,updateHandleTransform:null,clear:function(t){this._lastValue=null,this._lastStatus=null;var e=t.getZr(),n=this._group,i=this._handle;e&&n&&(this._lastGraphicKey=null,n&&e.remove(n),i&&e.remove(i),this._group=null,this._handle=null,this._payloadInfo=null)},doClear:function(){},buildLabel:function(t,e,n){return n=n||0,{x:t[n],y:t[1-n],width:e[n],height:e[1-n]}}}).constructor=Uh,zn(Uh);var jw=Uh.extend({makeElOption:function(t,e,n,i,r){var o=n.axis,a=o.grid,s=i.get("type"),l=ou(a,o).getOtherAxis(o).getGlobalExtent(),h=o.toGlobalCoord(o.dataToCoord(e,!0));if(s&&"none"!==s){var u=Kh(i),c=Yw[s](o,h,l,u);c.style=u,t.graphicKey=c.type,t.pointer=c}nu(e,t,lh(a.model,n),n,i,r)},getHandleTransform:function(t,e,n){var i=lh(e.axis.grid.model,e,{labelInside:!1});return i.labelMargin=n.get("handle.margin"),{position:eu(e.axis,t,i),rotation:i.rotation+(i.labelDirection<0?Math.PI:0)}},updateHandleTransform:function(t,e,n,i){var r=n.axis,o=r.grid,a=r.getGlobalExtent(!0),s=ou(o,r).getOtherAxis(r).getGlobalExtent(),l="x"===r.dim?0:1,h=t.position;h[l]+=e[l],h[l]=Math.min(a[1],h[l]),h[l]=Math.max(a[0],h[l]);var u=(s[1]+s[0])/2,c=[u,u];c[l]=h[l];var d=[{verticalAlign:"middle"},{align:"center"}];return{position:h,rotation:t.rotation,cursorPoint:c,tooltipOption:d[l]}}}),Yw={line:function(t,e,n,i){var r=iu([e,n[0]],[e,n[1]],au(t));return Oi({shape:r,style:i}),{type:"Line",shape:r}},shadow:function(t,e,n,i){var r=t.getBandWidth(),o=n[1]-n[0];return{type:"Rect",shape:ru([e-r/2,n[0]],[r,o],au(t))}}};gw.registerAxisPointerClass("CartesianAxisPointer",jw),$a(function(t){if(t){(!t.axisPointer||0===t.axisPointer.length)&&(t.axisPointer={});var e=t.axisPointer.link;e&&!y(e)&&(t.axisPointer.link=[e])}}),Ka(hx.PROCESSOR.STATISTIC,function(t,e){t.getComponent("axisPointer").coordSysAxesInfo=ql(t,e)}),Qa({type:"updateAxisPointer",event:"updateAxisPointer",update:":updateAxisPointer"},function(t,e,n){var i=t.currTrigger,r=[t.x,t.y],o=t,a=t.dispatchAction||m(n.dispatchAction,n),s=e.getComponent("axisPointer").coordSysAxesInfo;if(s){Nh(r)&&(r=Nw({seriesIndex:o.seriesIndex,dataIndex:o.dataIndex},e).point);var l=Nh(r),h=o.axesInfo,u=s.axesInfo,c="leave"===i||Nh(r),d={},f={},p={list:[],map:{}},g={showPointer:Vw(kh,f),showTooltip:Vw(Ph,p)};Bw(s.coordSysMap,function(t,e){var n=l||t.containPoint(r);Bw(s.coordSysAxesInfo[e],function(t,e){var i=t.axis,o=Eh(h,t);if(!c&&n&&(!h||o)){var a=o&&o.value;null!=a||l||(a=i.pointToData(r)),null!=a&&Ah(t,a,g,!1,d)}})});var v={};return Bw(u,function(t,e){var n=t.linkGroup;n&&!f[e]&&Bw(n.axesInfo,function(e,i){var r=f[i];if(e!==t&&r){var o=r.value;n.mapper&&(o=t.axis.scale.parse(n.mapper(o,Rh(e),Rh(t)))),v[t.key]=o}})}),Bw(v,function(t,e){Ah(u[e],t,g,!0,d)}),Lh(f,u,d),Oh(p,r,t,a),zh(u,0,n),d}}),is({type:"tooltip",dependencies:["axisPointer"],defaultOption:{zlevel:0,z:8,show:!0,showContent:!0,trigger:"item",triggerOn:"mousemove|click",alwaysShowContent:!1,displayMode:"single",confine:!1,showDelay:0,hideDelay:100,transitionDuration:.4,enterable:!1,backgroundColor:"rgba(50,50,50,0.7)",borderColor:"#333",borderRadius:4,borderWidth:0,padding:5,extraCssText:"",axisPointer:{type:"line",axis:"auto",animation:"auto",animationDurationUpdate:200,animationEasingUpdate:"exponentialOut",crossStyle:{color:"#999",width:1,type:"dashed",textStyle:{}}},textStyle:{color:"#fff",fontSize:14}}});var qw=d,$w=Or,Kw=["","-webkit-","-moz-","-o-"];uu.prototype={constructor:uu,_enterable:!0,update:function(){var t=this._container,e=t.currentStyle||document.defaultView.getComputedStyle(t),n=t.style;"absolute"!==n.position&&"absolute"!==e.position&&(n.position="relative")},show:function(t){clearTimeout(this._hideTimeout);var e=this.el;e.style.cssText="position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;"+hu(t)+";left:"+this._x+"px;top:"+this._y+"px;"+(t.get("extraCssText")||""),e.style.display=e.innerHTML?"block":"none",this._show=!0},setContent:function(t){this.el.innerHTML=null==t?"":t},setEnterable:function(t){this._enterable=t},getSize:function(){var t=this.el;return[t.clientWidth,t.clientHeight]},moveTo:function(t,e){var n,i=this._zr;i&&i.painter&&(n=i.painter.getViewportRootOffset())&&(t+=n.offsetLeft,e+=n.offsetTop);var r=this.el.style;r.left=t+"px",r.top=e+"px",this._x=t,this._y=e},hide:function(){this.el.style.display="none",this._show=!1},hideLater:function(t){!this._show||this._inContent&&this._enterable||(t?(this._hideDelay=t,this._show=!1,this._hideTimeout=setTimeout(m(this.hide,this),t)):this.hide())},isShow:function(){return this._show}};var Qw=m,Jw=d,tb=xr,eb=new lv({shape:{x:-1,y:-1,width:2,height:2}});rs({type:"tooltip",init:function(t,e){if(!Zf.node){var n=new uu(e.getDom(),e);this._tooltipContent=n}},render:function(t,e,n){if(!Zf.node&&!Zf.wxa){this.group.removeAll(),this._tooltipModel=t,this._ecModel=e,this._api=n,this._lastDataByCoordSys=null,this._alwaysShowContent=t.get("alwaysShowContent");var i=this._tooltipContent;i.update(),i.setEnterable(t.get("enterable")),this._initGlobalListener(),this._keepShow()}},_initGlobalListener:function(){var t=this._tooltipModel.get("triggerOn");Bh("itemTooltip",this._api,Qw(function(e,n,i){"none"!==t&&(t.indexOf(e)>=0?this._tryShow(n,i):"leave"===e&&this._hide(i))},this))},_keepShow:function(){var t=this._tooltipModel,e=this._ecModel,n=this._api;if(null!=this._lastX&&null!=this._lastY&&"none"!==t.get("triggerOn")){var i=this;clearTimeout(this._refreshUpdateTimeout),this._refreshUpdateTimeout=setTimeout(function(){i.manuallyShowTip(t,e,n,{x:i._lastX,y:i._lastY})})}},manuallyShowTip:function(t,e,n,i){if(i.from!==this.uid&&!Zf.node){var r=du(i,n);this._ticket="";var o=i.dataByCoordSys;if(i.tooltip&&null!=i.x&&null!=i.y){var a=eb;a.position=[i.x,i.y],a.update(),a.tooltip=i.tooltip,this._tryShow({offsetX:i.x,offsetY:i.y,target:a},r)}else if(o)this._tryShow({offsetX:i.x,offsetY:i.y,position:i.position,event:{},dataByCoordSys:i.dataByCoordSys,tooltipOption:i.tooltipOption},r);else if(null!=i.seriesIndex){if(this._manuallyAxisShowTip(t,e,n,i))return;var s=Nw(i,e),l=s.point[0],h=s.point[1];null!=l&&null!=h&&this._tryShow({offsetX:l,offsetY:h,position:i.position,target:s.el,event:{}},r)}else null!=i.x&&null!=i.y&&(n.dispatchAction({type:"updateAxisPointer",x:i.x,y:i.y}),this._tryShow({offsetX:i.x,offsetY:i.y,position:i.position,target:n.getZr().findHover(i.x,i.y).target,event:{}},r))}},manuallyHideTip:function(t,e,n,i){var r=this._tooltipContent;!this._alwaysShowContent&&this._tooltipModel&&r.hideLater(this._tooltipModel.get("hideDelay")),this._lastX=this._lastY=null,i.from!==this.uid&&this._hide(du(i,n))},_manuallyAxisShowTip:function(t,e,n,i){var r=i.seriesIndex,o=i.dataIndex,a=e.getComponent("axisPointer").coordSysAxesInfo;if(null!=r&&null!=o&&null!=a){var s=e.getSeriesByIndex(r);if(s&&"axis"===(t=cu([s.getData().getItemModel(o),s,(s.coordinateSystem||{}).model,t])).get("trigger"))return n.dispatchAction({type:"updateAxisPointer",seriesIndex:r,dataIndex:o,position:i.position}),!0}},_tryShow:function(t,e){var n=t.target;if(this._tooltipModel){this._lastX=t.offsetX,this._lastY=t.offsetY;var i=t.dataByCoordSys;i&&i.length?this._showAxisTooltip(i,t):n&&null!=n.dataIndex?(this._lastDataByCoordSys=null,this._showSeriesItemTooltip(t,n,e)):n&&n.tooltip?(this._lastDataByCoordSys=null,this._showComponentItemTooltip(t,n,e)):(this._lastDataByCoordSys=null,this._hide(e))}},_showOrMove:function(t,e){var n=t.get("showDelay");e=m(e,this),clearTimeout(this._showTimout),n>0?this._showTimout=setTimeout(e,n):e()},_showAxisTooltip:function(t,e){var n=this._ecModel,i=this._tooltipModel,r=[e.offsetX,e.offsetY],o=[],a=[],s=cu([e.tooltipOption,i]);Jw(t,function(t){Jw(t.dataByAxis,function(t){var e=n.getComponent(t.axisDim+"Axis",t.axisIndex),i=t.value,r=[];if(e&&null!=i){var s=tu(i,e.axis,n,t.seriesDataIndices,t.valueLabelOpt);d(t.seriesDataIndices,function(o){var l=n.getSeriesByIndex(o.seriesIndex),h=o.dataIndexInside,u=l&&l.getDataParams(h);u.axisDim=t.axisDim,u.axisIndex=t.axisIndex,u.axisType=t.axisType,u.axisId=t.axisId,u.axisValue=qs(e.axis,i),u.axisValueLabel=s,u&&(a.push(u),r.push(l.formatTooltip(h,!0)))});var l=s;o.push((l?zr(l)+"
    ":"")+r.join("
    "))}})},this),o.reverse(),o=o.join("

    ");var l=e.position;this._showOrMove(s,function(){this._updateContentNotChangedOnAxis(t)?this._updatePosition(s,l,r[0],r[1],this._tooltipContent,a):this._showTooltipContent(s,o,a,Math.random(),r[0],r[1],l)})},_showSeriesItemTooltip:function(t,e,n){var i=this._ecModel,r=e.seriesIndex,o=i.getSeriesByIndex(r),a=e.dataModel||o,s=e.dataIndex,l=e.dataType,h=a.getData(),u=cu([h.getItemModel(s),a,o&&(o.coordinateSystem||{}).model,this._tooltipModel]),c=u.get("trigger");if(null==c||"item"===c){var d=a.getDataParams(s,l),f=a.formatTooltip(s,!1,l),p="item_"+a.name+"_"+s;this._showOrMove(u,function(){this._showTooltipContent(u,f,d,p,t.offsetX,t.offsetY,t.position,t.target)}),n({type:"showTip",dataIndexInside:s,dataIndex:h.getRawIndex(s),seriesIndex:r,from:this.uid})}},_showComponentItemTooltip:function(t,e,n){var i=e.tooltip;if("string"==typeof i){var r=i;i={content:r,formatter:r}}var o=new fr(i,this._tooltipModel,this._ecModel),a=o.get("content"),s=Math.random();this._showOrMove(o,function(){this._showTooltipContent(o,a,o.get("formatterParams")||{},s,t.offsetX,t.offsetY,t.position,e)}),n({type:"showTip",from:this.uid})},_showTooltipContent:function(t,e,n,i,r,o,a,s){if(this._ticket="",t.get("showContent")&&t.get("show")){var l=this._tooltipContent,h=t.get("formatter");a=a||t.get("position");var u=e;if(h&&"string"==typeof h)u=Er(h,n,!0);else if("function"==typeof h){var c=Qw(function(e,i){e===this._ticket&&(l.setContent(i),this._updatePosition(t,a,r,o,l,n,s))},this);this._ticket=i,u=h(n,i,c)}l.setContent(u),l.show(t),this._updatePosition(t,a,r,o,l,n,s)}},_updatePosition:function(t,e,n,i,r,o,a){var s=this._api.getWidth(),l=this._api.getHeight();e=e||t.get("position");var h=r.getSize(),u=t.get("align"),c=t.get("verticalAlign"),d=a&&a.getBoundingRect().clone();if(a&&d.applyTransform(a.transform),"function"==typeof e&&(e=e([n,i],o,r.el,d,{viewSize:[s,l],contentSize:h.slice()})),y(e))n=tb(e[0],s),i=tb(e[1],l);else if(w(e)){e.width=h[0],e.height=h[1];var f=Fr(e,{width:s,height:l});n=f.x,i=f.y,u=null,c=null}else"string"==typeof e&&a?(n=(p=mu(e,d,h))[0],i=p[1]):(n=(p=fu(n,i,r.el,s,l,u?null:20,c?null:20))[0],i=p[1]);if(u&&(n-=vu(u)?h[0]/2:"right"===u?h[0]:0),c&&(i-=vu(c)?h[1]/2:"bottom"===c?h[1]:0),t.get("confine")){var p=pu(n,i,r.el,s,l);n=p[0],i=p[1]}r.moveTo(n,i)},_updateContentNotChangedOnAxis:function(t){var e=this._lastDataByCoordSys,n=!!e&&e.length===t.length;return n&&Jw(e,function(e,i){var r=e.dataByAxis||{},o=(t[i]||{}).dataByAxis||[];(n&=r.length===o.length)&&Jw(r,function(t,e){var i=o[e]||{},r=t.seriesDataIndices||[],a=i.seriesDataIndices||[];(n&=t.value===i.value&&t.axisType===i.axisType&&t.axisId===i.axisId&&r.length===a.length)&&Jw(r,function(t,e){var i=a[e];n&=t.seriesIndex===i.seriesIndex&&t.dataIndex===i.dataIndex})})}),this._lastDataByCoordSys=t,!!n},_hide:function(t){this._lastDataByCoordSys=null,t({type:"hideTip",from:this.uid})},dispose:function(t,e){Zf.node||(this._tooltipContent.hide(),Zh("itemTooltip",e))}}),Qa({type:"showTip",event:"showTip",update:"tooltip:manuallyShowTip"},function(){}),Qa({type:"hideTip",event:"hideTip",update:"tooltip:manuallyHideTip"},function(){});var nb=is({type:"legend.plain",dependencies:["series"],layoutMode:{type:"box",ignoreSize:!0},init:function(t,e,n){this.mergeDefaultAndTheme(t,n),t.selected=t.selected||{}},mergeOption:function(t){nb.superCall(this,"mergeOption",t)},optionUpdated:function(){this._updateData(this.ecModel);var t=this._data;if(t[0]&&"single"===this.get("selectedMode")){for(var e=!1,n=0;n=0},defaultOption:{zlevel:0,z:4,show:!0,orient:"horizontal",left:"center",top:0,align:"auto",backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderRadius:0,borderWidth:0,padding:5,itemGap:10,itemWidth:25,itemHeight:14,inactiveColor:"#ccc",textStyle:{color:"#333"},selectedMode:!0,tooltip:{show:!1}}});Qa("legendToggleSelect","legendselectchanged",v(yu,"toggleSelected")),Qa("legendSelect","legendselected",v(yu,"select")),Qa("legendUnSelect","legendunselected",v(yu,"unSelect"));var ib=v,rb=d,ob=Xp,ab=rs({type:"legend.plain",newlineDisabled:!1,init:function(){this.group.add(this._contentGroup=new ob),this._backgroundEl},getContentGroup:function(){return this._contentGroup},render:function(t,e,n){if(this.resetInner(),t.get("show",!0)){var i=t.get("align");i&&"auto"!==i||(i="right"===t.get("left")&&"vertical"===t.get("orient")?"right":"left"),this.renderInner(i,t,e,n);var r=t.getBoxLayoutParams(),o={width:n.getWidth(),height:n.getHeight()},s=t.get("padding"),l=Fr(r,o,s),h=this.layoutInner(t,i,l),u=Fr(a({width:h.width,height:h.height},r),o,s);this.group.attr("position",[u.x-h.x,u.y-h.y]),this.group.add(this._backgroundEl=_u(h,t))}},resetInner:function(){this.getContentGroup().removeAll(),this._backgroundEl&&this.group.remove(this._backgroundEl)},renderInner:function(t,e,n,i){var r=this.getContentGroup(),o=R(),a=e.get("selectedMode");rb(e.getData(),function(s,l){var h=s.get("name");if(this.newlineDisabled||""!==h&&"\n"!==h){var u=n.getSeriesByName(h)[0];if(!o.get(h))if(u){var c=u.getData(),d=c.getVisual("color");"function"==typeof d&&(d=d(u.getDataParams(0)));var f=c.getVisual("legendSymbol")||"roundRect",p=c.getVisual("symbol");this._createItem(h,l,s,e,f,p,t,d,a).on("click",ib(wu,h,i)).on("mouseover",ib(bu,u,null,i)).on("mouseout",ib(Su,u,null,i)),o.set(h,!0)}else n.eachRawSeries(function(n){if(!o.get(h)&&n.legendDataProvider){var r=n.legendDataProvider(),u=r.indexOfName(h);if(u<0)return;var c=r.getItemVisual(u,"color");this._createItem(h,l,s,e,"roundRect",null,t,c,a).on("click",ib(wu,h,i)).on("mouseover",ib(bu,n,h,i)).on("mouseout",ib(Su,n,h,i)),o.set(h,!0)}},this)}else r.add(new ob({newline:!0}))},this)},_createItem:function(t,e,n,i,r,a,s,l,h){var u=i.get("itemWidth"),c=i.get("itemHeight"),d=i.get("inactiveColor"),f=i.isSelected(t),p=new ob,g=n.getModel("textStyle"),m=n.get("icon"),v=n.getModel("tooltip"),y=v.parentModel;if(r=m||r,p.add(Ks(r,0,0,u,c,f?l:d,!0)),!m&&a&&(a!==r||"none"==a)){var x=.8*c;"none"===a&&(a="circle"),p.add(Ks(a,(u-x)/2,(c-x)/2,x,x,f?l:d))}var _="left"===s?u+5:-5,w=s,b=i.get("formatter"),S=t;"string"==typeof b&&b?S=b.replace("{name}",null!=t?t:""):"function"==typeof b&&(S=b(t)),p.add(new Qm({style:$i({},g,{text:S,x:_,y:c/2,textFill:f?g.getTextColor():d,textAlign:w,textVerticalAlign:"middle"})}));var M=new lv({shape:p.getBoundingRect(),invisible:!0,tooltip:v.get("show")?o({content:t,formatter:y.get("formatter",!0)||function(){return t},formatterParams:{componentType:"legend",legendIndex:i.componentIndex,name:t,$vars:["name"]}},v.option):null});return p.add(M),p.eachChild(function(t){t.silent=!0}),M.silent=!h,this.getContentGroup().add(p),Yi(p),p.__legendDataIndex=e,p},layoutInner:function(t,e,n){var i=this.getContentGroup();Wv(t.get("orient"),i,t.get("itemGap"),n.width,n.height);var r=i.getBoundingRect();return i.attr("position",[-r.x,-r.y]),this.group.getBoundingRect()}});Ka(function(t){var e=t.findComponents({mainType:"legend"});e&&e.length&&t.filterSeries(function(t){for(var n=0;nn[s],f=[-u.x,-u.y];f[a]=i.position[a];var p=[0,0],g=[-c.x,-c.y],m=C(t.get("pageButtonGap",!0),t.get("itemGap",!0));d&&("end"===t.get("pageButtonPosition",!0)?g[a]+=n[s]-c[s]:p[a]+=c[s]+m),g[1-a]+=u[l]/2-c[l]/2,i.attr("position",f),r.attr("position",p),o.attr("position",g);var v=this.group.getBoundingRect();if((v={x:0,y:0})[s]=d?n[s]:u[s],v[l]=Math.max(u[l],c[l]),v[h]=Math.min(0,c[h]+g[1-a]),r.__rectSize=n[s],d){var y={x:0,y:0};y[s]=Math.max(n[s]-c[s]-m,0),y[l]=v[l],r.setClipPath(new lv({shape:y})),r.__rectSize=y[s]}else o.eachChild(function(t){t.attr({invisible:!0,silent:!0})});var x=this._getPageInfo(t);return null!=x.pageIndex&&or(i,{position:x.contentPosition},!!d&&t),this._updatePageInfoView(t,x),v},_pageGo:function(t,e,n){var i=this._getPageInfo(e)[t];null!=i&&n.dispatchAction({type:"legendScroll",scrollDataIndex:i,legendId:e.id})},_updatePageInfoView:function(t,e){var n=this._controllerGroup;d(["pagePrev","pageNext"],function(i){var r=null!=e[i+"DataIndex"],o=n.childOfName(i);o&&(o.setStyle("fill",r?t.get("pageIconColor",!0):t.get("pageIconInactiveColor",!0)),o.cursor=r?"pointer":"default")});var i=n.childOfName("pageText"),r=t.get("pageFormatter"),o=e.pageIndex,a=null!=o?o+1:0,s=e.pageCount;i&&r&&i.setStyle("text",_(r)?r.replace("{current}",a).replace("{total}",s):r({current:a,total:s}))},_getPageInfo:function(t){function e(t){var e=t.getBoundingRect().clone();return e[f]+=t.position[u],e}var n,i,r,o,a=t.get("scrollDataIndex",!0),s=this.getContentGroup(),l=s.getBoundingRect(),h=this._containerGroup.__rectSize,u=t.getOrient().index,c=hb[u],d=hb[1-u],f=ub[u],p=s.position.slice();this._showController?s.eachChild(function(t){t.__legendDataIndex===a&&(o=t)}):o=s.childAt(0);var g=h?Math.ceil(l[c]/h):0;if(o){var m=o.getBoundingRect(),v=o.position[u]+m[f];p[u]=-v-l[f],n=Math.floor(g*(v+m[f]+h/2)/l[c]),n=l[c]&&g?Math.max(0,Math.min(g-1,n)):-1;var y={x:0,y:0};y[c]=h,y[d]=l[d],y[f]=-p[u]-l[f];var x,_=s.children();if(s.eachChild(function(t,n){var i=e(t);i.intersect(y)&&(null==x&&(x=n),r=t.__legendDataIndex),n===_.length-1&&i[f]+i[c]<=y[f]+y[c]&&(r=null)}),null!=x){var w=e(_[x]);if(y[f]=w[f]+w[c]-y[c],x<=0&&w[f]>=y[f])i=null;else{for(;x>0&&e(_[x-1]).intersect(y);)x--;i=_[x].__legendDataIndex}}}return{contentPosition:p,pageIndex:n,pageCount:g,pagePrevDataIndex:i,pageNextDataIndex:r}}});Qa("legendScroll","legendscroll",function(t,e){var n=t.scrollDataIndex;null!=n&&e.eachComponent({mainType:"legend",subType:"scroll",query:t},function(t){t.setScrollDataIndex(n)})}),is({type:"title",layoutMode:{type:"box",ignoreSize:!0},defaultOption:{zlevel:0,z:6,show:!0,text:"",target:"blank",subtext:"",subtarget:"blank",left:0,top:0,backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,itemGap:10,textStyle:{fontSize:18,fontWeight:"bolder",color:"#333"},subtextStyle:{color:"#aaa"}}}),rs({type:"title",render:function(t,e,n){if(this.group.removeAll(),t.get("show")){var i=this.group,r=t.getModel("textStyle"),o=t.getModel("subtextStyle"),a=t.get("textAlign"),s=t.get("textBaseline"),l=new Qm({style:$i({},r,{text:t.get("text"),textFill:r.getTextColor()},{disableBox:!0}),z2:10}),h=l.getBoundingRect(),u=t.get("subtext"),c=new Qm({style:$i({},o,{text:u,textFill:o.getTextColor(),y:h.height+t.get("itemGap"),textVerticalAlign:"top"},{disableBox:!0}),z2:10}),d=t.get("link"),f=t.get("sublink");l.silent=!d,c.silent=!f,d&&l.on("click",function(){window.open(d,"_"+t.get("target"))}),f&&c.on("click",function(){window.open(f,"_"+t.get("subtarget"))}),i.add(l),u&&i.add(c);var p=i.getBoundingRect(),g=t.getBoxLayoutParams();g.width=p.width,g.height=p.height;var m=Fr(g,{width:n.getWidth(),height:n.getHeight()},t.get("padding"));a||("middle"===(a=t.get("left")||t.get("right"))&&(a="center"),"right"===a?m.x+=m.width:"center"===a&&(m.x+=m.width/2)),s||("center"===(s=t.get("top")||t.get("bottom"))&&(s="middle"),"bottom"===s?m.y+=m.height:"middle"===s&&(m.y+=m.height/2),s=s||"top"),i.attr("position",[m.x,m.y]);var v={textAlign:a,textVerticalAlign:s};l.setStyle(v),c.setStyle(v),p=i.getBoundingRect();var y=m.margin,x=t.getItemStyle(["color","opacity"]);x.fill=t.get("backgroundColor");var _=new lv({shape:{x:p.x-y[3],y:p.y-y[0],width:p.width+y[1]+y[3],height:p.height+y[0]+y[2],r:t.get("borderRadius")},style:x,silent:!0});zi(_),i.add(_)}}});var db=Lr,fb=zr,pb=is({type:"marker",dependencies:["series","grid","polar","geo"],init:function(t,e,n,i){this.mergeDefaultAndTheme(t,n),this.mergeOption(t,n,i.createdBySelf,!0)},isAnimationEnabled:function(){if(Zf.node)return!1;var t=this.__hostSeries;return this.getShallow("animation")&&t&&t.isAnimationEnabled()},mergeOption:function(t,e,n,i){var r=this.constructor,a=this.mainType+"Model";n||e.eachSeries(function(t){var n=t.get(this.mainType),s=t[a];n&&n.data?(s?s.mergeOption(n,e,!0):(i&&Iu(n),d(n.data,function(t){t instanceof Array?(Iu(t[0]),Iu(t[1])):Iu(t)}),o(s=new r(n,this,e),{mainType:this.mainType,seriesIndex:t.seriesIndex,name:t.name,createdBySelf:!0}),s.__hostSeries=t),t[a]=s):t[a]=null},this)},formatTooltip:function(t){var e=this.getData(),n=this.getRawValue(t),i=y(n)?f(n,db).join(", "):db(n),r=e.getName(t),o=fb(this.name);return(null!=n||r)&&(o+="
    "),r&&(o+=fb(r),null!=n&&(o+=" : ")),null!=n&&(o+=fb(i)),o},getData:function(){return this._data},setData:function(t){this._data=t}});u(pb,Ay),pb.extend({type:"markPoint",defaultOption:{zlevel:0,z:5,symbol:"pin",symbolSize:50,tooltip:{trigger:"item"},label:{show:!0,position:"inside"},itemStyle:{borderWidth:2},emphasis:{label:{show:!0}}}});var gb=l,mb=v,vb={min:mb(Du,"min"),max:mb(Du,"max"),average:mb(Du,"average")},yb=rs({type:"marker",init:function(){this.markerGroupMap=R()},render:function(t,e,n){var i=this.markerGroupMap;i.each(function(t){t.__keep=!1});var r=this.type+"Model";e.eachSeries(function(t){var i=t[r];i&&this.renderSeries(t,i,e,n)},this),i.each(function(t){!t.__keep&&this.group.remove(t.group)},this)},renderSeries:function(){}});yb.extend({type:"markPoint",updateTransform:function(t,e,n){e.eachSeries(function(t){var e=t.markPointModel;e&&(Ru(e.getData(),t,n),this.markerGroupMap.get(t.id).updateLayout(e))},this)},renderSeries:function(t,e,n,i){var r=t.coordinateSystem,o=t.id,a=t.getData(),s=this.markerGroupMap,l=s.get(o)||s.set(o,new hl),h=Nu(r,t,e);e.setData(h),Ru(e.getData(),t,i),h.each(function(t){var n=h.getItemModel(t),i=n.getShallow("symbolSize");"function"==typeof i&&(i=i(e.getRawValue(t),e.getDataParams(t))),h.setItemVisual(t,{symbolSize:i,color:n.get("itemStyle.color")||a.getVisual("color"),symbol:n.getShallow("symbol")})}),l.updateData(h),this.group.add(l.group),h.eachItemGraphicEl(function(t){t.traverse(function(t){t.dataModel=e})}),l.__keep=!0,l.group.silent=e.get("silent")||t.get("silent")}}),$a(function(t){t.markPoint=t.markPoint||{}}),pb.extend({type:"markLine",defaultOption:{zlevel:0,z:5,symbol:["circle","arrow"],symbolSize:[8,16],precision:2,tooltip:{trigger:"item"},label:{show:!0,position:"end"},lineStyle:{type:"dashed"},emphasis:{label:{show:!0},lineStyle:{width:3}},animationEasing:"linear"}});var xb=hv.prototype,_b=cv.prototype,wb=Ai({type:"ec-line",style:{stroke:"#000",fill:null},shape:{x1:0,y1:0,x2:0,y2:0,percent:1,cpx1:null,cpy1:null},buildPath:function(t,e){(Bu(e)?xb:_b).buildPath(t,e)},pointAt:function(t){return Bu(this.shape)?xb.pointAt.call(this,t):_b.pointAt.call(this,t)},tangentAt:function(t){var e=this.shape,n=Bu(e)?[e.x2-e.x1,e.y2-e.y1]:_b.tangentAt.call(this,t);return j(n,n)}}),bb=["fromSymbol","toSymbol"],Sb=Wu.prototype;Sb.beforeUpdate=function(){var t=this,e=t.childOfName("fromSymbol"),n=t.childOfName("toSymbol"),i=t.childOfName("label");if(e||n||!i.ignore){for(var r=1,o=this.parent;o;)o.scale&&(r/=o.scale[0]),o=o.parent;var a=t.childOfName("line");if(this.__dirty||a.__dirty){var s=a.shape.percent,l=a.pointAt(0),h=a.pointAt(s),u=W([],h,l);if(j(u,u),e&&(e.attr("position",l),c=a.tangentAt(0),e.attr("rotation",Math.PI/2-Math.atan2(c[1],c[0])),e.attr("scale",[r*s,r*s])),n){n.attr("position",h);var c=a.tangentAt(1);n.attr("rotation",-Math.PI/2-Math.atan2(c[1],c[0])),n.attr("scale",[r*s,r*s])}if(!i.ignore){i.attr("position",h);var d,f,p,g=5*r;if("end"===i.__position)d=[u[0]*g+h[0],u[1]*g+h[1]],f=u[0]>.8?"left":u[0]<-.8?"right":"center",p=u[1]>.8?"top":u[1]<-.8?"bottom":"middle";else if("middle"===i.__position){var m=s/2,v=[(c=a.tangentAt(m))[1],-c[0]],y=a.pointAt(m);v[1]>0&&(v[0]=-v[0],v[1]=-v[1]),d=[y[0]+v[0]*g,y[1]+v[1]*g],f="center",p="bottom";var x=-Math.atan2(c[1],c[0]);h[0].8?"right":u[0]<-.8?"left":"center",p=u[1]>.8?"bottom":u[1]<-.8?"top":"middle";i.attr({style:{textVerticalAlign:i.__verticalAlign||p,textAlign:i.__textAlign||f},position:d,scale:[r,r]})}}}},Sb._createLine=function(t,e,n){var i=t.hostModel,r=Gu(t.getItemLayout(e));r.shape.percent=0,ar(r,{shape:{percent:1}},i,e),this.add(r);var o=new Qm({name:"label"});this.add(o),d(bb,function(n){var i=Fu(n,t,e);this.add(i),this[Vu(n)]=t.getItemVisual(e,n)},this),this._updateCommonStl(t,e,n)},Sb.updateData=function(t,e,n){var i=t.hostModel,r=this.childOfName("line"),o=t.getItemLayout(e),a={shape:{}};Hu(a.shape,o),or(r,a,i,e),d(bb,function(n){var i=t.getItemVisual(e,n),r=Vu(n);if(this[r]!==i){this.remove(this.childOfName(n));var o=Fu(n,t,e);this.add(o)}this[r]=i},this),this._updateCommonStl(t,e,n)},Sb._updateCommonStl=function(t,e,n){var i=t.hostModel,r=this.childOfName("line"),o=n&&n.lineStyle,s=n&&n.hoverLineStyle,l=n&&n.labelModel,h=n&&n.hoverLabelModel;if(!n||t.hasItemOption){var u=t.getItemModel(e);o=u.getModel("lineStyle").getLineStyle(),s=u.getModel("emphasis.lineStyle").getLineStyle(),l=u.getModel("label"),h=u.getModel("emphasis.label")}var c=t.getItemVisual(e,"color"),f=A(t.getItemVisual(e,"opacity"),o.opacity,1);r.useStyle(a({strokeNoScale:!0,fill:"none",stroke:c,opacity:f},o)),r.hoverStyle=s,d(bb,function(t){var e=this.childOfName(t);e&&(e.setColor(c),e.setStyle({opacity:f}))},this);var p,g,m,v=l.getShallow("show"),y=h.getShallow("show"),x=this.childOfName("label");if(v||y){if(p=c||"#000",null==(g=i.getFormattedLabel(e,"normal",t.dataType))){var _=i.getRawValue(e);g=null==_?t.getName(e):isFinite(_)?_r(_):_}m=C(i.getFormattedLabel(e,"emphasis",t.dataType),g)}if(v){var w=$i(x.style,l,{text:g},{autoColor:p});x.__textAlign=w.textAlign,x.__verticalAlign=w.textVerticalAlign,x.__position=l.get("position")||"middle"}else x.setStyle("text",null);x.hoverStyle=y?{text:m,textFill:h.getTextColor(!0),fontStyle:h.getShallow("fontStyle"),fontWeight:h.getShallow("fontWeight"),fontSize:h.getShallow("fontSize"),fontFamily:h.getShallow("fontFamily")}:{text:null},x.ignore=!v&&!y,Yi(this)},Sb.highlight=function(){this.trigger("emphasis")},Sb.downplay=function(){this.trigger("normal")},Sb.updateLayout=function(t,e){this.setLinePoints(t.getItemLayout(e))},Sb.setLinePoints=function(t){var e=this.childOfName("line");Hu(e.shape,t),e.dirty()},h(Wu,Xp);var Mb=Zu.prototype;Mb.isPersistent=function(){return!0},Mb.updateData=function(t){var e=this,n=e.group,i=e._lineData;e._lineData=t,i||n.removeAll();var r=ju(t);t.diff(i).add(function(n){Uu(e,t,n,r)}).update(function(n,o){Xu(e,i,t,o,n,r)}).remove(function(t){n.remove(i.getItemGraphicEl(t))}).execute()},Mb.updateLayout=function(){var t=this._lineData;t.eachItemGraphicEl(function(e,n){e.updateLayout(t,n)},this)},Mb.incrementalPrepareUpdate=function(t){this._seriesScope=ju(t),this._lineData=null,this.group.removeAll()},Mb.incrementalUpdate=function(t,e){for(var n=t.start;n=0&&"number"==typeof u&&(u=+u.toFixed(Math.min(m,20))),p.coord[d]=g.coord[d]=u,a=[p,g,{type:l,valueIndex:a.valueIndex,value:u}]}return a=[ku(t,a[0]),ku(t,a[1]),o({},a[2])],a[2].type=a[2].type||"",i(a[2],a[0]),i(a[2],a[1]),a};yb.extend({type:"markLine",updateTransform:function(t,e,n){e.eachSeries(function(t){var e=t.markLineModel;if(e){var i=e.getData(),r=e.__from,o=e.__to;r.each(function(e){Ju(r,e,!0,t,n),Ju(o,e,!1,t,n)}),i.each(function(t){i.setItemLayout(t,[r.getItemLayout(t),o.getItemLayout(t)])}),this.markerGroupMap.get(t.id).updateLayout()}},this)},renderSeries:function(t,e,n,i){function r(e,n,r){var o=e.getItemModel(n);Ju(e,n,r,t,i),e.setItemVisual(n,{symbolSize:o.get("symbolSize")||g[r?0:1],symbol:o.get("symbol",!0)||p[r?0:1],color:o.get("itemStyle.color")||s.getVisual("color")})}var o=t.coordinateSystem,a=t.id,s=t.getData(),l=this.markerGroupMap,h=l.get(a)||l.set(a,new Zu);this.group.add(h.group);var u=tc(o,t,e),c=u.from,d=u.to,f=u.line;e.__from=c,e.__to=d,e.setData(f);var p=e.get("symbol"),g=e.get("symbolSize");y(p)||(p=[p,p]),"number"==typeof g&&(g=[g,g]),u.from.each(function(t){r(c,t,!0),r(d,t,!1)}),f.each(function(t){var e=f.getItemModel(t).get("lineStyle.color");f.setItemVisual(t,{color:e||c.getItemVisual(t,"color")}),f.setItemLayout(t,[c.getItemLayout(t),d.getItemLayout(t)]),f.setItemVisual(t,{fromSymbolSize:c.getItemVisual(t,"symbolSize"),fromSymbol:c.getItemVisual(t,"symbol"),toSymbolSize:d.getItemVisual(t,"symbolSize"),toSymbol:d.getItemVisual(t,"symbol")})}),h.updateData(f),u.line.eachItemGraphicEl(function(t,n){t.traverse(function(t){t.dataModel=e})}),h.__keep=!0,h.group.silent=e.get("silent")||t.get("silent")}}),$a(function(t){t.markLine=t.markLine||{}}),pb.extend({type:"markArea",defaultOption:{zlevel:0,z:1,tooltip:{trigger:"item"},animation:!1,label:{show:!0,position:"top"},itemStyle:{borderWidth:0},emphasis:{label:{show:!0,position:"top"}}}});var Tb=function(t,e,n,i){var o=ku(t,i[0]),a=ku(t,i[1]),s=T,l=o.coord,h=a.coord;l[0]=s(l[0],-1/0),l[1]=s(l[1],-1/0),h[0]=s(h[0],1/0),h[1]=s(h[1],1/0);var u=r([{},o,a]);return u.coord=[o.coord,a.coord],u.x0=o.x,u.y0=o.y,u.x1=a.x,u.y1=a.y,u},Cb=[["x0","y0"],["x1","y0"],["x1","y1"],["x0","y1"]];yb.extend({type:"markArea",updateTransform:function(t,e,n){e.eachSeries(function(t){var e=t.markAreaModel;if(e){var i=e.getData();i.each(function(e){var r=f(Cb,function(r){return rc(i,e,r,t,n)});i.setItemLayout(e,r),i.getItemGraphicEl(e).setShape("points",r)})}},this)},renderSeries:function(t,e,n,i){var r=t.coordinateSystem,o=t.name,s=t.getData(),l=this.markerGroupMap,h=l.get(o)||l.set(o,{group:new Xp});this.group.add(h.group),h.__keep=!0;var u=oc(r,t,e);e.setData(u),u.each(function(e){u.setItemLayout(e,f(Cb,function(n){return rc(u,e,n,t,i)})),u.setItemVisual(e,{color:s.getVisual("color")})}),u.diff(h.__data).add(function(t){var e=new av({shape:{points:u.getItemLayout(t)}});u.setItemGraphicEl(t,e),h.group.add(e)}).update(function(t,n){var i=h.__data.getItemGraphicEl(n);or(i,{shape:{points:u.getItemLayout(t)}},e,t),h.group.add(i),u.setItemGraphicEl(t,i)}).remove(function(t){var e=h.__data.getItemGraphicEl(t);h.group.remove(e)}).execute(),u.eachItemGraphicEl(function(t,n){var i=u.getItemModel(n),r=i.getModel("label"),o=i.getModel("emphasis.label"),s=u.getItemVisual(n,"color");t.useStyle(a(i.getModel("itemStyle").getItemStyle(),{fill:Pt(s,.4),stroke:s})),t.hoverStyle=i.getModel("emphasis.itemStyle").getItemStyle(),qi(t.style,t.hoverStyle,r,o,{labelFetcher:e,labelDataIndex:n,defaultText:u.getName(n)||"",isRectText:!0,autoColor:s}),Yi(t,{}),t.dataModel=e}),h.__data=u,h.group.silent=e.get("silent")||t.get("silent")}}),$a(function(t){t.markArea=t.markArea||{}}),Xv.registerSubTypeDefaulter("dataZoom",function(){return"slider"});var Ab=["cartesian2d","polar","singleAxis"],Db=function(t,e){var n=f(t=t.slice(),Br),i=f(e=(e||[]).slice(),Br);return function(r,o){d(t,function(t,a){for(var s={name:t,capital:n[a]},l=0;l=a[0]&&t<=a[1]}if(t===this._dataZoomModel){var i=this._dimName,r=this.getTargetSeriesModels(),o=t.get("filterMode"),a=this._valueWindow;if("none"!==o){var s=this.getOtherAxisModel();t.get("$fromToolbox")&&s&&s.hasSeriesStacked&&(o="empty"),kb(r,function(t){var e=t.getData(),r=e.mapDimension(i,!0);"weakFilter"===o?e.filterSelf(function(t){for(var n,i,o,s=0;sa[1];if(h&&!u&&!c)return!0;h&&(o=!0),u&&(n=!0),c&&(i=!0)}return o&&n&&i}):kb(r,function(i){if("empty"===o)t.setData(e.map(i,function(t){return n(t)?t:NaN}));else{var r={};r[i]=a,e.selectRange(r)}}),kb(r,function(t){e.setApproximateExtent(a,t)})})}}}};var Ob=d,zb=Db,Eb=is({type:"dataZoom",dependencies:["xAxis","yAxis","zAxis","radiusAxis","angleAxis","singleAxis","series"],defaultOption:{zlevel:0,z:4,orient:null,xAxisIndex:null,yAxisIndex:null,filterMode:"filter",throttle:null,start:0,end:100,startValue:null,endValue:null,minSpan:null,maxSpan:null,minValueSpan:null,maxValueSpan:null,rangeMode:null},init:function(t,e,n){this._dataIntervalByAxis={},this._dataInfo={},this._axisProxies={},this.textStyleModel,this._autoThrottle=!0,this._rangePropMode=["percent","percent"];var i=dc(t);this.mergeDefaultAndTheme(t,n),this.doInit(i)},mergeOption:function(t){var e=dc(t);i(this.option,t,!0),this.doInit(e)},doInit:function(t){var e=this.option;Zf.canvasSupported||(e.realtime=!1),this._setDefaultThrottle(t),fc(this,t),Ob([["start","startValue"],["end","endValue"]],function(t,n){"value"===this._rangePropMode[n]&&(e[t[0]]=null)},this),this.textStyleModel=this.getModel("textStyle"),this._resetTarget(),this._giveAxisProxies()},_giveAxisProxies:function(){var t=this._axisProxies;this.eachTargetAxis(function(e,n,i,r){var o=this.dependentModels[e.axis][n],a=o.__dzAxisProxy||(o.__dzAxisProxy=new Lb(e.name,n,this,r));t[e.name+"_"+n]=a},this)},_resetTarget:function(){var t=this.option,e=this._judgeAutoMode();zb(function(e){var n=e.axisIndex;t[n]=xn(t[n])},this),"axisIndex"===e?this._autoSetAxisIndex():"orient"===e&&this._autoSetOrient()},_judgeAutoMode:function(){var t=this.option,e=!1;zb(function(n){null!=t[n.axisIndex]&&(e=!0)},this);var n=t.orient;return null==n&&e?"orient":e?void 0:(null==n&&(t.orient="horizontal"),"axisIndex")},_autoSetAxisIndex:function(){var t=!0,e=this.get("orient",!0),n=this.option,i=this.dependentModels;if(t){var r="vertical"===e?"y":"x";i[r+"Axis"].length?(n[r+"AxisIndex"]=[0],t=!1):Ob(i.singleAxis,function(i){t&&i.get("orient",!0)===e&&(n.singleAxisIndex=[i.componentIndex],t=!1)})}t&&zb(function(e){if(t){var i=[],r=this.dependentModels[e.axis];if(r.length&&!i.length)for(var o=0,a=r.length;o0?100:20}},getFirstTargetAxisModel:function(){var t;return zb(function(e){if(null==t){var n=this.get(e.axisIndex);n.length&&(t=this.dependentModels[e.axis][n[0]])}},this),t},eachTargetAxis:function(t,e){var n=this.ecModel;zb(function(i){Ob(this.get(i.axisIndex),function(r){t.call(e,i,r,this,n)},this)},this)},getAxisProxy:function(t,e){return this._axisProxies[t+"_"+e]},getAxisModel:function(t,e){var n=this.getAxisProxy(t,e);return n&&n.getAxisModel()},setRawRange:function(t,e){var n=this.option;Ob([["start","startValue"],["end","endValue"]],function(e){null==t[e[0]]&&null==t[e[1]]||(n[e[0]]=t[e[0]],n[e[1]]=t[e[1]])},this),!e&&fc(this,t)},getPercentRange:function(){var t=this.findRepresentativeAxisProxy();if(t)return t.getDataPercentWindow()},getValueRange:function(t,e){if(null!=t||null!=e)return this.getAxisProxy(t,e).getDataValueWindow();var n=this.findRepresentativeAxisProxy();return n?n.getDataValueWindow():void 0},findRepresentativeAxisProxy:function(t){if(t)return t.__dzAxisProxy;var e=this._axisProxies;for(var n in e)if(e.hasOwnProperty(n)&&e[n].hostedBy(this))return e[n];for(var n in e)if(e.hasOwnProperty(n)&&!e[n].hostedBy(this))return e[n]},getRangePropMode:function(){return this._rangePropMode.slice()}}),Rb=Ly.extend({type:"dataZoom",render:function(t,e,n,i){this.dataZoomModel=t,this.ecModel=e,this.api=n},getTargetCoordInfo:function(){function t(t,e,n,i){for(var r,o=0;oo&&(e[1-i]=e[i]+u.sign*o),e}),Bb=lv,Vb=yr,Fb=wr,Gb=m,Hb=d,Wb="horizontal",Zb=5,Ub=["line","bar","candlestick","scatter"],Xb=Rb.extend({type:"dataZoom.slider",init:function(t,e){this._displayables={},this._orient,this._range,this._handleEnds,this._size,this._handleWidth,this._handleHeight,this._location,this._dragging,this._dataShadowInfo,this.api=e},render:function(t,e,n,i){Xb.superApply(this,"render",arguments),sa(this,"_dispatchZoomAction",this.dataZoomModel.get("throttle"),"fixRate"),this._orient=t.get("orient"),!1!==this.dataZoomModel.get("show")?(i&&"dataZoom"===i.type&&i.from===this.uid||this._buildView(),this._updateView()):this.group.removeAll()},remove:function(){Xb.superApply(this,"remove",arguments),la(this,"_dispatchZoomAction")},dispose:function(){Xb.superApply(this,"dispose",arguments),la(this,"_dispatchZoomAction")},_buildView:function(){var t=this.group;t.removeAll(),this._resetLocation(),this._resetInterval();var e=this._displayables.barGroup=new Xp;this._renderBackground(),this._renderHandle(),this._renderDataShadow(),t.add(e),this._positionGroup()},_resetLocation:function(){var t=this.dataZoomModel,e=this.api,n=this._findCoordRect(),i={width:e.getWidth(),height:e.getHeight()},r=this._orient===Wb?{right:i.width-n.x-n.width,top:i.height-30-7,width:n.width,height:30}:{right:7,top:n.y,width:30,height:n.height},o=Wr(t.option);d(["right","top","width","height"],function(t){"ph"===o[t]&&(o[t]=r[t])});var a=Fr(o,i,t.padding);this._location={x:a.x,y:a.y},this._size=[a.width,a.height],"vertical"===this._orient&&this._size.reverse()},_positionGroup:function(){var t=this.group,e=this._location,n=this._orient,i=this.dataZoomModel.getFirstTargetAxisModel(),r=i&&i.get("inverse"),o=this._displayables.barGroup,a=(this._dataShadowInfo||{}).otherAxisInverse;o.attr(n!==Wb||r?n===Wb&&r?{scale:a?[-1,1]:[-1,-1]}:"vertical"!==n||r?{scale:a?[-1,-1]:[-1,1],rotation:Math.PI/2}:{scale:a?[1,-1]:[1,1],rotation:Math.PI/2}:{scale:a?[1,1]:[1,-1]});var s=t.getBoundingRect([o]);t.attr("position",[e.x-s.x,e.y-s.y])},_getViewExtent:function(){return[0,this._size[0]]},_renderBackground:function(){var t=this.dataZoomModel,e=this._size,n=this._displayables.barGroup;n.add(new Bb({silent:!0,shape:{x:0,y:0,width:e[0],height:e[1]},style:{fill:t.get("backgroundColor")},z2:-40})),n.add(new Bb({shape:{x:0,y:0,width:e[0],height:e[1]},style:{fill:"transparent"},z2:0,onclick:m(this._onClickPanelClick,this)}))},_renderDataShadow:function(){var t=this._dataShadowInfo=this._prepareDataShadowInfo();if(t){var e=this._size,n=t.series,i=n.getRawData(),r=n.getShadowDim?n.getShadowDim():t.otherDim;if(null!=r){var o=i.getDataExtent(r),s=.3*(o[1]-o[0]);o=[o[0]-s,o[1]+s];var l,h=[0,e[1]],u=[0,e[0]],c=[[e[0],0],[0,0]],d=[],f=u[1]/(i.count()-1),p=0,g=Math.round(i.count()/e[0]);i.each([r],function(t,e){if(g>0&&e%g)p+=f;else{var n=null==t||isNaN(t)||""===t,i=n?0:Vb(t,o,h,!0);n&&!l&&e?(c.push([c[c.length-1][0],0]),d.push([d[d.length-1][0],0])):!n&&l&&(c.push([p,0]),d.push([p,0])),c.push([p,i]),d.push([p,i]),p+=f,l=n}});var m=this.dataZoomModel;this._displayables.barGroup.add(new av({shape:{points:c},style:a({fill:m.get("dataBackgroundColor")},m.getModel("dataBackground.areaStyle").getAreaStyle()),silent:!0,z2:-20})),this._displayables.barGroup.add(new sv({shape:{points:d},style:m.getModel("dataBackground.lineStyle").getLineStyle(),silent:!0,z2:-19}))}}},_prepareDataShadowInfo:function(){var t=this.dataZoomModel,e=t.get("showDataShadow");if(!1!==e){var n,i=this.ecModel;return t.eachTargetAxis(function(r,o){d(t.getAxisProxy(r.name,o).getTargetSeriesModels(),function(t){if(!(n||!0!==e&&l(Ub,t.get("type"))<0)){var a,s=i.getComponent(r.axis,o).axis,h=mc(r.name),u=t.coordinateSystem;null!=h&&u.getOtherAxis&&(a=u.getOtherAxis(s).inverse),h=t.getData().mapDimension(h),n={thisAxis:s,series:t,thisDim:r.name,otherDim:h,otherAxisInverse:a}}},this)},this),n}},_renderHandle:function(){var t=this._displayables,e=t.handles=[],n=t.handleLabels=[],i=this._displayables.barGroup,r=this._size,o=this.dataZoomModel;i.add(t.filler=new Bb({draggable:!0,cursor:vc(this._orient),drift:Gb(this._onDragMove,this,"all"),onmousemove:function(t){bg(t.event)},ondragstart:Gb(this._showDataInfo,this,!0),ondragend:Gb(this._onDragEnd,this),onmouseover:Gb(this._showDataInfo,this,!0),onmouseout:Gb(this._showDataInfo,this,!1),style:{fill:o.get("fillerColor"),textPosition:"inside"}})),i.add(new Bb(zi({silent:!0,shape:{x:0,y:0,width:r[0],height:r[1]},style:{stroke:o.get("dataBackgroundColor")||o.get("borderColor"),lineWidth:1,fill:"rgba(0,0,0,0)"}}))),Hb([0,1],function(t){var r=dr(o.get("handleIcon"),{cursor:vc(this._orient),draggable:!0,drift:Gb(this._onDragMove,this,t),onmousemove:function(t){bg(t.event)},ondragend:Gb(this._onDragEnd,this),onmouseover:Gb(this._showDataInfo,this,!0),onmouseout:Gb(this._showDataInfo,this,!1)},{x:-1,y:0,width:2,height:2}),a=r.getBoundingRect();this._handleHeight=xr(o.get("handleSize"),this._size[1]),this._handleWidth=a.width/a.height*this._handleHeight,r.setStyle(o.getModel("handleStyle").getItemStyle());var s=o.get("handleColor");null!=s&&(r.style.fill=s),i.add(e[t]=r);var l=o.textStyleModel;this.group.add(n[t]=new Qm({silent:!0,invisible:!0,style:{x:0,y:0,text:"",textVerticalAlign:"middle",textAlign:"center",textFill:l.getTextColor(),textFont:l.getFont()},z2:10}))},this)},_resetInterval:function(){var t=this._range=this.dataZoomModel.getPercentRange(),e=this._getViewExtent();this._handleEnds=[Vb(t[0],[0,100],e,!0),Vb(t[1],[0,100],e,!0)]},_updateInterval:function(t,e){var n=this.dataZoomModel,i=this._handleEnds,r=this._getViewExtent(),o=n.findRepresentativeAxisProxy().getMinMaxSpan(),a=[0,100];Nb(e,i,r,n.get("zoomLock")?"all":t,null!=o.minSpan?Vb(o.minSpan,a,r,!0):null,null!=o.maxSpan?Vb(o.maxSpan,a,r,!0):null),this._range=Fb([Vb(i[0],r,a,!0),Vb(i[1],r,a,!0)])},_updateView:function(t){var e=this._displayables,n=this._handleEnds,i=Fb(n.slice()),r=this._size;Hb([0,1],function(t){var i=e.handles[t],o=this._handleHeight;i.attr({scale:[o/2,o/2],position:[n[t],r[1]/2-o/2]})},this),e.filler.setShape({x:i[0],y:0,width:i[1]-i[0],height:r[1]}),this._updateDataInfo(t)},_updateDataInfo:function(t){function e(t){var e=sr(i.handles[t].parent,this.group),n=hr(0===t?"right":"left",e),s=this._handleWidth/2+Zb,l=lr([c[t]+(0===t?-s:s),this._size[1]/2],e);r[t].setStyle({x:l[0],y:l[1],textVerticalAlign:o===Wb?"middle":n,textAlign:o===Wb?n:"center",text:a[t]})}var n=this.dataZoomModel,i=this._displayables,r=i.handleLabels,o=this._orient,a=["",""];if(n.get("showDetail")){var s=n.findRepresentativeAxisProxy();if(s){var l=s.getAxisModel().axis,h=this._range,u=t?s.calculateDataWindow({start:h[0],end:h[1]}).valueWindow:s.getDataValueWindow();a=[this._formatLabel(u[0],l),this._formatLabel(u[1],l)]}}var c=Fb(this._handleEnds.slice());e.call(this,0),e.call(this,1)},_formatLabel:function(t,e){var n=this.dataZoomModel,i=n.get("labelFormatter"),r=n.get("labelPrecision");null!=r&&"auto"!==r||(r=e.getPixelPrecision());var o=null==t||isNaN(t)?"":"category"===e.type||"time"===e.type?e.scale.getLabel(Math.round(t)):t.toFixed(Math.min(r,20));return x(i)?i(t,o):_(i)?i.replace("{value}",o):o},_showDataInfo:function(t){t=this._dragging||t;var e=this._displayables.handleLabels;e[0].attr("invisible",!t),e[1].attr("invisible",!t)},_onDragMove:function(t,e,n){this._dragging=!0;var i=lr([e,n],this._displayables.barGroup.getLocalTransform(),!0);this._updateInterval(t,i[0]);var r=this.dataZoomModel.get("realtime");this._updateView(!r),r&&this._dispatchZoomAction()},_onDragEnd:function(){this._dragging=!1,this._showDataInfo(!1),!this.dataZoomModel.get("realtime")&&this._dispatchZoomAction()},_onClickPanelClick:function(t){var e=this._size,n=this._displayables.barGroup.transformCoordToLocal(t.offsetX,t.offsetY);if(!(n[0]<0||n[0]>e[0]||n[1]<0||n[1]>e[1])){var i=this._handleEnds,r=(i[0]+i[1])/2;this._updateInterval("all",n[0]-r),this._updateView(),this._dispatchZoomAction()}},_dispatchZoomAction:function(){var t=this._range;this.api.dispatchAction({type:"dataZoom",from:this.uid,dataZoomId:this.dataZoomModel.id,start:t[0],end:t[1]})},_findCoordRect:function(){var t;if(Hb(this.getTargetCoordInfo(),function(e){if(!t&&e.length){var n=e[0].model.coordinateSystem;t=n.getRect&&n.getRect()}}),!t){var e=this.api.getWidth(),n=this.api.getHeight();t={x:.2*e,y:.2*n,width:.6*e,height:.6*n}}return t}});Eb.extend({type:"dataZoom.inside",defaultOption:{disabled:!1,zoomLock:!1,zoomOnMouseWheel:!0,moveOnMouseMove:!0,preventDefaultMouseMove:!0}});var jb="\0_ec_interaction_mutex";Qa({type:"takeGlobalCursor",event:"globalCursorTaken",update:"update"},function(){}),u(bc,dp);var Yb=v,qb="\0_ec_dataZoom_roams",$b=m,Kb=Rb.extend({type:"dataZoom.inside",init:function(t,e){this._range},render:function(t,e,n,i){Kb.superApply(this,"render",arguments),Lc(i,t.id)&&(this._range=t.getPercentRange()),d(this.getTargetCoordInfo(),function(e,i){var r=f(e,function(t){return Oc(t.model)});d(e,function(e){var o=e.model,a=t.option;kc(n,{coordId:Oc(o),allCoordIds:r,containsPoint:function(t,e,n){return o.coordinateSystem.containPoint([e,n])},dataZoomId:t.id,throttleRate:t.get("throttle",!0),panGetRange:$b(this._onPan,this,e,i),zoomGetRange:$b(this._onZoom,this,e,i),zoomLock:a.zoomLock,disabled:a.disabled,roamControllerOpt:{zoomOnMouseWheel:a.zoomOnMouseWheel,moveOnMouseMove:a.moveOnMouseMove,preventDefaultMouseMove:a.preventDefaultMouseMove}})},this)},this)},dispose:function(){Pc(this.api,this.dataZoomModel.id),Kb.superApply(this,"dispose",arguments),this._range=null},_onPan:function(t,e,n,i,r,o,a,s,l){var h=this._range.slice(),u=t.axisModels[0];if(u){var c=Qb[e]([o,a],[s,l],u,n,t),d=c.signal*(h[1]-h[0])*c.pixel/c.pixelLength;return Nb(d,h,[0,100],"all"),this._range=h}},_onZoom:function(t,e,n,i,r,o){var a=this._range.slice(),s=t.axisModels[0];if(s){var l=Qb[e](null,[r,o],s,n,t),h=(l.signal>0?l.pixelStart+l.pixelLength-l.pixel:l.pixel-l.pixelStart)/l.pixelLength*(a[1]-a[0])+a[0];i=Math.max(1/i,0),a[0]=(a[0]-h)*i+h,a[1]=(a[1]-h)*i+h;var u=this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();return Nb(0,a,[0,100],0,u.minSpan,u.maxSpan),this._range=a}}}),Qb={grid:function(t,e,n,i,r){var o=n.axis,a={},s=r.model.coordinateSystem.getRect();return t=t||[0,0],"x"===o.dim?(a.pixel=e[0]-t[0],a.pixelLength=s.width,a.pixelStart=s.x,a.signal=o.inverse?1:-1):(a.pixel=e[1]-t[1],a.pixelLength=s.height,a.pixelStart=s.y,a.signal=o.inverse?-1:1),a},polar:function(t,e,n,i,r){var o=n.axis,a={},s=r.model.coordinateSystem,l=s.getRadiusAxis().getExtent(),h=s.getAngleAxis().getExtent();return t=t?s.pointToCoord(t):[0,0],e=s.pointToCoord(e),"radiusAxis"===n.mainType?(a.pixel=e[0]-t[0],a.pixelLength=l[1]-l[0],a.pixelStart=l[0],a.signal=o.inverse?1:-1):(a.pixel=e[1]-t[1],a.pixelLength=h[1]-h[0],a.pixelStart=h[0],a.signal=o.inverse?-1:1),a},singleAxis:function(t,e,n,i,r){var o=n.axis,a=r.model.coordinateSystem.getRect(),s={};return t=t||[0,0],"horizontal"===o.orient?(s.pixel=e[0]-t[0],s.pixelLength=a.width,s.pixelStart=a.x,s.signal=o.inverse?1:-1):(s.pixel=e[1]-t[1],s.pixelLength=a.height,s.pixelStart=a.y,s.signal=o.inverse?-1:1),s}};Ka({getTargetSeries:function(t){var e=R();return t.eachComponent("dataZoom",function(t){t.eachTargetAxis(function(t,n,i){d(i.getAxisProxy(t.name,n).getTargetSeriesModels(),function(t){e.set(t.uid,t)})})}),e},isOverallFilter:!0,overallReset:function(t,e){t.eachComponent("dataZoom",function(t){t.eachTargetAxis(function(t,n,i){i.getAxisProxy(t.name,n).reset(i,e)}),t.eachTargetAxis(function(t,n,i){i.getAxisProxy(t.name,n).filterData(i,e)})}),t.eachComponent("dataZoom",function(t){var e=t.findRepresentativeAxisProxy(),n=e.getDataPercentWindow(),i=e.getDataValueWindow();t.setRawRange({start:n[0],end:n[1],startValue:i[0],endValue:i[1]},!0)})}}),Qa("dataZoom",function(t,e){var n=sc(m(e.eachComponent,e,"dataZoom"),Db,function(t,e){return t.get(e.axisIndex)}),i=[];e.eachComponent({mainType:"dataZoom",query:t},function(t,e){i.push.apply(i,n(t).nodes)}),d(i,function(e,n){e.setRawRange({start:t.start,end:t.end,startValue:t.startValue,endValue:t.endValue})})});var Jb={},tS=is({type:"toolbox",layoutMode:{type:"box",ignoreSize:!0},mergeDefaultAndTheme:function(t){tS.superApply(this,"mergeDefaultAndTheme",arguments),d(this.option.feature,function(t,e){var n=Wc(e);n&&i(t,n.defaultOption)})},defaultOption:{show:!0,z:6,zlevel:0,orient:"horizontal",left:"right",top:"top",backgroundColor:"transparent",borderColor:"#ccc",borderRadius:0,borderWidth:0,padding:5,itemSize:15,itemGap:8,showTitle:!0,iconStyle:{borderColor:"#666",color:"none"},emphasis:{iconStyle:{borderColor:"#3E98C5"}}}});rs({type:"toolbox",render:function(t,e,n,i){function r(r,a){var s,c=u[r],d=u[a],f=new fr(l[c],t,t.ecModel);if(c&&!d){if(Zc(c))s={model:f,onclick:f.option.onclick,featureName:c};else{var p=Wc(c);if(!p)return;s=new p(f,e,n)}h[c]=s}else{if(!(s=h[d]))return;s.model=f,s.ecModel=e,s.api=n}c||!d?f.get("show")&&!s.unusable?(o(f,s,c),f.setIconStatus=function(t,e){var n=this.option,i=this.iconPaths;n.iconStatus=n.iconStatus||{},n.iconStatus[t]=e,i[t]&&i[t].trigger(e)},s.render&&s.render(f,e,n,i)):s.remove&&s.remove(e,n):s.dispose&&s.dispose(e,n)}function o(i,r,o){var l=i.getModel("iconStyle"),h=i.getModel("emphasis.iconStyle"),u=r.getIcons?r.getIcons():i.get("icon"),c=i.get("title")||{};if("string"==typeof u){var f=u,p=c;c={},(u={})[o]=f,c[o]=p}var g=i.iconPaths={};d(u,function(o,u){var d=dr(o,{},{x:-s/2,y:-s/2,width:s,height:s});d.setStyle(l.getItemStyle()),d.hoverStyle=h.getItemStyle(),Yi(d),t.get("showTitle")&&(d.__title=c[u],d.on("mouseover",function(){var t=h.getItemStyle();d.setStyle({text:c[u],textPosition:t.textPosition||"bottom",textFill:t.fill||t.stroke||"#000",textAlign:t.textAlign||"center"})}).on("mouseout",function(){d.setStyle({textFill:null})})),d.trigger(i.get("iconStatus."+u)||"normal"),a.add(d),d.on("click",m(r.onclick,r,e,n,u)),g[u]=d})}var a=this.group;if(a.removeAll(),t.get("show")){var s=+t.get("itemSize"),l=t.get("feature")||{},h=this._features||(this._features={}),u=[];d(l,function(t,e){u.push(e)}),new ls(this._featureNames||[],u).add(r).update(r).remove(v(r,null)).execute(),this._featureNames=u,xu(a,t,n),a.add(_u(a.getBoundingRect(),t)),a.eachChild(function(t){var e=t.__title,i=t.hoverStyle;if(i&&e){var r=ce(e,Te(i)),o=t.position[0]+a.position[0],l=!1;t.position[1]+a.position[1]+s+r.height>n.getHeight()&&(i.textPosition="top",l=!0);var h=l?-5-r.height:s+8;o+r.width/2>n.getWidth()?(i.textPosition=["100%",h],i.textAlign="right"):o-r.width/2<0&&(i.textPosition=[0,h],i.textAlign="left")}})}},updateView:function(t,e,n,i){d(this._features,function(t){t.updateView&&t.updateView(t.model,e,n,i)})},remove:function(t,e){d(this._features,function(n){n.remove&&n.remove(t,e)}),this.group.removeAll()},dispose:function(t,e){d(this._features,function(n){n.dispose&&n.dispose(t,e)})}});var eS=Hy.toolbox.saveAsImage;Uc.defaultOption={show:!0,icon:"M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0",title:eS.title,type:"png",name:"",excludeComponents:["toolbox"],pixelRatio:1,lang:eS.lang.slice()},Uc.prototype.unusable=!Zf.canvasSupported,Uc.prototype.onclick=function(t,e){var n=this.model,i=n.get("name")||t.get("title.0.text")||"echarts",r=document.createElement("a"),o=n.get("type",!0)||"png";r.download=i+"."+o,r.target="_blank";var a=e.getConnectedDataURL({type:o,backgroundColor:n.get("backgroundColor",!0)||t.get("backgroundColor")||"#fff",excludeComponents:n.get("excludeComponents"),pixelRatio:n.get("pixelRatio")});if(r.href=a,"function"!=typeof MouseEvent||Zf.browser.ie||Zf.browser.edge)if(window.navigator.msSaveOrOpenBlob){for(var s=atob(a.split(",")[1]),l=s.length,h=new Uint8Array(l);l--;)h[l]=s.charCodeAt(l);var u=new Blob([h]);window.navigator.msSaveOrOpenBlob(u,i+"."+o)}else{var c=n.get("lang"),d='';window.open().document.write(d)}else{var f=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!1});r.dispatchEvent(f)}},Hc("saveAsImage",Uc);var nS=Hy.toolbox.magicType;Xc.defaultOption={show:!0,type:[],icon:{line:"M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4",bar:"M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7",stack:"M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z",tiled:"M2.3,2.2h22.8V25H2.3V2.2z M35,2.2h22.8V25H35V2.2zM2.3,35h22.8v22.8H2.3V35z M35,35h22.8v22.8H35V35z"},title:n(nS.title),option:{},seriesIndex:{}};var iS=Xc.prototype;iS.getIcons=function(){var t=this.model,e=t.get("icon"),n={};return d(t.get("type"),function(t){e[t]&&(n[t]=e[t])}),n};var rS={line:function(t,e,n,r){if("bar"===t)return i({id:e,type:"line",data:n.get("data"),stack:n.get("stack"),markPoint:n.get("markPoint"),markLine:n.get("markLine")},r.get("option.line")||{},!0)},bar:function(t,e,n,r){if("line"===t)return i({id:e,type:"bar",data:n.get("data"),stack:n.get("stack"),markPoint:n.get("markPoint"),markLine:n.get("markLine")},r.get("option.bar")||{},!0)},stack:function(t,e,n,r){if("line"===t||"bar"===t)return i({id:e,stack:"__ec_magicType_stack__"},r.get("option.stack")||{},!0)},tiled:function(t,e,n,r){if("line"===t||"bar"===t)return i({id:e,stack:""},r.get("option.tiled")||{},!0)}},oS=[["line","bar"],["stack","tiled"]];iS.onclick=function(t,e,n){var i=this.model,r=i.get("seriesIndex."+n);if(rS[n]){var o={series:[]};d(oS,function(t){l(t,n)>=0&&d(t,function(t){i.setIconStatus(t,"normal")})}),i.setIconStatus(n,"emphasis"),t.eachComponent({mainType:"series",query:null==r?null:{seriesIndex:r}},function(e){var r=e.subType,s=e.id,l=rS[n](r,s,e,i);l&&(a(l,e.option),o.series.push(l));var h=e.coordinateSystem;if(h&&"cartesian2d"===h.type&&("line"===n||"bar"===n)){var u=h.getAxesByScale("ordinal")[0];if(u){var c=u.dim+"Axis",d=t.queryComponents({mainType:c,index:e.get(name+"Index"),id:e.get(name+"Id")})[0].componentIndex;o[c]=o[c]||[];for(var f=0;f<=d;f++)o[c][d]=o[c][d]||{};o[c][d].boundaryGap="bar"===n}}}),e.dispatchAction({type:"changeMagicType",currentType:n,newOption:o})}},Qa({type:"changeMagicType",event:"magicTypeChanged",update:"prepareAndUpdate"},function(t,e){e.mergeOption(t.newOption)}),Hc("magicType",Xc);var aS=Hy.toolbox.dataView,sS=new Array(60).join("-"),lS="\t",hS=new RegExp("["+lS+"]+","g");nd.defaultOption={show:!0,readOnly:!1,optionToContent:null,contentToOption:null,icon:"M17.5,17.3H33 M17.5,17.3H33 M45.4,29.5h-28 M11.5,2v56H51V14.8L38.4,2H11.5z M38.4,2.2v12.7H51 M45.4,41.7h-28",title:n(aS.title),lang:n(aS.lang),backgroundColor:"#fff",textColor:"#000",textareaColor:"#fff",textareaBorderColor:"#333",buttonColor:"#c23531",buttonTextColor:"#fff"},nd.prototype.onclick=function(t,e){function n(){i.removeChild(o),x._dom=null}var i=e.getDom(),r=this.model;this._dom&&i.removeChild(this._dom);var o=document.createElement("div");o.style.cssText="position:absolute;left:5px;top:5px;bottom:5px;right:5px;",o.style.backgroundColor=r.get("backgroundColor")||"#fff";var a=document.createElement("h4"),s=r.get("lang")||[];a.innerHTML=s[0]||r.get("title"),a.style.cssText="margin: 10px 20px;",a.style.color=r.get("textColor");var l=document.createElement("div"),h=document.createElement("textarea");l.style.cssText="display:block;width:100%;overflow:auto;";var u=r.get("optionToContent"),c=r.get("contentToOption"),d=$c(t);if("function"==typeof u){var f=u(e.getOption());"string"==typeof f?l.innerHTML=f:M(f)&&l.appendChild(f)}else l.appendChild(h),h.readOnly=r.get("readOnly"),h.style.cssText="width:100%;height:100%;font-family:monospace;font-size:14px;line-height:1.6rem;",h.style.color=r.get("textColor"),h.style.borderColor=r.get("textareaBorderColor"),h.style.backgroundColor=r.get("textareaColor"),h.value=d.value;var p=d.meta,g=document.createElement("div");g.style.cssText="position:absolute;bottom:0;left:0;right:0;";var m="float:right;margin-right:20px;border:none;cursor:pointer;padding:2px 5px;font-size:12px;border-radius:3px",v=document.createElement("div"),y=document.createElement("div");m+=";background-color:"+r.get("buttonColor"),m+=";color:"+r.get("buttonTextColor");var x=this;on(v,"click",n),on(y,"click",function(){var t;try{t="function"==typeof c?c(l,e.getOption()):ed(h.value,p)}catch(t){throw n(),new Error("Data view format error "+t)}t&&e.dispatchAction({type:"changeDataView",newOption:t}),n()}),v.innerHTML=s[1],y.innerHTML=s[2],y.style.cssText=m,v.style.cssText=m,!r.get("readOnly")&&g.appendChild(y),g.appendChild(v),on(h,"keydown",function(t){if(9===(t.keyCode||t.which)){var e=this.value,n=this.selectionStart,i=this.selectionEnd;this.value=e.substring(0,n)+lS+e.substring(i),this.selectionStart=this.selectionEnd=n+1,bg(t)}}),o.appendChild(a),o.appendChild(l),o.appendChild(g),l.style.height=i.clientHeight-80+"px",i.appendChild(o),this._dom=o},nd.prototype.remove=function(t,e){this._dom&&e.getDom().removeChild(this._dom)},nd.prototype.dispose=function(t,e){this.remove(t,e)},Hc("dataView",nd),Qa({type:"changeDataView",event:"dataViewChanged",update:"prepareAndUpdate"},function(t,e){var n=[];d(t.newOption.series,function(t){var i=e.getSeriesByName(t.name)[0];if(i){var r=i.get("data");n.push({name:t.name,data:id(t.data,r)})}else n.push(o({type:"scatter"},t))}),e.mergeOption(a({series:n},t.newOption))});var uS=v,cS=d,dS=f,fS=Math.min,pS=Math.max,gS=Math.pow,mS=1e4,vS=6,yS=6,xS="globalPan",_S={w:[0,0],e:[0,1],n:[1,0],s:[1,1]},wS={w:"ew",e:"ew",n:"ns",s:"ns",ne:"nesw",sw:"nesw",nw:"nwse",se:"nwse"},bS={brushStyle:{lineWidth:2,stroke:"rgba(0,0,0,0.3)",fill:"rgba(0,0,0,0.1)"},transformable:!0,brushMode:"single",removeOnClick:!1},SS=0;rd.prototype={constructor:rd,enableBrush:function(t){return this._brushType&&ad(this),t.brushType&&od(this,t),this},setPanels:function(t){if(t&&t.length){var e=this._panels={};d(t,function(t){e[t.panelId]=n(t)})}else this._panels=null;return this},mount:function(t){t=t||{},this._enableGlobalPan=t.enableGlobalPan;var e=this.group;return this._zr.add(e),e.attr({position:t.position||[0,0],rotation:t.rotation||0,scale:t.scale||[1,1]}),this._transform=e.getLocalTransform(),this},eachCover:function(t,e){cS(this._covers,t,e)},updateCovers:function(t){function e(t,e){return(null!=t.id?t.id:o+e)+"-"+t.brushType}function r(e,n){var i=t[e];if(null!=n&&a[n]===h)s[e]=a[n];else{var r=s[e]=null!=n?(a[n].__brushOption=i,a[n]):ld(l,sd(l,i));cd(l,r)}}t=f(t,function(t){return i(n(bS),t,!0)});var o="\0-brush-index-",a=this._covers,s=this._covers=[],l=this,h=this._creatingCover;return new ls(a,t,function(t,n){return e(t.__brushOption,n)},e).add(r).update(r).remove(function(t){a[t]!==h&&l.group.remove(a[t])}).execute(),this},unmount:function(){return this.enableBrush(!1),gd(this),this._zr.remove(this.group),this},dispose:function(){this.unmount(),this.off()}},u(rd,dp);var MS={mousedown:function(t){if(this._dragging)Nd.call(this,t);else if(!t.target||!t.target.draggable){Od(t);var e=this.group.transformCoordToLocal(t.offsetX,t.offsetY);this._creatingCover=null,(this._creatingPanel=fd(this,t,e))&&(this._dragging=!0,this._track=[e.slice()])}},mousemove:function(t){var e=this.group.transformCoordToLocal(t.offsetX,t.offsetY);if(Ld(this,t,e),this._dragging){Od(t);var n=Ed(this,t,e,!1);n&&md(this,n)}},mouseup:Nd},IS={lineX:Bd(0),lineY:Bd(1),rect:{createCover:function(t,e){return xd(uS(Cd,function(t){return t},function(t){return t}),t,e,["w","e","n","s","se","sw","ne","nw"])},getCreatingRange:function(t){var e=yd(t);return Md(e[1][0],e[1][1],e[0][0],e[0][1])},updateCoverShape:function(t,e,n,i){_d(t,e,n,i)},updateCommon:wd,contain:zd},polygon:{createCover:function(t,e){var n=new Xp;return n.add(new sv({name:"main",style:Sd(e),silent:!0})),n},getCreatingRange:function(t){return t},endCreating:function(t,e){e.remove(e.childAt(0)),e.add(new av({name:"main",draggable:!0,drift:uS(Ad,t,e),ondragend:uS(md,t,{isEnd:!0})}))},updateCoverShape:function(t,e,n,i){e.childAt(0).setShape({points:kd(t,e,n)})},updateCommon:wd,contain:zd}},TS={axisPointer:1,tooltip:1,brush:1},CS=d,AS=l,DS=v,kS=["dataToPoint","pointToData"],PS=["grid","xAxis","yAxis","geo","graph","polar","radiusAxis","angleAxis","bmap"],LS=Zd.prototype;LS.setOutputRanges=function(t,e){this.matchOutputRanges(t,e,function(t,e,n){if((t.coordRanges||(t.coordRanges=[])).push(e),!t.coordRange){t.coordRange=e;var i=RS[t.brushType](0,n,e);t.__rangeOffset={offset:NS[t.brushType](i.values,t.range,[1,1]),xyMinMax:i.xyMinMax}}})},LS.matchOutputRanges=function(t,e,n){CS(t,function(t){var i=this.findTargetInfo(t,e);i&&!0!==i&&d(i.coordSyses,function(i){var r=RS[t.brushType](1,i,t.range);n(t,r.values,i,e)})},this)},LS.setInputRanges=function(t,e){CS(t,function(t){var n=this.findTargetInfo(t,e);if(t.range=t.range||[],n&&!0!==n){t.panelId=n.panelId;var i=RS[t.brushType](0,n.coordSys,t.coordRange),r=t.__rangeOffset;t.range=r?NS[t.brushType](i.values,r.offset,qd(i.xyMinMax,r.xyMinMax)):i.values}},this)},LS.makePanelOpts=function(t,e){return f(this._targetInfoList,function(n){var i=n.getPanelRect();return{panelId:n.panelId,defaultBrushType:e&&e(n),clipPath:Fd(i),isTargetByCursor:Hd(i,t,n.coordSysModel),getLinearBrushOtherExtent:Gd(i)}})},LS.controlSeries=function(t,e,n){var i=this.findTargetInfo(t,n);return!0===i||i&&AS(i.coordSyses,e.coordinateSystem)>=0},LS.findTargetInfo=function(t,e){for(var n=this._targetInfoList,i=Xd(e,t),r=0;r=0||AS(i,t.getAxis("y").model)>=0)&&o.push(t)}),e.push({panelId:"grid--"+t.id,gridModel:t,coordSysModel:t,coordSys:o[0],coordSyses:o,getPanelRect:ES.grid,xAxisDeclared:a[t.id],yAxisDeclared:s[t.id]})}))},geo:function(t,e){CS(t.geoModels,function(t){var n=t.coordinateSystem;e.push({panelId:"geo--"+t.id,geoModel:t,coordSysModel:t,coordSys:n,coordSyses:[n],getPanelRect:ES.geo})})}},zS=[function(t,e){var n=t.xAxisModel,i=t.yAxisModel,r=t.gridModel;return!r&&n&&(r=n.axis.grid.model),!r&&i&&(r=i.axis.grid.model),r&&r===e.gridModel},function(t,e){var n=t.geoModel;return n&&n===e.geoModel}],ES={grid:function(){return this.coordSys.grid.getRect().clone()},geo:function(){var t=this.coordSys,e=t.getBoundingRect().clone();return e.applyTransform(sr(t)),e}},RS={lineX:DS(jd,0),lineY:DS(jd,1),rect:function(t,e,n){var i=e[kS[t]]([n[0][0],n[1][0]]),r=e[kS[t]]([n[0][1],n[1][1]]),o=[Ud([i[0],r[0]]),Ud([i[1],r[1]])];return{values:o,xyMinMax:o}},polygon:function(t,e,n){var i=[[1/0,-1/0],[1/0,-1/0]];return{values:f(n,function(n){var r=e[kS[t]](n);return i[0][0]=Math.min(i[0][0],r[0]),i[1][0]=Math.min(i[1][0],r[1]),i[0][1]=Math.max(i[0][1],r[0]),i[1][1]=Math.max(i[1][1],r[1]),r}),xyMinMax:i}}},NS={lineX:DS(Yd,0),lineY:DS(Yd,1),rect:function(t,e,n){return[[t[0][0]-n[0]*e[0][0],t[0][1]-n[0]*e[0][1]],[t[1][0]-n[1]*e[1][0],t[1][1]-n[1]*e[1][1]]]},polygon:function(t,e,n){return f(t,function(t,i){return[t[0]-n[0]*e[i][0],t[1]-n[1]*e[i][1]]})}},BS=d,VS="\0_ec_hist_store";Eb.extend({type:"dataZoom.select"}),Rb.extend({type:"dataZoom.select"});var FS=Hy.toolbox.dataZoom,GS=d,HS="\0_ec_\0toolbox-dataZoom_";nf.defaultOption={show:!0,icon:{zoom:"M0,13.5h26.9 M13.5,26.9V0 M32.1,13.5H58V58H13.5 V32.1",back:"M22,1.4L9.9,13.5l12.3,12.3 M10.3,13.5H54.9v44.6 H10.3v-26"},title:n(FS.title)};var WS=nf.prototype;WS.render=function(t,e,n,i){this.model=t,this.ecModel=e,this.api=n,af(t,e,this,i,n),of(t,e)},WS.onclick=function(t,e,n){ZS[n].call(this)},WS.remove=function(t,e){this._brushController.unmount()},WS.dispose=function(t,e){this._brushController.dispose()};var ZS={zoom:function(){var t=!this._isZoomActive;this.api.dispatchAction({type:"takeGlobalCursor",key:"dataZoomSelect",dataZoomSelectActive:t})},back:function(){this._dispatchZoomAction(Qd(this.ecModel))}};WS._onBrush=function(t,e){function n(t,e,n){var a=e.getAxis(t),s=a.model,l=i(t,s,o),h=l.findRepresentativeAxisProxy(s).getMinMaxSpan();null==h.minValueSpan&&null==h.maxValueSpan||(n=Nb(0,n.slice(),a.scale.getExtent(),0,h.minValueSpan,h.maxValueSpan)),l&&(r[l.id]={dataZoomId:l.id,startValue:n[0],endValue:n[1]})}function i(t,e,n){var i;return n.eachComponent({mainType:"dataZoom",subType:"select"},function(n){n.getAxisModel(t,e.componentIndex)&&(i=n)}),i}if(e.isEnd&&t.length){var r={},o=this.ecModel;this._brushController.updateCovers([]),new Zd(rf(this.model.option),o,{include:["grid"]}).matchOutputRanges(t,o,function(t,e,i){if("cartesian2d"===i.type){var r=t.brushType;"rect"===r?(n("x",i,e[0]),n("y",i,e[1])):n({lineX:"x",lineY:"y"}[r],i,e)}}),Kd(o,r),this._dispatchZoomAction(r)}},WS._dispatchZoomAction=function(t){var e=[];GS(t,function(t,i){e.push(n(t))}),e.length&&this.api.dispatchAction({type:"dataZoom",from:this.uid,batch:e})},Hc("dataZoom",nf),$a(function(t){function e(t,e){if(e){var r=t+"Index",o=e[r];null==o||"all"==o||y(o)||(o=!1===o||"none"===o?[]:[o]),n(t,function(e,n){if(null==o||"all"==o||-1!==l(o,n)){var a={type:"select",$fromToolbox:!0,id:HS+t+n};a[r]=n,i.push(a)}})}}function n(e,n){var i=t[e];y(i)||(i=i?[i]:[]),GS(i,n)}if(t){var i=t.dataZoom||(t.dataZoom=[]);y(i)||(t.dataZoom=i=[i]);var r=t.toolbox;if(r&&(y(r)&&(r=r[0]),r&&r.feature)){var o=r.feature.dataZoom;e("xAxis",o),e("yAxis",o)}}});var US=Hy.toolbox.restore;sf.defaultOption={show:!0,icon:"M3.8,33.4 M47,18.9h9.8V8.7 M56.3,20.1 C52.1,9,40.5,0.6,26.8,2.1C12.6,3.7,1.6,16.2,2.1,30.6 M13,41.1H3.1v10.2 M3.7,39.9c4.2,11.1,15.8,19.5,29.5,18 c14.2-1.6,25.2-14.1,24.7-28.5",title:US.title},sf.prototype.onclick=function(t,e,n){Jd(t),e.dispatchAction({type:"restore",from:this.uid})},Hc("restore",sf),Qa({type:"restore",event:"restore",update:"prepareAndUpdate"},function(t,e){e.resetOption("recreate")});var XS,jS="urn:schemas-microsoft-com:vml",YS="undefined"==typeof window?null:window,qS=!1,$S=YS&&YS.document;if($S&&!Zf.canvasSupported)try{!$S.namespaces.zrvml&&$S.namespaces.add("zrvml",jS),XS=function(t){return $S.createElement("')}}catch(t){XS=function(t){return $S.createElement("<"+t+' xmlns="'+jS+'" class="zrvml">')}}var KS=Am.CMD,QS=Math.round,JS=Math.sqrt,tM=Math.abs,eM=Math.cos,nM=Math.sin,iM=Math.max;if(!Zf.canvasSupported){var rM=21600,oM=rM/2,aM=function(t){t.style.cssText="position:absolute;left:0;top:0;width:1px;height:1px;",t.coordsize=rM+","+rM,t.coordorigin="0,0"},sM=function(t){return String(t).replace(/&/g,"&").replace(/"/g,""")},lM=function(t,e,n){return"rgb("+[t,e,n].join(",")+")"},hM=function(t,e){e&&t&&e.parentNode!==t&&t.appendChild(e)},uM=function(t,e){e&&t&&e.parentNode===t&&t.removeChild(e)},cM=function(t,e,n){return 1e5*(parseFloat(t)||0)+1e3*(parseFloat(e)||0)+n},dM=function(t,e){return"string"==typeof t?t.lastIndexOf("%")>=0?parseFloat(t)/100*e:parseFloat(t):t},fM=function(t,e,n){var i=Mt(e);n=+n,isNaN(n)&&(n=1),i&&(t.color=lM(i[0],i[1],i[2]),t.opacity=n*i[3])},pM=function(t){var e=Mt(t);return[lM(e[0],e[1],e[2]),e[3]]},gM=function(t,e,n){var i=e.fill;if(null!=i)if(i instanceof pv){var r,o=0,a=[0,0],s=0,l=1,h=n.getBoundingRect(),u=h.width,c=h.height;if("linear"===i.type){r="gradient";var d=n.transform,f=[i.x*u,i.y*c],p=[i.x2*u,i.y2*c];d&&($(f,f,d),$(p,p,d));var g=p[0]-f[0],m=p[1]-f[1];(o=180*Math.atan2(g,m)/Math.PI)<0&&(o+=360),o<1e-6&&(o=0)}else{r="gradientradial";var f=[i.x*u,i.y*c],d=n.transform,v=n.scale,y=u,x=c;a=[(f[0]-h.x)/y,(f[1]-h.y)/x],d&&$(f,f,d),y/=v[0]*rM,x/=v[1]*rM;var _=iM(y,x);s=0/_,l=2*i.r/_-s}var w=i.colorStops.slice();w.sort(function(t,e){return t.offset-e.offset});for(var b=w.length,S=[],M=[],I=0;I=2){var A=S[0][0],D=S[1][0],k=S[0][1]*e.opacity,P=S[1][1]*e.opacity;t.type=r,t.method="none",t.focus="100%",t.angle=o,t.color=A,t.color2=D,t.colors=M.join(","),t.opacity=P,t.opacity2=k}"radial"===r&&(t.focusposition=a.join(","))}else fM(t,i,e.opacity)},mM=function(t,e){null!=e.lineDash&&(t.dashstyle=e.lineDash.join(" ")),null==e.stroke||e.stroke instanceof pv||fM(t,e.stroke,e.opacity)},vM=function(t,e,n,i){var r="fill"==e,o=t.getElementsByTagName(e)[0];null!=n[e]&&"none"!==n[e]&&(r||!r&&n.lineWidth)?(t[r?"filled":"stroked"]="true",n[e]instanceof pv&&uM(t,o),o||(o=lf(e)),r?gM(o,n,i):mM(o,n),hM(t,o)):(t[r?"filled":"stroked"]="false",uM(t,o))},yM=[[],[],[]],xM=function(t,e){var n,i,r,o,a,s,l=KS.M,h=KS.C,u=KS.L,c=KS.A,d=KS.Q,f=[],p=t.data,g=t.len();for(o=0;o.01?O&&(z+=.0125):Math.abs(E-A)<1e-4?O&&zC?x-=.0125:x+=.0125:O&&EA?y+=.0125:y-=.0125),f.push(R,QS(((C-D)*M+b)*rM-oM),",",QS(((A-k)*I+S)*rM-oM),",",QS(((C+D)*M+b)*rM-oM),",",QS(((A+k)*I+S)*rM-oM),",",QS((z*M+b)*rM-oM),",",QS((E*I+S)*rM-oM),",",QS((y*M+b)*rM-oM),",",QS((x*I+S)*rM-oM)),a=y,s=x;break;case KS.R:var N=yM[0],B=yM[1];N[0]=p[o++],N[1]=p[o++],B[0]=N[0]+p[o++],B[1]=N[1]+p[o++],e&&($(N,N,e),$(B,B,e)),N[0]=QS(N[0]*rM-oM),B[0]=QS(B[0]*rM-oM),N[1]=QS(N[1]*rM-oM),B[1]=QS(B[1]*rM-oM),f.push(" m ",N[0],",",N[1]," l ",B[0],",",N[1]," l ",B[0],",",B[1]," l ",N[0],",",B[1]);break;case KS.Z:f.push(" x ")}if(n>0){f.push(i);for(var V=0;V100&&(SM=0,bM={});var n,i=MM.style;try{i.font=t,n=i.fontFamily.split(",")[0]}catch(t){}e={style:i.fontStyle||"normal",variant:i.fontVariant||"normal",weight:i.fontWeight||"normal",size:0|parseFloat(i.fontSize||12),family:n||"Microsoft YaHei"},bM[t]=e,SM++}return e};!function(t,e){dg[t]=e}("measureText",function(t,e){var n=$S;wM||((wM=n.createElement("div")).style.cssText="position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;",$S.body.appendChild(wM));try{wM.style.font=e}catch(t){}return wM.innerHTML="",wM.appendChild(n.createTextNode(t)),{width:wM.offsetWidth}});for(var TM=new Xt,CM=[mg,Xe,je,yi,Qm],AM=0;AM=r&&h+1>=o){for(var u=[],c=0;c=r&&c+1>=o)return If(0,s.components);l[n]=s}else l[n]=void 0}a++}();if(d)return d}},pushComponent:function(t,e,n){var i=t[t.length-1];i&&i.added===e&&i.removed===n?t[t.length-1]={count:i.count+1,added:e,removed:n}:t.push({count:1,added:e,removed:n})},extractCommon:function(t,e,n,i){for(var r=e.length,o=n.length,a=t.newPos,s=a-i,l=0;a+1=0;--i)if(e[i]===t)return!0;return!1}),n):null:n[0]},Cf.prototype.update=function(t,e){if(t){var n=this.getDefs(!1);if(t[this._domName]&&n.contains(t[this._domName]))"function"==typeof e&&e(t);else{var i=this.add(t);i&&(t[this._domName]=i)}}},Cf.prototype.addDom=function(t){this.getDefs(!0).appendChild(t)},Cf.prototype.removeDom=function(t){var e=this.getDefs(!1);e&&t[this._domName]&&(e.removeChild(t[this._domName]),t[this._domName]=null)},Cf.prototype.getDoms=function(){var t=this.getDefs(!1);if(!t)return[];var e=[];return d(this._tagNames,function(n){var i=t.getElementsByTagName(n);e=e.concat([].slice.call(i))}),e},Cf.prototype.markAllUnused=function(){var t=this;d(this.getDoms(),function(e){e[t._markLabel]="0"})},Cf.prototype.markUsed=function(t){t&&(t[this._markLabel]="1")},Cf.prototype.removeUnused=function(){var t=this.getDefs(!1);if(t){var e=this;d(this.getDoms(),function(n){"1"!==n[e._markLabel]&&t.removeChild(n)})}},Cf.prototype.getSvgProxy=function(t){return t instanceof yi?GM:t instanceof je?HM:t instanceof Qm?WM:GM},Cf.prototype.getTextSvgElement=function(t){return t.__textSvgEl},Cf.prototype.getSvgElement=function(t){return t.__svgEl},h(Af,Cf),Af.prototype.addWithoutUpdate=function(t,e){if(e&&e.style){var n=this;d(["fill","stroke"],function(i){if(e.style[i]&&("linear"===e.style[i].type||"radial"===e.style[i].type)){var r,o=e.style[i],a=n.getDefs(!0);o._dom?(r=o._dom,a.contains(o._dom)||n.addDom(r)):r=n.add(o),n.markUsed(e);var s=r.getAttribute("id");t.setAttribute(i,"url(#"+s+")")}})}},Af.prototype.add=function(t){var e;if("linear"===t.type)e=this.createElement("linearGradient");else{if("radial"!==t.type)return Fp("Illegal gradient type."),null;e=this.createElement("radialGradient")}return t.id=t.id||this.nextId++,e.setAttribute("id","zr"+this._zrId+"-gradient-"+t.id),this.updateDom(t,e),this.addDom(e),e},Af.prototype.update=function(t){var e=this;Cf.prototype.update.call(this,t,function(){var n=t.type,i=t._dom.tagName;"linear"===n&&"linearGradient"===i||"radial"===n&&"radialGradient"===i?e.updateDom(t,t._dom):(e.removeDom(t),e.add(t))})},Af.prototype.updateDom=function(t,e){if("linear"===t.type)e.setAttribute("x1",t.x),e.setAttribute("y1",t.y),e.setAttribute("x2",t.x2),e.setAttribute("y2",t.y2);else{if("radial"!==t.type)return void Fp("Illegal gradient type.");e.setAttribute("cx",t.x),e.setAttribute("cy",t.y),e.setAttribute("r",t.r)}t.global?e.setAttribute("gradientUnits","userSpaceOnUse"):e.setAttribute("gradientUnits","objectBoundingBox"),e.innerHTML="";for(var n=t.colorStops,i=0,r=n.length;i0){var i,r,o=this.getDefs(!0),a=e[0],s=n?"_textDom":"_dom";a[s]?(r=a[s].getAttribute("id"),i=a[s],o.contains(i)||o.appendChild(i)):(r="zr"+this._zrId+"-clip-"+this.nextId,++this.nextId,(i=this.createElement("clipPath")).setAttribute("id",r),o.appendChild(i),a[s]=i);var l=this.getSvgProxy(a);if(a.transform&&a.parent.invTransform&&!n){var h=Array.prototype.slice.call(a.transform);st(a.transform,a.parent.invTransform,a.transform),l.brush(a),a.transform=h}else l.brush(a);var u=this.getSvgElement(a);i.innerHTML="",i.appendChild(u.cloneNode()),t.setAttribute("clip-path","url(#"+r+")"),e.length>1&&this.updateDom(i,e.slice(1),n)}else t&&t.setAttribute("clip-path","none")},Df.prototype.markUsed=function(t){var e=this;t.__clipPaths&&t.__clipPaths.length>0&&d(t.__clipPaths,function(t){t._dom&&Cf.prototype.markUsed.call(e,t._dom),t._textDom&&Cf.prototype.markUsed.call(e,t._textDom)})},h(kf,Cf),kf.prototype.addWithoutUpdate=function(t,e){if(e&&Pf(e.style)){var n,i=e.style;i._shadowDom?(n=i._shadowDom,this.getDefs(!0).contains(i._shadowDom)||this.addDom(n)):n=this.add(e),this.markUsed(e);var r=n.getAttribute("id");t.style.filter="url(#"+r+")"}},kf.prototype.add=function(t){var e=this.createElement("filter"),n=t.style;return n._shadowDomId=n._shadowDomId||this.nextId++,e.setAttribute("id","zr"+this._zrId+"-shadow-"+n._shadowDomId),this.updateDom(t,e),this.addDom(e),e},kf.prototype.update=function(t,e){var n=e.style;if(Pf(n)){var i=this;Cf.prototype.update.call(this,e,function(t){i.updateDom(e,t._shadowDom)})}else this.remove(t,n)},kf.prototype.remove=function(t,e){null!=e._shadowDomId&&(this.removeDom(e),t.style.filter="")},kf.prototype.updateDom=function(t,e){var n=e.getElementsByTagName("feDropShadow");n=0===n.length?this.createElement("feDropShadow"):n[0];var i,r,o,a,s=t.style,l=t.scale?t.scale[0]||1:1,h=t.scale?t.scale[1]||1:1;if(s.shadowBlur||s.shadowOffsetX||s.shadowOffsetY)i=s.shadowOffsetX||0,r=s.shadowOffsetY||0,o=s.shadowBlur,a=s.shadowColor;else{if(!s.textShadowBlur)return void this.removeDom(e,s);i=s.textShadowOffsetX||0,r=s.textShadowOffsetY||0,o=s.textShadowBlur,a=s.textShadowColor}n.setAttribute("dx",i/l),n.setAttribute("dy",r/h),n.setAttribute("flood-color",a);var u=o/2/l+" "+o/2/h;n.setAttribute("stdDeviation",u),e.setAttribute("x","-100%"),e.setAttribute("y","-100%"),e.setAttribute("width",Math.ceil(o/2*200)+"%"),e.setAttribute("height",Math.ceil(o/2*200)+"%"),e.appendChild(n),s._shadowDom=e},kf.prototype.markUsed=function(t){var e=t.style;e&&e._shadowDom&&Cf.prototype.markUsed.call(this,e._shadowDom)};var YM=function(t,e,n,i){this.root=t,this.storage=e,this._opts=n=o({},n||{});var r=ff("svg");r.setAttribute("xmlns","http://www.w3.org/2000/svg"),r.setAttribute("version","1.1"),r.setAttribute("baseProfile","full"),r.style.cssText="user-select:none;position:absolute;left:0;top:0;",this.gradientManager=new Af(i,r),this.clipPathManager=new Df(i,r),this.shadowManager=new kf(i,r);var a=document.createElement("div");a.style.cssText="overflow:hidden;position:relative",this._svgRoot=r,this._viewport=a,t.appendChild(a),a.appendChild(r),this.resize(n.width,n.height),this._visibleList=[]};YM.prototype={constructor:YM,getType:function(){return"svg"},getViewportRoot:function(){return this._viewport},getViewportRootOffset:function(){var t=this.getViewportRoot();if(t)return{offsetLeft:t.offsetLeft||0,offsetTop:t.offsetTop||0}},refresh:function(){var t=this.storage.getDisplayList(!0);this._paintList(t)},_paintList:function(t){this.gradientManager.markAllUnused(),this.clipPathManager.markAllUnused(),this.shadowManager.markAllUnused();var e,n=this._svgRoot,i=this._visibleList,r=t.length,o=[];for(e=0;e=0;--i)if(e[i]===t)return!0;return!1}),n):null:n[0]},resize:function(t,e){var n=this._viewport;n.style.display="none";var i=this._opts;if(null!=t&&(i.width=t),null!=e&&(i.height=e),t=this._getSize(0),e=this._getSize(1),n.style.display="",this._width!==t||this._height!==e){this._width=t,this._height=e;var r=n.style;r.width=t+"px",r.height=e+"px";var o=this._svgRoot;o.setAttribute("width",t),o.setAttribute("height",e)}},getWidth:function(){return this._width},getHeight:function(){return this._height},_getSize:function(t){var e=this._opts,n=["width","height"][t],i=["clientWidth","clientHeight"][t],r=["paddingLeft","paddingTop"][t],o=["paddingRight","paddingBottom"][t];if(null!=e[n]&&"auto"!==e[n])return parseFloat(e[n]);var a=this.root,s=document.defaultView.getComputedStyle(a);return(a[i]||Lf(s[n])||Lf(a.style[n]))-(Lf(s[r])||0)-(Lf(s[o])||0)|0},dispose:function(){this.root.innerHTML="",this._svgRoot=this._viewport=this.storage=null},clear:function(){this._viewport&&this.root.removeChild(this._viewport)},pathToSvg:function(){this.refresh();var t=this._svgRoot.outerHTML;return"data:img/svg+xml;utf-8,"+unescape(t)}},d(["getLayer","insertLayer","eachLayer","eachBuiltinLayer","eachOtherLayer","getLayers","modLayer","delLayer","clearLayer","toDataURL","pathToImage"],function(t){YM.prototype[t]=Ff(t)}),vn("svg",YM),t.version="4.0.2",t.dependencies=ox,t.PRIORITY=hx,t.init=function(t,e,n){var i=Ya(t);if(i)return i;var r=new Ta(t,e,n);return r.id="ec_"+Cx++,Ix[r.id]=r,kn(t,Dx,r.id),Xa(r),r},t.connect=function(t){if(y(t)){var e=t;t=null,ex(e,function(e){null!=e.group&&(t=e.group)}),t=t||"g_"+Ax++,ex(e,function(e){e.group=t})}return Tx[t]=!0,t},t.disConnect=ja,t.disconnect=Px,t.dispose=function(t){"string"==typeof t?t=Ix[t]:t instanceof Ta||(t=Ya(t)),t instanceof Ta&&!t.isDisposed()&&t.dispose()},t.getInstanceByDom=Ya,t.getInstanceById=function(t){return Ix[t]},t.registerTheme=qa,t.registerPreprocessor=$a,t.registerProcessor=Ka,t.registerPostUpdate=function(t){_x.push(t)},t.registerAction=Qa,t.registerCoordinateSystem=function(t,e){mo.register(t,e)},t.getCoordinateSystemDimensions=function(t){var e=mo.get(t);if(e)return e.getDimensionsInfo?e.getDimensionsInfo():e.dimensions.slice()},t.registerLayout=Ja,t.registerVisual=ts,t.registerLoading=ns,t.extendComponentModel=is,t.extendComponentView=rs,t.extendSeriesModel=os,t.extendChartView=as,t.setCanvasCreator=function(t){e("createCanvas",t)},t.registerMap=function(t,e,n){e.geoJson&&!e.features&&(n=e.specialAreas,e=e.geoJson),"string"==typeof e&&(e="undefined"!=typeof JSON&&JSON.parse?JSON.parse(e):new Function("return ("+e+");")()),kx[t]={geoJson:e,specialAreas:n}},t.getMap=function(t){return kx[t]},t.dataTool=Lx,t.zrender=Rg,t.graphic=bv,t.number=Lv,t.format=Vv,t.throttle=aa,t.helper=__,t.matrix=vp,t.vector=up,t.color=zp,t.parseGeoJSON=b_,t.parseGeoJson=T_,t.util=C_,t.List=Fx,t.Model=fr,t.Axis=I_,t.env=Zf}); diff --git a/web/resource/js/lib/hammer.min.js b/web/resource/js/lib/hammer.min.js new file mode 100644 index 0000000..edadee1 --- /dev/null +++ b/web/resource/js/lib/hammer.min.js @@ -0,0 +1,7 @@ +/*! Hammer.JS - v2.0.8 - 2016-04-23 + * http://hammerjs.github.io/ + * + * Copyright (c) 2016 Jorik Tangelder; + * Licensed under the MIT license */ +!function(a,b,c,d){"use strict";function e(a,b,c){return setTimeout(j(a,c),b)}function f(a,b,c){return Array.isArray(a)?(g(a,c[b],c),!0):!1}function g(a,b,c){var e;if(a)if(a.forEach)a.forEach(b,c);else if(a.length!==d)for(e=0;e\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",f=a.console&&(a.console.warn||a.console.log);return f&&f.call(a.console,e,d),b.apply(this,arguments)}}function i(a,b,c){var d,e=b.prototype;d=a.prototype=Object.create(e),d.constructor=a,d._super=e,c&&la(d,c)}function j(a,b){return function(){return a.apply(b,arguments)}}function k(a,b){return typeof a==oa?a.apply(b?b[0]||d:d,b):a}function l(a,b){return a===d?b:a}function m(a,b,c){g(q(b),function(b){a.addEventListener(b,c,!1)})}function n(a,b,c){g(q(b),function(b){a.removeEventListener(b,c,!1)})}function o(a,b){for(;a;){if(a==b)return!0;a=a.parentNode}return!1}function p(a,b){return a.indexOf(b)>-1}function q(a){return a.trim().split(/\s+/g)}function r(a,b,c){if(a.indexOf&&!c)return a.indexOf(b);for(var d=0;dc[b]}):d.sort()),d}function u(a,b){for(var c,e,f=b[0].toUpperCase()+b.slice(1),g=0;g1&&!c.firstMultiple?c.firstMultiple=D(b):1===e&&(c.firstMultiple=!1);var f=c.firstInput,g=c.firstMultiple,h=g?g.center:f.center,i=b.center=E(d);b.timeStamp=ra(),b.deltaTime=b.timeStamp-f.timeStamp,b.angle=I(h,i),b.distance=H(h,i),B(c,b),b.offsetDirection=G(b.deltaX,b.deltaY);var j=F(b.deltaTime,b.deltaX,b.deltaY);b.overallVelocityX=j.x,b.overallVelocityY=j.y,b.overallVelocity=qa(j.x)>qa(j.y)?j.x:j.y,b.scale=g?K(g.pointers,d):1,b.rotation=g?J(g.pointers,d):0,b.maxPointers=c.prevInput?b.pointers.length>c.prevInput.maxPointers?b.pointers.length:c.prevInput.maxPointers:b.pointers.length,C(c,b);var k=a.element;o(b.srcEvent.target,k)&&(k=b.srcEvent.target),b.target=k}function B(a,b){var c=b.center,d=a.offsetDelta||{},e=a.prevDelta||{},f=a.prevInput||{};b.eventType!==Ea&&f.eventType!==Ga||(e=a.prevDelta={x:f.deltaX||0,y:f.deltaY||0},d=a.offsetDelta={x:c.x,y:c.y}),b.deltaX=e.x+(c.x-d.x),b.deltaY=e.y+(c.y-d.y)}function C(a,b){var c,e,f,g,h=a.lastInterval||b,i=b.timeStamp-h.timeStamp;if(b.eventType!=Ha&&(i>Da||h.velocity===d)){var j=b.deltaX-h.deltaX,k=b.deltaY-h.deltaY,l=F(i,j,k);e=l.x,f=l.y,c=qa(l.x)>qa(l.y)?l.x:l.y,g=G(j,k),a.lastInterval=b}else c=h.velocity,e=h.velocityX,f=h.velocityY,g=h.direction;b.velocity=c,b.velocityX=e,b.velocityY=f,b.direction=g}function D(a){for(var b=[],c=0;ce;)c+=a[e].clientX,d+=a[e].clientY,e++;return{x:pa(c/b),y:pa(d/b)}}function F(a,b,c){return{x:b/a||0,y:c/a||0}}function G(a,b){return a===b?Ia:qa(a)>=qa(b)?0>a?Ja:Ka:0>b?La:Ma}function H(a,b,c){c||(c=Qa);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return Math.sqrt(d*d+e*e)}function I(a,b,c){c||(c=Qa);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return 180*Math.atan2(e,d)/Math.PI}function J(a,b){return I(b[1],b[0],Ra)+I(a[1],a[0],Ra)}function K(a,b){return H(b[0],b[1],Ra)/H(a[0],a[1],Ra)}function L(){this.evEl=Ta,this.evWin=Ua,this.pressed=!1,x.apply(this,arguments)}function M(){this.evEl=Xa,this.evWin=Ya,x.apply(this,arguments),this.store=this.manager.session.pointerEvents=[]}function N(){this.evTarget=$a,this.evWin=_a,this.started=!1,x.apply(this,arguments)}function O(a,b){var c=s(a.touches),d=s(a.changedTouches);return b&(Ga|Ha)&&(c=t(c.concat(d),"identifier",!0)),[c,d]}function P(){this.evTarget=bb,this.targetIds={},x.apply(this,arguments)}function Q(a,b){var c=s(a.touches),d=this.targetIds;if(b&(Ea|Fa)&&1===c.length)return d[c[0].identifier]=!0,[c,c];var e,f,g=s(a.changedTouches),h=[],i=this.target;if(f=c.filter(function(a){return o(a.target,i)}),b===Ea)for(e=0;e-1&&d.splice(a,1)};setTimeout(e,cb)}}function U(a){for(var b=a.srcEvent.clientX,c=a.srcEvent.clientY,d=0;d=f&&db>=g)return!0}return!1}function V(a,b){this.manager=a,this.set(b)}function W(a){if(p(a,jb))return jb;var b=p(a,kb),c=p(a,lb);return b&&c?jb:b||c?b?kb:lb:p(a,ib)?ib:hb}function X(){if(!fb)return!1;var b={},c=a.CSS&&a.CSS.supports;return["auto","manipulation","pan-y","pan-x","pan-x pan-y","none"].forEach(function(d){b[d]=c?a.CSS.supports("touch-action",d):!0}),b}function Y(a){this.options=la({},this.defaults,a||{}),this.id=v(),this.manager=null,this.options.enable=l(this.options.enable,!0),this.state=nb,this.simultaneous={},this.requireFail=[]}function Z(a){return a&sb?"cancel":a&qb?"end":a&pb?"move":a&ob?"start":""}function $(a){return a==Ma?"down":a==La?"up":a==Ja?"left":a==Ka?"right":""}function _(a,b){var c=b.manager;return c?c.get(a):a}function aa(){Y.apply(this,arguments)}function ba(){aa.apply(this,arguments),this.pX=null,this.pY=null}function ca(){aa.apply(this,arguments)}function da(){Y.apply(this,arguments),this._timer=null,this._input=null}function ea(){aa.apply(this,arguments)}function fa(){aa.apply(this,arguments)}function ga(){Y.apply(this,arguments),this.pTime=!1,this.pCenter=!1,this._timer=null,this._input=null,this.count=0}function ha(a,b){return b=b||{},b.recognizers=l(b.recognizers,ha.defaults.preset),new ia(a,b)}function ia(a,b){this.options=la({},ha.defaults,b||{}),this.options.inputTarget=this.options.inputTarget||a,this.handlers={},this.session={},this.recognizers=[],this.oldCssProps={},this.element=a,this.input=y(this),this.touchAction=new V(this,this.options.touchAction),ja(this,!0),g(this.options.recognizers,function(a){var b=this.add(new a[0](a[1]));a[2]&&b.recognizeWith(a[2]),a[3]&&b.requireFailure(a[3])},this)}function ja(a,b){var c=a.element;if(c.style){var d;g(a.options.cssProps,function(e,f){d=u(c.style,f),b?(a.oldCssProps[d]=c.style[d],c.style[d]=e):c.style[d]=a.oldCssProps[d]||""}),b||(a.oldCssProps={})}}function ka(a,c){var d=b.createEvent("Event");d.initEvent(a,!0,!0),d.gesture=c,c.target.dispatchEvent(d)}var la,ma=["","webkit","Moz","MS","ms","o"],na=b.createElement("div"),oa="function",pa=Math.round,qa=Math.abs,ra=Date.now;la="function"!=typeof Object.assign?function(a){if(a===d||null===a)throw new TypeError("Cannot convert undefined or null to object");for(var b=Object(a),c=1;ch&&(b.push(a),h=b.length-1):e&(Ga|Ha)&&(c=!0),0>h||(b[h]=a,this.callback(this.manager,e,{pointers:b,changedPointers:[a],pointerType:f,srcEvent:a}),c&&b.splice(h,1))}});var Za={touchstart:Ea,touchmove:Fa,touchend:Ga,touchcancel:Ha},$a="touchstart",_a="touchstart touchmove touchend touchcancel";i(N,x,{handler:function(a){var b=Za[a.type];if(b===Ea&&(this.started=!0),this.started){var c=O.call(this,a,b);b&(Ga|Ha)&&c[0].length-c[1].length===0&&(this.started=!1),this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:za,srcEvent:a})}}});var ab={touchstart:Ea,touchmove:Fa,touchend:Ga,touchcancel:Ha},bb="touchstart touchmove touchend touchcancel";i(P,x,{handler:function(a){var b=ab[a.type],c=Q.call(this,a,b);c&&this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:za,srcEvent:a})}});var cb=2500,db=25;i(R,x,{handler:function(a,b,c){var d=c.pointerType==za,e=c.pointerType==Ba;if(!(e&&c.sourceCapabilities&&c.sourceCapabilities.firesTouchEvents)){if(d)S.call(this,b,c);else if(e&&U.call(this,c))return;this.callback(a,b,c)}},destroy:function(){this.touch.destroy(),this.mouse.destroy()}});var eb=u(na.style,"touchAction"),fb=eb!==d,gb="compute",hb="auto",ib="manipulation",jb="none",kb="pan-x",lb="pan-y",mb=X();V.prototype={set:function(a){a==gb&&(a=this.compute()),fb&&this.manager.element.style&&mb[a]&&(this.manager.element.style[eb]=a),this.actions=a.toLowerCase().trim()},update:function(){this.set(this.manager.options.touchAction)},compute:function(){var a=[];return g(this.manager.recognizers,function(b){k(b.options.enable,[b])&&(a=a.concat(b.getTouchAction()))}),W(a.join(" "))},preventDefaults:function(a){var b=a.srcEvent,c=a.offsetDirection;if(this.manager.session.prevented)return void b.preventDefault();var d=this.actions,e=p(d,jb)&&!mb[jb],f=p(d,lb)&&!mb[lb],g=p(d,kb)&&!mb[kb];if(e){var h=1===a.pointers.length,i=a.distance<2,j=a.deltaTime<250;if(h&&i&&j)return}return g&&f?void 0:e||f&&c&Na||g&&c&Oa?this.preventSrc(b):void 0},preventSrc:function(a){this.manager.session.prevented=!0,a.preventDefault()}};var nb=1,ob=2,pb=4,qb=8,rb=qb,sb=16,tb=32;Y.prototype={defaults:{},set:function(a){return la(this.options,a),this.manager&&this.manager.touchAction.update(),this},recognizeWith:function(a){if(f(a,"recognizeWith",this))return this;var b=this.simultaneous;return a=_(a,this),b[a.id]||(b[a.id]=a,a.recognizeWith(this)),this},dropRecognizeWith:function(a){return f(a,"dropRecognizeWith",this)?this:(a=_(a,this),delete this.simultaneous[a.id],this)},requireFailure:function(a){if(f(a,"requireFailure",this))return this;var b=this.requireFail;return a=_(a,this),-1===r(b,a)&&(b.push(a),a.requireFailure(this)),this},dropRequireFailure:function(a){if(f(a,"dropRequireFailure",this))return this;a=_(a,this);var b=r(this.requireFail,a);return b>-1&&this.requireFail.splice(b,1),this},hasRequireFailures:function(){return this.requireFail.length>0},canRecognizeWith:function(a){return!!this.simultaneous[a.id]},emit:function(a){function b(b){c.manager.emit(b,a)}var c=this,d=this.state;qb>d&&b(c.options.event+Z(d)),b(c.options.event),a.additionalEvent&&b(a.additionalEvent),d>=qb&&b(c.options.event+Z(d))},tryEmit:function(a){return this.canEmit()?this.emit(a):void(this.state=tb)},canEmit:function(){for(var a=0;af?Ja:Ka,c=f!=this.pX,d=Math.abs(a.deltaX)):(e=0===g?Ia:0>g?La:Ma,c=g!=this.pY,d=Math.abs(a.deltaY))),a.direction=e,c&&d>b.threshold&&e&b.direction},attrTest:function(a){return aa.prototype.attrTest.call(this,a)&&(this.state&ob||!(this.state&ob)&&this.directionTest(a))},emit:function(a){this.pX=a.deltaX,this.pY=a.deltaY;var b=$(a.direction);b&&(a.additionalEvent=this.options.event+b),this._super.emit.call(this,a)}}),i(ca,aa,{defaults:{event:"pinch",threshold:0,pointers:2},getTouchAction:function(){return[jb]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.scale-1)>this.options.threshold||this.state&ob)},emit:function(a){if(1!==a.scale){var b=a.scale<1?"in":"out";a.additionalEvent=this.options.event+b}this._super.emit.call(this,a)}}),i(da,Y,{defaults:{event:"press",pointers:1,time:251,threshold:9},getTouchAction:function(){return[hb]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distanceb.time;if(this._input=a,!d||!c||a.eventType&(Ga|Ha)&&!f)this.reset();else if(a.eventType&Ea)this.reset(),this._timer=e(function(){this.state=rb,this.tryEmit()},b.time,this);else if(a.eventType&Ga)return rb;return tb},reset:function(){clearTimeout(this._timer)},emit:function(a){this.state===rb&&(a&&a.eventType&Ga?this.manager.emit(this.options.event+"up",a):(this._input.timeStamp=ra(),this.manager.emit(this.options.event,this._input)))}}),i(ea,aa,{defaults:{event:"rotate",threshold:0,pointers:2},getTouchAction:function(){return[jb]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.rotation)>this.options.threshold||this.state&ob)}}),i(fa,aa,{defaults:{event:"swipe",threshold:10,velocity:.3,direction:Na|Oa,pointers:1},getTouchAction:function(){return ba.prototype.getTouchAction.call(this)},attrTest:function(a){var b,c=this.options.direction;return c&(Na|Oa)?b=a.overallVelocity:c&Na?b=a.overallVelocityX:c&Oa&&(b=a.overallVelocityY),this._super.attrTest.call(this,a)&&c&a.offsetDirection&&a.distance>this.options.threshold&&a.maxPointers==this.options.pointers&&qa(b)>this.options.velocity&&a.eventType&Ga},emit:function(a){var b=$(a.offsetDirection);b&&this.manager.emit(this.options.event+b,a),this.manager.emit(this.options.event,a)}}),i(ga,Y,{defaults:{event:"tap",pointers:1,taps:1,interval:300,time:250,threshold:9,posThreshold:10},getTouchAction:function(){return[ib]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distancemodel('module'); +load()->model('extension'); + +$entry_module_name = safe_gpc_string($_GPC['module_name']) ? safe_gpc_string($_GPC['module_name']) : safe_gpc_string($_GPC['m']); +$entry = array( + 'module' => $entry_module_name, + 'do' => $_GPC['do'], + 'state' => $_GPC['state'], + 'direct' => $_GPC['direct'], +); +if (empty($entry['do'])) { + itoast('非法访问.', '', ''); +} + +$module = module_fetch($entry['module']); +if (empty($module)) { + itoast("访问非法, 没有操作权限. (module: {$entry['module']})", '', ''); +} +$_GPC['__entry'] = $entry['title']; +$_GPC['__state'] = $entry['state']; +$_GPC['state'] = $entry['state']; +$_GPC['m'] = $entry['module']; +$_GPC['do'] = $entry['do']; + +$_W['current_module'] = $module; + +if ('system_welcome' == $entry['entry'] || 'system_welcome' == $_GPC['module_type']) { + $_GPC['module_type'] = 'system_welcome'; + define('SYSTEM_WELCOME_MODULE', true); + $site = WeUtility::createModuleSystemWelcome($entry['module']); +} else { + $site = WeUtility::createModuleSite($entry['module']); +} + +define('IN_MODULE', $entry['module']); +if (!is_error($site)) { + if (ACCOUNT_MANAGE_NAME_OWNER == $_W['role']) { + $_W['role'] = ACCOUNT_MANAGE_NAME_MANAGER; + } + $sysmodule = module_system(); + if (in_array($m, $sysmodule)) { + $site_urls = $site->getTabUrls(); + } + + + $do_function = defined('SYSTEM_WELCOME_MODULE') ? 'doPage' : 'doWeb'; + $method = $do_function . ucfirst($entry['do']); + + exit($site->$method()); +} +itoast("访问的方法 {$method} 不存在.", referer(), 'error'); \ No newline at end of file diff --git a/web/source/user/edit.ctrl.php b/web/source/user/edit.ctrl.php new file mode 100644 index 0000000..4754681 --- /dev/null +++ b/web/source/user/edit.ctrl.php @@ -0,0 +1,45 @@ +model('user'); + +$dos = array('edit_base'); +$do = in_array($do, $dos) ? $do : 'edit_base'; + +$uid = intval($_GPC['uid']); +$user = user_single($uid); +if (empty($user)) { + if ($_W['isajax']) { + iajax(-1, '访问错误, 未找到该用户.'); + } + itoast('访问错误, 未找到该用户.', url('user/display'), 'error'); +} +if (USER_STATUS_NORMAL != $user['status']) { + if ($_W['isajax']) { + iajax(-1, '该用户未审核或者已被禁用,请先修改用户状态'); + } + itoast('该用户未审核或者已被禁用,请先修改用户状态', url('user/display'), 'info'); +} + +$profile = pdo_get('users_profile', array('uid' => $uid)); +if (!empty($profile)) { + $profile['avatar'] = tomedia($profile['avatar']); +} +if ('edit_base' == $do) { + $user['last_visit'] = date('Y-m-d H:i:s', $user['lastvisit']); + $user['joindate'] = date('Y-m-d H:i:s', $user['joindate']); + $user['endtype'] = 0 == $user['endtime'] ? 1 : 2; + $user['end'] = user_end_time($uid); + $user['end'] = 0 == $user['end'] ? '永久' : $user['end']; + $profile = user_detail_formate($profile); + + if ($_W['isajax']) { + iajax(0, array( + 'user' => $user, + 'profile' => $profile, + 'extra_fileds' => '' + )); + } + template('user/edit-base'); +} diff --git a/web/source/user/find-password.ctrl.php b/web/source/user/find-password.ctrl.php new file mode 100644 index 0000000..504a8c7 --- /dev/null +++ b/web/source/user/find-password.ctrl.php @@ -0,0 +1,64 @@ +model('user'); +load()->model('setting'); +load()->model('utility'); +$dos = array('valid_mobile', 'set_password', 'success'); +$do = in_array($do, $dos) ? $do : ''; + +$setting_sms_sign = setting_load('site_sms_sign'); +$find_password_sign = !empty($setting_sms_sign['site_sms_sign']['find_password']) ? $setting_sms_sign['site_sms_sign']['find_password'] : ''; + +if (!empty($do)) { + $mobile = safe_gpc_string($_GPC['receiver']); + $find_mobile = user_check_mobile($mobile); + if (is_error($find_mobile)) { + iajax($find_mobile['errno'], $find_mobile['message']); + } +} + +if ('valid_mobile' == $do) { + iajax(0, '手机号正确.'); +} + +if ('set_password' == $do) { + if ($_W['isajax'] && $_W['ispost']) { + $code = safe_gpc_string($_GPC['code']); + if (empty($code)) { + iajax(-1, '短信验证码不能为空'); + } + + $verify_res = utility_smscode_verify(0, $mobile, $code); + if (is_error($verify_res)) { + iajax($verify_res['errno'], $verify_res['message']); + } + + $password = safe_gpc_string($_GPC['password']); + $repassword = safe_gpc_string($_GPC['repassword']); + if (empty($password) || empty($repassword)) { + iajax(-1, '密码不能为空'); + } + + if ($password != $repassword) { + iajax(-1, '两次密码不一致'); + } + + $user_info = user_single($find_mobile['uid']); + $password = user_password($password, $find_mobile['uid']); + if ($password == $user_info['password']) { + iajax(-2, '密码未做更改'); + } + $result = pdo_update('users', array('password' => $password), array('uid' => $user_info['uid'])); + if ($result) { + iajax(0, '设置密码成功'); + } else { + iajax(-1, '密码设置失败!'); + } + } +} +template('user/find-password'); \ No newline at end of file diff --git a/web/source/utility/emulator.ctrl.php b/web/source/utility/emulator.ctrl.php new file mode 100644 index 0000000..8dc11f8 --- /dev/null +++ b/web/source/utility/emulator.ctrl.php @@ -0,0 +1,720 @@ + + +
    +
    + 模拟测试 +
    +
    +
    +
    + +
    + +
    + + +
    +
    +
    + +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    + +
    +
    +
    + +
    + +
    +
    + +
    + +
    +
    
    +						
    +
    +
    +
    +
    +
    + + + +
    + + + +
    +
    +
    +
    +
    + + + + + + \ No newline at end of file diff --git a/web/source/utility/file.ctrl.php b/web/source/utility/file.ctrl.php new file mode 100644 index 0000000..a8af791 --- /dev/null +++ b/web/source/utility/file.ctrl.php @@ -0,0 +1,895 @@ +func('file'); +load()->model('material'); +load()->model('attachment'); +load()->model('module'); + +if (!in_array($do, array('upload', 'fetch', 'browser', 'delete', 'image', 'module', 'video', 'voice', 'news', 'keyword', + 'networktowechat', 'networktolocal', 'towechat', 'tolocal', 'wechat_upload', + 'group_list', 'add_group', 'change_group', 'del_group', 'move_to_group', 'change_name', 'video_del'))) { + if ($_W['isajax']) { + iajax(-1, 'Access Denied'); + } + exit('Access Denied'); +} +$result = array( + 'error' => 1, + 'message' => '', + 'data' => '', +); + +error_reporting(0); +$type = $_GPC['upload_type']; +$type = in_array($type, array('image', 'audio', 'video')) ? $type : 'image'; +$option = array(); +$option = array_elements(array('uploadtype', 'dest_dir'), $_POST); +$option['width'] = intval($option['width']); +$module_name = empty($_GPC['module_name']) ? '' : safe_gpc_string(trim($_GPC['module_name'])); + +$dest_dir = $_GPC['dest_dir']; +if (preg_match('/^[a-zA-Z0-9_\/]{0,50}$/', $dest_dir)) { + $dest_dir = trim($dest_dir, '/'); + $pieces = explode('/', $dest_dir); + if (count($pieces) > 3) { + $dest_dir = ''; + } +} else { + $dest_dir = ''; +} +$module_upload_dir = ''; +if ('' != $dest_dir) { + $module_upload_dir = sha1($dest_dir); +} + +$setting = $_W['setting']['upload'][$type]; +$uniacid = intval($_W['uniacid']); + +if (isset($_GPC['uniacid'])) { + $requniacid = intval($_GPC['uniacid']); + if (!empty($module_name)) { + $modules = module_fetch($module_name); + if (!empty($modules) && (MODULE_SUPPORT_SYSTEMWELCOME == $modules['welcome_support'])) { + $requniacid = 0; + } + } + attachment_reset_uniacid($requniacid); + $uniacid = intval($_W['uniacid']); +} + +if ($uniacid == 0 && !empty($_W['isfounder'])) { + $setting['folder'] = "{$type}s/global/"; + if (!empty($dest_dir)) { + $setting['folder'] .= '' . $dest_dir . '/'; + } +} else { + $setting['folder'] = "{$type}s/{$uniacid}"; + if (empty($dest_dir)) { + $setting['folder'] .= '/' . date('Y/m/'); + } else { + $setting['folder'] .= '/' . $dest_dir . '/'; + } +} + +if ('fetch' == $do) { + $url = trim($_GPC['url']); + $resp = ihttp_get($url); + if (is_error($resp)) { + $result['message'] = '提取文件失败, 错误信息: ' . $resp['message']; + die(json_encode($result)); + } + if (200 != intval($resp['code'])) { + $result['message'] = '提取文件失败: 未找到该资源文件.'; + die(json_encode($result)); + } + $ext = ''; + if ('image' == $type) { + switch ($resp['headers']['Content-Type']) { + case 'application/x-jpg': + case 'image/jpeg': + $ext = 'jpg'; + break; + case 'image/png': + $ext = 'png'; + break; + case 'image/gif': + $ext = 'gif'; + break; + default: + $result['message'] = '提取资源失败, 资源文件类型错误.'; + die(json_encode($result)); + break; + } + } else { + $result['message'] = '提取资源失败, 仅支持图片提取.'; + die(json_encode($result)); + } + $size = intval($resp['headers']['Content-Length']); + if ($size > $setting['limit'] * 1024) { + $result['message'] = '上传的媒体文件过大(' . sizecount($size) . ' > ' . sizecount($setting['limit'] * 1024); + die(json_encode($result)); + } + $originname = pathinfo($url, PATHINFO_BASENAME); + $filename = file_random_name(ATTACHMENT_ROOT . '/' . $setting['folder'], $ext); + $pathname = $setting['folder'] . $filename; + $fullname = ATTACHMENT_ROOT . '/' . $pathname; + if (false == file_put_contents($fullname, $resp['content'])) { + $result['message'] = '提取失败.'; + die(json_encode($result)); + } +} + +if ('upload' == $do) { + + if (empty($_FILES['file']['name'])) { + $result['message'] = '上传失败, 请选择要上传的文件!'; + iajax(-1, $result['message']); + } + if ($_FILES['file']['error'] != 0) { + $result['message'] = '上传失败, 请重试.错误码:' . $_FILES['file']['error']; + iajax(-1, $result['message']); + } + $ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION); + $ext = strtolower($ext); + $size = intval($_FILES['file']['size']); + $originname = $_FILES['file']['name']; + $filename = file_random_name(ATTACHMENT_ROOT . '/' . $setting['folder'], $ext); + $zip_percentage = empty($_W['setting']['upload']['image']['zip_percentage']) ? false : true; + $file = file_upload($_FILES['file'], $type, $setting['folder'] . $filename, $zip_percentage); + + if (is_error($file)) { + $result['message'] = $file['message']; + iajax(-1, $result['message']); + } + $pathname = $file['path']; + $fullname = ATTACHMENT_ROOT . '/' . $pathname; + +} + +if ('fetch' == $do || 'upload' == $do) { + if ('image' == $type) { + $thumb = empty($setting['thumb']) || 'gif' == $ext ? 0 : 1; + $width = intval($setting['width']); + if (isset($option['thumb'])) { + $thumb = empty($option['thumb']) ? 0 : 1; + } + if ($thumb && $width <= 0) { + $width = 800; + } + if (isset($option['width']) && !empty($option['width'])) { + $width = intval($option['width']); + } + if (1 == $thumb && $width > 0) { + $thumbnail = file_image_thumb($fullname, '', $width); + @unlink($fullname); + if (is_error($thumbnail)) { + $result['message'] = $thumbnail['message']; + iajax(-1, $result); + } else { + $filename = pathinfo($thumbnail, PATHINFO_BASENAME); + $pathname = $thumbnail; + $fullname = ATTACHMENT_ROOT . '/' . $pathname; + } + } + } + $group_id = safe_gpc_int($_GPC['group_id']); + $module_info = table('modules')->getByName($module_name); + if (in_array($type, array('image', 'thumb')) && $group_id <= 0 && !empty($module_info)) { + $group_exist = table('core_attachment_group') + ->where(array('type' => 0, 'name' => $module_info['title'])) + ->searchWithUniacidOrUid($uniacid, $_W['uid']) + ->getcolumn('id'); + if (empty($group_exist)) { + table('core_attachment_group') + ->fill(array( + 'name' => $module_info['title'], + 'uniacid' => $uniacid, + 'uid' => $_W['uid'], + 'type' => 0 + )) + ->save(); + $group_id = pdo_insertid(); + } else { + $group_id = $group_exist; + } + } + $info = array( + 'name' => $originname, + 'ext' => $ext, + 'filename' => $pathname, + 'attachment' => $pathname, + 'url' => tomedia($pathname), + 'is_image' => 'image' == $type ? 1 : 0, + 'filesize' => filesize($fullname), + 'group_id' => $group_id, + ); + if ('image' == $type) { + $size = getimagesize($fullname); + $info['width'] = $size[0]; + $info['height'] = $size[1]; + } else { + $size = filesize($fullname); + $info['size'] = sizecount($size); + } + $uni_remote_setting = uni_setting_load('remote'); + if ($uniacid != 0 && !empty($uni_remote_setting['remote']['type'])) { + $_W['setting']['remote'] = $uni_remote_setting['remote']; + } + if ($uniacid == 0) { + $_W['setting']['remote'] = $_W['setting']['remote_complete_info']; + } + if (!empty($_W['setting']['remote']['type'])) { + $remotestatus = file_remote_upload($pathname); + if (is_error($remotestatus)) { + $result['message'] = '远程附件上传失败,请检查配置并重新上传'; + file_delete($pathname); + iajax(-1, $result['message']); + } else { + $info['url'] = tomedia($pathname); + } + } + pdo_insert('core_attachment', array( + 'uniacid' => $uniacid, + 'uid' => $_W['uid'], + 'filename' => safe_gpc_html(htmlspecialchars_decode($originname, ENT_QUOTES)), + 'attachment' => $pathname, + 'type' => 'image' == $type ? 1 : ('audio' == $type || 'voice' == $type ? 2 : 3), + 'createtime' => TIMESTAMP, + 'module_upload_dir' => $module_upload_dir, + 'group_id' => intval($_GPC['group_id']), + )); + if ($_W['isw7_request']) { + iajax(0, '上传成功!'); + } + $info['state'] = 'SUCCESS'; + die(json_encode($info)); +} + +if ('change_name' == $do) { + if (empty($_W['isfounder']) && ACCOUNT_MANAGE_NAME_MANAGER != $_W['role'] && ACCOUNT_MANAGE_NAME_OWNER != $_W['role']) { + iajax(1, '您没有权限删除文件'); + } + $id = intval($_GPC['id']); + $core_attachment_table = table('core_attachment'); + $condition = array('id' => $id, 'type' => ATTACH_TYPE_IMAGE); + if (empty($uniacid)) { + $condition['uid'] = $_W['uid']; + } else { + $condition['uniacid'] = $uniacid; + } + $new_filename = safe_gpc_string($_GPC['new_filename']); + $data = array('filename' => $new_filename); + $result = $core_attachment_table->where($condition)->fill($data)->save(); + if ($result) { + iajax(0, '修改成功!'); + } else { + iajax(-1, '修改失败!'); + } +} + +if ('delete' == $do) { + if (empty($_W['isfounder']) && ACCOUNT_MANAGE_NAME_MANAGER != $_W['role'] && ACCOUNT_MANAGE_NAME_OWNER != $_W['role']) { + iajax(1, '您没有权限删除文件'); + } + $id = $_GPC['id']; + if (!is_array($id)) { + $id = array(intval($id)); + } + $id = safe_gpc_array($id); + $core_attachment_table = table('core_attachment'); + $core_attachment_table->searchWithId($id); + if (empty($uniacid)) { + $core_attachment_table->searchWithUid($_W['uid']); + $_W['setting']['remote'] = $_W['setting']['remote_complete_info']; + } else { + $core_attachment_table->searchWithUniacid($uniacid); + $uni_remote_setting = uni_setting_load('remote'); + if (!empty($uni_remote_setting['remote']['type'])) { + $_W['setting']['remote'] = $uni_remote_setting['remote']; + } + } + $attachments = $core_attachment_table->getall(); + $delete_ids = array(); + foreach ($attachments as $media) { + if (!empty($_W['setting']['remote']['type'])) { + $status = file_remote_delete($media['attachment']); + } else { + $status = file_delete($media['attachment']); + } + if (is_error($status)) { + iajax(1, $status['message']); + exit; + } + $delete_ids[] = $media['id']; + } + + pdo_delete('core_attachment', array('id' => $delete_ids, 'uniacid' => $uniacid)); + iajax(0, '删除成功'); +} + +$limit = array(); +$limit['temp'] = array( + 'image' => array( + 'ext' => array('jpg', 'logo'), + 'size' => 1024 * 1024, + 'errmsg' => '临时图片只支持jpg/logo格式,大小不超过为1M', + ), + 'voice' => array( + 'ext' => array('amr', 'mp3'), + 'size' => 2048 * 1024, + 'errmsg' => '临时语音只支持amr/mp3格式,大小不超过为2M', + ), + 'video' => array( + 'ext' => array('mp4'), + 'size' => 10240 * 1024, + 'errmsg' => '临时视频只支持mp4格式,大小不超过为10M', + ), + 'thumb' => array( + 'ext' => array('jpg', 'logo'), + 'size' => 64 * 1024, + 'errmsg' => '临时缩略图只支持jpg/logo格式,大小不超过为64K', + ), +); +$limit['perm'] = array( + 'image' => array( + 'ext' => array('bmp', 'png', 'jpeg', 'jpg', 'gif'), + 'size' => 2048 * 1024, + 'max' => 100000, + 'errmsg' => '永久图片只支持bmp/png/jpeg/jpg/gif格式,大小不超过为2M', + ), + 'voice' => array( + 'ext' => array('mp3', 'wma', 'wav', 'amr'), + 'size' => 2048 * 1024, + 'max' => 1000, + 'errmsg' => '永久语音只支持mp3/wma/wav/amr格式,大小不超过为2M,长度不超过60秒', + ), + 'video' => array( + 'ext' => array('mp4'), + 'size' => 10240 * 1024, + 'max' => 1000, + 'errmsg' => '永久视频只支持mp4格式,大小不超过为10M', + ), + 'thumb' => array( + 'ext' => array('jpg'), + 'size' => 64 * 1024, + 'max' => 1000, + 'errmsg' => '永久缩略图只支持jpg格式,大小不超过为64KB', + ), +); + +$limit['file_upload'] = array( + 'image' => array( + 'ext' => array('jpg'), + 'size' => 1024 * 1024, + 'max' => -1, + 'errmsg' => '图片只支持jpg格式,大小不超过为1M', + ), +); +if ('wechat_upload' == $do) { + $type = trim($_GPC['upload_type']); + $mode = trim($_GPC['mode']); + if ('image' == $type || 'thumb' == $type) { + $type = 'image'; + } + if ('audio' == $type) { + $type = 'voice'; + } + + $setting['folder'] = "{$type}s/{$_W['uniacid']}" . '/' . date('Y/m/'); + + if ('perm' == $mode) { + $now_count = pdo_fetchcolumn('SELECT COUNT(*) FROM ' . tablename('wechat_attachment') . ' WHERE uniacid = :aid AND model = :model AND type = :type', array(':aid' => $_W['uniacid'], ':model' => $mode, ':type' => $type)); + if ($now_count >= $limit['perm'][$type]['max']) { + $result['message'] = '文件数量超过限制,请先删除部分文件再上传'; + iajax(-1, $result['message']); + } + } + + if (empty($mode) || empty($type) || !$_W['acid']) { + $result['message'] = '上传配置出错'; + iajax(-1, $result['message']); + } + + if (empty($_FILES['file']['name'])) { + $result['message'] = '上传失败, 请选择要上传的文件!'; + iajax(-1, $result['message']); + } + + if ($_FILES['file']['error'] != 0) { + $result['message'] = '上传失败, 请重试.'; + iajax(-1, $result['message']); + } + + $ext = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION); + $ext = strtolower($ext); + $size = intval($_FILES['file']['size']); + $originname = $_FILES['file']['name']; + + if (!in_array($ext, $limit[$mode][$type]['ext']) || ($size > $limit[$mode][$type]['size'])) { + $result['message'] = $limit[$mode][$type]['errmsg']; + iajax(-1, $result['message']); + } + + $filename = file_random_name(ATTACHMENT_ROOT . '/' . $setting['folder'], $ext); + + $file = file_wechat_upload($_FILES['file'], $type, $setting['folder'] . $filename, true); + + if (is_error($file)) { + $result['message'] = $file['message']; + iajax(-1, $result['message']); + } + + $pathname = $file['path']; + $fullname = ATTACHMENT_ROOT . '/' . $pathname; + $acc = WeAccount::createByUniacid(); + if ('perm' == $mode || 'temp' == $mode) { + if ('video' != $type) { + $result = $acc->uploadMediaFixed($pathname, $type); + } else { + $result = $acc->uploadVideoFixed($originname, $originname, $pathname); + } + } + + if ('perm' == $mode || 'temp' == $mode) { + if (!empty($content['media_id'])) { + $result['media_id'] = $content['media_id']; + } + if (!empty($content['thumb_media_id'])) { + $result['media_id'] = $content['thumb_media_id']; + } + } elseif ('file_upload' == $mode) { + $result['media_id'] = $content['url']; + } + + if ('image' == $type || 'thumb' == $type) { + $file['path'] = file_image_thumb($fullname, '', 300); + } + + if (!empty($_W['setting']['remote']['type']) && !empty($file['path'])) { + $remotestatus = file_remote_upload($file['path']); + if (is_error($remotestatus)) { + file_delete($pathname); + if ('image' == $type || 'thumb' == $type) { + file_delete($file['path']); + } + $result['error'] = 0; + $result['message'] = '远程附件上传失败,请检查配置并重新上传'; + iajax(-1, $result['message']); + } else { + file_delete($pathname); + if ('image' == $type || 'thumb' == $type) { + file_delete($file['path']); + } + } + } + + $insert = array( + 'uniacid' => $_W['uniacid'], + 'acid' => $_W['acid'], + 'uid' => $_W['uid'], + 'filename' => $originname, + 'attachment' => $file['path'], + 'media_id' => $result['media_id'], + 'type' => $type, + 'model' => $mode, + 'createtime' => TIMESTAMP, + 'module_upload_dir' => $module_upload_dir, + 'group_id' => intval($_GPC['group_id']), + ); + if ('image' == $type || 'thumb' == $type) { + $size = getimagesize($fullname); + $insert['width'] = $size[0]; + $insert['height'] = $size[1]; + if ('perm' == $mode) { + $insert['tag'] = $content['url']; + } + if (!empty($insert['tag'])) { + $insert['attachment'] = $content['url']; + } + $result['width'] = $size[0]; + $result['hieght'] = $size[1]; + } + if ('video' == $type) { + $insert['tag'] = iserializer(array('title' => $originname, 'url' => '')); + } + + if ('video' == $type && 'perm' == $mode) { + if (!is_error($result)) { + pdo_insert('wechat_attachment', $insert); + } + } else { + pdo_insert('wechat_attachment', $insert); + } + + $result['type'] = $type; + $result['url'] = tomedia($file['path']); + + if ('image' == $type || 'thumb' == $type) { + @unlink($fullname); + } + $result['mode'] = $mode; + die(json_encode($result)); +} + +$type = $_GPC['type']; +$resourceid = intval($_GPC['resource_id']); +$uid = intval($_W['uid']); +$acid = intval($_W['acid']); +$url = $_GPC['url']; +$isnetwork_convert = !empty($url); +$islocal = 'local' == $_GPC['local']; + +if ('keyword' == $do) { + $keyword = addslashes($_GPC['keyword']); + $pindex = max(1, $_GPC['page']); + $psize = 24; + $condition = array('uniacid' => $uniacid, 'status' => 1); + if (!empty($keyword)) { + $condition['content like'] = '%' . $keyword . '%'; + } + + $keyword_lists = pdo_getslice('rule_keyword', $condition, array($pindex, $psize), $total, array(), 'id'); + $result = array( + 'items' => $keyword_lists, + 'pager' => pagination($total, $pindex, $psize, '', array('before' => '2', 'after' => '3', 'ajaxcallback' => 'null', 'isajax' => 1)), + ); + iajax(0, $result); +} +if ('module' == $do) { + $enable_modules = array(); + $is_user_module = isset($_GPC['user_module']) ? intval($_GPC['user_module']) : 0; + $uid = empty($_GPC['uid']) || !is_numeric($_GPC['uid']) ? $_W['uid'] : intval($_GPC['uid']); + $module_uniacid = empty($_GPC['module_uniacid']) || !is_numeric($_GPC['module_uniacid']) ? $_W['uniacid'] : intval($_GPC['module_uniacid']); + $have_cover = 'true' == $_GPC['cover'] ? true : false; + $account_all_type = uni_account_type(); + $module_type = in_array($_GPC['mtype'], array_keys(uni_account_type_sign())) ? $_GPC['mtype'] : ''; + if ($is_user_module) { + $installedmodulelist = user_modules($uid); + } else { + $installedmodulelist = uni_modules_by_uniacid($module_uniacid); + } + + $sysmods = module_system(); + foreach ($installedmodulelist as $k => $value) { + if ('system' == $value['type'] || in_array($value['name'], $sysmods)) { + unset($installedmodulelist[$k]); + continue; + } + + $continue = false; + foreach ($account_all_type as $account_type) { + if ($module_type == $account_type['type_sign'] && $value[$account_type['module_support_name']] != $account_type['module_support_value']) { + $continue = true; + break; + } + } + if ($continue) { + unset($installedmodulelist[$k]); + continue; + } + + if ($have_cover) { + $module_entries = module_entries($value['name'], array('cover')); + if (empty($module_entries)) { + unset($installedmodulelist[$k]); + continue; + } + } + + $installedmodulelist[$k]['official'] = empty($value['issystem']) && (strexists($value['author'], 'WeEngine Team') || strexists($value['author'], '微擎团队')); + } + foreach ($installedmodulelist as $name => $module) { + if ($module['issystem']) { + $path = '/framework/builtin/' . $module['name']; + } else { + $path = '../addons/' . $module['name']; + } + $cion = $path . '/icon-custom.jpg'; + if (!file_exists($cion)) { + $cion = $path . '/icon.jpg'; + if (!file_exists($cion)) { + $cion = './resource/images/nopic-small.jpg'; + } + } + $module['icon'] = $cion; + $enable_modules[] = $module; + } + $result = array('items' => $enable_modules, 'pager' => ''); + iajax(0, $result); +} + +if ('video' == $do || 'voice' == $do) { + $server = $islocal ? MATERIAL_LOCAL : MATERIAL_WEXIN; + $page_index = max(1, $_GPC['page']); + $page_size = 10; + $material_news_list = material_list($do, $server, array('page_index' => $page_index, 'page_size' => $page_size)); + $material_list = $material_news_list['material_list']; + $pager = $material_news_list['page']; + foreach ($material_list as &$item) { + $item['url'] = tomedia($item['attachment']); + unset($item['uid']); + } + $result = array( + 'list' => $material_list, + 'page' => $page_index, + 'page_size' => $page_size, + 'total' => $material_news_list['total'], + 'pager' => $pager, + 'items' => $material_list, + 'pager' => $pager, + ); + iajax(0, $result); +} + +if ('news' == $do) { + $server = $islocal ? MATERIAL_LOCAL : MATERIAL_WEXIN; + $page_index = max(1, $_GPC['page']); + $page_size = 24; + $search = addslashes($_GPC['keyword']); + $material_news_list = material_news_list($server, $search, array('page_index' => $page_index, 'page_size' => $page_size)); + + $material_list = array_values($material_news_list['material_list']); + $pager = $material_news_list['page']; + $result = array('items' => $material_list, 'pager' => $pager); + iajax(0, $result); +} +if ('image' == $do) { + $year = $_GPC['year']; + $month = $_GPC['month']; + $page = max(1, intval($_GPC['page'])); + $groupid = safe_gpc_int($_GPC['group_id']); + $keyword = safe_gpc_string($_GPC['keyword']); + $order = safe_gpc_string($_GPC['order']); + $page_size = 18; + $page = max(1, $page); + if ($islocal) { + $attachment_table = table('core_attachment'); + } else { + $attachment_table = table('wechat_attachment'); + } + $attachment_table->searchWithUniacid($uniacid); + $attachment_table->searchWithUploadDir($module_upload_dir); + + if (empty($uniacid)) { + $attachment_table->searchWithUid($_W['uid']); + } + if ($groupid > 0) { + $attachment_table->searchWithGroupId($groupid); + } + + if (0 == $groupid) { + $attachment_table->searchWithGroupId(-1); + } + + if ($year || $month) { + $start_time = strtotime("{$year}-{$month}-01"); + $end_time = strtotime('+1 month', $start_time); + $attachment_table->searchWithTime($start_time, $end_time); + } + if ($islocal) { + $attachment_table->searchWithType(ATTACH_TYPE_IMAGE); + } else { + $attachment_table->searchWithType(ATTACHMENT_IMAGE); + } + + if (!empty($keyword)) { + $attachment_table->where('filename LIKE', "%$keyword%"); + } + + if (!empty($order)) { + if (in_array($order, array('ase', 'desc'))) { + $attachment_table->orderby('id', $order); + } + if (in_array($order, array('filename_ase', 'filename_desc'))) { + $order = $order == 'filename_ase' ? 'ase' : 'desc'; + $attachment_table->orderby('filename', $order); + } + } + + $attachment_table->searchWithPage($page, $page_size); + + $list = $attachment_table->orderby('createtime', 'desc')->getall(); + $total = $attachment_table->getLastQueryTotal(); + if (!empty($list)) { + foreach ($list as &$meterial) { + if ($islocal) { + if ($uniacid == 0) { + $meterial['url'] = to_global_media($meterial['attachment']); + } else { + $meterial['url'] = tomedia($meterial['attachment']); + } + unset($meterial['uid']); + } else { + if (!empty($_W['setting']['remote']['type'])) { + $meterial['attach'] = tomedia($meterial['attachment']); + } else { + $meterial['attach'] = tomedia($meterial['attachment'], true); + } + $meterial['url'] = $meterial['attach']; + } + } + } + + $pager = pagination($total, $page, $page_size, '', $context = array('before' => 5, 'after' => 4, 'isajax' => $_W['isajax'])); + $result = array( + 'list' => $list, + 'total' => $total, + 'page' => $page, + 'page_size' => $page_size, + 'pager' => $pager, + 'items' => $list, + ); + iajax(0, $result); +} + +if ('tolocal' == $do || 'towechat' == $do) { + if (!in_array($type, array('news', 'image', 'video', 'voice'))) { + iajax(1, '转换类型不正确'); + } +} + +if ('networktolocal' == $do) { + $type = $_GPC['type']; + if (!in_array($type, array('image', 'video'))) { + $type = 'image'; + } + + $material = material_network_to_local($url, $uniacid, $uid, $type); + if (is_error($material)) { + iajax(1, $material['message']); + } + iajax(0, $material); +} + +if ('tolocal' == $do) { + if ('news' == $type) { + $material = material_news_to_local($resourceid); + } else { + $material = material_to_local($resourceid, $uniacid, $uid, $type); + } + if (is_error($material)) { + iajax(1, $material['message']); + } + iajax(0, $material); +} + +if ('networktowechat' == $do) { + $type = $_GPC['type']; + if (!in_array($type, array('image', 'video'))) { + $type = 'image'; + } + $url_host = parse_url($url, PHP_URL_HOST); + $is_ip = preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/', $url_host); + if ($is_ip) { + iajax(1, '网络链接不支持IP地址!'); + } + $material = material_network_to_wechat($url, $uniacid, $uid, $acid, $type); + if (is_error($material)) { + iajax(1, $material['message']); + } + iajax(0, $material); +} + +if ('towechat' == $do) { + $material = null; + if ('news' != $type) { + $material = material_to_wechat($resourceid, $uniacid, $uid, $acid, $type); + } else { + $material = material_local_news_upload($resourceid); + if (!is_error($material)) { + $material['items'] = $material['news']; + } + } + if (is_error($material)) { + iajax(1, $material['message']); + } + iajax(0, $material); +} + +$is_local_image = ($islocal ? true : false); + + +if ('group_list' == $do) { + $query = table('core_attachment_group')->where('type', $is_local_image ? 0 : 1); + $query->searchWithUniacidOrUid($uniacid, $_W['uid']); + $list = attachment_recursion_group($query->getall()); + iajax(0, $list); +} + +if ('add_group' == $do) { + $table = table('core_attachment_group'); + $fields = array( + 'uid' => $_W['uid'], + 'uniacid' => $uniacid, + 'name' => safe_gpc_string($_GPC['name']), + 'type' => $is_local_image ? 0 : 1, + ); + if (!empty($_GPC['pid'])) { + $fields['pid'] = safe_gpc_int($_GPC['pid']); + } + $table->fill($fields); + $result = $table->save(); + if (is_error($result)) { + iajax($result['errno'], $result['message']); + } + iajax(0, array('id' => pdo_insertid())); +} + +if ('change_group' == $do) { + $table = table('core_attachment_group'); + $type = $is_local_image ? 0 : 1; + $name = safe_gpc_string($_GPC['name']); + $id = intval($_GPC['id']); + $table->searchWithUniacidOrUid($uniacid, $_W['uid']); + $updated = $table->where('type', $type) + ->fill('name', $name) + ->where('id', $id)->save(); + iajax($updated ? 0 : 1, $updated ? '更新成功' : '更新失败'); +} + +if ('del_group' == $do) { + + if ($islocal) { + if (empty($_W['isfounder']) && ACCOUNT_MANAGE_NAME_MANAGER != $_W['role'] && ACCOUNT_MANAGE_NAME_OWNER != $_W['role']) { + iajax(1, '您没有权限删除图片组'); + } + } else { + $result_permission = permission_check_account_user('platform_material_delete',false); + if (!$result_permission) { + iajax(1, '您没有权限删除图片组'); + } + } + + $table = table('core_attachment_group'); + $type = $is_local_image ? 0 : 1; + $id = intval($_GPC['group_id']); + $table->searchWithUniacidOrUid($uniacid, $_W['uid']); + $deleted = $table->where('type', $type)->where('id', $id)->delete(); + iajax($deleted ? 0 : 1, $deleted ? '删除成功' : '删除失败'); +} + +if ('move_to_group' == $do) { + $group_id = intval($_GPC['group_id']); + $ids = safe_gpc_array($_GPC['id']); + + if ($is_local_image) { + $table = table('core_attachment'); + } else { + $table = table('wechat_attachment'); + } + $updated = $table->where('id', $ids)->where('uniacid', $uniacid)->fill('group_id', $group_id)->save(); + + iajax($updated ? 0 : -1, $updated ? '更新成功' : '更新失败'); +} + +if ('video_del' == $do) { + + if ($islocal) { + if (empty($_W['isfounder']) && ACCOUNT_MANAGE_NAME_MANAGER != $_W['role'] && ACCOUNT_MANAGE_NAME_OWNER != $_W['role']) { + iajax(1, '您没有权限删除视频'); + } + } else { + $result_permission = permission_check_account_user('platform_material_delete',false); + if (!$result_permission) { + iajax(1, '您没有权限删除视频'); + } + } + + $id = intval($_GPC['material_id']); + + $table = table('core_attachment'); + + $info = pdo_get('core_attachment',['id' => $id],['id','attachment']); + if ($info) { + $fullName = PATH_ATTACHMENT . $info['attachment']; + unlink($fullName); + } else { + iajax(1, '视频信息有误,删除失败'); + } + + $delRes = pdo_delete('core_attachment',['id' => $info['id']]); + + iajax($delRes ? 0 : -1, $delRes ? '删除成功' : '删除失败'); +} diff --git a/web/themes/default/common/footer-base.html b/web/themes/default/common/footer-base.html new file mode 100644 index 0000000..1e818b7 --- /dev/null +++ b/web/themes/default/common/footer-base.html @@ -0,0 +1,19 @@ + + {if !empty($_W['setting']['copyright']['statcode'])}{$_W['setting']['copyright']['statcode']}{/if} + {if !empty($_GPC['m']) && !in_array($_GPC['m'], array('keyword', 'special', 'welcome', 'default', 'userapi')) || defined('IN_MODULE')} + + {/if} + {if !defined('IN_MODULE')} + + {/if} \ No newline at end of file diff --git a/web/themes/default/common/footer.html b/web/themes/default/common/footer.html new file mode 100644 index 0000000..303fca9 --- /dev/null +++ b/web/themes/default/common/footer.html @@ -0,0 +1,33 @@ + +
    + + + + + +{template 'common/footer-base'} + + \ No newline at end of file diff --git a/web/themes/default/common/header-base.html b/web/themes/default/common/header-base.html new file mode 100644 index 0000000..06c714b --- /dev/null +++ b/web/themes/default/common/header-base.html @@ -0,0 +1,55 @@ + + + + {if !defined('FRAME')}{php define('FRAME', '')}{/if} + {php $frames = buildframes(FRAME);_calc_current_frames($frames);} + + + + {if !empty($_W['page']['title'])}{$_W['page']['title']}{else}平台{/if}{if !empty($_W['page']['copyright']['sitename'])} - {$_W['page']['copyright']['sitename']}{/if} + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/themes/default/common/header-topnav.html b/web/themes/default/common/header-topnav.html new file mode 100644 index 0000000..1cc2882 --- /dev/null +++ b/web/themes/default/common/header-topnav.html @@ -0,0 +1,12 @@ +{php global $top_nav} +{if $_W['iscontroller'] && $_W['isadmin']} +{loop $top_nav $key $nav} + +{if (FRAME == 'account' && $nav['name'] == 'platform') && !defined('IN_MODULE')}{php $nav['name'] = FRAME}{/if} +{if defined('IN_MODULE') && $nav['name'] == 'module'}{php $nav['name'] = 'account'}{/if} + +
  • + {$nav['title']} +
  • +{/loop} +{/if} \ No newline at end of file diff --git a/web/themes/default/common/header-user.html b/web/themes/default/common/header-user.html new file mode 100644 index 0000000..2ae9dcb --- /dev/null +++ b/web/themes/default/common/header-user.html @@ -0,0 +1,37 @@ + {if $_W['iscontroller'] && $_W['isadmin']} +
  • 客户端
  • + {else} + {if $_W['isadmin']} +
  • 控制台
  • + {/if} + {/if} + + + + + + + \ No newline at end of file diff --git a/web/themes/default/common/header.html b/web/themes/default/common/header.html new file mode 100644 index 0000000..c1937c9 --- /dev/null +++ b/web/themes/default/common/header.html @@ -0,0 +1,149 @@ +{template 'common/header-base'} +
    + {if $_GPC['c'] == 'home' && in_array($_GPC['do'], array('system_home', 'system'))} +
    + {else} +
    + {/if} + + + + + + +
    +
    +
    + {if !$_W['iscontroller']} +
    + + {if $_W['breadcrumb']} +
    + + + + +
    {$_W['breadcrumb']}
    +
    + {/if} +
    + {/if} + {if !empty($_W['uid'])} + + {else} + + {/if} +
    +
    + {if !defined('IN_MESSAGE')} + {if $frames['dimension'] == 3 && in_array(FRAME, array('account', 'system', 'cloud', 'site'))} +
    +
    +
    + +
    +
    + + +
    + {loop $frames['section'] $frame_section_id $frame_section} + + {if !isset($frame_section['is_display']) || !empty($frame_section['is_display'])} +
    + {if $frame_section['title']} +
    + + {$frame_section['title']} + +
    + {/if} + +
    + {/if} + {/loop} +
    + +
    + {/if} +
    +
    + {if !empty($_W['page']['title']) && $frames['title'] != '首页' && !empty($frames['title']) && !defined('IN_MODULE') && $_W['iscontroller']} +
    {$_W['page']['title']}
    + {/if} + {if $frames['dimension'] == 2} + + {if !in_array(FRAME, array('user_manage', 'message', 'platform', 'module', 'myself', 'workorder'))} + + + {/if} + + {/if} + {/if} diff --git a/web/themes/default/home/home.html b/web/themes/default/home/home.html new file mode 100644 index 0000000..4538f92 --- /dev/null +++ b/web/themes/default/home/home.html @@ -0,0 +1,24 @@ +{template 'common/header'} + +
    + + +
    我的平台
    +
    + + +
    +{template 'common/footer'} \ No newline at end of file diff --git a/web/themes/default/user/edit-base.html b/web/themes/default/user/edit-base.html new file mode 100644 index 0000000..bd32793 --- /dev/null +++ b/web/themes/default/user/edit-base.html @@ -0,0 +1,232 @@ +{template 'common/header'} +
    + + +
    + +
    +

    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + +
    账户设置设置
    头像
    用户名
    密码******
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {if $_W['isfounder']} + + + + + + {/if} +
    基础信息
    真实姓名
    手机号
    上次登录时间
    上次登录IP
    注册时间
    到期时间
    备注
    + + + +
    + +{template 'common/footer'} \ No newline at end of file diff --git a/web/themes/default/user/find-password.html b/web/themes/default/user/find-password.html new file mode 100644 index 0000000..2122245 --- /dev/null +++ b/web/themes/default/user/find-password.html @@ -0,0 +1,119 @@ +{template 'common/header-base'} + + +{template 'common/footer-base'} \ No newline at end of file diff --git a/web/themes/default/utility/emulator.html b/web/themes/default/utility/emulator.html new file mode 100644 index 0000000..8e2220e --- /dev/null +++ b/web/themes/default/utility/emulator.html @@ -0,0 +1,38 @@ + +{if $_W['debug_data']} + {if $_W['debug_data']['is_default']} +
    + 该关键字触发了默认回复。 + {if !empty($_W['debug_data']['params'])} + 系统的默认回复关键字对应以下几条回复, 查看默认回复 + {else} + 但系统默认回复没有设置关键字或设置的关键字没有有效的回复规则,查看默认回复 + {/if} +
    + {/if} + {if !empty($_W['debug_data']['params'])} + + + + + + + + + + + {loop $_W['debug_data']['params'] $row} + + + + + + + {/loop} + +
    模块标识关键字规则id
    {$_W['modules'][$row['module']]['title']}{$_W['modules'][$row['module']]['name']}{$row['keyword']['content']}{$row['keyword']['rid']}
    +
    红色选中代表最终回复给粉丝的回复消息
    + {/if} +{/if}