diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..3729ff0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..2cbf89f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# CS1591: 缺少对公共可见类型或成员的 XML 注释 +dotnet_diagnostic.CS1591.severity = none diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1e0aaba --- /dev/null +++ b/.gitignore @@ -0,0 +1,345 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ +# ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true +**/wwwroot/lib/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb +/WaterCloud.Web/DataProtection +/WaterCloud.Web/wwwroot/file/local/20221006 +/WaterCloud.Web/watercloudnetdb.db-journal +/RabbitMq diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cd4403d --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 钱玮鸿 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..1445ff2 --- /dev/null +++ b/README.md @@ -0,0 +1,101 @@ +

+

+ +

+ +

+
+ +[![star](https://gitee.com/qian_wei_hong/WaterCloud/badge/star.svg)](https://gitee.com/qian_wei_hong/WaterCloud/stargazers) +[![fork](https://gitee.com/qian_wei_hong/WaterCloud/badge/fork.svg)](https://gitee.com/qian_wei_hong/WaterCloud/members) +![](https://img.shields.io/badge/release-3.0.0.preview-red) + +![](https://img.shields.io/badge/.net-8.0.0-blue) +![](https://img.shields.io/badge/SqlSugar-5.1.4.59-blue) +![](https://img.shields.io/badge/layui-2.9.0-blue) +
+ +---- +# WaterCloud + +#### 介绍 + +- 请勿用于违反我国法律的项目上。 +- WaterCloud是一套基于ASP.NET 8.0 MVC + API + SqlSugar + LayUI的框架,源代码完全开源,可以帮助你解决C#.NET项目的重复工作! +- 采用主流架构思想,容易上手,简单易学,学习成本低。 +- 可完全实现二次开发让开发更多关注业务逻辑。既能快速提高开发效率,帮助公司节省人力成本,同时又不失灵活性。 +- 支持SQLServer、MySQL 等多数据库类型。模块化设计,层次结构清晰。内置一系列企业信息管理的基础功能。 +- 操作权限基于RBAC,权限控制精密细致,对所有管理链接都进行权限验证,可控制到导航菜单、功能按钮,控制到行级,列表级,表单字段级。 +- 数据权限,精细化数据权限控制,实现不同人看不同数据。 +- 代码生成功能,简单前后端代码生成。 +- 表单设计器,提供多种方式设计表单,动态表单拖拉式设计以及自定义表单。 +- 流程设计器,动态设计流程,节点及连线条件设计。 +- 内容管理,已配置好wangEditor编辑器,可以使用。 +- 文件管理,提供文件上传及下载功能。 +- 提高开发效率及质量。常用类封装,日志、缓存、验证、字典、文件、邮件、Excel。等等。 +- 页面为响应式设计,支持电脑、平板、智能手机等设备,微信浏览器以及各种常见浏览器。 +- 适用范围:可以开发OA、ERP、BPM、CRM、WMS、TMS、MIS、BI、电商平台后台、物流管理系统、快递管理系统、教务管理系统等各类管理软件。 +- 租户管理,基于Database的多租户功能(SqlSugar支持)。 +- 定时任务,基于quartz的定时任务功能(可以集群)。 +- 项目演示地址:http://47.116.127.212:5000/ (账号:admin 密码:0000,数据库2个小时还原一次) +- 文档地址:https://gitee.com/qian_wei_hong/WaterCloud/wikis/pages +- 在线项目地址:https://replit.com/@MonsterUncle/WaterCloud + +#### 前端以及后端使用技术介绍 + +1、前端技术 + +- js框架:jquery-3.4.1、LayUI、LayUI mini(开源)。 +- 图标:Font Awesome 4.7.0及LayUI自带。 +- 客户端验证:LayUI verify。 +- 富文本编辑器:开源wangEditor、LayUI editor。 +- 上传文件:LayUI upoload。 +- 动态页签:LayUI mini miniTab。 +- 数据表格:LayUI table、LayUI 开源 soul-table组件(已实现后端筛选)。 +- 下拉选择框:LayUI select、xmselect。 +- 树结构控件:LayUI 开源 dtree。 +- 树状表格:LayUI 开源 treetable-lay,框架改造treetable低版本(兼容soul-table组件、修复固定列等BUG)。 +- 穿梭框:LayUI transfer。 +- 页面布局:LayUI、LayUI mini。 +- 图表插件:echarts +- 日期控件:LayUI laydate +- 图标选择:LayUI 开源 IconPicker +- 省市区选择:LayUI 开源 layarea + +2、后端技术 + +- 核心框架:ASP.NET 8.0、WEB API +- 定时任务:QuartZ,实现web控制 +- 持久层框架:SqlSugar(支持多种数据库,复杂查询操作、多租户、分库分表等)、Chloe(支持多种数据库,复杂查询操作,比较稳定) +- 安全支持:过滤器、Sql注入、请求伪造 +- 服务端验证:实体模型验证 +- 缓存框架:Redis/Memory(单点登录控制) +- 消息队列: RabbitMq +- 事件总线: Jaina +- 日志管理:Log、登录日志、操作日志 +- 工具类:MiniExcel、Newtonsoft.Json、验证码、丰富公共类 +- 其他:AutoFac、Swagger + + +#### 环境要求 + +1. VS2022及以上版本; +2. Asp.net 8.0; +3. Mysql或者SQLSERVER2005及以上版本,database文件夹下有sql文件可执行; +4. 请使用VS2022及以上版本打开解决方案。 +5. Redis和RabbitMq在项目文件夹里有 + +#### 友情链接 + +1. 前端框架Layui 文档地址:https://layui.gitee.io/v2/ +2. Layui前端框架Layuimini 码云地址:https://gitee.com/zhongshaofa/layuimini +3. SqlSugar.ORM 文档地址:https://www.donet5.com/home/doc +4. WaterCloud讨论交流QQ群(1065447456)[![](https://pub.idqqimg.com/wpa/images/group.png)](https://jq.qq.com/?_wv=1027&k=51RHQVG) +5. .NET易用底层框架 Furion,码云地址:https://gitee.com/dotnetchina/Furion + +#### 捐赠支持 + +开源项目不易,若此项目能得到你的青睐,可以捐赠支持作者持续开发与维护,感谢所有支持开源的朋友。 + + +![输入图片说明](https://images.gitee.com/uploads/images/2020/0331/144842_7cf04ad6_7353672.jpeg "1585637076201.jpg") ![输入图片说明](https://images.gitee.com/uploads/images/2020/0331/144852_8b26c8cb_7353672.png "mm_facetoface_collect_qrcode_1585637044089.png") \ No newline at end of file diff --git a/Redis/Redis-x64-3.2.100.msi b/Redis/Redis-x64-3.2.100.msi new file mode 100644 index 0000000..6b7e300 Binary files /dev/null and b/Redis/Redis-x64-3.2.100.msi differ diff --git a/Redis/Redis说明.docx b/Redis/Redis说明.docx new file mode 100644 index 0000000..e42bd1a Binary files /dev/null and b/Redis/Redis说明.docx differ diff --git a/Redis/打开.jpg b/Redis/打开.jpg new file mode 100644 index 0000000..a7bf86f Binary files /dev/null and b/Redis/打开.jpg differ diff --git a/WaterCloud.Code/Attribute/HandlerAdminAttribute.cs b/WaterCloud.Code/Attribute/HandlerAdminAttribute.cs new file mode 100644 index 0000000..b384dc8 --- /dev/null +++ b/WaterCloud.Code/Attribute/HandlerAdminAttribute.cs @@ -0,0 +1,32 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace WaterCloud.Code +{ + /// + /// 管理员特性,MVC使用 + /// + public class HandlerAdminAttribute : ActionFilterAttribute + { + private readonly bool _isSuper; + + public HandlerAdminAttribute(bool isSuper = true) + { + _isSuper = isSuper; + } + + public override void OnActionExecuting(ActionExecutingContext filterContext) + { + if (OperatorProvider.Provider.GetCurrent() != null && _isSuper == true ? OperatorProvider.Provider.GetCurrent().IsSuperAdmin : OperatorProvider.Provider.GetCurrent().IsAdmin) + { + return; + } + else + { + //filterContext.HttpContext.Response.WriteAsync(""); + filterContext.Result = new RedirectResult(filterContext.HttpContext.Request.PathBase + "/Home/Error?msg=403"); + return; + } + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Attribute/HandlerAjaxOnlyAttribute.cs b/WaterCloud.Code/Attribute/HandlerAjaxOnlyAttribute.cs new file mode 100644 index 0000000..bad2714 --- /dev/null +++ b/WaterCloud.Code/Attribute/HandlerAjaxOnlyAttribute.cs @@ -0,0 +1,34 @@ +using Microsoft.AspNetCore.Mvc.Abstractions; +using Microsoft.AspNetCore.Mvc.ActionConstraints; +using Microsoft.AspNetCore.Routing; +using System; + +namespace WaterCloud.Code +{ + /// + /// ajax验证 + /// + [AttributeUsage(AttributeTargets.Method)] + public class HandlerAjaxOnlyAttribute : ActionMethodSelectorAttribute + { + public bool Ignore { get; set; } + + public HandlerAjaxOnlyAttribute(bool ignore = false) + { + Ignore = ignore; + } + + public override bool IsValidForRequest(RouteContext routeContext, ActionDescriptor action) + { + if (Ignore) + return true; + bool result = false; + var xreq = routeContext.HttpContext.Request.Headers.ContainsKey("x-requested-with"); + if (xreq) + { + result = routeContext.HttpContext.Request.Headers.ContainsKey("x-requested-with"); + } + return result; + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Attribute/HandlerLockAttribute.cs b/WaterCloud.Code/Attribute/HandlerLockAttribute.cs new file mode 100644 index 0000000..566b897 --- /dev/null +++ b/WaterCloud.Code/Attribute/HandlerLockAttribute.cs @@ -0,0 +1,56 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace WaterCloud.Code +{ + /// + /// 防重复锁,MVC使用 + /// + public class HandlerLockAttribute : ActionFilterAttribute + { + public HandlerLockAttribute() + { + } + + public override void OnActionExecuting(ActionExecutingContext filterContext) + { + if (OperatorProvider.Provider.GetCurrent() == null) + { + WebHelper.WriteCookie("WaterCloud_login_error", "overdue"); + //filterContext.HttpContext.Response.WriteAsync(""); + OperatorProvider.Provider.EmptyCurrent("pc_").GetAwaiter().GetResult(); + filterContext.Result = new RedirectResult(filterContext.HttpContext.Request.PathBase + "/Home/Error?msg=408"); + return; + } + else + { + string token = filterContext.HttpContext.Request.Cookies["pc_" + GlobalContext.SystemConfig.TokenName]; + string cacheToken = CacheHelper.GetAsync("pc_" + GlobalContext.SystemConfig.TokenName + "_" + OperatorProvider.Provider.GetCurrent().UserId + "_" + OperatorProvider.Provider.GetCurrent().LoginTime).GetAwaiter().GetResult(); + if (string.IsNullOrWhiteSpace(token)) + { + filterContext.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = "token不能空" }); + return; + } + if (string.IsNullOrWhiteSpace(cacheToken)) + { + filterContext.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = "token不能空" }); + return; + } + if (token != cacheToken) + { + filterContext.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = "请求异常" }); + return; + } + //固定加锁5秒 + bool result = CacheHelper.SetNx(token, token, 5); + if (!result) + { + filterContext.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = "请求太频繁,请稍后" }); + return; + } + } + //随机值 + base.OnActionExecuting(filterContext); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Attribute/LockAttribute.cs b/WaterCloud.Code/Attribute/LockAttribute.cs new file mode 100644 index 0000000..fd04a6c --- /dev/null +++ b/WaterCloud.Code/Attribute/LockAttribute.cs @@ -0,0 +1,52 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using System.Diagnostics; +using System.Threading.Tasks; + +namespace WaterCloud.Code +{ + /// + /// 防重复提交,api使用 + /// + public class LockAttribute : ActionFilterAttribute + { + /// + /// 拦截 + /// + /// + /// + /// + public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + if (GlobalContext.SystemConfig.Debug == false) + { + if (OperatorProvider.Provider.GetCurrent() == null) + { + context.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = "抱歉,没有操作权限" }); + return; + } + else + { + string token = context.HttpContext.Request.Headers[GlobalContext.SystemConfig.TokenName].ParseToString(); + if (string.IsNullOrWhiteSpace(token)) + { + context.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = "token不能空" }); + return; + } + //固定加锁5秒 + bool result = CacheHelper.SetNx(token, token, 5); + if (!result) + { + context.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = "请求太频繁,请稍后" }); + return; + } + } + } + await next(); + + sw.Stop(); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Attribute/ServiceDescriptionAttribute.cs b/WaterCloud.Code/Attribute/ServiceDescriptionAttribute.cs new file mode 100644 index 0000000..c408bda --- /dev/null +++ b/WaterCloud.Code/Attribute/ServiceDescriptionAttribute.cs @@ -0,0 +1,23 @@ +using System; + +namespace WaterCloud.Code +{ + [AttributeUsage(AttributeTargets.Class, Inherited = true)] + public class ServiceDescriptionAttribute : Attribute + { + public string ClassDescription + { + get; + set; + } + + private ServiceDescriptionAttribute() + { + } + + public ServiceDescriptionAttribute(string classDescription) + { + ClassDescription = classDescription; + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Cache/CacheHelper.cs b/WaterCloud.Code/Cache/CacheHelper.cs new file mode 100644 index 0000000..10674b7 --- /dev/null +++ b/WaterCloud.Code/Cache/CacheHelper.cs @@ -0,0 +1,468 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace WaterCloud.Code +{ + public abstract class BaseHelper : RedisHelper + { } + + public abstract class HandleLogHelper : RedisHelper + { } + + public class CacheHelper + { + private static string cacheProvider = GlobalContext.SystemConfig.CacheProvider; + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 缓存时长h + /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// + public static async Task SetAsync(string key, object value, int expiresIn = -1, bool isSliding = true) + { + return await SetBySecondAsync(key, value, expiresIn * 3600, isSliding); + } + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 缓存时长秒 + /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// + public static async Task SetBySecondAsync(string key, object value, int expiresIn = -1, bool isSliding = true) + { + if (string.IsNullOrEmpty(key)) + throw new ArgumentNullException(nameof(key)); + if (value == null) + throw new ArgumentNullException(nameof(value)); + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + if (expiresIn > 0) + { + await BaseHelper.SetAsync(key, value, expiresIn); + } + else + { + await BaseHelper.SetAsync(key, value); + } + return await ExistsAsync(key); + + case Define.CACHEPROVIDER_MEMORY: + if (expiresIn > 0) + { + MemoryCacheHelper.Set(key, value, TimeSpan.FromSeconds(expiresIn), isSliding); + } + else + { + MemoryCacheHelper.Set(key, value); + } + return await ExistsAsync(key); + + default: + if (expiresIn > 0) + { + MemoryCacheHelper.Set(key, value, TimeSpan.FromSeconds(expiresIn), isSliding); + } + else + { + MemoryCacheHelper.Set(key, value); + } + return await ExistsAsync(key); + } + } + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 缓存时长秒 + /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// + public static bool SetBySecond(string key, object value, int expiresIn = -1, bool isSliding = true) + { + if (string.IsNullOrEmpty(key)) + throw new ArgumentNullException(nameof(key)); + if (value == null) + throw new ArgumentNullException(nameof(value)); + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + if (expiresIn > 0) + { + BaseHelper.Set(key, value, expiresIn); + } + else + { + BaseHelper.Set(key, value); + } + return Exists(key); + + case Define.CACHEPROVIDER_MEMORY: + if (expiresIn > 0) + { + MemoryCacheHelper.Set(key, value, TimeSpan.FromSeconds(expiresIn), isSliding); + } + else + { + MemoryCacheHelper.Set(key, value); + } + return Exists(key); + + default: + if (expiresIn > 0) + { + MemoryCacheHelper.Set(key, value, TimeSpan.FromSeconds(expiresIn), isSliding); + } + else + { + MemoryCacheHelper.Set(key, value); + } + return Exists(key); + } + } + + /// + /// 获取缓存 + /// + /// 缓存Key + /// + public static async Task GetAsync(string key) + { + if (string.IsNullOrEmpty(key)) + throw new ArgumentNullException(nameof(key)); + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + return await BaseHelper.GetAsync(key); + + case Define.CACHEPROVIDER_MEMORY: + return MemoryCacheHelper.Get(key); + + default: + return MemoryCacheHelper.Get(key); + } + } + + /// + /// 获取缓存 + /// + /// 缓存Key + /// + public static T Get(string key) + { + if (string.IsNullOrEmpty(key)) + throw new ArgumentNullException(nameof(key)); + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + return BaseHelper.Get(key); + + case Define.CACHEPROVIDER_MEMORY: + return MemoryCacheHelper.Get(key); + + default: + return MemoryCacheHelper.Get(key); + } + } + + /// + /// 删除缓存 + /// + /// 缓存Key + /// + public static async Task RemoveAsync(string key) + { + if (string.IsNullOrEmpty(key)) + throw new ArgumentNullException(nameof(key)); + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + await BaseHelper.DelAsync(key); + break; + + case Define.CACHEPROVIDER_MEMORY: + MemoryCacheHelper.Remove(key); + break; + } + } + + /// + /// 删除缓存 + /// + /// 缓存Key + /// + public static void Remove(string key) + { + if (string.IsNullOrEmpty(key)) + throw new ArgumentNullException(nameof(key)); + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + BaseHelper.Del(key); + break; + + case Define.CACHEPROVIDER_MEMORY: + MemoryCacheHelper.Remove(key); + break; + } + } + + /// + /// 验证缓存项是否存在 + /// + /// 缓存Key + /// + public static async Task ExistsAsync(string key) + { + if (string.IsNullOrEmpty(key)) + throw new ArgumentNullException(nameof(key)); + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + return await BaseHelper.ExistsAsync(key); + + case Define.CACHEPROVIDER_MEMORY: + return MemoryCacheHelper.Exists(key); + + default: + return MemoryCacheHelper.Exists(key); + } + } + + /// + /// 验证缓存项是否存在 + /// + /// 缓存Key + /// + public static bool Exists(string key) + { + if (string.IsNullOrEmpty(key)) + throw new ArgumentNullException(nameof(key)); + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + return BaseHelper.Exists(key); + + case Define.CACHEPROVIDER_MEMORY: + return MemoryCacheHelper.Exists(key); + + default: + return MemoryCacheHelper.Exists(key); + } + } + + /// + /// 缓存续期 + /// + /// 缓存Key + /// 时间小时 + /// + public static async Task ExpireAsync(string key, int hour) + { + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + await BaseHelper.ExpireAtAsync(key, DateTime.Now.AddHours(hour)); + break; + + default: + break; + } + } + + /// + /// 缓存续期 + /// + /// 缓存Key + /// 时间小时 + /// + public static void Expire(string key, int hour) + { + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + BaseHelper.ExpireAt(key, DateTime.Now.AddHours(hour)); + break; + + default: + break; + } + } + + /// + /// 清空缓存 + /// + /// 缓存Key + /// + public static async Task FlushAllAsync() + { + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + await BaseHelper.NodesServerManager.FlushDbAsync(); + break; + + case Define.CACHEPROVIDER_MEMORY: + MemoryCacheHelper.RemoveCacheAll(); + break; + + default: + MemoryCacheHelper.RemoveCacheAll(); + break; + } + } + + /// + /// 清空缓存 + /// + /// 缓存Key + /// + public static void FlushAll1() + { + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + BaseHelper.NodesServerManager.FlushDb(); + break; + + case Define.CACHEPROVIDER_MEMORY: + MemoryCacheHelper.RemoveCacheAll(); + break; + + default: + MemoryCacheHelper.RemoveCacheAll(); + break; + } + } + + /// + /// 不存在就插入 + /// + /// 缓存Key + /// 缓存Value + /// 过期时间 + /// + public static async Task SetNxAsync(string key, object value, int second = 10) + { + bool result = false; + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + result = await BaseHelper.SetNxAsync(key, value); + await BaseHelper.ExpireAtAsync(key, DateTime.Now.AddSeconds(second)); + break; + + case Define.CACHEPROVIDER_MEMORY: + if (MemoryCacheHelper.Exists(key)) + { + result = false; + MemoryCacheHelper.Get(key); + } + else + { + result = true; + MemoryCacheHelper.Set(key, value, TimeSpan.FromSeconds(second), true); + } + break; + + default: + if (MemoryCacheHelper.Exists(key)) + { + result = false; + MemoryCacheHelper.Get(key); + } + else + { + result = true; + MemoryCacheHelper.Set(key, value, TimeSpan.FromSeconds(second), true); + } + break; + } + return result; + } + + /// + /// 不存在就插入 + /// + /// 缓存Key + /// 缓存Value + /// 过期时间 + /// + public static bool SetNx(string key, object value, int second = 10) + { + bool result = false; + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + result = BaseHelper.SetNx(key, value); + BaseHelper.ExpireAt(key, DateTime.Now.AddSeconds(second)); + break; + + case Define.CACHEPROVIDER_MEMORY: + if (MemoryCacheHelper.Exists(key)) + { + result = false; + MemoryCacheHelper.Get(key); + } + else + { + result = true; + MemoryCacheHelper.Set(key, value, TimeSpan.FromSeconds(second), true); + } + break; + + default: + if (MemoryCacheHelper.Exists(key)) + { + result = false; + MemoryCacheHelper.Get(key); + } + else + { + result = true; + MemoryCacheHelper.Set(key, value, TimeSpan.FromSeconds(second), true); + } + break; + } + return result; + } + + public static async Task> GetAllKeyAsync() + { + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + return await BaseHelper.KeysAsync("SqlSugarDataCache.*"); + + case Define.CACHEPROVIDER_MEMORY: + return MemoryCacheHelper.GetCacheKeys(); + + default: + return MemoryCacheHelper.GetCacheKeys(); + } + } + + public static IEnumerable GetAllKey() + { + switch (cacheProvider) + { + case Define.CACHEPROVIDER_REDIS: + return BaseHelper.Keys("SqlSugarDataCache.*"); + + case Define.CACHEPROVIDER_MEMORY: + return MemoryCacheHelper.GetCacheKeys(); + + default: + return MemoryCacheHelper.GetCacheKeys(); + } + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Cache/MemoryCacheHelper.cs b/WaterCloud.Code/Cache/MemoryCacheHelper.cs new file mode 100644 index 0000000..fbde7a0 --- /dev/null +++ b/WaterCloud.Code/Cache/MemoryCacheHelper.cs @@ -0,0 +1,244 @@ +using Microsoft.Extensions.Caching.Memory; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; + +namespace WaterCloud.Code +{ + /// + /// 缓存帮助类 + /// + public class MemoryCacheHelper + { + private static readonly MemoryCache Cache = new MemoryCache(new MemoryCacheOptions()); + + /// + /// 验证缓存项是否存在 + /// + /// 缓存Key + /// + public static bool Exists(string key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + return Cache.TryGetValue(key, out _); + } + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// 绝对过期时长 + /// + public static bool Set(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + if (value == null) + throw new ArgumentNullException(nameof(value)); + + Cache.Set(key, value.ToJson(), + new MemoryCacheEntryOptions().SetSlidingExpiration(expiresSliding) + .SetAbsoluteExpiration(expiressAbsoulte)); + return Exists(key); + } + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// 缓存时长 + /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间) + /// + public static bool Set(string key, object value, TimeSpan expiresIn, bool isSliding = false) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + if (value == null) + throw new ArgumentNullException(nameof(value)); + Cache.Set(key, value.ToJson(), + isSliding + ? new MemoryCacheEntryOptions().SetSlidingExpiration(expiresIn) + : new MemoryCacheEntryOptions().SetAbsoluteExpiration(expiresIn)); + + return Exists(key); + } + + /// + /// 添加缓存 + /// + /// 缓存Key + /// 缓存Value + /// + public static bool Set(string key, object value) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + if (value == null) + throw new ArgumentNullException(nameof(value)); + Cache.Set(key, value.ToJson()); + + return Exists(key); + } + + #region 删除缓存 + + /// + /// 删除缓存 + /// + /// 缓存Key + /// + public static void Remove(string key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + + Cache.Remove(key); + } + + /// + /// 批量删除缓存 + /// + /// + public static void RemoveAll(IEnumerable keys) + { + if (keys == null) + throw new ArgumentNullException(nameof(keys)); + + keys.ToList().ForEach(item => Cache.Remove(item)); + } + + #endregion 删除缓存 + + #region 获取缓存 + + /// + /// 获取缓存 + /// + /// 缓存Key + /// + public static T Get(string key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + object temp; + if (Cache.TryGetValue(key, out temp)) + { + return temp.ToString().ToObject(); + } + return default(T); + } + + /// + /// 获取缓存 + /// + /// 缓存Key + /// + public static string Get(string key) + { + if (key == null) + throw new ArgumentNullException(nameof(key)); + if (Cache.Get(key) == null) + { + return string.Empty; + } + return Cache.Get(key).ToString(); + } + + /// + /// 获取缓存集合 + /// + /// 缓存Key集合 + /// + public static IDictionary GetAll(IEnumerable keys) + { + if (keys == null) + throw new ArgumentNullException(nameof(keys)); + + var dict = new Dictionary(); + keys.ToList().ForEach(item => dict.Add(item, Cache.Get(item))); + return dict; + } + + #endregion 获取缓存 + + /// + /// 删除所有缓存 + /// + public static void RemoveCacheAll() + { + var l = GetCacheKeys(); + foreach (var s in l) + { + Remove(s); + } + } + + /// + /// 删除匹配到的缓存 + /// + /// + /// + public static void RemoveCacheRegex(string pattern) + { + IEnumerable l = SearchCacheRegex(pattern); + foreach (var s in l) + { + Remove(s); + } + } + + /// + /// 搜索 匹配到的缓存 + /// + /// + /// + public static IEnumerable SearchCacheRegex(string pattern) + { + var cacheKeys = GetCacheKeys(); + var l = cacheKeys.Where(k => Regex.IsMatch(k, pattern)).ToList(); + return l.AsReadOnly(); + } + + /// + /// 获取所有缓存键 + /// + /// + public static List GetCacheKeys() + { +#if NET8_0 + const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; + var entries = Cache.GetType().GetField("_coherentState", flags)?.GetValue(Cache); + var cacheItems = entries?.GetType()?.GetProperty("EntriesCollection", flags)?.GetValue(entries) as ICollection; //entries as IDictionary; + var keys = new List(); + if (cacheItems == null) return keys; + foreach (var item in cacheItems) + { + var methodInfo = item.GetType().GetProperty("Key"); + + var val = methodInfo.GetValue(item); + + keys.Add(val.ToString()); + } + return keys; +#else + const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; + var entries = Cache.GetType().GetField("_entries", flags).GetValue(Cache); + var cacheItems = entries as IDictionary; + var keys = new List(); + if (cacheItems == null) return keys; + foreach (DictionaryEntry cacheItem in cacheItems) + { + keys.Add(cacheItem.Key.ToString()); + } + return keys; +#endif + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/DefaultStartUp.cs b/WaterCloud.Code/DefaultStartUp.cs new file mode 100644 index 0000000..d32336a --- /dev/null +++ b/WaterCloud.Code/DefaultStartUp.cs @@ -0,0 +1,368 @@ +using Autofac; +using CSRedis; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.ResponseCompression; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.OpenApi.Models; +using Serenity.Abstractions; +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Reflection; +using System.Text.Encodings.Web; +using System.Text.Unicode; +using WaterCloud.Code.Model; + +namespace WaterCloud.Code +{ + public class DefaultStartUp + { + protected IConfiguration Configuration { get; set; } + protected IWebHostEnvironment WebHostEnvironment { get; set; } + + public DefaultStartUp(IConfiguration configuration, IWebHostEnvironment env) + { + Configuration = configuration; + WebHostEnvironment = env; + GlobalContext.LogWhenStart(env); + GlobalContext.HostingEnvironment = env; + } + + public virtual void ConfigureServices(IServiceCollection services) + { + var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); + //没有设置环境变量就默认生产环境 + if (string.IsNullOrWhiteSpace(environment)) + environment = "Production"; + Configuration = new ConfigurationBuilder().AddJsonFile($"appsettings.{environment}.json", optional: true, reloadOnChange: true).Build(); + + GlobalContext.SystemConfig = Configuration.GetSection("SystemConfig").Get(); + GlobalContext.Services = services; + GlobalContext.Configuration = Configuration; + services.Configure(options => + { + options.CheckConsentNeeded = context => true; + options.MinimumSameSitePolicy = SameSiteMode.None; + }); + //解决session问题 + services.AddSession(options => + { + options.Cookie.IsEssential = true;//是否强制存储cookie + options.Cookie.SameSite = SameSiteMode.None; + }); + //代替HttpContext.Current + services.AddHttpContextAccessor(); + //缓存缓存选择 + if (GlobalContext.SystemConfig.CacheProvider != Define.CACHEPROVIDER_REDIS) + { + services.AddMemoryCache(); + } + else + { + //redis 注入服务 + string redisConnectiong = GlobalContext.SystemConfig.RedisConnectionString; + // 多客户端 1、基础 2、操作日志 + var redisDB1 = new CSRedisClient(redisConnectiong + ",defaultDatabase=" + 0); + BaseHelper.Initialization(redisDB1); + var redisDB2 = new CSRedisClient(redisConnectiong + ",defaultDatabase=" + 1); + HandleLogHelper.Initialization(redisDB2); + services.AddSingleton(redisDB1); + services.AddSingleton(redisDB2); + } + //连续guid初始化,示例IDGen.NextId() + services.AddSingleton(); + services.AddCors(options => options.AddPolicy("CorsPolicy", + builder => + { + builder.AllowAnyMethod().AllowAnyHeader() + .WithOrigins(GlobalContext.SystemConfig.AllowCorsSite.Split(",")) + .AllowCredentials(); + })); + services.AddOptions(); + services.AddHttpClient(); + services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN"); + services.AddControllersWithViews().AddControllersAsServices(); + //启用 Gzip 和 Brotil 压缩功能 + services.AddResponseCompression(options => + { + options.Providers.Add(); + options.Providers.Add(); + options.MimeTypes = + ResponseCompressionDefaults.MimeTypes.Concat( + new[] { "image/svg+xml" }); + }); + services.Configure(options => + { + options.Level = CompressionLevel.SmallestSize; + }); + services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo(GlobalContext.HostingEnvironment.ContentRootPath + Path.DirectorySeparatorChar + "DataProtection")); + } + + /// + /// Autofac配置 + /// + /// + /// 扫描程序 + /// 控制器 + /// 服务接口 + /// 程序 + public void AutofacConfigureContainer(ContainerBuilder builder, List projects, Type controller, Type IService, Type program) + { + if (projects == null) + { + projects = new List(); + } + var baseType = IService;//IDenpendency 是一个接口(所有要实现依赖注入的借口都要继承该接口) + var controllerBaseType = controller; + foreach (var item in projects) + { + var assemblys = Assembly.Load(item);//Service是继承接口的实现方法类库名称 + builder.RegisterAssemblyTypes(assemblys).Where(m => baseType.IsAssignableFrom(m) && m != baseType) + .InstancePerLifetimeScope()//生命周期,这里没有使用接口方式 + .PropertiesAutowired();//属性注入 + //插件Controller中使用属性注入 + builder.RegisterAssemblyTypes(assemblys) + .Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType) + .PropertiesAutowired(); + } + //Controller中使用属性注入 + builder.RegisterAssemblyTypes(program.Assembly) + .Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType) + .PropertiesAutowired(); + //注册html解析 + builder.RegisterInstance(HtmlEncoder.Create(UnicodeRanges.All)).SingleInstance(); + } + + public virtual void Configure(IApplicationBuilder app) + { + GlobalContext.RootServices = app.ApplicationServices; + //实时通讯跨域 + app.UseCors("CorsPolicy"); + if (WebHostEnvironment.IsDevelopment()) + { + GlobalContext.SystemConfig.Debug = true; + app.UseDeveloperExceptionPage(); + } + else + { + app.UseDeveloperExceptionPage(); + } + //文件地址Resource + //静态资源wwwroot + app.UseStaticFiles(new StaticFileOptions + { + ContentTypeProvider = new CustomerFileExtensionContentTypeProvider(), + OnPrepareResponse = GlobalContext.SetCacheControl + }); + //启用 Gzip 和 Brotil 压缩功能 + app.UseResponseCompression(); + app.Use(async (context, next) => + { + context.Request.EnableBuffering(); + // 执行下一个中间件 + await next.Invoke(); + // 释放所有未托管的服务提供器 + GlobalContext.DisposeUnmanagedObjects(); + }); + //session + app.UseSession(); + //路径 + app.UseRouting(); + } + } + + /// + /// StartUp扩展 + /// + public static class StartUpExtends + { + /// + /// 默认MVC配置 + /// + /// + /// + public static IMvcBuilder AddDefaultMVC(this IServiceCollection services) + { + return services.AddControllersWithViews(options => + { + options.Filters.Add(); + options.Filters.Add(); + options.ModelMetadataDetailsProviders.Add(new ModelBindingMetadataProvider()); + //options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()); + }); + } + + /// + /// 默认API配置 + /// + /// + /// + public static IMvcBuilder AddDefaultAPI(this IServiceCollection services) + { + services.AddDirectoryBrowser(); + return services.AddControllers(options => + { + options.Filters.Add(); + options.ModelMetadataDetailsProviders.Add(new ModelBindingMetadataProvider()); + }).ConfigureApiBehaviorOptions(options => + { + options.SuppressModelStateInvalidFilter = true; + }); + } + + /// + /// 默认API配置 + /// + /// + /// + public static IServiceCollection AddDefaultSwaggerGen(this IServiceCollection services, string name) + { + services.AddSwaggerGen(config => + { + foreach (var item in GlobalContext.SystemConfig.DocumentSettings.GroupOpenApiInfos) + { + config.SwaggerDoc($"{item.Group}", new OpenApiInfo { Title = item.Title, Version = item.Version, Description = item.Description }); + } + var xmlFile = $"{name}.xml"; + var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); + config.IncludeXmlComments(xmlPath, true); //添加控制器层注释(true表示显示控制器注释) + config.AddSecurityDefinition(GlobalContext.SystemConfig.TokenName, new OpenApiSecurityScheme + { + Description = "header token", + Name = GlobalContext.SystemConfig.TokenName, + In = ParameterLocation.Header, + Scheme = "", + Type = SecuritySchemeType.ApiKey,//设置类型 + BearerFormat = "" + }); + config.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = GlobalContext.SystemConfig.TokenName } + }, + new List() + } + }); + }); + return services; + } + + /// + /// 默认API配置 + /// + /// + /// + public static IApplicationBuilder AddDefaultSwaggerGen(this IApplicationBuilder app) + { + app.UseSwagger(c => + { + c.RouteTemplate = "api-doc/{documentName}/swagger.json"; + }); + app.UseSwaggerUI(c => + { + c.RoutePrefix = "api-doc"; + foreach (var item in GlobalContext.SystemConfig.DocumentSettings.GroupOpenApiInfos) + { + c.SwaggerEndpoint($"{item.Group}/swagger.json", $"{item.Title}"); + } + }); + return app; + } + + /// + /// 注入RabbitMq + /// + /// + /// json配置 + /// 生命周期,默认:单例模式 + /// + public static IServiceCollection AddRabbitMq( + this IServiceCollection @this, + ServiceLifetime lifeTime = ServiceLifetime.Singleton) + { + if (GlobalContext.SystemConfig.RabbitMq.Enabled == false) + return @this; + + switch (lifeTime) + { + case ServiceLifetime.Singleton: + @this.AddSingleton(x => new RabbitMqHelper(GlobalContext.SystemConfig.RabbitMq)); + break; + + case ServiceLifetime.Scoped: + @this.AddScoped(x => new RabbitMqHelper(GlobalContext.SystemConfig.RabbitMq)); + break; + + case ServiceLifetime.Transient: + @this.AddTransient(x => new RabbitMqHelper(GlobalContext.SystemConfig.RabbitMq)); + break; + + default: + break; + } + return @this; + } + + #region AddWorkerService + + /// + /// 自动注入 继承 BackgroundService 的后台服务 + /// + /// + /// + public static IServiceCollection AddWorkerService( + this IServiceCollection @this) + { + var ret = new List(); + var assemblies = Directory.GetFiles(AppContext.BaseDirectory, "WaterCloud.*.dll") + .Select(x => x.Substring(@"\").Substring(@"/").Replace(".dll", "")) + .Select(x => Assembly.Load(x)).ToArray(); + //排除列表 + var ignoreList= new List{ "EventBusHostedService" }; + foreach (var item in assemblies) + { + ret.AddRange(item.GetTypes() //获取当前类库下所有类型 + .Where(t => typeof(BackgroundService).IsAssignableFrom(t)) //获取间接或直接继承t的所有类型 + .Where(t => !t.IsAbstract && t.IsClass && !ignoreList.Contains(t.Name)));//获取非抽象类 排除接口继承 + } + foreach (var item in ret) + { + @this.AddTransient(typeof(IHostedService), item); + } + return @this; + } + + #endregion AddWorkerService + + #region AddIf + + /// + /// 根据条件注入服务 + /// + /// + /// + /// + /// + public static IServiceCollection AddIf( + this IServiceCollection @this, + bool condition, + Action action) + { + if (condition && action != null) + action(@this); + + return @this; + } + + #endregion AddIf + } +} \ No newline at end of file diff --git a/WaterCloud.Code/DistributedIDGenerator/Enums/SequentialGuidType.cs b/WaterCloud.Code/DistributedIDGenerator/Enums/SequentialGuidType.cs new file mode 100644 index 0000000..e8d8231 --- /dev/null +++ b/WaterCloud.Code/DistributedIDGenerator/Enums/SequentialGuidType.cs @@ -0,0 +1,40 @@ +// ----------------------------------------------------------------------------- +// 让 .NET 开发更简单,更通用,更流行。 +// Copyright © 2020-2021 Furion, 百小僧, Baiqian Co.,Ltd. +// +// 框架名称:Furion +// 框架作者:百小僧 +// 框架版本:2.7.9 +// 源码地址:Gitee: https://gitee.com/dotnetchina/Furion +// Github:https://github.com/monksoul/Furion +// 开源协议:Apache-2.0(https://gitee.com/dotnetchina/Furion/blob/master/LICENSE) +// ----------------------------------------------------------------------------- + +using System.ComponentModel; + +namespace WaterCloud.Code +{ + /// + /// 连续 GUID 类型选项 + /// + public enum SequentialGuidType + { + /// + /// 标准连续 GUID 字符串 + /// + [Description("标准连续 GUID 字符串")] + SequentialAsString, + + /// + /// Byte 数组类型的连续 `GUID` 字符串 + /// + [Description("Byte 数组类型的连续 `GUID` 字符串")] + SequentialAsBinary, + + /// + /// 连续部分在末尾展示 + /// + [Description("连续部分在末尾展示")] + SequentialAtEnd + } +} \ No newline at end of file diff --git a/WaterCloud.Code/DistributedIDGenerator/Generators/IDistributedIDGenerator.cs b/WaterCloud.Code/DistributedIDGenerator/Generators/IDistributedIDGenerator.cs new file mode 100644 index 0000000..4025cc0 --- /dev/null +++ b/WaterCloud.Code/DistributedIDGenerator/Generators/IDistributedIDGenerator.cs @@ -0,0 +1,27 @@ +// ----------------------------------------------------------------------------- +// 让 .NET 开发更简单,更通用,更流行。 +// Copyright © 2020-2021 Furion, 百小僧, Baiqian Co.,Ltd. +// +// 框架名称:Furion +// 框架作者:百小僧 +// 框架版本:2.7.9 +// 源码地址:Gitee: https://gitee.com/dotnetchina/Furion +// Github:https://github.com/monksoul/Furion +// 开源协议:Apache-2.0(https://gitee.com/dotnetchina/Furion/blob/master/LICENSE) +// ----------------------------------------------------------------------------- + +namespace WaterCloud.Code +{ + /// + /// 分布式 ID 生成器 + /// + public interface IDistributedIDGenerator + { + /// + /// 生成逻辑 + /// + /// + /// + object Create(object idGeneratorOptions = default); + } +} \ No newline at end of file diff --git a/WaterCloud.Code/DistributedIDGenerator/Generators/SequentialGuidIDGenerator.cs b/WaterCloud.Code/DistributedIDGenerator/Generators/SequentialGuidIDGenerator.cs new file mode 100644 index 0000000..797313e --- /dev/null +++ b/WaterCloud.Code/DistributedIDGenerator/Generators/SequentialGuidIDGenerator.cs @@ -0,0 +1,86 @@ +// ----------------------------------------------------------------------------- +// 让 .NET 开发更简单,更通用,更流行。 +// Copyright © 2020-2021 Furion, 百小僧, Baiqian Co.,Ltd. +// +// 框架名称:Furion +// 框架作者:百小僧 +// 框架版本:2.7.9 +// 源码地址:Gitee: https://gitee.com/dotnetchina/Furion +// Github:https://github.com/monksoul/Furion +// 开源协议:Apache-2.0(https://gitee.com/dotnetchina/Furion/blob/master/LICENSE) +// ----------------------------------------------------------------------------- + +using System; +using System.Security.Cryptography; + +namespace WaterCloud.Code +{ + /// + /// 连续 GUID ID 生成器 + /// 代码参考自:https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/blob/ebe011a6f1b2a2a9709fe558cfc7ed3215b55c37/src/EFCore.MySql/ValueGeneration/Internal/MySqlSequentialGuidValueGenerator.cs + /// + public class SequentialGuidIDGenerator : IDistributedIDGenerator + { + /// + /// 随机数生成器 + /// + private static readonly RandomNumberGenerator _rng = RandomNumberGenerator.Create(); + + /// + /// 生成逻辑 + /// + /// + /// + public object Create(object idGeneratorOptions = null) + { + // According to RFC 4122: + // dddddddd-dddd-Mddd-Ndrr-rrrrrrrrrrrr + // - M = RFC version, in this case '4' for random UUID + // - N = RFC variant (plus other bits), in this case 0b1000 for variant 1 + // - d = nibbles based on UTC date/time in ticks + // - r = nibbles based on random bytes + + var options = (idGeneratorOptions ?? new SequentialGuidSettings()) as SequentialGuidSettings; + + var randomBytes = new byte[7]; + _rng.GetBytes(randomBytes); + var ticks = (ulong)options.TimeNow.Ticks; + + var uuidVersion = (ushort)4; + var uuidVariant = (ushort)0b1000; + + var ticksAndVersion = (ushort)((ticks << 48 >> 52) | (ushort)(uuidVersion << 12)); + var ticksAndVariant = (byte)((ticks << 60 >> 60) | (byte)(uuidVariant << 4)); + + if (options.LittleEndianBinary16Format) + { + var guidBytes = new byte[16]; + var tickBytes = BitConverter.GetBytes(ticks); + if (BitConverter.IsLittleEndian) + { + Array.Reverse(tickBytes); + } + + Buffer.BlockCopy(tickBytes, 0, guidBytes, 0, 6); + guidBytes[6] = (byte)(ticksAndVersion << 8 >> 8); + guidBytes[7] = (byte)(ticksAndVersion >> 8); + guidBytes[8] = ticksAndVariant; + Buffer.BlockCopy(randomBytes, 0, guidBytes, 9, 7); + + return new Guid(guidBytes); + } + + var guid = new Guid((uint)(ticks >> 32), (ushort)(ticks << 32 >> 48), ticksAndVersion, + ticksAndVariant, + randomBytes[0], + randomBytes[1], + randomBytes[2], + randomBytes[3], + randomBytes[4], + randomBytes[5], + randomBytes[6]); + + return guid; + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/DistributedIDGenerator/IDGen.cs b/WaterCloud.Code/DistributedIDGenerator/IDGen.cs new file mode 100644 index 0000000..b08142e --- /dev/null +++ b/WaterCloud.Code/DistributedIDGenerator/IDGen.cs @@ -0,0 +1,45 @@ +// ----------------------------------------------------------------------------- +// 让 .NET 开发更简单,更通用,更流行。 +// Copyright © 2020-2021 Furion, 百小僧, Baiqian Co.,Ltd. +// +// 框架名称:Furion +// 框架作者:百小僧 +// 框架版本:2.7.9 +// 源码地址:Gitee: https://gitee.com/dotnetchina/Furion +// Github:https://github.com/monksoul/Furion +// 开源协议:Apache-2.0(https://gitee.com/dotnetchina/Furion/blob/master/LICENSE) +// ----------------------------------------------------------------------------- + +using System; + +namespace WaterCloud.Code +{ + /// + /// ID 生成器 + /// + public static class IDGen + { + /// + /// 生成唯一 ID + /// + /// + /// + /// + public static object NextID(object idGeneratorOptions) + { + return ((IDistributedIDGenerator)GlobalContext.RootServices.GetService(typeof(IDistributedIDGenerator))).Create(idGeneratorOptions); + } + + /// + /// 生成连续 GUID + /// + /// + /// + /// + public static Guid NextID(SequentialGuidType guidType = SequentialGuidType.SequentialAsString) + { + var sequentialGuid = GlobalContext.RootServices.GetService(typeof(IDistributedIDGenerator)) as IDistributedIDGenerator; + return (Guid)sequentialGuid.Create(); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/DistributedIDGenerator/Settings/SequentialGuidSettings.cs b/WaterCloud.Code/DistributedIDGenerator/Settings/SequentialGuidSettings.cs new file mode 100644 index 0000000..ad1950d --- /dev/null +++ b/WaterCloud.Code/DistributedIDGenerator/Settings/SequentialGuidSettings.cs @@ -0,0 +1,32 @@ +// ----------------------------------------------------------------------------- +// 让 .NET 开发更简单,更通用,更流行。 +// Copyright © 2020-2021 Furion, 百小僧, Baiqian Co.,Ltd. +// +// 框架名称:Furion +// 框架作者:百小僧 +// 框架版本:2.7.9 +// 源码地址:Gitee: https://gitee.com/dotnetchina/Furion +// Github:https://github.com/monksoul/Furion +// 开源协议:Apache-2.0(https://gitee.com/dotnetchina/Furion/blob/master/LICENSE) +// ----------------------------------------------------------------------------- + +using System; + +namespace WaterCloud.Code +{ + /// + /// 连续 GUID 配置 + /// + public sealed class SequentialGuidSettings + { + /// + /// 当前时间 + /// + public DateTimeOffset TimeNow { get; set; } = DateTimeOffset.UtcNow; + + /// + /// LittleEndianBinary 16 格式化 + /// + public bool LittleEndianBinary16Format { get; set; } = false; + } +} \ No newline at end of file diff --git a/WaterCloud.Code/DistributedIDGenerator/ShortID/Internal/Constants.cs b/WaterCloud.Code/DistributedIDGenerator/ShortID/Internal/Constants.cs new file mode 100644 index 0000000..6b94011 --- /dev/null +++ b/WaterCloud.Code/DistributedIDGenerator/ShortID/Internal/Constants.cs @@ -0,0 +1,35 @@ +// ----------------------------------------------------------------------------- +// 让 .NET 开发更简单,更通用,更流行。 +// Copyright © 2020-2021 Furion, 百小僧, Baiqian Co.,Ltd. +// +// 框架名称:Furion +// 框架作者:百小僧 +// 框架版本:2.7.9 +// 源码地址:Gitee: https://gitee.com/dotnetchina/Furion +// Github:https://github.com/monksoul/Furion +// 开源协议:Apache-2.0(https://gitee.com/dotnetchina/Furion/blob/master/LICENSE) +// ----------------------------------------------------------------------------- + +namespace WaterCloud.Code +{ + /// + /// 短 ID 约束 + /// + internal static class Constants + { + /// + /// 最小长度 + /// + public const int MinimumAutoLength = 8; + + /// + /// 最大长度 + /// + public const int MaximumAutoLength = 14; + + /// + /// 最小可选字符长度 + /// + public const int MinimumCharacterSetLength = 50; + } +} \ No newline at end of file diff --git a/WaterCloud.Code/DistributedIDGenerator/ShortID/Internal/RandomHelpers.cs b/WaterCloud.Code/DistributedIDGenerator/ShortID/Internal/RandomHelpers.cs new file mode 100644 index 0000000..6c06ccc --- /dev/null +++ b/WaterCloud.Code/DistributedIDGenerator/ShortID/Internal/RandomHelpers.cs @@ -0,0 +1,46 @@ +// ----------------------------------------------------------------------------- +// 让 .NET 开发更简单,更通用,更流行。 +// Copyright © 2020-2021 Furion, 百小僧, Baiqian Co.,Ltd. +// +// 框架名称:Furion +// 框架作者:百小僧 +// 框架版本:2.7.9 +// 源码地址:Gitee: https://gitee.com/dotnetchina/Furion +// Github:https://github.com/monksoul/Furion +// 开源协议:Apache-2.0(https://gitee.com/dotnetchina/Furion/blob/master/LICENSE) +// ----------------------------------------------------------------------------- + +using System; + +namespace WaterCloud.Code +{ + /// + /// 随机数帮助类 + /// + internal static class RandomHelpers + { + /// + /// 随机数对象 + /// + private static readonly Random Random = new(); + + /// + /// 线程锁 + /// + private static readonly object ThreadLock = new(); + + /// + /// 生成线程安全的范围内随机数 + /// + /// + /// + /// + public static int GenerateNumberInRange(int min, int max) + { + lock (ThreadLock) + { + return Random.Next(min, max); + } + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/DistributedIDGenerator/ShortID/Options/GenerationOptions.cs b/WaterCloud.Code/DistributedIDGenerator/ShortID/Options/GenerationOptions.cs new file mode 100644 index 0000000..73cc5da --- /dev/null +++ b/WaterCloud.Code/DistributedIDGenerator/ShortID/Options/GenerationOptions.cs @@ -0,0 +1,37 @@ +// ----------------------------------------------------------------------------- +// 让 .NET 开发更简单,更通用,更流行。 +// Copyright © 2020-2021 Furion, 百小僧, Baiqian Co.,Ltd. +// +// 框架名称:Furion +// 框架作者:百小僧 +// 框架版本:2.7.9 +// 源码地址:Gitee: https://gitee.com/dotnetchina/Furion +// Github:https://github.com/monksoul/Furion +// 开源协议:Apache-2.0(https://gitee.com/dotnetchina/Furion/blob/master/LICENSE) +// ----------------------------------------------------------------------------- + +namespace WaterCloud.Code +{ + /// + /// 短 ID 生成配置选项 + /// + public class GenerationOptions + { + /// + /// 是否使用数字 + /// 默认 false + /// + public bool UseNumbers { get; set; } + + /// + /// 是否使用特殊字符 + /// 默认 true + /// + public bool UseSpecialCharacters { get; set; } = true; + + /// + /// 设置短 ID 长度 + /// + public int Length { get; set; } = RandomHelpers.GenerateNumberInRange(Constants.MinimumAutoLength, Constants.MaximumAutoLength); + } +} \ No newline at end of file diff --git a/WaterCloud.Code/DistributedIDGenerator/ShortID/ShortIDGen.cs b/WaterCloud.Code/DistributedIDGenerator/ShortID/ShortIDGen.cs new file mode 100644 index 0000000..f8a8c39 --- /dev/null +++ b/WaterCloud.Code/DistributedIDGenerator/ShortID/ShortIDGen.cs @@ -0,0 +1,161 @@ +// ----------------------------------------------------------------------------- +// 让 .NET 开发更简单,更通用,更流行。 +// Copyright © 2020-2021 Furion, 百小僧, Baiqian Co.,Ltd. +// +// 框架名称:Furion +// 框架作者:百小僧 +// 框架版本:2.7.9 +// 源码地址:Gitee: https://gitee.com/dotnetchina/Furion +// Github:https://github.com/monksoul/Furion +// 开源协议:Apache-2.0(https://gitee.com/dotnetchina/Furion/blob/master/LICENSE) +// ----------------------------------------------------------------------------- + +using System; +using System.Linq; +using System.Text; + +namespace WaterCloud.Code +{ + /// + /// 短 ID 生成核心代码 + /// 代码参考自:https://github.com/bolorundurowb/shortid + /// + public static class ShortIDGen + { + /// + /// 短 ID 生成器期初数据 + /// + private static Random _random = new(); + + private const string Bigs = "ABCDEFGHIJKLMNPQRSTUVWXY"; + private const string Smalls = "abcdefghjklmnopqrstuvwxyz"; + private const string Numbers = "0123456789"; + private const string Specials = "_-"; + private static string _pool = $"{Smalls}{Bigs}"; + + /// + /// 线程安全锁 + /// + private static readonly object ThreadLock = new(); + + /// + /// 生成目前比较主流的短 ID + /// 包含字母、数字,不包含特殊字符 + /// 默认生成 8 位 + /// + /// + public static string NextID() + { + return NextID(new GenerationOptions + { + UseNumbers = true, + UseSpecialCharacters = false, + Length = 8 + }); + } + + /// + /// 生成短 ID + /// + /// + /// + public static string NextID(GenerationOptions options) + { + // 配置必填 + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + // 判断生成的长度是否小于规定的长度,规定为 8 + if (options.Length < Constants.MinimumAutoLength) + { + throw new ArgumentException( + $"The specified length of {options.Length} is less than the lower limit of {Constants.MinimumAutoLength} to avoid conflicts."); + } + + var characterPool = _pool; + var poolBuilder = new StringBuilder(characterPool); + + // 是否包含数字 + if (options.UseNumbers) + { + poolBuilder.Append(Numbers); + } + + // 是否包含特殊字符 + if (options.UseSpecialCharacters) + { + poolBuilder.Append(Specials); + } + + var pool = poolBuilder.ToString(); + + // 生成拼接 + var output = new char[options.Length]; + for (var i = 0; i < options.Length; i++) + { + lock (ThreadLock) + { + var charIndex = _random.Next(0, pool.Length); + output[i] = pool[charIndex]; + } + } + + return new string(output); + } + + /// + /// 设置参与运算的字符,最少 50 位 + /// + /// + public static void SetCharacters(string characters) + { + if (string.IsNullOrWhiteSpace(characters)) + { + throw new ArgumentException("The replacement characters must not be null or empty."); + } + + var charSet = characters + .ToCharArray() + .Where(x => !char.IsWhiteSpace(x)) + .Distinct() + .ToArray(); + + if (charSet.Length < Constants.MinimumCharacterSetLength) + { + throw new InvalidOperationException( + $"The replacement characters must be at least {Constants.MinimumCharacterSetLength} letters in length and without whitespace."); + } + + lock (ThreadLock) + { + _pool = new string(charSet); + } + } + + /// + /// 设置种子步长 + /// + /// + public static void SetSeed(int seed) + { + lock (ThreadLock) + { + _random = new Random(seed); + } + } + + /// + /// 重置所有配置 + /// + public static void Reset() + { + lock (ThreadLock) + { + _random = new Random(); + _pool = $"{Smalls}{Bigs}"; + } + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Extend/Ext.Convert.cs b/WaterCloud.Code/Extend/Ext.Convert.cs new file mode 100644 index 0000000..a7ca62b --- /dev/null +++ b/WaterCloud.Code/Extend/Ext.Convert.cs @@ -0,0 +1,788 @@ +/******************************************************************************* + * Copyright © 2016 WaterCloud.Framework 版权所有 + * Author: WaterCloud + * Description: WaterCloud快速开发平台 + * Website: +*********************************************************************************/ + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace WaterCloud.Code +{ + public static partial class Extensions + { + #region 数值转换 + + /// + /// 转换为整型 + /// + /// 数据 + public static int ToInt(this object data) + { + if (data == null) + return 0; + int result; + var success = int.TryParse(data.ToString(), out result); + if (success) + return result; + try + { + return Convert.ToInt32(ToDouble(data, 0)); + } + catch (Exception) + { + return 0; + } + } + + /// + /// 将object转换为long,若转换失败,则返回0。不抛出异常。 + /// + /// + /// + public static long ToLong(this object obj) + { + try + { + return long.Parse(obj.ToString()); + } + catch + { + return 0L; + } + } + + /// + /// 转换为可空整型 + /// + /// 数据 + public static int? ToIntOrNull(this object data) + { + if (data == null) + return null; + int result; + bool isValid = int.TryParse(data.ToString(), out result); + if (isValid) + return result; + return null; + } + + /// + /// 转换为双精度浮点数 + /// + /// 数据 + public static double ToDouble(this object data) + { + if (data == null) + return 0; + double result; + return double.TryParse(data.ToString(), out result) ? result : 0; + } + + /// + /// 转换为双精度浮点数,并按指定的小数位4舍5入 + /// + /// 数据 + /// 小数位数 + public static double ToDouble(this object data, int digits) + { + return Math.Round(ToDouble(data), digits); + } + + /// + /// 转换为可空双精度浮点数 + /// + /// 数据 + public static double? ToDoubleOrNull(this object data) + { + if (data == null) + return null; + double result; + bool isValid = double.TryParse(data.ToString(), out result); + if (isValid) + return result; + return null; + } + + /// + /// 转换为高精度浮点数 + /// + /// 数据 + public static decimal ToDecimal(this object data) + { + if (data == null) + return 0; + decimal result; + return decimal.TryParse(data.ToString(), out result) ? result : 0; + } + + /// + /// 转换为高精度浮点数,并按指定的小数位4舍5入 + /// + /// 数据 + /// 小数位数 + public static decimal ToDecimal(this object data, int digits) + { + return Math.Round(ToDecimal(data), digits); + } + + /// + /// 转换为可空高精度浮点数 + /// + /// 数据 + public static decimal? ToDecimalOrNull(this object data) + { + if (data == null) + return null; + decimal result; + bool isValid = decimal.TryParse(data.ToString(), out result); + if (isValid) + return result; + return null; + } + + /// + /// 转换为可空高精度浮点数,并按指定的小数位4舍5入 + /// + /// 数据 + /// 小数位数 + public static decimal? ToDecimalOrNull(this object data, int digits) + { + var result = ToDecimalOrNull(data); + if (result == null) + return null; + return Math.Round(result.Value, digits); + } + + #endregion 数值转换 + + #region 日期转换 + + /// + /// 转换为日期 + /// + /// 数据 + public static DateTime ToDate(this object data) + { + if (data == null) + return DateTime.MinValue; + DateTime result; + return DateTime.TryParse(data.ToString(), out result) ? result : DateTime.MinValue; + } + + /// + /// 转换为可空日期 + /// + /// 数据 + public static DateTime? ToDateOrNull(this object data) + { + if (data == null) + return null; + DateTime result; + bool isValid = DateTime.TryParse(data.ToString(), out result); + if (isValid) + return result; + return null; + } + + #endregion 日期转换 + + #region 布尔转换 + + /// + /// 转换为布尔值 + /// + /// 数据 + public static bool ToBool(this object data) + { + if (data == null) + return false; + bool? value = GetBool(data); + if (value != null) + return value.Value; + bool result; + return bool.TryParse(data.ToString(), out result) && result; + } + + /// + /// 获取布尔值 + /// + private static bool? GetBool(this object data) + { + switch (data.ToString().Trim().ToLower()) + { + case "0": + return false; + + case "1": + return true; + + case "是": + return true; + + case "否": + return false; + + case "yes": + return true; + + case "no": + return false; + + default: + return null; + } + } + + /// + /// 转换为可空布尔值 + /// + /// 数据 + public static bool? ToBoolOrNull(this object data) + { + if (data == null) + return null; + bool? value = GetBool(data); + if (value != null) + return value.Value; + bool result; + bool isValid = bool.TryParse(data.ToString(), out result); + if (isValid) + return result; + return null; + } + + #endregion 布尔转换 + + #region 是否为空 + + /// + /// 是否为空 + /// + /// 值 + public static bool IsEmpty(this string value) + { + return string.IsNullOrWhiteSpace(value); + } + + /// + /// 是否为空 + /// + /// + /// + public static bool IsEmpty(this object value) + { + if (value != null && !string.IsNullOrEmpty(value.ToString())) + { + return false; + } + else + { + return true; + } + } + + /// + /// 是否为空 + /// + /// 值 + public static bool IsEmpty(this Guid? value) + { + if (value == null) + return true; + return IsEmpty(value.Value); + } + + /// + /// 是否为空 + /// + /// 值 + public static bool IsEmpty(this Guid value) + { + if (value == Guid.Empty) + return true; + return false; + } + + #endregion 是否为空 + + #region 强制转换类型 + + /// + /// 强制转换类型 + /// + /// + /// + /// + public static IEnumerable CastSuper(this IEnumerable source) + { + foreach (object item in source) + { + yield return (TResult)Convert.ChangeType(item, typeof(TResult)); + } + } + + #endregion 强制转换类型 + + #region 转换为long + + /// + /// 将object转换为long,若转换失败,则返回0。不抛出异常。 + /// + /// + /// + public static long ParseToLong(this object obj) + { + try + { + return long.Parse(obj.ToString()); + } + catch + { + return 0L; + } + } + + /// + /// 将object转换为long,若转换失败,则返回指定值。不抛出异常。 + /// + /// + /// + /// + public static long ParseToLong(this string str, long defaultValue) + { + try + { + return long.Parse(str); + } + catch + { + return defaultValue; + } + } + + #endregion 转换为long + + #region 转换为int + + /// + /// 将object转换为int,若转换失败,则返回0。不抛出异常。 + /// + /// + /// + public static int ParseToInt(this object str) + { + try + { + return Convert.ToInt32(str); + } + catch + { + return 0; + } + } + + /// + /// 将object转换为int,若转换失败,则返回指定值。不抛出异常。 + /// null返回默认值 + /// + /// + /// + /// + public static int ParseToInt(this object str, int defaultValue) + { + if (str == null) + { + return defaultValue; + } + try + { + return Convert.ToInt32(str); + } + catch + { + return defaultValue; + } + } + + #endregion 转换为int + + #region 转换为short + + /// + /// 将object转换为short,若转换失败,则返回0。不抛出异常。 + /// + /// + /// + public static short ParseToShort(this object obj) + { + try + { + return short.Parse(obj.ToString()); + } + catch + { + return 0; + } + } + + /// + /// 将object转换为short,若转换失败,则返回指定值。不抛出异常。 + /// + /// + /// + public static short ParseToShort(this object str, short defaultValue) + { + try + { + return short.Parse(str.ToString()); + } + catch + { + return defaultValue; + } + } + + #endregion 转换为short + + #region 转换为demical + + /// + /// 将object转换为demical,若转换失败,则返回指定值。不抛出异常。 + /// + /// + /// + public static decimal ParseToDecimal(this object str, decimal defaultValue) + { + try + { + return decimal.Parse(str.ToString()); + } + catch + { + return defaultValue; + } + } + + /// + /// 将object转换为demical,若转换失败,则返回0。不抛出异常。 + /// + /// + /// + public static decimal ParseToDecimal(this object str) + { + try + { + return decimal.Parse(str.ToString()); + } + catch + { + return 0; + } + } + + #endregion 转换为demical + + #region 转化为bool + + /// + /// 将object转换为bool,若转换失败,则返回false。不抛出异常。 + /// + /// + /// + public static bool ParseToBool(this object str) + { + try + { + return bool.Parse(str.ToString()); + } + catch + { + return false; + } + } + + /// + /// 将object转换为bool,若转换失败,则返回指定值。不抛出异常。 + /// + /// + /// + public static bool ParseToBool(this object str, bool result) + { + try + { + return bool.Parse(str.ToString()); + } + catch + { + return result; + } + } + + #endregion 转化为bool + + #region 转换为float + + /// + /// 将object转换为float,若转换失败,则返回0。不抛出异常。 + /// + /// + /// + public static float ParseToFloat(this object str) + { + try + { + return float.Parse(str.ToString()); + } + catch + { + return 0; + } + } + + /// + /// 将object转换为float,若转换失败,则返回指定值。不抛出异常。 + /// + /// + /// + public static float ParseToFloat(this object str, float result) + { + try + { + return float.Parse(str.ToString()); + } + catch + { + return result; + } + } + + #endregion 转换为float + + #region 转换为Guid + + /// + /// 将string转换为Guid,若转换失败,则返回Guid.Empty。不抛出异常。 + /// + /// + /// + public static Guid ParseToGuid(this string str) + { + try + { + return new Guid(str); + } + catch + { + return Guid.Empty; + } + } + + #endregion 转换为Guid + + #region 转换为DateTime + + /// + /// 将string转换为DateTime,若转换失败,则返回日期最小值。不抛出异常。 + /// + /// + /// + public static DateTime ParseToDateTime(this string str) + { + try + { + if (string.IsNullOrWhiteSpace(str)) + { + return DateTime.MinValue; + } + if (str.Contains("-") || str.Contains("/")) + { + return DateTime.Parse(str); + } + else + { + int length = str.Length; + switch (length) + { + case 4: + return DateTime.ParseExact(str, "yyyy", System.Globalization.CultureInfo.CurrentCulture); + + case 6: + return DateTime.ParseExact(str, "yyyyMM", System.Globalization.CultureInfo.CurrentCulture); + + case 8: + return DateTime.ParseExact(str, "yyyyMMdd", System.Globalization.CultureInfo.CurrentCulture); + + case 10: + return DateTime.ParseExact(str, "yyyyMMddHH", System.Globalization.CultureInfo.CurrentCulture); + + case 12: + return DateTime.ParseExact(str, "yyyyMMddHHmm", System.Globalization.CultureInfo.CurrentCulture); + + case 14: + return DateTime.ParseExact(str, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture); + + default: + return DateTime.ParseExact(str, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture); + } + } + } + catch + { + return DateTime.MinValue; + } + } + + /// + /// 将string转换为DateTime,若转换失败,则返回默认值。 + /// + /// + /// + /// + public static DateTime ParseToDateTime(this string str, DateTime? defaultValue) + { + try + { + if (string.IsNullOrWhiteSpace(str)) + { + return defaultValue.GetValueOrDefault(); + } + if (str.Contains("-") || str.Contains("/")) + { + return DateTime.Parse(str); + } + else + { + int length = str.Length; + switch (length) + { + case 4: + return DateTime.ParseExact(str, "yyyy", System.Globalization.CultureInfo.CurrentCulture); + + case 6: + return DateTime.ParseExact(str, "yyyyMM", System.Globalization.CultureInfo.CurrentCulture); + + case 8: + return DateTime.ParseExact(str, "yyyyMMdd", System.Globalization.CultureInfo.CurrentCulture); + + case 10: + return DateTime.ParseExact(str, "yyyyMMddHH", System.Globalization.CultureInfo.CurrentCulture); + + case 12: + return DateTime.ParseExact(str, "yyyyMMddHHmm", System.Globalization.CultureInfo.CurrentCulture); + + case 14: + return DateTime.ParseExact(str, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture); + + default: + return DateTime.ParseExact(str, "yyyyMMddHHmmss", System.Globalization.CultureInfo.CurrentCulture); + } + } + } + catch + { + return defaultValue.GetValueOrDefault(); + } + } + + #endregion 转换为DateTime + + #region 转换为string + + /// + /// 将object转换为string,若转换失败,则返回""。不抛出异常。 + /// + /// + /// + public static string ParseToString(this object obj) + { + try + { + if (obj == null) + { + return string.Empty; + } + else + { + return obj.ToString(); + } + } + catch + { + return string.Empty; + } + } + + public static string ParseToStrings(this object obj) + { + try + { + var list = obj as IEnumerable; + if (list != null) + { + return string.Join(",", list); + } + else + { + return obj.ToString(); + } + } + catch + { + return string.Empty; + } + } + + #endregion 转换为string + + #region 转换为double + + /// + /// 将object转换为double,若转换失败,则返回0。不抛出异常。 + /// + /// + /// + public static double ParseToDouble(this object obj) + { + try + { + return double.Parse(obj.ToString()); + } + catch + { + return 0; + } + } + + /// + /// 将object转换为double,若转换失败,则返回指定值。不抛出异常。 + /// + /// + /// + /// + public static double ParseToDouble(this object str, double defaultValue) + { + try + { + return double.Parse(str.ToString()); + } + catch + { + return defaultValue; + } + } + + #endregion 转换为double + + /// + /// 安全返回值 + /// + /// 可空值 + public static T SafeValue(this T? value) where T : struct + { + return value ?? default(T); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Extend/Ext.DateTime.cs b/WaterCloud.Code/Extend/Ext.DateTime.cs new file mode 100644 index 0000000..4d0f494 --- /dev/null +++ b/WaterCloud.Code/Extend/Ext.DateTime.cs @@ -0,0 +1,187 @@ +/******************************************************************************* + * Copyright © 2016 WaterCloud.Framework 版权所有 + * Author: WaterCloud + * Description: WaterCloud快速开发平台 + * Website: +*********************************************************************************/ + +using System; +using System.Text; + +namespace WaterCloud.Code +{ + public static partial class Extensions + { + /// + /// 获取格式化字符串,带时分秒,格式:"yyyy-MM-dd HH:mm:ss" + /// + /// 日期 + /// 是否移除秒 + public static string ToDateTimeString(this DateTime dateTime, bool isRemoveSecond = false) + { + if (isRemoveSecond) + return dateTime.ToString("yyyy-MM-dd HH:mm"); + return dateTime.ToString("yyyy-MM-dd HH:mm:ss"); + } + + /// + /// 获取格式化字符串,带时分秒,格式:"yyyy-MM-dd HH:mm:ss" + /// + /// 日期 + /// 是否移除秒 + public static string ToDateTimeString(this DateTime? dateTime, bool isRemoveSecond = false) + { + if (dateTime == null) + return string.Empty; + return ToDateTimeString(dateTime.Value, isRemoveSecond); + } + + /// + /// 获取格式化字符串,不带时分秒,格式:"yyyy-MM-dd" + /// + /// 日期 + public static string ToDateString(this DateTime dateTime) + { + return dateTime.ToString("yyyy-MM-dd"); + } + + /// + /// 获取格式化字符串,不带时分秒,格式:"yyyy-MM-dd" + /// + /// 日期 + public static string ToDateString() + { + return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); + } + + /// + /// 获取格式化字符串,不带时分秒,格式:"yyyy-MM-dd" + /// + /// 日期 + public static string ToDateString(this DateTime? dateTime) + { + if (dateTime == null) + return string.Empty; + return ToDateString(dateTime.Value); + } + + /// + /// 获取格式化字符串,不带年月日,格式:"HH:mm:ss" + /// + /// 日期 + public static string ToTimeString(this DateTime dateTime) + { + return dateTime.ToString("HH:mm:ss"); + } + + /// + /// 获取格式化字符串,不带年月日,格式:"HH:mm:ss" + /// + /// 日期 + public static string ToTimeString(this DateTime? dateTime) + { + if (dateTime == null) + return string.Empty; + return ToTimeString(dateTime.Value); + } + + /// + /// 获取格式化字符串,带毫秒,格式:"yyyy-MM-dd HH:mm:ss.fff" + /// + /// 日期 + public static string ToMillisecondString(this DateTime dateTime) + { + return dateTime.ToString("yyyy-MM-dd HH:mm:ss.fff"); + } + + /// + /// 获取格式化字符串,带毫秒,格式:"yyyy-MM-dd HH:mm:ss.fff" + /// + /// 日期 + public static string ToMillisecondString(this DateTime? dateTime) + { + if (dateTime == null) + return string.Empty; + return ToMillisecondString(dateTime.Value); + } + + /// + /// 获取格式化字符串,不带时分秒,格式:"yyyy年MM月dd日" + /// + /// 日期 + public static string ToChineseDateString(this DateTime dateTime) + { + return string.Format("{0}年{1}月{2}日", dateTime.Year, dateTime.Month, dateTime.Day); + } + + /// + /// 获取格式化字符串,不带时分秒,格式:"yyyy年MM月dd日" + /// + /// 日期 + public static string ToChineseDateString(this DateTime? dateTime) + { + if (dateTime == null) + return string.Empty; + return ToChineseDateString(dateTime.SafeValue()); + } + + /// + /// 获取格式化字符串,带时分秒,格式:"yyyy年MM月dd日 HH时mm分" + /// + /// 日期 + /// 是否移除秒 + public static string ToChineseDateTimeString(this DateTime dateTime, bool isRemoveSecond = false) + { + StringBuilder result = new StringBuilder(); + result.AppendFormat("{0}年{1}月{2}日", dateTime.Year, dateTime.Month, dateTime.Day); + result.AppendFormat(" {0}时{1}分", dateTime.Hour, dateTime.Minute); + if (isRemoveSecond == false) + result.AppendFormat("{0}秒", dateTime.Second); + return result.ToString(); + } + + /// + /// 获取格式化字符串,带时分秒,格式:"yyyy年MM月dd日 HH时mm分" + /// + /// 日期 + /// 是否移除秒 + public static string ToChineseDateTimeString(this DateTime? dateTime, bool isRemoveSecond = false) + { + if (dateTime == null) + return string.Empty; + return ToChineseDateTimeString(dateTime.Value); + } + + #region 毫秒转天时分秒 + + /// + /// 毫秒转天时分秒 + /// + /// + /// + public static string FormatTime(long ms) + { + int ss = 1000; + int mi = ss * 60; + int hh = mi * 60; + int dd = hh * 24; + + long day = ms / dd; + long hour = (ms - day * dd) / hh; + long minute = (ms - day * dd - hour * hh) / mi; + long second = (ms - day * dd - hour * hh - minute * mi) / ss; + long milliSecond = ms - day * dd - hour * hh - minute * mi - second * ss; + + string sDay = day < 10 ? "0" + day : "" + day; //天 + string sHour = hour < 10 ? "0" + hour : "" + hour;//小时 + string sMinute = minute < 10 ? "0" + minute : "" + minute;//分钟 + string sSecond = second < 10 ? "0" + second : "" + second;//秒 + string sMilliSecond = milliSecond < 10 ? "0" + milliSecond : "" + milliSecond;//毫秒 + sMilliSecond = milliSecond < 100 ? "0" + sMilliSecond : "" + sMilliSecond; + + return string.Format("{0} 天 {1} 小时 {2} 分 {3} 秒", sDay, sHour, sMinute, sSecond); + } + + #endregion 毫秒转天时分秒 + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Extend/Ext.Enum.cs b/WaterCloud.Code/Extend/Ext.Enum.cs new file mode 100644 index 0000000..6bafe4b --- /dev/null +++ b/WaterCloud.Code/Extend/Ext.Enum.cs @@ -0,0 +1,114 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; + +namespace WaterCloud.Code +{ + public static partial class Extensions + { + #region 枚举成员转成dictionary类型 + + /// + /// 转成dictionary类型 + /// + /// + /// + public static Dictionary EnumToDictionary(this Type enumType) + { + Dictionary dictionary = new Dictionary(); + Type typeDescription = typeof(DescriptionAttribute); + FieldInfo[] fields = enumType.GetFields(); + int sValue = 0; + string sText = string.Empty; + foreach (FieldInfo field in fields) + { + if (field.FieldType.IsEnum) + { + sValue = ((int)enumType.InvokeMember(field.Name, BindingFlags.GetField, null, null, null)); + object[] arr = field.GetCustomAttributes(typeDescription, true); + if (arr.Length > 0) + { + DescriptionAttribute da = (DescriptionAttribute)arr[0]; + sText = da.Description; + } + else + { + sText = field.Name; + } + dictionary.Add(sValue, sText); + } + } + return dictionary; + } + + /// + /// 枚举成员转成键值对Json字符串 + /// + /// + /// + public static string EnumToDictionaryString(this Type enumType) + { + List> dictionaryList = EnumToDictionary(enumType).ToList(); + var sJson = JsonConvert.SerializeObject(dictionaryList); + return sJson; + } + + #endregion 枚举成员转成dictionary类型 + + #region 获取枚举的描述 + + /// + /// 获取枚举值对应的描述 + /// + /// + /// + public static string GetDescription(this System.Enum enumType) + { + FieldInfo EnumInfo = enumType.GetType().GetField(enumType.ToString()); + if (EnumInfo != null) + { + DescriptionAttribute[] EnumAttributes = (DescriptionAttribute[])EnumInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); + if (EnumAttributes.Length > 0) + { + return EnumAttributes[0].Description; + } + } + return enumType.ToString(); + } + + #endregion 获取枚举的描述 + + #region 根据值获取枚举的描述 + + public static string GetDescriptionByEnum(this object obj) + { + var tEnum = System.Enum.Parse(typeof(T), obj.ParseToString()) as System.Enum; + var description = tEnum.GetDescription(); + return description; + } + + /// + /// 枚举 + /// + /// + /// + public static string ToDescription(this Enum enumType) + { + if (enumType == null) + return ""; + + System.Reflection.FieldInfo fieldInfo = enumType.GetType().GetField(enumType.ToString()); + + object[] attribArray = fieldInfo.GetCustomAttributes(false); + if (attribArray.Length == 0) + return enumType.ToString(); + else + return (attribArray[0] as DescriptionAttribute).Description; + } + + #endregion 根据值获取枚举的描述 + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Extend/Ext.Exception.cs b/WaterCloud.Code/Extend/Ext.Exception.cs new file mode 100644 index 0000000..49daf6f --- /dev/null +++ b/WaterCloud.Code/Extend/Ext.Exception.cs @@ -0,0 +1,14 @@ +using System; + +namespace WaterCloud.Code +{ + public static partial class Extensions + { + public static Exception GetOriginalException(this Exception ex) + { + if (ex.InnerException == null) return ex; + + return ex.InnerException.GetOriginalException(); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Extend/Ext.Format.cs b/WaterCloud.Code/Extend/Ext.Format.cs new file mode 100644 index 0000000..d8283ae --- /dev/null +++ b/WaterCloud.Code/Extend/Ext.Format.cs @@ -0,0 +1,156 @@ +/******************************************************************************* + * Copyright © 2016 WaterCloud.Framework 版权所有 + * Author: WaterCloud + * Description: WaterCloud快速开发平台 + * Website: +*********************************************************************************/ + +namespace WaterCloud.Code +{ + public static partial class Extensions + { + /// + /// 获取描述 + /// + /// 布尔值 + public static string Description(this bool value) + { + return value ? "是" : "否"; + } + + /// + /// 获取描述 + /// + /// 布尔值 + public static string Description(this bool? value) + { + return value == null ? "" : Description(value.Value); + } + + /// + /// 获取格式化字符串 + /// + /// 数值 + /// 空值显示的默认文本 + public static string Format(this int number, string defaultValue = "") + { + if (number == 0) + return defaultValue; + return number.ToString(); + } + + /// + /// 获取格式化字符串 + /// + /// 数值 + /// 空值显示的默认文本 + public static string Format(this int? number, string defaultValue = "") + { + return Format(number.SafeValue(), defaultValue); + } + + /// + /// 获取格式化字符串 + /// + /// 数值 + /// 空值显示的默认文本 + public static string Format(this decimal number, string defaultValue = "") + { + if (number == 0) + return defaultValue; + return string.Format("{0:0.##}", number); + } + + /// + /// 获取格式化字符串 + /// + /// 数值 + /// 空值显示的默认文本 + public static string Format(this decimal? number, string defaultValue = "") + { + return Format(number.SafeValue(), defaultValue); + } + + /// + /// 获取格式化字符串 + /// + /// 数值 + /// 空值显示的默认文本 + public static string Format(this double number, string defaultValue = "") + { + if (number == 0) + return defaultValue; + return string.Format("{0:0.##}", number); + } + + /// + /// 获取格式化字符串 + /// + /// 数值 + /// 空值显示的默认文本 + public static string Format(this double? number, string defaultValue = "") + { + return Format(number.SafeValue(), defaultValue); + } + + /// + /// 获取格式化字符串,带¥ + /// + /// 数值 + public static string FormatRmb(this decimal number) + { + if (number == 0) + return "¥0"; + return string.Format("¥{0:0.##}", number); + } + + /// + /// 获取格式化字符串,带¥ + /// + /// 数值 + public static string FormatRmb(this decimal? number) + { + return FormatRmb(number.SafeValue()); + } + + /// + /// 获取格式化字符串,带% + /// + /// 数值 + public static string FormatPercent(this decimal number) + { + if (number == 0) + return string.Empty; + return string.Format("{0:0.##}%", number); + } + + /// + /// 获取格式化字符串,带% + /// + /// 数值 + public static string FormatPercent(this decimal? number) + { + return FormatPercent(number.SafeValue()); + } + + /// + /// 获取格式化字符串,带% + /// + /// 数值 + public static string FormatPercent(this double number) + { + if (number == 0) + return string.Empty; + return string.Format("{0:0.##}%", number); + } + + /// + /// 获取格式化字符串,带% + /// + /// 数值 + public static string FormatPercent(this double? number) + { + return FormatPercent(number.SafeValue()); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Extend/Ext.Linq.cs b/WaterCloud.Code/Extend/Ext.Linq.cs new file mode 100644 index 0000000..74a74fd --- /dev/null +++ b/WaterCloud.Code/Extend/Ext.Linq.cs @@ -0,0 +1,211 @@ +/******************************************************************************* + * Copyright © 2016 WaterCloud.Framework 版权所有 + * Author: WaterCloud + * Description: WaterCloud快速开发平台 + * Website: +*********************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace WaterCloud.Code +{ + public static partial class ExtLinq + { + public static Expression Property(this Expression expression, string propertyName) + { + return Expression.Property(expression, propertyName); + } + + public static Expression AndAlso(this Expression left, Expression right) + { + return Expression.AndAlso(left, right); + } + + public static Expression OrElse(this Expression left, Expression right) + { + return Expression.OrElse(left, right); + } + + public static Expression Call(this Expression instance, string methodName, params Expression[] arguments) + { + return Expression.Call(instance, instance.Type.GetMethod(methodName), arguments); + } + + public static Expression GreaterThan(this Expression left, Expression right) + { + return Expression.GreaterThan(left, right); + } + + public static Expression ToLambda(this Expression body, params ParameterExpression[] parameters) + { + return Expression.Lambda(body, parameters); + } + + public static Expression> True() + { return param => true; } + + public static Expression> False() + { return param => false; } + + public static Expression> AndAlso(this Expression> first, Expression> second) + { + return first.Compose(second, Expression.AndAlso); + } + + public static Expression> OrElse(this Expression> first, Expression> second) + { + return first.Compose(second, Expression.OrElse); + } + + public static Expression Compose(this Expression first, Expression second, Func merge) + { + var map = first.Parameters + .Select((f, i) => new { f, s = second.Parameters[i] }) + .ToDictionary(p => p.s, p => p.f); + var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body); + return Expression.Lambda(merge(first.Body, secondBody), first.Parameters); + } + + private class ParameterRebinder : ExpressionVisitor + { + private readonly Dictionary map; + + /// + /// Initializes a new instance of the class. + /// + /// The map. + private ParameterRebinder(Dictionary map) + { + this.map = map ?? new Dictionary(); + } + + /// + /// Replaces the parameters. + /// + /// The map. + /// The exp. + /// Expression + public static Expression ReplaceParameters(Dictionary map, Expression exp) + { + return new ParameterRebinder(map).Visit(exp); + } + + protected override Expression VisitParameter(ParameterExpression p) + { + ParameterExpression replacement; + + if (map.TryGetValue(p, out replacement)) + { + p = replacement; + } + return base.VisitParameter(p); + } + } + + public static ParameterExpression CreateLambdaParam(string name) + { + return Expression.Parameter(typeof(T), name); + } + + /// + /// 创建完整的lambda + /// + public static LambdaExpression GenerateLambda(this ParameterExpression param, Expression body) + { + //c=>c.XXX=="XXX" + return Expression.Lambda(body, param); + } + + public static Expression> GenerateTypeLambda(this ParameterExpression param, Expression body) + { + return (Expression>)(param.GenerateLambda(body)); + } + + public static Expression Or(this Expression expression, Expression expressionRight) + { + return Expression.Or(expression, expressionRight); + } + + public static Expression And(this Expression expression, Expression expressionRight) + { + return Expression.And(expression, expressionRight); + } + + public static IOrderedQueryable SortBy(this IQueryable query, Expression> sortPredicate) + where TEntity : class, new() + { + return InvokeSortBy(query, sortPredicate, SortOrder.Ascending); + } + + public static IOrderedQueryable SortByDescending(this IQueryable query, Expression> sortPredicate) + where TEntity : class, new() + { + return InvokeSortBy(query, sortPredicate, SortOrder.Descending); + } + + private static IOrderedQueryable InvokeSortBy(IQueryable query, + Expression> sortPredicate, SortOrder sortOrder) + where TEntity : class, new() + { + var param = sortPredicate.Parameters[0]; + string propertyName = null; + Type propertyType = null; + Expression bodyExpression = null; + if (sortPredicate.Body is UnaryExpression) + { + var unaryExpression = sortPredicate.Body as UnaryExpression; + bodyExpression = unaryExpression.Operand; + } + else if (sortPredicate.Body is MemberExpression) + { + bodyExpression = sortPredicate.Body; + } + else + throw new ArgumentException(@"The body of the sort predicate expression should be + either UnaryExpression or MemberExpression.", "sortPredicate"); + var memberExpression = (MemberExpression)bodyExpression; + propertyName = memberExpression.Member.Name; + if (memberExpression.Member.MemberType == MemberTypes.Property) + { + var propertyInfo = memberExpression.Member as PropertyInfo; + if (propertyInfo != null) propertyType = propertyInfo.PropertyType; + } + else + throw new InvalidOperationException(@"Cannot evaluate the type of property since the member expression + represented by the sort predicate expression does not contain a PropertyInfo object."); + + var funcType = typeof(Func<,>).MakeGenericType(typeof(TEntity), propertyType); + var convertedExpression = Expression.Lambda(funcType, + Expression.Convert(Expression.Property(param, propertyName), propertyType), param); + + var sortingMethods = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static); + var sortingMethodName = GetSortingMethodName(sortOrder); + var sortingMethod = sortingMethods.First(sm => sm.Name == sortingMethodName && + sm.GetParameters().Length == 2); + return (IOrderedQueryable)sortingMethod + .MakeGenericMethod(typeof(TEntity), propertyType) + .Invoke(null, new object[] { query, convertedExpression }); + } + + private static string GetSortingMethodName(SortOrder sortOrder) + { + switch (sortOrder) + { + case SortOrder.Ascending: + return "OrderBy"; + + case SortOrder.Descending: + return "OrderByDescending"; + + default: + throw new ArgumentException("Sort Order must be specified as either Ascending or Descending.", + "sortOrder"); + } + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Extend/Ext.List.cs b/WaterCloud.Code/Extend/Ext.List.cs new file mode 100644 index 0000000..ef61c00 --- /dev/null +++ b/WaterCloud.Code/Extend/Ext.List.cs @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright © 2016 WaterCloud.Framework 版权所有 + * Author: WaterCloud + * Description: WaterCloud快速开发平台 + * Website: +*********************************************************************************/ + +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace WaterCloud.Code +{ + public static partial class Extensions + { + /// + /// 获取表里某页的数据 + /// + /// 表数据 + /// 当前页 + /// 分页大小 + /// 返回总页数 + /// 返回当页表数据 + public static List GetPage(this List data, int pageIndex, int pageSize, out int allPage) + { + allPage = 1; + return null; + } + + /// + /// IList转成List + /// + /// + /// + /// + public static List IListToList(IList list) + { + T[] array = new T[list.Count]; + list.CopyTo(array, 0); + return new List(array); + } + + /// + /// 去除空元素 + /// + public static List removeNull(List oldList) + { + // 临时集合 + List listTemp = new List(); + foreach (var item in oldList) + { + if (!string.IsNullOrEmpty(item)) + { + listTemp.Add(item); + } + } + return listTemp; + } + } + + public class ExtList : IEqualityComparer where T : class, new() + { + private string[] comparintFiledName = { }; + + public ExtList() + { } + + public ExtList(params string[] comparintFiledName) + { + this.comparintFiledName = comparintFiledName; + } + + bool IEqualityComparer.Equals(T x, T y) + { + if (x == null && y == null) + { + return false; + } + if (comparintFiledName.Length == 0) + { + return x.Equals(y); + } + bool result = true; + var typeX = x.GetType();//获取类型 + var typeY = y.GetType(); + foreach (var filedName in comparintFiledName) + { + var xPropertyInfo = (from p in typeX.GetProperties() where p.Name.Equals(filedName) select p).FirstOrDefault(); + var yPropertyInfo = (from p in typeY.GetProperties() where p.Name.Equals(filedName) select p).FirstOrDefault(); + + result = result + && xPropertyInfo != null && yPropertyInfo != null + && xPropertyInfo.GetValue(x, null).ToString().Equals(yPropertyInfo.GetValue(y, null)); + } + return result; + } + + int IEqualityComparer.GetHashCode(T obj) + { + return obj.ToString().GetHashCode(); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Extend/Ext.Mapper.cs b/WaterCloud.Code/Extend/Ext.Mapper.cs new file mode 100644 index 0000000..0b1a095 --- /dev/null +++ b/WaterCloud.Code/Extend/Ext.Mapper.cs @@ -0,0 +1,59 @@ +using AutoMapper; +using System; +using System.Collections; +using System.Collections.Generic; + +namespace WaterCloud.Code +{ + public static partial class Extensions + { + /// + /// 类型映射 + /// + public static T MapTo(this object obj) + { + if (obj == null) return default(T); + + var config = new MapperConfiguration(cfg => cfg.CreateMap(obj.GetType(), typeof(T))); + var mapper = config.CreateMapper(); + return mapper.Map(obj); + } + + /// + /// 集合列表类型映射 + /// + public static List MapToList(this IEnumerable source) + { + Type sourceType = source.GetType().GetGenericArguments()[0]; //获取枚举的成员类型 + var config = new MapperConfiguration(cfg => cfg.CreateMap(sourceType, typeof(TDestination))); + var mapper = config.CreateMapper(); + + return mapper.Map>(source); + } + + /// + /// 集合列表类型映射 + /// + public static List MapToList(this IEnumerable source) + { + var config = new MapperConfiguration(cfg => cfg.CreateMap(typeof(TSource), typeof(TDestination))); + var mapper = config.CreateMapper(); + + return mapper.Map>(source); + } + + /// + /// 类型映射 + /// + public static TDestination MapTo(this TSource source, TDestination destination) + where TSource : class + where TDestination : class + { + if (source == null) return destination; + + var config = new MapperConfiguration(cfg => cfg.CreateMap(typeof(TSource), typeof(TDestination))); + var mapper = config.CreateMapper(); + return mapper.Map(source); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Extend/Ext.Number.cs b/WaterCloud.Code/Extend/Ext.Number.cs new file mode 100644 index 0000000..d8b3c41 --- /dev/null +++ b/WaterCloud.Code/Extend/Ext.Number.cs @@ -0,0 +1,96 @@ + +using System; +using System.Text; +using System.Collections.Generic; +using System.Security.Cryptography; + +namespace WaterCloud.Code +{ + /// + /// 数值扩展类 + /// + public static partial class Extensions + { + #region 进制转换 + /// + /// 10进制转换到2-36进制 + /// + /// 10进制数字 + /// 进制,范围2-36 + /// 编码取值规则,最大转换位数不能大于该字符串的长度 + /// + public static string ToBase(this long @this, int radix, string digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") + { + const int BitsInLong = 64; + + if (radix < 2 || radix > digits.Length) + throw new ArgumentException("The radix must be >= 2 and <= " + digits.Length.ToString()); + + if (@this == 0) + return "0"; + + var index = BitsInLong - 1; + var currentNumber = Math.Abs(@this); + var charArray = new char[BitsInLong]; + + while (currentNumber != 0) + { + var remainder = (int)(currentNumber % radix); + charArray[index--] = digits[remainder]; + currentNumber /= radix; + } + + var result = new string(charArray, index + 1, BitsInLong - index - 1); + if (@this < 0) + { + result = "-" + result; + } + + return result; + } + + /// + /// byte转16进制 + /// + /// + /// + public static string ToHex(this byte @this) => Convert.ToString(@this, 16); + + /// + /// 2进制转16进制 + /// + /// + /// + public static string ToHex(this string @this) => Convert.ToString(Convert.ToInt64(@this, 2), 16); + + /// + /// 16进制转2进制 + /// + /// + /// + public static string ToBinary(this string @this) => Convert.ToString(Convert.ToInt64(@this, 16), 2); + + /// + /// 2进制/16进制转8进制 + /// + /// + /// 2或者16,表示2进制或者16进制; + /// + public static string ToOctal(this string @this, int fromBase) => Convert.ToString(Convert.ToInt64(@this, fromBase), 8); + + /// + /// 2进制/16进制转10进制 + /// + /// + /// 2或者16,表示2进制或者16进制; + /// + public static string ToDecimalism(this string @this, int fromBase) + { + if (fromBase == 16) + return Convert.ToInt32(@this, 16).ToString(); + else + return Convert.ToString(Convert.ToInt64(@this, 2), 10); + } + #endregion + } +} diff --git a/WaterCloud.Code/Extend/Ext.String.cs b/WaterCloud.Code/Extend/Ext.String.cs new file mode 100644 index 0000000..fb08a10 --- /dev/null +++ b/WaterCloud.Code/Extend/Ext.String.cs @@ -0,0 +1,37 @@ +using System; + +namespace WaterCloud.Code +{ + /// + /// string扩展类 + /// + public static partial class Extensions + { + /// + /// 从分隔符开始向尾部截取字符串 + /// + /// 源字符串 + /// 分隔符 + /// true:从最后一个匹配的分隔符开始截取,false:从第一个匹配的分隔符开始截取,默认:true + /// string + public static string Substring(this string @this, string separator, bool lastIndexOf = true) + { + var startIndex = (lastIndexOf ? + @this.LastIndexOf(separator, StringComparison.OrdinalIgnoreCase) : + @this.IndexOf(separator, StringComparison.OrdinalIgnoreCase)) + + separator.Length; + + var length = @this.Length - startIndex; + return @this.Substring(startIndex, length); + } + #region 字符串截取第一个 + public static string ReplaceFrist(this string str, string oldChar, string newChar) + { + int idx = str.IndexOf(oldChar); + str = str.Remove(idx, oldChar.Length); + str = str.Insert(idx, newChar); + return str; + } + #endregion + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Extend/Ext.Table.cs b/WaterCloud.Code/Extend/Ext.Table.cs new file mode 100644 index 0000000..b6e0361 --- /dev/null +++ b/WaterCloud.Code/Extend/Ext.Table.cs @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright © 2016 WaterCloud.Framework 版权所有 + * Author: WaterCloud + * Description: WaterCloud快速开发平台 + * Website: +*********************************************************************************/ + +using System.Data; + +namespace WaterCloud.Code +{ + public static partial class Extensions + { + /// + /// 获取表里某页的数据 + /// + /// 表数据 + /// 当前页 + /// 分页大小 + /// 返回总页数 + /// 返回当页表数据 + public static DataTable GetPage(this DataTable data, int pageIndex, int pageSize, out int allPage) + { + allPage = data.Rows.Count / pageSize; + allPage += data.Rows.Count % pageSize == 0 ? 0 : 1; + DataTable Ntable = data.Clone(); + int startIndex = pageIndex * pageSize; + int endIndex = startIndex + pageSize > data.Rows.Count ? data.Rows.Count : startIndex + pageSize; + if (startIndex < endIndex) + for (int i = startIndex; i < endIndex; i++) + { + Ntable.ImportRow(data.Rows[i]); + } + return Ntable; + } + + /// + /// 根据字段过滤表的内容 + /// + /// 表数据 + /// 条件 + /// + /// + public static DataTable GetDataFilter(DataTable data, string condition) + { + if (data != null && data.Rows.Count > 0) + { + if (condition.Trim() == "") + { + return data; + } + else + { + DataTable newdt = new DataTable(); + newdt = data.Clone(); + DataRow[] dr = data.Select(condition); + for (int i = 0; i < dr.Length; i++) + { + newdt.ImportRow((DataRow)dr[i]); + } + return newdt; + } + } + else + { + return null; + } + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Extend/Ext.Validate.cs b/WaterCloud.Code/Extend/Ext.Validate.cs new file mode 100644 index 0000000..7f77108 --- /dev/null +++ b/WaterCloud.Code/Extend/Ext.Validate.cs @@ -0,0 +1,30 @@ +using Microsoft.AspNetCore.Http; +using System; + +namespace WaterCloud.Code +{ + public static partial class Extensions + { + public static bool IsNullOrZero(this object value) + { + if (value == null || value.ParseToString().Trim() == "0") + { + return true; + } + else + { + return false; + } + } + + public static bool IsAjaxRequest(this HttpRequest request) + { + if (request == null) + throw new ArgumentNullException("request"); + + if (request.Headers != null) + return request.Headers["X-Requested-With"] == "XMLHttpRequest"; + return false; + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Filter/GlobalExceptionFilter.cs b/WaterCloud.Code/Filter/GlobalExceptionFilter.cs new file mode 100644 index 0000000..8347bd0 --- /dev/null +++ b/WaterCloud.Code/Filter/GlobalExceptionFilter.cs @@ -0,0 +1,41 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using System.Threading.Tasks; + +namespace WaterCloud.Code +{ + /// + /// 全局异常过滤器,MVC使用 + /// + public class GlobalExceptionFilter : IExceptionFilter, IAsyncExceptionFilter + { + public void OnException(ExceptionContext context) + { + LogHelper.WriteWithTime(context); + if (context.HttpContext.Request.IsAjaxRequest()) + { + AlwaysResult obj = new AlwaysResult(); + obj.state = ResultType.error.ToString(); + obj.message = context.Exception.GetOriginalException().Message; + if (string.IsNullOrEmpty(obj.message)) + { + obj.message = "抱歉,系统错误,请联系管理员!"; + } + context.Result = new JsonResult(obj); + context.ExceptionHandled = true; + } + else + { + //context.HttpContext.Response.WriteAsync(""); + context.Result = new RedirectResult(context.HttpContext.Request.PathBase + "/Home/Error?msg=500"); + context.ExceptionHandled = true; + } + } + + public Task OnExceptionAsync(ExceptionContext context) + { + OnException(context); + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Filter/GlobalExceptionMiddleware.cs b/WaterCloud.Code/Filter/GlobalExceptionMiddleware.cs new file mode 100644 index 0000000..d8c730b --- /dev/null +++ b/WaterCloud.Code/Filter/GlobalExceptionMiddleware.cs @@ -0,0 +1,47 @@ +using Microsoft.AspNetCore.Http; +using Newtonsoft.Json; +using System; +using System.Net; +using System.Threading.Tasks; + +namespace WaterCloud.Code +{ + /// + /// 全局异常中间件,api使用 + /// + public class GlobalExceptionMiddleware + { + private readonly RequestDelegate next; + + public GlobalExceptionMiddleware(RequestDelegate next) + { + this.next = next; + } + + public async Task Invoke(HttpContext context /* other dependencies */) + { + try + { + await next(context); + } + catch (Exception ex) + { + await HandleExceptionAsync(context, ex); + } + } + + private static Task HandleExceptionAsync(HttpContext context, Exception exception) + { + var code = HttpStatusCode.OK; + LogHelper.WriteWithTime(exception); + var result = JsonConvert.SerializeObject(new AlwaysResult + { + state = ResultType.error.ToString(), + message = exception.Message + }); + context.Response.ContentType = "application/json"; + context.Response.StatusCode = (int)code; + return context.Response.WriteAsync(result); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Filter/ModelActionFilter.cs b/WaterCloud.Code/Filter/ModelActionFilter.cs new file mode 100644 index 0000000..17ac71f --- /dev/null +++ b/WaterCloud.Code/Filter/ModelActionFilter.cs @@ -0,0 +1,31 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace WaterCloud.Code +{ + /// + /// 模型验证过滤器 + /// + public class ModelActionFilter : ActionFilterAttribute, IActionFilter + { + public override void OnActionExecuting(ActionExecutingContext context) + { + string message = ""; + if (!context.ModelState.IsValid) + { + foreach (var item in context.ModelState.Values) + { + foreach (var error in item.Errors) + { + message = message += error.ErrorMessage + "|"; + } + } + if (message.Length > 0) + { + message = message.Substring(0, message.Length - 1); + } + context.Result = new JsonResult(new AlwaysResult { state = ResultType.error.ToString(), message = message }); + } + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Flow/Flow.cs b/WaterCloud.Code/Flow/Flow.cs new file mode 100644 index 0000000..84e3a20 --- /dev/null +++ b/WaterCloud.Code/Flow/Flow.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace WaterCloud.Code +{ + public class Flow + { + public string title { get; set; } + public int initNum { get; set; } + public List lines { get; set; } + public List nodes { get; set; } + public List areas { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Flow/FlowArea.cs b/WaterCloud.Code/Flow/FlowArea.cs new file mode 100644 index 0000000..a777d27 --- /dev/null +++ b/WaterCloud.Code/Flow/FlowArea.cs @@ -0,0 +1,18 @@ +namespace WaterCloud.Code +{ + public class FlowArea + { + public string id { get; set; } + + public string name { get; set; } + + public string color { get; set; } + + public int left { get; set; } + public int top { get; set; } + + public int width { get; set; } + public int height { get; set; } + public bool alt { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Flow/FlowLine.cs b/WaterCloud.Code/Flow/FlowLine.cs new file mode 100644 index 0000000..f506150 --- /dev/null +++ b/WaterCloud.Code/Flow/FlowLine.cs @@ -0,0 +1,272 @@ +using Newtonsoft.Json.Linq; +using System.Collections.Generic; +using System.Linq; + +namespace WaterCloud.Code +{ + /// + /// 流程连线 + /// + public class FlowLine + { + public string id { get; set; } + public string label { get; set; } + public string type { get; set; } + public string from { get; set; } + public string to { get; set; } + public string name { get; set; } + public bool dash { get; set; } + public double M { get; set; } + public bool alt { get; set; } + + /// 分支条件 + public List Compares { get; set; } + + public bool Compare(JObject frmDataJson) + { + bool result = true; + foreach (var compare in Compares) + { + compare.FieldName = compare.FieldName.ToLower(); + compare.Value = compare.Value.ToLower(); + decimal value = 0; //参考值 + decimal frmvalue = 0; //表单中填写的值 + if (compare.Operation != DataCompare.Equal && compare.Operation != DataCompare.NotEqual) + { + value = decimal.Parse(compare.Value); + frmvalue = decimal.Parse(frmDataJson.GetValue(compare.FieldName.ToLower()).ToString()); //表单中填写的值 + } + bool res = false; + if (compare.Condition == "and") + { + switch (compare.Operation) + { + case DataCompare.Equal: + result &= compare.Value == frmDataJson.GetValue(compare.FieldName).ToString(); + break; + + case DataCompare.NotEqual: + result &= compare.Value != frmDataJson.GetValue(compare.FieldName).ToString(); + break; + + case DataCompare.Larger: + result &= frmvalue > value; + break; + + case DataCompare.Less: + result &= frmvalue < value; + break; + + case DataCompare.LargerEqual: + result &= frmvalue <= value; + break; + + case DataCompare.LessEqual: + result &= frmvalue <= value; + break; + + case DataCompare.In: + if (compare.FieldName == "申请人" || compare.FieldName == "所属部门") + { + var arr = compare.Value.Split(','); + foreach (var item in frmDataJson.GetValue(compare.FieldName).ToString().Split(',')) + { + if (arr.Contains(item)) + { + res = true; + break; + } + } + result &= res; + break; + } + else + { + var arr = compare.Value.Split(','); + if (arr.Contains(frmvalue.ToString())) + { + res = true; + break; + } + result &= res; + break; + } + case DataCompare.NotIn: + if (compare.FieldName == "申请人" || compare.FieldName == "所属部门") + { + var arr = compare.Value.Split(','); + foreach (var item in frmDataJson.GetValue(compare.FieldName).ToString().Split(',')) + { + if (arr.Contains(item)) + { + res = false; + break; + } + } + result &= res; + break; + } + else + { + var arr = compare.Value.Split(','); + if (arr.Contains(frmvalue.ToString())) + { + res = false; + break; + } + result &= res; + break; + } + } + } + else + { + switch (compare.Operation) + { + case DataCompare.Equal: + if (compare.FieldName == "申请人" || compare.FieldName == "所属部门") + { + var arr = compare.Value.Split(','); + foreach (var item in frmDataJson.GetValue(compare.FieldName).ToString().Split(',')) + { + if (arr.Contains(item)) + { + res = true; + break; + } + } + result |= res; + break; + } + result |= compare.Value == frmDataJson.GetValue(compare.FieldName).ToString(); + break; + + case DataCompare.NotEqual: + if (compare.FieldName == "申请人" || compare.FieldName == "所属部门") + { + var arr = compare.Value.Split(','); + foreach (var item in frmDataJson.GetValue(compare.FieldName).ToString().Split(',')) + { + if (arr.Contains(item)) + { + res = false; + break; + } + } + result |= res; + break; + } + result |= compare.Value != frmDataJson.GetValue(compare.FieldName).ToString(); + break; + + case DataCompare.Larger: + result |= frmvalue > value; + break; + + case DataCompare.Less: + result |= frmvalue < value; + break; + + case DataCompare.LargerEqual: + result |= frmvalue <= value; + break; + + case DataCompare.LessEqual: + result |= frmvalue <= value; + break; + + case DataCompare.In: + if (compare.FieldName == "申请人" || compare.FieldName == "所属部门") + { + var arr = compare.Value.Split(','); + foreach (var item in frmDataJson.GetValue(compare.FieldName).ToString().Split(',')) + { + if (arr.Contains(item)) + { + res = true; + break; + } + } + result |= res; + break; + } + else + { + var arr = compare.Value.Split(','); + if (arr.Contains(frmvalue.ToString())) + { + res = true; + } + result |= res; + break; + } + case DataCompare.NotIn: + if (compare.FieldName == "申请人" || compare.FieldName == "所属部门") + { + var arr = compare.Value.Split(','); + foreach (var item in frmDataJson.GetValue(compare.FieldName).ToString().Split(',')) + { + if (arr.Contains(item)) + { + res = false; + break; + } + } + result |= res; + break; + } + else + { + var arr = compare.Value.Split(','); + if (arr.Contains(frmvalue.ToString())) + { + res = false; + } + result |= res; + break; + } + } + } + } + + return result; + } + } + + /// + /// 分支条件 + /// + public class DataCompare + { + public const string Larger = ">"; + public const string Less = "<"; + public const string LargerEqual = ">="; + public const string LessEqual = "<="; + public const string NotEqual = "!="; + public const string Equal = "="; + public const string In = "in"; + public const string NotIn = "not in"; + + /// 操作类型比如大于/等于/小于 + public string Operation { get; set; } + + /// form种的字段名称 + public string FieldName { get; set; } + + /// 字段类型:"form":为表单中的字段,后期扩展系统表等. + public string FieldType { get; set; } + + /// 实际的值 + public string Value { get; set; } + + /// + /// 显示值 + /// + public string Name { get; set; } + + /// + /// 条件关系 + /// + public string Condition { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Flow/FlowNode.cs b/WaterCloud.Code/Flow/FlowNode.cs new file mode 100644 index 0000000..8c43674 --- /dev/null +++ b/WaterCloud.Code/Flow/FlowNode.cs @@ -0,0 +1,131 @@ +namespace WaterCloud.Code +{ + /// + /// 流程节点 + /// + public class FlowNode + { + public const string START = "start round mix"; + public const string END = "end round"; + public const string NODE = "node"; + public const string FORK = "fork"; //会签开始节点 + public const string JOIN = "join"; //会签结束节点 + + public string id { get; set; } + + public string name { get; set; } + + public string type { get; set; } + + public int left { get; set; } + public int top { get; set; } + + public int width { get; set; } + public int height { get; set; } + public bool alt { get; set; } + + /// + /// 节点的附加数据项 + /// + /// The set information. + public Setinfo setInfo { get; set; } + } + + public class Setinfo + { + public const string SPECIAL_USER = "SPECIAL_USER"; //指定用户 + public const string ALL_USER = "ALL_USER"; //所有用户 + public const string SPECIAL_ROLE = "SPECIAL_ROLE"; //指定角色 + public const string DEPARTMENT_MANAGER = "DEPARTMENT_MANAGER"; //部门负责人 + public const string USER_MANAGER = "USER_MANAGER"; //直属上级 + public const string MORE_USER_MANAGER = "MORE_USER_MANAGER"; //连续多级直属上级 + public const string RUNTIME_SPECIAL_ROLE = "RUNTIME_SPECIAL_ROLE"; //运行时指定角色 + public const string RUNTIME_SPECIAL_USER = "RUNTIME_SPECIAL_USER"; //运行时指定用户 + + /// + /// 节点执行权限类型 + /// + public string NodeDesignate { get; set; } + + public Nodedesignatedata NodeDesignateData { get; set; } + public string NodeCode { get; set; } + public string NodeName { get; set; } + + /// + /// 流程执行时,三方回调的URL地址 + /// + public string ThirdPartyUrl { get; set; } + + /// + /// 驳回节点0"前一步"1"第一步"2"某一步" 3"不处理" + /// + public string NodeRejectType { get; set; } + + public int? Taged { get; set; } + public string UserName { get; set; } + public string UserId { get; set; } + public string Description { get; set; } + public string TagedTime { get; set; } + + //节点会签方式, + //all/空:默认为全部通过 + //one :至少有一个通过 + public string NodeConfluenceType { get; set; } + + /// + /// 会签通过的个数 + /// + public int? ConfluenceOk { get; set; } + + /// + /// 会签拒绝的个数 + /// + public int? ConfluenceNo { get; set; } + + /// + /// 可写的表单项ID + /// + public string[] CanWriteFormItemIds { get; set; } + } + + /// + /// 节点执行人 + /// + public class Nodedesignatedata + { + public string[] users { get; set; } + public string[] roles { get; set; } + public string[] orgs { get; set; } + public bool currentDepart { get; set; } + } + + /// + /// 节点执行结果标签 + /// + public class Tag + { + /// + /// 1: 通过 + /// 2:不通过 + /// 3:驳回 + /// + public int Taged { get; set; } + + public string UserId { get; set; } + public string UserName { get; set; } + public string Description { get; set; } + public string TagedTime { get; set; } + } + + /// + /// 1: 通过 + /// 2:不通过 + /// 3:驳回 + /// + public enum TagState + { + Ok = 1, + No, + Reject + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Form/FormUtil.cs b/WaterCloud.Code/Form/FormUtil.cs new file mode 100644 index 0000000..863795d --- /dev/null +++ b/WaterCloud.Code/Form/FormUtil.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; + +namespace WaterCloud.Code +{ + public class FormUtil + { + /// + /// 获取值 + /// + /// The form. + /// System.String. + public static List SetValue(string content) + { + List list = JsonHelper.ToObject>(content); + List temp = new List(); + SetFormValue(list, temp); + return temp; + } + + private static List SetFormValue(List list, List temp) + { + foreach (var item in list) + { + if (item.tag == "grid") + { + foreach (var column in item.columns) + { + SetFormValue(column.list, temp); + } + } + else + { + temp.Add(item.id); + } + } + return temp; + } + + public static List SetValueByWeb(string webForm) + { + var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory; + var referencedAssemblies = Directory.GetFiles(path, "*.dll").Select(Assembly.LoadFrom).ToArray(); + var t = referencedAssemblies + .SelectMany(a => a.GetTypes().Where(t => t.FullName.Contains("WaterCloud.Domain.") && t.FullName.Contains("." + webForm + "Entity"))).First(); + List temp = new List(); + PropertyInfo[] pArray = t.GetProperties(); + Array.ForEach(pArray, p => + { + temp.Add(p.Name); + }); + return temp; + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Form/FormValue.cs b/WaterCloud.Code/Form/FormValue.cs new file mode 100644 index 0000000..edf3e12 --- /dev/null +++ b/WaterCloud.Code/Form/FormValue.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; + +namespace WaterCloud.Code +{ + /// + /// 表单设计类 + /// + public class FormValue + { + public string id { get; set; } + public string label { get; set; } + public int index { get; set; } + public string tag { get; set; } + public int span { get; set; } + public List columns { get; set; } + public string name { get; set; } + } + + public class FormEx + { + public int span { get; set; } + public List list { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Globals/GlobalContext.cs b/WaterCloud.Code/Globals/GlobalContext.cs new file mode 100644 index 0000000..4ab9d24 --- /dev/null +++ b/WaterCloud.Code/Globals/GlobalContext.cs @@ -0,0 +1,254 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.StaticFiles; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyModel; +using Microsoft.Extensions.Hosting; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using System.Text; +using WaterCloud.Code.Model; + +namespace WaterCloud.Code +{ + public static class GlobalContext + { + + /// + /// 构造函数 + /// + static GlobalContext() + { + // 未托管的对象 + UnmanagedObjects = new ConcurrentBag(); + Assemblies = GetAssemblies(); + EffectiveTypes = Assemblies.SelectMany(GetTypes); + } + /// + /// 服务集合 + /// + public static IServiceCollection Services { get; set; } + + /// + /// 根服务 + /// + public static IServiceProvider RootServices { get; set; } + + public static IConfiguration Configuration { get; set; } + + public static IWebHostEnvironment HostingEnvironment { get; set; } + + /// + /// 未托管的对象集合 + /// + public static readonly ConcurrentBag UnmanagedObjects; + + public static HttpContext HttpContext => RootServices?.GetService()?.HttpContext; + + public static SystemConfig SystemConfig { get; set; } + + + /// + /// 应用有效程序集(类型为project,项目应用的,不包括包和手动应用) + /// + public static readonly IEnumerable Assemblies; + /// + /// 有效程序集类型 + /// + public static readonly IEnumerable EffectiveTypes; + /// + /// 获取请求生存周期的服务(未注册返回null) + /// + /// + /// + /// + public static TService GetService(IServiceProvider serviceProvider = null) where TService : class + { + return GetService(typeof(TService), serviceProvider) as TService; + } + + /// + /// 获取请求生存周期的服务(未注册返回null) + /// + /// + /// + /// + public static object GetService(Type type, IServiceProvider serviceProvider = null) + { + return (serviceProvider ?? GetServiceProvider(type)).GetService(type); + } + + /// + /// 获取请求生存周期的服务(未注册异常) + /// + /// + /// + /// + public static TService GetRequiredService(IServiceProvider serviceProvider = null) where TService : class + { + return GetRequiredService(typeof(TService), serviceProvider) as TService; + } + + /// + /// 获取请求生存周期的服务(未注册异常) + /// + /// + /// + /// + public static object GetRequiredService(Type type, IServiceProvider serviceProvider = null) + { + return (serviceProvider ?? GetServiceProvider(type)).GetRequiredService(type); + } + + /// + /// 获取服务注册器 + /// + /// + /// + public static IServiceProvider GetServiceProvider(Type serviceType) + { + if (HostingEnvironment == null) + { + return RootServices; + } + if (RootServices != null && Services.Where((ServiceDescriptor u) => u.ServiceType == (serviceType.IsGenericType ? serviceType.GetGenericTypeDefinition() : serviceType)).Any((ServiceDescriptor u) => u.Lifetime == ServiceLifetime.Singleton)) + { + return RootServices; + } + // 第二选择是获取 HttpContext 对象的 RequestServices + var httpContext = HttpContext; + if (httpContext?.RequestServices != null) return httpContext.RequestServices; + // 第三选择,创建新的作用域并返回服务提供器 + else if (RootServices != null) + { + var scoped = RootServices.CreateScope(); + UnmanagedObjects.Add(scoped); + return scoped.ServiceProvider; + } + // 第四选择,构建新的服务对象(性能最差) + else + { + var serviceProvider = Services.BuildServiceProvider(); + UnmanagedObjects.Add(serviceProvider); + return serviceProvider; + } + } + + + /// + /// GC 回收默认间隔 + /// + private const int GC_COLLECT_INTERVAL_SECONDS = 5; + + /// + /// 记录最近 GC 回收时间 + /// + private static DateTime? LastGCCollectTime { get; set; } + + /// + /// 释放所有未托管的对象 + /// + public static void DisposeUnmanagedObjects() + { + foreach (var dsp in UnmanagedObjects) + { + try + { + dsp?.Dispose(); + } + finally { } + } + + // 强制手动回收 GC 内存 + if (UnmanagedObjects.Any()) + { + var nowTime = DateTime.UtcNow; + if ((LastGCCollectTime == null || (nowTime - LastGCCollectTime.Value).TotalSeconds > GC_COLLECT_INTERVAL_SECONDS)) + { + LastGCCollectTime = nowTime; + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + } + + UnmanagedObjects.Clear(); + } + /// + /// 获取版本号 + /// + /// + public static string GetVersion() + { + Version version = Assembly.GetEntryAssembly().GetName().Version; + return version.ToString(); + } + /// + /// 获取请求跟踪 Id + /// + /// + public static string GetTraceId() + { + return Activity.Current?.Id ?? (RootServices == null ? default : HttpContext?.TraceIdentifier); + } + /// + /// 程序启动时,记录目录 + /// + /// + public static void LogWhenStart(IWebHostEnvironment env) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine("程序启动"); + sb.AppendLine("ContentRootPath:" + env.ContentRootPath); + sb.AppendLine("WebRootPath:" + env.WebRootPath); + sb.AppendLine("IsDevelopment:" + env.IsDevelopment()); + LogHelper.WriteWithTime(sb.ToString()); + } + + /// + /// 设置cache control + /// + /// + public static void SetCacheControl(StaticFileResponseContext context) + { + int second = 365 * 24 * 60 * 60; + context.Context.Response.Headers.Add("Cache-Control", new[] { "public,max-age=" + second }); + context.Context.Response.Headers.Add("Expires", new[] { DateTime.UtcNow.AddYears(1).ToString("R") }); // Format RFC1123 + } + public static IEnumerable GetAssemblies() + { + var projects = DependencyContext + .Default + .RuntimeLibraries + .Where(u => u.Type == "project" || u.Type == "reference") + .Select(u => AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(u.Name))); + + return projects; + } + /// + /// 加载程序集中的所有类型 + /// + /// + /// + private static IEnumerable GetTypes(Assembly ass) + { + var types = Array.Empty(); + + try + { + types = ass.GetTypes(); + } + catch + { + Console.WriteLine($"Error load `{ass.FullName}` assembly."); + } + + return types.Where(u => u.IsPublic); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/LayUI/FilterSo.cs b/WaterCloud.Code/LayUI/FilterSo.cs new file mode 100644 index 0000000..f2625f0 --- /dev/null +++ b/WaterCloud.Code/LayUI/FilterSo.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; + +namespace WaterCloud.Code +{ + public class FilterSo + { + /** + * 唯一id + */ + public long id { get; set; } + /** + * 前缀 and、or + */ + public string prefix { get; set; } + /** + * 模式 in、condition、date + */ + public string mode { get; set; } + /** + * 字段名 + */ + public string field { get; set; } + /** + * 筛选类型 + */ + public string type { get; set; } + /** + * 是否有分隔符 + */ + public string split { get; set; } + /** + * 筛选值 + */ + public string value { get; set; } + /** + * 筛选值 + */ + public List values { get; set; } + + /** + * 子组数据 + */ + public List children { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/LayUI/SoulPage.cs b/WaterCloud.Code/LayUI/SoulPage.cs new file mode 100644 index 0000000..902bb02 --- /dev/null +++ b/WaterCloud.Code/LayUI/SoulPage.cs @@ -0,0 +1,210 @@ +using Serenity; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace WaterCloud.Code +{ + /// + ///封装table查询数据 + /// + /// + public class SoulPage + { + /** + * layui表格必须参数⬇⬇⬇⬇⬇⬇ + */ + public int state { get; set; } + public string message { get; set; } + /** + * 总记录 + */ + public int count { get; set; } + /** + * 显示的记录 + */ + public List data { get; set; } + + /** + * 请求条件 + */ + public object obj { get; set; } + /** + * 查询条件 + */ + public Dictionary condition = new Dictionary(); + /** + * 请求参数⬇⬇⬇⬇⬇⬇ + */ + /** + * 当前页 从1开始 + */ + public int page { get; set; } + /** + * 页大小 + */ + public int rows { get; set; } + /** + * 查询列数据 + */ + public string columns { get; set; } + + /** + * 表格列类型 + */ + public string tableFilterType { get; set; } + /** + * 筛选信息 + */ + public string filterSos { get; set; } + + /** + * 排序信息 + */ + public string field { get; set; } + + public string order { get; set; } + + public SoulPage() + { + this.state = 0; + this.message = ""; + this.page = 1; + this.rows = 100000000; + this.order = "asc"; + } + + public SoulPage(int page, int limit) + { + this.state = 0; + this.message = ""; + this.page = 1; + this.rows = 100000000; + this.order = "asc"; + this.page = page; + this.rows = limit; + } + + public List getFilterSos() + { + if (string.IsNullOrEmpty(filterSos)) + { + return new List(); + } + return filterSos.ToObject>(); + } + + public bool isColumn() + { + return getColumns().Count > 0; + } + + public int getOffset() + { + return (page - 1) * rows; + } + + public List getColumns() + { + return !string.IsNullOrEmpty(columns) ? columns.ToObject>() : new List(); + } + + private string dateFormat(DateTime date, string format) + { + if (string.IsNullOrEmpty(format)) + { + return date.ToString("yyyy-MM-dd HH:mm:ss"); + } + else + { + return date.ToString(format); + } + } + + public Dictionary> getTypeMap() + { + Dictionary> typeMap = new Dictionary>(); + if (!string.IsNullOrEmpty(tableFilterType)) + { + Dictionary filterType = tableFilterType.ToObject>(); + foreach (var item in filterType) + { + Dictionary map = new Dictionary(); + map.Add("type", item.Value.Substring(0, item.Value.IndexOf("["))); + int IndexofA = item.Value.IndexOf('['); //字符串的话总以第一位为指定位置 + int IndexofB = item.Value.IndexOf(']'); + map.Add("value", item.Value.Substring(IndexofA + 1, IndexofB - IndexofA - 1)); + typeMap.Add(item.Key, map); + }; + } + return typeMap; + } + + public string getFormatValue(Dictionary> typeMap, string column, object columnObject) + { + string columnValue; + if (typeMap.ContainsKey(column)) + { + if ("date".Equals(typeMap.Get(column).Get("type")) && columnObject is DateTime) + { + columnValue = dateFormat((DateTime)columnObject, typeMap.Get(column).Get("value")); + } + else + { + columnValue = columnObject.ToString(); + } + } + else + { + if (columnObject is DateTime || columnObject is Nullable) + { + columnValue = dateFormat((DateTime)columnObject, null); + } + else if (columnObject is bool || columnObject is Nullable) + { + columnValue = (bool)columnObject == true ? "1" : "0"; + } + else + { + columnValue = columnObject.ToString(); + } + } + return columnValue; + } + + public Object setData(List data) + { + if (isColumn()) + { + Dictionary> typeMap = getTypeMap(); + Dictionary> columnMap = new Dictionary>(); + foreach (T datum in data) + { + foreach (string column in getColumns()) + { + if (!columnMap.ContainsKey(column)) + { + columnMap.Add(column, new HashSet()); + } + var columnObject = ReflectionHelper.GetObjectPropertyValue(datum, column); + if (columnObject != null) + { //空值不展示 + columnMap.Get(column).Add(getFormatValue(typeMap, column, columnObject)); + } + } + } + Dictionary> columnSortMap = new Dictionary>(); + foreach (var item in columnMap) + { + columnSortMap.Add(item.Key, item.Value.ToList()); + } + return columnSortMap; + } + else + { + this.data = data; + return this; + } + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/LayUI/TableCols.cs b/WaterCloud.Code/LayUI/TableCols.cs new file mode 100644 index 0000000..1143a70 --- /dev/null +++ b/WaterCloud.Code/LayUI/TableCols.cs @@ -0,0 +1,83 @@ +namespace WaterCloud.Code +{ + /// + /// LayUI Table 列 + /// + public class TableCols + { + /// + /// 类型(normal(常规列)、checkbox(复选框)、radio(单选框)、numbers(序号)、space(空)) + /// + public string type { get; set; } + + /// + /// 字段 + /// + public string field { get; set; } + + /// + /// 标题 + /// + public string title { get; set; } + + /// + /// 宽度 + /// + public int? width { get; set; } + + /// + /// 最小宽度 + /// + public int? minWidth { get; set; } + + /// + /// 是否全选 + /// + public bool? LAY_CHECKED { get; set; } + + /// + /// 固定列 + /// + public string Fixed { get; set; } + + /// + /// 隐藏 + /// + public string hide { get; set; } + + /// + /// 排序 + /// + public bool? sort { get; set; } + + /// + /// 是否禁用拖到列 + /// + public bool? unresize { get; set; } + + /// + /// 样式 + /// + public string style { get; set; } + + /// + /// 对齐方式 + /// + public string align { get; set; } + + /// + /// 所占列数 + /// + public int? colspan { get; set; } + + /// + /// 所占行数 + /// + public int? rowspan { get; set; } + + /// + /// 绑定工具栏模板 + /// + public string toolbar { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Model/ApiToken.cs b/WaterCloud.Code/Model/ApiToken.cs new file mode 100644 index 0000000..fe7813b --- /dev/null +++ b/WaterCloud.Code/Model/ApiToken.cs @@ -0,0 +1,15 @@ +using System.ComponentModel; +using System.ComponentModel.DataAnnotations.Schema; + +namespace WaterCloud.Code.Model +{ + /// + /// 这个是移动端Api用的 + /// + public class BaseApiToken + { + [NotMapped] + [Description("WebApi没有Cookie和Session,所以需要传入Token来标识用户身份,请加在Url后面")] + public string Token { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Model/AppLogEntity.cs b/WaterCloud.Code/Model/AppLogEntity.cs new file mode 100644 index 0000000..857cad7 --- /dev/null +++ b/WaterCloud.Code/Model/AppLogEntity.cs @@ -0,0 +1,7 @@ +namespace WaterCloud.Code.Model +{ + public class AppLogEntity + { + public string FileName { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Model/DbLogType.cs b/WaterCloud.Code/Model/DbLogType.cs new file mode 100644 index 0000000..c1d7c24 --- /dev/null +++ b/WaterCloud.Code/Model/DbLogType.cs @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright © 2020 WaterCloud.Framework 版权所有 + * Author: WaterCloud + * Description: WaterCloud快速开发平台 + * Website: +*********************************************************************************/ + +using System.ComponentModel; + +namespace WaterCloud.Code +{ + public enum DbLogType + { + [Description("其他")] + Other = 0, + + [Description("登录")] + Login = 1, + + [Description("退出")] + Exit = 2, + + [Description("访问")] + Visit = 3, + + [Description("新增")] + Create = 4, + + [Description("删除")] + Delete = 5, + + [Description("修改")] + Update = 6, + + [Description("提交")] + Submit = 7, + + [Description("异常")] + Exception = 8, + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Model/Define.cs b/WaterCloud.Code/Model/Define.cs new file mode 100644 index 0000000..fc11849 --- /dev/null +++ b/WaterCloud.Code/Model/Define.cs @@ -0,0 +1,18 @@ +namespace WaterCloud.Code +{ + public static class Define + { + public const string PROVIDER_COOKIE = "Cookie"; + public const string PROVIDER_SESSION = "Session"; + public const string PROVIDER_WEBAPI = "WebApi"; + + public const string CACHEPROVIDER_REDIS = "Redis"; + public const string CACHEPROVIDER_MEMORY = "Memory"; + + public const string DATAPRIVILEGE_LOGINUSER = "{loginUser}"; //数据权限配置中,当前登录用户的key + public const string DATAPRIVILEGE_LOGINROLE = "{loginRole}"; //数据权限配置中,当前登录用户角色的key + public const string DATAPRIVILEGE_LOGINORG = "{loginOrg}"; //数据权限配置中,当前登录用户部门的key + public const string SQL_MORE = "MoreSql";//多库 + public const string SQL_TENANT = "TenantSql";//多租户 + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Model/Filter.cs b/WaterCloud.Code/Model/Filter.cs new file mode 100644 index 0000000..320c905 --- /dev/null +++ b/WaterCloud.Code/Model/Filter.cs @@ -0,0 +1,22 @@ +namespace WaterCloud.Code +{ + public class Filter + { + public string Key { get; set; } + public string Value { get; set; } + public string Contrast { get; set; } + + public string Text { get; set; } + } + + public class FilterList + { + /// + /// and + /// + public string Operation { get; set; } + + public string Filters { get; set; } + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Model/KeyValue.cs b/WaterCloud.Code/Model/KeyValue.cs new file mode 100644 index 0000000..441c641 --- /dev/null +++ b/WaterCloud.Code/Model/KeyValue.cs @@ -0,0 +1,9 @@ +namespace WaterCloud.Code +{ + public class KeyValue + { + public string Key { get; set; } + public string Value { get; set; } + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Model/PrintEntity.cs b/WaterCloud.Code/Model/PrintEntity.cs new file mode 100644 index 0000000..9cce8e9 --- /dev/null +++ b/WaterCloud.Code/Model/PrintEntity.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WaterCloud.Code.Model +{ + public class PrintEntity + { + public string cmd { get; set; } = "print"; + public string requestId { get; set; } + public PrintDetail data { get; set; } + } + public class PrintDetail + { + public PrintInitInfo printIniInfo { get; set; } + public object data { get; set; } + } + public class PrintInitInfo + { + public string filePath { get; set; } + public string realName { get; set; } + public int? printType { get; set; } = 1; + public string printName { get; set; } = ""; + public bool landscape { get; set; } = true; + public string paperSize { get; set; } + public string duplex { get; set; } + public bool? isBatch { get; set; } = false; + } +} diff --git a/WaterCloud.Code/Model/SystemConfig.cs b/WaterCloud.Code/Model/SystemConfig.cs new file mode 100644 index 0000000..f02f396 --- /dev/null +++ b/WaterCloud.Code/Model/SystemConfig.cs @@ -0,0 +1,185 @@ +using System.Collections.Generic; + +namespace WaterCloud.Code.Model +{ + public class SystemConfig + { + /// + /// 是否是Demo模式 + /// + public bool Demo { get; set; } + + /// + /// 是否是调试模式 + /// + public bool Debug { get; set; } + + /// + /// 允许一个用户在多个电脑同时登录 + /// + public bool LoginMultiple { get; set; } + + /// + /// 允许跨域的站点 + /// + public string AllowCorsSite { get; set; } + + /// + /// 主库数据库类型 + /// + public string DBProvider { get; set; } + + /// + /// 主库数据库连接 + /// + public string DBConnectionString { get; set; } + + /// + /// 数据库连接超时 + /// + public int DBCommandTimeout { get; set; } + + /// + /// 是否初始化数据库 + /// + public bool IsInitDb { get; set; } + + /// + /// 是否初始化种子数据 + /// + public bool IsSeedData { get; set; } + + /// + /// 缓存类型 + /// + public string CacheProvider { get; set; } + + /// + /// redis连接串 + /// + public string RedisConnectionString { get; set; } + + /// + /// api token名称 + /// + public string TokenName { get; set; } + + //缓存过期时间 + public int LoginExpire { get; set; } + + /// + /// 主页 + /// + public string HomePage { get; set; } + + /// + /// 是否局域网 + /// + public bool? LocalLAN { get; set; } + + /// + /// 数据库模式 + /// + public string SqlMode { get; set; } + + /// + /// 项目前缀 + /// + public string ProjectPrefix { get; set; } + + /// + /// 是否重置密码 + /// + public bool? ReviseSystem { get; set; } + + /// + /// 登录错误次数 + /// + public int? LoginErrorCount { get; set; } + + /// + /// 多数据库组 + /// + public List SqlConfig { get; set; } + + /// + /// 是否集群 + /// + public bool? IsCluster { get; set; } + + /// + /// 是否删除定时调度任务 + /// + public bool? NeedClear { get; set; } + + /// + /// 主程序数据库编号 + /// + public string MainDbNumber { get; set; } + + /// + /// 是否开启定时任务 + /// + public bool? OpenQuartz { get; set; } + + /// + /// api文档配置 + /// + public DocumentSettings DocumentSettings { get; set; } + + /// + /// rabbitmq配置 + /// + public MqConfig RabbitMq { get; set; } + } + + public class DocumentSettings + { + /// + /// 标题 + /// + public string DocumentTitle { get; set; } + public List GroupOpenApiInfos { get; set; } + } + + public class GroupOpenApiInfo + { + /// + /// 分组 + /// + public string Group { get; set; } + + /// + /// 组标题 + /// + public string Title { get; set; } + + /// + /// 描述 + /// + public string Description { get; set; } + + /// + /// 版本 + /// + public string Version { get; set; } + } + + public class DBConfig + { + /// + /// 数据库序号 + /// + public string DBNumber { get; set; } + + /// + /// 数据库类型 + /// + public string DBProvider { get; set; } + + /// + /// 数据库连接 + /// + public string DBConnectionString { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Operator/OperatorModel.cs b/WaterCloud.Code/Operator/OperatorModel.cs new file mode 100644 index 0000000..ace445f --- /dev/null +++ b/WaterCloud.Code/Operator/OperatorModel.cs @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright © 2016 WaterCloud.Framework 版权所有 + * Author: WaterCloud + * Description: WaterCloud快速开发平台 + * Website: +*********************************************************************************/ + +using System; + +namespace WaterCloud.Code +{ + /// + /// 当前用户信息 + /// + public class OperatorModel + { + public string UserId { get; set; } + public string UserCode { get; set; } + public string UserName { get; set; } + public string UserPwd { get; set; } + public string CompanyId { get; set; } + public string OrganizeId { get; set; } + public string RoleId { get; set; } + public string LoginIPAddress { get; set; } + public string LoginIPAddressName { get; set; } + public string LoginToken { get; set; } + public DateTime LoginTime { get; set; } + + //超管 + public bool IsSuperAdmin { get; set; } + + public bool IsAdmin { get; set; } + public bool IsBoss { get; set; } + public bool IsSenior { get; set; } + public bool IsSaleman { get; set; } + + // 拓展字段,2019-03-03 + public string DdUserId { get; set; } + + public string WxOpenId { get; set; } + public string Avatar { get; set; } + public string loginMark { get; set; } + + //扩展字段 数据库序号,2021-05-12 + public string DbNumber { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Operator/OperatorProvider.cs b/WaterCloud.Code/Operator/OperatorProvider.cs new file mode 100644 index 0000000..ffa6de9 --- /dev/null +++ b/WaterCloud.Code/Operator/OperatorProvider.cs @@ -0,0 +1,395 @@ +/******************************************************************************* + * Copyright © 2016 WaterCloud.Framework 版权所有 + * Author: WaterCloud + * Description: WaterCloud快速开发平台 + * Website: +*********************************************************************************/ + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace WaterCloud.Code +{ + public class OperatorProvider + { + //是否允许一个账户在多处登录 + private static bool LoginMultiple = GlobalContext.SystemConfig.LoginMultiple; + + //缓存过期时间 + private static int LoginExpire = GlobalContext.SystemConfig.LoginExpire; + + private static string projectPrefix = GlobalContext.SystemConfig.ProjectPrefix; + + public static OperatorProvider Provider + { + get { return new OperatorProvider(); } + } + + //watercloud_operator_pc_ PC端登录 + //watercloud_operator_info_ 登录次数 + // + /// + /// 缓存操作类 + /// + private string cacheKeyOperator = projectPrefix + "_operator_";// +登录者token + + private string cacheKeyToken = projectPrefix + "_token_";// +登录者token + private string cacheKeyError = projectPrefix + "_error_";// + Mark + + /// + /// 秘钥 + /// + private string LoginUserToken = projectPrefix + "_Token"; + + /// + /// 标记登录的浏览器 + /// + private string LoginUserMarkKey = projectPrefix + "_Mark"; + + public string GetProvider(string key) + { + var token = GetToken(); + if (!string.IsNullOrEmpty(token)) + return token; + token = WebHelper.GetCookie(key).ToString(); + if (!string.IsNullOrEmpty(token)) + return token; + return WebHelper.GetSession(key).ToString(); + } + + public void SetProvider(string key, string value) + { + WebHelper.WriteCookie(key, value); + WebHelper.WriteSession(key, value); + } + + public string GetToken() + { + try + { + if (GlobalContext.HttpContext == null) + { + return null; + } + //查请求头 + string token = GlobalContext.HttpContext.Request.Headers[GlobalContext.SystemConfig.TokenName].ParseToString(); + if (!String.IsNullOrEmpty(token)) return token; + + //查参数 + token = GlobalContext.HttpContext.Request.Query[GlobalContext.SystemConfig.TokenName]; + if (!String.IsNullOrEmpty(token)) return token; + + //查cookies + string cookie = GlobalContext.HttpContext.Request.Cookies[GlobalContext.SystemConfig.TokenName]; + return cookie == null ? string.Empty : cookie; + } + catch (Exception) + { + return null; + } + } + + public void RemoveProvider(string key) + { + WebHelper.RemoveCookie(key); + WebHelper.RemoveSession(key); + } + + public OperatorModel GetCurrent() + { + OperatorModel operatorModel = new OperatorModel(); + try + { + string loginMark = GetProvider(LoginUserMarkKey); + operatorModel = CacheHelper.Get(cacheKeyOperator + loginMark); + } + catch + { + operatorModel = null; + } + return operatorModel; + } + + /// + /// 获取浏览器设配号 + /// + /// + public string GetMark() + { + string cookieMark = GetProvider(LoginUserMarkKey); + if (string.IsNullOrEmpty(cookieMark)) + { + cookieMark = Guid.NewGuid().ToString(); + SetProvider(LoginUserMarkKey, cookieMark); + } + return cookieMark; + } + + /// + /// 登录者信息添加到缓存中 + /// + /// 用户 + /// 设备标识uid + /// 设备类型 + /// 是否保存cookie,默认是 + /// + public async Task AddLoginUser(OperatorModel operatorModel, string loginMark, string facilityMark) + { + string token = Guid.NewGuid().ToString(); + try + { + // 填写登录信息 + operatorModel.LoginToken = token; + //登录信息更新 + if (string.IsNullOrEmpty(loginMark)) + { + string cookieMark = GetProvider(LoginUserMarkKey); + if (string.IsNullOrEmpty(cookieMark)) + { + operatorModel.loginMark = Guid.NewGuid().ToString(); + SetProvider(LoginUserMarkKey, operatorModel.loginMark); + } + else + { + operatorModel.loginMark = cookieMark; + } + SetProvider(LoginUserToken, token); + } + else + { + operatorModel.loginMark = loginMark; + RemoveProvider(LoginUserMarkKey); + } + //redis 登录token列表更新 + Dictionary tokenMarkList = await CacheHelper.GetAsync>(cacheKeyToken + operatorModel.UserId); + if (tokenMarkList == null)// 此账号第一次登录 + { + tokenMarkList = new Dictionary(); + tokenMarkList.Add(operatorModel.loginMark, token); + } + else + { + if (tokenMarkList.ContainsKey(operatorModel.loginMark)) + { + tokenMarkList[operatorModel.loginMark] = token; + } + else + { + tokenMarkList.Add(operatorModel.loginMark, token); + } + } + + await CacheHelper.SetAsync(cacheKeyToken + operatorModel.UserId, tokenMarkList); + await CacheHelper.SetAsync(cacheKeyOperator + operatorModel.loginMark, operatorModel, LoginExpire); + await CacheHelper.RemoveAsync(cacheKeyOperator + facilityMark + operatorModel.UserId); + await CacheHelper.SetAsync(cacheKeyOperator + facilityMark + operatorModel.UserId, token, LoginExpire); + return token; + } + catch (Exception) + { + throw; + } + } + + /// + /// 清空当前登录信息 + /// + /// apitoken + /// 设备类型 + public async Task EmptyCurrent(string facilityMark) + { + try + { + string token = GetProvider(LoginUserToken); + string loginMark = GetProvider(LoginUserMarkKey); + await EmptyCurrent(token, facilityMark, loginMark); + RemoveProvider(LoginUserMarkKey.Trim()); + RemoveProvider(LoginUserToken.Trim()); + } + catch (Exception) + { + } + } + + /// + /// 清空当前登录信息 + /// + /// 登录票据 + /// 登录设备 + /// 登录设备标识 + public async Task EmptyCurrent(string token, string facilityMark, string loginMark) + { + try + { + OperatorModel operatorInfo = await CacheHelper.GetAsync(cacheKeyOperator + loginMark); + if (operatorInfo != null) + { + Dictionary tokenMarkList = await CacheHelper.GetAsync>(cacheKeyToken + operatorInfo.UserId); + tokenMarkList.Remove(loginMark); + await CacheHelper.RemoveAsync(cacheKeyOperator + loginMark); + if (operatorInfo.LoginToken == token || facilityMark == "api_") + { + await CacheHelper.RemoveAsync(cacheKeyOperator + facilityMark + operatorInfo.UserId); + } + await CacheHelper.SetAsync(cacheKeyToken + operatorInfo.UserId, tokenMarkList); + await CacheHelper.RemoveAsync(facilityMark + GlobalContext.SystemConfig.TokenName + "_" + operatorInfo.UserId + "_" + operatorInfo.LoginTime); + } + } + catch (Exception) + { + } + } + + /// + /// 判断登录状态 + /// + /// 登录设备 + /// apitoken + /// -1未登录,1登录成功,0登录过期,-2账号被顶 + public async Task IsOnLine(string facilityMark) + { + try + { + string token = GetProvider(LoginUserToken); + string loginMark = GetProvider(LoginUserMarkKey); + return await IsOnLine(token, facilityMark, loginMark); + } + catch (Exception) + { + return new OperatorResult { stateCode = -1 }; + } + } + + /// + /// 判断登录状态 + /// + /// 登录票据 + /// 登录设备 + /// 登录设备标识 + /// -1未登录,1登录成功,0登录过期,-2账号被顶 + public async Task IsOnLine(string token, string facilityMark, string loginMark) + { + OperatorResult operatorResult = new OperatorResult(); + operatorResult.stateCode = -1; // -1未登录,1登录成功,0登录过期 + try + { + if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(loginMark)) + { + return operatorResult; + } + OperatorModel operatorInfo = await CacheHelper.GetAsync(cacheKeyOperator + loginMark); + if (operatorInfo != null) + { + Dictionary tokenMarkList = await CacheHelper.GetAsync>(cacheKeyToken + operatorInfo.UserId); + if ((token == operatorInfo.LoginToken || facilityMark == "api_") && tokenMarkList.ContainsKey(operatorInfo.loginMark) && tokenMarkList[operatorInfo.loginMark] == operatorInfo.LoginToken) + { + ////账号被顶(排除admin) + if (!LoginMultiple && !operatorInfo.IsSuperAdmin && operatorInfo.LoginToken != await CacheHelper.GetAsync(cacheKeyOperator + facilityMark + operatorInfo.UserId)) + { + operatorResult.stateCode = -2; + tokenMarkList = await CacheHelper.GetAsync>(cacheKeyToken + operatorInfo.UserId); + tokenMarkList.Remove(loginMark); + await CacheHelper.SetAsync(cacheKeyToken + operatorInfo.UserId, tokenMarkList); + await CacheHelper.RemoveAsync(cacheKeyOperator + loginMark); + } + else + { + operatorResult.userInfo = operatorInfo; + operatorResult.stateCode = 1; + await CacheHelper.ExpireAsync(cacheKeyOperator + loginMark, LoginExpire); + await CacheHelper.ExpireAsync(cacheKeyOperator + facilityMark + operatorInfo.UserId, LoginExpire); + await CacheHelper.ExpireAsync(facilityMark + GlobalContext.SystemConfig.TokenName + "_" + operatorInfo.UserId + "_" + operatorInfo.LoginTime, LoginExpire); + } + } + } + return operatorResult; + } + catch (Exception) + { + return operatorResult; + } + } + + #region 登录错误次数记录 + + /// + /// 获取当前登录错误次数 + /// + /// + public async Task GetCurrentErrorNum() + { + int res = 0; + try + { + string cookieMark = GetProvider(LoginUserMarkKey); + if (string.IsNullOrEmpty(cookieMark)) + { + cookieMark = Guid.NewGuid().ToString(); + SetProvider(LoginUserMarkKey, cookieMark); + } + string num = await CacheHelper.GetAsync(cacheKeyError + cookieMark); + if (!string.IsNullOrEmpty(num)) + { + res = Convert.ToInt32(num); + } + } + catch (Exception) + { + } + return res; + } + + /// + /// 增加错误次数 + /// + /// + public async Task AddCurrentErrorNum() + { + int res = 0; + try + { + string cookieMark = GetProvider(LoginUserMarkKey); + if (string.IsNullOrEmpty(cookieMark)) + { + cookieMark = Guid.NewGuid().ToString(); + SetProvider(LoginUserMarkKey, cookieMark); + } + string num = await CacheHelper.GetAsync(cacheKeyError + cookieMark); + if (!string.IsNullOrEmpty(num)) + { + res = Convert.ToInt32(num); + } + res++; + num = res + ""; + await CacheHelper.SetAsync(cacheKeyError + cookieMark, num, 24); + } + catch (Exception) + { + } + return res; + } + + /// + /// 清除当前登录错误次数 + /// + public async Task ClearCurrentErrorNum() + { + try + { + string cookieMark = GetProvider(LoginUserMarkKey); + if (string.IsNullOrEmpty(cookieMark)) + { + cookieMark = Guid.NewGuid().ToString(); + SetProvider(LoginUserMarkKey, cookieMark); + } + await CacheHelper.RemoveAsync(cacheKeyError + cookieMark); + } + catch (Exception) + { + } + } + + #endregion 登录错误次数记录 + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Operator/OperatorResult.cs b/WaterCloud.Code/Operator/OperatorResult.cs new file mode 100644 index 0000000..22e43dd --- /dev/null +++ b/WaterCloud.Code/Operator/OperatorResult.cs @@ -0,0 +1,15 @@ +namespace WaterCloud.Code +{ + public class OperatorResult + { + /// + /// 状态码-1未登录,1登录成功,0登录过期 + /// + public int stateCode { get; set; } + + /// + /// 登录者用户信息 + /// + public OperatorModel userInfo { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Operator/OperatorUserInfo.cs b/WaterCloud.Code/Operator/OperatorUserInfo.cs new file mode 100644 index 0000000..e592d41 --- /dev/null +++ b/WaterCloud.Code/Operator/OperatorUserInfo.cs @@ -0,0 +1,50 @@ +using System; + +namespace WaterCloud.Code +{ + public class OperatorUserInfo + { + //密码 + public string F_UserPassword { get; set; } + + // + public string F_UserSecretkey { get; set; } + + //登录时间设置 + public DateTime? F_AllowStartTime { get; set; } + + public DateTime? F_AllowEndTime { get; set; } + + //锁定时间设置 + public DateTime? F_LockStartDate { get; set; } + + public DateTime? F_LockEndDate { get; set; } + + //第一次登录 + public DateTime? F_FirstVisitTime { get; set; } + + //上一次登录时间 + public DateTime? F_PreviousVisitTime { get; set; } + + //最后一次登录时间 + public DateTime? F_LastVisitTime { get; set; } + + //修改密码时间 + public DateTime? F_ChangePasswordDate { get; set; } + + //登录次数 + public int? F_LogOnCount { get; set; } + + //在线标记 + public bool? F_UserOnLine { get; set; } + + //安全问题 + public string F_Question { get; set; } + + //问题答案 + public string F_AnswerQuestion { get; set; } + + //默认主题 + public string F_Theme { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Properties/launchSettings.json b/WaterCloud.Code/Properties/launchSettings.json new file mode 100644 index 0000000..4d97569 --- /dev/null +++ b/WaterCloud.Code/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:59747/", + "sslPort": 44332 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "WaterCloud.Code": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Provider/CustomerFileExtensionContentTypeProvider.cs b/WaterCloud.Code/Provider/CustomerFileExtensionContentTypeProvider.cs new file mode 100644 index 0000000..efb1dd3 --- /dev/null +++ b/WaterCloud.Code/Provider/CustomerFileExtensionContentTypeProvider.cs @@ -0,0 +1,1540 @@ +using Microsoft.AspNetCore.StaticFiles; +using System; +using System.Collections.Generic; + +namespace WaterCloud.Code +{ + /// + /// mime文件 + /// + public class CustomerFileExtensionContentTypeProvider : FileExtensionContentTypeProvider + { + public CustomerFileExtensionContentTypeProvider() : + base((IDictionary)new Dictionary( + (IEqualityComparer)StringComparer.OrdinalIgnoreCase) + { + { + ".frx", + "application/rtf" + }, + { + ".323", + "text/h323" + }, + { + ".3g2", + "video/3gpp2" + }, + { + ".3gp2", + "video/3gpp2" + }, + { + ".3gp", + "video/3gpp" + }, + { + ".3gpp", + "video/3gpp" + }, + { + ".aac", + "audio/aac" + }, + { + ".aaf", + "application/octet-stream" + }, + { + ".aca", + "application/octet-stream" + }, + { + ".accdb", + "application/msaccess" + }, + { + ".accde", + "application/msaccess" + }, + { + ".accdt", + "application/msaccess" + }, + { + ".acx", + "application/internet-property-stream" + }, + { + ".adt", + "audio/vnd.dlna.adts" + }, + { + ".adts", + "audio/vnd.dlna.adts" + }, + { + ".afm", + "application/octet-stream" + }, + { + ".ai", + "application/postscript" + }, + { + ".aif", + "audio/x-aiff" + }, + { + ".aifc", + "audio/aiff" + }, + { + ".aiff", + "audio/aiff" + }, + { + ".appcache", + "text/cache-manifest" + }, + { + ".application", + "application/x-ms-application" + }, + { + ".art", + "image/x-jg" + }, + { + ".asd", + "application/octet-stream" + }, + { + ".asf", + "video/x-ms-asf" + }, + { + ".asi", + "application/octet-stream" + }, + { + ".asm", + "text/plain" + }, + { + ".asr", + "video/x-ms-asf" + }, + { + ".asx", + "video/x-ms-asf" + }, + { + ".atom", + "application/atom+xml" + }, + { + ".au", + "audio/basic" + }, + { + ".avi", + "video/x-msvideo" + }, + { + ".axs", + "application/olescript" + }, + { + ".bas", + "text/plain" + }, + { + ".bcpio", + "application/x-bcpio" + }, + { + ".bin", + "application/octet-stream" + }, + { + ".bmp", + "image/bmp" + }, + { + ".c", + "text/plain" + }, + { + ".cab", + "application/vnd.ms-cab-compressed" + }, + { + ".calx", + "application/vnd.ms-office.calx" + }, + { + ".cat", + "application/vnd.ms-pki.seccat" + }, + { + ".cdf", + "application/x-cdf" + }, + { + ".chm", + "application/octet-stream" + }, + { + ".class", + "application/x-java-applet" + }, + { + ".clp", + "application/x-msclip" + }, + { + ".cmx", + "image/x-cmx" + }, + { + ".cnf", + "text/plain" + }, + { + ".cod", + "image/cis-cod" + }, + { + ".cpio", + "application/x-cpio" + }, + { + ".cpp", + "text/plain" + }, + { + ".crd", + "application/x-mscardfile" + }, + { + ".crl", + "application/pkix-crl" + }, + { + ".crt", + "application/x-x509-ca-cert" + }, + { + ".csh", + "application/x-csh" + }, + { + ".css", + "text/css" + }, + { + ".csv", + "application/octet-stream" + }, + { + ".cur", + "application/octet-stream" + }, + { + ".dcr", + "application/x-director" + }, + { + ".deploy", + "application/octet-stream" + }, + { + ".der", + "application/x-x509-ca-cert" + }, + { + ".dib", + "image/bmp" + }, + { + ".dir", + "application/x-director" + }, + { + ".disco", + "text/xml" + }, + { + ".dlm", + "text/dlm" + }, + { + ".doc", + "application/msword" + }, + { + ".docm", + "application/vnd.ms-word.document.macroEnabled.12" + }, + { + ".docx", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document" + }, + { + ".dot", + "application/msword" + }, + { + ".dotm", + "application/vnd.ms-word.template.macroEnabled.12" + }, + { + ".dotx", + "application/vnd.openxmlformats-officedocument.wordprocessingml.template" + }, + { + ".dsp", + "application/octet-stream" + }, + { + ".dtd", + "text/xml" + }, + { + ".dvi", + "application/x-dvi" + }, + { + ".dvr-ms", + "video/x-ms-dvr" + }, + { + ".dwf", + "drawing/x-dwf" + }, + { + ".dwp", + "application/octet-stream" + }, + { + ".dxr", + "application/x-director" + }, + { + ".eml", + "message/rfc822" + }, + { + ".emz", + "application/octet-stream" + }, + { + ".eot", + "application/vnd.ms-fontobject" + }, + { + ".eps", + "application/postscript" + }, + { + ".etx", + "text/x-setext" + }, + { + ".evy", + "application/envoy" + }, + { + ".fdf", + "application/vnd.fdf" + }, + { + ".fif", + "application/fractals" + }, + { + ".fla", + "application/octet-stream" + }, + { + ".flr", + "x-world/x-vrml" + }, + { + ".flv", + "video/x-flv" + }, + { + ".gif", + "image/gif" + }, + { + ".gtar", + "application/x-gtar" + }, + { + ".gz", + "application/x-gzip" + }, + { + ".h", + "text/plain" + }, + { + ".hdf", + "application/x-hdf" + }, + { + ".hdml", + "text/x-hdml" + }, + { + ".hhc", + "application/x-oleobject" + }, + { + ".hhk", + "application/octet-stream" + }, + { + ".hhp", + "application/octet-stream" + }, + { + ".hlp", + "application/winhlp" + }, + { + ".hqx", + "application/mac-binhex40" + }, + { + ".hta", + "application/hta" + }, + { + ".htc", + "text/x-component" + }, + { + ".htm", + "text/html" + }, + { + ".html", + "text/html" + }, + { + ".htt", + "text/webviewhtml" + }, + { + ".hxt", + "text/html" + }, + { + ".ical", + "text/calendar" + }, + { + ".icalendar", + "text/calendar" + }, + { + ".ico", + "image/x-icon" + }, + { + ".ics", + "text/calendar" + }, + { + ".ief", + "image/ief" + }, + { + ".ifb", + "text/calendar" + }, + { + ".iii", + "application/x-iphone" + }, + { + ".inf", + "application/octet-stream" + }, + { + ".ins", + "application/x-internet-signup" + }, + { + ".isp", + "application/x-internet-signup" + }, + { + ".IVF", + "video/x-ivf" + }, + { + ".jar", + "application/java-archive" + }, + { + ".java", + "application/octet-stream" + }, + { + ".jck", + "application/liquidmotion" + }, + { + ".jcz", + "application/liquidmotion" + }, + { + ".jfif", + "image/pjpeg" + }, + { + ".jpb", + "application/octet-stream" + }, + { + ".jpe", + "image/jpeg" + }, + { + ".jpeg", + "image/jpeg" + }, + { + ".jpg", + "image/jpeg" + }, + { + ".js", + "application/javascript" + }, + { + ".json", + "application/json" + }, + { + ".jsx", + "text/jscript" + }, + { + ".latex", + "application/x-latex" + }, + { + ".lit", + "application/x-ms-reader" + }, + { + ".lpk", + "application/octet-stream" + }, + { + ".lsf", + "video/x-la-asf" + }, + { + ".lsx", + "video/x-la-asf" + }, + { + ".lzh", + "application/octet-stream" + }, + { + ".m13", + "application/x-msmediaview" + }, + { + ".m14", + "application/x-msmediaview" + }, + { + ".m1v", + "video/mpeg" + }, + { + ".m2ts", + "video/vnd.dlna.mpeg-tts" + }, + { + ".m3u", + "audio/x-mpegurl" + }, + { + ".m4a", + "audio/mp4" + }, + { + ".m4v", + "video/mp4" + }, + { + ".man", + "application/x-troff-man" + }, + { + ".manifest", + "application/x-ms-manifest" + }, + { + ".map", + "text/plain" + }, + { + ".markdown", + "text/markdown" + }, + { + ".md", + "text/markdown" + }, + { + ".mdb", + "application/x-msaccess" + }, + { + ".mdp", + "application/octet-stream" + }, + { + ".me", + "application/x-troff-me" + }, + { + ".mht", + "message/rfc822" + }, + { + ".mhtml", + "message/rfc822" + }, + { + ".mid", + "audio/mid" + }, + { + ".midi", + "audio/mid" + }, + { + ".mix", + "application/octet-stream" + }, + { + ".mmf", + "application/x-smaf" + }, + { + ".mno", + "text/xml" + }, + { + ".mny", + "application/x-msmoney" + }, + { + ".mov", + "video/quicktime" + }, + { + ".movie", + "video/x-sgi-movie" + }, + { + ".mp2", + "video/mpeg" + }, + { + ".mp3", + "audio/mpeg" + }, + { + ".mp4", + "video/mp4" + }, + { + ".mp4v", + "video/mp4" + }, + { + ".mpa", + "video/mpeg" + }, + { + ".mpe", + "video/mpeg" + }, + { + ".mpeg", + "video/mpeg" + }, + { + ".mpg", + "video/mpeg" + }, + { + ".mpp", + "application/vnd.ms-project" + }, + { + ".mpv2", + "video/mpeg" + }, + { + ".ms", + "application/x-troff-ms" + }, + { + ".msi", + "application/octet-stream" + }, + { + ".mso", + "application/octet-stream" + }, + { + ".mvb", + "application/x-msmediaview" + }, + { + ".mvc", + "application/x-miva-compiled" + }, + { + ".nc", + "application/x-netcdf" + }, + { + ".nsc", + "video/x-ms-asf" + }, + { + ".nws", + "message/rfc822" + }, + { + ".ocx", + "application/octet-stream" + }, + { + ".oda", + "application/oda" + }, + { + ".odc", + "text/x-ms-odc" + }, + { + ".ods", + "application/oleobject" + }, + { + ".oga", + "audio/ogg" + }, + { + ".ogg", + "video/ogg" + }, + { + ".ogv", + "video/ogg" + }, + { + ".ogx", + "application/ogg" + }, + { + ".one", + "application/onenote" + }, + { + ".onea", + "application/onenote" + }, + { + ".onetoc", + "application/onenote" + }, + { + ".onetoc2", + "application/onenote" + }, + { + ".onetmp", + "application/onenote" + }, + { + ".onepkg", + "application/onenote" + }, + { + ".osdx", + "application/opensearchdescription+xml" + }, + { + ".otf", + "font/otf" + }, + { + ".p10", + "application/pkcs10" + }, + { + ".p12", + "application/x-pkcs12" + }, + { + ".p7b", + "application/x-pkcs7-certificates" + }, + { + ".p7c", + "application/pkcs7-mime" + }, + { + ".p7m", + "application/pkcs7-mime" + }, + { + ".p7r", + "application/x-pkcs7-certreqresp" + }, + { + ".p7s", + "application/pkcs7-signature" + }, + { + ".pbm", + "image/x-portable-bitmap" + }, + { + ".pcx", + "application/octet-stream" + }, + { + ".pcz", + "application/octet-stream" + }, + { + ".pdf", + "application/pdf" + }, + { + ".pfb", + "application/octet-stream" + }, + { + ".pfm", + "application/octet-stream" + }, + { + ".pfx", + "application/x-pkcs12" + }, + { + ".pgm", + "image/x-portable-graymap" + }, + { + ".pko", + "application/vnd.ms-pki.pko" + }, + { + ".pma", + "application/x-perfmon" + }, + { + ".pmc", + "application/x-perfmon" + }, + { + ".pml", + "application/x-perfmon" + }, + { + ".pmr", + "application/x-perfmon" + }, + { + ".pmw", + "application/x-perfmon" + }, + { + ".png", + "image/png" + }, + { + ".pnm", + "image/x-portable-anymap" + }, + { + ".pnz", + "image/png" + }, + { + ".pot", + "application/vnd.ms-powerpoint" + }, + { + ".potm", + "application/vnd.ms-powerpoint.template.macroEnabled.12" + }, + { + ".potx", + "application/vnd.openxmlformats-officedocument.presentationml.template" + }, + { + ".ppam", + "application/vnd.ms-powerpoint.addin.macroEnabled.12" + }, + { + ".ppm", + "image/x-portable-pixmap" + }, + { + ".pps", + "application/vnd.ms-powerpoint" + }, + { + ".ppsm", + "application/vnd.ms-powerpoint.slideshow.macroEnabled.12" + }, + { + ".ppsx", + "application/vnd.openxmlformats-officedocument.presentationml.slideshow" + }, + { + ".ppt", + "application/vnd.ms-powerpoint" + }, + { + ".pptm", + "application/vnd.ms-powerpoint.presentation.macroEnabled.12" + }, + { + ".pptx", + "application/vnd.openxmlformats-officedocument.presentationml.presentation" + }, + { + ".prf", + "application/pics-rules" + }, + { + ".prm", + "application/octet-stream" + }, + { + ".prx", + "application/octet-stream" + }, + { + ".ps", + "application/postscript" + }, + { + ".psd", + "application/octet-stream" + }, + { + ".psm", + "application/octet-stream" + }, + { + ".psp", + "application/octet-stream" + }, + { + ".pub", + "application/x-mspublisher" + }, + { + ".qt", + "video/quicktime" + }, + { + ".qtl", + "application/x-quicktimeplayer" + }, + { + ".qxd", + "application/octet-stream" + }, + { + ".ra", + "audio/x-pn-realaudio" + }, + { + ".ram", + "audio/x-pn-realaudio" + }, + { + ".rar", + "application/octet-stream" + }, + { + ".ras", + "image/x-cmu-raster" + }, + { + ".rf", + "image/vnd.rn-realflash" + }, + { + ".rgb", + "image/x-rgb" + }, + { + ".rm", + "application/vnd.rn-realmedia" + }, + { + ".rmi", + "audio/mid" + }, + { + ".roff", + "application/x-troff" + }, + { + ".rpm", + "audio/x-pn-realaudio-plugin" + }, + { + ".rtf", + "application/rtf" + }, + { + ".rtx", + "text/richtext" + }, + { + ".scd", + "application/x-msschedule" + }, + { + ".sct", + "text/scriptlet" + }, + { + ".sea", + "application/octet-stream" + }, + { + ".setpay", + "application/set-payment-initiation" + }, + { + ".setreg", + "application/set-registration-initiation" + }, + { + ".sgml", + "text/sgml" + }, + { + ".sh", + "application/x-sh" + }, + { + ".shar", + "application/x-shar" + }, + { + ".sit", + "application/x-stuffit" + }, + { + ".sldm", + "application/vnd.ms-powerpoint.slide.macroEnabled.12" + }, + { + ".sldx", + "application/vnd.openxmlformats-officedocument.presentationml.slide" + }, + { + ".smd", + "audio/x-smd" + }, + { + ".smi", + "application/octet-stream" + }, + { + ".smx", + "audio/x-smd" + }, + { + ".smz", + "audio/x-smd" + }, + { + ".snd", + "audio/basic" + }, + { + ".snp", + "application/octet-stream" + }, + { + ".spc", + "application/x-pkcs7-certificates" + }, + { + ".spl", + "application/futuresplash" + }, + { + ".spx", + "audio/ogg" + }, + { + ".src", + "application/x-wais-source" + }, + { + ".ssm", + "application/streamingmedia" + }, + { + ".sst", + "application/vnd.ms-pki.certstore" + }, + { + ".stl", + "application/vnd.ms-pki.stl" + }, + { + ".sv4cpio", + "application/x-sv4cpio" + }, + { + ".sv4crc", + "application/x-sv4crc" + }, + { + ".svg", + "image/svg+xml" + }, + { + ".svgz", + "image/svg+xml" + }, + { + ".swf", + "application/x-shockwave-flash" + }, + { + ".t", + "application/x-troff" + }, + { + ".tar", + "application/x-tar" + }, + { + ".tcl", + "application/x-tcl" + }, + { + ".tex", + "application/x-tex" + }, + { + ".texi", + "application/x-texinfo" + }, + { + ".texinfo", + "application/x-texinfo" + }, + { + ".tgz", + "application/x-compressed" + }, + { + ".thmx", + "application/vnd.ms-officetheme" + }, + { + ".thn", + "application/octet-stream" + }, + { + ".tif", + "image/tiff" + }, + { + ".tiff", + "image/tiff" + }, + { + ".toc", + "application/octet-stream" + }, + { + ".tr", + "application/x-troff" + }, + { + ".trm", + "application/x-msterminal" + }, + { + ".ts", + "video/vnd.dlna.mpeg-tts" + }, + { + ".tsv", + "text/tab-separated-values" + }, + { + ".ttc", + "application/x-font-ttf" + }, + { + ".ttf", + "application/x-font-ttf" + }, + { + ".tts", + "video/vnd.dlna.mpeg-tts" + }, + { + ".txt", + "text/plain" + }, + { + ".u32", + "application/octet-stream" + }, + { + ".uls", + "text/iuls" + }, + { + ".ustar", + "application/x-ustar" + }, + { + ".vbs", + "text/vbscript" + }, + { + ".vcf", + "text/x-vcard" + }, + { + ".vcs", + "text/plain" + }, + { + ".vdx", + "application/vnd.ms-visio.viewer" + }, + { + ".vml", + "text/xml" + }, + { + ".vsd", + "application/vnd.visio" + }, + { + ".vss", + "application/vnd.visio" + }, + { + ".vst", + "application/vnd.visio" + }, + { + ".vsto", + "application/x-ms-vsto" + }, + { + ".vsw", + "application/vnd.visio" + }, + { + ".vsx", + "application/vnd.visio" + }, + { + ".vtx", + "application/vnd.visio" + }, + { + ".wasm", + "application/wasm" + }, + { + ".wav", + "audio/wav" + }, + { + ".wax", + "audio/x-ms-wax" + }, + { + ".wbmp", + "image/vnd.wap.wbmp" + }, + { + ".wcm", + "application/vnd.ms-works" + }, + { + ".wdb", + "application/vnd.ms-works" + }, + { + ".webm", + "video/webm" + }, + { + ".webp", + "image/webp" + }, + { + ".wks", + "application/vnd.ms-works" + }, + { + ".wm", + "video/x-ms-wm" + }, + { + ".wma", + "audio/x-ms-wma" + }, + { + ".wmd", + "application/x-ms-wmd" + }, + { + ".wmf", + "application/x-msmetafile" + }, + { + ".wml", + "text/vnd.wap.wml" + }, + { + ".wmlc", + "application/vnd.wap.wmlc" + }, + { + ".wmls", + "text/vnd.wap.wmlscript" + }, + { + ".wmlsc", + "application/vnd.wap.wmlscriptc" + }, + { + ".wmp", + "video/x-ms-wmp" + }, + { + ".wmv", + "video/x-ms-wmv" + }, + { + ".wmx", + "video/x-ms-wmx" + }, + { + ".wmz", + "application/x-ms-wmz" + }, + { + ".woff", + "application/font-woff" + }, + { + ".woff2", + "font/woff2" + }, + { + ".wps", + "application/vnd.ms-works" + }, + { + ".wri", + "application/x-mswrite" + }, + { + ".wrl", + "x-world/x-vrml" + }, + { + ".wrz", + "x-world/x-vrml" + }, + { + ".wsdl", + "text/xml" + }, + { + ".wtv", + "video/x-ms-wtv" + }, + { + ".wvx", + "video/x-ms-wvx" + }, + { + ".x", + "application/directx" + }, + { + ".xaf", + "x-world/x-vrml" + }, + { + ".xaml", + "application/xaml+xml" + }, + { + ".xap", + "application/x-silverlight-app" + }, + { + ".xbap", + "application/x-ms-xbap" + }, + { + ".xbm", + "image/x-xbitmap" + }, + { + ".xdr", + "text/plain" + }, + { + ".xht", + "application/xhtml+xml" + }, + { + ".xhtml", + "application/xhtml+xml" + }, + { + ".xla", + "application/vnd.ms-excel" + }, + { + ".xlam", + "application/vnd.ms-excel.addin.macroEnabled.12" + }, + { + ".xlc", + "application/vnd.ms-excel" + }, + { + ".xlm", + "application/vnd.ms-excel" + }, + { + ".xls", + "application/vnd.ms-excel" + }, + { + ".xlsb", + "application/vnd.ms-excel.sheet.binary.macroEnabled.12" + }, + { + ".xlsm", + "application/vnd.ms-excel.sheet.macroEnabled.12" + }, + { + ".xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + }, + { + ".xlt", + "application/vnd.ms-excel" + }, + { + ".xltm", + "application/vnd.ms-excel.template.macroEnabled.12" + }, + { + ".xltx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.template" + }, + { + ".xlw", + "application/vnd.ms-excel" + }, + { + ".xml", + "text/xml" + }, + { + ".xof", + "x-world/x-vrml" + }, + { + ".xpm", + "image/x-xpixmap" + }, + { + ".xps", + "application/vnd.ms-xpsdocument" + }, + { + ".xsd", + "text/xml" + }, + { + ".xsf", + "text/xml" + }, + { + ".xsl", + "text/xml" + }, + { + ".xslt", + "text/xml" + }, + { + ".xsn", + "application/octet-stream" + }, + { + ".xtp", + "application/octet-stream" + }, + { + ".xwd", + "image/x-xwindowdump" + }, + { + ".z", + "application/x-compress" + }, + { + ".zip", + "application/x-zip-compressed" + }, + { + ".less", + "stylesheet/css" + } + }) + { + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Provider/ModelBindingMetadataProvider.cs b/WaterCloud.Code/Provider/ModelBindingMetadataProvider.cs new file mode 100644 index 0000000..096cbd6 --- /dev/null +++ b/WaterCloud.Code/Provider/ModelBindingMetadataProvider.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata; + +namespace WaterCloud.Code +{ + /// + /// Controller Model Binding 处理 + /// + public class ModelBindingMetadataProvider : IMetadataDetailsProvider, IDisplayMetadataProvider + { + public void CreateDisplayMetadata(DisplayMetadataProviderContext context) + { + if (context.Key.MetadataKind == ModelMetadataKind.Property) + { + context.DisplayMetadata.ConvertEmptyStringToNull = false; + } + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Security/DESEncrypt.cs b/WaterCloud.Code/Security/DESEncrypt.cs new file mode 100644 index 0000000..630a28d --- /dev/null +++ b/WaterCloud.Code/Security/DESEncrypt.cs @@ -0,0 +1,238 @@ +/******************************************************************************* + * Copyright © 2016 WaterCloud.Framework 版权所有 + * Author: WaterCloud + * Description: WaterCloud快速开发平台 + * Website: +*********************************************************************************/ + +using System; +using System.Security.Cryptography; +using System.Text; + +namespace WaterCloud.Code +{ + /// + /// DES加密、解密帮助类 + /// + public class DESEncrypt + { + private static string DESKey = "WaterCloud_desencrypt_2019"; + + #region ========加密======== + + /// + /// 加密 + /// + /// + /// + public static string Encrypt(string Text) + { + return Encrypt(Text, DESKey); + } + + /// + /// 加密数据,用Web.Security的Hash方式加密 + /// + /// + /// + /// + public static string Encrypt(string Text, string sKey) + { + DES des = DES.Create(); + byte[] inputByteArray; + inputByteArray = Encoding.Default.GetBytes(Text); + des.Key = ASCIIEncoding.ASCII.GetBytes(DecryptMd5(sKey)); + des.IV = ASCIIEncoding.ASCII.GetBytes(DecryptMd5(sKey)); + System.IO.MemoryStream ms = new System.IO.MemoryStream(); + CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write); + cs.Write(inputByteArray, 0, inputByteArray.Length); + cs.FlushFinalBlock(); + StringBuilder ret = new StringBuilder(); + foreach (byte b in ms.ToArray()) + { + ret.AppendFormat("{0:X2}", b); + } + return ret.ToString(); + } + + /// + /// 加密数据, 用Security.MD5而非Web.Security的Hash方式加密 + /// + /// + /// + public static string Encrypt2(string Text) + { + return Encrypt2(Text, DESKey); + } + + /// + /// 加密数据, 用Security.MD5而非Web.Security的Hash方式加密 + /// + /// + /// + /// + public static string Encrypt2(string Text, string sKey) + { + DES des = DES.Create(); + byte[] inputByteArray; + inputByteArray = Encoding.Default.GetBytes(Text); + sKey = MD5(sKey).Substring(0, 8); + des.Key = ASCIIEncoding.ASCII.GetBytes(sKey); + des.IV = ASCIIEncoding.ASCII.GetBytes(sKey); + System.IO.MemoryStream ms = new System.IO.MemoryStream(); + CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write); + cs.Write(inputByteArray, 0, inputByteArray.Length); + cs.FlushFinalBlock(); + StringBuilder ret = new StringBuilder(); + foreach (byte b in ms.ToArray()) + { + ret.AppendFormat("{0:X2}", b); + } + return ret.ToString(); + } + + #endregion ========加密======== + + #region ========解密======== + + /// + /// 解密 + /// + /// + /// + public static string Decrypt(string Text) + { + if (!string.IsNullOrEmpty(Text)) + { + return Decrypt(Text, DESKey); + } + else + { + return ""; + } + } + + /// + /// 解密数据,用Web.Security的Hash方式加密 + /// + /// + /// + /// + public static string Decrypt(string Text, string sKey) + { + DES des = DES.Create(); + int len; + len = Text.Length / 2; + byte[] inputByteArray = new byte[len]; + int x, i; + for (x = 0; x < len; x++) + { + i = Convert.ToInt32(Text.Substring(x * 2, 2), 16); + inputByteArray[x] = (byte)i; + } + + des.Key = ASCIIEncoding.ASCII.GetBytes(DecryptMd5(sKey)); + des.IV = ASCIIEncoding.ASCII.GetBytes(DecryptMd5(sKey)); + System.IO.MemoryStream ms = new System.IO.MemoryStream(); + CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write); + cs.Write(inputByteArray, 0, inputByteArray.Length); + cs.FlushFinalBlock(); + return Encoding.Default.GetString(ms.ToArray()); + } + + public static string DecryptMd5(string str) + { + string strEncrypt = string.Empty; + var md5 = System.Security.Cryptography.MD5.Create(); + var data = md5.ComputeHash(Encoding.UTF8.GetBytes(str)); + StringBuilder builder = new StringBuilder(); + // 循环遍历哈希数据的每一个字节并格式化为十六进制字符串 + for (int i = 0; i < data.Length; i++) + { + builder.Append(data[i].ToString("X2")); + } + strEncrypt = builder.ToString().Substring(0, 8); + return strEncrypt; + } + + /// + /// 解密数据,用Security.MD5而非Web.Security的Hash方式加密 + /// + /// + /// + public static string Decrypt2(string Text) + { + if (!string.IsNullOrEmpty(Text)) + { + return Decrypt2(Text, DESKey); + } + else + { + return ""; + } + } + + /// + /// 解密数据,用Security.MD5而非Web.Security的Hash方式加密 + /// + /// + /// + /// + public static string Decrypt2(string Text, string sKey) + { + DES des = DES.Create(); + int len; + len = Text.Length / 2; + byte[] inputByteArray = new byte[len]; + int x, i; + for (x = 0; x < len; x++) + { + i = Convert.ToInt32(Text.Substring(x * 2, 2), 16); + inputByteArray[x] = (byte)i; + } + sKey = MD5(sKey).Substring(0, 8); + des.Key = ASCIIEncoding.ASCII.GetBytes(sKey); + des.IV = ASCIIEncoding.ASCII.GetBytes(sKey); + System.IO.MemoryStream ms = new System.IO.MemoryStream(); + CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write); + cs.Write(inputByteArray, 0, inputByteArray.Length); + cs.FlushFinalBlock(); + return Encoding.Default.GetString(ms.ToArray()); + } + + #endregion ========解密======== + + public static string MD5(string pwd) + { + MD5 md5 = System.Security.Cryptography.MD5.Create(); + byte[] data = System.Text.Encoding.Default.GetBytes(pwd); + byte[] md5data = md5.ComputeHash(data); + md5.Clear(); + string str = ""; + for (int i = 0; i < md5data.Length; i++) + { + str += md5data[i].ToString("x").PadLeft(2, '0'); + } + return str; + } + + /// + /// 基于Sha1的自定义加密字符串方法:输入一个字符串,返回一个由40个字符组成的十六进制的哈希散列(字符串)。 + /// + /// 要加密的字符串 + /// 加密后的十六进制的哈希散列(字符串) + public static string Sha1(string str) + { + var buffer = Encoding.UTF8.GetBytes(str); + var data = SHA1.Create().ComputeHash(buffer); + + var sb = new StringBuilder(); + foreach (var t in data) + { + sb.Append(t.ToString("X2")); + } + + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Security/Md5.cs b/WaterCloud.Code/Security/Md5.cs new file mode 100644 index 0000000..af3925a --- /dev/null +++ b/WaterCloud.Code/Security/Md5.cs @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright © 2016 WaterCloud.Framework 版权所有 + * Author: WaterCloud + * Description: WaterCloud快速开发平台 + * Website: +*********************************************************************************/ + +using System; +using System.Security.Cryptography; +using System.Text; + +namespace WaterCloud.Code +{ + /// + /// MD5加密 + /// + public class Md5 + { + /// + /// MD5加密 + /// + /// 加密字符 + /// 加密位数16/32 + /// + public static string md5(string str, int code) + { + string strEncrypt = string.Empty; + if (code == 16) + { + var md5 = System.Security.Cryptography.MD5.Create(); + var data = md5.ComputeHash(Encoding.UTF8.GetBytes(str)); + StringBuilder builder = new StringBuilder(); + // 循环遍历哈希数据的每一个字节并格式化为十六进制字符串 + for (int i = 0; i < data.Length; i++) + { + builder.Append(data[i].ToString("X2")); + } + strEncrypt = builder.ToString().Substring(8, 16); + } + + if (code == 32) + { + var md5 = System.Security.Cryptography.MD5.Create(); + var data = md5.ComputeHash(Encoding.UTF8.GetBytes(str)); + StringBuilder builder = new StringBuilder(); + // 循环遍历哈希数据的每一个字节并格式化为十六进制字符串 + for (int i = 0; i < data.Length; i++) + { + builder.Append(data[i].ToString("X2")); + } + strEncrypt = builder.ToString(); + } + + return strEncrypt; + } + + public static string MD5(string str) + { + MD5 md5 = System.Security.Cryptography.MD5.Create(); + byte[] data = System.Text.Encoding.Default.GetBytes(str); + byte[] md5data = md5.ComputeHash(data); + md5.Clear(); + str = ""; + for (int i = 0; i < md5data.Length; i++) + { + str += md5data[i].ToString("x").PadLeft(2, '0'); + } + return str; + } + + public static string MD5Lower16(string str) + { + return MD5(str).ToLower().Substring(8, 16); + } + + public static string MD5Lower32(string str) + { + return MD5(str).ToLower(); ; + } + + /// + /// 32位小写 + /// + /// + public static string SHA1(string s) + { + SHA1 sha1 = System.Security.Cryptography.SHA1.Create(); + byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(s)); + string shaStr = BitConverter.ToString(hash); + shaStr = shaStr.Replace("-", ""); + shaStr = shaStr.ToLower(); + return s.ToLower(); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/AsyncTaskHelper.cs b/WaterCloud.Code/Util/AsyncTaskHelper.cs new file mode 100644 index 0000000..cf9bd92 --- /dev/null +++ b/WaterCloud.Code/Util/AsyncTaskHelper.cs @@ -0,0 +1,28 @@ +using System; +using System.Threading.Tasks; + +namespace WaterCloud.Code +{ + public class AsyncTaskHelper + { + /// + /// 开始异步任务 + /// + /// + public static void StartTask(Action action) + { + try + { + Action newAction = () => + { }; + newAction += action; + Task task = new Task(newAction); + task.Start(); + } + catch (Exception ex) + { + LogHelper.WriteWithTime(ex); + } + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/CommonEnum.cs b/WaterCloud.Code/Util/CommonEnum.cs new file mode 100644 index 0000000..40b84a1 --- /dev/null +++ b/WaterCloud.Code/Util/CommonEnum.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; + +namespace WaterCloud.Code +{ + public enum StatusEnum + { + [Description("启用")] + Yes = 1, + + [Description("禁用")] + No = 0 + } + + public enum IsEnum + { + [Description("是")] + Yes = 1, + + [Description("否")] + No = 0 + } + + public enum NeedEnum + { + [Description("不需要")] + NotNeed = 0, + + [Description("需要")] + Need = 1 + } + + public enum OperateStatusEnum + { + [Description("失败")] + Fail = 0, + + [Description("成功")] + Success = 1 + } + + public enum UploadFileType + { + [Description("头像")] + Portrait = 1, + + [Description("新闻图片")] + News = 2, + + [Description("导入的文件")] + Import = 10 + } + + public enum PlatformEnum + { + [Description("Web后台")] + Web = 1, + + [Description("WebApi")] + WebApi = 2 + } + + public enum PayStatusEnum + { + [Description("未知")] + Unknown = 0, + + [Description("已支付")] + Success = 1, + + [Description("转入退款")] + Refund = 2, + + [Description("未支付")] + NotPay = 3, + + [Description("已关闭")] + Closed = 4, + + [Description("已撤销(付款码支付)")] + Revoked = 5, + + [Description("用户支付中(付款码支付)")] + UserPaying = 6, + + [Description("支付失败(其他原因,如银行返回失败)")] + PayError = 7 + } + + public class EnumHelper + { + /// + /// 获取枚举列表 + /// + /// + /// + public static Dictionary EnumToDic() + { + Dictionary list = new Dictionary(); + foreach (var e in Enum.GetValues(typeof(T))) + { + list.Add(Convert.ToInt32(e), e.GetDescriptionByEnum()); + } + return list; + } + + /// + /// 获取枚举列表 + /// + /// + /// + public static List EnumToList() + { + List list = new List(); + + foreach (var e in Enum.GetValues(typeof(T))) + { + list.Add(e.GetDescriptionByEnum()); + } + return list; + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/ComputerHelper.cs b/WaterCloud.Code/Util/ComputerHelper.cs new file mode 100644 index 0000000..37acf5e --- /dev/null +++ b/WaterCloud.Code/Util/ComputerHelper.cs @@ -0,0 +1,150 @@ +using System; +using System.Runtime.InteropServices; + +namespace WaterCloud.Code +{ + public class ComputerHelper + { + public static ComputerInfo GetComputerInfo() + { + ComputerInfo computerInfo = new ComputerInfo(); + try + { + MemoryMetricsClient client = new MemoryMetricsClient(); + MemoryMetrics memoryMetrics = client.GetMetrics(); + computerInfo.TotalRAM = Math.Ceiling(memoryMetrics.Total / 1024).ToString() + " GB"; + computerInfo.RAMRate = Math.Ceiling(100 * memoryMetrics.Used / memoryMetrics.Total).ToString(); + computerInfo.CPURate = Math.Ceiling(GetCPURate().ToDouble()).ToString(); + computerInfo.RunTime = GetRunTime(); + } + catch (Exception ex) + { + LogHelper.WriteWithTime(ex); + } + return computerInfo; + } + + public static bool IsUnix() + { + var isUnix = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + return isUnix; + } + + public static string GetCPURate() + { + string cpuRate = string.Empty; + if (IsUnix()) + { + string output = ShellHelper.Bash("top -b -n1 | grep \"Cpu(s)\" | awk '{print $2 + $4}'"); + cpuRate = output.Trim(); + } + else + { + string output = ShellHelper.Cmd("wmic", "cpu get LoadPercentage"); + cpuRate = output.Replace("LoadPercentage", string.Empty).Trim(); + } + return cpuRate; + } + + public static string GetRunTime() + { + string runTime = string.Empty; + try + { + if (IsUnix()) + { + string output = ShellHelper.Bash("uptime -s"); + output = output.Trim(); + runTime = Extensions.FormatTime((DateTime.Now - output.ToDate()).TotalMilliseconds.ToString().Split('.')[0].ToLong()); + } + else + { + string output = ShellHelper.Cmd("wmic", "OS get LastBootUpTime/Value"); + string[] outputArr = output.Split("=", StringSplitOptions.RemoveEmptyEntries); + if (outputArr.Length == 2) + { + runTime = Extensions.FormatTime((DateTime.Now - outputArr[1].Split('.')[0].ToDate()).TotalMilliseconds.ToString().Split('.')[0].ToLong()); + } + } + } + catch (Exception ex) + { + LogHelper.WriteWithTime(ex); + } + return runTime; + } + } + + public class MemoryMetrics + { + public double Total { get; set; } + public double Used { get; set; } + public double Free { get; set; } + } + + public class MemoryMetricsClient + { + public MemoryMetrics GetMetrics() + { + if (ComputerHelper.IsUnix()) + { + return GetUnixMetrics(); + } + return GetWindowsMetrics(); + } + + private MemoryMetrics GetWindowsMetrics() + { + string output = ShellHelper.Cmd("wmic", "OS get FreePhysicalMemory,TotalVisibleMemorySize /Value"); + + var lines = output.Trim().Split("\n"); + var freeMemoryParts = lines[0].Split("=", StringSplitOptions.RemoveEmptyEntries); + var totalMemoryParts = lines[1].Split("=", StringSplitOptions.RemoveEmptyEntries); + + var metrics = new MemoryMetrics(); + metrics.Total = Math.Round(double.Parse(totalMemoryParts[1]) / 1024, 0); + metrics.Free = Math.Round(double.Parse(freeMemoryParts[1]) / 1024, 0); + metrics.Used = metrics.Total - metrics.Free; + + return metrics; + } + + private MemoryMetrics GetUnixMetrics() + { + string output = ShellHelper.Bash("free -m"); + + var lines = output.Split("\n"); + var memory = lines[1].Split(" ", StringSplitOptions.RemoveEmptyEntries); + + var metrics = new MemoryMetrics(); + metrics.Total = double.Parse(memory[1]); + metrics.Used = double.Parse(memory[2]); + metrics.Free = double.Parse(memory[3]); + + return metrics; + } + } + + public class ComputerInfo + { + /// + /// CPU使用率 + /// + public string CPURate { get; set; } + + /// + /// 总内存 + /// + public string TotalRAM { get; set; } + + /// + /// 内存使用率 + /// + public string RAMRate { get; set; } + + /// + /// 系统运行时间 + /// + public string RunTime { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/ConcurrentList.cs b/WaterCloud.Code/Util/ConcurrentList.cs new file mode 100644 index 0000000..e32b660 --- /dev/null +++ b/WaterCloud.Code/Util/ConcurrentList.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace WaterCloud.Code +{ + public class ConcurrentList : IList + { + protected static object _lock = new object(); + protected List _interalList = new List(); + + public IEnumerator GetEnumerator() + { + return Clone().GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return Clone().GetEnumerator(); + } + + public int Count + { get { return _interalList.Count; } } + + public bool IsReadOnly + { get { return false; } } + + public T this[int index] + { + get + { + lock (_lock) + { + return _interalList[index]; + } + } + set + { + lock (_lock) + { + _interalList[index] = value; + } + } + } + + public List Clone() + { + List newList = new List(); + lock (_lock) + { + _interalList.ForEach(x => newList.Add(x)); + } + return newList; + } + + public int IndexOf(T item) + { + return _interalList.IndexOf(item); + } + + public void Insert(int index, T item) + { + _interalList.Insert(index, item); + } + + public void RemoveAt(int index) + { + lock (_lock) + { + _interalList.RemoveAt(index); + } + } + + public void Add(T item) + { + lock (_lock) + { + _interalList.Add(item); + } + } + + public void AddRange(IEnumerable list) + { + foreach (T item in list) + { + Add(item); + } + } + + public void Clear() + { + lock (_lock) + { + _interalList.Clear(); + } + } + + public bool Contains(T item) + { + return _interalList.Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + _interalList.CopyTo(array, arrayIndex); + } + + public bool Remove(T item) + { + if (item == null) + { + return false; + } + lock (_lock) + { + return _interalList.Remove(item); + } + } + + public void RemoveAll(Predicate match) + { + if (match == null) + { + return; + } + Contract.Ensures(Contract.Result() >= 0); + Contract.Ensures(Contract.Result() <= Contract.OldValue(Count)); + Contract.EndContractBlock(); + + foreach (T t in Clone()) + { + if (match(t)) + { + Remove(t); + } + } + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/DataTableHelper.cs b/WaterCloud.Code/Util/DataTableHelper.cs new file mode 100644 index 0000000..4fd42c8 --- /dev/null +++ b/WaterCloud.Code/Util/DataTableHelper.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Reflection; + +namespace WaterCloud.Code +{ + public static class DataTableHelper + { + public static DataTable ListToDataTable(List entitys) + { + //检查实体集合不能为空 + if (entitys == null || entitys.Count < 1) + { + throw new Exception("需转换的集合为空"); + } + //取出第一个实体的所有Propertie + Type entityType = entitys[0].GetType(); + PropertyInfo[] entityProperties = entityType.GetProperties(); + + //生成DataTable的structure + //生产代码中,应将生成的DataTable结构Cache起来,此处略 + DataTable dt = new DataTable(); + for (int i = 0; i < entityProperties.Length; i++) + { + dt.Columns.Add(entityProperties[i].Name); + } + //将所有entity添加到DataTable中 + foreach (object entity in entitys) + { + //检查所有的的实体都为同一类型 + if (entity.GetType() != entityType) + { + throw new Exception("要转换的集合元素类型不一致"); + } + object[] entityValues = new object[entityProperties.Length]; + for (int i = 0; i < entityProperties.Length; i++) + { + entityValues[i] = entityProperties[i].GetValue(entity, null); + } + dt.Rows.Add(entityValues); + } + return dt; + } + + /// + /// List过滤 + /// + /// + /// + /// + /// + public static List ListFilter(List entitys, List list) + { + //检查实体集合不能为空 + if (entitys == null || entitys.Count < 1) + { + throw new Exception("需转换的集合为空"); + } + //取出第一个实体的所有Propertie + Type entityType = entitys[0].GetType(); + PropertyInfo[] entityProperties = entityType.GetProperties(); + + //将所有entity过滤 + foreach (object entity in entitys) + { + //检查所有的的实体都为同一类型 + if (entity.GetType() != entityType) + { + throw new Exception("要转换的集合元素类型不一致"); + } + for (int i = 0; i < entityProperties.Length; i++) + { + if (!list.Contains(entityProperties[i].Name)) + { + entityProperties[i].SetValue(entity, null); + } + } + } + return entitys; + } + + /// + /// DataTable转成List + /// + /// + /// + /// + public static List ToDataList(this DataTable dt) + { + var list = new List(); + var plist = new List(typeof(T).GetProperties()); + foreach (DataRow item in dt.Rows) + { + T s = Activator.CreateInstance(); + for (int i = 0; i < dt.Columns.Count; i++) + { + PropertyInfo info = plist.Find(p => p.Name == dt.Columns[i].ColumnName); + if (info != null) + { + try + { + if (!Convert.IsDBNull(item[i])) + { + object v = null; + if (info.PropertyType.ToString().Contains("System.Nullable")) + { + v = Convert.ChangeType(item[i], Nullable.GetUnderlyingType(info.PropertyType)); + } + else + { + v = Convert.ChangeType(item[i], info.PropertyType); + } + info.SetValue(s, v, null); + } + } + catch (Exception ex) + { + throw new Exception("字段[" + info.Name + "]转换出错," + ex.Message); + } + } + } + list.Add(s); + } + return list; + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/FileHelper.cs b/WaterCloud.Code/Util/FileHelper.cs new file mode 100644 index 0000000..653c224 --- /dev/null +++ b/WaterCloud.Code/Util/FileHelper.cs @@ -0,0 +1,697 @@ +using System; +using System.Data; +using System.IO; +using System.Text; + +namespace WaterCloud.Code +{ + public class FileHelper + { + public static string MapPath(string path) + { + try + { + string rootdir = Directory.GetCurrentDirectory(); + //DirectoryInfo Dir = Directory.GetParent(rootdir); + //string root = Dir.Parent.Parent.Parent.FullName; + return rootdir + path; + } + catch (Exception) + { + return path; + } + } + + #region 获取文件到集合中 + + /// + /// 读取指定位置文件列表到集合中 + /// + /// 指定路径 + /// + public static DataTable GetFileTable(string path) + { + DataTable dt = new DataTable(); + dt.Columns.Add("name", typeof(string)); + dt.Columns.Add("ext", typeof(string)); + dt.Columns.Add("size", typeof(long)); + dt.Columns.Add("time", typeof(DateTime)); + + if (Directory.Exists(path)) + { + DirectoryInfo dirinfo = new DirectoryInfo(path); + FileInfo fi; + DirectoryInfo dir; + string FileName, FileExt; + long FileSize = 0; + DateTime FileModify; + try + { + foreach (FileSystemInfo fsi in dirinfo.GetFileSystemInfos()) + { + FileName = string.Empty; + FileExt = string.Empty; + if (fsi is FileInfo) + { + fi = (FileInfo)fsi; + //获取文件名称 + FileName = fi.Name; + //获取文件扩展名 + FileExt = fi.Extension; + //获取文件大小 + FileSize = fi.Length; + //获取文件最后修改时间 + FileModify = fi.LastWriteTime; + } + else + { + dir = (DirectoryInfo)fsi; + //获取目录名 + FileName = dir.Name; + //获取目录最后修改时间 + FileModify = dir.LastWriteTime; + //设置目录文件为文件夹 + FileExt = "文件夹"; + } + DataRow dr = dt.NewRow(); + dr["name"] = FileName; + dr["ext"] = FileExt; + dr["size"] = FileSize; + dr["time"] = FileModify; + dt.Rows.Add(dr); + } + } + catch + { + throw; + } + } + return dt; + } + + #endregion 获取文件到集合中 + + #region 检测指定路径是否存在 + + /// + /// 检测指定路径是否存在 + /// + /// 目录的绝对路径 + public static bool IsExistDirectory(string path) + { + return Directory.Exists(path); + } + + #endregion 检测指定路径是否存在 + + #region 检测指定文件是否存在,如果存在则返回true + + /// + /// 检测指定文件是否存在,如果存在则返回true + /// + /// 文件的绝对路径 + public static bool IsExistFile(string filePath) + { + return File.Exists(filePath); + } + + #endregion 检测指定文件是否存在,如果存在则返回true + + #region 创建文件夹 + + /// + /// 创建文件夹 + /// + /// 文件夹的绝对路径 + public static void CreateFolder(string folderPath) + { + if (!IsExistDirectory(folderPath)) + { + Directory.CreateDirectory(folderPath); + } + } + + #endregion 创建文件夹 + + #region 判断上传文件后缀名 + + /// + /// 判断上传文件后缀名 + /// + /// 后缀名 + public static bool IsCanEdit(string strExtension) + { + strExtension = strExtension.ToLower(); + if (strExtension.LastIndexOf(".", StringComparison.Ordinal) >= 0) + { + strExtension = strExtension.Substring(strExtension.LastIndexOf(".", StringComparison.Ordinal)); + } + else + { + strExtension = ".txt"; + } + string[] strArray = new string[] { ".htm", ".html", ".txt", ".js", ".css", ".xml", ".sitemap" }; + for (int i = 0; i < strArray.Length; i++) + { + if (strExtension.Equals(strArray[i])) + { + return true; + } + } + return false; + } + + public static bool IsSafeName(string strExtension) + { + strExtension = strExtension.ToLower(); + if (strExtension.LastIndexOf(".") >= 0) + { + strExtension = strExtension.Substring(strExtension.LastIndexOf(".")); + } + else + { + strExtension = ".txt"; + } + string[] strArray = new string[] { ".jpg", ".gif", ".png" }; + for (int i = 0; i < strArray.Length; i++) + { + if (strExtension.Equals(strArray[i])) + { + return true; + } + } + return false; + } + + public static bool IsZipName(string strExtension) + { + strExtension = strExtension.ToLower(); + if (strExtension.LastIndexOf(".") >= 0) + { + strExtension = strExtension.Substring(strExtension.LastIndexOf(".")); + } + else + { + strExtension = ".txt"; + } + string[] strArray = new string[] { ".zip", ".rar" }; + for (int i = 0; i < strArray.Length; i++) + { + if (strExtension.Equals(strArray[i])) + { + return true; + } + } + return false; + } + + #endregion 判断上传文件后缀名 + + #region 创建文件夹 + + /// + /// 创建文件夹 + /// + /// 文件的绝对路径 + public static void CreateSuffic(string fileName) + { + try + { + if (!Directory.Exists(fileName)) + { + Directory.CreateDirectory(fileName); + } + } + catch (Exception) + { + throw; + } + } + + /// + /// 创建文件夹 + /// + /// 文件的绝对路径 + public static void CreateFiles(string fileName) + { + try + { + //判断文件是否存在,不存在创建该文件 + if (!IsExistFile(fileName)) + { + FileInfo file = new FileInfo(fileName); + FileStream fs = file.Create(); + fs.Close(); + } + } + catch (Exception ex) + { + LogHelper.WriteWithTime(ex); + } + } + + #region 创建文本文件 + + /// + /// 创建文件 + /// + /// + /// + public static void CreateFile(string path, string content) + { + if (!Directory.Exists(Path.GetDirectoryName(path))) + { + Directory.CreateDirectory(Path.GetDirectoryName(path)); + } + using (StreamWriter sw = new StreamWriter(path, false, Encoding.UTF8)) + { + sw.Write(content); + } + } + + #endregion 创建文本文件 + + /// + /// 创建一个文件,并将字节流写入文件。 + /// + /// 文件的绝对路径 + /// 二进制流数据 + public static void CreateFile(string filePath, byte[] buffer) + { + try + { + //判断文件是否存在,不存在创建该文件 + if (!IsExistFile(filePath)) + { + FileInfo file = new FileInfo(filePath); + FileStream fs = file.Create(); + fs.Write(buffer, 0, buffer.Length); + fs.Close(); + } + else + { + File.WriteAllBytes(filePath, buffer); + } + } + catch (Exception ex) + { + LogHelper.WriteWithTime(ex); + } + } + + #endregion 创建文件夹 + + #region 将文件移动到指定目录 + + /// + /// 将文件移动到指定目录 + /// + /// 需要移动的源文件的绝对路径 + /// 移动到的目录的绝对路径 + public static void Move(string sourceFilePath, string descDirectoryPath) + { + string sourceName = GetFileName(sourceFilePath); + if (IsExistDirectory(descDirectoryPath)) + { + //如果目标中存在同名文件,则删除 + if (IsExistFile(descDirectoryPath + "\\" + sourceFilePath)) + { + DeleteFile(descDirectoryPath + "\\" + sourceFilePath); + } + else + { + //将文件移动到指定目录 + File.Move(sourceFilePath, descDirectoryPath + "\\" + sourceFilePath); + } + } + } + + #endregion 将文件移动到指定目录 + + #region 将源文件的内容复制到目标文件中 + + /// + /// 将源文件的内容复制到目标文件中 + /// + /// 源文件的绝对路径 + /// 目标文件的绝对路径 + public static void Copy(string sourceFilePath, string descDirectoryPath) + { + File.Copy(sourceFilePath, descDirectoryPath, true); + } + + #endregion 将源文件的内容复制到目标文件中 + + #region 从文件的绝对路径中获取文件名( 不包含扩展名 ) + + /// + /// 从文件的绝对路径中获取文件名( 不包含扩展名 ) + /// + /// 文件的绝对路径 + public static string GetFileName(string filePath) + { + FileInfo file = new FileInfo(filePath); + return file.Name; + } + + #endregion 从文件的绝对路径中获取文件名( 不包含扩展名 ) + + #region 获取文件的后缀名 + + /// + /// 获取文件的后缀名 + /// + /// 文件的绝对路径 + public static string GetExtension(string filePath) + { + FileInfo file = new FileInfo(filePath); + return file.Extension; + } + + /// + /// 返回文件扩展名,不含“.” + /// + /// 文件全名称 + /// string + public static string GetFileExt(string filepath) + { + if (string.IsNullOrEmpty(filepath)) + { + return ""; + } + if (filepath.LastIndexOf(".", StringComparison.Ordinal) > 0) + { + return filepath.Substring(filepath.LastIndexOf(".", StringComparison.Ordinal) + 1); //文件扩展名,不含“.” + } + return ""; + } + + #endregion 获取文件的后缀名 + + #region 删除指定文件 + + /// + /// 删除指定文件 + /// + /// 文件的绝对路径 + public static void DeleteFile(string filePath) + { + if (IsExistFile(filePath)) + { + File.Delete(filePath); + } + } + + #endregion 删除指定文件 + + #region 删除指定目录及其所有子目录 + + /// + /// 删除指定目录及其所有子目录 + /// + /// 文件的绝对路径 + public static void DeleteDirectory(string directoryPath) + { + if (IsExistDirectory(directoryPath)) + { + Directory.Delete(directoryPath); + } + } + + #endregion 删除指定目录及其所有子目录 + + #region 清空指定目录下所有文件及子目录,但该目录依然保存. + + /// + /// 清空指定目录下所有文件及子目录,但该目录依然保存. + /// + /// 指定目录的绝对路径 + public static void ClearDirectory(string directoryPath) + { + if (!IsExistDirectory(directoryPath)) return; + //删除目录中所有的文件 + string[] fileNames = GetFileNames(directoryPath); + for (int i = 0; i < fileNames.Length; i++) + { + DeleteFile(fileNames[i]); + } + //删除目录中所有的子目录 + string[] directoryNames = GetDirectories(directoryPath); + for (int i = 0; i < directoryNames.Length; i++) + { + DeleteDirectory(directoryNames[i]); + } + } + + #endregion 清空指定目录下所有文件及子目录,但该目录依然保存. + + #region 剪切 粘贴 + + /// + /// 剪切文件 + /// + /// 原路径 + /// 新路径 + public bool FileMove(string source, string destination) + { + bool ret = false; + FileInfo file_s = new FileInfo(source); + FileInfo file_d = new FileInfo(destination); + if (file_s.Exists) + { + if (!file_d.Exists) + { + file_s.MoveTo(destination); + ret = true; + } + } + if (ret == true) + { + //Response.Write(""); + } + else + { + //Response.Write(""); + } + return ret; + } + + #endregion 剪切 粘贴 + + #region 检测指定目录是否为空 + + /// + /// 检测指定目录是否为空 + /// + /// 指定目录的绝对路径 + public static bool IsEmptyDirectory(string directoryPath) + { + try + { + //判断文件是否存在 + string[] fileNames = GetFileNames(directoryPath); + if (fileNames.Length > 0) + { + return false; + } + //判断是否存在文件夹 + string[] directoryNames = GetDirectories(directoryPath); + if (directoryNames.Length > 0) + { + return false; + } + return true; + } + catch (Exception) + { + return true; + } + } + + #endregion 检测指定目录是否为空 + + #region 获取指定目录中所有文件列表 + + /// + /// 获取指定目录中所有文件列表 + /// + /// 指定目录的绝对路径 + public static string[] GetFileNames(string directoryPath) + { + if (!IsExistDirectory(directoryPath)) + { + throw new FileNotFoundException(); + } + return Directory.GetFiles(directoryPath); + } + + #endregion 获取指定目录中所有文件列表 + + #region 获取指定目录中的子目录列表 + + /// + /// 获取指定目录中所有子目录列表,若要搜索嵌套的子目录列表,请使用重载方法 + /// + /// 指定目录的绝对路径 + public static string[] GetDirectories(string directoryPath) + { + return Directory.GetDirectories(directoryPath); + } + + /// + /// 获取指定目录及子目录中所有子目录列表 + /// + /// 指定目录的绝对路径 + /// 模式字符串,"*"代表0或N个字符,"?"代表1个字符。 + /// 范例:"Log*.xml"表示搜索所有以Log开头的Xml文件。 + /// 是否搜索子目录 + public static string[] GetDirectories(string directoryPath, string searchPattern, bool isSearchChild) + { + if (isSearchChild) + { + return Directory.GetDirectories(directoryPath, searchPattern, SearchOption.AllDirectories); + } + else + { + return Directory.GetDirectories(directoryPath, searchPattern, SearchOption.TopDirectoryOnly); + } + } + + #endregion 获取指定目录中的子目录列表 + + #region 获取一个文件的长度 + + /// + /// 获取一个文件的长度,单位为Byte + /// + /// 文件的绝对路径 + public static int GetFileSize(string filePath) + { + //创建一个文件对象 + FileInfo fi = new FileInfo(filePath); + //获取文件的大小 + return (int)fi.Length; + } + + /// + /// 获取一个文件的长度,单位为KB + /// + /// 文件的路径 + public static double GetFileSizeByKb(string filePath) + { + //创建一个文件对象 + FileInfo fi = new FileInfo(filePath); + //获取文件的大小 + return Math.Round(Convert.ToDouble(filePath.Length) / 1024, 2);// ConvertHelper.ToDouble(ConvertHelper.ToDouble(fi.Length) / 1024, 1); + } + + /// + /// 获取一个文件的长度,单位为MB + /// + /// 文件的路径 + public static double GetFileSizeByMb(string filePath) + { + //创建一个文件对象 + FileInfo fi = new FileInfo(filePath); + //获取文件的大小 + return Math.Round(Convert.ToDouble(Convert.ToDouble(fi.Length) / 1024 / 1024), 2); + } + + #endregion 获取一个文件的长度 + + #region 获取文件大小并以B,KB,GB,TB + + /// + /// 计算文件大小函数(保留两位小数),Size为字节大小 + /// + /// 初始文件大小 + /// + public static string ToFileSize(long size) + { + string m_strSize = ""; + long FactSize = 0; + FactSize = size; + if (FactSize < 1024.00) + m_strSize = FactSize.ToString("F2") + " 字节"; + else if (FactSize >= 1024.00 && FactSize < 1048576) + m_strSize = (FactSize / 1024.00).ToString("F2") + " KB"; + else if (FactSize >= 1048576 && FactSize < 1073741824) + m_strSize = (FactSize / 1024.00 / 1024.00).ToString("F2") + " MB"; + else if (FactSize >= 1073741824) + m_strSize = (FactSize / 1024.00 / 1024.00 / 1024.00).ToString("F2") + " GB"; + return m_strSize; + } + + #endregion 获取文件大小并以B,KB,GB,TB + + #region 将文件读取到字符串中 + + /// + /// 将文件读取到字符串中 + /// + /// 文件的绝对路径 + public static string FileToString(string filePath) + { + return FileToString(filePath, Encoding.UTF8); + } + + /// + /// 将文件读取到字符串中 + /// + /// 文件的绝对路径 + /// 字符编码 + public static string FileToString(string filePath, Encoding encoding) + { + //创建流读取器 + StreamReader reader = new StreamReader(filePath, encoding); + try + { + //读取流 + return reader.ReadToEnd(); + } + finally + { + //关闭流读取器 + reader.Close(); + } + } + + #endregion 将文件读取到字符串中 + + #region 判断文件 + + // 判断文件是否是bai图片 + public static bool IsPicture(string fileName) + { + string strFilter = ".jpeg|.gif|.jpg|.png|.bmp|.pic|.tiff|.ico|.iff|.lbm|.mag|.mac|.mpt|.opt|"; + char[] separtor = { '|' }; + string[] tempFileds = StringSplit(strFilter, separtor); + foreach (string str in tempFileds) + { + if (str.ToUpper() == fileName.Substring(fileName.LastIndexOf("."), fileName.Length - fileName.LastIndexOf(".")).ToUpper()) { return true; } + } + return false; + } + + // 判断文件是否是excle + public static bool IsExcel(string fileName) + { + string strFilter = ".xls|.xlsx|"; + char[] separtor = { '|' }; + string[] tempFileds = StringSplit(strFilter, separtor); + foreach (string str in tempFileds) + { + if (str.ToUpper() == fileName.Substring(fileName.LastIndexOf("."), fileName.Length - fileName.LastIndexOf(".")).ToUpper()) { return true; } + } + return false; + } + + // 通过字符串,分隔符返回zhistring[]数组  + public static string[] StringSplit(string s, char[] separtor) + { + string[] tempFileds = s.Trim().Split(separtor); return tempFileds; + } + + #endregion 判断文件 + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/HttpWebClient.cs b/WaterCloud.Code/Util/HttpWebClient.cs new file mode 100644 index 0000000..08c58f2 --- /dev/null +++ b/WaterCloud.Code/Util/HttpWebClient.cs @@ -0,0 +1,225 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; + +namespace WaterCloud.Code +{ + public class HttpWebClient + { + private IHttpClientFactory _httpClientFactory; + + public HttpWebClient(IHttpClientFactory httpClientFactory) + { + this._httpClientFactory = httpClientFactory; + } + + /// + /// Get异步请求 + /// + /// + /// + /// + /// + public async Task GetAsync(string url, Dictionary dicHeaders, int timeoutSecond = 120) + { + var client = _httpClientFactory.CreateClient(); + var request = new HttpRequestMessage(HttpMethod.Get, url); + if (dicHeaders != null) + { + foreach (var header in dicHeaders) + { + request.Headers.Add(header.Key, header.Value); + } + } + client.Timeout = TimeSpan.FromSeconds(timeoutSecond); + var response = await client.SendAsync(request); + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadAsStringAsync(); + return result; + } + else + { + throw new CustomerHttpException($"接口请求错误,错误代码{response.StatusCode},错误原因{response.ReasonPhrase}"); + } + } + + /// + /// + /// + /// + /// + /// + /// + /// + public async Task PostAsync(string url, string requestString, Dictionary dicHeaders, int timeoutSecond) + { + var client = _httpClientFactory.CreateClient(); + var requestContent = new StringContent(requestString); + if (dicHeaders != null) + { + foreach (var head in dicHeaders) + { + requestContent.Headers.Add(head.Key, head.Value); + } + } + client.Timeout = TimeSpan.FromSeconds(timeoutSecond); + var response = await client.PostAsync(url, requestContent); + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadAsStringAsync(); + return result; + } + else + { + throw new CustomerHttpException($"接口请求错误,错误代码{response.StatusCode},错误原因{response.ReasonPhrase}"); + } + } + + /// + /// + /// + /// + /// + /// + /// + /// + public async Task PutAsync(string url, string requestString, Dictionary dicHeaders, int timeoutSecond) + { + var client = _httpClientFactory.CreateClient(); + var requestContent = new StringContent(requestString); + if (dicHeaders != null) + { + foreach (var head in dicHeaders) + { + requestContent.Headers.Add(head.Key, head.Value); + } + } + client.Timeout = TimeSpan.FromSeconds(timeoutSecond); + var response = await client.PutAsync(url, requestContent); + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadAsStringAsync(); + return result; + } + else + { + throw new CustomerHttpException($"接口请求错误,错误代码{response.StatusCode},错误原因{response.ReasonPhrase}"); + } + } + + /// + /// Patch异步请求 + /// + /// + /// + /// + /// + /// + public async Task PatchAsync(string url, string requestString, Dictionary dicHeaders, int timeoutSecond) + { + var client = _httpClientFactory.CreateClient(); + var requestContent = new StringContent(requestString); + if (dicHeaders != null) + { + foreach (var head in dicHeaders) + { + requestContent.Headers.Add(head.Key, head.Value); + } + } + client.Timeout = TimeSpan.FromSeconds(timeoutSecond); + var response = await client.PatchAsync(url, requestContent); + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadAsStringAsync(); + return result; + } + else + { + throw new CustomerHttpException($"接口请求错误,错误代码{response.StatusCode},错误原因{response.ReasonPhrase}"); + } + } + + public async Task DeleteAsync(string url, Dictionary dicHeaders, int timeoutSecond) + { + var client = _httpClientFactory.CreateClient(); + var request = new HttpRequestMessage(HttpMethod.Delete, url); + if (dicHeaders != null) + { + foreach (var head in dicHeaders) + { + request.Headers.Add(head.Key, head.Value); + } + } + client.Timeout = TimeSpan.FromSeconds(timeoutSecond); + var response = await client.SendAsync(request); + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadAsStringAsync(); + return result; + } + else + { + throw new CustomerHttpException($"接口请求错误,错误代码{response.StatusCode},错误原因{response.ReasonPhrase}"); + } + } + + /// + /// 异步请求(通用) + /// + /// + /// + /// + /// + /// + /// + public async Task ExecuteAsync(string url, HttpMethod method, string requestString, Dictionary dicHeaders, int timeoutSecond = 120, + string accept = "application/json") + { + var client = _httpClientFactory.CreateClient(); + if (url.IndexOf('?') > -1) + { + url += "&v=" + DateTime.Now.ToString("yyyyMMddhhmmss"); + } + else + { + url += "?v=" + DateTime.Now.ToString("yyyyMMddhhmmss"); + } + var request = new HttpRequestMessage(method, url) + { + Content = new StringContent(requestString), + }; + request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); + if (dicHeaders != null) + { + foreach (var header in dicHeaders) + { + request.Headers.Add(header.Key, header.Value); + } + } + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(accept) { CharSet = "utf-8" }); + var response = await client.SendAsync(request); + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadAsStringAsync(); + return result; + } + else + { + throw new CustomerHttpException($"接口请求错误,错误代码{response.StatusCode},错误原因{response.ReasonPhrase}"); + } + } + } + + public class CustomerHttpException : Exception + { + public CustomerHttpException() : base() + { } + + public CustomerHttpException(string message) : base(message) + { + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/JsonHelper.cs b/WaterCloud.Code/Util/JsonHelper.cs new file mode 100644 index 0000000..d5e07f8 --- /dev/null +++ b/WaterCloud.Code/Util/JsonHelper.cs @@ -0,0 +1,138 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; + +namespace WaterCloud.Code +{ + #region JsonHelper + + public static class JsonHelper + { + /// + /// 把数组转为逗号连接的字符串 + /// + /// + /// + /// + public static string ArrayToString(dynamic data, string Str) + { + string resStr = Str; + foreach (var item in data) + { + if (resStr != "") + { + resStr += ","; + } + + if (item is string) + { + resStr += item; + } + else + { + resStr += item.Value; + } + } + return resStr; + } + + public static object ToObject(this string Json) + { + return string.IsNullOrEmpty(Json) ? null : JsonConvert.DeserializeObject(Json); + } + + public static T ToObject(this string Json) + { + Json = Json.Replace(" ", ""); + return Json == null ? default(T) : JsonConvert.DeserializeObject(Json); + } + + public static JObject ToJObject(this string Json) + { + return Json == null ? JObject.Parse("{}") : JObject.Parse(Json.Replace(" ", "")); + } + + public static List ToList(this string Json) + { + return Json == null ? null : JsonConvert.DeserializeObject>(Json); + } + + public static string ToJson(this object obj, string dateFormat = "yyyy/MM/dd HH:mm:ss") + { + return obj == null ? string.Empty : JsonConvert.SerializeObject(obj, new IsoDateTimeConverter { DateTimeFormat = dateFormat }); + } + } + + #endregion JsonHelper + + #region JsonConverter + + /// + /// Json数据返回到前端js的时候,把数值很大的long类型转成字符串 + /// + public class StringJsonConverter : JsonConverter + { + public StringJsonConverter() + { } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + return reader.Value.ToLong(); + } + + public override bool CanConvert(Type objectType) + { + return true; + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (value == null) + { + writer.WriteNull(); + return; + } + string sValue = value.ToString(); + writer.WriteValue(sValue); + } + } + + /// + /// DateTime类型序列化的时候,转成指定的格式 + /// + public class DateTimeJsonConverter : JsonConverter + { + public DateTimeJsonConverter() + { } + + public override bool CanConvert(Type objectType) + { + return true; + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + return reader.Value.ParseToString().ToDate(); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (value == null) + { + writer.WriteNull(); + return; + } + DateTime? dt = value as DateTime?; + if (dt == null) + { + writer.WriteNull(); + return; + } + writer.WriteValue(dt.Value.ToString("yyyy/MM/dd HH:mm:ss")); + } + } + + #endregion JsonConverter +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/LogHelper.cs b/WaterCloud.Code/Util/LogHelper.cs new file mode 100644 index 0000000..e15a75d --- /dev/null +++ b/WaterCloud.Code/Util/LogHelper.cs @@ -0,0 +1,252 @@ +using Microsoft.AspNetCore.Http.Extensions; +using Microsoft.AspNetCore.Mvc.Filters; +using System; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace WaterCloud.Code +{ + public class LogHelper + { + private static object lockHelper = new object(); + + #region 写文本日志 + + /// + /// 写日志 异步 + /// 默认路径:根目录/Log/yyyy-MM/ + /// 默认文件:yyyy-MM-dd.log + /// + /// 日志内容 自动附加时间 + public static void Write(string logContent) + { + string logPath = DateTime.Now.ToString("yyyy-MM"); + Write(logPath, logContent); + } + + public static void WriteWithTime(string logContent) + { + string logPath = DateTime.Now.ToString("yyyy-MM"); + logContent = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + Environment.NewLine + logContent; + Write(logPath, logContent); + } + + #endregion 写文本日志 + + #region 写异常日志 + + /// + /// 写异常日志 + /// + /// + public static void Write(Exception ex) + { + string logContent = string.Empty; + string logPath = DateTime.Now.ToString("yyyy-MM"); + logContent += GetExceptionMessage(ex); + Write(logPath, logContent); + } + + public static void WriteWithTime(Exception ex) + { + string logContent = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + Environment.NewLine; + string logPath = DateTime.Now.ToString("yyyy-MM"); + logContent += GetExceptionMessage(ex); + Write(logPath, logContent); + } + + public static void WriteWithTime(ExceptionContext ex) + { + if (ex == null) + return; + string logContent = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + Environment.NewLine; + logContent += "程序异常" + Environment.NewLine; + string logPath = DateTime.Now.ToString("yyyy-MM"); + Exception Error = ex.Exception; + LogMessage logMessage = new LogMessage(); + logMessage.OperationTime = DateTime.Now; + logMessage.Url = ex.HttpContext.Request.GetDisplayUrl(); + if (ex.ActionDescriptor != null) + { + logMessage.Class = ex.ActionDescriptor.DisplayName; + } + else + { + logMessage.Class = "服务器配置问题"; + } + logMessage.Ip = WebHelper.Ip; + logMessage.Host = ex.HttpContext.Request.Host.ToString(); + var current = OperatorProvider.Provider.GetCurrent(); + if (current != null) + { + logMessage.UserName = current.UserCode + "(" + current.UserName + ")"; + } + var err = Error.GetOriginalException(); + logMessage.ExceptionInfo = err.Message; + logMessage.ExceptionSource = err.Source; + logMessage.ExceptionRemark = err.StackTrace; + logContent += ExceptionFormat(logMessage); + Write(logPath, logContent); + } + + private static string GetExceptionMessage(Exception ex) + { + string message = string.Empty; + if (ex != null) + { + message += ex.Message; + message += Environment.NewLine; + Exception originalException = ex.GetOriginalException(); + if (originalException != null) + { + if (originalException.Message != ex.Message) + { + message += originalException.Message; + message += Environment.NewLine; + } + } + message += ex.StackTrace; + message += Environment.NewLine; + } + return message; + } + + #endregion 写异常日志 + + #region 写日志到指定路径 + + /// + /// 写日志 异步 + /// 默认文件:yyyy-MM-dd.log + /// + /// 日志目录[默认程序根目录\Log\下添加,故使用相对路径,如:营销任务] + /// 日志内容 自动附加时间 + public static void Write(string logPath, string logContent) + { + string logFileName = DateTime.Now.ToString("yyyy-MM-dd") + ".log"; + Write(logPath, logFileName, logContent); + } + + /// + /// 写日志 异步 + /// + /// 日志目录 + /// 日志文件名 + /// 日志内容 自动附加时间 + public static void Write(string logPath, string logFileName, string logContent) + { + if (string.IsNullOrWhiteSpace(logContent)) + { + return; + } + if (string.IsNullOrWhiteSpace(logPath)) + { + logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", DateTime.Now.ToString("yyyy-MM")); + } + else + { + logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", logPath.Trim('\\')); + } + if (string.IsNullOrWhiteSpace(logFileName)) + { + logFileName = DateTime.Now.ToString("yyyy-MM-dd") + ".log"; + } + if (!Directory.Exists(logPath)) + { + Directory.CreateDirectory(logPath); + } + string fileName = Path.Combine(logPath, logFileName); + Action taskAction = () => + { + lock (lockHelper) + { + using (StreamWriter sw = File.AppendText(fileName)) + { + sw.WriteLine(logContent + Environment.NewLine); + sw.Flush(); + sw.Close(); + } + } + }; + Task task = new Task(taskAction); + task.Start(); + } + + /// + /// 生成异常信息 + /// + /// 对象 + /// + public static string ExceptionFormat(LogMessage logMessage) + { + StringBuilder strInfo = new StringBuilder(); + strInfo.Append("1. 调试: >> 操作时间: " + logMessage.OperationTime + " 操作人: " + logMessage.UserName + " \r\n"); + strInfo.Append("2. 地址: " + logMessage.Url + " \r\n"); + strInfo.Append("3. 类名: " + logMessage.Class + " \r\n"); + strInfo.Append("4. 主机: " + logMessage.Host + " Ip : " + logMessage.Ip + " \r\n"); + strInfo.Append("5. 异常: " + logMessage.ExceptionInfo + "\r\n"); + strInfo.Append("6. 来源: " + logMessage.ExceptionSource + "\r\n"); + strInfo.Append("7. 实例: " + logMessage.ExceptionRemark + "\r\n"); + strInfo.Append("-----------------------------------------------------------------------------------------------------------------------------\r\n"); + return strInfo.ToString(); + } + + /// + /// 格式化异常信息 + /// + /// 对象 + /// + public static string ExMsgFormat(string message) + { + //数据库异常 + if (message.Contains("An exception occurred while executing DbCommand.")) + { + if (message.Contains("Duplicate entry '") && message.Contains("key")) + { + message = "数据违反唯一约束,请检查"; + } + else if (message.Contains("Data too long for column")) + { + message = "数据长度过长,请检查"; + } + else + { + message = "数据操作异常,请联系管理员"; + } + } + //其他异常 + else + { + if (message.Contains("Object reference not set to an instance of an object.")) + { + message = "操作对象为空,请联系管理员"; + } + else if (message.Contains("Value cannot be null")) + { + message = "值为空,请联系管理员"; + } + } + if (!IsHasCHZN(message)) + { + message = "程序内部异常,请联系管理员"; + } + return message; + } + + /// + /// 检测是否有中文字符 + /// + /// + /// + private static bool IsHasCHZN(string inputData) + { + Regex RegCHZN = new Regex("[\u4e00-\u9fa5]"); + Match m = RegCHZN.Match(inputData); + return m.Success; + } + + #endregion 写日志到指定路径 + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/LogMessage.cs b/WaterCloud.Code/Util/LogMessage.cs new file mode 100644 index 0000000..cf2189c --- /dev/null +++ b/WaterCloud.Code/Util/LogMessage.cs @@ -0,0 +1,57 @@ +using System; + +namespace WaterCloud.Code +{ + public class LogMessage + { + /// + /// 操作时间 + /// + public DateTime OperationTime { get; set; } + + /// + /// Url地址 + /// + public string Url { get; set; } + + /// + /// 类名 + /// + public string Class { get; set; } + + /// + /// IP + /// + public string Ip { get; set; } + + /// + /// 主机 + /// + public string Host { get; set; } + + /// + /// 操作人 + /// + public string UserName { get; set; } + + /// + /// 内容 + /// + public string Content { get; set; } + + /// + /// 异常信息 + /// + public string ExceptionInfo { get; set; } + + /// + /// 异常来源 + /// + public string ExceptionSource { get; set; } + + /// + /// 异常信息备注 + /// + public string ExceptionRemark { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/MimeMapping.cs b/WaterCloud.Code/Util/MimeMapping.cs new file mode 100644 index 0000000..de8e8f5 --- /dev/null +++ b/WaterCloud.Code/Util/MimeMapping.cs @@ -0,0 +1,236 @@ +using System; +using System.Collections; + +namespace WaterCloud.Code +{ + // 通过自己定义一个静态类 + // 将所有的Content Type都扔进去吧 + // 调用的时候直接调用静态方法即可。 + public static class MimeMapping + { + private static Hashtable _mimeMappingTable; + + private static void AddMimeMapping(string extension, string MimeType) + { + MimeMapping._mimeMappingTable.Add(extension, MimeType); + } + + public static string GetMimeMapping(string FileName) + { + string text = null; + int num = FileName.LastIndexOf('.'); + if (0 < num && num > FileName.LastIndexOf('\\')) + { + text = (string)MimeMapping._mimeMappingTable[FileName.Substring(num)]; + } + if (text == null) + { + text = (string)MimeMapping._mimeMappingTable[".*"]; + } + return text; + } + + static MimeMapping() + { + MimeMapping._mimeMappingTable = new Hashtable(190, StringComparer.CurrentCultureIgnoreCase); + MimeMapping.AddMimeMapping(".323", "text/h323"); + MimeMapping.AddMimeMapping(".asx", "video/x-ms-asf"); + MimeMapping.AddMimeMapping(".acx", "application/internet-property-stream"); + MimeMapping.AddMimeMapping(".ai", "application/postscript"); + MimeMapping.AddMimeMapping(".aif", "audio/x-aiff"); + MimeMapping.AddMimeMapping(".aiff", "audio/aiff"); + MimeMapping.AddMimeMapping(".axs", "application/olescript"); + MimeMapping.AddMimeMapping(".aifc", "audio/aiff"); + MimeMapping.AddMimeMapping(".asr", "video/x-ms-asf"); + MimeMapping.AddMimeMapping(".avi", "video/x-msvideo"); + MimeMapping.AddMimeMapping(".asf", "video/x-ms-asf"); + MimeMapping.AddMimeMapping(".au", "audio/basic"); + MimeMapping.AddMimeMapping(".application", "application/x-ms-application"); + MimeMapping.AddMimeMapping(".bin", "application/octet-stream"); + MimeMapping.AddMimeMapping(".bas", "text/plain"); + MimeMapping.AddMimeMapping(".bcpio", "application/x-bcpio"); + MimeMapping.AddMimeMapping(".bmp", "image/bmp"); + MimeMapping.AddMimeMapping(".cdf", "application/x-cdf"); + MimeMapping.AddMimeMapping(".cat", "application/vndms-pkiseccat"); + MimeMapping.AddMimeMapping(".crt", "application/x-x509-ca-cert"); + MimeMapping.AddMimeMapping(".c", "text/plain"); + MimeMapping.AddMimeMapping(".css", "text/css"); + MimeMapping.AddMimeMapping(".cer", "application/x-x509-ca-cert"); + MimeMapping.AddMimeMapping(".crl", "application/pkix-crl"); + MimeMapping.AddMimeMapping(".cmx", "image/x-cmx"); + MimeMapping.AddMimeMapping(".csh", "application/x-csh"); + MimeMapping.AddMimeMapping(".cod", "image/cis-cod"); + MimeMapping.AddMimeMapping(".cpio", "application/x-cpio"); + MimeMapping.AddMimeMapping(".clp", "application/x-msclip"); + MimeMapping.AddMimeMapping(".crd", "application/x-mscardfile"); + MimeMapping.AddMimeMapping(".deploy", "application/octet-stream"); + MimeMapping.AddMimeMapping(".dll", "application/x-msdownload"); + MimeMapping.AddMimeMapping(".dot", "application/msword"); + MimeMapping.AddMimeMapping(".doc", "application/msword"); + MimeMapping.AddMimeMapping(".dvi", "application/x-dvi"); + MimeMapping.AddMimeMapping(".dir", "application/x-director"); + MimeMapping.AddMimeMapping(".dxr", "application/x-director"); + MimeMapping.AddMimeMapping(".der", "application/x-x509-ca-cert"); + MimeMapping.AddMimeMapping(".dib", "image/bmp"); + MimeMapping.AddMimeMapping(".dcr", "application/x-director"); + MimeMapping.AddMimeMapping(".disco", "text/xml"); + MimeMapping.AddMimeMapping(".exe", "application/octet-stream"); + MimeMapping.AddMimeMapping(".etx", "text/x-setext"); + MimeMapping.AddMimeMapping(".evy", "application/envoy"); + MimeMapping.AddMimeMapping(".eml", "message/rfc822"); + MimeMapping.AddMimeMapping(".eps", "application/postscript"); + MimeMapping.AddMimeMapping(".flr", "x-world/x-vrml"); + MimeMapping.AddMimeMapping(".fif", "application/fractals"); + MimeMapping.AddMimeMapping(".gtar", "application/x-gtar"); + MimeMapping.AddMimeMapping(".gif", "image/gif"); + MimeMapping.AddMimeMapping(".gz", "application/x-gzip"); + MimeMapping.AddMimeMapping(".hta", "application/hta"); + MimeMapping.AddMimeMapping(".htc", "text/x-component"); + MimeMapping.AddMimeMapping(".htt", "text/webviewhtml"); + MimeMapping.AddMimeMapping(".h", "text/plain"); + MimeMapping.AddMimeMapping(".hdf", "application/x-hdf"); + MimeMapping.AddMimeMapping(".hlp", "application/winhlp"); + MimeMapping.AddMimeMapping(".html", "text/html"); + MimeMapping.AddMimeMapping(".htm", "text/html"); + MimeMapping.AddMimeMapping(".hqx", "application/mac-binhex40"); + MimeMapping.AddMimeMapping(".isp", "application/x-internet-signup"); + MimeMapping.AddMimeMapping(".iii", "application/x-iphone"); + MimeMapping.AddMimeMapping(".ief", "image/ief"); + MimeMapping.AddMimeMapping(".ivf", "video/x-ivf"); + MimeMapping.AddMimeMapping(".ins", "application/x-internet-signup"); + MimeMapping.AddMimeMapping(".ico", "image/x-icon"); + MimeMapping.AddMimeMapping(".jpg", "image/jpeg"); + MimeMapping.AddMimeMapping(".jfif", "image/pjpeg"); + MimeMapping.AddMimeMapping(".jpe", "image/jpeg"); + MimeMapping.AddMimeMapping(".jpeg", "image/jpeg"); + MimeMapping.AddMimeMapping(".js", "application/x-javascript"); + MimeMapping.AddMimeMapping(".lsx", "video/x-la-asf"); + MimeMapping.AddMimeMapping(".latex", "application/x-latex"); + MimeMapping.AddMimeMapping(".lsf", "video/x-la-asf"); + MimeMapping.AddMimeMapping(".manifest", "application/x-ms-manifest"); + MimeMapping.AddMimeMapping(".mhtml", "message/rfc822"); + MimeMapping.AddMimeMapping(".mny", "application/x-msmoney"); + MimeMapping.AddMimeMapping(".mht", "message/rfc822"); + MimeMapping.AddMimeMapping(".mid", "audio/mid"); + MimeMapping.AddMimeMapping(".mpv2", "video/mpeg"); + MimeMapping.AddMimeMapping(".man", "application/x-troff-man"); + MimeMapping.AddMimeMapping(".mvb", "application/x-msmediaview"); + MimeMapping.AddMimeMapping(".mpeg", "video/mpeg"); + MimeMapping.AddMimeMapping(".m3u", "audio/x-mpegurl"); + MimeMapping.AddMimeMapping(".mdb", "application/x-msaccess"); + MimeMapping.AddMimeMapping(".mpp", "application/vnd.ms-project"); + MimeMapping.AddMimeMapping(".m1v", "video/mpeg"); + MimeMapping.AddMimeMapping(".mpa", "video/mpeg"); + MimeMapping.AddMimeMapping(".me", "application/x-troff-me"); + MimeMapping.AddMimeMapping(".m13", "application/x-msmediaview"); + MimeMapping.AddMimeMapping(".movie", "video/x-sgi-movie"); + MimeMapping.AddMimeMapping(".m14", "application/x-msmediaview"); + MimeMapping.AddMimeMapping(".mpe", "video/mpeg"); + MimeMapping.AddMimeMapping(".mp2", "video/mpeg"); + MimeMapping.AddMimeMapping(".mov", "video/quicktime"); + MimeMapping.AddMimeMapping(".mp3", "audio/mpeg"); + MimeMapping.AddMimeMapping(".mpg", "video/mpeg"); + MimeMapping.AddMimeMapping(".ms", "application/x-troff-ms"); + MimeMapping.AddMimeMapping(".nc", "application/x-netcdf"); + MimeMapping.AddMimeMapping(".nws", "message/rfc822"); + MimeMapping.AddMimeMapping(".oda", "application/oda"); + MimeMapping.AddMimeMapping(".ods", "application/oleobject"); + MimeMapping.AddMimeMapping(".pmc", "application/x-perfmon"); + MimeMapping.AddMimeMapping(".p7r", "application/x-pkcs7-certreqresp"); + MimeMapping.AddMimeMapping(".p7b", "application/x-pkcs7-certificates"); + MimeMapping.AddMimeMapping(".p7s", "application/pkcs7-signature"); + MimeMapping.AddMimeMapping(".pmw", "application/x-perfmon"); + MimeMapping.AddMimeMapping(".ps", "application/postscript"); + MimeMapping.AddMimeMapping(".p7c", "application/pkcs7-mime"); + MimeMapping.AddMimeMapping(".pbm", "image/x-portable-bitmap"); + MimeMapping.AddMimeMapping(".ppm", "image/x-portable-pixmap"); + MimeMapping.AddMimeMapping(".pub", "application/x-mspublisher"); + MimeMapping.AddMimeMapping(".pnm", "image/x-portable-anymap"); + MimeMapping.AddMimeMapping(".png", "image/png"); + MimeMapping.AddMimeMapping(".pml", "application/x-perfmon"); + MimeMapping.AddMimeMapping(".p10", "application/pkcs10"); + MimeMapping.AddMimeMapping(".pfx", "application/x-pkcs12"); + MimeMapping.AddMimeMapping(".p12", "application/x-pkcs12"); + MimeMapping.AddMimeMapping(".pdf", "application/pdf"); + MimeMapping.AddMimeMapping(".pps", "application/vnd.ms-powerpoint"); + MimeMapping.AddMimeMapping(".p7m", "application/pkcs7-mime"); + MimeMapping.AddMimeMapping(".pko", "application/vndms-pkipko"); + MimeMapping.AddMimeMapping(".ppt", "application/vnd.ms-powerpoint"); + MimeMapping.AddMimeMapping(".pmr", "application/x-perfmon"); + MimeMapping.AddMimeMapping(".pma", "application/x-perfmon"); + MimeMapping.AddMimeMapping(".pot", "application/vnd.ms-powerpoint"); + MimeMapping.AddMimeMapping(".prf", "application/pics-rules"); + MimeMapping.AddMimeMapping(".pgm", "image/x-portable-graymap"); + MimeMapping.AddMimeMapping(".qt", "video/quicktime"); + MimeMapping.AddMimeMapping(".ra", "audio/x-pn-realaudio"); + MimeMapping.AddMimeMapping(".rgb", "image/x-rgb"); + MimeMapping.AddMimeMapping(".ram", "audio/x-pn-realaudio"); + MimeMapping.AddMimeMapping(".rmi", "audio/mid"); + MimeMapping.AddMimeMapping(".ras", "image/x-cmu-raster"); + MimeMapping.AddMimeMapping(".roff", "application/x-troff"); + MimeMapping.AddMimeMapping(".rtf", "application/rtf"); + MimeMapping.AddMimeMapping(".rtx", "text/richtext"); + MimeMapping.AddMimeMapping(".sv4crc", "application/x-sv4crc"); + MimeMapping.AddMimeMapping(".spc", "application/x-pkcs7-certificates"); + MimeMapping.AddMimeMapping(".setreg", "application/set-registration-initiation"); + MimeMapping.AddMimeMapping(".snd", "audio/basic"); + MimeMapping.AddMimeMapping(".stl", "application/vndms-pkistl"); + MimeMapping.AddMimeMapping(".setpay", "application/set-payment-initiation"); + MimeMapping.AddMimeMapping(".stm", "text/html"); + MimeMapping.AddMimeMapping(".shar", "application/x-shar"); + MimeMapping.AddMimeMapping(".sh", "application/x-sh"); + MimeMapping.AddMimeMapping(".sit", "application/x-stuffit"); + MimeMapping.AddMimeMapping(".spl", "application/futuresplash"); + MimeMapping.AddMimeMapping(".sct", "text/scriptlet"); + MimeMapping.AddMimeMapping(".scd", "application/x-msschedule"); + MimeMapping.AddMimeMapping(".sst", "application/vndms-pkicertstore"); + MimeMapping.AddMimeMapping(".src", "application/x-wais-source"); + MimeMapping.AddMimeMapping(".sv4cpio", "application/x-sv4cpio"); + MimeMapping.AddMimeMapping(".tex", "application/x-tex"); + MimeMapping.AddMimeMapping(".tgz", "application/x-compressed"); + MimeMapping.AddMimeMapping(".t", "application/x-troff"); + MimeMapping.AddMimeMapping(".tar", "application/x-tar"); + MimeMapping.AddMimeMapping(".tr", "application/x-troff"); + MimeMapping.AddMimeMapping(".tif", "image/tiff"); + MimeMapping.AddMimeMapping(".txt", "text/plain"); + MimeMapping.AddMimeMapping(".texinfo", "application/x-texinfo"); + MimeMapping.AddMimeMapping(".trm", "application/x-msterminal"); + MimeMapping.AddMimeMapping(".tiff", "image/tiff"); + MimeMapping.AddMimeMapping(".tcl", "application/x-tcl"); + MimeMapping.AddMimeMapping(".texi", "application/x-texinfo"); + MimeMapping.AddMimeMapping(".tsv", "text/tab-separated-values"); + MimeMapping.AddMimeMapping(".ustar", "application/x-ustar"); + MimeMapping.AddMimeMapping(".uls", "text/iuls"); + MimeMapping.AddMimeMapping(".vcf", "text/x-vcard"); + MimeMapping.AddMimeMapping(".wps", "application/vnd.ms-works"); + MimeMapping.AddMimeMapping(".wav", "audio/wav"); + MimeMapping.AddMimeMapping(".wrz", "x-world/x-vrml"); + MimeMapping.AddMimeMapping(".wri", "application/x-mswrite"); + MimeMapping.AddMimeMapping(".wks", "application/vnd.ms-works"); + MimeMapping.AddMimeMapping(".wmf", "application/x-msmetafile"); + MimeMapping.AddMimeMapping(".wcm", "application/vnd.ms-works"); + MimeMapping.AddMimeMapping(".wrl", "x-world/x-vrml"); + MimeMapping.AddMimeMapping(".wdb", "application/vnd.ms-works"); + MimeMapping.AddMimeMapping(".wsdl", "text/xml"); + MimeMapping.AddMimeMapping(".xap", "application/x-silverlight-app"); + MimeMapping.AddMimeMapping(".xml", "text/xml"); + MimeMapping.AddMimeMapping(".xlm", "application/vnd.ms-excel"); + MimeMapping.AddMimeMapping(".xaf", "x-world/x-vrml"); + MimeMapping.AddMimeMapping(".xla", "application/vnd.ms-excel"); + MimeMapping.AddMimeMapping(".xls", "application/vnd.ms-excel"); + MimeMapping.AddMimeMapping(".xof", "x-world/x-vrml"); + MimeMapping.AddMimeMapping(".xlt", "application/vnd.ms-excel"); + MimeMapping.AddMimeMapping(".xlc", "application/vnd.ms-excel"); + MimeMapping.AddMimeMapping(".xsl", "text/xml"); + MimeMapping.AddMimeMapping(".xbm", "image/x-xbitmap"); + MimeMapping.AddMimeMapping(".xlw", "application/vnd.ms-excel"); + MimeMapping.AddMimeMapping(".xpm", "image/x-xpixmap"); + MimeMapping.AddMimeMapping(".xwd", "image/x-xwindowdump"); + MimeMapping.AddMimeMapping(".xsd", "text/xml"); + MimeMapping.AddMimeMapping(".z", "application/x-compress"); + MimeMapping.AddMimeMapping(".zip", "application/x-zip-compressed"); + MimeMapping.AddMimeMapping(".*", "application/octet-stream"); + MimeMapping.AddMimeMapping(".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/PdfHelper.cs b/WaterCloud.Code/Util/PdfHelper.cs new file mode 100644 index 0000000..76ad84b --- /dev/null +++ b/WaterCloud.Code/Util/PdfHelper.cs @@ -0,0 +1,58 @@ +using iTextSharp.text; +using iTextSharp.text.pdf; + +namespace WaterCloud.Code +{ + public class PdfHelper + { + } + + public class PDFFooter : PdfPageEventHelper + { + // write on top of document + public override void OnOpenDocument(PdfWriter writer, Document document) + { + base.OnOpenDocument(writer, document); + PdfPTable tabFot = new PdfPTable(new float[] { 1F }); + tabFot.SpacingAfter = 10F; + PdfPCell cell; + tabFot.TotalWidth = 300F; + cell = new PdfPCell(new Phrase("Header")); + tabFot.AddCell(cell); + tabFot.WriteSelectedRows(0, -1, 150, document.Top, writer.DirectContent); + } + + // write on start of each page + public override void OnStartPage(PdfWriter writer, Document document) + { + base.OnStartPage(writer, document); + } + + // write on end of each page + public override void OnEndPage(PdfWriter writer, Document document) + { + base.OnEndPage(writer, document); + //PdfPTable tabFot = new PdfPTable(new float[] { 1F }); + //tabFot.TotalWidth = 700f; + //tabFot.DefaultCell.Border = 0; + //// var footFont = FontFactory.GetFont("Lato", 12 * 0.667f, new Color(60, 60, 60)); + //string fontpath = HttpContext.Current.Server.MapPath("~/App_Data"); + //BaseFont customfont = BaseFont.CreateFont(fontpath + "\\Lato-Regular.ttf", BaseFont.CP1252, BaseFont.EMBEDDED); + //var footFont = new Font(customfont, 12 * 0.667f, Font.NORMAL, new Color(170, 170, 170)); + + //PdfPCell cell; + //cell = new PdfPCell(new Phrase("@ 2016 . All Rights Reserved", footFont)); + //cell.VerticalAlignment = Element.ALIGN_CENTER; + //cell.Border = 0; + //cell.PaddingLeft = 100f; + //tabFot.AddCell(cell); + //tabFot.WriteSelectedRows(0, -1, 150, document.Bottom, writer.DirectContent); + } + + //write on close of document + public override void OnCloseDocument(PdfWriter writer, Document document) + { + base.OnCloseDocument(writer, document); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/QueueHelper.cs b/WaterCloud.Code/Util/QueueHelper.cs new file mode 100644 index 0000000..876487e --- /dev/null +++ b/WaterCloud.Code/Util/QueueHelper.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections.Concurrent; +using System.Threading; +using System.Threading.Tasks; + +namespace WaterCloud.Code +{ + /// + /// 队列工具类,用于另起线程处理执行类型数据 + /// + /// + public class QueueHelper : IDisposable + { + #region Private Field + + /// + /// The inner queue. + /// + private readonly ConcurrentQueue _innerQueue; + + /// + /// The deal task. + /// + private readonly Task _dealTask; + + /// + /// The flag for end thread. + /// + private bool _endThreadFlag = false; + + /// + /// The auto reset event. + /// + private readonly AutoResetEvent _autoResetEvent = new(true); + + #endregion Private Field + + #region Public Property + + /// + /// The deal action. + /// + public Action DealAction { get; set; } + + #endregion Public Property + + #region Constructor + + /// + /// Initializes a new instance of the QueueHelper`1 class. + /// + public QueueHelper() + { + this._innerQueue = new(); + this._dealTask = Task.Run(() => this.DealQueue()); + } + + /// + /// Initializes a new instance of the QueueHelper<T> class. + /// + /// The deal action. + public QueueHelper(Action DealAction) + { + this.DealAction = DealAction; + this._innerQueue = new(); + this._dealTask = Task.Run(() => this.DealQueue()); + } + + #endregion Constructor + + #region Public Method + + /// + /// Save entity to Queue. + /// + /// The entity what will be deal. + public bool Enqueue(T entity) + { + if (!this._endThreadFlag) + { + this._innerQueue.Enqueue(entity); + this._autoResetEvent.Set(); + + return true; + } + + return false; + } + + /// + /// Disposes current instance, end the deal thread and inner queue. + /// + public void Dispose() + { + if (!this._endThreadFlag) + { + this._endThreadFlag = true; + this._innerQueue.Enqueue(default); + this._autoResetEvent.Set(); + + if (!this._dealTask.IsCompleted) + this._dealTask.Wait(); + + this._dealTask.Dispose(); + + this._autoResetEvent.Dispose(); + this._autoResetEvent.Close(); + } + } + + #endregion Public Method + + #region Private Method + + /// + /// Out Queue. + /// + /// The init entity. + /// The entity what will be deal. + private bool Dequeue(out T entity) + { + return this._innerQueue.TryDequeue(out entity); + } + + /// + /// Deal entity in Queue. + /// + private void DealQueue() + { + try + { + while (true) + { + if (this.Dequeue(out T entity)) + { + if (this._endThreadFlag && Equals(entity, default(T))) + return; + + try + { + this.DealAction?.Invoke(entity); + } + catch (Exception ex) + { + LogHelper.Write(ex); + } + } + else + { + this._autoResetEvent.WaitOne(); + } + } + } + catch (Exception ex) + { + LogHelper.Write(ex); + } + } + + #endregion Private Method + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/RabbitMqHelper.cs b/WaterCloud.Code/Util/RabbitMqHelper.cs new file mode 100644 index 0000000..eaf0e31 --- /dev/null +++ b/WaterCloud.Code/Util/RabbitMqHelper.cs @@ -0,0 +1,2066 @@ +using RabbitMQ.Client; +using RabbitMQ.Client.Events; +using Serenity; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace WaterCloud.Code +{ + /// + /// RabbitMq工具类 + /// + public class RabbitMqHelper : IDisposable + { + #region 私有静态字段 + + /// + /// RabbitMQ建议客户端线程之间不要共用Model,至少要保证共用Model的线程发送消息必须是串行的,但是建议尽量共用Connection。 + /// + private static readonly ConcurrentDictionary _channelDic = new(); + + /// + /// QueueHelper缓存 + /// + private static readonly ConcurrentDictionary> _queueHelperDic = new(); + + /// + /// 用于缓存路由键数据 + /// + private static readonly ConcurrentDictionary _routeDic = new(); + + /// + /// RabbitMq连接 + /// + private static IConnection _connection; + + /// + /// 线程对象,线程锁使用 + /// + private static readonly object _locker = new(); + + #endregion 私有静态字段 + + #region 公有属性 + + /// + /// 默认内置死信交换机,默认值:deadletter.default.router + /// + public string DefaultDeadLetterExchange { get; set; } = "deadletter.default.router"; + + #endregion 公有属性 + + #region 构造函数 + + /// + /// 构造函数 + /// + /// RabbitMq配置 + public RabbitMqHelper(MqConfig config) + { + if (config == null) + throw new ArgumentNullException(nameof(config)); + + if (_connection == null) + { + lock (_locker) + { + if (_connection == null) + _connection = new ConnectionFactory + { + //设置主机名 + HostName = config.HostName, + + //虚拟主机 + VirtualHost = config.VirtualHost, + + //设置心跳时间 + RequestedHeartbeat = config.RequestedHeartbeat, + + //设置自动重连 + AutomaticRecoveryEnabled = config.AutomaticRecoveryEnabled, + + //重连时间 + NetworkRecoveryInterval = config.NetworkRecoveryInterval, + + //用户名 + UserName = config.UserName, + + //密码 + Password = config.Password, + + //配置端口 + Port=config.Port + }.CreateConnection(); + } + } + } + + /// + /// 构造函数 + /// + /// RabbitMq连接工厂 + public RabbitMqHelper(ConnectionFactory factory) + { + if (factory == null) + throw new ArgumentNullException(nameof(factory)); + + if (_connection == null) + { + lock (_locker) + { + if (_connection == null) + _connection = factory.CreateConnection(); + } + } + } + + #endregion 构造函数 + + #region 管道 + + /// + /// 获取管道 + /// + /// 队列名称 + /// + public IModel GetChannel(string queue = "default") + { + IModel channel = null; + + if (!string.IsNullOrEmpty(queue) && _channelDic.ContainsKey(queue)) + channel = _channelDic[queue]; + + if (!string.IsNullOrEmpty(queue) && channel == null) + { + lock (_locker) + { + channel = _channelDic.GetOrAdd(queue, queue => + { + var model = _connection.CreateModel(); + _channelDic[queue] = model; + + return model; + }); + } + } + + channel ??= _connection.CreateModel(); + + return EnsureOpened(channel); + } + + /// + /// 确保管道是已打开状态 + /// + /// 管道 + /// + public IModel EnsureOpened(IModel channel) + { + channel ??= GetChannel(); + + if (channel.IsClosed) + { + var data = _channelDic.Where(x => x.Value == channel)?.FirstOrDefault(); + if (data != null && data.Value.Key != null) + { + //移除已关闭的管道 + _channelDic.TryRemove(data.Value.Key, out var model); + + //重新获取管道 + channel = GetChannel(data.Value.Key); + } + else + { + channel = GetChannel(); + } + } + + return channel; + } + + /// + /// 如果交换机或者队列不存在则移除缓存中异常关闭的管道 + /// + /// + public void RemoveIfNotExist(IModel channel) + { + var data = _channelDic.Where(x => x.Value == channel)?.FirstOrDefault(); + if (data != null && data.Value.Key != null) + { + //移除已关闭的管道 + _channelDic.TryRemove(data.Value.Key, out var model); + channel = null; + } + } + + /// + /// 获取QueueHelper + /// + /// + /// + public QueueHelper GetQueueHelper(string queue) + { + if (!string.IsNullOrEmpty(queue)) + queue = "default"; + + if (_queueHelperDic.ContainsKey(queue)) + return _queueHelperDic[queue]; + + lock (_locker) + { + return _queueHelperDic.GetOrAdd(queue, queue => + { + var queueHelper = new QueueHelper(x => + PublishRabbitMqMessage( + x.Exchange, + x.Queue, + x.RoutingKey, + x.Body, + x.ExchangeType, + x.Durable, + x.Confirm, + x.Expiration, + x.Priority, + x.QueueArguments, + x.ExchangeArguments, + x.Headers)); + + _queueHelperDic[queue] = queueHelper; + + return queueHelper; + }); + } + } + + #endregion 管道 + + #region 交换机 + + /// + /// 声明交换机,交换机可以重复声明,但是声明所使用的参数必须一致,否则会抛出异常。 + /// + /// 管道 + /// 交换机名称 + /// 交换机类型: + /// 1、Direct Exchange – 处理路由键。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全 + /// 匹配。这是一个完整的匹配。如果一个队列绑定到该交换机上要求路由键 “dog”,则只有被标记为“dog”的 + /// 消息才被转发,不会转发dog.puppy,也不会转发dog.guard,只会转发dog + /// 2、Fanout Exchange – 不处理路由键。你只需要简单的将队列绑定到交换机上。一个发送到交换机的消息都 + /// 会被转发到与该交换机绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。Fanout + /// 交换机转发消息是最快的。 + /// 3、Topic Exchange – 将路由键和某模式进行匹配。此时队列需要绑定要一个模式上。符号“#”匹配一个或多 + /// 个词,符号“*”匹配不多不少一个词。因此“audit.#”能够匹配到“audit.irs.corporate”,但是“audit.*” + /// 只会匹配到“audit.irs”。 + /// 持久化 + /// 自动删除 + /// 参数 + /// 管道 + public IModel ExchangeDeclare( + IModel channel, + string exchange, + string exchangeType = ExchangeType.Direct, + bool durable = true, + bool autoDelete = false, + IDictionary arguments = null) + { + channel = EnsureOpened(channel); + channel.ExchangeDeclare(exchange, exchangeType, durable, autoDelete, arguments); + + return channel; + } + + /// + /// 声明交换机,交换机可以重复声明,但是声明所使用的参数必须一致,否则会抛出异常。 + /// + /// 管道 + /// 交换机名称 + /// 交换机类型: + /// 1、Direct Exchange – 处理路由键。需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全 + /// 匹配。这是一个完整的匹配。如果一个队列绑定到该交换机上要求路由键 “dog”,则只有被标记为“dog”的 + /// 消息才被转发,不会转发dog.puppy,也不会转发dog.guard,只会转发dog + /// 2、Fanout Exchange – 不处理路由键。你只需要简单的将队列绑定到交换机上。一个发送到交换机的消息都 + /// 会被转发到与该交换机绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。Fanout + /// 交换机转发消息是最快的。 + /// 3、Topic Exchange – 将路由键和某模式进行匹配。此时队列需要绑定要一个模式上。符号“#”匹配一个或多 + /// 个词,符号“*”匹配不多不少一个词。因此“audit.#”能够匹配到“audit.irs.corporate”,但是“audit.*” + /// 只会匹配到“audit.irs”。 + /// 持久化 + /// 自动删除 + /// 参数 + /// 管道 + public IModel ExchangeDeclareNoWait( + IModel channel, + string exchange, + string exchangeType = ExchangeType.Direct, + bool durable = true, + bool autoDelete = false, + IDictionary arguments = null) + { + channel = EnsureOpened(channel); + channel.ExchangeDeclareNoWait(exchange, exchangeType, durable, autoDelete, arguments); + + return channel; + } + + /// + /// 被动声明交换机,用于判断交换机是否存在,若存在则无异常,若不存在则抛出异常 + /// + /// 管道 + /// 交换机名称 + public void ExchangeDeclarePassive(IModel channel, string exchange) + { + EnsureOpened(channel).ExchangeDeclarePassive(exchange); + } + + /// + /// 判断交换机是否存在 + /// + /// 管道 + /// 交换机名称 + /// + public bool IsExchangeExist(IModel channel, string exchange) + { + try + { + ExchangeDeclarePassive(channel, exchange); + return true; + } + catch + { + RemoveIfNotExist(channel); + return false; + } + } + + /// + /// 删除交换机 + /// + /// 管道 + /// 交换机名称 + /// 是否没有被使用 + public void ExchangeDelete( + IModel channel, + string exchange, + bool ifUnused = false) + { + RouteKeyRemoveByExchange(exchange); + EnsureOpened(channel).ExchangeDelete(exchange, ifUnused); + } + + /// + /// 删除交换机 + /// + /// 管道 + /// 交换机名称 + /// 是否没有被使用 + public void ExchangeDeleteNoWait( + IModel channel, + string exchange, + bool ifUnused = false) + { + RouteKeyRemoveByExchange(exchange); + EnsureOpened(channel).ExchangeDeleteNoWait(exchange, ifUnused); + } + + /// + /// 绑定交换机 + /// + /// 管道 + /// 目标交换机 + /// 源交换机 + /// 路由键 + /// 参数 + public void ExchangeBind( + IModel channel, + string destinationExchange, + string sourceExchange, + string routingKey, + IDictionary arguments = null) + { + EnsureOpened(channel).ExchangeBind(destinationExchange, sourceExchange, routingKey, arguments); + } + + /// + /// 绑定交换机 + /// + /// 管道 + /// 目标交换机 + /// 源交换机 + /// 路由键 + /// 参数 + public void ExchangeBindNoWait( + IModel channel, + string destinationExchange, + string sourceExchange, + string routingKey, + IDictionary arguments = null) + { + EnsureOpened(channel).ExchangeBindNoWait(destinationExchange, sourceExchange, routingKey, arguments); + } + + /// + /// 解绑交换机 + /// + /// 管道 + /// 目标交换机 + /// 源交换机 + /// 路由键 + /// 参数 + public void ExchangeUnbind( + IModel channel, + string destinationExchange, + string sourceExchange, + string routingKey, + IDictionary arguments = null) + { + EnsureOpened(channel).ExchangeUnbind(destinationExchange, sourceExchange, routingKey, arguments); + } + + /// + /// 解绑交换机 + /// + /// 管道 + /// 目标交换机 + /// 源交换机 + /// 路由键 + /// 参数 + public void ExchangeUnbindNoWait( + IModel channel, + string destinationExchange, + string sourceExchange, + string routingKey, + IDictionary arguments = null) + { + EnsureOpened(channel).ExchangeUnbindNoWait(destinationExchange, sourceExchange, routingKey, arguments); + } + + #endregion 交换机 + + #region 队列 + + /// + /// 声明队列,队列可以重复声明,但是声明所使用的参数必须一致,否则会抛出异常。 + /// + /// 管道 + /// 队列名称 + /// 持久化 + /// 排他队列,如果一个队列被声明为排他队列,该队列仅对首次声明它的连接可见, + /// 并在连接断开时自动删除。这里需要注意三点:其一,排他队列是基于连接可见的,同一连接的不同信道是可 + /// 以同时访问同一个连接创建的排他队列的。其二,“首次”,如果一个连接已经声明了一个排他队列,其他连 + /// 接是不允许建立同名的排他队列的,这个与普通队列不同。其三,即使该队列是持久化的,一旦连接关闭或者 + /// 客户端退出,该排他队列都会被自动删除的。这种队列适用于只限于一个客户端发送读取消息的应用场景。 + /// 自动删除 + /// 参数 + /// 管道 + public IModel QueueDeclare( + IModel channel, + string queue, + bool durable = true, + bool exclusive = false, + bool autoDelete = false, + IDictionary arguments = null) + { + channel = EnsureOpened(channel); + channel.QueueDeclare(queue, durable, exclusive, autoDelete, arguments); + + return channel; + } + + /// + /// 声明队列,队列可以重复声明,但是声明所使用的参数必须一致,否则会抛出异常。 + /// + /// 管道 + /// 队列名称 + /// 持久化 + /// 排他队列,如果一个队列被声明为排他队列,该队列仅对首次声明它的连接可见, + /// 并在连接断开时自动删除。这里需要注意三点:其一,排他队列是基于连接可见的,同一连接的不同信道是可 + /// 以同时访问同一个连接创建的排他队列的。其二,“首次”,如果一个连接已经声明了一个排他队列,其他连 + /// 接是不允许建立同名的排他队列的,这个与普通队列不同。其三,即使该队列是持久化的,一旦连接关闭或者 + /// 客户端退出,该排他队列都会被自动删除的。这种队列适用于只限于一个客户端发送读取消息的应用场景。 + /// 自动删除 + /// 参数 + /// 管道 + public IModel QueueDeclareNoWait( + IModel channel, + string queue, + bool durable = true, + bool exclusive = false, + bool autoDelete = false, + IDictionary arguments = null) + { + channel = EnsureOpened(channel); + channel.QueueDeclareNoWait(queue, durable, exclusive, autoDelete, arguments); + + return channel; + } + + /// + /// 被动声明队列,用于判断队列是否存在,若队列存在则无异常,若不存在则抛异常 + /// + /// 管道 + /// 队列名称 + public void QueueDeclarePassive(IModel channel, string queue) + { + EnsureOpened(channel).QueueDeclarePassive(queue); + } + + /// + /// 判断队列是否存在 + /// + /// 管道 + /// 队列名称 + /// + public bool IsQueueExist(IModel channel, string queue) + { + try + { + QueueDeclarePassive(channel, queue); + return true; + } + catch + { + RemoveIfNotExist(channel); + return false; + } + } + + /// + /// 删除队列 + /// + /// 管道 + /// 队列名称 + /// 是否没有被使用 + /// 是否为空 + /// + public uint QueueDelete( + IModel channel, + string queue, + bool ifUnused = false, + bool ifEmpty = false) + { + RouteKeyRemoveByQueue(queue); + return EnsureOpened(channel).QueueDelete(queue, ifUnused, ifEmpty); + } + + /// + /// 删除队列 + /// + /// 管道 + /// 队列名称 + /// 是否没有被使用 + /// 是否为空 + public void QueueDeleteNoWait( + IModel channel, + string queue, + bool ifUnused = false, + bool ifEmpty = false) + { + RouteKeyRemoveByQueue(queue); + EnsureOpened(channel).QueueDeleteNoWait(queue, ifUnused, ifEmpty); + } + + /// + /// 绑定队列 + /// + /// 管道 + /// 交换机名称 + /// 队列名称 + /// 路由键 + /// 参数 + public void QueueBind( + IModel channel, + string exchange, + string queue, + string routingKey, + IDictionary arguments = null) + { + if (IsRouteKeyExist(exchange, queue, routingKey)) + return; + + EnsureOpened(channel).QueueBind(queue, exchange, routingKey, arguments); + } + + /// + /// 绑定队列 + /// + /// 管道 + /// 交换机名称 + /// 队列名称 + /// 路由键 + /// 参数 + public void QueueBindNoWait( + IModel channel, + string exchange, + string queue, + string routingKey, + IDictionary arguments = null) + { + if (IsRouteKeyExist(exchange, queue, routingKey)) + return; + + EnsureOpened(channel).QueueBindNoWait(queue, exchange, routingKey, arguments); + } + + /// + /// 解绑队列 + /// + /// 管道 + /// 交换机名称 + /// 队列名称 + /// 路由键 + /// 参数 + public void QueueUnbind( + IModel channel, + string exchange, + string queue, + string routingKey, + IDictionary arguments = null) + { + RouteKeyRemove(exchange, queue, routingKey); + EnsureOpened(channel).QueueUnbind(queue, exchange, routingKey, arguments); + } + + /// + /// 清除队列 + /// + /// 管道 + /// 队列名称 + public void QueuePurge(IModel channel, string queue) + { + EnsureOpened(channel).QueuePurge(queue); + } + + #endregion 队列 + + #region 路由 + + /// + /// 判断路由键是否存在,仅在内存中作判断 + /// + /// 交换机 + /// 队列 + /// 路由键 + /// + public bool IsRouteKeyExist(string exchange, string queue, string routeKey) + { + var key = $"{exchange}.{queue}.{routeKey}"; + + if (_routeDic.ContainsKey(key)) + return true; + else + { + lock (_locker) + { + if (!_routeDic.ContainsKey(key)) + { + _routeDic.TryAdd(key, (exchange, queue, routeKey)); + return false; + } + return true; + } + } + } + + /// + /// 移除路由键缓存 + /// + /// + /// + /// + public void RouteKeyRemove(string exchange, string queue, string routeKey) + { + var key = $"{exchange}.{queue}.{routeKey}"; + if (_routeDic.ContainsKey(key)) + { + lock (_locker) + { + if (_routeDic.ContainsKey(key)) + _routeDic.TryRemove(key, out var _); + } + } + } + + /// + /// 移除路由键缓存 + /// + /// 队列 + public void RouteKeyRemoveByQueue(string queue) + { + if (!_routeDic.IsEmpty && _routeDic.Values.Any(x => x.queue == queue)) + { + lock (_locker) + { + if (!_routeDic.IsEmpty && _routeDic.Values.Any(x => x.queue == queue)) + { + var keys = _routeDic.Keys.Where(x => x.Split('.')[1] == queue); + foreach (var key in keys) + { + _routeDic.TryRemove(key, out var _); + } + } + } + } + } + + /// + /// 移除路由键缓存 + /// + /// 交换机 + public void RouteKeyRemoveByExchange(string exchange) + { + if (!_routeDic.IsEmpty && _routeDic.Values.Any(x => x.exchange == exchange)) + { + lock (_locker) + { + if (!_routeDic.IsEmpty && _routeDic.Values.Any(x => x.exchange == exchange)) + { + var keys = _routeDic.Keys.Where(x => x.Split('.')[0] == exchange); + foreach (var key in keys) + { + _routeDic.TryRemove(key, out var _); + } + } + } + } + } + + #endregion 路由 + + #region 发布消息 + + /// + /// 发布消息 + /// + /// 消息指令 + /// 消息发送确认 + /// 单个消息过期时间,单位ms + /// 单个消息优先级,数值越大优先级越高,取值范围:0-9 + /// + public bool Publish( + T command, + bool confirm = false, + string expiration = null, + byte? priority = null) + where T : class + { + var attribute = typeof(T).GetAttribute(); + if (attribute == null) + throw new ArgumentException("RabbitMqAttribute Is Null!"); + + return Publish(attribute, command, confirm, expiration, priority); + } + + /// + /// 发布消息 + /// + /// RabbitMq特性配置 + /// 消息指令 + /// 消息发送确认 + /// 单个消息过期时间,单位ms + /// 单个消息优先级,数值越大优先级越高,取值范围:0-9 + /// + public bool Publish( + RabbitMqAttribute attribute, + T command, + bool confirm = false, + string expiration = null, + byte? priority = null) + where T : class + { + //消息内容 + var body = command.ToJson(); + + //自定义队列参数 + var arguments = new Dictionary(); + + //设置队列消息过期时间,指整个队列的所有消息 + if (attribute.MessageTTL > 0) + arguments["x-message-ttl"] = attribute.MessageTTL; + + //设置队列过期时间 + if (attribute.AutoExpire > 0) + arguments["x-expires"] = attribute.AutoExpire; + + //设置队列最大长度 + if (attribute.MaxLength > 0) + arguments["x-max-length"] = attribute.MaxLength; + + //设置队列占用最大空间 + if (attribute.MaxLengthBytes > 0) + arguments["x-max-length-bytes"] = attribute.MaxLengthBytes; + + //设置队列溢出行为 + if (attribute.OverflowBehaviour == "drop-head" || attribute.OverflowBehaviour == "reject-publish") + arguments["x-overflow"] = attribute.OverflowBehaviour; + + //设置死信交换机 + if (!attribute.DeadLetterExchange.IsNullOrEmpty()) + arguments["x-dead-letter-exchange"] = attribute.DeadLetterExchange; + + //设置死信路由键 + if (!attribute.DeadLetterRoutingKey.IsNullOrEmpty()) + arguments["x-dead-letter-routing-key"] = attribute.DeadLetterRoutingKey; + + //设置队列优先级 + if (attribute.MaximumPriority > 0 && attribute.MaximumPriority <= 10) + arguments["x-max-priority"] = attribute.MaximumPriority; + + //设置队列惰性模式 + if (attribute.LazyMode == "default" || attribute.LazyMode == "lazy") + arguments["x-queue-mode"] = attribute.LazyMode; + + //设置集群配置 + if (!attribute.MasterLocator.IsNullOrEmpty()) + arguments["x-queue-master-locator"] = attribute.MasterLocator; + + //发送消息 + return Publish( + attribute.Exchange, + attribute.Queue, + attribute.RoutingKey, + body, + attribute.ExchangeType, + attribute.Durable, + confirm, + expiration, + priority, + arguments, + null, + attribute.Header?.ToObject>()); + } + + /// + /// 发布消息 + /// + /// 消息指令 + /// 消息发送确认 + /// 单个消息过期时间,单位ms + /// 单个消息优先级,数值越大优先级越高,取值范围:0-9 + /// + public bool Publish( + IEnumerable command, + bool confirm = false, + string expiration = null, + byte? priority = null) + where T : class + { + var attribute = typeof(T).GetAttribute(); + if (attribute == null) + throw new ArgumentException("RabbitMqAttribute Is Null!"); + + return Publish(attribute, command, confirm, expiration, priority); + } + + /// + /// 发布消息 + /// + /// RabbitMq特性配置 + /// 消息指令 + /// 消息发送确认 + /// 单个消息过期时间,单位ms + /// 单个消息优先级,数值越大优先级越高,取值范围:0-9 + /// + public bool Publish( + RabbitMqAttribute attribute, + IEnumerable command, + bool confirm = false, + string expiration = null, + byte? priority = null) + where T : class + { + //消息内容 + var body = command.Select(x => x.ToJson()); + + //自定义队列参数 + var arguments = new Dictionary(); + + //设置队列消息过期时间,指整个队列的所有消息 + if (attribute.MessageTTL > 0) + arguments["x-message-ttl"] = attribute.MessageTTL; + + //设置队列过期时间 + if (attribute.AutoExpire > 0) + arguments["x-expires"] = attribute.AutoExpire; + + //设置队列最大长度 + if (attribute.MaxLength > 0) + arguments["x-max-length"] = attribute.MaxLength; + + //设置队列占用最大空间 + if (attribute.MaxLengthBytes > 0) + arguments["x-max-length-bytes"] = attribute.MaxLengthBytes; + + //设置队列溢出行为 + if (attribute.OverflowBehaviour == "drop-head" || attribute.OverflowBehaviour == "reject-publish") + arguments["x-overflow"] = attribute.OverflowBehaviour; + + //设置死信交换机 + if (!attribute.DeadLetterExchange.IsNullOrEmpty()) + arguments["x-dead-letter-exchange"] = attribute.DeadLetterExchange; + + //设置死信路由键 + if (!attribute.DeadLetterRoutingKey.IsNullOrEmpty()) + arguments["x-dead-letter-routing-key"] = attribute.DeadLetterRoutingKey; + + //设置队列优先级 + if (attribute.MaximumPriority > 0 && attribute.MaximumPriority <= 10) + arguments["x-max-priority"] = attribute.MaximumPriority; + + //设置队列惰性模式 + if (attribute.LazyMode == "default" || attribute.LazyMode == "lazy") + arguments["x-queue-mode"] = attribute.LazyMode; + + //设置集群配置 + if (!attribute.MasterLocator.IsNullOrEmpty()) + arguments["x-queue-master-locator"] = attribute.MasterLocator; + + //发送消息 + return Publish( + attribute.Exchange, + attribute.Queue, + attribute.RoutingKey, + body, + attribute.ExchangeType, + attribute.Durable, + confirm, + expiration, + priority, + arguments, + null, + attribute.Header?.ToObject>()); + } + + /// + /// 发布消息 + /// + /// 交换机名称 + /// 队列名称 + /// 路由键 + /// 消息内容 + /// 交换机类型 + /// 持久化 + /// 消息发送确认 + /// 单个消息过期时间,单位ms + /// 单个消息优先级,数值越大优先级越高,取值范围:0-9 + /// 队列参数 + /// 交换机参数 + /// 消息头部 + /// + public bool Publish( + string exchange, + string queue, + string routingKey, + string body, + string exchangeType = ExchangeType.Direct, + bool durable = true, + bool confirm = false, + string expiration = null, + byte? priority = null, + IDictionary queueArguments = null, + IDictionary exchangeArguments = null, + IDictionary headers = null) + { + return Publish( + exchange, + queue, + routingKey, + new[] { body }, + exchangeType, + durable, + confirm, + expiration, + priority, + queueArguments, + exchangeArguments, + headers); + } + + /// + /// 发布消息 + /// + /// 交换机名称 + /// 队列名称 + /// 路由键 + /// 消息内容 + /// 交换机类型 + /// 持久化 + /// 消息发送确认 + /// 单个消息过期时间,单位ms + /// 单个消息优先级,数值越大优先级越高,取值范围:0-9 + /// 队列参数 + /// 交换机参数 + /// 消息头部 + /// + public bool Publish( + string exchange, + string queue, + string routingKey, + IEnumerable body, + string exchangeType = ExchangeType.Direct, + bool durable = true, + bool confirm = false, + string expiration = null, + byte? priority = null, + IDictionary queueArguments = null, + IDictionary exchangeArguments = null, + IDictionary headers = null) + { + return GetQueueHelper(queue).Enqueue( + new QueueMessage + { + Exchange = exchange, + Queue = queue, + RoutingKey = routingKey, + Body = body, + ExchangeType = exchangeType, + Durable = durable, + Confirm = confirm, + Expiration = expiration, + Priority = priority, + QueueArguments = queueArguments, + ExchangeArguments = exchangeArguments, + Headers = headers + }); + } + + /// + /// 发布消息到RabbitMq,注意此方法使用IModel线程不安全,建议使用Publish方法,若要使用需要保证单线程调用 + /// + /// 交换机名称 + /// 队列名称 + /// 路由键 + /// 消息内容 + /// 交换机类型 + /// 持久化 + /// 消息发送确认 + /// 单个消息过期时间,单位ms + /// 单个消息优先级,数值越大优先级越高,取值范围:0-9 + /// 队列参数 + /// 交换机参数 + /// 消息头部 + /// + public bool PublishRabbitMqMessage( + string exchange, + string queue, + string routingKey, + IEnumerable body, + string exchangeType = ExchangeType.Direct, + bool durable = true, + bool confirm = false, + string expiration = null, + byte? priority = null, + IDictionary queueArguments = null, + IDictionary exchangeArguments = null, + IDictionary headers = null) + { + //获取管道 + var channel = GetChannel(queue); + + //判断交换机是否存在 + if (!IsExchangeExist(channel, exchange)) + channel = ExchangeDeclare(channel, exchange, exchangeType, durable, arguments: exchangeArguments); + + //判断队列是否存在 + if (!IsQueueExist(channel, queue)) + channel = QueueDeclare(channel, queue, durable, arguments: queueArguments); + + //绑定交换机和队列 + QueueBind(channel, exchange, queue, routingKey); + + //声明消息属性 + var props = channel.CreateBasicProperties(); + + //持久化 + props.Persistent = durable; + + //单个消息过期时间 + if (!expiration.IsNullOrEmpty()) + props.Expiration = expiration; + + //单个消息优先级 + if (priority >= 0 && priority <= 9) + props.Priority = priority.Value; + + //消息头部 + if (headers != null) + props.Headers = headers; + + //是否启用消息发送确认机制 + if (confirm) + channel.ConfirmSelect(); + + //发送消息 + foreach (var item in body) + { + var text = string.IsNullOrEmpty(item) ? null : Encoding.UTF8.GetBytes(item); + channel.BasicPublish(exchange, routingKey, props, text); + } + + //消息发送失败处理 + if (confirm && !channel.WaitForConfirms()) + return false; + + return true; + } + + /// + /// 发布消息到内置死信队列 + /// + /// 队列名称 + /// 交换机名称 + /// 路由键 + /// 消息内容 + /// 重试次数 + /// 异常 + /// + private bool PublishToDead( + string queue, + string exchange, + string routingKey, + string body, + int retryCount, + Exception exception) + { + //内置死信队列、交换机、路由键 + var deadLetterQueue = $"{queue.ToLower()}.{(exception != null ? "error" : "fail")}"; + var deadLetterExchange = DefaultDeadLetterExchange; + var deadLetterRoutingKey = $"{queue.ToLower()}.deadletter"; + + //内置死信队列内容 + var deadLetterBody = new DeadLetterQueue + { + Body = body, + CreateDateTime = DateTime.Now, + Exception = exception, + ExceptionMsg = exception?.Message, + Queue = queue, + RoutingKey = routingKey, + Exchange = exchange, + RetryCount = retryCount + }; + + //发送内置死信消息,注意此处与原生的死信消息无关 + return Publish(deadLetterExchange, deadLetterQueue, deadLetterRoutingKey, deadLetterBody.ToJson()); + } + + #endregion 发布消息 + + #region 订阅消息 + + /// + /// 订阅消息 + /// + /// + /// 消费处理委托 + /// 异常处理委托 + /// 注册事件 + /// 取消注册事件 + /// 关闭事件 + public void Subscribe( + Func subscriber, + Action handler, + EventHandler registered = null, + EventHandler unregistered = null, + EventHandler shutdown = null) + where T : class + { + var attribute = typeof(T).GetAttribute(); + if (attribute == null) + throw new ArgumentException("RabbitMqAttribute Is Null!"); + + Subscribe(attribute, subscriber, handler, registered, unregistered, shutdown); + } + + /// + /// 订阅消息 + /// + /// + /// RabbitMq特性配置 + /// 消费处理委托 + /// 异常处理委托 + /// 注册事件 + /// 取消注册事件 + /// 关闭事件 + public void Subscribe( + RabbitMqAttribute attribute, + Func subscriber, + Action handler, + EventHandler registered = null, + EventHandler unregistered = null, + EventHandler shutdown = null) + where T : class + { + //自定义参数 + var arguments = new Dictionary(); + + //设置队列消息过期时间,指整个队列的所有消息 + if (attribute.MessageTTL > 0) + arguments["x-message-ttl"] = attribute.MessageTTL; + + //设置队列过期时间 + if (attribute.AutoExpire > 0) + arguments["x-expires"] = attribute.AutoExpire; + + //设置队列最大长度 + if (attribute.MaxLength > 0) + arguments["x-max-length"] = attribute.MaxLength; + + //设置队列占用最大空间 + if (attribute.MaxLengthBytes > 0) + arguments["x-max-length-bytes"] = attribute.MaxLengthBytes; + + //设置队列溢出行为 + if (attribute.OverflowBehaviour == "drop-head" || attribute.OverflowBehaviour == "reject-publish") + arguments["x-overflow"] = attribute.OverflowBehaviour; + + //设置死信交换机 + if (!attribute.DeadLetterExchange.IsNullOrEmpty()) + arguments["x-dead-letter-exchange"] = attribute.DeadLetterExchange; + + //设置死信路由键 + if (!attribute.DeadLetterRoutingKey.IsNullOrEmpty()) + arguments["x-dead-letter-routing-key"] = attribute.DeadLetterRoutingKey; + + //设置队列优先级 + if (attribute.MaximumPriority > 0 && attribute.MaximumPriority <= 10) + arguments["x-max-priority"] = attribute.MaximumPriority; + + //设置队列惰性模式 + if (attribute.LazyMode == "default" || attribute.LazyMode == "lazy") + arguments["x-queue-mode"] = attribute.LazyMode; + + //设置集群配置 + if (!attribute.MasterLocator.IsNullOrEmpty()) + arguments["x-queue-master-locator"] = attribute.MasterLocator; + + //订阅消息 + Subscribe( + attribute.Exchange, + attribute.Queue, + attribute.RoutingKey, + subscriber, + handler, + attribute.RetryCount, + attribute.PrefetchCount, + attribute.DeadLetter, + attribute.ExchangeType, + attribute.Durable, + attribute.ConsumerCount, + arguments, + registered: registered, + unregistered: unregistered, + shutdown: shutdown); + } + + /// + /// 订阅消息 + /// + /// + /// 消费处理委托 + /// 异常处理委托 + /// 注册事件 + /// 取消注册事件 + /// 关闭事件 + public void Subscribe( + Func> subscriber, + Func handler, + EventHandler registered = null, + EventHandler unregistered = null, + EventHandler shutdown = null) + where T : class + { + var attribute = typeof(T).GetAttribute(); + if (attribute == null) + throw new ArgumentException("RabbitMqAttribute Is Null!"); + + Subscribe(attribute, subscriber, handler, registered, unregistered, shutdown); + } + + /// + /// 订阅消息 + /// + /// + /// RabbitMq特性配置 + /// 消费处理委托 + /// 异常处理委托 + /// 注册事件 + /// 取消注册事件 + /// 关闭事件 + public void Subscribe( + RabbitMqAttribute attribute, + Func> subscriber, + Func handler, + EventHandler registered = null, + EventHandler unregistered = null, + EventHandler shutdown = null) + where T : class + { + //自定义参数 + var arguments = new Dictionary(); + + //设置队列消息过期时间,指整个队列的所有消息 + if (attribute.MessageTTL > 0) + arguments["x-message-ttl"] = attribute.MessageTTL; + + //设置队列过期时间 + if (attribute.AutoExpire > 0) + arguments["x-expires"] = attribute.AutoExpire; + + //设置队列最大长度 + if (attribute.MaxLength > 0) + arguments["x-max-length"] = attribute.MaxLength; + + //设置队列占用最大空间 + if (attribute.MaxLengthBytes > 0) + arguments["x-max-length-bytes"] = attribute.MaxLengthBytes; + + //设置队列溢出行为 + if (attribute.OverflowBehaviour == "drop-head" || attribute.OverflowBehaviour == "reject-publish") + arguments["x-overflow"] = attribute.OverflowBehaviour; + + //设置死信交换机 + if (!attribute.DeadLetterExchange.IsNullOrEmpty()) + arguments["x-dead-letter-exchange"] = attribute.DeadLetterExchange; + + //设置死信路由键 + if (!attribute.DeadLetterRoutingKey.IsNullOrEmpty()) + arguments["x-dead-letter-routing-key"] = attribute.DeadLetterRoutingKey; + + //设置队列优先级 + if (attribute.MaximumPriority > 0 && attribute.MaximumPriority <= 10) + arguments["x-max-priority"] = attribute.MaximumPriority; + + //设置队列惰性模式 + if (attribute.LazyMode == "default" || attribute.LazyMode == "lazy") + arguments["x-queue-mode"] = attribute.LazyMode; + + //设置集群配置 + if (!attribute.MasterLocator.IsNullOrEmpty()) + arguments["x-queue-master-locator"] = attribute.MasterLocator; + + //订阅消息 + Subscribe( + attribute.Exchange, + attribute.Queue, + attribute.RoutingKey, + subscriber, + handler, + attribute.RetryCount, + attribute.PrefetchCount, + attribute.DeadLetter, + attribute.ExchangeType, + attribute.Durable, + attribute.ConsumerCount, + arguments, + registered: registered, + unregistered: unregistered, + shutdown: shutdown); + } + + /// + /// 订阅消息 + /// + /// + /// 交换机名称 + /// 队列名称 + /// 路由键 + /// 消费处理委托 + /// 异常处理委托 + /// 重试次数 + /// 预取数量 + /// 是否进入内置死信队列,此处与原生死信无关 + /// 交换机类型 + /// 持久化 + /// 消费者数量 + /// 队列参数 + /// 交换机参数 + /// 注册事件 + /// 取消注册事件 + /// 关闭事件 + public void Subscribe( + string exchange, + string queue, + string routingKey, + Func subscriber, + Action handler, + int retryCount = 5, + ushort prefetchCount = 1, + bool deadLetter = true, + string exchangeType = ExchangeType.Direct, + bool durable = true, + int consumerCount = 1, + IDictionary queueArguments = null, + IDictionary exchangeArguments = null, + EventHandler registered = null, + EventHandler unregistered = null, + EventHandler shutdown = null) + where T : class + { + //获取管道 + var channel = GetChannel(queue); + + //判断交换机是否存在 + if (!IsExchangeExist(channel, exchange)) + channel = ExchangeDeclare(channel, exchange, exchangeType, durable, arguments: exchangeArguments); + + //判断队列是否存在 + if (!IsQueueExist(channel, queue)) + channel = QueueDeclare(channel, queue, durable, arguments: queueArguments); + + //绑定交换机和队列 + QueueBind(channel, exchange, queue, routingKey); + + //设置每次预取数量 + channel.BasicQos(0, prefetchCount, false); + + //根据设置的消费者数量创建消费者 + for (int i = 0; i < consumerCount; i++) + { + //创建消费者 + var consumer = new EventingBasicConsumer(channel); + + //接收消息事件 + consumer.Received += (sender, ea) => + { + var text = Encoding.UTF8.GetString(ea.Body.ToArray()); + var body = text; + var numberOfRetries = 0; + Exception exception = null; + bool? result = false; + + while (numberOfRetries <= retryCount) + { + try + { + var msg = body.ToObject(); + + result = subscriber?.Invoke(msg, ea); + + if (result == true) + channel.BasicAck(ea.DeliveryTag, false); + else + channel.BasicNack(ea.DeliveryTag, false, false); + + //异常置空 + exception = null; + break; + } + catch (Exception ex) + { + exception = ex; + handler?.Invoke(body, numberOfRetries, ex); + numberOfRetries++; + } + } + + //重试后异常仍未解决 + if (exception != null) + channel.BasicNack(ea.DeliveryTag, false, false); + + //是否进入内置死信队列 + if (deadLetter && (!(result == true) || exception != null)) + PublishToDead( + queue, + ea.Exchange, + ea.RoutingKey, + body, + exception == null ? numberOfRetries : numberOfRetries - 1, + exception); + }; + + //注册事件 + if (registered != null) + consumer.Registered += registered; + + //取消注册事件 + if (unregistered != null) + consumer.Unregistered += unregistered; + + //关闭事件 + if (shutdown != null) + consumer.Shutdown += shutdown; + + //手动确认 + channel.BasicConsume(queue, false, consumer); + } + } + + /// + /// 订阅消息 + /// + /// + /// 交换机名称 + /// 队列名称 + /// 路由键 + /// 消费处理委托 + /// 异常处理委托 + /// 重试次数 + /// 预取数量 + /// 是否进入内置死信队列,此处与原生死信无关 + /// 交换机类型 + /// 持久化 + /// 消费者数量 + /// 队列参数 + /// 交换机参数 + /// 注册事件 + /// 取消注册事件 + /// 关闭事件 + public void Subscribe( + string exchange, + string queue, + string routingKey, + Func> subscriber, + Func handler, + int retryCount = 5, + ushort prefetchCount = 1, + bool deadLetter = true, + string exchangeType = ExchangeType.Direct, + bool durable = true, + int consumerCount = 1, + IDictionary queueArguments = null, + IDictionary exchangeArguments = null, + EventHandler registered = null, + EventHandler unregistered = null, + EventHandler shutdown = null) + where T : class + { + //获取管道 + var channel = GetChannel(queue); + + //判断交换机是否存在 + if (!IsExchangeExist(channel, exchange)) + channel = ExchangeDeclare(channel, exchange, exchangeType, durable, arguments: exchangeArguments); + + //判断队列是否存在 + if (!IsQueueExist(channel, queue)) + channel = QueueDeclare(channel, queue, durable, arguments: queueArguments); + + //绑定交换机和队列 + QueueBind(channel, exchange, queue, routingKey); + + //设置每次预取数量 + channel.BasicQos(0, prefetchCount, false); + + //根据设置的消费者数量创建消费者 + for (int i = 0; i < consumerCount; i++) + { + //创建消费者 + var consumer = new EventingBasicConsumer(channel); + + //接收消息事件 + consumer.Received += async (sender, ea) => + { + var text = Encoding.UTF8.GetString(ea.Body.ToArray()); + var body = text; + var numberOfRetries = 0; + Exception exception = null; + bool? result = false; + + while (numberOfRetries <= retryCount) + { + try + { + var msg = body.ToObject(); + + if (subscriber != null) + result = await subscriber(msg, ea); + + if (result == true) + channel.BasicAck(ea.DeliveryTag, false); + else + channel.BasicNack(ea.DeliveryTag, false, false); + + //异常置空 + exception = null; + break; + } + catch (Exception ex) + { + exception = ex; + + if (handler != null) + await handler(body, numberOfRetries, ex); + + numberOfRetries++; + } + } + + //重试后异常仍未解决 + if (exception != null) + channel.BasicNack(ea.DeliveryTag, false, false); + + //是否进入内置死信队列 + if (deadLetter && (!(result == true) || exception != null)) + PublishToDead( + queue, + ea.Exchange, + ea.RoutingKey, + body, + exception == null ? numberOfRetries : numberOfRetries - 1, + exception); + }; + + //注册事件 + if (registered != null) + consumer.Registered += registered; + + //取消注册事件 + if (unregistered != null) + consumer.Unregistered += unregistered; + + //关闭事件 + if (shutdown != null) + consumer.Shutdown += shutdown; + + //手动确认 + channel.BasicConsume(queue, false, consumer); + } + } + + #endregion 订阅消息 + + #region 获取消息 + + /// + /// 获取消息 + /// + /// + /// 消费处理委托 + public void Pull( + Action handler) + where T : class + { + var attribute = typeof(T).GetAttribute(); + if (attribute == null) + throw new ArgumentException("RabbitMqAttribute Is Null!"); + + Pull(attribute.Exchange, attribute.Queue, attribute.RoutingKey, handler); + } + + /// + /// 获取消息 + /// + /// + /// 交换机名称 + /// 队列名称 + /// 路由键 + /// 消费处理委托 + public void Pull( + string exchange, + string queue, + string routingKey, + Action handler) + where T : class + { + //获取管道 + var channel = GetChannel(queue); + + //判断交换机是否存在 + if (!IsExchangeExist(channel, exchange)) + channel = ExchangeDeclare(channel, exchange); + + //判断队列是否存在 + if (!IsQueueExist(channel, queue)) + channel = QueueDeclare(channel, queue); + + //绑定交换机和队列 + QueueBind(channel, exchange, queue, routingKey); + + var result = channel.BasicGet(queue, false); + if (result == null) + return; + var text = Encoding.UTF8.GetString(result.Body.ToArray()); + var msg = text.ToObject(); + try + { + handler(msg, result); + } + catch (Exception) + { + throw; + } + finally + { + channel.BasicAck(result.DeliveryTag, false); + } + } + + /// + /// 获取消息 + /// + /// + /// 消费处理委托 + public async Task PullAsync( + Func handler) + where T : class + { + var attribute = typeof(T).GetAttribute(); + if (attribute == null) + throw new ArgumentException("RabbitMqAttribute Is Null!"); + + await PullAsync(attribute.Exchange, attribute.Queue, attribute.RoutingKey, handler); + } + + /// + /// 获取消息 + /// + /// + /// 交换机名称 + /// 队列名称 + /// 路由键 + /// 消费处理委托 + public async Task PullAsync( + string exchange, + string queue, + string routingKey, + Func handler) + where T : class + { + //获取管道 + var channel = GetChannel(queue); + + //判断交换机是否存在 + if (!IsExchangeExist(channel, exchange)) + channel = ExchangeDeclare(channel, exchange); + + //判断队列是否存在 + if (!IsQueueExist(channel, queue)) + channel = QueueDeclare(channel, queue); + + //绑定交换机和队列 + QueueBind(channel, exchange, queue, routingKey); + + var result = channel.BasicGet(queue, false); + if (result == null) + return; + var text = Encoding.UTF8.GetString(result.Body.ToArray()); + var msg = text.ToObject(); + try + { + if (handler != null) + await handler(msg, result); + } + catch (Exception) + { + throw; + } + finally + { + channel.BasicAck(result.DeliveryTag, false); + } + } + + /// + /// 获取消息数量 + /// + /// 管道 + /// 队列名称 + /// + public uint GetMessageCount( + IModel channel, + string queue) + { + return (channel ?? GetChannel(queue)).MessageCount(queue); + } + + #endregion 获取消息 + + #region 释放资源 + + /// + /// 执行与释放或重置非托管资源关联的应用程序定义的任务。 + /// + public void Dispose() + { + foreach (var item in _channelDic) + { + item.Value?.Dispose(); + } + + foreach (var item in _queueHelperDic) + { + item.Value?.Dispose(); + } + + _connection?.Dispose(); + _channelDic.Clear(); + _queueHelperDic.Clear(); + } + + #endregion 释放资源 + } + + /// + /// RabbitMq连接配置 + /// + public class MqConfig + { + /// + /// 是否启用 + /// + public bool Enabled { get; set; } + + /// + /// 主机名 + /// + public string HostName { get; set; } = "localhost"; + + /// + /// 心跳时间 + /// + public TimeSpan RequestedHeartbeat { get; set; } = TimeSpan.FromSeconds(10); + + /// + /// 自动重连 + /// + public bool AutomaticRecoveryEnabled { get; set; } = true; + + /// + /// 重连时间 + /// + public TimeSpan NetworkRecoveryInterval { get; set; } = TimeSpan.FromSeconds(10); + + /// + /// 用户名 + /// + public string UserName { get; set; } = "guest"; + + /// + /// 密码 + /// + public string Password { get; set; } = "guest"; + + /// + /// 端口号 + /// + public int Port { get; set; } = 5672; + + /// + /// 虚拟主机 + /// + public string VirtualHost { get; set; } = "/"; + } + + /// + /// 自定义的RabbitMq队列信息实体特性 + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] + public class RabbitMqAttribute : Attribute + { + /// + /// 交换机 + /// + public string Exchange { get; set; } + + /// + /// 交换机类型(广播fanout,队列direct) + /// + public string ExchangeType { get; set; } + + /// + /// 队列 + /// + public string Queue { get; set; } + + /// + /// 路由键 + /// + public string RoutingKey { get; set; } + + /// + /// 是否持久化,默认true + /// + public bool Durable { get; set; } = true; + + /// + /// 预取数量,默认1 + /// + public ushort PrefetchCount { get; set; } = 1; + + /// + /// 异常重试次数,默认5次 + /// + public int RetryCount { get; set; } = 5; + + /// + /// 消息过期时间,过期后队列中消息自动被删除,单位ms + /// + public int MessageTTL { get; set; } + + /// + /// 消息头部对象json字符串 + /// + public string Header { get; set; } + + /// + /// 队列消费者数量,默认1 + /// + public int ConsumerCount { get; set; } = 1; + + /// + /// 队列过期时间,过期后队列自动被删除,单位ms + /// + public int AutoExpire { get; set; } + + /// + /// 队列最大长度 + /// + public int MaxLength { get; set; } + + /// + /// 队列占用的最大空间 + /// + public int MaxLengthBytes { get; set; } + + /// + /// 队列溢出行为,可选值:drop-head或者reject-publish,默认drop-head + /// + public string OverflowBehaviour { get; set; } + + /// + /// 是否启用系统内置死信队列处理逻辑,默认true;注意:此处与原生的死信无关 + /// + public bool DeadLetter { get; set; } = true; + + /// + /// 死信交换机 + /// + public string DeadLetterExchange { get; set; } + + /// + /// 死信路由键 + /// + public string DeadLetterRoutingKey { get; set; } + + /// + /// 队列最大优先级,数值越大优先级越高,范围1-255,建议取值1-10 + /// + public int MaximumPriority { get; set; } + + /// + /// 队列惰性模式,可选值:default或者lazy + /// + public string LazyMode { get; set; } + + /// + /// 主定位器,集群配置 + /// + public string MasterLocator { get; set; } + } + + /// + /// 内置死信队列实体 + /// + public class DeadLetterQueue + { + /// + /// 消息内容 + /// + public string Body { get; set; } + + /// + /// 交换机 + /// + public string Exchange { get; set; } + + /// + /// 队列 + /// + public string Queue { get; set; } + + /// + /// 路由键 + /// + public string RoutingKey { get; set; } + + /// + /// 重试次数 + /// + public int RetryCount { get; set; } + + /// + /// 异常消息 + /// + public string ExceptionMsg { get; set; } + + /// + /// 异常 + /// + public Exception Exception { get; set; } + + /// + /// 创建时间 + /// + public DateTime CreateDateTime { get; set; } = DateTime.Now; + } + + /// + /// 内存队列消息 + /// + public class QueueMessage + { + /// + /// 交换机名称 + /// + public string Exchange { get; set; } + + /// + /// 队列名称 + /// + public string Queue { get; set; } + + /// + /// 路由键 + /// + public string RoutingKey { get; set; } + + /// + /// 消息内容 + /// + public IEnumerable Body { get; set; } + + /// + /// 交换机类型 + /// + public string ExchangeType { get; set; } + + /// + /// 持久化 + /// + public bool Durable { get; set; } + + /// + /// 消息发送确认 + /// + public bool Confirm { get; set; } + + /// + /// 单个消息过期时间,单位ms + /// + public string Expiration { get; set; } + + /// + /// 单个消息优先级,数值越大优先级越高,取值范围:0-9 + /// + public byte? Priority { get; set; } + + /// + /// 队列参数 + /// + public IDictionary QueueArguments { get; set; } + + /// + /// 交换机参数 + /// + public IDictionary ExchangeArguments { get; set; } + + /// + /// 消息头部 + /// + public IDictionary Headers { get; set; } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/ReflectionHelper.cs b/WaterCloud.Code/Util/ReflectionHelper.cs new file mode 100644 index 0000000..485806e --- /dev/null +++ b/WaterCloud.Code/Util/ReflectionHelper.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; + +namespace WaterCloud.Code +{ + public class ReflectionHelper + { + private static ConcurrentDictionary dictCache = new ConcurrentDictionary(); + private static List exceptionList = new List { "BaseService", "BaseController" }; + + #region 得到类里面的属性集合 + + /// + /// 得到类里面的属性集合 + /// + /// + /// + /// + public static PropertyInfo[] GetProperties(Type type, string[] columns = null) + { + PropertyInfo[] properties = null; + if (dictCache.ContainsKey(type.FullName)) + { + properties = dictCache[type.FullName] as PropertyInfo[]; + } + else + { + properties = type.GetProperties(); + dictCache.TryAdd(type.FullName, properties); + } + + if (columns != null && columns.Length > 0) + { + // 按columns顺序返回属性 + var columnPropertyList = new List(); + foreach (var column in columns) + { + var columnProperty = properties.Where(p => p.Name == column).FirstOrDefault(); + if (columnProperty != null) + { + columnPropertyList.Add(columnProperty); + } + } + return columnPropertyList.ToArray(); + } + else + { + return properties; + } + } + + public static object GetObjectPropertyValue(T t, string propertyname) + { + Type type = typeof(T); + PropertyInfo property = type.GetProperty(propertyname); + if (property == null) return string.Empty; + object o = property.GetValue(t, null); + if (o == null) return string.Empty; + return o; + } + + #endregion 得到类里面的属性集合 + + /// + /// StackTrace获取名称 + /// + /// 搜索层级 + /// 前缀 + /// + public static string GetModuleName(int count = 10, bool isReplace = true, string prefix = "Service") + { + try + { + string moduleName = ""; + + for (int i = 0; i < count; i++) + { + if (!string.IsNullOrEmpty(moduleName)) + { + break; + } + string className = new StackFrame(i, true).GetMethod().DeclaringType.FullName; + className = className.Split('+')[0]; + className = className.Split('.').LastOrDefault(); + bool skip = false; + foreach (var item in exceptionList) + { + if (className.Contains(item)) + { + skip = true; + break; + } + } + if (skip) + { + continue; + } + if (className.IndexOf(prefix) > -1) + { + moduleName = className; + if (isReplace) + { + moduleName = moduleName.Replace(prefix, ""); + } + } + } + return moduleName; + } + catch (Exception ex) + { + LogHelper.WriteWithTime(ex); + return ""; + } + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/ShellHelper.cs b/WaterCloud.Code/Util/ShellHelper.cs new file mode 100644 index 0000000..800254f --- /dev/null +++ b/WaterCloud.Code/Util/ShellHelper.cs @@ -0,0 +1,44 @@ +using System.Diagnostics; + +namespace WaterCloud.Code +{ + public class ShellHelper + { + public static string Bash(string command) + { + var escapedArgs = command.Replace("\"", "\\\""); + var process = new Process() + { + StartInfo = new ProcessStartInfo + { + FileName = "/bin/bash", + Arguments = $"-c \"{escapedArgs}\"", + RedirectStandardOutput = true, + UseShellExecute = false, + CreateNoWindow = true, + } + }; + process.Start(); + string result = process.StandardOutput.ReadToEnd(); + process.WaitForExit(); + process.Dispose(); + return result; + } + + public static string Cmd(string fileName, string args) + { + string output = string.Empty; + + var info = new ProcessStartInfo(); + info.FileName = fileName; + info.Arguments = args; + info.RedirectStandardOutput = true; + + using (var process = Process.Start(info)) + { + output = process.StandardOutput.ReadToEnd(); + } + return output; + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/TextHelper.cs b/WaterCloud.Code/Util/TextHelper.cs new file mode 100644 index 0000000..415d16f --- /dev/null +++ b/WaterCloud.Code/Util/TextHelper.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace WaterCloud.Code +{ + public class TextHelper + { + /// + /// 获取默认值 + /// + /// + /// + /// + public static string GetCustomValue(string value, string defaultValue) + { + if (string.IsNullOrEmpty(value)) + { + return defaultValue; + } + else + { + return value; + } + } + + /// + /// 截取指定长度的字符串 + /// + /// + /// + /// + public static string GetSubString(string value, int length, bool ellipsis = false) + { + if (string.IsNullOrEmpty(value)) + { + return value; + } + if (value.Length > length) + { + value = value.Substring(0, length); + if (ellipsis) + { + value += "..."; + } + } + return value; + } + + /// + /// 字符串转指定类型数组 + /// + /// + /// + /// + public static T[] SplitToArray(string value, char split) + { + T[] arr = value.Split(new string[] { split.ToString() }, StringSplitOptions.RemoveEmptyEntries).CastSuper().ToArray(); + return arr; + } + + /// + /// 判断是否有交集 + /// + /// + /// + /// + /// + public static bool IsArrayIntersection(List list1, List list2) + { + List t = list1.Distinct().ToList(); + + var exceptArr = t.Except(list2).ToList(); + + if (exceptArr.Count < t.Count) + { + return true; + } + else + { + return false; + } + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/Utils.cs b/WaterCloud.Code/Util/Utils.cs new file mode 100644 index 0000000..5ad6f71 --- /dev/null +++ b/WaterCloud.Code/Util/Utils.cs @@ -0,0 +1,37 @@ +using System; + +namespace WaterCloud.Code +{ + public class Utils + { + #region 自动生成编号 + + /// + /// 表示全局唯一标识符 (GUID)。 + /// + /// + public static string GuId() + { + return IDGen.NextID().ToString(); + } + + /// + /// 自动生成编号 201008251145409865 + /// + /// + public static string CreateNo() + { + Random random = new Random(); + string strRandom = random.Next(1000, 10000).ToString(); //生成编号 + string code = DateTime.Now.ToString("yyyyMMddHHmmss") + strRandom;//形如 + return code; + } + + #endregion 自动生成编号 + + public static string GetGuid() + { + return IDGen.NextID().ToString().Replace("-", string.Empty).ToLower(); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/ValidatorHelper.cs b/WaterCloud.Code/Util/ValidatorHelper.cs new file mode 100644 index 0000000..f53cf3c --- /dev/null +++ b/WaterCloud.Code/Util/ValidatorHelper.cs @@ -0,0 +1,379 @@ +using System; +using System.Linq; +using System.Text.RegularExpressions; + +namespace WaterCloud.Code +{ + public static class ValidatorHelper + { + #region 验证输入字符串为数字(带小数) + + /// + /// 验证输入字符串为带小数点正数 + /// + /// 输入字符 + /// 返回一个bool类型的值 + public static bool IsNumber(this string str) + { + return Regex.IsMatch(str, "^([0]|([1-9]+\\d{0,}?))(.[\\d]+)?$"); + } + + /// + /// 验证输入字符串为带小数点正负数 + /// + /// 输入字符 + /// 返回一个bool类型的值 + public static bool IsNumberic(this string str) + { + return Regex.IsMatch(str, "^-?\\d+$|^(-?\\d+)(\\.\\d+)?$"); + } + + #endregion 验证输入字符串为数字(带小数) + + #region 验证中国电话格式是否有效,格式010-85849685 + + /// + /// 验证中国电话格式是否有效,格式010-85849685 + /// + /// 输入字符 + /// 返回一个bool类型的值 + public static bool IsTel(this string str) + { + return Regex.IsMatch(str, @"^(0[0-9]{2,3}\-)?([2-9][0-9]{6,7})+(\-[0-9]{1,4})?$", RegexOptions.IgnoreCase); + } + + #endregion 验证中国电话格式是否有效,格式010-85849685 + + #region 验证输入字符串为电话号码 + + /// + /// 验证输入字符串为电话号码 + /// + /// 输入字符 + /// 返回一个bool类型的值 + public static bool IsPhone(this string str) + { + return Regex.IsMatch(str, @"(^(\d{2,4}[-_-—]?)?\d{3,8}([-_-—]?\d{3,8})?([-_-—]?\d{1,7})?$)|(^0?1[35]\d{9}$)"); + //弱一点的验证: @"\d{3,4}-\d{7,8}" + } + + #endregion 验证输入字符串为电话号码 + + #region 验证是否是有效传真号码 + + /// + /// 验证是否是有效传真号码 + /// + /// 输入字符 + /// 返回一个bool类型的值 + public static bool IsFax(this string str) + { + return Regex.IsMatch(str, @"^[+]{0,1}(\d){1,3}[ ]?([-]?((\d)|[ ]){1,12})+$"); + } + + #endregion 验证是否是有效传真号码 + + #region 验证手机号是否合法 + + /// + /// 验证手机号是否合法 号段为13,14,15,16,17,18,19 0,86开头将自动识别 + /// + /// 输入字符 + /// 返回一个bool类型的值 + public static bool IsMobile(this string str) + { + if (!str.StartsWith("1")) + { + str = str.TrimStart(new char[] { '8', '6', }).TrimStart('0'); + } + return Regex.IsMatch(str, @"^(13|14|15|16|17|18|19)\d{9}$"); + } + + #endregion 验证手机号是否合法 + + #region 验证身份证是否有效 + + /// + /// 验证身份证是否有效 + /// + /// 输入字符 + /// 返回一个bool类型的值 + public static bool IsIDCard(this string str) + { + switch (str.Length) + { + case 18: + { + return str.IsIDCard18(); + } + case 15: + { + return str.IsIDCard15(); + } + default: + return false; + } + } + + /// + /// 验证输入字符串为18位的身份证号码 + /// + /// 输入字符 + /// 返回一个bool类型的值 + public static bool IsIDCard18(this string str) + { + long n = 0; + if (long.TryParse(str.Remove(17), out n) == false || n < Math.Pow(10, 16) || long.TryParse(str.Replace('x', '0').Replace('X', '0'), out n) == false) + { + return false;//数字验证 + } + const string address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91"; + if (address.IndexOf(str.Remove(2), StringComparison.Ordinal) == -1) + { + return false;//省份验证 + } + string birth = str.Substring(6, 8).Insert(6, "-").Insert(4, "-"); + DateTime time; + if (DateTime.TryParse(birth, out time) == false) + { + return false;//生日验证 + } + string[] arrVarifyCode = ("1,0,x,9,8,7,6,5,4,3,2").Split(','); + string[] wi = ("7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2").Split(','); + char[] ai = str.Remove(17).ToCharArray(); + int sum = 0; + for (int i = 0; i < 17; i++) + { + sum += int.Parse(wi[i]) * int.Parse(ai[i].ToString()); + } + int y = -1; + Math.DivRem(sum, 11, out y); + return arrVarifyCode[y] == str.Substring(17, 1).ToLower(); + } + + /// + /// 验证输入字符串为15位的身份证号码 + /// + /// 输入字符 + /// 返回一个bool类型的值 + public static bool IsIDCard15(this string str) + { + long n = 0; + if (long.TryParse(str, out n) == false || n < Math.Pow(10, 14)) + { + return false;//数字验证 + } + const string address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91"; + if (address.IndexOf(str.Remove(2), StringComparison.Ordinal) == -1) + { + return false;//省份验证 + } + string birth = str.Substring(6, 6).Insert(4, "-").Insert(2, "-"); + DateTime time; + return DateTime.TryParse(birth, out time) != false; + } + + #endregion 验证身份证是否有效 + + #region 验证是否是有效邮箱地址 + + /// + /// 验证是否是有效邮箱地址 + /// + /// 输入字符 + /// 返回一个bool类型的值 + public static bool IsEmail(this string str) + { + return Regex.IsMatch(str, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"); + } + + #endregion 验证是否是有效邮箱地址 + + #region 验证是否只含有汉字 + + /// + /// 验证是否只含有汉字 + /// + /// 输入字符 + /// + public static bool IsOnlyChinese(this string strln) + { + return Regex.IsMatch(strln, @"^[\u4e00-\u9fa5]+$"); + } + + #endregion 验证是否只含有汉字 + + #region 是否有多余的字符 防止SQL注入 + + /// + /// 是否有多余的字符 防止SQL注入 + /// + /// 输入字符 + /// + public static bool IsBadString(this string str) + { + if (string.IsNullOrEmpty(str)) + return false; + //列举一些特殊字符串 + const string badChars = "@,*,#,$,!,+,',=,--,%,^,&,?,(,), <,>,[,],{,},/,\\,;,:,\",\"\",delete,update,drop,alert,select"; + var arraryBadChar = badChars.Split(','); + return arraryBadChar.Any(t => !str.Contains(t)); + } + + #endregion 是否有多余的字符 防止SQL注入 + + #region 是否由数字、26个英文字母或者下划线組成的字串 + + /// + /// 是否由数字、26个英文字母或者下划线組成的字串 + /// + /// 输入字符 + /// + public static bool IsNzx(this string str) + { + return Regex.Match(str, "^[0-9a-zA-Z_]+$").Success; + } + + #endregion 是否由数字、26个英文字母或者下划线組成的字串 + + #region 由数字、26个英文字母、汉字組成的字串 + + /// + /// 由数字、26个英文字母、汉字組成的字串 + /// + /// 输入字符 + /// + public static bool IsSzzmChinese(this string str) + { + return Regex.Match(str, @"^[0-9a-zA-Z\u4e00-\u9fa5]+$").Success; + } + + #endregion 由数字、26个英文字母、汉字組成的字串 + + #region 由数字、26个英文字母組成的字串 + + /// + /// 是否由数字、26个英文字母組成的字串 + /// + /// 输入字符 + /// + public static bool IsSzzm(this string str) + { + return Regex.Match(str, @"^[0-9a-zA-Z]+$").Success; + } + + #endregion 由数字、26个英文字母組成的字串 + + #region 验证输入字符串为邮政编码 + + /// + /// 验证输入字符串为邮政编码 + /// + /// 输入字符 + /// 返回一个bool类型的值 + public static bool IsPostCode(this string str) + { + return Regex.IsMatch(str, @"\d{6}"); + } + + #endregion 验证输入字符串为邮政编码 + + #region 检查对象的输入长度 + + /// + /// 检查对象的输入长度 + /// + /// 输入字符 + /// 指定的长度 + /// false 太长,true -太短 + public static bool CheckLength(this string str, int length) + { + if (str.Length > length) + { + return false;//长度太长 + } + return str.Length >= length; + } + + #endregion 检查对象的输入长度 + + #region 判断用户输入是否为日期 + + /// + /// 判断用户输入是否为日期 + /// + /// 输入字符 + /// 返回一个bool类型的值 + /// + /// 可判断格式如下(其中-可替换为/,不影响验证) + /// YYYY | YYYY-MM | YYYY-MM-DD | YYYY-MM-DD HH:MM:SS | YYYY-MM-DD HH:MM:SS.FFF + /// + public static bool IsDateTime(this string str) + { + if (null == str) + { + return false; + } + const string regexDate = @"[1-2]{1}[0-9]{3}((-|\/|\.){1}(([0]?[1-9]{1})|(1[0-2]{1}))((-|\/|\.){1}((([0]?[1-9]{1})|([1-2]{1}[0-9]{1})|(3[0-1]{1})))( (([0-1]{1}[0-9]{1})|2[0-3]{1}):([0-5]{1}[0-9]{1}):([0-5]{1}[0-9]{1})(\.[0-9]{3})?)?)?)?$"; + if (Regex.IsMatch(str, regexDate)) + { + //以下各月份日期验证,保证验证的完整性 + int indexY = -1; + int indexM = -1; + int indexD = -1; + if (-1 != (indexY = str.IndexOf("-", StringComparison.Ordinal))) + { + indexM = str.IndexOf("-", indexY + 1, StringComparison.Ordinal); + indexD = str.IndexOf(":", StringComparison.Ordinal); + } + else + { + indexY = str.IndexOf("/", StringComparison.Ordinal); + indexM = str.IndexOf("/", indexY + 1, StringComparison.Ordinal); + indexD = str.IndexOf(":", StringComparison.Ordinal); + } + //不包含日期部分,直接返回true + if (-1 == indexM) + return true; + if (-1 == indexD) + { + indexD = str.Length + 3; + } + int iYear = Convert.ToInt32(str.Substring(0, indexY)); + int iMonth = Convert.ToInt32(str.Substring(indexY + 1, indexM - indexY - 1)); + int iDate = Convert.ToInt32(str.Substring(indexM + 1, indexD - indexM - 4)); + //判断月份日期 + if ((iMonth < 8 && 1 == iMonth % 2) || (iMonth > 8 && 0 == iMonth % 2)) + { + if (iDate < 32) + return true; + } + else + { + if (iMonth != 2) + { + if (iDate < 31) + return true; + } + else + { + //闰年 + if ((0 == iYear % 400) || (0 == iYear % 4 && 0 < iYear % 100)) + { + if (iDate < 30) + return true; + } + else + { + if (iDate < 29) + return true; + } + } + } + } + return false; + } + + #endregion 判断用户输入是否为日期 + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/VerifyCodeHelper.cs b/WaterCloud.Code/Util/VerifyCodeHelper.cs new file mode 100644 index 0000000..4256a6a --- /dev/null +++ b/WaterCloud.Code/Util/VerifyCodeHelper.cs @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright © 2016 WaterCloud.Framework 版权所有 + * Author: WaterCloud + * Description: WaterCloud快速开发平台 + * Website: +*********************************************************************************/ + +using System; +using System.DrawingCore; +using System.DrawingCore.Imaging; +using System.IO; + +namespace WaterCloud.Code +{ + public class VerifyCodeHelper + { + public byte[] GetVerifyCode() + { + int codeW = 80; + int codeH = 30; + int fontSize = 16; + string chkCode = string.Empty; + //颜色列表,用于验证码、噪线、噪点 + Color[] color = { Color.Black, Color.Red, Color.Blue, Color.Green, Color.Orange, Color.Brown, Color.Brown, Color.DarkBlue }; + //字体列表,用于验证码 + string[] font = { "Times New Roman" }; + //验证码的字符集,去掉了一些容易混淆的字符 + char[] character = { '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'd', 'e', 'f', 'h', 'k', 'm', 'n', 'r', 'x', 'y', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W', 'X', 'Y' }; + Random rnd = new Random(); + //生成验证码字符串 + for (int i = 0; i < 4; i++) + { + chkCode += character[rnd.Next(character.Length)]; + } + //写入Session、验证码加密 + WebHelper.WriteSession("wcloud_session_verifycode", Md5.md5(chkCode.ToLower(), 16)); + //创建画布 + Bitmap bmp = new Bitmap(codeW, codeH); + Graphics g = Graphics.FromImage(bmp); + g.Clear(Color.White); + //画噪线 + for (int i = 0; i < 3; i++) + { + int x1 = rnd.Next(codeW); + int y1 = rnd.Next(codeH); + int x2 = rnd.Next(codeW); + int y2 = rnd.Next(codeH); + Color clr = color[rnd.Next(color.Length)]; + g.DrawLine(new Pen(clr), x1, y1, x2, y2); + } + //画验证码字符串 + for (int i = 0; i < chkCode.Length; i++) + { + string fnt = font[rnd.Next(font.Length)]; + Font ft = new Font(fnt, fontSize); + Color clr = color[rnd.Next(color.Length)]; + g.DrawString(chkCode[i].ToString(), ft, new SolidBrush(clr), (float)i * 18, (float)0); + } + //将验证码图片写入内存流,并将其以 "image/Png" 格式输出 + MemoryStream ms = new MemoryStream(); + try + { + bmp.Save(ms, ImageFormat.Png); + return ms.ToArray(); + } + catch (Exception) + { + return null; + } + finally + { + g.Dispose(); + bmp.Dispose(); + } + } + } + + public class GetJsVesion + { + public static string GetVcode() + { + TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); + return Convert.ToInt64(ts.TotalSeconds).ToString(); + } + } +} \ No newline at end of file diff --git a/WaterCloud.Code/Util/WebHelper.cs b/WaterCloud.Code/Util/WebHelper.cs new file mode 100644 index 0000000..4b7eff6 --- /dev/null +++ b/WaterCloud.Code/Util/WebHelper.cs @@ -0,0 +1,685 @@ +/******************************************************************************* + * Copyright © 2016 WaterCloud.Framework 版权所有 + * Author: WaterCloud + * Description: WaterCloud快速开发平台 + * Website: +*********************************************************************************/ + +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Net.Sockets; +using System.Text; +using System.Text.Encodings.Web; +using System.Text.RegularExpressions; +using System.Web; + +namespace WaterCloud.Code +{ + public class WebHelper + { + #region ResolveUrl(解析相对Url) + + /// + /// 解析相对Url + /// + /// 相对Url + public static string ResolveUrl(string relativeUrl) + { + if (string.IsNullOrWhiteSpace(relativeUrl)) + return string.Empty; + relativeUrl = relativeUrl.Replace("\\", "/"); + if (relativeUrl.StartsWith("/")) + return relativeUrl; + if (relativeUrl.Contains("://")) + return relativeUrl; + return VirtualPathUtility.ToAbsolute(relativeUrl); + } + + #endregion ResolveUrl(解析相对Url) + + #region HtmlEncode(对html字符串进行编码) + + /// + /// 对html字符串进行编码 + /// + /// html字符串 + public static string HtmlEncode(string html) + { + return HttpUtility.HtmlEncode(html); + } + + /// + /// 对html字符串进行解码 + /// + /// html字符串 + public static string HtmlDecode(string html) + { + return HttpUtility.HtmlDecode(html); + } + + #endregion HtmlEncode(对html字符串进行编码) + + #region UrlEncode(对Url进行编码) + + /// + /// 对Url进行编码 + /// + /// url + /// 编码字符是否转成大写,范例,"http://"转成"http%3A%2F%2F" + public static string UrlEncode(string url, bool isUpper = false) + { + return UrlEncode(url, Encoding.UTF8, isUpper); + } + + /// + /// 对Url进行编码 + /// + /// url + /// 字符编码 + /// 编码字符是否转成大写,范例,"http://"转成"http%3A%2F%2F" + public static string UrlEncode(string url, Encoding encoding, bool isUpper = false) + { + var result = HttpUtility.UrlEncode(url, encoding); + if (!isUpper) + return result; + return GetUpperEncode(result); + } + + /// + /// 获取大写编码字符串 + /// + private static string GetUpperEncode(string encode) + { + var result = new StringBuilder(); + int index = int.MinValue; + for (int i = 0; i < encode.Length; i++) + { + string character = encode[i].ToString(); + if (character == "%") + index = i; + if (i - index == 1 || i - index == 2) + character = character.ToUpper(); + result.Append(character); + } + return result.ToString(); + } + + #endregion UrlEncode(对Url进行编码) + + #region UrlDecode(对Url进行解码) + + /// + /// 对Url进行解码,对于javascript的encodeURIComponent函数编码参数,应使用utf-8字符编码来解码 + /// + /// url + public static string UrlDecode(string url) + { + return HttpUtility.UrlDecode(url); + } + + /// + /// 对Url进行解码,对于javascript的encodeURIComponent函数编码参数,应使用utf-8字符编码来解码 + /// + /// url + /// 字符编码,对于javascript的encodeURIComponent函数编码参数,应使用utf-8字符编码来解码 + public static string UrlDecode(string url, Encoding encoding) + { + return HttpUtility.UrlDecode(url, encoding); + } + + #endregion UrlDecode(对Url进行解码) + + #region Session操作 + + /// + /// 写Session + /// + /// Session的键名 + /// Session的键值 + public static void WriteSession(string key, string value) + { + if (key.IsEmpty()) + return; + GlobalContext.HttpContext?.Session.SetString(key, value); + } + + /// + /// 读取Session的值 + /// + /// Session的键名 + public static string GetSession(string key) + { + if (string.IsNullOrEmpty(key)) + { + return string.Empty; + } + return GlobalContext.HttpContext?.Session.GetString(key) ?? ""; + } + + /// + /// 删除指定Session + /// + /// Session的键名 + public static void RemoveSession(string key) + { + if (string.IsNullOrEmpty(key)) + { + return; + } + GlobalContext.HttpContext?.Session.Remove(key); + } + + #endregion Session操作 + + #region Cookie操作 + + /// + /// 写cookie值 + /// + /// 名称 + /// 值 + public static void WriteCookie(string strName, string strValue, CookieOptions option = null) + { + if (option == null) + { + option = new CookieOptions(); + option.Expires = DateTime.Now.AddDays(30); + } + GlobalContext.HttpContext?.Response.Cookies.Append(strName, strValue, option); + } + + /// + /// 写cookie值 + /// + /// 名称 + /// 值 + /// 过期时间(分钟) + public static void WriteCookie(string strName, string strValue, int expires) + { + CookieOptions option = new CookieOptions(); + option.Expires = DateTime.Now.AddMinutes(expires); + GlobalContext.HttpContext?.Response.Cookies.Append(strName, strValue, option); + } + + /// + /// 读cookie值 + /// + /// 名称 + /// cookie值 + public static string GetCookie(string strName) + { + return GlobalContext.HttpContext?.Request.Cookies[strName] ?? ""; + } + + /// + /// 删除Cookie对象 + /// + /// Cookie对象名称 + public static void RemoveCookie(string CookiesName) + { + GlobalContext.HttpContext?.Response.Cookies.Delete(CookiesName); + } + + #endregion Cookie操作 + + #region 去除HTML标记 + + /// + /// 去除HTML标记 + /// + /// 包括HTML的源码 + /// 已经去除后的文字 + public static string NoHtml(string Htmlstring) + { + //删除脚本 + Htmlstring = Regex.Replace(Htmlstring, @"]*?>.*?", "", RegexOptions.IgnoreCase); + //删除HTML + Htmlstring = Regex.Replace(Htmlstring, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase); + Htmlstring = Regex.Replace(Htmlstring, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase); + Htmlstring = Regex.Replace(Htmlstring, @"-->", "", RegexOptions.IgnoreCase); + Htmlstring = Regex.Replace(Htmlstring, @" +
    +
+ + + + + + + + + +
+
+ + +
+
+
+ + +
+ + +
+ +
+ +
+
    +
  • +
+
+
  • +
  • +
  • + +
  • +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + + + diff --git a/WaterCloud.Web/Views/Home/Message.cshtml b/WaterCloud.Web/Views/Home/Message.cshtml new file mode 100644 index 0000000..8afa0ad --- /dev/null +++ b/WaterCloud.Web/Views/Home/Message.cshtml @@ -0,0 +1,404 @@ + + + + 通知中心 + + + + + + + + + + + + + + + + +
    +
    +
      +
    • +
    • +
    • +
    +
    + +
    +
    +
    + +
    + +
    没有通知
    +
    + 全部标记已读 +
    + +
    +
    +
    + +
    + +
    没有私信
    +
    + 全部标记已读 +
    + +
    +
    +
    + +
    + +
    没有待办
    +
    + 全部标记已读 +
    +
    +
    +
    + + + \ No newline at end of file diff --git a/WaterCloud.Web/Views/Home/UserSetting.cshtml b/WaterCloud.Web/Views/Home/UserSetting.cshtml new file mode 100644 index 0000000..3af645e --- /dev/null +++ b/WaterCloud.Web/Views/Home/UserSetting.cshtml @@ -0,0 +1,123 @@ +@{ + ViewBag.Title = "Index"; + Layout = "~/Views/Shared/_Index.cshtml"; +} + + + + + 基本资料 + + + + + + +
    +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    +
    + + + \ No newline at end of file diff --git a/WaterCloud.Web/Views/Login/Index.cshtml b/WaterCloud.Web/Views/Login/Index.cshtml new file mode 100644 index 0000000..ded5392 --- /dev/null +++ b/WaterCloud.Web/Views/Login/Index.cshtml @@ -0,0 +1,249 @@ + + + + + @ViewBag.ProjectName + + + + + + + + + + + + + + + + + + + + + @*动画特效*@ +@*
    *@ +
    + +
    + + + + \ No newline at end of file diff --git a/WaterCloud.Web/Views/Shared/_Form.cshtml b/WaterCloud.Web/Views/Shared/_Form.cshtml new file mode 100644 index 0000000..77aeee9 --- /dev/null +++ b/WaterCloud.Web/Views/Shared/_Form.cshtml @@ -0,0 +1,30 @@ + + + + + + @ViewBag.Title + + + + + + + + + + + + + + + + + + + + + @RenderBody() + @Html.AntiForgeryToken() + + diff --git a/WaterCloud.Web/Views/Shared/_Index.cshtml b/WaterCloud.Web/Views/Shared/_Index.cshtml new file mode 100644 index 0000000..bb3245c --- /dev/null +++ b/WaterCloud.Web/Views/Shared/_Index.cshtml @@ -0,0 +1,25 @@ + + + + + @ViewBag.Title + + + + + + + + + + + + + + + + + @RenderBody() + @Html.AntiForgeryToken() + + diff --git a/WaterCloud.Web/WaterCloud.Web.csproj b/WaterCloud.Web/WaterCloud.Web.csproj new file mode 100644 index 0000000..ccde475 --- /dev/null +++ b/WaterCloud.Web/WaterCloud.Web.csproj @@ -0,0 +1,88 @@ + + + + net8.0 + c1fb91bb-fd9e-4a3a-8c93-b84e89a0941a + Linux + 3.0.0-preview + True + WaterCloud.Web.xml + + + + false + AnyCPU + en + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + + + + + + + + + + diff --git a/WaterCloud.Web/WaterCloud.Web.xml b/WaterCloud.Web/WaterCloud.Web.xml new file mode 100644 index 0000000..3c8552d --- /dev/null +++ b/WaterCloud.Web/WaterCloud.Web.xml @@ -0,0 +1,390 @@ + + + + WaterCloud.Web + + + + + 创 建:超级管理员 + 日 期:2020-06-09 19:42 + 描 述:新闻类别控制器类 + + + + + 创 建:超级管理员 + 日 期:2020-06-09 19:42 + 描 述:新闻管理控制器类 + + + + + 创 建:超级管理员 + 日 期:2020-07-22 12:04 + 描 述:文件管理控制器类 + + + + + 创 建:超级管理员 + 日 期:2020-07-14 09:18 + 描 述:我的流程控制器类 + + + + + 待处理的流程 + + + + + 已完成的流程 + + + + + 处理界面 + + + + + + 获取一个流程实例的操作历史记录 + + + + + 创 建:超级管理员 + 日 期:2020-07-29 16:41 + 描 述:通知管理控制器类 + + + + + 创 建:超级管理员 + 日 期:2021-07-12 20:41 + 描 述:订单管理控制器类 + + + + + 创 建:超级管理员 + 日 期:2022-10-06 14:18 + 描 述:条码生成记录控制器类 + + + + + 创 建:超级管理员 + 日 期:2022-10-06 11:25 + 描 述:条码规则控制器类 + + + + + 创 建:超级管理员 + 日 期:2020-07-10 08:49 + 描 述:流程设计控制器类 + + + + + 创 建:超级管理员 + 日 期:2020-07-08 14:33 + 描 述:表单设计控制器类 + + + + + 创 建:超级管理员 + 日 期:2020-05-21 14:38 + 描 述:字段管理控制器类 + + + + + 创 建:超级管理员 + 日 期:2022-10-06 14:11 + 描 述:打印模板控制器类 + + + + + 创 建:超级管理员 + 日 期:2020-06-01 09:44 + 描 述:数据权限控制器类 + + + + + 创 建:超级管理员 + 日 期:2020-06-12 13:50 + 描 述:系统设置控制器类 + + + + + 获得指定路径下所有文件名 + + 列表 + 文件夹路径 + + + + 定时任务 + + + + + 获取本地可执行的任务列表 + + + + + 改变任务状态,启动/停止 + + + + + 立即执行任务 + + + + + 清除任务计划 + + + + + 测试文件 + + + + + 用户接口 + + + + + 用户登录 + + 请求对象 + + + + + 用户退出登录 + + + + + + 登录请求对象 + + + + + 用户名 + + + + + 密码 + + + + + 域名 + + + + + 演示模式过滤 + + + + + + + + 缓存操作类 + + + + + 初始数据加载请求方法 + + + + + + 清空缓存请求方法 + + + + + + 模块字段权限 + + + + + + 快捷菜单列表 + + + + + + 获取公告信息 + + + + + + 初始菜单列表请求方法 + + + + + + 获取公告信息请求方法 + + + + + + 获取当前用户信息请求方法 + + + + + + 获取快捷菜单请求方法 + + + + + + 获取数据信息接口 + + + + + + 菜单按钮信息 + + + + + + 菜单信息 + + + + + + + + 字段信息 + + + + + + 菜单按钮信息 + + + + + + 菜单字段信息 + + + + + + 验证码获取(此接口已弃用) + + + + + + 验证登录状态请求接口 + + + + + + 登录验证 + + 用户 + 密码 + 域名 + + + + + 权限验证 + + + + + 权限特性 + + 权限参数 + 是否鉴权 + + + + 验证 + + + + + + + + 验证token + + + + + 登录特性 + + 是否验证 + + + + 验证 + + + + + + + + 权限验证 + + + + + 权限特性 + + 权限参数 + 是否鉴权 + + + + 登录验证 + + + + + 登录特性 + + 是否验证 + + + diff --git a/WaterCloud.Web/appsettings.Development.json b/WaterCloud.Web/appsettings.Development.json new file mode 100644 index 0000000..d418f17 --- /dev/null +++ b/WaterCloud.Web/appsettings.Development.json @@ -0,0 +1,67 @@ +{ + "urls": "http://*:5000", + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "SystemConfig": { + "Demo": false, // 是否是演示模式 账号admin 密码0000 + "LoginMultiple": false, // 是否允许一个账户在多处登录 + "AllowCorsSite": "http://localhost:5000", // 允许的其他站点访问Api + "DBProvider": "MySql", //SqlServer //Oracle + "DBConnectionString": "server=192.168.31.37;user id=root;password=zhuyunyu;database=water", + "DBCommandTimeout": 180, // 数据库超时时间,单位秒 + "IsInitDb": true, //是否初始化数据库 + "IsSeedData": true, //是否初始化数据库数据 + "CacheProvider": "Redis", // 缓存使用方式 Redis/Memory + "RedisConnectionString": "192.168.31.37:6379,password=zhuyunyu", //docker部署 172.17.0.1 + "TokenName": "WC-Token", //api Token名称 + "LoginExpire": 1, //登录缓存过期时间(小时) + "HomePage": "../Home/Default", //登录主页地址 + "MainDbNumber": "0", //主程序数据库 + "LocalLAN": false, //是否局域网 + "OpenQuartz": true, //定时任务开启 + "SqlMode": "MoreSql", //数据库模式多租户或者多库 "MoreSql" + "ProjectPrefix": "watercloud", //项目中的前缀 + "ReviseSystem": false, //是否重置密码 + "LoginErrorCount": 4, //登录错误次数 + "IsCluster": false, //集群参数 开启时需要去quartz下载响应数据库 + "NeedClear": false, //是否删除定时调度任务 + "SqlConfig": [ + //{ + // "DBNumber": "1", + // "DBProvider": "SqlServer", //MySql //Oracle + // "DBConnectionString": "Data Source = .;Initial Catalog = WaterCloudNetDb;User ID=sa;Password=12345678;MultipleActiveResultSets=true;" //Data Source = 192.168.1.252;Initial Catalog = WaterCloudNetDb;User ID=sa;Password=admin@12345;MultipleActiveResultSets=true; + //} + ], + "RabbitMq": { + "Enabled": false, + "HostName": "localhost", + "UserName": "root", //默认guest + "Password": "root", //默认guest + "Port": 5672, + "VirtualHost": "/" + }, + "DocumentSettings": { + "DocumentTitle": "WaterCloud API", + "GroupOpenApiInfos": [ + { + "Group": "Default", + "Title": "WaterCloud API", + "Description": "WaterCloud .NET敏捷开发框架
    项目地址:https://gitee.com/qian_wei_hong/WaterCloud", + "Version": "1.0.0" + }, + { + "Group": "V2", + "Title": "V2", + "Description": "WaterCloud .NET敏捷开发框架
    项目地址:https://gitee.com/qian_wei_hong/WaterCloud", + "Version": "1.0.0" + } + ] + } + }, + "AllowedHosts": "*" +} \ No newline at end of file diff --git a/WaterCloud.Web/appsettings.Production.json b/WaterCloud.Web/appsettings.Production.json new file mode 100644 index 0000000..b770cdb --- /dev/null +++ b/WaterCloud.Web/appsettings.Production.json @@ -0,0 +1,67 @@ +{ + "urls": "http://*:5000", + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "SystemConfig": { + "Demo": false, // 是否是演示模式 账号admin 密码0000 + "LoginMultiple": false, // 是否允许一个账户在多处登录 + "AllowCorsSite": "http://localhost:5000", // 允许的其他站点访问Api + "DBProvider": "Sqlite", //SqlServer //Oracle + "DBConnectionString": "DataSource=./watercloudnetdb.db", + "DBCommandTimeout": 180, // 数据库超时时间,单位秒 + "IsInitDb": true, //是否初始化数据库 + "IsSeedData": true, //是否初始化数据库数据 + "CacheProvider": "Redis", // 缓存使用方式 Redis/Memory + "RedisConnectionString": "127.0.0.1:6379", //docker部署 172.17.0.1 + "TokenName": "WC-Token", //api Token名称 + "LoginExpire": 1, //登录缓存过期时间(小时) + "HomePage": "../Home/Default", //登录主页地址 + "MainDbNumber": "0", //主程序数据库 + "LocalLAN": false, //是否局域网 + "OpenQuartz": true, //定时任务开启 + "SqlMode": "TenantSql", //数据库模式多租户或者多库 "MoreSql" + "ProjectPrefix": "watercloud", //项目中的前缀 + "ReviseSystem": false, //是否重置密码 + "LoginErrorCount": 4, //登录错误次数 + "IsCluster": false, //集群参数 开启时需要去quartz下载响应数据库 + "NeedClear": false, //是否删除定时调度任务 + "SqlConfig": [ + //{ + // "DBNumber": "1", + // "DBProvider": "SqlServer", //MySql //Oracle + // "DBConnectionString": "Data Source = .;Initial Catalog = WaterCloudNetDb;User ID=sa;Password=12345678;MultipleActiveResultSets=true;" //Data Source = 192.168.1.252;Initial Catalog = WaterCloudNetDb;User ID=sa;Password=admin@12345;MultipleActiveResultSets=true; + //} + ], + "RabbitMq": { + "Enabled": false, + "HostName": "localhost", + "UserName": "root", //默认guest + "Password": "root", //默认guest + "Port": 5672, + "VirtualHost": "/" + }, + "DocumentSettings": { + "DocumentTitle": "WaterCloud API", + "GroupOpenApiInfos": [ + { + "Group": "Default", + "Title": "WaterCloud API", + "Description": "WaterCloud .NET敏捷开发框架
    项目地址:https://gitee.com/qian_wei_hong/WaterCloud", + "Version": "1.0.0" + }, + { + "Group": "V2", + "Title": "V2", + "Description": "WaterCloud .NET敏捷开发框架
    项目地址:https://gitee.com/qian_wei_hong/WaterCloud", + "Version": "1.0.0" + } + ] + } + }, + "AllowedHosts": "*" +} \ No newline at end of file diff --git a/WaterCloud.Web/libman.json b/WaterCloud.Web/libman.json new file mode 100644 index 0000000..b818c80 --- /dev/null +++ b/WaterCloud.Web/libman.json @@ -0,0 +1,14 @@ +{ + "version": "1.0", + "defaultProvider": "unpkg", + "libraries": [ + { + "library": "@microsoft/signalr@3.1.6", + "destination": "wwwroot/lib/signalr/", + "files": [ + "dist/browser/signalr.js", + "dist/browser/signalr.min.js" + ] + } + ] +} \ No newline at end of file diff --git a/WaterCloud.Web/watercloudnetdb.db b/WaterCloud.Web/watercloudnetdb.db new file mode 100644 index 0000000..e63c860 Binary files /dev/null and b/WaterCloud.Web/watercloudnetdb.db differ diff --git a/WaterCloud.Web/wwwroot/api/tableSelect.json b/WaterCloud.Web/wwwroot/api/tableSelect.json new file mode 100644 index 0000000..37fb0ed --- /dev/null +++ b/WaterCloud.Web/wwwroot/api/tableSelect.json @@ -0,0 +1,23 @@ +{ + "code": 0, + "msg": "", + "count": 16, + "data": [ + { "id":"001", "username":"张玉林", "sex":"女" }, + { "id":"002", "username":"刘晓军", "sex":"男" }, + { "id":"003", "username":"张恒", "sex":"男" }, + { "id":"004", "username":"朱一", "sex":"男" }, + { "id":"005", "username":"刘佳能", "sex":"女" }, + { "id":"006", "username":"晓梅", "sex":"女" }, + { "id":"007", "username":"马冬梅", "sex":"女" }, + { "id":"008", "username":"刘晓庆", "sex":"女" }, + { "id":"009", "username":"刘晓庆", "sex":"女" }, + { "id":"010", "username":"刘晓庆", "sex":"女" }, + { "id":"011", "username":"刘晓庆", "sex":"女" }, + { "id":"012", "username":"刘晓庆", "sex":"女" }, + { "id":"013", "username":"刘晓庆", "sex":"女" }, + { "id":"014", "username":"刘晓庆", "sex":"女" }, + { "id":"015", "username":"刘晓庆", "sex":"女" }, + { "id":"016", "username":"刘晓庆", "sex":"女" } + ] +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/api/upload.json b/WaterCloud.Web/wwwroot/api/upload.json new file mode 100644 index 0000000..691902d --- /dev/null +++ b/WaterCloud.Web/wwwroot/api/upload.json @@ -0,0 +1,10 @@ +{ + "code": 1, + "msg": "上传成功", + "data": { + "url": [ + "../images/logo.png", + "../images/captcha.jpg" + ] + } +} diff --git a/WaterCloud.Web/wwwroot/css/formpreview.css b/WaterCloud.Web/wwwroot/css/formpreview.css new file mode 100644 index 0000000..27ec6cd --- /dev/null +++ b/WaterCloud.Web/wwwroot/css/formpreview.css @@ -0,0 +1,65 @@ +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + background-color: #ffffff; + border: 1px solid #cccccc; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + -o-transition: border linear 0.2s, box-shadow linear 0.2s; + transition: border linear 0.2s, box-shadow linear 0.2s; +} + +select, +textarea, +input[type="text"], +input[type="password"], +input[type="datetime"], +input[type="datetime-local"], +input[type="date"], +input[type="month"], +input[type="time"], +input[type="week"], +input[type="number"], +input[type="email"], +input[type="url"], +input[type="search"], +input[type="tel"], +input[type="color"], +.uneditable-input { + display: inline-block; + padding: 4px 6px; + margin-bottom: 10px; + font-size: 14px; + line-height: 20px; + color: #555555; + vertical-align: middle; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + + +/* select[leipiplugins] { + display: inherit !important +} */ + +#frmPreview select, +#frmPreview input { + display: inline !important +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/css/knowledge.css b/WaterCloud.Web/wwwroot/css/knowledge.css new file mode 100644 index 0000000..b3288aa --- /dev/null +++ b/WaterCloud.Web/wwwroot/css/knowledge.css @@ -0,0 +1,461 @@ +body { +} +.content-center { + position:relative; + margin:32px auto 0; + overflow:visible!important +} +article, aside, blockquote, body, button, code, dd, details, div, dl, dt, fieldset, figcaption, figure, footer, form, h1, h2, h3, h4, h5, h6, header, hgroup, hr, input, legend, li, menu, nav, ol, p, pre, section, td, textarea, th, ul { + margin: 0; + padding: 0; +} + +h3 { + font-size: 18px; + line-height: 25px; +} + +h1, h2, h3, h4, h5, h6 { + font-weight: 300; + letter-spacing: -0.25px; +} + +li { + line-height: 20px; +} + +ul { + list-style-type: none; +} + +.rank-list { + margin: 0 20px 2px 0px; +} + + .rank-list li { + position: relative; + _display: block; + padding: 10px 0 0 25px; + height: 25px; + vertical-align: top; + } + + .rank-list li span { + float: right; + margin-left: 5px; + color: #999; + _padding: 2px 0 2px 5px; + _z-index: 2; + _position: absolute; + _background: #fff; + _right: 0; + } + + .rank-list li.active .num { + top: 12px; + background: #d60007; + font-family: Georgia, "Times New Roman", Times, serif; + } + + .rank-list li .num { + position: absolute; + left: 0px; + top: 12px; + display: inline-block; + vertical-align: -3px; + *vertical-align: middle; + width: 16px; + height: 16px; + margin-right: 10px; + background: #1389d7; + font-style: normal; + color: #fff; + font-size: 10px; + font-family: Verdana, Geneva, sans-serif; + text-align: center; + overflow: hidden; + } + + .rank-list li a { + display: block; + padding: 0; + color: #888; + font-size: 13px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + _position: absolute; + } + +.search-box { + height: 42px; + padding: 4px; + position: relative; +} + + .search-box .input-group .form-control { + box-shadow: none; + height: 38px; + line-height: 38px; + padding-top: 0px; + padding-bottom: 0px; + padding-right: 0px; + padding-left: 7px; + resize: none; + } + +.btn-primary { + background-color: #1ABC9C; + border-color: #1ABC9C; +} + +.search-box .input-group .btn { + padding: 0px 0px; + font-size: 14px; + height: 38px; + min-width: 40px; +} + + .search-box .input-group .btn i { + margin-right: 0px; + } + +.btn i { + margin-right: 4px; + font-size: 14px; +} + +.help-n-list { + padding-top: 10px; +} + + .help-n-list li { + display: block; + padding-bottom: 16px; + border-bottom: 1px solid #E5E5E5; + overflow: hidden; + } + + .help-n-list li h2 { + padding: 5px 0 5px 0; + font-size: 16px; + line-height: 20px; + font-weight: normal; + margin: 4px; + } + + .help-n-list li h2 a { + font-size: 16px; + font-weight: bold; + line-height: 29px; + color: #3b8dd1; + text-decoration: none; + } + + .help-n-list li .note .info { + padding-top: 5px; + font: 12px/1.5 "Microsoft Yahei"; + } + +.info span { + font-weight: 100; + padding: 5px; +} + +.zhaiyao{ + padding: 0 5px; + max-width:500px; + color: rgb(136, 136, 136); +font-size: 13px; +text-overflow: ellipsis; +white-space: nowrap; +overflow: hidden; +} +.list-item-tags{ + +} +.item-tags{ +border: 1px solid #1abc9c; +border-radius: 4px; +padding: 2px 4px; +font-size: 11px; +color: #1abc9c; +height: 20px; +line-height: 20px; +} + +.tags-list{ + margin: 5px 20px 2px 0px; +} +.tags-list .tag-info{ +border: 1px solid #1abc9c; +border-radius: 4px; +padding: 2px 6px; +font-size: 13px; +color: #1abc9c; +height: 24px; +line-height: 24px; +margin-right: 8px; +} + + +/* + 以下是评论功能样式 +*/ + .clear { + zoom: 1; + overflow: hidden; +} + em { + font-style: normal; +} + + .comment #mpbox { + margin: 0 auto; + width: 100%; + height: auto; + font-weight: 400; + text-align: left; + color: #333; + font-size: 12px; + line-height: 1; + overflow: visible; + background-color: transparent; +} + #mpbox { + font-weight: 400; + text-align: left; + color: #333; + font-size: 12px; + line-height: 1; +} + #mpbox .left { + float: left; + display: inline; +} + #mpbox .right { + float: right; + display: inline; + position: relative; +} + #mpbox .clear { + zoom: 1; + overflow: hidden; +} + #mpbox .c-comment-header { + padding: 11px 0 7px; + /*height: 42px;*/ + line-height: 24px; + font-size: 16px; +} + + #mpbox .c-comment-header .c-opinion { + font-size: 18px; + color: #191919; +} + #mpbox .c-comment-header .c-opinion .c-line { + float: left; + margin-top: 3px; + width: 4px; + height: 19px; + background: #fdd000; + border-radius: 2px; + margin-right: 12px; +} + + .c-num-red { + font-size: 22px; + font-family: "Georgia Regular",Georgia; + color: #d92227; +} + #mpbox .c-comment-submiter { + margin-top: 5px; + position: relative; + border: 1px solid #b7b7b7; +} + #mpbox .c-comment-submiter .c-comment-box { + position: relative; + z-index: 9; + zoom: 1; + padding: 7px 10px 0 15px; + overflow: hidden; + background-color: #fff; +} + #mpbox .c-comment-submiter .c-comment-box .c-comment-textbox { + padding: 0; + margin: 0 0 9px; + width: 100%; + height: 66px; + line-height: 22px; + font-size: 14px; + resize: none; + overflow-x: hidden; + overflow-y: auto; + background-image: none; + color: #ccc; + background-attachment: scroll; + border: 0; + outline: 0; +} + + #mpbox .c-comment-submiter.c-active { + border: 1px solid #ee4046; } + #mpbox .c-comment-submiter.c-active .c-comment-textbox { + color: #333; } + #mpbox .c-comment-submiter .c-submit-btn-unlogin { + + font-size: 14px; + text-indent: 0; + letter-spacing: 0; + +} + #mpbox .c-comment-submiter .c-submit-btn:hover, #mpbox .c-comment-submiter .c-submit-btn-unlogin:hover { + background: #cc0f15; + } + #mpbox .c-comment-submiter .c-submit-closed { + right: 0; + bottom: 0; + height: 35px; + background: #cdcdcd; + } + #mpbox .c-comment-submiter .c-submit-closed:hover { + background: #cdcdcd; + } + #mpbox .c-comment-submiter .c-submit-btn, #mpbox .c-comment-submiter .c-submit-btn-unlogin { + position: absolute; + right: -1px; + bottom: -1px; + width: 90px; + height: 37px; + font-size: 14px; + font-family: "Microsoft YaHei"; + line-height: 37px; + color: #fff; + background: #d81519; + z-index: 10; + cursor: pointer; + text-align: center; + text-indent: 2px; + letter-spacing: 0px; +} + + #mpbox .c-comment-submiter .c-empty { + display: none; + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 82px; + line-height: 82px; + font-size: 15px; + z-index: 10; + background: #fff; + color: #d92227; + text-align: center; + cursor: text; +} + #mpbox .c-comment-content .c-new { + margin-top: 20px; +} + #mpbox .c-comment-content .c-comment-title { + height: 17px; + line-height: 17px; +} + #mpbox .c-comment-content .c-comment-title span { + float: left; + line-height: 1; + font-size: 16px; +} + #mpbox .c-comment-content .c-comment-title span .c-line { + float: left; + margin-right: 12px; + width: 4px; + height: 17px; + background: #e0e0e0; + border-radius: 2px; +} + #mpbox .c-comment-content .c-comment-main { + margin-top: 10px; + border-top: 1px solid #ddd; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment { + padding: 20px 0 11px; + border-bottom: 1px dashed #e5e5e5; + overflow: visible; +} + + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-head { + width: 50px; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-head .c-head-wrapper { + width: 50px; + height: 50px; + border-radius: 50%; + overflow: hidden; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-head .c-head-wrapper img { + width: 50px; + height: 50px; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-content { + padding-left: 64px; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-content .c-item-info { + padding: 1px 0 15px; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-content .c-item-info .c-username { + font-size: 13px; + color: #d92227; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-content .c-item-info .c-username span { + font-size: 11px; + padding: 0 2px; + color: #7e7e7e; +} + .article-page #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-content .c-discuss, .article-page + #mpbox .c-make-floor .c-floor .c-floor-discuss { + word-wrap: break-word; + word-break: normal; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-content .c-discuss { + padding: 0 7px 11px 0; + line-height: 22px; + font-size: 14px; + word-break: break-all; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-content .c-controller { + position: relative; + text-align: right; + height: 16px; + line-height: 16px; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-content .c-controller .c-date { + font-size: 12px; + color: #7e7e7e; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-content .c-controller .c-reply { + padding: 0 10px; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-content .c-controller a { + margin: 0 5px; + color: #7e7e7e; + font-size: 12px; + line-height: 17px; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-content .c-controller a { + margin: 0 5px; + color: #7e7e7e; + font-size: 12px; + line-height: 17px; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-content .c-controller .c-thumb-icon { + vertical-align: top; + background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpjZTZhMmJiNS01YjA2LTY0NDgtOWUxZC03MDRmOGFkMTgzOGIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjJCMzQ3OUMyNEU0MTFFNzhBNjc5MTkxRTJCMEMxQjUiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjJCMzQ3OUIyNEU0MTFFNzhBNjc5MTkxRTJCMEMxQjUiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6Y2U2YTJiYjUtNWIwNi02NDQ4LTllMWQtNzA0ZjhhZDE4MzhiIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmNlNmEyYmI1LTViMDYtNjQ0OC05ZTFkLTcwNGY4YWQxODM4YiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgVjcsgAAACoSURBVHjaYvz//z8DCOzZs4cBDcwBYl8grgLiucgSTAy4gQsQiwFxPboELk1GQCwPZV9Al2TB4iw+IJ6MxG/B0ITGjwTiXiCWRBI7AsRfkPkgTYehHFsg7kDTAAKsQCyIxHcHabJBEuBiwA9+AXEWExZT8QE2IFZjYiADoGv6RkD9cyCuQdf0m4AmbpBFpDovGoh/skDjgREq+BGIP0EjGFvIgS0BCDAA0eEcY6x9OdEAAAAASUVORK5CYII=) no-repeat center; +} + #mpbox .c-comment-content .c-comment-main .c-item-comment .c-item-content .c-controller i { + vertical-align: middle; + margin-right: 2px; + display: inline-block; + width: 13px; + height: 13px; +} diff --git a/WaterCloud.Web/wwwroot/css/layout.css b/WaterCloud.Web/wwwroot/css/layout.css new file mode 100644 index 0000000..d6ddde9 --- /dev/null +++ b/WaterCloud.Web/wwwroot/css/layout.css @@ -0,0 +1,137 @@ +html{ +} +body { +} +a:active, a:hover { + outline: 0; +} +a:focus, a:hover { + text-decoration: none; +} +a:active { + text-decoration: none; +} +.fa-toggle-on{ + color: #1ABC9C; +} +.dcui-btn-area{ + margin-bottom:5px;border-bottom:1px solid #e6e6e6;padding-top:3px;padding-bottom:3px; +} +.dcui-search-area{ + margin-bottom:5px;padding-bottom:2px; +} +.dcui-btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 12px; + font-weight: 400; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid + transparent; + border-top-color: transparent; + border-right-color: transparent; + border-bottom-color: transparent; + border-left-color: transparent; + border-radius: 2px; + cursor: pointer; +} +.dcui-btn{ + text-decoration: none; +} + +.dcui-btn:hover { + background: #e2e2e2; + color: #000; + filter: none; + text-decoration: none; +} +.dcui-btn:hover,.dcui-btn:focus{ + color:#fff; +} +.dcui-btn-black:hover, .dcui-btn-blue:hover, .dcui-btn-brown:hover, .dcui-btn-green:hover, .dcui-btn-orange:hover, .dcui-btn-purple:hover, .dcui-btn-red:hover { + opacity: .7; + filter: alpha(opacity=80); +} +.dcui-btn i { + margin-right: 5px; + font-size: 13px; +} +.dcui-btn-green { + border:0; + background:#009688; + color:#fff +} +.dcui-btn-green:hover { + color:#fff; + background:#009688 +} +.dcui-btn-brown { + border:0; + background:brown; + color:#fff +} +.dcui-btn-brown:hover { + color:#fff; + background:brown +} +.dcui-btn-black { + border:0; + background:#2F4056; + color:#fff +} +.dcui-btn-black:hover { + color:#fff; + background:#2F4056 +} +.dcui-btn-blue { + border:0; + background:#1E9FFF; + color:#fff +} +.dcui-btn-blue:hover { + color:#fff; + background:#1E9FFF +} +.dcui-btn-orange { + border:0; + background:#FFB800; + color:#fff +} +.dcui-btn-orange:hover { + color:#fff; + background:#FFB800 +} +.dcui-btn-red { + border:0; + background:#FF5722; + color:#fff +} +.dcui-btn-red:hover { + color:#fff; + background:#FF5722 +} +.dcui-btn-purple { + border:0; + background:purple; + color:#fff +} + +.dcui-btn-purple:hover { + color:#fff; + background:purple +} + + +/*----------*/ \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/css/layuimini.css b/WaterCloud.Web/wwwroot/css/layuimini.css new file mode 100644 index 0000000..ea7596e --- /dev/null +++ b/WaterCloud.Web/wwwroot/css/layuimini.css @@ -0,0 +1,887 @@ +/** +配色方案(如有需要,请自行配置) + */ +/**头部-配色*/ +.layui-layout-admin .layui-header { + background-color: #1aa094 !important; +} + +.layui-header > ul > .layui-nav-item.layui-this, .layuimini-tool i:hover { + background-color: #197971 !important; +} + +.layui-header .layuimini-header-content > ul > .layui-nav-item.layui-this, .layuimini-tool i:hover { + background-color: #197971 !important; +} + +/**logo-配色*/ +.layui-layout-admin .layuimini-logo { + background-color: #243346 !important; +} + +/**左侧-配色*/ +.layui-side.layui-bg-black, .layui-side.layui-bg-black > .layuimini-menu-left > ul { + background-color: #2f4056 !important; +} + +.layuimini-menu-left .layui-nav .layui-nav-child a:hover:not(.layui-this) { + background-color: #3b3f4b; +} + +/**左侧菜单选中-配色*/ +.layui-layout-admin .layui-nav-tree .layui-this, .layui-layout-admin .layui-nav-tree .layui-this > a, .layui-layout-admin .layui-nav-tree .layui-nav-child dd.layui-this, .layui-layout-admin .layui-nav-tree .layui-nav-child dd.layui-this a { + background-color: #1aa094 !important; +} + + +/**头部样式 */ +.layui-layout-admin .header { + position: fixed; + left: 0; + right: 0; + top: 0; + bottom: 0; +} + +.layuimini-header-menu, .layui-header { + height: 60px !important; +} + + .layuimini-header-menu > .layui-nav-item { + color: #1b1d21; + height: 60px !important; + line-height: 60px !important; + } + + .layui-header > .layui-layout-right > .layui-nav-item { + height: 60px !important; + line-height: 60px !important; + } + +.layui-layout-left { + left: 295px !important; +} + +.layui-nav.layui-layout-left.layuimini-header-menu.layuimini-pc-show { + font-weight: bold; + transition: all .2s; +} + + +/**logo演示(通用) */ +.layui-layout-admin .layuimini-logo { + font-weight: bold; + color: #ffffff !important; + height: 60px !important; + line-height: 60px !important; + overflow: hidden; + line-height: 64px; + transition: all .2s !important; +} + + .layui-layout-admin .layuimini-logo img { + display: inline-block; + height: 40px; + vertical-align: middle; + } + + .layui-layout-admin .layuimini-logo h1 { + display: inline-block; + margin: 0 0 0 12px; + color: #ffffff; + font-weight: 600; + font-size: 20px; + font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif; + vertical-align: middle; + } + +/**缩放工具(通用) */ +.layuimini-tool { + position: absolute !important; + top: 0; + left: 235px; + width: 60px; + height: 100%; + line-height: 60px; + text-align: center; + color: #ffffff !important; + transition: all .2s; +} + + /**缩放工具(缩放) */ + .layuimini-tool i { + display: block; + color: #bbe3df; + width: 32px; + height: 32px; + line-height: 32px; + border-radius: 3px; + text-align: center; + margin-top: 15px; + cursor: pointer; + } + +/**tab选项卡 */ +.layuimini-tab { + margin: 0px; + overflow: hidden; + height: 100% !important; +} + + .layuimini-tab .layui-tab-content { + height: calc(100% - 37px) !important; + -webkit-overflow-scrolling: touch; + overflow-y: scroll; + } + + .layuimini-tab .layui-tab-content .layui-tab-item { + height: 100%; + } + + .layuimini-tab .layui-tab-content { + padding: 0px; + } + + .layuimini-tab .layui-tab-title { + border: none; + border: 1px solid whitesmoke; + background-color: white; + } + + .layuimini-tab .layui-tab-title li { + border-right: 1px solid whitesmoke; + color: dimgray; + } + + .layuimini-tab .layui-tab-title .layui-tab-bar { + display: none; + } + + .layuimini-tab .layui-tab-title .layui-this:after { + display: none; + } + + .layuimini-tab .layui-tab-title .layuimini-tab-active { + display: inline-block; + background-color: lightgray; + width: 9px; + height: 9px; + border-radius: 30px; + margin-right: 5px; + } + + .layuimini-tab .layui-tab-title .layui-this .layuimini-tab-active { + background-color: #1aa094; + } + + .layuimini-tab > .layui-tab-title, .layuimini-tab > .close-box { + height: 35px !important; + } + + .layuimini-tab > .layui-tab-title li, .layuimini-tab > .close-box li { + line-height: 35px !important; + } + + .layuimini-tab .layui-tab-title span { + color: #666; + } + + .layuimini-tab .layui-tab-title .layui-this span { + color: #2D8CF0; + } + + .layuimini-tab .layui-tab-title .layui-tab-close { + font-size: 12px !important; + width: 14px !important; + height: 14px !important; + line-height: 16px !important; + } + + .layuimini-tab .layui-tab-title .layui-tab-close:hover { + border-radius: 4em; + background: #ff5722; + } + + .layuimini-tab .layui-tab-title .disable-close + .layui-tab-close { + display: none; + } + + .layuimini-tab .layui-tab-title .able-close + .layui-tab-close { + display: inline-block; + } + + .layuimini-tab .layui-tab-control > li { + position: absolute; + top: 0px; + height: 35px; + line-height: 35px; + width: 35px; + text-align: center; + background-color: white; + border-top: whitesmoke 1px solid; + border-bottom: whitesmoke 1px solid; + } + + .layuimini-tab .layuimini-tab-roll-left { + left: 0px; + border-right: whitesmoke 1px solid; + border-left: whitesmoke 1px solid; + } + + .layuimini-tab .layuimini-tab-roll-right { + right: 35px; + border-left: 1px solid whitesmoke; + } + + .layuimini-tab .layui-tab-tool { + right: 0px; + border-left: 1px solid whitesmoke; + } + + .layuimini-tab .layui-tab-control .layui-tab-tool, + .layuimini-tab .layui-tab-control .layuimini-tab-roll-left, + .layuimini-tab .layui-tab-control .layuimini-tab-roll-right { + display: none; + } + + .layuimini-tab.layui-tab-roll .layui-tab-control .layuimini-tab-roll-left, + .layuimini-tab.layui-tab-roll .layui-tab-control .layuimini-tab-roll-right { + display: block; + } + + .layuimini-tab.layui-tab-roll .layui-tab-control .layuimini-tab-roll-right { + right: 0px; + border-right: 1px solid whitesmoke; + } + + .layuimini-tab.layui-tab-roll .layui-tab-title { + padding-left: 35px; + padding-right: 35px; + } + + + .layuimini-tab.layui-tab-tool .layui-tab-control .layui-tab-tool { + display: block; + } + + .layuimini-tab.layui-tab-tool .layui-tab-title { + padding-left: 0px; + padding-right: 35px; + } + + + .layuimini-tab.layui-tab-rollTool .layui-tab-title { + padding-left: 35px; + padding-right: 80px; + } + + .layuimini-tab.layui-tab-rollTool .layui-tab-control .layuimini-tab-roll-left, + .layuimini-tab.layui-tab-rollTool .layui-tab-control .layuimini-tab-roll-right, + .layuimini-tab.layui-tab-rollTool .layui-tab-control .layui-tab-tool { + display: block; + } + + .layuimini-tab .layui-tab-tool .layui-nav { + position: absolute; + height: 43px !important; + top: 0; + width: 100%; + height: 100%; + padding: 0; + background: 0 0; + } + + .layuimini-tab .layui-tab-tool .layui-nav-item { + height: 35px; + } + + .layuimini-tab .layui-tab-tool .layui-nav-bar { + display: none; + } + + .layuimini-tab .layui-tab-tool .layui-nav-child { + left: auto; + top: 45px; + right: 3px; + width: 120px; + border: 1px solid whitesmoke; + } + + .layuimini-tab .layui-tab-tool .layui-this a { + background-color: #009688; + } + +.layuimini-tab-loading { + position: absolute; + display: none; + width: 100%; + height: calc(100% - 37px); + top: 37px; + z-index: 19; + background-color: #fff +} + + .layuimini-tab-loading.close { + animation: close 1s; + -webkit-animation: close 1s; + animation-fill-mode: forwards; + } + +/**左侧菜单栏 (通用) */ +.layui-side.layui-bg-black { + transition: all .2s; +} + + .layui-side.layui-bg-black > .layuimini-menu-left > ul { + transition: all .2s; + } + + .layui-side.layui-bg-black > .layuimini-menu-left > ul > .layui-nav-item:first-child { + border-top: 1px solid #4b5461; + } + +.layuimini-menu-left .layui-nav .layui-nav-item a { + height: 40px; + line-height: 40px; + padding-right: 30px; +} + +.layuimini-menu-left .layui-nav .layui-nav-item > a { + padding-top: 5px; + padding-bottom: 5px; +} + +.layuimini-menu-left .layui-nav .layui-nav-child .layui-nav-child { + background: 0 0 !important +} + +.layuimini-menu-left .layui-nav .layui-nav-more { + right: 15px; +} + +.layuimini-menu-left .layui-nav .layui-nav-item a:hover { + background-color: transparent !important; +} + +.layuimini-menu-left .layui-nav { + background-color: transparent !important; +} + + +/**左侧菜单栏 (正常) */ +.layui-layout-body .layui-nav-itemed .layui-nav-child a, .layui-layout-body .layuimini-menu-left .layui-nav .layui-nav-child a { + padding-left: 35px; +} + +.layui-layout-body .layuimini-menu-left .layui-nav .layui-nav-child .layui-nav-child a { + padding-left: 45px; +} + +.layui-layout-body .layuimini-menu-left .layui-nav .layui-nav-child .layui-nav-child .layui-nav-child a { + padding-left: 55px; +} + +.layui-layout-body .layuimini-menu-left .layui-nav .layui-nav-child .layui-nav-child .layui-nav-child .layui-nav-child a { + padding-left: 65px; +} + +.layui-layout-body .layuimini-menu-left .layui-nav .layui-nav-itemed > .layui-nav-child { + padding: 5px 0; +} + +/**内容主体(通用) */ +.layui-layout-admin .layui-body { + overflow: hidden; + bottom: 0px !important; + top: 60px !important; + transition: all .2s; +} + +/**选择配色方案 */ +.layuimini-color .color-title { + padding: 10px 0 10px 20px; + border-bottom: 1px solid #d9dada; + margin-bottom: 8px; +} + +.layuimini-color .color-content { + padding: 10px 5px 0 5px; +} + + .layuimini-color .color-content ul { + list-style: none; + text-align: center; + } + + .layuimini-color .color-content ul li { + position: relative; + display: inline-block; + vertical-align: top; + width: 80px; + height: 50px; + margin: 0 15px 15px 0; + padding: 2px 2px 4px 2px; + background-color: #f2f2f2; + cursor: pointer; + font-size: 12px; + color: #666; + } + + .layuimini-color .color-content li.layui-this:after, .layuimini-color .color-content li:hover:after { + width: 100%; + height: 100%; + padding: 4px; + top: -5px; + left: -5px; + border-color: #d8d8d8; + opacity: 1; + } + + .layuimini-color .color-content li:after { + content: ''; + position: absolute; + z-index: 20; + top: 50%; + left: 50%; + width: 1px; + height: 0; + border: 1px solid #f2f2f2; + transition: all .3s; + -webkit-transition: all .3s; + opacity: 0; + } + + +/**其它 */ +.layui-tab-item { + width: 100% !important; + height: 100% !important; +} + +.layui-nav-item.layui-this { + background-color: #1b1d21; +} + +.layui-width-height { + width: 100%; + height: 95%; +} + +.layui-tab { + margin: 0 0 0 0; + z-index: 99999; +} + +.text-center { + height: 30px !important; + line-height: 30px !important; + text-align: center !important; +} + +.layui-nav { + padding: 0 !important; +} + + .layui-nav .layui-this:after, .layui-nav-bar, .layui-nav-tree .layui-nav-itemed:after { + width: 0 !important; + height: 0 !important; + } + +.layui-layout-admin .layui-side { + top: 60px !important; +} + +.layui-tab-card { + box-shadow: 0px 0px 0px #888888; + border-bottom: 0; +} + + +/**自定义滚动条样式 */ +::-webkit-scrollbar { + display: none +} + + +/*移动端遮罩层*/ +.layuimini-make { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 1000; + background: rgba(0, 0, 0, .5); + display: none; +} + +.layuimini-mini .layui-header { + z-index: 1001; +} +/**初始化加载层*/ +.layuimini-loader { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: #f2f2f2; + z-index: 999999; +} + + .layuimini-loader .layuimini-loader-inner { + display: block; + position: relative; + left: 50%; + top: 50%; + width: 150px; + height: 150px; + margin: -75px 0 0 -75px; + border-radius: 50%; + border: 3px solid transparent; + border-top-color: #ffb800; + animation: spin 2s linear infinite; + } + + .layuimini-loader .layuimini-loader-inner:before { + content: ""; + position: absolute; + top: 5px; + left: 5px; + right: 5px; + bottom: 5px; + border-radius: 50%; + border: 3px solid transparent; + border-top-color: #1e9fff; + animation: spin 3s linear infinite; + } + + .layuimini-loader .layuimini-loader-inner:after { + content: ""; + position: absolute; + top: 15px; + left: 15px; + right: 15px; + bottom: 15px; + border-radius: 50%; + border: 3px solid transparent; + border-top-color: #ff5722; + animation: spin 1.5s linear infinite; + } + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + + to { + transform: rotate(1turn); + } +} + +/*系统设置*/ + +.layuimini-color .layui-word-aux { + position: absolute; + left: 60px; + top: 12px; + font-size: 12px; +} + +.layuimini-color .layui-input-block { + margin-left: 15px; + min-height: 36px; +} + +.layuimini-color .more-menu-list { + width: 100%; + margin-top: 30px; +} + + +.layuimini-color .more-menu-item:first-child { + border-top: 1px solid #e8e8e8; +} + +.layuimini-color .more-menu-item .layui-icon { + font-size: 18px; + padding-right: 10px; +} + +.layuimini-color .more-menu-item { + color: #595959; + height: 50px; + line-height: 50px; + font-size: 16px; + padding: 0 25px; + border-bottom: 1px solid #e8e8e8; + font-style: normal; + display: block; +} + + .layuimini-color .more-menu-item:hover { + background-color: whitesmoke; + } + + .layuimini-color .more-menu-item:after { + color: #8c8c8c; + right: 16px; + content: "\e602"; + position: absolute; + font-family: layui-icon !important; + } + +/** +鼠标右键 + */ +.layuimini-tab-mousedown { + display: none; + width: 80px; + position: absolute; + top: 0px !important; + left: 0px !important; +} + + .layuimini-tab-mousedown dd a { + padding: 0 15px; + color: #484545; + } + +.layuimini-tab-make { + position: absolute; + top: 36px; + bottom: 0px; + width: 100%; + background: rgb(255, 255, 255,0); + padding: 0px; + overflow: hidden; +} + +/** +菜单缩放 + */ +.popup-tips .layui-layer-TipsG { + display: none; +} + +.popup-tips.layui-layer-tips .layui-layer-content { + padding: 0; +} + +.popup-tips .layui-nav-tree { + width: 150px; + border-radius: 10px; +} + +/**左侧菜单字体间距*/ +.layuimini-menu-left .layui-nav-item a span { + letter-spacing: 1px; +} + +/**头部菜单字体间距*/ +.layui-layout-admin .layui-header .layuimini-header-menu.layuimini-pc-show, .layui-layout-admin .layui-header .layuimini-header-menu.layuimini-mobile-show { + letter-spacing: 1px; +} + +/**修复左侧菜单字体不对齐的问题*/ +.layuimini-menu-left .layui-nav-item a .fa, .layuimini-menu-left .layui-nav-item a .layui-icon { + width: 20px; +} + +/** + PC版样式 + */ +@media screen and (min-width: 1025px) { + /**头部样式(缩放) */ + .layuimini-mini .layui-layout-left.layuimini-header-menu.layuimini-pc-show { + left: 155px !important; + } + + /**logo演示(缩放) */ + .layuimini-mini .layui-layout-admin .layuimini-logo { + width: 60px !important; + } + + .layuimini-mini .layui-layout-admin .layuimini-logo h1 { + display: none; + } + + /**左侧菜单栏(缩放) */ + .layuimini-mini .layuimini-menu-left { + width: 80px !important; + } + + .layuimini-mini .layui-side.layui-bg-black, .layuimini-mini .layuimini-menu-left > ul, .layuimini-mini .layuimini-menu-left > ul li i { + width: 60px !important; + } + + .layuimini-mini .layuimini-menu-left > ul li span:first-child { + display: none; + } + + .layuimini-mini .layuimini-menu-left > ul li span:last-child { + float: right; + right: 7px; + } + + .layuimini-mini .layuimini-menu-left .layui-nav .layui-nav-item a { + height: 40px; + line-height: 40px; + padding-right: 0px !important; + } + + /**内容主体(缩放) */ + .layuimini-mini .layui-layout-admin .layui-body { + left: 60px !important; + } + + .layuimini-mini .layuimini-tool { + left: 95px !important; + } + + .layuimini-pc-show { + display: block; + } + + .layuimini-mobile-show { + display: none; + } + + /**菜单缩放*/ + .layuimini-mini .layuimini-menu-left .layui-nav-more, .layuimini-mini .layuimini-menu-left .layui-nav-child { + display: none; + !important; + } +} + +/** + 手机自适应样式 +*/ +@media screen and (max-width: 1024px) { + .layuimini-pc-show { + display: none; + } + + .layuimini-mobile-show { + display: block; + } + + .layuimini-header-content { + left: 0; + } + + .layui-layout-admin .layui-body .layui-tab-item.layui-show { + border-top: 1px solid #e2e2e2; + } + + .layuimini-all .layui-layout-left.layuimini-header-menu { + left: 0px !important + } + + .layuimini-mini .layui-layout-left.layuimini-header-menu { + left: 205px !important + } + + .layui-layout-admin .layui-nav.layui-layout-right > li:not(.layuimini-setting) { + width: 40px !important; + } + + .layui-layout-admin .layui-nav.layui-layout-right > li:not(.layuimini-setting) a { + padding: 0 15px; + } + + .layuimini-all .layui-layout-admin .layui-body { + left: 0px !important; + } + + .layuimini-mini .layui-layout-admin .layuimini-menu-left, .layuimini-mini .layui-header .layuimini-logo { + left: 0; + transition: left .2s; + z-index: 1001 !important; + } + + .layuimini-all .layui-layout-admin .layuimini-menu-left, .layuimini-all .layui-header .layuimini-logo { + left: -200px; + transition: left .2s; + top: 0; + z-index: 1002; + } + + .layuimini-mini .layui-layout-admin .layui-body { + left: 0 !important; + transition: left .2s; + top: 0; + z-index: 998; + } + + .layuimini-mini .layuimini-make { + display: block; + } + + .layuimini-multi-module .layuimini-header-content .layuimini-tool { + display: none; + } + + .layuimini-single-module .layuimini-header-content .layuimini-tool { + left: 15px; + } + + .layuimini-mini .layuimini-site-mobile { + display: none !important; + } + + .layuimini-site-mobile { + display: block !important; + position: fixed; + z-index: 100000; + bottom: 15px; + left: 15px; + width: 40px; + height: 40px; + line-height: 40px; + border-radius: 2px; + text-align: center; + background-color: rgba(0, 0, 0, .7); + color: #fff; + } + + .layuimini-header-content { + z-index: 997; + } + + /*修复UC之类的浏览器点击无效*/ + .layuimini-make { + cursor: pointer; + } + + .layuimini-site-mobile { + cursor: pointer; + } +} + +@media screen and (max-width: 550px) { + + /**头部右侧数据*/ + .layuimini-multi-module.layuimini-mini .layuimini-header-content .layui-layout-right { + display: none; + } +} + +/**替换原有样式更新 2.6.7*/ +.layui-layout-admin .layui-body { + padding-bottom: 0px; +} + +/**替换原有样式更新 2.6.7*/ +.layui-nav-tree .layui-nav-item > a .layui-nav-more { + padding: 0px 0; +} +.layui-table { + width: 100%; + margin: 10px 0; + background-color: #fff; + color: black; +} +.layui-tab-control > ul > .layui-nav-item.layui-this { + background-color: none; +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/css/login.css b/WaterCloud.Web/wwwroot/css/login.css new file mode 100644 index 0000000..0744d24 --- /dev/null +++ b/WaterCloud.Web/wwwroot/css/login.css @@ -0,0 +1,237 @@ +html, body { + width: 100%; + height: 100%; + overflow: hidden +} + +body { + background-image: url(/images/moon.jpg); + background-size: cover; + font-family: 'Open Sans', sans-serif; + background-attachment: fixed; + background-position: center; +} + + body:after { + content: ''; + background-repeat: no-repeat; + background-size: cover; + -webkit-filter: blur(3px); + -moz-filter: blur(3px); + -o-filter: blur(3px); + -ms-filter: blur(3px); + filter: blur(3px); + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: -1; + } + +.layui-container { + width: 100%; + height: 100%; + overflow: hidden +} + +.admin-login-background { + color: #ffb800; + width: 360px; + height: 300px; + position: absolute; + left: 50%; + top: 40%; + margin-left: -180px; + margin-top: -100px; +} + +.logo-title { + text-align: center; + letter-spacing: 2px; + padding: 14px 0; +} + + .logo-title h1 { + color: #FFFFCE; + font-size: 25px; + font-weight: bold; + } + +.login-form { + border: 1px solid #fff; + border-radius: 3px; + padding: 14px 20px; + box-shadow: 0 0 8px #eeeeee; +} + + .login-form .layui-form-item { + position: relative; + } + + .login-form .layui-form-item label { + position: absolute; + left: 1px; + top: 1px; + width: 38px; + line-height: 36px; + text-align: center; + color: #d2d2d2; + } + + .login-form .layui-form-item input { + padding-left: 36px; + } + + .login-form .layui-form-item .layui-btn { + background-color: #2f4056; + color: #fafafa; + } + +.captcha { + width: 60%; + display: inline-block; +} + +.captcha-img { + display: inline-block; + width: 34%; + float: right; +} + + .captcha-img img { + height: 34px; + border: 1px solid #e6e6e6; + height: 36px; + width: 100%; + } + +.tips_msg { + height: 30px; + line-height: 30px; + color: red; + margin: 0 auto; + border-radius: 5px; + width: 300px; + font-size: 14px; +} + + .tips_msg i { + position: relative; + top: 0.5px; + font-size: 15px; + padding-right: 5px; + } + +#starsBox { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.75); + opacity: .5; +} + + #starsBox span { + display: inline-block; + width: auto; + position: absolute; + border-radius: 100%; + transition: 100s linear; + } + +p { + position: fixed; + top: 50%; + left: 0; + right: 0; + text-align: center; + transform: translateY(-50%); + font-size: 40px; + font-weight: 900; + color: white; + text-shadow: 0 0 50px black; + text-transform: capitalize; + font-family: 'Roboto','Helvetica','Arial',sans-serif; + letter-spacing: 5px; +} + + p > span { + display: block; + font-size: 12px; + color: #bdc3c7; + margin-top: 30px; + font-weight: 100; + text-shadow: 0 0 50px black; + letter-spacing: 3px; + } + + p > span > a { + font-weight: 700; + text-decoration: none; + color: #d64541; + padding-bottom: 2px; + border-bottom: 0px solid #d64541; + transition: 0.5s; + } + + p > span > a:hover { + padding-bottom: 5px; + border-bottom: 2px solid #d64541; + } + +.layui-form-item .layui-form-checkbox[lay-skin=primary] { + margin-top: 0px; +} + +.layui-form-checked[lay-skin=primary] i { + border-color: orange !important; + background-color: orange; + color: #fff; +} + +.code { + width: 100%; + margin: 0 auto; +} + +.input-val { + width: 63%; + background: #ffffff; + height: 2.8rem; + padding: 0 2%; + border-radius: 5px; + border: none; + border: 1px solid rgba(0,0,0,.2); + font-size: 0.9rem; +} + +#canvas { + float: right; + display: inline-block; + border: 1px solid #ccc; + border-radius: 5px; + cursor: pointer; + background-color: white; +} +.layui-tab-title { + position: relative; + left: 0; + height: 40px; + white-space: nowrap; + font-size: 0; + border-bottom-width: 1px; + border-bottom-style: unset; + transition: all .2s; + -webkit-transition: all .2s; +} + + .layui-tab-title .layui-this { + color: orange; + background-color: #FFFFCE; + } +.layui-form-select dl dd { + cursor: pointer; + color: black; +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/css/loginnew.css b/WaterCloud.Web/wwwroot/css/loginnew.css new file mode 100644 index 0000000..677f74f --- /dev/null +++ b/WaterCloud.Web/wwwroot/css/loginnew.css @@ -0,0 +1,239 @@ +html, body { + width: 100%; + height: 100%; + overflow: hidden +} + +body { + background-image: url(/images/bgnew.jpeg); + background-size: cover; + font-family: 'Open Sans', sans-serif; + background-attachment: fixed; + background-position: center; +} + + body:after { + content: ''; + background-repeat: no-repeat; + background-size: cover; + -webkit-filter: blur(3px); + -moz-filter: blur(3px); + -o-filter: blur(3px); + -ms-filter: blur(3px); + filter: blur(3px); + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: -1; + } + +.layui-container { + width: 100%; + height: 100%; + overflow: hidden +} + +.admin-login-background { + color: #ff5722; + width: 360px; + height: 300px; + position: absolute; + left: 50%; + top: 40%; + margin-left: -180px; + margin-top: -100px; +} + +.logo-title { + text-align: center; + letter-spacing: 2px; + padding: 14px 0; +} + + .logo-title h1 { + color: #1e9fff; + font-size: 25px; + font-weight: bold; + } + +.login-form { + border: 1px solid #fafafa; + border-radius: 3px; + padding: 14px 20px; + box-shadow: 0 0 8px #333; +} + + .login-form .layui-form-item { + position: relative; + } + + .login-form .layui-form-item label { + position: absolute; + left: 1px; + top: 1px; + width: 38px; + line-height: 36px; + text-align: center; + color: #d2d2d2; + } + + .login-form .layui-form-item input { + padding-left: 36px; + } + + .login-form .layui-form-item .layui-btn { + background-color: #1e9fff; + color: #fafafa; + } + +.captcha { + width: 60%; + display: inline-block; +} + +.captcha-img { + display: inline-block; + width: 34%; + float: right; +} + + .captcha-img img { + height: 34px; + border: 1px solid #e6e6e6; + height: 36px; + width: 100%; + } + +.tips_msg { + height: 30px; + line-height: 30px; + color: red; + margin: 0 auto; + border-radius: 5px; + width: 300px; + font-size: 14px; +} + + .tips_msg i { + position: relative; + top: 0.5px; + font-size: 15px; + padding-right: 5px; + } + +#starsBox { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.75); + opacity: .5; +} + + #starsBox span { + display: inline-block; + width: auto; + position: absolute; + border-radius: 100%; + transition: 100s linear; + } + +p { + position: fixed; + top: 50%; + left: 0; + right: 0; + text-align: center; + transform: translateY(-50%); + font-size: 40px; + font-weight: 900; + color: white; + text-shadow: 0 0 50px black; + text-transform: capitalize; + font-family: 'Roboto','Helvetica','Arial',sans-serif; + letter-spacing: 5px; +} + + p > span { + display: block; + font-size: 12px; + color: #bdc3c7; + margin-top: 30px; + font-weight: 100; + text-shadow: 0 0 50px black; + letter-spacing: 3px; + } + + p > span > a { + font-weight: 700; + text-decoration: none; + color: #d64541; + padding-bottom: 2px; + border-bottom: 0px solid #d64541; + transition: 0.5s; + } + + p > span > a:hover { + padding-bottom: 5px; + border-bottom: 2px solid #d64541; + } + +.layui-form-item .layui-form-checkbox[lay-skin=primary] { + margin-top: 0px; +} + +.layui-form-checked[lay-skin=primary] i { + border-color: orange !important; + background-color: orange; + color: #fff; +} + +.code { + width: 100%; + margin: 0 auto; +} + +.input-val { + width: 63%; + background: #ffffff; + height: 2.8rem; + padding: 0 2%; + border-radius: 5px; + border: none; + border: 1px solid rgba(0,0,0,.2); + font-size: 0.9rem; +} + +#canvas { + float: right; + display: inline-block; + border: 1px solid #ccc; + border-radius: 5px; + cursor: pointer; + background-color: white; +} + +.layui-tab-title { + position: relative; + left: 0; + height: 40px; + white-space: nowrap; + font-size: 0; + border-bottom-width: 1px; + border-bottom-style: unset; + transition: all .2s; + -webkit-transition: all .2s; +} + + .layui-tab-title .layui-this { + color: orange; + background-color: #FFFFCE; + } + +.layui-form-select dl dd { + cursor: pointer; + color: black; +} diff --git a/WaterCloud.Web/wwwroot/css/order.css b/WaterCloud.Web/wwwroot/css/order.css new file mode 100644 index 0000000..cdfd290 --- /dev/null +++ b/WaterCloud.Web/wwwroot/css/order.css @@ -0,0 +1,359 @@ +body { + font-size: 14px; + font-family: 'microsoft yahei',Verdana,Arial,Helvetica,sans-serif; + text-align: center; + background: #fff; +} +* { + margin: 0; + padding: 0px; + list-style: none; +} +body a { + text-decoration: none; + color: #0a4f83; +} +article, aside, audio, canvas, command, page-detail, details, embed, figcaption, figure, footer, header, hgroup, keygen, meter, nav, output, progress, section, source, video title { + display: block; +} + +/*头部Header*/ +.u_header { + position: relative; + width: 100%; + height: 40px; + /*background-color: #fa0000;*/ + background-color:#3cc51f; + text-align: center; + line-height: 40px; + color: #fff; + font-size: 18px; +} +.u_header .icon { + position: absolute; + top: 0; + display: block; + width: 40px; + height: 40px; + background-image: url(../images/header_icon.png); + background-size: 40px auto; +} +.u_header .l { left: 0;} +.u_header .r { right: 0;} +.u_header .icon1 { background:url(../images/menuicon.png) no-repeat center center; background-size:25px auto;} +.u_header .icon2 { background-position: center -40px;} +.u_header .icon3 { background:url(../images/nav_btn_back@2x.png) ; background-position: 5px -40px; background-size: 40px auto;} +.u_header .icon4 { background:url(../images/closeicon.png) no-repeat center center; background-size:20px auto;} +.u_header .icon5 { background:url(../images/nav_btn_add.png) no-repeat center center; background-size:20px auto;} +.u_header .font { + background-image: none; + color: #fff; +} +.u_header .icon1 i { + position: absolute; + top: 5px; + right: -3px; + display: none; + width: 9px; + height: 9px; + background: #fff; + border-radius: 9px; +} + +/*数据列表*/ +.page-detail { + /*margin: 10px 10px 0 10px;*/ + height: auto; + overflow: hidden; + font-size: 14px; + font-family: 'microsoft yahei',Verdana,Arial,Helvetica,sans-serif; + padding:8px; +} + +.page-detail_nr { + width: 100%; + height: auto; + overflow: hidden; + padding: 10px 0 0; +} +.page-detail_top { + border: 1px #ebebeb solid; +} + +.page-detail_t { + background-color: #ebebeb; + height: 36px; +} +.page-detail_t a { + width: 120px; + height: 36px; + line-height: 36px; + display: inline-block; + float: right; + color: #4d4e4f; + text-align: left; +} +.page-detail_b { + clear: both; + text-align: left; + border-top: 1px #e4e4e4 solid; + padding: 8px; + background-color: #f7f7f7; +} +.page-detail_b p { + line-height: 24px; + color: #4b4c4d; +} +.page-detail .aftermain-palce { + line-height: 1.8rem; + font-size: .65rem; + color: rgba(0,0,0,.27); + border-top: 1px dotted rgba(0,0,0,.27); + border-bottom: 1px dotted rgba(0,0,0,.27); +} +.page-detail .aftermain-palce span { + color: rgba(0,0,0,.72); +} +.page-detail .aftermian-doubleline { + margin-top: .4rem; + width: 100%; + height: .05rem; + border-top: 1px solid rgba(0,0,0,.32); + border-bottom: 1px solid rgba(0,0,0,.32); +} + +/* + 服务单详情 +*/ +html{ + font-size: 52.0833px; +} + +@media only screen and (min-width:400px) { + html { + font-size:52.0833px!important + } +} +@media only screen and (min-width:414px) { + html { + font-size:52.0833px!important + } +} +@media only screen and (min-width:480px) { + html { + font-size:52.0833px!important + } +} +body { + + font-size: .2rem; + color: #333; + +} +.page-service-detail { + background-color: #f5f5f5; + font-size: .269rem; + color: #333; +} +.page-service-detail .content { + padding: .2rem; +} +.page-service-detail .aftermain { + padding: .133rem .133rem .333rem; + background-color: #fff; +} +.page-service-detail .aftermian-head { + height: .41rem; +} +.page-service-detail .aftermian-head-icon { + float:left; + width:.41rem; + height:.41rem +} +.page-service-detail .aftermian-head-icon img { + width:100%; + height:auto +} +.page-service-detail .aftermian-head-text { + float:left; + margin-left:.2rem; + font-size:.21rem; + color:rgba(0,0,0,.27) +} +.page-service-detail .aftermian-head-btn { + float:right; + font-size:.23rem; + padding:.05rem; + color:rgba(0,0,0,.42); + border:1px solid rgba(0,0,0,.32); + margin-left:.1rem +} +.page-service-detail .aftermian-singleline { + margin-top: .21rem; + width: 100%; + height: .05rem; + border-bottom: 1px solid rgba(0,0,0,.32); +} + +.page-service-detail .aftermian-doubleline { + margin-top: .21rem; + width: 100%; + height: .05rem; + border-top: 1px solid rgba(0,0,0,.32); + border-bottom: 1px solid rgba(0,0,0,.32); +} +.page-service-detail .aftermian-timeline { + box-pack: justify; + -webkit-box-pack: justify; + height: 1.133rem; + padding: .16rem .26rem; + box-sizing: border-box; +} +.page-service-detail .aftermian-timeline-box.Y { + color: #35b258; +} + +.page-service-detail .aftermian-timeline-box { + color: rgba(0,0,0,.27); +} +.page-service-detail .aftermian-timeline-item { + width: .2rem; + height: .2rem; + border-radius: .1rem; + background-color: rgba(0,0,0,.27); + position: relative; +} +.page-service-detail .aftermian-timeline-box.Y .aftermian-timeline-item { + background-color: #35b258; +} +.page-service-detail .aftermian-timeline-item-text { + position: absolute; + top: -.33rem; + left: -.33rem; + white-space: nowrap; +} +.page-service-detail .aftermian-timeline-itemline { + border-bottom: 1px solid rgba(0,0,0,.27); +} +.page-service-detail .aftermian-timeline-box.lastItem { + box-flex: 0; + -webkit-box-flex: 0; + width: .2rem; +} +.ui-box { + display: box; + display: -webkit-box; + box-align: center; + -webkit-box-align: center; + box-pack: center; + -webkit-box-pack: center; +} +.ui-box .ui-box-flex { + -webkit-box-flex: 1; + box-flex: 1; +} + +.page-service-detail .aftermain-palce { + line-height: .8rem; + font-size: .25rem; + color: rgba(0,0,0,.27); + border-top: 1px dotted rgba(0,0,0,.27); + border-bottom: 1px dotted rgba(0,0,0,.27); +} +.page-service-detail .aftermain-palce span { + color: rgba(0,0,0,.72); +} +.page-service-detail .aftermain-info { + padding-top: .27rem; + font-size: .269rem; + color: rgba(0,0,0,.72); + text-align: left; +} +.page-service-detail .aftermain-info-h2 { + display: box; + display: -webkit-box; + box-align: start; + -webkit-box-align: start; + box-pack: start; + -webkit-box-pack: start; + margin-bottom: .1rem; +} +.page-service-detail .aftermain-info-h2-title { + max-width: 2rem; +} +.page-service-detail .aftermain-info-h2-desc { + max-width: 4.5rem; +} + + + +/* + 订单详情 +*/ +.order_top { + line-height: 36px; + text-align: left; + font-size: 14px; + padding: 0 10px; +} +.order_top a.order_red { + color: #d71249; +} + +.order_top a { + color: #0059a9; + text-align: right; + font-size: 14px; + width: auto; +} +.order_xq { + clear: both; + line-height: 20px; +} +.order_xx { + position: relative; + padding: 15px 30px 15px 10px; +} +.order_xq a { + color: #5e5e5e; +} +.order_xx a.order_more { + background-position: -215px -128px; + position: absolute; + right: 0; + top: 50%; + margin-top: -15px; +} +.operation_bt .m-btn { + padding: 0 8px; +} + +.btn-blue { + border-color: #0059a9; + background: #0059a9; +} +.m-btn { + display: inline-block; + height: 34px; + line-height: 34px; + text-align: center; + font-size: 16px; + color: #fff; + margin: 0 5px 0 0; + padding: 0 10px; + border: 1px solid #d1d1d1; + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + -ms-border-radius: 6px; + -o-border-radius: 6px; + border-radius: 6px; +} +.micon { + display: inline-block; + background: url(../images/icon.png) no-repeat; + background-size: 354px 354px; + width: 30px; + height: 30px; + text-indent: -10000px; + vertical-align: middle; +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/css/public.css b/WaterCloud.Web/wwwroot/css/public.css new file mode 100644 index 0000000..beedf89 --- /dev/null +++ b/WaterCloud.Web/wwwroot/css/public.css @@ -0,0 +1,70 @@ +body { + margin: 15px 15px 15px 15px; + background: #f2f2f2; +} + +.layuimini-container { + border: 1px solid #f2f2f2; + border-radius: 5px; + background-color: #ffffff +} + +.layuimini-main { + margin: 10px 10px 10px 10px; +} + +/**必填红点 */ +.layuimini-form > .layui-form-item > .required:after { + content: '*'; + color: red; + position: absolute; + margin-left: 4px; + font-weight: bold; + line-height: 1.8em; + top: 6px; + right: 5px; +} + +.layuimini-form > .layui-form-item > .layui-form-label { + width: 120px !important; +} + +.layuimini-form > .layui-form-item > .layui-input-block { + margin-left: 150px !important; +} + + .layuimini-form > .layui-form-item > .layui-input-block > tip { + display: inline-block; + margin-top: 10px; + line-height: 10px; + font-size: 10px; + color: #a29c9c; + } + +/**搜索框*/ +.layuimini-container .table-search-fieldset { + margin: 0; + border: 1px solid #e6e6e6; + padding: 10px 20px 5px 20px; + color: #6b6b6b; +} + +/**自定义滚动条样式 */ +::-webkit-scrollbar { + width: 6px; + height: 6px +} + +::-webkit-scrollbar-track { + background-color: transparent; + -webkit-border-radius: 2em; + -moz-border-radius: 2em; + border-radius: 2em; +} + +::-webkit-scrollbar-thumb { + background-color: #9c9da0; + -webkit-border-radius: 2em; + -moz-border-radius: 2em; + border-radius: 2em +} diff --git a/WaterCloud.Web/wwwroot/css/report.css b/WaterCloud.Web/wwwroot/css/report.css new file mode 100644 index 0000000..0833fbc --- /dev/null +++ b/WaterCloud.Web/wwwroot/css/report.css @@ -0,0 +1,181 @@ +@charset "UTF-8"; +.layui-elem-quote { + margin-bottom: 10px; + padding: 15px; + padding-left: 15px; + line-height: 22px; + border-left: 5px solid #009688; + border-radius: 0 2px 2px 0; + background-color: #f2f2f2; +} +blockquote, body, button, dd, div, dl, dt, form, h1, h2, h3, h4, h5, h6, input, li, ol, p, pre, td, textarea, th, ul { + margin: 0; + margin-bottom: 0px; + padding: 0; + -webkit-tap-highlight-color: rgba(0,0,0,0); +} +blockquote, body, button, code, dd, div, dl, dt, fieldset, form, h1, h2, h3, h4, h5, h6, input, legend, li, ol, p, pre, table, td, textarea, th, ul { + margin: 0; + padding: 0; + font: 14px/normal "microsoft yahei","Times New Roman","宋体",Times,serif; + font-size: 14px; + line-height: normal; + letter-spacing: 1px; +} +.layui-col-space30 > * { + padding: 15px; +} +.layui-table { + width: 100%; + background-color: #fff; + color: #666; +} +.layui-table, .layui-table-view { + margin: 10px 0; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +.layui-table tr { + transition: all .3s; + -webkit-transition: all .3s; +} +.layui-table td, .layui-table th { + position: relative; + padding: 9px 15px; + min-height: 20px; + line-height: 20px; + font-size: 14px; +} +.layui-table td, .layui-table th, .layui-table-col-set, .layui-table-fixed-r, .layui-table-grid-down, .layui-table-header, .layui-table-page, .layui-table-tips-main, .layui-table-tool, .layui-table-total, .layui-table-view, .layui-table[lay-skin="line"], .layui-table[lay-skin="row"] { + border-width: 1px; + border-style: solid; + border-color: #e6e6e6; +} + + +body,main{ + width: 100%; + height: 100%; + background: url("/images/report/bg.jpg") no-repeat; + -webkit-background-size: 100% 100%; + background-size: 100% 100%; + color: #fff; + /*padding-bottom: 10px;*/ +} +main .md3,.md12,.md6{ + background: url("/images/report/border-bg.png") no-repeat; + -webkit-background-size: 100% 100%; + background-size: 100% 100%; +} +.layui-elem-quote{ + width: 45%; + padding-left: 25px; + background: url("/images/report/title-bg.png") no-repeat; + -webkit-background-size: 100% 100%; + background-size: 100% 100%; + border-left: none; + line-height: 0; +} +.md6 .layui-elem-quote{ + padding-left: 30px; +} +.layui-col-space10>*{ + padding: 0; +} + +.layui-row{ + display: flex; + justify-content: space-around; + flex-wrap: wrap; + margin: 10px 0; +} +.md3{ + width: 45%; + overflow: hidden; +} + +.layui-table td{ + border-color: #00feff; + text-align: center; +} +.layui-table tbody tr:hover{ + background: #223244; + color: #fff; +} +.title{ + font-size: 18px; +} +.b-title{ + width: 100%; + display: flex; + justify-content: center; + flex-wrap: wrap; + padding: 20px 0 0 0 !important; +} +.b-title .date{ + width: 100%; + display: flex; + justify-content: flex-end; +} +.date .topjui-row{ + width: 95%; + margin: 0 auto; + display: flex; + justify-content: flex-end; +} +.c-title{ + color: #00feff !important; + font-size: 24px; + text-align: center; + width: 100%; + line-height: 2; + background: url("/images/report/header-bg.png") no-repeat; + -webkit-background-size: 100% 100%; + background-size: 100% 100%; +} +.t-title{ + width: 40%; + height: 50px; +} +/*.t-left{*/ + /*background: url("../../topjui/images/report/t-left-bg.png") no-repeat;*/ + /*-webkit-background-size: 100% 100%;*/ + /*background-size: 100% 100%;*/ +/*}*/ +/*.t-right{*/ + /*background: url("/coalmine/topjui/images/report/t-right-bg.png") no-repeat;*/ + /*-webkit-background-size: 100% 100%;*/ + /*background-size: 100% 100%;*/ +/*}*/ +.layui-table thead tr{ + background: #07414e; +} +.layui-table tbody{ + background: rgba(2,11,18,0.5); +} +.layui-table tbody tr{ + background: rgba(0,0,0,0.5); +} +.layui-table tbody tr:nth-last-of-type(even){ + background:transparent; +} +div.box{ + width: 100%; + height: 280px; + overflow: hidden; +} +@media screen and (max-width:1250px){ + .md3,.md6{ + width: 94% !important; + margin: 0 auto; + } + .md12{ + width: 94% !important; + } + .c-title{ + font-size: 18px !important; + line-height: 1.5 !important; + } +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/css/smartscreen.css b/WaterCloud.Web/wwwroot/css/smartscreen.css new file mode 100644 index 0000000..fd6b7f6 --- /dev/null +++ b/WaterCloud.Web/wwwroot/css/smartscreen.css @@ -0,0 +1,646 @@ +@charset "utf-8"; +/* CSS Document */ +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box +} + +*, body { + padding: 0px; + margin: 0px; + color: #222; + font-family: "微软雅黑"; +} + +@font-face { + font-family: electronicFont; + src: url(../fonts/DS-DIGIT.TTF) +} + +body { + background: #000d4a url(../picture/digitization.jpg) center top; + background-size: cover; + -moz-background-size: cover; + color: #666; + font-size: .1rem; +} + +li { + list-style-type: none; +} + +table { +} + +i { + margin: 0px; + padding: 0px; + text-indent: 0px; +} + +img { + border: none; + max-width: 100%; +} + +a { + text-decoration: none; + color: #399bff; +} + + a.active, a:focus { + outline: none !important; + text-decoration: none; + } + +ol, ul, p, h1, h2, h3, h4, h5, h6 { + padding: 0; + margin: 0 +} + +a:hover { + color: #06c; + text-decoration: none !important +} + + +.clearfix:after, .clearfix:before { + display: table; + content: " " +} + +.clearfix:after { + clear: both +} + +.pulll_left { + float: left; +} + +.pulll_right { + float: right; +} +/*谷哥滚动条样式*/ + +::-webkit-scrollbar { + width: 5px; + height: 5px; + position: absolute +} + +::-webkit-scrollbar-thumb { + background-color: #5bc0de +} + +::-webkit-scrollbar-track { + background-color: #ddd +} + +/***/ +.canvas { + position: absolute; + width: 100%; + left: 0; + top: 0; + height: 99%; + z-index: 1; +} + +.allnav { + min-height: 200px; + height: 2.3rem +} + +.loading { + position: fixed; + left: 0; + top: 0; + font-size: 18px; + z-index: 100000000; + width: 100%; + height: 100%; + background: #1a1a1c; + text-align: center; +} + +.loadbox { + position: absolute; + width: 160px; + height: 150px; + color: #aaa; + left: 50%; + top: 50%; + margin-top: -100px; + margin-left: -75px; +} + + .loadbox img { + margin: 10px auto; + display: block; + width: 40px; + } + +.copyright { + background: rgba(19,31,64,.32); + border: 1px solid rgba(255,255,255,.05); + line-height: .5rem; + text-align: center; + padding-right: 15px; + bottom: 0; + color: rgba(255,255,255,.7); + font-size: .16rem; +} + +.head { + height: 1.05rem; + background: url(../picture/head_bg.png) no-repeat center center; + background-size: 100% 100%; + position: relative; + z-index: 100; +} + + .head h1 { + color: #fff; + text-align: center; + font-size: .4rem; + line-height: .8rem; + } + + .head h1 img { + width: 1.5rem; + display: inline-block; + vertical-align: middle; + margin-right: .2rem + } + +.weather { + position: absolute; + left: .3rem; + top: 0; + line-height: .75rem; +} + + .weather img { + width: .37rem; + display: inline-block; + vertical-align: middle; + } + + .weather span { + color: #fff; + font-size: .3rem; + padding-right: .1rem; + } +.mainbox { + padding: .1rem .1rem 0rem .1rem; +} + + .mainbox > ul { + } + + .mainbox > ul > li { + float: left; + padding: 0 .1rem + } + + .mainbox > ul > li { + width: 30% + } + + .mainbox > ul > li:nth-child(2) { + width: 40%; + padding: 0 + } + +.boxall { + border: 1px solid rgba(25,186,139,.17); + padding: 0 .2rem .4rem .15rem; + background: rgba(255,255,255,.04) url(../picture/line.png); + background-size: 100% auto; + position: relative; + margin-bottom: .15rem; + z-index: 10; +} + + .boxall:before, + .boxall:after { + position: absolute; + width: .1rem; + height: .1rem; + content: ""; + border-top: 2px solid #02a6b5; + top: 0; + } + + .boxall:before, .boxfoot:before { + border-left: 2px solid #02a6b5; + left: 0; + } + + .boxall:after, .boxfoot:after { + border-right: 2px solid #02a6b5; + right: 0; + } + +.alltitle { + font-size: .25rem; + color: #fff; + text-align: center; + line-height: .5rem; +} + +.boxfoot { + position: absolute; + bottom: 0; + width: 100%; + left: 0; +} + + .boxfoot:before, + .boxfoot:after { + position: absolute; + width: .1rem; + height: .1rem; + content: ""; + border-bottom: 2px solid #02a6b5; + bottom: 0; + } + +.bar { + background: rgba(101,132,226,.1); + padding: .15rem; +} + +.barbox li, .barbox2 li { + width: 50%; + text-align: center; + position: relative; + z-index: 100; +} + +.barbox:before, +.barbox:after { + position: absolute; + width: .3rem; + height: .1rem; + content: ""; +} + +.barbox:before { + border-left: 2px solid #02a6b5; + left: 0; + border-top: 2px solid #02a6b5; +} + +.barbox:after { + border-right: 2px solid #02a6b5; + right: 0; + bottom: 0; + border-bottom: 2px solid #02a6b5; +} + +.barbox li:first-child:before { + position: absolute; + content: ""; + height: 50%; + width: 1px; + background: rgba(255,255,255,.2); + right: 0; + top: 25%; +} + +.barbox { + border: 1px solid rgba(25,186,139,.17); + position: relative; +} + + .barbox li { + font-size: .7rem; + color: #ffeb7b; + padding: .05rem 0; + font-family: electronicFont; + font-weight: bold; + } + +.barbox2 li { + font-size: .31rem; + color: rgba(255,255,255,.7); + padding-top: .2rem; + padding-bottom: .4rem; +} + +.map { + position: relative; + height: 4.6rem; + z-index: 9; + min-height: 400px; +} + +.map4 { + width: 200%; + height: 7rem; + position: relative; + left: -50%; + top: 4%; + margin-top: .2rem; + z-index: 5; +} + +.map1, .map2, .map3 { + position: absolute; + opacity: .5 +} + +.map1 { + width: 5rem; + z-index: 2; + top: 0rem; + left: .8rem; + animation: myfirst2 15s infinite linear; +} + +.map2 { + width: 4.5rem; + top: 0.25rem; + left: 1.05rem; + z-index: 3; + opacity: 0.2; + animation: myfirst 10s infinite linear; +} + +.map3 { + width: 4rem; + top: 0.5rem; + left: 1.3rem; + z-index: 1; +} + + + + + +.tabs { + text-align: center; + padding: .1rem 0 0 0; +} + + .tabs a { + position: relative; + display: inline-block; + margin-left: 1px; + padding: .05rem .2rem; + color: #898989; + transition: all .3s ease-out 0s; + font-size: 14px; + } + + .tabs li { + display: inline-block; + } + + .tabs a:after { + position: absolute; + width: 1px; + height: 10px; + background-color: rgba(255,255,255,.1); + content: ''; + margin-left: 0; + right: -1px; + margin-top: 7px; + } + + .tabs li a.active { + border: 1px solid rgba(25,186,139,.17); + background: rgba(255,255,255,.05); + color: #fff; + } + +.tit02 { + text-align: center; + margin: .1rem 0; + position: relative +} + + .tit02 span { + border: 1px solid rgba(25,186,139,.17); + letter-spacing: 2px; + padding: .01rem .2rem; + background: rgba(255,255,255,.05); + font-size: .18rem; + color: #49bcf7; + } + + .tit02:before, .tit02:after { + position: absolute; + width: 26%; + height: 1px; + background: rgba(25,186,139,.2); + content: ""; + top: .12rem; + } + + .tit02:after { + right: 0; + } + + .tit02:before { + left: 0; + } + +.wrap { + height: 2.54rem; + overflow: hidden; +} + + .wrap li { + line-height: .42rem; + height: .42rem; + font-size: .18rem; + text-indent: .24rem; + margin-bottom: .1rem; + } + + .wrap li p { + border: 1px solid rgba(25,186,139,.17); + color: rgba(255,255,255,.6); + } + +.sy { + float: left; + width: 33%; + height: 95%; + margin-top: .25rem; +} + + +.adduser { + height: 1.5rem; + overflow: hidden; +} + + .adduser li { + height: .5rem; + } + + .adduser img { + width: .40rem; + border-radius: .5rem; + margin-right: .1rem; + display: inline-block; + vertical-align: middle; + } + + .adduser span { + line-height: .5rem; + font-size: .18rem; + color: rgba(255,255,255,.6); + } + +.sycm ul { + margin-left: -.5rem; + margin-right: -.5rem; + padding: .16rem 0; +} + +.sycm li { + float: left; + width: 33.33%; + text-align: center; + position: relative +} + + .sycm li:before { + position: absolute; + content: ""; + height: 30%; + width: 1px; + background: rgba(255,255,255,.1); + right: 0; + top: 15%; + } + + .sycm li:last-child:before { + width: 0; + } + + .sycm li h2 { + font-size: .3rem; + color: #c5ccff; + } + + .sycm li span { + font-size: .18rem; + color: #fff; + opacity: .5; + } + +@keyframes myfirst2 { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(359deg); + } +} + +@keyframes myfirst { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(-359deg); + } +} + + +/*Plugin CSS*/ +.str_wrap { + overflow: hidden; + width: 100%; + position: relative; + -moz-user-select: none; + -khtml-user-select: none; + user-select: none; + white-space: nowrap; +} + + +.str_move { + white-space: nowrap; + position: absolute; + top: 0; + left: 0; + cursor: move; +} + +.str_move_clone { + display: inline-block; + vertical-align: top; + position: absolute; + left: 100%; + top: 0; +} + +.str_vertical .str_move_clone { + left: 0; + top: 100%; +} + +.str_down .str_move_clone { + left: 0; + bottom: 100%; +} + +.str_vertical .str_move, +.str_down .str_move { + white-space: normal; + width: 100%; +} + +.str_static .str_move, +.no_drag .str_move, +.noStop .str_move { + cursor: inherit; +} + +.str_wrap img { + max-width: none !important; +} +@media screen and (max-width: 800px) { + + .weather { + display: none; + } + .map { + display: none; + } + body { + background: #000d4a; + } +} +.layuimini-site-mobile { + display: block !important; + position: absolute; + z-index: 100000; + top: 5px; + right: 5px; + width: 40px; + height: 40px; + line-height: 40px; + border-radius: 2px; + text-align: center; + background-color: rgba(0, 0, 0, .7); + color: #fff; + cursor: pointer; +} +.layui-icon { + color: white; + font-size: 16px; +} +body.demo.layui-layer-content { + background-color: #c00; + color: #fff; +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/css/soulTable.css b/WaterCloud.Web/wwwroot/css/soulTable.css new file mode 100644 index 0000000..b5f6ba1 --- /dev/null +++ b/WaterCloud.Web/wwwroot/css/soulTable.css @@ -0,0 +1,784 @@ +/** 自定义字体 **/ +/** 这里使用在线字体,如果需要离线包,请看 font/README.md **/ +@font-face { + font-family: 'soul-icon'; /* project id 677836 */ + src: url('../fonts/iconfont.eot'); + src: url('../fonts/iconfont.eot?#iefix') format('embedded-opentype'), url('../fonts/iconfont.woff2') format('woff2'), url('../fonts/iconfont.woff') format('woff'), url('../fonts/iconfont.ttf') format('truetype'), url('../fonts/iconfont.svg#iconfont') format('svg'); +} + +.soul-icon { + font-family:"soul-icon" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.soul-icon-filter:before { content: "\e60b"; } +.soul-icon-filter-asc:before { content: "\e768"; } +.soul-icon-filter-desc:before { content: "\e767"; } +.soul-icon-asc:before { content: "\e6af"; } +.soul-icon-desc:before { content: "\e6ae"; } +.soul-icon-all-check:before { content: "\e670"; } +.soul-icon-invert-check:before { content: "\e614"; } +.soul-icon-fold:before { content: "\e760"; } +.soul-icon-unfold:before { content: "\e611"; } +.soul-icon-delete:before { content: "\e600"; } +.soul-icon-download:before { content: "\e601"; } +.soul-icon-drop-list:before { content: "\e6a3"; } +.soul-icon-query:before { content: "\e66d"; } +/* 全选*/ +.soul-icon-quanxuan:before { content: "\e623"; } +.soul-icon-qingkong:before { content: "\e63e"; } +.soul-icon-autoColumnWidth +:before { content: "\e614"; } + +/*最大化*/ +.soul-icon-min:before { content: "\e656"; } +.soul-icon-max:before { content: "\e61b"; } + + +/* 配色方案*/ +.layui-red { + color: #FF5722 +} +.layui-orange { + color: #FFB800 +} +.layui-green { + color: #009688 +} +.layui-cyan { + color: #2F4056 +} +.layui-blue { + color: #1E9FFF +} +.layui-black { + color: #393D49 +} +.layui-gray { + color: #eee +} +.layui-firebrick { + color: firebrick; +} +.layui-deeppink { + color: deeppink; +} +.layui-blueviolet { + color: blueviolet; +} + +.soul-condition [class*="layui-col-"] { + margin-top: 10px; +} +/* 表格排序样式*/ +.soul-edge { + display: inline-block; + width: 0; + height: 0; + border-width: 6px; + border-style: dashed; + border-color: transparent; + overflow: hidden +} +.soul-table-sort { + width: 10px; + height: 20px; + margin-left: 5px; + cursor: pointer !important; + position: relative; + display: inline-block; +} + +.soul-table-sort .soul-edge { + position: absolute; + left: 5px; + border-width: 5px +} + +.soul-table-sort .soul-table-sort-asc { + top: 10px; + border-top: none; + border-bottom-style: solid; + border-bottom-color: #b2b2b2 +} + +.soul-table-sort .soul-table-sort-asc:hover { + border-bottom-color: #666 +} + +.soul-table-sort .soul-table-sort-desc { + bottom: -2px; + border-bottom: none; + border-top-style: solid; + border-top-color: #b2b2b2 +} + +.soul-table-sort .soul-table-sort-desc:hover { + border-top-color: #666 +} + +.soul-table-sort[soul-sort=asc] .soul-table-sort-asc { + border-bottom-color: #000 +} + +.soul-table-sort[soul-sort=desc] .soul-table-sort-desc { + border-top-color: #000 +} + +.multiOption { + display: inline-block; + padding: 0 5px; + cursor: pointer; + color: #999; +} +/*表格筛选*/ +.soul-table-filter { + line-height: 20px; + color: #b2b2b2; + cursor: pointer; + margin-left: 5px; +} +.soul-table-filter .soul-icon-filter-asc,.soul-table-filter .soul-icon-filter-desc { + display: none; +} +.soul-table-filter[lay-sort="asc"] .soul-icon-filter-asc{ + display: block; + color: #000000; +} +.soul-table-filter[lay-sort="asc"] .soul-icon-filter,.soul-table-filter[lay-sort="asc"] .soul-icon-filter-desc{ + display: none; +} + +.soul-table-filter[lay-sort="desc"] .soul-icon-filter-desc{ + display: block; + color: #000000; +} +.soul-table-filter[lay-sort="desc"] .soul-icon-filter,.soul-table-filter[lay-sort="desc"] .soul-icon-filter-asc{ + display: none; +} +.soul-table-filter[soul-filter="true"] i { + color: #009688!important; +} + + +[id^=main-list], [id^=soul-columns], [id^=soul-dropList], [id^=soul-condition], [id^=soul-bf-prefix], [id^=soul-bf-column], [id^=soul-bf-type], [id^=soul-bf-cond2] { + display: inline-block; + position: absolute; + z-index: 2147483647; + background-color: white; + max-height: 200px; + min-width: 160px; + max-width: 300px; + overflow-y: auto; + border: 1px solid #e6e6e6; + border-radius: 5px; + box-shadow: 2px 2px 4px -2px rgba(0,0,0,.2); +} +[id^=main-list] { + max-height: initial; +} +[id^=soul-condition] { + overflow-y: visible; + max-height: initial; + min-width: 285px; + padding: 5px; +} +[id^=soul-condition] .layui-laydate-header { + padding: 4px 70px 5px +} +[id^=soul-condition] hr{ + margin: 5px 0; +} +[id^=soul-condition].soul-bf{ + min-width: 150px; +} +[id^=soul-filter-list] ul li { + padding: 3px 10px; + cursor: pointer; +} +[id^=soul-filter-list] ul li:hover { + background-color: deepskyblue; +} +[id^=soul-filter-list] i.layui-icon { + display: inline-block; + width: 16px; +} +[id^=soul-dropList] ul { + border: 0; + max-height: 116px; + overflow-y: auto; +} +[id^=soul-dropList] ul li, [id^=soul-filter-list] [id^=soul-columns]>li{ + padding: 2px 10px; +} +[id^=soul-dropList] .check { + padding: 5px 10px; +} +.filter-search { + padding: 5px 10px 0 10px; +} +[id^=soul-condition] .layui-inline { + width: 100px; +} +[id^=soul-condition] table.condition-table tr>td { + padding: 0 3px; +} +[id^=soul-condition] table.condition-table tr>td:first-child { + min-width: 60px; +} +[id^=soul-condition] .layui-form-switch { + background-color: #1E9FFF; + border: 1px solid #1E9FFF; + width: 35px; + margin-top: 0px; +} +[id^=soul-condition] .layui-form-switch.layui-form-onswitch { + background-color: #5FB878; + border: 1px solid #5FB878; +} +[id^=soul-condition] .layui-form-switch em { + color: #fff!important; +} +[id^=soul-condition] .layui-form-switch i { + background-color: #fff; +} +[data-type^=date][class$=Condition] { + width: 273px; +} +/*表格筛选*/ +[id^=soul-condition] > div { + width: 270px; +} + +.soul-condition-title { + text-align: center; + font-weight: bolder; +} + +/*底部筛选*/ +.soul-bottom-contion { + height: 31px; + /*line-height: 29px;*/ + border-top: solid 1px #e6e6e6; +} +.soul-bottom-contion .condition-items { + display: inline-block; + width: calc(100vw - 100px); + height: 30px; + float: left; + overflow: hidden; + white-space: nowrap; +} +.soul-bottom-contion .condition-item>div { + display: inline-block; + height: 28px; + line-height: 28px; + cursor: pointer; +} +.soul-bottom-contion .condition-items .condition-item>div[class^='item-']:hover{ + text-decoration: underline; +} +.soul-bottom-contion .condition-items .condition-item{ + padding: 0 10px; + margin: 0 2px; + font-weight: bold; + border: solid 1px darkslateblue; + border-radius: 10px; + display: inline-block; + height: 28px; + position: relative; +} +.soul-bottom-contion .editCondtion { + height: 30px; + float: right; +} +.soul-bottom-contion .item-value { + min-width: 20px; + display: inline-block; +} +.soul-bottom-contion .editCondtion a { + border: hidden; + border-left: solid 1px #e6e6e6; + height: 28px; + line-height: 29px; +} +.soul-bottom-contion .condition-items .condition-item .condition-item-close { + position: absolute; + cursor: pointer; + margin-top: -8px; +} +.soul-bottom-contion .condition-items>.condition-item>.condition-item-close { + margin-top: -2px; +} +.soul-bottom-contion .condition-items .condition-item .condition-item-close:hover{ + color: red +} +.soul-bottom-contion .condition-items .condition-item .condition-item-close:before { + background: white; + border-radius: 10px; +} +.soul-edit-out { + padding: 10px; +} +[id^=soul-bf] li { + padding: 0px 10px; + height: 22px; + line-height: 22px; + color: #000; + cursor: pointer; +} +[id^=soul-bf] li.soul-bf-selected { + background-color: deepskyblue; +} +[id^=soul-bf] li:hover { + background-color: deepskyblue; +} +.soul-edit-out .tempValue { + height: 25px; +} +.soul-bf-condition-value { + display: inline; + width: 100px; +} +/*子表格*/ +.layui-table tbody tr.noHover:hover { + background-color: white; +} + +/*编辑筛选*/ +.soul-edit-out .layui-form-radio { + margin: 0; +} +.soul-edit-out ul li > div { + display: inline-block; + margin-right: 10px; + height: 25px; + vertical-align: top; + cursor: pointer; +} +.soul-edit-out ul.group { + padding-left: 50px; +} +.soul-edit-out ul.group.line { + border-left: 1px dashed grey; +} +.soul-edit-out ul li { + line-height: 25px; +} +.soul-edit-out table { + display: inline-block; +} +.soul-edit-out table td[data-type='top'] { + width: 12px; + height: 12px; + border-left: dashed 1px grey; + border-bottom: dashed 1px grey; +} +.soul-edit-out table td[data-type='bottom'] { + width: 12px; + height: 12px; + border-left: dashed 1px grey; +} +.soul-edit-out li.last>div>table td[data-type='bottom'] { + border-left: none; +} +.soul-edit-out .layui-form-switch { + background-color: #1E9FFF; + border: 1px solid #1E9FFF; + width: 35px; + margin-top: 0px; +} +.soul-edit-out .layui-form-switch em { + color: #fff!important; +} +.soul-edit-out .layui-form-switch i { + background-color: #fff; +} +.soul-edit-out .layui-form-switch.layui-form-onswitch { + background-color: #5FB878; + border: 1px solid #5FB878; +} +.soul-edit-out .delete-item { + display: none; +} +.soul-edit-out li:hover>.delete-item { + display: inline-block; +} + +/* 拖拽相关 */ +#column-remove { + position: absolute; + z-index: 2147483647; +} +.layui-table-box.no-left-border td.isDrag, .layui-table-box.no-left-border th.isDrag { + border-left: inherit!important; +} +.soul-drag-bar { + position: absolute; + top: 100px; + z-index: 200; + left: 50%; + font-weight: 900; + color: white; + box-shadow: 0 1px 20px rgba(0,0,0,.15); + text-align: center; + transform: translateX(100vw); + /*transition: transform .3s;*/ +} +.soul-drag-bar.active { + transform: translateX(-98px); +} +.soul-drag-bar > div { + display: inline-block; + padding: 10px; + cursor: crosshair; + width: 62px; + background-color: rgba(0, 150, 136, 0.5); +} +.soul-drag-bar > div.active, .soul-drag-bar[data-type='left']>div[data-type='left'], .soul-drag-bar[data-type='right']>div[data-type='right'], .soul-drag-bar[data-type='none']>div[data-type='none'] { + background-color: rgb(0, 150, 136); +} + +/* 动画 */ +.animated { + -webkit-animation-duration: 1s; + -moz-animation-duration: 1s; + -o-animation-duration: 1s; + animation-duration: 1s; + -webkit-animation-fill-mode: both; + -moz-animation-fill-mode: both; + -o-animation-fill-mode: both; + animation-fill-mode: both; +} +@-moz-keyframes fadeInLeft { + 0% { + opacity: 0; + -moz-transform: translateX(-20px); + } + 100% { + opacity: 1; + -moz-transform: translateX(0); + } +} + +@-o-keyframes fadeInLeft { + 0% { + opacity: 0; + -o-transform: translateX(-20px); + } + 100% { + opacity: 1; + -o-transform: translateX(0); + } +} + +@keyframes fadeInLeft { + 0% { + opacity: 0; + transform: translateX(-20px); + } + 100% { + opacity: 1; + transform: translateX(0); + } +} + +.animated.fadeInLeft { + -webkit-animation-name: fadeInLeft; + -moz-animation-name: fadeInLeft; + -o-animation-name: fadeInLeft; + animation-name: fadeInLeft; +} + +@-webkit-keyframes fadeOutLeft { + 0% { + opacity: 1; + -webkit-transform: translateX(0); + } + 100% { + opacity: 0; + -webkit-transform: translateX(-20px); + } +} + +@-moz-keyframes fadeOutLeft { + 0% { + opacity: 1; + -moz-transform: translateX(0); + } + 100% { + opacity: 0; + -moz-transform: translateX(-20px); + } +} + +@-o-keyframes fadeOutLeft { + 0% { + opacity: 1; + -o-transform: translateX(0); + } + 100% { + opacity: 0; + -o-transform: translateX(-20px); + } +} + +@keyframes fadeOutLeft { + 0% { + opacity: 1; + transform: translateX(0); + } + 100% { + opacity: 0; + transform: translateX(-20px); + } +} + +.animated.fadeOutLeft { + -webkit-animation-name: fadeOutLeft; + -moz-animation-name: fadeOutLeft; + -o-animation-name: fadeOutLeft; + animation-name: fadeOutLeft; +} + +@-webkit-keyframes fadeInRight { + 0% { + opacity: 0; + -webkit-transform: translateX(20px); + } + 100% { + opacity: 1; + -webkit-transform: translateX(0); + } +} + +@-moz-keyframes fadeInRight { + 0% { + opacity: 0; + -moz-transform: translateX(20px); + } + 100% { + opacity: 1; + -moz-transform: translateX(0); + } +} + +@-o-keyframes fadeInRight { + 0% { + opacity: 0; + -o-transform: translateX(20px); + } + 100% { + opacity: 1; + -o-transform: translateX(0); + } +} + +@keyframes fadeInRight { + 0% { + opacity: 0; + transform: translateX(20px); + } + 100% { + opacity: 1; + transform: translateX(0); + } +} + +.animated.fadeInRight { + -webkit-animation-name: fadeInRight; + -moz-animation-name: fadeInRight; + -o-animation-name: fadeInRight; + animation-name: fadeInRight; +} + +@-webkit-keyframes fadeInUp { + 0% { + opacity: 0; + -webkit-transform: translateY(20px); + } + 100% { + opacity: 1; + -webkit-transform: translateY(0); + } +} + +@-moz-keyframes fadeInUp { + 0% { + opacity: 0; + -moz-transform: translateY(20px); + } + 100% { + opacity: 1; + -moz-transform: translateY(0); + } +} + +@-o-keyframes fadeInUp { + 0% { + opacity: 0; + -o-transform: translateY(20px); + } + 100% { + opacity: 1; + -o-transform: translateY(0); + } +} + +@keyframes fadeInUp { + 0% { + opacity: 0; + transform: translateY(20px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} + +.animated.fadeInUp { + -webkit-animation-name: fadeInUp; + -moz-animation-name: fadeInUp; + -o-animation-name: fadeInUp; + animation-name: fadeInUp; +} + +@-webkit-keyframes fadeOutDown { + 0% { + opacity: 1; + -webkit-transform: translateY(0); + } + 100% { + opacity: 0; + -webkit-transform: translateY(20px); + } +} + +@-moz-keyframes fadeOutDown { + 0% { + opacity: 1; + -moz-transform: translateY(0); + } + 100% { + opacity: 0; + -moz-transform: translateY(20px); + } +} + +@-o-keyframes fadeOutDown { + 0% { + opacity: 1; + -o-transform: translateY(0); + } + 100% { + opacity: 0; + -o-transform: translateY(20px); + } +} + +@keyframes fadeOutDown { + 0% { + opacity: 1; + transform: translateY(0); + } + 100% { + opacity: 0; + transform: translateY(20px); + } +} + +.animated.fadeOutDown { + -webkit-animation-name: fadeOutDown; + -moz-animation-name: fadeOutDown; + -o-animation-name: fadeOutDown; + animation-name: fadeOutDown; +} + +#soul-table-contextmenu-wrapper { + width: 0; +} +.soul-table-contextmenu { + position: absolute; + z-index: 2147483647; + list-style: none; + margin: 0; + padding: 0; + border: 1px solid #ebeef5; + box-shadow: 2px 2px 4px -2px rgba(0,0,0,.2); + background: white; +} +.soul-table-contextmenu li { + line-height: 26px; + padding: 0 30px; + cursor: pointer; + word-break: keep-all; +} +.soul-table-contextmenu li:hover { + background: #c5c5c5; +} +.soul-table-contextmenu li i.prefixIcon{ + position: absolute; + left: 8px; +} + +.soul-table-contextmenu li i.endIcon{ + position: absolute; + right: 8px; +} + +/*拖拽相关*/ +.layui-table-sort-invalid { + width: 10px; + height: 20px; + margin-left: 5px; + cursor: pointer!important; +} +.layui-table-sort-invalid .layui-table-sort-asc { + top: 3px; + border-top: none; + border-bottom-style: solid; + border-bottom-color: #b2b2b2; +} +.layui-table-sort-invalid .layui-edge { + position: absolute; + left: 5px; + border-width: 5px; +} +.layui-table-sort-invalid .layui-table-sort-desc { + bottom: 5px; + border-bottom: none; + border-top-style: solid; + border-top-color: #b2b2b2; +} +.layui-table-sort-invalid .layui-edge { + position: absolute; + left: 5px; + border-width: 5px; +} +.noselect { + + -webkit-touch-callout: none; /* iOS Safari */ + + -webkit-user-select: none; /* Chrome/Safari/Opera */ + + -khtml-user-select: none; /* Konqueror */ + + -moz-user-select: none; /* Firefox */ + + -ms-user-select: none; /* Internet Explorer/Edge */ + + user-select: none; /* Non-prefixed version, currently */ + +} +/* 固定列滚动 */ +.soul-fixed-scroll::-webkit-scrollbar{ + display: none +} +.soul-fixed-scroll{ + overflow-y: auto!important; + -ms-overflow-style:none; + overflow:-moz-scrollbars-none; +} diff --git a/WaterCloud.Web/wwwroot/css/stepcss.css b/WaterCloud.Web/wwwroot/css/stepcss.css new file mode 100644 index 0000000..a4a4cce --- /dev/null +++ b/WaterCloud.Web/wwwroot/css/stepcss.css @@ -0,0 +1,36 @@ +.layui-form-label { + float: left; + display: block; + padding: 9px 15px; + width: 60px; + font-weight: 400; + line-height: 20px; + text-align: right; +} + +.lay-step { + font-size: 0; + width: 400px; + margin: 0 auto; + max-width: 100%; + padding-left: 30px; +} + +.layui-table-view { + margin-left: 30px; + margin-right: 10px; +} + +.layui-input-block { + margin-left: 90px; + min-height: 36px; + margin-right: 10px; +} + +.layui-card > .layui-card-body { + position: relative; + padding: 10px 15px; + line-height: 24px; + overflow: auto; + height: 300px; +} diff --git a/WaterCloud.Web/wwwroot/css/themes/default.css b/WaterCloud.Web/wwwroot/css/themes/default.css new file mode 100644 index 0000000..6d29c7f --- /dev/null +++ b/WaterCloud.Web/wwwroot/css/themes/default.css @@ -0,0 +1,95 @@ +/*头部右侧背景色 headerRightBg */ +.layui-layout-admin .layui-header { + background-color: #2D8CF0 !important; +} + + /*头部右侧选中背景色 headerRightBgThis */ + .layui-layout-admin .layui-header .layuimini-header-content > ul > .layui-nav-item.layui-this, .layuimini-tool i:hover { + background-color: #0069b7 !important; + } + + /*头部右侧字体颜色 headerRightColor */ + .layui-layout-admin .layui-header .layui-nav .layui-nav-item a { + color: #fafafa; + } + + /**头部右侧下拉字体颜色 headerRightChildColor */ + .layui-layout-admin .layui-header .layui-nav .layui-nav-item .layui-nav-child a { + color: #676767 !important; + } + +/*头部右侧鼠标选中 headerRightColorThis */ +.layui-header .layuimini-menu-header-pc.layui-nav .layui-nav-item a:hover, .layui-header .layuimini-header-menu.layuimini-pc-show.layui-nav .layui-this a { + color: #ffffff !important; +} + +/*头部右侧更多下拉颜色 headerRightNavMore */ +.layui-header .layui-nav .layui-nav-more { + border-top-color: #fafafa !important; +} + +/*头部右侧更多下拉颜色 headerRightNavMore */ +.layui-header .layui-nav .layui-nav-mored, .layui-header .layui-nav-itemed > a .layui-nav-more { + border-color: transparent transparent #fafafa !important; +} + +/**头部右侧更多下拉配置色 headerRightNavMoreBg headerRightNavMoreColor */ +.layui-header .layui-nav .layui-nav-child dd.layui-this a, .layui-header .layui-nav-child dd.layui-this, .layui-layout-admin .layui-header .layui-nav .layui-nav-item .layui-nav-child .layui-this a { + background-color: #0069b7 !important; + color: #ffffff !important; +} + +/*头部缩放按钮样式 headerRightToolColor */ +.layui-layout-admin .layui-header .layuimini-tool i { + color: #bbe3df; +} + +/*logo背景颜色 headerLogoBg */ +.layui-layout-admin .layuimini-logo { + background-color: #0069b7 !important; +} + + /*logo字体颜色 headerLogoColor */ + .layui-layout-admin .layuimini-logo h1 { + color: #ffffff; + } + +/*左侧菜单更多下拉样式 leftMenuNavMore */ +.layuimini-menu-left .layui-nav .layui-nav-more, .layuimini-menu-left-zoom.layui-nav .layui-nav-more { + border-top-color: #ffffff; +} + +/*左侧菜单更多下拉样式 leftMenuNavMore */ +.layuimini-menu-left .layui-nav .layui-nav-mored, .layuimini-menu-left .layui-nav-itemed > a .layui-nav-more, .layuimini-menu-left-zoom.layui-nav .layui-nav-mored, .layuimini-menu-left-zoom.layui-nav-itemed > a .layui-nav-more { + border-color: transparent transparent #ffffff !important; +} + +/*左侧菜单背景 leftMenuBg */ +.layui-side.layui-bg-black, .layui-side.layui-bg-black > .layuimini-menu-left > ul, .layuimini-menu-left-zoom > ul { + background-color: #28333E !important; +} + +/*左侧菜单选中背景 leftMenuBgThis */ +.layuimini-menu-left .layui-nav-tree .layui-this, .layuimini-menu-left .layui-nav-tree .layui-this > a, .layuimini-menu-left .layui-nav-tree .layui-nav-child dd.layui-this, .layuimini-menu-left .layui-nav-tree .layui-nav-child dd.layui-this a, .layuimini-menu-left-zoom.layui-nav-tree .layui-this, .layuimini-menu-left-zoom.layui-nav-tree .layui-this > a, .layuimini-menu-left-zoom.layui-nav-tree .layui-nav-child dd.layui-this, .layuimini-menu-left-zoom.layui-nav-tree .layui-nav-child dd.layui-this a { + background-color: #2D8CF0 !important +} + +/*左侧菜单子菜单背景 leftMenuChildBg */ +.layuimini-menu-left .layui-nav-itemed > .layui-nav-child { + background-color: rgba(0,0,0,.3) !important; +} + +/*左侧菜单字体颜色 leftMenuColor */ +.layuimini-menu-left .layui-nav .layui-nav-item a, .layuimini-menu-left-zoom.layui-nav .layui-nav-item a { + color: #ffffff !important; +} + + /*左侧菜单选中字体颜色 leftMenuColorThis */ + .layuimini-menu-left .layui-nav .layui-nav-item a:hover, .layuimini-menu-left .layui-nav .layui-this a, .layuimini-menu-left-zoom.layui-nav .layui-nav-item a:hover, .layuimini-menu-left-zoom.layui-nav .layui-this a { + color: #ffffff !important; + } + +/**tab选项卡选中颜色 tabActiveColor */ +.layuimini-tab .layui-tab-title .layui-this .layuimini-tab-active { + background-color: #2d8cf0; +} diff --git a/WaterCloud.Web/wwwroot/css/watercloud.css b/WaterCloud.Web/wwwroot/css/watercloud.css new file mode 100644 index 0000000..c42ef59 --- /dev/null +++ b/WaterCloud.Web/wwwroot/css/watercloud.css @@ -0,0 +1,271 @@ +body { + margin: 5px 5px 5px 5px; + background: #f2f2f2; +} +.form-group-bottom { + position: fixed; + left: 0; + right: 0; + bottom: 0; + padding: 5px 5px; + background-color: #fff; + box-shadow: 0 -1px 2px 0 rgba(0, 0, 0, .05); + z-index:1; +} +.text-right { + text-align:right; +} +.form-bottom-button { + padding-bottom: 30px; +} +/*.layui-table-page { + background-color: #F0F0F0; + z-index: 99999; + position: fixed; + bottom: 0; +}*/ + +/*.layui-table-box { + margin-bottom: 30px; +}*/ + +.layui-form-item { + margin-bottom: 5px; + clear:both; +} +.error-page { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + text-align: center; +} + +.error-page-img { + max-width: 100%; + max-height: 300px; +} + +.error-page-info { + display: inline-block; + text-align: center; + vertical-align: middle; + padding-left: 30px; +} + + .error-page-info h1 { + color: #434e59; + font-size: 72px; + font-weight: 600; + margin-bottom: 10px; + } + +.error-page-info-desc { + color: #777; + font-size: 20px; + line-height: 28px; + margin-bottom: 16px; +} +.layui-btn-sm { + height: 30px; + line-height: 30px; + padding: 0 8px; + font-size: 11px; +} +.layui-btn-container .layui-btn { + margin-right: 5px; + margin-bottom: 5px; +} +.layui-table-tool > .layui-table-tool-temp { + padding-right: 119px; + display: inline-block; +} +.layui-table-tool .layui-table-tool-self > div:not(.layui-inline) .layui-table-tool-temp { + padding-right: 0px; +} +@media screen and (max-width: 450px) { + .layui-form-item .layui-inline { + margin-bottom: 5px; + margin-right: 10px; + clear:none; + } +} +@media screen and (max-width: 550px) { + .layui-laypage-default > .layui-laypage-skip { + display: none; + } +} +@media screen and (max-width: 380px) { + .layui-laypage-default > .layui-laypage-limits { + display: none; + } +} +.layui-card .table-search-fieldset { + margin: 0; + border: 1px solid #e6e6e6; + padding: 10px 20px 5px 20px; + color: #6b6b6b; +} +.scroll-wrapper { + -webkit-overflow-scrolling: touch; + overflow-y: scroll; +} +.layui-upload-img { + width: 100px; + height: 100px; + margin: 0 10px 10px 0; +} +/*轮播*/ +.layui-carousel > [carousel-item] { + overflow: visible; +} + + .layui-carousel > [carousel-item] > * { + height: auto; + } + +.layui-carousel-ind { + margin-top: -20px; + top: auto; + bottom: 10px; +} +/*表格单元格自动换行*/ +/*.layui-table-cell { + height: auto !important; + white-space: normal; + word-break: break-all; +}*/ +/**必填红点 */ +.layui-tab-item > .layui-form-item .required:after { + content: '*'; + color: red; + position: absolute; + margin-left: 4px; + font-weight: bold; + line-height: 1.8em; + top: 6px; + right: 5px; +} +/**必填红点 */ +.layui-tab-item > .layui-form-item > .layui-inline .required:after { + content: '*'; + color: red; + position: absolute; + margin-left: 4px; + font-weight: bold; + line-height: 1.8em; + top: 6px; + right: 5px; +} +/**必填红点 */ +.layui-form-item .required:after { + content: '*'; + color: red; + position: absolute; + margin-left: 4px; + font-weight: bold; + line-height: 1.8em; + top: 6px; + right: 5px; +} +.layui-form-selectup dl { + top: 42px; + bottom: unset; +} +.layui-table-tool .layui-btn-container { + margin-bottom:0px; +} +.layui-form-item .layui-inline { + margin-bottom: 5px; + margin-right: 5px; +} +.layuimini-container .table-search-fieldset { + margin: 0; + border: 1px solid #e6e6e6; + padding: 10px 10px 5px 10px; + color: #6b6b6b; +} +@media screen and (max-width: 450px) { + .layui-form-item .layui-form-label { + text-overflow: ellipsis; + overflow: hidden; + white-space: unset; + } +} + +.layui-table-tool-self { + position: absolute; + right: 10px; + top: 10px; +} +.layui-table-tool .layui-inline[lay-event] { + position: relative; + color: #333; + width: 30px; + height: 30px; + text-align: center; + margin-left: 5px; + padding: unset; + line-height: 30px; + display: inline-block; + border: 1px solid #ccc; + box-sizing: border-box; + vertical-align: middle; + -webkit-transition: .3s all; + transition: .3s all; + cursor: pointer; +} +.layui-table-tool .layui-table-tool-self .layui-inline[lay-event] { + margin: 0 0 0 5px; +} +.layuimini-form > .layui-form-item .layui-form-label { + width: 80px !important; +} +.layuimini-form > .layui-form-item .layui-input-block { + margin-left: 110px !important; +} +.layuimini-form > .layui-form-item > .layui-form-label { + width: 90px !important; +} + +.layuimini-form > .layui-form-item > .layui-input-block { + margin-left: 120px !important; +} +/*chrome滚动条*/ +::-webkit-scrollbar-track-piece { + -webkit-border-radius: 0; +} +.layui-laypage .layui-laypage-skip { + height: 30px; + line-height: 30px; + color: black; +} + +.layui-laypage .layui-laypage-curr .layui-laypage-em { + position: absolute; + left: -1px; + top: -1px; + padding: 1px; + width: 100%; + height: 100%; + background-color: #2D8CF0; +} +.layui-table th, .layui-table td, .layui-table[lay-skin="line"], .layui-table[lay-skin="row"], .layui-table-view, .layui-table-tool, .layui-table-header, .layui-table-col-set, .layui-table-total, .layui-table-page, .layui-table-fixed-r, .layui-table-tips-main, .layui-table-grid-down { + border-color: #e6e6e6; +} + .layui-table thead tr, .layui-table-header, .layui-table-tool, .layui-table-total, .layui-table-total tr, .layui-table-patch, .layui-table-mend, .layui-table tbody tr:hover, .layui-table-hover, .layui-table-click { + background-color: #f2f2f2; + } +.layui-form-pane .layui-form-label { + background-color: #f2f2f2; +} +.layui-disabled, .layui-disabled:hover { + color: rgba(0,0,0,.85) !important; + cursor: not-allowed !important; +} +.layui-checkbox-disabled span { + background-color: #d2d2d2 !important; +} +.layui-btn + .layui-btn { + margin-left: 5px; +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/file/PrintApp.zip b/WaterCloud.Web/wwwroot/file/PrintApp.zip new file mode 100644 index 0000000..f77322c Binary files /dev/null and b/WaterCloud.Web/wwwroot/file/PrintApp.zip differ diff --git a/WaterCloud.Web/wwwroot/file/Server.xml b/WaterCloud.Web/wwwroot/file/Server.xml new file mode 100644 index 0000000..12dff02 --- /dev/null +++ b/WaterCloud.Web/wwwroot/file/Server.xml @@ -0,0 +1,6 @@ + + + 1.0.0.0 + http://106.75.169.226:5000/file/PrintApp.zip + false + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/file/打印组件交互手册.docx b/WaterCloud.Web/wwwroot/file/打印组件交互手册.docx new file mode 100644 index 0000000..50322ff Binary files /dev/null and b/WaterCloud.Web/wwwroot/file/打印组件交互手册.docx differ diff --git a/WaterCloud.Web/wwwroot/fonts/DS-DIGIT.TTF b/WaterCloud.Web/wwwroot/fonts/DS-DIGIT.TTF new file mode 100644 index 0000000..65642f9 Binary files /dev/null and b/WaterCloud.Web/wwwroot/fonts/DS-DIGIT.TTF differ diff --git a/WaterCloud.Web/wwwroot/fonts/iconfont.eot b/WaterCloud.Web/wwwroot/fonts/iconfont.eot new file mode 100644 index 0000000..f61552c Binary files /dev/null and b/WaterCloud.Web/wwwroot/fonts/iconfont.eot differ diff --git a/WaterCloud.Web/wwwroot/fonts/iconfont.svg b/WaterCloud.Web/wwwroot/fonts/iconfont.svg new file mode 100644 index 0000000..62cc50e --- /dev/null +++ b/WaterCloud.Web/wwwroot/fonts/iconfont.svg @@ -0,0 +1,92 @@ + + + + + +Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WaterCloud.Web/wwwroot/fonts/iconfont.ttf b/WaterCloud.Web/wwwroot/fonts/iconfont.ttf new file mode 100644 index 0000000..3f81d16 Binary files /dev/null and b/WaterCloud.Web/wwwroot/fonts/iconfont.ttf differ diff --git a/WaterCloud.Web/wwwroot/fonts/iconfont.woff b/WaterCloud.Web/wwwroot/fonts/iconfont.woff new file mode 100644 index 0000000..af51392 Binary files /dev/null and b/WaterCloud.Web/wwwroot/fonts/iconfont.woff differ diff --git a/WaterCloud.Web/wwwroot/fonts/iconfont.woff2 b/WaterCloud.Web/wwwroot/fonts/iconfont.woff2 new file mode 100644 index 0000000..20f7357 Binary files /dev/null and b/WaterCloud.Web/wwwroot/fonts/iconfont.woff2 differ diff --git a/WaterCloud.Web/wwwroot/fonts/simsun.ttc b/WaterCloud.Web/wwwroot/fonts/simsun.ttc new file mode 100644 index 0000000..5f22ce3 Binary files /dev/null and b/WaterCloud.Web/wwwroot/fonts/simsun.ttc differ diff --git a/WaterCloud.Web/wwwroot/form/FormTest.html b/WaterCloud.Web/wwwroot/form/FormTest.html new file mode 100644 index 0000000..16f2b31 --- /dev/null +++ b/WaterCloud.Web/wwwroot/form/FormTest.html @@ -0,0 +1,115 @@ +
    +
    + +
    + + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +

    +
    + + +
    +
    +
    + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/icon/favicon.ico b/WaterCloud.Web/wwwroot/icon/favicon.ico new file mode 100644 index 0000000..ed730ee Binary files /dev/null and b/WaterCloud.Web/wwwroot/icon/favicon.ico differ diff --git a/WaterCloud.Web/wwwroot/icon/local/20250304/202503041153174976.jpg b/WaterCloud.Web/wwwroot/icon/local/20250304/202503041153174976.jpg new file mode 100644 index 0000000..35f7f6e Binary files /dev/null and b/WaterCloud.Web/wwwroot/icon/local/20250304/202503041153174976.jpg differ diff --git a/WaterCloud.Web/wwwroot/icon/local/20250305/202503051635367124.jpg b/WaterCloud.Web/wwwroot/icon/local/20250305/202503051635367124.jpg new file mode 100644 index 0000000..35f7f6e Binary files /dev/null and b/WaterCloud.Web/wwwroot/icon/local/20250305/202503051635367124.jpg differ diff --git a/WaterCloud.Web/wwwroot/icon/local/20250305/202503051635555159.jpg b/WaterCloud.Web/wwwroot/icon/local/20250305/202503051635555159.jpg new file mode 100644 index 0000000..35f7f6e Binary files /dev/null and b/WaterCloud.Web/wwwroot/icon/local/20250305/202503051635555159.jpg differ diff --git a/WaterCloud.Web/wwwroot/images/403.svg b/WaterCloud.Web/wwwroot/images/403.svg new file mode 100644 index 0000000..610f136 --- /dev/null +++ b/WaterCloud.Web/wwwroot/images/403.svg @@ -0,0 +1,508 @@ + + + + Group 9 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/images/404.svg b/WaterCloud.Web/wwwroot/images/404.svg new file mode 100644 index 0000000..5531d05 --- /dev/null +++ b/WaterCloud.Web/wwwroot/images/404.svg @@ -0,0 +1,314 @@ + + + + Group 4 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/images/500.svg b/WaterCloud.Web/wwwroot/images/500.svg new file mode 100644 index 0000000..de723b1 --- /dev/null +++ b/WaterCloud.Web/wwwroot/images/500.svg @@ -0,0 +1,208 @@ + + + + Group 4 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/images/bg.jpg b/WaterCloud.Web/wwwroot/images/bg.jpg new file mode 100644 index 0000000..d5870f5 Binary files /dev/null and b/WaterCloud.Web/wwwroot/images/bg.jpg differ diff --git a/WaterCloud.Web/wwwroot/images/bgnew.jpeg b/WaterCloud.Web/wwwroot/images/bgnew.jpeg new file mode 100644 index 0000000..b236742 Binary files /dev/null and b/WaterCloud.Web/wwwroot/images/bgnew.jpeg differ diff --git a/WaterCloud.Web/wwwroot/images/bgs.jpg b/WaterCloud.Web/wwwroot/images/bgs.jpg new file mode 100644 index 0000000..7cb5b25 Binary files /dev/null and b/WaterCloud.Web/wwwroot/images/bgs.jpg differ diff --git a/WaterCloud.Web/wwwroot/images/moon.jfif b/WaterCloud.Web/wwwroot/images/moon.jfif new file mode 100644 index 0000000..72aebef Binary files /dev/null and b/WaterCloud.Web/wwwroot/images/moon.jfif differ diff --git a/WaterCloud.Web/wwwroot/images/moon.jpg b/WaterCloud.Web/wwwroot/images/moon.jpg new file mode 100644 index 0000000..72aebef Binary files /dev/null and b/WaterCloud.Web/wwwroot/images/moon.jpg differ diff --git a/WaterCloud.Web/wwwroot/images/timg.jfif b/WaterCloud.Web/wwwroot/images/timg.jfif new file mode 100644 index 0000000..483c4fe Binary files /dev/null and b/WaterCloud.Web/wwwroot/images/timg.jfif differ diff --git a/WaterCloud.Web/wwwroot/js/Sortable/Sortable.js b/WaterCloud.Web/wwwroot/js/Sortable/Sortable.js new file mode 100644 index 0000000..c6d7f9d --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/Sortable/Sortable.js @@ -0,0 +1,3709 @@ +/**! + * Sortable 1.10.2 + * @author RubaXa + * @author owenm + * @license MIT + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.Sortable = factory()); +}(this, function () { 'use strict'; + + function _typeof(obj) { + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + _typeof = function (obj) { + return typeof obj; + }; + } else { + _typeof = function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + } + + return _typeof(obj); + } + + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; + } + + function _extends() { + _extends = Object.assign || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + + return _extends.apply(this, arguments); + } + + function _objectSpread(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + var ownKeys = Object.keys(source); + + if (typeof Object.getOwnPropertySymbols === 'function') { + ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { + return Object.getOwnPropertyDescriptor(source, sym).enumerable; + })); + } + + ownKeys.forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } + + return target; + } + + function _objectWithoutPropertiesLoose(source, excluded) { + if (source == null) return {}; + var target = {}; + var sourceKeys = Object.keys(source); + var key, i; + + for (i = 0; i < sourceKeys.length; i++) { + key = sourceKeys[i]; + if (excluded.indexOf(key) >= 0) continue; + target[key] = source[key]; + } + + return target; + } + + function _objectWithoutProperties(source, excluded) { + if (source == null) return {}; + + var target = _objectWithoutPropertiesLoose(source, excluded); + + var key, i; + + if (Object.getOwnPropertySymbols) { + var sourceSymbolKeys = Object.getOwnPropertySymbols(source); + + for (i = 0; i < sourceSymbolKeys.length; i++) { + key = sourceSymbolKeys[i]; + if (excluded.indexOf(key) >= 0) continue; + if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; + target[key] = source[key]; + } + } + + return target; + } + + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); + } + + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + + return arr2; + } + } + + function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); + } + + function _nonIterableSpread() { + throw new TypeError("Invalid attempt to spread non-iterable instance"); + } + + var version = "1.10.2"; + + function userAgent(pattern) { + if (typeof window !== 'undefined' && window.navigator) { + return !! + /*@__PURE__*/ + navigator.userAgent.match(pattern); + } + } + + var IE11OrLess = userAgent(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i); + var Edge = userAgent(/Edge/i); + var FireFox = userAgent(/firefox/i); + var Safari = userAgent(/safari/i) && !userAgent(/chrome/i) && !userAgent(/android/i); + var IOS = userAgent(/iP(ad|od|hone)/i); + var ChromeForAndroid = userAgent(/chrome/i) && userAgent(/android/i); + + var captureMode = { + capture: false, + passive: false + }; + + function on(el, event, fn) { + el.addEventListener(event, fn, !IE11OrLess && captureMode); + } + + function off(el, event, fn) { + el.removeEventListener(event, fn, !IE11OrLess && captureMode); + } + + function matches( + /**HTMLElement*/ + el, + /**String*/ + selector) { + if (!selector) return; + selector[0] === '>' && (selector = selector.substring(1)); + + if (el) { + try { + if (el.matches) { + return el.matches(selector); + } else if (el.msMatchesSelector) { + return el.msMatchesSelector(selector); + } else if (el.webkitMatchesSelector) { + return el.webkitMatchesSelector(selector); + } + } catch (_) { + return false; + } + } + + return false; + } + + function getParentOrHost(el) { + return el.host && el !== document && el.host.nodeType ? el.host : el.parentNode; + } + + function closest( + /**HTMLElement*/ + el, + /**String*/ + selector, + /**HTMLElement*/ + ctx, includeCTX) { + if (el) { + ctx = ctx || document; + + do { + if (selector != null && (selector[0] === '>' ? el.parentNode === ctx && matches(el, selector) : matches(el, selector)) || includeCTX && el === ctx) { + return el; + } + + if (el === ctx) break; + /* jshint boss:true */ + } while (el = getParentOrHost(el)); + } + + return null; + } + + var R_SPACE = /\s+/g; + + function toggleClass(el, name, state) { + if (el && name) { + if (el.classList) { + el.classList[state ? 'add' : 'remove'](name); + } else { + var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' '); + el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' '); + } + } + } + + function css(el, prop, val) { + var style = el && el.style; + + if (style) { + if (val === void 0) { + if (document.defaultView && document.defaultView.getComputedStyle) { + val = document.defaultView.getComputedStyle(el, ''); + } else if (el.currentStyle) { + val = el.currentStyle; + } + + return prop === void 0 ? val : val[prop]; + } else { + if (!(prop in style) && prop.indexOf('webkit') === -1) { + prop = '-webkit-' + prop; + } + + style[prop] = val + (typeof val === 'string' ? '' : 'px'); + } + } + } + + function matrix(el, selfOnly) { + var appliedTransforms = ''; + + if (typeof el === 'string') { + appliedTransforms = el; + } else { + do { + var transform = css(el, 'transform'); + + if (transform && transform !== 'none') { + appliedTransforms = transform + ' ' + appliedTransforms; + } + /* jshint boss:true */ + + } while (!selfOnly && (el = el.parentNode)); + } + + var matrixFn = window.DOMMatrix || window.WebKitCSSMatrix || window.CSSMatrix || window.MSCSSMatrix; + /*jshint -W056 */ + + return matrixFn && new matrixFn(appliedTransforms); + } + + function find(ctx, tagName, iterator) { + if (ctx) { + var list = ctx.getElementsByTagName(tagName), + i = 0, + n = list.length; + + if (iterator) { + for (; i < n; i++) { + iterator(list[i], i); + } + } + + return list; + } + + return []; + } + + function getWindowScrollingElement() { + var scrollingElement = document.scrollingElement; + + if (scrollingElement) { + return scrollingElement; + } else { + return document.documentElement; + } + } + /** + * Returns the "bounding client rect" of given element + * @param {HTMLElement} el The element whose boundingClientRect is wanted + * @param {[Boolean]} relativeToContainingBlock Whether the rect should be relative to the containing block of (including) the container + * @param {[Boolean]} relativeToNonStaticParent Whether the rect should be relative to the relative parent of (including) the contaienr + * @param {[Boolean]} undoScale Whether the container's scale() should be undone + * @param {[HTMLElement]} container The parent the element will be placed in + * @return {Object} The boundingClientRect of el, with specified adjustments + */ + + + function getRect(el, relativeToContainingBlock, relativeToNonStaticParent, undoScale, container) { + if (!el.getBoundingClientRect && el !== window) return; + var elRect, top, left, bottom, right, height, width; + + if (el !== window && el !== getWindowScrollingElement()) { + elRect = el.getBoundingClientRect(); + top = elRect.top; + left = elRect.left; + bottom = elRect.bottom; + right = elRect.right; + height = elRect.height; + width = elRect.width; + } else { + top = 0; + left = 0; + bottom = window.innerHeight; + right = window.innerWidth; + height = window.innerHeight; + width = window.innerWidth; + } + + if ((relativeToContainingBlock || relativeToNonStaticParent) && el !== window) { + // Adjust for translate() + container = container || el.parentNode; // solves #1123 (see: https://stackoverflow.com/a/37953806/6088312) + // Not needed on <= IE11 + + if (!IE11OrLess) { + do { + if (container && container.getBoundingClientRect && (css(container, 'transform') !== 'none' || relativeToNonStaticParent && css(container, 'position') !== 'static')) { + var containerRect = container.getBoundingClientRect(); // Set relative to edges of padding box of container + + top -= containerRect.top + parseInt(css(container, 'border-top-width')); + left -= containerRect.left + parseInt(css(container, 'border-left-width')); + bottom = top + elRect.height; + right = left + elRect.width; + break; + } + /* jshint boss:true */ + + } while (container = container.parentNode); + } + } + + if (undoScale && el !== window) { + // Adjust for scale() + var elMatrix = matrix(container || el), + scaleX = elMatrix && elMatrix.a, + scaleY = elMatrix && elMatrix.d; + + if (elMatrix) { + top /= scaleY; + left /= scaleX; + width /= scaleX; + height /= scaleY; + bottom = top + height; + right = left + width; + } + } + + return { + top: top, + left: left, + bottom: bottom, + right: right, + width: width, + height: height + }; + } + /** + * Checks if a side of an element is scrolled past a side of its parents + * @param {HTMLElement} el The element who's side being scrolled out of view is in question + * @param {String} elSide Side of the element in question ('top', 'left', 'right', 'bottom') + * @param {String} parentSide Side of the parent in question ('top', 'left', 'right', 'bottom') + * @return {HTMLElement} The parent scroll element that the el's side is scrolled past, or null if there is no such element + */ + + + function isScrolledPast(el, elSide, parentSide) { + var parent = getParentAutoScrollElement(el, true), + elSideVal = getRect(el)[elSide]; + /* jshint boss:true */ + + while (parent) { + var parentSideVal = getRect(parent)[parentSide], + visible = void 0; + + if (parentSide === 'top' || parentSide === 'left') { + visible = elSideVal >= parentSideVal; + } else { + visible = elSideVal <= parentSideVal; + } + + if (!visible) return parent; + if (parent === getWindowScrollingElement()) break; + parent = getParentAutoScrollElement(parent, false); + } + + return false; + } + /** + * Gets nth child of el, ignoring hidden children, sortable's elements (does not ignore clone if it's visible) + * and non-draggable elements + * @param {HTMLElement} el The parent element + * @param {Number} childNum The index of the child + * @param {Object} options Parent Sortable's options + * @return {HTMLElement} The child at index childNum, or null if not found + */ + + + function getChild(el, childNum, options) { + var currentChild = 0, + i = 0, + children = el.children; + + while (i < children.length) { + if (children[i].style.display !== 'none' && children[i] !== Sortable.ghost && children[i] !== Sortable.dragged && closest(children[i], options.draggable, el, false)) { + if (currentChild === childNum) { + return children[i]; + } + + currentChild++; + } + + i++; + } + + return null; + } + /** + * Gets the last child in the el, ignoring ghostEl or invisible elements (clones) + * @param {HTMLElement} el Parent element + * @param {selector} selector Any other elements that should be ignored + * @return {HTMLElement} The last child, ignoring ghostEl + */ + + + function lastChild(el, selector) { + var last = el.lastElementChild; + + while (last && (last === Sortable.ghost || css(last, 'display') === 'none' || selector && !matches(last, selector))) { + last = last.previousElementSibling; + } + + return last || null; + } + /** + * Returns the index of an element within its parent for a selected set of + * elements + * @param {HTMLElement} el + * @param {selector} selector + * @return {number} + */ + + + function index(el, selector) { + var index = 0; + + if (!el || !el.parentNode) { + return -1; + } + /* jshint boss:true */ + + + while (el = el.previousElementSibling) { + if (el.nodeName.toUpperCase() !== 'TEMPLATE' && el !== Sortable.clone && (!selector || matches(el, selector))) { + index++; + } + } + + return index; + } + /** + * Returns the scroll offset of the given element, added with all the scroll offsets of parent elements. + * The value is returned in real pixels. + * @param {HTMLElement} el + * @return {Array} Offsets in the format of [left, top] + */ + + + function getRelativeScrollOffset(el) { + var offsetLeft = 0, + offsetTop = 0, + winScroller = getWindowScrollingElement(); + + if (el) { + do { + var elMatrix = matrix(el), + scaleX = elMatrix.a, + scaleY = elMatrix.d; + offsetLeft += el.scrollLeft * scaleX; + offsetTop += el.scrollTop * scaleY; + } while (el !== winScroller && (el = el.parentNode)); + } + + return [offsetLeft, offsetTop]; + } + /** + * Returns the index of the object within the given array + * @param {Array} arr Array that may or may not hold the object + * @param {Object} obj An object that has a key-value pair unique to and identical to a key-value pair in the object you want to find + * @return {Number} The index of the object in the array, or -1 + */ + + + function indexOfObject(arr, obj) { + for (var i in arr) { + if (!arr.hasOwnProperty(i)) continue; + + for (var key in obj) { + if (obj.hasOwnProperty(key) && obj[key] === arr[i][key]) return Number(i); + } + } + + return -1; + } + + function getParentAutoScrollElement(el, includeSelf) { + // skip to window + if (!el || !el.getBoundingClientRect) return getWindowScrollingElement(); + var elem = el; + var gotSelf = false; + + do { + // we don't need to get elem css if it isn't even overflowing in the first place (performance) + if (elem.clientWidth < elem.scrollWidth || elem.clientHeight < elem.scrollHeight) { + var elemCSS = css(elem); + + if (elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll') || elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll')) { + if (!elem.getBoundingClientRect || elem === document.body) return getWindowScrollingElement(); + if (gotSelf || includeSelf) return elem; + gotSelf = true; + } + } + /* jshint boss:true */ + + } while (elem = elem.parentNode); + + return getWindowScrollingElement(); + } + + function extend(dst, src) { + if (dst && src) { + for (var key in src) { + if (src.hasOwnProperty(key)) { + dst[key] = src[key]; + } + } + } + + return dst; + } + + function isRectEqual(rect1, rect2) { + return Math.round(rect1.top) === Math.round(rect2.top) && Math.round(rect1.left) === Math.round(rect2.left) && Math.round(rect1.height) === Math.round(rect2.height) && Math.round(rect1.width) === Math.round(rect2.width); + } + + var _throttleTimeout; + + function throttle(callback, ms) { + return function () { + if (!_throttleTimeout) { + var args = arguments, + _this = this; + + if (args.length === 1) { + callback.call(_this, args[0]); + } else { + callback.apply(_this, args); + } + + _throttleTimeout = setTimeout(function () { + _throttleTimeout = void 0; + }, ms); + } + }; + } + + function cancelThrottle() { + clearTimeout(_throttleTimeout); + _throttleTimeout = void 0; + } + + function scrollBy(el, x, y) { + el.scrollLeft += x; + el.scrollTop += y; + } + + function clone(el) { + var Polymer = window.Polymer; + var $ = window.jQuery || window.Zepto; + + if (Polymer && Polymer.dom) { + return Polymer.dom(el).cloneNode(true); + } else if ($) { + return $(el).clone(true)[0]; + } else { + return el.cloneNode(true); + } + } + + function setRect(el, rect) { + css(el, 'position', 'absolute'); + css(el, 'top', rect.top); + css(el, 'left', rect.left); + css(el, 'width', rect.width); + css(el, 'height', rect.height); + } + + function unsetRect(el) { + css(el, 'position', ''); + css(el, 'top', ''); + css(el, 'left', ''); + css(el, 'width', ''); + css(el, 'height', ''); + } + + var expando = 'Sortable' + new Date().getTime(); + + function AnimationStateManager() { + var animationStates = [], + animationCallbackId; + return { + captureAnimationState: function captureAnimationState() { + animationStates = []; + if (!this.options.animation) return; + var children = [].slice.call(this.el.children); + children.forEach(function (child) { + if (css(child, 'display') === 'none' || child === Sortable.ghost) return; + animationStates.push({ + target: child, + rect: getRect(child) + }); + + var fromRect = _objectSpread({}, animationStates[animationStates.length - 1].rect); // If animating: compensate for current animation + + + if (child.thisAnimationDuration) { + var childMatrix = matrix(child, true); + + if (childMatrix) { + fromRect.top -= childMatrix.f; + fromRect.left -= childMatrix.e; + } + } + + child.fromRect = fromRect; + }); + }, + addAnimationState: function addAnimationState(state) { + animationStates.push(state); + }, + removeAnimationState: function removeAnimationState(target) { + animationStates.splice(indexOfObject(animationStates, { + target: target + }), 1); + }, + animateAll: function animateAll(callback) { + var _this = this; + + if (!this.options.animation) { + clearTimeout(animationCallbackId); + if (typeof callback === 'function') callback(); + return; + } + + var animating = false, + animationTime = 0; + animationStates.forEach(function (state) { + var time = 0, + target = state.target, + fromRect = target.fromRect, + toRect = getRect(target), + prevFromRect = target.prevFromRect, + prevToRect = target.prevToRect, + animatingRect = state.rect, + targetMatrix = matrix(target, true); + + if (targetMatrix) { + // Compensate for current animation + toRect.top -= targetMatrix.f; + toRect.left -= targetMatrix.e; + } + + target.toRect = toRect; + + if (target.thisAnimationDuration) { + // Could also check if animatingRect is between fromRect and toRect + if (isRectEqual(prevFromRect, toRect) && !isRectEqual(fromRect, toRect) && // Make sure animatingRect is on line between toRect & fromRect + (animatingRect.top - toRect.top) / (animatingRect.left - toRect.left) === (fromRect.top - toRect.top) / (fromRect.left - toRect.left)) { + // If returning to same place as started from animation and on same axis + time = calculateRealTime(animatingRect, prevFromRect, prevToRect, _this.options); + } + } // if fromRect != toRect: animate + + + if (!isRectEqual(toRect, fromRect)) { + target.prevFromRect = fromRect; + target.prevToRect = toRect; + + if (!time) { + time = _this.options.animation; + } + + _this.animate(target, animatingRect, toRect, time); + } + + if (time) { + animating = true; + animationTime = Math.max(animationTime, time); + clearTimeout(target.animationResetTimer); + target.animationResetTimer = setTimeout(function () { + target.animationTime = 0; + target.prevFromRect = null; + target.fromRect = null; + target.prevToRect = null; + target.thisAnimationDuration = null; + }, time); + target.thisAnimationDuration = time; + } + }); + clearTimeout(animationCallbackId); + + if (!animating) { + if (typeof callback === 'function') callback(); + } else { + animationCallbackId = setTimeout(function () { + if (typeof callback === 'function') callback(); + }, animationTime); + } + + animationStates = []; + }, + animate: function animate(target, currentRect, toRect, duration) { + if (duration) { + css(target, 'transition', ''); + css(target, 'transform', ''); + var elMatrix = matrix(this.el), + scaleX = elMatrix && elMatrix.a, + scaleY = elMatrix && elMatrix.d, + translateX = (currentRect.left - toRect.left) / (scaleX || 1), + translateY = (currentRect.top - toRect.top) / (scaleY || 1); + target.animatingX = !!translateX; + target.animatingY = !!translateY; + css(target, 'transform', 'translate3d(' + translateX + 'px,' + translateY + 'px,0)'); + repaint(target); // repaint + + css(target, 'transition', 'transform ' + duration + 'ms' + (this.options.easing ? ' ' + this.options.easing : '')); + css(target, 'transform', 'translate3d(0,0,0)'); + typeof target.animated === 'number' && clearTimeout(target.animated); + target.animated = setTimeout(function () { + css(target, 'transition', ''); + css(target, 'transform', ''); + target.animated = false; + target.animatingX = false; + target.animatingY = false; + }, duration); + } + } + }; + } + + function repaint(target) { + return target.offsetWidth; + } + + function calculateRealTime(animatingRect, fromRect, toRect, options) { + return Math.sqrt(Math.pow(fromRect.top - animatingRect.top, 2) + Math.pow(fromRect.left - animatingRect.left, 2)) / Math.sqrt(Math.pow(fromRect.top - toRect.top, 2) + Math.pow(fromRect.left - toRect.left, 2)) * options.animation; + } + + var plugins = []; + var defaults = { + initializeByDefault: true + }; + var PluginManager = { + mount: function mount(plugin) { + // Set default static properties + for (var option in defaults) { + if (defaults.hasOwnProperty(option) && !(option in plugin)) { + plugin[option] = defaults[option]; + } + } + + plugins.push(plugin); + }, + pluginEvent: function pluginEvent(eventName, sortable, evt) { + var _this = this; + + this.eventCanceled = false; + + evt.cancel = function () { + _this.eventCanceled = true; + }; + + var eventNameGlobal = eventName + 'Global'; + plugins.forEach(function (plugin) { + if (!sortable[plugin.pluginName]) return; // Fire global events if it exists in this sortable + + if (sortable[plugin.pluginName][eventNameGlobal]) { + sortable[plugin.pluginName][eventNameGlobal](_objectSpread({ + sortable: sortable + }, evt)); + } // Only fire plugin event if plugin is enabled in this sortable, + // and plugin has event defined + + + if (sortable.options[plugin.pluginName] && sortable[plugin.pluginName][eventName]) { + sortable[plugin.pluginName][eventName](_objectSpread({ + sortable: sortable + }, evt)); + } + }); + }, + initializePlugins: function initializePlugins(sortable, el, defaults, options) { + plugins.forEach(function (plugin) { + var pluginName = plugin.pluginName; + if (!sortable.options[pluginName] && !plugin.initializeByDefault) return; + var initialized = new plugin(sortable, el, sortable.options); + initialized.sortable = sortable; + initialized.options = sortable.options; + sortable[pluginName] = initialized; // Add default options from plugin + + _extends(defaults, initialized.defaults); + }); + + for (var option in sortable.options) { + if (!sortable.options.hasOwnProperty(option)) continue; + var modified = this.modifyOption(sortable, option, sortable.options[option]); + + if (typeof modified !== 'undefined') { + sortable.options[option] = modified; + } + } + }, + getEventProperties: function getEventProperties(name, sortable) { + var eventProperties = {}; + plugins.forEach(function (plugin) { + if (typeof plugin.eventProperties !== 'function') return; + + _extends(eventProperties, plugin.eventProperties.call(sortable[plugin.pluginName], name)); + }); + return eventProperties; + }, + modifyOption: function modifyOption(sortable, name, value) { + var modifiedValue; + plugins.forEach(function (plugin) { + // Plugin must exist on the Sortable + if (!sortable[plugin.pluginName]) return; // If static option listener exists for this option, call in the context of the Sortable's instance of this plugin + + if (plugin.optionListeners && typeof plugin.optionListeners[name] === 'function') { + modifiedValue = plugin.optionListeners[name].call(sortable[plugin.pluginName], value); + } + }); + return modifiedValue; + } + }; + + function dispatchEvent(_ref) { + var sortable = _ref.sortable, + rootEl = _ref.rootEl, + name = _ref.name, + targetEl = _ref.targetEl, + cloneEl = _ref.cloneEl, + toEl = _ref.toEl, + fromEl = _ref.fromEl, + oldIndex = _ref.oldIndex, + newIndex = _ref.newIndex, + oldDraggableIndex = _ref.oldDraggableIndex, + newDraggableIndex = _ref.newDraggableIndex, + originalEvent = _ref.originalEvent, + putSortable = _ref.putSortable, + extraEventProperties = _ref.extraEventProperties; + sortable = sortable || rootEl && rootEl[expando]; + if (!sortable) return; + var evt, + options = sortable.options, + onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1); // Support for new CustomEvent feature + + if (window.CustomEvent && !IE11OrLess && !Edge) { + evt = new CustomEvent(name, { + bubbles: true, + cancelable: true + }); + } else { + evt = document.createEvent('Event'); + evt.initEvent(name, true, true); + } + + evt.to = toEl || rootEl; + evt.from = fromEl || rootEl; + evt.item = targetEl || rootEl; + evt.clone = cloneEl; + evt.oldIndex = oldIndex; + evt.newIndex = newIndex; + evt.oldDraggableIndex = oldDraggableIndex; + evt.newDraggableIndex = newDraggableIndex; + evt.originalEvent = originalEvent; + evt.pullMode = putSortable ? putSortable.lastPutMode : undefined; + + var allEventProperties = _objectSpread({}, extraEventProperties, PluginManager.getEventProperties(name, sortable)); + + for (var option in allEventProperties) { + evt[option] = allEventProperties[option]; + } + + if (rootEl) { + rootEl.dispatchEvent(evt); + } + + if (options[onName]) { + options[onName].call(sortable, evt); + } + } + + var pluginEvent = function pluginEvent(eventName, sortable) { + var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, + originalEvent = _ref.evt, + data = _objectWithoutProperties(_ref, ["evt"]); + + PluginManager.pluginEvent.bind(Sortable)(eventName, sortable, _objectSpread({ + dragEl: dragEl, + parentEl: parentEl, + ghostEl: ghostEl, + rootEl: rootEl, + nextEl: nextEl, + lastDownEl: lastDownEl, + cloneEl: cloneEl, + cloneHidden: cloneHidden, + dragStarted: moved, + putSortable: putSortable, + activeSortable: Sortable.active, + originalEvent: originalEvent, + oldIndex: oldIndex, + oldDraggableIndex: oldDraggableIndex, + newIndex: newIndex, + newDraggableIndex: newDraggableIndex, + hideGhostForTarget: _hideGhostForTarget, + unhideGhostForTarget: _unhideGhostForTarget, + cloneNowHidden: function cloneNowHidden() { + cloneHidden = true; + }, + cloneNowShown: function cloneNowShown() { + cloneHidden = false; + }, + dispatchSortableEvent: function dispatchSortableEvent(name) { + _dispatchEvent({ + sortable: sortable, + name: name, + originalEvent: originalEvent + }); + } + }, data)); + }; + + function _dispatchEvent(info) { + dispatchEvent(_objectSpread({ + putSortable: putSortable, + cloneEl: cloneEl, + targetEl: dragEl, + rootEl: rootEl, + oldIndex: oldIndex, + oldDraggableIndex: oldDraggableIndex, + newIndex: newIndex, + newDraggableIndex: newDraggableIndex + }, info)); + } + + var dragEl, + parentEl, + ghostEl, + rootEl, + nextEl, + lastDownEl, + cloneEl, + cloneHidden, + oldIndex, + newIndex, + oldDraggableIndex, + newDraggableIndex, + activeGroup, + putSortable, + awaitingDragStarted = false, + ignoreNextClick = false, + sortables = [], + tapEvt, + touchEvt, + lastDx, + lastDy, + tapDistanceLeft, + tapDistanceTop, + moved, + lastTarget, + lastDirection, + pastFirstInvertThresh = false, + isCircumstantialInvert = false, + targetMoveDistance, + // For positioning ghost absolutely + ghostRelativeParent, + ghostRelativeParentInitialScroll = [], + // (left, top) + _silent = false, + savedInputChecked = []; + /** @const */ + + var documentExists = typeof document !== 'undefined', + PositionGhostAbsolutely = IOS, + CSSFloatProperty = Edge || IE11OrLess ? 'cssFloat' : 'float', + // This will not pass for IE9, because IE9 DnD only works on anchors + supportDraggable = documentExists && !ChromeForAndroid && !IOS && 'draggable' in document.createElement('div'), + supportCssPointerEvents = function () { + if (!documentExists) return; // false when <= IE11 + + if (IE11OrLess) { + return false; + } + + var el = document.createElement('x'); + el.style.cssText = 'pointer-events:auto'; + return el.style.pointerEvents === 'auto'; + }(), + _detectDirection = function _detectDirection(el, options) { + var elCSS = css(el), + elWidth = parseInt(elCSS.width) - parseInt(elCSS.paddingLeft) - parseInt(elCSS.paddingRight) - parseInt(elCSS.borderLeftWidth) - parseInt(elCSS.borderRightWidth), + child1 = getChild(el, 0, options), + child2 = getChild(el, 1, options), + firstChildCSS = child1 && css(child1), + secondChildCSS = child2 && css(child2), + firstChildWidth = firstChildCSS && parseInt(firstChildCSS.marginLeft) + parseInt(firstChildCSS.marginRight) + getRect(child1).width, + secondChildWidth = secondChildCSS && parseInt(secondChildCSS.marginLeft) + parseInt(secondChildCSS.marginRight) + getRect(child2).width; + + if (elCSS.display === 'flex') { + return elCSS.flexDirection === 'column' || elCSS.flexDirection === 'column-reverse' ? 'vertical' : 'horizontal'; + } + + if (elCSS.display === 'grid') { + return elCSS.gridTemplateColumns.split(' ').length <= 1 ? 'vertical' : 'horizontal'; + } + + if (child1 && firstChildCSS["float"] && firstChildCSS["float"] !== 'none') { + var touchingSideChild2 = firstChildCSS["float"] === 'left' ? 'left' : 'right'; + return child2 && (secondChildCSS.clear === 'both' || secondChildCSS.clear === touchingSideChild2) ? 'vertical' : 'horizontal'; + } + + return child1 && (firstChildCSS.display === 'block' || firstChildCSS.display === 'flex' || firstChildCSS.display === 'table' || firstChildCSS.display === 'grid' || firstChildWidth >= elWidth && elCSS[CSSFloatProperty] === 'none' || child2 && elCSS[CSSFloatProperty] === 'none' && firstChildWidth + secondChildWidth > elWidth) ? 'vertical' : 'horizontal'; + }, + _dragElInRowColumn = function _dragElInRowColumn(dragRect, targetRect, vertical) { + var dragElS1Opp = vertical ? dragRect.left : dragRect.top, + dragElS2Opp = vertical ? dragRect.right : dragRect.bottom, + dragElOppLength = vertical ? dragRect.width : dragRect.height, + targetS1Opp = vertical ? targetRect.left : targetRect.top, + targetS2Opp = vertical ? targetRect.right : targetRect.bottom, + targetOppLength = vertical ? targetRect.width : targetRect.height; + return dragElS1Opp === targetS1Opp || dragElS2Opp === targetS2Opp || dragElS1Opp + dragElOppLength / 2 === targetS1Opp + targetOppLength / 2; + }, + + /** + * Detects first nearest empty sortable to X and Y position using emptyInsertThreshold. + * @param {Number} x X position + * @param {Number} y Y position + * @return {HTMLElement} Element of the first found nearest Sortable + */ + _detectNearestEmptySortable = function _detectNearestEmptySortable(x, y) { + var ret; + sortables.some(function (sortable) { + if (lastChild(sortable)) return; + var rect = getRect(sortable), + threshold = sortable[expando].options.emptyInsertThreshold, + insideHorizontally = x >= rect.left - threshold && x <= rect.right + threshold, + insideVertically = y >= rect.top - threshold && y <= rect.bottom + threshold; + + if (threshold && insideHorizontally && insideVertically) { + return ret = sortable; + } + }); + return ret; + }, + _prepareGroup = function _prepareGroup(options) { + function toFn(value, pull) { + return function (to, from, dragEl, evt) { + var sameGroup = to.options.group.name && from.options.group.name && to.options.group.name === from.options.group.name; + + if (value == null && (pull || sameGroup)) { + // Default pull value + // Default pull and put value if same group + return true; + } else if (value == null || value === false) { + return false; + } else if (pull && value === 'clone') { + return value; + } else if (typeof value === 'function') { + return toFn(value(to, from, dragEl, evt), pull)(to, from, dragEl, evt); + } else { + var otherGroup = (pull ? to : from).options.group.name; + return value === true || typeof value === 'string' && value === otherGroup || value.join && value.indexOf(otherGroup) > -1; + } + }; + } + + var group = {}; + var originalGroup = options.group; + + if (!originalGroup || _typeof(originalGroup) != 'object') { + originalGroup = { + name: originalGroup + }; + } + + group.name = originalGroup.name; + group.checkPull = toFn(originalGroup.pull, true); + group.checkPut = toFn(originalGroup.put); + group.revertClone = originalGroup.revertClone; + options.group = group; + }, + _hideGhostForTarget = function _hideGhostForTarget() { + if (!supportCssPointerEvents && ghostEl) { + css(ghostEl, 'display', 'none'); + } + }, + _unhideGhostForTarget = function _unhideGhostForTarget() { + if (!supportCssPointerEvents && ghostEl) { + css(ghostEl, 'display', ''); + } + }; // #1184 fix - Prevent click event on fallback if dragged but item not changed position + + + if (documentExists) { + document.addEventListener('click', function (evt) { + if (ignoreNextClick) { + evt.preventDefault(); + evt.stopPropagation && evt.stopPropagation(); + evt.stopImmediatePropagation && evt.stopImmediatePropagation(); + ignoreNextClick = false; + return false; + } + }, true); + } + + var nearestEmptyInsertDetectEvent = function nearestEmptyInsertDetectEvent(evt) { + if (dragEl) { + evt = evt.touches ? evt.touches[0] : evt; + + var nearest = _detectNearestEmptySortable(evt.clientX, evt.clientY); + + if (nearest) { + // Create imitation event + var event = {}; + + for (var i in evt) { + if (evt.hasOwnProperty(i)) { + event[i] = evt[i]; + } + } + + event.target = event.rootEl = nearest; + event.preventDefault = void 0; + event.stopPropagation = void 0; + + nearest[expando]._onDragOver(event); + } + } + }; + + var _checkOutsideTargetEl = function _checkOutsideTargetEl(evt) { + if (dragEl) { + dragEl.parentNode[expando]._isOutsideThisEl(evt.target); + } + }; + /** + * @class Sortable + * @param {HTMLElement} el + * @param {Object} [options] + */ + + + function Sortable(el, options) { + if (!(el && el.nodeType && el.nodeType === 1)) { + throw "Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(el)); + } + + this.el = el; // root element + + this.options = options = _extends({}, options); // Export instance + + el[expando] = this; + var defaults = { + group: null, + sort: true, + disabled: false, + store: null, + handle: null, + draggable: /^[uo]l$/i.test(el.nodeName) ? '>li' : '>*', + swapThreshold: 1, + // percentage; 0 <= x <= 1 + invertSwap: false, + // invert always + invertedSwapThreshold: null, + // will be set to same as swapThreshold if default + removeCloneOnHide: true, + direction: function direction() { + return _detectDirection(el, this.options); + }, + ghostClass: 'sortable-ghost', + chosenClass: 'sortable-chosen', + dragClass: 'sortable-drag', + ignore: 'a, img', + filter: null, + preventOnFilter: true, + animation: 0, + easing: null, + setData: function setData(dataTransfer, dragEl) { + dataTransfer.setData('Text', dragEl.textContent); + }, + dropBubble: false, + dragoverBubble: false, + dataIdAttr: 'data-id', + delay: 0, + delayOnTouchOnly: false, + touchStartThreshold: (Number.parseInt ? Number : window).parseInt(window.devicePixelRatio, 10) || 1, + forceFallback: false, + fallbackClass: 'sortable-fallback', + fallbackOnBody: false, + fallbackTolerance: 0, + fallbackOffset: { + x: 0, + y: 0 + }, + supportPointer: Sortable.supportPointer !== false && 'PointerEvent' in window, + emptyInsertThreshold: 5 + }; + PluginManager.initializePlugins(this, el, defaults); // Set default options + + for (var name in defaults) { + !(name in options) && (options[name] = defaults[name]); + } + + _prepareGroup(options); // Bind all private methods + + + for (var fn in this) { + if (fn.charAt(0) === '_' && typeof this[fn] === 'function') { + this[fn] = this[fn].bind(this); + } + } // Setup drag mode + + + this.nativeDraggable = options.forceFallback ? false : supportDraggable; + + if (this.nativeDraggable) { + // Touch start threshold cannot be greater than the native dragstart threshold + this.options.touchStartThreshold = 1; + } // Bind events + + + if (options.supportPointer) { + on(el, 'pointerdown', this._onTapStart); + } else { + on(el, 'mousedown', this._onTapStart); + on(el, 'touchstart', this._onTapStart); + } + + if (this.nativeDraggable) { + on(el, 'dragover', this); + on(el, 'dragenter', this); + } + + sortables.push(this.el); // Restore sorting + + options.store && options.store.get && this.sort(options.store.get(this) || []); // Add animation state manager + + _extends(this, AnimationStateManager()); + } + + Sortable.prototype = + /** @lends Sortable.prototype */ + { + constructor: Sortable, + _isOutsideThisEl: function _isOutsideThisEl(target) { + if (!this.el.contains(target) && target !== this.el) { + lastTarget = null; + } + }, + _getDirection: function _getDirection(evt, target) { + return typeof this.options.direction === 'function' ? this.options.direction.call(this, evt, target, dragEl) : this.options.direction; + }, + _onTapStart: function _onTapStart( + /** Event|TouchEvent */ + evt) { + if (!evt.cancelable) return; + + var _this = this, + el = this.el, + options = this.options, + preventOnFilter = options.preventOnFilter, + type = evt.type, + touch = evt.touches && evt.touches[0] || evt.pointerType && evt.pointerType === 'touch' && evt, + target = (touch || evt).target, + originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0] || evt.composedPath && evt.composedPath()[0]) || target, + filter = options.filter; + + _saveInputCheckedState(el); // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group. + + + if (dragEl) { + return; + } + + if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) { + return; // only left button and enabled + } // cancel dnd if original target is content editable + + + if (originalTarget.isContentEditable) { + return; + } + + target = closest(target, options.draggable, el, false); + + if (target && target.animated) { + return; + } + + if (lastDownEl === target) { + // Ignoring duplicate `down` + return; + } // Get the index of the dragged element within its parent + + + oldIndex = index(target); + oldDraggableIndex = index(target, options.draggable); // Check filter + + if (typeof filter === 'function') { + if (filter.call(this, evt, target, this)) { + _dispatchEvent({ + sortable: _this, + rootEl: originalTarget, + name: 'filter', + targetEl: target, + toEl: el, + fromEl: el + }); + + pluginEvent('filter', _this, { + evt: evt + }); + preventOnFilter && evt.cancelable && evt.preventDefault(); + return; // cancel dnd + } + } else if (filter) { + filter = filter.split(',').some(function (criteria) { + criteria = closest(originalTarget, criteria.trim(), el, false); + + if (criteria) { + _dispatchEvent({ + sortable: _this, + rootEl: criteria, + name: 'filter', + targetEl: target, + fromEl: el, + toEl: el + }); + + pluginEvent('filter', _this, { + evt: evt + }); + return true; + } + }); + + if (filter) { + preventOnFilter && evt.cancelable && evt.preventDefault(); + return; // cancel dnd + } + } + + if (options.handle && !closest(originalTarget, options.handle, el, false)) { + return; + } // Prepare `dragstart` + + + this._prepareDragStart(evt, touch, target); + }, + _prepareDragStart: function _prepareDragStart( + /** Event */ + evt, + /** Touch */ + touch, + /** HTMLElement */ + target) { + var _this = this, + el = _this.el, + options = _this.options, + ownerDocument = el.ownerDocument, + dragStartFn; + + if (target && !dragEl && target.parentNode === el) { + var dragRect = getRect(target); + rootEl = el; + dragEl = target; + parentEl = dragEl.parentNode; + nextEl = dragEl.nextSibling; + lastDownEl = target; + activeGroup = options.group; + Sortable.dragged = dragEl; + tapEvt = { + target: dragEl, + clientX: (touch || evt).clientX, + clientY: (touch || evt).clientY + }; + tapDistanceLeft = tapEvt.clientX - dragRect.left; + tapDistanceTop = tapEvt.clientY - dragRect.top; + this._lastX = (touch || evt).clientX; + this._lastY = (touch || evt).clientY; + dragEl.style['will-change'] = 'all'; + + dragStartFn = function dragStartFn() { + pluginEvent('delayEnded', _this, { + evt: evt + }); + + if (Sortable.eventCanceled) { + _this._onDrop(); + + return; + } // Delayed drag has been triggered + // we can re-enable the events: touchmove/mousemove + + + _this._disableDelayedDragEvents(); + + if (!FireFox && _this.nativeDraggable) { + dragEl.draggable = true; + } // Bind the events: dragstart/dragend + + + _this._triggerDragStart(evt, touch); // Drag start event + + + _dispatchEvent({ + sortable: _this, + name: 'choose', + originalEvent: evt + }); // Chosen item + + + toggleClass(dragEl, options.chosenClass, true); + }; // Disable "draggable" + + + options.ignore.split(',').forEach(function (criteria) { + find(dragEl, criteria.trim(), _disableDraggable); + }); + on(ownerDocument, 'dragover', nearestEmptyInsertDetectEvent); + on(ownerDocument, 'mousemove', nearestEmptyInsertDetectEvent); + on(ownerDocument, 'touchmove', nearestEmptyInsertDetectEvent); + on(ownerDocument, 'mouseup', _this._onDrop); + on(ownerDocument, 'touchend', _this._onDrop); + on(ownerDocument, 'touchcancel', _this._onDrop); // Make dragEl draggable (must be before delay for FireFox) + + if (FireFox && this.nativeDraggable) { + this.options.touchStartThreshold = 4; + dragEl.draggable = true; + } + + pluginEvent('delayStart', this, { + evt: evt + }); // Delay is impossible for native DnD in Edge or IE + + if (options.delay && (!options.delayOnTouchOnly || touch) && (!this.nativeDraggable || !(Edge || IE11OrLess))) { + if (Sortable.eventCanceled) { + this._onDrop(); + + return; + } // If the user moves the pointer or let go the click or touch + // before the delay has been reached: + // disable the delayed drag + + + on(ownerDocument, 'mouseup', _this._disableDelayedDrag); + on(ownerDocument, 'touchend', _this._disableDelayedDrag); + on(ownerDocument, 'touchcancel', _this._disableDelayedDrag); + on(ownerDocument, 'mousemove', _this._delayedDragTouchMoveHandler); + on(ownerDocument, 'touchmove', _this._delayedDragTouchMoveHandler); + options.supportPointer && on(ownerDocument, 'pointermove', _this._delayedDragTouchMoveHandler); + _this._dragStartTimer = setTimeout(dragStartFn, options.delay); + } else { + dragStartFn(); + } + } + }, + _delayedDragTouchMoveHandler: function _delayedDragTouchMoveHandler( + /** TouchEvent|PointerEvent **/ + e) { + var touch = e.touches ? e.touches[0] : e; + + if (Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) >= Math.floor(this.options.touchStartThreshold / (this.nativeDraggable && window.devicePixelRatio || 1))) { + this._disableDelayedDrag(); + } + }, + _disableDelayedDrag: function _disableDelayedDrag() { + dragEl && _disableDraggable(dragEl); + clearTimeout(this._dragStartTimer); + + this._disableDelayedDragEvents(); + }, + _disableDelayedDragEvents: function _disableDelayedDragEvents() { + var ownerDocument = this.el.ownerDocument; + off(ownerDocument, 'mouseup', this._disableDelayedDrag); + off(ownerDocument, 'touchend', this._disableDelayedDrag); + off(ownerDocument, 'touchcancel', this._disableDelayedDrag); + off(ownerDocument, 'mousemove', this._delayedDragTouchMoveHandler); + off(ownerDocument, 'touchmove', this._delayedDragTouchMoveHandler); + off(ownerDocument, 'pointermove', this._delayedDragTouchMoveHandler); + }, + _triggerDragStart: function _triggerDragStart( + /** Event */ + evt, + /** Touch */ + touch) { + touch = touch || evt.pointerType == 'touch' && evt; + + if (!this.nativeDraggable || touch) { + if (this.options.supportPointer) { + on(document, 'pointermove', this._onTouchMove); + } else if (touch) { + on(document, 'touchmove', this._onTouchMove); + } else { + on(document, 'mousemove', this._onTouchMove); + } + } else { + on(dragEl, 'dragend', this); + on(rootEl, 'dragstart', this._onDragStart); + } + + try { + if (document.selection) { + // Timeout neccessary for IE9 + _nextTick(function () { + document.selection.empty(); + }); + } else { + window.getSelection().removeAllRanges(); + } + } catch (err) {} + }, + _dragStarted: function _dragStarted(fallback, evt) { + + awaitingDragStarted = false; + + if (rootEl && dragEl) { + pluginEvent('dragStarted', this, { + evt: evt + }); + + if (this.nativeDraggable) { + on(document, 'dragover', _checkOutsideTargetEl); + } + + var options = this.options; // Apply effect + + !fallback && toggleClass(dragEl, options.dragClass, false); + toggleClass(dragEl, options.ghostClass, true); + Sortable.active = this; + fallback && this._appendGhost(); // Drag start event + + _dispatchEvent({ + sortable: this, + name: 'start', + originalEvent: evt + }); + } else { + this._nulling(); + } + }, + _emulateDragOver: function _emulateDragOver() { + if (touchEvt) { + this._lastX = touchEvt.clientX; + this._lastY = touchEvt.clientY; + + _hideGhostForTarget(); + + var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY); + var parent = target; + + while (target && target.shadowRoot) { + target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY); + if (target === parent) break; + parent = target; + } + + dragEl.parentNode[expando]._isOutsideThisEl(target); + + if (parent) { + do { + if (parent[expando]) { + var inserted = void 0; + inserted = parent[expando]._onDragOver({ + clientX: touchEvt.clientX, + clientY: touchEvt.clientY, + target: target, + rootEl: parent + }); + + if (inserted && !this.options.dragoverBubble) { + break; + } + } + + target = parent; // store last element + } + /* jshint boss:true */ + while (parent = parent.parentNode); + } + + _unhideGhostForTarget(); + } + }, + _onTouchMove: function _onTouchMove( + /**TouchEvent*/ + evt) { + if (tapEvt) { + var options = this.options, + fallbackTolerance = options.fallbackTolerance, + fallbackOffset = options.fallbackOffset, + touch = evt.touches ? evt.touches[0] : evt, + ghostMatrix = ghostEl && matrix(ghostEl, true), + scaleX = ghostEl && ghostMatrix && ghostMatrix.a, + scaleY = ghostEl && ghostMatrix && ghostMatrix.d, + relativeScrollOffset = PositionGhostAbsolutely && ghostRelativeParent && getRelativeScrollOffset(ghostRelativeParent), + dx = (touch.clientX - tapEvt.clientX + fallbackOffset.x) / (scaleX || 1) + (relativeScrollOffset ? relativeScrollOffset[0] - ghostRelativeParentInitialScroll[0] : 0) / (scaleX || 1), + dy = (touch.clientY - tapEvt.clientY + fallbackOffset.y) / (scaleY || 1) + (relativeScrollOffset ? relativeScrollOffset[1] - ghostRelativeParentInitialScroll[1] : 0) / (scaleY || 1); // only set the status to dragging, when we are actually dragging + + if (!Sortable.active && !awaitingDragStarted) { + if (fallbackTolerance && Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) < fallbackTolerance) { + return; + } + + this._onDragStart(evt, true); + } + + if (ghostEl) { + if (ghostMatrix) { + ghostMatrix.e += dx - (lastDx || 0); + ghostMatrix.f += dy - (lastDy || 0); + } else { + ghostMatrix = { + a: 1, + b: 0, + c: 0, + d: 1, + e: dx, + f: dy + }; + } + + var cssMatrix = "matrix(".concat(ghostMatrix.a, ",").concat(ghostMatrix.b, ",").concat(ghostMatrix.c, ",").concat(ghostMatrix.d, ",").concat(ghostMatrix.e, ",").concat(ghostMatrix.f, ")"); + css(ghostEl, 'webkitTransform', cssMatrix); + css(ghostEl, 'mozTransform', cssMatrix); + css(ghostEl, 'msTransform', cssMatrix); + css(ghostEl, 'transform', cssMatrix); + lastDx = dx; + lastDy = dy; + touchEvt = touch; + } + + evt.cancelable && evt.preventDefault(); + } + }, + _appendGhost: function _appendGhost() { + // Bug if using scale(): https://stackoverflow.com/questions/2637058 + // Not being adjusted for + if (!ghostEl) { + var container = this.options.fallbackOnBody ? document.body : rootEl, + rect = getRect(dragEl, true, PositionGhostAbsolutely, true, container), + options = this.options; // Position absolutely + + if (PositionGhostAbsolutely) { + // Get relatively positioned parent + ghostRelativeParent = container; + + while (css(ghostRelativeParent, 'position') === 'static' && css(ghostRelativeParent, 'transform') === 'none' && ghostRelativeParent !== document) { + ghostRelativeParent = ghostRelativeParent.parentNode; + } + + if (ghostRelativeParent !== document.body && ghostRelativeParent !== document.documentElement) { + if (ghostRelativeParent === document) ghostRelativeParent = getWindowScrollingElement(); + rect.top += ghostRelativeParent.scrollTop; + rect.left += ghostRelativeParent.scrollLeft; + } else { + ghostRelativeParent = getWindowScrollingElement(); + } + + ghostRelativeParentInitialScroll = getRelativeScrollOffset(ghostRelativeParent); + } + + ghostEl = dragEl.cloneNode(true); + toggleClass(ghostEl, options.ghostClass, false); + toggleClass(ghostEl, options.fallbackClass, true); + toggleClass(ghostEl, options.dragClass, true); + css(ghostEl, 'transition', ''); + css(ghostEl, 'transform', ''); + css(ghostEl, 'box-sizing', 'border-box'); + css(ghostEl, 'margin', 0); + css(ghostEl, 'top', rect.top); + css(ghostEl, 'left', rect.left); + css(ghostEl, 'width', rect.width); + css(ghostEl, 'height', rect.height); + css(ghostEl, 'opacity', '0.8'); + css(ghostEl, 'position', PositionGhostAbsolutely ? 'absolute' : 'fixed'); + css(ghostEl, 'zIndex', '100000'); + css(ghostEl, 'pointerEvents', 'none'); + Sortable.ghost = ghostEl; + container.appendChild(ghostEl); // Set transform-origin + + css(ghostEl, 'transform-origin', tapDistanceLeft / parseInt(ghostEl.style.width) * 100 + '% ' + tapDistanceTop / parseInt(ghostEl.style.height) * 100 + '%'); + } + }, + _onDragStart: function _onDragStart( + /**Event*/ + evt, + /**boolean*/ + fallback) { + var _this = this; + + var dataTransfer = evt.dataTransfer; + var options = _this.options; + pluginEvent('dragStart', this, { + evt: evt + }); + + if (Sortable.eventCanceled) { + this._onDrop(); + + return; + } + + pluginEvent('setupClone', this); + + if (!Sortable.eventCanceled) { + cloneEl = clone(dragEl); + cloneEl.draggable = false; + cloneEl.style['will-change'] = ''; + + this._hideClone(); + + toggleClass(cloneEl, this.options.chosenClass, false); + Sortable.clone = cloneEl; + } // #1143: IFrame support workaround + + + _this.cloneId = _nextTick(function () { + pluginEvent('clone', _this); + if (Sortable.eventCanceled) return; + + if (!_this.options.removeCloneOnHide) { + rootEl.insertBefore(cloneEl, dragEl); + } + + _this._hideClone(); + + _dispatchEvent({ + sortable: _this, + name: 'clone' + }); + }); + !fallback && toggleClass(dragEl, options.dragClass, true); // Set proper drop events + + if (fallback) { + ignoreNextClick = true; + _this._loopId = setInterval(_this._emulateDragOver, 50); + } else { + // Undo what was set in _prepareDragStart before drag started + off(document, 'mouseup', _this._onDrop); + off(document, 'touchend', _this._onDrop); + off(document, 'touchcancel', _this._onDrop); + + if (dataTransfer) { + dataTransfer.effectAllowed = 'move'; + options.setData && options.setData.call(_this, dataTransfer, dragEl); + } + + on(document, 'drop', _this); // #1276 fix: + + css(dragEl, 'transform', 'translateZ(0)'); + } + + awaitingDragStarted = true; + _this._dragStartId = _nextTick(_this._dragStarted.bind(_this, fallback, evt)); + on(document, 'selectstart', _this); + moved = true; + + if (Safari) { + css(document.body, 'user-select', 'none'); + } + }, + // Returns true - if no further action is needed (either inserted or another condition) + _onDragOver: function _onDragOver( + /**Event*/ + evt) { + var el = this.el, + target = evt.target, + dragRect, + targetRect, + revert, + options = this.options, + group = options.group, + activeSortable = Sortable.active, + isOwner = activeGroup === group, + canSort = options.sort, + fromSortable = putSortable || activeSortable, + vertical, + _this = this, + completedFired = false; + + if (_silent) return; + + function dragOverEvent(name, extra) { + pluginEvent(name, _this, _objectSpread({ + evt: evt, + isOwner: isOwner, + axis: vertical ? 'vertical' : 'horizontal', + revert: revert, + dragRect: dragRect, + targetRect: targetRect, + canSort: canSort, + fromSortable: fromSortable, + target: target, + completed: completed, + onMove: function onMove(target, after) { + return _onMove(rootEl, el, dragEl, dragRect, target, getRect(target), evt, after); + }, + changed: changed + }, extra)); + } // Capture animation state + + + function capture() { + dragOverEvent('dragOverAnimationCapture'); + + _this.captureAnimationState(); + + if (_this !== fromSortable) { + fromSortable.captureAnimationState(); + } + } // Return invocation when dragEl is inserted (or completed) + + + function completed(insertion) { + dragOverEvent('dragOverCompleted', { + insertion: insertion + }); + + if (insertion) { + // Clones must be hidden before folding animation to capture dragRectAbsolute properly + if (isOwner) { + activeSortable._hideClone(); + } else { + activeSortable._showClone(_this); + } + + if (_this !== fromSortable) { + // Set ghost class to new sortable's ghost class + toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : activeSortable.options.ghostClass, false); + toggleClass(dragEl, options.ghostClass, true); + } + + if (putSortable !== _this && _this !== Sortable.active) { + putSortable = _this; + } else if (_this === Sortable.active && putSortable) { + putSortable = null; + } // Animation + + + if (fromSortable === _this) { + _this._ignoreWhileAnimating = target; + } + + _this.animateAll(function () { + dragOverEvent('dragOverAnimationComplete'); + _this._ignoreWhileAnimating = null; + }); + + if (_this !== fromSortable) { + fromSortable.animateAll(); + fromSortable._ignoreWhileAnimating = null; + } + } // Null lastTarget if it is not inside a previously swapped element + + + if (target === dragEl && !dragEl.animated || target === el && !target.animated) { + lastTarget = null; + } // no bubbling and not fallback + + + if (!options.dragoverBubble && !evt.rootEl && target !== document) { + dragEl.parentNode[expando]._isOutsideThisEl(evt.target); // Do not detect for empty insert if already inserted + + + !insertion && nearestEmptyInsertDetectEvent(evt); + } + + !options.dragoverBubble && evt.stopPropagation && evt.stopPropagation(); + return completedFired = true; + } // Call when dragEl has been inserted + + + function changed() { + newIndex = index(dragEl); + newDraggableIndex = index(dragEl, options.draggable); + + _dispatchEvent({ + sortable: _this, + name: 'change', + toEl: el, + newIndex: newIndex, + newDraggableIndex: newDraggableIndex, + originalEvent: evt + }); + } + + if (evt.preventDefault !== void 0) { + evt.cancelable && evt.preventDefault(); + } + + target = closest(target, options.draggable, el, true); + dragOverEvent('dragOver'); + if (Sortable.eventCanceled) return completedFired; + + if (dragEl.contains(evt.target) || target.animated && target.animatingX && target.animatingY || _this._ignoreWhileAnimating === target) { + return completed(false); + } + + ignoreNextClick = false; + + if (activeSortable && !options.disabled && (isOwner ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list + : putSortable === this || (this.lastPutMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) && group.checkPut(this, activeSortable, dragEl, evt))) { + vertical = this._getDirection(evt, target) === 'vertical'; + dragRect = getRect(dragEl); + dragOverEvent('dragOverValid'); + if (Sortable.eventCanceled) return completedFired; + + if (revert) { + parentEl = rootEl; // actualization + + capture(); + + this._hideClone(); + + dragOverEvent('revert'); + + if (!Sortable.eventCanceled) { + if (nextEl) { + rootEl.insertBefore(dragEl, nextEl); + } else { + rootEl.appendChild(dragEl); + } + } + + return completed(true); + } + + var elLastChild = lastChild(el, options.draggable); + + if (!elLastChild || _ghostIsLast(evt, vertical, this) && !elLastChild.animated) { + // If already at end of list: Do not insert + if (elLastChild === dragEl) { + return completed(false); + } // assign target only if condition is true + + + if (elLastChild && el === evt.target) { + target = elLastChild; + } + + if (target) { + targetRect = getRect(target); + } + + if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, !!target) !== false) { + capture(); + el.appendChild(dragEl); + parentEl = el; // actualization + + changed(); + return completed(true); + } + } else if (target.parentNode === el) { + targetRect = getRect(target); + var direction = 0, + targetBeforeFirstSwap, + differentLevel = dragEl.parentNode !== el, + differentRowCol = !_dragElInRowColumn(dragEl.animated && dragEl.toRect || dragRect, target.animated && target.toRect || targetRect, vertical), + side1 = vertical ? 'top' : 'left', + scrolledPastTop = isScrolledPast(target, 'top', 'top') || isScrolledPast(dragEl, 'top', 'top'), + scrollBefore = scrolledPastTop ? scrolledPastTop.scrollTop : void 0; + + if (lastTarget !== target) { + targetBeforeFirstSwap = targetRect[side1]; + pastFirstInvertThresh = false; + isCircumstantialInvert = !differentRowCol && options.invertSwap || differentLevel; + } + + direction = _getSwapDirection(evt, target, targetRect, vertical, differentRowCol ? 1 : options.swapThreshold, options.invertedSwapThreshold == null ? options.swapThreshold : options.invertedSwapThreshold, isCircumstantialInvert, lastTarget === target); + var sibling; + + if (direction !== 0) { + // Check if target is beside dragEl in respective direction (ignoring hidden elements) + var dragIndex = index(dragEl); + + do { + dragIndex -= direction; + sibling = parentEl.children[dragIndex]; + } while (sibling && (css(sibling, 'display') === 'none' || sibling === ghostEl)); + } // If dragEl is already beside target: Do not insert + + + if (direction === 0 || sibling === target) { + return completed(false); + } + + lastTarget = target; + lastDirection = direction; + var nextSibling = target.nextElementSibling, + after = false; + after = direction === 1; + + var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after); + + if (moveVector !== false) { + if (moveVector === 1 || moveVector === -1) { + after = moveVector === 1; + } + + _silent = true; + setTimeout(_unsilent, 30); + capture(); + + if (after && !nextSibling) { + el.appendChild(dragEl); + } else { + target.parentNode.insertBefore(dragEl, after ? nextSibling : target); + } // Undo chrome's scroll adjustment (has no effect on other browsers) + + + if (scrolledPastTop) { + scrollBy(scrolledPastTop, 0, scrollBefore - scrolledPastTop.scrollTop); + } + + parentEl = dragEl.parentNode; // actualization + // must be done before animation + + if (targetBeforeFirstSwap !== undefined && !isCircumstantialInvert) { + targetMoveDistance = Math.abs(targetBeforeFirstSwap - getRect(target)[side1]); + } + + changed(); + return completed(true); + } + } + + if (el.contains(dragEl)) { + return completed(false); + } + } + + return false; + }, + _ignoreWhileAnimating: null, + _offMoveEvents: function _offMoveEvents() { + off(document, 'mousemove', this._onTouchMove); + off(document, 'touchmove', this._onTouchMove); + off(document, 'pointermove', this._onTouchMove); + off(document, 'dragover', nearestEmptyInsertDetectEvent); + off(document, 'mousemove', nearestEmptyInsertDetectEvent); + off(document, 'touchmove', nearestEmptyInsertDetectEvent); + }, + _offUpEvents: function _offUpEvents() { + var ownerDocument = this.el.ownerDocument; + off(ownerDocument, 'mouseup', this._onDrop); + off(ownerDocument, 'touchend', this._onDrop); + off(ownerDocument, 'pointerup', this._onDrop); + off(ownerDocument, 'touchcancel', this._onDrop); + off(document, 'selectstart', this); + }, + _onDrop: function _onDrop( + /**Event*/ + evt) { + var el = this.el, + options = this.options; // Get the index of the dragged element within its parent + + newIndex = index(dragEl); + newDraggableIndex = index(dragEl, options.draggable); + pluginEvent('drop', this, { + evt: evt + }); + parentEl = dragEl && dragEl.parentNode; // Get again after plugin event + + newIndex = index(dragEl); + newDraggableIndex = index(dragEl, options.draggable); + + if (Sortable.eventCanceled) { + this._nulling(); + + return; + } + + awaitingDragStarted = false; + isCircumstantialInvert = false; + pastFirstInvertThresh = false; + clearInterval(this._loopId); + clearTimeout(this._dragStartTimer); + + _cancelNextTick(this.cloneId); + + _cancelNextTick(this._dragStartId); // Unbind events + + + if (this.nativeDraggable) { + off(document, 'drop', this); + off(el, 'dragstart', this._onDragStart); + } + + this._offMoveEvents(); + + this._offUpEvents(); + + if (Safari) { + css(document.body, 'user-select', ''); + } + + css(dragEl, 'transform', ''); + + if (evt) { + if (moved) { + evt.cancelable && evt.preventDefault(); + !options.dropBubble && evt.stopPropagation(); + } + + ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl); + + if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') { + // Remove clone(s) + cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl); + } + + if (dragEl) { + if (this.nativeDraggable) { + off(dragEl, 'dragend', this); + } + + _disableDraggable(dragEl); + + dragEl.style['will-change'] = ''; // Remove classes + // ghostClass is added in dragStarted + + if (moved && !awaitingDragStarted) { + toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : this.options.ghostClass, false); + } + + toggleClass(dragEl, this.options.chosenClass, false); // Drag stop event + + _dispatchEvent({ + sortable: this, + name: 'unchoose', + toEl: parentEl, + newIndex: null, + newDraggableIndex: null, + originalEvent: evt + }); + + if (rootEl !== parentEl) { + if (newIndex >= 0) { + // Add event + _dispatchEvent({ + rootEl: parentEl, + name: 'add', + toEl: parentEl, + fromEl: rootEl, + originalEvent: evt + }); // Remove event + + + _dispatchEvent({ + sortable: this, + name: 'remove', + toEl: parentEl, + originalEvent: evt + }); // drag from one list and drop into another + + + _dispatchEvent({ + rootEl: parentEl, + name: 'sort', + toEl: parentEl, + fromEl: rootEl, + originalEvent: evt + }); + + _dispatchEvent({ + sortable: this, + name: 'sort', + toEl: parentEl, + originalEvent: evt + }); + } + + putSortable && putSortable.save(); + } else { + if (newIndex !== oldIndex) { + if (newIndex >= 0) { + // drag & drop within the same list + _dispatchEvent({ + sortable: this, + name: 'update', + toEl: parentEl, + originalEvent: evt + }); + + _dispatchEvent({ + sortable: this, + name: 'sort', + toEl: parentEl, + originalEvent: evt + }); + } + } + } + + if (Sortable.active) { + /* jshint eqnull:true */ + if (newIndex == null || newIndex === -1) { + newIndex = oldIndex; + newDraggableIndex = oldDraggableIndex; + } + + _dispatchEvent({ + sortable: this, + name: 'end', + toEl: parentEl, + originalEvent: evt + }); // Save sorting + + + this.save(); + } + } + } + + this._nulling(); + }, + _nulling: function _nulling() { + pluginEvent('nulling', this); + rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = lastDownEl = cloneHidden = tapEvt = touchEvt = moved = newIndex = newDraggableIndex = oldIndex = oldDraggableIndex = lastTarget = lastDirection = putSortable = activeGroup = Sortable.dragged = Sortable.ghost = Sortable.clone = Sortable.active = null; + savedInputChecked.forEach(function (el) { + el.checked = true; + }); + savedInputChecked.length = lastDx = lastDy = 0; + }, + handleEvent: function handleEvent( + /**Event*/ + evt) { + switch (evt.type) { + case 'drop': + case 'dragend': + this._onDrop(evt); + + break; + + case 'dragenter': + case 'dragover': + if (dragEl) { + this._onDragOver(evt); + + _globalDragOver(evt); + } + + break; + + case 'selectstart': + evt.preventDefault(); + break; + } + }, + + /** + * Serializes the item into an array of string. + * @returns {String[]} + */ + toArray: function toArray() { + var order = [], + el, + children = this.el.children, + i = 0, + n = children.length, + options = this.options; + + for (; i < n; i++) { + el = children[i]; + + if (closest(el, options.draggable, this.el, false)) { + order.push(el.getAttribute(options.dataIdAttr) || _generateId(el)); + } + } + + return order; + }, + + /** + * Sorts the elements according to the array. + * @param {String[]} order order of the items + */ + sort: function sort(order) { + var items = {}, + rootEl = this.el; + this.toArray().forEach(function (id, i) { + var el = rootEl.children[i]; + + if (closest(el, this.options.draggable, rootEl, false)) { + items[id] = el; + } + }, this); + order.forEach(function (id) { + if (items[id]) { + rootEl.removeChild(items[id]); + rootEl.appendChild(items[id]); + } + }); + }, + + /** + * Save the current sorting + */ + save: function save() { + var store = this.options.store; + store && store.set && store.set(this); + }, + + /** + * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. + * @param {HTMLElement} el + * @param {String} [selector] default: `options.draggable` + * @returns {HTMLElement|null} + */ + closest: function closest$1(el, selector) { + return closest(el, selector || this.options.draggable, this.el, false); + }, + + /** + * Set/get option + * @param {string} name + * @param {*} [value] + * @returns {*} + */ + option: function option(name, value) { + var options = this.options; + + if (value === void 0) { + return options[name]; + } else { + var modifiedValue = PluginManager.modifyOption(this, name, value); + + if (typeof modifiedValue !== 'undefined') { + options[name] = modifiedValue; + } else { + options[name] = value; + } + + if (name === 'group') { + _prepareGroup(options); + } + } + }, + + /** + * Destroy + */ + destroy: function destroy() { + pluginEvent('destroy', this); + var el = this.el; + el[expando] = null; + off(el, 'mousedown', this._onTapStart); + off(el, 'touchstart', this._onTapStart); + off(el, 'pointerdown', this._onTapStart); + + if (this.nativeDraggable) { + off(el, 'dragover', this); + off(el, 'dragenter', this); + } // Remove draggable attributes + + + Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) { + el.removeAttribute('draggable'); + }); + + this._onDrop(); + + this._disableDelayedDragEvents(); + + sortables.splice(sortables.indexOf(this.el), 1); + this.el = el = null; + }, + _hideClone: function _hideClone() { + if (!cloneHidden) { + pluginEvent('hideClone', this); + if (Sortable.eventCanceled) return; + css(cloneEl, 'display', 'none'); + + if (this.options.removeCloneOnHide && cloneEl.parentNode) { + cloneEl.parentNode.removeChild(cloneEl); + } + + cloneHidden = true; + } + }, + _showClone: function _showClone(putSortable) { + if (putSortable.lastPutMode !== 'clone') { + this._hideClone(); + + return; + } + + if (cloneHidden) { + pluginEvent('showClone', this); + if (Sortable.eventCanceled) return; // show clone at dragEl or original position + + if (rootEl.contains(dragEl) && !this.options.group.revertClone) { + rootEl.insertBefore(cloneEl, dragEl); + } else if (nextEl) { + rootEl.insertBefore(cloneEl, nextEl); + } else { + rootEl.appendChild(cloneEl); + } + + if (this.options.group.revertClone) { + this.animate(dragEl, cloneEl); + } + + css(cloneEl, 'display', ''); + cloneHidden = false; + } + } + }; + + function _globalDragOver( + /**Event*/ + evt) { + if (evt.dataTransfer) { + evt.dataTransfer.dropEffect = 'move'; + } + + evt.cancelable && evt.preventDefault(); + } + + function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvent, willInsertAfter) { + var evt, + sortable = fromEl[expando], + onMoveFn = sortable.options.onMove, + retVal; // Support for new CustomEvent feature + + if (window.CustomEvent && !IE11OrLess && !Edge) { + evt = new CustomEvent('move', { + bubbles: true, + cancelable: true + }); + } else { + evt = document.createEvent('Event'); + evt.initEvent('move', true, true); + } + + evt.to = toEl; + evt.from = fromEl; + evt.dragged = dragEl; + evt.draggedRect = dragRect; + evt.related = targetEl || toEl; + evt.relatedRect = targetRect || getRect(toEl); + evt.willInsertAfter = willInsertAfter; + evt.originalEvent = originalEvent; + fromEl.dispatchEvent(evt); + + if (onMoveFn) { + retVal = onMoveFn.call(sortable, evt, originalEvent); + } + + return retVal; + } + + function _disableDraggable(el) { + el.draggable = false; + } + + function _unsilent() { + _silent = false; + } + + function _ghostIsLast(evt, vertical, sortable) { + var rect = getRect(lastChild(sortable.el, sortable.options.draggable)); + var spacer = 10; + return vertical ? evt.clientX > rect.right + spacer || evt.clientX <= rect.right && evt.clientY > rect.bottom && evt.clientX >= rect.left : evt.clientX > rect.right && evt.clientY > rect.top || evt.clientX <= rect.right && evt.clientY > rect.bottom + spacer; + } + + function _getSwapDirection(evt, target, targetRect, vertical, swapThreshold, invertedSwapThreshold, invertSwap, isLastTarget) { + var mouseOnAxis = vertical ? evt.clientY : evt.clientX, + targetLength = vertical ? targetRect.height : targetRect.width, + targetS1 = vertical ? targetRect.top : targetRect.left, + targetS2 = vertical ? targetRect.bottom : targetRect.right, + invert = false; + + if (!invertSwap) { + // Never invert or create dragEl shadow when target movemenet causes mouse to move past the end of regular swapThreshold + if (isLastTarget && targetMoveDistance < targetLength * swapThreshold) { + // multiplied only by swapThreshold because mouse will already be inside target by (1 - threshold) * targetLength / 2 + // check if past first invert threshold on side opposite of lastDirection + if (!pastFirstInvertThresh && (lastDirection === 1 ? mouseOnAxis > targetS1 + targetLength * invertedSwapThreshold / 2 : mouseOnAxis < targetS2 - targetLength * invertedSwapThreshold / 2)) { + // past first invert threshold, do not restrict inverted threshold to dragEl shadow + pastFirstInvertThresh = true; + } + + if (!pastFirstInvertThresh) { + // dragEl shadow (target move distance shadow) + if (lastDirection === 1 ? mouseOnAxis < targetS1 + targetMoveDistance // over dragEl shadow + : mouseOnAxis > targetS2 - targetMoveDistance) { + return -lastDirection; + } + } else { + invert = true; + } + } else { + // Regular + if (mouseOnAxis > targetS1 + targetLength * (1 - swapThreshold) / 2 && mouseOnAxis < targetS2 - targetLength * (1 - swapThreshold) / 2) { + return _getInsertDirection(target); + } + } + } + + invert = invert || invertSwap; + + if (invert) { + // Invert of regular + if (mouseOnAxis < targetS1 + targetLength * invertedSwapThreshold / 2 || mouseOnAxis > targetS2 - targetLength * invertedSwapThreshold / 2) { + return mouseOnAxis > targetS1 + targetLength / 2 ? 1 : -1; + } + } + + return 0; + } + /** + * Gets the direction dragEl must be swapped relative to target in order to make it + * seem that dragEl has been "inserted" into that element's position + * @param {HTMLElement} target The target whose position dragEl is being inserted at + * @return {Number} Direction dragEl must be swapped + */ + + + function _getInsertDirection(target) { + if (index(dragEl) < index(target)) { + return 1; + } else { + return -1; + } + } + /** + * Generate id + * @param {HTMLElement} el + * @returns {String} + * @private + */ + + + function _generateId(el) { + var str = el.tagName + el.className + el.src + el.href + el.textContent, + i = str.length, + sum = 0; + + while (i--) { + sum += str.charCodeAt(i); + } + + return sum.toString(36); + } + + function _saveInputCheckedState(root) { + savedInputChecked.length = 0; + var inputs = root.getElementsByTagName('input'); + var idx = inputs.length; + + while (idx--) { + var el = inputs[idx]; + el.checked && savedInputChecked.push(el); + } + } + + function _nextTick(fn) { + return setTimeout(fn, 0); + } + + function _cancelNextTick(id) { + return clearTimeout(id); + } // Fixed #973: + + + if (documentExists) { + on(document, 'touchmove', function (evt) { + if ((Sortable.active || awaitingDragStarted) && evt.cancelable) { + evt.preventDefault(); + } + }); + } // Export utils + + + Sortable.utils = { + on: on, + off: off, + css: css, + find: find, + is: function is(el, selector) { + return !!closest(el, selector, el, false); + }, + extend: extend, + throttle: throttle, + closest: closest, + toggleClass: toggleClass, + clone: clone, + index: index, + nextTick: _nextTick, + cancelNextTick: _cancelNextTick, + detectDirection: _detectDirection, + getChild: getChild + }; + /** + * Get the Sortable instance of an element + * @param {HTMLElement} element The element + * @return {Sortable|undefined} The instance of Sortable + */ + + Sortable.get = function (element) { + return element[expando]; + }; + /** + * Mount a plugin to Sortable + * @param {...SortablePlugin|SortablePlugin[]} plugins Plugins being mounted + */ + + + Sortable.mount = function () { + for (var _len = arguments.length, plugins = new Array(_len), _key = 0; _key < _len; _key++) { + plugins[_key] = arguments[_key]; + } + + if (plugins[0].constructor === Array) plugins = plugins[0]; + plugins.forEach(function (plugin) { + if (!plugin.prototype || !plugin.prototype.constructor) { + throw "Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(plugin)); + } + + if (plugin.utils) Sortable.utils = _objectSpread({}, Sortable.utils, plugin.utils); + PluginManager.mount(plugin); + }); + }; + /** + * Create sortable instance + * @param {HTMLElement} el + * @param {Object} [options] + */ + + + Sortable.create = function (el, options) { + return new Sortable(el, options); + }; // Export + + + Sortable.version = version; + + var autoScrolls = [], + scrollEl, + scrollRootEl, + scrolling = false, + lastAutoScrollX, + lastAutoScrollY, + touchEvt$1, + pointerElemChangedInterval; + + function AutoScrollPlugin() { + function AutoScroll() { + this.defaults = { + scroll: true, + scrollSensitivity: 30, + scrollSpeed: 10, + bubbleScroll: true + }; // Bind all private methods + + for (var fn in this) { + if (fn.charAt(0) === '_' && typeof this[fn] === 'function') { + this[fn] = this[fn].bind(this); + } + } + } + + AutoScroll.prototype = { + dragStarted: function dragStarted(_ref) { + var originalEvent = _ref.originalEvent; + + if (this.sortable.nativeDraggable) { + on(document, 'dragover', this._handleAutoScroll); + } else { + if (this.options.supportPointer) { + on(document, 'pointermove', this._handleFallbackAutoScroll); + } else if (originalEvent.touches) { + on(document, 'touchmove', this._handleFallbackAutoScroll); + } else { + on(document, 'mousemove', this._handleFallbackAutoScroll); + } + } + }, + dragOverCompleted: function dragOverCompleted(_ref2) { + var originalEvent = _ref2.originalEvent; + + // For when bubbling is canceled and using fallback (fallback 'touchmove' always reached) + if (!this.options.dragOverBubble && !originalEvent.rootEl) { + this._handleAutoScroll(originalEvent); + } + }, + drop: function drop() { + if (this.sortable.nativeDraggable) { + off(document, 'dragover', this._handleAutoScroll); + } else { + off(document, 'pointermove', this._handleFallbackAutoScroll); + off(document, 'touchmove', this._handleFallbackAutoScroll); + off(document, 'mousemove', this._handleFallbackAutoScroll); + } + + clearPointerElemChangedInterval(); + clearAutoScrolls(); + cancelThrottle(); + }, + nulling: function nulling() { + touchEvt$1 = scrollRootEl = scrollEl = scrolling = pointerElemChangedInterval = lastAutoScrollX = lastAutoScrollY = null; + autoScrolls.length = 0; + }, + _handleFallbackAutoScroll: function _handleFallbackAutoScroll(evt) { + this._handleAutoScroll(evt, true); + }, + _handleAutoScroll: function _handleAutoScroll(evt, fallback) { + var _this = this; + + var x = (evt.touches ? evt.touches[0] : evt).clientX, + y = (evt.touches ? evt.touches[0] : evt).clientY, + elem = document.elementFromPoint(x, y); + touchEvt$1 = evt; // IE does not seem to have native autoscroll, + // Edge's autoscroll seems too conditional, + // MACOS Safari does not have autoscroll, + // Firefox and Chrome are good + + if (fallback || Edge || IE11OrLess || Safari) { + autoScroll(evt, this.options, elem, fallback); // Listener for pointer element change + + var ogElemScroller = getParentAutoScrollElement(elem, true); + + if (scrolling && (!pointerElemChangedInterval || x !== lastAutoScrollX || y !== lastAutoScrollY)) { + pointerElemChangedInterval && clearPointerElemChangedInterval(); // Detect for pointer elem change, emulating native DnD behaviour + + pointerElemChangedInterval = setInterval(function () { + var newElem = getParentAutoScrollElement(document.elementFromPoint(x, y), true); + + if (newElem !== ogElemScroller) { + ogElemScroller = newElem; + clearAutoScrolls(); + } + + autoScroll(evt, _this.options, newElem, fallback); + }, 10); + lastAutoScrollX = x; + lastAutoScrollY = y; + } + } else { + // if DnD is enabled (and browser has good autoscrolling), first autoscroll will already scroll, so get parent autoscroll of first autoscroll + if (!this.options.bubbleScroll || getParentAutoScrollElement(elem, true) === getWindowScrollingElement()) { + clearAutoScrolls(); + return; + } + + autoScroll(evt, this.options, getParentAutoScrollElement(elem, false), false); + } + } + }; + return _extends(AutoScroll, { + pluginName: 'scroll', + initializeByDefault: true + }); + } + + function clearAutoScrolls() { + autoScrolls.forEach(function (autoScroll) { + clearInterval(autoScroll.pid); + }); + autoScrolls = []; + } + + function clearPointerElemChangedInterval() { + clearInterval(pointerElemChangedInterval); + } + + var autoScroll = throttle(function (evt, options, rootEl, isFallback) { + // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521 + if (!options.scroll) return; + var x = (evt.touches ? evt.touches[0] : evt).clientX, + y = (evt.touches ? evt.touches[0] : evt).clientY, + sens = options.scrollSensitivity, + speed = options.scrollSpeed, + winScroller = getWindowScrollingElement(); + var scrollThisInstance = false, + scrollCustomFn; // New scroll root, set scrollEl + + if (scrollRootEl !== rootEl) { + scrollRootEl = rootEl; + clearAutoScrolls(); + scrollEl = options.scroll; + scrollCustomFn = options.scrollFn; + + if (scrollEl === true) { + scrollEl = getParentAutoScrollElement(rootEl, true); + } + } + + var layersOut = 0; + var currentParent = scrollEl; + + do { + var el = currentParent, + rect = getRect(el), + top = rect.top, + bottom = rect.bottom, + left = rect.left, + right = rect.right, + width = rect.width, + height = rect.height, + canScrollX = void 0, + canScrollY = void 0, + scrollWidth = el.scrollWidth, + scrollHeight = el.scrollHeight, + elCSS = css(el), + scrollPosX = el.scrollLeft, + scrollPosY = el.scrollTop; + + if (el === winScroller) { + canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll' || elCSS.overflowX === 'visible'); + canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll' || elCSS.overflowY === 'visible'); + } else { + canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll'); + canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll'); + } + + var vx = canScrollX && (Math.abs(right - x) <= sens && scrollPosX + width < scrollWidth) - (Math.abs(left - x) <= sens && !!scrollPosX); + var vy = canScrollY && (Math.abs(bottom - y) <= sens && scrollPosY + height < scrollHeight) - (Math.abs(top - y) <= sens && !!scrollPosY); + + if (!autoScrolls[layersOut]) { + for (var i = 0; i <= layersOut; i++) { + if (!autoScrolls[i]) { + autoScrolls[i] = {}; + } + } + } + + if (autoScrolls[layersOut].vx != vx || autoScrolls[layersOut].vy != vy || autoScrolls[layersOut].el !== el) { + autoScrolls[layersOut].el = el; + autoScrolls[layersOut].vx = vx; + autoScrolls[layersOut].vy = vy; + clearInterval(autoScrolls[layersOut].pid); + + if (vx != 0 || vy != 0) { + scrollThisInstance = true; + /* jshint loopfunc:true */ + + autoScrolls[layersOut].pid = setInterval(function () { + // emulate drag over during autoscroll (fallback), emulating native DnD behaviour + if (isFallback && this.layer === 0) { + Sortable.active._onTouchMove(touchEvt$1); // To move ghost if it is positioned absolutely + + } + + var scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0; + var scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0; + + if (typeof scrollCustomFn === 'function') { + if (scrollCustomFn.call(Sortable.dragged.parentNode[expando], scrollOffsetX, scrollOffsetY, evt, touchEvt$1, autoScrolls[this.layer].el) !== 'continue') { + return; + } + } + + scrollBy(autoScrolls[this.layer].el, scrollOffsetX, scrollOffsetY); + }.bind({ + layer: layersOut + }), 24); + } + } + + layersOut++; + } while (options.bubbleScroll && currentParent !== winScroller && (currentParent = getParentAutoScrollElement(currentParent, false))); + + scrolling = scrollThisInstance; // in case another function catches scrolling as false in between when it is not + }, 30); + + var drop = function drop(_ref) { + var originalEvent = _ref.originalEvent, + putSortable = _ref.putSortable, + dragEl = _ref.dragEl, + activeSortable = _ref.activeSortable, + dispatchSortableEvent = _ref.dispatchSortableEvent, + hideGhostForTarget = _ref.hideGhostForTarget, + unhideGhostForTarget = _ref.unhideGhostForTarget; + if (!originalEvent) return; + var toSortable = putSortable || activeSortable; + hideGhostForTarget(); + var touch = originalEvent.changedTouches && originalEvent.changedTouches.length ? originalEvent.changedTouches[0] : originalEvent; + var target = document.elementFromPoint(touch.clientX, touch.clientY); + unhideGhostForTarget(); + + if (toSortable && !toSortable.el.contains(target)) { + dispatchSortableEvent('spill'); + this.onSpill({ + dragEl: dragEl, + putSortable: putSortable + }); + } + }; + + function Revert() {} + + Revert.prototype = { + startIndex: null, + dragStart: function dragStart(_ref2) { + var oldDraggableIndex = _ref2.oldDraggableIndex; + this.startIndex = oldDraggableIndex; + }, + onSpill: function onSpill(_ref3) { + var dragEl = _ref3.dragEl, + putSortable = _ref3.putSortable; + this.sortable.captureAnimationState(); + + if (putSortable) { + putSortable.captureAnimationState(); + } + + var nextSibling = getChild(this.sortable.el, this.startIndex, this.options); + + if (nextSibling) { + this.sortable.el.insertBefore(dragEl, nextSibling); + } else { + this.sortable.el.appendChild(dragEl); + } + + this.sortable.animateAll(); + + if (putSortable) { + putSortable.animateAll(); + } + }, + drop: drop + }; + + _extends(Revert, { + pluginName: 'revertOnSpill' + }); + + function Remove() {} + + Remove.prototype = { + onSpill: function onSpill(_ref4) { + var dragEl = _ref4.dragEl, + putSortable = _ref4.putSortable; + var parentSortable = putSortable || this.sortable; + parentSortable.captureAnimationState(); + dragEl.parentNode && dragEl.parentNode.removeChild(dragEl); + parentSortable.animateAll(); + }, + drop: drop + }; + + _extends(Remove, { + pluginName: 'removeOnSpill' + }); + + var lastSwapEl; + + function SwapPlugin() { + function Swap() { + this.defaults = { + swapClass: 'sortable-swap-highlight' + }; + } + + Swap.prototype = { + dragStart: function dragStart(_ref) { + var dragEl = _ref.dragEl; + lastSwapEl = dragEl; + }, + dragOverValid: function dragOverValid(_ref2) { + var completed = _ref2.completed, + target = _ref2.target, + onMove = _ref2.onMove, + activeSortable = _ref2.activeSortable, + changed = _ref2.changed, + cancel = _ref2.cancel; + if (!activeSortable.options.swap) return; + var el = this.sortable.el, + options = this.options; + + if (target && target !== el) { + var prevSwapEl = lastSwapEl; + + if (onMove(target) !== false) { + toggleClass(target, options.swapClass, true); + lastSwapEl = target; + } else { + lastSwapEl = null; + } + + if (prevSwapEl && prevSwapEl !== lastSwapEl) { + toggleClass(prevSwapEl, options.swapClass, false); + } + } + + changed(); + completed(true); + cancel(); + }, + drop: function drop(_ref3) { + var activeSortable = _ref3.activeSortable, + putSortable = _ref3.putSortable, + dragEl = _ref3.dragEl; + var toSortable = putSortable || this.sortable; + var options = this.options; + lastSwapEl && toggleClass(lastSwapEl, options.swapClass, false); + + if (lastSwapEl && (options.swap || putSortable && putSortable.options.swap)) { + if (dragEl !== lastSwapEl) { + toSortable.captureAnimationState(); + if (toSortable !== activeSortable) activeSortable.captureAnimationState(); + swapNodes(dragEl, lastSwapEl); + toSortable.animateAll(); + if (toSortable !== activeSortable) activeSortable.animateAll(); + } + } + }, + nulling: function nulling() { + lastSwapEl = null; + } + }; + return _extends(Swap, { + pluginName: 'swap', + eventProperties: function eventProperties() { + return { + swapItem: lastSwapEl + }; + } + }); + } + + function swapNodes(n1, n2) { + var p1 = n1.parentNode, + p2 = n2.parentNode, + i1, + i2; + if (!p1 || !p2 || p1.isEqualNode(n2) || p2.isEqualNode(n1)) return; + i1 = index(n1); + i2 = index(n2); + + if (p1.isEqualNode(p2) && i1 < i2) { + i2++; + } + + p1.insertBefore(n2, p1.children[i1]); + p2.insertBefore(n1, p2.children[i2]); + } + + var multiDragElements = [], + multiDragClones = [], + lastMultiDragSelect, + // for selection with modifier key down (SHIFT) + multiDragSortable, + initialFolding = false, + // Initial multi-drag fold when drag started + folding = false, + // Folding any other time + dragStarted = false, + dragEl$1, + clonesFromRect, + clonesHidden; + + function MultiDragPlugin() { + function MultiDrag(sortable) { + // Bind all private methods + for (var fn in this) { + if (fn.charAt(0) === '_' && typeof this[fn] === 'function') { + this[fn] = this[fn].bind(this); + } + } + + if (sortable.options.supportPointer) { + on(document, 'pointerup', this._deselectMultiDrag); + } else { + on(document, 'mouseup', this._deselectMultiDrag); + on(document, 'touchend', this._deselectMultiDrag); + } + + on(document, 'keydown', this._checkKeyDown); + on(document, 'keyup', this._checkKeyUp); + this.defaults = { + selectedClass: 'sortable-selected', + multiDragKey: null, + setData: function setData(dataTransfer, dragEl) { + var data = ''; + + if (multiDragElements.length && multiDragSortable === sortable) { + multiDragElements.forEach(function (multiDragElement, i) { + data += (!i ? '' : ', ') + multiDragElement.textContent; + }); + } else { + data = dragEl.textContent; + } + + dataTransfer.setData('Text', data); + } + }; + } + + MultiDrag.prototype = { + multiDragKeyDown: false, + isMultiDrag: false, + delayStartGlobal: function delayStartGlobal(_ref) { + var dragged = _ref.dragEl; + dragEl$1 = dragged; + }, + delayEnded: function delayEnded() { + this.isMultiDrag = ~multiDragElements.indexOf(dragEl$1); + }, + setupClone: function setupClone(_ref2) { + var sortable = _ref2.sortable, + cancel = _ref2.cancel; + if (!this.isMultiDrag) return; + + for (var i = 0; i < multiDragElements.length; i++) { + multiDragClones.push(clone(multiDragElements[i])); + multiDragClones[i].sortableIndex = multiDragElements[i].sortableIndex; + multiDragClones[i].draggable = false; + multiDragClones[i].style['will-change'] = ''; + toggleClass(multiDragClones[i], this.options.selectedClass, false); + multiDragElements[i] === dragEl$1 && toggleClass(multiDragClones[i], this.options.chosenClass, false); + } + + sortable._hideClone(); + + cancel(); + }, + clone: function clone(_ref3) { + var sortable = _ref3.sortable, + rootEl = _ref3.rootEl, + dispatchSortableEvent = _ref3.dispatchSortableEvent, + cancel = _ref3.cancel; + if (!this.isMultiDrag) return; + + if (!this.options.removeCloneOnHide) { + if (multiDragElements.length && multiDragSortable === sortable) { + insertMultiDragClones(true, rootEl); + dispatchSortableEvent('clone'); + cancel(); + } + } + }, + showClone: function showClone(_ref4) { + var cloneNowShown = _ref4.cloneNowShown, + rootEl = _ref4.rootEl, + cancel = _ref4.cancel; + if (!this.isMultiDrag) return; + insertMultiDragClones(false, rootEl); + multiDragClones.forEach(function (clone) { + css(clone, 'display', ''); + }); + cloneNowShown(); + clonesHidden = false; + cancel(); + }, + hideClone: function hideClone(_ref5) { + var _this = this; + + var sortable = _ref5.sortable, + cloneNowHidden = _ref5.cloneNowHidden, + cancel = _ref5.cancel; + if (!this.isMultiDrag) return; + multiDragClones.forEach(function (clone) { + css(clone, 'display', 'none'); + + if (_this.options.removeCloneOnHide && clone.parentNode) { + clone.parentNode.removeChild(clone); + } + }); + cloneNowHidden(); + clonesHidden = true; + cancel(); + }, + dragStartGlobal: function dragStartGlobal(_ref6) { + var sortable = _ref6.sortable; + + if (!this.isMultiDrag && multiDragSortable) { + multiDragSortable.multiDrag._deselectMultiDrag(); + } + + multiDragElements.forEach(function (multiDragElement) { + multiDragElement.sortableIndex = index(multiDragElement); + }); // Sort multi-drag elements + + multiDragElements = multiDragElements.sort(function (a, b) { + return a.sortableIndex - b.sortableIndex; + }); + dragStarted = true; + }, + dragStarted: function dragStarted(_ref7) { + var _this2 = this; + + var sortable = _ref7.sortable; + if (!this.isMultiDrag) return; + + if (this.options.sort) { + // Capture rects, + // hide multi drag elements (by positioning them absolute), + // set multi drag elements rects to dragRect, + // show multi drag elements, + // animate to rects, + // unset rects & remove from DOM + sortable.captureAnimationState(); + + if (this.options.animation) { + multiDragElements.forEach(function (multiDragElement) { + if (multiDragElement === dragEl$1) return; + css(multiDragElement, 'position', 'absolute'); + }); + var dragRect = getRect(dragEl$1, false, true, true); + multiDragElements.forEach(function (multiDragElement) { + if (multiDragElement === dragEl$1) return; + setRect(multiDragElement, dragRect); + }); + folding = true; + initialFolding = true; + } + } + + sortable.animateAll(function () { + folding = false; + initialFolding = false; + + if (_this2.options.animation) { + multiDragElements.forEach(function (multiDragElement) { + unsetRect(multiDragElement); + }); + } // Remove all auxiliary multidrag items from el, if sorting enabled + + + if (_this2.options.sort) { + removeMultiDragElements(); + } + }); + }, + dragOver: function dragOver(_ref8) { + var target = _ref8.target, + completed = _ref8.completed, + cancel = _ref8.cancel; + + if (folding && ~multiDragElements.indexOf(target)) { + completed(false); + cancel(); + } + }, + revert: function revert(_ref9) { + var fromSortable = _ref9.fromSortable, + rootEl = _ref9.rootEl, + sortable = _ref9.sortable, + dragRect = _ref9.dragRect; + + if (multiDragElements.length > 1) { + // Setup unfold animation + multiDragElements.forEach(function (multiDragElement) { + sortable.addAnimationState({ + target: multiDragElement, + rect: folding ? getRect(multiDragElement) : dragRect + }); + unsetRect(multiDragElement); + multiDragElement.fromRect = dragRect; + fromSortable.removeAnimationState(multiDragElement); + }); + folding = false; + insertMultiDragElements(!this.options.removeCloneOnHide, rootEl); + } + }, + dragOverCompleted: function dragOverCompleted(_ref10) { + var sortable = _ref10.sortable, + isOwner = _ref10.isOwner, + insertion = _ref10.insertion, + activeSortable = _ref10.activeSortable, + parentEl = _ref10.parentEl, + putSortable = _ref10.putSortable; + var options = this.options; + + if (insertion) { + // Clones must be hidden before folding animation to capture dragRectAbsolute properly + if (isOwner) { + activeSortable._hideClone(); + } + + initialFolding = false; // If leaving sort:false root, or already folding - Fold to new location + + if (options.animation && multiDragElements.length > 1 && (folding || !isOwner && !activeSortable.options.sort && !putSortable)) { + // Fold: Set all multi drag elements's rects to dragEl's rect when multi-drag elements are invisible + var dragRectAbsolute = getRect(dragEl$1, false, true, true); + multiDragElements.forEach(function (multiDragElement) { + if (multiDragElement === dragEl$1) return; + setRect(multiDragElement, dragRectAbsolute); // Move element(s) to end of parentEl so that it does not interfere with multi-drag clones insertion if they are inserted + // while folding, and so that we can capture them again because old sortable will no longer be fromSortable + + parentEl.appendChild(multiDragElement); + }); + folding = true; + } // Clones must be shown (and check to remove multi drags) after folding when interfering multiDragElements are moved out + + + if (!isOwner) { + // Only remove if not folding (folding will remove them anyways) + if (!folding) { + removeMultiDragElements(); + } + + if (multiDragElements.length > 1) { + var clonesHiddenBefore = clonesHidden; + + activeSortable._showClone(sortable); // Unfold animation for clones if showing from hidden + + + if (activeSortable.options.animation && !clonesHidden && clonesHiddenBefore) { + multiDragClones.forEach(function (clone) { + activeSortable.addAnimationState({ + target: clone, + rect: clonesFromRect + }); + clone.fromRect = clonesFromRect; + clone.thisAnimationDuration = null; + }); + } + } else { + activeSortable._showClone(sortable); + } + } + } + }, + dragOverAnimationCapture: function dragOverAnimationCapture(_ref11) { + var dragRect = _ref11.dragRect, + isOwner = _ref11.isOwner, + activeSortable = _ref11.activeSortable; + multiDragElements.forEach(function (multiDragElement) { + multiDragElement.thisAnimationDuration = null; + }); + + if (activeSortable.options.animation && !isOwner && activeSortable.multiDrag.isMultiDrag) { + clonesFromRect = _extends({}, dragRect); + var dragMatrix = matrix(dragEl$1, true); + clonesFromRect.top -= dragMatrix.f; + clonesFromRect.left -= dragMatrix.e; + } + }, + dragOverAnimationComplete: function dragOverAnimationComplete() { + if (folding) { + folding = false; + removeMultiDragElements(); + } + }, + drop: function drop(_ref12) { + var evt = _ref12.originalEvent, + rootEl = _ref12.rootEl, + parentEl = _ref12.parentEl, + sortable = _ref12.sortable, + dispatchSortableEvent = _ref12.dispatchSortableEvent, + oldIndex = _ref12.oldIndex, + putSortable = _ref12.putSortable; + var toSortable = putSortable || this.sortable; + if (!evt) return; + var options = this.options, + children = parentEl.children; // Multi-drag selection + + if (!dragStarted) { + if (options.multiDragKey && !this.multiDragKeyDown) { + this._deselectMultiDrag(); + } + + toggleClass(dragEl$1, options.selectedClass, !~multiDragElements.indexOf(dragEl$1)); + + if (!~multiDragElements.indexOf(dragEl$1)) { + multiDragElements.push(dragEl$1); + dispatchEvent({ + sortable: sortable, + rootEl: rootEl, + name: 'select', + targetEl: dragEl$1, + originalEvt: evt + }); // Modifier activated, select from last to dragEl + + if (evt.shiftKey && lastMultiDragSelect && sortable.el.contains(lastMultiDragSelect)) { + var lastIndex = index(lastMultiDragSelect), + currentIndex = index(dragEl$1); + + if (~lastIndex && ~currentIndex && lastIndex !== currentIndex) { + // Must include lastMultiDragSelect (select it), in case modified selection from no selection + // (but previous selection existed) + var n, i; + + if (currentIndex > lastIndex) { + i = lastIndex; + n = currentIndex; + } else { + i = currentIndex; + n = lastIndex + 1; + } + + for (; i < n; i++) { + if (~multiDragElements.indexOf(children[i])) continue; + toggleClass(children[i], options.selectedClass, true); + multiDragElements.push(children[i]); + dispatchEvent({ + sortable: sortable, + rootEl: rootEl, + name: 'select', + targetEl: children[i], + originalEvt: evt + }); + } + } + } else { + lastMultiDragSelect = dragEl$1; + } + + multiDragSortable = toSortable; + } else { + multiDragElements.splice(multiDragElements.indexOf(dragEl$1), 1); + lastMultiDragSelect = null; + dispatchEvent({ + sortable: sortable, + rootEl: rootEl, + name: 'deselect', + targetEl: dragEl$1, + originalEvt: evt + }); + } + } // Multi-drag drop + + + if (dragStarted && this.isMultiDrag) { + // Do not "unfold" after around dragEl if reverted + if ((parentEl[expando].options.sort || parentEl !== rootEl) && multiDragElements.length > 1) { + var dragRect = getRect(dragEl$1), + multiDragIndex = index(dragEl$1, ':not(.' + this.options.selectedClass + ')'); + if (!initialFolding && options.animation) dragEl$1.thisAnimationDuration = null; + toSortable.captureAnimationState(); + + if (!initialFolding) { + if (options.animation) { + dragEl$1.fromRect = dragRect; + multiDragElements.forEach(function (multiDragElement) { + multiDragElement.thisAnimationDuration = null; + + if (multiDragElement !== dragEl$1) { + var rect = folding ? getRect(multiDragElement) : dragRect; + multiDragElement.fromRect = rect; // Prepare unfold animation + + toSortable.addAnimationState({ + target: multiDragElement, + rect: rect + }); + } + }); + } // Multi drag elements are not necessarily removed from the DOM on drop, so to reinsert + // properly they must all be removed + + + removeMultiDragElements(); + multiDragElements.forEach(function (multiDragElement) { + if (children[multiDragIndex]) { + parentEl.insertBefore(multiDragElement, children[multiDragIndex]); + } else { + parentEl.appendChild(multiDragElement); + } + + multiDragIndex++; + }); // If initial folding is done, the elements may have changed position because they are now + // unfolding around dragEl, even though dragEl may not have his index changed, so update event + // must be fired here as Sortable will not. + + if (oldIndex === index(dragEl$1)) { + var update = false; + multiDragElements.forEach(function (multiDragElement) { + if (multiDragElement.sortableIndex !== index(multiDragElement)) { + update = true; + return; + } + }); + + if (update) { + dispatchSortableEvent('update'); + } + } + } // Must be done after capturing individual rects (scroll bar) + + + multiDragElements.forEach(function (multiDragElement) { + unsetRect(multiDragElement); + }); + toSortable.animateAll(); + } + + multiDragSortable = toSortable; + } // Remove clones if necessary + + + if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') { + multiDragClones.forEach(function (clone) { + clone.parentNode && clone.parentNode.removeChild(clone); + }); + } + }, + nullingGlobal: function nullingGlobal() { + this.isMultiDrag = dragStarted = false; + multiDragClones.length = 0; + }, + destroyGlobal: function destroyGlobal() { + this._deselectMultiDrag(); + + off(document, 'pointerup', this._deselectMultiDrag); + off(document, 'mouseup', this._deselectMultiDrag); + off(document, 'touchend', this._deselectMultiDrag); + off(document, 'keydown', this._checkKeyDown); + off(document, 'keyup', this._checkKeyUp); + }, + _deselectMultiDrag: function _deselectMultiDrag(evt) { + if (typeof dragStarted !== "undefined" && dragStarted) return; // Only deselect if selection is in this sortable + + if (multiDragSortable !== this.sortable) return; // Only deselect if target is not item in this sortable + + if (evt && closest(evt.target, this.options.draggable, this.sortable.el, false)) return; // Only deselect if left click + + if (evt && evt.button !== 0) return; + + while (multiDragElements.length) { + var el = multiDragElements[0]; + toggleClass(el, this.options.selectedClass, false); + multiDragElements.shift(); + dispatchEvent({ + sortable: this.sortable, + rootEl: this.sortable.el, + name: 'deselect', + targetEl: el, + originalEvt: evt + }); + } + }, + _checkKeyDown: function _checkKeyDown(evt) { + if (evt.key === this.options.multiDragKey) { + this.multiDragKeyDown = true; + } + }, + _checkKeyUp: function _checkKeyUp(evt) { + if (evt.key === this.options.multiDragKey) { + this.multiDragKeyDown = false; + } + } + }; + return _extends(MultiDrag, { + // Static methods & properties + pluginName: 'multiDrag', + utils: { + /** + * Selects the provided multi-drag item + * @param {HTMLElement} el The element to be selected + */ + select: function select(el) { + var sortable = el.parentNode[expando]; + if (!sortable || !sortable.options.multiDrag || ~multiDragElements.indexOf(el)) return; + + if (multiDragSortable && multiDragSortable !== sortable) { + multiDragSortable.multiDrag._deselectMultiDrag(); + + multiDragSortable = sortable; + } + + toggleClass(el, sortable.options.selectedClass, true); + multiDragElements.push(el); + }, + + /** + * Deselects the provided multi-drag item + * @param {HTMLElement} el The element to be deselected + */ + deselect: function deselect(el) { + var sortable = el.parentNode[expando], + index = multiDragElements.indexOf(el); + if (!sortable || !sortable.options.multiDrag || !~index) return; + toggleClass(el, sortable.options.selectedClass, false); + multiDragElements.splice(index, 1); + } + }, + eventProperties: function eventProperties() { + var _this3 = this; + + var oldIndicies = [], + newIndicies = []; + multiDragElements.forEach(function (multiDragElement) { + oldIndicies.push({ + multiDragElement: multiDragElement, + index: multiDragElement.sortableIndex + }); // multiDragElements will already be sorted if folding + + var newIndex; + + if (folding && multiDragElement !== dragEl$1) { + newIndex = -1; + } else if (folding) { + newIndex = index(multiDragElement, ':not(.' + _this3.options.selectedClass + ')'); + } else { + newIndex = index(multiDragElement); + } + + newIndicies.push({ + multiDragElement: multiDragElement, + index: newIndex + }); + }); + return { + items: _toConsumableArray(multiDragElements), + clones: [].concat(multiDragClones), + oldIndicies: oldIndicies, + newIndicies: newIndicies + }; + }, + optionListeners: { + multiDragKey: function multiDragKey(key) { + key = key.toLowerCase(); + + if (key === 'ctrl') { + key = 'Control'; + } else if (key.length > 1) { + key = key.charAt(0).toUpperCase() + key.substr(1); + } + + return key; + } + } + }); + } + + function insertMultiDragElements(clonesInserted, rootEl) { + multiDragElements.forEach(function (multiDragElement, i) { + var target = rootEl.children[multiDragElement.sortableIndex + (clonesInserted ? Number(i) : 0)]; + + if (target) { + rootEl.insertBefore(multiDragElement, target); + } else { + rootEl.appendChild(multiDragElement); + } + }); + } + /** + * Insert multi-drag clones + * @param {[Boolean]} elementsInserted Whether the multi-drag elements are inserted + * @param {HTMLElement} rootEl + */ + + + function insertMultiDragClones(elementsInserted, rootEl) { + multiDragClones.forEach(function (clone, i) { + var target = rootEl.children[clone.sortableIndex + (elementsInserted ? Number(i) : 0)]; + + if (target) { + rootEl.insertBefore(clone, target); + } else { + rootEl.appendChild(clone); + } + }); + } + + function removeMultiDragElements() { + multiDragElements.forEach(function (multiDragElement) { + if (multiDragElement === dragEl$1) return; + multiDragElement.parentNode && multiDragElement.parentNode.removeChild(multiDragElement); + }); + } + + Sortable.mount(new AutoScrollPlugin()); + Sortable.mount(Remove, Revert); + + Sortable.mount(new SwapPlugin()); + Sortable.mount(new MultiDragPlugin()); + + return Sortable; + +})); diff --git a/WaterCloud.Web/wwwroot/js/Sortable/Sortable.min.js b/WaterCloud.Web/wwwroot/js/Sortable/Sortable.min.js new file mode 100644 index 0000000..eba0614 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/Sortable/Sortable.min.js @@ -0,0 +1,2 @@ +/*! Sortable 1.10.2 - MIT | git://github.com/SortableJS/Sortable.git */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).Sortable=e()}(this,function(){"use strict";function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(){return(a=Object.assign||function(t){for(var e=1;e"===e[0]&&(e=e.substring(1)),t)try{if(t.matches)return t.matches(e);if(t.msMatchesSelector)return t.msMatchesSelector(e);if(t.webkitMatchesSelector)return t.webkitMatchesSelector(e)}catch(t){return!1}return!1}}function P(t,e,n,o){if(t){n=n||document;do{if(null!=e&&(">"===e[0]?t.parentNode===n&&h(t,e):h(t,e))||o&&t===n)return t;if(t===n)break}while(t=(i=t).host&&i!==document&&i.host.nodeType?i.host:i.parentNode)}var i;return null}var f,p=/\s+/g;function k(t,e,n){if(t&&e)if(t.classList)t.classList[n?"add":"remove"](e);else{var o=(" "+t.className+" ").replace(p," ").replace(" "+e+" "," ");t.className=(o+(n?" "+e:"")).replace(p," ")}}function R(t,e,n){var o=t&&t.style;if(o){if(void 0===n)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(t,""):t.currentStyle&&(n=t.currentStyle),void 0===e?n:n[e];e in o||-1!==e.indexOf("webkit")||(e="-webkit-"+e),o[e]=n+("string"==typeof n?"":"px")}}function v(t,e){var n="";if("string"==typeof t)n=t;else do{var o=R(t,"transform");o&&"none"!==o&&(n=o+" "+n)}while(!e&&(t=t.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function g(t,e,n){if(t){var o=t.getElementsByTagName(e),i=0,r=o.length;if(n)for(;i=e.left-n&&r<=e.right+n,i=a>=e.top-n&&a<=e.bottom+n;return n&&o&&i?l=t:void 0}}),l}((t=t.touches?t.touches[0]:t).clientX,t.clientY);if(e){var n={};for(var o in t)t.hasOwnProperty(o)&&(n[o]=t[o]);n.target=n.rootEl=e,n.preventDefault=void 0,n.stopPropagation=void 0,e[j]._onDragOver(n)}}}function kt(t){z&&z.parentNode[j]._isOutsideThisEl(t.target)}function Rt(t,e){if(!t||!t.nodeType||1!==t.nodeType)throw"Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(t));this.el=t,this.options=e=a({},e),t[j]=this;var n={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(t.nodeName)?">li":">*",swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Ot(t,this.options)},ghostClass:"sortable-ghost",chosenClass:"sortable-chosen",dragClass:"sortable-drag",ignore:"a, img",filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(t,e){t.setData("Text",e.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:"data-id",delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:"sortable-fallback",fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:!1!==Rt.supportPointer&&"PointerEvent"in window,emptyInsertThreshold:5};for(var o in O.initializePlugins(this,t,n),n)o in e||(e[o]=n[o]);for(var i in At(e),this)"_"===i.charAt(0)&&"function"==typeof this[i]&&(this[i]=this[i].bind(this));this.nativeDraggable=!e.forceFallback&&xt,this.nativeDraggable&&(this.options.touchStartThreshold=1),e.supportPointer?u(t,"pointerdown",this._onTapStart):(u(t,"mousedown",this._onTapStart),u(t,"touchstart",this._onTapStart)),this.nativeDraggable&&(u(t,"dragover",this),u(t,"dragenter",this)),bt.push(this.el),e.store&&e.store.get&&this.sort(e.store.get(this)||[]),a(this,T())}function Xt(t,e,n,o,i,r,a,l){var s,c,u=t[j],d=u.options.onMove;return!window.CustomEvent||w||E?(s=document.createEvent("Event")).initEvent("move",!0,!0):s=new CustomEvent("move",{bubbles:!0,cancelable:!0}),s.to=e,s.from=t,s.dragged=n,s.draggedRect=o,s.related=i||e,s.relatedRect=r||X(e),s.willInsertAfter=l,s.originalEvent=a,t.dispatchEvent(s),d&&(c=d.call(u,s,a)),c}function Yt(t){t.draggable=!1}function Bt(){Dt=!1}function Ft(t){for(var e=t.tagName+t.className+t.src+t.href+t.textContent,n=e.length,o=0;n--;)o+=e.charCodeAt(n);return o.toString(36)}function Ht(t){return setTimeout(t,0)}function Lt(t){return clearTimeout(t)}Rt.prototype={constructor:Rt,_isOutsideThisEl:function(t){this.el.contains(t)||t===this.el||(ht=null)},_getDirection:function(t,e){return"function"==typeof this.options.direction?this.options.direction.call(this,t,e,z):this.options.direction},_onTapStart:function(e){if(e.cancelable){var n=this,o=this.el,t=this.options,i=t.preventOnFilter,r=e.type,a=e.touches&&e.touches[0]||e.pointerType&&"touch"===e.pointerType&&e,l=(a||e).target,s=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||l,c=t.filter;if(function(t){St.length=0;var e=t.getElementsByTagName("input"),n=e.length;for(;n--;){var o=e[n];o.checked&&St.push(o)}}(o),!z&&!(/mousedown|pointerdown/.test(r)&&0!==e.button||t.disabled||s.isContentEditable||(l=P(l,t.draggable,o,!1))&&l.animated||Z===l)){if(J=F(l),et=F(l,t.draggable),"function"==typeof c){if(c.call(this,e,l,this))return W({sortable:n,rootEl:s,name:"filter",targetEl:l,toEl:o,fromEl:o}),K("filter",n,{evt:e}),void(i&&e.cancelable&&e.preventDefault())}else if(c&&(c=c.split(",").some(function(t){if(t=P(s,t.trim(),o,!1))return W({sortable:n,rootEl:t,name:"filter",targetEl:l,fromEl:o,toEl:o}),K("filter",n,{evt:e}),!0})))return void(i&&e.cancelable&&e.preventDefault());t.handle&&!P(s,t.handle,o,!1)||this._prepareDragStart(e,a,l)}}},_prepareDragStart:function(t,e,n){var o,i=this,r=i.el,a=i.options,l=r.ownerDocument;if(n&&!z&&n.parentNode===r){var s=X(n);if(q=r,G=(z=n).parentNode,V=z.nextSibling,Z=n,ot=a.group,rt={target:Rt.dragged=z,clientX:(e||t).clientX,clientY:(e||t).clientY},ct=rt.clientX-s.left,ut=rt.clientY-s.top,this._lastX=(e||t).clientX,this._lastY=(e||t).clientY,z.style["will-change"]="all",o=function(){K("delayEnded",i,{evt:t}),Rt.eventCanceled?i._onDrop():(i._disableDelayedDragEvents(),!c&&i.nativeDraggable&&(z.draggable=!0),i._triggerDragStart(t,e),W({sortable:i,name:"choose",originalEvent:t}),k(z,a.chosenClass,!0))},a.ignore.split(",").forEach(function(t){g(z,t.trim(),Yt)}),u(l,"dragover",Pt),u(l,"mousemove",Pt),u(l,"touchmove",Pt),u(l,"mouseup",i._onDrop),u(l,"touchend",i._onDrop),u(l,"touchcancel",i._onDrop),c&&this.nativeDraggable&&(this.options.touchStartThreshold=4,z.draggable=!0),K("delayStart",this,{evt:t}),!a.delay||a.delayOnTouchOnly&&!e||this.nativeDraggable&&(E||w))o();else{if(Rt.eventCanceled)return void this._onDrop();u(l,"mouseup",i._disableDelayedDrag),u(l,"touchend",i._disableDelayedDrag),u(l,"touchcancel",i._disableDelayedDrag),u(l,"mousemove",i._delayedDragTouchMoveHandler),u(l,"touchmove",i._delayedDragTouchMoveHandler),a.supportPointer&&u(l,"pointermove",i._delayedDragTouchMoveHandler),i._dragStartTimer=setTimeout(o,a.delay)}}},_delayedDragTouchMoveHandler:function(t){var e=t.touches?t.touches[0]:t;Math.max(Math.abs(e.clientX-this._lastX),Math.abs(e.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){z&&Yt(z),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var t=this.el.ownerDocument;d(t,"mouseup",this._disableDelayedDrag),d(t,"touchend",this._disableDelayedDrag),d(t,"touchcancel",this._disableDelayedDrag),d(t,"mousemove",this._delayedDragTouchMoveHandler),d(t,"touchmove",this._delayedDragTouchMoveHandler),d(t,"pointermove",this._delayedDragTouchMoveHandler)},_triggerDragStart:function(t,e){e=e||"touch"==t.pointerType&&t,!this.nativeDraggable||e?this.options.supportPointer?u(document,"pointermove",this._onTouchMove):u(document,e?"touchmove":"mousemove",this._onTouchMove):(u(z,"dragend",this),u(q,"dragstart",this._onDragStart));try{document.selection?Ht(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch(t){}},_dragStarted:function(t,e){if(vt=!1,q&&z){K("dragStarted",this,{evt:e}),this.nativeDraggable&&u(document,"dragover",kt);var n=this.options;t||k(z,n.dragClass,!1),k(z,n.ghostClass,!0),Rt.active=this,t&&this._appendGhost(),W({sortable:this,name:"start",originalEvent:e})}else this._nulling()},_emulateDragOver:function(){if(at){this._lastX=at.clientX,this._lastY=at.clientY,Nt();for(var t=document.elementFromPoint(at.clientX,at.clientY),e=t;t&&t.shadowRoot&&(t=t.shadowRoot.elementFromPoint(at.clientX,at.clientY))!==e;)e=t;if(z.parentNode[j]._isOutsideThisEl(t),e)do{if(e[j]){if(e[j]._onDragOver({clientX:at.clientX,clientY:at.clientY,target:t,rootEl:e})&&!this.options.dragoverBubble)break}t=e}while(e=e.parentNode);It()}},_onTouchMove:function(t){if(rt){var e=this.options,n=e.fallbackTolerance,o=e.fallbackOffset,i=t.touches?t.touches[0]:t,r=U&&v(U,!0),a=U&&r&&r.a,l=U&&r&&r.d,s=Ct&>&&b(gt),c=(i.clientX-rt.clientX+o.x)/(a||1)+(s?s[0]-Et[0]:0)/(a||1),u=(i.clientY-rt.clientY+o.y)/(l||1)+(s?s[1]-Et[1]:0)/(l||1);if(!Rt.active&&!vt){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))o.right+10||t.clientX<=o.right&&t.clientY>o.bottom&&t.clientX>=o.left:t.clientX>o.right&&t.clientY>o.top||t.clientX<=o.right&&t.clientY>o.bottom+10}(n,a,this)&&!g.animated){if(g===z)return A(!1);if(g&&l===n.target&&(s=g),s&&(i=X(s)),!1!==Xt(q,l,z,o,s,i,n,!!s))return O(),l.appendChild(z),G=l,N(),A(!0)}else if(s.parentNode===l){i=X(s);var v,m,b,y=z.parentNode!==l,w=!function(t,e,n){var o=n?t.left:t.top,i=n?t.right:t.bottom,r=n?t.width:t.height,a=n?e.left:e.top,l=n?e.right:e.bottom,s=n?e.width:e.height;return o===a||i===l||o+r/2===a+s/2}(z.animated&&z.toRect||o,s.animated&&s.toRect||i,a),E=a?"top":"left",D=Y(s,"top","top")||Y(z,"top","top"),S=D?D.scrollTop:void 0;if(ht!==s&&(m=i[E],yt=!1,wt=!w&&e.invertSwap||y),0!==(v=function(t,e,n,o,i,r,a,l){var s=o?t.clientY:t.clientX,c=o?n.height:n.width,u=o?n.top:n.left,d=o?n.bottom:n.right,h=!1;if(!a)if(l&&pt 1) { + v = '0' + v; + v = v.substr(v.length - 2); + } + return v; + } + else if (t === 'y') { + return (date.getFullYear() + '').substr(4 - all.length); + } + return all; + }); + return format; +}; + +//template魔板处理后台时间戳转日期方法 +function timestamp(value, format) { + var date = new Date(value); + var y = date.getFullYear(); + var m = date.getMonth() + 1; + m = m < 10 ? ('0' + m) : m; + var d = date.getDate(); + d = d < 10 ? ('0' + d) : d; + var h = date.getHours(); + h = h < 10 ? ('0' + h) : h; + var minute = date.getMinutes(); + var second = date.getSeconds(); + minute = minute < 10 ? ('0' + minute) : minute; + second = second < 10 ? ('0' + second) : second; + return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second; +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/art-template/template-web.js b/WaterCloud.Web/wwwroot/js/art-template/template-web.js new file mode 100644 index 0000000..7c400e3 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/art-template/template-web.js @@ -0,0 +1,3 @@ +/*! art-template@4.13.2 for browser | https://github.com/aui/art-template */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.template=t():e.template=t()}("undefined"!=typeof self?self:this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var n={};return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e["default"]}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=4)}([function(e,t,n){"use strict";var r=n(6),i=n(2),o=n(22),s=function(e,t){t.onerror(e,t);var n=function(){return"{Template Error}"};return n.mappings=[],n.sourcesContent=[],n},a=function u(e){var t=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};"string"!=typeof e?t=e:t.source=e,t=i.$extend(t),e=t.source,!0===t.debug&&(t.cache=!1,t.minimize=!1,t.compileDebug=!0),t.compileDebug&&(t.minimize=!1),t.filename&&(t.filename=t.resolveFilename(t.filename,t));var n=t.filename,a=t.cache,c=t.caches;if(a&&n){var l=c.get(n);if(l)return l}if(!e)try{e=t.loader(n,t),t.source=e}catch(m){var f=new o({name:"CompileError",path:n,message:"template not found: "+m.message,stack:m.stack});if(t.bail)throw f;return s(f,t)}var p=void 0,h=new r(t);try{p=h.build()}catch(f){if(f=new o(f),t.bail)throw f;return s(f,t)}var d=function(e,n){try{return p(e,n)}catch(f){if(!t.compileDebug)return t.cache=!1,t.compileDebug=!0,u(t)(e,n);if(f=new o(f),t.bail)throw f;return s(f,t)()}};return d.mappings=p.mappings,d.sourcesContent=p.sourcesContent,d.toString=function(){return p.toString()},a&&n&&c.set(n,d),d};a.Compiler=r,e.exports=a},function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=/((['"])(?:(?!\2|\\).|\\(?:\r\n|[\s\S]))*(\2)?|`(?:[^`\\$]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{[^}]*\}?)*\}?)*(`)?)|(\/\/.*)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|(\/(?!\*)(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)+\/(?:(?!\s*(?:\b|[\u0080-\uFFFF$\\'"~({]|[+\-!](?!=)|\.?\d))|[gmiyu]{1,5}\b(?![\u0080-\uFFFF$\\]|\s*(?:[+\-*%&|^<>!=?({]|\/(?![\/*])))))|(0[xX][\da-fA-F]+|0[oO][0-7]+|0[bB][01]+|(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?)|((?!\d)(?:(?!\s)[$\w\u0080-\uFFFF]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+)|(--|\+\+|&&|\|\||=>|\.{3}|(?:[+\-\/%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2})=?|[?~.,:;[\](){}])|(\s+)|(^$|[\s\S])/g,t.matchToToken=function(e){var t={type:"invalid",value:e[0]};return e[1]?(t.type="string",t.closed=!(!e[3]&&!e[4])):e[5]?t.type="comment":e[6]?(t.type="comment",t.closed=!!e[7]):e[8]?t.type="regex":e[9]?t.type="number":e[10]?t.type="name":e[11]?t.type="punctuator":e[12]&&(t.type="whitespace"),t}},function(e,t,n){"use strict";function r(){this.$extend=function(e){return e=e||{},o(e,e instanceof r?e:this)}}var i=n(10),o=n(12),s=n(13),a=n(14),u=n(15),c=n(16),l=n(17),f=n(18),p=n(19),h=n(21),d="undefined"==typeof window,m={source:null,filename:null,rules:[f,l],escape:!0,debug:!!d&&"production"!==process.env.NODE_ENV,bail:!0,cache:!0,minimize:!0,compileDebug:!1,resolveFilename:h,include:s,htmlMinifier:p,htmlMinifierOptions:{collapseWhitespace:!0,minifyCSS:!0,minifyJS:!0,ignoreCustomFragments:[]},onerror:a,loader:c,caches:u,root:"/",extname:".art",ignore:[],imports:i};r.prototype=m,e.exports=new r},function(e,t){},function(e,t,n){"use strict";var r=n(5),i=n(0),o=n(23),s=function(e,t){return t instanceof Object?r({filename:e},t):i({filename:e,source:t})};s.render=r,s.compile=i,s.defaults=o,e.exports=s},function(e,t,n){"use strict";var r=n(0),i=function(e,t,n){return r(e,n)(t)};e.exports=i},function(e,t,n){"use strict";function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t|\([\w\W]*?\))\s*{[\s;]*$)/,"$1})"],[/(^[\w\W]*?\([\w\W]*?\)\s*{[\s;]*$)/,"$1}"]],n=0;n2&&arguments[2]!==undefined?arguments[2]:{},o=[new i("string",e)],s=0;sd&&(p=new i("string",v.slice(d,h.index),p),m.push(p)),p=new i("expression",h[0],p),h[0]=r(p),p.script=a.use.apply(n,h),m.push(p),d=h.index+h[0].length;d]/;o.$escape=function(e){return r(n(e))},o.$each=function(e,t){if(Array.isArray(e))for(var n=0,r=e.length;n {{"+n+"}}")};switch("#"===t&&h("#value","@value"),p){case"set":i="var "+u.join("").trim();break;case"if":i="if("+u.join("").trim()+"){";break;case"else":var d=u.indexOf("if");~d?(u.splice(0,d+1),i="}else if("+u.join("").trim()+"){"):i="}else{";break;case"/if":i="}";break;case"each":l=r._split(a),l.shift(),"as"===l[1]&&(h("each object as value index","each object value index"),l.splice(1,1));i="$each("+(l[0]||"$data")+",function("+(l[1]||"$value")+","+(l[2]||"$index")+"){";break;case"/each":i="})";break;case"block":l=r._split(a),l.shift(),i="block("+l.join(",").trim()+",function(){";break;case"/block":i="})";break;case"echo":p="print",h("echo value","value");case"print":case"include":case"extend":if(0!==u.join("").trim().indexOf("(")){l=r._split(a),l.shift(),i=p+"("+l.join(",")+")";break}default:if(~u.indexOf("|")){var m=a.reduce(function(e,t){var n=t.value,r=t.type;return"|"===n?e.push([]):"whitespace"!==r&&"comment"!==r&&(e.length||e.push([]),":"===n&&1===e[e.length-1].length?h("value | filter: argv","value | filter argv"):e[e.length-1].push(t)),e},[]).map(function(e){return r._split(e)});i=m.reduce(function(e,t){var n=t.shift();return t.unshift(e),"$imports."+n+"("+t.join(",")+")"},m.shift().join(" ").trim())}f=f||"escape"}return c.code=i,c.output=f,c},_split:function(e){e=e.filter(function(e){var t=e.type;return"whitespace"!==t&&"comment"!==t});for(var t=0,n=e.shift(),r=/\]|\)/,i=[[n]];t/,use:function(e,t,n,r){return n={"-":"raw","=":"escape","":!1,"==":"raw","=#":"raw"}[n],t&&(r="/*"+r+"*/",n=!1),{code:r,output:n}}};e.exports=r},function(e,t,n){"use strict";function r(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t> ":" ")+n+"| "+e}).join("\n");return(r||"anonymous")+":"+i+":"+o+"\n"+f+"\n\n"+t+": "+a+(s?"\n generated: "+s:"")}var a=function(e){function t(e){r(this,t);var n=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e.message));return n.name="TemplateError",n.message=s(e),Error.captureStackTrace&&Error.captureStackTrace(n,n.constructor),n}return o(t,e),t}(Error);e.exports=a},function(e,t,n){"use strict";e.exports=n(2)}])}); \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/chat.js b/WaterCloud.Web/wwwroot/js/chat.js new file mode 100644 index 0000000..1b89291 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/chat.js @@ -0,0 +1,135 @@ +"use strict"; +//const connection = new signalR.HubConnectionBuilder().withUrl("https://watercloud.vip/chatHub") +const connection = new signalR.HubConnectionBuilder().withUrl("/chatHub") + .configureLogging(signalR.LogLevel.Information).build(); + +connection.serverTimeoutInMilliseconds = 24e4; +connection.keepAliveIntervalInMilliseconds = 12e4; +connection.start().then(function () { + //传入token值 + connection.invoke("SendLogin", "").catch(err => console.error("发送失败:" + err.toString())); + console.log("signalr连接成功"); +}).catch(function (ex) { + console.log("signalr连接失败" + ex); + //SignalR JavaScript 客户端不会自动重新连接,必须编写代码将手动重新连接你的客户端 + setTimeout(start(), 5000); + +}); + + +function start() { + try { + connection.start(); + console.log("connected"); + } catch (err) { + console.log(err); + setTimeout(start(), 5000); + } +}; +connection.on("ReceiveMessage", function (msg) { + var data = JSON.parse(msg); + layui.use(['notice','common'], function () { + var notice = layui.notice; + var common = layui.common; + if (data.F_MessageType == 0) { + notice.options = { + positionClass: "toast-bottom-right",//弹出的位置, + onclick: function () { + common.ajax({ + url: "/InfoManage/Message/ReadMsgForm", + data: { keyValue: data.F_Id }, + type: 'POST', + success: function () { + var title = '通知---' + data.F_CreatorUserName, + noticeTime = data.F_CreatorTime, + content = data.F_MessageInfo; + var html = '
    \n' + + '

    ' + title + '

    \n' + + '
    ' + content + '
    \n' + + '
    \n'; + parent.layer.open({ + type: 1, + title: '通知' + '' + noticeTime + '', + area: '150px;', + shade: 0.8, + id: 'layuimini-notice', + btn: ['确定'], + btnAlign: 'c', + moveType: 1, + content: html + }); + } + }); + } + }; + notice.success(data.F_MessageInfo); + } + else if (data.F_MessageType == 1) { + notice.options = { + positionClass: "toast-bottom-right",//弹出的位置, + onclick: function () { + common.ajax({ + url: "/InfoManage/Message/ReadMsgForm", + data: { keyValue: data.F_Id }, + type: 'POST', + success: function () { + var title = '私信---' + data.F_CreatorUserName, + noticeTime = data.F_CreatorTime, + content = data.F_MessageInfo; + var html = '
    \n' + + '

    ' + title + '

    \n' + + '
    ' + content + '
    \n' + + '
    \n'; + parent.layer.open({ + type: 1, + title: '私信' + '' + noticeTime + '', + area: '150px;', + shade: 0.8, + id: 'layuimini-notice', + btn: ['确定'], + btnAlign: 'c', + moveType: 1, + content: html + }); + } + }); + }, + }; + notice.warning(data.F_MessageInfo); + } + else { + notice.options = { + positionClass: "toast-bottom-right",//弹出的位置, + onclick: function () { + common.ajax({ + url: "/InfoManage/Message/ReadMsgForm", + data: { keyValue: data.F_Id }, + type: 'POST', + success: function () { + $("[layuimini-href='" + data.F_Href + "']", ".layuimini-menu-left").click(); + } + }); + } + }; + notice.error(data.F_MessageInfo); + } + $("#noticeMarker").html(""); + }) +}); +//下面测试断线重连机制 , +//重连之前调用 (只有在掉线的一瞬间,只进入一次) +connection.onreconnecting(function(error) { + console.log("重连中..."); +}); +//(默认4次重连),任何一次只要回调成功,调用 +connection.onreconnected(function(connectionId){ + console.log("重连成功"); +}); +//(默认4次重连) 全部都失败后,调用 +connection.onclose(function(error){ + console.log('重连失败'); +}); +//关闭连接方法 +window.onbeforeunload = function (e) { + connection.stop(); +}; \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/cookie/jquery.cookie.js b/WaterCloud.Web/wwwroot/js/cookie/jquery.cookie.js new file mode 100644 index 0000000..8e8e1d9 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/cookie/jquery.cookie.js @@ -0,0 +1,92 @@ +/** + * Cookie plugin + * + * Copyright (c) 2006 Klaus Hartl (stilbuero.de) + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + */ + +/** + * Create a cookie with the given name and value and other optional parameters. + * + * @example $.cookie('the_cookie', 'the_value'); + * @desc Set the value of a cookie. + * @example $.cookie('the_cookie', 'the_value', {expires: 7, path: '/', domain: 'jquery.com', secure: true}); + * @desc Create a cookie with all available options. + * @example $.cookie('the_cookie', 'the_value'); + * @desc Create a session cookie. + * @example $.cookie('the_cookie', null); + * @desc Delete a cookie by passing null as value. + * + * @param String name The name of the cookie. + * @param String value The value of the cookie. + * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. + * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. + * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. + * If set to null or omitted, the cookie will be a session cookie and will not be retained + * when the the browser exits. + * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). + * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). + * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will + * require a secure protocol (like HTTPS). + * @type undefined + * + * @name $.cookie + * @cat Plugins/Cookie + * @author Klaus Hartl/klaus.hartl@stilbuero.de + */ + +/** + * Get the value of a cookie with the given name. + * + * @example $.cookie('the_cookie'); + * @desc Get the value of a cookie. + * + * @param String name The name of the cookie. + * @return The value of the cookie. + * @type String + * + * @name $.cookie + * @cat Plugins/Cookie + * @author Klaus Hartl/klaus.hartl@stilbuero.de + */ +jQuery.cookie = function(name, value, options) { + if (typeof value != 'undefined') { // name and value given, set cookie + options = options || {}; + if (value === null) { + value = ''; + options.expires = -1; + } + var expires = ''; + if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) { + var date; + if (typeof options.expires == 'number') { + date = new Date(); + date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000)); + } else { + date = options.expires; + } + expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE + } + var path = options.path ? '; path=' + options.path : ''; + var domain = options.domain ? '; domain=' + options.domain : ''; + var secure = options.secure ? '; secure' : ''; + document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join(''); + } else { // only name given, get cookie + var cookieValue = null; + if (document.cookie && document.cookie != '') { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = jQuery.trim(cookies[i]); + // Does this cookie string begin with the name we want? + if (cookie.substring(0, name.length + 1) == (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; + } +}; \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/framework-clientdata.js b/WaterCloud.Web/wwwroot/js/framework-clientdata.js new file mode 100644 index 0000000..62581b3 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/framework-clientdata.js @@ -0,0 +1,56 @@ +var clients = {}; +var currentUser = {}; +$(function () { + if (!!top.clients && top.clients.hasOwnProperty("dataItems")) { + clients = top.clients; + } + else { + clients = $.clientsInit(); + } + if (!!top.currentUser && top.clients.hasOwnProperty("F_Id")) { + currentUser = top.currentUser; + } + else { + currentUser = $.userInit(); + } +}) +$.clientsInit = function () { + var dataJson = { + dataItems: [], + authorizeButton: [], + authorizeFields: [], + moduleFields: [], + }; + var init = function () { + $.ajax({ + url: "/ClientsData/GetClientsDataJson?v=" + new Date().Format("yyyy-MM-dd hh:mm:ss"), + type: "get", + dataType: "json", + async: false, + success: function (data) { + dataJson.dataItems = data.dataItems; + dataJson.authorizeButton = data.authorizeButton; + dataJson.authorizeFields = data.authorizeFields; + dataJson.moduleFields = data.moduleFields; + } + }); + } + init(); + return dataJson; +} +$.userInit = function () { + var dataJson = {}; + var init = function () { + $.ajax({ + url: "/ClientsData/GetUserCode?v=" + new Date().Format("yyyy-MM-dd hh:mm:ss"), + type: "get", + dataType: "json", + async: false, + success: function (data) { + dataJson = data; + } + }); + } + init(); + return dataJson; +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/framework-ui.js b/WaterCloud.Web/wwwroot/js/framework-ui.js new file mode 100644 index 0000000..1f68681 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/framework-ui.js @@ -0,0 +1,285 @@ +$(function () { + //document.body.className = localStorage.getItem('config-skin'); + //$("[data-toggle='tooltip']").tooltip(); +}) +//获取参数 +$.request = function (name) { + var search = location.search.slice(1); + var arr = search.split("&"); + for (var i = 0; i < arr.length; i++) { + var ar = arr[i].split("="); + if (ar[0] == name) { + if (unescape(ar[1]) == 'undefined') { + return ""; + } else { + return unescape(ar[1]); + } + } + } + return ""; +} +//json拼接 +$.jsonWhere = function (data, action) { + if (action == null) return; + var reval = new Array(); + $(data).each(function (i, v) { + if (action(v)) { + reval.push(v); + } + }) + return reval; +} +//select绑定 +$.fn.bindSelect = function (options) { + var defaults = { + id: "id", + text: "text", + search: false, + url: "", + param: [], + change: null, + data: null, + checked: 0, + }; + var options = $.extend(defaults, options); + var $element = $(this); + if (options.data != null) { + $.each(options.data, function (i) { + if (options.id == "") { + var temp = $("").val(i).html(options.data[i]); + //字典 + if (i == options.checked) { + temp.prop("selected", true); + } + $element.append(temp); + } + else { + var temp = $("").val(options.data[i][options.id]).html(options.data[i][options.text]); + //list + if (options.data[i][options.id] == options.checked) { + temp.prop("selected", true); + } + $element.append(temp); + } + }); + $element.on("change", function (e) { + if (options.change != null) { + options.change(options.data[$(this).find("option:selected").index()]); + } + }); + } + else if (options.url != "") { + //ie缓存问题 + if (options.url.indexOf("?") >= 0) { + options.url = options.url + '&v=' + new Date().Format("yyyy-MM-dd hh:mm:ss"); + } + else { + options.url = options.url + '?v=' + new Date().Format("yyyy-MM-dd hh:mm:ss"); + } + $.ajax({ + url: options.url, + data: options.param, + dataType: "json", + async: false, + success: function (data) { + $.each(data, function (i) { + if (options.id == "") { + var temp = $("").val(data[i]).html(data[i]); + //字典 + if (i == options.checked) { + temp.prop("selected", true); + } + $element.append(temp); + } + else { + var temp = $("").val(data[i][options.id]).html(data[i][options.text]); + //list + if (data[i][options.id] == options.checked) { + temp.prop("selected", true); + } + $element.append(temp); + } + $element.on("change", function (e) { + if (options.change != null) { + options.change(options.data[$(this).find("option:selected").index()]); + } + }); + }) + } + }); + } +} +//radio绑定 +$.fn.bindRadio = function (options) { + var defaults = { + id: "id", + text: "text", + search: false, + url: "", + param: [], + change: null, + data: null, + checked: 0, + filterName: "" + }; + var options = $.extend(defaults, options); + var $element = $(this); + if (options.data != null) { + $.each(options.data, function (i) { + if (!options.id) { + var temp = $("").val(i).attr("title", options.data[i]).attr("type", "radio").attr("name", $element.attr("id")); + //字典 + if (!options.filterName) { + temp.attr("lay-filter", $element.attr("id")); + } + else { + temp.attr("lay-filter", filterName); + } + if (i == options.checked) { + temp.prop("checked", "true"); + } + + $element.append(temp); + } + else { + var temp = $("").val(options.data[i][options.id]).attr("title", options.data[i][options.text]).attr("type", "radio").attr("name", options.id); + //list + if (!options.filterName) { + temp.attr("lay-filter", $element.attr("id")); + } + else { + temp.attr("lay-filter", filterName); + } + if (options.data[i][options.id] == options.checked) { + temp.prop("checked", "true"); + } + $element.append(temp); + } + }); + } + else if (options.url != "") { + //ie缓存问题 + if (options.url.indexOf("?") >= 0) { + options.url = options.url + '&v=' + new Date().Format("yyyy-MM-dd hh:mm:ss"); + } + else { + options.url = options.url + '?v=' + new Date().Format("yyyy-MM-dd hh:mm:ss"); + } + $.ajax({ + url: options.url, + data: options.param, + dataType: "json", + async: false, + success: function (data) { + $.each(data, function (i) { + if (!options.id) { + var temp = $("").val(data[i]).attr("title", data[i]).attr("type", "radio").attr("name", $element.attr("id")); + //字典 + if (!options.filterName) { + temp.attr("lay-filter", $element.attr("id")); + } + else { + temp.attr("lay-filter", filterName); + } + if (i == options.checked) { + temp.prop("checked", "true"); + } + $element.append(temp); + } + else { + var temp = $("").val(data[i][options.id]).attr("title", data[i][options.text]).attr("type", "radio").attr("name", $element.attr("id")); + //list + if (!options.filterName) { + temp.attr("lay-filter", $element.attr("id")); + } + else { + temp.attr("lay-filter", filterName); + } + if (data[i][options.id] == options.checked) { + temp.prop("checked", "true"); + } + $element.append(temp); + } + }); + } + }); + } +} +// 时间格式方法 +Date.prototype.Format = function (fmt) { + var o = { + + "M+": this.getMonth() + 1, //月份  + + "d+": this.getDate(), //日  + + "h+": this.getHours(), //小时  + + "m+": this.getMinutes(), //分  + + "s+": this.getSeconds(), //秒  + + "q+": Math.floor((this.getMonth() + 3) / 3), //季度  + + "S": this.getMilliseconds() //毫秒  + + }; + + if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); + + for (var k in o) + + if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); + return fmt; +} +Date.prototype.formatDate = function () { //author: meizz + var myyear = this.getFullYear(); + var mymonth = this.getMonth() + 1; + var myweekday = this.getDate(); + var myhour = this.getHours(); + var myminute = this.getMinutes(); + var second = this.getSeconds(); + if (mymonth < 10) { + mymonth = "0" + mymonth; + } + if (myweekday < 10) { + myweekday = "0" + myweekday; + } + if (myhour < 10) { + myhour = "0" + myhour; + } + if (myminute < 10) { + myminute = "0" + myminute; + } + if (second < 10) { + second = "0" + second; + } + return (myyear.toString() + mymonth.toString() + myweekday.toString() + myhour.toString() + myminute.toString() + second.toString()); +}; +//集合id +function uuid() { + var s = []; + var hexDigits = "0123456789abcdef"; + for (var i = 0; i < 36; i++) { + s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); + } + s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010 + s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01 + s[8] = s[13] = s[18] = s[23] = "-"; + + var uuid = s.join(""); + return uuid; +} +//父窗体方法 +Window.prototype.parentWindow = function () { //author: meizz + var index = parent.layer.getFrameIndex(this.name); + return window.top.iframesList[index]; +}; +function setIframeHeight(iframe) { + if (iframe) { + var iframeWin = iframe.contentWindow || iframe.contentDocument.parentWindow; + if (iframeWin.document.body) { + iframe.height = iframeWin.document.documentElement.scrollHeight || iframeWin.document.body.scrollHeight; + } + } +}; \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-config.js b/WaterCloud.Web/wwwroot/js/lay-config.js new file mode 100644 index 0000000..f835a33 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-config.js @@ -0,0 +1,55 @@ +/** + * date:2019/08/16 + * author:Mr.Chung + * description:此处放layui自定义扩展 + */ +var version; +window.rootPath = (function (src) { + src = document.scripts[document.scripts.length - 1].src; + //获取版本号 + version = src.substring(src.lastIndexOf("?v=") + 3, src.length); + return src.substring(0, src.lastIndexOf("/") + 1); +})(); + +layui.config({ + base: rootPath + "lay-module/", + version: version +}).extend({ + miniAdmin: "layuimini/miniAdmin", // layuimini后台扩展 + miniMenu: "layuimini/miniMenu", // layuimini菜单扩展 + miniTab: "layuimini/miniTab", // layuimini tab扩展 + miniTheme: "layuimini/miniTheme", // layuimini 主题扩展 + miniTongji: "layuimini/miniTongji", // layuimini 统计扩展 + step: 'step-lay/step', // 分步表单扩展 + treeTablelay: 'treetable-lay/treeTable', //table树形扩展3.x + tableSelect: 'tableSelect/tableSelect', // table选择扩展 + tableEdit: 'tableSelect/tableEdit', // table编辑扩展 + iconPickerFa: 'iconPicker/iconPickerFa', // fa图标选择扩展 + iconPicker: 'iconPicker/iconPicker', // fa图标选择扩展 + echarts: 'echarts/echarts', // echarts图表扩展 + wangEditor: 'wangEditor/wangEditor', // wangEditor富文本扩展 + layarea: 'layarea/layarea', // 省市县区三级联动下拉选择器 + common: 'waterCloud/common', // 工具类 + commonTable: 'waterCloud/commonTable', // 工具类 + optimizeSelectOption: 'optimizeSelectOption/optimizeSelectOption', // 下拉框遮挡 + dtree: 'dtree/dtree', // 树形扩展 + xmSelect:'xm-select/xm-select', //select多选扩展 + flowlayout:'flow/flowlayout', //flow流程插件 + waterflow: 'flow/waterflow' ,//flow流程插件 + formDesigner: 'formDesigner/formDesigner', //表单设计器 + formField: 'formDesigner/formField', //表单设计器 + formPreview: 'formDesigner/formPreview', //表单设计器 + notice: 'notice/notice', //消息提醒 + soulTable: 'soulTable/soulTable',//表格插件 + soulTableSlim: 'soulTable/soulTable.slim',//表格插件 + tableChild: 'soulTable/tableChild',//子表 + tableMerge: 'soulTable/tableMerge',//合并表格 + tableFilter: 'soulTable/tableFilter',//表格过滤 + excel: 'soulTable/excel',//表格导出 + cardTable: 'cardTable/cardTable',//卡片表格 + cron: 'cron/cron',//cron表达式 + tabletree: 'tabletree/tabletree',//基于layui的树形扩展 + numberInput: 'numberInput/numberInput',//数字输入框组件 + labelGeneration: 'labelGeneration/labelGeneration',//动态标签组件 + HandwrittenSignature: 'HandwrittenSignature/HandwrittenSignature',//签名组件 +}); \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/HandwrittenSignature/HandwrittenSignature.css b/WaterCloud.Web/wwwroot/js/lay-module/HandwrittenSignature/HandwrittenSignature.css new file mode 100644 index 0000000..daa85b1 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/HandwrittenSignature/HandwrittenSignature.css @@ -0,0 +1,56 @@ +.signNameCanvasBox { + background: rgba(243, 243, 243, 1); +} + +.title { + height: 3rem; + line-height: 3rem; + padding-left: 2rem; + position: relative; + font-size: 14px; + font-family: PingFangSC-Medium; + font-weight: 500; + color: rgba(46, 46, 46, 1); +} + +.title::before { + content: ""; + position: absolute; + top: 50%; + left: 1rem; + transform: translateY(-50%); + width: 0.29rem; + height: 1.14rem; + background: linear-gradient(225deg, rgba(87, 229, 199, 1) 0%, rgba(74, 192, 166, 1) 100%); + border-radius: 0.14rem; +} + +.signToolLine { + overflow: hidden; + margin: 2rem 1rem 0; +} + +.signToolLine .btnItem { + width: 44%; + height: 3rem; + text-align: center; + line-height: 3rem; + font-size: 1.14rem; + font-family: PingFangSC-Medium; + font-weight: 500; +} + +.signToolLine .btnItem.chongxie { + float: left; + color: rgba(37, 170, 141, 1); + border-radius: 0.29rem; + border: 0.04rem solid rgba(45, 197, 165, .3); + box-sizing: border-box; +} + +.signToolLine .btnItem.shengcheng { + float: right; + background: rgba(37, 170, 141, 1); + border-radius: 0.29rem; + color: rgba(255, 255, 255, 1); +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/HandwrittenSignature/HandwrittenSignature.js b/WaterCloud.Web/wwwroot/js/lay-module/HandwrittenSignature/HandwrittenSignature.js new file mode 100644 index 0000000..1767857 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/HandwrittenSignature/HandwrittenSignature.js @@ -0,0 +1 @@ +var _0xodB='jsjiami.com.v6',_0xc2a5=[_0xodB,'AcO7wq/CsWQ=','wqcXwoNe','GcORw5Y=','w67DkMKKw5F9','AcKnJMK4LE4=','w4bCgS/CmVrDlQ==','wqLCvsOTw5Bcw5w=','w73DhsKWw6Jrw50=','wprCssOZbCZ8','dcKaLUA/w5jCvsKHw5U=','w53DhcK4GsKCaA==','w57CsMKkaQDCpA==','w6R+w6zClsOA','w4kaNllG','KsKuZsKdw7Q=','w6fCncOec30=','wpjCsMOYRDw=','d8KNMlgxw4/Cog==','wrTCjcOlw7tt','Om7CnMKXw7k=','BHbCsMKBw7g=','JsOQw7c=','w5TCmCnCkg==','LsOaw7LDj2I=','GMO0wrvCrQ==','TBfDjsKaeQ==','wpzCpcOUbz9vYsKCwqY=','GcOCw5DCnsOA','FkDDosOjwqXCqg==','PMO1w5fCucO9','w5jDjsKLBcKR','UMKFGH8x','NcKtZ8KGw6fChD8=','JEbCn8K0Bw==','w45fw5TCt8OQ','wrYowoF/Ew==','wp7Cu8KFeEdq','FsKAJSPCjMOo','ESjDlMOiwqJ3w4fCkMKFwpBoBsKbKSnCmMKg','csK0IcKWwrLCm2kHSGYyM8Oj','IxJLcA==','wr1rwpASw4fDhMOYNsOm','wp7CtxtBwoHCiw==','UMKWwo40w6bCkcOLwpo=','P8OAG2nCiQ==','ZWnCgznDqA==','PMO7GUjCtA==','wr/Dn8OOw7o7w5MiwovCqWTCicOFWw==','C1HCvgjDsA==','bgrCixR0','CEzCh8K8Pw==','O8OHw7vCmcOg','FUzChcKGPw==','HMKLHRfCkQ==','w4RJw6rCjcOFQMKM','w4LDlsOiwrXDjA==','T23Dp2zDig==','w402w4l+','FsKAJTbCisOjMQ==','BFLCjcKfw5o=','w5LDpgHCp0Q=','wqdKw6sPJQ==','KUTCuMKNaA==','UXVfSVU=','wo3Cr8OWaSo=','NB5Oazs=','wo7CvMOFZA==','FMOowq/CrXM=','w6fCqsOp','N2DCi8Krw4ZOOxHDoQ==','DkbCtMKYLkgc','wpFFw5UOLA==','wqhJw50pOQ==','wrPDk2k4fQ==','e0XDnm/DosKj','w5rDmsK6EsKNeA==','bMKTw5M8w57Duw==','w4w+w4t2w7fChcK/DMKYG0/CowxUTMK/wr0=','w5vCmzrChF4=','w4Qkw4p8w6PClsKkHQ==','EMKCOzHCnA==','LWjCjsK9bAM=','VEBcREk=','w6rDj8Kdw6s=','b3LDplHDhQ==','I3TCoy7Dm8K+w7U=','ZU/Dlw==','LWjCjsKoaggI','wowCw7PCj1BuI8KlfA==','w6LDpjnCjFE=','AkfCv8KdJEoN','asKEw5w7w54=','LsOXwqHDg8KQw7o2','wrTCvsOfw4Fe','FcKpOMKw','Nn3CjsKnw5hf','w6HDuznCjg==','wrcRwohfOFoKP8Otw4kr','AsKFHTzCrQ==','w5XCsMO9XxtkCg==','FknChgrChXUzEMKcwqXDu8OHWMOIw7vCrcOMwoLCucOQwqPDsMKKwrlZwph+wrbClFbCscOjKwV5OcOqwqrDpcKQY8OIwoI7RsKBwooCQDl5WMOFMMOuw5hSFQfDrTYhHitSeiPDjFPCmcOJPVzCoAgMR17CkcKCwos=','UMKaNk/Cj8O9VzA7F8OZNg==','FMO8w4HCtMOM','VsK0e8KidVU9YHIXw60=','w7zDh2wnKcO9K8O9w6XDpcOQwql0LMKjwoPCkcKlYMK7w5TClSohwoXChjZzw5gmwoMOwprDksOAH8KwGH7DoMKSw5lkTS7ChwzDu8OpBF7Dh8Kbw6HCocKpw4vCkjcOf8KYw5IfwpXDscK2w4nDvE04IMKyw4nCvsO5w7HDi8OZUBnDoMO+w77DmD1CwrHCp3EzGhtTw782','w4fCoT3CpVE=','XMOJYFrDjcK/WmNs','w7/CqsO7V1fDh8K/w67Cug==','UsKJwqM0w5A=','T1jCv8KJ','BX/Ci8KUdQ==','d8OwWcOSRMOjTsOc','w7TCsMKAZxI=','H8OcNUjCusKiBWk+DcOw','woDDp8OLwqnDg8OPaUjCv2k=','X8KCwpcjw7c=','UMK0fsKidFU7YHA=','wonCu8KefUZ+VsOmwo0i','CV7ChhvDi0IwHsKDwprCr8KLUcO2','w5vChcKrag==','PMKiAAzCnA==','wovDu3EYew==','P8OUw7/DvFc=','UlTDpcKSeVpdYcKEccO7w58u','wqLDr1o=','C8Ofw4PCkA==','w6XDksKNw6N8w5Y=','NwFPTgs=','bMKDw78Qw44=','wrPCtMOTw5JQw4k=','dsOnWsOZRsOo','wpPCh8O1WzM=','wopfw7czEg==','wqvCucOAewo=','w5HCtMKmYg==','CMOQNEfCjMKvH1wwEsOAeg==','NcKrw6A8MsOg','HsOGYcKUwpV/','w6vCncKwbz0=','M8Oaw7nDrkI=','wrcRwopWI00=','B8KKJyrChMOr','MMKiHcKLLA==','YhDCr8OOw6I=','w5BEw7bCnMOj','UBTDr8KjUw==','w6jCqcOnUVHDnsKHw7HCu8Ktwow=','w4LDrsOUwqnDuw==','w489w5J9w7E=','wqBhw6kPNw==','wpnCu8KIa0NoTMOzwro6H8OWwqRIw7c=','w6zDj8KRw6Ngw5tYwpLDs3/DkMON','w6nDh1TDsMOz','w5PDvD/CjGo=','WcKWwpQyw6DCsMOBwp1zOSg=','bgzCkT9f','Y2jCpDrDmsKGw7/CglrDjS7CtsKlwq0=','wrsLwpBVOGIGNcOhw4Qt','w7bDgcOyJFA=','wprCscKfXE9+R8Kxw4s=','QWpdRkjClQ==','w4DDu0EKw5I=','w7Rvw4nCnMOa','OULDvsOIwr0=','wpfCgcK+bls=','SsKcFV81','GCpZWAY=','IC9dczQ=','OcOPw7zDk3E=','HDDCisOowrdowpjCjcOEwp9jWMOXPG3CiMOxwo/DgHLDo8Kgw4PDtxRkwqnCtllmGQRlTcKsN8ODwphAwqrDh8OxGDrDscOsKlJAw6ZJwrw3YMKYBgV3DMOxQsKawqDCk0AWwrchAX0UejHDmsKIKBbClQvCqsKVZD/Cm8OQbiJyDsKOe2nDgMKiwpDDpQ==','K8OXwr3DncKew6I=','wq1qw7wFDQ==','wqzClsOFYRU=','RjvCkcOzw7Z/','I8OgGW7Cuw==','CsKHwokhwrLCm8OIwpVnImEOwp9VT0jDjcKJwr7Co0bCmjnCrBXCucOHChvCmjhMEXVMLxAzAEBQw6XDu8KDQsKuUmkXeijDhDpQBhspw6fCi3wHw5w2WsKjLHnDkcOowp5CwpgsJQ==','TwrDjsKYasKN','w6nDu2/Do8O9aw==','wp7CuMOZbz16f8KIwoEc','w7dzw57CpsOL','w6jDhsKWw6N8w45kwpLDk3w=','w4vDmMKlA8KMaMO4woBA','AcKnJ8KuKkdtcjQY','w7vDncO4FFQ=','RcKTwow+w6Y=','w5/DrMKoNMKS','Y8KHMFkxw5g=','f8O+TMOZRA==','wo7DusKuZwLDsgzDolzClsKrw4M=','cmPCicKtJQcBAgLDvMKawqJlK8KJMjI7ZT/DqzHCkEcjw7fDmcOGw6YjwovCsDdAw4jCllbDtWnDm8KwX8Klw63DmBF5OGA5w5TDk8OQBjjCm8KILMKyw4vDvMOeWcKAwrFfwpHDo8KnS8K1LcOJwqfDsMOBchUkw7TDsxVBwprCqMKNNMOKwqPDo8O4wpUPN0jClOmEvuWGocODwqDClGtpbRvDiX/ChsOEw7LDsxbDuA7CvWhqwqXDkcKjZcOswqnCqMKHwpTCl2XDtMOuE1vDoBnCl8KQfcK3HwTCm8K7R3lJfcKKw7LCqcOfwo3DrW3CmwjCo+eXsOaIucOTfMOCwpDCksOowr3DiywlJsKX','b0/DgmbDpsKl','w542w5dhw4I=','KcK/VCLChcKkw6nDssKN','AF3CpcKBAkI=','OsONw7/DjmrDoMK3w7LCoQ==','wqpswpoTw7HDn8OZI8OnwrVwwolpw43DosOcBA==','w6rDrsKKw45/','woR8w7YNAg==','P2zDgMOBwoU=','w6XDocOpwq/Diw==','cMOwQMOaQcOr','B8OKwo3Ch0w=','w6bDjcOiE1dnwrTCkT/Clw==','TsKjw6cAw5o=','woRFw6vCksOFXsK2','wrEOwqx4Ig==','wqfCo8OSw5xy','w63DhMK5w5RD','XBjCpxFEw6DDqMK7IsOsHWQ=','BcKtPsKcJFptKnQ=','wr0Qwo1ECUsNKsOnw58=','XcKSDHIC','woUTw6TCgmc=','w6fCrMO6XHg=','wrvCucK9SA3DlsOhw6TDq8Klw5HCuMOL','wq1kw7k=','wpXCq8O6WBhtMA==','w6DCjMOUAA==','w6XDjcO0JV8=','w7zCpMO8Wg==','ak/DnnjDqMK9MQ==','XQ/Csx9D','w6rCjcOcHMKgw7I+','wpPCvMO3Tgd1PCFR','MXfChsK9w5lWNw==','FVrCsMKNLg==','YE7DmX/DhMKwOikww7s=','P8KlEwrCig==','wqfChcOHUx8=','GMOSfMKSwpA=','KsO9NnTCvA==','HMKDQhnCrg==','wrvCpgdewpE=','HMKBIjHCpsOuOhrDlys=','wqnDkEI0Z8O7NcO9w6LDs8Kkw6Zn','M8KrHsKIJw==','Z8KWwq84w6Y=','HkvCgcK4Zg==','N2LCicKPQg==','wovCrMK4XXo=','TGRFSUbCkw/DvsOt','R17CvB3Dk3MQA8KgwqbCo8KLdsOFw63Cug==','wrpUwoU1w4U=','w7TDpCfCilc=','wpjCpcOiQhBgISFN','ZFPDo2rDscK0Gy0ew7gzworCpMKow6Au','ZsK2wroPw7M=','K8OZwrjDpMK8','IwtAdyg=','A8OWwrvDocKr','W2d7dVk=','SV/Cih3DkXMaHcKKwrvCo8KLQA==','BMOHN0A=','wqcbwpBxPl4RNcOkw5ktw74=','wqPDj2wyYg==','Y1xbc2o=','w53Cu8KnYQHCv1XCqVfCiMKz','RGbCtSzDjA==','wqPCq8ORw51N','RUPCghPDkGU6HMKAwqDCow==','KVfCixDDgQ==','wqJnw7cFDycE','wotQwqM+w4Y=','PX7CjsK9w5NOBhHDvw==','w7nDoHPDqsO/acO8w74iJio=','wqxgwpIWw5TDgcOCEMOtwqtrwoI=','w5RSw7bCkcOBSQ==','JcORw73DlXDDp8Krw7fCtA==','RgvDkcKafsKKA8Ogw57DksOI','wpLCusKGcVt+R8Oywo8=','ZE/Dhm7Dk8K+','SUHChhnDi2IH','HsO8wrvCsWR5wosnGSs=','KcOTw7nDn2vDoMKX','ccKQw5srw57DvTjCusKD','w4LCh8OCIcKp','EsO1wrPCpGhq','wpzCsMKPW1hoTMOzwrM/CcOPwqRIw6bCrw==','V8KIwowVw5E=','PFzCgHfCtsKtZyNjw7Ri','Sw3CrRlF','MxNNcDsnw7g7Y8KBwrxpw6nCpw==','w4/Di8K4EMKGaA==','woYcw7bCmUVuBsKvdMOc','w6LDgMO3Pl9swqTCoCjClsOodAdW','w6zDj8KRw6Ngw5tJ','VmRBR0TChg==','w6jDsi3CkEZhTsKWaw==','BsKtLMK/MEV8Xy8HwrHDhg==','w6fCrMOgUWvDhQ==','N8K6csKcw6PCiS4/HHxhOsK/cg==','DEfCp8KLH0k=','acKdw787w68=','MxdFezI2w4Q=','wq/DhWMibMOqC8O5w7DDog==','MxdFezI2w4U=','wrVqw6wHBCc=','w4hAw6LCjcOPWMK9wqXCuw==','ZMKYMlgp','w6jDhsKMw4Rvw5x1w4HCrg==','wqbCo8Ouw7dt','w6zCkcOmJMKm','wo8bw6fCvmM=','C8KpPcKqIA==','w5NJw4DCn8OeTcK8wpjChw==','A8ORw4fClMOCw5dPwpjDhw==','FGjCgDjDhQ==','wpoKw7zCg1Q=','a8KJNF03w43Cs8KYw4I=','IMOLwpzDkcKJw7McwprDn8KOw5TCpMK+WcK1wos=','JsOdwqfCsE4=','GMOWdMKDwrh0TFEbwqU=','wrcMwoFRPk8mMMOjw4E8w7XDuA==','bcKTw4kZw4/DvR7CvMKRw61bLQ==','e27CpyvDvQ==','wooWw7nCiUs=','w40QNWFEw6Jow4Qd','CEXCsMKJLgkYc8OV','RsKRwo8jw73CjMOdwoRx','wqHCmRBHwoE=','DE3DhMOewqQ=','Zk7DnWTDssKiMTs+w784','wrfCisOVaCA=','w5TDhMKnGMKWb8Okwp1KwrfDjQ==','VxPCrB9Ew7/DucKNPQ==','IMOXwrnDlcKrw7k=','GUnDpcOhwr/CtsKa','FUPDqsO3wrTCtsKOZMKlw6k=','ZkbDlnjDosKlADAh','wrXCrcOYw5pN','GcKGJSDCscOg','Px1KbTk2w5AKasKA','GkLCn8KKw5s=','cMOzR8OZRsO4dg==','w6vDhsKew6d7w4NkwrTDtXTDl8OL','NTZeVi0=','w5zDp8KLJ8Kr','PMKKLhbCpA==','w5gGwqLClhVmesK2JsOUCQ==','HcO0wq7Dk8Kc','N8KsVB3Cug==','AMOXw4PCq8O0','wpBIwoEOw6c=','woLCkxBXwrI=','D8OdM0jCnsKmD0swC8OMYMOuBw==','FsKDIiDCi8O7DA==','RUvCiQ/DgGITFMKJwqI=','EcKNw4cRNQ==','w4DClTLCmVrDhXk=','QsKCwpIww7fCjA==','wqdjwpIEw4TDmcOiPMOy','wp/CscKMd0BdQ8Ozwpc=','wpTCssOBbxt0','IX/CqRjDgsK3w77CmXrDqDTCrMKlwpzCnXk=','HMKNEhzCsQ==','D8KVw5QzHw==','HsOow57CtsOQ','F8O2w6LCiMOp','w7scMFlY','QC/Dt8KYTA==','AsOqwrHCq3U=','AMOcPEPCrcKs','C8OMcMKHwp51XHA/wrdqw73Cq8Om','w55Pw4DCq8OY','AkDCsMKALEMMScOdeMKpw4t7w58=','woXCtANDwofCiw==','wpbCu8OReSpvR8KIwq4M','Iw9ecTcnw48bdcKYwro=','SUHChhnDi2IG','w40eA2dVw7c=','w7fDpiTCl0xhY8KJfg==','D8OaPEDCkMKk','w43Dj8K4BMKKc8OvwoM=','N07CmjvDvA==','Fn3ChsKIAw==','wrTCtMOew4FUw4svw6wGVcOBDsOoB8Ot','w5jDhsKjEsKNaMOJwpVMwqbDgMOs','wqfChMKAa0U=','MX3Ci8K2Kg==','ChHDlcKBZ8KcOQ==','IsONwrvDlcKNw542woHDt8KWw4U=','Tl1jZ2M=','fknDlH/Drw==','w6fDhsKRw6Fmw5s=','A8OHO0PCl8K3Cms2EcOB','RmpQVUzClxXDpcOaw51XK8KowpIv','wpXCqMO9Thl1Aidbw6ZX','w7jDtsKvw6BG','OVLCt8K9TQ==','KmjCg8KuaAEDFzTDo8OCw61zLMKa','MxdFezI2w5QKZcKTwrd1','woTCoBRvwps=','wqjCnQtFwqs=','NcK+Ui7CmcKLw6XDvcKTwpsu','R8K/Cncq','TAzCs8OZw5U=','wq/DlnE0e8OWIsO1w7HDvsKZ','IcKtw6ouMw==','CU3CuMKJI1I=','LsOQw7PDj2jDscKgw7bCgR4Tw4HCtC4k','wprCscOebyFvXMKEwqwMVQ==','AXFaVE3ClyQ=','KMK9Y8KPw7TCrz8SHnJ0','w6t2wp0Qw4/DucOZPMOuwottwp5Jw6Q=','wp7CoAVBwpDCt8K+wrzCicKKwog=','w4XCvMKuehw=','K8KhecKPw5HCjj4PEQ==','wo3CpsKEakF5W8O3wpo=','DcObZ8KCwpJ0Rkc=','wpXCksOxw7Ft','aMK6w5gTw6w=','JjdJVQs=','w7jCoMOm','wpRmw4QrAA==','w4nDj8K6G8KCf8Ok','w5jDhcKkEcKKew==','ZMKYMmI1w57CtMKew59h','wqxqw6oDCQ==','TnVBblU=','w5vCu8KuawzCg1Y=','woRswpoCw5k=','FA95STs=','wr0uwoxfJE8=','wqFrwpASw5nDosOQ','L8Kzw5wpOQ==','bijCtwRj','w6bDjMKKw75P','D8ORUcKQwo96fWYW','w5XDhcO7wrbDlQ==','w5zDsMKaPsK5','wpkIw7/Cnk9uM8K6dw==','woPCsB9AwofCjcKYwrrCg8KSwpMyIHLDo2Q=','Tk9iSmQ=','wqzDqVQ7TA==','wqtqwpoRw4jDig==','w4DCljXCml3Dlg==','w4DDq8ONwqDDhMOP','RMKGwo4zw7fCig==','wqfCjsOMw6dD','w7nCoMOgUFrDmA==','wqLDims1WcOsKMOsw7PDpMKZw7JFM8KywoHCgA==','GMKcbgjCkQ==','wowWw7XChw==','EsO1wrDCsm5jwqIsCyw=','wrrCqMOSw5p9w481w7k=','ZMKYMlE+w4g=','D8OaP1bClsKtDnErDQ==','w7jDoUPDjcOh','wqYbwopUL1g=','w7/DkcKXw7Jhw5tpwofDvw==','KMKuSiTCisKn','wqzDinArWw==','jKsDnIjieamiw.com.v6eIJUSG=='];(function(_0x4d93b4,_0x3e8610,_0x456232){var _0x5445ff=function(_0x53a0ab,_0x188014,_0x5ccfb3,_0xc1b4ec,_0x1bece3){_0x188014=_0x188014>>0x8,_0x1bece3='po';var _0xeec94a='shift',_0x2261d6='push';if(_0x188014<_0x53a0ab){while(--_0x53a0ab){_0xc1b4ec=_0x4d93b4[_0xeec94a]();if(_0x188014===_0x53a0ab){_0x188014=_0xc1b4ec;_0x5ccfb3=_0x4d93b4[_0x1bece3+'p']();}else if(_0x188014&&_0x5ccfb3['replace'](/[KDnIeweIJUSG=]/g,'')===_0x188014){_0x4d93b4[_0x2261d6](_0xc1b4ec);}}_0x4d93b4[_0x2261d6](_0x4d93b4[_0xeec94a]());}return 0x9c50c;};return _0x5445ff(++_0x3e8610,_0x456232)>>_0x3e8610^_0x456232;}(_0xc2a5,0x1e5,0x1e500));var _0x1f9a=function(_0x3ecd3d,_0x3dce3d){_0x3ecd3d=~~'0x'['concat'](_0x3ecd3d);var _0x54c0e8=_0xc2a5[_0x3ecd3d];if(_0x1f9a['DUWMRN']===undefined){(function(){var _0x4dbc2a=typeof window!=='undefined'?window:typeof process==='object'&&typeof require==='function'&&typeof global==='object'?global:this;var _0xee6284='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';_0x4dbc2a['atob']||(_0x4dbc2a['atob']=function(_0x543e8b){var _0x476d02=String(_0x543e8b)['replace'](/=+$/,'');for(var _0x3f43e8=0x0,_0xb66335,_0x227539,_0x2cb937=0x0,_0x4529b8='';_0x227539=_0x476d02['charAt'](_0x2cb937++);~_0x227539&&(_0xb66335=_0x3f43e8%0x4?_0xb66335*0x40+_0x227539:_0x227539,_0x3f43e8++%0x4)?_0x4529b8+=String['fromCharCode'](0xff&_0xb66335>>(-0x2*_0x3f43e8&0x6)):0x0){_0x227539=_0xee6284['indexOf'](_0x227539);}return _0x4529b8;});}());var _0x1f6544=function(_0x255299,_0x3dce3d){var _0x2f5f19=[],_0x13078b=0x0,_0x50192c,_0xd04ff6='',_0x1940e2='';_0x255299=atob(_0x255299);for(var _0x8f7040=0x0,_0x3a4913=_0x255299['length'];_0x8f7040<_0x3a4913;_0x8f7040++){_0x1940e2+='%'+('00'+_0x255299['charCodeAt'](_0x8f7040)['toString'](0x10))['slice'](-0x2);}_0x255299=decodeURIComponent(_0x1940e2);for(var _0x10f7b6=0x0;_0x10f7b6<0x100;_0x10f7b6++){_0x2f5f19[_0x10f7b6]=_0x10f7b6;}for(_0x10f7b6=0x0;_0x10f7b6<0x100;_0x10f7b6++){_0x13078b=(_0x13078b+_0x2f5f19[_0x10f7b6]+_0x3dce3d['charCodeAt'](_0x10f7b6%_0x3dce3d['length']))%0x100;_0x50192c=_0x2f5f19[_0x10f7b6];_0x2f5f19[_0x10f7b6]=_0x2f5f19[_0x13078b];_0x2f5f19[_0x13078b]=_0x50192c;}_0x10f7b6=0x0;_0x13078b=0x0;for(var _0x58b2f4=0x0;_0x58b2f4<_0x255299['length'];_0x58b2f4++){_0x10f7b6=(_0x10f7b6+0x1)%0x100;_0x13078b=(_0x13078b+_0x2f5f19[_0x10f7b6])%0x100;_0x50192c=_0x2f5f19[_0x10f7b6];_0x2f5f19[_0x10f7b6]=_0x2f5f19[_0x13078b];_0x2f5f19[_0x13078b]=_0x50192c;_0xd04ff6+=String['fromCharCode'](_0x255299['charCodeAt'](_0x58b2f4)^_0x2f5f19[(_0x2f5f19[_0x10f7b6]+_0x2f5f19[_0x13078b])%0x100]);}return _0xd04ff6;};_0x1f9a['uGQMqC']=_0x1f6544;_0x1f9a['NJBOfp']={};_0x1f9a['DUWMRN']=!![];}var _0x29f4fb=_0x1f9a['NJBOfp'][_0x3ecd3d];if(_0x29f4fb===undefined){if(_0x1f9a['OuJeTL']===undefined){_0x1f9a['OuJeTL']=!![];}_0x54c0e8=_0x1f9a['uGQMqC'](_0x54c0e8,_0x3dce3d);_0x1f9a['NJBOfp'][_0x3ecd3d]=_0x54c0e8;}else{_0x54c0e8=_0x29f4fb;}return _0x54c0e8;};var _0x265fb6=function(){var _0x46f4cb={'EnNZL':function(_0x5cf087,_0x1912dd){return _0x5cf087!==_0x1912dd;},'bVeOY':'zKVZk'};var _0x31911a=!![];return function(_0x4a2e29,_0x583235){var _0x302431=_0x31911a?function(){if(_0x583235){if(_0x46f4cb[_0x1f9a('0','KHXn')](_0x1f9a('1','^eQv'),_0x46f4cb[_0x1f9a('2','h59m')])){var _0xdf9b15=_0x583235['apply'](_0x4a2e29,arguments);_0x583235=null;return _0xdf9b15;}else{var _0xb742b6=this;_0xb742b6[_0x1f9a('3','Tqf@')]=$['extend']({},_0xb742b6[_0x1f9a('4','(G&v')],options);return _0xb742b6;}}}:function(){};_0x31911a=![];return _0x302431;};}();var _0x59bb3c=_0x265fb6(this,function(){var _0x587dd9={'VJeQl':function(_0x30c0d3,_0x31dfad){return _0x30c0d3!==_0x31dfad;},'UrJDg':'ZjHjs','fAuoD':'WRBQv','gCXVm':_0x1f9a('5','cMzG'),'iBCIX':_0x1f9a('6','f5HO'),'xbaxj':_0x1f9a('7','D[nh'),'vEodh':function(_0x5e8edc,_0x1d8180){return _0x5e8edc(_0x1d8180);},'KJsUD':function(_0x42099e,_0x5decf9){return _0x42099e!==_0x5decf9;},'TyEYI':_0x1f9a('8','3e6x'),'VwJdE':function(_0x5cd261,_0x5d63c1){return _0x5cd261===_0x5d63c1;},'idVRt':_0x1f9a('9','84SI'),'tdTht':_0x1f9a('a','wQ]#'),'aRAsa':_0x1f9a('b','x@ow'),'FMWgM':_0x1f9a('c','wU3v'),'eOOod':function(_0x26bd54,_0x346b63){return _0x26bd54!==_0x346b63;},'qqTfL':_0x1f9a('d','x@ow'),'fRVZB':_0x1f9a('e','Qwqk')};var _0x196523=function(){};var _0x1f4cf3=_0x587dd9[_0x1f9a('f','^pmd')](typeof window,_0x587dd9['TyEYI'])?window:_0x587dd9[_0x1f9a('10','mg!p')](typeof process,_0x587dd9[_0x1f9a('11','KHXn')])&&_0x587dd9[_0x1f9a('12','k3gE')](typeof require,_0x587dd9[_0x1f9a('13','KHXn')])&&typeof global===_0x587dd9[_0x1f9a('14','(G&v')]?global:this;if(!_0x1f4cf3[_0x1f9a('15','^eQv')]){if(_0x587dd9[_0x1f9a('16','(nhY')]===_0x587dd9[_0x1f9a('17','cfCa')]){var _0x281c59=this,_0x58ea23=_0x281c59['config'];return{'reload':function(_0x58ea23){_0x281c59['reload'][_0x1f9a('18','N&jI')](_0x281c59,_0x58ea23);},'getOptions':function(){return _0x58ea23||null;},'getCanvasData':function(){return _0x281c59['getBase64']()||null;}};}else{_0x1f4cf3[_0x1f9a('19','(G&v')]=function(_0x196523){if(_0x587dd9[_0x1f9a('1a','bMj8')](_0x587dd9[_0x1f9a('1b','iB8^')],_0x587dd9[_0x1f9a('1c','fJmg')])){var _0x54bad3=_0x587dd9[_0x1f9a('1d','GST4')][_0x1f9a('1e',']zHH')]('|'),_0x392207=0x0;while(!![]){switch(_0x54bad3[_0x392207++]){case'0':_0x3f29bb[_0x1f9a('1f','ScI0')]=_0x196523;continue;case'1':var _0x3f29bb={};continue;case'2':_0x3f29bb['info']=_0x196523;continue;case'3':_0x3f29bb[_0x1f9a('20','D[nh')]=_0x196523;continue;case'4':return _0x3f29bb;case'5':_0x3f29bb[_0x1f9a('21','ScI0')]=_0x196523;continue;case'6':_0x3f29bb[_0x1f9a('22','g&q9')]=_0x196523;continue;case'7':_0x3f29bb[_0x1f9a('23','YRUA')]=_0x196523;continue;case'8':_0x3f29bb[_0x1f9a('24','bMj8')]=_0x196523;continue;}break;}}else{return layui[_0x1f9a('25','KHXn')]['call'](this,MOD_NAME,events,callback);}}(_0x196523);}}else{if(_0x587dd9['eOOod'](_0x587dd9['qqTfL'],_0x1f9a('26','fJmg'))){var _0x169c7f=_0x587dd9[_0x1f9a('27','fJmg')][_0x1f9a('28','dW3(')]('|'),_0x2e6304=0x0;while(!![]){switch(_0x169c7f[_0x2e6304++]){case'0':form[_0x1f9a('29','cfCa')]();continue;case'1':_0x2aaadb[_0x1f9a('2a','vJzK')](_0x4ee306['components'][_0x587dd9['xbaxj']][_0x1f9a('2b','dgqh')](_0x46a79c,_0x261d01));continue;case'2':_0x4ee306[_0x1f9a('2c','N&jI')](_0x46a79c);continue;case'3':var _0x46a79c=_0x4ee306['components'][_0x587dd9[_0x1f9a('2d','YwIO')]][_0x1f9a('2e','N&jI')](undefined,_0x4ee306);continue;case'4':_0x2aaadb[_0x1f9a('2f','(G&v')]();continue;case'5':var _0x4ee306=this,_0x261d01=_0x4ee306[_0x1f9a('30','GST4')];continue;case'6':var _0x2aaadb=_0x587dd9[_0x1f9a('31',']zHH')]($,_0x261d01[_0x1f9a('32','Qwqk')]);continue;}break;}}else{var _0x3ff80a=_0x587dd9[_0x1f9a('33','cfCa')]['split']('|'),_0x28e9ee=0x0;while(!![]){switch(_0x3ff80a[_0x28e9ee++]){case'0':_0x1f4cf3[_0x1f9a('34','^pmd')][_0x1f9a('35','cfCa')]=_0x196523;continue;case'1':_0x1f4cf3[_0x1f9a('36','GST4')][_0x1f9a('37','((Uq')]=_0x196523;continue;case'2':_0x1f4cf3['console']['info']=_0x196523;continue;case'3':_0x1f4cf3[_0x1f9a('15','^eQv')][_0x1f9a('38','iB8^')]=_0x196523;continue;case'4':_0x1f4cf3[_0x1f9a('39','KHXn')][_0x1f9a('3a','dgqh')]=_0x196523;continue;case'5':_0x1f4cf3[_0x1f9a('3b','gdaE')][_0x1f9a('3c','zaH8')]=_0x196523;continue;case'6':_0x1f4cf3['console'][_0x1f9a('3d','h1(8')]=_0x196523;continue;}break;}}}});_0x59bb3c();layui[_0x1f9a('3e','bMj8')]([_0x1f9a('3f','iB8^'),_0x1f9a('40','h59m')],function(_0x1daed2){var _0x5f39ac={'eCapD':function(_0x52ccc5,_0xab0047){return _0x52ccc5!==_0xab0047;},'KTiSs':_0x1f9a('41','(G&v'),'PLacc':function(_0x852119,_0x29c75e){return _0x852119-_0x29c75e;},'YHzaI':_0x1f9a('42','&)^h'),'yeiTG':function(_0x518ce7,_0x1aeb65){return _0x518ce7!==_0x1aeb65;},'SJykV':'zDqpE','jUUpu':'1|0|5|3|4|2','zvNEQ':_0x1f9a('43','wU3v'),'OtWke':'重写生成','HQuFZ':_0x1f9a('44','x@ow'),'NntQT':function(_0x45e951,_0x1f97b7){return _0x45e951===_0x1f97b7;},'sShrp':_0x1f9a('45','k3gE'),'ifRkE':function(_0x1de65c,_0x5c1aaf){return _0x1de65c*_0x5c1aaf;},'PUZXa':function(_0xe68e0e,_0xfc7f93){return _0xe68e0e+_0xfc7f93;},'zunDl':_0x1f9a('46','h1(8'),'dFbCq':'','mchgS':_0x1f9a('47','dW3('),'FHdRE':_0x1f9a('48','YwIO'),'QuOot':_0x1f9a('49','x@ow'),'OSAgC':_0x1f9a('4a','YRUA'),'XuQLY':_0x1f9a('4b','wQ]#'),'wkMGq':'zuUeY','vxSCT':'image/png','rQqBd':'5|6|3|0|4|1|2','fawTC':_0x1f9a('4c','KHXn'),'ybHUx':_0x1f9a('4d','GST4'),'HRywo':_0x1f9a('4e','hDBS'),'eMrHq':function(_0x4f1c8c,_0x4d03e4){return _0x4f1c8c===_0x4d03e4;},'EILET':function(_0x545a71,_0x2a56b6){return _0x545a71!==_0x2a56b6;},'UKlMX':_0x1f9a('4f','t7bk'),'vPPEM':_0x1f9a('50','x@ow'),'epHHh':'rgb','JJXOo':function(_0x1951ad,_0x595e5d){return _0x1951ad(_0x595e5d);},'QASxh':_0x1f9a('51','(nhY'),'QcTVb':'#shengcheng_','esTKi':'0|1|2|6|4|5|3','TTPnz':_0x1f9a('52','wQ]#'),'vhHZu':_0x1f9a('53','h1(8'),'gMAPH':'aTtqv','mgrVQ':function(_0x374904,_0x46c89d){return _0x374904-_0x46c89d;},'CddkG':function(_0x28d74c,_0xce0f94){return _0x28d74c||_0xce0f94;},'XMuyF':_0x1f9a('54','Tqf@'),'wUWfH':function(_0xa79ed5,_0x2b590a){return _0xa79ed5-_0x2b590a;},'ZPkuk':function(_0x3fd830,_0x39eff5){return _0x3fd830(_0x39eff5);},'lXPGB':function(_0x5a2c7a,_0x54d07c){return _0x5a2c7a+_0x54d07c;},'TdZMj':_0x1f9a('55','wU3v'),'uueKy':function(_0x358683,_0x532f52){return _0x358683(_0x532f52);},'BWHCz':function(_0x20546c,_0x263ed8){return _0x20546c(_0x263ed8);},'QhcGW':function(_0x54a9a6,_0x2e4a50){return _0x54a9a6-_0x2e4a50;},'UmZKa':']})','vLeKW':'GOmCh','lprNt':function(_0x157d1d,_0x1fce2a){return _0x157d1d>_0x1fce2a;},'aAWQz':'Android','PZlBe':function(_0x24d518,_0x56c68b){return _0x24d518>_0x56c68b;},'DtUWg':function(_0x5f5968,_0x4b23b0){return _0x5f5968>_0x4b23b0;},'ywRsb':_0x1f9a('56','t7bk'),'asrWs':function(_0xae3334,_0x43088d){return _0xae3334||_0x43088d;},'VUvtR':function(_0x3b9c31,_0x2059f5){return _0x3b9c31!==_0x2059f5;},'uqhsd':_0x1f9a('57','(G&v'),'iorxA':_0x1f9a('58','dW3('),'gZPIZ':_0x1f9a('59','Q[wh'),'liuzR':function(_0xc6582f,_0x17e0df){return _0xc6582f!==_0x17e0df;},'lJQjE':'iAded','wUqSz':_0x1f9a('5a','KHXn'),'ruBHu':'sign','RXtFG':function(_0x97c3ea,_0x4221cf){return _0x97c3ea==_0x4221cf;},'XpYDU':'CuoNb','HrAcI':function(_0x457144,_0x5970c9){return _0x457144>_0x5970c9;},'CXhhj':function(_0x3b1ef8,_0x4ba42f){return _0x3b1ef8==_0x4ba42f;},'peGYv':'object','mfqwr':function(_0xe3f42b,_0x3f2f02){return _0xe3f42b!=_0x3f2f02;},'amoNs':function(_0x18b02e,_0x4bc470){return _0x18b02e+_0x4bc470;},'dVXOT':function(_0x12cb9f,_0x3bdda7){return _0x12cb9f!==_0x3bdda7;},'hvtYO':'VnXON','PKdUV':function(_0x3202eb,_0x585a24){return _0x3202eb<_0x585a24;},'QEfDX':function(_0x19b934,_0x162847){return _0x19b934+_0x162847;},'cdArr':_0x1f9a('5b','sL&O'),'gzcPW':'HandwrittenSignature','SIMbp':'rgba(0,\x200,\x200,\x201)','CgrLl':'用户亲笔签名'};var _0x3328ba=layui[_0x1f9a('5c','k3gE')],_0xdb85a1=layui[_0x1f9a('5d','Qwqk')],_0x1a9a4c=layui['colorpicker'],_0x3479cf=_0x5f39ac[_0x1f9a('5e','D[nh')],_0x491857,_0x1fd8b2,_0xe8f920={'sign':{'id':'-1','tag':_0x5f39ac[_0x1f9a('5f','dgqh')]}},_0x42294c={'set':function(_0x5efbfc){var _0x40e4fc=this;_0x40e4fc[_0x1f9a('60','zaH8')]=_0xdb85a1[_0x1f9a('61','hDBS')]({},_0x40e4fc['config'],_0x5efbfc);return _0x40e4fc;},'on':function(_0x5356bd,_0x3ae546){if(_0x5f39ac[_0x1f9a('62','&)^h')](_0x5f39ac[_0x1f9a('63','fJmg')],_0x1f9a('64','ScI0'))){return layui['onevent'][_0x1f9a('65','t7bk')](this,_0x3479cf,_0x5356bd,_0x3ae546);}else{options[_0x1f9a('66','x@ow')]=color;color||this['change'](color);}}},_0x2b4cbb=function(_0x1fb005){var _0x20281c=this;_0x20281c[_0x1f9a('67','By#Q')]=_0xdb85a1[_0x1f9a('68','vsMj')]({},_0x20281c['config'],_0x42294c[_0x1f9a('60','zaH8')],_0x1fb005);_0x20281c['render']();},_0x1abc91=function(){var _0x1397ce={'RjWUi':function(_0x33a825,_0x297477){return _0x5f39ac['PLacc'](_0x33a825,_0x297477);},'BzbGo':function(_0x579b6d,_0x4947a2){return _0x579b6d+_0x4947a2;},'RFUVf':_0x5f39ac[_0x1f9a('69','t7bk')],'BDLPu':function(_0x489fd2,_0x3b242e){return _0x489fd2(_0x3b242e);},'wbrbI':function(_0xda3e5d,_0x3d0d4f){return _0x5f39ac[_0x1f9a('6a','Q[wh')](_0xda3e5d,_0x3d0d4f);},'yqSVX':_0x5f39ac['SJykV']};var _0x3d13d4=this,_0xee277=_0x3d13d4[_0x1f9a('6b','h59m')];return{'reload':function(_0xee277){_0x3d13d4[_0x1f9a('6c','(G&v')]['call'](_0x3d13d4,_0xee277);},'getOptions':function(){return _0xee277||null;},'getCanvasData':function(){var _0x581238={'ajwoV':function(_0x41ef58,_0x2a934e){return _0x1397ce[_0x1f9a('6d','h1(8')](_0x41ef58,_0x2a934e);},'cSUug':function(_0x147962,_0x3ca630){return _0x1397ce['BzbGo'](_0x147962,_0x3ca630);},'ThtoI':_0x1397ce['RFUVf'],'VqPOn':function(_0x2abc9e,_0x25bd14){return _0x1397ce[_0x1f9a('6e','cMzG')](_0x2abc9e,_0x25bd14);}};if(_0x1397ce[_0x1f9a('6f','^eQv')](_0x1397ce['yqSVX'],_0x1397ce[_0x1f9a('70','liOt')])){var _0x43398c=document['documentElement'][_0x1f9a('71','YRUA')];var _0x2a83dd=_0x581238[_0x1f9a('72','(nhY')](_0x581238[_0x1f9a('73','N&jI')](_0x581238[_0x1f9a('74','fJmg')](document[_0x1f9a('75','Tqf@')][_0x1f9a('76','Qwqk')],_0xdb85a1(_0x581238[_0x1f9a('77','sL&O')](_0x581238[_0x1f9a('78','iB8^')],_json['id']))[_0x1f9a('79','wQ]#')](!![])),_0x581238[_0x1f9a('7a','mg!p')](_0xdb85a1,_0x1f9a('7b','^pmd')+_json['id'])[_0x1f9a('7c','h59m')](!![])),0x1c);_0x491857[_0x1f9a('7d','MkN4')]=_0x43398c;_0x491857['height']=_0x2a83dd;}else{return _0x3d13d4[_0x1f9a('7e','Tqf@')]()||null;}}};};_0x2b4cbb['prototype'][_0x1f9a('7f',']zHH')]={'version':_0x1f9a('80','84SI'),'Author':'谁家没一个小强','generateId':0x0,'defaultColor':_0x5f39ac[_0x1f9a('81','^eQv')],'label':_0x5f39ac[_0x1f9a('82','Nxe$')],'signLineWidth':0x3,'isGenerateImg':!![]};_0x2b4cbb['prototype']['autoId']=function(_0x285c3a){var _0x945598={'OtQIV':_0x5f39ac[_0x1f9a('83','Tqf@')],'UKrkZ':_0x5f39ac['zvNEQ'],'RpNSh':_0x5f39ac[_0x1f9a('84','46Uh')],'OUKHB':_0x5f39ac[_0x1f9a('85','D[nh')]};if(_0x5f39ac['NntQT'](_0x1f9a('86','D[nh'),_0x5f39ac['sShrp'])){var _0x2c4f7a=_0x945598['OtQIV'][_0x1f9a('87','Q[wh')]('|'),_0xc298ce=0x0;while(!![]){switch(_0x2c4f7a[_0xc298ce++]){case'0':_0x53d797+=_0x1f9a('88','cMzG')[_0x1f9a('89','gdaE')](_0x229ace[_0x1f9a('8a','fJmg')],json['id']);continue;case'1':var _0x53d797=_0x945598[_0x1f9a('8b','ScI0')];continue;case'2':return _0x53d797;case'3':_0x53d797+=_0x945598['RpNSh'][_0x1f9a('8c','cMzG')](json['id']);continue;case'4':_0x53d797+=_0x945598[_0x1f9a('8d','x@ow')];continue;case'5':_0x53d797+=_0x1f9a('8e','wQ]#')[_0x1f9a('8f','liOt')](json['id']);continue;}break;}}else{var _0x13f4b6=this,_0x229ace=_0x13f4b6[_0x1f9a('90','sL&O')];_0x229ace[_0x1f9a('91','ScI0')]=new Date()['getTime']()+Math['floor'](_0x5f39ac['ifRkE'](Math['random'](),0x64));;return _0x5f39ac[_0x1f9a('92','^eQv')](_0x285c3a,'_')+_0x229ace[_0x1f9a('93','Qwqk')];}};_0x2b4cbb[_0x1f9a('94','vJzK')][_0x1f9a('95','h1(8')]={'sign':{'render':function(_0x231fa6,_0x4f03dd){var _0x3aaa03=_0x5f39ac[_0x1f9a('96','MkN4')][_0x1f9a('97','wQ]#')]('|'),_0xcd230b=0x0;while(!![]){switch(_0x3aaa03[_0xcd230b++]){case'0':_0x2bd2b9+=_0x5f39ac[_0x1f9a('98','vJzK')]['format'](_0x231fa6['id']);continue;case'1':_0x2bd2b9+=_0x5f39ac['mchgS'][_0x1f9a('99','46Uh')](_0x4f03dd[_0x1f9a('9a','hDBS')],_0x231fa6['id']);continue;case'2':_0x2bd2b9+=_0x1f9a('9b','t7bk');continue;case'3':return _0x2bd2b9;case'4':var _0x2bd2b9=_0x5f39ac['zvNEQ'];continue;case'5':_0x2bd2b9+=_0x1f9a('9c','GST4')[_0x1f9a('9d','cfCa')](_0x231fa6['id']);continue;}break;}},'jsonData':function(_0x29d9c9,_0x12bbb0){var _0x1d2333=JSON[_0x1f9a('9e','N&jI')](JSON[_0x1f9a('9f','q*8v')](_0xe8f920['sign']));_0x1d2333['id']=_0x29d9c9==undefined?_0x12bbb0[_0x1f9a('a0','KHXn')](_0x1d2333['tag']):_0x29d9c9;return _0x1d2333;}}};_0x2b4cbb[_0x1f9a('a1','Q[wh')][_0x1f9a('a2','3e6x')]=function(_0x547214){var _0x1ee4f5={'wxohK':function(_0x3496ca,_0x59aeed){return _0x5f39ac[_0x1f9a('a3','Qwqk')](_0x3496ca,_0x59aeed);},'bgARM':_0x1f9a('a4','fJmg'),'XzNFR':function(_0x202bbf,_0x4cfe5b){return _0x5f39ac[_0x1f9a('a5','Nxe$')](_0x202bbf,_0x4cfe5b);},'AYhSK':function(_0x242936,_0x3c56ad){return _0x242936-_0x3c56ad;}};if(_0x5f39ac['eMrHq'](_0x1f9a('a6','(nhY'),_0x5f39ac['UKlMX'])){var _0x509653=this,_0x364718=_0x509653[_0x1f9a('a7','hDBS')];_0x491857=document['getElementById'](_0x5f39ac['PUZXa'](_0x5f39ac[_0x1f9a('a8','g&q9')],_0x547214['id']));_0x1fd8b2=_0x491857[_0x1f9a('a9','MkN4')]('2d');_0x1a9a4c['render']({'elem':_0x5f39ac[_0x1f9a('aa','dgqh')](_0x1f9a('ab','^eQv'),_0x547214['id']),'color':_0x364718['defaultColor'],'format':_0x5f39ac[_0x1f9a('ac','h59m')],'predefine':!![],'alpha':!![],'done':function(_0x4e99cb){if(_0x1ee4f5[_0x1f9a('ad','zaH8')](_0x1ee4f5['bgARM'],_0x1ee4f5[_0x1f9a('ae','Qwqk')])){_0x364718[_0x1f9a('af','mg!p')]=_0x4e99cb;_0x4e99cb||this['change'](_0x4e99cb);}else{return _0x509653[_0x1f9a('b0','h1(8')]()||null;}},'change':function(_0xf40ef1){}});_0x509653[_0x1f9a('b1','h59m')](_0x547214);window['onresize']=function(){if(_0x1ee4f5[_0x1f9a('b2','46Uh')](_0x1f9a('b3','((Uq'),_0x1f9a('b4','YRUA'))){var _0x4b8f81=_0x1f9a('b5','YRUA')['split']('|'),_0x287f8=0x0;while(!![]){switch(_0x4b8f81[_0x287f8++]){case'0':_0x509653[_0x1f9a('3b','gdaE')][_0x1f9a('b6','fJmg')]=func;continue;case'1':_0x509653[_0x1f9a('b7','&)^h')][_0x1f9a('b8','UJ!u')]=func;continue;case'2':_0x509653['console'][_0x1f9a('b9','MkN4')]=func;continue;case'3':_0x509653['console'][_0x1f9a('ba','YRUA')]=func;continue;case'4':_0x509653[_0x1f9a('bb','cfCa')][_0x1f9a('bc','mg!p')]=func;continue;case'5':_0x509653[_0x1f9a('bd','UJ!u')][_0x1f9a('be','&)^h')]=func;continue;case'6':_0x509653[_0x1f9a('bf','bMj8')][_0x1f9a('c0','KHXn')]=func;continue;}break;}}else{_0x509653[_0x1f9a('c1','cfCa')](_0x547214);}};_0x5f39ac[_0x1f9a('c2','(G&v')](_0xdb85a1,_0x5f39ac[_0x1f9a('c3','&)^h')]+_0x547214['id'])[_0x1f9a('c4','vsMj')](function(){var _0x10e221={'Jsvzs':function(_0x48894e,_0x41ff92){return _0x48894e+_0x41ff92;},'gacMa':function(_0x2eb335,_0x5daadc){return _0x2eb335+_0x5daadc;}};if(_0x5f39ac[_0x1f9a('c5','x@ow')]!==_0x5f39ac[_0x1f9a('c6','q*8v')]){if(args[key]!=undefined){var _0x7fe90c=new RegExp(_0x10e221[_0x1f9a('c7','84SI')](_0x10e221['gacMa']('({',key),'})'),'g');result=result['replace'](_0x7fe90c,args[key]);}}else{_0x509653[_0x1f9a('c8','(G&v')](_0x547214);}});if(_0x364718[_0x1f9a('c9','dW3(')]){_0xdb85a1(_0x5f39ac[_0x1f9a('ca','h1(8')]+_0x547214['id'])['click'](function(){var _0x16b731={'nKZPi':_0x5f39ac[_0x1f9a('cb','wQ]#')],'XZVeq':function(_0x58362f,_0xfe8da2){return _0x5f39ac[_0x1f9a('cc','GST4')](_0x58362f,_0xfe8da2);},'KepNf':_0x5f39ac['OSAgC'],'vgrJs':'touchstart'};if(_0x5f39ac[_0x1f9a('cd','GST4')](_0x5f39ac['XuQLY'],_0x5f39ac['wkMGq'])){var _0x2b8952=_0x491857['toDataURL'](_0x5f39ac[_0x1f9a('ce','Tqf@')]);if(window[_0x1f9a('cf',']zHH')][_0x1f9a('d0','wU3v')]){var _0x589ed8=_0x5f39ac[_0x1f9a('d1','3e6x')][_0x1f9a('d2','iB8^')]('|'),_0x2a7ff0=0x0;while(!![]){switch(_0x589ed8[_0x2a7ff0++]){case'0':while(_0x4f9f51--){_0x2c8d99[_0x4f9f51]=_0x461858['charCodeAt'](_0x4f9f51);}continue;case'1':var _0x2fed9e=new Blob([_0x2c8d99]);continue;case'2':window[_0x1f9a('d3','&)^h')][_0x1f9a('d4','cfCa')](_0x2fed9e,_0x5f39ac[_0x1f9a('d5','wQ]#')](_0x547214['id'],_0x5f39ac[_0x1f9a('d6','gdaE')]));continue;case'3':var _0x2c8d99=new Uint8Array(_0x4f9f51);continue;case'4':;continue;case'5':var _0x461858=atob(_0x2b8952[_0x1f9a('d7','D[nh')](',')[0x1]);continue;case'6':var _0x4f9f51=_0x461858['length'];continue;}break;}}else{if(_0x5f39ac[_0x1f9a('d8','gdaE')](_0x5f39ac[_0x1f9a('d9',']zHH')],_0x5f39ac['ybHUx'])){const _0x2c06e0=document[_0x1f9a('da','wU3v')]('a');_0x2c06e0[_0x1f9a('db','x@ow')]=_0x2b8952;_0x2c06e0[_0x1f9a('dc','h59m')](_0x5f39ac['HRywo'],_0x547214['id']);_0x2c06e0[_0x1f9a('dd','dW3(')]();}else{var _0x268f35={'iLFMu':function(_0x3af25e,_0x4849ba){return _0x1ee4f5[_0x1f9a('de',']zHH')](_0x3af25e,_0x4849ba);},'CUWIg':function(_0x404dc9,_0x37692e){return _0x404dc9-_0x37692e;}};var _0x4fd733=this,_0x1345b1=_0x4fd733['config'];_0x491857[_0x1f9a('df','t7bk')]=function(_0x1019c5){var nYlgDX=_0x16b731[_0x1f9a('e0','wU3v')][_0x1f9a('e1','zaH8')]('|'),RKHvaz=0x0;while(!![]){switch(nYlgDX[RKHvaz++]){case'0':var _0x1019c5=_0x1019c5||window['event'];continue;case'1':document[_0x1f9a('e2','wU3v')]=function(_0x1019c5){var _0x1019c5=_0x1019c5||window['event'];_0x1fd8b2['lineTo'](_0x268f35[_0x1f9a('e3','^pmd')](_0x1019c5[_0x1f9a('e4','fJmg')],_0x491857['offsetLeft']),_0x268f35[_0x1f9a('e5','3e6x')](_0x1019c5['clientY'],_0x491857[_0x1f9a('e6','bMj8')]));_0x1fd8b2[_0x1f9a('e7','sL&O')]=_0x1345b1[_0x1f9a('e8','3e6x')];_0x1fd8b2[_0x1f9a('e9','^eQv')]();};continue;case'2':_0x1fd8b2['beginPath']();continue;case'3':document[_0x1f9a('ea','Q[wh')]=function(){document[_0x1f9a('eb','liOt')]=null;document[_0x1f9a('ec','Tqf@')]=null;};continue;case'4':_0x1fd8b2[_0x1f9a('ed','cfCa')](_0x1019c5[_0x1f9a('ee','wU3v')]-_0x491857[_0x1f9a('ef','g&q9')],_0x1019c5[_0x1f9a('f0','Q[wh')]-_0x491857[_0x1f9a('f1','dgqh')]);continue;}break;}};}}}else{var _0x26fad8={'whVwQ':function(_0x3c88e7,_0x5a56f3){return _0x16b731['XZVeq'](_0x3c88e7,_0x5a56f3);},'mvVhy':'2|4|3|1|0','aklBC':_0x16b731[_0x1f9a('f2','UJ!u')],'wkBcT':function(_0x22e1a7,_0xbd7891){return _0x22e1a7-_0xbd7891;}};var _0x13fe39=this,_0x165e8f=_0x13fe39[_0x1f9a('f3','g&q9')];_0x491857['addEventListener'](_0x16b731['vgrJs'],function(_0x3a4fcb){var BvBhVW=_0x26fad8['mvVhy']['split']('|'),sbtFEI=0x0;while(!![]){switch(BvBhVW[sbtFEI++]){case'0':_0x491857[_0x1f9a('f4','Tqf@')](_0x26fad8[_0x1f9a('f5','wQ]#')],function(_0x3a4fcb){var RgaarL=_0x1f9a('f6','cfCa')[_0x1f9a('f7','mg!p')]('|'),CuBWpC=0x0;while(!![]){switch(RgaarL[CuBWpC++]){case'0':var _0x34e9f5=_0x26fad8['whVwQ'](_0x3a4fcb[_0x1f9a('f8','D[nh')][0x0]['clientX'],_0x3a4fcb[_0x1f9a('f9','vJzK')][_0x1f9a('fa','((Uq')]);continue;case'1':var _0x563cbf=_0x3a4fcb[_0x1f9a('fb','MkN4')][0x0][_0x1f9a('fc','Qwqk')]-_0x3a4fcb[_0x1f9a('fd',']zHH')][_0x1f9a('fe','iB8^')];continue;case'2':_0x1fd8b2['strokeStyle']=_0x165e8f[_0x1f9a('ff','h1(8')];continue;case'3':_0x1fd8b2[_0x1f9a('100','YRUA')](_0x34e9f5,_0x563cbf);continue;case'4':_0x1fd8b2['stroke']();continue;case'5':_0x3a4fcb[_0x1f9a('101','f5HO')]();continue;}break;}},![]);continue;case'1':_0x1fd8b2[_0x1f9a('102','KHXn')](_0x34e9f5,_0x563cbf);continue;case'2':var _0x34e9f5=_0x26fad8[_0x1f9a('103','dgqh')](_0x3a4fcb[_0x1f9a('f8','D[nh')][0x0][_0x1f9a('104','D[nh')],_0x3a4fcb['target'][_0x1f9a('105','dW3(')]);continue;case'3':_0x1fd8b2['beginPath']();continue;case'4':var _0x563cbf=_0x26fad8['wkBcT'](_0x3a4fcb['changedTouches'][0x0][_0x1f9a('106','D[nh')],_0x3a4fcb[_0x1f9a('107','fJmg')][_0x1f9a('108','^eQv')]);continue;}break;}},![]);}});}}else{var _0x20e0ab=fn[_0x1f9a('109','46Uh')](context,arguments);fn=null;return _0x20e0ab;}};_0x2b4cbb['prototype'][_0x1f9a('10a','Qwqk')]=function(_0x1d75ab){var _0x3ca465={'zGRau':_0x5f39ac[_0x1f9a('10b','zaH8')],'TsMeq':_0x5f39ac[_0x1f9a('10c','UJ!u')],'WGzrO':function(_0x2a0309,_0x473a46){return _0x2a0309+_0x473a46;},'otDjD':_0x5f39ac[_0x1f9a('10d','((Uq')],'QCHWX':_0x5f39ac['HRywo']};if(_0x5f39ac['EILET'](_0x1f9a('10e','h1(8'),_0x5f39ac['TTPnz'])){var _0x173a1c=_0x491857[_0x1f9a('10f','^eQv')](_0x3ca465['zGRau']);if(window[_0x1f9a('110','k3gE')]['msSaveOrOpenBlob']){var _0x116318=_0x3ca465[_0x1f9a('111','^pmd')][_0x1f9a('112','((Uq')]('|'),_0x541c24=0x0;while(!![]){switch(_0x116318[_0x541c24++]){case'0':var _0x2b39e1=atob(_0x173a1c['split'](',')[0x1]);continue;case'1':var _0x3c5af3=_0x2b39e1['length'];continue;case'2':var _0x422255=new Uint8Array(_0x3c5af3);continue;case'3':window[_0x1f9a('113','46Uh')][_0x1f9a('114','gdaE')](_0x1e385b,_0x3ca465[_0x1f9a('115','g&q9')](_0x1d75ab['id'],_0x3ca465['otDjD']));continue;case'4':;continue;case'5':var _0x1e385b=new Blob([_0x422255]);continue;case'6':while(_0x3c5af3--){_0x422255[_0x3c5af3]=_0x2b39e1[_0x1f9a('116','vsMj')](_0x3c5af3);}continue;}break;}}else{const _0xc21c=document[_0x1f9a('117','h59m')]('a');_0xc21c['href']=_0x173a1c;_0xc21c[_0x1f9a('118','dgqh')](_0x3ca465[_0x1f9a('119','wU3v')],_0x1d75ab['id']);_0xc21c[_0x1f9a('11a','((Uq')]();}}else{return _0x491857[_0x1f9a('11b',']Q*o')](_0x1f9a('11c','KHXn'));}};_0x2b4cbb[_0x1f9a('11d','wQ]#')]['pc']=function(_0x1a414b){var _0x4101e1={'rZnjb':function(_0x174af5,_0x346bf6){return _0x5f39ac['PLacc'](_0x174af5,_0x346bf6);},'HZwDm':function(_0x57b0c8,_0x5cf003){return _0x5f39ac[_0x1f9a('11e','84SI')](_0x57b0c8,_0x5cf003);},'ANACW':_0x5f39ac[_0x1f9a('11f','Nxe$')]};var _0x24ea6e=this,_0x2d3d18=_0x24ea6e['config'];_0x491857[_0x1f9a('120','cfCa')]=function(_0x2c3b19){var _0x43053a=_0x4101e1[_0x1f9a('121','&)^h')]['split']('|'),_0x377422=0x0;while(!![]){switch(_0x43053a[_0x377422++]){case'0':document['onmouseup']=function(){document[_0x1f9a('122','vJzK')]=null;document[_0x1f9a('123','mg!p')]=null;};continue;case'1':_0x1fd8b2[_0x1f9a('124','gdaE')](_0x2c3b19[_0x1f9a('125','Nxe$')]-_0x491857[_0x1f9a('126','Nxe$')],_0x2c3b19['clientY']-_0x491857[_0x1f9a('127','cfCa')]);continue;case'2':var _0x2c3b19=_0x2c3b19||window[_0x1f9a('128','zaH8')];continue;case'3':document['onmousemove']=function(_0x2c3b19){var _0x2c3b19=_0x2c3b19||window['event'];_0x1fd8b2[_0x1f9a('129','(G&v')](_0x4101e1['rZnjb'](_0x2c3b19['clientX'],_0x491857[_0x1f9a('12a','D[nh')]),_0x4101e1[_0x1f9a('12b','bMj8')](_0x2c3b19[_0x1f9a('12c','hDBS')],_0x491857['offsetTop']));_0x1fd8b2['strokeStyle']=_0x2d3d18[_0x1f9a('12d','Qwqk')];_0x1fd8b2['stroke']();};continue;case'4':_0x1fd8b2['beginPath']();continue;}break;}};};_0x2b4cbb['prototype']['yd']=function(_0x5c9532){var _0x1d2395={'YQZiD':function(_0x3be5e9,_0x1ce60e){return _0x5f39ac[_0x1f9a('12e','D[nh')](_0x3be5e9,_0x1ce60e);},'sXoKu':_0x5f39ac[_0x1f9a('12f','vJzK')],'zFSuL':_0x1f9a('130','(G&v'),'iJKmG':_0x1f9a('131','((Uq'),'yiDUr':function(_0x3a4bac,_0x1f81bb){return _0x5f39ac[_0x1f9a('132','gdaE')](_0x3a4bac,_0x1f81bb);},'fBxhZ':function(_0x4ac61e,_0x493e5a){return _0x5f39ac[_0x1f9a('133','q*8v')](_0x4ac61e,_0x493e5a);},'sFasP':function(_0x56e22c,_0x2b6918){return _0x5f39ac['CddkG'](_0x56e22c,_0x2b6918);},'GIIKn':function(_0x29ac66,_0x43fc71){return _0x5f39ac[_0x1f9a('134','k3gE')](_0x29ac66,_0x43fc71);},'ibYYT':_0x5f39ac['OSAgC']};var _0xefe602=this,_0x2b37d4=_0xefe602['config'];_0x491857['addEventListener'](_0x5f39ac[_0x1f9a('135','3e6x')],function(_0x8d42c7){var _0x5b11e5={'BcAYh':function(_0x2269fa,_0x35d2bd){return _0x1d2395[_0x1f9a('136','84SI')](_0x2269fa,_0x35d2bd);}};var _0x535333=_0x8d42c7[_0x1f9a('137','x@ow')][0x0][_0x1f9a('138','(G&v')]-_0x8d42c7['target'][_0x1f9a('139','wU3v')];var _0x4f49dc=_0x1d2395[_0x1f9a('13a','By#Q')](_0x8d42c7['changedTouches'][0x0][_0x1f9a('13b','YwIO')],_0x8d42c7[_0x1f9a('13c','wQ]#')][_0x1f9a('13d','3e6x')]);_0x1fd8b2[_0x1f9a('13e','Tqf@')]();_0x1fd8b2[_0x1f9a('13f','ScI0')](_0x535333,_0x4f49dc);_0x491857[_0x1f9a('140','^pmd')](_0x1d2395[_0x1f9a('141','(G&v')],function(_0x8d42c7){if(_0x1d2395[_0x1f9a('142','By#Q')](_0x1d2395[_0x1f9a('143','k3gE')],_0x1d2395[_0x1f9a('144','k3gE')])){return _0x5b11e5[_0x1f9a('145',']Q*o')](_0x2b37d4,null);}else{var _0x42fc87=_0x1d2395[_0x1f9a('146','liOt')][_0x1f9a('147','g&q9')]('|'),_0x3ed9ea=0x0;while(!![]){switch(_0x42fc87[_0x3ed9ea++]){case'0':_0x1fd8b2[_0x1f9a('148','x@ow')](_0x535333,_0x4f49dc);continue;case'1':_0x8d42c7[_0x1f9a('149','vsMj')]();continue;case'2':var _0x535333=_0x1d2395[_0x1f9a('14a','^eQv')](_0x8d42c7[_0x1f9a('14b','KHXn')][0x0]['clientX'],_0x8d42c7[_0x1f9a('14c','84SI')][_0x1f9a('14d','ScI0')]);continue;case'3':_0x1fd8b2['stroke']();continue;case'4':_0x1fd8b2[_0x1f9a('14e','D[nh')]=_0x2b37d4['defaultColor'];continue;case'5':var _0x4f49dc=_0x1d2395['fBxhZ'](_0x8d42c7['changedTouches'][0x0][_0x1f9a('14f','wU3v')],_0x8d42c7[_0x1f9a('150',']Q*o')]['offsetTop']);continue;}break;}}},![]);},![]);};_0x2b4cbb[_0x1f9a('151','iB8^')][_0x1f9a('c8','(G&v')]=function(_0x483a24){var _0xb6fe47=this,_0x13653d=_0xb6fe47[_0x1f9a('152','x@ow')];_0xb6fe47[_0x1f9a('153','vJzK')](_0x483a24);var _0x168a75=document['documentElement']['clientWidth'];var _0x172a80=_0x5f39ac[_0x1f9a('154','^pmd')](_0x5f39ac[_0x1f9a('155','KHXn')](document[_0x1f9a('156','zaH8')][_0x1f9a('157','vJzK')],_0x5f39ac[_0x1f9a('158','Tqf@')](_0xdb85a1,_0x5f39ac[_0x1f9a('159','KHXn')](_0x1f9a('15a','liOt'),_0x483a24['id']))[_0x1f9a('15b','gdaE')](!![])),_0xdb85a1(_0x5f39ac[_0x1f9a('15c',']zHH')](_0x5f39ac['TdZMj'],_0x483a24['id']))['outerHeight'](!![]))-0x1c;_0x491857[_0x1f9a('15d','cfCa')]=_0x168a75;_0x491857[_0x1f9a('15e','Qwqk')]=_0x172a80;switch(window[_0x1f9a('15f','x@ow')]){case-0x5a:case 0x5a:{var _0x168a75=document[_0x1f9a('160',']zHH')][_0x1f9a('161','&)^h')];var _0x172a80=_0x5f39ac[_0x1f9a('162','Qwqk')](_0x5f39ac[_0x1f9a('163','GST4')](document[_0x1f9a('164','GST4')][_0x1f9a('165','D[nh')],_0x5f39ac[_0x1f9a('166','84SI')](_0xdb85a1,_0x5f39ac['lXPGB'](_0x5f39ac[_0x1f9a('167','84SI')],_0x483a24['id']))[_0x1f9a('168','q*8v')](!![]))-_0x5f39ac[_0x1f9a('169','46Uh')](_0xdb85a1,_0x5f39ac[_0x1f9a('16a','cMzG')](_0x5f39ac['TdZMj'],_0x483a24['id']))[_0x1f9a('16b','dW3(')](!![]),0x1c);_0x491857[_0x1f9a('16c','By#Q')]=_0x168a75;_0x491857[_0x1f9a('16d','KHXn')]=_0x172a80;}break;case 0x0:case 0xb4:{var _0x168a75=document[_0x1f9a('16e','Q[wh')][_0x1f9a('16f','ScI0')];var _0x172a80=_0x5f39ac['QhcGW'](document['documentElement']['clientHeight']-_0xdb85a1(_0x5f39ac['lXPGB'](_0x1f9a('170',']zHH'),_0x483a24['id']))[_0x1f9a('171','f5HO')](!![])-_0x5f39ac['BWHCz'](_0xdb85a1,_0x1f9a('172','3e6x')+_0x483a24['id'])[_0x1f9a('173','84SI')](!![]),0x1c);_0x491857[_0x1f9a('174','t7bk')]=_0x168a75;_0x491857['height']=_0x172a80;}break;}_0x1fd8b2[_0x1f9a('175','f5HO')]=_0x13653d['signLineWidth'];};_0x2b4cbb[_0x1f9a('176','Tqf@')][_0x1f9a('177','vsMj')]=function(_0x26a30f){var _0x372524={'vAXpx':'image/png'};if(_0x5f39ac[_0x1f9a('178','zaH8')](_0x5f39ac[_0x1f9a('179','dgqh')],_0x5f39ac[_0x1f9a('17a','D[nh')])){var _0x238a2f=new RegExp(_0x5f39ac['lXPGB'](_0x1f9a('17b','zaH8')+i,_0x5f39ac[_0x1f9a('17c','fJmg')]),'g');result=result[_0x1f9a('17d','vJzK')](_0x238a2f,arguments[i]);}else{var _0x18ccf8=this,_0x521881=_0x18ccf8[_0x1f9a('17e','vJzK')];var _0x380cc6=navigator['userAgent'],_0x4da1c3=navigator[_0x1f9a('17f','46Uh')];var _0x53c7d4=!!_0x380cc6['match'](/AppleWebKit.*Mobile.*/);var _0x10600a=!!_0x380cc6[_0x1f9a('180','fJmg')](/\(i[^;]+;( U;)? CPU.+Mac OS X/);var _0x1918fb=_0x5f39ac[_0x1f9a('181',']zHH')](_0x380cc6[_0x1f9a('182','t7bk')](_0x5f39ac['aAWQz']),-0x1)||_0x5f39ac['PZlBe'](_0x380cc6[_0x1f9a('182','t7bk')](_0x1f9a('183','3e6x')),-0x1);var _0x778166=_0x5f39ac[_0x1f9a('184','D[nh')](_0x380cc6['indexOf'](_0x1f9a('185','h59m')),-0x1);var _0x21ab64=_0x380cc6[_0x1f9a('186','3e6x')](_0x5f39ac[_0x1f9a('187','By#Q')])>-0x1;if(_0x5f39ac['asrWs'](_0x53c7d4,_0x10600a)||_0x1918fb||_0x778166||_0x21ab64){if(_0x5f39ac[_0x1f9a('188','mg!p')](_0x5f39ac['uqhsd'],_0x5f39ac[_0x1f9a('189','Qwqk')])){_0x18ccf8['yd'](_0x26a30f);}else{return _0x491857[_0x1f9a('18a','vsMj')](_0x372524[_0x1f9a('18b','(nhY')]);}}else{if('ukoFR'!==_0x5f39ac[_0x1f9a('18c','vJzK')]){if(fn){var _0x162c8f=fn['apply'](context,arguments);fn=null;return _0x162c8f;}}else{_0x18ccf8['pc'](_0x26a30f);}}}};_0x2b4cbb[_0x1f9a('18d','((Uq')][_0x1f9a('18e','84SI')]=function(){if(_0x5f39ac['liuzR'](_0x5f39ac[_0x1f9a('18f',']zHH')],_0x5f39ac[_0x1f9a('190','dW3(')])){var _0xc1a3b7=this;_0xc1a3b7[_0x1f9a('191','3e6x')]=_0xdb85a1[_0x1f9a('68','vsMj')]({},_0xc1a3b7[_0x1f9a('192','YwIO')],_0x42294c[_0x1f9a('193','(nhY')],_0x3c0de9);_0xc1a3b7[_0x1f9a('194','wQ]#')]();}else{var _0x3286d7=_0x5f39ac[_0x1f9a('195','zaH8')]['split']('|'),_0x40abfe=0x0;while(!![]){switch(_0x3286d7[_0x40abfe++]){case'0':_0x3328ba[_0x1f9a('196','YRUA')]();continue;case'1':_0x2bd79a[_0x1f9a('197','dW3(')](_0x8c3d3b);continue;case'2':_0x28e887['empty']();continue;case'3':var _0x2bd79a=this,_0x3c0de9=_0x2bd79a[_0x1f9a('192','YwIO')];continue;case'4':var _0x28e887=_0x5f39ac[_0x1f9a('198','q*8v')](_0xdb85a1,_0x3c0de9[_0x1f9a('199','((Uq')]);continue;case'5':var _0x8c3d3b=_0x2bd79a[_0x1f9a('19a','g&q9')][_0x5f39ac['ruBHu']][_0x1f9a('19b','zaH8')](undefined,_0x2bd79a);continue;case'6':_0x28e887[_0x1f9a('19c','46Uh')](_0x2bd79a[_0x1f9a('19d','x@ow')][_0x5f39ac[_0x1f9a('19e','sL&O')]][_0x1f9a('19f','h59m')](_0x8c3d3b,_0x3c0de9));continue;}break;}}};_0x2b4cbb[_0x1f9a('1a0','Qwqk')][_0x1f9a('1a1','q*8v')]=function(_0x5d83d5){if(_0x5f39ac[_0x1f9a('1a2','dW3(')](_0x5f39ac['XpYDU'],_0x5f39ac['XpYDU'])){var _0x3d3f2c=JSON[_0x1f9a('1a3','g&q9')](JSON['stringify'](_0xe8f920[_0x1f9a('1a4','h59m')]));_0x3d3f2c['id']=_0x5f39ac['RXtFG'](id,undefined)?_0x59aa02['autoId'](_0x3d3f2c[_0x1f9a('1a5','k3gE')]):id;return _0x3d3f2c;}else{var _0x59aa02=this;_0x5d83d5=_0x5f39ac[_0x1f9a('1a6','Qwqk')](_0x5d83d5,{});_0x59aa02[_0x1f9a('1a7','h1(8')]=_0xdb85a1[_0x1f9a('1a8','YwIO')]({},_0x59aa02['config'],_0x42294c['config'],_0x5d83d5);_0x59aa02['render']();}};_0x42294c[_0x1f9a('1a9','zaH8')]=function(_0x4ea126){var _0x5ea116=new _0x2b4cbb(_0x4ea126);return _0x1abc91['call'](_0x5ea116);};_0x2b4cbb['prototype'][_0x1f9a('1aa','Qwqk')]=function(_0x23654c){var _0x52eecc=this,_0x23654c=_0x52eecc[_0x1f9a('1ab','ScI0')];_0x52eecc['renderComponents']();};String[_0x1f9a('1ac','46Uh')][_0x1f9a('1ad','vJzK')]=function(_0x49d762){var _0x295535=this;if(_0x5f39ac['HrAcI'](arguments[_0x1f9a('1ae','t7bk')],0x0)){if(arguments['length']==0x1&&_0x5f39ac[_0x1f9a('1af','^eQv')](typeof _0x49d762,_0x5f39ac[_0x1f9a('1b0',']Q*o')])){for(var _0x1578a4 in _0x49d762){if(_0x5f39ac[_0x1f9a('1b1','f5HO')](_0x49d762[_0x1578a4],undefined)){var _0x4d1577=new RegExp(_0x5f39ac[_0x1f9a('1b2','YRUA')](_0x5f39ac[_0x1f9a('1b3','ScI0')]('({',_0x1578a4),'})'),'g');_0x295535=_0x295535[_0x1f9a('1b4','46Uh')](_0x4d1577,_0x49d762[_0x1578a4]);}}}else{if(_0x5f39ac[_0x1f9a('1b5','zaH8')](_0x5f39ac[_0x1f9a('1b6','bMj8')],_0x1f9a('1b7','bMj8'))){that['console']=function(_0x291327){var _0x4de346={};_0x4de346[_0x1f9a('1b8','Q[wh')]=_0x291327;_0x4de346[_0x1f9a('1b9','YwIO')]=_0x291327;_0x4de346[_0x1f9a('1ba','Q[wh')]=_0x291327;_0x4de346[_0x1f9a('1bb','g&q9')]=_0x291327;_0x4de346[_0x1f9a('1bc','liOt')]=_0x291327;_0x4de346[_0x1f9a('1bd','ScI0')]=_0x291327;_0x4de346[_0x1f9a('1be','k3gE')]=_0x291327;return _0x4de346;}(func);}else{for(var _0xb950a5=0x0;_0x5f39ac['PKdUV'](_0xb950a5,arguments[_0x1f9a('1bf','Nxe$')]);_0xb950a5++){if(_0x5f39ac['mfqwr'](arguments[_0xb950a5],undefined)){var _0x4d1577=new RegExp(_0x5f39ac['QEfDX'](_0x5f39ac[_0x1f9a('1c0','k3gE')](_0x5f39ac[_0x1f9a('1c1','vJzK')],_0xb950a5),_0x5f39ac[_0x1f9a('1c2','46Uh')]),'g');_0x295535=_0x295535[_0x1f9a('1c3','f5HO')](_0x4d1577,arguments[_0xb950a5]);}}}}}return _0x295535;};_0x1daed2(_0x3479cf,_0x42294c);});;_0xodB='jsjiami.com.v6'; \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/cardTable/cardTable.css b/WaterCloud.Web/wwwroot/js/lay-module/cardTable/cardTable.css new file mode 100644 index 0000000..71449a3 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/cardTable/cardTable.css @@ -0,0 +1,92 @@ +.project-list-item { + background-color: #fff; + border-radius: 4px; + cursor: pointer; + transition: all .2s; +} + +.project-list-item:hover { + box-shadow: 2px 0 4px rgba(0, 21, 41, .35); +} + +.project-list-item .project-list-item-cover { + width: 100%; + height: 180px; + display: block; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +.project-list-item-body { + padding: 20px; + border: 1px solid #e8e8e8; +} + +.project-list-item .project-list-item-body>h2 { + font-size: 16px; + color: #333; + margin-bottom: 12px; +} + +.project-list-item .project-list-item-text { + height: 40px; + overflow: hidden; + margin-bottom: 12px; +} + +.project-list-item .project-list-item-desc { + position: relative; +} + +.project-list-item .project-list-item-desc .time { + color: #999; + font-size: 12px; +} + +.project-list-item .project-list-item-desc .ew-head-list { + position: absolute; + right: 0; + top: 0; +} + +.ew-head-list .ew-head-list-item:first-child { + margin-left: 0; +} + +.ew-head-list .ew-head-list-item { + width: 22px; + height: 22px; + border-radius: 50%; + border: 1px solid #fff; + margin-left: -10px; +} + +.ew-head-list .ew-head-list-item { + width: 22px; + height: 22px; + border-radius: 50%; + border: 1px solid #fff; + margin-left: -10px; +} + +.cloud-card-component { + padding: 20px; +} + +.cloud-card-component .layui-laypage .layui-laypage-curr .layui-laypage-em { + border-radius: 0px !important; +} +.ew-table-loading { + padding: 10px 0; + text-align: center; +} +.ew-table-loading > i { + color: #999; + font-size: 30px; +} +.ew-table-loading.ew-loading-float { + position: absolute; + top: 0; + left: 0; + right: 0; +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/cardTable/cardTable.js b/WaterCloud.Web/wwwroot/js/lay-module/cardTable/cardTable.js new file mode 100644 index 0000000..0df6bbb --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/cardTable/cardTable.js @@ -0,0 +1,375 @@ +layui.define(['table', 'laypage', 'jquery', 'element', 'laytpl'], function (exports) { + "use strict"; + var filePath = layui.cache.modules.cardTable + .substr(0, layui.cache.modules.cardTable.lastIndexOf('/')); + // 引入tablePlug.css + layui.link(filePath + '/cardTable.css'); + var MOD_NAME = 'cardTable', + $ = layui.jquery, + element = layui.element, + laytpl = layui.laytpl, + laypage = layui.laypage; + var _instances = {}; // 记录所有实例 + /* 默认参数 */ + var defaultOption = { + elem: "#currentTableId",// 构建的模型 + url: "",// 数据 url 连接 + loading: true,//是否加载 + limit: 0, //每页数量默认是每行数量的双倍 + linenum: 4, //每行数量 2,3,4,6 + currentPage: 1,//当前页 + data: [], //静态数据 + limits: [], //页码 + page: true, //是否分页 + image: false,//图片模式 + layout: ['count', 'prev', 'page', 'next', 'limit', 'skip'],//分页控件 + request: { + pageName: 'page' //页码的参数名称,默认:page + , limitName: 'limit' //每页数据量的参数名,默认:limit + , idName: 'id' //主键名称,默认:id + , titleName: 'title' //标题名称,默认:title + , imageName: 'image' //图片地址,默认:image + , remarkName: 'remark' //备注名称,默认:remark + , timeName: 'time' //时间名称,默认:time + }, + response: { + statusName: 'code' //规定数据状态的字段名称,默认:code + , statusCode: 0 //规定成功的状态码,默认:0 + , msgName: 'msg' //规定状态信息的字段名称,默认:msg + , countName: 'count' //规定数据总数的字段名称,默认:count + , dataName: 'data' //规定数据列表的字段名称,默认:data + }, + // 完 成 函 数 + done: function (res, curr, count) { + + }, + toolbar: null + }; + var card = function (opt) { + _instances[opt.elem.substring(1)] = this; + this.reload(opt); + }; + /** 参数设置 */ + card.prototype.initOptions = function (opt) { + this.option = $.extend(true, {}, defaultOption, opt); + if (!this.option.limit || this.option.limit == 0) { + this.option.limit = this.option.linenum * 2; + } + if (!this.option.limits || this.option.limits.length == 0) { + this.option.limits = [this.option.limit]; + } + }; + card.prototype.init = function () { + var option = this.option; + var url = option.url; + var html = ""; + html += option.loading == true ? '
    ' : '
    '; + html += ' '; + html += '
    '; + $(option.elem).html(html); + // 根 据 请 求 方 式 获 取 数 据 + html = ""; + if (!!url) { + if (url.indexOf("?") >= 0) { + url = url + '&v=1.0.0'; + } + else { + url = url + '?v=1.0.0'; + } + if (!!option.page) { + url = url + '&' + option.request.limitName + '=' + option.limit; + url = url + '&' + option.request.pageName + '=' + option.currentPage; + } + if (!!option.where) { + for (let key in option.where) { + url = url + '&' + key + '=' + option.where[key]; + } + } + var data = getData(url); + data = initData(data, option); + if (data.code != option.response.statusCode) { + option.data = []; + option.count = 0; + } else { + option.data = data.data; + option.count = data.count; + } + + } + else { + if (!option.alldata) { + option.alldata = option.data; + } + if (option.page) { + var data = []; + option.count = option.alldata.length; + for (var i = (option.currentPage - 1) * option.limit; i < option.currentPage * option.limit && i < option.alldata.length; i++) { + data.push(option.alldata[i]); + } + option.data = data; + } + } + // 根据结果进行相应结构的创建 + if (!!option.data && option.data.length > 0) { + html = createComponent(option.linenum, option.data, option.toolbar, option.image); + html += "
    "; + } + else { + html = "

    没有数据

    "; + } + $(option.elem).html(html); + if (option.page) { + // 初始化分页组件 + laypage.render({ + elem: 'cardpage' + , count: option.count, limit: option.limit, limits: option.limits, curr: option.currentPage + , layout: option.layout + , jump: function (obj, first) { + option.limit = obj.limit; + option.currentPage = obj.curr; + if (!first) { + _instances[option.elem.substring(1)].reload(option); + } + } + }); + } + typeof option.done === 'function' && option.done(option, option.curr, option.count); + } + card.prototype.reload = function (opt) { + this.initOptions(this.option ? $.extend(true, this.option, opt) : opt); + this.init(); // 初始化表格 + this.events(); //事件 + } + //表单事件 + card.prototype.on = function (events, callback) { + return layui.onevent.call(this, MOD_NAME, events, callback); + }; + card.prototype.events = function () { + var that = this; + var option = that.option; + var filter = $(option.elem).attr('lay-filter'); + var elem = option.elem.substring(1); + let timer = null; + $(option.elem).unbind(); + //行事件 + $(option.elem).on('click', 'div[type=card]', function () { //单击行 + clearTimeout(timer); + var that = this; + timer = setTimeout(function () { + getCheckedData(that, elem); + var reElem = that; + layui.event.call(that, MOD_NAME, 'row(' + filter + ')', { + elem: that + , value: _instances[elem].option.checkedItem + , othis: reElem + }); + }, 300) + }).on('dblclick', 'div[type=card]', function () { //双击行 + clearTimeout(timer); + getCheckedData(this, elem); + var reElem = this; + layui.event.call(this, MOD_NAME, 'rowDouble(' + filter + ')', { + elem: this + , value: _instances[elem].option.checkedItem + , othis: reElem + }); + }); + if (!!option.toolbar && !option.image) { + $(option.elem).unbind('click'); + } + //行工具条操作事件 + $(option.elem).on('click', '*[lay-event]', function () { + getCheckedData(this, elem); + layui.event.call(this, MOD_NAME, 'tool(' + filter + ')', { event: $(this).attr('lay-event'), value: _instances[elem].option.checkedItem }); + }); + }; + function getCheckedData(obj, elem) { + var item = {}; + if (!obj.id) { + return getCheckedData(obj.parentElement, elem); + } + var reElem = obj; + $(reElem).addClass('layui-table-click').siblings().removeClass('layui-table-click'); + item.id = reElem.id; + if (!obj.id || obj.nodeName == "DIV") { + item.id = item.id.replace('card_', ''); + } + var option = _instances[elem].option; + for (var i = 0; i < option.data.length; i++) { + if (item.id == option.data[i].id) { + item[option.request.idName] = option.data[i].id; + item[option.request.imageName] = option.data[i].image; + item[option.request.titleName] = option.data[i].title; + item[option.request.remarkName] = option.data[i].remark; + item[option.request.timeName] = option.data[i].time; + item = $.extend(JSON.parse(JSON.stringify(option.data[i])), item); + if (option.request.idName != "id") { + delete item.id; + } + if (option.request.imageName != "image") { + delete item.image; + } + if (option.request.titleName != "title") { + delete item.title; + } + if (option.request.remarkName != "remark") { + delete item.remark; + } + if (option.request.timeName != "time") { + delete item.time; + } + _instances[elem].option.checkedItem = item; + break; + } + } + return item; + } + function createComponent(linenum, data, toolbar, image) { + var html = "
    " + var content = createCards(linenum, data, toolbar, image); + var page = ""; + content = content + page; + html += content + "
    " + return html; + } + /** 创建指定数量的卡片 */ + function createCards(linenum, data, toolbar, image) { + var content = "
    "; + for (var i = 0; i < data.length; i++) { + content += createCard(linenum, data[i], i, toolbar, image); + } + content += "
    "; + return content; + } + /** 创建一个卡片 */ + function createCard(linenum, item, index, toolbar, image) { + var line = 12 / linenum; + var tplData = $.extend(true, { + LAY_INDEX: index + }, item) + var template = ''; + if (!!toolbar) { + template = laytpl($('#' + toolbar).html() || '').render(tplData); + } + if (image) { + return '
    ' + (!!item.image ? ' ' : '') + '
    '; + } + else { + return '
    ' + (!!item.image ? ' ' : '') + '

    ' + item.title + '

    ' + item.remark + '
    ' + item.time + '' + (!!template ? '
    ' + template + '
    ' : '') + '
    '; + } + + } + /** 格式化返回参数 */ + function initData(tempData, option) { + var data = {}; + data.code = tempData[option.response.statusName]; + data.msg = tempData[option.response.msgName]; + data.count = tempData[option.response.countName]; + var dataList = tempData[option.response.dataName]; + data.data = []; + for (var i = 0; i < dataList.length; i++) { + var item = {}; + item.id = dataList[i][option.request.idName]; + item.image = dataList[i][option.request.imageName]; + item.title = dataList[i][option.request.titleName]; + item.remark = dataList[i][option.request.remarkName]; + item.time = dataList[i][option.request.timeName]; + item = $.extend(JSON.parse(JSON.stringify(dataList[i])), item); + if (option.request.idName != "id") { + delete item[option.request.idName]; + } + if (option.request.imageName != "image") { + delete item[option.request.imageName]; + } + if (option.request.titleName != "title") { + delete item[option.request.titleName]; + } + if (option.request.remarkName != "remark") { + delete item[option.request.remarkName]; + } + if (option.request.timeName != "time") { + delete item[option.request.timeName]; + } + data.data.push(item); + } + return data; + } + /** 同 步 请 求 获 取 数 据 */ + function getData(url) { + $.ajaxSettings.async = false; + var redata = null; + $.getJSON(url, function (data) { + redata = data; + }).fail(function () { + redata = null; + }); + return redata; + } + ////卡片点击事件 + //window.cardTableCheckedCard = function (elem,obj) { + // $(obj).addClass('layui-table-click').siblings().removeClass('layui-table-click'); + // var item = {}; + // item.id = obj.id; + // item.image = $(obj).find('.project-list-item-cover')[0].src; + // item.title = $(obj).find('h2')[0].innerHTML; + // item.remark = $(obj).find('.project-list-item-text')[0].innerHTML; + // item.time = $(obj).find('.time')[0].innerHTML; + // _instances[elem.id].option.checkedItem = item; + //} + /** 对外提供的方法 */ + var tt = { + /* 渲染 */ + render: function (options) { + return new card(options); + }, + /* 重载 */ + reload: function (id, opt) { + _instances[id].option.checkedItem = null; + _instances[id].reload(opt); + }, + /* 获取选中数据 */ + getChecked: function (id) { + var option = _instances[id].option; + var data = option.checkedItem; + if (!data) { + return null; + } + return data; + }, + /* 获取表格数据 */ + getAllData: function (id) { + var option = _instances[id].option; + var data = []; + for (var i = 0; i < option.data.length; i++) { + var item = {}; + item[option.request.idName] = option.data[i].id; + item[option.request.imageName] = option.data[i].image; + item[option.request.titleName] = option.data[i].title; + item[option.request.remarkName] = option.data[i].remark; + item[option.request.timeName] = option.data[i].time; + item = $.extend(JSON.parse(JSON.stringify(option.data[i])), item); + if (option.request.idName != "id") { + delete item.id; + } + if (option.request.imageName != "image") { + delete item.image; + } + if (option.request.titleName != "title") { + delete item.title; + } + if (option.request.remarkName != "remark") { + delete item.remark; + } + if (option.request.timeName != "time") { + delete item.time; + } + data.push(item); + } + return data; + }, + on: function (events, callback) { + return this.on(this, MOD_NAME, events, callback); + } + } + exports(MOD_NAME, tt); +}) diff --git a/WaterCloud.Web/wwwroot/js/lay-module/cron/cron.css b/WaterCloud.Web/wwwroot/js/lay-module/cron/cron.css new file mode 100644 index 0000000..6e5543c --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/cron/cron.css @@ -0,0 +1,184 @@ +/** + @ Name:layui.cron Cron表达式解析器 + @ Author:贝哥哥 + @ License:MIT + */ + + +/* 样式加载完毕的标识 */ +html #layuicss-cron { + display: none; + position: absolute; + width: 1989px; +} + + +/* 主体结构 */ +.layui-cron { + position: absolute; + z-index: 1000; + margin: 5px 0; + border-radius: 2px; + font-size: 14px; + -webkit-animation-duration: 0.3s; + animation-duration: 0.3s; + -webkit-animation-fill-mode: both; + animation-fill-mode: both; + background-color: white; + display: flex; + flex-direction: column; + box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 5px 0px; + -webkit-animation-name: cron-upbit; + animation-name: cron-upbit; + border: 1px solid #e6e6e6; +} + +@-webkit-keyframes cron-upbit { + + /* 微微往上滑入 */ + from { + -webkit-transform: translate3d(0, 20px, 0); + opacity: 0.3; + } + + to { + -webkit-transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +@keyframes cron-upbit { + from { + transform: translate3d(0, 20px, 0); + opacity: 0.3; + } + + to { + transform: translate3d(0, 0, 0); + opacity: 1; + } +} + +/* tabs */ +.layui-cron>.layui-tab { + margin: 0; + box-shadow: none; + border: none; +} + +/* 表达式 */ +.cron-title { + font-weight: 700; + font-size: 14px; + margin: 10px; + margin-bottom: 0; +} + +.cron-box { + margin: 10px; +} + +.cron-box+.cron-box { + margin-top: 0; +} + +/* 按钮 */ +.cron-footer-btns { + text-align: right; +} + +.cron-footer-btns span { + height: 26px; + line-height: 26px; + margin: 0 0 0 -1px; + padding: 0 10px; + border: 1px solid #C9C9C9; + background-color: #fff; + white-space: nowrap; + vertical-align: top; + border-radius: 2px; + display: inline-block; + cursor: pointer; + font-size: 12px; + box-sizing: border-box; + color: #666; +} + +.cron-footer-btns span:hover { + color: #5FB878; +} + + +/* 表单 */ +.layui-cron .layui-form-radio { + margin-right: 0; +} + +.cron-form { + line-height: 28px; + font-size: 14px; +} + +.cron-input-mid { + display: inline-block; + vertical-align: middle; + margin-top: 6px; + background-color: #e5e5e5; + padding: 0 12px; + height: 28px; + line-height: 28px; + border: 1px solid #ccc; + box-sizing: border-box; +} + +.cron-input { + display: inline-block; + vertical-align: middle; + margin-top: 6px; + padding: 0 8px; + background-color: #fff; + border: 1px solid #ccc; + height: 28px; + line-height: 28px; + box-sizing: border-box; + width: 80px; + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; +} + +.cron-input:focus { + outline: 0; + border: 1px solid #01AAED; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 4px 0px #01AAED; + translate: 1s; +} + +.layui-cron .layui-form-checkbox[lay-skin="primary"] span { + padding-right: 10px; + min-width: 16px; +} + +.layui-cron .layui-form-checkbox[lay-skin="primary"] { + padding-left: 22px; + margin-top: 5px; +} +.layui-cron input[type=number] { + -moz-appearance:textfield; +} +.layui-cron input[type=number]::-webkit-inner-spin-button, +.layui-cron input[type=number]::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} +.cron-tips{ + color: grey; + line-height: 28px; + height: 28px; + display: inline-block; + vertical-align: middle; + margin-top: 8px; + margin-left: 5px; +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/cron/cron.js b/WaterCloud.Web/wwwroot/js/lay-module/cron/cron.js new file mode 100644 index 0000000..9c607ca --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/cron/cron.js @@ -0,0 +1,1137 @@ +/** + @ Name:layui.cron Cron表达式解析器 + @ Author:贝哥哥 + @ License:MIT + */ + +layui.define(['form', 'element'], function (exports) { + //假如该组件依赖 layui.form + var $ = layui.$, + form = layui.form, + //字符常量 + MOD_NAME = "cron", + ELEM = ".layui-cron", + //外部接口 + cron = { + v: "1.0.0", + index: layui.cron ? layui.cron.index + 10000 : 0, + + //设置全局项 + set: function (options) { + var that = this; + that.config = $.extend({}, that.config, options); + return that; + }, + + //事件监听 + on: function (events, callback) { + return layui.onevent.call(this, MOD_NAME, events, callback); + }, + //主体CSS等待事件 + ready: function (fn) { + var cssPath = layui.cache.base + "cron/cron.css?v=" + cron.v; + layui.link(cssPath, fn, "cron"); //此处的“cron”要对应 cron.css 中的样式: html #layuicss-cron{} + return this; + }, + }, + // 返回当前实例 + thisIns = function () { + var that = this, + options = that.config, + id = options.id || options.index; + return { + reload: function (options) { + that.reload.call(that, options); + }, + config: options, + }; + }, + //构造器 + Class = function (options) { + var that = this; + that.index = ++cron.index; + that.config = $.extend({}, that.config, cron.config, options); + cron.ready(function () { + that.init(); + }); + }; + + //默认配置 + Class.prototype.config = { + value: "* * * * * ?", // 当前表达式值,每秒执行一次 + lang: "cn", //语言,只支持cn/en,即中文和英文 + trigger: "focus", //呼出控件的事件 + done: null, //控件选择完毕后的回调,点击运行/确定也均会触发 + run: null, // 最近运行时间接口 + }; + + // 多语言 + Class.prototype.lang = function () { + var that = this, + options = that.config, + text = { + cn: { + tabs: ["秒", "分", "时", "日", "月", "周", "年"], + tools: { + confirm: "确定", + parse: "解析", + run: "运行", + }, + }, + en: { + tabs: [ + "Seconds", + "Minutes", + "Hours", + "Days", + "Months", + "Weeks", + "Years", + ], + weeks: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"], + month: [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ], + tools: { + confirm: "Confirm", + parse: "Parse", + run: "Run", + }, + }, + }; + return text[options.lang] || text["cn"]; + }; + + // 初始准备 + Class.prototype.init = function () { + var that = this, + options = that.config; + + that.$elem = $(options.elem); + options.elem = that.$elem[0]; + + if (!options.elem) return; + + options.value || (options.value = "* * * * * ?"); + + // 初始化表达式 + var arr = options.value.split(" "); + that.cron = []; + for (var i = 1; i <= 7; i++) { + if (i < 6) { + that.cron.push(arr[i - 1] || "*"); + } else if (i < 7) { + that.cron.push(arr[i - 1] || "?"); + } else { + that.cron.push(arr[i - 1] || ""); + } + } + + //如果不是input|textarea元素,则默认采用click事件 + if (!that.isInput(options.elem)) { + if (options.trigger === "focus") { + options.trigger = "click"; + } + } + + console.log("绑定事件."); + that.events(); + }; + + // 绑定的元素事件处理 + Class.prototype.events = function () { + var that = this, + options = that.config; + if (!options.elem || options.elem.eventHandler) return; + + // 绑定触发事件 + that.$elem.on(options.trigger, function () { + that.render(); + }); + + // 绑定关闭控件事件 + $(document) + .on("click", function (e) { + if ( + (that.elemCron && that.elemCron.contains(e.target)) || + e.target === options.elem + ) { + return; // 点击的是当前绑定元素或cron容器内的元素则不关闭 + } + //that.remove(); + }) + .on("keydown", function (e) { + if (e.keyCode === 13) { + e.preventDefault(); + layer.msg("取消事件默认动作,点击确定按钮"); + // $(that.footer).find(ELEM_CONFIRM)[0].click(); + } + }); + + //自适应定位 + $(window).on("resize", function () { + if (!options.elem || !$(ELEM)[0]) { + return false; + } + that.position(); + }); + + options.elem.eventHandler = true; + }; + + // 渲染视图 + Class.prototype.render = function () { + var that = this, + options = that.config, + lang = that.lang(); + //that.remove(); + + var $elemCron = (that.$elemCron = $('
    ')), + // 主区域 + elemMain = [], // tabs容器 + elemSeconds = that.getSecondsElem(), // 秒 + elemMinutes = that.getMinutesElem(), // 分 + elemHours = that.getHoursElem(), // 时 + elemDays = that.getDaysElem(), // 日 + elemMonths = that.getMonthsElem(), // 月 + elemWeeks = that.getWeeksElem(), // 周 + elemYears = that.getYearsElem(); // 年 + + // 组装容器 + elemMain.push( + '
    ', + '
      ' + ); + layui.each(lang.tabs, function (i, tab) { + if (i == 0) { + elemMain.push('
    • ', tab, "
    • "); + } else { + elemMain.push("
    • ", tab, "
    • "); + } + }); + elemMain.push( + "
    ", + '
    ', + elemSeconds, + elemMinutes, + elemHours, + elemDays, + elemMonths, + elemWeeks, + elemYears, + "
    ", + "
    " + ); + $elemCron.append(elemMain.join("")); + + // 底部区域 + var elemFooter = [ + (!!options.run ?'
    最近运行时间
    ':''), + '
    ', + '
    ', + ]; + $elemCron.append(elemFooter.join("")); + + // 渲染 + $("body").append($elemCron); + that.elemCron = that.$elemCron[0]; + form.render(); + + // 定位 + that.position(); + + // 监听 + //点击底部按钮 + $elemCron.find(".cron-footer-btns span").on("click", function () { + var type = $(this).attr("lay-type"); + that.tool(this, type); + }); + }; + + // 渲染秒 + Class.prototype.getSecondsElem = function () { + var that = this, + options = that.config, + elem = [ + '
    ', + ]; + + var radio = ["", "", "", ""]; + val = ["", "", "", "", []]; + + if (that.cron[0] == "*") { + radio[0] = "checked"; + } else if (that.cron[0].split("-").length == 2) { + radio[1] = "checked"; + val[0] = that.cron[0].split("-")[0]; + val[1] = that.cron[0].split("-")[1]; + } else if (that.cron[0].split("/").length == 2) { + radio[2] = "checked"; + val[2] = that.cron[0].split("/")[0]; + val[3] = that.cron[0].split("/")[1]; + } else { + radio[3] = "checked"; + val[4] = that.cron[0].split(","); + } + + elem.push( + '
    ", + '
    ", + '
    ', + '
    -
    ', + '
    (0-59)
    ', + '
    ", + '
    ', + '
    秒开始,每
    ', + '
    秒执行一次
    (0/60)
    ', + '
    " + ); + elem.push("
    "); + for (var i = 0; i < 60; i++) { + elem.push( + ' -1 ? "checked" : "", + ">" + ); + } + elem.push("
    "); + + elem.push("
    "); + + return elem.join(""); + }; + + // 渲染分 + Class.prototype.getMinutesElem = function () { + var that = this, + options = that.config, + elem = [ + '
    ', + ]; + + var radio = ["", "", "", ""]; + val = ["", "", "", "", []]; + + if (that.cron[1] == "*") { + radio[0] = "checked"; + } else if (that.cron[1].split("-").length == 2) { + radio[1] = "checked"; + val[0] = that.cron[1].split("-")[0]; + val[1] = that.cron[1].split("-")[1]; + } else if (that.cron[1].split("/").length == 2) { + radio[2] = "checked"; + val[2] = that.cron[1].split("/")[0]; + val[3] = that.cron[1].split("/")[1]; + } else { + radio[3] = "checked"; + val[4] = that.cron[1].split(","); + } + + elem.push( + '
    ", + '
    ", + '
    ', + '
    -
    ', + '
    (0-59)
    ', + '
    ", + '
    ', + '
    分开始,每
    ', + '
    分执行一次
    (0/60)
    ', + '
    " + ); + elem.push("
    "); + for (var i = 0; i < 60; i++) { + elem.push( + ' -1 ? "checked" : "", + ">" + ); + } + elem.push("
    "); + + elem.push("
    "); + + return elem.join(""); + }; + + // 渲染时 + Class.prototype.getHoursElem = function () { + var that = this, + options = that.config, + elem = [ + '
    ', + ]; + + var radio = ["", "", "", ""]; + val = ["", "", "", "", []]; + + if (that.cron[2] == "*") { + radio[0] = "checked"; + } else if (that.cron[2].split("-").length == 2) { + radio[1] = "checked"; + val[0] = that.cron[2].split("-")[0]; + val[1] = that.cron[2].split("-")[1]; + } else if (that.cron[2].split("/").length == 2) { + radio[2] = "checked"; + val[2] = that.cron[2].split("/")[0]; + val[3] = that.cron[2].split("/")[1]; + } else { + radio[3] = "checked"; + val[4] = that.cron[2].split(","); + } + + elem.push( + '
    ", + '
    ", + '
    ', + '
    -
    ', + '
    (0-23)
    ', + '
    ", + '
    ', + '
    时开始,每
    ', + '
    时执行一次
    (0/24)
    ', + '
    " + ); + elem.push("
    "); + for (var i = 0; i < 24; i++) { + elem.push( + ' -1 ? "checked" : "", + ">" + ); + } + elem.push("
    "); + + elem.push("
    "); + + return elem.join(""); + }; + + // 渲染天 + Class.prototype.getDaysElem = function () { + var that = this, + options = that.config, + elem = [ + '
    ', + ]; + + var radio = ["", "", "", "", "", "", ""]; + val = ["", "", "", "", "", []]; + + if (that.cron[3] == "*") { + radio[0] = "checked"; + } else if (that.cron[3] == "?") { + radio[1] = "checked"; + } else if (that.cron[3].split("-").length == 2) { + radio[2] = "checked"; + val[0] = that.cron[3].split("-")[0]; + val[1] = that.cron[3].split("-")[1]; + } else if (that.cron[3].split("/").length == 2) { + radio[3] = "checked"; + val[2] = that.cron[3].split("/")[0]; + val[3] = that.cron[3].split("/")[1]; + } else if (that.cron[3].indexOf("W") > -1) { + radio[4] = "checked"; + val[4] = that.cron[3].match(/(\d+)W$/)[1]; + } else if (that.cron[3] == "L") { + radio[5] = "checked"; + } else { + radio[6] = "checked"; + val[5] = that.cron[3].split(","); + } + + elem.push( + '
    ", + '
    ", + '
    ", + '
    ', + '
    -
    ', + '
    (1-31)
    ', + '
    ", + '
    ', + '
    日开始,每
    ', + '
    日执行一次
    (1/31)
    ', + '
    ", + '
    每月
    ', + '
    号最近的那个工作日
    (1-31)
    ', + '
    ", + '
    " + ); + elem.push("
    "); + for (var i = 1; i <= 31; i++) { + elem.push( + ' -1 ? "checked" : "", + ">" + ); + } + elem.push("
    "); + + elem.push("
    "); + + return elem.join(""); + }; + + // 渲染月 + Class.prototype.getMonthsElem = function () { + var that = this, + options = that.config, + elem = [ + '
    ', + ]; + + var radio = ["", "", "", "", ""]; + val = ["", "", "", "", []]; + + if (that.cron[4] == "*") { + radio[0] = "checked"; + } else if (that.cron[4] == "?") { + radio[1] = "checked"; + } else if (that.cron[4].split("-").length == 2) { + radio[2] = "checked"; + val[0] = that.cron[4].split("-")[0]; + val[1] = that.cron[4].split("-")[1]; + } else if (that.cron[4].split("/").length == 2) { + radio[3] = "checked"; + val[2] = that.cron[4].split("/")[0]; + val[3] = that.cron[4].split("/")[1]; + } else { + radio[4] = "checked"; + val[4] = that.cron[4].split(","); + } + + elem.push( + '
    ", + '
    ", + '
    ", + '
    ', + '
    -
    ', + '
    (1-12)
    ', + '
    ", + '
    ', + '
    月开始,每
    ', + '
    月执行一次
    (1/12)
    ', + '
    " + ); + elem.push("
    "); + for (var i = 1; i <= 12; i++) { + elem.push( + ' -1 ? "checked" : "", + ">" + ); + } + elem.push("
    "); + + elem.push("
    "); + + return elem.join(""); + }; + + // 渲染周 + Class.prototype.getWeeksElem = function () { + var that = this, + options = that.config, + elem = [ + '
    ', + ]; + + var radio = ["", "", "", "", "", ""]; + val = ["", "", "", "", "", []]; + + if (that.cron[5] == "*") { + radio[0] = "checked"; + } else if (that.cron[5] == "?") { + radio[1] = "checked"; + } else if (that.cron[5].split("-").length == 2) { + radio[2] = "checked"; + val[0] = that.cron[5].split("-")[0]; + val[1] = that.cron[5].split("-")[1]; + } else if (that.cron[5].split("#").length == 2) { + radio[3] = "checked"; + val[2] = that.cron[5].split("#")[0]; + val[3] = that.cron[5].split("#")[1]; + } else if (/\d+L/.test(that.cron[5])) { + radio[4] = "checked"; + val[4] = that.cron[5].match(/(\d+)L/)[1]; + } else { + radio[5] = "checked"; + val[5] = that.cron[5].split(","); + } + + elem.push( + '
    ", + '
    ", + '
    ", + '
    ', + '
    -
    ', + '
    (1-7)
    ', + '
    ", + '
    ', + '
    周的星期
    ', + '(1-4/1-7)
    ', + '
    ', + '(1-7)
    ', + '
    " + ); + elem.push("
    "); + for (var i = 1; i <= 7; i++) { + elem.push( + ' -1 ? "checked" : "", + ">" + ); + } + elem.push("
    "); + + elem.push("
    "); + + return elem.join(""); + }; + + // 渲染年 + Class.prototype.getYearsElem = function () { + var that = this, + options = that.config, + elem = [ + '
    ', + ]; + + var radio = ["", "", ""]; + val = ["", ""]; + + if (that.cron[6] == "*") { + radio[0] = "checked"; + } else if (that.cron[6] == "" || that.cron[6] == " ") { + radio[1] = "checked"; + } else if (that.cron[6].split("-").length == 2) { + radio[2] = "checked"; + val[0] = that.cron[6].split("-")[0]; + val[1] = that.cron[6].split("-")[1]; + } + + elem.push( + '
    ", + '
    ", + '
    ", + '
    ', + '
    -
    ', + '
    ' + ); + + elem.push("
    "); + + return elem.join(""); + }; + + function isNotBlank(str) { + return str != undefined && str !== ""; + } + + // 底部按钮事件 + Class.prototype.tool = function (btn, type) { + var that = this, + options = that.config, + active = { + // 计算秒 + calSeconds: function () { + var data = form.val("cronSecForm"), + dataType = data["type[0]"]; + if ( + "range" == dataType && + isNotBlank(data.rangeStart) && + isNotBlank(data.rangeEnd) + ) { + that.cron[0] = data.rangeStart + "-" + data.rangeEnd; + } else if ( + "per" == dataType && + isNotBlank(data.perFrom) && + isNotBlank(data.perVal) + ) { + that.cron[0] = data.perFrom + "/" + data.perVal; + } else if ("assign" == dataType) { + var checkbox = []; + layui.each(data, function (key, value) { + if (/^seconds/.test(key)) { + checkbox.push(value); + } + }); + if (checkbox.length) { + that.cron[0] = checkbox.join(","); + } else { + that.cron[0] = "*"; + } + } else if ("all" == dataType) { + that.cron[0] = "*"; + } + }, + calMinutes: function () { + var data = form.val("cronMinForm"), + dataType = data["type[1]"]; + if ( + "range" == dataType && + isNotBlank(data.rangeStart) && + isNotBlank(data.rangeEnd) + ) { + that.cron[1] = data.rangeStart + "-" + data.rangeEnd; + } else if ( + "per" == dataType && + isNotBlank(data.perFrom) && + isNotBlank(data.perVal) + ) { + that.cron[1] = data.perFrom + "/" + data.perVal; + } else if ("assign" == dataType) { + var checkbox = []; + layui.each(data, function (key, value) { + if (/^minutes/.test(key)) { + checkbox.push(value); + } + }); + if (checkbox.length) { + that.cron[1] = checkbox.join(","); + } else { + that.cron[1] = "*"; + } + } else if ("all" == dataType) { + that.cron[1] = "*"; + } + }, + calHours: function () { + var data = form.val("cronHourForm"), + dataType = data["type[2]"]; + if ( + "range" == dataType && + isNotBlank(data.rangeStart) && + isNotBlank(data.rangeEnd) + ) { + that.cron[2] = data.rangeStart + "-" + data.rangeEnd; + } else if ( + "per" == dataType && + isNotBlank(data.perFrom) && + isNotBlank(data.perVal) + ) { + that.cron[2] = data.perFrom + "/" + data.perVal; + } else if ("assign" == dataType) { + var checkbox = []; + layui.each(data, function (key, value) { + if (/^hours/.test(key)) { + checkbox.push(value); + } + }); + if (checkbox.length) { + that.cron[2] = checkbox.join(","); + } else { + that.cron[2] = "*"; + } + } else if ("all" == dataType) { + that.cron[2] = "*"; + } + }, + calDays: function () { + var data = form.val("cronDayForm"), + dataType = data["type[3]"]; + + if ( + "range" == dataType && + isNotBlank(data.rangeStart) && + isNotBlank(data.rangeEnd) + ) { + that.cron[3] = data.rangeStart + "-" + data.rangeEnd; + } else if ( + "per" == dataType && + isNotBlank(data.perFrom) && + isNotBlank(data.perVal) + ) { + that.cron[3] = data.perFrom + "/" + data.perVal; + } else if ("work" == dataType && isNotBlank(data.workDay)) { + that.cron[3] = data.workDay + "W"; + } else if ("last" == dataType) { + that.cron[3] = "L"; + } else if ("assign" == dataType) { + var checkbox = []; + layui.each(data, function (key, value) { + if (/^days/.test(key)) { + checkbox.push(value); + } + }); + if (checkbox.length) { + that.cron[3] = checkbox.join(","); + } else { + that.cron[3] = "*"; + } + } else if ("all" == dataType) { + that.cron[3] = "*"; + } else if ("none" == dataType) { + that.cron[3] = "?"; + } + }, + calMonths: function () { + var data = form.val("cronMonthForm"), + dataType = data["type[4]"]; + if ( + "range" == dataType && + isNotBlank(data.rangeStart) && + isNotBlank(data.rangeEnd) + ) { + that.cron[4] = data.rangeStart + "-" + data.rangeEnd; + } else if ( + "per" == dataType && + isNotBlank(data.perFrom) && + isNotBlank(data.perVal) + ) { + that.cron[4] = data.perFrom + "/" + data.perVal; + } else if ("assign" == dataType) { + var checkbox = []; + layui.each(data, function (key, value) { + if (/^months/.test(key)) { + checkbox.push(value); + } + }); + if (checkbox.length) { + that.cron[4] = checkbox.join(","); + } else { + that.cron[4] = "*"; + } + } else if ("all" == dataType) { + that.cron[4] = "*"; + } else if ("none" == dataType) { + that.cron[4] = "?"; + } + }, + calWeeks: function () { + var data = form.val("cronWeekForm"), + dataType = data["type[5]"]; + console.log(data); + if ( + "range" == dataType && + isNotBlank(data.rangeStart) && + isNotBlank(data.rangeEnd) + ) { + that.cron[5] = data.rangeStart + "-" + data.rangeEnd; + } else if ( + "per" == dataType && + isNotBlank(data.perFrom) && + isNotBlank(data.perVal) + ) { + that.cron[5] = data.perFrom + "#" + data.perVal; + } else if ("last" == dataType && isNotBlank(data.lastVal)) { + that.cron[5] = data.lastVal + "L"; + } else if ("assign" == dataType) { + var checkbox = []; + layui.each(data, function (key, value) { + if (/^weeks/.test(key)) { + checkbox.push(value); + } + }); + if (checkbox.length) { + that.cron[5] = checkbox.join(","); + } else { + that.cron[5] = "*"; + } + } else if ("all" == dataType) { + that.cron[5] = "*"; + } else if ("none" == dataType) { + that.cron[5] = "?"; + } + }, + calYears: function () { + var data = form.val("cronYearForm"), + dataType = data["type[6]"]; + if ( + "range" == dataType && + isNotBlank(data.rangeStart) && + isNotBlank(data.rangeEnd) + ) { + that.cron[6] = data.rangeStart + "-" + data.rangeEnd; + } else if ("all" == dataType) { + that.cron[6] = "*"; + } else if ("none" == dataType) { + that.cron[6] = ""; + } + }, + + // 计算表达式 + calculate: function () { + active.calSeconds(); + active.calMinutes(); + active.calHours(); + active.calDays(); + active.calMonths(); + active.calWeeks(); + active.calYears(); + if (that.cron[5] != "?" && that.cron[3] != "?") { + layer.msg("不支持周参数和日参数同时存在"); + return false; + } + return true; + }, + // 运行 + run: function () { + if (!active.calculate()) { + return; + } + var cronStr = that.cron.join(" ").trim(); + // TODO 请求接口获取最近运行时间,或js生成最近运行时间 + if (options.url) { + $.post( + options.url, + { cron: cronStr }, + function (res) { + if (res.code == 200) { + $("#run-list").empty().append(res.data.join("
    ")); + } else { + layer.alert(res.msg, { icon: 2, title: "错误" }); + } + }, + "json" + ); + } + options.done(cronStr); + }, + + //确定 + confirm: function () { + if (!active.calculate()) { + return; + } + var cronStr = that.cron.join(" ").trim(); + options.done && options.done(cronStr); + that.remove(); + }, + }; + active[type] && active[type](); + }; + + // 定位算法 + Class.prototype.position = function () { + var that = this, + options = that.config, + elem = options.elem, + rect = elem.getBoundingClientRect(), //绑定元素的坐标 + cronWidth = that.elemCron.offsetWidth, //控件的宽度 + cronHeight = that.elemCron.offsetHeight, //控件的高度 + //滚动条高度 + scrollArea = function (type) { + type = type ? "scrollLeft" : "scrollTop"; + return document.body[type] | document.documentElement[type]; + }, + winArea = function (type) { + return document.documentElement[type ? "clientWidth" : "clientHeight"]; + }, + margin = 5, + left = rect.left, + top = rect.bottom; + + //如果右侧超出边界 + if (left + cronWidth + margin > winArea("width")) { + left = winArea("width") - cronWidth - margin; + } + + //如果底部超出边界 + if (top + cronHeight + margin > winArea()) { + top = + rect.top > cronHeight //顶部是否有足够区域显示完全 + ? rect.top - cronHeight + : winArea() - cronHeight; + top = top - margin * 2; + } + + that.elemCron.style.left = + left + (options.position === "fixed" ? 0 : scrollArea(1)) + "px"; + that.elemCron.style.top = + top + (options.position === "fixed" ? 0 : scrollArea()) + "px"; + }; + + // 控件移除 + Class.prototype.remove = function () { + var that = this, + options = that.config; + $(ELEM).remove(); + }; + + // 是否输入框 + Class.prototype.isInput = function (elem) { + return /input|textarea/.test(elem.tagName.toLocaleLowerCase()); + }; + + /** + * 核心入口 + * @param options + * @returns {{reload: reload, config: *}} + */ + cron.render = function (options) { + var ins = new Class(options); + return thisIns.call(ins); + }; + + exports("cron", cron); +}); diff --git a/WaterCloud.Web/wwwroot/js/lay-module/dtree/dtree.css b/WaterCloud.Web/wwwroot/js/lay-module/dtree/dtree.css new file mode 100644 index 0000000..6caec28 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/dtree/dtree.css @@ -0,0 +1,113 @@ + +/**************** 主题换肤 ****************/ +/* 默认风格*/ +.dtree-theme-item-this{background-color: #d2d2d2!important;} +.dtree-theme-item:hover{background-color: #eaeceb!important;} +.dtree-theme-item cite{font-size:12px!important;} +.dtree-theme-item:hover cite{color:#fe7786!important;} + +.dtree-theme-dtreefont{font-size: 16px!important;} +.dtree-theme-ficon{color:#000!important;} +.dtree-theme-icon{color:orange!important;} +.dtree-theme-checkbox:hover{color:#fe7786!important;} +.dtree-theme-choose{color:#fe7786!important;} + +/* layui主题风格*/ +.dtree-layui-item-this{background: none!important;} +.dtree-layui-item:hover{background: none!important;} +.dtree-layui-item cite{font-size:14px!important;} +.dtree-layui-item:hover cite{opacity:0.5;filter:Alpha(opacity=50);text-decoration: underline;} + +.dtree-layui-dtreefont{font-size: 18px!important;} +.dtree-layui-ficon{font-size: 18px!important;color:#393D49!important;} +.dtree-layui-icon{color:#666!important;} +.dtree-layui-checkbox:hover{color:#5FB878!important;} +.dtree-layui-choose{color:#5FB878!important;} + +/* laySimple主题风格*/ +.dtree-laySimple-item-this{background-color: #d2d2d2!important;} +.dtree-laySimple-item:hover{background-color: #eaeceb!important;} +.dtree-laySimple-item cite{font-size:12px!important;} +.dtree-laySimple-item:hover cite{color:#01AAED!important;} + +.dtree-laySimple-dtreefont{font-size: 16px!important;} +.dtree-laySimple-ficon{font-size: 14px!important;color:#393D49!important;} +.dtree-laySimple-icon{color:#393D49!important;} +.dtree-laySimple-checkbox:hover{color:#01AAED!important;} +.dtree-laySimple-choose{color:#01AAED!important;} +/**************** 树基础 ****************/ +/* 菜单栏*/ +.dtree-menubar {padding-left: 10px;} +.dtree-menubar .layui-btn-group .layui-btn-sm{height: 20px;line-height: 20px;padding: 0 5px;font-size: 12px;} +.dtree-menubar .layui-btn-group .layui-btn-sm i{font-size: 12px!important;} + +/* 工具栏*/ +.dtree-toolbar{position: absolute;z-index: 940520;padding: 0;background-color: #eceaeb;} +.dtree-toolbar .layui-nav-child{position: static;} +.dtree-toolbar .layui-nav-child dd{cursor: pointer;} +.dtree-toolbar .layui-nav-child dd a i{font-size:16px;display: inline-block;margin: 0px 1px;color:#fe7786;} +.dtree-toolbar .layui-nav-child dd a i:hover{font-weight: bold;} +.dtree-toolbar .layui-nav-bar{display: none!important;} +.dtree-toolbar-tool{padding: 30px;} + +.dtree-toolbar-fixed{position: absolute;right: 5px;top: 2px;font-style: normal;transition: all .3s;-webkit-transition: all .3s;} +/*.dtree-toolbar-fixed a{border:1px solid #fe7786;}*/ +.dtree-toolbar-fixed a i{font-size:14px;display: inline-block;margin: 0px 1px;color:#fe7786;} +.dtree-toolbar-fixed a i:hover{opacity:0.8;filter:Alpha(opacity=80);} + +/* 树基本*/ +.dtree{width:260px;} +.dtree-nav-item{line-height:33px;padding-left:16px;} +.dtree-nav-ul-sid{display: none;} +.dtree-none-text{font-size: 12px;text-align: center;color: gray;} + +/* 树线*/ +.dtree-nav-first-line,.dtree-nav-line,.dtree-nav-last-line{position: relative;} +.dtree-nav-first-line:before{content:"";position: absolute;height: 0;border-left: 1px dotted #c0c4cc;} +.dtree-nav-first-line:after{content:"";position: absolute;height: 0;border-top: 1px dotted #c0c4cc;} + +.dtree-nav-line:before{content:"";position: absolute;top: 0;left: 7px;width: 0;height: 100%;border-left: 1px dotted #c0c4cc;} +.dtree-nav-line:after{content:"";position: absolute;top: 16px;left: 8px;width: 9px;height: 0;border-top: 1px dotted #c0c4cc;} + +.dtree-nav-last-line:before{content:"";position: absolute;top: 0;left: 7px;width: 0;height: 17px;border-left: 1px dotted #c0c4cc;} +.dtree-nav-last-line:after{content:"";position: absolute;top: 16px;left: 8px;width: 9px;height: 0;border-top: 1px dotted #c0c4cc;} + + +/* 图标及复选框*/ +.dtreefont{cursor: pointer;} +.dtreefont-special{margin: 0 4px;} +.dtree-nav-checkbox-div{display: inline-block;} +.dtree-nav-checkbox-div>i{display: inline-block;margin: 0px 1px;} +.dtree-nav-checkbox-div>i:last-child{margin-right: 4px;} +.dtree-nav-checkbox-div>i:hover{opacity:0.8;filter:Alpha(opacity=80);} + +/* 行 文字*/ +.dtree-nav-div{display:block;vertical-align:top;position:relative;} +.dtree-nav-div cite{font-style: normal;cursor: pointer;} +.dtree-nav-div:hover cite{opacity:0.7;filter:Alpha(opacity=70);transition: all .3s;-webkit-transition: all .3s;} + +/* 规则属性*/ +.dtree-nav-show {display: block!important;} +.dtree-nav-hide {display: none!important;} +.dtree-nav-this {} +.dtree-icon-hide {opacity:0;filter:Alpha(opacity=0);} +.dtree-icon-null-open,.dtree-icon-null-close,.dtree-icon-null{margin: 0 2px;} +.dtree-disabled{cursor: not-allowed; color:#c2c2c2!important;} +.dtree-disabled:hover{color:#c2c2c2!important;} +.dtree-nav-div cite.dtree-disabled{font-style: normal; cursor: not-allowed; color:#c2c2c2!important;} +.dtree-nav-div>cite.dtree-disabled:hover{color:#c2c2c2!important;} + + +/** 下拉树属性*/ +.dtree-select{position: absolute;max-height: 500px;height: 350px;overflow: auto;width: 99%;z-index: 123;display: none;border:1px solid silver;top: 42px;} +.dtree-select-show{display: block!important;} +.dtree-select-up{top: auto; bottom: 42px;} + +/* 简单适配*/ +@media screen and (max-width:1700px) and (min-width:1300px){ + .dtree-nav-item {padding-left: 15px;} +} + + + + diff --git a/WaterCloud.Web/wwwroot/js/lay-module/dtree/dtree.js b/WaterCloud.Web/wwwroot/js/lay-module/dtree/dtree.js new file mode 100644 index 0000000..bda8762 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/dtree/dtree.js @@ -0,0 +1,5543 @@ +/** + *@Name dtree 树形组件 + *@Author 智慧的小西瓜 + *@DOCS http://www.wisdomelon.com/DTreeHelper/ + *@License https://www.layui.com/ + *@LASTTIME 2020/03/31 + *@VERSION v2.5.8 + */ +layui.define(['jquery','layer','form'], function(exports) { + var $ = layui.$, + layer = layui.layer, + form = layui.form; + + // 树的公共定义样式汇总 + var LI_NAV_CHILD = "dtree-nav-ul-sid", LI_NAV_ITEM = "dtree-nav-item", + LI_DIV_ITEM = "dtree-nav-div", DTREEFONTSPECIAL="dtreefont-special", NONETITLE="dtree-none-text", + LI_DIV_MENUBAR = "dtree-menubar", + LI_DIV_TOOLBAR = "dtree-toolbar", TOOLBAR_TOOL = "dtree-toolbar-tool", TOOLBAR_TOOL_EM = "dtree-toolbar-fixed", + LI_DIV_CHECKBAR = "dtree-nav-checkbox-div", + LI_CLICK_CHECKBAR = "d-click-checkbar", //绑定点击复选框时需要用到 + LI_DIV_TEXT_CLASS = "t-click", UL_ROOT="dtree", + LI_NAV_FIRST_LINE = "dtree-nav-first-line", LI_NAV_LINE = "dtree-nav-line", LI_NAV_LAST_LINE = "dtree-nav-last-line"; + + + // 树的公共指定 + var NAV_THIS = "dtree-nav-this", //当前节点 + NAV_SHOW = "dtree-nav-show", //显示子节点 + NAV_HIDE = "dtree-nav-hide", //隐藏节点 + NAV_DIS = "dtree-disabled", //禁用节点 + ICON_HIDE = "dtree-icon-hide", //隐藏图标 + $BODY = $("body"), //body选择器 + $WIN = $(window), //window窗口 + $DOC = $(document), //当前文档 + MOD_NAME = "dtree", //模块名称 + VERSION = "v2.5.8", //版本 + OPTIONS = {}, //全局属性配置 + DTrees = {}; //当前被实例化的树的集合 + + // 树的自定义图标 + var DTREEFONT = "dtreefont", //默认使用图标字体 + LI_DIV_CHECKBAR_ON = "dtree-icon-fuxuankuangxuanzhong", //复选框选中图标 + LI_DIV_CHECKBAR_OUT = "dtree-icon-fuxuankuang", //复选框未选中图标 + LI_DIV_CHECKBAR_NOALL = "dtree-icon-fuxuankuang-banxuan", //复选框半选图标 + LI_DIV_MENUBAR_DOWN = "dtree-icon-move-down", //menubar的展开全部的图标 + LI_DIV_MENUBAR_UP = "dtree-icon-move-up", //menubar的收缩全部的图标 + LI_DIV_MENUBAR_REFRESH = "dtree-icon-refresh", //menubar的刷新图标 + LI_DIV_MENUBAR_CHECKALL = "dtree-icon-roundcheckfill", //menubar的全选图标 + LI_DIV_MENUBAR_UNCHECKALL = "dtree-icon-roundclosefill", //menubar的全不选图标 + LI_DIV_MENUBAR_INVERTALL = "dtree-icon-roundcheck", //menubar的反选图标 + LI_DIV_MENUBAR_DELETE = "dtree-icon-delete1", //menubar的删除图标 + LI_DIV_MENUBAR_SEARCH = "dtree-icon-search_list_light", //menubar的搜索图标 + LI_DIV_TOOLBAR_PULLDOWN = "dtree-icon-pulldown", //toolbar的展开图标 + LI_DIV_TOOLBAR_PULLUP = "dtree-icon-pullup", //toolbar的收缩图标 + LI_DIV_TOOLBAR_ADD = "dtree-icon-roundadd", //toolbar的新增图标 + LI_DIV_TOOLBAR_EDIT = "dtree-icon-bianji", //toolbar的编辑图标 + LI_DIV_TOOLBAR_DEL = "dtree-icon-roundclose"; //toolbar的删除图标 + + // 树的非叶子节点图标集合 + var nodeIconArray = { + "-1": {"open": "dtree-icon-null-open", "close": "dtree-icon-null-close"}, //未指定 + "0" : {"open": "dtree-icon-wenjianjiazhankai", "close": "dtree-icon-weibiaoti5"}, //文件夹(二级图标默认样式) + "1" : {"open": "dtree-icon-jian", "close": "dtree-icon-jia"}, //+-图标(一级图标默认样式) + "2" : {"open": "dtree-icon-xiangxia1", "close": "dtree-icon-xiangyou"} //箭头图标 + }; + + // 树的叶子节点图标集合 + var leafIconArray = { + "-1": "dtree-icon-null", //未指定 + "0" : "dtree-icon-weibiaoti5", //文件夹 + "1" : "dtree-icon-yonghu", //人员 + "2" : "dtree-icon-fenzhijigou", //机构 + "3" : "dtree-icon-fenguangbaobiao", //报表 + "4" : "dtree-icon-xinxipilu", //信息 + "5" : "dtree-icon-shuye1", //叶子(二级图标默认样式) + "6" : "dtree-icon-caidan_xunzhang", //勋章 + "7" : "dtree-icon-normal-file", //文件 + "8" : "dtree-icon-dian", //小圆点(一级图标默认样式) + "9" : "dtree-icon-set-sm", //齿轮 + "10" : "dtree-icon-rate" //星星 + }; + + // 树的自定义样式 + var DTREE = "dtree-", //自定义样式前缀 + ITEMTHIS = "-item-this", //自定义样式当前行选中后缀 + ITEM = "-item", //自定义样式当前行后缀 + DFONT = "-dtreefont", //自定义样式图标样式后缀 + FICON = "-ficon", //自定义样式一级图标样式后缀 + ICON = "-icon", //自定义样式二级图标样式后缀 + CBOX = "-checkbox", //自定义样式复选框样式后缀 + CHS = "-choose"; //自定义样式复选框选中样式后缀 + + // 树自定义操作事件名称集合 绑定dtree-click的事件 + var eventName = { + checkNodeClick: "checkNodeClick", //点击复选框 + itemNodeClick: "itemNodeClick" //点击子节点div + }; + + // 树默认toolbar提供的功能集合 绑定dtree-tool的事件 + var defaultTool = { + pulldown: "pulldown", //点击展开当前节点下的全部节点 + pullup: "pullup", //点击收缩当前节点下的全部节点 + addTool: "addToolbar", //点击toolbar新增 + editTool: "editToolbar", //点击toolbar编辑 + delTool: "delToolbar" //点击toolbar删除 + }; + + // 树默认menubar提供的功能集合 绑定dtree-menu的事件 + var defaultMenu = { + moveDown: "moveDown", //menubar展开全部节点 + moveUp: "moveUp", //menubar收缩全部节点 + refresh: "refresh", //menubar刷新树 + checkAll: "checkAll", //menubar全选 + unCheckAll: "unCheckAll", //menubar全不选 + invertAll: "invertAll", //menubar反选 + remove: "remove", //menubar删除选中节点 + searchNode: "searchNode" //menubar查询节点 + }; + + // 树的公共事件 + var event = { + getElemId: function(options){ // 根据传入的参数获取ID + var elem = options.elem || ""; + var obj = options.obj || $(elem); + + if (obj.length == 0) { //页面中未找到绑定id + return ""; + } else { + return $(obj)[0].id; + } + }, + escape: function(html){ // 编码 + if(typeof html !== 'string') return ''; + return html.replace(entityReg.escape, function(match){return entityMap.escape[match];}); + }, + unescape: function(str){ // 解码 + if(typeof str !== 'string') return ''; + return str.replace(entityReg.unescape, function(match){return entityMap.unescape[match];}); + }, + cloneObj: function (obj, filter) { //深复制对象方法 + var newObj = {}; + if (obj instanceof Array) { + newObj = []; + } + var str = ""; + if(typeof filter !== 'undefined') {str = filter.join(",");} + for (var key in obj) { + if(str.indexOf(key) == -1){ + var val = obj[key]; + newObj[key] = typeof val === 'object' ? event.cloneObj(val, typeof filter !== undefined ? filter : []): val; + } + + } + return newObj; + }, + trimToDot: function(str){ + return str.replace(/ /g, "."); + } + }; + + // 特殊符号转义 + var keys = Object.keys || function(obj) { + obj = Object(obj); + var arr = []; + for(var a in obj) arr.push(a); + return arr; + }; + var invert = function(obj){ + obj = Object(obj); + var result = {}; + for(var a in obj) result[obj[a]] = a; + return result; + }; + var entityMap = { + escape: { + "&" : "&", + "<" : "<", + ">" : ">", + "'" : "&quo;" + } + }; + entityMap.unescape = invert(entityMap.escape); + var entityReg = { + escape: RegExp('[' + keys(entityMap.escape).join('') + ']', 'g'), + unescape: RegExp('(' + keys(entityMap.unescape).join('|') + ')', 'g') + }; + + //异步加载接口 + var AjaxHelper = { + request : function(config) { + var data = config.data ? config.data : {}; + var async = (typeof (config.async) === "boolean") ? config.async : true; + $.ajax({ + type : config.type ? config.type : "POST", + headers : config.headers, + url : config.url, + dataType : config.dataType ? config.dataType : "json", + data : data, + async : async, + contentType : config.contentType, + xhrFields: {withCredentials: config.withCredentials}, + beforeSend: function (XMLHttpRequest, self) { + if (typeof (config.beforeSend) === "function") { + return config.beforeSend(XMLHttpRequest, self); + } + return true; + }, + success : config.success, + error : function(XMLHttpRequest, textStatus, errorThrown) { + if (typeof (config.error) === "function") { + config.error(XMLHttpRequest, textStatus, errorThrown); + } else { + layer.msg("异步加载失败: " + textStatus,{icon:5, shift:6}); + } + }, + statusCode : { + 404 : function() { + layer.msg('未找到指定请求,请检查访问路径!',{icon:5, shift:6}); + }, + 500 : function() { + layer.msg('系统错误!',{icon:5, shift:6}); + } + }, + complete : function(XMLHttpRequest, textStatus) { + if (typeof (config.complete) === "function") { + config.complete(XMLHttpRequest, textStatus); + } + } + }); + }, + serialize: function(first, param){ //json序列化 key=value&key1=value1 + var p = first; + for (var key in param) { + p += key + "=" + param[key] + "&"; + } + p = p.substring(0, p.length-1); + return p; + } + }; + + /** 树类 Class定义 */ + var DTree = function(options){ + var _this = this; + /** 默认赋值**/ + this.formatter = { // 数据过滤 + title: false // 文字,默认不开启 + }; + this.response = { // 树返回的json格式 + statusName: "code", //返回标识 + statusCode: 200, //返回码 + message: "message", //返回信息 + rootName: "data", //根节点名称 + treeId: "id", //节点ID + parentId: "parentId", //父节点ID + title: "title", //节点名称 + ficonClass: "ficonClass", //自定义一级图标 + iconClass: "iconClass", //自定义二级图标 + childName: "children", //子节点名称 + last: "last", //是否最后一级节点 +// level: "level", //层级 + spread: "spread", //展开 + disabled: "disabled", //禁用 + hide: "hide", //隐藏 + checkArr: "checkArr", //复选框列表 + checked: "checked", //是否选中 + type: "type", //复选框标记 + basicData: "basicData" //表示用户自定义需要存储在树节点中的数据 + }; + this.defaultRequest = { // 树的默认发起请求参数格式,最后会将value作为参数名称传递 + nodeId: "nodeId", //节点ID + parentId: "parentId", //父节点ID + context: "context", //节点内容 + leaf: "leaf", //是否叶子节点 + level: "level", //层级 + spread: "spread", //节点展开状态 + dataType: "dataType", //节点标记 + checked: "checked", //节点复选框选中状态 + initchecked: "initchecked", //节点复选框初始状态 + basicData: "basicData", //用户自定义的记录节点数据 + recordData: "recordData", //当前data数据(排除basicData和children字段) + }; + this.toolbarFun = { + addTreeNode: function(param, $div) { //添加树节点后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + editTreeNode: function(param, $div) { //编辑树节点后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + editTreeLoad: function(param){ // 编辑树的数据回显,用于打开编辑时,回填数据 + return ; + }, + delTreeNode: function(param, $div){ //删除树后调用的函数,用于用户自定义,如未指定则树不会发生变化 + return ; + }, + loadToolbarBefore: function(buttons, param, $div){ // 右键菜单加载前的函数 + return buttons; + } + }; + this.toolbarStyle = { // 工具栏弹出层的自定义样式 + title: "节点", + area: ["60%","80%"] + }; + this.menubarFun = { + remove: function(checkbarNodes){ //删除复选框选中节点,需要用户自定义,如未指定则树只是页面上做了修改 + return true; + } + }; + this.menubarTips = { // 菜单栏的默认显示 + toolbar: [], + group: [defaultMenu.moveDown, defaultMenu.moveUp, defaultMenu.refresh, defaultMenu.checkAll, defaultMenu.unCheckAll, defaultMenu.invertAll, defaultMenu.remove, defaultMenu.searchNode], + freedom: [] + }; + this.checkbarFun = { + chooseBefore: function($i, node){ // 复选框点击前回调 + return true; + }, + chooseDone: function(checkbarNodesParam) { //复选框点击事件完毕后,返回该树关于复选框操作的全部信息,用于用户自定义,如未指定则树只是页面上做了修改 + return ; + } + }; + this.iframeDefaultRequest = { //iframe的默认参数,目的是与加载树的参数不一样 + nodeId: "nodeId", //节点ID + parentId: "parentId", //父节点ID + context: "context", //节点内容 + leaf: "leaf", //是否叶子节点 + level: "level", //层级 + spread: "spread", //节点展开状态 + dataType: "dataType", //节点标记 + checked: "checked", //节点复选框选中状态 + initchecked: "initchecked", //节点复选框初始状态 + basicData: "basicData", //用户自定义的记录节点数据 + recordData: "recordData", //当前data数据(排除basicData和children字段) + }; + + this.iframeFun = { + iframeDone: function(iframeParam){ //iframe加载完毕后,用于用户自定义事件 + return ; + } + }; + this.style = { //树最终使用的样式集合 + item: "", //每一项div的样式 + itemThis: "", //选中div的样式 + dfont: "", //一级图标的样式 + icon: "", //二级图标的样式 + cbox: "", //复选框的样式 + chs: "" //复选框选中的样式 + }; + this.usefontStyle = { //树最终使用的图标集合 + fnode:{ //一级节点 + node:{ //非叶子节点 + open:"", //节点展开 + close:"" //节点关闭 + }, + leaf:"" //叶子节点 + }, + snode:{ //二级节点 + node:{ //非叶子节点 + open:"", //节点展开 + close:"" //节点关闭 + }, + leaf:"" //叶子节点 + }, + checkbox:{ //复选框 + on:"", //复选框选中 + out:"", //未选中 + noall:"" //半选 + }, + menubar:{ //菜单栏 + movedown:"", //全部展开 + moveup:"", //全部收缩 + refresh:"", //刷新 + checkAll:"", //全选 + unCheckAll:"", //全不选 + invertAll:"", //反选 + remove:"", //删除 + search:"" //搜索 + }, + menubarExt:"", //扩展菜单栏 + toolbar:{ //工具栏 + menubar:{ //依附在菜单栏的工具栏 + movedown:"", //全部展开 + moveup:"", //全部收缩 + refresh:"", //刷新 + checkAll:"", //全选 + unCheckAll:"", //全不选 + invertAll:"", //反选 + remove:"", //删除 + search:"" //搜索 + }, + menubarExt:"", //依附在菜单栏的扩展菜单栏 + pulldown:"", //展开 + pullup:"", //收缩 + add:"", //添加 + edit:"", //编辑 + del:"" //删除 + }, + toolbarExt:"" //扩展工具栏 + } + + /** 数据绑定**/ + this.node = { // 树节点选中时,包含当前节点的全部信息 + nodeId: "", //节点ID + parentId: "", //父节点ID + context: "", //节点内容 + leaf: "", //是否叶子节点 + level: "", //层级 + spread: "", //节点展开状态 + dataType: "", //节点标记 + checked: "", //节点复选框选中状态 + initchecked: "", //节点复选框初始状态 + basicData: "", //用户自定义的记录节点数据 + recordData: "", //当前data数据(排除basicData和children字段) + }; + + this.toolbarMenu = {}; // 工具栏右键菜单绑定的所有元素 + this.checkbarNode = []; // 复选框标记的全部节点数据 + this.errData = []; // 记录在渲染节点时有问题的数据 + this.checkArrLen = 0; // 添加节点的时判断复选框个数 + this.temp = []; // 临时变量 + this.bak = ""; // 临时变量 + this.setting(options); + }; + + /******************** 初始参数加载 ********************/ + /** + * @Desc: 设置基本属性值 + * @Param: options:JSON对象,初始设置dtree所需的全部属性 + */ + DTree.prototype.setting = function(options) { + this.options = options || {}; + + /** 绑定元素参数(必填,2个参数项必填一个)**/ + this.elem = this.options.elem || OPTIONS.elem || ""; //树绑定的元素ID:#elem + if(typeof this.options.obj === 'undefined'){ + if(this.elem) { + if($(this.elem).length > 0) { + this.obj = $(this.elem); + } + } + } else { + this.obj = this.options.obj || OPTIONS.obj || this.obj; //树绑定的jquery元素,用于当元素是延迟加载出来的话,可以用这个找到 + this.elem = "#" + this.obj[0].id; + } + + /** 基本参数**/ + this.scroll = this.options.scroll || OPTIONS.scroll || this.elem; //树的上级div容器,让树可以显示滚动条的div容器的ID + this.accordion = (typeof (this.options.accordion) === "boolean") ? this.options.accordion : (typeof (OPTIONS.accordion) === "boolean") ? OPTIONS.accordion : false; //手风琴加载, 默认false + if(this.accordion) { + this.initLevel = 1; //默认展开节点 1节 + } else { + this.initLevel = this.options.initLevel || OPTIONS.initLevel || 2; //默认展开节点 2节 + } + this.type = this.options.type || OPTIONS.type || "load"; //树的加载方式 all,全量树, load,增量树,默认load + this.cache = (typeof (this.options.cache) === "boolean") ? this.options.cache : (typeof (OPTIONS.cache) === "boolean") ? OPTIONS.cache : true; //数据缓存,默认true + this.record = this.options.record || OPTIONS.record || false; //开启数据记录模式,默认false + this.load = (typeof (this.options.load) === "boolean") ? this.options.load : (typeof (OPTIONS.load) === "boolean") ? OPTIONS.load : true; //开启加载动画,默认true + this.none = this.options.none || OPTIONS.nont || "无数据"; //初始加载无记录时显示文字 + this.tempHeight = this.options.height || OPTIONS.height; //临时转换高度变量 + if(this.tempHeight) { // 设置高度 + if(/^full-\d+$/.test(this.tempHeight)) { + this.fullHeightGap = this.tempHeight.split('-')[1]; + this.height = $WIN.height() - this.fullHeightGap; //设置高度 + } else { + this.fullHeightGap = this.tempHeight; + this.height = this.tempHeight; + } + } else { + this.fullHeightGap = ""; + this.height = ""; + } + this.width = this.options.width || OPTIONS.width || "260"; //宽度 + this.obj.css("width", this.width); + + /** 样式相关参数**/ + this.iconfont = this.options.iconfont || OPTIONS.iconfont || DTREEFONT; //默认图标字体 dtreefont + this.iconfontStyle = this.options.iconfontStyle || OPTIONS.iconfontStyle || {}; //用于自定义树的每个关键部位使用的图标 + this.nodeIconArray = $.extend(nodeIconArray, this.options.nodeIconArray || OPTIONS.nodeIconArray) || nodeIconArray; //用户自定义非叶子节点图标集合,node + this.leafIconArray = $.extend(leafIconArray, this.options.leafIconArray || OPTIONS.leafIconArray) || leafIconArray; //用户自定义叶子节点图标集合,leaf + this.skin = this.options.skin || OPTIONS.skin || "theme"; // 自定义样式 + if(this.skin == "layui"){ // layui主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : (typeof (OPTIONS.line) === "boolean") ? OPTIONS.line : true; //开启树线,默认开启 + this.ficon = this.options.ficon || OPTIONS.ficon || "7"; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'7' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; //一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "-1"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else if(this.skin == "laySimple"){ // laySimple主题 + this.line = this.options.line || OPTIONS.line || false; //开启树线,默认不开启 + this.ficon = this.options.ficon || OPTIONS.ficon || ["2","-1"]; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'-1' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "2") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'2' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "-1"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else { // 默认主题 或者自定义主题 + this.line = this.options.line || OPTIONS.line || false; //开启树线,默认不开启 + this.ficon = this.options.ficon || OPTIONS.ficon || "8"; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'8' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示一级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || OPTIONS.icon || "5"; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'5' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "0") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'0' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } + + /** 数据加载参数**/ + this.url = this.options.url || OPTIONS.url || ""; //请求地址 + this.async = (typeof (this.options.async) === "boolean") ? this.options.async : (typeof (OPTIONS.async) === "boolean") ? OPTIONS.async : true; //异步同步加载,默认异步加载 + this.asyncLoad = this.options.asyncLoad || OPTIONS.asyncLoad || []; //初始异步加载层级数据 + this.headers = this.options.headers || OPTIONS.headers || {}; //ajax header属性 + this.method = this.options.method || OPTIONS.method || "post"; //请求类型 + this.dataType = this.options.dataType || OPTIONS.dataType || "json"; //参数类型 + this.contentType = this.options.contentType || OPTIONS.contentType || "application/x-www-form-urlencoded"; //发送信息至服务器时内容编码类型 + this.defaultRequest = $.extend(this.defaultRequest, this.options.defaultRequest || OPTIONS.defaultRequest) || this.defaultRequest; //默认请求参数 + this.filterRequest = this.options.filterRequest || OPTIONS.filterRequest || []; //过滤请求参数 + this.request = this.options.request || OPTIONS.request || {}; //用户自定义请求参数 + this.response = $.extend(this.response, this.options.response || OPTIONS.response) || this.response; //返回json格式 + this.data = this.options.data || OPTIONS.data || null; //初始化指定该参数,则不会访问异步接口 + this.dataFormat = this.options.dataFormat || OPTIONS.dataFormat || "levelRelationship"; //用于用户配置的data数据格式,list:列表, levelRelationship:层级关系,默认 + this.dataStyle = this.options.dataStyle || OPTIONS.dataStyle || "defaultStyle"; //用于用户配置layui通用的json数据风格,layuiStyle:layui风格,defaultStyle:默认风格 + this.errDataShow = this.options.errDataShow || OPTIONS.errDataShow || false; //是否在递归数据出现错误后,显示错误信息,默认false + this.withCredentials = this.options.withCredentials || OPTIONS.withCredentials || false; //是否允许跨域请求,默认false + this.beforeSend = this.options.beforeSend || OPTIONS.beforeSend || function(ajax, XMLHttpRequest, self){return true}; //异步加载之前的回调 + this.success = this.options.success || OPTIONS.success || function(data, obj, first){}; //树加载完毕后执行解析树之前的回调 + this.done = this.options.done || OPTIONS.done || function(data, obj, first){}; //树加载完毕后的回调 + this.formatter = $.extend(this.formatter, this.options.formatter || OPTIONS.formatter) || this.formatter; //数据过滤 + this.error = this.options.error || OPTIONS.error || function(XMLHttpRequest, textStatus, errorThrown){}; // 异步加载异常回调 + this.complete = this.options.complete || OPTIONS.complete || function(XMLHttpRequest, textStatus){}; // 异步加载完成回调 + + /** 复选框参数**/ + this.checkbar = this.options.checkbar || OPTIONS.checkbar || false; //是否开启复选框模式 + this.checkbarLoad = this.options.checkbarLoad || OPTIONS.checkbarLoad || "node"; //复选框作用范围,node:所有节点, leaf:最后一级;默认所有节点 + this.checkbarType = this.options.checkbarType || OPTIONS.checkbarType || "all"; //复选框选中形式 all:子集选中父级也选中, no-all:子集选中父级半选中,子集全选父级选中,p-casc:父级选中子集全选,子集无法改变父级选中状态, self:没有任何级联关系,only:只能选中一个复选框。 默认all + this.checkbarData = this.options.checkbarData || OPTIONS.checkbarData || "choose"; //复选框记录数据类型形式, change表示记录变更数据,choose表示记录选中数据,all记录全部数据,halfChoose记录选中和半选中的数据,默认choose + this.checkbarFun = $.extend(this.checkbarFun, this.options.checkbarFun || OPTIONS.checkbarFun) || this.checkbarFun; //checkbar事件加载 + + /** 菜单栏参数**/ + this.menubar = this.options.menubar || OPTIONS.menubar || false; //是否打开菜单栏 + this.menubarTips = $.extend(this.menubarTips, this.options.menubarTips || OPTIONS.menubarTips) || this.menubarTips; //菜单栏吸附, toolbar:依附在工具栏,group:依附在按钮组,freedom,自由 + this.menubarFun = $.extend(this.menubarFun, this.options.menubarFun || OPTIONS.menubarFun) || this.menubarFun; //menubar事件加载 + + /** 工具栏参数**/ + this.toolbar = this.options.toolbar || OPTIONS.toolbar || false; //是否开启可编辑模式 + this.toolbarWay = this.options.toolbarWay || OPTIONS.toolbarWay || "contextmenu"; //工具栏显示方式,contextmenu:右键,follow:跟随节点,fixed:固定在节点右侧 + this.toolbarStyle = $.extend(this.toolbarStyle, this.options.toolbarStyle || OPTIONS.toolbarStyle) || this.toolbarStyle; //toolbar的自定义风格,标题,弹框大小 + this.toolbarLoad = this.options.toolbarLoad || OPTIONS.toolbarLoad || "node"; //toolbar作用范围:node:所有节点,noleaf:非最后一级节点,leaf:最后一级 + this.toolbarShow = this.options.toolbarShow || OPTIONS.toolbarShow || ["add","edit","delete"]; //toolbar三个按钮自定义加载 + this.toolbarBtn = this.options.toolbarBtn || OPTIONS.toolbarBtn || null; //toolbar增删改中内容的自定义加载 + this.toolbarExt = this.options.toolbarExt || OPTIONS.toolbarExt || []; //toolbar按钮扩展 + this.toolbarFun = $.extend(this.toolbarFun, this.options.toolbarFun || OPTIONS.toolbarFun) || this.toolbarFun; //toolbar事件加载 + + /** iframe模式参数**/ + this.useIframe = this.options.useIframe || OPTIONS.useIframe || false; //是否加载iframe 默认false, + this.iframeElem = this.options.iframeElem || OPTIONS.iframeElem || ""; //iframe的ID + this.iframeUrl = this.options.iframeUrl || OPTIONS.iframeUrl || ""; //树关联的iframe地址 + this.iframeLoad = this.options.iframeLoad || OPTIONS.iframeLoad || "leaf"; //点击哪一层加载frame: node:所有节点, leaf:默认,最后一级 + this.iframeDefaultRequest = $.extend(this.iframeDefaultRequest, this.options.iframeDefaultRequest || OPTIONS.iframeDefaultRequest) || this.iframeDefaultRequest; //iframe的默认传递参数 + this.iframeRequest = $.extend(this.iframeRequest, this.options.iframeRequest) || $.extend(this.iframeRequest, OPTIONS.iframeRequest) || this.iframeRequest; //iframe的自定义参数 + this.iframeFun = $.extend(this.iframeFun, this.options.iframeFun) || $.extend(this.iframeFun, OPTIONS.iframeFun) || this.iframeFun; //iframe事件加载 + + /** 下拉树模式参数**/ + this.select = this.options.select || false; + if(this.select) { + // 重置下拉树 + this.selectSetting(); + } + + /** 调用确认最终主题方法*/ + this.ensureTheme(); + }; + + /** + * @Desc: 重置基本属性值 + * @Param: options:JSON对象,重置dtree所需的全部属性 + */ + DTree.prototype.reloadSetting = function(options) { + this.options = $.extend(this.options, options) || this.options; + + /** 绑定元素参数**/ + this.elem = this.options.elem || this.elem; //树绑定的元素ID:#elem + if(typeof this.options.obj === 'undefined'){ + if(this.elem) { + if($(this.elem).length > 0) { + this.obj = $(this.elem); + } + } + } else { + this.obj = this.options.obj || this.obj; //树绑定的jquery元素,用于当元素是延迟加载出来的话,可以用这个找到 + this.elem = "#" + this.obj[0].id; + } + + /** 基本参数**/ + this.scroll = this.options.scroll || this.scroll; //树的上级div容器,让树可以显示滚动条的div容器 + this.accordion = (typeof (this.options.accordion) === "boolean") ? this.options.accordion : this.accordion; //开启手风琴加载 + if(this.accordion) { + this.initLevel = 1; //默认展开节点 1节 + } else { + this.initLevel = this.options.initLevel || this.initLevel; //默认展开节点 2节 + } + this.type = this.options.type || this.type; //树的加载方式 all,全量树, load,增量树,默认load + this.cache = (typeof (this.options.cache) === "boolean") ? this.options.cache : this.cache; //开启数据缓存 + this.record = (typeof (this.options.record) === "boolean") ? this.options.record : this.record; //开启数据记录模式 + this.load = (typeof (this.options.load) === "boolean") ? this.options.load : this.load; //开启加载动画 + this.none = this.options.none || this.none; //初始节点加载无数据时显示文字 + this.tempHeight = this.options.height || this.height; //临时转换高度变量 + if(this.tempHeight) { //设置高度 + if(/^full-\d+$/.test(this.tempHeight)) { + this.fullHeightGap = this.tempHeight.split('-')[1]; + this.height = $WIN.height() - this.fullHeightGap; + } else { + this.fullHeightGap = this.tempHeight; + this.height = this.tempHeight; + } + } + this.width = this.options.width || this.width; //宽度 + this.obj.css("width", this.width); + + /** 样式相关参数**/ + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : this.line; //开启树线,默认不开启 + this.iconfont = this.options.iconfont || this.iconfont; //默认图标字体 dtreefont + this.iconfontStyle = this.options.iconfontStyle || this.iconfontStyle; //用于自定义树的每个关键部位使用的图标 + this.nodeIconArray = $.extend(nodeIconArray, this.options.nodeIconArray) || this.nodeIconArray; //用户自定义非叶子节点图标集合,node + this.leafIconArray = $.extend(leafIconArray, this.options.leafIconArray) || this.leafIconArray; //用户自定义叶子节点图标集合,leaf + this.skin = this.options.skin || this.skin; //自定义样式 + if(this.skin == "layui"){ //layui主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : true; //开启树线,默认开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'7' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; //一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else if(this.skin == "laySimple"){ //laySimple主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : false; //开启树线,默认不开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'-1' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "2") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'2' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1];//一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'-1' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "-1") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'-1' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } else { // 默认主题 或者自定义主题 + this.line = (typeof (this.options.line) === "boolean") ? this.options.line : false; //开启树线,默认不开启 + this.ficon = this.options.ficon || this.ficon; //一级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示一级图标。默认'8' + this.fnodeIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? (this.ficon == "-1" ? "-1" : "1") : this.ficon[0]; //一级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'1' + this.fleafIcon = (typeof this.ficon === 'string' || typeof this.ficon === 'number') ? this.ficon : this.ficon[1]; // 一级图标中的leaf节点图标 + this.icon = this.options.icon || this.icon; //二级图标样式,0:文件夹,1:人员,2:机构,3:报表,4:信息,5:叶子,6:勋章,7:文件,8:小圆点,9:齿轮,10:星星, -1:不显示二级图标。默认'5' + this.nodeIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? (this.icon == "-1" ? "-1" : "0") : this.icon[0]; //二级图标中的node节点图标。0:文件夹,1:+、-,2:三角形, -1:不显示二级图标,默认'0' + this.leafIcon = (typeof this.icon === 'string' || typeof this.icon === 'number') ? this.icon : this.icon[1]; //二级图标中的leaf节点图标 + } + + /** 数据加载参数**/ + this.url = this.options.url || this.url; //请求地址 + this.async = (typeof (this.options.async) === "boolean") ? this.options.async : this.async; //异步同步加载,默认异步加载 + this.asyncLoad = this.options.asyncLoad || this.asyncLoad; //初始异步加载层级数据 + this.headers = this.options.headers || this.headers; //ajax header属性 + this.method = this.options.method || this.method; //请求类型 + this.dataType = this.options.dataType || this.dataType; //参数类型 + this.contentType = this.options.contentType || this.contentType; //发送信息至服务器时内容编码类型 + this.defaultRequest = $.extend(this.defaultRequest, this.options.defaultRequest) || this.defaultRequest; //默认请求参数 + this.filterRequest = this.options.filterRequest || this.filterRequest; //过滤请求参数 + this.request = this.options.request || this.request; //用户自定义请求参数 + this.response = $.extend(this.response, this.options.response) || this.response; //返回json格式 + this.data = this.options.data || this.data; //初始化指定该参数,则不会访问异步接口 + this.dataFormat = this.options.dataFormat || this.dataFormat; //用于用户配置的data数据格式,list:列表, levelRelationship:层级关系,默认 + this.dataStyle = this.options.dataStyle || this.dataStyle; //用于用户配置layui通用的json数据风格,layuiStyle:layui风格,defaultStyle:默认风格 + this.errDataShow = (typeof (this.options.errDataShow) === "boolean") ? this.options.errDataShow : this.errDataShow; //是否在使用list模式递归数据出现错误时,显示错误信息 + this.withCredentials = (typeof (this.options.withCredentials) === "boolean") ? this.options.withCredentials : this.withCredentials; //是否允许跨域请求 + this.beforeSend = this.options.beforeSend || this.beforeSend; //异步加载之前的回调 + this.success = this.options.success || this.success; //树加载完毕后执行解析树之前的回调 + this.done = this.options.done || this.done; //树加载完毕后的回调 + this.formatter = $.extend(this.formatter, this.options.formatter)|| this.formatter; //数据过滤 + this.error = this.options.error || this.error; //异步加载异常回调 + this.complete = this.options.complete || this.complete; //异步加载完成回调 + + /** 复选框参数**/ + this.checkbar = this.options.checkbar || this.checkbar; //是否开启复选框模式 + this.checkbarLoad = this.options.checkbarLoad || this.checkbarLoad; //复选框作用范围,node:所有节点, leaf:最后一级;默认所有节点 + this.checkbarType = this.options.checkbarType || this.checkbarType; //复选框选中形式 all:子集选中父级也选中, no-all:子集选中父级半选中,子集全选父级选中,p-casc:父级选中子集全选,子集无法改变父级选中状态, self:没有任何级联关系,only:只能选中一个复选框。 默认all + this.checkbarData = this.options.checkbarData || this.checkbarData; //复选框记录数据类型形式, change表示记录变更数据,choose表示记录选中数据,all记录全部数据,halfChoose记录选中和半选中的数据,默认choose + this.checkbarFun = $.extend(this.checkbarFun, this.options.checkbarFun)|| this.checkbarFun; //checkbar事件加载 + + /** 菜单栏参数**/ + this.menubar = this.options.menubar || this.menubar; //是否打开菜单栏 + this.menubarTips = $.extend(this.menubarTips, this.options.menubarTips) || this.menubarTips; //菜单栏吸附, toolbar:依附在工具栏,group:依附在按钮组,freedom,自由 + this.menubarFun = $.extend(this.menubarFun, this.options.menubarFun) || this.menubarFun; //menubar事件加载 + + /** 工具栏参数**/ + this.toolbar = this.options.toolbar || this.toolbar; //是否开启工具栏 + this.toolbarWay = this.options.toolbarWay || this.toolbarWay; //工具栏显示方式,contextmenu:右键,follow:跟随节点,fixed:固定在节点右侧 + this.toolbarStyle = $.extend(this.toolbarStyle, this.options.toolbarStyle) || this.toolbarStyle; //toolbar的自定义风格,标题,弹框大小 + this.toolbarLoad = this.options.toolbarLoad || this.toolbarLoad; //toolbar作用范围:node:所有节点,noleaf:非最后一级节点,leaf:最后一级 + this.toolbarShow = this.options.toolbarShow || this.toolbarShow; //toolbar三个按钮 + this.toolbarBtn = this.options.toolbarBtn || this.toolbarBtn; //toolbar增删改中内容的自定义加载 + this.toolbarExt = this.options.toolbarExt || this.toolbarExt; //toolbar按钮扩展 + this.toolbarFun = $.extend(this.toolbarFun, this.options.toolbarFun) || this.toolbarFun; //toolbar事件加载 + + /** iframe模式参数**/ + this.useIframe = this.options.useIframe || this.useIframe;//是否加载iframe 默认false + this.iframeElem = this.options.iframeElem || this.iframeElem; //iframe的ID + this.iframeUrl = this.options.iframeUrl || this.iframeUrl; //树关联的iframe地址 + this.iframeLoad = this.options.iframeLoad || this.iframeLoad; //点击哪一层加载frame: node:所有节点, leaf:默认,最后一级 + this.iframeDefaultRequest = $.extend(this.iframeDefaultRequest, this.options.iframeDefaultRequest) || this.iframeDefaultRequest; //iframe的默认传递参数 + this.iframeRequest = $.extend(this.iframeRequest, this.options.iframeRequest) || this.iframeRequest; //iframe的自定义参数 + this.iframeFun = $.extend(this.iframeFun, this.options.iframeFun) || this.iframeFun; //iframe事件加载 + + /** 下拉树模式参数**/ + if(this.select) { + // 重置下拉树 + this.reloadSelectSetting(); + } + + /** 调用确认最终主题方法*/ + this.ensureTheme(); + + }; + + /** + * @Desc: 设置下拉树的基本参数值 + */ + DTree.prototype.selectSetting = function() { + /** select模式参数*/ + this.select = true; //配置成select模式 + + this.selectInitVal = this.obj.attr("data-value") || this.options.selectInitVal || ""; //输入框的值 + this.selectTreeDiv = this.obj[0].id + "_tree_div"; // 上级DIV节点 + this.selectCardDiv = this.obj[0].id + "_select_card_div"; // 上级layui卡片节点 + this.selectDiv = this.obj[0].id + "_select_div"; // 模拟的select节点 + this.selectTipsName = this.obj[0].id + "_select_input"; // select的提示输入框名称 + this.selectTips = this.options.selectTips || "请选择"; // 输入框的提示语 + this.selectCardHeight = this.options.selectCardHeight || "350"; // 下拉面板的高度 + this.selectInputName = this.options.selectInputName || {nodeId: this.obj[0].id + "_select_nodeId"}; // select表单中的元素 + + // 调取下拉树的特殊处理页面元素标识 + this.renderSelectDom(); + } + + /** + * @Desc: 重置下拉树的基本参数值 + */ + DTree.prototype.reloadSelectSetting = function() { + + this.selectInitVal = this.obj.attr("data-value") || this.options.selectInitVal || this.selectInitVal; //输入框的值 + this.selectTips = this.options.selectTips || this.selectTips; // 输入框的提示语 + this.selectCardHeight = this.options.selectCardHeight || this.selectCardHeight; // 下拉面板的高度 + this.selectInputName = $.extend(this.selectInputName, this.options.selectInputName) || this.selectInputName; // select表单中的元素 + + // 调取下拉树的特殊处理页面元素标识 + this.reloadSelectDom(); + } + + /******************** 下拉树设置区域 ********************/ + /** + * @Desc: 渲染下拉树的Dom结构 + */ + DTree.prototype.renderSelectDom = function() { + var _this = this; + var rootId = _this.obj[0].id; + + // 设置自定义表单隐藏域 + var selectInputName = _this.selectInputName; + var selectInput = []; + for(var key in selectInputName) { + selectInput.push(''); + } + + // 设置html + var prevHtml = ['
    ', + '
    ', selectInput.join(""), + '', + '', + '
    '].join(''); + + _this.obj.before(prevHtml); + + var cardStyle = "style="; + if(this.selectCardHeight) { + cardStyle += "'height:"+_this.selectCardHeight+"px'"; + } + _this.obj.wrap('
    ').wrap('
    ').wrap('
    '); + + } + + /** + * @Desc: 重新渲染下拉树的Dom结构 + */ + DTree.prototype.reloadSelectDom = function() { + var _this = this; + var rootId = _this.obj[0].id; + + // 设置自定义表单隐藏域 + var selectInputName = _this.selectInputName; + var selectInput = []; + for(var key in selectInputName) { + selectInput.push(''); + } + + $("div[dtree-id='"+rootId+"'][dtree-select='"+_this.selectDiv+"']").find("div.layui-select-title").html(""); + + // 设置html + var prevHtml = [selectInput.join(""), + '', + ''].join(''); + + $("div[dtree-id='"+rootId+"'][dtree-select='"+_this.selectDiv+"']").find("div.layui-select-title").html(prevHtml); + + var cardStyle = "style="; + if(this.selectCardHeight) { + cardStyle += "'height:"+_this.selectCardHeight+"px'"; + } + $("div[dtree-id='"+rootId+"'][dtree-card='"+_this.selectCardDiv+"']").attr("style", cardStyle); + } + + /** + * @Desc: 设置下拉树模式中,input输入框的值 + * @Param: param: input中的值对应树数据的ID值\当前树选中的数据JSON对象,可不传,不传的话则树内部读取 + */ + DTree.prototype.selectVal = function(param) { + var _this = this; + var rootId = _this.obj[0].id; + var selectInputName = _this.selectInputName; + var selectTipsNameValue = ""; + var selectValues = {}; + + // 如果开启了复选框,则此方法用来取值 + if(_this.checkbar) { + return _this.selectCheckboxVal(); + } + + if(typeof param === 'undefined') { // 不传,则为当前树中记录的ID + param = _this.getNowParam(); + } + if(typeof param === 'string') { // 传递ID,则查询树节点ID对应的值 + param = _this.getParam(param); + } + + selectTipsNameValue = param["context"]; + for(var key in selectInputName) { + selectValues[selectInputName[key]] = param[key]; + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+selectInputName[key]+"']").val(param[key] || ""); + } + + if(param["nodeId"] && !param["context"]) { + selectTipsNameValue = _this.getParam(param["nodeId"]); + } + + // 返显提示输入框值 + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+_this.selectTipsName+"']").val(selectTipsNameValue || ""); + + // 返回隐藏域中的值 + return selectValues; + } + + /** + * @Desc: 设置复选框模式中的下拉树的选中值 + */ + DTree.prototype.selectCheckboxVal = function() { + var _this = this; + var rootId = _this.obj[0].id; + var selectInputName = _this.selectInputName; + + // 获取全部复选框选中节点 + var param = _this.getCheckbarJsonArrParam(); + + selectTipsNameValue = param["context"]; + var selectValues = {}; + for(var key in selectInputName) { + var value = param[key].join(","); + selectValues[selectInputName[key]] = value; + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+selectInputName[key]+"']").val(value); + } + + $("div[dtree-select='" + _this.selectDiv + "']").find("input[dtree-id='" + rootId + "'][name='"+_this.selectTipsName+"']").val(selectTipsNameValue); + + // 返回隐藏域中的值 + return selectValues; + } + + /** + * @Desc: 重置下拉树的值,1.表单清空;2.节点重置;3.复选框重置 + */ + DTree.prototype.selectResetVal = function() { + var _this = this; + var rootId = _this.obj[0].id; + // 表单清空 + $("input[dtree-id='"+rootId+"']").val(""); + // 节点重置 + _this.cancelNavThis(); + if(_this.checkbar) { + // 复选框重置 + _this.cancelCheckedNode(); + } + } + + + /******************** 字体及图标区域 ********************/ + /** + * @Desc: 树使用的最终主题方案 + */ + DTree.prototype.ensureTheme = function(){ + var _this = this; + + // 确认style + this.style.item = DTREE + this.skin + ITEM; + this.style.itemThis = DTREE + this.skin + ITEMTHIS; + this.style.dfont = DTREE + this.skin + DFONT; + this.style.ficon = DTREE + this.skin + FICON; + this.style.icon = DTREE + this.skin + ICON; + this.style.cbox = DTREE + this.skin + CBOX; + this.style.chs = DTREE + this.skin + CHS; + + // 确认usefontStyle + var iconfont = this.iconfont; + var iconfonts = []; + if(typeof iconfont === 'string') { + iconfonts.push(iconfont); + } else { + iconfonts = iconfont; + } + + var iconfontStyle = this.iconfontStyle; + var iconfontStyles = []; + if(iconfontStyle.length == undefined) { + iconfontStyles.push(iconfontStyle); + } else { + iconfontStyles = iconfontStyle; + } + + for(var i=0; i 0) { + $lis.each(function(){ + _this.showLineLi($(this)); + }); + } else { + _this.obj.find("li[data-id]").each(function(){ + _this.showLineLi($(this)); + }); + } + } + } + + /** + * @Desc: 真正显示树线的方法 + * @Param: $li: JQuery对象,表示组成树的li节点 + */ + DTree.prototype.showLineLi = function($li){ + var _this = this; + var $div = $li.children("div"), + $nextLi = $li.next("li"), + $ul = $li.parent("ul"); + if($ul[0].id == _this.obj[0].id) { + // 根节点下的节点 + $li.removeClass(LI_NAV_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_FIRST_LINE); + } else { + // 非根节点下的节点 + var $pnextLi = $ul.parent("li").next("li"); + if($pnextLi.length == 0) { + if($nextLi.length == 0){ + $li.removeClass(LI_NAV_LINE); + $li.removeClass(LI_NAV_FIRST_LINE); + $li.addClass(LI_NAV_LAST_LINE); + } else { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_LINE); + } + }else { + var $pnextdiv = $pnextLi.children("div"); + if($nextLi.length == 0 && $div.children("cite").attr("data-leaf") == "leaf" && $pnextdiv.children("cite").attr("data-leaf") == "leaf") { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LINE); + $li.addClass(LI_NAV_LAST_LINE); + } else { + $li.removeClass(LI_NAV_FIRST_LINE); + $li.removeClass(LI_NAV_LAST_LINE); + $li.addClass(LI_NAV_LINE); + } + } + } + } + + /******************** 初始化数据区域 ********************/ + /** + * @Desc: 设置高度 + */ + DTree.prototype.autoHeight = function(){ + var _this = this; + var height = _this.height; + if(height != "") { + if(_this.elem == _this.scroll){ + _this.obj.parent().css("height", height + "px"); + } else { + var $toolbarDiv = _this.obj.closest(_this.scroll); + $toolbarDiv.css("height", height + "px"); + } + } + }; + + /** + * @Desc: 重载树 + * @Param: options: dtree的所有属性的json对象 + */ + DTree.prototype.reload = function(options){ + var _this = this; + _this.reloadSetting(options); + _this.init(); + }; + + /** + * @Desc: 初始化加载 + */ + DTree.prototype.loadTreeInit = function(){ + var _this = this; + var asyncLoad = _this.asyncLoad; + // 初始化加载 + _this.init(function(){ + // ajax加载之后的回调 + if(asyncLoad && asyncLoad.length > 0) { + _this.obj.addClass(NAV_SHOW); + + // 说明此时要异步加载子节点 + _this.loadChildTreeInit(asyncLoad, 0); + } + }) + } + + /** + * @Desc: 初始化加载子节点 + * @Param: asyncLoad: 需异步加载的层级,在基础属性中配置 + * @Param: i: 已经加载到的层级 + */ + DTree.prototype.loadChildTreeInit = function(asyncLoad, i){ + var _this = this; + if(i == asyncLoad.length) { // 满足条件,终止递归 + return ; + } + + var $div = _this.getNode(asyncLoad[i]); + + if($div && $div.length > 0) { + // 设置节点状态 + var $ul = $div.next("ul"), + $i_fnode = _this.getNodeDom($div).fnode(), + $i_snode = _this.getNodeDom($div).snode(); + + $ul.addClass(NAV_SHOW); + _this.accordionUL($ul); + _this.operateIcon($i_fnode, $i_snode).open(); + // 加载子节点 + _this.getChild($div, undefined, function(){ + // 继续递归 + _this.loadChildTreeInit(asyncLoad, ++i); + }); + } + + } + + /** + * @Desc: 初始化树 + * @Param: callback: 异步加载完成之后的回调函数 + */ + DTree.prototype.init = function(callback){ + var _this = this; + if (typeof _this !== "object") { + layer.msg("树组件未成功加载,请检查配置", {icon:5}); + return ; + } + + // 设置组件高度 + _this.autoHeight(); + + if(_this.data) { + _this.dataLoadTree(true, _this.obj, _this.data); + } else { + _this.asyncLoadTree(true, _this.obj, callback); + } + }; + + /** + * @Desc: 加载子节点 + * @Param: $div: JQuery对象,代表当前子节点的父节点div + * @Param: data: data方式加载的数据 + * @Param: callback: 子节点加载完成之后的回调喊出 + */ + DTree.prototype.getChild = function($div, data, callback) { + var _this = this, $ul = $div.next("ul"); + + _this.setNodeParam($div); + + if(typeof data !== 'undefined') { + _this.dataLoadTree(false, $ul, data); + } else { + _this.asyncLoadTree(false, $ul, callback); + } + }; + + /** + * @Desc: 用data加载树 + * @Param: first: 表示是否第一次加载 + * @Param: $ul: JQuery对象,代表当前数据加载到的ul标签里 + * @Param: data: data加载的数据 + */ + DTree.prototype.dataLoadTree = function(first, $ul, data){ + var _this = this; + + if(typeof data.length === 'undefined'){ + layer.msg("数据解析异常,data数据格式不正确", {icon:5}); + return ; + } + + if(first && data.length == 0) { + $ul.html(_this.getNoneDom().text()); + return ; + } + + //先将ul中的元素清空 + $ul.html(""); + + var index = _this.load ? layer.load(1) : ""; + + setTimeout(function () { + // 加载完毕后执行树解析前的回调 + var returnData = _this.success(data, $ul, first); + if(returnData) { + data = returnData; + } + + var pid = (first == true) ? $ul.attr("data-id") : _this.node.nodeId; + var level = (first == true) ? 1 : parseInt(_this.node.level)+1; + + // 解析树 + if (_this.dataFormat == 'list'){ + //1.构建一个存放节点的树组 + var rootListData = _this.queryListTreeByPid(pid, data); + _this.loadListTree(rootListData, _this.data, level); + } else { + _this.loadTree(data, level); + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + // 设置下拉树的初始值 + if(first && _this.select && _this.selectInitVal){ + if(_this.checkbar) { // 复选框模式下 + _this.chooseDataInit(_this.selectInitVal); + _this.selectCheckboxVal(_this.selectInitVal); + } else { // 普通模式下 + _this.dataInit(_this.selectInitVal); + _this.selectVal(_this.selectInitVal); + } + } + + // 保存树副本 + _this.bak = _this.obj.html(); + + // 加载完毕后的回调 + _this.done(_this.data, $ul, first); + + if(_this.load){layer.close(index);} + }, 100); + } + + /** + * @Desc: 异步加载树 + * @Param: first: 表示是否第一次加载 + * @Param: $ul: JQuery对象,代表当前数据加载到的ul标签里 + * @Param: callback: 异步加载完成之后的回调函数 + */ + DTree.prototype.asyncLoadTree = function(first, $ul, callback){ + var _this = this; + + if (!_this.url) { + layer.msg("数据请求异常,url参数未指定", {icon:5}); + return ; + } + + //先将ul中的元素清空 + $ul.html(""); + + var index = ""; + + AjaxHelper.request({ + async: _this.async, + headers: _this.headers, + type: _this.method, + url: _this.url, + dataType: _this.dataType, + contentType: _this.contentType, + withCredentials: _this.withCredentials, + data: _this.getFilterRequestParam(_this.getRequestParam()), + beforeSend: function(XMLHttpRequest, self){ + index = _this.load ? layer.load(1) : ""; + var returnFlag = _this.beforeSend(this, XMLHttpRequest, self); + if(!returnFlag) { + if(_this.load){layer.close(index);} + } + return returnFlag; + }, + success: function(result) { + if (typeof result === 'string') { + result = $.parseJSON(result); + } + + // 加载完毕后执行树解析前的回调 + var returnData = _this.success(result, $ul, first); + if(returnData) { + result = returnData; + } + + var code = ""; + if (_this.dataStyle == 'layuiStyle'){ + code = result[_this.response.statusName]; + } else { + code = result.status[_this.response.statusName]; + } + + if (code == _this.response.statusCode) { + + var d = result[_this.response.rootName]; + + if(first && typeof d.length === 'undefined'){ + $ul.html(_this.getNoneDom().errText("数据解析异常,url回调后的数据格式不正确")); + //layer.msg("数据解析异常,url回调后的数据格式不正确", {icon:5}); + return ; + } + + if(first && d.length == 0) { + $ul.html(_this.getNoneDom().text()); + return ; + } + + //1.识别根节点ul中的data-id标签,判断顶级父节点 + var pid = (first == true) ? $ul.attr("data-id") : _this.node.nodeId; + var level = (first == true) ? 1 : parseInt(_this.node.level)+1; + + // 第一次解析树 + if (_this.dataFormat == 'list'){ + //1.构建一个存放节点的树组 + var rootListData = _this.queryListTreeByPid(pid, d); + if(first) { + _this.loadListTree(rootListData, d, level); + } else { + _this.loadListTree(rootListData, d, level, $ul); + } + } else { + if(first) { + _this.loadTree(d, level); + } else { + _this.loadTree(d, level, $ul); + } + } + + // 显示树线 + _this.showLine(); + + // 这种情况下需要一开始就将toolbar显示在页面上 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.setToolbarDom().setToolbarPlace(_this.toolbarMenu); + } + + // 判断是否存在错误数据,并是否打印错误数据 + _this.msgErrData(); + + if(!first) { + $ul.addClass(NAV_SHOW); + } + + // 设置下拉树的初始值 + if(first && _this.select && _this.selectInitVal){ + if(_this.checkbar) { // 复选框模式下 + _this.chooseDataInit(_this.selectInitVal); + _this.selectCheckboxVal(_this.selectInitVal); + } else { // 普通模式下 + _this.dataInit(_this.selectInitVal); + _this.selectVal(_this.selectInitVal); + } + } + + // 保存树副本 + _this.bak = _this.obj.html(); + + // 加载完毕后的回调 + _this.done(result, $ul, first); + + callback && callback(); + } else { + // 如果打印不出任何信息说明是在这里,用了错误的数据格式, 或返回码不正确 + if (_this.dataStyle == 'layuiStyle'){ + _this.obj.html(_this.getNoneDom().errText(result[_this.response.message])); + _this.error(null, code, result[_this.response.message]); + } else { + _this.obj.html(_this.getNoneDom().errText(result.status[_this.response.message])); + _this.error(null, code, result.status[_this.response.message]); + } + } + }, + error: function(XMLHttpRequest, textStatus, errorThrown){// 异步加载异常回调 + _this.obj.html(_this.getNoneDom().errText(textStatus + ": " + errorThrown)); + _this.error(XMLHttpRequest, textStatus, errorThrown); + }, + complete: function(XMLHttpRequest, textStatus){// 异步加载完成回调 + if(_this.load){layer.close(index);} + _this.complete(XMLHttpRequest, textStatus); + } + }); + + } + + /** + * @Desc: 初始化渲染树或者拼接渲染树,list模式下 + * @Param: nowListData: 表示当前需要被渲染的数据 + * @Param: listData: 表示全部数据 + * @Param: level: 当前渲染的层级 + * @Param: $ul: JQuery对象,代表当前数据加载到的ul标签里 + */ + DTree.prototype.loadListTree = function(nowListData, listData, level, $ul){ + var _this = this; + $ul = $ul || _this.getNodeDom().nowOrRootUl(); //当前选中的节点或根节点 + if (nowListData.length > 0){ + for (var i = 0; i < nowListData.length; i++) { + // 1.获取已知节点的全部数据 + var data = nowListData[i]; + if(typeof data !== "object") continue; + var parseData = _this.parseData(data); + var childListData = _this.queryListTreeByPid(parseData.treeId(), listData); // 根据已知数据的id判断该条数据是否还有子数据 + + // 3. 页面元素加载数据 + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(childListData.length), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(level), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), ($ul.hasClass(UL_ROOT) ? "root" : "item"))); + // 4.有子数据的元素加载子节点 + if(childListData.length > 0){ + var cLevel = parseInt(level)+1; + _this.loadListTree(childListData, listData, cLevel, _this.obj.find("ul[data-id='"+parseData.treeId()+"']")); + } + } + } + }; + + /** + * @Desc: 根据父ID查找list数据中匹配的元素 + * @Param: pid: 表示父ID + * @Param: listData: 表示全部数据 + */ + DTree.prototype.queryListTreeByPid = function(pid, listData){ + var _this = this; + var rootListData = []; + if (listData) { + for (var i = 0; i < listData.length; i++) { + var data = listData[i]; + if(typeof data !== "object") continue; + if(pid == "null" || pid == null){ + if(data[_this.response.parentId] == null) { rootListData.push(data); } + } else { + if (data[_this.response.parentId] == pid){ + if (data[_this.response.treeId] == pid){ + _this.errData.push(data); + } else { + rootListData.push(data); + } + } + } + } + } + return rootListData; + }; + + /** + * @Desc: 初始化渲染树或者拼接渲染树,层级关系模式下 + * @Param: listData: 表示全部数据 + * @Param: level: 当前渲染的层级 + * @Param: $ul: JQuery对象,代表当前数据加载到的ul标签里 + */ + DTree.prototype.loadTree = function(listData, level, $ul){ + var _this = this; + if (listData) { + $ul = $ul || _this.getNodeDom().nowOrRootUl(); //当前选中的节点或根节点 + for (var i = 0; i < listData.length; i++) { // 遍历跟节点或追加的跟节点 + var data = listData[i]; + if(typeof data !== "object") continue; + if(data[_this.response.treeId] == data[_this.response.parentId]) { _this.errData.push(data); } + var parseData = _this.parseData(data); + var children = parseData.children(); + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(children.length), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(level), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), ($ul.hasClass(UL_ROOT) ? "root" : "item"))); + if (children.length != 0) { + var cLevel = parseInt(level)+1; + _this.loadTree(children, cLevel, _this.obj.find("ul[data-id='"+parseData.treeId()+"']")); + } + } + } + }; + + /** + * @Desc: 判断在数据加载时是否存在错误数据,并是否打印错误数据 + * @Param: + */ + DTree.prototype.msgErrData = function() { + var _this = this; + if(_this.errData.length > 0 && _this.errDataShow) { + var title = ""; + for(var i=0; i<_this.errData.length; i++) { + var edata = _this.errData[i]; + title += "数据:【"+edata[_this.response.title]+"】中节点id和上级id值一致! \n"; + } + layer.msg(title, {icon:2,time:5000}); + } + // 显示之后,将错误数据制空 + _this.errData = []; + }; + + /** + * @Desc: 解析单个数据 + * @Param: data: 被解析的单个数据对象 + */ + DTree.prototype.parseData = function(data) { + var _this = this; + + return { + treeId: function(){ + return data[_this.response.treeId]; + }, + parentId: function(){ + return data[_this.response.parentId]; + }, + fmtTitle: function(){ + if(typeof _this.formatter.title === 'function'){ + var ftitle = _this.formatter.title(data); + var tt = data[_this.response.title]; + tt = (ftitle == "" || ftitle == undefined || ftitle == null) ? tt : ftitle; + return tt || ""; + } + return data[_this.response.title]; + }, + title: function(){ + return data[_this.response.title]; + }, + level: function(){ + return data[_this.response.level] || ""; + }, + ficonClass: function(){ + return data[_this.response.ficonClass] || ""; + }, + iconClass: function(){ + return data[_this.response.iconClass] || ""; + }, + last: function(len){ + return ((len == 0) ? + ((typeof (data[_this.response.last]) === "boolean") ? data[_this.response.last] : true) : + ((typeof (data[_this.response.last]) === "boolean") ? data[_this.response.last] : false)); + }, + spread: function(level){ + return ((level < _this.initLevel) ? + ((typeof (data[_this.response.spread]) === "boolean") ? data[_this.response.spread] : true) : + ((typeof (data[_this.response.spread]) === "boolean") ? data[_this.response.spread] : false)); + }, + disabled: function(){ + return (typeof (data[_this.response.disabled]) === "boolean") ? data[_this.response.disabled] : false; + }, + hide: function(){ + return (typeof (data[_this.response.hide]) === "boolean") ? data[_this.response.hide] : false; + }, + checkArr: function(){ + var checkArr = []; + var checkArrData = data[_this.response.checkArr]; + if(typeof checkArrData === 'string'){ + if(checkArrData.indexOf("{") > -1 && checkArrData.indexOf("}") > -1){ + checkArrData = JSON.parse(checkArrData); + } else { + checkArrData = {"type":"0","checked":checkArrData}; + } + } + if((typeof checkArrData === 'object') && (checkArrData !== null)){ + if(typeof checkArrData.length === 'undefined'){ + checkArr.push(checkArrData); + } else { + checkArr = checkArrData; + } + } + + if(checkArr.length > 0 && checkArr.length > _this.checkArrLen){ + _this.checkArrLen = checkArr.length; // 获取复选框个数 + } + return checkArr; + + }, + children: function(){ + return data[_this.response.childName] || []; + }, + basicData: function(){ + return event.escape(JSON.stringify(data[_this.response.basicData])) || JSON.stringify({}); + }, + recordData: function(){ + var recordData = _this.record ? event.cloneObj(data, [_this.response.treeId, + _this.response.parentId, + _this.response.title, + _this.response.iconClass, + _this.response.childName, + _this.response.last, + _this.response.spread, + _this.response.disabled, + _this.response.hide, + _this.response.checkArr, + _this.response.checked, + _this.response.type, + _this.response.basicData]) : {}; + + return event.escape(JSON.stringify(recordData)); + }, + data: function(){ + return data; + } + } + + }; + + /** + * @Desc: 无节点数据、节点数据异常时显示dom + */ + DTree.prototype.getNoneDom = function(){ + var _this = this, + rootId = _this.obj[0].id, + noneTitle = _this.none; + + return { + text: function(){ + return "
    "+noneTitle+"
    "; + }, + errText: function(errInfo){ + return "
    "+errInfo+"
    "; + } + } + }; + + /** + * @Desc: 新增节点的dom值 + * @Param: treeId: 节点ID + * @Param: parentId: 节点父ID + * @Param: title: 节点标题 + * @Param: fmtTitle: 节点附加标题 + * @Param: last: 是否最后一级节点 + * @Param: ficonClass: 一级图标class + * @Param: iconClass: 二级图标class + * @Param: checkArr: 复选框 + * @Param: spread: 是否展开 + * @Param: disabled: 是否禁用 + * @Param: hide: 是否隐藏 + */ + DTree.prototype.getDom = function(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide) { + var _this = this, + rootId = _this.obj[0].id, + toolbar = _this.toolbar, + checkbar = _this.checkbar; + + return { + fnode: function() { // + - 图标 + // 获取图标的变量 + var fnodeIcon = _this.fnodeIcon, + fleafIcon = _this.fleafIcon; + + var fleafIconLeaf = _this.usefontStyle.fnode.leaf, + fnodeIconOpen = _this.usefontStyle.fnode.node.open, + fnodeIconClose = _this.usefontStyle.fnode.node.close; + + if(ficonClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + fleafIconLeaf = iconfont + " " + ficonClass; + fnodeIconOpen = iconfont + " " + ficonClass; + fnodeIconClose = iconfont + " " + ficonClass; + } else { + fleafIconLeaf = iconfont[0] + " " + ficonClass; + fnodeIconOpen = iconfont[0] + " " + ficonClass; + fnodeIconClose = iconfont[0] + " " + ficonClass; + } + } + + if(fnodeIcon != "-1" && fleafIcon != "-1"){ // 都加载 + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon != "-1" && fleafIcon == "-1"){ // 加载node 隐藏leaf + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon == "-1" && fleafIcon != "-1"){ // 隐藏node 加载leaf + return last ? "" : + (spread ? "" : ""); + } + + if(fnodeIcon == "-1" && fleafIcon == "-1"){ // 都隐藏 + return last ? "" : + (spread ? "" : ""); + } + }, + node: function() { // 二级图标样式 + // 获取图标的变量 + var nodeIcon = _this.nodeIcon, + leafIcon = _this.leafIcon; + + var sleafIconLeaf = _this.usefontStyle.snode.leaf, + snodeIconOpen = _this.usefontStyle.snode.node.open, + snodeIconClose = _this.usefontStyle.snode.node.close; + if(iconClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + sleafIconLeaf = iconfont + " " + iconClass; + snodeIconOpen = iconfont + " " + iconClass; + snodeIconClose = iconfont + " " + iconClass; + } else { + sleafIconLeaf = iconfont[0] + " " + iconClass; + snodeIconOpen = iconfont[0] + " " + iconClass; + snodeIconClose = iconfont[0] + " " + iconClass; + } + } + + if(nodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + return last ? "" : + (spread ? "" : ""); + } + + if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + return last ? "" : + (spread ? "" : ""); + } + }, + checkbox: function() { // 复选框 + var flag = false; + if(_this.checkbarLoad == "node"){if (checkbar) {flag = true;}} else {if (last) {if (checkbar) {flag = true;}}} + + if(flag){ + var result = "
    "; + if(checkArr && checkArr.length > 0){ + + for (var i = 0; i < checkArr.length; i++) { + var checkData = checkArr[i]; + var checked = checkData[_this.response.checked]; + var type = checkData[_this.response.type]; + var CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + if (checked == "2") { //半选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.noall + " " + _this.style.chs; + } else if (checked == "1") { //选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.on + " " + _this.style.chs; + } else { //未选择或者无值 + CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + } + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + result += ""; + } + } + result += "
    "; + return result; + } + + return ""; + }, + text: function() { // 文字显示 + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + return ""+fmtTitle+""; + }, + ul: function() { //子节点ul + return last ? "
      " : + (spread ? "
        " : "
          "); + } + }; + }; + + /** + * @Desc: 替换节点的dom值,或指定这些值 + * @Param: $div: JQuery对象,表示当前被操作的节点 + * @Param: treeId: 节点ID + * @Param: last: 是否最后一级节点 + * @Param: spread: 是否展开 + * @Param: disabled: 是否禁用 + * @Param: hide: 是否隐藏 + */ + DTree.prototype.replaceDom = function($div, treeId, last, spread, disabled, hide) { + var _this = this, + rootId = _this.obj[0].id, + toolbar = _this.toolbar, + checkbar = _this.checkbar; + + return { + fnode: function(ficonClass) { // + - 图标 + var fnode = ""; + + // 获取图标的变量 + var fnodeIcon = _this.fnodeIcon, + fleafIcon = _this.fleafIcon; + + var fleafIconLeaf = _this.usefontStyle.fnode.leaf, + fnodeIconOpen = _this.usefontStyle.fnode.node.open, + fnodeIconClose = _this.usefontStyle.fnode.node.close; + + if(ficonClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + fleafIconLeaf = iconfont + " " + ficonClass; + fnodeIconOpen = iconfont + " " + ficonClass; + fnodeIconClose = iconfont + " " + ficonClass; + } else { + fleafIconLeaf = iconfont[0] + " " + ficonClass; + fnodeIconOpen = iconfont[0] + " " + ficonClass; + fnodeIconClose = iconfont[0] + " " + ficonClass; + } + } + + if(fnodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + fnode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + fnode = last ? "" : + (spread ? "" : ""); + } + if(fnode != ""){_this.getNodeDom($div).fnode().replaceWith($(fnode));} + }, + node: function(iconClass) { // 二级图标样式 + var snode = ""; + + // 获取图标的变量 + var nodeIcon = _this.nodeIcon, + leafIcon = _this.leafIcon; + + var sleafIconLeaf = _this.usefontStyle.snode.leaf, + snodeIconOpen = _this.usefontStyle.snode.node.open, + snodeIconClose = _this.usefontStyle.snode.node.close; + if(iconClass){ + var iconfont = _this.iconfont; + if(typeof iconfont === 'string') { + sleafIconLeaf = iconfont + " " + iconClass; + snodeIconOpen = iconfont + " " + iconClass; + snodeIconClose = iconfont + " " + iconClass; + } else { + sleafIconLeaf = iconfont[0] + " " + iconClass; + snodeIconOpen = iconfont[0] + " " + iconClass; + snodeIconClose = iconfont[0] + " " + iconClass; + } + } + + if(nodeIcon != "-1" && leafIcon != "-1"){ // 都加载 + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon != "-1" && leafIcon == "-1"){ // 加载node 隐藏leaf + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon != "-1"){ // 隐藏node 加载leaf + snode = last ? "" : + (spread ? "" : ""); + }else if(nodeIcon == "-1" && leafIcon == "-1"){ // 都隐藏 + snode = last ? "" : + (spread ? "" : ""); + } + if(snode != ""){_this.getNodeDom($div).snode().replaceWith($(snode));} + }, + checkbox: function(checkArr) { // 复选框 + var flag = false; + if(_this.checkbarLoad == "node"){if (checkbar) {flag = true;}} else {if (last) {if (checkbar) {flag = true;}}} + + if(flag){ + var result = "
          "; + if(checkArr && checkArr.length > 0){ + + for (var i = 0; i < checkArr.length; i++) { + var checkData = checkArr[i]; + var checked = checkData[_this.response.checked]; + var type = checkData[_this.response.type]; + var CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + if (checked == "2") { //半选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.noall + " " + _this.style.chs; + } else if (checked == "1") { //选择 + CHOOSE_CLASS = _this.usefontStyle.checkbox.on + " " + _this.style.chs; + } else { //未选择或者无值 + CHOOSE_CLASS = _this.usefontStyle.checkbox.out; + } + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + result += ""; + } + } + result += "
          "; + _this.getNodeDom($div).snode().next("div").replaceWith($(result)); + } + }, + text: function(title) { // 文字显示 + var disClass = ""; + if(disabled){disClass = NAV_DIS;} + var cite = ""+title+"" + _this.getNodeDom($div).cite().replaceWith($(cite)); + }, + ul: function() { //子节点ul + var ul = last ? "
            " : + (spread ? "
              " : "
                "); + _this.getNodeDom($div).nextUl().replaceWith($(ul)); + }, + div: function(){ + $div.attr("data-id", treeId); + }, + basicData: function(basicData){ + basicData = (basicData == "{}") ? "" : basicData; + $div.attr("data-basic", basicData); + }, + recordData: function(recordData){ + recordData = (recordData == "{}") ? "" : recordData; + $div.attr("data-record", recordData); + }, + p_li: function(pId){ + var $li = $div.parent("li"); + $li.attr("data-id", treeId); + if(pId) { + $li.attr("data-pid", pId); + } + return $li; + } + }; + + }; + + /** + * @Desc: 获取拼接好的li的dom + * @Param: treeId: 节点ID + * @Param: parentId: 节点父ID + * @Param: title: 节点标题 + * @Param: fmtTitle: 节点附加标题 + * @Param: last: 是否最后一级节点 + * @Param: ficonClass: 一级图标class + * @Param: iconClass: 二级图标class + * @Param: checkArr: 复选框 + * @Param: level: 当前li的层级 + * @Param: spread: 是否展开 + * @Param: disabled: 是否禁用 + * @Param: hide: 是否隐藏 + * @Param: basicData: 自定义的扩展字段值(转义后的JSON字符) + * @Param: recordData: 开启记录模式的记录值(转义后的JSON字符) + * @Param: isRoot: 当前节点是否是根节点下的节点 + */ + DTree.prototype.getLiItemDom = function(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide, basicData, recordData, isRoot) { + var _this = this, + rootId = _this.obj[0].id; + + var dom = _this.getDom(treeId, parentId, title, fmtTitle, last, ficonClass, iconClass, checkArr, level, spread, disabled, hide); + basicData = (basicData == "{}") ? "" : basicData; + recordData = (recordData == "{}") ? "" : recordData; + var div = "
                " + + div , + dom.fnode(), + dom.node(), + dom.checkbox(), + dom.text(), + "
                ", dom.ul(), ""].join(""); + + return li; + }; + + /** + * @Desc: 初始化节点,用于数据回显 + * @Param: chooseId: 节点ID + */ + DTree.prototype.dataInit = function(chooseId){ + var _this = this; + var $div = _this.obj.find("div[data-id='"+chooseId+"']"); + if($div && $div.length > 0) { + _this.obj.find("."+NAV_THIS).removeClass(NAV_THIS); + _this.obj.find("."+_this.style.itemThis).removeClass(_this.style.itemThis); + $div.addClass(NAV_THIS); + $div.addClass(_this.style.itemThis); + _this.setNodeParam($div); + // 将该节点的父节点全部展开 + var $li_parents = $div.parents("."+LI_NAV_ITEM); + $li_parents.children("ul").addClass(NAV_SHOW); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.fnode.node.close)).addClass(_this.usefontStyle.fnode.node.open); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.fnode.node.close)).removeClass(_this.usefontStyle.fnode.node.close); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.snode.node.close)).addClass(_this.usefontStyle.snode.node.open); + $li_parents.children("."+LI_DIV_ITEM).children("i[data-spread]."+event.trimToDot(_this.usefontStyle.snode.node.close)).removeClass(_this.usefontStyle.snode.node.close); + } + return _this.getNowParam(); + }; + + /** + * @Desc: 基于备份的Html数据回滚 + * @Param: chooseId: 节点ID + */ + DTree.prototype.rollbackHtml = function(chooseId){ + var _this = this; + if(_this.bak) { + _this.obj.html(_this.bak); + // 取消全部选中状态 + _this.cancelNavThis(); + if(_this.checkbar) { + _this.cancelCheckedNode(); + _this.chooseDataInit(chooseId); + } else { + _this.dataInit(chooseId); + } + + _this.bak = _this.obj.html(); + } + }; + + + /******************** 基础事件区域 ********************/ + /** + * @Desc: 数据格式化 + * @Param: html: 需要格式化的数据 + */ + DTree.prototype.escape = function(html){ + return event.escape(html); + }; + + /** + * @Desc: 格式化数据转回正常数据 + * @Param: str: 需要转回的数据 + */ + DTree.prototype.unescape = function(str){ + return event.unescape(str); + }; + + /** + * @Desc: 取消选中当前选中的div + */ + DTree.prototype.cancelNavThis = function(){ + var _this = this; + _this.obj.find("div[data-id]").parent().find("."+NAV_THIS).removeClass(NAV_THIS); + _this.obj.find("div[data-id]").parent().find("."+_this.style.itemThis).removeClass(_this.style.itemThis); + } + + /** + * @Desc: 选中div + * @Param: id: 当前div本身 / 当前选中div的id值 + */ + DTree.prototype.navThis = function(id){ + var _this = this; + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null) { + _this.cancelNavThis(); + $div.addClass(NAV_THIS); + $div.addClass(_this.style.itemThis); + } + } + + /** + * @Desc: 手风琴模式操作其他节点 + * @Param: $ul: JQuery对象,表示dtree中的ul节点 + */ + DTree.prototype.accordionUL = function($ul) { + var _this = this; + if(_this.accordion) { + $ul.closest("li[data-index]").siblings("li[data-index]").children("ul[data-id]").removeClass(NAV_SHOW); + var $divs = $ul.closest("li[data-index]").siblings("li[data-index]").children("ul[data-id]").prev("div"); + if($divs.length && $divs.length > 0) { + for (var i=0; i<$divs.length; i++) { + var $div = $($divs[i]); + var $i_fnode = _this.getNodeDom($div).fnode(), + $i_snode = _this.getNodeDom($div).snode(); + if($i_fnode.attr("data-spread") != 'last'){ + _this.operateIcon($i_fnode, $i_snode).close(); + } + } + } + + } + }; + + /** + * @Desc: 展开或隐藏节点 作用点: div + * @Param: $div: JQuery对象,表示当前操作的div节点 + */ + DTree.prototype.clickSpread = function($div) { + var _this = this; + var $i_fnode = _this.getNodeDom($div).fnode(), + $i_snode = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_fnode.attr("data-spread"), + $ul = $div.next("ul"); + + if ($ul.length > 0) { + if (spread == "close") { + if (_this.type=="load") { //增加加载 + if (_this.cache) { //开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + _this.accordionUL($ul); + } else { //加载节点 + _this.getChild($div); + _this.accordionUL($ul); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + _this.accordionUL($ul); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + _this.accordionUL($ul); + } + _this.operateIcon($i_fnode, $i_snode).open(); + } else if (spread == "open") { + $ul.removeClass(NAV_SHOW); + _this.operateIcon($i_fnode, $i_snode).close(); + } + } + }; + + /** + * @Desc: 设置节点为disabled + * @Param: disabledIds: 需要设置禁用的节点id字符串集合(用,分割)/id数组 + */ + DTree.prototype.setDisabledNodes = function(disabledIds){ + var _this = this; + var disabledId = []; + if(typeof disabledIds === "string") { + disabledId = disabledIds.split(","); + } else { + disabledId = disabledIds; + } + + if(disabledIds.length) { + for (var i=0; i 0) { + _this.getChild($div, data); + } else { + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var level = parseInt($div.parent("li").attr("data-index"))+1; + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(0), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), "item")); + + // 建造完毕后,选中该DIV + $thisDiv = $ul.find("div[data-id='"+parseData.treeId()+"']"); + _this.setNodeParam($thisDiv); + + _this.showLine($ul.find("li")); + } else { + layer.msg("添加失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } + } else { + _this.getChild($div); + } + } + + /** + * @Desc: 局部刷新树--编辑当前节点选中节点时 + * @Param: $div: JQuery对象,当前编辑节点的Div + * @Param: data: 当前需要渲染的数据,JSON对象、字符串 + */ + DTree.prototype.partialRefreshEdit = function($div, data){ + var _this = this; + $ul = $div.next("ul"), + $p_li = $div.parent("li"); + + if(data) { + if(typeof data === 'object') { + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var replaceDom = _this.replaceDom($div, parseData.treeId(), parseData.last(0), parseData.spread(), parseData.disabled(), parseData.hide()); + replaceDom.div(); + replaceDom.node(parseData.iconClass()); + replaceDom.checkbox(parseData.checkArr()); + replaceDom.text(parseData.title()); + replaceDom.ul(); + replaceDom.basicData(parseData.basicData()); + replaceDom.recordData(parseData.recordData()); + + var parentId = parseData.parentId(); + var oldParentId = $p_li.attr("data-pid"); + if(parentId && parentId != oldParentId) { + // 变更了父节点 + $p_li = replaceDom.p_li(parentId); + + // 根据parentId找到下挂节点的ul + var $goto_div = _this.getNodeDom(parentId).div(), + $goto_ul = _this.getNodeDom(parentId).nextUl(); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($goto_ul.children("li").length == 0){ + var $icon_i = $goto_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).openWithLeaf(); + $goto_ul.addClass(NAV_SHOW); + } + $goto_ul.append($p_li); + } else { + replaceDom.p_li(); + } + _this.setNodeParam($div); + } else { + layer.msg("编辑失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } else { + _this.getNodeDom($div).cite().html(data); + } + } + } + + /** + * @Desc: 局部刷新树--当前节点选中被删除时 + * @Param: $div: JQuery对象,当前被删除节点的Div + */ + DTree.prototype.partialRefreshDel = function($div){ + var _this = this; + $p_li = $div.parent("li"); + $p_ul = _this.getNodeDom($div).parentUl(); + $p_div = _this.getNodeDom($div).parentDiv(); + + $p_li.remove(); + _this.showLine($p_ul.find("li")); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($p_ul.children("li").length == 0){ + var $icon_i = $p_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).closeWithLeaf(); + } + _this.initNodeParam(); + } + + /*** + * @Desc: 搜索节点,保留上级节点 + * @param: value: 传入的节点名称 + * layui-dtree群友: 没水平的水瓶提供。 + */ + DTree.prototype.fuzzySearch = function (value) { + var _this = this; + // + if (value.trim() == '') { + _this.obj.find("li").removeClass("layui-hide").attr("dtree-hide", false) + return + } + _this.obj.find("li").addClass("layui-hide").attr("dtree-hide", true) + + var cites = [] + var filterMode = _this.filterMode + /*if (filterMode == 'default') { + cites = _this.obj.find("li>div cite:contains('" + value + "')"); + }*/ + cites = _this.obj.find("li>div cite:contains('" + value + "')"); + cites.each(function (index, cite) { + var li = $(cite).parent().parent(); + var curNode = _this.getParam(li.attr("data-id")); + li.removeClass("layui-hide").attr("dtree-hide", false); + // 显示所有子级 + li.find('ul li').removeClass("layui-hide").attr("dtree-hide", false); + // 显示所有父级 + li.parents('li').removeClass("layui-hide").attr("dtree-hide", false); + }) + } + + /******************** 复选框区域 ********************/ + /** + * @Desc: 初始化复选框的值 + * @Param: chooseIds: 需要被选中的节点id字符串集合(用,分割)/id数组/id二维数组(多级复选框) + */ + DTree.prototype.chooseDataInit = function(chooseIds){ + var _this = this; + // 多级复选框二维数组 + var chooseIdArrs = []; + var chooseId = []; + if(typeof chooseIds === "string") { + chooseId = chooseIds.split(","); + } else { + chooseId = chooseIds; + } + if(chooseId.length) { + // 说明是数组 + for (var i=0; i."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + if (flag == 0) { + //把父级去掉选中 + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($item_i).noCheck(); + } + } + } else { + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + //把父级选中 + _this.checkStatus($item_i).check(); + } + } + }; + + /** + * @Desc: 实现复选框点击, no-all 子集选中父级半选中,子集全选父级选中 + * @Param: $i: JQuery对象,表示当前点击的checkbox节点 + */ + DTree.prototype.checkAllOrNoallOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag == 0) { + //把父级去掉选中 + _this.checkStatus($item_i).noCheck(); + } else { + //把父级半选 + _this.checkStatus($item_i).noallCheck(); + } + } + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag1 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var flag2 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag1 != flag2) { + // 父级复选框半选 + _this.checkStatus($item_i).noallCheck(); + } else { + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + }; + + /** + * @Desc: 实现复选框点击,p-casc:父级选中子集全选,子集无法改变父级选中状态 + * @Param: $i: JQuery对象,表示当前点击的checkbox节点 + */ + DTree.prototype.checkAllOrPcascOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).noCheck(); + + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var $item_i = item.eq(i).find(">." + LI_DIV_ITEM + ">." + LI_DIV_CHECKBAR + ">i[data-type='" + dataType + "']"); + //把父级选中 + _this.checkStatus($item_i).check(); + } + // 处理子级节点的选中状态 + var $child_li_i = $child_li.find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + _this.checkStatus($child_li_i).check(); + } + }; + + /** + * @Desc: 实现复选框点击,self:各自选中互不影响 + * @Param: $i: JQuery对象,表示当前点击的checkbox节点 + */ + DTree.prototype.checkOrNot = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + if ($i.attr("data-checked") == "1") { //当前复选框为选中状态,点击后变为未选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).noCheck(); + } else { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + } + }; + + /** + * @Desc: 实现复选框点击,only:只能选中1个复选框 + * @Param: $i: JQuery对象,表示当前点击的checkbox节点 + */ + DTree.prototype.checkOnly = function($i) { + var _this = this; + //$i 当前点击的checkbox + var $div = $i.closest("."+LI_DIV_ITEM), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + var checked = $i.attr("data-checked"); + // 将全部节点全部设为未选中状态 + var $all_i = _this.obj.find("i[data-checked]"); + _this.checkStatus($all_i).noCheck(); + + if (checked != "1") { //当前复选框为未选中状态,点击后变为选中状态 + // 处理当前节点的选中状态 + _this.checkStatus($i).check(); + } + }; + + /** + * @Desc: 实现复选框点击汇总,分派具体的点击方式 + * @Param: $i: JQuery对象,表示当前点击的checkbox节点 + */ + DTree.prototype.changeCheck = function($i) { + var _this = this; + var temp = _this.temp; + if(typeof $i === 'undefined') { + $i = temp[0]; + } + // 复选框选中事件 + if (_this.checkbarType == "all") { + _this.checkAllOrNot($i); + } else if(_this.checkbarType == "no-all") { + _this.checkAllOrNoallOrNot($i); + } else if(_this.checkbarType == "p-casc") { + _this.checkAllOrPcascOrNot($i); + } else if(_this.checkbarType == "self") { + _this.checkOrNot($i); + } else if(_this.checkbarType == "only") { + _this.checkOnly($i); + } else { + _this.checkAllOrNot($i); + } + + if(_this.select) { + // 设置复选框模式中的下拉树的值 + _this.selectCheckboxVal(); + } + + // 获取复选框选中节点的内容 + var checkbarNodes = _this.setAndGetCheckbarNodesParam(true); + + // 用户自定义想做的事情 + _this.checkbarFun.chooseDone(checkbarNodes); + layui.event.call(this, MOD_NAME, "chooseDone("+$(_this.obj)[0].id+")", {"checkbarParams": checkbarNodes}); + _this.temp = []; + }; + + /** + * @Desc: 复选框半选状态初始化设置,树节点渲染完毕后重置半选状态 + */ + DTree.prototype.initNoAllCheck = function(){ + var _this = this; + //1.获取所有选中节点 + var $is = _this.obj.find("i[data-checked='1']"); + if($is.length > 0){ + for ( var key = 0; key < $is.length; key++) { + var $i = $($is[key]), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var flag1 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"'][data-checked='1']").length; + var flag2 = item.eq(i).find(">."+LI_NAV_CHILD+" ."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']").length; + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + if (flag1 != flag2) { + // 父级复选框半选 + _this.checkStatus($item_i).noallCheck(); + } else { + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + } + }; + + /** + * @Desc: 复选框选中状态初始化设置,树节点渲染完毕后重置选中状态 + */ + DTree.prototype.initAllCheck = function(){ + var _this = this; + //1.获取所有选中节点 + var $is = _this.obj.find("i[data-checked='1']"); + if($is.length > 0){ + for ( var key = 0; key < $is.length; key++) { + var $i = $($is[key]), + dataPar = $i.attr("data-par"), + dataType = $i.attr("data-type"), + $li = $i.closest(dataPar), //当前checkbox的上级li节点 + $parent_li = $i.parents(dataPar), //当前checkbox的所有父级li节点 + $child_li = $li.find(dataPar); //当前checkbox的上级li节点下的所有子级li节点 + + // 处理父级节点的选中状态 + for (var i = 1, item = $parent_li; i < item.length; i++) { + var $item_i = item.eq(i).find(">."+LI_DIV_ITEM+">."+LI_DIV_CHECKBAR+">i[data-type='"+dataType+"']"); + // 父级复选框全选 + _this.checkStatus($item_i).check(); + } + } + } + }; + + /** + * @Desc: 设置复选框选中/未选中/半选 _this.checkStatus($i).check(); _this.checkStatus($i).noCheck(); _this.checkStatus($i).noallCheck(); + * @Param: $i: JQuery对象,表示当前点击的checkbox节点 + */ + DTree.prototype.checkStatus = function($i) { + var _this = this; + return { + check: function(){ + $i.removeClass(_this.usefontStyle.checkbox.out); + $i.removeClass(_this.usefontStyle.checkbox.noall); + $i.addClass(_this.usefontStyle.checkbox.on); + $i.addClass(_this.style.chs); + $i.attr("data-checked","1"); + }, + noCheck: function(){ + $i.removeClass(_this.usefontStyle.checkbox.noall); + $i.removeClass(_this.usefontStyle.checkbox.on); + $i.removeClass(_this.style.chs); + $i.addClass(_this.usefontStyle.checkbox.out); + $i.attr("data-checked","0"); + }, + noallCheck: function(){ + $i.removeClass(_this.usefontStyle.checkbox.out); + $i.removeClass(_this.usefontStyle.checkbox.on); + $i.addClass(_this.usefontStyle.checkbox.noall); + $i.addClass(_this.style.chs); + $i.attr("data-checked","2"); + } + } + }; + + /** + * @Desc: 设置树的复选框操作值的全部参数,并获取 + * @Param: requestParamFlag: 设置复选框返回值的数据结构, true:基于请求类型的返回对象数组, false:原始的节点返回对象数组 + */ + DTree.prototype.setAndGetCheckbarNodesParam = function(requestParamFlag) { + var _this = this; + //操作前先清空 + _this.checkbarNode = []; + // 选择所有复选框节点 + if (_this.checkbarData == "change"){ //记录变更数据 + _this.obj.find("i[data-par][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if ($i.attr("data-checked") != $i.attr("data-initchecked")) { + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + } + }); + } else if (_this.checkbarData == "all"){ //记录全部数据 + _this.obj.find("i[data-par][data-checked][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } else if (_this.checkbarData == "choose"){ //记录选中数据 + _this.obj.find("i[data-par][data-checked='1'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } else if (_this.checkbarData == "halfChoose"){ //记录选中和半选数据 + _this.obj.find("i[data-par][data-checked='1'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + _this.obj.find("i[data-par][data-checked='2'][dtree-disabled='false']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + if(requestParamFlag) { + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + } else { + _this.checkbarNode.push(_this.getCheckbarNodeParam($div, $i)); + } + }); + } + return _this.checkbarNode; + }; + + /** + * @Desc: 获取树的复选框操作值的全部参数 + */ + DTree.prototype.getCheckbarNodesParam = function() { + var _this = this; + return _this.setAndGetCheckbarNodesParam(true); + }; + + /** + * @Desc: 获取树的一个复选框的参数 + * @Param: $div: JQuery对象,表示当前选中节点 + * @Param: $i: JQuery对象,表示当前选中的复选框节点 + */ + DTree.prototype.getCheckbarNodeParam = function($div, $i){ + var _this = this; + var temp_node = {}; + temp_node.nodeId = $div.attr("data-id"); + temp_node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + temp_node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + temp_node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + temp_node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + temp_node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + temp_node.basicData = basicData; + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + temp_node.recordData = recordData; + + temp_node.dataType = $i.attr("data-type"); + temp_node.checked = $i.attr("data-checked"); + temp_node.initchecked = $i.attr("data-initchecked"); + return temp_node; + }; + + /** + * @Desc: 获取基于返回参数的树的复选框参数,选中数据横向存储 + */ + DTree.prototype.getCheckbarJsonArrParam = function(){ + var _this = this; + var checkbarJsonArr = { + nodeId: [], //节点ID + parentId: [], //父节点ID + context: [], //节点内容 + leaf: [], //是否叶子节点 + level: [], //层级 + spread: [], //节点展开状态 + dataType: [], //节点标记 + checked: [], //节点复选框选中状态 + initchecked: [], //节点复选框初始状态 + basicData: [], //用户自定义的记录节点数据 + recordData: [], //当前data数据(排除basicData和children字段) + }; + // 获取全部复选框选中节点 + var params = _this.setAndGetCheckbarNodesParam(false); + if(params && params.length > 0) { + for(var i=0; i 0) { _this.checkStatus($i).check(); } + } + + /** + * @Desc: 取消全部复选框选中 + */ + DTree.prototype.cancelCheckedNode = function(){ + var _this = this; + var $i = _this.obj.find("i[data-par][data-checked!='0']"); + if($i.length > 0) { _this.checkStatus($i).noCheck(); } + } + + /** + * @Desc: 反选复选框 + */ + DTree.prototype.invertCheckedNode = function(){ + var _this = this; + if(_this.obj.find("i[data-par]").length > 0) { + var flag = false; + _this.obj.find("i[data-par]").each(function(){ + var $i = $(this); + if($i.attr("data-checked") == '2'){ + flag = true; + }else if($i.attr("data-checked") == '0') { + _this.checkStatus($i).check(); + }else if($i.attr("data-checked") == '1') { + _this.checkStatus($i).noCheck(); + } + }); + + if(flag) { + _this.initNoAllCheck(); + } else { + _this.initAllCheck(); + } + } + } + + /** + * @Desc: 删除选中节点 + */ + DTree.prototype.removeCheckedNode = function(){ + var _this = this; + var len = _this.obj.find("i[data-par][data-checked='1']").length; + if(len == 0){ + layer.msg("请至少选中一个节点",{icon:2}); + }else{ + //操作前先清空 + _this.checkbarNode = []; + // 选择所有复选框节点 + var i_node = {}; + _this.obj.find("i[data-par][data-checked='1']").each(function(){ + var $i = $(this), $div = $i.closest("."+LI_DIV_ITEM); + + _this.checkbarNode.push(_this.getRequestParam(_this.getCheckbarNodeParam($div, $i))); + }); + + layer.confirm('确定要删除选中节点?', {icon: 3, title:'删除选中节点'}, function(index1){ + var flag = _this.menubarFun.remove(_this.checkbarNode); + if(flag){ + _this.obj.find("i[data-par][data-checked='1']").closest("."+LI_DIV_ITEM).next("ul").remove(); + _this.obj.find("i[data-par][data-checked='1']").closest("."+LI_DIV_ITEM).remove(); + _this.checkbarNode=[]; + } + + layer.close(index1); + }); + } + } + + /******************** 工具栏及菜单栏区域 ********************/ + /** + * @Desc: 初始化菜单栏和工具栏的div + */ + DTree.prototype.initTreePlus = function(){ + var _this = this; + // 初始化菜单栏和工具栏的div + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).remove(); + _this.toolbarMenu = {}; + if(_this.menubar && _this.menubarTips.group && _this.menubarTips.group.length > 0) _this.obj.before("
                "); + if(_this.toolbar){ + if(_this.toolbarWay == "contextmenu") { + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).remove(); + if(_this.toolbarShow && _this.toolbarShow.length > 0) { + _this.obj.before("
                "); + } + } + } + + }; + + /** + * @Desc: 开启工具栏和菜单栏 + */ + DTree.prototype.openTreePlus = function(){ + var _this = this; + // 先对工具栏做处理,因为菜单栏可能会与工具栏产生关联。 + var ggMenu = []; + if(_this.toolbar) _this.getToolbarDom(); + + if(_this.menubar) { + var menubarTips = _this.menubarTips, + mtbar = menubarTips.toolbar, + group = menubarTips.group, + freedom = menubarTips.freedom; + if(mtbar && mtbar.length > 0){ + // 菜单栏吸附工具栏上 + for(var i=0; i 0){ + // 菜单栏吸附在上方的按钮组div中 + for(var i=0; i"; + break; + case defaultMenu.moveUp: + gg = ""; + break; + case defaultMenu.refresh: + gg = ""; + break; + case defaultMenu.checkAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.unCheckAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.invertAll: + gg = (_this.checkbar && _this.checkbarType != 'only') ? "" : ""; + break; + case defaultMenu.remove: + gg = (_this.checkbar) ? "" : ""; + break; + case defaultMenu.searchNode: + gg = ""; + break; + } + return gg; + }; + + /** + * @Desc: 获取扩展菜单栏 + * @Param: menu: 扩展菜单栏的Json对象 + */ + DTree.prototype.getExtMenubarDom = function(menu){ + var _this = this; + return ""; + }; + + /** + * @Desc: 获取依附在工具栏的菜单栏 + * @Param: menu: 菜单栏的具体操作字符串 + */ + DTree.prototype.getMenubarToolDom = function(menu){ + var _this = this; + var rootId = _this.obj[0].id; + switch (menu) { + case defaultMenu.moveDown: + _this.toolbarMenu[defaultMenu.moveDown] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.moveDown, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.movedown, "展开全部"); + break; + case defaultMenu.moveUp: + _this.toolbarMenu[defaultMenu.moveUp] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.moveUp, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.moveup, "收缩全部"); + break; + case defaultMenu.refresh: + _this.toolbarMenu[defaultMenu.refresh] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.refresh, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.refresh, "刷新"); + break; + case defaultMenu.checkAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.checkAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.checkAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.checkAll, "全选节点"); + break; + case defaultMenu.unCheckAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.unCheckAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.unCheckAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.unCheckAll, "全不选节点"); + break; + case defaultMenu.invertAll: + if(_this.checkbar && _this.checkbarType != 'only') + _this.toolbarMenu[defaultMenu.invertAll] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.invertAll, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.invertAll, "反选节点"); + break; + case defaultMenu.remove: + if(_this.checkbar) + _this.toolbarMenu[defaultMenu.remove] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.remove, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.remove, "删除选中"); + break; + case defaultMenu.searchNode: + _this.toolbarMenu[defaultMenu.searchNode] = _this.setToolbarDom().setMenuToolbarOption(defaultMenu.searchNode, _this.toolbarStyle.title, _this.usefontStyle.toolbar.menubar.searchNode, "查询"); + break; + } + }; + + /** + * @Desc: 获取依附在工具栏的扩展菜单栏 + * @Param: menu: 扩展菜单栏的Json对象 + */ + DTree.prototype.getExtMenubarToolDom = function(menu){ + var _this = this; + _this.toolbarMenu[menu.menubarId] = _this.setToolbarDom().setMenuToolbarOption(menu.menubarId, menu.title, _this.usefontStyle.toolbar.menubarExt+" "+menu.icon, ""); + }; + + /** + * @Desc: menubar内置方法 + */ + DTree.prototype.menubarMethod = function(){ + var _this = this; + return { + openAllNode: function(obj){ // 展开所有节点 + var $ulNode = obj || _this.obj.children("li").children("ul"); + // 遍历所有ul子节点 + for (var i = 0; i < $ulNode.length; i++) { + // 获取当前节点的信息 + var $ul = $($ulNode[i]), + $div = $ul.prev("div"), + $i_fnode = _this.getNodeDom($div).fnode(), + $i_snode = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_fnode.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + if (leaf == "leaf") { + continue; + } // 说明是叶子了,则继续循环下一个 + + if (spread == "open") { + // 说明该节点已经展开了,则进行子节点循环 + } else { + if (_this.type=="load") { //是否全量加载 + if (_this.cache) { //是否开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + } else { //加载节点 + _this.getChild($div); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + } + _this.operateIcon($i_fnode, $i_snode).open(); + + } + var $childUl = $ul.children("li").children("ul"); + _this.menubarMethod().openAllNode($childUl); + } + }, + closeAllNode: function(){ //收缩所有节点 + _this.obj.find("."+LI_NAV_CHILD).each(function(){ + // 获取当前节点的信息 + var $ul = $(this), + $div = $ul.prev("div"), + $i_fnode = _this.getNodeDom($div).fnode(), + $i_snode = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_fnode.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + $ul.removeClass(NAV_SHOW); + if(leaf !== "leaf") { + _this.operateIcon($i_fnode, $i_snode).close(); + } + }); + }, + refreshTree: function(){// 刷新树 + _this.refreshTree(); + }, + checkAll: function(){ // 全选节点 + _this.checkAllNode(); + }, + unCheckAll: function(){ // 全不选节点 + _this.cancelCheckedNode(); + }, + invertAll: function(){ // 反选节点 + _this.invertCheckedNode(); + }, + remove: function(){// 删除选中节点 + _this.removeCheckedNode(); + }, + searchNode: function(){//模糊查询该值,展开该值节点 + layer.prompt({ + formType: 0, + value: "", + title: '查询节点' + }, function(value, index1, elem){ + if (value) { + var flag = _this.searchNode(value); + if (!flag) { + layer.msg("该名称节点不存在!", {icon:5}); + } + } else { + layer.msg("未指定查询节点名称", {icon:5}); + } + layer.close(index1); + }); + }, + extMethod: function(menuId, $div, flag){ + if(_this.menubar && _this.menubarTips.group && _this.menubarTips.group.length > 0 && flag == "group"){ + for(var i=0; i<_this.menubarTips.group.length; i++){ + var ext = _this.menubarTips.group[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + if(_this.menubar && _this.menubarTips.toolbar && _this.menubarTips.toolbar.length > 0 && flag == "toolbar"){ + for(var i=0; i<_this.menubarTips.toolbar.length; i++){ + var ext = _this.menubarTips.toolbar[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + if(_this.menubar && _this.menubarTips.freedom && _this.menubarTips.freedom.length > 0 && flag == "freedom"){ + for(var i=0; i<_this.menubarTips.freedom.length; i++){ + var ext = _this.menubarTips.freedom[i]; + if (menuId == ext.menubarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div), $div)); + break; + } + } + } + } + }; + }; + + /** + * @Desc: menubar监听方法 + * @Param: menuId:菜单栏的具体操作字符串 + * @Param: flag:菜单栏的显示方式 + */ + DTree.prototype.menubarListener = function(menuId, flag){ + var _this = this; + var $div = _this.getNodeDom().nowDiv(); + switch (menuId) { + case defaultMenu.moveDown: // 展开全部节点 + _this.menubarMethod().openAllNode(); + break; + case defaultMenu.moveUp: // 收缩全部节点 + _this.menubarMethod().closeAllNode(); + break; + case defaultMenu.refresh: + _this.menubarMethod().refreshTree(); // 刷新树 + break; + case defaultMenu.checkAll: + _this.menubarMethod().checkAll(); + break; + case defaultMenu.unCheckAll: + _this.menubarMethod().unCheckAll(); + break; + case defaultMenu.invertAll: + _this.menubarMethod().invertAll(); + break; + case defaultMenu.remove: + _this.menubarMethod().remove(); + break; + case defaultMenu.searchNode: + _this.menubarMethod().searchNode(); + break; + default: + _this.menubarMethod().extMethod(menuId, $div, flag); + break; + } + }; + + /** + * @Desc: 模糊查询该值,展开该值节点 + * @Param: value: 模糊查询的值 + */ + DTree.prototype.searchNode = function(value){ + var _this = this; + var b = false; + var $lis = []; + _this.obj.find("cite[data-leaf]").each(function(){ + var $nthis = $(this); + var html = $nthis.html(); + if(html.indexOf(value) > -1){ + if($nthis.attr("data-leaf") == "leaf") { + // 叶子节点提供包含父节点的所有信息 + var title = ""; + $nthis.parents("li").each(function(){ + title = "-" + $(this).find("cite[data-leaf]").html() + title; + }); + title = title.substring(1, title.length); + $nthis.attr("title", title); + } + // 保存当前cite所在的li及父li中包含该值,则只保留父的 + var i = 0; + $nthis.parents("li").each(function(){ + var html2 = $(this).find("cite[data-leaf]").html(); + if(html2.indexOf(value) > -1){ + i++; + } + if(i >= 2){ + return true; + } + }); + if (i < 2){ + $lis.push($nthis.closest("li").prop("outerHTML")); + } + } + }); + if($lis.length > 0) { + b = true; + // 1.将树节点清空 + _this.obj.html(""); + // 2.遍历所有cite节点,展开当前cite节点 + for(var i=0; i<$lis.length; i++){ + _this.obj.append($lis[i]); + } + } + return b; + }; + + + /******************** 工具栏区域 ********************/ + /** + * @Desc: 获取工具栏 + */ + DTree.prototype.getToolbarDom = function(){ + var _this = this; + var toolbarShow = _this.toolbarShow, + toolbarExt = _this.toolbarExt, + toolbarWay = _this.toolbarWay; + + if(toolbarShow.length > 0){ + for(var i=0; i 0){ + for(var i=0; i "+other +title+""; + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + return ""; + } + }, + setMenuToolbarOption: function(menubarId, title, classId, other){ + var rootId = _this.obj[0].id; + if(toolbarWay == "contextmenu") { + return "
                 "+other +title+"
                "; + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + return ""; + } + }, + setToolbarPlace: function(toolbarMenu){ + if(toolbarWay == "contextmenu") { + if(toolbarMenu){ + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).find('div.layui-nav-item>dl.layui-nav-child').html(""); + for(var key in toolbarMenu){ + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).find('div.layui-nav-item>dl.layui-nav-child').append(toolbarMenu[key]); + } + } + } else if(toolbarWay == "fixed" || toolbarWay == "follow") { + _this.obj.find("cite[data-leaf][dtree-disabled='false']").each(function(){ + var $cite = $(this); + _this.dynamicToolbarDom($cite); + }); + } + } + } + }; + + /** + * @Desc: 在节点后动态绑定fixed和follow条件的工具栏 + * @Param: $cite: JQuery对象,表示当前文本节点 + */ + DTree.prototype.dynamicToolbarDom = function($cite){ + var _this = this; + var toolbarWay = _this.toolbarWay; + if($cite.next("em."+TOOLBAR_TOOL_EM).length == 0) { + var $div = $cite.parent("div"); + var param = _this.getRequestParam(_this.getTempNodeParam($div)); + var toolbarMenus = _this.toolbarFun.loadToolbarBefore(event.cloneObj(_this.toolbarMenu), param, $div); + var hideCls = (toolbarWay == "follow") ? NAV_HIDE : ""; + var em = [""]; + if(toolbarMenus){ + for(var key in toolbarMenus){ + em.push(toolbarMenus[key]); + } + } + em.push(""); + $cite.after(em.join('')); + } + } + + /** + * @Desc: 隐藏toolbar + */ + DTree.prototype.toolbarHide = function() { + var _this = this; + if(_this.toolbar && _this.toolbarWay == "contextmenu") { + var $toolBarDiv = _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id); + $toolBarDiv.find(".layui-nav-child").removeClass('layui-anim-fadein layui-show'); + } + } + + /** + * @Desc: toolbar内置方法 + */ + DTree.prototype.toolbarMethod = function(){ + var _this = this; + return { + pulldown: function(obj){ // 展开当前点击节点的下面全部节点 + if(!obj) return; + var $ulNode = obj; + // 遍历所有ul子节点 + for (var i = 0; i < $ulNode.length; i++) { + // 获取当前节点的信息 + var $ul = $($ulNode[i]), + $div = $ul.prev("div"), + $i_fnode = _this.getNodeDom($div).fnode(), + $i_snode = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_fnode.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + if (leaf == "leaf") { continue; } // 说明是叶子了,则继续循环下一个 + + if (spread == "open") { + // 说明该节点已经展开了,则进行子节点循环 + } else { + if (_this.type=="load") { //是否全量加载 + if (_this.cache) { //是否开启缓存 + if ($ul.html()) { + $ul.addClass(NAV_SHOW); + } else { //加载节点 + _this.getChild($div); + } + }else { //每次取新的数据 + $ul.html(""); + _this.getChild($div); + } + } else { // 全量加载 + $ul.addClass(NAV_SHOW); + } + _this.operateIcon($i_fnode, $i_snode).open(); + + } + var $childUl = $ul.children("li").children("ul"); + _this.toolbarMethod().pulldown($childUl); + } + }, + pullup: function($li){ // 收缩当前点击节点的下面全部节点 + $li.find("."+LI_NAV_CHILD).each(function(){ + // 获取当前节点的信息 + var $ul = $(this), + $div = $ul.prev("div"), + $i_fnode = _this.getNodeDom($div).fnode(), + $i_snode = _this.getNodeDom($div).snode(), + $cite = _this.getNodeDom($div).cite(), + spread = $i_fnode.attr("data-spread"), + leaf = $cite.attr("data-leaf"); + + $ul.removeClass(NAV_SHOW); + if(leaf !== "leaf") { + _this.operateIcon($i_fnode, $i_snode).close(); + } + }); + } + } + }; + + /** + * @Desc: toolbar监听方法 + * @Param: tool: 工具栏的具体操作字符串 + * @Param: $div: JQuery对象,表示当前操作节点 + */ + DTree.prototype.toolbarListener = function(tool, $div) { + var _this = this; + var $cite = $div.children("cite[data-leaf]"), + $ul = $div.next("ul"), + $p_li = $div.parent("li[data-index]"), //当前选中节点的顶级li节点 + $p_ul = $p_li.parent("ul"), //当前选中节点的顶级li节点的父级ul + $p_div = $p_ul.prev("div"), //当前选中节点的顶级li节点的父级ul的前一个div + title = (typeof _this.formatter.title === 'function') ? $cite.attr("data-title") : $cite.text(); + + switch (tool) { + case defaultTool.pulldown: + _this.toolbarMethod().pulldown($ul); + break; + case defaultTool.pullup: + _this.toolbarMethod().pullup($p_li); + break; + case defaultTool.addTool: + var content = _this.loadToolBar(title, defaultTool.addTool); + + layer.open({ + title: "新增"+_this.toolbarStyle.title, + type: 1, + area: _this.toolbarStyle.area, + content: content, + success: function(layero, index){ + form.render(); + form.on("submit(dtree_addNode_" + _this.obj[0].id + "_form)",function(data){ + var data = data.field; + var parentId = $div.attr("data-id"), + id = $div.attr("data-id")+"_node_"+$ul[0].childNodes.length, + leaf = true, + checked = "0", + level = parseInt($p_li.attr("data-index"))+1; + + var type = _this.response.type; + var checked = _this.response.checked; + // 创建子节点的DOM,添加子节点 + var checkArr = []; + if (_this.checkArrLen > 0) { + for (var i = 0; i < _this.checkArrLen; i++) { + checkArr.push({type: i, checked: "0"}); + } + } + + $ul.append(_this.getLiItemDom(id, parentId, data.addNodeName, data.addNodeName, true, "", "", checkArr, level, false, false, false, "", "", "item")); + // 先将li节点隐藏 + $ul.find("li[data-id='"+id+"']").hide(); + // 重新赋值 + var $addDiv = $ul.find("div[data-id='"+id+"']"); + node = _this.getNodeParam($addDiv); + + //获取组装后的requestNode,组合参数 + var requestNode = _this.getRequestParam(node); + requestNode = $.extend(requestNode, data); + + _this.temp = [id, $ul, $div, level]; + // 用户自定义想做的事情 + _this.toolbarFun.addTreeNode(requestNode, $div); + + layer.close(index); + return false; + }); + } + }); + break; + case defaultTool.editTool: + var content = _this.loadToolBar(title, defaultTool.editTool); + + layer.open({ + title: "编辑"+_this.toolbarStyle.title, + type: 1, + area: _this.toolbarStyle.area, + content: content, + success: function(layero, index){ + _this.toolbarFun.editTreeLoad(_this.getRequestParam(_this.getNodeParam($div))); + form.render(); + form.on("submit(dtree_editNode_" + _this.obj[0].id + "_form)",function(data){ + var data = data.field; + $cite.html(data.editNodeName); + node = _this.getNodeParam($div); + var requestNode = _this.getRequestParam(node); + requestNode = $.extend(requestNode, data); + _this.temp = [$cite, $div, title, $p_div]; + _this.toolbarFun.editTreeNode(requestNode, $div); + + layer.close(index); + }); + } + }); + break; + case defaultTool.delTool: + layer.confirm('确定要删除该'+_this.toolbarStyle.title+'?', {icon: 3, title:'删除'+_this.toolbarStyle.title}, function(index){ + var node = _this.getNodeParam($div); + _this.temp = [$p_li, $p_div]; + _this.toolbarFun.delTreeNode(_this.getRequestParam(_this.getNodeParam($div)), $div); + + layer.close(index); + }); + break; + default: + if(_this.toolbarExt.length > 0){ + for(var i=0; i<_this.toolbarExt.length; i++){ + var ext = _this.toolbarExt[i]; + if (tool == ext.toolbarId){ + ext.handler(_this.getRequestParam(_this.getNodeParam($div)), $div); + break; + } + } + } + break; + } + } + + + /** + * @Desc: 加载toolbar中的内容 + * @Param: title: 默认操作中的input输入框的值 + * @Param: name: 工具栏的具体操作字符串 + */ + DTree.prototype.loadToolBar = function(title, name){ + var _this = this; + var toolbarShow = _this.toolbarShow; + var nodeBarContents = _this.toolbarBtn; + + var html = ""; + switch (name) { + case defaultTool.addTool: + var addNodeBarDef = [{"label": "当前选中", "name": "nodeTitle", "type": "text", "value": title, "defElem": "nowChoose", "readonly": true}, + {"label": "新增"+_this.toolbarStyle.title, "name": "addNodeName", "type": "text", "value": "", "defElem": "nowChange", "verify": "required"}, + {"type": "submit", "value": "确认添加", "defElem": "btn", "filter": "dtree_addNode_" + _this.obj[0].id + "_form"}]; + + //2. 用户自定义的节点内容 + var addNodeBar = ['
                ']; + + if(nodeBarContents != null && nodeBarContents.length > 0){ + if(nodeBarContents[0] != null && nodeBarContents[0] != undefined && nodeBarContents[0].length > 0){ + var addNodeBarContents = nodeBarContents[0]; + // 1. 检查是否包含了now、newly、btn这三个默认项,将其他元素依次排列,将特殊元素至于栈顶 + for(var i=0; i', '
                ']; + // 3.遍历生成按钮 + for(var j=0; j
                '); + addNodeBar.push(addBtn.join('')); + addNodeBar.push('
                '); + html = addNodeBar.join(''); + break; + + case defaultTool.editTool: + var editNodeBarDef = [{"label": "当前选中", "name": "nodeTitle", "type": "text", "value": title, "defElem": "nowChoose", "readonly": true}, + {"label": "编辑"+_this.toolbarStyle.title, "name": "editNodeName", "type": "text", "value": "", "defElem": "nowChange", "verify": "required"}, + {"type": "submit", "value": "确认编辑", "defElem": "btn", "filter": "dtree_editNode_" + _this.obj[0].id + "_form"}]; + + var editNodeBar = ['
                ']; + //2. 用户自定义的节点内容 + if(nodeBarContents != null && nodeBarContents.length > 0){ + + if(nodeBarContents[1] != null && nodeBarContents[1] != undefined && nodeBarContents[1].length > 0){ + var editNodeBarContents = nodeBarContents[1]; + // 1. 检查是否包含了now、newly、btn这三个默认项,将其他元素依次排列,将特殊元素至于栈顶 + for(var i=0; i', '
                ']; + // 3.遍历生成按钮 + for(var j=0; j
                '); + editNodeBar.push(editBtn.join('')); + editNodeBar.push('
                '); + html = editNodeBar.join(''); + break; + } + return html; + }; + + /** + * @Desc: 获取toolbar详细的标签信息 + * @Param: nodeBarContents: 工具栏中的数据渲染内容JSON对象 + */ + DTree.prototype.loadToolBarDetail = function(nodeBarContents){ + var _this = this; + var readonly = (typeof (nodeBarContents.readonly) === "boolean") ? nodeBarContents.readonly : false; + var disabled = (typeof (nodeBarContents.disabled) === "boolean") ? nodeBarContents.disabled : false; + var id = nodeBarContents.id ? nodeBarContents.id : ""; + var name = nodeBarContents.name ? nodeBarContents.name : ""; + var val = nodeBarContents.value ? nodeBarContents.value : ""; + var verify = nodeBarContents.verify ? nodeBarContents.verify : ""; + var placeholder = nodeBarContents.placeholder ? nodeBarContents.placeholder : val; + return{ + text: function(){ + return ['
                ', + '', + '
                ', + '', + '
                ', + '
                '].join(''); + }, + textarea: function(){ + return ['
                ', + '', + '
                ', + '', + '
                ', + '
                '].join(''); + }, + hidden: function(){ + return [''].join(''); + }, + select: function(){ + var optionsData = (typeof nodeBarContents.optionsData === 'object') ? nodeBarContents.optionsData : nodeBarContents.optionsData(); + var options = ""; + for(var key in optionsData){ + if(val == optionsData[key]){ + options += ""; + } else { + options += ""; + } + } + return ['
                ', + '', + '
                ', + '', '
                ', '
                '].join(''); + }, + submit: function(){ + var filter = nodeBarContents.filter; + return [''].join(''); + }, + button: function(){ + return [''].join(''); + }, + reset: function(){ + return [''].join(''); + } + } + }; + + /** + * @Desc: 新增节点后改变节点内容 + * @Param: returnID: 当前需要加载的内容,JSON对象、字符串、指定字符串("refresh")、true + */ + DTree.prototype.changeTreeNodeAdd = function(returnID){ + var _this = this; + var temp = _this.temp; + var id = temp[0], $ul = temp[1], $div = temp[2], level = temp[3]; + var flag = false; + if(returnID){ + var $thisDiv = _this.obj.find("[data-id='"+id+"']"); + if(typeof returnID === "object"){ + // 如果是JSON格式数据,则将当前DIV删除,重新建造DIV + $thisDiv.remove(); + var parseData = _this.parseData(returnID); + + if(parseData.treeId()){ + $ul.append(_this.getLiItemDom(parseData.treeId(), parseData.parentId(), parseData.title(), parseData.fmtTitle(), parseData.last(0), parseData.ficonClass(), parseData.iconClass(), parseData.checkArr(), level, parseData.spread(), parseData.disabled(), parseData.hide(), parseData.basicData(), parseData.recordData(), "item")); + + // 建造完毕后,选中该DIV + $thisDiv = $ul.find("div[data-id='"+parseData.treeId()+"']"); + _this.setNodeParam($thisDiv) + } else { + layer.msg("添加失败,节点ID为undefined!",{icon:5}); + // 将li节点删除 + $ul.find("li[data-id='"+id+"']").remove(); + // 重新赋值 + _this.setNodeParam($div); + // 临时变量制空 + _this.temp = []; + return ; + } + }else if(returnID == 'refresh' || returnID == true){ + // 如果是设置为refresh参数,则向后台发送请求,获取新增节点下的真实参数,局部刷新树。 + flag = true; + } else if(typeof returnID === "string" || typeof returnID === 'number'){ + $thisDiv.attr("data-id", returnID); + // 将li节点展示 + $ul.find("li[data-id='"+returnID+"']").show(); + _this.setNodeParam($thisDiv) + } + + // 判断当前点击的节点是否是最后一级节点,如果是,则需要修改节点的样式 + var $icon_i = $div.find("i[data-spread]"); + if ($icon_i.eq(0).attr("data-spread") == "last") { + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).openWithLeaf(); + } else { //如果不是,也要修改节点样式 + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).open(); + } + $ul.addClass(NAV_SHOW); //展开UL + _this.accordionUL($ul); + if(flag) { + _this.getChild($div); + } else { + // _this.showLine(); + _this.showLine($ul.find("li")); + // 这种情况下需要在新增节点后对节点新增工具栏 + if(_this.toolbar && _this.toolbarWay != 'contextmenu') { + _this.dynamicToolbarDom($thisDiv.find("cite[data-leaf]")); + } + } + + } else { + // 将li节点删除 + $ul.find("li[data-id='"+id+"']").remove(); + // 重新赋值 + _this.setNodeParam($div); + } + + _this.temp = []; // 临时变量制空 + + }; + + /** + * @Desc: 编辑页打开后显示编辑页内容 + * @Param: param: 编辑页打开之后回显的数据集 + */ + DTree.prototype.changeTreeNodeDone = function(param){ + var _this = this; + form.val('dtree_editNode_' + _this.obj[0].id + '_form', param); + form.render(); + }; + + /** + * @Desc: 修改节点后改变节点内容 + * @Param: returnID: 当前需要变更的内容,JSON对象 + */ + DTree.prototype.changeTreeNodeEdit = function(returnID){ + var _this = this; + var temp = _this.temp; + var $cite = temp[0], $div = temp[1], title = temp[2], $p_div = temp[3]; + var flag = false; + if(returnID){ + if(typeof returnID === "object"){ + var parseData = _this.parseData(data); + + if(parseData.treeId()){ + var replaceDom = _this.replaceDom($div, parseData.treeId(), parseData.last(0), parseData.spread(), parseData.disabled(), parseData.hide()); + replaceDom.node(parseData.iconClass()); + replaceDom.checkbox(parseData.checkArr()); + replaceDom.text(parseData.title()); + replaceDom.ul(); + replaceDom.basicData(parseData.basicData()); + replaceDom.recordData(parseData.recordData()); + _this.setNodeParam($div); + } else { + layer.msg("编辑失败,节点ID为undefined!",{icon:5}); + // 重新赋值 + _this.setNodeParam($div); + } + } + } else { + $cite.html(title); + _this.getNodeParam($div); + } + + _this.temp = []; // 临时变量制空 + }; + + /** + * @Desc: 删除节点后改变节点内容 + * @Param: flag: 是否要删除节点 + */ + DTree.prototype.changeTreeNodeDel = function(flag){ + var _this = this; + var temp = _this.temp; + var $p_li = temp[0], + $p_ul = $p_li.parent("ul"), + $p_div = temp[1]; + + if(flag){ + $p_li.remove(); + _this.showLine($p_ul.find("li")); + // 判断父级ul中是否还存在li,如果不存在,则需要修改节点的样式 + if($p_ul.children("li").length == 0){ + var $icon_i = $p_div.find("i[data-spread]"); + _this.operateIcon($icon_i.eq(0), $icon_i.eq(1)).closeWithLeaf(); + } + _this.initNodeParam(); + } + + _this.temp = []; // 临时变量制空 + }; + + /******************** iframe区域 ********************/ + /** + * @Desc: 加载iframe + * @Param: $div: JQuery对象,表示当前节点 + * @Param: iframeParam: iframe加载的参数 + */ + DTree.prototype.loadIframe = function($div, iframeParam) { + var _this = this; + var $cite = _this.getNodeDom($div).cite(); + if (!_this.useIframe) { // 启用iframe + return false; + } + var iframeElem = _this.iframeElem, + iframeUrl = _this.iframeUrl, + iframeLoad = _this.iframeLoad; + + var flag = iframeLoad == "leaf" ? (($cite.attr("data-leaf") == "leaf") ? true : false) : true; + + if (flag) { + if ($(iframeElem).length > 0) { //iframe存在 + if (!iframeUrl) { + layer.msg("数据请求异常,iframeUrl参数未指定", {icon:5}); + return false; + } + var param = AjaxHelper.serialize("?", iframeParam); + if(iframeUrl.indexOf("?")> -1){ + param = "&"+param.substring(1, param.length); + } + var url = iframeUrl + param; + $(iframeElem).attr("src", url); + } else { + layer.msg("iframe绑定异常,请确认页面中是否有iframe页对应的容器", {icon:5}); + return false; + } + } + return flag; + }; + + /** + * @Desc: 获取传递出去的参数,根据iframe.iframeDefaultRequest、iframe.iframeRequest和node拼出发出请求的参数 + * @Param: nodes: 需要传递出去的参数 + */ + DTree.prototype.getIframeRequestParam = function(nodes){ + var _this = this; + var request = _this.iframeRequest, + defaultRequestNames = _this.iframeDefaultRequest, + node = nodes || _this.node, + requestParam = {}; + + // 先拼用户自定义的,在拼树生成的,这样的话用户可以自定义当树未生成时的节点的初始值 + for ( var key in request) { + requestParam[key] = request[key]; + } + for ( var key in defaultRequestNames) { + var paramName = defaultRequestNames[key]; + var paramValue = node[key]; + if(typeof paramValue === "boolean"){ + requestParam[paramName] = paramValue; + }else { + if(paramValue){ + requestParam[paramName] = paramValue; + } + } + } + + // 解决传递中文的乱码问题 + var reg = /[\u4E00-\u9FA5\uF900-\uFA2D]/; //正则匹配中文 + for(var key in requestParam){ + if(reg.test(requestParam[key])) { + var str = requestParam[key]; + requestParam[key] = encodeURI(encodeURI(str)); + } + } + + return requestParam; + }; + + /******************** 数据回调区域 ********************/ + /** + * @Desc: 根据具体的id获取基于当前id的div以及对应的其他dom元素 + * @Param: id: 节点的ID值 + */ + DTree.prototype.getNodeDom = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + return { + div: function(){ // 获取当前div + return $div; + }, + fnode: function(){ // 获取一级图标元素 + return ($div == null) ? null : $div.find("i[data-spread]").eq(0); + }, + snode: function(){ // 获取二级图标元素 + return ($div == null) ? null : $div.find("i[data-spread]").eq(1); + }, + checkbox: function(){ // 获取复选框元素 + return ($div == null) ? null : $div.find("i[data-par]"); + }, + cite: function(){ // 获取cite元素 + return ($div == null) ? null : $div.find("cite[data-leaf]"); + }, + nextUl: function(){ // 获取相邻的ul元素 + return ($div == null) ? null : $div.next("ul"); + }, + parentLi: function(){ // 获取父级li元素 + return ($div == null) ? null : $div.parent("li"); + }, + parentUl: function(){ // 获取基于当前$div的上级$ul + return ($div == null) ? null : $div.parent("li").parent("ul"); + }, + parentDiv: function(){ // 获取基于当前$div的上级$div + return ($div == null) ? null : $div.parent("li").parent("ul").prev("div"); + }, + nowDiv: function(){ // 获取当前选中节点,没有则返回null + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS); + }, + nowOrRootDiv: function(){ // 获取当前选中节点,没有则返回根节点下的第一个div + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? _this.obj.children("li").eq(0).children("div").eq(0) : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS); + }, + nowOrRootUl: function(){ // 获取当前选中节点下一个UL 或根节点。为了将新节点放入ul下 + return (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).length == 0) ? _this.obj : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id]").parent().find("."+NAV_THIS).next("ul"); + } + } + }; + + /** + * @Desc: 获取当前选中节点下一个ul节点 或根节点。为了将新节点放入ul下 + */ + DTree.prototype.getNowNodeUl = function() { + var _this = this; + return _this.getNodeDom().nowOrRootUl(); + }; + + /** + * @Desc: 获取当前选中div节点 或第一个根div节点。 + */ + DTree.prototype.getNowNode = function() { + var _this = this; + return _this.getNodeDom().nowOrRootDiv(); + }; + + /** + * @Desc: 获取当前选中div节点 无则返回null。 + */ + DTree.prototype.getNowNodeOrNull = function() { + var _this = this; + return _this.getNodeDom().nowDiv(); + }; + + /** + * @Desc: 根据获取指定div节点。 + * @Param: id: 指定节点的ID + */ + DTree.prototype.getNode = function(id) { + var _this = this; + return _this.getNodeDom(id).div(); + }; + + /** + * @Desc: 设置当前选中节点的全部参数 + * @Param: $div: 当前选中的节点 + */ + DTree.prototype.setNodeParam = function($div) { + var _this = this; + _this.node.nodeId = $div.attr("data-id"); + _this.node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + _this.node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + _this.node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + _this.node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + _this.node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + _this.node.basicData = basicData; + + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + _this.node.recordData = recordData; + + if (_this.getNodeDom($div).checkbox()) { + var dataTypes = "", checkeds = "", initcheckeds = ""; + _this.getNodeDom($div).checkbox().each(function(){ + dataTypes += $(this).attr("data-type") + ","; + checkeds += $(this).attr("data-checked") + ","; + initcheckeds += $(this).attr("data-initchecked") + ","; + }); + dataTypes = dataTypes.substring(0, dataTypes.length-1); + checkeds = checkeds.substring(0, checkeds.length-1); + initcheckeds = initcheckeds.substring(0, initcheckeds.length-1); + + _this.node.dataType = dataTypes; + _this.node.checked = checkeds; + _this.node.initchecked = initcheckeds; + } + }; + + /** + * @Desc: 获取当前选中节点的全部参数 + * @Param: $div: 当前选中的节点 + */ + DTree.prototype.getNodeParam = function($div) { + var _this = this; + if ($div) { + _this.setNodeParam($div); + } else { + if(_this.obj.find("div[data-id]").parent().find("."+NAV_THIS).length == 0){ + _this.initNodeParam(); + } + } + return this.node; + }; + + /** + * @Desc: 获取一个临时的node参数 + * @Param: $div: 当前选中的节点 + */ + DTree.prototype.getTempNodeParam = function($div) { + var _this = this; + var temp_node = {}; + temp_node.nodeId = $div.attr("data-id"); + temp_node.parentId = _this.getNodeDom($div).parentLi().attr("data-pid"); + temp_node.context = (typeof _this.formatter.title === 'function') ? _this.getNodeDom($div).cite().attr("data-title") : _this.getNodeDom($div).cite().text(); + temp_node.leaf = _this.getNodeDom($div).cite().attr("data-leaf") == "leaf" ? true : false; + temp_node.level = _this.getNodeDom($div).parentLi().attr("data-index"); + temp_node.spread = _this.getNodeDom($div).fnode().attr("data-spread") == "open" ? true : false; + + var basicData = $div.attr("data-basic"); + if(basicData) { + basicData = JSON.parse(event.unescape(basicData)); + } + temp_node.basicData = basicData; + var recordData = $div.attr("data-record"); + if(recordData) { + recordData = JSON.parse(event.unescape(recordData)); + } + temp_node.recordData = recordData; + + if (_this.getNodeDom($div).checkbox()) { + var dataTypes = "", checkeds = "", initcheckeds = ""; + _this.getNodeDom($div).checkbox().each(function(){ + dataTypes += $(this).attr("data-type") + ","; + checkeds += $(this).attr("data-checked") + ","; + initcheckeds += $(this).attr("data-initchecked") + ","; + }); + dataTypes = dataTypes.substring(0, dataTypes.length-1); + checkeds = checkeds.substring(0, checkeds.length-1); + initcheckeds = initcheckeds.substring(0, initcheckeds.length-1); + + temp_node.dataType = dataTypes; + temp_node.checked = checkeds; + temp_node.initchecked = initcheckeds; + } + return temp_node; + }; + + /** + * @Desc: 重置内置参数 + */ + DTree.prototype.initNodeParam = function(){ + var _this = this; + _this.node.nodeId = ""; + _this.node.parentId = ""; + _this.node.context = ""; + _this.node.leaf = ""; + _this.node.level = ""; + _this.node.spread = ""; + _this.node.dataType = ""; + _this.node.checked = ""; + _this.node.initchecked = ""; + _this.node.basicData = ""; + _this.node.recordData = ""; + + if(_this.select) { + _this.selectResetVal(); + } + }; + + /** + * @Desc: 获取传递出去的参数,根据defaultRequest、request和node拼出发出请求的参数 + * @Param: nodes:需要传递出去的参数 + */ + DTree.prototype.getRequestParam = function(nodes){ + var _this = this; + var request = _this.request, + defaultRequestNames = _this.defaultRequest, + node = nodes || _this.node, + requestParam = {}; + + // 先拼用户自定义的,在拼树生成的,这样的话用户可以自定义当树未生成时的节点的初始值 + for ( var key in request) { + requestParam[key] = request[key]; + } + for ( var key in defaultRequestNames) { + var paramName = defaultRequestNames[key]; + var paramValue = node[key]; + if(typeof paramValue === "boolean"){ + requestParam[paramName] = paramValue; + }else { + if(paramValue){ + requestParam[paramName] = paramValue; + } + } + + } + return requestParam; + }; + + /** + * @Desc: 获取filterParam过滤后的requestParam + * @Param: requestParam:请求参数 + */ + DTree.prototype.getFilterRequestParam = function(requestParam){ + var _this = this; + var filterRequest = _this.filterRequest; + return event.cloneObj(requestParam, filterRequest); + }; + + /** + * @Desc: 获取当前选中的请求参数 + */ + DTree.prototype.getNowParam = function(){ + var _this = this; + + return _this.getRequestParam(_this.getNodeParam()); + }; + + /** + * @Desc: 根据id获取指定div节点选中参数 + * @Param: id:节点的ID值 + */ + DTree.prototype.getParam = function(id){ + var _this = this; + + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null){ return _this.callbackData().node(_this.getTempNodeParam($div)); } else { return {}; } + }; + + /** + * @Desc: 根据id获取节点上级节点参数 + * @Param: id:节点的ID值 + */ + DTree.prototype.getParentParam = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + if($div != null){ return _this.callbackData().parentNode($div); } else { return {}; } + }; + + /** + * @Desc: 根据id获取节点的全部上级节点参数值 + * @Param: id:节点的ID值 + */ + DTree.prototype.getAllParentParam = function(id){ + var _this = this; + // 获取当前div,如果id就是一个dom,则就是这个,如果不是则进行选择。如果选不中则为null + var $div = (typeof id === 'object') ? id : (_this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']").length == 0) ? null : _this.obj.find("div[dtree-click='"+eventName.itemNodeClick+"'][data-id='"+id+"']"); + var arr = []; + if($div != null){ + var level = _this.getTempNodeParam($div).level; + for(var i=1; i 0){ + $childDivs.each(function(){ + var $cDiv = $(this); + childNode.push(_this.getRequestParam(_this.getTempNodeParam($cDiv))); + }); + } + return childNode; + }, + parentNode: function($div){ // 获取上级节点值 + var pId = _this.getNodeDom($div).parentLi().attr("data-pid"); + var $pdiv = _this.obj.find("div[data-id='"+pId+"']"); + if($pdiv.length > 0) {return _this.getRequestParam(_this.getTempNodeParam($pdiv));} else {return {};} + + } + } + }; + + /******************** 事件回调区域 ********************/ + /** + * @Desc: 绑定浏览器事件 + */ + DTree.prototype.bindBrowserEvent = function(){ + var _this = this; + var rootId = _this.obj[0].id; + + // 绑定文件夹展开/收缩的图标的点击事件,点击时给当前节点的div添加选中class + _this.obj.on("click", "i[data-spread]", function(event) { + event.stopPropagation(); + var $i = $(this), + $div = $i.parent("div"), + node = _this.getNodeParam($div); + + _this.toolbarHide(); + _this.navThis($div); + _this.clickSpread($div); // 展开或隐藏节点 + + // 树状态改变后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "changeTree("+$(_this.obj)[0].id+")", { + dom: _this.callbackData().dom($i), + param: _this.callbackData().node(node), + show: _this.callbackData().dom($i).attr("data-spread") == "open" ? true : false + }); + }); + + // 绑定所有子节点div的单击事件,点击时触发加载iframe或用户自定义想做的事情 + _this.obj.on("click", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event) { + event.stopPropagation(); + var $div = $(this), + $cite = $div.find("cite"), + node = _this.getNodeParam($div); + _this.toolbarHide(); + _this.navThis($div); + + if(_this.select) { + _this.selectVal(node.nodeId); + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").click(); + } + + if (_this.useIframe) { + var iframeParam = _this.getFilterRequestParam(_this.getIframeRequestParam(node)); + var flag = _this.loadIframe($div, iframeParam); // 加载iframe + if (flag) { + // iframe加载完毕后,用户自定义想做的事情 + _this.iframeFun.iframeDone(iframeParam); + + layui.event.call(this, MOD_NAME, "iframeDone("+$(_this.obj)[0].id+")", { + "iframeParam": iframeParam, + dom: _this.callbackData().dom($div) + }); + } + } else { + // 单击事件执行完毕后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "node("+$(_this.obj)[0].id+")", { + param: _this.callbackData().node(node), + childParams: _this.callbackData().childNode($div), + parentParam: _this.callbackData().parentNode($div), + dom: _this.callbackData().dom($div) + }); + } + }); + + // 绑定所有子节点div的双击事件,暴露on给用户自定义 + _this.obj.on("dblclick", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event) { + event.stopPropagation(); + var $div = $(this), + $cite = $div.find("cite"), + node = _this.getNodeParam($div); + _this.toolbarHide(); + _this.navThis($div); + + if(_this.select) { + _this.selectVal(node.nodeId); + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").click(); + } + + // 双击事件执行完毕后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "nodedblclick("+$(_this.obj)[0].id+")", { + param: _this.callbackData().node(node), + childParams: _this.callbackData().childNode($div), + parentParam: _this.callbackData().parentNode($div), + dom: _this.callbackData().dom($div) + }); + }); + + if(_this.checkbar) { + // 绑定cheboxbar的节点复选框 + _this.obj.on("click", "i[dtree-click='"+eventName.checkNodeClick+"'][dtree-disabled='false']", function(event) { + _this.toolbarHide(); + var $i = $(this), + $div = $i.closest("div[dtree-click='"+eventName.itemNodeClick+"']"), + node = _this.getNodeParam($div); + // 复选框选中前的回调 + var flag = _this.checkbarFun.chooseBefore($i, _this.getRequestParam(node)); + _this.temp = [$i]; + if(flag){_this.changeCheck();} + + event.stopPropagation(); + }); + } + + if(_this.menubar) { + // 绑定menubar的点击事件 + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).on("click", "button[d-menu]", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("d-menu"), "group"); + }); + + // 绑定menubar的点击事件 + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).on("click", "a[d-menu]", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("d-menu"), "toolbar"); + }); + + // 绑定menubar的点击按钮事件 + _this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").on("click", function(event) { + event.stopPropagation(); + _this.toolbarHide(); + _this.menubarListener($(this).attr("dtree-menu"), "freedom"); + }); + } + + if(_this.toolbar) { + if(_this.toolbarWay == "contextmenu") { + //绑定所有子节点div的右键点击事件,用于显示toolbar + _this.obj.on("contextmenu", "div[dtree-click='"+eventName.itemNodeClick+"'][d-contextmenu='true'][dtree-disabled='false']", function(e){ + var $div = $(this), + node = _this.getNodeParam($div); + + _this.toolbarHide(); + // toolbar加载前执行的方法,执行完毕之后创建按钮 + _this.setToolbarDom().setToolbarPlace(_this.toolbarFun.loadToolbarBefore(event.cloneObj(_this.toolbarMenu), _this.getRequestParam(node), $div)); + + var e = e || window.event, + mx = e.pageX - $div.offset().left +45 , + my = $div.offset().top - _this.obj.closest(_this.scroll).offset().top +15; + + _this.navThis($div); + var $toolBarDiv = _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id); + $toolBarDiv.find(".layui-nav-child").addClass('layui-anim-fadein layui-show'); + $toolBarDiv.css({'left':mx+'px','top':my+'px'}); + + e.stopPropagation(); + return false; + }); + + // 绑定装载树的上层出现滚动条的容器,让toolbar隐藏 + _this.obj.closest(_this.scroll).scroll(function() { + _this.toolbarHide(); + }); + + // 绑定toolbar的点击事件 + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $div = _this.getNodeDom().nowOrRootDiv(), + node = _this.getNodeParam($div); + _this.toolbarHide(); + var tool = $(this).attr("dtree-tool"); + _this.toolbarListener(tool, $div); + }); + } else if(_this.toolbarWay == "fixed") { + // 绑定toolbar的点击事件 + _this.obj.on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $a = $(this), + $cite = $a.parent("em."+TOOLBAR_TOOL_EM).prev("cite"), //当前选中节点的text + $div = $cite.parent("div"), + node = _this.getNodeParam($div); + var tool = $a.attr("dtree-tool"); + + _this.toolbarHide(); + _this.navThis($div); + _this.toolbarListener(tool, $div); + }); + } else if(_this.toolbarWay == "follow") { + //绑定所有子节点div的mouseover mouseout事件,用于显示或隐藏toolbar + _this.obj.on("mouseover mouseout", "div[dtree-click='"+eventName.itemNodeClick+"'][dtree-disabled='false']", function(event){ + var $div = $(this), + $toolBarEm = $div.children("em."+TOOLBAR_TOOL_EM); + if(event.type == "mouseover"){ + $toolBarEm.removeClass(NAV_HIDE); + event.stopPropagation(); + } else if(event.type == "mouseout"){ + $toolBarEm.addClass(NAV_HIDE); + event.stopPropagation(); + } + }); + + // 绑定toolbar的点击事件 + _this.obj.on("click", "a[dtree-tool]", function(event) { + event.stopPropagation(); + var $a = $(this), + $cite = $a.parent("em."+TOOLBAR_TOOL_EM).prev("cite"), //当前选中节点的text + $div = $cite.parent("div"), + node = _this.getNodeParam($div); + var tool = $a.attr("dtree-tool"); + + _this.toolbarHide(); + _this.navThis($div); + _this.toolbarListener(tool, $div); + }); + } + } + + if(_this.select) { + // 绑定select的点击事件 + $("div[dtree-id='" + rootId + "'][dtree-select='"+_this.selectDiv+"']").on("click", function(event){ + event.stopPropagation(); + var dl = $(this).find('dl'); + //debugger; + $(this).toggleClass("layui-form-selected"); + + var $card = $("div[dtree-id='" + rootId + "'][dtree-card='"+_this.selectCardDiv+"']"); + + $card.toggleClass("dtree-select-show layui-anim layui-anim-upbit"); + var top = $(this).offset().top + $(this).outerHeight() - $WIN.scrollTop() - 5, + cardHeight = $card.height(), + winHeight = $WIN.height(); +// console.log("top = $(this).offset().top: " + $(this).offset().top + " + $(this).outerHeight(): " + $(this).outerHeight() + " - $WIN.scrollTop(): " + $WIN.scrollTop() + " - 5 =" + top); +// console.log("winHeight = " + winHeight); + if($card.hasClass('dtree-select-up')) { + $card.removeClass('dtree-select-up'); + } + + //上下定位识别 + if(top + cardHeight > $WIN.height() && top >= cardHeight){ + console.log(" top + cardHeight : "+ top + " + " + cardHeight + " > $WIN.height() :" + $WIN.height() + " && top >= cardHeight :" + top + " > " + cardHeight); + if($card.hasClass('dtree-select-up')) { + $card.removeClass('dtree-select-up'); + } else { + $card.addClass('dtree-select-up'); + } + } else { + $card.removeClass('dtree-select-up'); + } + + // 下拉树面板开闭状态改变后,用户自定义想做的事情 + layui.event.call(this, MOD_NAME, "changeSelect("+$(_this.obj)[0].id+")", { + show: $(this).hasClass("layui-form-selected"), + param: _this.selectVal() + }); + }); + + } + }; + + // 绑定body的单击,让本页面所有的toolbar隐藏 + $BODY.on("click", function(event){ + $("div."+LI_DIV_TOOLBAR).find(".layui-show").removeClass('layui-anim-fadein layui-show'); + // $("div[dtree-id][dtree-select]").removeClass("layui-form-selected"); + // $("div[dtree-id][dtree-card]").removeClass("dtree-select-show layui-anim layui-anim-upbit"); + + }); + + // 解绑浏览器事件 + DTree.prototype.unbindBrowserEvent = function(){ + var _this = this; + + // 本身事件解绑 + _this.obj.unbind(); + // 菜单栏解绑 + if(_this.menubar){ + _this.obj.prevAll('div#dtree_menubar_'+_this.obj[0].id).unbind(); + if(_this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").length > 0){ + _this.obj.closest('body').find("*[dtree-id='"+_this.obj[0].id+"'][dtree-menu]").unbind(); + } + } + + // 工具栏解绑 + if(_this.toolbar){ + if(_this.toolbarWay == "contextmenu") { + _this.obj.prevAll('div#dtree_toolbar_'+_this.obj[0].id).unbind(); + if(_this.obj.closest(_this.scroll).length > 0){ + _this.obj.closest(_this.scroll).unbind(); + } + } + } + + // 下拉树解绑 + if(_this.select) { + // 解绑select的点击事件 + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-select='"+_this.selectDiv+"']").removeClass("layui-form-selected"); + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-card='"+_this.selectCardDiv+"']").removeClass("dtree-select-show layui-anim layui-anim-upbit"); + $("div[dtree-id='" + _this.obj[0].id + "'][dtree-select='"+_this.selectDiv+"']").unbind(); + } + }; + + + /** 外部访问 **/ + var dtree = { + set: function(options){ //设置全局属性 + if(typeof options !== 'undefined') { + $.extend(OPTIONS, options); + } + }, + render: function(options){ // 初始化树 + var dTree = null; + var id = event.getElemId(options); + if(id == "") { + layer.msg("页面中未找到绑定id", {icon:5}); + } else { + dTree = DTrees[id]; + if(typeof dTree === 'object'){ + dTree.unbindBrowserEvent(); + } + // 创建树 + dTree = new DTree(options); + // 添加到树数组中去 + DTrees[id] = dTree; + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.loadTreeInit(); + dTree.bindBrowserEvent(); + } + + return dTree; + }, + renderSelect: function(options){ // 初始化下拉树 + var dTree = null; + var id = event.getElemId(options); + if(id == "") { + layer.msg("页面中未找到绑定id", {icon:5}); + } else { + dTree = DTrees[id]; + if(typeof dTree === 'object'){ + dTree.unbindBrowserEvent(); + } + // 创建下拉树 + dTree = new DTree(options); + dTree.selectSetting(); + // 添加到树数组中去 + DTrees[id] = dTree; + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.loadTreeInit(); + dTree.bindBrowserEvent(); + } + + return dTree; + }, + reload: function(dTree, options){ // 重新加载树 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + dTree.reloadSetting(options); + dTree.initTreePlus(); + dTree.openTreePlus(); + dTree.initNodeParam(); + dTree.loadTreeInit(); + dTree.unbindBrowserEvent(); + dTree.bindBrowserEvent(); + }, + on: function(events, callback) { // 绑定事件 + if(events.indexOf("'") > 0){ + events = events.replace(/'/g,""); + } + if(events.indexOf('"') > 0) { + events = events.replace(/"/g,""); + } + return layui.onevent.call(this, MOD_NAME, events, callback); + }, + click: function(dTree, id) { // 模拟单击事件 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + $("div[dtree-click='"+eventName.itemNodeClick+"'][dtree-id='"+dTree.obj[0].id+"'][data-id='"+id+"']").click(); + }, + getNowParam: function(dTree){ // 获取当前选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getNowParam(); // 获取当前选中值 + }, + getParam: function(dTree, id){ // 获取指定节点值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getParam(id); // 获取指定节点值 + }, + getParentParam: function(dTree, id){ // 获取参数的上级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getParentParam(id); + }, + getAllParentParam: function(dTree, id){ // 获取参数的全部上级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getAllParentParam(id); + }, + getChildParam: function(dTree, id){ // 获取参数的全部下级节点 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.getChildParam(id); + }, + getCheckbarNodesParam: function(dTree){ // 获取复选框选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return {}; + } + return dTree.getCheckbarNodesParam(); // 获取复选框选中值 + }, + getCheckbarJsonArrParam: function(dTree){ // 获取复选框选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return {}; + } + return dTree.getCheckbarJsonArrParam(); // 获取复选框选中值 + }, + dataInit: function(dTree, chooseId){ // 初始化选中树,针对数据反选 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + if(chooseId){ + return dTree.dataInit(chooseId); + } + }, + chooseDataInit: function(dTree, chooseIds){ // 初始化复选框选中,针对数据反选 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + if(chooseIds){ + return dTree.chooseDataInit(chooseIds); + } + }, + changeCheckbarNodes: function(dTree){ //判断复选框是否发生变更 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.changeCheckbarNodes(); + }, + initNoAllCheck: function(dTree) { //复选框半选状态初始化设置 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.initNoAllCheck(); + }, + initAllCheck: function(dTree){ // 复选框选中状态初始化设置 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.initAllCheck(); + }, + selectVal: function(dTree, param){ // select模式设置输入框选中值 + if(typeof dTree === "string"){ + dTree = DTrees[dTree]; + } + if(typeof dTree === "undefined"){ + layer.msg("方法获取失败,请检查ID或对象传递是否正确",{icon:2}); + return ; + } + return dTree.selectVal(param); // select模式设置输入框选中值 + }, + escape: function(html){ // 字符串格式化 + return event.escape(html); + }, + unescape: function(str){ // 字符串反格式化 + return event.unescape(str); + }, + serialize: function(first, param) { // 序列化JSON对象 + return AjaxHelper.serialize(first, param); + }, + version: function(){ //获取版本号 + return VERSION; + } + }; + + exports('dtree', dtree); +}); \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.css b/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.css new file mode 100644 index 0000000..df7af65 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.css @@ -0,0 +1,229 @@ +@font-face { + font-family: 'dtreefont'; + src: url('dtreefont.eot?x3m8fp'); + src: url('dtreefont.eot?x3m8fp#iefix') format('embedded-opentype'), + url('dtreefont.ttf?x3m8fp') format('truetype'), + url('dtreefont.woff?x3m8fp') format('woff'), + url('dtreefont.svg?x3m8fp#dtreefont') format('svg'); + font-weight: normal; + font-style: normal; +} + +[class^="dtree-icon-"], [class*=" dtree-icon-"] { + /* use !important to prevent issues with browser extensions that change font */ + font-family: 'dtreefont' !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; +} + +.dtree-icon-xiangxia1:before { + content: "\e771"; +} +.dtree-icon-normal-file:before { + content: "\e60c"; +} +.dtree-icon-xiangyou:before { + content: "\e78f"; +} +.dtree-icon-ok-circle:before { + content: "\1005"; +} +.dtree-icon-close1:before { + content: "\1006"; +} +.dtree-icon-close-fill:before { + content: "\1007"; +} +.dtree-icon-jian1:before { + content: "\e600"; +} +.dtree-icon-jia1:before { + content: "\e601"; +} +.dtree-icon-bianji:before { + content: "\e602"; +} +.dtree-icon-yonghu:before { + content: "\e603"; +} +.dtree-icon-shijian:before { + content: "\e606"; +} +.dtree-icon-fuxuankuang-banxuan:before { + content: "\e607"; +} +.dtree-icon-star:before { + content: "\e608"; +} +.dtree-icon-wenjianjiazhankai:before { + content: "\e60e"; +} +.dtree-icon-xiangmuxiaoxi:before { + content: "\e60f"; +} +.dtree-icon-search2:before { + content: "\e615"; +} +.dtree-icon-weibiaoti5:before { + content: "\e618"; +} +.dtree-icon-layim-theme:before { + content: "\e61b"; +} +.dtree-icon-shuye1:before { + content: "\e61e"; +} +.dtree-icon-add-circle:before { + content: "\e61f"; +} +.dtree-icon-xinxipilu:before { + content: "\e620"; +} +.dtree-icon-set-sm:before { + content: "\e621"; +} +.dtree-icon-about:before { + content: "\e623"; +} +.dtree-icon-chart-screen:before { + content: "\e62a"; +} +.dtree-icon-delete1:before { + content: "\e640"; +} +.dtree-icon-share3:before { + content: "\e641"; +} +.dtree-icon-youjian:before { + content: "\e642"; +} +.dtree-icon-check:before { + content: "\e645"; +} +.dtree-icon-close:before { + content: "\e646"; +} +.dtree-icon-favorfill:before { + content: "\e64b"; +} +.dtree-icon-favor:before { + content: "\e64c"; +} +.dtree-icon-fuxuankuangxuanzhong:before { + content: "\e652"; +} +.dtree-icon-fenguangbaobiao:before { + content: "\e655"; +} +.dtree-icon-jian:before { + content: "\e656"; +} +.dtree-icon-jia:before { + content: "\e657"; +} +.dtree-icon-fenzhijigou:before { + content: "\e658"; +} +.dtree-icon-roundcheckfill:before { + content: "\e659"; +} +.dtree-icon-roundcheck:before { + content: "\e65a"; +} +.dtree-icon-roundclosefill:before { + content: "\e65b"; +} +.dtree-icon-roundclose:before { + content: "\e65c"; +} +.dtree-icon-roundrightfill:before { + content: "\e65d"; +} +.dtree-icon-roundright:before { + content: "\e65e"; +} +.dtree-icon-like:before { + content: "\e66c"; +} +.dtree-icon-samefill:before { + content: "\e671"; +} +.dtree-icon-same:before { + content: "\e672"; +} +.dtree-icon-evaluate:before { + content: "\e674"; +} +.dtree-icon-circle1:before { + content: "\e687"; +} +.dtree-icon-radio:before { + content: "\e688"; +} +.dtree-icon-caidan_xunzhang:before { + content: "\e68e"; +} +.dtree-icon-pulldown:before { + content: "\e6a0"; +} +.dtree-icon-pullup:before { + content: "\e6a1"; +} +.dtree-icon-refresh:before { + content: "\e6a4"; +} +.dtree-icon-qrcode1:before { + content: "\e6b0"; +} +.dtree-icon-profile1:before { + content: "\e6b7"; +} +.dtree-icon-home1:before { + content: "\e6b8"; +} +.dtree-icon-homefill:before { + content: "\e6bb"; +} +.dtree-icon-roundaddfill:before { + content: "\e6d8"; +} +.dtree-icon-roundadd:before { + content: "\e6d9"; +} +.dtree-icon-fuxuankuang:before { + content: "\e6f2"; +} +.dtree-icon-wefill:before { + content: "\e6f5"; +} +.dtree-icon-sort:before { + content: "\e701"; +} +.dtree-icon-repair:before { + content: "\e738"; +} +.dtree-icon-shujudaping:before { + content: "\e742"; +} +.dtree-icon-dian:before { + content: "\e7a5"; +} +.dtree-icon-search_list_light:before { + content: "\e807"; +} +.dtree-icon-round_list_light:before { + content: "\e82b"; +} +.dtree-icon-star-fill:before { + content: "\e832"; +} +.dtree-icon-rate:before { + content: "\e833"; +} +.dtree-icon-move-up:before { + content: "\ea47"; +} +.dtree-icon-move-down:before { + content: "\ea48"; +} diff --git a/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.eot b/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.eot new file mode 100644 index 0000000..68bf5f2 Binary files /dev/null and b/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.eot differ diff --git a/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.svg b/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.svg new file mode 100644 index 0000000..90fe50f --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.svg @@ -0,0 +1,80 @@ + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.ttf b/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.ttf new file mode 100644 index 0000000..78bacd1 Binary files /dev/null and b/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.ttf differ diff --git a/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.woff b/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.woff new file mode 100644 index 0000000..2b54645 Binary files /dev/null and b/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/dtreefont.woff differ diff --git a/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/icons.json b/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/icons.json new file mode 100644 index 0000000..fca4788 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/dtree/font/icons.json @@ -0,0 +1,283 @@ +{ + "data": [{ + "cls": "dtree-icon-xiangxia1", + "uncode": "e771" + }, + { + "cls": "dtree-icon-xiangyou", + "uncode": "e78f" + }, + { + "cls": "dtree-icon-jian", + "uncode": "e656" + }, + { + "cls": "dtree-icon-jia", + "uncode": "e657" + }, + { + "cls": "dtree-icon-weibiaoti5", + "uncode": "e618" + }, + { + "cls": "dtree-icon-wenjianjiazhankai", + "uncode": "e60e" + }, + { + "cls": "dtree-icon-dian", + "uncode": "e7a5" + }, + { + "cls": "dtree-icon-yonghu", + "uncode": "e603" + }, + { + "cls": "dtree-icon-fenzhijigou", + "uncode": "e658" + }, + { + "cls": "dtree-icon-fenguangbaobiao", + "uncode": "e655" + }, + { + "cls": "dtree-icon-xinxipilu", + "uncode": "e620" + }, + { + "cls": "dtree-icon-shuye1", + "uncode": "e61e" + }, + { + "cls": "dtree-icon-caidan_xunzhang", + "uncode": "e68e" + }, + { + "cls": "dtree-icon-normal-file", + "uncode": "e60c" + }, + { + "cls": "dtree-icon-roundclose", + "uncode": "e65c" + }, + { + "cls": "dtree-icon-bianji", + "uncode": "e602" + }, + { + "cls": "dtree-icon-roundadd", + "uncode": "e6d9" + }, + { + "cls": "dtree-icon-fuxuankuangxuanzhong", + "uncode": "e652" + }, + { + "cls": "dtree-icon-fuxuankuang", + "uncode": "e6f2" + }, + { + "cls": "dtree-icon-fuxuankuang-banxuan", + "uncode": "e607" + }, + { + "cls": "dtree-icon-search_list_light", + "uncode": "e807" + }, + { + "cls": "dtree-icon-move-up", + "uncode": "ea47" + }, + { + "cls": "dtree-icon-move-down", + "uncode": "ea48" + }, + { + "cls": "dtree-icon-delete1", + "uncode": "e640" + }, + { + "cls": "dtree-icon-refresh", + "uncode": "e6a4" + }, + { + "cls": "dtree-icon-roundcheckfill", + "uncode": "e659" + }, + { + "cls": "dtree-icon-roundclosefill", + "uncode": "e65b" + }, + { + "cls": "dtree-icon-roundcheck", + "uncode": "e65a" + }, + { + "cls": "dtree-icon-pulldown", + "uncode": "e6a0" + }, + { + "cls": "dtree-icon-pullup", + "uncode": "e6a1" + }, + { + "cls": "dtree-icon-set-sm", + "uncode": "e621" + }, + { + "cls": "dtree-icon-rate", + "uncode": "e833" + }, + { + "cls": "dtree-icon-jian1", + "uncode": "e600" + }, + { + "cls": "dtree-icon-jia1", + "uncode": "e601" + }, + { + "cls": "dtree-icon-shijian", + "uncode": "e606" + }, + { + "cls": "dtree-icon-check", + "uncode": "e645" + }, + { + "cls": "dtree-icon-close", + "uncode": "e646" + }, + { + "cls": "dtree-icon-favorfill", + "uncode": "e64b" + }, + { + "cls": "dtree-icon-favor", + "uncode": "e64c" + }, + { + "cls": "dtree-icon-roundrightfill", + "uncode": "e65d" + }, + { + "cls": "dtree-icon-roundright", + "uncode": "e65e" + }, + { + "cls": "dtree-icon-samefill", + "uncode": "e671" + }, + { + "cls": "dtree-icon-same", + "uncode": "e672" + }, + { + "cls": "dtree-icon-qrcode1", + "uncode": "e6b0" + }, + { + "cls": "dtree-icon-profile1", + "uncode": "e6b7" + }, + { + "cls": "dtree-icon-home1", + "uncode": "e6b8" + }, + { + "cls": "dtree-icon-homefill", + "uncode": "e6bb" + }, + { + "cls": "dtree-icon-roundaddfill", + "uncode": "e6d8" + }, + { + "cls": "dtree-icon-wefill", + "uncode": "e6f5" + }, + { + "cls": "dtree-icon-sort", + "uncode": "e701" + }, + { + "cls": "dtree-icon-round_list_light", + "uncode": "e82b" + }, + { + "cls": "dtree-icon-search2", + "uncode": "e615" + }, + { + "cls": "dtree-icon-close1", + "uncode": "1006" + }, + { + "cls": "dtree-icon-close-fill", + "uncode": "1007" + }, + { + "cls": "dtree-icon-chart-screen", + "uncode": "e62a" + }, + { + "cls": "dtree-icon-star", + "uncode": "e608" + }, + { + "cls": "dtree-icon-ok-circle", + "uncode": "1005" + }, + { + "cls": "dtree-icon-add-circle", + "uncode": "e61f" + }, + { + "cls": "dtree-icon-about", + "uncode": "e623" + }, + { + "cls": "dtree-icon-circle1", + "uncode": "e687" + }, + { + "cls": "dtree-icon-radio", + "uncode": "e688" + }, + { + "cls": "dtree-icon-star-fill", + "uncode": "e832" + }, + { + "cls": "dtree-icon-shujudaping", + "uncode": "e742" + }, + { + "cls": "dtree-icon-share3", + "uncode": "e641" + }, + { + "cls": "dtree-icon-youjian", + "uncode": "e642" + }, + { + "cls": "dtree-icon-repair", + "uncode": "e738" + }, + { + "cls": "dtree-icon-evaluate", + "uncode": "e674" + }, + { + "cls": "dtree-icon-like", + "uncode": "e66c" + }, + { + "cls": "dtree-icon-layim-theme", + "uncode": "e61b" + }, + { + "cls": "dtree-icon-xiangmuxiaoxi", + "uncode": "e60f" + } + ] +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/dtree/开发者日志.txt b/WaterCloud.Web/wwwroot/js/lay-module/dtree/开发者日志.txt new file mode 100644 index 0000000..e383482 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/dtree/开发者日志.txt @@ -0,0 +1,332 @@ +大改》 修复 》 优化 》 新增 》 更新 》 移除 +基础属性 》 checkbar属性 》 menubar属性 》 toolbar属性 》 iframe属性 》 基础方法 》 内置方法 + +------------------------v2.5.8(2020/?/?)【优化】:------------------------ +【修复】toolbar模块修复:默认编辑页面中,提交失败的问题。 +【修复】menubar模块修复:点击收缩节点按钮导致树数据节点错乱,重复加载节点的问题。 +【修复】基础数据模块修复:当复选框字段存在且传递数据为null的时候,解析失败的问题。 +【优化】异步模块优化:success回调函数现在可以存在返回值,返回的值为你重新设置的树的数据。 +【优化】toolbar模块优化:当toolbarShow设置为[]时,点击右键会出现一个白色的小框的问题。 +【优化】toolbar模块优化:点击pullup按钮导致树数据节点错乱,重复加载节点的问题。 + + + +------------------------v2.5.7(2020/01/19)【优化】:------------------------ +【修复】select模块修复:当设置默认值时,存在点击select面板后,默认值消失的问题。 +【修复】select模块修复:带复选框的下拉树设置默认值无效的问题。 +【修复】内置属性修复:修复response设置了checked和type映射却无效的问题 +【新增】内置函数新增:fuzzySearch,模糊查询,搜索节点,保留父节点。 +【优化】内置函数优化:setDisabledNodes,现支持传入单个数据、带分隔符的字符串、数组、二维数组。 +【新增】内置函数新增:setDisabledNode,设置单个节点的禁用 +【优化】内置函数优化:cancelDisabledNodes,现支持传入单个数据、带分隔符的字符串、数组、二维数组。 +【新增】内置函数新增:cancelDisabledNode,设置单个节点的取消禁用 +【优化】内置函数优化:getDisabledNodesParam,现支持传入单个数据、带分隔符的字符串、数组、二维数组。 +【优化】内置函数优化:setHideNodes,现支持传入单个数据、带分隔符的字符串、数组、二维数组。 +【新增】内置函数新增:setHideNode,设置单个节点的隐藏 +【优化】内置函数优化:cancelHideNodes,现支持传入单个数据、带分隔符的字符串、数组、二维数组。 +【新增】内置函数新增:cancelHideNode,设置单个节点的取消隐藏 +【优化】内置函数优化:getHideNodesParam,现支持传入单个数据、带分隔符的字符串、数组、二维数组。 +【优化】内置函数优化:chooseDataInit,现支持传入单个数据、带分隔符的字符串、数组、二维数组(多级复选框)。 +【新增】基础方法新增:getCheckbarJsonArrParam,获取基于返回参数的树的复选框参数,选中数据横向存储 +【新增】基础方法新增:beforeSend,异步加载发送ajax请求之前的回调 +【新增】基础方法新增:serialize,序列化json对象 +【优化】基础方法优化:success方法,新增一个入参,表示是否第一次渲染数据,并支持在增量加载时,加载子节点时也可以回调该方法。 +【优化】基础方法优化:done方法,新增一个入参,表示是否第一次渲染数据,并支持在增量加载时,在加载子节点时也可以回调该方法。 +【优化】内置方法优化:dataInit方法,仅支持一个节点改变背景色的优化。 +【优化】内置方法优化:init方法,入参新增一个异步加载完成后的回调函数,内部使用。 +【优化】内置方法优化:getChild方法,入参新增一个异步加载完成后的回调函数,内部使用。 +【优化】异步加载优化:使用data加载,也会出现load效果。 +【优化】toolbat模块优化:当设置dataFormat时,默认的增删改数据中会出现dataFormat配置的元素,优化之后仅获取文字。 +【优化】select模块优化:自适应当前组件的位置,向上或向下展开树。 +【新增】基础属性新增:asyncLoad,异步加载初始加载层级树组 +【新增】基础属性新增:selectCardHeight,树面板的高度 +【新增】内置方法新增:loadTreeInit,初始化加载树 +【新增】内置方法新增:loadChildTreeInit,初始化加载子节点 +【新增】内置方法新增:dataLoadTree,用data加载树 +【新增】内置方法新增:asyncLoadTree,异步加载树 + + +------------------------v2.5.6(2019/10/24)【新增】:------------------------ +【修复】标签属性修复:ul标签上data-value属性设置无效的问题 +【优化】数据格式:获取格式中的basicData和recordData将提前转化为JSON格式,不在需要手动转换。 +【优化】基础方法优化:render,支持加载下拉树 +【优化】基础方法优化:reload,支持重载下拉树 +【新增】基础属性新增:bak,内置属性,备份Html。 +【新增】事件监听:changeSelect,下拉树面板开闭状态改变后,触发事件。 +【新增】内置方法新增:rollbackHtml,基于备份的Html数据回滚 +【新增】内置方法新增:setDisabledAllNodes,设置全部节点为disabled +【新增】内置方法新增:reloadSelectSetting,重新设置下拉树的基本参数 +【新增】内置方法新增:reloadSelectDom,重新渲染下拉树的Dom结构 +【新增】内置方法新增:selectCheckboxVal,设置复选框模式中的下拉树的值 +【新增】内置方法新增:getCheckbarJsonArrParam,获取基于返回参数的树的复选框参数数组 +【新增】内置方法新增:checkAllNode,复选框全选 +【新增】内置方法新增:cancelCheckedNode,取消全部复选框选中 +【新增】内置方法新增:invertCheckedNode,反选复选框 +【新增】内置方法新增:removeCheckedNode,删除选中节点 + +------------------------v2.5.5(2019/10/12)【新增】:------------------------ +【修复】内置方法修复:partialRefreshEdit,支持修改parentId后及时返显到下挂节点 +【优化】单页模式中树的缓存问题 +【优化】基础属性优化,开启line时,toolbar的fixed显示不正常 +【优化】基础属性优化,开启line时,div选中 悬停背景对齐 +【优化】基础方法优化:success方法的放置位置,可以将不同的数据格式在success方法内做转换,或添加根节点。 +【优化】iframe模块优化:将原来用iframe包住的属性提出,撤销iframe这一层。 +【优化】内置属性优化:scroll属性更名为scroll。 +【优化】内置方法优化:当异步加载出现异常时,以文字形式而非弹框形式提示。 +【新增】标签属性新增:ul标签上新增data-value属性,用于指定下拉树的初始展示值 +【新增】基础属性新增:width,设置树的宽度 +【新增】基础属性新增:select,设置树模式为下拉树 +【新增】基础属性新增:selectTips,设置下拉树时的输入框提示文字 +【新增】基础属性新增:selectInputName,设置下拉树内部表单标签的name +【新增】基础属性新增:selectInitVal,设置下拉树的初始展示值 +【新增】基础属性新增:withCredentials,用于开启生成跨域的XHR对象,设置后可指定同源session,默认false。 +【新增】基础方法新增:set,可以增加同一次引用中,dtree的公共属性指定,所有基础属性都可以指定。 +【新增】基础方法新增:renderSelect,初始化下拉树 +【新增】基础方法新增:selectVal,设置下拉树的初始展示值 +【新增】内置方法新增:selectVal,设置下拉树的初始展示值 +【新增】内置方法新增:selectSetting,设置下拉树的初始元素 +【新增】内置方法新增:renderSelectDom,渲染下拉树的Dom结构 +【新增】内置方法新增:clickNodeCheckbar,点击节点选中复选框 +【更新】内置方法更新:getNoneDom方法,添加errText子方法,显示错误信息。 + +------------------------v2.5.4(2019/6/14)【修复】:------------------------ +【修复】内置方法中,使用data方法获取值不到的问题。 +【优化】基础属性优化:ficon,可以设置Array型数据,与icon的配置方式相同 +【优化】基础属性优化:skin,其中设置layui看起来更像layui的风格,新增laySimple风格,遵从简约版layui树形菜单。 +【优化】内置方法优化:涉及样式的一系列内置方法优化 +【新增】基础属性新增:height,调整高度,与table用法一致 +【新增】基础属性新增:response中新增ficonClass,可以指定一级图标样式。 +【新增】内置方法新增:cancelNavThis,取消选中div。 +【更新】内置方法更新:parseData:增加对ficonClass属性的解析 +【更新】内置方法更新:changeCheck,可以通过传递参数的方式传递复选框dom。 +【移除】基础属性移除:dot,移除一级图标小圆点的单独设置,改为在ficon中配置,与icon的配置方式相同 +【移除】基础属性移除:firstIconArray,与nodeIconArray合并。 + +------------------------v2.5.0(2019/6/01)【适配】:------------------------ +【适配】对layui2.5适配 +【修复】基础属性修复,error方法,现在可以正确的获取参数列表中的参数,如无定义则默认打印textStatus。 +【修复】基础属性修复,complete方法,现在可以正确的获取参数列表中的参数 +【优化】一系列内置方法优化 +【新增】基础属性新增:line,用于指定树线 +【新增】内置方法新增:showLine:用于显示树线 +【新增】内置方法新增:showLineLi:作用在单个LI显示树线 + +------------------------v2.5.0(2019/5/20)【大版本】:------------------------ +【大改】数据格式:reponse中isLast属性更换为last属性。 +【大改】数据格式:reponse中isChecked属性更换为checked属性。 +【大改】数据格式:defaultRequest中isLeaf属性更换为leaf属性。 +【大改】数据格式:defaultRequest中isChecked属性更换为checked属性。 +【大改】内置属性:record开启后,原来记录节点的全部数据(排除children和basicData)改为只记录用户自定义的数据(同样排除children和basicData) +【修复】toolbar模块修复:自定义的toolbar的回调函数的第二个$div参数修复,现在可以取到值 +【修复】toolbar模块修复:内置函数:changeTreeNodeEdit中的title未定义的问题。 +【修复】menubar模块修复:将dtree放在form中,menubar的默认按钮单击之后会提交表单的问题。 +【修复】iframe模块修复:配置了iframeDefaultRequest时,只会显示iframeDefaultRequest中的参数的问题。 +【优化】toolbar模块优化:内置的三个按钮中的label均加上title提示 +【优化】基础方法优化:render方法和reload方法中,如果树在当前页面中被加载过一次了,再次加载会从缓存中取出树,并将树上次点击的节点作为参数记录下载,现在优化为还是从缓存中取,但是会重置上次记录的参数。 +【优化】内置函数优化:getLiItemDom 当parentId为0时组件自动判定为false从而使用内置parentId的问题。 +【新增】基础属性新增:iconfont属性,用于定义使用图标数组或string +【新增】基础属性新增:iconfontStyle属性,用于自定义树的每个关键部位使用的图标 +【新增】基础属性新增:accordion属性,用于开启手风琴模式 +【新增】基础属性新增:contentType属性,用于可以显示配置发送信息至服务器时内容编码类型 +【新增】基础属性新增:response属性中新增disabled,标识节点禁用。 +【新增】基础属性新增:response属性中新增isHide,标识节点隐藏。 +【新增】基础属性新增:formatter属性,用于对树展示节点的文字信息格式化处理。 +【新增】基础属性新增:errDataShow属性,标识是否在递归数据出现错误后,显示错误信息。 +【新增】基础属性新增:none,用于定于树初始化未加载节点时的提示文字。 +【新增】基础属性新增:error:用于异步加载中出现异常时的用户自定义函数。 +【新增】基础属性新增:errDataShow属性,标识是否在递归数据出现错误后,显示错误信息。 +【新增】基础属性新增:drawable属性,用于开启拖拽。 +【新增】基础方法新增:getParam: 获取指定节点选中值 +【新增】基础方法新增:getAllParentParam: 获取指定节点的全部上级节点 +【新增】基础方法新增:initNoAllCheck: 复选框半选状态初始化设置 +【新增】基础方法新增:initAllCheck: 复选框选中状态初始化设置 +【新增】基础方法新增:click:模拟单击事件 +【新增】checkbar模块新增:checkbarData新增属性:"halfChoose",用于记录选中和半选中的数据 +【新增】menubar模块新增:menubar内置新增三个默认方法:checkAll:全选,unCheckAll:全不选,invertAll:反选 +【新增】toolbar模块新增:toolbar内置新增两个默认方法:pulldown:展开当前节点下的全部节点,pullup:收缩当前节点下的全部节点 +【新增】toolbar模块新增:toolbar新增属性:toolbarWay,工具栏显示方式,contextmenu:右键,follow:跟随节点,fixed:固定在节点右侧 +【新增】toolbar模块新增:toolbarBtn中新增一系列的属性(id、placeholder、verify、defElem、readonly、disabled、filter) +【新增】toolbar模块新增:toolbarBtn中,optionsData支持使用function回调 +【新增】内置属性新增:errNode属性,记录在渲染节点时有问题的数据。 +【新增】内置属性新增:usefontStyle属性,用于最终指定树的每个关键部位使用的图标 +【新增】内置方法新增:replaceDom:替换节点的dom值,或指定值。 +【新增】内置方法新增:partialRefreshAdd:局部刷新树--当前节点新增子节点时 +【新增】内置方法新增:partialRefreshEdit:局部刷新树--当前节点选中时 +【新增】内置方法新增:partialRefreshDel:局部刷新树--当前节点选中被删除时 +【新增】内置方法新增:ensureTheme:确认最终主题。 +【新增】内置方法新增:useDefaultOrUserDefineFnodeStyle:赋值一级图标 +【新增】内置方法新增:useDefaultOrUserDefineSnodeStyle:赋值二级图标 +【新增】内置方法新增:useDefaultOrUserDefineCheckboxStyle:赋值复选框图标 +【新增】内置方法新增:useDefaultOrUserDefineMenubarStyle:赋值菜单栏图标 +【新增】内置方法新增:useDefaultOrUserDefineMenubarExtStyle:赋值扩展菜单栏图标 +【新增】内置方法新增:useDefaultOrUserDefineToolbarStyle:赋值扩展菜单栏图标 +【新增】内置方法新增:useDefaultOrUserDefineToolbarExtStyle:赋值扩展工具栏图标 +【新增】内置方法新增:operateIcon: 设置图标的展开关闭,以及展开时/关闭时是最后一级图标的处理 +【新增】内置方法新增:msgErrNode: 判断在数据加载时是否存在错误数据,并是否打印错误数据 +【新增】内置方法新增:getParam: 获取指定节点选中值 +【新增】内置方法新增:getAllParentParam: 获取指定节点的全部上级节点 +【新增】内置方法新增:getNodeDom: 根据具体的id获取基于当前id的div以及对应的其他dom元素 +【新增】内置方法新增:getNode: 获取指定节点Div +【新增】内置方法新增:accordionUL: 开启手风琴模式时对其他节点的处理 +【新增】内置方法新增:setDisabledNodes: 设置节点为disabled +【新增】内置方法新增:cancelDisabledNodes:将节点的disabled取消 +【新增】内置方法新增:getDisabledNodesParam: 获取指定disabled节点的值 +【新增】内置方法新增:getAllDisabledNodesParam: 获取全部disabled节点的值 +【新增】内置方法新增:setHideNodes: 设置节点为hide +【新增】内置方法新增:cancelHideNodes: 将节点的hide取消 +【新增】内置方法新增:getHideNodesParam: 获取指定hide节点的值 +【新增】内置方法新增:getAllHideNodesParam: 获取全部hide节点的值 +【新增】内置方法新增:toolbarHide:隐藏toolbar +【新增】内置方法新增:toolbarMethod:toolbar内置方法 +【新增】内置方法新增:toolbarListener:toolbar内置监听 +【新增】内置方法新增:getNowNodeOrNull:获取当前选中div,没有选中则为null +【新增】内置方法新增:navThis:选中div +【新增】内置方法新增:getNoneDom:当无节点数据时显示dom信息 +【新增】内置方法新增:dynamicToolbarDom:在节点后动态绑定fixed和follow条件的工具栏 +【更新】内置方法更新:setToolbarDom,设置工具栏按钮,现在区别开来哪种toolbar的创建方式 +【更新】内置方法更新:changeTreeNodeAdd新增一个回传参数:refresh,用于新增完成后,局部刷新 +【更新】内置方法更新:parseData新增一个回传参数:fmtTitle,用于获取formatter标记过的内容,原来的title函数只获取原始title信息 + + + +------------------------v2.4.5_finally(2018/12/22)【修复】:------------------------ +1.【修复】单页应用中,未开启toolbar导致body上的所有事件失效。 +2.【优化】更新dist文件夹中的dtree压缩 +3.【优化】toolbar模块优化:新增节点时,当开启了record参数时不会将参数新增到节点上的问题。 + + +------------------------v2.4.5_finally(2018/12/21)【优化】:------------------------ +1.【优化】menubar模块优化:点击收缩时,当前页的所有树都收缩的问题。 +2.【优化】menubar模块优化:点击删除复选框时,展开和收缩节点会报错,现在改为删除的节点如果有子集的话,子集会一并删除,但是回调函数中只会提供你勾中的数据。 +3.【优化】基础方法优化:dataInit方法回显数据时,当前选中的数据无法被获取到的问题。 +4.【优化】基础方法优化:parseData方法的basicData()方法,basicData如果未指定,前端的该项属性无数据,而不是"" +5.【优化】异步属性优化:使用data加载时,可以允许指定的data为[]。 +6.【优化】异步属性优化:使用data加载时,现在也有success和done的回调 +7.【新增】checkbar模块新增:checkbarType新增属性:"only",用于模拟单选,只能同时选择一个复选框。 +8.【新增】异步回调方法新增:新增success回调,用于数据加载完毕后的回调,在done之前执行 +9.【新增】异步属性新增:filterRequest属性,用于过滤树自动发起的请求中你不需要的参数。 +10.【新增】基础属性新增:record属性,开启数据记录模式,用于记录用户提供的JSON数据串中,指定当前节点的JSON数据(排除basicData字段和children字段) +11.【新增】基础属性新增:load属性,是否开启加载遮罩。 +12.【新增】内置函数新增:getFilterRequestParam,获取filterParam过滤后的requestParam + +------------------------v2.4.5_finally_beta(2018/12/07)【大改】:------------------------ +0.【新增】提供的内容中新增dist/dtree.js压缩js文件。 +1.【大改】css:css样式均加上dtree前缀。 +2.【大改】图标:iconfont更改为dtreefont。 +3.【大改】事件监听:图标点击事件返回的参数改为一个JSON对象,具体查看基础文档的事件监听。 +4.【大改】事件监听:节点点击事件返回的参数改为一个JSON对象,具体查看基础文档的事件监听。 +5.【大改】事件监听:节点双击事件返回的参数改为一个JSON对象,具体查看基础文档的事件监听。 +6.【大改】事件监听:复选框点击事件返回的参数改为一个JSON对象,具体查看基础文档的事件监听。 +7.【大改】事件监听:iframe加载完毕事件返回的参数改为一个JSON对象,具体查看基础文档的事件监听。 +8.【新增】基础方法新增:getChildParam,获取全部下级节点 +9.【新增】menubar模块新增:menubarTips属性,用于指定menubar的依附方式。 +10.【新增】toolbar模块新增:toolbarFun新增loadToolbarBefore函数,用于呈现右键菜单之前调用的函数。 +11.【新增】内置函数新增:initTreePlus 用于初始化菜单栏和工具栏的div。 +12.【新增】内置函数新增:openTreePlus 用于开启工具栏和菜单栏。 +13.【新增】内置函数新增:getMenubarDom 用于获取菜单栏。 +14.【新增】内置函数新增:getExtMenubarDom 用于获取扩展菜单栏。 +15.【新增】内置函数新增:getMenubarToolDom 用于获取依附在工具栏的菜单栏。 +16.【新增】内置函数新增:getExtMenubarToolDom 用于获取依附在工具栏的扩展菜单栏。 +17.【新增】内置函数新增:menubarMethod 用于menubar内置调用方法。 +17.【新增】内置函数新增:menubarListener 用于menubar内置监听。 +18.【新增】内置函数新增:setToolbarDom 用于设置工具栏按钮。 +19.【新增】内置函数新增:unbindBrowserEvent 用于解绑浏览器事件。 +19.【新增】内置属性新增:response属性中新增spread。 +20.【优化】优化了图标显示。 +21.【优化】toolbar模块:单页应用中,右键菜单的显示位置问题。 +22.【优化】menubar模块:在开启了toolbar模块时按钮点击失效的问题。 +23.【优化】iframe模块:iframeuUrl指定了"?"时,实际发送的url会出现两个"?"的问题。 +23.【优化】数据格式:默认数据格式中非必须指定isLast属性,移除level属性的作用。 +24.【修复】数据格式:在开启了list风格参数时,修复必须指定isLast返回的问题和设置initLevel无效的问题。 +25.【修复】toolbar模块:新增节点返回json格式后显示数据未定义的问题。 +26.【移除】内置函数移除:refreshTree,现放置在menubarMethod方法中。 +27.【移除】内置函数移除:openAllNode,现放置在menubarMethod方法中。 +28.【移除】内置函数移除:closeAllNode,现放置在menubarMethod方法中。 +28.【移除】内置函数移除:loadChildTree。 +29.【移除】内置函数移除:openMenubar。 +30.【移除】内置函数移除:openToolbar。 +31.【移除】内置属性移除:level。 +32.【移除】内置属性移除:response属性中移除level。 + + +------------------------v2.4.5(2018/11/30)【修复】:------------------------ +1.【修复】基础方法修复:dataInit方法的返回数据异常。 +2.【修复】基础方法修复:render函数自动识别是否重载树,代码再次修复(针对单页应用)。 +3.【新增】内置函数新增:refreshTree,用于刷新树。 +4.【新增】内置函数新增:parseData 用于解析数据。 +5.【优化】checkbar模块:checkArr属性支持传递字符串。 +6.【修复】toolbar模块:拼接新增节点内容的代码异常 。 + +------------------------v2.4.5(2018/11/25)【修复】:------------------------ +1.【修复】render函数自动识别是否重载树,代码修复。 +2.【修复】内部代码bug。 +3.【优化】修改了右键菜单弹出的动画效果。 + +------------------------v2.4.5(2018/11/25)【新增】:------------------------ +1.【优化】优化了图标显示。 +2.【新增】内置图标新增。 +3.【新增】ficon属性:用于用户自定义一级图标 +4.【新增】firstIconArray属性:用于用户自定义扩展一级图标 +5.【新增】异步加载模块添加headers属性。 +6.【新增】toolbar模块:新增属性toolbarExt,用于自定义扩展工具栏右键菜单按钮 +7.【新增】checkbar模块:新增checkbarFun中的回调方法:chooseBefore,用于复选框点击前回调 +8.【新增】内置函数新增:changeCheck,用于改变复选框状态。 +9.【优化】render函数自动识别是否重载树。 +10.【优化】内部代码优化。 +11.【更新】更新了帮助文档 + +------------------------v2.4.5(2018/11/23)【修复】:------------------------ +1.【修复】toolbar模块点击删除按钮时,控制台报错。 +2.【修复】配置了dot:false时,toolbar模块新增节点后一级图标不显示的问题。 +3.【修复】内置函数优化:initNoAllCheck,修复了显示bug +4.【新增】内置函数新增:initAllCheck,复选框选中状态初始化设置 +5.【新增】内置函数新增:checkStatus,设置复选框选中/未选中/半选 +6.【优化】toolbar模块:点击删除时,当删除了某个节点下的最后一个子节点,那该节点也会改变样式变成叶子节点。 +7.【优化】toolbar模块:addTreeNode方法优化,ajax请求不限于同步,方法无需返回 +8.【新增】内置函数新增:changeTreeNodeAdd,新增节点后改变节点内容 +9.【优化】toolbar模块:editTreeNode方法优化,ajax请求不限于同步,方法无需返回 +10.【新增】内置函数新增:changeTreeNodeEdit,编辑节点后改变节点内容 +11.【优化】toolbar模块:delTreeNode方法优化,ajax请求不限于同步,方法无需返回 +12.【新增】内置函数新增:changeTreeNodeDel,删除节点后改变节点内容 +13.【优化】toolbar模块:editTreeLoad方法优化,ajax请求不限于同步,方法无需返回 +14.【新增】内置函数新增:changeTreeNodeDone,编辑页打开后显示编辑页内容 +15.【更新】更新了帮助文档 + +------------------------v2.4.5(2018/11/22)【修复】:------------------------ +1.【修复】树重载时,使用data属性会造成数据重复加载问题。 +2.【修复】输出参数的字段,spared修改为spread(之前单词拼错了。。。。)。 +3.【新增】toolbar模块中新增属性:toolbarStyle,用于自定义toolbar的显示文字,弹框大小。 +4.【移除】基础属性中移除了addIndex属性。 +5.【新增】skin属性:用于用户自定义主题。 +6.【更新】更新了帮助文档 + +------------------------v2.4.5(2018/11/21)【修复】:------------------------ +1.【修复】使用dataFormat属性时,直接使用data属性配置节点内容失效的问题。 +2.【修复】parentId为null导致节点数据加载失效的问题。 +3.【优化】反选节点时将选中哪一级的节点展开,单选和多选均生效。 +4.【新增】dot属性,用于用户自定义一级图标中的小圆点是否显示。 +5.【更新】更新了帮助文档 + +------------------------v2.4.5(2018/11/21)【新增】:------------------------ +1.【新增】toolbar取消按钮的显示,开始绑定右键点击事件。 +2.【新增】toolbar模块新增一个属性:scroll 用于绑定树的上级div容器,让树可以显示滚动条的div容器,右键菜单绑定必填项。 +3.【新增】toolbar模块新增编辑页数据回显功能。 +4.【新增】树加载完毕后的回调函数 +5.【新增】dataStyle属性,用于用户配置layui通用的json数据风格 +6.【新增】dataFormat属性,用于用户自定义data中的数据格式(即支持传入一个大的list) +7.【更新】更新了帮助文档 + +------------------------v2.4.5(2018/11/09)【优化】:------------------------ +1.【优化】更新了图标库,精简了图标(60个) + +------------------------v2.4.5(2018/11/09)【初始】:------------------------ +1.【初始】基本树形展示,无限级,支持自定义修改树的展示图标 +2.【初始】支持异步/同步数据加载,支持静态数据加载,支持数据缓存 +3.【初始】支持自定义返回json格式,支持自定义异步/同步加载参数 +4.【初始】支持复选框,1-N级,支持复选框的四种选中形式,支持记录复选框选中/更改数据的回调 +5.【初始】支持工具栏,即可直接修改当前树节点,新增/ 编辑/删除等 +6.【初始】支持菜单栏,即可直接对树进行全部节点展开/收缩、删除全部选中节点、刷新树、搜索树等 +7.【初始】支持加载iframe,即点击树节点时,可以带上一个访问iframe的url,这个设计在左树右内容风格的页面极为有用 +8.【初始】支持数据回调,单击节点回调、双击节点回调、复选框选中回调、iframe加载完毕回调等 +9.【初始】支持数据获取,即获取当前选中节点数据,当前选中复选框节点数据等 +10.【初始】支持数据反显,即加载树之后将需要反显的节点高亮显示或选中 \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/echarts/echarts.js b/WaterCloud.Web/wwwroot/js/lay-module/echarts/echarts.js new file mode 100644 index 0000000..5bfaa4e --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/echarts/echarts.js @@ -0,0 +1,78200 @@ + +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + window.layui && layui.define ? layui.define(function (exports) { + exports('echarts', factory(exports)) + }) : + (factory((global.echarts = {}))); +}(this, (function (exports) { + 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + PERFORMANCE OF THIS SOFTWARE. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + function __spreadArrays() { + for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; + for (var r = Array(s), k = 0, i = 0; i < il; i++) + for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) + r[k] = a[j]; + return r; + } + + var Browser = (function () { + function Browser() { + this.firefox = false; + this.ie = false; + this.edge = false; + this.newEdge = false; + this.weChat = false; + } + return Browser; + }()); + var Env = (function () { + function Env() { + this.browser = new Browser(); + this.node = false; + this.wxa = false; + this.worker = false; + this.canvasSupported = false; + this.svgSupported = false; + this.touchEventsSupported = false; + this.pointerEventsSupported = false; + this.domSupported = false; + } + return Env; + }()); + var env = new Env(); + if (typeof wx === 'object' && typeof wx.getSystemInfoSync === 'function') { + env.wxa = true; + env.canvasSupported = true; + env.touchEventsSupported = true; + } + else if (typeof document === 'undefined' && typeof self !== 'undefined') { + env.worker = true; + env.canvasSupported = true; + } + else if (typeof navigator === 'undefined') { + env.node = true; + env.canvasSupported = true; + env.svgSupported = true; + } + else { + detect(navigator.userAgent, env); + } + function detect(ua, env) { + var browser = env.browser; + var firefox = ua.match(/Firefox\/([\d.]+)/); + var ie = ua.match(/MSIE\s([\d.]+)/) + || ua.match(/Trident\/.+?rv:(([\d.]+))/); + var edge = ua.match(/Edge?\/([\d.]+)/); + var weChat = (/micromessenger/i).test(ua); + if (firefox) { + browser.firefox = true; + browser.version = firefox[1]; + } + if (ie) { + browser.ie = true; + browser.version = ie[1]; + } + if (edge) { + browser.edge = true; + browser.version = edge[1]; + browser.newEdge = +edge[1].split('.')[0] > 18; + } + if (weChat) { + browser.weChat = true; + } + env.canvasSupported = !!document.createElement('canvas').getContext; + env.svgSupported = typeof SVGRect !== 'undefined'; + env.touchEventsSupported = 'ontouchstart' in window && !browser.ie && !browser.edge; + env.pointerEventsSupported = 'onpointerdown' in window + && (browser.edge || (browser.ie && +browser.version >= 11)); + env.domSupported = typeof document !== 'undefined'; + } + + var BUILTIN_OBJECT = { + '[object Function]': true, + '[object RegExp]': true, + '[object Date]': true, + '[object Error]': true, + '[object CanvasGradient]': true, + '[object CanvasPattern]': true, + '[object Image]': true, + '[object Canvas]': true + }; + var TYPED_ARRAY = { + '[object Int8Array]': true, + '[object Uint8Array]': true, + '[object Uint8ClampedArray]': true, + '[object Int16Array]': true, + '[object Uint16Array]': true, + '[object Int32Array]': true, + '[object Uint32Array]': true, + '[object Float32Array]': true, + '[object Float64Array]': true + }; + var objToString = Object.prototype.toString; + var arrayProto = Array.prototype; + var nativeForEach = arrayProto.forEach; + var nativeFilter = arrayProto.filter; + var nativeSlice = arrayProto.slice; + var nativeMap = arrayProto.map; + var ctorFunction = function () { }.constructor; + var protoFunction = ctorFunction ? ctorFunction.prototype : null; + var methods = {}; + function $override(name, fn) { + methods[name] = fn; + } + var idStart = 0x0907; + function guid() { + return idStart++; + } + function logError() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + if (typeof console !== 'undefined') { + console.error.apply(console, args); + } + } + function clone(source) { + if (source == null || typeof source !== 'object') { + return source; + } + var result = source; + var typeStr = objToString.call(source); + if (typeStr === '[object Array]') { + if (!isPrimitive(source)) { + result = []; + for (var i = 0, len = source.length; i < len; i++) { + result[i] = clone(source[i]); + } + } + } + else if (TYPED_ARRAY[typeStr]) { + if (!isPrimitive(source)) { + var Ctor = source.constructor; + if (Ctor.from) { + result = Ctor.from(source); + } + else { + result = new Ctor(source.length); + for (var i = 0, len = source.length; i < len; i++) { + result[i] = clone(source[i]); + } + } + } + } + else if (!BUILTIN_OBJECT[typeStr] && !isPrimitive(source) && !isDom(source)) { + result = {}; + for (var key in source) { + if (source.hasOwnProperty(key)) { + result[key] = clone(source[key]); + } + } + } + return result; + } + function merge(target, source, overwrite) { + if (!isObject(source) || !isObject(target)) { + return overwrite ? clone(source) : target; + } + for (var key in source) { + if (source.hasOwnProperty(key)) { + var targetProp = target[key]; + var sourceProp = source[key]; + if (isObject(sourceProp) + && isObject(targetProp) + && !isArray(sourceProp) + && !isArray(targetProp) + && !isDom(sourceProp) + && !isDom(targetProp) + && !isBuiltInObject(sourceProp) + && !isBuiltInObject(targetProp) + && !isPrimitive(sourceProp) + && !isPrimitive(targetProp)) { + merge(targetProp, sourceProp, overwrite); + } + else if (overwrite || !(key in target)) { + target[key] = clone(source[key]); + } + } + } + return target; + } + function mergeAll(targetAndSources, overwrite) { + var result = targetAndSources[0]; + for (var i = 1, len = targetAndSources.length; i < len; i++) { + result = merge(result, targetAndSources[i], overwrite); + } + return result; + } + function extend(target, source) { + if (Object.assign) { + Object.assign(target, source); + } + else { + for (var key in source) { + if (source.hasOwnProperty(key)) { + target[key] = source[key]; + } + } + } + return target; + } + function defaults(target, source, overlay) { + var keysArr = keys(source); + for (var i = 0; i < keysArr.length; i++) { + var key = keysArr[i]; + if ((overlay ? source[key] != null : target[key] == null)) { + target[key] = source[key]; + } + } + return target; + } + var createCanvas = function () { + return methods.createCanvas(); + }; + methods.createCanvas = function () { + return document.createElement('canvas'); + }; + function indexOf(array, value) { + if (array) { + if (array.indexOf) { + return array.indexOf(value); + } + for (var i = 0, len = array.length; i < len; i++) { + if (array[i] === value) { + return i; + } + } + } + return -1; + } + function inherits(clazz, baseClazz) { + var clazzPrototype = clazz.prototype; + function F() { } + F.prototype = baseClazz.prototype; + clazz.prototype = new F(); + for (var prop in clazzPrototype) { + if (clazzPrototype.hasOwnProperty(prop)) { + clazz.prototype[prop] = clazzPrototype[prop]; + } + } + clazz.prototype.constructor = clazz; + clazz.superClass = baseClazz; + } + function mixin(target, source, override) { + target = 'prototype' in target ? target.prototype : target; + source = 'prototype' in source ? source.prototype : source; + if (Object.getOwnPropertyNames) { + var keyList = Object.getOwnPropertyNames(source); + for (var i = 0; i < keyList.length; i++) { + var key = keyList[i]; + if (key !== 'constructor') { + if ((override ? source[key] != null : target[key] == null)) { + target[key] = source[key]; + } + } + } + } + else { + defaults(target, source, override); + } + } + function isArrayLike(data) { + if (!data) { + return false; + } + if (typeof data === 'string') { + return false; + } + return typeof data.length === 'number'; + } + function each(arr, cb, context) { + if (!(arr && cb)) { + return; + } + if (arr.forEach && arr.forEach === nativeForEach) { + arr.forEach(cb, context); + } + else if (arr.length === +arr.length) { + for (var i = 0, len = arr.length; i < len; i++) { + cb.call(context, arr[i], i, arr); + } + } + else { + for (var key in arr) { + if (arr.hasOwnProperty(key)) { + cb.call(context, arr[key], key, arr); + } + } + } + } + function map(arr, cb, context) { + if (!arr) { + return []; + } + if (!cb) { + return slice(arr); + } + if (arr.map && arr.map === nativeMap) { + return arr.map(cb, context); + } + else { + var result = []; + for (var i = 0, len = arr.length; i < len; i++) { + result.push(cb.call(context, arr[i], i, arr)); + } + return result; + } + } + function reduce(arr, cb, memo, context) { + if (!(arr && cb)) { + return; + } + for (var i = 0, len = arr.length; i < len; i++) { + memo = cb.call(context, memo, arr[i], i, arr); + } + return memo; + } + function filter(arr, cb, context) { + if (!arr) { + return []; + } + if (!cb) { + return slice(arr); + } + if (arr.filter && arr.filter === nativeFilter) { + return arr.filter(cb, context); + } + else { + var result = []; + for (var i = 0, len = arr.length; i < len; i++) { + if (cb.call(context, arr[i], i, arr)) { + result.push(arr[i]); + } + } + return result; + } + } + function find(arr, cb, context) { + if (!(arr && cb)) { + return; + } + for (var i = 0, len = arr.length; i < len; i++) { + if (cb.call(context, arr[i], i, arr)) { + return arr[i]; + } + } + } + function keys(obj) { + if (!obj) { + return []; + } + if (Object.keys) { + return Object.keys(obj); + } + var keyList = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + keyList.push(key); + } + } + return keyList; + } + function bindPolyfill(func, context) { + var args = []; + for (var _i = 2; _i < arguments.length; _i++) { + args[_i - 2] = arguments[_i]; + } + return function () { + return func.apply(context, args.concat(nativeSlice.call(arguments))); + }; + } + var bind = (protoFunction && isFunction(protoFunction.bind)) + ? protoFunction.call.bind(protoFunction.bind) + : bindPolyfill; + function curry(func) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + return function () { + return func.apply(this, args.concat(nativeSlice.call(arguments))); + }; + } + function isArray(value) { + if (Array.isArray) { + return Array.isArray(value); + } + return objToString.call(value) === '[object Array]'; + } + function isFunction(value) { + return typeof value === 'function'; + } + function isString(value) { + return typeof value === 'string'; + } + function isStringSafe(value) { + return objToString.call(value) === '[object String]'; + } + function isNumber(value) { + return typeof value === 'number'; + } + function isObject(value) { + var type = typeof value; + return type === 'function' || (!!value && type === 'object'); + } + function isBuiltInObject(value) { + return !!BUILTIN_OBJECT[objToString.call(value)]; + } + function isTypedArray(value) { + return !!TYPED_ARRAY[objToString.call(value)]; + } + function isDom(value) { + return typeof value === 'object' + && typeof value.nodeType === 'number' + && typeof value.ownerDocument === 'object'; + } + function isGradientObject(value) { + return value.colorStops != null; + } + function isPatternObject(value) { + return value.image != null; + } + function isRegExp(value) { + return objToString.call(value) === '[object RegExp]'; + } + function eqNaN(value) { + return value !== value; + } + function retrieve() { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + for (var i = 0, len = args.length; i < len; i++) { + if (args[i] != null) { + return args[i]; + } + } + } + function retrieve2(value0, value1) { + return value0 != null + ? value0 + : value1; + } + function retrieve3(value0, value1, value2) { + return value0 != null + ? value0 + : value1 != null + ? value1 + : value2; + } + function slice(arr) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + return nativeSlice.apply(arr, args); + } + function normalizeCssArray(val) { + if (typeof (val) === 'number') { + return [val, val, val, val]; + } + var len = val.length; + if (len === 2) { + return [val[0], val[1], val[0], val[1]]; + } + else if (len === 3) { + return [val[0], val[1], val[2], val[1]]; + } + return val; + } + function assert(condition, message) { + if (!condition) { + throw new Error(message); + } + } + function trim(str) { + if (str == null) { + return null; + } + else if (typeof str.trim === 'function') { + return str.trim(); + } + else { + return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); + } + } + var primitiveKey = '__ec_primitive__'; + function setAsPrimitive(obj) { + obj[primitiveKey] = true; + } + function isPrimitive(obj) { + return obj[primitiveKey]; + } + var HashMap = (function () { + function HashMap(obj) { + this.data = {}; + var isArr = isArray(obj); + this.data = {}; + var thisMap = this; + (obj instanceof HashMap) + ? obj.each(visit) + : (obj && each(obj, visit)); + function visit(value, key) { + isArr ? thisMap.set(value, key) : thisMap.set(key, value); + } + } + HashMap.prototype.get = function (key) { + return this.data.hasOwnProperty(key) ? this.data[key] : null; + }; + HashMap.prototype.set = function (key, value) { + return (this.data[key] = value); + }; + HashMap.prototype.each = function (cb, context) { + for (var key in this.data) { + if (this.data.hasOwnProperty(key)) { + cb.call(context, this.data[key], key); + } + } + }; + HashMap.prototype.keys = function () { + return keys(this.data); + }; + HashMap.prototype.removeKey = function (key) { + delete this.data[key]; + }; + return HashMap; + }()); + function createHashMap(obj) { + return new HashMap(obj); + } + function concatArray(a, b) { + var newArray = new a.constructor(a.length + b.length); + for (var i = 0; i < a.length; i++) { + newArray[i] = a[i]; + } + var offset = a.length; + for (var i = 0; i < b.length; i++) { + newArray[i + offset] = b[i]; + } + return newArray; + } + function createObject(proto, properties) { + var obj; + if (Object.create) { + obj = Object.create(proto); + } + else { + var StyleCtor = function () { }; + StyleCtor.prototype = proto; + obj = new StyleCtor(); + } + if (properties) { + extend(obj, properties); + } + return obj; + } + function hasOwn(own, prop) { + return own.hasOwnProperty(prop); + } + function noop() { } + + var util = /*#__PURE__*/Object.freeze({ + __proto__: null, + $override: $override, + guid: guid, + logError: logError, + clone: clone, + merge: merge, + mergeAll: mergeAll, + extend: extend, + defaults: defaults, + createCanvas: createCanvas, + indexOf: indexOf, + inherits: inherits, + mixin: mixin, + isArrayLike: isArrayLike, + each: each, + map: map, + reduce: reduce, + filter: filter, + find: find, + keys: keys, + bind: bind, + curry: curry, + isArray: isArray, + isFunction: isFunction, + isString: isString, + isStringSafe: isStringSafe, + isNumber: isNumber, + isObject: isObject, + isBuiltInObject: isBuiltInObject, + isTypedArray: isTypedArray, + isDom: isDom, + isGradientObject: isGradientObject, + isPatternObject: isPatternObject, + isRegExp: isRegExp, + eqNaN: eqNaN, + retrieve: retrieve, + retrieve2: retrieve2, + retrieve3: retrieve3, + slice: slice, + normalizeCssArray: normalizeCssArray, + assert: assert, + trim: trim, + setAsPrimitive: setAsPrimitive, + isPrimitive: isPrimitive, + HashMap: HashMap, + createHashMap: createHashMap, + concatArray: concatArray, + createObject: createObject, + hasOwn: hasOwn, + noop: noop + }); + + function create(x, y) { + if (x == null) { + x = 0; + } + if (y == null) { + y = 0; + } + return [x, y]; + } + function copy(out, v) { + out[0] = v[0]; + out[1] = v[1]; + return out; + } + function clone$1(v) { + return [v[0], v[1]]; + } + function set(out, a, b) { + out[0] = a; + out[1] = b; + return out; + } + function add(out, v1, v2) { + out[0] = v1[0] + v2[0]; + out[1] = v1[1] + v2[1]; + return out; + } + function scaleAndAdd(out, v1, v2, a) { + out[0] = v1[0] + v2[0] * a; + out[1] = v1[1] + v2[1] * a; + return out; + } + function sub(out, v1, v2) { + out[0] = v1[0] - v2[0]; + out[1] = v1[1] - v2[1]; + return out; + } + function len(v) { + return Math.sqrt(lenSquare(v)); + } + var length = len; + function lenSquare(v) { + return v[0] * v[0] + v[1] * v[1]; + } + var lengthSquare = lenSquare; + function mul(out, v1, v2) { + out[0] = v1[0] * v2[0]; + out[1] = v1[1] * v2[1]; + return out; + } + function div(out, v1, v2) { + out[0] = v1[0] / v2[0]; + out[1] = v1[1] / v2[1]; + return out; + } + function dot(v1, v2) { + return v1[0] * v2[0] + v1[1] * v2[1]; + } + function scale(out, v, s) { + out[0] = v[0] * s; + out[1] = v[1] * s; + return out; + } + function normalize(out, v) { + var d = len(v); + if (d === 0) { + out[0] = 0; + out[1] = 0; + } + else { + out[0] = v[0] / d; + out[1] = v[1] / d; + } + return out; + } + function distance(v1, v2) { + return Math.sqrt((v1[0] - v2[0]) * (v1[0] - v2[0]) + + (v1[1] - v2[1]) * (v1[1] - v2[1])); + } + var dist = distance; + function distanceSquare(v1, v2) { + return (v1[0] - v2[0]) * (v1[0] - v2[0]) + + (v1[1] - v2[1]) * (v1[1] - v2[1]); + } + var distSquare = distanceSquare; + function negate(out, v) { + out[0] = -v[0]; + out[1] = -v[1]; + return out; + } + function lerp(out, v1, v2, t) { + out[0] = v1[0] + t * (v2[0] - v1[0]); + out[1] = v1[1] + t * (v2[1] - v1[1]); + return out; + } + function applyTransform(out, v, m) { + var x = v[0]; + var y = v[1]; + out[0] = m[0] * x + m[2] * y + m[4]; + out[1] = m[1] * x + m[3] * y + m[5]; + return out; + } + function min(out, v1, v2) { + out[0] = Math.min(v1[0], v2[0]); + out[1] = Math.min(v1[1], v2[1]); + return out; + } + function max(out, v1, v2) { + out[0] = Math.max(v1[0], v2[0]); + out[1] = Math.max(v1[1], v2[1]); + return out; + } + + var vector = /*#__PURE__*/Object.freeze({ + __proto__: null, + create: create, + copy: copy, + clone: clone$1, + set: set, + add: add, + scaleAndAdd: scaleAndAdd, + sub: sub, + len: len, + length: length, + lenSquare: lenSquare, + lengthSquare: lengthSquare, + mul: mul, + div: div, + dot: dot, + scale: scale, + normalize: normalize, + distance: distance, + dist: dist, + distanceSquare: distanceSquare, + distSquare: distSquare, + negate: negate, + lerp: lerp, + applyTransform: applyTransform, + min: min, + max: max + }); + + var Param = (function () { + function Param(target, e) { + this.target = target; + this.topTarget = e && e.topTarget; + } + return Param; + }()); + var Draggable = (function () { + function Draggable(handler) { + this.handler = handler; + handler.on('mousedown', this._dragStart, this); + handler.on('mousemove', this._drag, this); + handler.on('mouseup', this._dragEnd, this); + } + Draggable.prototype._dragStart = function (e) { + var draggingTarget = e.target; + while (draggingTarget && !draggingTarget.draggable) { + draggingTarget = draggingTarget.parent; + } + if (draggingTarget) { + this._draggingTarget = draggingTarget; + draggingTarget.dragging = true; + this._x = e.offsetX; + this._y = e.offsetY; + this.handler.dispatchToElement(new Param(draggingTarget, e), 'dragstart', e.event); + } + }; + Draggable.prototype._drag = function (e) { + var draggingTarget = this._draggingTarget; + if (draggingTarget) { + var x = e.offsetX; + var y = e.offsetY; + var dx = x - this._x; + var dy = y - this._y; + this._x = x; + this._y = y; + draggingTarget.drift(dx, dy, e); + this.handler.dispatchToElement(new Param(draggingTarget, e), 'drag', e.event); + var dropTarget = this.handler.findHover(x, y, draggingTarget).target; + var lastDropTarget = this._dropTarget; + this._dropTarget = dropTarget; + if (draggingTarget !== dropTarget) { + if (lastDropTarget && dropTarget !== lastDropTarget) { + this.handler.dispatchToElement(new Param(lastDropTarget, e), 'dragleave', e.event); + } + if (dropTarget && dropTarget !== lastDropTarget) { + this.handler.dispatchToElement(new Param(dropTarget, e), 'dragenter', e.event); + } + } + } + }; + Draggable.prototype._dragEnd = function (e) { + var draggingTarget = this._draggingTarget; + if (draggingTarget) { + draggingTarget.dragging = false; + } + this.handler.dispatchToElement(new Param(draggingTarget, e), 'dragend', e.event); + if (this._dropTarget) { + this.handler.dispatchToElement(new Param(this._dropTarget, e), 'drop', e.event); + } + this._draggingTarget = null; + this._dropTarget = null; + }; + return Draggable; + }()); + + var Eventful = (function () { + function Eventful(eventProcessors) { + if (eventProcessors) { + this._$eventProcessor = eventProcessors; + } + } + Eventful.prototype.on = function (event, query, handler, context) { + if (!this._$handlers) { + this._$handlers = {}; + } + var _h = this._$handlers; + if (typeof query === 'function') { + context = handler; + handler = query; + query = null; + } + if (!handler || !event) { + return this; + } + var eventProcessor = this._$eventProcessor; + if (query != null && eventProcessor && eventProcessor.normalizeQuery) { + query = eventProcessor.normalizeQuery(query); + } + if (!_h[event]) { + _h[event] = []; + } + for (var i = 0; i < _h[event].length; i++) { + if (_h[event][i].h === handler) { + return this; + } + } + var wrap = { + h: handler, + query: query, + ctx: (context || this), + callAtLast: handler.zrEventfulCallAtLast + }; + var lastIndex = _h[event].length - 1; + var lastWrap = _h[event][lastIndex]; + (lastWrap && lastWrap.callAtLast) + ? _h[event].splice(lastIndex, 0, wrap) + : _h[event].push(wrap); + return this; + }; + Eventful.prototype.isSilent = function (eventName) { + var _h = this._$handlers; + return !_h || !_h[eventName] || !_h[eventName].length; + }; + Eventful.prototype.off = function (eventType, handler) { + var _h = this._$handlers; + if (!_h) { + return this; + } + if (!eventType) { + this._$handlers = {}; + return this; + } + if (handler) { + if (_h[eventType]) { + var newList = []; + for (var i = 0, l = _h[eventType].length; i < l; i++) { + if (_h[eventType][i].h !== handler) { + newList.push(_h[eventType][i]); + } + } + _h[eventType] = newList; + } + if (_h[eventType] && _h[eventType].length === 0) { + delete _h[eventType]; + } + } + else { + delete _h[eventType]; + } + return this; + }; + Eventful.prototype.trigger = function (eventType) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + if (!this._$handlers) { + return this; + } + var _h = this._$handlers[eventType]; + var eventProcessor = this._$eventProcessor; + if (_h) { + var argLen = args.length; + var len = _h.length; + for (var i = 0; i < len; i++) { + var hItem = _h[i]; + if (eventProcessor + && eventProcessor.filter + && hItem.query != null + && !eventProcessor.filter(eventType, hItem.query)) { + continue; + } + switch (argLen) { + case 0: + hItem.h.call(hItem.ctx); + break; + case 1: + hItem.h.call(hItem.ctx, args[0]); + break; + case 2: + hItem.h.call(hItem.ctx, args[0], args[1]); + break; + default: + hItem.h.apply(hItem.ctx, args); + break; + } + } + } + eventProcessor && eventProcessor.afterTrigger + && eventProcessor.afterTrigger(eventType); + return this; + }; + Eventful.prototype.triggerWithContext = function (type) { + if (!this._$handlers) { + return this; + } + var _h = this._$handlers[type]; + var eventProcessor = this._$eventProcessor; + if (_h) { + var args = arguments; + var argLen = args.length; + var ctx = args[argLen - 1]; + var len = _h.length; + for (var i = 0; i < len; i++) { + var hItem = _h[i]; + if (eventProcessor + && eventProcessor.filter + && hItem.query != null + && !eventProcessor.filter(type, hItem.query)) { + continue; + } + switch (argLen) { + case 0: + hItem.h.call(ctx); + break; + case 1: + hItem.h.call(ctx, args[0]); + break; + case 2: + hItem.h.call(ctx, args[0], args[1]); + break; + default: + hItem.h.apply(ctx, args.slice(1, argLen - 1)); + break; + } + } + } + eventProcessor && eventProcessor.afterTrigger + && eventProcessor.afterTrigger(type); + return this; + }; + return Eventful; + }()); + + var LN2 = Math.log(2); + function determinant(rows, rank, rowStart, rowMask, colMask, detCache) { + var cacheKey = rowMask + '-' + colMask; + var fullRank = rows.length; + if (detCache.hasOwnProperty(cacheKey)) { + return detCache[cacheKey]; + } + if (rank === 1) { + var colStart = Math.round(Math.log(((1 << fullRank) - 1) & ~colMask) / LN2); + return rows[rowStart][colStart]; + } + var subRowMask = rowMask | (1 << rowStart); + var subRowStart = rowStart + 1; + while (rowMask & (1 << subRowStart)) { + subRowStart++; + } + var sum = 0; + for (var j = 0, colLocalIdx = 0; j < fullRank; j++) { + var colTag = 1 << j; + if (!(colTag & colMask)) { + sum += (colLocalIdx % 2 ? -1 : 1) * rows[rowStart][j] + * determinant(rows, rank - 1, subRowStart, subRowMask, colMask | colTag, detCache); + colLocalIdx++; + } + } + detCache[cacheKey] = sum; + return sum; + } + function buildTransformer(src, dest) { + var mA = [ + [src[0], src[1], 1, 0, 0, 0, -dest[0] * src[0], -dest[0] * src[1]], + [0, 0, 0, src[0], src[1], 1, -dest[1] * src[0], -dest[1] * src[1]], + [src[2], src[3], 1, 0, 0, 0, -dest[2] * src[2], -dest[2] * src[3]], + [0, 0, 0, src[2], src[3], 1, -dest[3] * src[2], -dest[3] * src[3]], + [src[4], src[5], 1, 0, 0, 0, -dest[4] * src[4], -dest[4] * src[5]], + [0, 0, 0, src[4], src[5], 1, -dest[5] * src[4], -dest[5] * src[5]], + [src[6], src[7], 1, 0, 0, 0, -dest[6] * src[6], -dest[6] * src[7]], + [0, 0, 0, src[6], src[7], 1, -dest[7] * src[6], -dest[7] * src[7]] + ]; + var detCache = {}; + var det = determinant(mA, 8, 0, 0, 0, detCache); + if (det === 0) { + return; + } + var vh = []; + for (var i = 0; i < 8; i++) { + for (var j = 0; j < 8; j++) { + vh[j] == null && (vh[j] = 0); + vh[j] += ((i + j) % 2 ? -1 : 1) + * determinant(mA, 7, i === 0 ? 1 : 0, 1 << i, 1 << j, detCache) + / det * dest[i]; + } + } + return function (out, srcPointX, srcPointY) { + var pk = srcPointX * vh[6] + srcPointY * vh[7] + 1; + out[0] = (srcPointX * vh[0] + srcPointY * vh[1] + vh[2]) / pk; + out[1] = (srcPointX * vh[3] + srcPointY * vh[4] + vh[5]) / pk; + }; + } + + var EVENT_SAVED_PROP = '___zrEVENTSAVED'; + var _calcOut = []; + function transformLocalCoord(out, elFrom, elTarget, inX, inY) { + return transformCoordWithViewport(_calcOut, elFrom, inX, inY, true) + && transformCoordWithViewport(out, elTarget, _calcOut[0], _calcOut[1]); + } + function transformCoordWithViewport(out, el, inX, inY, inverse) { + if (el.getBoundingClientRect && env.domSupported && !isCanvasEl(el)) { + var saved = el[EVENT_SAVED_PROP] || (el[EVENT_SAVED_PROP] = {}); + var markers = prepareCoordMarkers(el, saved); + var transformer = preparePointerTransformer(markers, saved, inverse); + if (transformer) { + transformer(out, inX, inY); + return true; + } + } + return false; + } + function prepareCoordMarkers(el, saved) { + var markers = saved.markers; + if (markers) { + return markers; + } + markers = saved.markers = []; + var propLR = ['left', 'right']; + var propTB = ['top', 'bottom']; + for (var i = 0; i < 4; i++) { + var marker = document.createElement('div'); + var stl = marker.style; + var idxLR = i % 2; + var idxTB = (i >> 1) % 2; + stl.cssText = [ + 'position: absolute', + 'visibility: hidden', + 'padding: 0', + 'margin: 0', + 'border-width: 0', + 'user-select: none', + 'width:0', + 'height:0', + propLR[idxLR] + ':0', + propTB[idxTB] + ':0', + propLR[1 - idxLR] + ':auto', + propTB[1 - idxTB] + ':auto', + '' + ].join('!important;'); + el.appendChild(marker); + markers.push(marker); + } + return markers; + } + function preparePointerTransformer(markers, saved, inverse) { + var transformerName = inverse ? 'invTrans' : 'trans'; + var transformer = saved[transformerName]; + var oldSrcCoords = saved.srcCoords; + var srcCoords = []; + var destCoords = []; + var oldCoordTheSame = true; + for (var i = 0; i < 4; i++) { + var rect = markers[i].getBoundingClientRect(); + var ii = 2 * i; + var x = rect.left; + var y = rect.top; + srcCoords.push(x, y); + oldCoordTheSame = oldCoordTheSame && oldSrcCoords && x === oldSrcCoords[ii] && y === oldSrcCoords[ii + 1]; + destCoords.push(markers[i].offsetLeft, markers[i].offsetTop); + } + return (oldCoordTheSame && transformer) + ? transformer + : (saved.srcCoords = srcCoords, + saved[transformerName] = inverse + ? buildTransformer(destCoords, srcCoords) + : buildTransformer(srcCoords, destCoords)); + } + function isCanvasEl(el) { + return el.nodeName.toUpperCase() === 'CANVAS'; + } + + var isDomLevel2 = (typeof window !== 'undefined') && !!window.addEventListener; + var MOUSE_EVENT_REG = /^(?:mouse|pointer|contextmenu|drag|drop)|click/; + var _calcOut$1 = []; + function clientToLocal(el, e, out, calculate) { + out = out || {}; + if (calculate || !env.canvasSupported) { + calculateZrXY(el, e, out); + } + else if (env.browser.firefox + && e.layerX != null + && e.layerX !== e.offsetX) { + out.zrX = e.layerX; + out.zrY = e.layerY; + } + else if (e.offsetX != null) { + out.zrX = e.offsetX; + out.zrY = e.offsetY; + } + else { + calculateZrXY(el, e, out); + } + return out; + } + function calculateZrXY(el, e, out) { + if (env.domSupported && el.getBoundingClientRect) { + var ex = e.clientX; + var ey = e.clientY; + if (isCanvasEl(el)) { + var box = el.getBoundingClientRect(); + out.zrX = ex - box.left; + out.zrY = ey - box.top; + return; + } + else { + if (transformCoordWithViewport(_calcOut$1, el, ex, ey)) { + out.zrX = _calcOut$1[0]; + out.zrY = _calcOut$1[1]; + return; + } + } + } + out.zrX = out.zrY = 0; + } + function getNativeEvent(e) { + return e + || window.event; + } + function normalizeEvent(el, e, calculate) { + e = getNativeEvent(e); + if (e.zrX != null) { + return e; + } + var eventType = e.type; + var isTouch = eventType && eventType.indexOf('touch') >= 0; + if (!isTouch) { + clientToLocal(el, e, e, calculate); + var wheelDelta = getWheelDeltaMayPolyfill(e); + e.zrDelta = wheelDelta ? wheelDelta / 120 : -(e.detail || 0) / 3; + } + else { + var touch = eventType !== 'touchend' + ? e.targetTouches[0] + : e.changedTouches[0]; + touch && clientToLocal(el, touch, e, calculate); + } + var button = e.button; + if (e.which == null && button !== undefined && MOUSE_EVENT_REG.test(e.type)) { + e.which = (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0))); + } + return e; + } + function getWheelDeltaMayPolyfill(e) { + var rawWheelDelta = e.wheelDelta; + if (rawWheelDelta) { + return rawWheelDelta; + } + var deltaX = e.deltaX; + var deltaY = e.deltaY; + if (deltaX == null || deltaY == null) { + return rawWheelDelta; + } + var delta = deltaY !== 0 ? Math.abs(deltaY) : Math.abs(deltaX); + var sign = deltaY > 0 ? -1 + : deltaY < 0 ? 1 + : deltaX > 0 ? -1 + : 1; + return 3 * delta * sign; + } + function addEventListener(el, name, handler, opt) { + if (isDomLevel2) { + el.addEventListener(name, handler, opt); + } + else { + el.attachEvent('on' + name, handler); + } + } + function removeEventListener(el, name, handler, opt) { + if (isDomLevel2) { + el.removeEventListener(name, handler, opt); + } + else { + el.detachEvent('on' + name, handler); + } + } + var stop = isDomLevel2 + ? function (e) { + e.preventDefault(); + e.stopPropagation(); + e.cancelBubble = true; + } + : function (e) { + e.returnValue = false; + e.cancelBubble = true; + }; + function isMiddleOrRightButtonOnMouseUpDown(e) { + return e.which === 2 || e.which === 3; + } + + var GestureMgr = (function () { + function GestureMgr() { + this._track = []; + } + GestureMgr.prototype.recognize = function (event, target, root) { + this._doTrack(event, target, root); + return this._recognize(event); + }; + GestureMgr.prototype.clear = function () { + this._track.length = 0; + return this; + }; + GestureMgr.prototype._doTrack = function (event, target, root) { + var touches = event.touches; + if (!touches) { + return; + } + var trackItem = { + points: [], + touches: [], + target: target, + event: event + }; + for (var i = 0, len = touches.length; i < len; i++) { + var touch = touches[i]; + var pos = clientToLocal(root, touch, {}); + trackItem.points.push([pos.zrX, pos.zrY]); + trackItem.touches.push(touch); + } + this._track.push(trackItem); + }; + GestureMgr.prototype._recognize = function (event) { + for (var eventName in recognizers) { + if (recognizers.hasOwnProperty(eventName)) { + var gestureInfo = recognizers[eventName](this._track, event); + if (gestureInfo) { + return gestureInfo; + } + } + } + }; + return GestureMgr; + }()); + function dist$1(pointPair) { + var dx = pointPair[1][0] - pointPair[0][0]; + var dy = pointPair[1][1] - pointPair[0][1]; + return Math.sqrt(dx * dx + dy * dy); + } + function center(pointPair) { + return [ + (pointPair[0][0] + pointPair[1][0]) / 2, + (pointPair[0][1] + pointPair[1][1]) / 2 + ]; + } + var recognizers = { + pinch: function (tracks, event) { + var trackLen = tracks.length; + if (!trackLen) { + return; + } + var pinchEnd = (tracks[trackLen - 1] || {}).points; + var pinchPre = (tracks[trackLen - 2] || {}).points || pinchEnd; + if (pinchPre + && pinchPre.length > 1 + && pinchEnd + && pinchEnd.length > 1) { + var pinchScale = dist$1(pinchEnd) / dist$1(pinchPre); + !isFinite(pinchScale) && (pinchScale = 1); + event.pinchScale = pinchScale; + var pinchCenter = center(pinchEnd); + event.pinchX = pinchCenter[0]; + event.pinchY = pinchCenter[1]; + return { + type: 'pinch', + target: tracks[0].target, + event: event + }; + } + } + }; + + var SILENT = 'silent'; + function makeEventPacket(eveType, targetInfo, event) { + return { + type: eveType, + event: event, + target: targetInfo.target, + topTarget: targetInfo.topTarget, + cancelBubble: false, + offsetX: event.zrX, + offsetY: event.zrY, + gestureEvent: event.gestureEvent, + pinchX: event.pinchX, + pinchY: event.pinchY, + pinchScale: event.pinchScale, + wheelDelta: event.zrDelta, + zrByTouch: event.zrByTouch, + which: event.which, + stop: stopEvent + }; + } + function stopEvent() { + stop(this.event); + } + var EmptyProxy = (function (_super) { + __extends(EmptyProxy, _super); + function EmptyProxy() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.handler = null; + return _this; + } + EmptyProxy.prototype.dispose = function () { }; + EmptyProxy.prototype.setCursor = function () { }; + return EmptyProxy; + }(Eventful)); + var HoveredResult = (function () { + function HoveredResult(x, y) { + this.x = x; + this.y = y; + } + return HoveredResult; + }()); + var handlerNames = [ + 'click', 'dblclick', 'mousewheel', 'mouseout', + 'mouseup', 'mousedown', 'mousemove', 'contextmenu' + ]; + var Handler = (function (_super) { + __extends(Handler, _super); + function Handler(storage, painter, proxy, painterRoot) { + var _this = _super.call(this) || this; + _this._hovered = new HoveredResult(0, 0); + _this.storage = storage; + _this.painter = painter; + _this.painterRoot = painterRoot; + proxy = proxy || new EmptyProxy(); + _this.proxy = null; + _this.setHandlerProxy(proxy); + _this._draggingMgr = new Draggable(_this); + return _this; + } + Handler.prototype.setHandlerProxy = function (proxy) { + if (this.proxy) { + this.proxy.dispose(); + } + if (proxy) { + each(handlerNames, function (name) { + proxy.on && proxy.on(name, this[name], this); + }, this); + proxy.handler = this; + } + this.proxy = proxy; + }; + Handler.prototype.mousemove = function (event) { + var x = event.zrX; + var y = event.zrY; + var isOutside = isOutsideBoundary(this, x, y); + var lastHovered = this._hovered; + var lastHoveredTarget = lastHovered.target; + if (lastHoveredTarget && !lastHoveredTarget.__zr) { + lastHovered = this.findHover(lastHovered.x, lastHovered.y); + lastHoveredTarget = lastHovered.target; + } + var hovered = this._hovered = isOutside ? new HoveredResult(x, y) : this.findHover(x, y); + var hoveredTarget = hovered.target; + var proxy = this.proxy; + proxy.setCursor && proxy.setCursor(hoveredTarget ? hoveredTarget.cursor : 'default'); + if (lastHoveredTarget && hoveredTarget !== lastHoveredTarget) { + this.dispatchToElement(lastHovered, 'mouseout', event); + } + this.dispatchToElement(hovered, 'mousemove', event); + if (hoveredTarget && hoveredTarget !== lastHoveredTarget) { + this.dispatchToElement(hovered, 'mouseover', event); + } + }; + Handler.prototype.mouseout = function (event) { + var eventControl = event.zrEventControl; + if (eventControl !== 'only_globalout') { + this.dispatchToElement(this._hovered, 'mouseout', event); + } + if (eventControl !== 'no_globalout') { + this.trigger('globalout', { type: 'globalout', event: event }); + } + }; + Handler.prototype.resize = function () { + this._hovered = new HoveredResult(0, 0); + }; + Handler.prototype.dispatch = function (eventName, eventArgs) { + var handler = this[eventName]; + handler && handler.call(this, eventArgs); + }; + Handler.prototype.dispose = function () { + this.proxy.dispose(); + this.storage = null; + this.proxy = null; + this.painter = null; + }; + Handler.prototype.setCursorStyle = function (cursorStyle) { + var proxy = this.proxy; + proxy.setCursor && proxy.setCursor(cursorStyle); + }; + Handler.prototype.dispatchToElement = function (targetInfo, eventName, event) { + targetInfo = targetInfo || {}; + var el = targetInfo.target; + if (el && el.silent) { + return; + } + var eventKey = ('on' + eventName); + var eventPacket = makeEventPacket(eventName, targetInfo, event); + while (el) { + el[eventKey] + && (eventPacket.cancelBubble = !!el[eventKey].call(el, eventPacket)); + el.trigger(eventName, eventPacket); + el = el.__hostTarget ? el.__hostTarget : el.parent; + if (eventPacket.cancelBubble) { + break; + } + } + if (!eventPacket.cancelBubble) { + this.trigger(eventName, eventPacket); + if (this.painter && this.painter.eachOtherLayer) { + this.painter.eachOtherLayer(function (layer) { + if (typeof (layer[eventKey]) === 'function') { + layer[eventKey].call(layer, eventPacket); + } + if (layer.trigger) { + layer.trigger(eventName, eventPacket); + } + }); + } + } + }; + Handler.prototype.findHover = function (x, y, exclude) { + var list = this.storage.getDisplayList(); + var out = new HoveredResult(x, y); + for (var i = list.length - 1; i >= 0; i--) { + var hoverCheckResult = void 0; + if (list[i] !== exclude + && !list[i].ignore + && (hoverCheckResult = isHover(list[i], x, y))) { + !out.topTarget && (out.topTarget = list[i]); + if (hoverCheckResult !== SILENT) { + out.target = list[i]; + break; + } + } + } + return out; + }; + Handler.prototype.processGesture = function (event, stage) { + if (!this._gestureMgr) { + this._gestureMgr = new GestureMgr(); + } + var gestureMgr = this._gestureMgr; + stage === 'start' && gestureMgr.clear(); + var gestureInfo = gestureMgr.recognize(event, this.findHover(event.zrX, event.zrY, null).target, this.proxy.dom); + stage === 'end' && gestureMgr.clear(); + if (gestureInfo) { + var type = gestureInfo.type; + event.gestureEvent = type; + var res = new HoveredResult(); + res.target = gestureInfo.target; + this.dispatchToElement(res, type, gestureInfo.event); + } + }; + return Handler; + }(Eventful)); + each(['click', 'mousedown', 'mouseup', 'mousewheel', 'dblclick', 'contextmenu'], function (name) { + Handler.prototype[name] = function (event) { + var x = event.zrX; + var y = event.zrY; + var isOutside = isOutsideBoundary(this, x, y); + var hovered; + var hoveredTarget; + if (name !== 'mouseup' || !isOutside) { + hovered = this.findHover(x, y); + hoveredTarget = hovered.target; + } + if (name === 'mousedown') { + this._downEl = hoveredTarget; + this._downPoint = [event.zrX, event.zrY]; + this._upEl = hoveredTarget; + } + else if (name === 'mouseup') { + this._upEl = hoveredTarget; + } + else if (name === 'click') { + if (this._downEl !== this._upEl + || !this._downPoint + || dist(this._downPoint, [event.zrX, event.zrY]) > 4) { + return; + } + this._downPoint = null; + } + this.dispatchToElement(hovered, name, event); + }; + }); + function isHover(displayable, x, y) { + if (displayable[displayable.rectHover ? 'rectContain' : 'contain'](x, y)) { + var el = displayable; + var isSilent = void 0; + var ignoreClip = false; + while (el) { + if (el.ignoreClip) { + ignoreClip = true; + } + if (!ignoreClip) { + var clipPath = el.getClipPath(); + if (clipPath && !clipPath.contain(x, y)) { + return false; + } + if (el.silent) { + isSilent = true; + } + } + var hostEl = el.__hostTarget; + el = hostEl ? hostEl : el.parent; + } + return isSilent ? SILENT : true; + } + return false; + } + function isOutsideBoundary(handlerInstance, x, y) { + var painter = handlerInstance.painter; + return x < 0 || x > painter.getWidth() || y < 0 || y > painter.getHeight(); + } + + function create$1() { + return [1, 0, 0, 1, 0, 0]; + } + function identity(out) { + out[0] = 1; + out[1] = 0; + out[2] = 0; + out[3] = 1; + out[4] = 0; + out[5] = 0; + return out; + } + function copy$1(out, m) { + out[0] = m[0]; + out[1] = m[1]; + out[2] = m[2]; + out[3] = m[3]; + out[4] = m[4]; + out[5] = m[5]; + return out; + } + function mul$1(out, m1, m2) { + var out0 = m1[0] * m2[0] + m1[2] * m2[1]; + var out1 = m1[1] * m2[0] + m1[3] * m2[1]; + var out2 = m1[0] * m2[2] + m1[2] * m2[3]; + var out3 = m1[1] * m2[2] + m1[3] * m2[3]; + var out4 = m1[0] * m2[4] + m1[2] * m2[5] + m1[4]; + var out5 = m1[1] * m2[4] + m1[3] * m2[5] + m1[5]; + out[0] = out0; + out[1] = out1; + out[2] = out2; + out[3] = out3; + out[4] = out4; + out[5] = out5; + return out; + } + function translate(out, a, v) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + out[4] = a[4] + v[0]; + out[5] = a[5] + v[1]; + return out; + } + function rotate(out, a, rad) { + var aa = a[0]; + var ac = a[2]; + var atx = a[4]; + var ab = a[1]; + var ad = a[3]; + var aty = a[5]; + var st = Math.sin(rad); + var ct = Math.cos(rad); + out[0] = aa * ct + ab * st; + out[1] = -aa * st + ab * ct; + out[2] = ac * ct + ad * st; + out[3] = -ac * st + ct * ad; + out[4] = ct * atx + st * aty; + out[5] = ct * aty - st * atx; + return out; + } + function scale$1(out, a, v) { + var vx = v[0]; + var vy = v[1]; + out[0] = a[0] * vx; + out[1] = a[1] * vy; + out[2] = a[2] * vx; + out[3] = a[3] * vy; + out[4] = a[4] * vx; + out[5] = a[5] * vy; + return out; + } + function invert(out, a) { + var aa = a[0]; + var ac = a[2]; + var atx = a[4]; + var ab = a[1]; + var ad = a[3]; + var aty = a[5]; + var det = aa * ad - ab * ac; + if (!det) { + return null; + } + det = 1.0 / det; + out[0] = ad * det; + out[1] = -ab * det; + out[2] = -ac * det; + out[3] = aa * det; + out[4] = (ac * aty - ad * atx) * det; + out[5] = (ab * atx - aa * aty) * det; + return out; + } + function clone$2(a) { + var b = create$1(); + copy$1(b, a); + return b; + } + + var matrix = /*#__PURE__*/Object.freeze({ + __proto__: null, + create: create$1, + identity: identity, + copy: copy$1, + mul: mul$1, + translate: translate, + rotate: rotate, + scale: scale$1, + invert: invert, + clone: clone$2 + }); + + var mIdentity = identity; + var EPSILON = 5e-5; + function isNotAroundZero(val) { + return val > EPSILON || val < -EPSILON; + } + var scaleTmp = []; + var tmpTransform = []; + var originTransform = create$1(); + var abs = Math.abs; + var Transformable = (function () { + function Transformable() { + } + Transformable.prototype.setPosition = function (arr) { + this.x = arr[0]; + this.y = arr[1]; + }; + Transformable.prototype.setScale = function (arr) { + this.scaleX = arr[0]; + this.scaleY = arr[1]; + }; + Transformable.prototype.setOrigin = function (arr) { + this.originX = arr[0]; + this.originY = arr[1]; + }; + Transformable.prototype.needLocalTransform = function () { + return isNotAroundZero(this.rotation) + || isNotAroundZero(this.x) + || isNotAroundZero(this.y) + || isNotAroundZero(this.scaleX - 1) + || isNotAroundZero(this.scaleY - 1); + }; + Transformable.prototype.updateTransform = function () { + var parent = this.parent; + var parentHasTransform = parent && parent.transform; + var needLocalTransform = this.needLocalTransform(); + var m = this.transform; + if (!(needLocalTransform || parentHasTransform)) { + m && mIdentity(m); + return; + } + m = m || create$1(); + if (needLocalTransform) { + this.getLocalTransform(m); + } + else { + mIdentity(m); + } + if (parentHasTransform) { + if (needLocalTransform) { + mul$1(m, parent.transform, m); + } + else { + copy$1(m, parent.transform); + } + } + this.transform = m; + this._resolveGlobalScaleRatio(m); + }; + Transformable.prototype._resolveGlobalScaleRatio = function (m) { + var globalScaleRatio = this.globalScaleRatio; + if (globalScaleRatio != null && globalScaleRatio !== 1) { + this.getGlobalScale(scaleTmp); + var relX = scaleTmp[0] < 0 ? -1 : 1; + var relY = scaleTmp[1] < 0 ? -1 : 1; + var sx = ((scaleTmp[0] - relX) * globalScaleRatio + relX) / scaleTmp[0] || 0; + var sy = ((scaleTmp[1] - relY) * globalScaleRatio + relY) / scaleTmp[1] || 0; + m[0] *= sx; + m[1] *= sx; + m[2] *= sy; + m[3] *= sy; + } + this.invTransform = this.invTransform || create$1(); + invert(this.invTransform, m); + }; + Transformable.prototype.getLocalTransform = function (m) { + return Transformable.getLocalTransform(this, m); + }; + Transformable.prototype.getComputedTransform = function () { + var transformNode = this; + var ancestors = []; + while (transformNode) { + ancestors.push(transformNode); + transformNode = transformNode.parent; + } + while (transformNode = ancestors.pop()) { + transformNode.updateTransform(); + } + return this.transform; + }; + Transformable.prototype.setLocalTransform = function (m) { + if (!m) { + return; + } + var sx = m[0] * m[0] + m[1] * m[1]; + var sy = m[2] * m[2] + m[3] * m[3]; + if (isNotAroundZero(sx - 1)) { + sx = Math.sqrt(sx); + } + if (isNotAroundZero(sy - 1)) { + sy = Math.sqrt(sy); + } + if (m[0] < 0) { + sx = -sx; + } + if (m[3] < 0) { + sy = -sy; + } + this.rotation = Math.atan2(-m[1] / sy, m[0] / sx); + if (sx < 0 && sy < 0) { + this.rotation += Math.PI; + sx = -sx; + sy = -sy; + } + this.x = m[4]; + this.y = m[5]; + this.scaleX = sx; + this.scaleY = sy; + }; + Transformable.prototype.decomposeTransform = function () { + if (!this.transform) { + return; + } + var parent = this.parent; + var m = this.transform; + if (parent && parent.transform) { + mul$1(tmpTransform, parent.invTransform, m); + m = tmpTransform; + } + var ox = this.originX; + var oy = this.originY; + if (ox || oy) { + originTransform[4] = ox; + originTransform[5] = oy; + mul$1(tmpTransform, m, originTransform); + tmpTransform[4] -= ox; + tmpTransform[5] -= oy; + m = tmpTransform; + } + this.setLocalTransform(m); + }; + Transformable.prototype.getGlobalScale = function (out) { + var m = this.transform; + out = out || []; + if (!m) { + out[0] = 1; + out[1] = 1; + return out; + } + out[0] = Math.sqrt(m[0] * m[0] + m[1] * m[1]); + out[1] = Math.sqrt(m[2] * m[2] + m[3] * m[3]); + if (m[0] < 0) { + out[0] = -out[0]; + } + if (m[3] < 0) { + out[1] = -out[1]; + } + return out; + }; + Transformable.prototype.transformCoordToLocal = function (x, y) { + var v2 = [x, y]; + var invTransform = this.invTransform; + if (invTransform) { + applyTransform(v2, v2, invTransform); + } + return v2; + }; + Transformable.prototype.transformCoordToGlobal = function (x, y) { + var v2 = [x, y]; + var transform = this.transform; + if (transform) { + applyTransform(v2, v2, transform); + } + return v2; + }; + Transformable.prototype.getLineScale = function () { + var m = this.transform; + return m && abs(m[0] - 1) > 1e-10 && abs(m[3] - 1) > 1e-10 + ? Math.sqrt(abs(m[0] * m[3] - m[2] * m[1])) + : 1; + }; + Transformable.getLocalTransform = function (target, m) { + m = m || []; + mIdentity(m); + var ox = target.originX || 0; + var oy = target.originY || 0; + var sx = target.scaleX; + var sy = target.scaleY; + var rotation = target.rotation || 0; + var x = target.x; + var y = target.y; + m[4] -= ox; + m[5] -= oy; + m[0] *= sx; + m[1] *= sy; + m[2] *= sx; + m[3] *= sy; + m[4] *= sx; + m[5] *= sy; + if (rotation) { + rotate(m, m, rotation); + } + m[4] += ox; + m[5] += oy; + m[4] += x; + m[5] += y; + return m; + }; + Transformable.initDefaultProps = (function () { + var proto = Transformable.prototype; + proto.x = 0; + proto.y = 0; + proto.scaleX = 1; + proto.scaleY = 1; + proto.originX = 0; + proto.originY = 0; + proto.rotation = 0; + proto.globalScaleRatio = 1; + })(); + return Transformable; + }()); + + var easing = { + linear: function (k) { + return k; + }, + quadraticIn: function (k) { + return k * k; + }, + quadraticOut: function (k) { + return k * (2 - k); + }, + quadraticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k; + } + return -0.5 * (--k * (k - 2) - 1); + }, + cubicIn: function (k) { + return k * k * k; + }, + cubicOut: function (k) { + return --k * k * k + 1; + }, + cubicInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k; + } + return 0.5 * ((k -= 2) * k * k + 2); + }, + quarticIn: function (k) { + return k * k * k * k; + }, + quarticOut: function (k) { + return 1 - (--k * k * k * k); + }, + quarticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k * k; + } + return -0.5 * ((k -= 2) * k * k * k - 2); + }, + quinticIn: function (k) { + return k * k * k * k * k; + }, + quinticOut: function (k) { + return --k * k * k * k * k + 1; + }, + quinticInOut: function (k) { + if ((k *= 2) < 1) { + return 0.5 * k * k * k * k * k; + } + return 0.5 * ((k -= 2) * k * k * k * k + 2); + }, + sinusoidalIn: function (k) { + return 1 - Math.cos(k * Math.PI / 2); + }, + sinusoidalOut: function (k) { + return Math.sin(k * Math.PI / 2); + }, + sinusoidalInOut: function (k) { + return 0.5 * (1 - Math.cos(Math.PI * k)); + }, + exponentialIn: function (k) { + return k === 0 ? 0 : Math.pow(1024, k - 1); + }, + exponentialOut: function (k) { + return k === 1 ? 1 : 1 - Math.pow(2, -10 * k); + }, + exponentialInOut: function (k) { + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if ((k *= 2) < 1) { + return 0.5 * Math.pow(1024, k - 1); + } + return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2); + }, + circularIn: function (k) { + return 1 - Math.sqrt(1 - k * k); + }, + circularOut: function (k) { + return Math.sqrt(1 - (--k * k)); + }, + circularInOut: function (k) { + if ((k *= 2) < 1) { + return -0.5 * (Math.sqrt(1 - k * k) - 1); + } + return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1); + }, + elasticIn: function (k) { + var s; + var a = 0.1; + var p = 0.4; + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if (!a || a < 1) { + a = 1; + s = p / 4; + } + else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + return -(a * Math.pow(2, 10 * (k -= 1)) + * Math.sin((k - s) * (2 * Math.PI) / p)); + }, + elasticOut: function (k) { + var s; + var a = 0.1; + var p = 0.4; + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if (!a || a < 1) { + a = 1; + s = p / 4; + } + else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + return (a * Math.pow(2, -10 * k) + * Math.sin((k - s) * (2 * Math.PI) / p) + 1); + }, + elasticInOut: function (k) { + var s; + var a = 0.1; + var p = 0.4; + if (k === 0) { + return 0; + } + if (k === 1) { + return 1; + } + if (!a || a < 1) { + a = 1; + s = p / 4; + } + else { + s = p * Math.asin(1 / a) / (2 * Math.PI); + } + if ((k *= 2) < 1) { + return -0.5 * (a * Math.pow(2, 10 * (k -= 1)) + * Math.sin((k - s) * (2 * Math.PI) / p)); + } + return a * Math.pow(2, -10 * (k -= 1)) + * Math.sin((k - s) * (2 * Math.PI) / p) * 0.5 + 1; + }, + backIn: function (k) { + var s = 1.70158; + return k * k * ((s + 1) * k - s); + }, + backOut: function (k) { + var s = 1.70158; + return --k * k * ((s + 1) * k + s) + 1; + }, + backInOut: function (k) { + var s = 1.70158 * 1.525; + if ((k *= 2) < 1) { + return 0.5 * (k * k * ((s + 1) * k - s)); + } + return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2); + }, + bounceIn: function (k) { + return 1 - easing.bounceOut(1 - k); + }, + bounceOut: function (k) { + if (k < (1 / 2.75)) { + return 7.5625 * k * k; + } + else if (k < (2 / 2.75)) { + return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75; + } + else if (k < (2.5 / 2.75)) { + return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375; + } + else { + return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375; + } + }, + bounceInOut: function (k) { + if (k < 0.5) { + return easing.bounceIn(k * 2) * 0.5; + } + return easing.bounceOut(k * 2 - 1) * 0.5 + 0.5; + } + }; + + var Clip = (function () { + function Clip(opts) { + this._initialized = false; + this._startTime = 0; + this._pausedTime = 0; + this._paused = false; + this._life = opts.life || 1000; + this._delay = opts.delay || 0; + this.loop = opts.loop == null ? false : opts.loop; + this.gap = opts.gap || 0; + this.easing = opts.easing || 'linear'; + this.onframe = opts.onframe; + this.ondestroy = opts.ondestroy; + this.onrestart = opts.onrestart; + } + Clip.prototype.step = function (globalTime, deltaTime) { + if (!this._initialized) { + this._startTime = globalTime + this._delay; + this._initialized = true; + } + if (this._paused) { + this._pausedTime += deltaTime; + return; + } + var percent = (globalTime - this._startTime - this._pausedTime) / this._life; + if (percent < 0) { + percent = 0; + } + percent = Math.min(percent, 1); + var easing$1 = this.easing; + var easingFunc = typeof easing$1 === 'string' + ? easing[easing$1] : easing$1; + var schedule = typeof easingFunc === 'function' + ? easingFunc(percent) + : percent; + this.onframe && this.onframe(schedule); + if (percent === 1) { + if (this.loop) { + this._restart(globalTime); + this.onrestart && this.onrestart(); + } + else { + return true; + } + } + return false; + }; + Clip.prototype._restart = function (globalTime) { + var remainder = (globalTime - this._startTime - this._pausedTime) % this._life; + this._startTime = globalTime - remainder + this.gap; + this._pausedTime = 0; + }; + Clip.prototype.pause = function () { + this._paused = true; + }; + Clip.prototype.resume = function () { + this._paused = false; + }; + return Clip; + }()); + + var Entry = (function () { + function Entry(val) { + this.value = val; + } + return Entry; + }()); + var LinkedList = (function () { + function LinkedList() { + this._len = 0; + } + LinkedList.prototype.insert = function (val) { + var entry = new Entry(val); + this.insertEntry(entry); + return entry; + }; + LinkedList.prototype.insertEntry = function (entry) { + if (!this.head) { + this.head = this.tail = entry; + } + else { + this.tail.next = entry; + entry.prev = this.tail; + entry.next = null; + this.tail = entry; + } + this._len++; + }; + LinkedList.prototype.remove = function (entry) { + var prev = entry.prev; + var next = entry.next; + if (prev) { + prev.next = next; + } + else { + this.head = next; + } + if (next) { + next.prev = prev; + } + else { + this.tail = prev; + } + entry.next = entry.prev = null; + this._len--; + }; + LinkedList.prototype.len = function () { + return this._len; + }; + LinkedList.prototype.clear = function () { + this.head = this.tail = null; + this._len = 0; + }; + return LinkedList; + }()); + var LRU = (function () { + function LRU(maxSize) { + this._list = new LinkedList(); + this._maxSize = 10; + this._map = {}; + this._maxSize = maxSize; + } + LRU.prototype.put = function (key, value) { + var list = this._list; + var map = this._map; + var removed = null; + if (map[key] == null) { + var len = list.len(); + var entry = this._lastRemovedEntry; + if (len >= this._maxSize && len > 0) { + var leastUsedEntry = list.head; + list.remove(leastUsedEntry); + delete map[leastUsedEntry.key]; + removed = leastUsedEntry.value; + this._lastRemovedEntry = leastUsedEntry; + } + if (entry) { + entry.value = value; + } + else { + entry = new Entry(value); + } + entry.key = key; + list.insertEntry(entry); + map[key] = entry; + } + return removed; + }; + LRU.prototype.get = function (key) { + var entry = this._map[key]; + var list = this._list; + if (entry != null) { + if (entry !== list.tail) { + list.remove(entry); + list.insertEntry(entry); + } + return entry.value; + } + }; + LRU.prototype.clear = function () { + this._list.clear(); + this._map = {}; + }; + LRU.prototype.len = function () { + return this._list.len(); + }; + return LRU; + }()); + + var kCSSColorTable = { + '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] + }; + function clampCssByte(i) { + i = Math.round(i); + return i < 0 ? 0 : i > 255 ? 255 : i; + } + function clampCssAngle(i) { + i = Math.round(i); + return i < 0 ? 0 : i > 360 ? 360 : i; + } + function clampCssFloat(f) { + return f < 0 ? 0 : f > 1 ? 1 : f; + } + function parseCssInt(val) { + var str = val; + if (str.length && str.charAt(str.length - 1) === '%') { + return clampCssByte(parseFloat(str) / 100 * 255); + } + return clampCssByte(parseInt(str, 10)); + } + function parseCssFloat(val) { + var str = val; + if (str.length && str.charAt(str.length - 1) === '%') { + return clampCssFloat(parseFloat(str) / 100); + } + return clampCssFloat(parseFloat(str)); + } + function cssHueToRgb(m1, m2, h) { + if (h < 0) { + h += 1; + } + else if (h > 1) { + h -= 1; + } + if (h * 6 < 1) { + return m1 + (m2 - m1) * h * 6; + } + if (h * 2 < 1) { + return m2; + } + if (h * 3 < 2) { + return m1 + (m2 - m1) * (2 / 3 - h) * 6; + } + return m1; + } + function lerpNumber(a, b, p) { + return a + (b - a) * p; + } + function setRgba(out, r, g, b, a) { + out[0] = r; + out[1] = g; + out[2] = b; + out[3] = a; + return out; + } + function copyRgba(out, a) { + out[0] = a[0]; + out[1] = a[1]; + out[2] = a[2]; + out[3] = a[3]; + return out; + } + var colorCache = new LRU(20); + var lastRemovedArr = null; + function putToCache(colorStr, rgbaArr) { + if (lastRemovedArr) { + copyRgba(lastRemovedArr, rgbaArr); + } + lastRemovedArr = colorCache.put(colorStr, lastRemovedArr || (rgbaArr.slice())); + } + function parse(colorStr, rgbaArr) { + if (!colorStr) { + return; + } + rgbaArr = rgbaArr || []; + var cached = colorCache.get(colorStr); + if (cached) { + return copyRgba(rgbaArr, cached); + } + colorStr = colorStr + ''; + var str = colorStr.replace(/ /g, '').toLowerCase(); + if (str in kCSSColorTable) { + copyRgba(rgbaArr, kCSSColorTable[str]); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + var strLen = str.length; + if (str.charAt(0) === '#') { + if (strLen === 4 || strLen === 5) { + var iv = parseInt(str.slice(1, 4), 16); + if (!(iv >= 0 && iv <= 0xfff)) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + setRgba(rgbaArr, ((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8), (iv & 0xf0) | ((iv & 0xf0) >> 4), (iv & 0xf) | ((iv & 0xf) << 4), strLen === 5 ? parseInt(str.slice(4), 16) / 0xf : 1); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + else if (strLen === 7 || strLen === 9) { + var iv = parseInt(str.slice(1, 7), 16); + if (!(iv >= 0 && iv <= 0xffffff)) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + setRgba(rgbaArr, (iv & 0xff0000) >> 16, (iv & 0xff00) >> 8, iv & 0xff, strLen === 9 ? parseInt(str.slice(7), 16) / 0xff : 1); + putToCache(colorStr, rgbaArr); + return rgbaArr; + } + return; + } + var op = str.indexOf('('); + var ep = str.indexOf(')'); + if (op !== -1 && ep + 1 === strLen) { + var fname = str.substr(0, op); + var params = str.substr(op + 1, ep - (op + 1)).split(','); + var alpha = 1; + switch (fname) { + case 'rgba': + if (params.length !== 4) { + return params.length === 3 + ? setRgba(rgbaArr, +params[0], +params[1], +params[2], 1) + : setRgba(rgbaArr, 0, 0, 0, 1); + } + alpha = parseCssFloat(params.pop()); + case 'rgb': + if (params.length !== 3) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + setRgba(rgbaArr, parseCssInt(params[0]), parseCssInt(params[1]), parseCssInt(params[2]), alpha); + putToCache(colorStr, rgbaArr); + return rgbaArr; + case 'hsla': + if (params.length !== 4) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + params[3] = parseCssFloat(params[3]); + hsla2rgba(params, rgbaArr); + putToCache(colorStr, rgbaArr); + return rgbaArr; + case 'hsl': + if (params.length !== 3) { + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + hsla2rgba(params, rgbaArr); + putToCache(colorStr, rgbaArr); + return rgbaArr; + default: + return; + } + } + setRgba(rgbaArr, 0, 0, 0, 1); + return; + } + function hsla2rgba(hsla, rgba) { + var h = (((parseFloat(hsla[0]) % 360) + 360) % 360) / 360; + var s = parseCssFloat(hsla[1]); + var l = parseCssFloat(hsla[2]); + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + rgba = rgba || []; + setRgba(rgba, clampCssByte(cssHueToRgb(m1, m2, h + 1 / 3) * 255), clampCssByte(cssHueToRgb(m1, m2, h) * 255), clampCssByte(cssHueToRgb(m1, m2, h - 1 / 3) * 255), 1); + if (hsla.length === 4) { + rgba[3] = hsla[3]; + } + return rgba; + } + function rgba2hsla(rgba) { + if (!rgba) { + return; + } + var R = rgba[0] / 255; + var G = rgba[1] / 255; + var B = rgba[2] / 255; + var vMin = Math.min(R, G, B); + var vMax = Math.max(R, G, B); + var delta = vMax - vMin; + var L = (vMax + vMin) / 2; + var H; + var S; + if (delta === 0) { + H = 0; + S = 0; + } + else { + if (L < 0.5) { + S = delta / (vMax + vMin); + } + else { + S = delta / (2 - vMax - vMin); + } + var deltaR = (((vMax - R) / 6) + (delta / 2)) / delta; + var deltaG = (((vMax - G) / 6) + (delta / 2)) / delta; + var deltaB = (((vMax - B) / 6) + (delta / 2)) / delta; + if (R === vMax) { + H = deltaB - deltaG; + } + else if (G === vMax) { + H = (1 / 3) + deltaR - deltaB; + } + else if (B === vMax) { + H = (2 / 3) + deltaG - deltaR; + } + if (H < 0) { + H += 1; + } + if (H > 1) { + H -= 1; + } + } + var hsla = [H * 360, S, L]; + if (rgba[3] != null) { + hsla.push(rgba[3]); + } + return hsla; + } + function lift(color, level) { + var colorArr = parse(color); + if (colorArr) { + for (var i = 0; i < 3; i++) { + if (level < 0) { + colorArr[i] = colorArr[i] * (1 - level) | 0; + } + else { + colorArr[i] = ((255 - colorArr[i]) * level + colorArr[i]) | 0; + } + if (colorArr[i] > 255) { + colorArr[i] = 255; + } + else if (colorArr[i] < 0) { + colorArr[i] = 0; + } + } + return stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb'); + } + } + function toHex(color) { + var colorArr = parse(color); + if (colorArr) { + return ((1 << 24) + (colorArr[0] << 16) + (colorArr[1] << 8) + (+colorArr[2])).toString(16).slice(1); + } + } + function fastLerp(normalizedValue, colors, out) { + if (!(colors && colors.length) + || !(normalizedValue >= 0 && normalizedValue <= 1)) { + return; + } + out = out || []; + var value = normalizedValue * (colors.length - 1); + var leftIndex = Math.floor(value); + var rightIndex = Math.ceil(value); + var leftColor = colors[leftIndex]; + var rightColor = colors[rightIndex]; + var dv = value - leftIndex; + out[0] = clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)); + out[1] = clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)); + out[2] = clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)); + out[3] = clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv)); + return out; + } + var fastMapToColor = fastLerp; + function lerp$1(normalizedValue, colors, fullOutput) { + if (!(colors && colors.length) + || !(normalizedValue >= 0 && normalizedValue <= 1)) { + return; + } + var value = normalizedValue * (colors.length - 1); + var leftIndex = Math.floor(value); + var rightIndex = Math.ceil(value); + var leftColor = parse(colors[leftIndex]); + var rightColor = parse(colors[rightIndex]); + var dv = value - leftIndex; + var color = stringify([ + clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)), + clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)), + clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)), + clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv)) + ], 'rgba'); + return fullOutput + ? { + color: color, + leftIndex: leftIndex, + rightIndex: rightIndex, + value: value + } + : color; + } + var mapToColor = lerp$1; + function modifyHSL(color, h, s, l) { + var colorArr = parse(color); + if (color) { + colorArr = rgba2hsla(colorArr); + h != null && (colorArr[0] = clampCssAngle(h)); + s != null && (colorArr[1] = parseCssFloat(s)); + l != null && (colorArr[2] = parseCssFloat(l)); + return stringify(hsla2rgba(colorArr), 'rgba'); + } + } + function modifyAlpha(color, alpha) { + var colorArr = parse(color); + if (colorArr && alpha != null) { + colorArr[3] = clampCssFloat(alpha); + return stringify(colorArr, 'rgba'); + } + } + function stringify(arrColor, type) { + if (!arrColor || !arrColor.length) { + return; + } + var colorStr = arrColor[0] + ',' + arrColor[1] + ',' + arrColor[2]; + if (type === 'rgba' || type === 'hsva' || type === 'hsla') { + colorStr += ',' + arrColor[3]; + } + return type + '(' + colorStr + ')'; + } + function lum(color, backgroundLum) { + var arr = parse(color); + return arr + ? (0.299 * arr[0] + 0.587 * arr[1] + 0.114 * arr[2]) * arr[3] / 255 + + (1 - arr[3]) * backgroundLum + : 0; + } + function random() { + var r = Math.round(Math.random() * 255); + var g = Math.round(Math.random() * 255); + var b = Math.round(Math.random() * 255); + return 'rgb(' + r + ',' + g + ',' + b + ')'; + } + + var color = /*#__PURE__*/Object.freeze({ + __proto__: null, + parse: parse, + lift: lift, + toHex: toHex, + fastLerp: fastLerp, + fastMapToColor: fastMapToColor, + lerp: lerp$1, + mapToColor: mapToColor, + modifyHSL: modifyHSL, + modifyAlpha: modifyAlpha, + stringify: stringify, + lum: lum, + random: random + }); + + var arraySlice = Array.prototype.slice; + function interpolateNumber(p0, p1, percent) { + return (p1 - p0) * percent + p0; + } + function step(p0, p1, percent) { + return percent > 0.5 ? p1 : p0; + } + function interpolate1DArray(out, p0, p1, percent) { + var len = p0.length; + for (var i = 0; i < len; i++) { + out[i] = interpolateNumber(p0[i], p1[i], percent); + } + } + function interpolate2DArray(out, p0, p1, percent) { + var len = p0.length; + var len2 = len && p0[0].length; + for (var i = 0; i < len; i++) { + if (!out[i]) { + out[i] = []; + } + for (var j = 0; j < len2; j++) { + out[i][j] = interpolateNumber(p0[i][j], p1[i][j], percent); + } + } + } + function add1DArray(out, p0, p1, sign) { + var len = p0.length; + for (var i = 0; i < len; i++) { + out[i] = p0[i] + p1[i] * sign; + } + return out; + } + function add2DArray(out, p0, p1, sign) { + var len = p0.length; + var len2 = len && p0[0].length; + for (var i = 0; i < len; i++) { + if (!out[i]) { + out[i] = []; + } + for (var j = 0; j < len2; j++) { + out[i][j] = p0[i][j] + p1[i][j] * sign; + } + } + return out; + } + function fillArray(val0, val1, arrDim) { + var arr0 = val0; + var arr1 = val1; + if (!arr0.push || !arr1.push) { + return; + } + var arr0Len = arr0.length; + var arr1Len = arr1.length; + if (arr0Len !== arr1Len) { + var isPreviousLarger = arr0Len > arr1Len; + if (isPreviousLarger) { + arr0.length = arr1Len; + } + else { + for (var i = arr0Len; i < arr1Len; i++) { + arr0.push(arrDim === 1 ? arr1[i] : arraySlice.call(arr1[i])); + } + } + } + var len2 = arr0[0] && arr0[0].length; + for (var i = 0; i < arr0.length; i++) { + if (arrDim === 1) { + if (isNaN(arr0[i])) { + arr0[i] = arr1[i]; + } + } + else { + for (var j = 0; j < len2; j++) { + if (isNaN(arr0[i][j])) { + arr0[i][j] = arr1[i][j]; + } + } + } + } + } + function is1DArraySame(arr0, arr1) { + var len = arr0.length; + if (len !== arr1.length) { + return false; + } + for (var i = 0; i < len; i++) { + if (arr0[i] !== arr1[i]) { + return false; + } + } + return true; + } + function catmullRomInterpolate(p0, p1, p2, p3, t, t2, t3) { + var v0 = (p2 - p0) * 0.5; + var v1 = (p3 - p1) * 0.5; + return (2 * (p1 - p2) + v0 + v1) * t3 + + (-3 * (p1 - p2) - 2 * v0 - v1) * t2 + + v0 * t + p1; + } + function catmullRomInterpolate1DArray(out, p0, p1, p2, p3, t, t2, t3) { + var len = p0.length; + for (var i = 0; i < len; i++) { + out[i] = catmullRomInterpolate(p0[i], p1[i], p2[i], p3[i], t, t2, t3); + } + } + function catmullRomInterpolate2DArray(out, p0, p1, p2, p3, t, t2, t3) { + var len = p0.length; + var len2 = p0[0].length; + for (var i = 0; i < len; i++) { + if (!out[i]) { + out[1] = []; + } + for (var j = 0; j < len2; j++) { + out[i][j] = catmullRomInterpolate(p0[i][j], p1[i][j], p2[i][j], p3[i][j], t, t2, t3); + } + } + } + function cloneValue(value) { + if (isArrayLike(value)) { + var len = value.length; + if (isArrayLike(value[0])) { + var ret = []; + for (var i = 0; i < len; i++) { + ret.push(arraySlice.call(value[i])); + } + return ret; + } + return arraySlice.call(value); + } + return value; + } + function rgba2String(rgba) { + rgba[0] = Math.floor(rgba[0]); + rgba[1] = Math.floor(rgba[1]); + rgba[2] = Math.floor(rgba[2]); + return 'rgba(' + rgba.join(',') + ')'; + } + function guessArrayDim(value) { + return isArrayLike(value && value[0]) ? 2 : 1; + } + var tmpRgba = [0, 0, 0, 0]; + var Track = (function () { + function Track(propName) { + this.keyframes = []; + this.maxTime = 0; + this.arrDim = 0; + this.interpolable = true; + this._needsSort = false; + this._isAllValueEqual = true; + this._lastFrame = 0; + this._lastFramePercent = 0; + this.propName = propName; + } + Track.prototype.isFinished = function () { + return this._finished; + }; + Track.prototype.setFinished = function () { + this._finished = true; + if (this._additiveTrack) { + this._additiveTrack.setFinished(); + } + }; + Track.prototype.needsAnimate = function () { + return !this._isAllValueEqual && this.keyframes.length >= 2 && this.interpolable; + }; + Track.prototype.getAdditiveTrack = function () { + return this._additiveTrack; + }; + Track.prototype.addKeyframe = function (time, value) { + if (time >= this.maxTime) { + this.maxTime = time; + } + else { + this._needsSort = true; + } + var keyframes = this.keyframes; + var len = keyframes.length; + if (this.interpolable) { + if (isArrayLike(value)) { + var arrayDim = guessArrayDim(value); + if (len > 0 && this.arrDim !== arrayDim) { + this.interpolable = false; + return; + } + if (arrayDim === 1 && typeof value[0] !== 'number' + || arrayDim === 2 && typeof value[0][0] !== 'number') { + this.interpolable = false; + return; + } + if (len > 0) { + var lastFrame = keyframes[len - 1]; + if (this._isAllValueEqual) { + if (arrayDim === 1) { + if (!is1DArraySame(value, lastFrame.value)) { + this._isAllValueEqual = false; + } + } + else { + this._isAllValueEqual = false; + } + } + } + this.arrDim = arrayDim; + } + else { + if (this.arrDim > 0) { + this.interpolable = false; + return; + } + if (typeof value === 'string') { + var colorArray = parse(value); + if (colorArray) { + value = colorArray; + this.isValueColor = true; + } + else { + this.interpolable = false; + } + } + else if (typeof value !== 'number') { + this.interpolable = false; + return; + } + if (this._isAllValueEqual && len > 0) { + var lastFrame = keyframes[len - 1]; + if (this.isValueColor && !is1DArraySame(lastFrame.value, value)) { + this._isAllValueEqual = false; + } + else if (lastFrame.value !== value) { + this._isAllValueEqual = false; + } + } + } + } + var kf = { + time: time, + value: value, + percent: 0 + }; + this.keyframes.push(kf); + return kf; + }; + Track.prototype.prepare = function (additiveTrack) { + var kfs = this.keyframes; + if (this._needsSort) { + kfs.sort(function (a, b) { + return a.time - b.time; + }); + } + var arrDim = this.arrDim; + var kfsLen = kfs.length; + var lastKf = kfs[kfsLen - 1]; + for (var i = 0; i < kfsLen; i++) { + kfs[i].percent = kfs[i].time / this.maxTime; + if (arrDim > 0 && i !== kfsLen - 1) { + fillArray(kfs[i].value, lastKf.value, arrDim); + } + } + if (additiveTrack + && this.needsAnimate() + && additiveTrack.needsAnimate() + && arrDim === additiveTrack.arrDim + && this.isValueColor === additiveTrack.isValueColor + && !additiveTrack._finished) { + this._additiveTrack = additiveTrack; + var startValue = kfs[0].value; + for (var i = 0; i < kfsLen; i++) { + if (arrDim === 0) { + if (this.isValueColor) { + kfs[i].additiveValue + = add1DArray([], kfs[i].value, startValue, -1); + } + else { + kfs[i].additiveValue = kfs[i].value - startValue; + } + } + else if (arrDim === 1) { + kfs[i].additiveValue = add1DArray([], kfs[i].value, startValue, -1); + } + else if (arrDim === 2) { + kfs[i].additiveValue = add2DArray([], kfs[i].value, startValue, -1); + } + } + } + }; + Track.prototype.step = function (target, percent) { + if (this._finished) { + return; + } + if (this._additiveTrack && this._additiveTrack._finished) { + this._additiveTrack = null; + } + var isAdditive = this._additiveTrack != null; + var valueKey = isAdditive ? 'additiveValue' : 'value'; + var keyframes = this.keyframes; + var kfsNum = this.keyframes.length; + var propName = this.propName; + var arrDim = this.arrDim; + var isValueColor = this.isValueColor; + var frameIdx; + if (percent < 0) { + frameIdx = 0; + } + else if (percent < this._lastFramePercent) { + var start = Math.min(this._lastFrame + 1, kfsNum - 1); + for (frameIdx = start; frameIdx >= 0; frameIdx--) { + if (keyframes[frameIdx].percent <= percent) { + break; + } + } + frameIdx = Math.min(frameIdx, kfsNum - 2); + } + else { + for (frameIdx = this._lastFrame; frameIdx < kfsNum; frameIdx++) { + if (keyframes[frameIdx].percent > percent) { + break; + } + } + frameIdx = Math.min(frameIdx - 1, kfsNum - 2); + } + var nextFrame = keyframes[frameIdx + 1]; + var frame = keyframes[frameIdx]; + if (!(frame && nextFrame)) { + return; + } + this._lastFrame = frameIdx; + this._lastFramePercent = percent; + var range = (nextFrame.percent - frame.percent); + if (range === 0) { + return; + } + var w = (percent - frame.percent) / range; + var targetArr = isAdditive ? this._additiveValue + : (isValueColor ? tmpRgba : target[propName]); + if ((arrDim > 0 || isValueColor) && !targetArr) { + targetArr = this._additiveValue = []; + } + if (this.useSpline) { + var p1 = keyframes[frameIdx][valueKey]; + var p0 = keyframes[frameIdx === 0 ? frameIdx : frameIdx - 1][valueKey]; + var p2 = keyframes[frameIdx > kfsNum - 2 ? kfsNum - 1 : frameIdx + 1][valueKey]; + var p3 = keyframes[frameIdx > kfsNum - 3 ? kfsNum - 1 : frameIdx + 2][valueKey]; + if (arrDim > 0) { + arrDim === 1 + ? catmullRomInterpolate1DArray(targetArr, p0, p1, p2, p3, w, w * w, w * w * w) + : catmullRomInterpolate2DArray(targetArr, p0, p1, p2, p3, w, w * w, w * w * w); + } + else if (isValueColor) { + catmullRomInterpolate1DArray(targetArr, p0, p1, p2, p3, w, w * w, w * w * w); + if (!isAdditive) { + target[propName] = rgba2String(targetArr); + } + } + else { + var value = void 0; + if (!this.interpolable) { + value = p2; + } + else { + value = catmullRomInterpolate(p0, p1, p2, p3, w, w * w, w * w * w); + } + if (isAdditive) { + this._additiveValue = value; + } + else { + target[propName] = value; + } + } + } + else { + if (arrDim > 0) { + arrDim === 1 + ? interpolate1DArray(targetArr, frame[valueKey], nextFrame[valueKey], w) + : interpolate2DArray(targetArr, frame[valueKey], nextFrame[valueKey], w); + } + else if (isValueColor) { + interpolate1DArray(targetArr, frame[valueKey], nextFrame[valueKey], w); + if (!isAdditive) { + target[propName] = rgba2String(targetArr); + } + } + else { + var value = void 0; + if (!this.interpolable) { + value = step(frame[valueKey], nextFrame[valueKey], w); + } + else { + value = interpolateNumber(frame[valueKey], nextFrame[valueKey], w); + } + if (isAdditive) { + this._additiveValue = value; + } + else { + target[propName] = value; + } + } + } + if (isAdditive) { + this._addToTarget(target); + } + }; + Track.prototype._addToTarget = function (target) { + var arrDim = this.arrDim; + var propName = this.propName; + var additiveValue = this._additiveValue; + if (arrDim === 0) { + if (this.isValueColor) { + parse(target[propName], tmpRgba); + add1DArray(tmpRgba, tmpRgba, additiveValue, 1); + target[propName] = rgba2String(tmpRgba); + } + else { + target[propName] = target[propName] + additiveValue; + } + } + else if (arrDim === 1) { + add1DArray(target[propName], target[propName], additiveValue, 1); + } + else if (arrDim === 2) { + add2DArray(target[propName], target[propName], additiveValue, 1); + } + }; + return Track; + }()); + var Animator = (function () { + function Animator(target, loop, additiveTo) { + this._tracks = {}; + this._trackKeys = []; + this._delay = 0; + this._maxTime = 0; + this._paused = false; + this._started = 0; + this._clip = null; + this._target = target; + this._loop = loop; + if (loop && additiveTo) { + logError('Can\' use additive animation on looped animation.'); + return; + } + this._additiveAnimators = additiveTo; + } + Animator.prototype.getTarget = function () { + return this._target; + }; + Animator.prototype.changeTarget = function (target) { + this._target = target; + }; + Animator.prototype.when = function (time, props) { + return this.whenWithKeys(time, props, keys(props)); + }; + Animator.prototype.whenWithKeys = function (time, props, propNames) { + var tracks = this._tracks; + for (var i = 0; i < propNames.length; i++) { + var propName = propNames[i]; + var track = tracks[propName]; + if (!track) { + track = tracks[propName] = new Track(propName); + var initialValue = void 0; + var additiveTrack = this._getAdditiveTrack(propName); + if (additiveTrack) { + var lastFinalKf = additiveTrack.keyframes[additiveTrack.keyframes.length - 1]; + initialValue = lastFinalKf && lastFinalKf.value; + if (additiveTrack.isValueColor && initialValue) { + initialValue = rgba2String(initialValue); + } + } + else { + initialValue = this._target[propName]; + } + if (initialValue == null) { + continue; + } + if (time !== 0) { + track.addKeyframe(0, cloneValue(initialValue)); + } + this._trackKeys.push(propName); + } + track.addKeyframe(time, cloneValue(props[propName])); + } + this._maxTime = Math.max(this._maxTime, time); + return this; + }; + Animator.prototype.pause = function () { + this._clip.pause(); + this._paused = true; + }; + Animator.prototype.resume = function () { + this._clip.resume(); + this._paused = false; + }; + Animator.prototype.isPaused = function () { + return !!this._paused; + }; + Animator.prototype._doneCallback = function () { + this._setTracksFinished(); + this._clip = null; + var doneList = this._doneList; + if (doneList) { + var len = doneList.length; + for (var i = 0; i < len; i++) { + doneList[i].call(this); + } + } + }; + Animator.prototype._abortedCallback = function () { + this._setTracksFinished(); + var animation = this.animation; + var abortedList = this._abortedList; + if (animation) { + animation.removeClip(this._clip); + } + this._clip = null; + if (abortedList) { + for (var i = 0; i < abortedList.length; i++) { + abortedList[i].call(this); + } + } + }; + Animator.prototype._setTracksFinished = function () { + var tracks = this._tracks; + var tracksKeys = this._trackKeys; + for (var i = 0; i < tracksKeys.length; i++) { + tracks[tracksKeys[i]].setFinished(); + } + }; + Animator.prototype._getAdditiveTrack = function (trackName) { + var additiveTrack; + var additiveAnimators = this._additiveAnimators; + if (additiveAnimators) { + for (var i = 0; i < additiveAnimators.length; i++) { + var track = additiveAnimators[i].getTrack(trackName); + if (track) { + additiveTrack = track; + } + } + } + return additiveTrack; + }; + Animator.prototype.start = function (easing, forceAnimate) { + if (this._started > 0) { + return; + } + this._started = 1; + var self = this; + var tracks = []; + for (var i = 0; i < this._trackKeys.length; i++) { + var propName = this._trackKeys[i]; + var track = this._tracks[propName]; + var additiveTrack = this._getAdditiveTrack(propName); + var kfs = track.keyframes; + track.prepare(additiveTrack); + if (track.needsAnimate()) { + tracks.push(track); + } + else if (!track.interpolable) { + var lastKf = kfs[kfs.length - 1]; + if (lastKf) { + self._target[track.propName] = lastKf.value; + } + } + } + if (tracks.length || forceAnimate) { + var clip = new Clip({ + life: this._maxTime, + loop: this._loop, + delay: this._delay, + onframe: function (percent) { + self._started = 2; + var additiveAnimators = self._additiveAnimators; + if (additiveAnimators) { + var stillHasAdditiveAnimator = false; + for (var i = 0; i < additiveAnimators.length; i++) { + if (additiveAnimators[i]._clip) { + stillHasAdditiveAnimator = true; + break; + } + } + if (!stillHasAdditiveAnimator) { + self._additiveAnimators = null; + } + } + for (var i = 0; i < tracks.length; i++) { + tracks[i].step(self._target, percent); + } + var onframeList = self._onframeList; + if (onframeList) { + for (var i = 0; i < onframeList.length; i++) { + onframeList[i](self._target, percent); + } + } + }, + ondestroy: function () { + self._doneCallback(); + } + }); + this._clip = clip; + if (this.animation) { + this.animation.addClip(clip); + } + if (easing && easing !== 'spline') { + clip.easing = easing; + } + } + else { + this._doneCallback(); + } + return this; + }; + Animator.prototype.stop = function (forwardToLast) { + if (!this._clip) { + return; + } + var clip = this._clip; + if (forwardToLast) { + clip.onframe(1); + } + this._abortedCallback(); + }; + Animator.prototype.delay = function (time) { + this._delay = time; + return this; + }; + Animator.prototype.during = function (cb) { + if (cb) { + if (!this._onframeList) { + this._onframeList = []; + } + this._onframeList.push(cb); + } + return this; + }; + Animator.prototype.done = function (cb) { + if (cb) { + if (!this._doneList) { + this._doneList = []; + } + this._doneList.push(cb); + } + return this; + }; + Animator.prototype.aborted = function (cb) { + if (cb) { + if (!this._abortedList) { + this._abortedList = []; + } + this._abortedList.push(cb); + } + return this; + }; + Animator.prototype.getClip = function () { + return this._clip; + }; + Animator.prototype.getTrack = function (propName) { + return this._tracks[propName]; + }; + Animator.prototype.stopTracks = function (propNames, forwardToLast) { + if (!propNames.length || !this._clip) { + return true; + } + var tracks = this._tracks; + var tracksKeys = this._trackKeys; + for (var i = 0; i < propNames.length; i++) { + var track = tracks[propNames[i]]; + if (track) { + if (forwardToLast) { + track.step(this._target, 1); + } + else if (this._started === 1) { + track.step(this._target, 0); + } + track.setFinished(); + } + } + var allAborted = true; + for (var i = 0; i < tracksKeys.length; i++) { + if (!tracks[tracksKeys[i]].isFinished()) { + allAborted = false; + break; + } + } + if (allAborted) { + this._abortedCallback(); + } + return allAborted; + }; + Animator.prototype.saveFinalToTarget = function (target, trackKeys) { + if (!target) { + return; + } + trackKeys = trackKeys || this._trackKeys; + for (var i = 0; i < trackKeys.length; i++) { + var propName = trackKeys[i]; + var track = this._tracks[propName]; + if (!track || track.isFinished()) { + continue; + } + var kfs = track.keyframes; + var lastKf = kfs[kfs.length - 1]; + if (lastKf) { + var val = cloneValue(lastKf.value); + if (track.isValueColor) { + val = rgba2String(val); + } + target[propName] = val; + } + } + }; + Animator.prototype.__changeFinalValue = function (finalProps, trackKeys) { + trackKeys = trackKeys || keys(finalProps); + for (var i = 0; i < trackKeys.length; i++) { + var propName = trackKeys[i]; + var track = this._tracks[propName]; + if (!track) { + continue; + } + var kfs = track.keyframes; + if (kfs.length > 1) { + var lastKf = kfs.pop(); + track.addKeyframe(lastKf.time, finalProps[propName]); + track.prepare(track.getAdditiveTrack()); + } + } + }; + return Animator; + }()); + + var Point = (function () { + function Point(x, y) { + this.x = x || 0; + this.y = y || 0; + } + Point.prototype.copy = function (other) { + this.x = other.x; + this.y = other.y; + return this; + }; + Point.prototype.clone = function () { + return new Point(this.x, this.y); + }; + Point.prototype.set = function (x, y) { + this.x = x; + this.y = y; + return this; + }; + Point.prototype.equal = function (other) { + return other.x === this.x && other.y === this.y; + }; + Point.prototype.add = function (other) { + this.x += other.x; + this.y += other.y; + return this; + }; + Point.prototype.scale = function (scalar) { + this.x *= scalar; + this.y *= scalar; + }; + Point.prototype.scaleAndAdd = function (other, scalar) { + this.x += other.x * scalar; + this.y += other.y * scalar; + }; + Point.prototype.sub = function (other) { + this.x -= other.x; + this.y -= other.y; + return this; + }; + Point.prototype.dot = function (other) { + return this.x * other.x + this.y * other.y; + }; + Point.prototype.len = function () { + return Math.sqrt(this.x * this.x + this.y * this.y); + }; + Point.prototype.lenSquare = function () { + return this.x * this.x + this.y * this.y; + }; + Point.prototype.normalize = function () { + var len = this.len(); + this.x /= len; + this.y /= len; + return this; + }; + Point.prototype.distance = function (other) { + var dx = this.x - other.x; + var dy = this.y - other.y; + return Math.sqrt(dx * dx + dy * dy); + }; + Point.prototype.distanceSquare = function (other) { + var dx = this.x - other.x; + var dy = this.y - other.y; + return dx * dx + dy * dy; + }; + Point.prototype.negate = function () { + this.x = -this.x; + this.y = -this.y; + return this; + }; + Point.prototype.transform = function (m) { + if (!m) { + return; + } + var x = this.x; + var y = this.y; + this.x = m[0] * x + m[2] * y + m[4]; + this.y = m[1] * x + m[3] * y + m[5]; + return this; + }; + Point.prototype.toArray = function (out) { + out[0] = this.x; + out[1] = this.y; + return out; + }; + Point.prototype.fromArray = function (input) { + this.x = input[0]; + this.y = input[1]; + }; + Point.set = function (p, x, y) { + p.x = x; + p.y = y; + }; + Point.copy = function (p, p2) { + p.x = p2.x; + p.y = p2.y; + }; + Point.len = function (p) { + return Math.sqrt(p.x * p.x + p.y * p.y); + }; + Point.lenSquare = function (p) { + return p.x * p.x + p.y * p.y; + }; + Point.dot = function (p0, p1) { + return p0.x * p1.x + p0.y * p1.y; + }; + Point.add = function (out, p0, p1) { + out.x = p0.x + p1.x; + out.y = p0.y + p1.y; + }; + Point.sub = function (out, p0, p1) { + out.x = p0.x - p1.x; + out.y = p0.y - p1.y; + }; + Point.scale = function (out, p0, scalar) { + out.x = p0.x * scalar; + out.y = p0.y * scalar; + }; + Point.scaleAndAdd = function (out, p0, p1, scalar) { + out.x = p0.x + p1.x * scalar; + out.y = p0.y + p1.y * scalar; + }; + Point.lerp = function (out, p0, p1, t) { + var onet = 1 - t; + out.x = onet * p0.x + t * p1.x; + out.y = onet * p0.y + t * p1.y; + }; + return Point; + }()); + + var mathMin = Math.min; + var mathMax = Math.max; + var lt = new Point(); + var rb = new Point(); + var lb = new Point(); + var rt = new Point(); + var minTv = new Point(); + var maxTv = new Point(); + var BoundingRect = (function () { + function BoundingRect(x, y, width, height) { + if (width < 0 && isFinite(width)) { + x = x + width; + width = -width; + } + if (height < 0 && isFinite(height)) { + y = y + height; + height = -height; + } + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + BoundingRect.prototype.union = function (other) { + var x = mathMin(other.x, this.x); + var y = mathMin(other.y, this.y); + if (isFinite(this.x) && isFinite(this.width)) { + this.width = mathMax(other.x + other.width, this.x + this.width) - x; + } + else { + this.width = other.width; + } + if (isFinite(this.y) && isFinite(this.height)) { + this.height = mathMax(other.y + other.height, this.y + this.height) - y; + } + else { + this.height = other.height; + } + this.x = x; + this.y = y; + }; + BoundingRect.prototype.applyTransform = function (m) { + BoundingRect.applyTransform(this, this, m); + }; + BoundingRect.prototype.calculateTransform = function (b) { + var a = this; + var sx = b.width / a.width; + var sy = b.height / a.height; + var m = create$1(); + translate(m, m, [-a.x, -a.y]); + scale$1(m, m, [sx, sy]); + translate(m, m, [b.x, b.y]); + return m; + }; + BoundingRect.prototype.intersect = function (b, mtv) { + if (!b) { + return false; + } + if (!(b instanceof BoundingRect)) { + b = BoundingRect.create(b); + } + var a = this; + var ax0 = a.x; + var ax1 = a.x + a.width; + var ay0 = a.y; + var ay1 = a.y + a.height; + var bx0 = b.x; + var bx1 = b.x + b.width; + var by0 = b.y; + var by1 = b.y + b.height; + var overlap = !(ax1 < bx0 || bx1 < ax0 || ay1 < by0 || by1 < ay0); + if (mtv) { + var dMin = Infinity; + var dMax = 0; + var d0 = Math.abs(ax1 - bx0); + var d1 = Math.abs(bx1 - ax0); + var d2 = Math.abs(ay1 - by0); + var d3 = Math.abs(by1 - ay0); + var dx = Math.min(d0, d1); + var dy = Math.min(d2, d3); + if (ax1 < bx0 || bx1 < ax0) { + if (dx > dMax) { + dMax = dx; + if (d0 < d1) { + Point.set(maxTv, -d0, 0); + } + else { + Point.set(maxTv, d1, 0); + } + } + } + else { + if (dx < dMin) { + dMin = dx; + if (d0 < d1) { + Point.set(minTv, d0, 0); + } + else { + Point.set(minTv, -d1, 0); + } + } + } + if (ay1 < by0 || by1 < ay0) { + if (dy > dMax) { + dMax = dy; + if (d2 < d3) { + Point.set(maxTv, 0, -d2); + } + else { + Point.set(maxTv, 0, d3); + } + } + } + else { + if (dx < dMin) { + dMin = dx; + if (d2 < d3) { + Point.set(minTv, 0, d2); + } + else { + Point.set(minTv, 0, -d3); + } + } + } + } + if (mtv) { + Point.copy(mtv, overlap ? minTv : maxTv); + } + return overlap; + }; + BoundingRect.prototype.contain = function (x, y) { + var rect = this; + return x >= rect.x + && x <= (rect.x + rect.width) + && y >= rect.y + && y <= (rect.y + rect.height); + }; + BoundingRect.prototype.clone = function () { + return new BoundingRect(this.x, this.y, this.width, this.height); + }; + BoundingRect.prototype.copy = function (other) { + BoundingRect.copy(this, other); + }; + BoundingRect.prototype.plain = function () { + return { + x: this.x, + y: this.y, + width: this.width, + height: this.height + }; + }; + BoundingRect.prototype.isFinite = function () { + return isFinite(this.x) + && isFinite(this.y) + && isFinite(this.width) + && isFinite(this.height); + }; + BoundingRect.prototype.isZero = function () { + return this.width === 0 || this.height === 0; + }; + BoundingRect.create = function (rect) { + return new BoundingRect(rect.x, rect.y, rect.width, rect.height); + }; + BoundingRect.copy = function (target, source) { + target.x = source.x; + target.y = source.y; + target.width = source.width; + target.height = source.height; + }; + BoundingRect.applyTransform = function (target, source, m) { + if (!m) { + if (target !== source) { + BoundingRect.copy(target, source); + } + return; + } + if (m[1] < 1e-5 && m[1] > -1e-5 && m[2] < 1e-5 && m[2] > -1e-5) { + var sx = m[0]; + var sy = m[3]; + var tx = m[4]; + var ty = m[5]; + target.x = source.x * sx + tx; + target.y = source.y * sy + ty; + target.width = source.width * sx; + target.height = source.height * sy; + if (target.width < 0) { + target.x += target.width; + target.width = -target.width; + } + if (target.height < 0) { + target.y += target.height; + target.height = -target.height; + } + return; + } + lt.x = lb.x = source.x; + lt.y = rt.y = source.y; + rb.x = rt.x = source.x + source.width; + rb.y = lb.y = source.y + source.height; + lt.transform(m); + rt.transform(m); + rb.transform(m); + lb.transform(m); + target.x = mathMin(lt.x, rb.x, lb.x, rt.x); + target.y = mathMin(lt.y, rb.y, lb.y, rt.y); + var maxX = mathMax(lt.x, rb.x, lb.x, rt.x); + var maxY = mathMax(lt.y, rb.y, lb.y, rt.y); + target.width = maxX - target.x; + target.height = maxY - target.y; + }; + return BoundingRect; + }()); + + var textWidthCache = {}; + var DEFAULT_FONT = '12px sans-serif'; + var _ctx; + var _cachedFont; + function defaultMeasureText(text, font) { + if (!_ctx) { + _ctx = createCanvas().getContext('2d'); + } + if (_cachedFont !== font) { + _cachedFont = _ctx.font = font || DEFAULT_FONT; + } + return _ctx.measureText(text); + } + var methods$1 = { + measureText: defaultMeasureText + }; + function getWidth(text, font) { + font = font || DEFAULT_FONT; + var cacheOfFont = textWidthCache[font]; + if (!cacheOfFont) { + cacheOfFont = textWidthCache[font] = new LRU(500); + } + var width = cacheOfFont.get(text); + if (width == null) { + width = methods$1.measureText(text, font).width; + cacheOfFont.put(text, width); + } + return width; + } + function innerGetBoundingRect(text, font, textAlign, textBaseline) { + var width = getWidth(text, font); + var height = getLineHeight(font); + var x = adjustTextX(0, width, textAlign); + var y = adjustTextY(0, height, textBaseline); + var rect = new BoundingRect(x, y, width, height); + return rect; + } + function getBoundingRect(text, font, textAlign, textBaseline) { + var textLines = ((text || '') + '').split('\n'); + var len = textLines.length; + if (len === 1) { + return innerGetBoundingRect(textLines[0], font, textAlign, textBaseline); + } + else { + var uniondRect = new BoundingRect(0, 0, 0, 0); + for (var i = 0; i < textLines.length; i++) { + var rect = innerGetBoundingRect(textLines[i], font, textAlign, textBaseline); + i === 0 ? uniondRect.copy(rect) : uniondRect.union(rect); + } + return uniondRect; + } + } + function adjustTextX(x, width, textAlign) { + if (textAlign === 'right') { + x -= width; + } + else if (textAlign === 'center') { + x -= width / 2; + } + return x; + } + function adjustTextY(y, height, verticalAlign) { + if (verticalAlign === 'middle') { + y -= height / 2; + } + else if (verticalAlign === 'bottom') { + y -= height; + } + return y; + } + function getLineHeight(font) { + return getWidth('国', font); + } + function parsePercent(value, maxValue) { + if (typeof value === 'string') { + if (value.lastIndexOf('%') >= 0) { + return parseFloat(value) / 100 * maxValue; + } + return parseFloat(value); + } + return value; + } + function calculateTextPosition(out, opts, rect) { + var textPosition = opts.position || 'inside'; + var distance = opts.distance != null ? opts.distance : 5; + var height = rect.height; + var width = rect.width; + var halfHeight = height / 2; + var x = rect.x; + var y = rect.y; + var textAlign = 'left'; + var textVerticalAlign = 'top'; + if (textPosition instanceof Array) { + x += parsePercent(textPosition[0], rect.width); + y += parsePercent(textPosition[1], rect.height); + textAlign = null; + textVerticalAlign = null; + } + else { + switch (textPosition) { + case 'left': + x -= distance; + y += halfHeight; + textAlign = 'right'; + textVerticalAlign = 'middle'; + break; + case 'right': + x += distance + width; + y += halfHeight; + textVerticalAlign = 'middle'; + break; + case 'top': + x += width / 2; + y -= distance; + textAlign = 'center'; + textVerticalAlign = 'bottom'; + break; + case 'bottom': + x += width / 2; + y += height + distance; + textAlign = 'center'; + break; + case 'inside': + x += width / 2; + y += halfHeight; + textAlign = 'center'; + textVerticalAlign = 'middle'; + break; + case 'insideLeft': + x += distance; + y += halfHeight; + textVerticalAlign = 'middle'; + break; + case 'insideRight': + x += width - distance; + y += halfHeight; + textAlign = 'right'; + textVerticalAlign = 'middle'; + break; + case 'insideTop': + x += width / 2; + y += distance; + textAlign = 'center'; + break; + case 'insideBottom': + x += width / 2; + y += height - distance; + textAlign = 'center'; + textVerticalAlign = 'bottom'; + break; + case 'insideTopLeft': + x += distance; + y += distance; + break; + case 'insideTopRight': + x += width - distance; + y += distance; + textAlign = 'right'; + break; + case 'insideBottomLeft': + x += distance; + y += height - distance; + textVerticalAlign = 'bottom'; + break; + case 'insideBottomRight': + x += width - distance; + y += height - distance; + textAlign = 'right'; + textVerticalAlign = 'bottom'; + break; + } + } + out = out || {}; + out.x = x; + out.y = y; + out.align = textAlign; + out.verticalAlign = textVerticalAlign; + return out; + } + + var dpr = 1; + if (typeof window !== 'undefined') { + dpr = Math.max(window.devicePixelRatio + || (window.screen && window.screen.deviceXDPI / window.screen.logicalXDPI) + || 1, 1); + } + var devicePixelRatio = dpr; + var DARK_MODE_THRESHOLD = 0.4; + var DARK_LABEL_COLOR = '#333'; + var LIGHT_LABEL_COLOR = '#ccc'; + var LIGHTER_LABEL_COLOR = '#eee'; + + var PRESERVED_NORMAL_STATE = '__zr_normal__'; + var PRIMARY_STATES_KEYS = ['x', 'y', 'scaleX', 'scaleY', 'originX', 'originY', 'rotation', 'ignore']; + var DEFAULT_ANIMATABLE_MAP = { + x: true, + y: true, + scaleX: true, + scaleY: true, + originX: true, + originY: true, + rotation: true, + ignore: false + }; + var tmpTextPosCalcRes = {}; + var tmpBoundingRect = new BoundingRect(0, 0, 0, 0); + var Element = (function () { + function Element(props) { + this.id = guid(); + this.animators = []; + this.currentStates = []; + this.states = {}; + this._init(props); + } + Element.prototype._init = function (props) { + this.attr(props); + }; + Element.prototype.drift = function (dx, dy, e) { + switch (this.draggable) { + case 'horizontal': + dy = 0; + break; + case 'vertical': + dx = 0; + break; + } + var m = this.transform; + if (!m) { + m = this.transform = [1, 0, 0, 1, 0, 0]; + } + m[4] += dx; + m[5] += dy; + this.decomposeTransform(); + this.markRedraw(); + }; + Element.prototype.beforeUpdate = function () { }; + Element.prototype.afterUpdate = function () { }; + Element.prototype.update = function () { + this.updateTransform(); + if (this.__dirty) { + this.updateInnerText(); + } + }; + Element.prototype.updateInnerText = function (forceUpdate) { + var textEl = this._textContent; + if (textEl && (!textEl.ignore || forceUpdate)) { + if (!this.textConfig) { + this.textConfig = {}; + } + var textConfig = this.textConfig; + var isLocal = textConfig.local; + var attachedTransform = textEl.attachedTransform; + var textAlign = void 0; + var textVerticalAlign = void 0; + var textStyleChanged = false; + if (isLocal) { + attachedTransform.parent = this; + } + else { + attachedTransform.parent = null; + } + var innerOrigin = false; + attachedTransform.x = textEl.x; + attachedTransform.y = textEl.y; + attachedTransform.originX = textEl.originX; + attachedTransform.originY = textEl.originY; + attachedTransform.rotation = textEl.rotation; + attachedTransform.scaleX = textEl.scaleX; + attachedTransform.scaleY = textEl.scaleY; + if (textConfig.position != null) { + var layoutRect = tmpBoundingRect; + if (textConfig.layoutRect) { + layoutRect.copy(textConfig.layoutRect); + } + else { + layoutRect.copy(this.getBoundingRect()); + } + if (!isLocal) { + layoutRect.applyTransform(this.transform); + } + if (this.calculateTextPosition) { + this.calculateTextPosition(tmpTextPosCalcRes, textConfig, layoutRect); + } + else { + calculateTextPosition(tmpTextPosCalcRes, textConfig, layoutRect); + } + attachedTransform.x = tmpTextPosCalcRes.x; + attachedTransform.y = tmpTextPosCalcRes.y; + textAlign = tmpTextPosCalcRes.align; + textVerticalAlign = tmpTextPosCalcRes.verticalAlign; + var textOrigin = textConfig.origin; + if (textOrigin && textConfig.rotation != null) { + var relOriginX = void 0; + var relOriginY = void 0; + if (textOrigin === 'center') { + relOriginX = layoutRect.width * 0.5; + relOriginY = layoutRect.height * 0.5; + } + else { + relOriginX = parsePercent(textOrigin[0], layoutRect.width); + relOriginY = parsePercent(textOrigin[1], layoutRect.height); + } + innerOrigin = true; + attachedTransform.originX = -attachedTransform.x + relOriginX + (isLocal ? 0 : layoutRect.x); + attachedTransform.originY = -attachedTransform.y + relOriginY + (isLocal ? 0 : layoutRect.y); + } + } + if (textConfig.rotation != null) { + attachedTransform.rotation = textConfig.rotation; + } + var textOffset = textConfig.offset; + if (textOffset) { + attachedTransform.x += textOffset[0]; + attachedTransform.y += textOffset[1]; + if (!innerOrigin) { + attachedTransform.originX = -textOffset[0]; + attachedTransform.originY = -textOffset[1]; + } + } + var isInside = textConfig.inside == null + ? (typeof textConfig.position === 'string' && textConfig.position.indexOf('inside') >= 0) + : textConfig.inside; + var innerTextDefaultStyle = this._innerTextDefaultStyle || (this._innerTextDefaultStyle = {}); + var textFill = void 0; + var textStroke = void 0; + var autoStroke = void 0; + if (isInside && this.canBeInsideText()) { + textFill = textConfig.insideFill; + textStroke = textConfig.insideStroke; + if (textFill == null || textFill === 'auto') { + textFill = this.getInsideTextFill(); + } + if (textStroke == null || textStroke === 'auto') { + textStroke = this.getInsideTextStroke(textFill); + autoStroke = true; + } + } + else { + textFill = textConfig.outsideFill; + textStroke = textConfig.outsideStroke; + if (textFill == null || textFill === 'auto') { + textFill = this.getOutsideFill(); + } + if (textStroke == null || textStroke === 'auto') { + textStroke = this.getOutsideStroke(textFill); + autoStroke = true; + } + } + textFill = textFill || '#000'; + if (textFill !== innerTextDefaultStyle.fill + || textStroke !== innerTextDefaultStyle.stroke + || autoStroke !== innerTextDefaultStyle.autoStroke + || textAlign !== innerTextDefaultStyle.align + || textVerticalAlign !== innerTextDefaultStyle.verticalAlign) { + textStyleChanged = true; + innerTextDefaultStyle.fill = textFill; + innerTextDefaultStyle.stroke = textStroke; + innerTextDefaultStyle.autoStroke = autoStroke; + innerTextDefaultStyle.align = textAlign; + innerTextDefaultStyle.verticalAlign = textVerticalAlign; + textEl.setDefaultTextStyle(innerTextDefaultStyle); + } + if (textStyleChanged) { + textEl.dirtyStyle(); + } + textEl.markRedraw(); + } + }; + Element.prototype.canBeInsideText = function () { + return true; + }; + Element.prototype.getInsideTextFill = function () { + return '#fff'; + }; + Element.prototype.getInsideTextStroke = function (textFill) { + return '#000'; + }; + Element.prototype.getOutsideFill = function () { + return this.__zr && this.__zr.isDarkMode() ? LIGHT_LABEL_COLOR : DARK_LABEL_COLOR; + }; + Element.prototype.getOutsideStroke = function (textFill) { + var backgroundColor = this.__zr && this.__zr.getBackgroundColor(); + var colorArr = typeof backgroundColor === 'string' && parse(backgroundColor); + if (!colorArr) { + colorArr = [255, 255, 255, 1]; + } + var alpha = colorArr[3]; + var isDark = this.__zr.isDarkMode(); + for (var i = 0; i < 3; i++) { + colorArr[i] = colorArr[i] * alpha + (isDark ? 0 : 255) * (1 - alpha); + } + colorArr[3] = 1; + return stringify(colorArr, 'rgba'); + }; + Element.prototype.traverse = function (cb, context) { }; + Element.prototype.attrKV = function (key, value) { + if (key === 'textConfig') { + this.setTextConfig(value); + } + else if (key === 'textContent') { + this.setTextContent(value); + } + else if (key === 'clipPath') { + this.setClipPath(value); + } + else if (key === 'extra') { + this.extra = this.extra || {}; + extend(this.extra, value); + } + else { + this[key] = value; + } + }; + Element.prototype.hide = function () { + this.ignore = true; + this.markRedraw(); + }; + Element.prototype.show = function () { + this.ignore = false; + this.markRedraw(); + }; + Element.prototype.attr = function (keyOrObj, value) { + if (typeof keyOrObj === 'string') { + this.attrKV(keyOrObj, value); + } + else if (isObject(keyOrObj)) { + var obj = keyOrObj; + var keysArr = keys(obj); + for (var i = 0; i < keysArr.length; i++) { + var key = keysArr[i]; + this.attrKV(key, keyOrObj[key]); + } + } + this.markRedraw(); + return this; + }; + Element.prototype.saveCurrentToNormalState = function (toState) { + this._innerSaveToNormal(toState); + var normalState = this._normalState; + for (var i = 0; i < this.animators.length; i++) { + var animator = this.animators[i]; + var fromStateTransition = animator.__fromStateTransition; + if (fromStateTransition && fromStateTransition !== PRESERVED_NORMAL_STATE) { + continue; + } + var targetName = animator.targetName; + var target = targetName + ? normalState[targetName] : normalState; + animator.saveFinalToTarget(target); + } + }; + Element.prototype._innerSaveToNormal = function (toState) { + var normalState = this._normalState; + if (!normalState) { + normalState = this._normalState = {}; + } + if (toState.textConfig && !normalState.textConfig) { + normalState.textConfig = this.textConfig; + } + this._savePrimaryToNormal(toState, normalState, PRIMARY_STATES_KEYS); + }; + Element.prototype._savePrimaryToNormal = function (toState, normalState, primaryKeys) { + for (var i = 0; i < primaryKeys.length; i++) { + var key = primaryKeys[i]; + if (toState[key] != null && !(key in normalState)) { + normalState[key] = this[key]; + } + } + }; + Element.prototype.hasState = function () { + return this.currentStates.length > 0; + }; + Element.prototype.getState = function (name) { + return this.states[name]; + }; + Element.prototype.ensureState = function (name) { + var states = this.states; + if (!states[name]) { + states[name] = {}; + } + return states[name]; + }; + Element.prototype.clearStates = function (noAnimation) { + this.useState(PRESERVED_NORMAL_STATE, false, noAnimation); + }; + Element.prototype.useState = function (stateName, keepCurrentStates, noAnimation) { + var toNormalState = stateName === PRESERVED_NORMAL_STATE; + var hasStates = this.hasState(); + if (!hasStates && toNormalState) { + return; + } + var currentStates = this.currentStates; + var animationCfg = this.stateTransition; + if (indexOf(currentStates, stateName) >= 0 && (keepCurrentStates || currentStates.length === 1)) { + return; + } + var state; + if (this.stateProxy && !toNormalState) { + state = this.stateProxy(stateName); + } + if (!state) { + state = (this.states && this.states[stateName]); + } + if (!state && !toNormalState) { + logError("State " + stateName + " not exists."); + return; + } + if (!toNormalState) { + this.saveCurrentToNormalState(state); + } + var useHoverLayer = !!(state && state.hoverLayer); + if (useHoverLayer) { + this._toggleHoverLayerFlag(true); + } + this._applyStateObj(stateName, state, this._normalState, keepCurrentStates, !noAnimation && !this.__inHover && animationCfg && animationCfg.duration > 0, animationCfg); + if (this._textContent) { + this._textContent.useState(stateName, keepCurrentStates); + } + if (this._textGuide) { + this._textGuide.useState(stateName, keepCurrentStates); + } + if (toNormalState) { + this.currentStates = []; + this._normalState = {}; + } + else { + if (!keepCurrentStates) { + this.currentStates = [stateName]; + } + else { + this.currentStates.push(stateName); + } + } + this._updateAnimationTargets(); + this.markRedraw(); + if (!useHoverLayer && this.__inHover) { + this._toggleHoverLayerFlag(false); + this.__dirty &= ~Element.REDARAW_BIT; + } + return state; + }; + Element.prototype.useStates = function (states, noAnimation) { + if (!states.length) { + this.clearStates(); + } + else { + var stateObjects = []; + var currentStates = this.currentStates; + var len = states.length; + var notChange = len === currentStates.length; + if (notChange) { + for (var i = 0; i < len; i++) { + if (states[i] !== currentStates[i]) { + notChange = false; + break; + } + } + } + if (notChange) { + return; + } + for (var i = 0; i < len; i++) { + var stateName = states[i]; + var stateObj = void 0; + if (this.stateProxy) { + stateObj = this.stateProxy(stateName, states); + } + if (!stateObj) { + stateObj = this.states[stateName]; + } + if (stateObj) { + stateObjects.push(stateObj); + } + } + var useHoverLayer = !!(stateObjects[len - 1] && stateObjects[len - 1].hoverLayer); + if (useHoverLayer) { + this._toggleHoverLayerFlag(true); + } + var mergedState = this._mergeStates(stateObjects); + var animationCfg = this.stateTransition; + this.saveCurrentToNormalState(mergedState); + this._applyStateObj(states.join(','), mergedState, this._normalState, false, !noAnimation && !this.__inHover && animationCfg && animationCfg.duration > 0, animationCfg); + if (this._textContent) { + this._textContent.useStates(states); + } + if (this._textGuide) { + this._textGuide.useStates(states); + } + this._updateAnimationTargets(); + this.currentStates = states.slice(); + this.markRedraw(); + if (!useHoverLayer && this.__inHover) { + this._toggleHoverLayerFlag(false); + this.__dirty &= ~Element.REDARAW_BIT; + } + } + }; + Element.prototype._updateAnimationTargets = function () { + for (var i = 0; i < this.animators.length; i++) { + var animator = this.animators[i]; + if (animator.targetName) { + animator.changeTarget(this[animator.targetName]); + } + } + }; + Element.prototype.removeState = function (state) { + var idx = indexOf(this.currentStates, state); + if (idx >= 0) { + var currentStates = this.currentStates.slice(); + currentStates.splice(idx, 1); + this.useStates(currentStates); + } + }; + Element.prototype.replaceState = function (oldState, newState, forceAdd) { + var currentStates = this.currentStates.slice(); + var idx = indexOf(currentStates, oldState); + var newStateExists = indexOf(currentStates, newState) >= 0; + if (idx >= 0) { + if (!newStateExists) { + currentStates[idx] = newState; + } + else { + currentStates.splice(idx, 1); + } + } + else if (forceAdd && !newStateExists) { + currentStates.push(newState); + } + this.useStates(currentStates); + }; + Element.prototype.toggleState = function (state, enable) { + if (enable) { + this.useState(state, true); + } + else { + this.removeState(state); + } + }; + Element.prototype._mergeStates = function (states) { + var mergedState = {}; + var mergedTextConfig; + for (var i = 0; i < states.length; i++) { + var state = states[i]; + extend(mergedState, state); + if (state.textConfig) { + mergedTextConfig = mergedTextConfig || {}; + extend(mergedTextConfig, state.textConfig); + } + } + if (mergedTextConfig) { + mergedState.textConfig = mergedTextConfig; + } + return mergedState; + }; + Element.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) { + var needsRestoreToNormal = !(state && keepCurrentStates); + if (state && state.textConfig) { + this.textConfig = extend({}, keepCurrentStates ? this.textConfig : normalState.textConfig); + extend(this.textConfig, state.textConfig); + } + else if (needsRestoreToNormal) { + if (normalState.textConfig) { + this.textConfig = normalState.textConfig; + } + } + var transitionTarget = {}; + var hasTransition = false; + for (var i = 0; i < PRIMARY_STATES_KEYS.length; i++) { + var key = PRIMARY_STATES_KEYS[i]; + var propNeedsTransition = transition && DEFAULT_ANIMATABLE_MAP[key]; + if (state && state[key] != null) { + if (propNeedsTransition) { + hasTransition = true; + transitionTarget[key] = state[key]; + } + else { + this[key] = state[key]; + } + } + else if (needsRestoreToNormal) { + if (normalState[key] != null) { + if (propNeedsTransition) { + hasTransition = true; + transitionTarget[key] = normalState[key]; + } + else { + this[key] = normalState[key]; + } + } + } + } + if (!transition) { + for (var i = 0; i < this.animators.length; i++) { + var animator = this.animators[i]; + var targetName = animator.targetName; + animator.__changeFinalValue(targetName + ? (state || normalState)[targetName] + : (state || normalState)); + } + } + if (hasTransition) { + this._transitionState(stateName, transitionTarget, animationCfg); + } + }; + Element.prototype._attachComponent = function (componentEl) { + if (componentEl.__zr && !componentEl.__hostTarget) { + throw new Error('Text element has been added to zrender.'); + } + if (componentEl === this) { + throw new Error('Recursive component attachment.'); + } + var zr = this.__zr; + if (zr) { + componentEl.addSelfToZr(zr); + } + componentEl.__zr = zr; + componentEl.__hostTarget = this; + }; + Element.prototype._detachComponent = function (componentEl) { + if (componentEl.__zr) { + componentEl.removeSelfFromZr(componentEl.__zr); + } + componentEl.__zr = null; + componentEl.__hostTarget = null; + }; + Element.prototype.getClipPath = function () { + return this._clipPath; + }; + Element.prototype.setClipPath = function (clipPath) { + if (this._clipPath && this._clipPath !== clipPath) { + this.removeClipPath(); + } + this._attachComponent(clipPath); + this._clipPath = clipPath; + this.markRedraw(); + }; + Element.prototype.removeClipPath = function () { + var clipPath = this._clipPath; + if (clipPath) { + this._detachComponent(clipPath); + this._clipPath = null; + this.markRedraw(); + } + }; + Element.prototype.getTextContent = function () { + return this._textContent; + }; + Element.prototype.setTextContent = function (textEl) { + var previousTextContent = this._textContent; + if (previousTextContent === textEl) { + return; + } + if (previousTextContent && previousTextContent !== textEl) { + this.removeTextContent(); + } + if (textEl.__zr && !textEl.__hostTarget) { + throw new Error('Text element has been added to zrender.'); + } + textEl.attachedTransform = new Transformable(); + this._attachComponent(textEl); + this._textContent = textEl; + this.markRedraw(); + }; + Element.prototype.setTextConfig = function (cfg) { + if (!this.textConfig) { + this.textConfig = {}; + } + extend(this.textConfig, cfg); + this.markRedraw(); + }; + Element.prototype.removeTextContent = function () { + var textEl = this._textContent; + if (textEl) { + textEl.attachedTransform = null; + this._detachComponent(textEl); + this._textContent = null; + this._innerTextDefaultStyle = null; + this.markRedraw(); + } + }; + Element.prototype.getTextGuideLine = function () { + return this._textGuide; + }; + Element.prototype.setTextGuideLine = function (guideLine) { + if (this._textGuide && this._textGuide !== guideLine) { + this.removeTextGuideLine(); + } + this._attachComponent(guideLine); + this._textGuide = guideLine; + this.markRedraw(); + }; + Element.prototype.removeTextGuideLine = function () { + var textGuide = this._textGuide; + if (textGuide) { + this._detachComponent(textGuide); + this._textGuide = null; + this.markRedraw(); + } + }; + Element.prototype.markRedraw = function () { + this.__dirty |= Element.REDARAW_BIT; + var zr = this.__zr; + if (zr) { + if (this.__inHover) { + zr.refreshHover(); + } + else { + zr.refresh(); + } + } + if (this.__hostTarget) { + this.__hostTarget.markRedraw(); + } + }; + Element.prototype.dirty = function () { + this.markRedraw(); + }; + Element.prototype._toggleHoverLayerFlag = function (inHover) { + this.__inHover = inHover; + var textContent = this._textContent; + var textGuide = this._textGuide; + if (textContent) { + textContent.__inHover = inHover; + } + if (textGuide) { + textGuide.__inHover = inHover; + } + }; + Element.prototype.addSelfToZr = function (zr) { + this.__zr = zr; + var animators = this.animators; + if (animators) { + for (var i = 0; i < animators.length; i++) { + zr.animation.addAnimator(animators[i]); + } + } + if (this._clipPath) { + this._clipPath.addSelfToZr(zr); + } + if (this._textContent) { + this._textContent.addSelfToZr(zr); + } + if (this._textGuide) { + this._textGuide.addSelfToZr(zr); + } + }; + Element.prototype.removeSelfFromZr = function (zr) { + this.__zr = null; + var animators = this.animators; + if (animators) { + for (var i = 0; i < animators.length; i++) { + zr.animation.removeAnimator(animators[i]); + } + } + if (this._clipPath) { + this._clipPath.removeSelfFromZr(zr); + } + if (this._textContent) { + this._textContent.removeSelfFromZr(zr); + } + if (this._textGuide) { + this._textGuide.removeSelfFromZr(zr); + } + }; + Element.prototype.animate = function (key, loop) { + var target = key ? this[key] : this; + if (!target) { + logError('Property "' + + key + + '" is not existed in element ' + + this.id); + return; + } + var animator = new Animator(target, loop); + this.addAnimator(animator, key); + return animator; + }; + Element.prototype.addAnimator = function (animator, key) { + var zr = this.__zr; + var el = this; + animator.during(function () { + el.updateDuringAnimation(key); + }).done(function () { + var animators = el.animators; + var idx = indexOf(animators, animator); + if (idx >= 0) { + animators.splice(idx, 1); + } + }); + this.animators.push(animator); + if (zr) { + zr.animation.addAnimator(animator); + } + zr && zr.wakeUp(); + }; + Element.prototype.updateDuringAnimation = function (key) { + this.markRedraw(); + }; + Element.prototype.stopAnimation = function (scope, forwardToLast) { + var animators = this.animators; + var len = animators.length; + var leftAnimators = []; + for (var i = 0; i < len; i++) { + var animator = animators[i]; + if (!scope || scope === animator.scope) { + animator.stop(forwardToLast); + } + else { + leftAnimators.push(animator); + } + } + this.animators = leftAnimators; + return this; + }; + Element.prototype.animateTo = function (target, cfg, animationProps) { + animateTo(this, target, cfg, animationProps); + }; + Element.prototype.animateFrom = function (target, cfg, animationProps) { + animateTo(this, target, cfg, animationProps, true); + }; + Element.prototype._transitionState = function (stateName, target, cfg, animationProps) { + var animators = animateTo(this, target, cfg, animationProps); + for (var i = 0; i < animators.length; i++) { + animators[i].__fromStateTransition = stateName; + } + }; + Element.prototype.getBoundingRect = function () { + return null; + }; + Element.prototype.getPaintRect = function () { + return null; + }; + Element.REDARAW_BIT = 1; + Element.initDefaultProps = (function () { + var elProto = Element.prototype; + elProto.type = 'element'; + elProto.name = ''; + elProto.ignore = false; + elProto.silent = false; + elProto.isGroup = false; + elProto.draggable = false; + elProto.dragging = false; + elProto.ignoreClip = false; + elProto.__inHover = false; + elProto.__dirty = Element.REDARAW_BIT; + var logs = {}; + function logDeprecatedError(key, xKey, yKey) { + if (!logs[key + xKey + yKey]) { + console.warn("DEPRECATED: '" + key + "' has been deprecated. use '" + xKey + "', '" + yKey + "' instead"); + logs[key + xKey + yKey] = true; + } + } + function createLegacyProperty(key, privateKey, xKey, yKey) { + Object.defineProperty(elProto, key, { + get: function () { + logDeprecatedError(key, xKey, yKey); + if (!this[privateKey]) { + var pos = this[privateKey] = []; + enhanceArray(this, pos); + } + return this[privateKey]; + }, + set: function (pos) { + logDeprecatedError(key, xKey, yKey); + this[xKey] = pos[0]; + this[yKey] = pos[1]; + this[privateKey] = pos; + enhanceArray(this, pos); + } + }); + function enhanceArray(self, pos) { + Object.defineProperty(pos, 0, { + get: function () { + return self[xKey]; + }, + set: function (val) { + self[xKey] = val; + } + }); + Object.defineProperty(pos, 1, { + get: function () { + return self[yKey]; + }, + set: function (val) { + self[yKey] = val; + } + }); + } + } + if (Object.defineProperty && (!env.browser.ie || env.browser.version > 8)) { + createLegacyProperty('position', '_legacyPos', 'x', 'y'); + createLegacyProperty('scale', '_legacyScale', 'scaleX', 'scaleY'); + createLegacyProperty('origin', '_legacyOrigin', 'originX', 'originY'); + } + })(); + return Element; + }()); + mixin(Element, Eventful); + mixin(Element, Transformable); + function animateTo(animatable, target, cfg, animationProps, reverse) { + cfg = cfg || {}; + var animators = []; + animateToShallow(animatable, '', animatable, target, cfg, animationProps, animators, reverse); + var finishCount = animators.length; + var doneHappened = false; + var cfgDone = cfg.done; + var cfgAborted = cfg.aborted; + var doneCb = function () { + doneHappened = true; + finishCount--; + if (finishCount <= 0) { + doneHappened + ? (cfgDone && cfgDone()) + : (cfgAborted && cfgAborted()); + } + }; + var abortedCb = function () { + finishCount--; + if (finishCount <= 0) { + doneHappened + ? (cfgDone && cfgDone()) + : (cfgAborted && cfgAborted()); + } + }; + if (!finishCount) { + cfgDone && cfgDone(); + } + if (animators.length > 0 && cfg.during) { + animators[0].during(function (target, percent) { + cfg.during(percent); + }); + } + for (var i = 0; i < animators.length; i++) { + var animator = animators[i]; + if (doneCb) { + animator.done(doneCb); + } + if (abortedCb) { + animator.aborted(abortedCb); + } + animator.start(cfg.easing, cfg.force); + } + return animators; + } + function copyArrShallow(source, target, len) { + for (var i = 0; i < len; i++) { + source[i] = target[i]; + } + } + function is2DArray(value) { + return isArrayLike(value[0]); + } + function copyValue(target, source, key) { + if (isArrayLike(source[key])) { + if (!isArrayLike(target[key])) { + target[key] = []; + } + if (isTypedArray(source[key])) { + var len = source[key].length; + if (target[key].length !== len) { + target[key] = new (source[key].constructor)(len); + copyArrShallow(target[key], source[key], len); + } + } + else { + var sourceArr = source[key]; + var targetArr = target[key]; + var len0 = sourceArr.length; + if (is2DArray(sourceArr)) { + var len1 = sourceArr[0].length; + for (var i = 0; i < len0; i++) { + if (!targetArr[i]) { + targetArr[i] = Array.prototype.slice.call(sourceArr[i]); + } + else { + copyArrShallow(targetArr[i], sourceArr[i], len1); + } + } + } + else { + copyArrShallow(targetArr, sourceArr, len0); + } + targetArr.length = sourceArr.length; + } + } + else { + target[key] = source[key]; + } + } + function animateToShallow(animatable, topKey, source, target, cfg, animationProps, animators, reverse) { + var animatableKeys = []; + var changedKeys = []; + var targetKeys = keys(target); + var duration = cfg.duration; + var delay = cfg.delay; + var additive = cfg.additive; + var setToFinal = cfg.setToFinal; + var animateAll = !isObject(animationProps); + for (var k = 0; k < targetKeys.length; k++) { + var innerKey = targetKeys[k]; + if (source[innerKey] != null + && target[innerKey] != null + && (animateAll || animationProps[innerKey])) { + if (isObject(target[innerKey]) && !isArrayLike(target[innerKey])) { + if (topKey) { + if (!reverse) { + source[innerKey] = target[innerKey]; + animatable.updateDuringAnimation(topKey); + } + continue; + } + animateToShallow(animatable, innerKey, source[innerKey], target[innerKey], cfg, animationProps && animationProps[innerKey], animators, reverse); + } + else { + animatableKeys.push(innerKey); + changedKeys.push(innerKey); + } + } + else if (!reverse) { + source[innerKey] = target[innerKey]; + animatable.updateDuringAnimation(topKey); + changedKeys.push(innerKey); + } + } + var keyLen = animatableKeys.length; + if (keyLen > 0 + || (cfg.force && !animators.length)) { + var existsAnimators = animatable.animators; + var existsAnimatorsOnSameTarget = []; + for (var i = 0; i < existsAnimators.length; i++) { + if (existsAnimators[i].targetName === topKey) { + existsAnimatorsOnSameTarget.push(existsAnimators[i]); + } + } + if (!additive && existsAnimatorsOnSameTarget.length) { + for (var i = 0; i < existsAnimatorsOnSameTarget.length; i++) { + var allAborted = existsAnimatorsOnSameTarget[i].stopTracks(changedKeys); + if (allAborted) { + var idx = indexOf(existsAnimators, existsAnimatorsOnSameTarget[i]); + existsAnimators.splice(idx, 1); + } + } + } + var revertedSource = void 0; + var reversedTarget = void 0; + var sourceClone = void 0; + if (reverse) { + reversedTarget = {}; + if (setToFinal) { + revertedSource = {}; + } + for (var i = 0; i < keyLen; i++) { + var innerKey = animatableKeys[i]; + reversedTarget[innerKey] = source[innerKey]; + if (setToFinal) { + revertedSource[innerKey] = target[innerKey]; + } + else { + source[innerKey] = target[innerKey]; + } + } + } + else if (setToFinal) { + sourceClone = {}; + for (var i = 0; i < keyLen; i++) { + var innerKey = animatableKeys[i]; + sourceClone[innerKey] = cloneValue(source[innerKey]); + copyValue(source, target, innerKey); + } + } + var animator = new Animator(source, false, additive ? existsAnimatorsOnSameTarget : null); + animator.targetName = topKey; + if (cfg.scope) { + animator.scope = cfg.scope; + } + if (setToFinal && revertedSource) { + animator.whenWithKeys(0, revertedSource, animatableKeys); + } + if (sourceClone) { + animator.whenWithKeys(0, sourceClone, animatableKeys); + } + animator.whenWithKeys(duration == null ? 500 : duration, reverse ? reversedTarget : target, animatableKeys).delay(delay || 0); + animatable.addAnimator(animator, topKey); + animators.push(animator); + } + } + + var DEFAULT_MIN_MERGE = 32; + var DEFAULT_MIN_GALLOPING = 7; + function minRunLength(n) { + var r = 0; + while (n >= DEFAULT_MIN_MERGE) { + r |= n & 1; + n >>= 1; + } + return n + r; + } + function makeAscendingRun(array, lo, hi, compare) { + var runHi = lo + 1; + if (runHi === hi) { + return 1; + } + if (compare(array[runHi++], array[lo]) < 0) { + while (runHi < hi && compare(array[runHi], array[runHi - 1]) < 0) { + runHi++; + } + reverseRun(array, lo, runHi); + } + else { + while (runHi < hi && compare(array[runHi], array[runHi - 1]) >= 0) { + runHi++; + } + } + return runHi - lo; + } + function reverseRun(array, lo, hi) { + hi--; + while (lo < hi) { + var t = array[lo]; + array[lo++] = array[hi]; + array[hi--] = t; + } + } + function binaryInsertionSort(array, lo, hi, start, compare) { + if (start === lo) { + start++; + } + for (; start < hi; start++) { + var pivot = array[start]; + var left = lo; + var right = start; + var mid; + while (left < right) { + mid = left + right >>> 1; + if (compare(pivot, array[mid]) < 0) { + right = mid; + } + else { + left = mid + 1; + } + } + var n = start - left; + switch (n) { + case 3: + array[left + 3] = array[left + 2]; + case 2: + array[left + 2] = array[left + 1]; + case 1: + array[left + 1] = array[left]; + break; + default: + while (n > 0) { + array[left + n] = array[left + n - 1]; + n--; + } + } + array[left] = pivot; + } + } + function gallopLeft(value, array, start, length, hint, compare) { + var lastOffset = 0; + var maxOffset = 0; + var offset = 1; + if (compare(value, array[start + hint]) > 0) { + maxOffset = length - hint; + while (offset < maxOffset && compare(value, array[start + hint + offset]) > 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + if (offset <= 0) { + offset = maxOffset; + } + } + if (offset > maxOffset) { + offset = maxOffset; + } + lastOffset += hint; + offset += hint; + } + else { + maxOffset = hint + 1; + while (offset < maxOffset && compare(value, array[start + hint - offset]) <= 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + if (offset <= 0) { + offset = maxOffset; + } + } + if (offset > maxOffset) { + offset = maxOffset; + } + var tmp = lastOffset; + lastOffset = hint - offset; + offset = hint - tmp; + } + lastOffset++; + while (lastOffset < offset) { + var m = lastOffset + (offset - lastOffset >>> 1); + if (compare(value, array[start + m]) > 0) { + lastOffset = m + 1; + } + else { + offset = m; + } + } + return offset; + } + function gallopRight(value, array, start, length, hint, compare) { + var lastOffset = 0; + var maxOffset = 0; + var offset = 1; + if (compare(value, array[start + hint]) < 0) { + maxOffset = hint + 1; + while (offset < maxOffset && compare(value, array[start + hint - offset]) < 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + if (offset <= 0) { + offset = maxOffset; + } + } + if (offset > maxOffset) { + offset = maxOffset; + } + var tmp = lastOffset; + lastOffset = hint - offset; + offset = hint - tmp; + } + else { + maxOffset = length - hint; + while (offset < maxOffset && compare(value, array[start + hint + offset]) >= 0) { + lastOffset = offset; + offset = (offset << 1) + 1; + if (offset <= 0) { + offset = maxOffset; + } + } + if (offset > maxOffset) { + offset = maxOffset; + } + lastOffset += hint; + offset += hint; + } + lastOffset++; + while (lastOffset < offset) { + var m = lastOffset + (offset - lastOffset >>> 1); + if (compare(value, array[start + m]) < 0) { + offset = m; + } + else { + lastOffset = m + 1; + } + } + return offset; + } + function TimSort(array, compare) { + var minGallop = DEFAULT_MIN_GALLOPING; + var length = 0; + var runStart; + var runLength; + var stackSize = 0; + length = array.length; + var tmp = []; + runStart = []; + runLength = []; + function pushRun(_runStart, _runLength) { + runStart[stackSize] = _runStart; + runLength[stackSize] = _runLength; + stackSize += 1; + } + function mergeRuns() { + while (stackSize > 1) { + var n = stackSize - 2; + if ((n >= 1 && runLength[n - 1] <= runLength[n] + runLength[n + 1]) + || (n >= 2 && runLength[n - 2] <= runLength[n] + runLength[n - 1])) { + if (runLength[n - 1] < runLength[n + 1]) { + n--; + } + } + else if (runLength[n] > runLength[n + 1]) { + break; + } + mergeAt(n); + } + } + function forceMergeRuns() { + while (stackSize > 1) { + var n = stackSize - 2; + if (n > 0 && runLength[n - 1] < runLength[n + 1]) { + n--; + } + mergeAt(n); + } + } + function mergeAt(i) { + var start1 = runStart[i]; + var length1 = runLength[i]; + var start2 = runStart[i + 1]; + var length2 = runLength[i + 1]; + runLength[i] = length1 + length2; + if (i === stackSize - 3) { + runStart[i + 1] = runStart[i + 2]; + runLength[i + 1] = runLength[i + 2]; + } + stackSize--; + var k = gallopRight(array[start2], array, start1, length1, 0, compare); + start1 += k; + length1 -= k; + if (length1 === 0) { + return; + } + length2 = gallopLeft(array[start1 + length1 - 1], array, start2, length2, length2 - 1, compare); + if (length2 === 0) { + return; + } + if (length1 <= length2) { + mergeLow(start1, length1, start2, length2); + } + else { + mergeHigh(start1, length1, start2, length2); + } + } + function mergeLow(start1, length1, start2, length2) { + var i = 0; + for (i = 0; i < length1; i++) { + tmp[i] = array[start1 + i]; + } + var cursor1 = 0; + var cursor2 = start2; + var dest = start1; + array[dest++] = array[cursor2++]; + if (--length2 === 0) { + for (i = 0; i < length1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + return; + } + if (length1 === 1) { + for (i = 0; i < length2; i++) { + array[dest + i] = array[cursor2 + i]; + } + array[dest + length2] = tmp[cursor1]; + return; + } + var _minGallop = minGallop; + var count1; + var count2; + var exit; + while (1) { + count1 = 0; + count2 = 0; + exit = false; + do { + if (compare(array[cursor2], tmp[cursor1]) < 0) { + array[dest++] = array[cursor2++]; + count2++; + count1 = 0; + if (--length2 === 0) { + exit = true; + break; + } + } + else { + array[dest++] = tmp[cursor1++]; + count1++; + count2 = 0; + if (--length1 === 1) { + exit = true; + break; + } + } + } while ((count1 | count2) < _minGallop); + if (exit) { + break; + } + do { + count1 = gallopRight(array[cursor2], tmp, cursor1, length1, 0, compare); + if (count1 !== 0) { + for (i = 0; i < count1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + dest += count1; + cursor1 += count1; + length1 -= count1; + if (length1 <= 1) { + exit = true; + break; + } + } + array[dest++] = array[cursor2++]; + if (--length2 === 0) { + exit = true; + break; + } + count2 = gallopLeft(tmp[cursor1], array, cursor2, length2, 0, compare); + if (count2 !== 0) { + for (i = 0; i < count2; i++) { + array[dest + i] = array[cursor2 + i]; + } + dest += count2; + cursor2 += count2; + length2 -= count2; + if (length2 === 0) { + exit = true; + break; + } + } + array[dest++] = tmp[cursor1++]; + if (--length1 === 1) { + exit = true; + break; + } + _minGallop--; + } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); + if (exit) { + break; + } + if (_minGallop < 0) { + _minGallop = 0; + } + _minGallop += 2; + } + minGallop = _minGallop; + minGallop < 1 && (minGallop = 1); + if (length1 === 1) { + for (i = 0; i < length2; i++) { + array[dest + i] = array[cursor2 + i]; + } + array[dest + length2] = tmp[cursor1]; + } + else if (length1 === 0) { + throw new Error(); + } + else { + for (i = 0; i < length1; i++) { + array[dest + i] = tmp[cursor1 + i]; + } + } + } + function mergeHigh(start1, length1, start2, length2) { + var i = 0; + for (i = 0; i < length2; i++) { + tmp[i] = array[start2 + i]; + } + var cursor1 = start1 + length1 - 1; + var cursor2 = length2 - 1; + var dest = start2 + length2 - 1; + var customCursor = 0; + var customDest = 0; + array[dest--] = array[cursor1--]; + if (--length1 === 0) { + customCursor = dest - (length2 - 1); + for (i = 0; i < length2; i++) { + array[customCursor + i] = tmp[i]; + } + return; + } + if (length2 === 1) { + dest -= length1; + cursor1 -= length1; + customDest = dest + 1; + customCursor = cursor1 + 1; + for (i = length1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + array[dest] = tmp[cursor2]; + return; + } + var _minGallop = minGallop; + while (true) { + var count1 = 0; + var count2 = 0; + var exit = false; + do { + if (compare(tmp[cursor2], array[cursor1]) < 0) { + array[dest--] = array[cursor1--]; + count1++; + count2 = 0; + if (--length1 === 0) { + exit = true; + break; + } + } + else { + array[dest--] = tmp[cursor2--]; + count2++; + count1 = 0; + if (--length2 === 1) { + exit = true; + break; + } + } + } while ((count1 | count2) < _minGallop); + if (exit) { + break; + } + do { + count1 = length1 - gallopRight(tmp[cursor2], array, start1, length1, length1 - 1, compare); + if (count1 !== 0) { + dest -= count1; + cursor1 -= count1; + length1 -= count1; + customDest = dest + 1; + customCursor = cursor1 + 1; + for (i = count1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + if (length1 === 0) { + exit = true; + break; + } + } + array[dest--] = tmp[cursor2--]; + if (--length2 === 1) { + exit = true; + break; + } + count2 = length2 - gallopLeft(array[cursor1], tmp, 0, length2, length2 - 1, compare); + if (count2 !== 0) { + dest -= count2; + cursor2 -= count2; + length2 -= count2; + customDest = dest + 1; + customCursor = cursor2 + 1; + for (i = 0; i < count2; i++) { + array[customDest + i] = tmp[customCursor + i]; + } + if (length2 <= 1) { + exit = true; + break; + } + } + array[dest--] = array[cursor1--]; + if (--length1 === 0) { + exit = true; + break; + } + _minGallop--; + } while (count1 >= DEFAULT_MIN_GALLOPING || count2 >= DEFAULT_MIN_GALLOPING); + if (exit) { + break; + } + if (_minGallop < 0) { + _minGallop = 0; + } + _minGallop += 2; + } + minGallop = _minGallop; + if (minGallop < 1) { + minGallop = 1; + } + if (length2 === 1) { + dest -= length1; + cursor1 -= length1; + customDest = dest + 1; + customCursor = cursor1 + 1; + for (i = length1 - 1; i >= 0; i--) { + array[customDest + i] = array[customCursor + i]; + } + array[dest] = tmp[cursor2]; + } + else if (length2 === 0) { + throw new Error(); + } + else { + customCursor = dest - (length2 - 1); + for (i = 0; i < length2; i++) { + array[customCursor + i] = tmp[i]; + } + } + } + return { + mergeRuns: mergeRuns, + forceMergeRuns: forceMergeRuns, + pushRun: pushRun + }; + } + function sort(array, compare, lo, hi) { + if (!lo) { + lo = 0; + } + if (!hi) { + hi = array.length; + } + var remaining = hi - lo; + if (remaining < 2) { + return; + } + var runLength = 0; + if (remaining < DEFAULT_MIN_MERGE) { + runLength = makeAscendingRun(array, lo, hi, compare); + binaryInsertionSort(array, lo, hi, lo + runLength, compare); + return; + } + var ts = TimSort(array, compare); + var minRun = minRunLength(remaining); + do { + runLength = makeAscendingRun(array, lo, hi, compare); + if (runLength < minRun) { + var force = remaining; + if (force > minRun) { + force = minRun; + } + binaryInsertionSort(array, lo, lo + force, lo + runLength, compare); + runLength = force; + } + ts.pushRun(lo, runLength); + ts.mergeRuns(); + remaining -= runLength; + lo += runLength; + } while (remaining !== 0); + ts.forceMergeRuns(); + } + + var invalidZErrorLogged = false; + function logInvalidZError() { + if (invalidZErrorLogged) { + return; + } + invalidZErrorLogged = true; + console.warn('z / z2 / zlevel of displayable is invalid, which may cause unexpected errors'); + } + function shapeCompareFunc(a, b) { + if (a.zlevel === b.zlevel) { + if (a.z === b.z) { + return a.z2 - b.z2; + } + return a.z - b.z; + } + return a.zlevel - b.zlevel; + } + var Storage = (function () { + function Storage() { + this._roots = []; + this._displayList = []; + this._displayListLen = 0; + this.displayableSortFunc = shapeCompareFunc; + } + Storage.prototype.traverse = function (cb, context) { + for (var i = 0; i < this._roots.length; i++) { + this._roots[i].traverse(cb, context); + } + }; + Storage.prototype.getDisplayList = function (update, includeIgnore) { + includeIgnore = includeIgnore || false; + var displayList = this._displayList; + if (update || !displayList.length) { + this.updateDisplayList(includeIgnore); + } + return displayList; + }; + Storage.prototype.updateDisplayList = function (includeIgnore) { + this._displayListLen = 0; + var roots = this._roots; + var displayList = this._displayList; + for (var i = 0, len = roots.length; i < len; i++) { + this._updateAndAddDisplayable(roots[i], null, includeIgnore); + } + displayList.length = this._displayListLen; + env.canvasSupported && sort(displayList, shapeCompareFunc); + }; + Storage.prototype._updateAndAddDisplayable = function (el, clipPaths, includeIgnore) { + if (el.ignore && !includeIgnore) { + return; + } + el.beforeUpdate(); + el.update(); + el.afterUpdate(); + var userSetClipPath = el.getClipPath(); + if (el.ignoreClip) { + clipPaths = null; + } + else if (userSetClipPath) { + if (clipPaths) { + clipPaths = clipPaths.slice(); + } + else { + clipPaths = []; + } + var currentClipPath = userSetClipPath; + var parentClipPath = el; + while (currentClipPath) { + currentClipPath.parent = parentClipPath; + currentClipPath.updateTransform(); + clipPaths.push(currentClipPath); + parentClipPath = currentClipPath; + currentClipPath = currentClipPath.getClipPath(); + } + } + if (el.childrenRef) { + var children = el.childrenRef(); + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (el.__dirty) { + child.__dirty |= Element.REDARAW_BIT; + } + this._updateAndAddDisplayable(child, clipPaths, includeIgnore); + } + el.__dirty = 0; + } + else { + var disp = el; + if (clipPaths && clipPaths.length) { + disp.__clipPaths = clipPaths; + } + else if (disp.__clipPaths && disp.__clipPaths.length > 0) { + disp.__clipPaths = []; + } + if (isNaN(disp.z)) { + logInvalidZError(); + disp.z = 0; + } + if (isNaN(disp.z2)) { + logInvalidZError(); + disp.z2 = 0; + } + if (isNaN(disp.zlevel)) { + logInvalidZError(); + disp.zlevel = 0; + } + this._displayList[this._displayListLen++] = disp; + } + var decalEl = el.getDecalElement && el.getDecalElement(); + if (decalEl) { + this._updateAndAddDisplayable(decalEl, clipPaths, includeIgnore); + } + var textGuide = el.getTextGuideLine(); + if (textGuide) { + this._updateAndAddDisplayable(textGuide, clipPaths, includeIgnore); + } + var textEl = el.getTextContent(); + if (textEl) { + this._updateAndAddDisplayable(textEl, clipPaths, includeIgnore); + } + }; + Storage.prototype.addRoot = function (el) { + if (el.__zr && el.__zr.storage === this) { + return; + } + this._roots.push(el); + }; + Storage.prototype.delRoot = function (el) { + if (el instanceof Array) { + for (var i = 0, l = el.length; i < l; i++) { + this.delRoot(el[i]); + } + return; + } + var idx = indexOf(this._roots, el); + if (idx >= 0) { + this._roots.splice(idx, 1); + } + }; + Storage.prototype.delAllRoots = function () { + this._roots = []; + this._displayList = []; + this._displayListLen = 0; + return; + }; + Storage.prototype.getRoots = function () { + return this._roots; + }; + Storage.prototype.dispose = function () { + this._displayList = null; + this._roots = null; + }; + return Storage; + }()); + + var requestAnimationFrame; + requestAnimationFrame = (typeof window !== 'undefined' + && ((window.requestAnimationFrame && window.requestAnimationFrame.bind(window)) + || (window.msRequestAnimationFrame && window.msRequestAnimationFrame.bind(window)) + || window.mozRequestAnimationFrame + || window.webkitRequestAnimationFrame)) || function (func) { + return setTimeout(func, 16); + }; + var requestAnimationFrame$1 = requestAnimationFrame; + + var Animation = (function (_super) { + __extends(Animation, _super); + function Animation(opts) { + var _this = _super.call(this) || this; + _this._running = false; + _this._time = 0; + _this._pausedTime = 0; + _this._pauseStart = 0; + _this._paused = false; + opts = opts || {}; + _this.stage = opts.stage || {}; + _this.onframe = opts.onframe || function () { }; + return _this; + } + Animation.prototype.addClip = function (clip) { + if (clip.animation) { + this.removeClip(clip); + } + if (!this._clipsHead) { + this._clipsHead = this._clipsTail = clip; + } + else { + this._clipsTail.next = clip; + clip.prev = this._clipsTail; + clip.next = null; + this._clipsTail = clip; + } + clip.animation = this; + }; + Animation.prototype.addAnimator = function (animator) { + animator.animation = this; + var clip = animator.getClip(); + if (clip) { + this.addClip(clip); + } + }; + Animation.prototype.removeClip = function (clip) { + if (!clip.animation) { + return; + } + var prev = clip.prev; + var next = clip.next; + if (prev) { + prev.next = next; + } + else { + this._clipsHead = next; + } + if (next) { + next.prev = prev; + } + else { + this._clipsTail = prev; + } + clip.next = clip.prev = clip.animation = null; + }; + Animation.prototype.removeAnimator = function (animator) { + var clip = animator.getClip(); + if (clip) { + this.removeClip(clip); + } + animator.animation = null; + }; + Animation.prototype.update = function (notTriggerFrameAndStageUpdate) { + var time = new Date().getTime() - this._pausedTime; + var delta = time - this._time; + var clip = this._clipsHead; + while (clip) { + var nextClip = clip.next; + var finished = clip.step(time, delta); + if (finished) { + clip.ondestroy && clip.ondestroy(); + this.removeClip(clip); + clip = nextClip; + } + else { + clip = nextClip; + } + } + this._time = time; + if (!notTriggerFrameAndStageUpdate) { + this.onframe(delta); + this.trigger('frame', delta); + this.stage.update && this.stage.update(); + } + }; + Animation.prototype._startLoop = function () { + var self = this; + this._running = true; + function step() { + if (self._running) { + requestAnimationFrame$1(step); + !self._paused && self.update(); + } + } + requestAnimationFrame$1(step); + }; + Animation.prototype.start = function () { + if (this._running) { + return; + } + this._time = new Date().getTime(); + this._pausedTime = 0; + this._startLoop(); + }; + Animation.prototype.stop = function () { + this._running = false; + }; + Animation.prototype.pause = function () { + if (!this._paused) { + this._pauseStart = new Date().getTime(); + this._paused = true; + } + }; + Animation.prototype.resume = function () { + if (this._paused) { + this._pausedTime += (new Date().getTime()) - this._pauseStart; + this._paused = false; + } + }; + Animation.prototype.clear = function () { + var clip = this._clipsHead; + while (clip) { + var nextClip = clip.next; + clip.prev = clip.next = clip.animation = null; + clip = nextClip; + } + this._clipsHead = this._clipsTail = null; + }; + Animation.prototype.isFinished = function () { + return this._clipsHead == null; + }; + Animation.prototype.animate = function (target, options) { + options = options || {}; + this.start(); + var animator = new Animator(target, options.loop); + this.addAnimator(animator); + return animator; + }; + return Animation; + }(Eventful)); + + var TOUCH_CLICK_DELAY = 300; + var globalEventSupported = env.domSupported; + var localNativeListenerNames = (function () { + var mouseHandlerNames = [ + 'click', 'dblclick', 'mousewheel', 'wheel', 'mouseout', + 'mouseup', 'mousedown', 'mousemove', 'contextmenu' + ]; + var touchHandlerNames = [ + 'touchstart', 'touchend', 'touchmove' + ]; + var pointerEventNameMap = { + pointerdown: 1, pointerup: 1, pointermove: 1, pointerout: 1 + }; + var pointerHandlerNames = map(mouseHandlerNames, function (name) { + var nm = name.replace('mouse', 'pointer'); + return pointerEventNameMap.hasOwnProperty(nm) ? nm : name; + }); + return { + mouse: mouseHandlerNames, + touch: touchHandlerNames, + pointer: pointerHandlerNames + }; + })(); + var globalNativeListenerNames = { + mouse: ['mousemove', 'mouseup'], + pointer: ['pointermove', 'pointerup'] + }; + var wheelEventSupported = false; + function isPointerFromTouch(event) { + var pointerType = event.pointerType; + return pointerType === 'pen' || pointerType === 'touch'; + } + function setTouchTimer(scope) { + scope.touching = true; + if (scope.touchTimer != null) { + clearTimeout(scope.touchTimer); + scope.touchTimer = null; + } + scope.touchTimer = setTimeout(function () { + scope.touching = false; + scope.touchTimer = null; + }, 700); + } + function markTouch(event) { + event && (event.zrByTouch = true); + } + function normalizeGlobalEvent(instance, event) { + return normalizeEvent(instance.dom, new FakeGlobalEvent(instance, event), true); + } + function isLocalEl(instance, el) { + var elTmp = el; + var isLocal = false; + while (elTmp && elTmp.nodeType !== 9 + && !(isLocal = elTmp.domBelongToZr + || (elTmp !== el && elTmp === instance.painterRoot))) { + elTmp = elTmp.parentNode; + } + return isLocal; + } + var FakeGlobalEvent = (function () { + function FakeGlobalEvent(instance, event) { + this.stopPropagation = noop; + this.stopImmediatePropagation = noop; + this.preventDefault = noop; + this.type = event.type; + this.target = this.currentTarget = instance.dom; + this.pointerType = event.pointerType; + this.clientX = event.clientX; + this.clientY = event.clientY; + } + return FakeGlobalEvent; + }()); + var localDOMHandlers = { + mousedown: function (event) { + event = normalizeEvent(this.dom, event); + this.__mayPointerCapture = [event.zrX, event.zrY]; + this.trigger('mousedown', event); + }, + mousemove: function (event) { + event = normalizeEvent(this.dom, event); + var downPoint = this.__mayPointerCapture; + if (downPoint && (event.zrX !== downPoint[0] || event.zrY !== downPoint[1])) { + this.__togglePointerCapture(true); + } + this.trigger('mousemove', event); + }, + mouseup: function (event) { + event = normalizeEvent(this.dom, event); + this.__togglePointerCapture(false); + this.trigger('mouseup', event); + }, + mouseout: function (event) { + event = normalizeEvent(this.dom, event); + var element = event.toElement || event.relatedTarget; + if (!isLocalEl(this, element)) { + if (this.__pointerCapturing) { + event.zrEventControl = 'no_globalout'; + } + this.trigger('mouseout', event); + } + }, + wheel: function (event) { + wheelEventSupported = true; + event = normalizeEvent(this.dom, event); + this.trigger('mousewheel', event); + }, + mousewheel: function (event) { + if (wheelEventSupported) { + return; + } + event = normalizeEvent(this.dom, event); + this.trigger('mousewheel', event); + }, + touchstart: function (event) { + event = normalizeEvent(this.dom, event); + markTouch(event); + this.__lastTouchMoment = new Date(); + this.handler.processGesture(event, 'start'); + localDOMHandlers.mousemove.call(this, event); + localDOMHandlers.mousedown.call(this, event); + }, + touchmove: function (event) { + event = normalizeEvent(this.dom, event); + markTouch(event); + this.handler.processGesture(event, 'change'); + localDOMHandlers.mousemove.call(this, event); + }, + touchend: function (event) { + event = normalizeEvent(this.dom, event); + markTouch(event); + this.handler.processGesture(event, 'end'); + localDOMHandlers.mouseup.call(this, event); + if (+new Date() - (+this.__lastTouchMoment) < TOUCH_CLICK_DELAY) { + localDOMHandlers.click.call(this, event); + } + }, + pointerdown: function (event) { + localDOMHandlers.mousedown.call(this, event); + }, + pointermove: function (event) { + if (!isPointerFromTouch(event)) { + localDOMHandlers.mousemove.call(this, event); + } + }, + pointerup: function (event) { + localDOMHandlers.mouseup.call(this, event); + }, + pointerout: function (event) { + if (!isPointerFromTouch(event)) { + localDOMHandlers.mouseout.call(this, event); + } + } + }; + each(['click', 'dblclick', 'contextmenu'], function (name) { + localDOMHandlers[name] = function (event) { + event = normalizeEvent(this.dom, event); + this.trigger(name, event); + }; + }); + var globalDOMHandlers = { + pointermove: function (event) { + if (!isPointerFromTouch(event)) { + globalDOMHandlers.mousemove.call(this, event); + } + }, + pointerup: function (event) { + globalDOMHandlers.mouseup.call(this, event); + }, + mousemove: function (event) { + this.trigger('mousemove', event); + }, + mouseup: function (event) { + var pointerCaptureReleasing = this.__pointerCapturing; + this.__togglePointerCapture(false); + this.trigger('mouseup', event); + if (pointerCaptureReleasing) { + event.zrEventControl = 'only_globalout'; + this.trigger('mouseout', event); + } + } + }; + function mountLocalDOMEventListeners(instance, scope) { + var domHandlers = scope.domHandlers; + if (env.pointerEventsSupported) { + each(localNativeListenerNames.pointer, function (nativeEventName) { + mountSingleDOMEventListener(scope, nativeEventName, function (event) { + domHandlers[nativeEventName].call(instance, event); + }); + }); + } + else { + if (env.touchEventsSupported) { + each(localNativeListenerNames.touch, function (nativeEventName) { + mountSingleDOMEventListener(scope, nativeEventName, function (event) { + domHandlers[nativeEventName].call(instance, event); + setTouchTimer(scope); + }); + }); + } + each(localNativeListenerNames.mouse, function (nativeEventName) { + mountSingleDOMEventListener(scope, nativeEventName, function (event) { + event = getNativeEvent(event); + if (!scope.touching) { + domHandlers[nativeEventName].call(instance, event); + } + }); + }); + } + } + function mountGlobalDOMEventListeners(instance, scope) { + if (env.pointerEventsSupported) { + each(globalNativeListenerNames.pointer, mount); + } + else if (!env.touchEventsSupported) { + each(globalNativeListenerNames.mouse, mount); + } + function mount(nativeEventName) { + function nativeEventListener(event) { + event = getNativeEvent(event); + if (!isLocalEl(instance, event.target)) { + event = normalizeGlobalEvent(instance, event); + scope.domHandlers[nativeEventName].call(instance, event); + } + } + mountSingleDOMEventListener(scope, nativeEventName, nativeEventListener, { capture: true }); + } + } + function mountSingleDOMEventListener(scope, nativeEventName, listener, opt) { + scope.mounted[nativeEventName] = listener; + scope.listenerOpts[nativeEventName] = opt; + addEventListener(scope.domTarget, nativeEventName, listener, opt); + } + function unmountDOMEventListeners(scope) { + var mounted = scope.mounted; + for (var nativeEventName in mounted) { + if (mounted.hasOwnProperty(nativeEventName)) { + removeEventListener(scope.domTarget, nativeEventName, mounted[nativeEventName], scope.listenerOpts[nativeEventName]); + } + } + scope.mounted = {}; + } + var DOMHandlerScope = (function () { + function DOMHandlerScope(domTarget, domHandlers) { + this.mounted = {}; + this.listenerOpts = {}; + this.touching = false; + this.domTarget = domTarget; + this.domHandlers = domHandlers; + } + return DOMHandlerScope; + }()); + var HandlerDomProxy = (function (_super) { + __extends(HandlerDomProxy, _super); + function HandlerDomProxy(dom, painterRoot) { + var _this = _super.call(this) || this; + _this.__pointerCapturing = false; + _this.dom = dom; + _this.painterRoot = painterRoot; + _this._localHandlerScope = new DOMHandlerScope(dom, localDOMHandlers); + if (globalEventSupported) { + _this._globalHandlerScope = new DOMHandlerScope(document, globalDOMHandlers); + } + mountLocalDOMEventListeners(_this, _this._localHandlerScope); + return _this; + } + HandlerDomProxy.prototype.dispose = function () { + unmountDOMEventListeners(this._localHandlerScope); + if (globalEventSupported) { + unmountDOMEventListeners(this._globalHandlerScope); + } + }; + HandlerDomProxy.prototype.setCursor = function (cursorStyle) { + this.dom.style && (this.dom.style.cursor = cursorStyle || 'default'); + }; + HandlerDomProxy.prototype.__togglePointerCapture = function (isPointerCapturing) { + this.__mayPointerCapture = null; + if (globalEventSupported + && ((+this.__pointerCapturing) ^ (+isPointerCapturing))) { + this.__pointerCapturing = isPointerCapturing; + var globalHandlerScope = this._globalHandlerScope; + isPointerCapturing + ? mountGlobalDOMEventListeners(this, globalHandlerScope) + : unmountDOMEventListeners(globalHandlerScope); + } + }; + return HandlerDomProxy; + }(Eventful)); + + var Group = (function (_super) { + __extends(Group, _super); + function Group(opts) { + var _this = _super.call(this) || this; + _this.isGroup = true; + _this._children = []; + _this.attr(opts); + return _this; + } + Group.prototype.childrenRef = function () { + return this._children; + }; + Group.prototype.children = function () { + return this._children.slice(); + }; + Group.prototype.childAt = function (idx) { + return this._children[idx]; + }; + Group.prototype.childOfName = function (name) { + var children = this._children; + for (var i = 0; i < children.length; i++) { + if (children[i].name === name) { + return children[i]; + } + } + }; + Group.prototype.childCount = function () { + return this._children.length; + }; + Group.prototype.add = function (child) { + if (child) { + if (child !== this && child.parent !== this) { + this._children.push(child); + this._doAdd(child); + } + if (child.__hostTarget) { + throw 'This elemenet has been used as an attachment'; + } + } + return this; + }; + Group.prototype.addBefore = function (child, nextSibling) { + if (child && child !== this && child.parent !== this + && nextSibling && nextSibling.parent === this) { + var children = this._children; + var idx = children.indexOf(nextSibling); + if (idx >= 0) { + children.splice(idx, 0, child); + this._doAdd(child); + } + } + return this; + }; + Group.prototype.replaceAt = function (child, index) { + var children = this._children; + var old = children[index]; + if (child && child !== this && child.parent !== this && child !== old) { + children[index] = child; + old.parent = null; + var zr = this.__zr; + if (zr) { + old.removeSelfFromZr(zr); + } + this._doAdd(child); + } + return this; + }; + Group.prototype._doAdd = function (child) { + if (child.parent) { + child.parent.remove(child); + } + child.parent = this; + var zr = this.__zr; + if (zr && zr !== child.__zr) { + child.addSelfToZr(zr); + } + zr && zr.refresh(); + }; + Group.prototype.remove = function (child) { + var zr = this.__zr; + var children = this._children; + var idx = indexOf(children, child); + if (idx < 0) { + return this; + } + children.splice(idx, 1); + child.parent = null; + if (zr) { + child.removeSelfFromZr(zr); + } + zr && zr.refresh(); + return this; + }; + Group.prototype.removeAll = function () { + var children = this._children; + var zr = this.__zr; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (zr) { + child.removeSelfFromZr(zr); + } + child.parent = null; + } + children.length = 0; + return this; + }; + Group.prototype.eachChild = function (cb, context) { + var children = this._children; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + cb.call(context, child, i); + } + return this; + }; + Group.prototype.traverse = function (cb, context) { + for (var i = 0; i < this._children.length; i++) { + var child = this._children[i]; + var stopped = cb.call(context, child); + if (child.isGroup && !stopped) { + child.traverse(cb, context); + } + } + return this; + }; + Group.prototype.addSelfToZr = function (zr) { + _super.prototype.addSelfToZr.call(this, zr); + for (var i = 0; i < this._children.length; i++) { + var child = this._children[i]; + child.addSelfToZr(zr); + } + }; + Group.prototype.removeSelfFromZr = function (zr) { + _super.prototype.removeSelfFromZr.call(this, zr); + for (var i = 0; i < this._children.length; i++) { + var child = this._children[i]; + child.removeSelfFromZr(zr); + } + }; + Group.prototype.getBoundingRect = function (includeChildren) { + var tmpRect = new BoundingRect(0, 0, 0, 0); + var children = includeChildren || this._children; + var tmpMat = []; + var rect = null; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (child.ignore || child.invisible) { + continue; + } + var childRect = child.getBoundingRect(); + var transform = child.getLocalTransform(tmpMat); + if (transform) { + BoundingRect.applyTransform(tmpRect, childRect, transform); + rect = rect || tmpRect.clone(); + rect.union(tmpRect); + } + else { + rect = rect || childRect.clone(); + rect.union(childRect); + } + } + return rect || tmpRect; + }; + return Group; + }(Element)); + Group.prototype.type = 'group'; + + /*! + * ZRender, a high performance 2d drawing library. + * + * Copyright (c) 2013, Baidu Inc. + * All rights reserved. + * + * LICENSE + * https://github.com/ecomfe/zrender/blob/master/LICENSE.txt + */ + var useVML = !env.canvasSupported; + var painterCtors = {}; + var instances = {}; + function delInstance(id) { + delete instances[id]; + } + function isDarkMode(backgroundColor) { + if (!backgroundColor) { + return false; + } + if (typeof backgroundColor === 'string') { + return lum(backgroundColor, 1) < DARK_MODE_THRESHOLD; + } + else if (backgroundColor.colorStops) { + var colorStops = backgroundColor.colorStops; + var totalLum = 0; + var len = colorStops.length; + for (var i = 0; i < len; i++) { + totalLum += lum(colorStops[i].color, 1); + } + totalLum /= len; + return totalLum < DARK_MODE_THRESHOLD; + } + return false; + } + var ZRender = (function () { + function ZRender(id, dom, opts) { + var _this = this; + this._sleepAfterStill = 10; + this._stillFrameAccum = 0; + this._needsRefresh = true; + this._needsRefreshHover = true; + this._darkMode = false; + opts = opts || {}; + this.dom = dom; + this.id = id; + var storage = new Storage(); + var rendererType = opts.renderer || 'canvas'; + if (useVML) { + throw new Error('IE8 support has been dropped since 5.0'); + } + if (!painterCtors[rendererType]) { + rendererType = keys(painterCtors)[0]; + } + if (!painterCtors[rendererType]) { + throw new Error("Renderer '" + rendererType + "' is not imported. Please import it first."); + } + opts.useDirtyRect = opts.useDirtyRect == null + ? false + : opts.useDirtyRect; + var painter = new painterCtors[rendererType](dom, storage, opts, id); + this.storage = storage; + this.painter = painter; + var handerProxy = (!env.node && !env.worker) + ? new HandlerDomProxy(painter.getViewportRoot(), painter.root) + : null; + this.handler = new Handler(storage, painter, handerProxy, painter.root); + this.animation = new Animation({ + stage: { + update: function () { return _this._flush(true); } + } + }); + this.animation.start(); + } + ZRender.prototype.add = function (el) { + if (!el) { + return; + } + this.storage.addRoot(el); + el.addSelfToZr(this); + this.refresh(); + }; + ZRender.prototype.remove = function (el) { + if (!el) { + return; + } + this.storage.delRoot(el); + el.removeSelfFromZr(this); + this.refresh(); + }; + ZRender.prototype.configLayer = function (zLevel, config) { + if (this.painter.configLayer) { + this.painter.configLayer(zLevel, config); + } + this.refresh(); + }; + ZRender.prototype.setBackgroundColor = function (backgroundColor) { + if (this.painter.setBackgroundColor) { + this.painter.setBackgroundColor(backgroundColor); + } + this.refresh(); + this._backgroundColor = backgroundColor; + this._darkMode = isDarkMode(backgroundColor); + }; + ZRender.prototype.getBackgroundColor = function () { + return this._backgroundColor; + }; + ZRender.prototype.setDarkMode = function (darkMode) { + this._darkMode = darkMode; + }; + ZRender.prototype.isDarkMode = function () { + return this._darkMode; + }; + ZRender.prototype.refreshImmediately = function (fromInside) { + if (!fromInside) { + this.animation.update(true); + } + this._needsRefresh = false; + this.painter.refresh(); + this._needsRefresh = false; + }; + ZRender.prototype.refresh = function () { + this._needsRefresh = true; + this.animation.start(); + }; + ZRender.prototype.flush = function () { + this._flush(false); + }; + ZRender.prototype._flush = function (fromInside) { + var triggerRendered; + var start = new Date().getTime(); + if (this._needsRefresh) { + triggerRendered = true; + this.refreshImmediately(fromInside); + } + if (this._needsRefreshHover) { + triggerRendered = true; + this.refreshHoverImmediately(); + } + var end = new Date().getTime(); + if (triggerRendered) { + this._stillFrameAccum = 0; + this.trigger('rendered', { + elapsedTime: end - start + }); + } + else if (this._sleepAfterStill > 0) { + this._stillFrameAccum++; + if (this._stillFrameAccum > this._sleepAfterStill) { + this.animation.stop(); + } + } + }; + ZRender.prototype.setSleepAfterStill = function (stillFramesCount) { + this._sleepAfterStill = stillFramesCount; + }; + ZRender.prototype.wakeUp = function () { + this.animation.start(); + this._stillFrameAccum = 0; + }; + ZRender.prototype.addHover = function (el) { + }; + ZRender.prototype.removeHover = function (el) { + }; + ZRender.prototype.clearHover = function () { + }; + ZRender.prototype.refreshHover = function () { + this._needsRefreshHover = true; + }; + ZRender.prototype.refreshHoverImmediately = function () { + this._needsRefreshHover = false; + if (this.painter.refreshHover && this.painter.getType() === 'canvas') { + this.painter.refreshHover(); + } + }; + ZRender.prototype.resize = function (opts) { + opts = opts || {}; + this.painter.resize(opts.width, opts.height); + this.handler.resize(); + }; + ZRender.prototype.clearAnimation = function () { + this.animation.clear(); + }; + ZRender.prototype.getWidth = function () { + return this.painter.getWidth(); + }; + ZRender.prototype.getHeight = function () { + return this.painter.getHeight(); + }; + ZRender.prototype.pathToImage = function (e, dpr) { + if (this.painter.pathToImage) { + return this.painter.pathToImage(e, dpr); + } + }; + ZRender.prototype.setCursorStyle = function (cursorStyle) { + this.handler.setCursorStyle(cursorStyle); + }; + ZRender.prototype.findHover = function (x, y) { + return this.handler.findHover(x, y); + }; + ZRender.prototype.on = function (eventName, eventHandler, context) { + this.handler.on(eventName, eventHandler, context); + return this; + }; + ZRender.prototype.off = function (eventName, eventHandler) { + this.handler.off(eventName, eventHandler); + }; + ZRender.prototype.trigger = function (eventName, event) { + this.handler.trigger(eventName, event); + }; + ZRender.prototype.clear = function () { + var roots = this.storage.getRoots(); + for (var i = 0; i < roots.length; i++) { + if (roots[i] instanceof Group) { + roots[i].removeSelfFromZr(this); + } + } + this.storage.delAllRoots(); + this.painter.clear(); + }; + ZRender.prototype.dispose = function () { + this.animation.stop(); + this.clear(); + this.storage.dispose(); + this.painter.dispose(); + this.handler.dispose(); + this.animation = + this.storage = + this.painter = + this.handler = null; + delInstance(this.id); + }; + return ZRender; + }()); + function init(dom, opts) { + var zr = new ZRender(guid(), dom, opts); + instances[zr.id] = zr; + return zr; + } + function dispose(zr) { + zr.dispose(); + } + function disposeAll() { + for (var key in instances) { + if (instances.hasOwnProperty(key)) { + instances[key].dispose(); + } + } + instances = {}; + } + function getInstance(id) { + return instances[id]; + } + function registerPainter(name, Ctor) { + painterCtors[name] = Ctor; + } + var version = '5.0.3'; + + var zrender = /*#__PURE__*/Object.freeze({ + __proto__: null, + init: init, + dispose: dispose, + disposeAll: disposeAll, + getInstance: getInstance, + registerPainter: registerPainter, + version: version + }); + + var RADIAN_EPSILON = 1e-4; + + function _trim(str) { + return str.replace(/^\s+|\s+$/g, ''); + } + + function linearMap(val, domain, range, clamp) { + var subDomain = domain[1] - domain[0]; + var subRange = range[1] - range[0]; + + if (subDomain === 0) { + return subRange === 0 ? range[0] : (range[0] + range[1]) / 2; + } + + if (clamp) { + if (subDomain > 0) { + if (val <= domain[0]) { + return range[0]; + } else if (val >= domain[1]) { + return range[1]; + } + } else { + if (val >= domain[0]) { + return range[0]; + } else if (val <= domain[1]) { + return range[1]; + } + } + } else { + if (val === domain[0]) { + return range[0]; + } + + if (val === domain[1]) { + return range[1]; + } + } + + return (val - domain[0]) / subDomain * subRange + range[0]; + } + function parsePercent$1(percent, all) { + switch (percent) { + case 'center': + case 'middle': + percent = '50%'; + break; + + case 'left': + case 'top': + percent = '0%'; + break; + + case 'right': + case 'bottom': + percent = '100%'; + break; + } + + if (typeof percent === 'string') { + if (_trim(percent).match(/%$/)) { + return parseFloat(percent) / 100 * all; + } + + return parseFloat(percent); + } + + return percent == null ? NaN : +percent; + } + function round(x, precision, returnStr) { + if (precision == null) { + precision = 10; + } + + precision = Math.min(Math.max(0, precision), 20); + x = (+x).toFixed(precision); + return returnStr ? x : +x; + } + function asc(arr) { + arr.sort(function (a, b) { + return a - b; + }); + return arr; + } + function getPrecision(val) { + val = +val; + + if (isNaN(val)) { + return 0; + } + + var e = 1; + var count = 0; + + while (Math.round(val * e) / e !== val) { + e *= 10; + count++; + } + + return count; + } + function getPrecisionSafe(val) { + var str = val.toString(); + var eIndex = str.indexOf('e'); + + if (eIndex > 0) { + var precision = +str.slice(eIndex + 1); + return precision < 0 ? -precision : 0; + } else { + var dotIndex = str.indexOf('.'); + return dotIndex < 0 ? 0 : str.length - 1 - dotIndex; + } + } + function getPixelPrecision(dataExtent, pixelExtent) { + var log = Math.log; + var LN10 = Math.LN10; + var dataQuantity = Math.floor(log(dataExtent[1] - dataExtent[0]) / LN10); + var sizeQuantity = Math.round(log(Math.abs(pixelExtent[1] - pixelExtent[0])) / LN10); + var precision = Math.min(Math.max(-dataQuantity + sizeQuantity, 0), 20); + return !isFinite(precision) ? 20 : precision; + } + function getPercentWithPrecision(valueList, idx, precision) { + if (!valueList[idx]) { + return 0; + } + + var sum = reduce(valueList, function (acc, val) { + return acc + (isNaN(val) ? 0 : val); + }, 0); + + if (sum === 0) { + return 0; + } + + var digits = Math.pow(10, precision); + var votesPerQuota = map(valueList, function (val) { + return (isNaN(val) ? 0 : val) / sum * digits * 100; + }); + var targetSeats = digits * 100; + var seats = map(votesPerQuota, function (votes) { + return Math.floor(votes); + }); + var currentSum = reduce(seats, function (acc, val) { + return acc + val; + }, 0); + var remainder = map(votesPerQuota, function (votes, idx) { + return votes - seats[idx]; + }); + + while (currentSum < targetSeats) { + var max = Number.NEGATIVE_INFINITY; + var maxId = null; + + for (var i = 0, len = remainder.length; i < len; ++i) { + if (remainder[i] > max) { + max = remainder[i]; + maxId = i; + } + } + + ++seats[maxId]; + remainder[maxId] = 0; + ++currentSum; + } + + return seats[idx] / digits; + } + var MAX_SAFE_INTEGER = 9007199254740991; + function remRadian(radian) { + var pi2 = Math.PI * 2; + return (radian % pi2 + pi2) % pi2; + } + function isRadianAroundZero(val) { + return val > -RADIAN_EPSILON && val < RADIAN_EPSILON; + } + var TIME_REG = /^(?:(\d{4})(?:[-\/](\d{1,2})(?:[-\/](\d{1,2})(?:[T ](\d{1,2})(?::(\d{1,2})(?::(\d{1,2})(?:[.,](\d+))?)?)?(Z|[\+\-]\d\d:?\d\d)?)?)?)?)?$/; + function parseDate(value) { + if (value instanceof Date) { + return value; + } else if (typeof value === 'string') { + var match = TIME_REG.exec(value); + + if (!match) { + return new Date(NaN); + } + + if (!match[8]) { + return new Date(+match[1], +(match[2] || 1) - 1, +match[3] || 1, +match[4] || 0, +(match[5] || 0), +match[6] || 0, +match[7] || 0); + } else { + var hour = +match[4] || 0; + + if (match[8].toUpperCase() !== 'Z') { + hour -= +match[8].slice(0, 3); + } + + return new Date(Date.UTC(+match[1], +(match[2] || 1) - 1, +match[3] || 1, hour, +(match[5] || 0), +match[6] || 0, +match[7] || 0)); + } + } else if (value == null) { + return new Date(NaN); + } + + return new Date(Math.round(value)); + } + function quantity(val) { + return Math.pow(10, quantityExponent(val)); + } + function quantityExponent(val) { + if (val === 0) { + return 0; + } + + var exp = Math.floor(Math.log(val) / Math.LN10); + + if (val / Math.pow(10, exp) >= 10) { + exp++; + } + + return exp; + } + function nice(val, round) { + var exponent = quantityExponent(val); + var exp10 = Math.pow(10, exponent); + var f = val / exp10; + var nf; + + if (round) { + if (f < 1.5) { + nf = 1; + } else if (f < 2.5) { + nf = 2; + } else if (f < 4) { + nf = 3; + } else if (f < 7) { + nf = 5; + } else { + nf = 10; + } + } else { + if (f < 1) { + nf = 1; + } else if (f < 2) { + nf = 2; + } else if (f < 3) { + nf = 3; + } else if (f < 5) { + nf = 5; + } else { + nf = 10; + } + } + + val = nf * exp10; + return exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val; + } + function quantile(ascArr, p) { + var H = (ascArr.length - 1) * p + 1; + var h = Math.floor(H); + var v = +ascArr[h - 1]; + var e = H - h; + return e ? v + e * (ascArr[h] - v) : v; + } + function reformIntervals(list) { + list.sort(function (a, b) { + return littleThan(a, b, 0) ? -1 : 1; + }); + var curr = -Infinity; + var currClose = 1; + + for (var i = 0; i < list.length;) { + var interval = list[i].interval; + var close_1 = list[i].close; + + for (var lg = 0; lg < 2; lg++) { + if (interval[lg] <= curr) { + interval[lg] = curr; + close_1[lg] = !lg ? 1 - currClose : 1; + } + + curr = interval[lg]; + currClose = close_1[lg]; + } + + if (interval[0] === interval[1] && close_1[0] * close_1[1] !== 1) { + list.splice(i, 1); + } else { + i++; + } + } + + return list; + + function littleThan(a, b, lg) { + return a.interval[lg] < b.interval[lg] || a.interval[lg] === b.interval[lg] && (a.close[lg] - b.close[lg] === (!lg ? 1 : -1) || !lg && littleThan(a, b, 1)); + } + } + function numericToNumber(val) { + var valFloat = parseFloat(val); + return valFloat == val && (valFloat !== 0 || typeof val !== 'string' || val.indexOf('x') <= 0) ? valFloat : NaN; + } + function isNumeric(val) { + return !isNaN(numericToNumber(val)); + } + function getRandomIdBase() { + return Math.round(Math.random() * 9); + } + function getGreatestCommonDividor(a, b) { + if (b === 0) { + return a; + } + + return getGreatestCommonDividor(b, a % b); + } + function getLeastCommonMultiple(a, b) { + if (a == null) { + return b; + } + + if (b == null) { + return a; + } + + return a * b / getGreatestCommonDividor(a, b); + } + + var ECHARTS_PREFIX = '[ECharts] '; + var storedLogs = {}; + var hasConsole = typeof console !== 'undefined' && console.warn && console.log; + function warn(str) { + if (hasConsole) { + console.warn(ECHARTS_PREFIX + str); + } + } + function error(str) { + if (hasConsole) { + console.error(ECHARTS_PREFIX + str); + } + } + function deprecateLog(str) { + if ("development" !== 'production') { + if (storedLogs[str]) { + return; + } + + if (hasConsole) { + storedLogs[str] = true; + console.warn(ECHARTS_PREFIX + 'DEPRECATED: ' + str); + } + } + } + function deprecateReplaceLog(oldOpt, newOpt, scope) { + if ("development" !== 'production') { + deprecateLog((scope ? "[" + scope + "]" : '') + (oldOpt + " is deprecated, use " + newOpt + " instead.")); + } + } + function consoleLog() { + var args = []; + + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + + if ("development" !== 'production') { + if (typeof console !== 'undefined' && console.log) { + console.log.apply(console, args); + } + } + } + function makePrintable() { + var hintInfo = []; + + for (var _i = 0; _i < arguments.length; _i++) { + hintInfo[_i] = arguments[_i]; + } + + var msg = ''; + + if ("development" !== 'production') { + var makePrintableStringIfPossible_1 = function (val) { + return val === void 0 ? 'undefined' : val === Infinity ? 'Infinity' : val === -Infinity ? '-Infinity' : eqNaN(val) ? 'NaN' : val instanceof Date ? 'Date(' + val.toISOString() + ')' : isFunction(val) ? 'function () { ... }' : isRegExp(val) ? val + '' : null; + }; + + msg = map(hintInfo, function (arg) { + if (isString(arg)) { + return arg; + } else { + var printableStr = makePrintableStringIfPossible_1(arg); + + if (printableStr != null) { + return printableStr; + } else if (typeof JSON !== 'undefined' && JSON.stringify) { + try { + return JSON.stringify(arg, function (n, val) { + var printableStr = makePrintableStringIfPossible_1(val); + return printableStr == null ? val : printableStr; + }); + } catch (err) { + return '?'; + } + } else { + return '?'; + } + } + }).join(' '); + } + + return msg; + } + function throwError(msg) { + throw new Error(msg); + } + + var DUMMY_COMPONENT_NAME_PREFIX = 'series\0'; + var INTERNAL_COMPONENT_ID_PREFIX = '\0_ec_\0'; + function normalizeToArray(value) { + return value instanceof Array ? value : value == null ? [] : [value]; + } + function defaultEmphasis(opt, key, subOpts) { + if (opt) { + opt[key] = opt[key] || {}; + opt.emphasis = opt.emphasis || {}; + opt.emphasis[key] = opt.emphasis[key] || {}; + + for (var i = 0, len = subOpts.length; i < len; i++) { + var subOptName = subOpts[i]; + + if (!opt.emphasis[key].hasOwnProperty(subOptName) && opt[key].hasOwnProperty(subOptName)) { + opt.emphasis[key][subOptName] = opt[key][subOptName]; + } + } + } + } + var TEXT_STYLE_OPTIONS = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'rich', 'tag', 'color', 'textBorderColor', 'textBorderWidth', 'width', 'height', 'lineHeight', 'align', 'verticalAlign', 'baseline', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY', 'textShadowColor', 'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY', 'backgroundColor', 'borderColor', 'borderWidth', 'borderRadius', 'padding']; + function getDataItemValue(dataItem) { + return isObject(dataItem) && !isArray(dataItem) && !(dataItem instanceof Date) ? dataItem.value : dataItem; + } + function isDataItemOption(dataItem) { + return isObject(dataItem) && !(dataItem instanceof Array); + } + function mappingToExists(existings, newCmptOptions, mode) { + var isNormalMergeMode = mode === 'normalMerge'; + var isReplaceMergeMode = mode === 'replaceMerge'; + var isReplaceAllMode = mode === 'replaceAll'; + existings = existings || []; + newCmptOptions = (newCmptOptions || []).slice(); + var existingIdIdxMap = createHashMap(); + each(newCmptOptions, function (cmptOption, index) { + if (!isObject(cmptOption)) { + newCmptOptions[index] = null; + return; + } + + if ("development" !== 'production') { + if (cmptOption.id != null && !isValidIdOrName(cmptOption.id)) { + warnInvalidateIdOrName(cmptOption.id); + } + + if (cmptOption.name != null && !isValidIdOrName(cmptOption.name)) { + warnInvalidateIdOrName(cmptOption.name); + } + } + }); + var result = prepareResult(existings, existingIdIdxMap, mode); + + if (isNormalMergeMode || isReplaceMergeMode) { + mappingById(result, existings, existingIdIdxMap, newCmptOptions); + } + + if (isNormalMergeMode) { + mappingByName(result, newCmptOptions); + } + + if (isNormalMergeMode || isReplaceMergeMode) { + mappingByIndex(result, newCmptOptions, isReplaceMergeMode); + } else if (isReplaceAllMode) { + mappingInReplaceAllMode(result, newCmptOptions); + } + + makeIdAndName(result); + return result; + } + + function prepareResult(existings, existingIdIdxMap, mode) { + var result = []; + + if (mode === 'replaceAll') { + return result; + } + + for (var index = 0; index < existings.length; index++) { + var existing = existings[index]; + + if (existing && existing.id != null) { + existingIdIdxMap.set(existing.id, index); + } + + result.push({ + existing: mode === 'replaceMerge' || isComponentIdInternal(existing) ? null : existing, + newOption: null, + keyInfo: null, + brandNew: null + }); + } + + return result; + } + + function mappingById(result, existings, existingIdIdxMap, newCmptOptions) { + each(newCmptOptions, function (cmptOption, index) { + if (!cmptOption || cmptOption.id == null) { + return; + } + + var optionId = makeComparableKey(cmptOption.id); + var existingIdx = existingIdIdxMap.get(optionId); + + if (existingIdx != null) { + var resultItem = result[existingIdx]; + assert(!resultItem.newOption, 'Duplicated option on id "' + optionId + '".'); + resultItem.newOption = cmptOption; + resultItem.existing = existings[existingIdx]; + newCmptOptions[index] = null; + } + }); + } + + function mappingByName(result, newCmptOptions) { + each(newCmptOptions, function (cmptOption, index) { + if (!cmptOption || cmptOption.name == null) { + return; + } + + for (var i = 0; i < result.length; i++) { + var existing = result[i].existing; + + if (!result[i].newOption && existing && (existing.id == null || cmptOption.id == null) && !isComponentIdInternal(cmptOption) && !isComponentIdInternal(existing) && keyExistAndEqual('name', existing, cmptOption)) { + result[i].newOption = cmptOption; + newCmptOptions[index] = null; + return; + } + } + }); + } + + function mappingByIndex(result, newCmptOptions, brandNew) { + each(newCmptOptions, function (cmptOption) { + if (!cmptOption) { + return; + } + + var resultItem; + var nextIdx = 0; + + while ((resultItem = result[nextIdx]) && (resultItem.newOption || isComponentIdInternal(resultItem.existing) || resultItem.existing && cmptOption.id != null && !keyExistAndEqual('id', cmptOption, resultItem.existing))) { + nextIdx++; + } + + if (resultItem) { + resultItem.newOption = cmptOption; + resultItem.brandNew = brandNew; + } else { + result.push({ + newOption: cmptOption, + brandNew: brandNew, + existing: null, + keyInfo: null + }); + } + + nextIdx++; + }); + } + + function mappingInReplaceAllMode(result, newCmptOptions) { + each(newCmptOptions, function (cmptOption) { + result.push({ + newOption: cmptOption, + brandNew: true, + existing: null, + keyInfo: null + }); + }); + } + + function makeIdAndName(mapResult) { + var idMap = createHashMap(); + each(mapResult, function (item) { + var existing = item.existing; + existing && idMap.set(existing.id, item); + }); + each(mapResult, function (item) { + var opt = item.newOption; + assert(!opt || opt.id == null || !idMap.get(opt.id) || idMap.get(opt.id) === item, 'id duplicates: ' + (opt && opt.id)); + opt && opt.id != null && idMap.set(opt.id, item); + !item.keyInfo && (item.keyInfo = {}); + }); + each(mapResult, function (item, index) { + var existing = item.existing; + var opt = item.newOption; + var keyInfo = item.keyInfo; + + if (!isObject(opt)) { + return; + } + + keyInfo.name = opt.name != null ? makeComparableKey(opt.name) : existing ? existing.name : DUMMY_COMPONENT_NAME_PREFIX + index; + + if (existing) { + keyInfo.id = makeComparableKey(existing.id); + } else if (opt.id != null) { + keyInfo.id = makeComparableKey(opt.id); + } else { + var idNum = 0; + + do { + keyInfo.id = '\0' + keyInfo.name + '\0' + idNum++; + } while (idMap.get(keyInfo.id)); + } + + idMap.set(keyInfo.id, item); + }); + } + + function keyExistAndEqual(attr, obj1, obj2) { + var key1 = convertOptionIdName(obj1[attr], null); + var key2 = convertOptionIdName(obj2[attr], null); + return key1 != null && key2 != null && key1 === key2; + } + + function makeComparableKey(val) { + if ("development" !== 'production') { + if (val == null) { + throw new Error(); + } + } + + return convertOptionIdName(val, ''); + } + + function convertOptionIdName(idOrName, defaultValue) { + if (idOrName == null) { + return defaultValue; + } + + var type = typeof idOrName; + return type === 'string' ? idOrName : type === 'number' || isStringSafe(idOrName) ? idOrName + '' : defaultValue; + } + + function warnInvalidateIdOrName(idOrName) { + if ("development" !== 'production') { + warn('`' + idOrName + '` is invalid id or name. Must be a string or number.'); + } + } + + function isValidIdOrName(idOrName) { + return isStringSafe(idOrName) || isNumeric(idOrName); + } + + function isNameSpecified(componentModel) { + var name = componentModel.name; + return !!(name && name.indexOf(DUMMY_COMPONENT_NAME_PREFIX)); + } + function isComponentIdInternal(cmptOption) { + return cmptOption && cmptOption.id != null && makeComparableKey(cmptOption.id).indexOf(INTERNAL_COMPONENT_ID_PREFIX) === 0; + } + function makeInternalComponentId(idSuffix) { + return INTERNAL_COMPONENT_ID_PREFIX + idSuffix; + } + function setComponentTypeToKeyInfo(mappingResult, mainType, componentModelCtor) { + each(mappingResult, function (item) { + var newOption = item.newOption; + + if (isObject(newOption)) { + item.keyInfo.mainType = mainType; + item.keyInfo.subType = determineSubType(mainType, newOption, item.existing, componentModelCtor); + } + }); + } + + function determineSubType(mainType, newCmptOption, existComponent, componentModelCtor) { + var subType = newCmptOption.type ? newCmptOption.type : existComponent ? existComponent.subType : componentModelCtor.determineSubType(mainType, newCmptOption); + return subType; + } + + function compressBatches(batchA, batchB) { + var mapA = {}; + var mapB = {}; + makeMap(batchA || [], mapA); + makeMap(batchB || [], mapB, mapA); + return [mapToArray(mapA), mapToArray(mapB)]; + + function makeMap(sourceBatch, map, otherMap) { + for (var i = 0, len = sourceBatch.length; i < len; i++) { + var seriesId = convertOptionIdName(sourceBatch[i].seriesId, null); + + if (seriesId == null) { + return; + } + + var dataIndices = normalizeToArray(sourceBatch[i].dataIndex); + var otherDataIndices = otherMap && otherMap[seriesId]; + + for (var j = 0, lenj = dataIndices.length; j < lenj; j++) { + var dataIndex = dataIndices[j]; + + if (otherDataIndices && otherDataIndices[dataIndex]) { + otherDataIndices[dataIndex] = null; + } else { + (map[seriesId] || (map[seriesId] = {}))[dataIndex] = 1; + } + } + } + } + + function mapToArray(map, isData) { + var result = []; + + for (var i in map) { + if (map.hasOwnProperty(i) && map[i] != null) { + if (isData) { + result.push(+i); + } else { + var dataIndices = mapToArray(map[i], true); + dataIndices.length && result.push({ + seriesId: i, + dataIndex: dataIndices + }); + } + } + } + + return result; + } + } + function queryDataIndex(data, payload) { + if (payload.dataIndexInside != null) { + return payload.dataIndexInside; + } else if (payload.dataIndex != null) { + return isArray(payload.dataIndex) ? map(payload.dataIndex, function (value) { + return data.indexOfRawIndex(value); + }) : data.indexOfRawIndex(payload.dataIndex); + } else if (payload.name != null) { + return isArray(payload.name) ? map(payload.name, function (value) { + return data.indexOfName(value); + }) : data.indexOfName(payload.name); + } + } + function makeInner() { + var key = '__ec_inner_' + innerUniqueIndex++; + return function (hostObj) { + return hostObj[key] || (hostObj[key] = {}); + }; + } + var innerUniqueIndex = getRandomIdBase(); + function parseFinder(ecModel, finderInput, opt) { + var finder; + + if (isString(finderInput)) { + var obj = {}; + obj[finderInput + 'Index'] = 0; + finder = obj; + } else { + finder = finderInput; + } + + var queryOptionMap = createHashMap(); + var result = {}; + var mainTypeSpecified = false; + each(finder, function (value, key) { + if (key === 'dataIndex' || key === 'dataIndexInside') { + result[key] = value; + return; + } + + var parsedKey = key.match(/^(\w+)(Index|Id|Name)$/) || []; + var mainType = parsedKey[1]; + var queryType = (parsedKey[2] || '').toLowerCase(); + + if (!mainType || !queryType || opt && opt.includeMainTypes && indexOf(opt.includeMainTypes, mainType) < 0) { + return; + } + + mainTypeSpecified = mainTypeSpecified || !!mainType; + var queryOption = queryOptionMap.get(mainType) || queryOptionMap.set(mainType, {}); + queryOption[queryType] = value; + }); + var defaultMainType = opt ? opt.defaultMainType : null; + + if (!mainTypeSpecified && defaultMainType) { + queryOptionMap.set(defaultMainType, {}); + } + + queryOptionMap.each(function (queryOption, mainType) { + var queryResult = queryReferringComponents(ecModel, mainType, queryOption, { + useDefault: defaultMainType === mainType, + enableAll: opt && opt.enableAll != null ? opt.enableAll : true, + enableNone: opt && opt.enableNone != null ? opt.enableNone : true + }); + result[mainType + 'Models'] = queryResult.models; + result[mainType + 'Model'] = queryResult.models[0]; + }); + return result; + } + var SINGLE_REFERRING = { + useDefault: true, + enableAll: false, + enableNone: false + }; + var MULTIPLE_REFERRING = { + useDefault: false, + enableAll: true, + enableNone: true + }; + function queryReferringComponents(ecModel, mainType, userOption, opt) { + opt = opt || SINGLE_REFERRING; + var indexOption = userOption.index; + var idOption = userOption.id; + var nameOption = userOption.name; + var result = { + models: null, + specified: indexOption != null || idOption != null || nameOption != null + }; + + if (!result.specified) { + var firstCmpt = void 0; + result.models = opt.useDefault && (firstCmpt = ecModel.getComponent(mainType)) ? [firstCmpt] : []; + return result; + } + + if (indexOption === 'none' || indexOption === false) { + assert(opt.enableNone, '`"none"` or `false` is not a valid value on index option.'); + result.models = []; + return result; + } + + if (indexOption === 'all') { + assert(opt.enableAll, '`"all"` is not a valid value on index option.'); + indexOption = idOption = nameOption = null; + } + + result.models = ecModel.queryComponents({ + mainType: mainType, + index: indexOption, + id: idOption, + name: nameOption + }); + return result; + } + function setAttribute(dom, key, value) { + dom.setAttribute ? dom.setAttribute(key, value) : dom[key] = value; + } + function getAttribute(dom, key) { + return dom.getAttribute ? dom.getAttribute(key) : dom[key]; + } + function getTooltipRenderMode(renderModeOption) { + if (renderModeOption === 'auto') { + return env.domSupported ? 'html' : 'richText'; + } else { + return renderModeOption || 'html'; + } + } + function groupData(array, getKey) { + var buckets = createHashMap(); + var keys = []; + each(array, function (item) { + var key = getKey(item); + (buckets.get(key) || (keys.push(key), buckets.set(key, []))).push(item); + }); + return { + keys: keys, + buckets: buckets + }; + } + function interpolateRawValues(data, precision, sourceValue, targetValue, percent) { + var isAutoPrecision = precision == null || precision === 'auto'; + + if (targetValue == null) { + return targetValue; + } + + if (typeof targetValue === 'number') { + var value = interpolateNumber(sourceValue || 0, targetValue, percent); + return round(value, isAutoPrecision ? Math.max(getPrecisionSafe(sourceValue || 0), getPrecisionSafe(targetValue)) : precision); + } else if (typeof targetValue === 'string') { + return percent < 1 ? sourceValue : targetValue; + } else { + var interpolated = []; + var leftArr = sourceValue; + var rightArr = targetValue; + var length_1 = Math.max(leftArr ? leftArr.length : 0, rightArr.length); + + for (var i = 0; i < length_1; ++i) { + var info = data.getDimensionInfo(i); + + if (info.type === 'ordinal') { + interpolated[i] = (percent < 1 && leftArr ? leftArr : rightArr)[i]; + } else { + var leftVal = leftArr && leftArr[i] ? leftArr[i] : 0; + var rightVal = rightArr[i]; + var value = interpolateNumber(leftVal, rightVal, percent); + interpolated[i] = round(value, isAutoPrecision ? Math.max(getPrecisionSafe(leftVal), getPrecisionSafe(rightVal)) : precision); + } + } + + return interpolated; + } + } + + var TYPE_DELIMITER = '.'; + var IS_CONTAINER = '___EC__COMPONENT__CONTAINER___'; + var IS_EXTENDED_CLASS = '___EC__EXTENDED_CLASS___'; + function parseClassType(componentType) { + var ret = { + main: '', + sub: '' + }; + + if (componentType) { + var typeArr = componentType.split(TYPE_DELIMITER); + ret.main = typeArr[0] || ''; + ret.sub = typeArr[1] || ''; + } + + return ret; + } + + function checkClassType(componentType) { + assert(/^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(componentType), 'componentType "' + componentType + '" illegal'); + } + + function isExtendedClass(clz) { + return !!(clz && clz[IS_EXTENDED_CLASS]); + } + function enableClassExtend(rootClz, mandatoryMethods) { + rootClz.$constructor = rootClz; + + rootClz.extend = function (proto) { + if ("development" !== 'production') { + each(mandatoryMethods, function (method) { + if (!proto[method]) { + console.warn('Method `' + method + '` should be implemented' + (proto.type ? ' in ' + proto.type : '') + '.'); + } + }); + } + + var superClass = this; + + function ExtendedClass() { + var args = []; + + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + + if (!proto.$constructor) { + if (!isESClass(superClass)) { + superClass.apply(this, arguments); + } else { + var ins = createObject(ExtendedClass.prototype, new (superClass.bind.apply(superClass, __spreadArrays([void 0], args)))()); + return ins; + } + } else { + proto.$constructor.apply(this, arguments); + } + } + + ExtendedClass[IS_EXTENDED_CLASS] = true; + extend(ExtendedClass.prototype, proto); + ExtendedClass.extend = this.extend; + ExtendedClass.superCall = superCall; + ExtendedClass.superApply = superApply; + inherits(ExtendedClass, this); + ExtendedClass.superClass = superClass; + return ExtendedClass; + }; + } + + function isESClass(fn) { + return typeof fn === 'function' && /^class\s/.test(Function.prototype.toString.call(fn)); + } + + function mountExtend(SubClz, SupperClz) { + SubClz.extend = SupperClz.extend; + } + var classBase = Math.round(Math.random() * 10); + function enableClassCheck(target) { + var classAttr = ['__\0is_clz', classBase++].join('_'); + target.prototype[classAttr] = true; + + if ("development" !== 'production') { + assert(!target.isInstance, 'The method "is" can not be defined.'); + } + + target.isInstance = function (obj) { + return !!(obj && obj[classAttr]); + }; + } + + function superCall(context, methodName) { + var args = []; + + for (var _i = 2; _i < arguments.length; _i++) { + args[_i - 2] = arguments[_i]; + } + + return this.superClass.prototype[methodName].apply(context, args); + } + + function superApply(context, methodName, args) { + return this.superClass.prototype[methodName].apply(context, args); + } + + function enableClassManagement(target) { + var storage = {}; + + target.registerClass = function (clz) { + var componentFullType = clz.type || clz.prototype.type; + + if (componentFullType) { + checkClassType(componentFullType); + clz.prototype.type = componentFullType; + var componentTypeInfo = parseClassType(componentFullType); + + if (!componentTypeInfo.sub) { + if ("development" !== 'production') { + if (storage[componentTypeInfo.main]) { + console.warn(componentTypeInfo.main + ' exists.'); + } + } + + storage[componentTypeInfo.main] = clz; + } else if (componentTypeInfo.sub !== IS_CONTAINER) { + var container = makeContainer(componentTypeInfo); + container[componentTypeInfo.sub] = clz; + } + } + + return clz; + }; + + target.getClass = function (mainType, subType, throwWhenNotFound) { + var clz = storage[mainType]; + + if (clz && clz[IS_CONTAINER]) { + clz = subType ? clz[subType] : null; + } + + if (throwWhenNotFound && !clz) { + throw new Error(!subType ? mainType + '.' + 'type should be specified.' : 'Component ' + mainType + '.' + (subType || '') + ' not exists. Load it first.'); + } + + return clz; + }; + + target.getClassesByMainType = function (componentType) { + var componentTypeInfo = parseClassType(componentType); + var result = []; + var obj = storage[componentTypeInfo.main]; + + if (obj && obj[IS_CONTAINER]) { + each(obj, function (o, type) { + type !== IS_CONTAINER && result.push(o); + }); + } else { + result.push(obj); + } + + return result; + }; + + target.hasClass = function (componentType) { + var componentTypeInfo = parseClassType(componentType); + return !!storage[componentTypeInfo.main]; + }; + + target.getAllClassMainTypes = function () { + var types = []; + each(storage, function (obj, type) { + types.push(type); + }); + return types; + }; + + target.hasSubTypes = function (componentType) { + var componentTypeInfo = parseClassType(componentType); + var obj = storage[componentTypeInfo.main]; + return obj && obj[IS_CONTAINER]; + }; + + function makeContainer(componentTypeInfo) { + var container = storage[componentTypeInfo.main]; + + if (!container || !container[IS_CONTAINER]) { + container = storage[componentTypeInfo.main] = {}; + container[IS_CONTAINER] = true; + } + + return container; + } + } + + function makeStyleMapper(properties, ignoreParent) { + for (var i = 0; i < properties.length; i++) { + if (!properties[i][1]) { + properties[i][1] = properties[i][0]; + } + } + + ignoreParent = ignoreParent || false; + return function (model, excludes, includes) { + var style = {}; + + for (var i = 0; i < properties.length; i++) { + var propName = properties[i][1]; + + if (excludes && indexOf(excludes, propName) >= 0 || includes && indexOf(includes, propName) < 0) { + continue; + } + + var val = model.getShallow(propName, ignoreParent); + + if (val != null) { + style[properties[i][0]] = val; + } + } + + return style; + }; + } + + var AREA_STYLE_KEY_MAP = [['fill', 'color'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['opacity'], ['shadowColor']]; + var getAreaStyle = makeStyleMapper(AREA_STYLE_KEY_MAP); + + var AreaStyleMixin = function () { + function AreaStyleMixin() {} + + AreaStyleMixin.prototype.getAreaStyle = function (excludes, includes) { + return getAreaStyle(this, excludes, includes); + }; + + return AreaStyleMixin; + }(); + + var globalImageCache = new LRU(50); + function findExistImage(newImageOrSrc) { + if (typeof newImageOrSrc === 'string') { + var cachedImgObj = globalImageCache.get(newImageOrSrc); + return cachedImgObj && cachedImgObj.image; + } + else { + return newImageOrSrc; + } + } + function createOrUpdateImage(newImageOrSrc, image, hostEl, onload, cbPayload) { + if (!newImageOrSrc) { + return image; + } + else if (typeof newImageOrSrc === 'string') { + if ((image && image.__zrImageSrc === newImageOrSrc) || !hostEl) { + return image; + } + var cachedImgObj = globalImageCache.get(newImageOrSrc); + var pendingWrap = { hostEl: hostEl, cb: onload, cbPayload: cbPayload }; + if (cachedImgObj) { + image = cachedImgObj.image; + !isImageReady(image) && cachedImgObj.pending.push(pendingWrap); + } + else { + image = new Image(); + image.onload = image.onerror = imageOnLoad; + globalImageCache.put(newImageOrSrc, image.__cachedImgObj = { + image: image, + pending: [pendingWrap] + }); + image.src = image.__zrImageSrc = newImageOrSrc; + } + return image; + } + else { + return newImageOrSrc; + } + } + function imageOnLoad() { + var cachedImgObj = this.__cachedImgObj; + this.onload = this.onerror = this.__cachedImgObj = null; + for (var i = 0; i < cachedImgObj.pending.length; i++) { + var pendingWrap = cachedImgObj.pending[i]; + var cb = pendingWrap.cb; + cb && cb(this, pendingWrap.cbPayload); + pendingWrap.hostEl.dirty(); + } + cachedImgObj.pending.length = 0; + } + function isImageReady(image) { + return image && image.width && image.height; + } + + var STYLE_REG = /\{([a-zA-Z0-9_]+)\|([^}]*)\}/g; + function truncateText(text, containerWidth, font, ellipsis, options) { + if (!containerWidth) { + return ''; + } + var textLines = (text + '').split('\n'); + options = prepareTruncateOptions(containerWidth, font, ellipsis, options); + for (var i = 0, len = textLines.length; i < len; i++) { + textLines[i] = truncateSingleLine(textLines[i], options); + } + return textLines.join('\n'); + } + function prepareTruncateOptions(containerWidth, font, ellipsis, options) { + options = options || {}; + var preparedOpts = extend({}, options); + preparedOpts.font = font; + ellipsis = retrieve2(ellipsis, '...'); + preparedOpts.maxIterations = retrieve2(options.maxIterations, 2); + var minChar = preparedOpts.minChar = retrieve2(options.minChar, 0); + preparedOpts.cnCharWidth = getWidth('国', font); + var ascCharWidth = preparedOpts.ascCharWidth = getWidth('a', font); + preparedOpts.placeholder = retrieve2(options.placeholder, ''); + var contentWidth = containerWidth = Math.max(0, containerWidth - 1); + for (var i = 0; i < minChar && contentWidth >= ascCharWidth; i++) { + contentWidth -= ascCharWidth; + } + var ellipsisWidth = getWidth(ellipsis, font); + if (ellipsisWidth > contentWidth) { + ellipsis = ''; + ellipsisWidth = 0; + } + contentWidth = containerWidth - ellipsisWidth; + preparedOpts.ellipsis = ellipsis; + preparedOpts.ellipsisWidth = ellipsisWidth; + preparedOpts.contentWidth = contentWidth; + preparedOpts.containerWidth = containerWidth; + return preparedOpts; + } + function truncateSingleLine(textLine, options) { + var containerWidth = options.containerWidth; + var font = options.font; + var contentWidth = options.contentWidth; + if (!containerWidth) { + return ''; + } + var lineWidth = getWidth(textLine, font); + if (lineWidth <= containerWidth) { + return textLine; + } + for (var j = 0;; j++) { + if (lineWidth <= contentWidth || j >= options.maxIterations) { + textLine += options.ellipsis; + break; + } + var subLength = j === 0 + ? estimateLength(textLine, contentWidth, options.ascCharWidth, options.cnCharWidth) + : lineWidth > 0 + ? Math.floor(textLine.length * contentWidth / lineWidth) + : 0; + textLine = textLine.substr(0, subLength); + lineWidth = getWidth(textLine, font); + } + if (textLine === '') { + textLine = options.placeholder; + } + return textLine; + } + function estimateLength(text, contentWidth, ascCharWidth, cnCharWidth) { + var width = 0; + var i = 0; + for (var len = text.length; i < len && width < contentWidth; i++) { + var charCode = text.charCodeAt(i); + width += (0 <= charCode && charCode <= 127) ? ascCharWidth : cnCharWidth; + } + return i; + } + function parsePlainText(text, style) { + text != null && (text += ''); + var overflow = style.overflow; + var padding = style.padding; + var font = style.font; + var truncate = overflow === 'truncate'; + var calculatedLineHeight = getLineHeight(font); + var lineHeight = retrieve2(style.lineHeight, calculatedLineHeight); + var truncateLineOverflow = style.lineOverflow === 'truncate'; + var width = style.width; + var lines; + if (width != null && overflow === 'break' || overflow === 'breakAll') { + lines = text ? wrapText(text, style.font, width, overflow === 'breakAll', 0).lines : []; + } + else { + lines = text ? text.split('\n') : []; + } + var contentHeight = lines.length * lineHeight; + var height = retrieve2(style.height, contentHeight); + if (contentHeight > height && truncateLineOverflow) { + var lineCount = Math.floor(height / lineHeight); + lines = lines.slice(0, lineCount); + } + var outerHeight = height; + var outerWidth = width; + if (padding) { + outerHeight += padding[0] + padding[2]; + if (outerWidth != null) { + outerWidth += padding[1] + padding[3]; + } + } + if (text && truncate && outerWidth != null) { + var options = prepareTruncateOptions(width, font, style.ellipsis, { + minChar: style.truncateMinChar, + placeholder: style.placeholder + }); + for (var i = 0; i < lines.length; i++) { + lines[i] = truncateSingleLine(lines[i], options); + } + } + if (width == null) { + var maxWidth = 0; + for (var i = 0; i < lines.length; i++) { + maxWidth = Math.max(getWidth(lines[i], font), maxWidth); + } + width = maxWidth; + } + return { + lines: lines, + height: height, + outerHeight: outerHeight, + lineHeight: lineHeight, + calculatedLineHeight: calculatedLineHeight, + contentHeight: contentHeight, + width: width + }; + } + var RichTextToken = (function () { + function RichTextToken() { + } + return RichTextToken; + }()); + var RichTextLine = (function () { + function RichTextLine(tokens) { + this.tokens = []; + if (tokens) { + this.tokens = tokens; + } + } + return RichTextLine; + }()); + var RichTextContentBlock = (function () { + function RichTextContentBlock() { + this.width = 0; + this.height = 0; + this.contentWidth = 0; + this.contentHeight = 0; + this.outerWidth = 0; + this.outerHeight = 0; + this.lines = []; + } + return RichTextContentBlock; + }()); + function parseRichText(text, style) { + var contentBlock = new RichTextContentBlock(); + text != null && (text += ''); + if (!text) { + return contentBlock; + } + var topWidth = style.width; + var topHeight = style.height; + var overflow = style.overflow; + var wrapInfo = (overflow === 'break' || overflow === 'breakAll') && topWidth != null + ? { width: topWidth, accumWidth: 0, breakAll: overflow === 'breakAll' } + : null; + var lastIndex = STYLE_REG.lastIndex = 0; + var result; + while ((result = STYLE_REG.exec(text)) != null) { + var matchedIndex = result.index; + if (matchedIndex > lastIndex) { + pushTokens(contentBlock, text.substring(lastIndex, matchedIndex), style, wrapInfo); + } + pushTokens(contentBlock, result[2], style, wrapInfo, result[1]); + lastIndex = STYLE_REG.lastIndex; + } + if (lastIndex < text.length) { + pushTokens(contentBlock, text.substring(lastIndex, text.length), style, wrapInfo); + } + var pendingList = []; + var calculatedHeight = 0; + var calculatedWidth = 0; + var stlPadding = style.padding; + var truncate = overflow === 'truncate'; + var truncateLine = style.lineOverflow === 'truncate'; + function finishLine(line, lineWidth, lineHeight) { + line.width = lineWidth; + line.lineHeight = lineHeight; + calculatedHeight += lineHeight; + calculatedWidth = Math.max(calculatedWidth, lineWidth); + } + outer: for (var i = 0; i < contentBlock.lines.length; i++) { + var line = contentBlock.lines[i]; + var lineHeight = 0; + var lineWidth = 0; + for (var j = 0; j < line.tokens.length; j++) { + var token = line.tokens[j]; + var tokenStyle = token.styleName && style.rich[token.styleName] || {}; + var textPadding = token.textPadding = tokenStyle.padding; + var paddingH = textPadding ? textPadding[1] + textPadding[3] : 0; + var font = token.font = tokenStyle.font || style.font; + token.contentHeight = getLineHeight(font); + var tokenHeight = retrieve2(tokenStyle.height, token.contentHeight); + token.innerHeight = tokenHeight; + textPadding && (tokenHeight += textPadding[0] + textPadding[2]); + token.height = tokenHeight; + token.lineHeight = retrieve3(tokenStyle.lineHeight, style.lineHeight, tokenHeight); + token.align = tokenStyle && tokenStyle.align || style.align; + token.verticalAlign = tokenStyle && tokenStyle.verticalAlign || 'middle'; + if (truncateLine && topHeight != null && calculatedHeight + token.lineHeight > topHeight) { + if (j > 0) { + line.tokens = line.tokens.slice(0, j); + finishLine(line, lineWidth, lineHeight); + contentBlock.lines = contentBlock.lines.slice(0, i + 1); + } + else { + contentBlock.lines = contentBlock.lines.slice(0, i); + } + break outer; + } + var styleTokenWidth = tokenStyle.width; + var tokenWidthNotSpecified = styleTokenWidth == null || styleTokenWidth === 'auto'; + if (typeof styleTokenWidth === 'string' && styleTokenWidth.charAt(styleTokenWidth.length - 1) === '%') { + token.percentWidth = styleTokenWidth; + pendingList.push(token); + token.contentWidth = getWidth(token.text, font); + } + else { + if (tokenWidthNotSpecified) { + var textBackgroundColor = tokenStyle.backgroundColor; + var bgImg = textBackgroundColor && textBackgroundColor.image; + if (bgImg) { + bgImg = findExistImage(bgImg); + if (isImageReady(bgImg)) { + token.width = Math.max(token.width, bgImg.width * tokenHeight / bgImg.height); + } + } + } + var remainTruncWidth = truncate && topWidth != null + ? topWidth - lineWidth : null; + if (remainTruncWidth != null && remainTruncWidth < token.width) { + if (!tokenWidthNotSpecified || remainTruncWidth < paddingH) { + token.text = ''; + token.width = token.contentWidth = 0; + } + else { + token.text = truncateText(token.text, remainTruncWidth - paddingH, font, style.ellipsis, { minChar: style.truncateMinChar }); + token.width = token.contentWidth = getWidth(token.text, font); + } + } + else { + token.contentWidth = getWidth(token.text, font); + } + } + token.width += paddingH; + lineWidth += token.width; + tokenStyle && (lineHeight = Math.max(lineHeight, token.lineHeight)); + } + finishLine(line, lineWidth, lineHeight); + } + contentBlock.outerWidth = contentBlock.width = retrieve2(topWidth, calculatedWidth); + contentBlock.outerHeight = contentBlock.height = retrieve2(topHeight, calculatedHeight); + contentBlock.contentHeight = calculatedHeight; + contentBlock.contentWidth = calculatedWidth; + if (stlPadding) { + contentBlock.outerWidth += stlPadding[1] + stlPadding[3]; + contentBlock.outerHeight += stlPadding[0] + stlPadding[2]; + } + for (var i = 0; i < pendingList.length; i++) { + var token = pendingList[i]; + var percentWidth = token.percentWidth; + token.width = parseInt(percentWidth, 10) / 100 * contentBlock.width; + } + return contentBlock; + } + function pushTokens(block, str, style, wrapInfo, styleName) { + var isEmptyStr = str === ''; + var tokenStyle = styleName && style.rich[styleName] || {}; + var lines = block.lines; + var font = tokenStyle.font || style.font; + var newLine = false; + var strLines; + var linesWidths; + if (wrapInfo) { + var tokenPadding = tokenStyle.padding; + var tokenPaddingH = tokenPadding ? tokenPadding[1] + tokenPadding[3] : 0; + if (tokenStyle.width != null && tokenStyle.width !== 'auto') { + var outerWidth_1 = parsePercent$2(tokenStyle.width, wrapInfo.width) + tokenPaddingH; + if (lines.length > 0) { + if (outerWidth_1 + wrapInfo.accumWidth > wrapInfo.width) { + strLines = str.split('\n'); + newLine = true; + } + } + wrapInfo.accumWidth = outerWidth_1; + } + else { + var res = wrapText(str, font, wrapInfo.width, wrapInfo.breakAll, wrapInfo.accumWidth); + wrapInfo.accumWidth = res.accumWidth + tokenPaddingH; + linesWidths = res.linesWidths; + strLines = res.lines; + } + } + else { + strLines = str.split('\n'); + } + for (var i = 0; i < strLines.length; i++) { + var text = strLines[i]; + var token = new RichTextToken(); + token.styleName = styleName; + token.text = text; + token.isLineHolder = !text && !isEmptyStr; + if (typeof tokenStyle.width === 'number') { + token.width = tokenStyle.width; + } + else { + token.width = linesWidths + ? linesWidths[i] + : getWidth(text, font); + } + if (!i && !newLine) { + var tokens = (lines[lines.length - 1] || (lines[0] = new RichTextLine())).tokens; + var tokensLen = tokens.length; + (tokensLen === 1 && tokens[0].isLineHolder) + ? (tokens[0] = token) + : ((text || !tokensLen || isEmptyStr) && tokens.push(token)); + } + else { + lines.push(new RichTextLine([token])); + } + } + } + function isLatin(ch) { + var code = ch.charCodeAt(0); + return code >= 0x21 && code <= 0xFF; + } + var breakCharMap = reduce(',&?/;] '.split(''), function (obj, ch) { + obj[ch] = true; + return obj; + }, {}); + function isWordBreakChar(ch) { + if (isLatin(ch)) { + if (breakCharMap[ch]) { + return true; + } + return false; + } + return true; + } + function wrapText(text, font, lineWidth, isBreakAll, lastAccumWidth) { + var lines = []; + var linesWidths = []; + var line = ''; + var currentWord = ''; + var currentWordWidth = 0; + var accumWidth = 0; + for (var i = 0; i < text.length; i++) { + var ch = text.charAt(i); + if (ch === '\n') { + if (currentWord) { + line += currentWord; + accumWidth += currentWordWidth; + } + lines.push(line); + linesWidths.push(accumWidth); + line = ''; + currentWord = ''; + currentWordWidth = 0; + accumWidth = 0; + continue; + } + var chWidth = getWidth(ch, font); + var inWord = isBreakAll ? false : !isWordBreakChar(ch); + if (!lines.length + ? lastAccumWidth + accumWidth + chWidth > lineWidth + : accumWidth + chWidth > lineWidth) { + if (!accumWidth) { + if (inWord) { + lines.push(currentWord); + linesWidths.push(currentWordWidth); + currentWord = ch; + currentWordWidth = chWidth; + } + else { + lines.push(ch); + linesWidths.push(chWidth); + } + } + else if (line || currentWord) { + if (inWord) { + if (!line) { + line = currentWord; + currentWord = ''; + currentWordWidth = 0; + accumWidth = currentWordWidth; + } + lines.push(line); + linesWidths.push(accumWidth - currentWordWidth); + currentWord += ch; + currentWordWidth += chWidth; + line = ''; + accumWidth = currentWordWidth; + } + else { + if (currentWord) { + line += currentWord; + accumWidth += currentWordWidth; + currentWord = ''; + currentWordWidth = 0; + } + lines.push(line); + linesWidths.push(accumWidth); + line = ch; + accumWidth = chWidth; + } + } + continue; + } + accumWidth += chWidth; + if (inWord) { + currentWord += ch; + currentWordWidth += chWidth; + } + else { + if (currentWord) { + line += currentWord; + currentWord = ''; + currentWordWidth = 0; + } + line += ch; + } + } + if (!lines.length && !line) { + line = text; + currentWord = ''; + currentWordWidth = 0; + } + if (currentWord) { + line += currentWord; + } + if (line) { + lines.push(line); + linesWidths.push(accumWidth); + } + if (lines.length === 1) { + accumWidth += lastAccumWidth; + } + return { + accumWidth: accumWidth, + lines: lines, + linesWidths: linesWidths + }; + } + function parsePercent$2(value, maxValue) { + if (typeof value === 'string') { + if (value.lastIndexOf('%') >= 0) { + return parseFloat(value) / 100 * maxValue; + } + return parseFloat(value); + } + return value; + } + + var STYLE_MAGIC_KEY = '__zr_style_' + Math.round((Math.random() * 10)); + var DEFAULT_COMMON_STYLE = { + shadowBlur: 0, + shadowOffsetX: 0, + shadowOffsetY: 0, + shadowColor: '#000', + opacity: 1, + blend: 'source-over' + }; + var DEFAULT_COMMON_ANIMATION_PROPS = { + style: { + shadowBlur: true, + shadowOffsetX: true, + shadowOffsetY: true, + shadowColor: true, + opacity: true + } + }; + DEFAULT_COMMON_STYLE[STYLE_MAGIC_KEY] = true; + var PRIMARY_STATES_KEYS$1 = ['z', 'z2', 'invisible']; + var Displayable = (function (_super) { + __extends(Displayable, _super); + function Displayable(props) { + return _super.call(this, props) || this; + } + Displayable.prototype._init = function (props) { + var keysArr = keys(props); + for (var i = 0; i < keysArr.length; i++) { + var key = keysArr[i]; + if (key === 'style') { + this.useStyle(props[key]); + } + else { + _super.prototype.attrKV.call(this, key, props[key]); + } + } + if (!this.style) { + this.useStyle({}); + } + }; + Displayable.prototype.beforeBrush = function () { }; + Displayable.prototype.afterBrush = function () { }; + Displayable.prototype.innerBeforeBrush = function () { }; + Displayable.prototype.innerAfterBrush = function () { }; + Displayable.prototype.shouldBePainted = function (viewWidth, viewHeight, considerClipPath, considerAncestors) { + var m = this.transform; + if (this.ignore + || this.invisible + || this.style.opacity === 0 + || (this.culling + && isDisplayableCulled(this, viewWidth, viewHeight)) + || (m && !m[0] && !m[3])) { + return false; + } + if (considerClipPath && this.__clipPaths) { + for (var i = 0; i < this.__clipPaths.length; ++i) { + if (this.__clipPaths[i].isZeroArea()) { + return false; + } + } + } + if (considerAncestors && this.parent) { + var parent_1 = this.parent; + while (parent_1) { + if (parent_1.ignore) { + return false; + } + parent_1 = parent_1.parent; + } + } + return true; + }; + Displayable.prototype.contain = function (x, y) { + return this.rectContain(x, y); + }; + Displayable.prototype.traverse = function (cb, context) { + cb.call(context, this); + }; + Displayable.prototype.rectContain = function (x, y) { + var coord = this.transformCoordToLocal(x, y); + var rect = this.getBoundingRect(); + return rect.contain(coord[0], coord[1]); + }; + Displayable.prototype.getPaintRect = function () { + var rect = this._paintRect; + if (!this._paintRect || this.__dirty) { + var transform = this.transform; + var elRect = this.getBoundingRect(); + var style = this.style; + var shadowSize = style.shadowBlur || 0; + var shadowOffsetX = style.shadowOffsetX || 0; + var shadowOffsetY = style.shadowOffsetY || 0; + rect = this._paintRect || (this._paintRect = new BoundingRect(0, 0, 0, 0)); + if (transform) { + BoundingRect.applyTransform(rect, elRect, transform); + } + else { + rect.copy(elRect); + } + if (shadowSize || shadowOffsetX || shadowOffsetY) { + rect.width += shadowSize * 2 + Math.abs(shadowOffsetX); + rect.height += shadowSize * 2 + Math.abs(shadowOffsetY); + rect.x = Math.min(rect.x, rect.x + shadowOffsetX - shadowSize); + rect.y = Math.min(rect.y, rect.y + shadowOffsetY - shadowSize); + } + var tolerance = this.dirtyRectTolerance; + if (!rect.isZero()) { + rect.x = Math.floor(rect.x - tolerance); + rect.y = Math.floor(rect.y - tolerance); + rect.width = Math.ceil(rect.width + 1 + tolerance * 2); + rect.height = Math.ceil(rect.height + 1 + tolerance * 2); + } + } + return rect; + }; + Displayable.prototype.setPrevPaintRect = function (paintRect) { + if (paintRect) { + this._prevPaintRect = this._prevPaintRect || new BoundingRect(0, 0, 0, 0); + this._prevPaintRect.copy(paintRect); + } + else { + this._prevPaintRect = null; + } + }; + Displayable.prototype.getPrevPaintRect = function () { + return this._prevPaintRect; + }; + Displayable.prototype.animateStyle = function (loop) { + return this.animate('style', loop); + }; + Displayable.prototype.updateDuringAnimation = function (targetKey) { + if (targetKey === 'style') { + this.dirtyStyle(); + } + else { + this.markRedraw(); + } + }; + Displayable.prototype.attrKV = function (key, value) { + if (key !== 'style') { + _super.prototype.attrKV.call(this, key, value); + } + else { + if (!this.style) { + this.useStyle(value); + } + else { + this.setStyle(value); + } + } + }; + Displayable.prototype.setStyle = function (keyOrObj, value) { + if (typeof keyOrObj === 'string') { + this.style[keyOrObj] = value; + } + else { + extend(this.style, keyOrObj); + } + this.dirtyStyle(); + return this; + }; + Displayable.prototype.dirtyStyle = function () { + this.markRedraw(); + this.__dirty |= Displayable.STYLE_CHANGED_BIT; + if (this._rect) { + this._rect = null; + } + }; + Displayable.prototype.dirty = function () { + this.dirtyStyle(); + }; + Displayable.prototype.styleChanged = function () { + return !!(this.__dirty & Displayable.STYLE_CHANGED_BIT); + }; + Displayable.prototype.styleUpdated = function () { + this.__dirty &= ~Displayable.STYLE_CHANGED_BIT; + }; + Displayable.prototype.createStyle = function (obj) { + return createObject(DEFAULT_COMMON_STYLE, obj); + }; + Displayable.prototype.useStyle = function (obj) { + if (!obj[STYLE_MAGIC_KEY]) { + obj = this.createStyle(obj); + } + if (this.__inHover) { + this.__hoverStyle = obj; + } + else { + this.style = obj; + } + this.dirtyStyle(); + }; + Displayable.prototype.isStyleObject = function (obj) { + return obj[STYLE_MAGIC_KEY]; + }; + Displayable.prototype._innerSaveToNormal = function (toState) { + _super.prototype._innerSaveToNormal.call(this, toState); + var normalState = this._normalState; + if (toState.style && !normalState.style) { + normalState.style = this._mergeStyle(this.createStyle(), this.style); + } + this._savePrimaryToNormal(toState, normalState, PRIMARY_STATES_KEYS$1); + }; + Displayable.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) { + _super.prototype._applyStateObj.call(this, stateName, state, normalState, keepCurrentStates, transition, animationCfg); + var needsRestoreToNormal = !(state && keepCurrentStates); + var targetStyle; + if (state && state.style) { + if (transition) { + if (keepCurrentStates) { + targetStyle = state.style; + } + else { + targetStyle = this._mergeStyle(this.createStyle(), normalState.style); + this._mergeStyle(targetStyle, state.style); + } + } + else { + targetStyle = this._mergeStyle(this.createStyle(), keepCurrentStates ? this.style : normalState.style); + this._mergeStyle(targetStyle, state.style); + } + } + else if (needsRestoreToNormal) { + targetStyle = normalState.style; + } + if (targetStyle) { + if (transition) { + var sourceStyle = this.style; + this.style = this.createStyle(needsRestoreToNormal ? {} : sourceStyle); + if (needsRestoreToNormal) { + var changedKeys = keys(sourceStyle); + for (var i = 0; i < changedKeys.length; i++) { + var key = changedKeys[i]; + if (key in targetStyle) { + targetStyle[key] = targetStyle[key]; + this.style[key] = sourceStyle[key]; + } + } + } + var targetKeys = keys(targetStyle); + for (var i = 0; i < targetKeys.length; i++) { + var key = targetKeys[i]; + this.style[key] = this.style[key]; + } + this._transitionState(stateName, { + style: targetStyle + }, animationCfg, this.getAnimationStyleProps()); + } + else { + this.useStyle(targetStyle); + } + } + for (var i = 0; i < PRIMARY_STATES_KEYS$1.length; i++) { + var key = PRIMARY_STATES_KEYS$1[i]; + if (state && state[key] != null) { + this[key] = state[key]; + } + else if (needsRestoreToNormal) { + if (normalState[key] != null) { + this[key] = normalState[key]; + } + } + } + }; + Displayable.prototype._mergeStates = function (states) { + var mergedState = _super.prototype._mergeStates.call(this, states); + var mergedStyle; + for (var i = 0; i < states.length; i++) { + var state = states[i]; + if (state.style) { + mergedStyle = mergedStyle || {}; + this._mergeStyle(mergedStyle, state.style); + } + } + if (mergedStyle) { + mergedState.style = mergedStyle; + } + return mergedState; + }; + Displayable.prototype._mergeStyle = function (targetStyle, sourceStyle) { + extend(targetStyle, sourceStyle); + return targetStyle; + }; + Displayable.prototype.getAnimationStyleProps = function () { + return DEFAULT_COMMON_ANIMATION_PROPS; + }; + Displayable.STYLE_CHANGED_BIT = 2; + Displayable.initDefaultProps = (function () { + var dispProto = Displayable.prototype; + dispProto.type = 'displayable'; + dispProto.invisible = false; + dispProto.z = 0; + dispProto.z2 = 0; + dispProto.zlevel = 0; + dispProto.culling = false; + dispProto.cursor = 'pointer'; + dispProto.rectHover = false; + dispProto.incremental = false; + dispProto._rect = null; + dispProto.dirtyRectTolerance = 0; + dispProto.__dirty = Element.REDARAW_BIT | Displayable.STYLE_CHANGED_BIT; + })(); + return Displayable; + }(Element)); + var tmpRect = new BoundingRect(0, 0, 0, 0); + var viewRect = new BoundingRect(0, 0, 0, 0); + function isDisplayableCulled(el, width, height) { + tmpRect.copy(el.getBoundingRect()); + if (el.transform) { + tmpRect.applyTransform(el.transform); + } + viewRect.width = width; + viewRect.height = height; + return !tmpRect.intersect(viewRect); + } + + var mathPow = Math.pow; + var mathSqrt = Math.sqrt; + var EPSILON$1 = 1e-8; + var EPSILON_NUMERIC = 1e-4; + var THREE_SQRT = mathSqrt(3); + var ONE_THIRD = 1 / 3; + var _v0 = create(); + var _v1 = create(); + var _v2 = create(); + function isAroundZero(val) { + return val > -EPSILON$1 && val < EPSILON$1; + } + function isNotAroundZero$1(val) { + return val > EPSILON$1 || val < -EPSILON$1; + } + function cubicAt(p0, p1, p2, p3, t) { + var onet = 1 - t; + return onet * onet * (onet * p0 + 3 * t * p1) + + t * t * (t * p3 + 3 * onet * p2); + } + function cubicDerivativeAt(p0, p1, p2, p3, t) { + var onet = 1 - t; + return 3 * (((p1 - p0) * onet + 2 * (p2 - p1) * t) * onet + + (p3 - p2) * t * t); + } + function cubicRootAt(p0, p1, p2, p3, val, roots) { + var a = p3 + 3 * (p1 - p2) - p0; + var b = 3 * (p2 - p1 * 2 + p0); + var c = 3 * (p1 - p0); + var d = p0 - val; + var A = b * b - 3 * a * c; + var B = b * c - 9 * a * d; + var C = c * c - 3 * b * d; + var n = 0; + if (isAroundZero(A) && isAroundZero(B)) { + if (isAroundZero(b)) { + roots[0] = 0; + } + else { + var t1 = -c / b; + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + } + else { + var disc = B * B - 4 * A * C; + if (isAroundZero(disc)) { + var K = B / A; + var t1 = -b / a + K; + var t2 = -K / 2; + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + roots[n++] = t2; + } + } + else if (disc > 0) { + var discSqrt = mathSqrt(disc); + var Y1 = A * b + 1.5 * a * (-B + discSqrt); + var Y2 = A * b + 1.5 * a * (-B - discSqrt); + if (Y1 < 0) { + Y1 = -mathPow(-Y1, ONE_THIRD); + } + else { + Y1 = mathPow(Y1, ONE_THIRD); + } + if (Y2 < 0) { + Y2 = -mathPow(-Y2, ONE_THIRD); + } + else { + Y2 = mathPow(Y2, ONE_THIRD); + } + var t1 = (-b - (Y1 + Y2)) / (3 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + else { + var T = (2 * A * b - 3 * a * B) / (2 * mathSqrt(A * A * A)); + var theta = Math.acos(T) / 3; + var ASqrt = mathSqrt(A); + var tmp = Math.cos(theta); + var t1 = (-b - 2 * ASqrt * tmp) / (3 * a); + var t2 = (-b + ASqrt * (tmp + THREE_SQRT * Math.sin(theta))) / (3 * a); + var t3 = (-b + ASqrt * (tmp - THREE_SQRT * Math.sin(theta))) / (3 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + roots[n++] = t2; + } + if (t3 >= 0 && t3 <= 1) { + roots[n++] = t3; + } + } + } + return n; + } + function cubicExtrema(p0, p1, p2, p3, extrema) { + var b = 6 * p2 - 12 * p1 + 6 * p0; + var a = 9 * p1 + 3 * p3 - 3 * p0 - 9 * p2; + var c = 3 * p1 - 3 * p0; + var n = 0; + if (isAroundZero(a)) { + if (isNotAroundZero$1(b)) { + var t1 = -c / b; + if (t1 >= 0 && t1 <= 1) { + extrema[n++] = t1; + } + } + } + else { + var disc = b * b - 4 * a * c; + if (isAroundZero(disc)) { + extrema[0] = -b / (2 * a); + } + else if (disc > 0) { + var discSqrt = mathSqrt(disc); + var t1 = (-b + discSqrt) / (2 * a); + var t2 = (-b - discSqrt) / (2 * a); + if (t1 >= 0 && t1 <= 1) { + extrema[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + extrema[n++] = t2; + } + } + } + return n; + } + function cubicSubdivide(p0, p1, p2, p3, t, out) { + var p01 = (p1 - p0) * t + p0; + var p12 = (p2 - p1) * t + p1; + var p23 = (p3 - p2) * t + p2; + var p012 = (p12 - p01) * t + p01; + var p123 = (p23 - p12) * t + p12; + var p0123 = (p123 - p012) * t + p012; + out[0] = p0; + out[1] = p01; + out[2] = p012; + out[3] = p0123; + out[4] = p0123; + out[5] = p123; + out[6] = p23; + out[7] = p3; + } + function cubicProjectPoint(x0, y0, x1, y1, x2, y2, x3, y3, x, y, out) { + var t; + var interval = 0.005; + var d = Infinity; + var prev; + var next; + var d1; + var d2; + _v0[0] = x; + _v0[1] = y; + for (var _t = 0; _t < 1; _t += 0.05) { + _v1[0] = cubicAt(x0, x1, x2, x3, _t); + _v1[1] = cubicAt(y0, y1, y2, y3, _t); + d1 = distSquare(_v0, _v1); + if (d1 < d) { + t = _t; + d = d1; + } + } + d = Infinity; + for (var i = 0; i < 32; i++) { + if (interval < EPSILON_NUMERIC) { + break; + } + prev = t - interval; + next = t + interval; + _v1[0] = cubicAt(x0, x1, x2, x3, prev); + _v1[1] = cubicAt(y0, y1, y2, y3, prev); + d1 = distSquare(_v1, _v0); + if (prev >= 0 && d1 < d) { + t = prev; + d = d1; + } + else { + _v2[0] = cubicAt(x0, x1, x2, x3, next); + _v2[1] = cubicAt(y0, y1, y2, y3, next); + d2 = distSquare(_v2, _v0); + if (next <= 1 && d2 < d) { + t = next; + d = d2; + } + else { + interval *= 0.5; + } + } + } + if (out) { + out[0] = cubicAt(x0, x1, x2, x3, t); + out[1] = cubicAt(y0, y1, y2, y3, t); + } + return mathSqrt(d); + } + function cubicLength(x0, y0, x1, y1, x2, y2, x3, y3, iteration) { + var px = x0; + var py = y0; + var d = 0; + var step = 1 / iteration; + for (var i = 1; i <= iteration; i++) { + var t = i * step; + var x = cubicAt(x0, x1, x2, x3, t); + var y = cubicAt(y0, y1, y2, y3, t); + var dx = x - px; + var dy = y - py; + d += Math.sqrt(dx * dx + dy * dy); + px = x; + py = y; + } + return d; + } + function quadraticAt(p0, p1, p2, t) { + var onet = 1 - t; + return onet * (onet * p0 + 2 * t * p1) + t * t * p2; + } + function quadraticDerivativeAt(p0, p1, p2, t) { + return 2 * ((1 - t) * (p1 - p0) + t * (p2 - p1)); + } + function quadraticRootAt(p0, p1, p2, val, roots) { + var a = p0 - 2 * p1 + p2; + var b = 2 * (p1 - p0); + var c = p0 - val; + var n = 0; + if (isAroundZero(a)) { + if (isNotAroundZero$1(b)) { + var t1 = -c / b; + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + } + else { + var disc = b * b - 4 * a * c; + if (isAroundZero(disc)) { + var t1 = -b / (2 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + } + else if (disc > 0) { + var discSqrt = mathSqrt(disc); + var t1 = (-b + discSqrt) / (2 * a); + var t2 = (-b - discSqrt) / (2 * a); + if (t1 >= 0 && t1 <= 1) { + roots[n++] = t1; + } + if (t2 >= 0 && t2 <= 1) { + roots[n++] = t2; + } + } + } + return n; + } + function quadraticExtremum(p0, p1, p2) { + var divider = p0 + p2 - 2 * p1; + if (divider === 0) { + return 0.5; + } + else { + return (p0 - p1) / divider; + } + } + function quadraticSubdivide(p0, p1, p2, t, out) { + var p01 = (p1 - p0) * t + p0; + var p12 = (p2 - p1) * t + p1; + var p012 = (p12 - p01) * t + p01; + out[0] = p0; + out[1] = p01; + out[2] = p012; + out[3] = p012; + out[4] = p12; + out[5] = p2; + } + function quadraticProjectPoint(x0, y0, x1, y1, x2, y2, x, y, out) { + var t; + var interval = 0.005; + var d = Infinity; + _v0[0] = x; + _v0[1] = y; + for (var _t = 0; _t < 1; _t += 0.05) { + _v1[0] = quadraticAt(x0, x1, x2, _t); + _v1[1] = quadraticAt(y0, y1, y2, _t); + var d1 = distSquare(_v0, _v1); + if (d1 < d) { + t = _t; + d = d1; + } + } + d = Infinity; + for (var i = 0; i < 32; i++) { + if (interval < EPSILON_NUMERIC) { + break; + } + var prev = t - interval; + var next = t + interval; + _v1[0] = quadraticAt(x0, x1, x2, prev); + _v1[1] = quadraticAt(y0, y1, y2, prev); + var d1 = distSquare(_v1, _v0); + if (prev >= 0 && d1 < d) { + t = prev; + d = d1; + } + else { + _v2[0] = quadraticAt(x0, x1, x2, next); + _v2[1] = quadraticAt(y0, y1, y2, next); + var d2 = distSquare(_v2, _v0); + if (next <= 1 && d2 < d) { + t = next; + d = d2; + } + else { + interval *= 0.5; + } + } + } + if (out) { + out[0] = quadraticAt(x0, x1, x2, t); + out[1] = quadraticAt(y0, y1, y2, t); + } + return mathSqrt(d); + } + function quadraticLength(x0, y0, x1, y1, x2, y2, iteration) { + var px = x0; + var py = y0; + var d = 0; + var step = 1 / iteration; + for (var i = 1; i <= iteration; i++) { + var t = i * step; + var x = quadraticAt(x0, x1, x2, t); + var y = quadraticAt(y0, y1, y2, t); + var dx = x - px; + var dy = y - py; + d += Math.sqrt(dx * dx + dy * dy); + px = x; + py = y; + } + return d; + } + + var mathMin$1 = Math.min; + var mathMax$1 = Math.max; + var mathSin = Math.sin; + var mathCos = Math.cos; + var PI2 = Math.PI * 2; + var start = create(); + var end = create(); + var extremity = create(); + function fromPoints(points, min, max) { + if (points.length === 0) { + return; + } + var p = points[0]; + var left = p[0]; + var right = p[0]; + var top = p[1]; + var bottom = p[1]; + for (var i = 1; i < points.length; i++) { + p = points[i]; + left = mathMin$1(left, p[0]); + right = mathMax$1(right, p[0]); + top = mathMin$1(top, p[1]); + bottom = mathMax$1(bottom, p[1]); + } + min[0] = left; + min[1] = top; + max[0] = right; + max[1] = bottom; + } + function fromLine(x0, y0, x1, y1, min, max) { + min[0] = mathMin$1(x0, x1); + min[1] = mathMin$1(y0, y1); + max[0] = mathMax$1(x0, x1); + max[1] = mathMax$1(y0, y1); + } + var xDim = []; + var yDim = []; + function fromCubic(x0, y0, x1, y1, x2, y2, x3, y3, min, max) { + var cubicExtrema$1 = cubicExtrema; + var cubicAt$1 = cubicAt; + var n = cubicExtrema$1(x0, x1, x2, x3, xDim); + min[0] = Infinity; + min[1] = Infinity; + max[0] = -Infinity; + max[1] = -Infinity; + for (var i = 0; i < n; i++) { + var x = cubicAt$1(x0, x1, x2, x3, xDim[i]); + min[0] = mathMin$1(x, min[0]); + max[0] = mathMax$1(x, max[0]); + } + n = cubicExtrema$1(y0, y1, y2, y3, yDim); + for (var i = 0; i < n; i++) { + var y = cubicAt$1(y0, y1, y2, y3, yDim[i]); + min[1] = mathMin$1(y, min[1]); + max[1] = mathMax$1(y, max[1]); + } + min[0] = mathMin$1(x0, min[0]); + max[0] = mathMax$1(x0, max[0]); + min[0] = mathMin$1(x3, min[0]); + max[0] = mathMax$1(x3, max[0]); + min[1] = mathMin$1(y0, min[1]); + max[1] = mathMax$1(y0, max[1]); + min[1] = mathMin$1(y3, min[1]); + max[1] = mathMax$1(y3, max[1]); + } + function fromQuadratic(x0, y0, x1, y1, x2, y2, min, max) { + var quadraticExtremum$1 = quadraticExtremum; + var quadraticAt$1 = quadraticAt; + var tx = mathMax$1(mathMin$1(quadraticExtremum$1(x0, x1, x2), 1), 0); + var ty = mathMax$1(mathMin$1(quadraticExtremum$1(y0, y1, y2), 1), 0); + var x = quadraticAt$1(x0, x1, x2, tx); + var y = quadraticAt$1(y0, y1, y2, ty); + min[0] = mathMin$1(x0, x2, x); + min[1] = mathMin$1(y0, y2, y); + max[0] = mathMax$1(x0, x2, x); + max[1] = mathMax$1(y0, y2, y); + } + function fromArc(x, y, rx, ry, startAngle, endAngle, anticlockwise, min$1, max$1) { + var vec2Min = min; + var vec2Max = max; + var diff = Math.abs(startAngle - endAngle); + if (diff % PI2 < 1e-4 && diff > 1e-4) { + min$1[0] = x - rx; + min$1[1] = y - ry; + max$1[0] = x + rx; + max$1[1] = y + ry; + return; + } + start[0] = mathCos(startAngle) * rx + x; + start[1] = mathSin(startAngle) * ry + y; + end[0] = mathCos(endAngle) * rx + x; + end[1] = mathSin(endAngle) * ry + y; + vec2Min(min$1, start, end); + vec2Max(max$1, start, end); + startAngle = startAngle % (PI2); + if (startAngle < 0) { + startAngle = startAngle + PI2; + } + endAngle = endAngle % (PI2); + if (endAngle < 0) { + endAngle = endAngle + PI2; + } + if (startAngle > endAngle && !anticlockwise) { + endAngle += PI2; + } + else if (startAngle < endAngle && anticlockwise) { + startAngle += PI2; + } + if (anticlockwise) { + var tmp = endAngle; + endAngle = startAngle; + startAngle = tmp; + } + for (var angle = 0; angle < endAngle; angle += Math.PI / 2) { + if (angle > startAngle) { + extremity[0] = mathCos(angle) * rx + x; + extremity[1] = mathSin(angle) * ry + y; + vec2Min(min$1, extremity, min$1); + vec2Max(max$1, extremity, max$1); + } + } + } + + var CMD = { + M: 1, + L: 2, + C: 3, + Q: 4, + A: 5, + Z: 6, + R: 7 + }; + var tmpOutX = []; + var tmpOutY = []; + var min$1 = []; + var max$1 = []; + var min2 = []; + var max2 = []; + var mathMin$2 = Math.min; + var mathMax$2 = Math.max; + var mathCos$1 = Math.cos; + var mathSin$1 = Math.sin; + var mathSqrt$1 = Math.sqrt; + var mathAbs = Math.abs; + var PI = Math.PI; + var PI2$1 = PI * 2; + var hasTypedArray = typeof Float32Array !== 'undefined'; + var tmpAngles = []; + function modPI2(radian) { + var n = Math.round(radian / PI * 1e8) / 1e8; + return (n % 2) * PI; + } + function normalizeArcAngles(angles, anticlockwise) { + var newStartAngle = modPI2(angles[0]); + if (newStartAngle < 0) { + newStartAngle += PI2$1; + } + var delta = newStartAngle - angles[0]; + var newEndAngle = angles[1]; + newEndAngle += delta; + if (!anticlockwise && newEndAngle - newStartAngle >= PI2$1) { + newEndAngle = newStartAngle + PI2$1; + } + else if (anticlockwise && newStartAngle - newEndAngle >= PI2$1) { + newEndAngle = newStartAngle - PI2$1; + } + else if (!anticlockwise && newStartAngle > newEndAngle) { + newEndAngle = newStartAngle + + (PI2$1 - modPI2(newStartAngle - newEndAngle)); + } + else if (anticlockwise && newStartAngle < newEndAngle) { + newEndAngle = newStartAngle - + (PI2$1 - modPI2(newEndAngle - newStartAngle)); + } + angles[0] = newStartAngle; + angles[1] = newEndAngle; + } + var PathProxy = (function () { + function PathProxy(notSaveData) { + this.dpr = 1; + this._version = 0; + this._xi = 0; + this._yi = 0; + this._x0 = 0; + this._y0 = 0; + this._len = 0; + if (notSaveData) { + this._saveData = false; + } + if (this._saveData) { + this.data = []; + } + } + PathProxy.prototype.increaseVersion = function () { + this._version++; + }; + PathProxy.prototype.getVersion = function () { + return this._version; + }; + PathProxy.prototype.setScale = function (sx, sy, segmentIgnoreThreshold) { + segmentIgnoreThreshold = segmentIgnoreThreshold || 0; + if (segmentIgnoreThreshold > 0) { + this._ux = mathAbs(segmentIgnoreThreshold / devicePixelRatio / sx) || 0; + this._uy = mathAbs(segmentIgnoreThreshold / devicePixelRatio / sy) || 0; + } + }; + PathProxy.prototype.setDPR = function (dpr) { + this.dpr = dpr; + }; + PathProxy.prototype.setContext = function (ctx) { + this._ctx = ctx; + }; + PathProxy.prototype.getContext = function () { + return this._ctx; + }; + PathProxy.prototype.beginPath = function () { + this._ctx && this._ctx.beginPath(); + this.reset(); + return this; + }; + PathProxy.prototype.reset = function () { + if (this._saveData) { + this._len = 0; + } + if (this._lineDash) { + this._lineDash = null; + this._dashOffset = 0; + } + if (this._pathSegLen) { + this._pathSegLen = null; + this._pathLen = 0; + } + this._version++; + }; + PathProxy.prototype.moveTo = function (x, y) { + this.addData(CMD.M, x, y); + this._ctx && this._ctx.moveTo(x, y); + this._x0 = x; + this._y0 = y; + this._xi = x; + this._yi = y; + return this; + }; + PathProxy.prototype.lineTo = function (x, y) { + var exceedUnit = mathAbs(x - this._xi) > this._ux + || mathAbs(y - this._yi) > this._uy + || this._len < 5; + this.addData(CMD.L, x, y); + if (this._ctx && exceedUnit) { + this._needsDash ? this._dashedLineTo(x, y) + : this._ctx.lineTo(x, y); + } + if (exceedUnit) { + this._xi = x; + this._yi = y; + } + return this; + }; + PathProxy.prototype.bezierCurveTo = function (x1, y1, x2, y2, x3, y3) { + this.addData(CMD.C, x1, y1, x2, y2, x3, y3); + if (this._ctx) { + this._needsDash ? this._dashedBezierTo(x1, y1, x2, y2, x3, y3) + : this._ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); + } + this._xi = x3; + this._yi = y3; + return this; + }; + PathProxy.prototype.quadraticCurveTo = function (x1, y1, x2, y2) { + this.addData(CMD.Q, x1, y1, x2, y2); + if (this._ctx) { + this._needsDash ? this._dashedQuadraticTo(x1, y1, x2, y2) + : this._ctx.quadraticCurveTo(x1, y1, x2, y2); + } + this._xi = x2; + this._yi = y2; + return this; + }; + PathProxy.prototype.arc = function (cx, cy, r, startAngle, endAngle, anticlockwise) { + tmpAngles[0] = startAngle; + tmpAngles[1] = endAngle; + normalizeArcAngles(tmpAngles, anticlockwise); + startAngle = tmpAngles[0]; + endAngle = tmpAngles[1]; + var delta = endAngle - startAngle; + this.addData(CMD.A, cx, cy, r, r, startAngle, delta, 0, anticlockwise ? 0 : 1); + this._ctx && this._ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise); + this._xi = mathCos$1(endAngle) * r + cx; + this._yi = mathSin$1(endAngle) * r + cy; + return this; + }; + PathProxy.prototype.arcTo = function (x1, y1, x2, y2, radius) { + if (this._ctx) { + this._ctx.arcTo(x1, y1, x2, y2, radius); + } + return this; + }; + PathProxy.prototype.rect = function (x, y, w, h) { + this._ctx && this._ctx.rect(x, y, w, h); + this.addData(CMD.R, x, y, w, h); + return this; + }; + PathProxy.prototype.closePath = function () { + this.addData(CMD.Z); + var ctx = this._ctx; + var x0 = this._x0; + var y0 = this._y0; + if (ctx) { + this._needsDash && this._dashedLineTo(x0, y0); + ctx.closePath(); + } + this._xi = x0; + this._yi = y0; + return this; + }; + PathProxy.prototype.fill = function (ctx) { + ctx && ctx.fill(); + this.toStatic(); + }; + PathProxy.prototype.stroke = function (ctx) { + ctx && ctx.stroke(); + this.toStatic(); + }; + PathProxy.prototype.setLineDash = function (lineDash) { + if (lineDash instanceof Array) { + this._lineDash = lineDash; + this._dashIdx = 0; + var lineDashSum = 0; + for (var i = 0; i < lineDash.length; i++) { + lineDashSum += lineDash[i]; + } + this._dashSum = lineDashSum; + this._needsDash = true; + } + else { + this._lineDash = null; + this._needsDash = false; + } + return this; + }; + PathProxy.prototype.setLineDashOffset = function (offset) { + this._dashOffset = offset; + return this; + }; + PathProxy.prototype.len = function () { + return this._len; + }; + PathProxy.prototype.setData = function (data) { + var len = data.length; + if (!(this.data && this.data.length === len) && hasTypedArray) { + this.data = new Float32Array(len); + } + for (var i = 0; i < len; i++) { + this.data[i] = data[i]; + } + this._len = len; + }; + PathProxy.prototype.appendPath = function (path) { + if (!(path instanceof Array)) { + path = [path]; + } + var len = path.length; + var appendSize = 0; + var offset = this._len; + for (var i = 0; i < len; i++) { + appendSize += path[i].len(); + } + if (hasTypedArray && (this.data instanceof Float32Array)) { + this.data = new Float32Array(offset + appendSize); + } + for (var i = 0; i < len; i++) { + var appendPathData = path[i].data; + for (var k = 0; k < appendPathData.length; k++) { + this.data[offset++] = appendPathData[k]; + } + } + this._len = offset; + }; + PathProxy.prototype.addData = function (cmd, a, b, c, d, e, f, g, h) { + if (!this._saveData) { + return; + } + var data = this.data; + if (this._len + arguments.length > data.length) { + this._expandData(); + data = this.data; + } + for (var i = 0; i < arguments.length; i++) { + data[this._len++] = arguments[i]; + } + }; + PathProxy.prototype._expandData = function () { + if (!(this.data instanceof Array)) { + var newData = []; + for (var i = 0; i < this._len; i++) { + newData[i] = this.data[i]; + } + this.data = newData; + } + }; + PathProxy.prototype._dashedLineTo = function (x1, y1) { + var dashSum = this._dashSum; + var lineDash = this._lineDash; + var ctx = this._ctx; + var offset = this._dashOffset; + var x0 = this._xi; + var y0 = this._yi; + var dx = x1 - x0; + var dy = y1 - y0; + var dist = mathSqrt$1(dx * dx + dy * dy); + var x = x0; + var y = y0; + var nDash = lineDash.length; + var dash; + var idx; + dx /= dist; + dy /= dist; + if (offset < 0) { + offset = dashSum + offset; + } + offset %= dashSum; + x -= offset * dx; + y -= offset * dy; + while ((dx > 0 && x <= x1) || (dx < 0 && x >= x1) + || (dx === 0 && ((dy > 0 && y <= y1) || (dy < 0 && y >= y1)))) { + idx = this._dashIdx; + dash = lineDash[idx]; + x += dx * dash; + y += dy * dash; + this._dashIdx = (idx + 1) % nDash; + if ((dx > 0 && x < x0) || (dx < 0 && x > x0) || (dy > 0 && y < y0) || (dy < 0 && y > y0)) { + continue; + } + ctx[idx % 2 ? 'moveTo' : 'lineTo'](dx >= 0 ? mathMin$2(x, x1) : mathMax$2(x, x1), dy >= 0 ? mathMin$2(y, y1) : mathMax$2(y, y1)); + } + dx = x - x1; + dy = y - y1; + this._dashOffset = -mathSqrt$1(dx * dx + dy * dy); + }; + PathProxy.prototype._dashedBezierTo = function (x1, y1, x2, y2, x3, y3) { + var ctx = this._ctx; + var dashSum = this._dashSum; + var offset = this._dashOffset; + var lineDash = this._lineDash; + var x0 = this._xi; + var y0 = this._yi; + var bezierLen = 0; + var idx = this._dashIdx; + var nDash = lineDash.length; + var t; + var dx; + var dy; + var x; + var y; + var tmpLen = 0; + if (offset < 0) { + offset = dashSum + offset; + } + offset %= dashSum; + for (t = 0; t < 1; t += 0.1) { + dx = cubicAt(x0, x1, x2, x3, t + 0.1) + - cubicAt(x0, x1, x2, x3, t); + dy = cubicAt(y0, y1, y2, y3, t + 0.1) + - cubicAt(y0, y1, y2, y3, t); + bezierLen += mathSqrt$1(dx * dx + dy * dy); + } + for (; idx < nDash; idx++) { + tmpLen += lineDash[idx]; + if (tmpLen > offset) { + break; + } + } + t = (tmpLen - offset) / bezierLen; + while (t <= 1) { + x = cubicAt(x0, x1, x2, x3, t); + y = cubicAt(y0, y1, y2, y3, t); + idx % 2 ? ctx.moveTo(x, y) + : ctx.lineTo(x, y); + t += lineDash[idx] / bezierLen; + idx = (idx + 1) % nDash; + } + (idx % 2 !== 0) && ctx.lineTo(x3, y3); + dx = x3 - x; + dy = y3 - y; + this._dashOffset = -mathSqrt$1(dx * dx + dy * dy); + }; + PathProxy.prototype._dashedQuadraticTo = function (x1, y1, x2, y2) { + var x3 = x2; + var y3 = y2; + x2 = (x2 + 2 * x1) / 3; + y2 = (y2 + 2 * y1) / 3; + x1 = (this._xi + 2 * x1) / 3; + y1 = (this._yi + 2 * y1) / 3; + this._dashedBezierTo(x1, y1, x2, y2, x3, y3); + }; + PathProxy.prototype.toStatic = function () { + if (!this._saveData) { + return; + } + var data = this.data; + if (data instanceof Array) { + data.length = this._len; + if (hasTypedArray && this._len > 11) { + this.data = new Float32Array(data); + } + } + }; + PathProxy.prototype.getBoundingRect = function () { + min$1[0] = min$1[1] = min2[0] = min2[1] = Number.MAX_VALUE; + max$1[0] = max$1[1] = max2[0] = max2[1] = -Number.MAX_VALUE; + var data = this.data; + var xi = 0; + var yi = 0; + var x0 = 0; + var y0 = 0; + var i; + for (i = 0; i < this._len;) { + var cmd = data[i++]; + var isFirst = i === 1; + if (isFirst) { + xi = data[i]; + yi = data[i + 1]; + x0 = xi; + y0 = yi; + } + switch (cmd) { + case CMD.M: + xi = x0 = data[i++]; + yi = y0 = data[i++]; + min2[0] = x0; + min2[1] = y0; + max2[0] = x0; + max2[1] = y0; + break; + case CMD.L: + fromLine(xi, yi, data[i], data[i + 1], min2, max2); + xi = data[i++]; + yi = data[i++]; + break; + case CMD.C: + fromCubic(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], min2, max2); + xi = data[i++]; + yi = data[i++]; + break; + case CMD.Q: + fromQuadratic(xi, yi, data[i++], data[i++], data[i], data[i + 1], min2, max2); + xi = data[i++]; + yi = data[i++]; + break; + case CMD.A: + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var startAngle = data[i++]; + var endAngle = data[i++] + startAngle; + i += 1; + var anticlockwise = !data[i++]; + if (isFirst) { + x0 = mathCos$1(startAngle) * rx + cx; + y0 = mathSin$1(startAngle) * ry + cy; + } + fromArc(cx, cy, rx, ry, startAngle, endAngle, anticlockwise, min2, max2); + xi = mathCos$1(endAngle) * rx + cx; + yi = mathSin$1(endAngle) * ry + cy; + break; + case CMD.R: + x0 = xi = data[i++]; + y0 = yi = data[i++]; + var width = data[i++]; + var height = data[i++]; + fromLine(x0, y0, x0 + width, y0 + height, min2, max2); + break; + case CMD.Z: + xi = x0; + yi = y0; + break; + } + min(min$1, min$1, min2); + max(max$1, max$1, max2); + } + if (i === 0) { + min$1[0] = min$1[1] = max$1[0] = max$1[1] = 0; + } + return new BoundingRect(min$1[0], min$1[1], max$1[0] - min$1[0], max$1[1] - min$1[1]); + }; + PathProxy.prototype._calculateLength = function () { + var data = this.data; + var len = this._len; + var ux = this._ux; + var uy = this._uy; + var xi = 0; + var yi = 0; + var x0 = 0; + var y0 = 0; + if (!this._pathSegLen) { + this._pathSegLen = []; + } + var pathSegLen = this._pathSegLen; + var pathTotalLen = 0; + var segCount = 0; + for (var i = 0; i < len;) { + var cmd = data[i++]; + var isFirst = i === 1; + if (isFirst) { + xi = data[i]; + yi = data[i + 1]; + x0 = xi; + y0 = yi; + } + var l = -1; + switch (cmd) { + case CMD.M: + xi = x0 = data[i++]; + yi = y0 = data[i++]; + break; + case CMD.L: { + var x2 = data[i++]; + var y2 = data[i++]; + var dx = x2 - xi; + var dy = y2 - yi; + if (mathAbs(dx) > ux || mathAbs(dy) > uy || i === len - 1) { + l = Math.sqrt(dx * dx + dy * dy); + xi = x2; + yi = y2; + } + break; + } + case CMD.C: { + var x1 = data[i++]; + var y1 = data[i++]; + var x2 = data[i++]; + var y2 = data[i++]; + var x3 = data[i++]; + var y3 = data[i++]; + l = cubicLength(xi, yi, x1, y1, x2, y2, x3, y3, 10); + xi = x3; + yi = y3; + break; + } + case CMD.Q: { + var x1 = data[i++]; + var y1 = data[i++]; + var x2 = data[i++]; + var y2 = data[i++]; + l = quadraticLength(xi, yi, x1, y1, x2, y2, 10); + xi = x2; + yi = y2; + break; + } + case CMD.A: + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var startAngle = data[i++]; + var delta = data[i++]; + var endAngle = delta + startAngle; + i += 1; + var anticlockwise = !data[i++]; + if (isFirst) { + x0 = mathCos$1(startAngle) * rx + cx; + y0 = mathSin$1(startAngle) * ry + cy; + } + l = mathMax$2(rx, ry) * mathMin$2(PI2$1, Math.abs(delta)); + xi = mathCos$1(endAngle) * rx + cx; + yi = mathSin$1(endAngle) * ry + cy; + break; + case CMD.R: { + x0 = xi = data[i++]; + y0 = yi = data[i++]; + var width = data[i++]; + var height = data[i++]; + l = width * 2 + height * 2; + break; + } + case CMD.Z: { + var dx = x0 - xi; + var dy = y0 - yi; + l = Math.sqrt(dx * dx + dy * dy); + xi = x0; + yi = y0; + break; + } + } + if (l >= 0) { + pathSegLen[segCount++] = l; + pathTotalLen += l; + } + } + this._pathLen = pathTotalLen; + return pathTotalLen; + }; + PathProxy.prototype.rebuildPath = function (ctx, percent) { + var d = this.data; + var ux = this._ux; + var uy = this._uy; + var len = this._len; + var x0; + var y0; + var xi; + var yi; + var x; + var y; + var drawPart = percent < 1; + var pathSegLen; + var pathTotalLen; + var accumLength = 0; + var segCount = 0; + var displayedLength; + if (drawPart) { + if (!this._pathSegLen) { + this._calculateLength(); + } + pathSegLen = this._pathSegLen; + pathTotalLen = this._pathLen; + displayedLength = percent * pathTotalLen; + if (!displayedLength) { + return; + } + } + lo: for (var i = 0; i < len;) { + var cmd = d[i++]; + var isFirst = i === 1; + if (isFirst) { + xi = d[i]; + yi = d[i + 1]; + x0 = xi; + y0 = yi; + } + switch (cmd) { + case CMD.M: + x0 = xi = d[i++]; + y0 = yi = d[i++]; + ctx.moveTo(xi, yi); + break; + case CMD.L: { + x = d[i++]; + y = d[i++]; + if (mathAbs(x - xi) > ux || mathAbs(y - yi) > uy || i === len - 1) { + if (drawPart) { + var l = pathSegLen[segCount++]; + if (accumLength + l > displayedLength) { + var t = (displayedLength - accumLength) / l; + ctx.lineTo(xi * (1 - t) + x * t, yi * (1 - t) + y * t); + break lo; + } + accumLength += l; + } + ctx.lineTo(x, y); + xi = x; + yi = y; + } + break; + } + case CMD.C: { + var x1 = d[i++]; + var y1 = d[i++]; + var x2 = d[i++]; + var y2 = d[i++]; + var x3 = d[i++]; + var y3 = d[i++]; + if (drawPart) { + var l = pathSegLen[segCount++]; + if (accumLength + l > displayedLength) { + var t = (displayedLength - accumLength) / l; + cubicSubdivide(xi, x1, x2, x3, t, tmpOutX); + cubicSubdivide(yi, y1, y2, y3, t, tmpOutY); + ctx.bezierCurveTo(tmpOutX[1], tmpOutY[1], tmpOutX[2], tmpOutY[2], tmpOutX[3], tmpOutY[3]); + break lo; + } + accumLength += l; + } + ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3); + xi = x3; + yi = y3; + break; + } + case CMD.Q: { + var x1 = d[i++]; + var y1 = d[i++]; + var x2 = d[i++]; + var y2 = d[i++]; + if (drawPart) { + var l = pathSegLen[segCount++]; + if (accumLength + l > displayedLength) { + var t = (displayedLength - accumLength) / l; + quadraticSubdivide(xi, x1, x2, t, tmpOutX); + quadraticSubdivide(yi, y1, y2, t, tmpOutY); + ctx.quadraticCurveTo(tmpOutX[1], tmpOutY[1], tmpOutX[2], tmpOutY[2]); + break lo; + } + accumLength += l; + } + ctx.quadraticCurveTo(x1, y1, x2, y2); + xi = x2; + yi = y2; + break; + } + case CMD.A: + var cx = d[i++]; + var cy = d[i++]; + var rx = d[i++]; + var ry = d[i++]; + var startAngle = d[i++]; + var delta = d[i++]; + var psi = d[i++]; + var anticlockwise = !d[i++]; + var r = (rx > ry) ? rx : ry; + var isEllipse = mathAbs(rx - ry) > 1e-3; + var endAngle = startAngle + delta; + var breakBuild = false; + if (drawPart) { + var l = pathSegLen[segCount++]; + if (accumLength + l > displayedLength) { + endAngle = startAngle + delta * (displayedLength - accumLength) / l; + breakBuild = true; + } + accumLength += l; + } + if (isEllipse && ctx.ellipse) { + ctx.ellipse(cx, cy, rx, ry, psi, startAngle, endAngle, anticlockwise); + } + else { + ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise); + } + if (breakBuild) { + break lo; + } + if (isFirst) { + x0 = mathCos$1(startAngle) * rx + cx; + y0 = mathSin$1(startAngle) * ry + cy; + } + xi = mathCos$1(endAngle) * rx + cx; + yi = mathSin$1(endAngle) * ry + cy; + break; + case CMD.R: + x0 = xi = d[i]; + y0 = yi = d[i + 1]; + x = d[i++]; + y = d[i++]; + var width = d[i++]; + var height = d[i++]; + if (drawPart) { + var l = pathSegLen[segCount++]; + if (accumLength + l > displayedLength) { + var d_1 = displayedLength - accumLength; + ctx.moveTo(x, y); + ctx.lineTo(x + mathMin$2(d_1, width), y); + d_1 -= width; + if (d_1 > 0) { + ctx.lineTo(x + width, y + mathMin$2(d_1, height)); + } + d_1 -= height; + if (d_1 > 0) { + ctx.lineTo(x + mathMax$2(width - d_1, 0), y + height); + } + d_1 -= width; + if (d_1 > 0) { + ctx.lineTo(x, y + mathMax$2(height - d_1, 0)); + } + break lo; + } + accumLength += l; + } + ctx.rect(x, y, width, height); + break; + case CMD.Z: + if (drawPart) { + var l = pathSegLen[segCount++]; + if (accumLength + l > displayedLength) { + var t = (displayedLength - accumLength) / l; + ctx.lineTo(xi * (1 - t) + x0 * t, yi * (1 - t) + y0 * t); + break lo; + } + accumLength += l; + } + ctx.closePath(); + xi = x0; + yi = y0; + } + } + }; + PathProxy.CMD = CMD; + PathProxy.initDefaultProps = (function () { + var proto = PathProxy.prototype; + proto._saveData = true; + proto._needsDash = false; + proto._dashOffset = 0; + proto._dashIdx = 0; + proto._dashSum = 0; + proto._ux = 0; + proto._uy = 0; + })(); + return PathProxy; + }()); + + function containStroke(x0, y0, x1, y1, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + var _a = 0; + var _b = x0; + if ((y > y0 + _l && y > y1 + _l) + || (y < y0 - _l && y < y1 - _l) + || (x > x0 + _l && x > x1 + _l) + || (x < x0 - _l && x < x1 - _l)) { + return false; + } + if (x0 !== x1) { + _a = (y0 - y1) / (x0 - x1); + _b = (x0 * y1 - x1 * y0) / (x0 - x1); + } + else { + return Math.abs(x - x0) <= _l / 2; + } + var tmp = _a * x - y + _b; + var _s = tmp * tmp / (_a * _a + 1); + return _s <= _l / 2 * _l / 2; + } + + function containStroke$1(x0, y0, x1, y1, x2, y2, x3, y3, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + if ((y > y0 + _l && y > y1 + _l && y > y2 + _l && y > y3 + _l) + || (y < y0 - _l && y < y1 - _l && y < y2 - _l && y < y3 - _l) + || (x > x0 + _l && x > x1 + _l && x > x2 + _l && x > x3 + _l) + || (x < x0 - _l && x < x1 - _l && x < x2 - _l && x < x3 - _l)) { + return false; + } + var d = cubicProjectPoint(x0, y0, x1, y1, x2, y2, x3, y3, x, y, null); + return d <= _l / 2; + } + + function containStroke$2(x0, y0, x1, y1, x2, y2, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + if ((y > y0 + _l && y > y1 + _l && y > y2 + _l) + || (y < y0 - _l && y < y1 - _l && y < y2 - _l) + || (x > x0 + _l && x > x1 + _l && x > x2 + _l) + || (x < x0 - _l && x < x1 - _l && x < x2 - _l)) { + return false; + } + var d = quadraticProjectPoint(x0, y0, x1, y1, x2, y2, x, y, null); + return d <= _l / 2; + } + + var PI2$2 = Math.PI * 2; + function normalizeRadian(angle) { + angle %= PI2$2; + if (angle < 0) { + angle += PI2$2; + } + return angle; + } + + var PI2$3 = Math.PI * 2; + function containStroke$3(cx, cy, r, startAngle, endAngle, anticlockwise, lineWidth, x, y) { + if (lineWidth === 0) { + return false; + } + var _l = lineWidth; + x -= cx; + y -= cy; + var d = Math.sqrt(x * x + y * y); + if ((d - _l > r) || (d + _l < r)) { + return false; + } + if (Math.abs(startAngle - endAngle) % PI2$3 < 1e-4) { + return true; + } + if (anticlockwise) { + var tmp = startAngle; + startAngle = normalizeRadian(endAngle); + endAngle = normalizeRadian(tmp); + } + else { + startAngle = normalizeRadian(startAngle); + endAngle = normalizeRadian(endAngle); + } + if (startAngle > endAngle) { + endAngle += PI2$3; + } + var angle = Math.atan2(y, x); + if (angle < 0) { + angle += PI2$3; + } + return (angle >= startAngle && angle <= endAngle) + || (angle + PI2$3 >= startAngle && angle + PI2$3 <= endAngle); + } + + function windingLine(x0, y0, x1, y1, x, y) { + if ((y > y0 && y > y1) || (y < y0 && y < y1)) { + return 0; + } + if (y1 === y0) { + return 0; + } + var t = (y - y0) / (y1 - y0); + var dir = y1 < y0 ? 1 : -1; + if (t === 1 || t === 0) { + dir = y1 < y0 ? 0.5 : -0.5; + } + var x_ = t * (x1 - x0) + x0; + return x_ === x ? Infinity : x_ > x ? dir : 0; + } + + var CMD$1 = PathProxy.CMD; + var PI2$4 = Math.PI * 2; + var EPSILON$2 = 1e-4; + function isAroundEqual(a, b) { + return Math.abs(a - b) < EPSILON$2; + } + var roots = [-1, -1, -1]; + var extrema = [-1, -1]; + function swapExtrema() { + var tmp = extrema[0]; + extrema[0] = extrema[1]; + extrema[1] = tmp; + } + function windingCubic(x0, y0, x1, y1, x2, y2, x3, y3, x, y) { + if ((y > y0 && y > y1 && y > y2 && y > y3) + || (y < y0 && y < y1 && y < y2 && y < y3)) { + return 0; + } + var nRoots = cubicRootAt(y0, y1, y2, y3, y, roots); + if (nRoots === 0) { + return 0; + } + else { + var w = 0; + var nExtrema = -1; + var y0_ = void 0; + var y1_ = void 0; + for (var i = 0; i < nRoots; i++) { + var t = roots[i]; + var unit = (t === 0 || t === 1) ? 0.5 : 1; + var x_ = cubicAt(x0, x1, x2, x3, t); + if (x_ < x) { + continue; + } + if (nExtrema < 0) { + nExtrema = cubicExtrema(y0, y1, y2, y3, extrema); + if (extrema[1] < extrema[0] && nExtrema > 1) { + swapExtrema(); + } + y0_ = cubicAt(y0, y1, y2, y3, extrema[0]); + if (nExtrema > 1) { + y1_ = cubicAt(y0, y1, y2, y3, extrema[1]); + } + } + if (nExtrema === 2) { + if (t < extrema[0]) { + w += y0_ < y0 ? unit : -unit; + } + else if (t < extrema[1]) { + w += y1_ < y0_ ? unit : -unit; + } + else { + w += y3 < y1_ ? unit : -unit; + } + } + else { + if (t < extrema[0]) { + w += y0_ < y0 ? unit : -unit; + } + else { + w += y3 < y0_ ? unit : -unit; + } + } + } + return w; + } + } + function windingQuadratic(x0, y0, x1, y1, x2, y2, x, y) { + if ((y > y0 && y > y1 && y > y2) + || (y < y0 && y < y1 && y < y2)) { + return 0; + } + var nRoots = quadraticRootAt(y0, y1, y2, y, roots); + if (nRoots === 0) { + return 0; + } + else { + var t = quadraticExtremum(y0, y1, y2); + if (t >= 0 && t <= 1) { + var w = 0; + var y_ = quadraticAt(y0, y1, y2, t); + for (var i = 0; i < nRoots; i++) { + var unit = (roots[i] === 0 || roots[i] === 1) ? 0.5 : 1; + var x_ = quadraticAt(x0, x1, x2, roots[i]); + if (x_ < x) { + continue; + } + if (roots[i] < t) { + w += y_ < y0 ? unit : -unit; + } + else { + w += y2 < y_ ? unit : -unit; + } + } + return w; + } + else { + var unit = (roots[0] === 0 || roots[0] === 1) ? 0.5 : 1; + var x_ = quadraticAt(x0, x1, x2, roots[0]); + if (x_ < x) { + return 0; + } + return y2 < y0 ? unit : -unit; + } + } + } + function windingArc(cx, cy, r, startAngle, endAngle, anticlockwise, x, y) { + y -= cy; + if (y > r || y < -r) { + return 0; + } + var tmp = Math.sqrt(r * r - y * y); + roots[0] = -tmp; + roots[1] = tmp; + var dTheta = Math.abs(startAngle - endAngle); + if (dTheta < 1e-4) { + return 0; + } + if (dTheta >= PI2$4 - 1e-4) { + startAngle = 0; + endAngle = PI2$4; + var dir = anticlockwise ? 1 : -1; + if (x >= roots[0] + cx && x <= roots[1] + cx) { + return dir; + } + else { + return 0; + } + } + if (startAngle > endAngle) { + var tmp_1 = startAngle; + startAngle = endAngle; + endAngle = tmp_1; + } + if (startAngle < 0) { + startAngle += PI2$4; + endAngle += PI2$4; + } + var w = 0; + for (var i = 0; i < 2; i++) { + var x_ = roots[i]; + if (x_ + cx > x) { + var angle = Math.atan2(y, x_); + var dir = anticlockwise ? 1 : -1; + if (angle < 0) { + angle = PI2$4 + angle; + } + if ((angle >= startAngle && angle <= endAngle) + || (angle + PI2$4 >= startAngle && angle + PI2$4 <= endAngle)) { + if (angle > Math.PI / 2 && angle < Math.PI * 1.5) { + dir = -dir; + } + w += dir; + } + } + } + return w; + } + function containPath(path, lineWidth, isStroke, x, y) { + var data = path.data; + var len = path.len(); + var w = 0; + var xi = 0; + var yi = 0; + var x0 = 0; + var y0 = 0; + var x1; + var y1; + for (var i = 0; i < len;) { + var cmd = data[i++]; + var isFirst = i === 1; + if (cmd === CMD$1.M && i > 1) { + if (!isStroke) { + w += windingLine(xi, yi, x0, y0, x, y); + } + } + if (isFirst) { + xi = data[i]; + yi = data[i + 1]; + x0 = xi; + y0 = yi; + } + switch (cmd) { + case CMD$1.M: + x0 = data[i++]; + y0 = data[i++]; + xi = x0; + yi = y0; + break; + case CMD$1.L: + if (isStroke) { + if (containStroke(xi, yi, data[i], data[i + 1], lineWidth, x, y)) { + return true; + } + } + else { + w += windingLine(xi, yi, data[i], data[i + 1], x, y) || 0; + } + xi = data[i++]; + yi = data[i++]; + break; + case CMD$1.C: + if (isStroke) { + if (containStroke$1(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], lineWidth, x, y)) { + return true; + } + } + else { + w += windingCubic(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], x, y) || 0; + } + xi = data[i++]; + yi = data[i++]; + break; + case CMD$1.Q: + if (isStroke) { + if (containStroke$2(xi, yi, data[i++], data[i++], data[i], data[i + 1], lineWidth, x, y)) { + return true; + } + } + else { + w += windingQuadratic(xi, yi, data[i++], data[i++], data[i], data[i + 1], x, y) || 0; + } + xi = data[i++]; + yi = data[i++]; + break; + case CMD$1.A: + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var theta = data[i++]; + var dTheta = data[i++]; + i += 1; + var anticlockwise = !!(1 - data[i++]); + x1 = Math.cos(theta) * rx + cx; + y1 = Math.sin(theta) * ry + cy; + if (!isFirst) { + w += windingLine(xi, yi, x1, y1, x, y); + } + else { + x0 = x1; + y0 = y1; + } + var _x = (x - cx) * ry / rx + cx; + if (isStroke) { + if (containStroke$3(cx, cy, ry, theta, theta + dTheta, anticlockwise, lineWidth, _x, y)) { + return true; + } + } + else { + w += windingArc(cx, cy, ry, theta, theta + dTheta, anticlockwise, _x, y); + } + xi = Math.cos(theta + dTheta) * rx + cx; + yi = Math.sin(theta + dTheta) * ry + cy; + break; + case CMD$1.R: + x0 = xi = data[i++]; + y0 = yi = data[i++]; + var width = data[i++]; + var height = data[i++]; + x1 = x0 + width; + y1 = y0 + height; + if (isStroke) { + if (containStroke(x0, y0, x1, y0, lineWidth, x, y) + || containStroke(x1, y0, x1, y1, lineWidth, x, y) + || containStroke(x1, y1, x0, y1, lineWidth, x, y) + || containStroke(x0, y1, x0, y0, lineWidth, x, y)) { + return true; + } + } + else { + w += windingLine(x1, y0, x1, y1, x, y); + w += windingLine(x0, y1, x0, y0, x, y); + } + break; + case CMD$1.Z: + if (isStroke) { + if (containStroke(xi, yi, x0, y0, lineWidth, x, y)) { + return true; + } + } + else { + w += windingLine(xi, yi, x0, y0, x, y); + } + xi = x0; + yi = y0; + break; + } + } + if (!isStroke && !isAroundEqual(yi, y0)) { + w += windingLine(xi, yi, x0, y0, x, y) || 0; + } + return w !== 0; + } + function contain(pathProxy, x, y) { + return containPath(pathProxy, 0, false, x, y); + } + function containStroke$4(pathProxy, lineWidth, x, y) { + return containPath(pathProxy, lineWidth, true, x, y); + } + + var DEFAULT_PATH_STYLE = defaults({ + fill: '#000', + stroke: null, + strokePercent: 1, + fillOpacity: 1, + strokeOpacity: 1, + lineDashOffset: 0, + lineWidth: 1, + lineCap: 'butt', + miterLimit: 10, + strokeNoScale: false, + strokeFirst: false + }, DEFAULT_COMMON_STYLE); + var DEFAULT_PATH_ANIMATION_PROPS = { + style: defaults({ + fill: true, + stroke: true, + strokePercent: true, + fillOpacity: true, + strokeOpacity: true, + lineDashOffset: true, + lineWidth: true, + miterLimit: true + }, DEFAULT_COMMON_ANIMATION_PROPS.style) + }; + var pathCopyParams = [ + 'x', 'y', 'rotation', 'scaleX', 'scaleY', 'originX', 'originY', 'invisible', + 'culling', 'z', 'z2', 'zlevel', 'parent' + ]; + var Path = (function (_super) { + __extends(Path, _super); + function Path(opts) { + return _super.call(this, opts) || this; + } + Path.prototype.update = function () { + var _this = this; + _super.prototype.update.call(this); + var style = this.style; + if (style.decal) { + var decalEl = this._decalEl + = this._decalEl || new Path(); + if (decalEl.buildPath === Path.prototype.buildPath) { + decalEl.buildPath = function (ctx) { + _this.buildPath(ctx, _this.shape); + }; + } + decalEl.silent = true; + var decalElStyle = decalEl.style; + for (var key in style) { + if (decalElStyle[key] !== style[key]) { + decalElStyle[key] = style[key]; + } + } + decalElStyle.fill = style.fill ? style.decal : null; + decalElStyle.decal = null; + decalElStyle.shadowColor = null; + style.strokeFirst && (decalElStyle.stroke = null); + for (var i = 0; i < pathCopyParams.length; ++i) { + decalEl[pathCopyParams[i]] = this[pathCopyParams[i]]; + } + decalEl.__dirty |= Element.REDARAW_BIT; + } + else if (this._decalEl) { + this._decalEl = null; + } + }; + Path.prototype.getDecalElement = function () { + return this._decalEl; + }; + Path.prototype._init = function (props) { + var keysArr = keys(props); + this.shape = this.getDefaultShape(); + var defaultStyle = this.getDefaultStyle(); + if (defaultStyle) { + this.useStyle(defaultStyle); + } + for (var i = 0; i < keysArr.length; i++) { + var key = keysArr[i]; + var value = props[key]; + if (key === 'style') { + if (!this.style) { + this.useStyle(value); + } + else { + extend(this.style, value); + } + } + else if (key === 'shape') { + extend(this.shape, value); + } + else { + _super.prototype.attrKV.call(this, key, value); + } + } + if (!this.style) { + this.useStyle({}); + } + }; + Path.prototype.getDefaultStyle = function () { + return null; + }; + Path.prototype.getDefaultShape = function () { + return {}; + }; + Path.prototype.canBeInsideText = function () { + return this.hasFill(); + }; + Path.prototype.getInsideTextFill = function () { + var pathFill = this.style.fill; + if (pathFill !== 'none') { + if (isString(pathFill)) { + var fillLum = lum(pathFill, 0); + if (fillLum > 0.5) { + return DARK_LABEL_COLOR; + } + else if (fillLum > 0.2) { + return LIGHTER_LABEL_COLOR; + } + return LIGHT_LABEL_COLOR; + } + else if (pathFill) { + return LIGHT_LABEL_COLOR; + } + } + return DARK_LABEL_COLOR; + }; + Path.prototype.getInsideTextStroke = function (textFill) { + var pathFill = this.style.fill; + if (isString(pathFill)) { + var zr = this.__zr; + var isDarkMode = !!(zr && zr.isDarkMode()); + var isDarkLabel = lum(textFill, 0) < DARK_MODE_THRESHOLD; + if (isDarkMode === isDarkLabel) { + return pathFill; + } + } + }; + Path.prototype.buildPath = function (ctx, shapeCfg, inBundle) { }; + Path.prototype.pathUpdated = function () { + this.__dirty &= ~Path.SHAPE_CHANGED_BIT; + }; + Path.prototype.createPathProxy = function () { + this.path = new PathProxy(false); + }; + Path.prototype.hasStroke = function () { + var style = this.style; + var stroke = style.stroke; + return !(stroke == null || stroke === 'none' || !(style.lineWidth > 0)); + }; + Path.prototype.hasFill = function () { + var style = this.style; + var fill = style.fill; + return fill != null && fill !== 'none'; + }; + Path.prototype.getBoundingRect = function () { + var rect = this._rect; + var style = this.style; + var needsUpdateRect = !rect; + if (needsUpdateRect) { + var firstInvoke = false; + if (!this.path) { + firstInvoke = true; + this.createPathProxy(); + } + var path = this.path; + if (firstInvoke || (this.__dirty & Path.SHAPE_CHANGED_BIT)) { + path.beginPath(); + this.buildPath(path, this.shape, false); + this.pathUpdated(); + } + rect = path.getBoundingRect(); + } + this._rect = rect; + if (this.hasStroke() && this.path && this.path.len() > 0) { + var rectWithStroke = this._rectWithStroke || (this._rectWithStroke = rect.clone()); + if (this.__dirty || needsUpdateRect) { + rectWithStroke.copy(rect); + var lineScale = style.strokeNoScale ? this.getLineScale() : 1; + var w = style.lineWidth; + if (!this.hasFill()) { + var strokeContainThreshold = this.strokeContainThreshold; + w = Math.max(w, strokeContainThreshold == null ? 4 : strokeContainThreshold); + } + if (lineScale > 1e-10) { + rectWithStroke.width += w / lineScale; + rectWithStroke.height += w / lineScale; + rectWithStroke.x -= w / lineScale / 2; + rectWithStroke.y -= w / lineScale / 2; + } + } + return rectWithStroke; + } + return rect; + }; + Path.prototype.contain = function (x, y) { + var localPos = this.transformCoordToLocal(x, y); + var rect = this.getBoundingRect(); + var style = this.style; + x = localPos[0]; + y = localPos[1]; + if (rect.contain(x, y)) { + var pathProxy = this.path; + if (this.hasStroke()) { + var lineWidth = style.lineWidth; + var lineScale = style.strokeNoScale ? this.getLineScale() : 1; + if (lineScale > 1e-10) { + if (!this.hasFill()) { + lineWidth = Math.max(lineWidth, this.strokeContainThreshold); + } + if (containStroke$4(pathProxy, lineWidth / lineScale, x, y)) { + return true; + } + } + } + if (this.hasFill()) { + return contain(pathProxy, x, y); + } + } + return false; + }; + Path.prototype.dirtyShape = function () { + this.__dirty |= Path.SHAPE_CHANGED_BIT; + if (this._rect) { + this._rect = null; + } + if (this._decalEl) { + this._decalEl.dirtyShape(); + } + this.markRedraw(); + }; + Path.prototype.dirty = function () { + this.dirtyStyle(); + this.dirtyShape(); + }; + Path.prototype.animateShape = function (loop) { + return this.animate('shape', loop); + }; + Path.prototype.updateDuringAnimation = function (targetKey) { + if (targetKey === 'style') { + this.dirtyStyle(); + } + else if (targetKey === 'shape') { + this.dirtyShape(); + } + else { + this.markRedraw(); + } + }; + Path.prototype.attrKV = function (key, value) { + if (key === 'shape') { + this.setShape(value); + } + else { + _super.prototype.attrKV.call(this, key, value); + } + }; + Path.prototype.setShape = function (keyOrObj, value) { + var shape = this.shape; + if (!shape) { + shape = this.shape = {}; + } + if (typeof keyOrObj === 'string') { + shape[keyOrObj] = value; + } + else { + extend(shape, keyOrObj); + } + this.dirtyShape(); + return this; + }; + Path.prototype.shapeChanged = function () { + return !!(this.__dirty & Path.SHAPE_CHANGED_BIT); + }; + Path.prototype.createStyle = function (obj) { + return createObject(DEFAULT_PATH_STYLE, obj); + }; + Path.prototype._innerSaveToNormal = function (toState) { + _super.prototype._innerSaveToNormal.call(this, toState); + var normalState = this._normalState; + if (toState.shape && !normalState.shape) { + normalState.shape = extend({}, this.shape); + } + }; + Path.prototype._applyStateObj = function (stateName, state, normalState, keepCurrentStates, transition, animationCfg) { + _super.prototype._applyStateObj.call(this, stateName, state, normalState, keepCurrentStates, transition, animationCfg); + var needsRestoreToNormal = !(state && keepCurrentStates); + var targetShape; + if (state && state.shape) { + if (transition) { + if (keepCurrentStates) { + targetShape = state.shape; + } + else { + targetShape = extend({}, normalState.shape); + extend(targetShape, state.shape); + } + } + else { + targetShape = extend({}, keepCurrentStates ? this.shape : normalState.shape); + extend(targetShape, state.shape); + } + } + else if (needsRestoreToNormal) { + targetShape = normalState.shape; + } + if (targetShape) { + if (transition) { + this.shape = extend({}, this.shape); + var targetShapePrimaryProps = {}; + var shapeKeys = keys(targetShape); + for (var i = 0; i < shapeKeys.length; i++) { + var key = shapeKeys[i]; + if (typeof targetShape[key] === 'object') { + this.shape[key] = targetShape[key]; + } + else { + targetShapePrimaryProps[key] = targetShape[key]; + } + } + this._transitionState(stateName, { + shape: targetShapePrimaryProps + }, animationCfg); + } + else { + this.shape = targetShape; + this.dirtyShape(); + } + } + }; + Path.prototype._mergeStates = function (states) { + var mergedState = _super.prototype._mergeStates.call(this, states); + var mergedShape; + for (var i = 0; i < states.length; i++) { + var state = states[i]; + if (state.shape) { + mergedShape = mergedShape || {}; + this._mergeStyle(mergedShape, state.shape); + } + } + if (mergedShape) { + mergedState.shape = mergedShape; + } + return mergedState; + }; + Path.prototype.getAnimationStyleProps = function () { + return DEFAULT_PATH_ANIMATION_PROPS; + }; + Path.prototype.isZeroArea = function () { + return false; + }; + Path.extend = function (defaultProps) { + var Sub = (function (_super) { + __extends(Sub, _super); + function Sub(opts) { + var _this = _super.call(this, opts) || this; + defaultProps.init && defaultProps.init.call(_this, opts); + return _this; + } + Sub.prototype.getDefaultStyle = function () { + return clone(defaultProps.style); + }; + Sub.prototype.getDefaultShape = function () { + return clone(defaultProps.shape); + }; + return Sub; + }(Path)); + for (var key in defaultProps) { + if (typeof defaultProps[key] === 'function') { + Sub.prototype[key] = defaultProps[key]; + } + } + return Sub; + }; + Path.SHAPE_CHANGED_BIT = 4; + Path.initDefaultProps = (function () { + var pathProto = Path.prototype; + pathProto.type = 'path'; + pathProto.strokeContainThreshold = 5; + pathProto.segmentIgnoreThreshold = 0; + pathProto.subPixelOptimize = false; + pathProto.autoBatch = false; + pathProto.__dirty = Element.REDARAW_BIT | Displayable.STYLE_CHANGED_BIT | Path.SHAPE_CHANGED_BIT; + })(); + return Path; + }(Displayable)); + + var DEFAULT_TSPAN_STYLE = defaults({ + strokeFirst: true, + font: DEFAULT_FONT, + x: 0, + y: 0, + textAlign: 'left', + textBaseline: 'top', + miterLimit: 2 + }, DEFAULT_PATH_STYLE); + var TSpan = (function (_super) { + __extends(TSpan, _super); + function TSpan() { + return _super !== null && _super.apply(this, arguments) || this; + } + TSpan.prototype.hasStroke = function () { + var style = this.style; + var stroke = style.stroke; + return stroke != null && stroke !== 'none' && style.lineWidth > 0; + }; + TSpan.prototype.hasFill = function () { + var style = this.style; + var fill = style.fill; + return fill != null && fill !== 'none'; + }; + TSpan.prototype.createStyle = function (obj) { + return createObject(DEFAULT_TSPAN_STYLE, obj); + }; + TSpan.prototype.setBoundingRect = function (rect) { + this._rect = rect; + }; + TSpan.prototype.getBoundingRect = function () { + var style = this.style; + if (!this._rect) { + var text = style.text; + text != null ? (text += '') : (text = ''); + var rect = getBoundingRect(text, style.font, style.textAlign, style.textBaseline); + rect.x += style.x || 0; + rect.y += style.y || 0; + if (this.hasStroke()) { + var w = style.lineWidth; + rect.x -= w / 2; + rect.y -= w / 2; + rect.width += w; + rect.height += w; + } + this._rect = rect; + } + return this._rect; + }; + TSpan.initDefaultProps = (function () { + var tspanProto = TSpan.prototype; + tspanProto.dirtyRectTolerance = 10; + })(); + return TSpan; + }(Displayable)); + TSpan.prototype.type = 'tspan'; + + var DEFAULT_IMAGE_STYLE = defaults({ + x: 0, + y: 0 + }, DEFAULT_COMMON_STYLE); + var DEFAULT_IMAGE_ANIMATION_PROPS = { + style: defaults({ + x: true, + y: true, + width: true, + height: true, + sx: true, + sy: true, + sWidth: true, + sHeight: true + }, DEFAULT_COMMON_ANIMATION_PROPS.style) + }; + function isImageLike(source) { + return !!(source + && typeof source !== 'string' + && source.width && source.height); + } + var ZRImage = (function (_super) { + __extends(ZRImage, _super); + function ZRImage() { + return _super !== null && _super.apply(this, arguments) || this; + } + ZRImage.prototype.createStyle = function (obj) { + return createObject(DEFAULT_IMAGE_STYLE, obj); + }; + ZRImage.prototype._getSize = function (dim) { + var style = this.style; + var size = style[dim]; + if (size != null) { + return size; + } + var imageSource = isImageLike(style.image) + ? style.image : this.__image; + if (!imageSource) { + return 0; + } + var otherDim = dim === 'width' ? 'height' : 'width'; + var otherDimSize = style[otherDim]; + if (otherDimSize == null) { + return imageSource[dim]; + } + else { + return imageSource[dim] / imageSource[otherDim] * otherDimSize; + } + }; + ZRImage.prototype.getWidth = function () { + return this._getSize('width'); + }; + ZRImage.prototype.getHeight = function () { + return this._getSize('height'); + }; + ZRImage.prototype.getAnimationStyleProps = function () { + return DEFAULT_IMAGE_ANIMATION_PROPS; + }; + ZRImage.prototype.getBoundingRect = function () { + var style = this.style; + if (!this._rect) { + this._rect = new BoundingRect(style.x || 0, style.y || 0, this.getWidth(), this.getHeight()); + } + return this._rect; + }; + return ZRImage; + }(Displayable)); + ZRImage.prototype.type = 'image'; + + function buildPath(ctx, shape) { + var x = shape.x; + var y = shape.y; + var width = shape.width; + var height = shape.height; + var r = shape.r; + var r1; + var r2; + var r3; + var r4; + if (width < 0) { + x = x + width; + width = -width; + } + if (height < 0) { + y = y + height; + height = -height; + } + if (typeof r === 'number') { + r1 = r2 = r3 = r4 = r; + } + else if (r instanceof Array) { + if (r.length === 1) { + r1 = r2 = r3 = r4 = r[0]; + } + else if (r.length === 2) { + r1 = r3 = r[0]; + r2 = r4 = r[1]; + } + else if (r.length === 3) { + r1 = r[0]; + r2 = r4 = r[1]; + r3 = r[2]; + } + else { + r1 = r[0]; + r2 = r[1]; + r3 = r[2]; + r4 = r[3]; + } + } + else { + r1 = r2 = r3 = r4 = 0; + } + var total; + if (r1 + r2 > width) { + total = r1 + r2; + r1 *= width / total; + r2 *= width / total; + } + if (r3 + r4 > width) { + total = r3 + r4; + r3 *= width / total; + r4 *= width / total; + } + if (r2 + r3 > height) { + total = r2 + r3; + r2 *= height / total; + r3 *= height / total; + } + if (r1 + r4 > height) { + total = r1 + r4; + r1 *= height / total; + r4 *= height / total; + } + ctx.moveTo(x + r1, y); + ctx.lineTo(x + width - r2, y); + r2 !== 0 && ctx.arc(x + width - r2, y + r2, r2, -Math.PI / 2, 0); + ctx.lineTo(x + width, y + height - r3); + r3 !== 0 && ctx.arc(x + width - r3, y + height - r3, r3, 0, Math.PI / 2); + ctx.lineTo(x + r4, y + height); + r4 !== 0 && ctx.arc(x + r4, y + height - r4, r4, Math.PI / 2, Math.PI); + ctx.lineTo(x, y + r1); + r1 !== 0 && ctx.arc(x + r1, y + r1, r1, Math.PI, Math.PI * 1.5); + } + + var round$1 = Math.round; + function subPixelOptimizeLine(outputShape, inputShape, style) { + if (!inputShape) { + return; + } + var x1 = inputShape.x1; + var x2 = inputShape.x2; + var y1 = inputShape.y1; + var y2 = inputShape.y2; + outputShape.x1 = x1; + outputShape.x2 = x2; + outputShape.y1 = y1; + outputShape.y2 = y2; + var lineWidth = style && style.lineWidth; + if (!lineWidth) { + return outputShape; + } + if (round$1(x1 * 2) === round$1(x2 * 2)) { + outputShape.x1 = outputShape.x2 = subPixelOptimize(x1, lineWidth, true); + } + if (round$1(y1 * 2) === round$1(y2 * 2)) { + outputShape.y1 = outputShape.y2 = subPixelOptimize(y1, lineWidth, true); + } + return outputShape; + } + function subPixelOptimizeRect(outputShape, inputShape, style) { + if (!inputShape) { + return; + } + var originX = inputShape.x; + var originY = inputShape.y; + var originWidth = inputShape.width; + var originHeight = inputShape.height; + outputShape.x = originX; + outputShape.y = originY; + outputShape.width = originWidth; + outputShape.height = originHeight; + var lineWidth = style && style.lineWidth; + if (!lineWidth) { + return outputShape; + } + outputShape.x = subPixelOptimize(originX, lineWidth, true); + outputShape.y = subPixelOptimize(originY, lineWidth, true); + outputShape.width = Math.max(subPixelOptimize(originX + originWidth, lineWidth, false) - outputShape.x, originWidth === 0 ? 0 : 1); + outputShape.height = Math.max(subPixelOptimize(originY + originHeight, lineWidth, false) - outputShape.y, originHeight === 0 ? 0 : 1); + return outputShape; + } + function subPixelOptimize(position, lineWidth, positiveOrNegative) { + if (!lineWidth) { + return position; + } + var doubledPosition = round$1(position * 2); + return (doubledPosition + round$1(lineWidth)) % 2 === 0 + ? doubledPosition / 2 + : (doubledPosition + (positiveOrNegative ? 1 : -1)) / 2; + } + + var RectShape = (function () { + function RectShape() { + this.x = 0; + this.y = 0; + this.width = 0; + this.height = 0; + } + return RectShape; + }()); + var subPixelOptimizeOutputShape = {}; + var Rect = (function (_super) { + __extends(Rect, _super); + function Rect(opts) { + return _super.call(this, opts) || this; + } + Rect.prototype.getDefaultShape = function () { + return new RectShape(); + }; + Rect.prototype.buildPath = function (ctx, shape) { + var x; + var y; + var width; + var height; + if (this.subPixelOptimize) { + var optimizedShape = subPixelOptimizeRect(subPixelOptimizeOutputShape, shape, this.style); + x = optimizedShape.x; + y = optimizedShape.y; + width = optimizedShape.width; + height = optimizedShape.height; + optimizedShape.r = shape.r; + shape = optimizedShape; + } + else { + x = shape.x; + y = shape.y; + width = shape.width; + height = shape.height; + } + if (!shape.r) { + ctx.rect(x, y, width, height); + } + else { + buildPath(ctx, shape); + } + }; + Rect.prototype.isZeroArea = function () { + return !this.shape.width || !this.shape.height; + }; + return Rect; + }(Path)); + Rect.prototype.type = 'rect'; + + var DEFAULT_RICH_TEXT_COLOR = { + fill: '#000' + }; + var DEFAULT_STROKE_LINE_WIDTH = 2; + var DEFAULT_TEXT_ANIMATION_PROPS = { + style: defaults({ + fill: true, + stroke: true, + fillOpacity: true, + strokeOpacity: true, + lineWidth: true, + fontSize: true, + lineHeight: true, + width: true, + height: true, + textShadowColor: true, + textShadowBlur: true, + textShadowOffsetX: true, + textShadowOffsetY: true, + backgroundColor: true, + padding: true, + borderColor: true, + borderWidth: true, + borderRadius: true + }, DEFAULT_COMMON_ANIMATION_PROPS.style) + }; + var ZRText = (function (_super) { + __extends(ZRText, _super); + function ZRText(opts) { + var _this = _super.call(this) || this; + _this.type = 'text'; + _this._children = []; + _this._defaultStyle = DEFAULT_RICH_TEXT_COLOR; + _this.attr(opts); + return _this; + } + ZRText.prototype.childrenRef = function () { + return this._children; + }; + ZRText.prototype.update = function () { + if (this.styleChanged()) { + this._updateSubTexts(); + } + for (var i = 0; i < this._children.length; i++) { + var child = this._children[i]; + child.zlevel = this.zlevel; + child.z = this.z; + child.z2 = this.z2; + child.culling = this.culling; + child.cursor = this.cursor; + child.invisible = this.invisible; + } + var attachedTransform = this.attachedTransform; + if (attachedTransform) { + attachedTransform.updateTransform(); + var m = attachedTransform.transform; + if (m) { + this.transform = this.transform || []; + copy$1(this.transform, m); + } + else { + this.transform = null; + } + } + else { + _super.prototype.update.call(this); + } + }; + ZRText.prototype.getComputedTransform = function () { + if (this.__hostTarget) { + this.__hostTarget.getComputedTransform(); + this.__hostTarget.updateInnerText(true); + } + return this.attachedTransform ? this.attachedTransform.getComputedTransform() + : _super.prototype.getComputedTransform.call(this); + }; + ZRText.prototype._updateSubTexts = function () { + this._childCursor = 0; + normalizeTextStyle(this.style); + this.style.rich + ? this._updateRichTexts() + : this._updatePlainTexts(); + this._children.length = this._childCursor; + this.styleUpdated(); + }; + ZRText.prototype.addSelfToZr = function (zr) { + _super.prototype.addSelfToZr.call(this, zr); + for (var i = 0; i < this._children.length; i++) { + this._children[i].__zr = zr; + } + }; + ZRText.prototype.removeSelfFromZr = function (zr) { + _super.prototype.removeSelfFromZr.call(this, zr); + for (var i = 0; i < this._children.length; i++) { + this._children[i].__zr = null; + } + }; + ZRText.prototype.getBoundingRect = function () { + if (this.styleChanged()) { + this._updateSubTexts(); + } + if (!this._rect) { + var tmpRect = new BoundingRect(0, 0, 0, 0); + var children = this._children; + var tmpMat = []; + var rect = null; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + var childRect = child.getBoundingRect(); + var transform = child.getLocalTransform(tmpMat); + if (transform) { + tmpRect.copy(childRect); + tmpRect.applyTransform(transform); + rect = rect || tmpRect.clone(); + rect.union(tmpRect); + } + else { + rect = rect || childRect.clone(); + rect.union(childRect); + } + } + this._rect = rect || tmpRect; + } + return this._rect; + }; + ZRText.prototype.setDefaultTextStyle = function (defaultTextStyle) { + this._defaultStyle = defaultTextStyle || DEFAULT_RICH_TEXT_COLOR; + }; + ZRText.prototype.setTextContent = function (textContent) { + throw new Error('Can\'t attach text on another text'); + }; + ZRText.prototype._mergeStyle = function (targetStyle, sourceStyle) { + if (!sourceStyle) { + return targetStyle; + } + var sourceRich = sourceStyle.rich; + var targetRich = targetStyle.rich || (sourceRich && {}); + extend(targetStyle, sourceStyle); + if (sourceRich && targetRich) { + this._mergeRich(targetRich, sourceRich); + targetStyle.rich = targetRich; + } + else if (targetRich) { + targetStyle.rich = targetRich; + } + return targetStyle; + }; + ZRText.prototype._mergeRich = function (targetRich, sourceRich) { + var richNames = keys(sourceRich); + for (var i = 0; i < richNames.length; i++) { + var richName = richNames[i]; + targetRich[richName] = targetRich[richName] || {}; + extend(targetRich[richName], sourceRich[richName]); + } + }; + ZRText.prototype.getAnimationStyleProps = function () { + return DEFAULT_TEXT_ANIMATION_PROPS; + }; + ZRText.prototype._getOrCreateChild = function (Ctor) { + var child = this._children[this._childCursor]; + if (!child || !(child instanceof Ctor)) { + child = new Ctor(); + } + this._children[this._childCursor++] = child; + child.__zr = this.__zr; + child.parent = this; + return child; + }; + ZRText.prototype._updatePlainTexts = function () { + var style = this.style; + var textFont = style.font || DEFAULT_FONT; + var textPadding = style.padding; + var text = getStyleText(style); + var contentBlock = parsePlainText(text, style); + var needDrawBg = needDrawBackground(style); + var bgColorDrawn = !!(style.backgroundColor); + var outerHeight = contentBlock.outerHeight; + var textLines = contentBlock.lines; + var lineHeight = contentBlock.lineHeight; + var defaultStyle = this._defaultStyle; + var baseX = style.x || 0; + var baseY = style.y || 0; + var textAlign = style.align || defaultStyle.align || 'left'; + var verticalAlign = style.verticalAlign || defaultStyle.verticalAlign || 'top'; + var textX = baseX; + var textY = adjustTextY(baseY, contentBlock.contentHeight, verticalAlign); + if (needDrawBg || textPadding) { + var outerWidth_1 = contentBlock.width; + textPadding && (outerWidth_1 += textPadding[1] + textPadding[3]); + var boxX = adjustTextX(baseX, outerWidth_1, textAlign); + var boxY = adjustTextY(baseY, outerHeight, verticalAlign); + needDrawBg && this._renderBackground(style, style, boxX, boxY, outerWidth_1, outerHeight); + } + textY += lineHeight / 2; + if (textPadding) { + textX = getTextXForPadding(baseX, textAlign, textPadding); + if (verticalAlign === 'top') { + textY += textPadding[0]; + } + else if (verticalAlign === 'bottom') { + textY -= textPadding[2]; + } + } + var defaultLineWidth = 0; + var useDefaultFill = false; + var textFill = getFill('fill' in style + ? style.fill + : (useDefaultFill = true, defaultStyle.fill)); + var textStroke = getStroke('stroke' in style + ? style.stroke + : (!bgColorDrawn + && (!defaultStyle.autoStroke || useDefaultFill)) + ? (defaultLineWidth = DEFAULT_STROKE_LINE_WIDTH, defaultStyle.stroke) + : null); + var hasShadow = style.textShadowBlur > 0; + var fixedBoundingRect = style.width != null + && (style.overflow === 'truncate' || style.overflow === 'break' || style.overflow === 'breakAll'); + var calculatedLineHeight = contentBlock.calculatedLineHeight; + for (var i = 0; i < textLines.length; i++) { + var el = this._getOrCreateChild(TSpan); + var subElStyle = el.createStyle(); + el.useStyle(subElStyle); + subElStyle.text = textLines[i]; + subElStyle.x = textX; + subElStyle.y = textY; + if (textAlign) { + subElStyle.textAlign = textAlign; + } + subElStyle.textBaseline = 'middle'; + subElStyle.opacity = style.opacity; + subElStyle.strokeFirst = true; + if (hasShadow) { + subElStyle.shadowBlur = style.textShadowBlur || 0; + subElStyle.shadowColor = style.textShadowColor || 'transparent'; + subElStyle.shadowOffsetX = style.textShadowOffsetX || 0; + subElStyle.shadowOffsetY = style.textShadowOffsetY || 0; + } + if (textStroke) { + subElStyle.stroke = textStroke; + subElStyle.lineWidth = style.lineWidth || defaultLineWidth; + subElStyle.lineDash = style.lineDash; + subElStyle.lineDashOffset = style.lineDashOffset || 0; + } + if (textFill) { + subElStyle.fill = textFill; + } + subElStyle.font = textFont; + textY += lineHeight; + if (fixedBoundingRect) { + el.setBoundingRect(new BoundingRect(adjustTextX(subElStyle.x, style.width, subElStyle.textAlign), adjustTextY(subElStyle.y, calculatedLineHeight, subElStyle.textBaseline), style.width, calculatedLineHeight)); + } + } + }; + ZRText.prototype._updateRichTexts = function () { + var style = this.style; + var text = getStyleText(style); + var contentBlock = parseRichText(text, style); + var contentWidth = contentBlock.width; + var outerWidth = contentBlock.outerWidth; + var outerHeight = contentBlock.outerHeight; + var textPadding = style.padding; + var baseX = style.x || 0; + var baseY = style.y || 0; + var defaultStyle = this._defaultStyle; + var textAlign = style.align || defaultStyle.align; + var verticalAlign = style.verticalAlign || defaultStyle.verticalAlign; + var boxX = adjustTextX(baseX, outerWidth, textAlign); + var boxY = adjustTextY(baseY, outerHeight, verticalAlign); + var xLeft = boxX; + var lineTop = boxY; + if (textPadding) { + xLeft += textPadding[3]; + lineTop += textPadding[0]; + } + var xRight = xLeft + contentWidth; + if (needDrawBackground(style)) { + this._renderBackground(style, style, boxX, boxY, outerWidth, outerHeight); + } + var bgColorDrawn = !!(style.backgroundColor); + for (var i = 0; i < contentBlock.lines.length; i++) { + var line = contentBlock.lines[i]; + var tokens = line.tokens; + var tokenCount = tokens.length; + var lineHeight = line.lineHeight; + var remainedWidth = line.width; + var leftIndex = 0; + var lineXLeft = xLeft; + var lineXRight = xRight; + var rightIndex = tokenCount - 1; + var token = void 0; + while (leftIndex < tokenCount + && (token = tokens[leftIndex], !token.align || token.align === 'left')) { + this._placeToken(token, style, lineHeight, lineTop, lineXLeft, 'left', bgColorDrawn); + remainedWidth -= token.width; + lineXLeft += token.width; + leftIndex++; + } + while (rightIndex >= 0 + && (token = tokens[rightIndex], token.align === 'right')) { + this._placeToken(token, style, lineHeight, lineTop, lineXRight, 'right', bgColorDrawn); + remainedWidth -= token.width; + lineXRight -= token.width; + rightIndex--; + } + lineXLeft += (contentWidth - (lineXLeft - xLeft) - (xRight - lineXRight) - remainedWidth) / 2; + while (leftIndex <= rightIndex) { + token = tokens[leftIndex]; + this._placeToken(token, style, lineHeight, lineTop, lineXLeft + token.width / 2, 'center', bgColorDrawn); + lineXLeft += token.width; + leftIndex++; + } + lineTop += lineHeight; + } + }; + ZRText.prototype._placeToken = function (token, style, lineHeight, lineTop, x, textAlign, parentBgColorDrawn) { + var tokenStyle = style.rich[token.styleName] || {}; + tokenStyle.text = token.text; + var verticalAlign = token.verticalAlign; + var y = lineTop + lineHeight / 2; + if (verticalAlign === 'top') { + y = lineTop + token.height / 2; + } + else if (verticalAlign === 'bottom') { + y = lineTop + lineHeight - token.height / 2; + } + var needDrawBg = !token.isLineHolder && needDrawBackground(tokenStyle); + needDrawBg && this._renderBackground(tokenStyle, style, textAlign === 'right' + ? x - token.width + : textAlign === 'center' + ? x - token.width / 2 + : x, y - token.height / 2, token.width, token.height); + var bgColorDrawn = !!tokenStyle.backgroundColor; + var textPadding = token.textPadding; + if (textPadding) { + x = getTextXForPadding(x, textAlign, textPadding); + y -= token.height / 2 - textPadding[0] - token.innerHeight / 2; + } + var el = this._getOrCreateChild(TSpan); + var subElStyle = el.createStyle(); + el.useStyle(subElStyle); + var defaultStyle = this._defaultStyle; + var useDefaultFill = false; + var defaultLineWidth = 0; + var textFill = getStroke('fill' in tokenStyle ? tokenStyle.fill + : 'fill' in style ? style.fill + : (useDefaultFill = true, defaultStyle.fill)); + var textStroke = getStroke('stroke' in tokenStyle ? tokenStyle.stroke + : 'stroke' in style ? style.stroke + : (!bgColorDrawn + && !parentBgColorDrawn + && (!defaultStyle.autoStroke || useDefaultFill)) ? (defaultLineWidth = DEFAULT_STROKE_LINE_WIDTH, defaultStyle.stroke) + : null); + var hasShadow = tokenStyle.textShadowBlur > 0 + || style.textShadowBlur > 0; + subElStyle.text = token.text; + subElStyle.x = x; + subElStyle.y = y; + if (hasShadow) { + subElStyle.shadowBlur = tokenStyle.textShadowBlur || style.textShadowBlur || 0; + subElStyle.shadowColor = tokenStyle.textShadowColor || style.textShadowColor || 'transparent'; + subElStyle.shadowOffsetX = tokenStyle.textShadowOffsetX || style.textShadowOffsetX || 0; + subElStyle.shadowOffsetY = tokenStyle.textShadowOffsetY || style.textShadowOffsetY || 0; + } + subElStyle.textAlign = textAlign; + subElStyle.textBaseline = 'middle'; + subElStyle.font = token.font || DEFAULT_FONT; + subElStyle.opacity = retrieve3(tokenStyle.opacity, style.opacity, 1); + if (textStroke) { + subElStyle.lineWidth = retrieve3(tokenStyle.lineWidth, style.lineWidth, defaultLineWidth); + subElStyle.lineDash = retrieve2(tokenStyle.lineDash, style.lineDash); + subElStyle.lineDashOffset = style.lineDashOffset || 0; + subElStyle.stroke = textStroke; + } + if (textFill) { + subElStyle.fill = textFill; + } + var textWidth = token.contentWidth; + var textHeight = token.contentHeight; + el.setBoundingRect(new BoundingRect(adjustTextX(subElStyle.x, textWidth, subElStyle.textAlign), adjustTextY(subElStyle.y, textHeight, subElStyle.textBaseline), textWidth, textHeight)); + }; + ZRText.prototype._renderBackground = function (style, topStyle, x, y, width, height) { + var textBackgroundColor = style.backgroundColor; + var textBorderWidth = style.borderWidth; + var textBorderColor = style.borderColor; + var isPlainBg = isString(textBackgroundColor); + var textBorderRadius = style.borderRadius; + var self = this; + var rectEl; + var imgEl; + if (isPlainBg || (textBorderWidth && textBorderColor)) { + rectEl = this._getOrCreateChild(Rect); + rectEl.useStyle(rectEl.createStyle()); + rectEl.style.fill = null; + var rectShape = rectEl.shape; + rectShape.x = x; + rectShape.y = y; + rectShape.width = width; + rectShape.height = height; + rectShape.r = textBorderRadius; + rectEl.dirtyShape(); + } + if (isPlainBg) { + var rectStyle = rectEl.style; + rectStyle.fill = textBackgroundColor || null; + rectStyle.fillOpacity = retrieve2(style.fillOpacity, 1); + } + else if (textBackgroundColor && textBackgroundColor.image) { + imgEl = this._getOrCreateChild(ZRImage); + imgEl.onload = function () { + self.dirtyStyle(); + }; + var imgStyle = imgEl.style; + imgStyle.image = textBackgroundColor.image; + imgStyle.x = x; + imgStyle.y = y; + imgStyle.width = width; + imgStyle.height = height; + } + if (textBorderWidth && textBorderColor) { + var rectStyle = rectEl.style; + rectStyle.lineWidth = textBorderWidth; + rectStyle.stroke = textBorderColor; + rectStyle.strokeOpacity = retrieve2(style.strokeOpacity, 1); + rectStyle.lineDash = style.borderDash; + rectStyle.lineDashOffset = style.borderDashOffset || 0; + rectEl.strokeContainThreshold = 0; + if (rectEl.hasFill() && rectEl.hasStroke()) { + rectStyle.strokeFirst = true; + rectStyle.lineWidth *= 2; + } + } + var commonStyle = (rectEl || imgEl).style; + commonStyle.shadowBlur = style.shadowBlur || 0; + commonStyle.shadowColor = style.shadowColor || 'transparent'; + commonStyle.shadowOffsetX = style.shadowOffsetX || 0; + commonStyle.shadowOffsetY = style.shadowOffsetY || 0; + commonStyle.opacity = retrieve3(style.opacity, topStyle.opacity, 1); + }; + ZRText.makeFont = function (style) { + var font = ''; + if (style.fontSize || style.fontFamily || style.fontWeight) { + var fontSize = ''; + if (typeof style.fontSize === 'string' + && (style.fontSize.indexOf('px') !== -1 + || style.fontSize.indexOf('rem') !== -1 + || style.fontSize.indexOf('em') !== -1)) { + fontSize = style.fontSize; + } + else if (!isNaN(+style.fontSize)) { + fontSize = style.fontSize + 'px'; + } + else { + fontSize = '12px'; + } + font = [ + style.fontStyle, + style.fontWeight, + fontSize, + style.fontFamily || 'sans-serif' + ].join(' '); + } + return font && trim(font) || style.textFont || style.font; + }; + return ZRText; + }(Displayable)); + var VALID_TEXT_ALIGN = { left: true, right: 1, center: 1 }; + var VALID_TEXT_VERTICAL_ALIGN = { top: 1, bottom: 1, middle: 1 }; + function normalizeTextStyle(style) { + normalizeStyle(style); + each(style.rich, normalizeStyle); + return style; + } + function normalizeStyle(style) { + if (style) { + style.font = ZRText.makeFont(style); + var textAlign = style.align; + textAlign === 'middle' && (textAlign = 'center'); + style.align = (textAlign == null || VALID_TEXT_ALIGN[textAlign]) ? textAlign : 'left'; + var verticalAlign = style.verticalAlign; + verticalAlign === 'center' && (verticalAlign = 'middle'); + style.verticalAlign = (verticalAlign == null || VALID_TEXT_VERTICAL_ALIGN[verticalAlign]) ? verticalAlign : 'top'; + var textPadding = style.padding; + if (textPadding) { + style.padding = normalizeCssArray(style.padding); + } + } + } + function getStroke(stroke, lineWidth) { + return (stroke == null || lineWidth <= 0 || stroke === 'transparent' || stroke === 'none') + ? null + : (stroke.image || stroke.colorStops) + ? '#000' + : stroke; + } + function getFill(fill) { + return (fill == null || fill === 'none') + ? null + : (fill.image || fill.colorStops) + ? '#000' + : fill; + } + function getTextXForPadding(x, textAlign, textPadding) { + return textAlign === 'right' + ? (x - textPadding[1]) + : textAlign === 'center' + ? (x + textPadding[3] / 2 - textPadding[1] / 2) + : (x + textPadding[3]); + } + function getStyleText(style) { + var text = style.text; + text != null && (text += ''); + return text; + } + function needDrawBackground(style) { + return !!(style.backgroundColor + || (style.borderWidth && style.borderColor)); + } + + var getECData = makeInner(); + + var _highlightNextDigit = 1; + var _highlightKeyMap = {}; + var getSavedStates = makeInner(); + var HOVER_STATE_NORMAL = 0; + var HOVER_STATE_BLUR = 1; + var HOVER_STATE_EMPHASIS = 2; + var SPECIAL_STATES = ['emphasis', 'blur', 'select']; + var DISPLAY_STATES = ['normal', 'emphasis', 'blur', 'select']; + var Z2_EMPHASIS_LIFT = 10; + var Z2_SELECT_LIFT = 9; + var HIGHLIGHT_ACTION_TYPE = 'highlight'; + var DOWNPLAY_ACTION_TYPE = 'downplay'; + var SELECT_ACTION_TYPE = 'select'; + var UNSELECT_ACTION_TYPE = 'unselect'; + var TOGGLE_SELECT_ACTION_TYPE = 'toggleSelect'; + + function hasFillOrStroke(fillOrStroke) { + return fillOrStroke != null && fillOrStroke !== 'none'; + } + + var liftedColorCache = new LRU(100); + + function liftColor(color$1) { + if (typeof color$1 !== 'string') { + return color$1; + } + + var liftedColor = liftedColorCache.get(color$1); + + if (!liftedColor) { + liftedColor = lift(color$1, -0.1); + liftedColorCache.put(color$1, liftedColor); + } + + return liftedColor; + } + + function doChangeHoverState(el, stateName, hoverStateEnum) { + if (el.onHoverStateChange && (el.hoverState || 0) !== hoverStateEnum) { + el.onHoverStateChange(stateName); + } + + el.hoverState = hoverStateEnum; + } + + function singleEnterEmphasis(el) { + doChangeHoverState(el, 'emphasis', HOVER_STATE_EMPHASIS); + } + + function singleLeaveEmphasis(el) { + if (el.hoverState === HOVER_STATE_EMPHASIS) { + doChangeHoverState(el, 'normal', HOVER_STATE_NORMAL); + } + } + + function singleEnterBlur(el) { + doChangeHoverState(el, 'blur', HOVER_STATE_BLUR); + } + + function singleLeaveBlur(el) { + if (el.hoverState === HOVER_STATE_BLUR) { + doChangeHoverState(el, 'normal', HOVER_STATE_NORMAL); + } + } + + function singleEnterSelect(el) { + el.selected = true; + } + + function singleLeaveSelect(el) { + el.selected = false; + } + + function updateElementState(el, updater, commonParam) { + updater(el, commonParam); + } + + function traverseUpdateState(el, updater, commonParam) { + updateElementState(el, updater, commonParam); + el.isGroup && el.traverse(function (child) { + updateElementState(child, updater, commonParam); + }); + } + + function setStatesFlag(el, stateName) { + switch (stateName) { + case 'emphasis': + el.hoverState = HOVER_STATE_EMPHASIS; + break; + + case 'normal': + el.hoverState = HOVER_STATE_NORMAL; + break; + + case 'blur': + el.hoverState = HOVER_STATE_BLUR; + break; + + case 'select': + el.selected = true; + } + } + + function getFromStateStyle(el, props, toStateName, defaultValue) { + var style = el.style; + var fromState = {}; + + for (var i = 0; i < props.length; i++) { + var propName = props[i]; + var val = style[propName]; + fromState[propName] = val == null ? defaultValue && defaultValue[propName] : val; + } + + for (var i = 0; i < el.animators.length; i++) { + var animator = el.animators[i]; + + if (animator.__fromStateTransition && animator.__fromStateTransition.indexOf(toStateName) < 0 && animator.targetName === 'style') { + animator.saveFinalToTarget(fromState, props); + } + } + + return fromState; + } + + function createEmphasisDefaultState(el, stateName, targetStates, state) { + var hasSelect = targetStates && indexOf(targetStates, 'select') >= 0; + var cloned = false; + + if (el instanceof Path) { + var store = getSavedStates(el); + var fromFill = hasSelect ? store.selectFill || store.normalFill : store.normalFill; + var fromStroke = hasSelect ? store.selectStroke || store.normalStroke : store.normalStroke; + + if (hasFillOrStroke(fromFill) || hasFillOrStroke(fromStroke)) { + state = state || {}; + var emphasisStyle = state.style || {}; + + if (!hasFillOrStroke(emphasisStyle.fill) && hasFillOrStroke(fromFill)) { + cloned = true; + state = extend({}, state); + emphasisStyle = extend({}, emphasisStyle); + emphasisStyle.fill = liftColor(fromFill); + } else if (!hasFillOrStroke(emphasisStyle.stroke) && hasFillOrStroke(fromStroke)) { + if (!cloned) { + state = extend({}, state); + emphasisStyle = extend({}, emphasisStyle); + } + + emphasisStyle.stroke = liftColor(fromStroke); + } + + state.style = emphasisStyle; + } + } + + if (state) { + if (state.z2 == null) { + if (!cloned) { + state = extend({}, state); + } + + var z2EmphasisLift = el.z2EmphasisLift; + state.z2 = el.z2 + (z2EmphasisLift != null ? z2EmphasisLift : Z2_EMPHASIS_LIFT); + } + } + + return state; + } + + function createSelectDefaultState(el, stateName, state) { + if (state) { + if (state.z2 == null) { + state = extend({}, state); + var z2SelectLift = el.z2SelectLift; + state.z2 = el.z2 + (z2SelectLift != null ? z2SelectLift : Z2_SELECT_LIFT); + } + } + + return state; + } + + function createBlurDefaultState(el, stateName, state) { + var hasBlur = indexOf(el.currentStates, stateName) >= 0; + var currentOpacity = el.style.opacity; + var fromState = !hasBlur ? getFromStateStyle(el, ['opacity'], stateName, { + opacity: 1 + }) : null; + state = state || {}; + var blurStyle = state.style || {}; + + if (blurStyle.opacity == null) { + state = extend({}, state); + blurStyle = extend({ + opacity: hasBlur ? currentOpacity : fromState.opacity * 0.1 + }, blurStyle); + state.style = blurStyle; + } + + return state; + } + + function elementStateProxy(stateName, targetStates) { + var state = this.states[stateName]; + + if (this.style) { + if (stateName === 'emphasis') { + return createEmphasisDefaultState(this, stateName, targetStates, state); + } else if (stateName === 'blur') { + return createBlurDefaultState(this, stateName, state); + } else if (stateName === 'select') { + return createSelectDefaultState(this, stateName, state); + } + } + + return state; + } + + function setDefaultStateProxy(el) { + el.stateProxy = elementStateProxy; + var textContent = el.getTextContent(); + var textGuide = el.getTextGuideLine(); + + if (textContent) { + textContent.stateProxy = elementStateProxy; + } + + if (textGuide) { + textGuide.stateProxy = elementStateProxy; + } + } + function enterEmphasisWhenMouseOver(el, e) { + !shouldSilent(el, e) && !el.__highByOuter && traverseUpdateState(el, singleEnterEmphasis); + } + function leaveEmphasisWhenMouseOut(el, e) { + !shouldSilent(el, e) && !el.__highByOuter && traverseUpdateState(el, singleLeaveEmphasis); + } + function enterEmphasis(el, highlightDigit) { + el.__highByOuter |= 1 << (highlightDigit || 0); + traverseUpdateState(el, singleEnterEmphasis); + } + function leaveEmphasis(el, highlightDigit) { + !(el.__highByOuter &= ~(1 << (highlightDigit || 0))) && traverseUpdateState(el, singleLeaveEmphasis); + } + function enterBlur(el) { + traverseUpdateState(el, singleEnterBlur); + } + function leaveBlur(el) { + traverseUpdateState(el, singleLeaveBlur); + } + function enterSelect(el) { + traverseUpdateState(el, singleEnterSelect); + } + function leaveSelect(el) { + traverseUpdateState(el, singleLeaveSelect); + } + + function shouldSilent(el, e) { + return el.__highDownSilentOnTouch && e.zrByTouch; + } + + function allLeaveBlur(api) { + var model = api.getModel(); + model.eachComponent(function (componentType, componentModel) { + var view = componentType === 'series' ? api.getViewOfSeriesModel(componentModel) : api.getViewOfComponentModel(componentModel); + view.group.traverse(function (child) { + singleLeaveBlur(child); + }); + }); + } + + function toggleSeriesBlurState(targetSeriesIndex, focus, blurScope, api, isBlur) { + var ecModel = api.getModel(); + blurScope = blurScope || 'coordinateSystem'; + + function leaveBlurOfIndices(data, dataIndices) { + for (var i = 0; i < dataIndices.length; i++) { + var itemEl = data.getItemGraphicEl(dataIndices[i]); + itemEl && leaveBlur(itemEl); + } + } + + if (!isBlur) { + allLeaveBlur(api); + return; + } + + if (targetSeriesIndex == null) { + return; + } + + if (!focus || focus === 'none') { + return; + } + + var targetSeriesModel = ecModel.getSeriesByIndex(targetSeriesIndex); + var targetCoordSys = targetSeriesModel.coordinateSystem; + + if (targetCoordSys && targetCoordSys.master) { + targetCoordSys = targetCoordSys.master; + } + + var blurredSeries = []; + ecModel.eachSeries(function (seriesModel) { + var sameSeries = targetSeriesModel === seriesModel; + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && coordSys.master) { + coordSys = coordSys.master; + } + + var sameCoordSys = coordSys && targetCoordSys ? coordSys === targetCoordSys : sameSeries; + + if (!(blurScope === 'series' && !sameSeries || blurScope === 'coordinateSystem' && !sameCoordSys || focus === 'series' && sameSeries)) { + var view = api.getViewOfSeriesModel(seriesModel); + view.group.traverse(function (child) { + singleEnterBlur(child); + }); + + if (isArrayLike(focus)) { + leaveBlurOfIndices(seriesModel.getData(), focus); + } else if (isObject(focus)) { + var dataTypes = keys(focus); + + for (var d = 0; d < dataTypes.length; d++) { + leaveBlurOfIndices(seriesModel.getData(dataTypes[d]), focus[dataTypes[d]]); + } + } + + blurredSeries.push(seriesModel); + } + }); + ecModel.eachComponent(function (componentType, componentModel) { + if (componentType === 'series') { + return; + } + + var view = api.getViewOfComponentModel(componentModel); + + if (view && view.blurSeries) { + view.blurSeries(blurredSeries, ecModel); + } + }); + } + function toggleSeriesBlurStateFromPayload(seriesModel, payload, api) { + if (!isHighDownPayload(payload)) { + return; + } + + var isHighlight = payload.type === HIGHLIGHT_ACTION_TYPE; + var seriesIndex = seriesModel.seriesIndex; + var data = seriesModel.getData(payload.dataType); + var dataIndex = queryDataIndex(data, payload); + dataIndex = (isArray(dataIndex) ? dataIndex[0] : dataIndex) || 0; + var el = data.getItemGraphicEl(dataIndex); + + if (!el) { + var count = data.count(); + var current = 0; + + while (!el && current < count) { + el = data.getItemGraphicEl(current++); + } + } + + if (el) { + var ecData = getECData(el); + toggleSeriesBlurState(seriesIndex, ecData.focus, ecData.blurScope, api, isHighlight); + } else { + var focus_1 = seriesModel.get(['emphasis', 'focus']); + var blurScope = seriesModel.get(['emphasis', 'blurScope']); + + if (focus_1 != null) { + toggleSeriesBlurState(seriesIndex, focus_1, blurScope, api, isHighlight); + } + } + } + function toggleSelectionFromPayload(seriesModel, payload, api) { + if (!isSelectChangePayload(payload)) { + return; + } + + var dataType = payload.dataType; + var data = seriesModel.getData(dataType); + var dataIndex = queryDataIndex(data, payload); + + if (!isArray(dataIndex)) { + dataIndex = [dataIndex]; + } + + seriesModel[payload.type === TOGGLE_SELECT_ACTION_TYPE ? 'toggleSelect' : payload.type === SELECT_ACTION_TYPE ? 'select' : 'unselect'](dataIndex, dataType); + } + function updateSeriesElementSelection(seriesModel) { + var allData = seriesModel.getAllData(); + each(allData, function (_a) { + var data = _a.data, + type = _a.type; + data.eachItemGraphicEl(function (el, idx) { + seriesModel.isSelected(idx, type) ? enterSelect(el) : leaveSelect(el); + }); + }); + } + function getAllSelectedIndices(ecModel) { + var ret = []; + ecModel.eachSeries(function (seriesModel) { + var allData = seriesModel.getAllData(); + each(allData, function (_a) { + var data = _a.data, + type = _a.type; + var dataIndices = seriesModel.getSelectedDataIndices(); + + if (dataIndices.length > 0) { + var item = { + dataIndex: dataIndices, + seriesIndex: seriesModel.seriesIndex + }; + + if (type != null) { + item.dataType = type; + } + + ret.push(item); + } + }); + }); + return ret; + } + function enableHoverEmphasis(el, focus, blurScope) { + setAsHighDownDispatcher(el, true); + traverseUpdateState(el, setDefaultStateProxy); + enableHoverFocus(el, focus, blurScope); + } + function enableHoverFocus(el, focus, blurScope) { + var ecData = getECData(el); + + if (focus != null) { + ecData.focus = focus; + ecData.blurScope = blurScope; + } else if (ecData.focus) { + ecData.focus = null; + } + } + var OTHER_STATES = ['emphasis', 'blur', 'select']; + var defaultStyleGetterMap = { + itemStyle: 'getItemStyle', + lineStyle: 'getLineStyle', + areaStyle: 'getAreaStyle' + }; + function setStatesStylesFromModel(el, itemModel, styleType, getter) { + styleType = styleType || 'itemStyle'; + + for (var i = 0; i < OTHER_STATES.length; i++) { + var stateName = OTHER_STATES[i]; + var model = itemModel.getModel([stateName, styleType]); + var state = el.ensureState(stateName); + state.style = getter ? getter(model) : model[defaultStyleGetterMap[styleType]](); + } + } + function setAsHighDownDispatcher(el, asDispatcher) { + var disable = asDispatcher === false; + var extendedEl = el; + + if (el.highDownSilentOnTouch) { + extendedEl.__highDownSilentOnTouch = el.highDownSilentOnTouch; + } + + if (!disable || extendedEl.__highDownDispatcher) { + extendedEl.__highByOuter = extendedEl.__highByOuter || 0; + extendedEl.__highDownDispatcher = !disable; + } + } + function isHighDownDispatcher(el) { + return !!(el && el.__highDownDispatcher); + } + function getHighlightDigit(highlightKey) { + var highlightDigit = _highlightKeyMap[highlightKey]; + + if (highlightDigit == null && _highlightNextDigit <= 32) { + highlightDigit = _highlightKeyMap[highlightKey] = _highlightNextDigit++; + } + + return highlightDigit; + } + function isSelectChangePayload(payload) { + var payloadType = payload.type; + return payloadType === SELECT_ACTION_TYPE || payloadType === UNSELECT_ACTION_TYPE || payloadType === TOGGLE_SELECT_ACTION_TYPE; + } + function isHighDownPayload(payload) { + var payloadType = payload.type; + return payloadType === HIGHLIGHT_ACTION_TYPE || payloadType === DOWNPLAY_ACTION_TYPE; + } + function savePathStates(el) { + var store = getSavedStates(el); + store.normalFill = el.style.fill; + store.normalStroke = el.style.stroke; + var selectState = el.states.select || {}; + store.selectFill = selectState.style && selectState.style.fill || null; + store.selectStroke = selectState.style && selectState.style.stroke || null; + } + + var CMD$2 = PathProxy.CMD; + var points = [[], [], []]; + var mathSqrt$2 = Math.sqrt; + var mathAtan2 = Math.atan2; + function transformPath(path, m) { + var data = path.data; + var len = path.len(); + var cmd; + var nPoint; + var i; + var j; + var k; + var p; + var M = CMD$2.M; + var C = CMD$2.C; + var L = CMD$2.L; + var R = CMD$2.R; + var A = CMD$2.A; + var Q = CMD$2.Q; + for (i = 0, j = 0; i < len;) { + cmd = data[i++]; + j = i; + nPoint = 0; + switch (cmd) { + case M: + nPoint = 1; + break; + case L: + nPoint = 1; + break; + case C: + nPoint = 3; + break; + case Q: + nPoint = 2; + break; + case A: + var x = m[4]; + var y = m[5]; + var sx = mathSqrt$2(m[0] * m[0] + m[1] * m[1]); + var sy = mathSqrt$2(m[2] * m[2] + m[3] * m[3]); + var angle = mathAtan2(-m[1] / sy, m[0] / sx); + data[i] *= sx; + data[i++] += x; + data[i] *= sy; + data[i++] += y; + data[i++] *= sx; + data[i++] *= sy; + data[i++] += angle; + data[i++] += angle; + i += 2; + j = i; + break; + case R: + p[0] = data[i++]; + p[1] = data[i++]; + applyTransform(p, p, m); + data[j++] = p[0]; + data[j++] = p[1]; + p[0] += data[i++]; + p[1] += data[i++]; + applyTransform(p, p, m); + data[j++] = p[0]; + data[j++] = p[1]; + } + for (k = 0; k < nPoint; k++) { + var p_1 = points[k]; + p_1[0] = data[i++]; + p_1[1] = data[i++]; + applyTransform(p_1, p_1, m); + data[j++] = p_1[0]; + data[j++] = p_1[1]; + } + } + path.increaseVersion(); + } + + var mathSqrt$3 = Math.sqrt; + var mathSin$2 = Math.sin; + var mathCos$2 = Math.cos; + var PI$1 = Math.PI; + function vMag(v) { + return Math.sqrt(v[0] * v[0] + v[1] * v[1]); + } + function vRatio(u, v) { + return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v)); + } + function vAngle(u, v) { + return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) + * Math.acos(vRatio(u, v)); + } + function processArc(x1, y1, x2, y2, fa, fs, rx, ry, psiDeg, cmd, path) { + var psi = psiDeg * (PI$1 / 180.0); + var xp = mathCos$2(psi) * (x1 - x2) / 2.0 + + mathSin$2(psi) * (y1 - y2) / 2.0; + var yp = -1 * mathSin$2(psi) * (x1 - x2) / 2.0 + + mathCos$2(psi) * (y1 - y2) / 2.0; + var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry); + if (lambda > 1) { + rx *= mathSqrt$3(lambda); + ry *= mathSqrt$3(lambda); + } + var f = (fa === fs ? -1 : 1) + * mathSqrt$3((((rx * rx) * (ry * ry)) + - ((rx * rx) * (yp * yp)) + - ((ry * ry) * (xp * xp))) / ((rx * rx) * (yp * yp) + + (ry * ry) * (xp * xp))) || 0; + var cxp = f * rx * yp / ry; + var cyp = f * -ry * xp / rx; + var cx = (x1 + x2) / 2.0 + + mathCos$2(psi) * cxp + - mathSin$2(psi) * cyp; + var cy = (y1 + y2) / 2.0 + + mathSin$2(psi) * cxp + + mathCos$2(psi) * cyp; + var theta = vAngle([1, 0], [(xp - cxp) / rx, (yp - cyp) / ry]); + var u = [(xp - cxp) / rx, (yp - cyp) / ry]; + var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry]; + var dTheta = vAngle(u, v); + if (vRatio(u, v) <= -1) { + dTheta = PI$1; + } + if (vRatio(u, v) >= 1) { + dTheta = 0; + } + if (dTheta < 0) { + var n = Math.round(dTheta / PI$1 * 1e6) / 1e6; + dTheta = PI$1 * 2 + (n % 2) * PI$1; + } + path.addData(cmd, cx, cy, rx, ry, theta, dTheta, psi, fs); + } + var commandReg = /([mlvhzcqtsa])([^mlvhzcqtsa]*)/ig; + var numberReg = /-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g; + function createPathProxyFromString(data) { + var path = new PathProxy(); + if (!data) { + return path; + } + var cpx = 0; + var cpy = 0; + var subpathX = cpx; + var subpathY = cpy; + var prevCmd; + var CMD = PathProxy.CMD; + var cmdList = data.match(commandReg); + if (!cmdList) { + return path; + } + for (var l = 0; l < cmdList.length; l++) { + var cmdText = cmdList[l]; + var cmdStr = cmdText.charAt(0); + var cmd = void 0; + var p = cmdText.match(numberReg) || []; + var pLen = p.length; + for (var i = 0; i < pLen; i++) { + p[i] = parseFloat(p[i]); + } + var off = 0; + while (off < pLen) { + var ctlPtx = void 0; + var ctlPty = void 0; + var rx = void 0; + var ry = void 0; + var psi = void 0; + var fa = void 0; + var fs = void 0; + var x1 = cpx; + var y1 = cpy; + var len = void 0; + var pathData = void 0; + switch (cmdStr) { + case 'l': + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'L': + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'm': + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.M; + path.addData(cmd, cpx, cpy); + subpathX = cpx; + subpathY = cpy; + cmdStr = 'l'; + break; + case 'M': + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.M; + path.addData(cmd, cpx, cpy); + subpathX = cpx; + subpathY = cpy; + cmdStr = 'L'; + break; + case 'h': + cpx += p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'H': + cpx = p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'v': + cpy += p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'V': + cpy = p[off++]; + cmd = CMD.L; + path.addData(cmd, cpx, cpy); + break; + case 'C': + cmd = CMD.C; + path.addData(cmd, p[off++], p[off++], p[off++], p[off++], p[off++], p[off++]); + cpx = p[off - 2]; + cpy = p[off - 1]; + break; + case 'c': + cmd = CMD.C; + path.addData(cmd, p[off++] + cpx, p[off++] + cpy, p[off++] + cpx, p[off++] + cpy, p[off++] + cpx, p[off++] + cpy); + cpx += p[off - 2]; + cpy += p[off - 1]; + break; + case 'S': + ctlPtx = cpx; + ctlPty = cpy; + len = path.len(); + pathData = path.data; + if (prevCmd === CMD.C) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cmd = CMD.C; + x1 = p[off++]; + y1 = p[off++]; + cpx = p[off++]; + cpy = p[off++]; + path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy); + break; + case 's': + ctlPtx = cpx; + ctlPty = cpy; + len = path.len(); + pathData = path.data; + if (prevCmd === CMD.C) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cmd = CMD.C; + x1 = cpx + p[off++]; + y1 = cpy + p[off++]; + cpx += p[off++]; + cpy += p[off++]; + path.addData(cmd, ctlPtx, ctlPty, x1, y1, cpx, cpy); + break; + case 'Q': + x1 = p[off++]; + y1 = p[off++]; + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.Q; + path.addData(cmd, x1, y1, cpx, cpy); + break; + case 'q': + x1 = p[off++] + cpx; + y1 = p[off++] + cpy; + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.Q; + path.addData(cmd, x1, y1, cpx, cpy); + break; + case 'T': + ctlPtx = cpx; + ctlPty = cpy; + len = path.len(); + pathData = path.data; + if (prevCmd === CMD.Q) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.Q; + path.addData(cmd, ctlPtx, ctlPty, cpx, cpy); + break; + case 't': + ctlPtx = cpx; + ctlPty = cpy; + len = path.len(); + pathData = path.data; + if (prevCmd === CMD.Q) { + ctlPtx += cpx - pathData[len - 4]; + ctlPty += cpy - pathData[len - 3]; + } + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.Q; + path.addData(cmd, ctlPtx, ctlPty, cpx, cpy); + break; + case 'A': + rx = p[off++]; + ry = p[off++]; + psi = p[off++]; + fa = p[off++]; + fs = p[off++]; + x1 = cpx, y1 = cpy; + cpx = p[off++]; + cpy = p[off++]; + cmd = CMD.A; + processArc(x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path); + break; + case 'a': + rx = p[off++]; + ry = p[off++]; + psi = p[off++]; + fa = p[off++]; + fs = p[off++]; + x1 = cpx, y1 = cpy; + cpx += p[off++]; + cpy += p[off++]; + cmd = CMD.A; + processArc(x1, y1, cpx, cpy, fa, fs, rx, ry, psi, cmd, path); + break; + } + } + if (cmdStr === 'z' || cmdStr === 'Z') { + cmd = CMD.Z; + path.addData(cmd); + cpx = subpathX; + cpy = subpathY; + } + prevCmd = cmd; + } + path.toStatic(); + return path; + } + var SVGPath = (function (_super) { + __extends(SVGPath, _super); + function SVGPath() { + return _super !== null && _super.apply(this, arguments) || this; + } + SVGPath.prototype.applyTransform = function (m) { }; + return SVGPath; + }(Path)); + function isPathProxy(path) { + return path.setData != null; + } + function createPathOptions(str, opts) { + var pathProxy = createPathProxyFromString(str); + var innerOpts = extend({}, opts); + innerOpts.buildPath = function (path) { + if (isPathProxy(path)) { + path.setData(pathProxy.data); + var ctx = path.getContext(); + if (ctx) { + path.rebuildPath(ctx, 1); + } + } + else { + var ctx = path; + pathProxy.rebuildPath(ctx, 1); + } + }; + innerOpts.applyTransform = function (m) { + transformPath(pathProxy, m); + this.dirtyShape(); + }; + return innerOpts; + } + function createFromString(str, opts) { + return new SVGPath(createPathOptions(str, opts)); + } + function extendFromString(str, defaultOpts) { + var innerOpts = createPathOptions(str, defaultOpts); + var Sub = (function (_super) { + __extends(Sub, _super); + function Sub(opts) { + var _this = _super.call(this, opts) || this; + _this.applyTransform = innerOpts.applyTransform; + _this.buildPath = innerOpts.buildPath; + return _this; + } + return Sub; + }(SVGPath)); + return Sub; + } + function mergePath(pathEls, opts) { + var pathList = []; + var len = pathEls.length; + for (var i = 0; i < len; i++) { + var pathEl = pathEls[i]; + if (!pathEl.path) { + pathEl.createPathProxy(); + } + if (pathEl.shapeChanged()) { + pathEl.buildPath(pathEl.path, pathEl.shape, true); + } + pathList.push(pathEl.path); + } + var pathBundle = new Path(opts); + pathBundle.createPathProxy(); + pathBundle.buildPath = function (path) { + if (isPathProxy(path)) { + path.appendPath(pathList); + var ctx = path.getContext(); + if (ctx) { + path.rebuildPath(ctx, 1); + } + } + }; + return pathBundle; + } + + var CircleShape = (function () { + function CircleShape() { + this.cx = 0; + this.cy = 0; + this.r = 0; + } + return CircleShape; + }()); + var Circle = (function (_super) { + __extends(Circle, _super); + function Circle(opts) { + return _super.call(this, opts) || this; + } + Circle.prototype.getDefaultShape = function () { + return new CircleShape(); + }; + Circle.prototype.buildPath = function (ctx, shape, inBundle) { + if (inBundle) { + ctx.moveTo(shape.cx + shape.r, shape.cy); + } + ctx.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2); + }; + return Circle; + }(Path)); + Circle.prototype.type = 'circle'; + + var EllipseShape = (function () { + function EllipseShape() { + this.cx = 0; + this.cy = 0; + this.rx = 0; + this.ry = 0; + } + return EllipseShape; + }()); + var Ellipse = (function (_super) { + __extends(Ellipse, _super); + function Ellipse(opts) { + return _super.call(this, opts) || this; + } + Ellipse.prototype.getDefaultShape = function () { + return new EllipseShape(); + }; + Ellipse.prototype.buildPath = function (ctx, shape) { + var k = 0.5522848; + var x = shape.cx; + var y = shape.cy; + var a = shape.rx; + var b = shape.ry; + var ox = a * k; + var oy = b * k; + ctx.moveTo(x - a, y); + ctx.bezierCurveTo(x - a, y - oy, x - ox, y - b, x, y - b); + ctx.bezierCurveTo(x + ox, y - b, x + a, y - oy, x + a, y); + ctx.bezierCurveTo(x + a, y + oy, x + ox, y + b, x, y + b); + ctx.bezierCurveTo(x - ox, y + b, x - a, y + oy, x - a, y); + ctx.closePath(); + }; + return Ellipse; + }(Path)); + Ellipse.prototype.type = 'ellipse'; + + var PI$2 = Math.PI; + var PI2$5 = PI$2 * 2; + var mathSin$3 = Math.sin; + var mathCos$3 = Math.cos; + var mathACos = Math.acos; + var mathATan2 = Math.atan2; + var mathAbs$1 = Math.abs; + var mathSqrt$4 = Math.sqrt; + var mathMax$3 = Math.max; + var mathMin$3 = Math.min; + var e = 1e-4; + function intersect(x0, y0, x1, y1, x2, y2, x3, y3) { + var x10 = x1 - x0; + var y10 = y1 - y0; + var x32 = x3 - x2; + var y32 = y3 - y2; + var t = y32 * x10 - x32 * y10; + if (t * t < e) { + return; + } + t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / t; + return [x0 + t * x10, y0 + t * y10]; + } + function computeCornerTangents(x0, y0, x1, y1, radius, cr, clockwise) { + var x01 = x0 - x1; + var y01 = y0 - y1; + var lo = (clockwise ? cr : -cr) / mathSqrt$4(x01 * x01 + y01 * y01); + var ox = lo * y01; + var oy = -lo * x01; + var x11 = x0 + ox; + var y11 = y0 + oy; + var x10 = x1 + ox; + var y10 = y1 + oy; + var x00 = (x11 + x10) / 2; + var y00 = (y11 + y10) / 2; + var dx = x10 - x11; + var dy = y10 - y11; + var d2 = dx * dx + dy * dy; + var r = radius - cr; + var s = x11 * y10 - x10 * y11; + var d = (dy < 0 ? -1 : 1) * mathSqrt$4(mathMax$3(0, r * r * d2 - s * s)); + var cx0 = (s * dy - dx * d) / d2; + var cy0 = (-s * dx - dy * d) / d2; + var cx1 = (s * dy + dx * d) / d2; + var cy1 = (-s * dx + dy * d) / d2; + var dx0 = cx0 - x00; + var dy0 = cy0 - y00; + var dx1 = cx1 - x00; + var dy1 = cy1 - y00; + if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) { + cx0 = cx1; + cy0 = cy1; + } + return { + cx: cx0, + cy: cy0, + x01: -ox, + y01: -oy, + x11: cx0 * (radius / r - 1), + y11: cy0 * (radius / r - 1) + }; + } + function buildPath$1(ctx, shape) { + var radius = mathMax$3(shape.r, 0); + var innerRadius = mathMax$3(shape.r0 || 0, 0); + var hasRadius = radius > 0; + var hasInnerRadius = innerRadius > 0; + if (!hasRadius && !hasInnerRadius) { + return; + } + if (!hasRadius) { + radius = innerRadius; + innerRadius = 0; + } + if (innerRadius > radius) { + var tmp = radius; + radius = innerRadius; + innerRadius = tmp; + } + var clockwise = !!shape.clockwise; + var startAngle = shape.startAngle; + var endAngle = shape.endAngle; + var tmpAngles = [startAngle, endAngle]; + normalizeArcAngles(tmpAngles, !clockwise); + var arc = mathAbs$1(tmpAngles[0] - tmpAngles[1]); + var x = shape.cx; + var y = shape.cy; + var cornerRadius = shape.cornerRadius || 0; + var innerCornerRadius = shape.innerCornerRadius || 0; + if (!(radius > e)) { + ctx.moveTo(x, y); + } + else if (arc > PI2$5 - e) { + ctx.moveTo(x + radius * mathCos$3(startAngle), y + radius * mathSin$3(startAngle)); + ctx.arc(x, y, radius, startAngle, endAngle, !clockwise); + if (innerRadius > e) { + ctx.moveTo(x + innerRadius * mathCos$3(endAngle), y + innerRadius * mathSin$3(endAngle)); + ctx.arc(x, y, innerRadius, endAngle, startAngle, clockwise); + } + } + else { + var halfRd = mathAbs$1(radius - innerRadius) / 2; + var cr = mathMin$3(halfRd, cornerRadius); + var icr = mathMin$3(halfRd, innerCornerRadius); + var cr0 = icr; + var cr1 = cr; + var xrs = radius * mathCos$3(startAngle); + var yrs = radius * mathSin$3(startAngle); + var xire = innerRadius * mathCos$3(endAngle); + var yire = innerRadius * mathSin$3(endAngle); + var xre = void 0; + var yre = void 0; + var xirs = void 0; + var yirs = void 0; + if (cr > e || icr > e) { + xre = radius * mathCos$3(endAngle); + yre = radius * mathSin$3(endAngle); + xirs = innerRadius * mathCos$3(startAngle); + yirs = innerRadius * mathSin$3(startAngle); + if (arc < PI$2) { + var it_1 = intersect(xrs, yrs, xirs, yirs, xre, yre, xire, yire); + if (it_1) { + var x0 = xrs - it_1[0]; + var y0 = yrs - it_1[1]; + var x1 = xre - it_1[0]; + var y1 = yre - it_1[1]; + var a = 1 / mathSin$3(mathACos((x0 * x1 + y0 * y1) / (mathSqrt$4(x0 * x0 + y0 * y0) * mathSqrt$4(x1 * x1 + y1 * y1))) / 2); + var b = mathSqrt$4(it_1[0] * it_1[0] + it_1[1] * it_1[1]); + cr0 = mathMin$3(icr, (innerRadius - b) / (a - 1)); + cr1 = mathMin$3(cr, (radius - b) / (a + 1)); + } + } + } + if (!(arc > e)) { + ctx.moveTo(x + xrs, y + yrs); + } + else if (cr1 > e) { + var ct0 = computeCornerTangents(xirs, yirs, xrs, yrs, radius, cr1, clockwise); + var ct1 = computeCornerTangents(xre, yre, xire, yire, radius, cr1, clockwise); + ctx.moveTo(x + ct0.cx + ct0.x01, y + ct0.cy + ct0.y01); + if (cr1 < cr) { + ctx.arc(x + ct0.cx, y + ct0.cy, cr1, mathATan2(ct0.y01, ct0.x01), mathATan2(ct1.y01, ct1.x01), !clockwise); + } + else { + ctx.arc(x + ct0.cx, y + ct0.cy, cr1, mathATan2(ct0.y01, ct0.x01), mathATan2(ct0.y11, ct0.x11), !clockwise); + ctx.arc(x, y, radius, mathATan2(ct0.cy + ct0.y11, ct0.cx + ct0.x11), mathATan2(ct1.cy + ct1.y11, ct1.cx + ct1.x11), !clockwise); + ctx.arc(x + ct1.cx, y + ct1.cy, cr1, mathATan2(ct1.y11, ct1.x11), mathATan2(ct1.y01, ct1.x01), !clockwise); + } + } + else { + ctx.moveTo(x + xrs, y + yrs); + ctx.arc(x, y, radius, startAngle, endAngle, !clockwise); + } + if (!(innerRadius > e) || !(arc > e)) { + ctx.lineTo(x + xire, y + yire); + } + else if (cr0 > e) { + var ct0 = computeCornerTangents(xire, yire, xre, yre, innerRadius, -cr0, clockwise); + var ct1 = computeCornerTangents(xrs, yrs, xirs, yirs, innerRadius, -cr0, clockwise); + ctx.lineTo(x + ct0.cx + ct0.x01, y + ct0.cy + ct0.y01); + if (cr0 < icr) { + ctx.arc(x + ct0.cx, y + ct0.cy, cr0, mathATan2(ct0.y01, ct0.x01), mathATan2(ct1.y01, ct1.x01), !clockwise); + } + else { + ctx.arc(x + ct0.cx, y + ct0.cy, cr0, mathATan2(ct0.y01, ct0.x01), mathATan2(ct0.y11, ct0.x11), !clockwise); + ctx.arc(x, y, innerRadius, mathATan2(ct0.cy + ct0.y11, ct0.cx + ct0.x11), mathATan2(ct1.cy + ct1.y11, ct1.cx + ct1.x11), clockwise); + ctx.arc(x + ct1.cx, y + ct1.cy, cr0, mathATan2(ct1.y11, ct1.x11), mathATan2(ct1.y01, ct1.x01), !clockwise); + } + } + else { + ctx.lineTo(x + xire, y + yire); + ctx.arc(x, y, innerRadius, endAngle, startAngle, clockwise); + } + } + ctx.closePath(); + } + + var SectorShape = (function () { + function SectorShape() { + this.cx = 0; + this.cy = 0; + this.r0 = 0; + this.r = 0; + this.startAngle = 0; + this.endAngle = Math.PI * 2; + this.clockwise = true; + this.cornerRadius = 0; + this.innerCornerRadius = 0; + } + return SectorShape; + }()); + var Sector = (function (_super) { + __extends(Sector, _super); + function Sector(opts) { + return _super.call(this, opts) || this; + } + Sector.prototype.getDefaultShape = function () { + return new SectorShape(); + }; + Sector.prototype.buildPath = function (ctx, shape) { + buildPath$1(ctx, shape); + }; + Sector.prototype.isZeroArea = function () { + return this.shape.startAngle === this.shape.endAngle + || this.shape.r === this.shape.r0; + }; + return Sector; + }(Path)); + Sector.prototype.type = 'sector'; + + var RingShape = (function () { + function RingShape() { + this.cx = 0; + this.cy = 0; + this.r = 0; + this.r0 = 0; + } + return RingShape; + }()); + var Ring = (function (_super) { + __extends(Ring, _super); + function Ring(opts) { + return _super.call(this, opts) || this; + } + Ring.prototype.getDefaultShape = function () { + return new RingShape(); + }; + Ring.prototype.buildPath = function (ctx, shape) { + var x = shape.cx; + var y = shape.cy; + var PI2 = Math.PI * 2; + ctx.moveTo(x + shape.r, y); + ctx.arc(x, y, shape.r, 0, PI2, false); + ctx.moveTo(x + shape.r0, y); + ctx.arc(x, y, shape.r0, 0, PI2, true); + }; + return Ring; + }(Path)); + Ring.prototype.type = 'ring'; + + function interpolate(p0, p1, p2, p3, t, t2, t3) { + var v0 = (p2 - p0) * 0.5; + var v1 = (p3 - p1) * 0.5; + return (2 * (p1 - p2) + v0 + v1) * t3 + + (-3 * (p1 - p2) - 2 * v0 - v1) * t2 + + v0 * t + p1; + } + function smoothSpline(points, isLoop) { + var len = points.length; + var ret = []; + var distance$1 = 0; + for (var i = 1; i < len; i++) { + distance$1 += distance(points[i - 1], points[i]); + } + var segs = distance$1 / 2; + segs = segs < len ? len : segs; + for (var i = 0; i < segs; i++) { + var pos = i / (segs - 1) * (isLoop ? len : len - 1); + var idx = Math.floor(pos); + var w = pos - idx; + var p0 = void 0; + var p1 = points[idx % len]; + var p2 = void 0; + var p3 = void 0; + if (!isLoop) { + p0 = points[idx === 0 ? idx : idx - 1]; + p2 = points[idx > len - 2 ? len - 1 : idx + 1]; + p3 = points[idx > len - 3 ? len - 1 : idx + 2]; + } + else { + p0 = points[(idx - 1 + len) % len]; + p2 = points[(idx + 1) % len]; + p3 = points[(idx + 2) % len]; + } + var w2 = w * w; + var w3 = w * w2; + ret.push([ + interpolate(p0[0], p1[0], p2[0], p3[0], w, w2, w3), + interpolate(p0[1], p1[1], p2[1], p3[1], w, w2, w3) + ]); + } + return ret; + } + + function smoothBezier(points, smooth, isLoop, constraint) { + var cps = []; + var v = []; + var v1 = []; + var v2 = []; + var prevPoint; + var nextPoint; + var min$1; + var max$1; + if (constraint) { + min$1 = [Infinity, Infinity]; + max$1 = [-Infinity, -Infinity]; + for (var i = 0, len = points.length; i < len; i++) { + min(min$1, min$1, points[i]); + max(max$1, max$1, points[i]); + } + min(min$1, min$1, constraint[0]); + max(max$1, max$1, constraint[1]); + } + for (var i = 0, len = points.length; i < len; i++) { + var point = points[i]; + if (isLoop) { + prevPoint = points[i ? i - 1 : len - 1]; + nextPoint = points[(i + 1) % len]; + } + else { + if (i === 0 || i === len - 1) { + cps.push(clone$1(points[i])); + continue; + } + else { + prevPoint = points[i - 1]; + nextPoint = points[i + 1]; + } + } + sub(v, nextPoint, prevPoint); + scale(v, v, smooth); + var d0 = distance(point, prevPoint); + var d1 = distance(point, nextPoint); + var sum = d0 + d1; + if (sum !== 0) { + d0 /= sum; + d1 /= sum; + } + scale(v1, v, -d0); + scale(v2, v, d1); + var cp0 = add([], point, v1); + var cp1 = add([], point, v2); + if (constraint) { + max(cp0, cp0, min$1); + min(cp0, cp0, max$1); + max(cp1, cp1, min$1); + min(cp1, cp1, max$1); + } + cps.push(cp0); + cps.push(cp1); + } + if (isLoop) { + cps.push(cps.shift()); + } + return cps; + } + + function buildPath$2(ctx, shape, closePath) { + var smooth = shape.smooth; + var points = shape.points; + if (points && points.length >= 2) { + if (smooth && smooth !== 'spline') { + var controlPoints = smoothBezier(points, smooth, closePath, shape.smoothConstraint); + ctx.moveTo(points[0][0], points[0][1]); + var len = points.length; + for (var i = 0; i < (closePath ? len : len - 1); i++) { + var cp1 = controlPoints[i * 2]; + var cp2 = controlPoints[i * 2 + 1]; + var p = points[(i + 1) % len]; + ctx.bezierCurveTo(cp1[0], cp1[1], cp2[0], cp2[1], p[0], p[1]); + } + } + else { + if (smooth === 'spline') { + points = smoothSpline(points, closePath); + } + ctx.moveTo(points[0][0], points[0][1]); + for (var i = 1, l = points.length; i < l; i++) { + ctx.lineTo(points[i][0], points[i][1]); + } + } + closePath && ctx.closePath(); + } + } + + var PolygonShape = (function () { + function PolygonShape() { + this.points = null; + this.smooth = 0; + this.smoothConstraint = null; + } + return PolygonShape; + }()); + var Polygon = (function (_super) { + __extends(Polygon, _super); + function Polygon(opts) { + return _super.call(this, opts) || this; + } + Polygon.prototype.getDefaultShape = function () { + return new PolygonShape(); + }; + Polygon.prototype.buildPath = function (ctx, shape) { + buildPath$2(ctx, shape, true); + }; + return Polygon; + }(Path)); + Polygon.prototype.type = 'polygon'; + + var PolylineShape = (function () { + function PolylineShape() { + this.points = null; + this.percent = 1; + this.smooth = 0; + this.smoothConstraint = null; + } + return PolylineShape; + }()); + var Polyline = (function (_super) { + __extends(Polyline, _super); + function Polyline(opts) { + return _super.call(this, opts) || this; + } + Polyline.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + Polyline.prototype.getDefaultShape = function () { + return new PolylineShape(); + }; + Polyline.prototype.buildPath = function (ctx, shape) { + buildPath$2(ctx, shape, false); + }; + return Polyline; + }(Path)); + Polyline.prototype.type = 'polyline'; + + var subPixelOptimizeOutputShape$1 = {}; + var LineShape = (function () { + function LineShape() { + this.x1 = 0; + this.y1 = 0; + this.x2 = 0; + this.y2 = 0; + this.percent = 1; + } + return LineShape; + }()); + var Line = (function (_super) { + __extends(Line, _super); + function Line(opts) { + return _super.call(this, opts) || this; + } + Line.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + Line.prototype.getDefaultShape = function () { + return new LineShape(); + }; + Line.prototype.buildPath = function (ctx, shape) { + var x1; + var y1; + var x2; + var y2; + if (this.subPixelOptimize) { + var optimizedShape = subPixelOptimizeLine(subPixelOptimizeOutputShape$1, shape, this.style); + x1 = optimizedShape.x1; + y1 = optimizedShape.y1; + x2 = optimizedShape.x2; + y2 = optimizedShape.y2; + } + else { + x1 = shape.x1; + y1 = shape.y1; + x2 = shape.x2; + y2 = shape.y2; + } + var percent = shape.percent; + if (percent === 0) { + return; + } + ctx.moveTo(x1, y1); + if (percent < 1) { + x2 = x1 * (1 - percent) + x2 * percent; + y2 = y1 * (1 - percent) + y2 * percent; + } + ctx.lineTo(x2, y2); + }; + Line.prototype.pointAt = function (p) { + var shape = this.shape; + return [ + shape.x1 * (1 - p) + shape.x2 * p, + shape.y1 * (1 - p) + shape.y2 * p + ]; + }; + return Line; + }(Path)); + Line.prototype.type = 'line'; + + var out = []; + var BezierCurveShape = (function () { + function BezierCurveShape() { + this.x1 = 0; + this.y1 = 0; + this.x2 = 0; + this.y2 = 0; + this.cpx1 = 0; + this.cpy1 = 0; + this.percent = 1; + } + return BezierCurveShape; + }()); + function someVectorAt(shape, t, isTangent) { + var cpx2 = shape.cpx2; + var cpy2 = shape.cpy2; + if (cpx2 === null || cpy2 === null) { + return [ + (isTangent ? cubicDerivativeAt : cubicAt)(shape.x1, shape.cpx1, shape.cpx2, shape.x2, t), + (isTangent ? cubicDerivativeAt : cubicAt)(shape.y1, shape.cpy1, shape.cpy2, shape.y2, t) + ]; + } + else { + return [ + (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.x1, shape.cpx1, shape.x2, t), + (isTangent ? quadraticDerivativeAt : quadraticAt)(shape.y1, shape.cpy1, shape.y2, t) + ]; + } + } + var BezierCurve = (function (_super) { + __extends(BezierCurve, _super); + function BezierCurve(opts) { + return _super.call(this, opts) || this; + } + BezierCurve.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + BezierCurve.prototype.getDefaultShape = function () { + return new BezierCurveShape(); + }; + BezierCurve.prototype.buildPath = function (ctx, shape) { + var x1 = shape.x1; + var y1 = shape.y1; + var x2 = shape.x2; + var y2 = shape.y2; + var cpx1 = shape.cpx1; + var cpy1 = shape.cpy1; + var cpx2 = shape.cpx2; + var cpy2 = shape.cpy2; + var percent = shape.percent; + if (percent === 0) { + return; + } + ctx.moveTo(x1, y1); + if (cpx2 == null || cpy2 == null) { + if (percent < 1) { + quadraticSubdivide(x1, cpx1, x2, percent, out); + cpx1 = out[1]; + x2 = out[2]; + quadraticSubdivide(y1, cpy1, y2, percent, out); + cpy1 = out[1]; + y2 = out[2]; + } + ctx.quadraticCurveTo(cpx1, cpy1, x2, y2); + } + else { + if (percent < 1) { + cubicSubdivide(x1, cpx1, cpx2, x2, percent, out); + cpx1 = out[1]; + cpx2 = out[2]; + x2 = out[3]; + cubicSubdivide(y1, cpy1, cpy2, y2, percent, out); + cpy1 = out[1]; + cpy2 = out[2]; + y2 = out[3]; + } + ctx.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x2, y2); + } + }; + BezierCurve.prototype.pointAt = function (t) { + return someVectorAt(this.shape, t, false); + }; + BezierCurve.prototype.tangentAt = function (t) { + var p = someVectorAt(this.shape, t, true); + return normalize(p, p); + }; + return BezierCurve; + }(Path)); + BezierCurve.prototype.type = 'bezier-curve'; + + var ArcShape = (function () { + function ArcShape() { + this.cx = 0; + this.cy = 0; + this.r = 0; + this.startAngle = 0; + this.endAngle = Math.PI * 2; + this.clockwise = true; + } + return ArcShape; + }()); + var Arc = (function (_super) { + __extends(Arc, _super); + function Arc(opts) { + return _super.call(this, opts) || this; + } + Arc.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + Arc.prototype.getDefaultShape = function () { + return new ArcShape(); + }; + Arc.prototype.buildPath = function (ctx, shape) { + var x = shape.cx; + var y = shape.cy; + var r = Math.max(shape.r, 0); + var startAngle = shape.startAngle; + var endAngle = shape.endAngle; + var clockwise = shape.clockwise; + var unitX = Math.cos(startAngle); + var unitY = Math.sin(startAngle); + ctx.moveTo(unitX * r + x, unitY * r + y); + ctx.arc(x, y, r, startAngle, endAngle, !clockwise); + }; + return Arc; + }(Path)); + Arc.prototype.type = 'arc'; + + var CompoundPath = (function (_super) { + __extends(CompoundPath, _super); + function CompoundPath() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.type = 'compound'; + return _this; + } + CompoundPath.prototype._updatePathDirty = function () { + var paths = this.shape.paths; + var dirtyPath = this.shapeChanged(); + for (var i = 0; i < paths.length; i++) { + dirtyPath = dirtyPath || paths[i].shapeChanged(); + } + if (dirtyPath) { + this.dirtyShape(); + } + }; + CompoundPath.prototype.beforeBrush = function () { + this._updatePathDirty(); + var paths = this.shape.paths || []; + var scale = this.getGlobalScale(); + for (var i = 0; i < paths.length; i++) { + if (!paths[i].path) { + paths[i].createPathProxy(); + } + paths[i].path.setScale(scale[0], scale[1], paths[i].segmentIgnoreThreshold); + } + }; + CompoundPath.prototype.buildPath = function (ctx, shape) { + var paths = shape.paths || []; + for (var i = 0; i < paths.length; i++) { + paths[i].buildPath(ctx, paths[i].shape, true); + } + }; + CompoundPath.prototype.afterBrush = function () { + var paths = this.shape.paths || []; + for (var i = 0; i < paths.length; i++) { + paths[i].pathUpdated(); + } + }; + CompoundPath.prototype.getBoundingRect = function () { + this._updatePathDirty.call(this); + return Path.prototype.getBoundingRect.call(this); + }; + return CompoundPath; + }(Path)); + + var Gradient = (function () { + function Gradient(colorStops) { + this.colorStops = colorStops || []; + } + Gradient.prototype.addColorStop = function (offset, color) { + this.colorStops.push({ + offset: offset, + color: color + }); + }; + return Gradient; + }()); + + var LinearGradient = (function (_super) { + __extends(LinearGradient, _super); + function LinearGradient(x, y, x2, y2, colorStops, globalCoord) { + var _this = _super.call(this, colorStops) || this; + _this.x = x == null ? 0 : x; + _this.y = y == null ? 0 : y; + _this.x2 = x2 == null ? 1 : x2; + _this.y2 = y2 == null ? 0 : y2; + _this.type = 'linear'; + _this.global = globalCoord || false; + return _this; + } + return LinearGradient; + }(Gradient)); + + var RadialGradient = (function (_super) { + __extends(RadialGradient, _super); + function RadialGradient(x, y, r, colorStops, globalCoord) { + var _this = _super.call(this, colorStops) || this; + _this.x = x == null ? 0.5 : x; + _this.y = y == null ? 0.5 : y; + _this.r = r == null ? 0.5 : r; + _this.type = 'radial'; + _this.global = globalCoord || false; + return _this; + } + return RadialGradient; + }(Gradient)); + + var extent = [0, 0]; + var extent2 = [0, 0]; + var minTv$1 = new Point(); + var maxTv$1 = new Point(); + var OrientedBoundingRect = (function () { + function OrientedBoundingRect(rect, transform) { + this._corners = []; + this._axes = []; + this._origin = [0, 0]; + for (var i = 0; i < 4; i++) { + this._corners[i] = new Point(); + } + for (var i = 0; i < 2; i++) { + this._axes[i] = new Point(); + } + if (rect) { + this.fromBoundingRect(rect, transform); + } + } + OrientedBoundingRect.prototype.fromBoundingRect = function (rect, transform) { + var corners = this._corners; + var axes = this._axes; + var x = rect.x; + var y = rect.y; + var x2 = x + rect.width; + var y2 = y + rect.height; + corners[0].set(x, y); + corners[1].set(x2, y); + corners[2].set(x2, y2); + corners[3].set(x, y2); + if (transform) { + for (var i = 0; i < 4; i++) { + corners[i].transform(transform); + } + } + Point.sub(axes[0], corners[1], corners[0]); + Point.sub(axes[1], corners[3], corners[0]); + axes[0].normalize(); + axes[1].normalize(); + for (var i = 0; i < 2; i++) { + this._origin[i] = axes[i].dot(corners[0]); + } + }; + OrientedBoundingRect.prototype.intersect = function (other, mtv) { + var overlapped = true; + var noMtv = !mtv; + minTv$1.set(Infinity, Infinity); + maxTv$1.set(0, 0); + if (!this._intersectCheckOneSide(this, other, minTv$1, maxTv$1, noMtv, 1)) { + overlapped = false; + if (noMtv) { + return overlapped; + } + } + if (!this._intersectCheckOneSide(other, this, minTv$1, maxTv$1, noMtv, -1)) { + overlapped = false; + if (noMtv) { + return overlapped; + } + } + if (!noMtv) { + Point.copy(mtv, overlapped ? minTv$1 : maxTv$1); + } + return overlapped; + }; + OrientedBoundingRect.prototype._intersectCheckOneSide = function (self, other, minTv, maxTv, noMtv, inverse) { + var overlapped = true; + for (var i = 0; i < 2; i++) { + var axis = this._axes[i]; + this._getProjMinMaxOnAxis(i, self._corners, extent); + this._getProjMinMaxOnAxis(i, other._corners, extent2); + if (extent[1] < extent2[0] || extent[0] > extent2[1]) { + overlapped = false; + if (noMtv) { + return overlapped; + } + var dist0 = Math.abs(extent2[0] - extent[1]); + var dist1 = Math.abs(extent[0] - extent2[1]); + if (Math.min(dist0, dist1) > maxTv.len()) { + if (dist0 < dist1) { + Point.scale(maxTv, axis, -dist0 * inverse); + } + else { + Point.scale(maxTv, axis, dist1 * inverse); + } + } + } + else if (minTv) { + var dist0 = Math.abs(extent2[0] - extent[1]); + var dist1 = Math.abs(extent[0] - extent2[1]); + if (Math.min(dist0, dist1) < minTv.len()) { + if (dist0 < dist1) { + Point.scale(minTv, axis, dist0 * inverse); + } + else { + Point.scale(minTv, axis, -dist1 * inverse); + } + } + } + } + return overlapped; + }; + OrientedBoundingRect.prototype._getProjMinMaxOnAxis = function (dim, corners, out) { + var axis = this._axes[dim]; + var origin = this._origin; + var proj = corners[0].dot(axis) + origin[dim]; + var min = proj; + var max = proj; + for (var i = 1; i < corners.length; i++) { + var proj_1 = corners[i].dot(axis) + origin[dim]; + min = Math.min(proj_1, min); + max = Math.max(proj_1, max); + } + out[0] = min; + out[1] = max; + }; + return OrientedBoundingRect; + }()); + + var m = []; + var IncrementalDisplayable = (function (_super) { + __extends(IncrementalDisplayable, _super); + function IncrementalDisplayable() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.notClear = true; + _this.incremental = true; + _this._displayables = []; + _this._temporaryDisplayables = []; + _this._cursor = 0; + return _this; + } + IncrementalDisplayable.prototype.traverse = function (cb, context) { + cb.call(context, this); + }; + IncrementalDisplayable.prototype.useStyle = function () { + this.style = {}; + }; + IncrementalDisplayable.prototype.getCursor = function () { + return this._cursor; + }; + IncrementalDisplayable.prototype.innerAfterBrush = function () { + this._cursor = this._displayables.length; + }; + IncrementalDisplayable.prototype.clearDisplaybles = function () { + this._displayables = []; + this._temporaryDisplayables = []; + this._cursor = 0; + this.markRedraw(); + this.notClear = false; + }; + IncrementalDisplayable.prototype.clearTemporalDisplayables = function () { + this._temporaryDisplayables = []; + }; + IncrementalDisplayable.prototype.addDisplayable = function (displayable, notPersistent) { + if (notPersistent) { + this._temporaryDisplayables.push(displayable); + } + else { + this._displayables.push(displayable); + } + this.markRedraw(); + }; + IncrementalDisplayable.prototype.addDisplayables = function (displayables, notPersistent) { + notPersistent = notPersistent || false; + for (var i = 0; i < displayables.length; i++) { + this.addDisplayable(displayables[i], notPersistent); + } + }; + IncrementalDisplayable.prototype.getDisplayables = function () { + return this._displayables; + }; + IncrementalDisplayable.prototype.getTemporalDisplayables = function () { + return this._temporaryDisplayables; + }; + IncrementalDisplayable.prototype.eachPendingDisplayable = function (cb) { + for (var i = this._cursor; i < this._displayables.length; i++) { + cb && cb(this._displayables[i]); + } + for (var i = 0; i < this._temporaryDisplayables.length; i++) { + cb && cb(this._temporaryDisplayables[i]); + } + }; + IncrementalDisplayable.prototype.update = function () { + this.updateTransform(); + for (var i = this._cursor; i < this._displayables.length; i++) { + var displayable = this._displayables[i]; + displayable.parent = this; + displayable.update(); + displayable.parent = null; + } + for (var i = 0; i < this._temporaryDisplayables.length; i++) { + var displayable = this._temporaryDisplayables[i]; + displayable.parent = this; + displayable.update(); + displayable.parent = null; + } + }; + IncrementalDisplayable.prototype.getBoundingRect = function () { + if (!this._rect) { + var rect = new BoundingRect(Infinity, Infinity, -Infinity, -Infinity); + for (var i = 0; i < this._displayables.length; i++) { + var displayable = this._displayables[i]; + var childRect = displayable.getBoundingRect().clone(); + if (displayable.needLocalTransform()) { + childRect.applyTransform(displayable.getLocalTransform(m)); + } + rect.union(childRect); + } + this._rect = rect; + } + return this._rect; + }; + IncrementalDisplayable.prototype.contain = function (x, y) { + var localPos = this.transformCoordToLocal(x, y); + var rect = this.getBoundingRect(); + if (rect.contain(localPos[0], localPos[1])) { + for (var i = 0; i < this._displayables.length; i++) { + var displayable = this._displayables[i]; + if (displayable.contain(x, y)) { + return true; + } + } + } + return false; + }; + return IncrementalDisplayable; + }(Displayable)); + + var mathMax$4 = Math.max; + var mathMin$4 = Math.min; + var _customShapeMap = {}; + function extendShape(opts) { + return Path.extend(opts); + } + var extendPathFromString = extendFromString; + function extendPath(pathData, opts) { + return extendPathFromString(pathData, opts); + } + function registerShape(name, ShapeClass) { + _customShapeMap[name] = ShapeClass; + } + function getShapeClass(name) { + if (_customShapeMap.hasOwnProperty(name)) { + return _customShapeMap[name]; + } + } + function makePath(pathData, opts, rect, layout) { + var path = createFromString(pathData, opts); + + if (rect) { + if (layout === 'center') { + rect = centerGraphic(rect, path.getBoundingRect()); + } + + resizePath(path, rect); + } + + return path; + } + function makeImage(imageUrl, rect, layout) { + var zrImg = new ZRImage({ + style: { + image: imageUrl, + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + }, + onload: function (img) { + if (layout === 'center') { + var boundingRect = { + width: img.width, + height: img.height + }; + zrImg.setStyle(centerGraphic(rect, boundingRect)); + } + } + }); + return zrImg; + } + + function centerGraphic(rect, boundingRect) { + var aspect = boundingRect.width / boundingRect.height; + var width = rect.height * aspect; + var height; + + if (width <= rect.width) { + height = rect.height; + } else { + width = rect.width; + height = width / aspect; + } + + var cx = rect.x + rect.width / 2; + var cy = rect.y + rect.height / 2; + return { + x: cx - width / 2, + y: cy - height / 2, + width: width, + height: height + }; + } + + var mergePath$1 = mergePath; + function resizePath(path, rect) { + if (!path.applyTransform) { + return; + } + + var pathRect = path.getBoundingRect(); + var m = pathRect.calculateTransform(rect); + path.applyTransform(m); + } + function subPixelOptimizeLine$1(param) { + subPixelOptimizeLine(param.shape, param.shape, param.style); + return param; + } + function subPixelOptimizeRect$1(param) { + subPixelOptimizeRect(param.shape, param.shape, param.style); + return param; + } + var subPixelOptimize$1 = subPixelOptimize; + + function animateOrSetProps(animationType, el, props, animatableModel, dataIndex, cb, during) { + var isFrom = false; + var removeOpt; + + if (typeof dataIndex === 'function') { + during = cb; + cb = dataIndex; + dataIndex = null; + } else if (isObject(dataIndex)) { + cb = dataIndex.cb; + during = dataIndex.during; + isFrom = dataIndex.isFrom; + removeOpt = dataIndex.removeOpt; + dataIndex = dataIndex.dataIndex; + } + + var isUpdate = animationType === 'update'; + var isRemove = animationType === 'remove'; + var animationPayload; + + if (animatableModel && animatableModel.ecModel) { + var updatePayload = animatableModel.ecModel.getUpdatePayload(); + animationPayload = updatePayload && updatePayload.animation; + } + + var animationEnabled = animatableModel && animatableModel.isAnimationEnabled(); + + if (!isRemove) { + el.stopAnimation('remove'); + } + + if (animationEnabled) { + var duration = void 0; + var animationEasing = void 0; + var animationDelay = void 0; + + if (animationPayload) { + duration = animationPayload.duration || 0; + animationEasing = animationPayload.easing || 'cubicOut'; + animationDelay = animationPayload.delay || 0; + } else if (isRemove) { + removeOpt = removeOpt || {}; + duration = retrieve2(removeOpt.duration, 200); + animationEasing = retrieve2(removeOpt.easing, 'cubicOut'); + animationDelay = 0; + } else { + duration = animatableModel.getShallow(isUpdate ? 'animationDurationUpdate' : 'animationDuration'); + animationEasing = animatableModel.getShallow(isUpdate ? 'animationEasingUpdate' : 'animationEasing'); + animationDelay = animatableModel.getShallow(isUpdate ? 'animationDelayUpdate' : 'animationDelay'); + } + + if (typeof animationDelay === 'function') { + animationDelay = animationDelay(dataIndex, animatableModel.getAnimationDelayParams ? animatableModel.getAnimationDelayParams(el, dataIndex) : null); + } + + if (typeof duration === 'function') { + duration = duration(dataIndex); + } + + duration > 0 ? isFrom ? el.animateFrom(props, { + duration: duration, + delay: animationDelay || 0, + easing: animationEasing, + done: cb, + force: !!cb || !!during, + scope: animationType, + during: during + }) : el.animateTo(props, { + duration: duration, + delay: animationDelay || 0, + easing: animationEasing, + done: cb, + force: !!cb || !!during, + setToFinal: true, + scope: animationType, + during: during + }) : (el.stopAnimation(), !isFrom && el.attr(props), cb && cb()); + } else { + el.stopAnimation(); + !isFrom && el.attr(props); + during && during(1); + cb && cb(); + } + } + + function updateProps(el, props, animatableModel, dataIndex, cb, during) { + animateOrSetProps('update', el, props, animatableModel, dataIndex, cb, during); + } + function initProps(el, props, animatableModel, dataIndex, cb, during) { + animateOrSetProps('init', el, props, animatableModel, dataIndex, cb, during); + } + function removeElement(el, props, animatableModel, dataIndex, cb, during) { + if (isElementRemoved(el)) { + return; + } + + animateOrSetProps('remove', el, props, animatableModel, dataIndex, cb, during); + } + + function fadeOutDisplayable(el, animatableModel, dataIndex, done) { + el.removeTextContent(); + el.removeTextGuideLine(); + removeElement(el, { + style: { + opacity: 0 + } + }, animatableModel, dataIndex, done); + } + + function removeElementWithFadeOut(el, animatableModel, dataIndex) { + function doRemove() { + el.parent && el.parent.remove(el); + } + + if (!el.isGroup) { + fadeOutDisplayable(el, animatableModel, dataIndex, doRemove); + } else { + el.traverse(function (disp) { + if (!disp.isGroup) { + fadeOutDisplayable(disp, animatableModel, dataIndex, doRemove); + } + }); + } + } + function isElementRemoved(el) { + if (!el.__zr) { + return true; + } + + for (var i = 0; i < el.animators.length; i++) { + var animator = el.animators[i]; + + if (animator.scope === 'remove') { + return true; + } + } + + return false; + } + function getTransform(target, ancestor) { + var mat = identity([]); + + while (target && target !== ancestor) { + mul$1(mat, target.getLocalTransform(), mat); + target = target.parent; + } + + return mat; + } + function applyTransform$1(target, transform, invert$1) { + if (transform && !isArrayLike(transform)) { + transform = Transformable.getLocalTransform(transform); + } + + if (invert$1) { + transform = invert([], transform); + } + + return applyTransform([], target, transform); + } + function transformDirection(direction, transform, invert) { + var hBase = transform[4] === 0 || transform[5] === 0 || transform[0] === 0 ? 1 : Math.abs(2 * transform[4] / transform[0]); + var vBase = transform[4] === 0 || transform[5] === 0 || transform[2] === 0 ? 1 : Math.abs(2 * transform[4] / transform[2]); + var vertex = [direction === 'left' ? -hBase : direction === 'right' ? hBase : 0, direction === 'top' ? -vBase : direction === 'bottom' ? vBase : 0]; + vertex = applyTransform$1(vertex, transform, invert); + return Math.abs(vertex[0]) > Math.abs(vertex[1]) ? vertex[0] > 0 ? 'right' : 'left' : vertex[1] > 0 ? 'bottom' : 'top'; + } + + function isNotGroup(el) { + return !el.isGroup; + } + + function isPath(el) { + return el.shape != null; + } + + function groupTransition(g1, g2, animatableModel) { + if (!g1 || !g2) { + return; + } + + function getElMap(g) { + var elMap = {}; + g.traverse(function (el) { + if (isNotGroup(el) && el.anid) { + elMap[el.anid] = el; + } + }); + return elMap; + } + + function getAnimatableProps(el) { + var obj = { + x: el.x, + y: el.y, + rotation: el.rotation + }; + + if (isPath(el)) { + obj.shape = extend({}, el.shape); + } + + return obj; + } + + var elMap1 = getElMap(g1); + g2.traverse(function (el) { + if (isNotGroup(el) && el.anid) { + var oldEl = elMap1[el.anid]; + + if (oldEl) { + var newProp = getAnimatableProps(el); + el.attr(getAnimatableProps(oldEl)); + updateProps(el, newProp, animatableModel, getECData(el).dataIndex); + } + } + }); + } + function clipPointsByRect(points, rect) { + return map(points, function (point) { + var x = point[0]; + x = mathMax$4(x, rect.x); + x = mathMin$4(x, rect.x + rect.width); + var y = point[1]; + y = mathMax$4(y, rect.y); + y = mathMin$4(y, rect.y + rect.height); + return [x, y]; + }); + } + function clipRectByRect(targetRect, rect) { + var x = mathMax$4(targetRect.x, rect.x); + var x2 = mathMin$4(targetRect.x + targetRect.width, rect.x + rect.width); + var y = mathMax$4(targetRect.y, rect.y); + var y2 = mathMin$4(targetRect.y + targetRect.height, rect.y + rect.height); + + if (x2 >= x && y2 >= y) { + return { + x: x, + y: y, + width: x2 - x, + height: y2 - y + }; + } + } + function createIcon(iconStr, opt, rect) { + var innerOpts = extend({ + rectHover: true + }, opt); + var style = innerOpts.style = { + strokeNoScale: true + }; + rect = rect || { + x: -1, + y: -1, + width: 2, + height: 2 + }; + + if (iconStr) { + return iconStr.indexOf('image://') === 0 ? (style.image = iconStr.slice(8), defaults(style, rect), new ZRImage(innerOpts)) : makePath(iconStr.replace('path://', ''), innerOpts, rect, 'center'); + } + } + function linePolygonIntersect(a1x, a1y, a2x, a2y, points) { + for (var i = 0, p2 = points[points.length - 1]; i < points.length; i++) { + var p = points[i]; + + if (lineLineIntersect(a1x, a1y, a2x, a2y, p[0], p[1], p2[0], p2[1])) { + return true; + } + + p2 = p; + } + } + function lineLineIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y) { + var mx = a2x - a1x; + var my = a2y - a1y; + var nx = b2x - b1x; + var ny = b2y - b1y; + var nmCrossProduct = crossProduct2d(nx, ny, mx, my); + + if (nearZero(nmCrossProduct)) { + return false; + } + + var b1a1x = a1x - b1x; + var b1a1y = a1y - b1y; + var q = crossProduct2d(b1a1x, b1a1y, mx, my) / nmCrossProduct; + + if (q < 0 || q > 1) { + return false; + } + + var p = crossProduct2d(b1a1x, b1a1y, nx, ny) / nmCrossProduct; + + if (p < 0 || p > 1) { + return false; + } + + return true; + } + + function crossProduct2d(x1, y1, x2, y2) { + return x1 * y2 - x2 * y1; + } + + function nearZero(val) { + return val <= 1e-6 && val >= -1e-6; + } + + registerShape('circle', Circle); + registerShape('ellipse', Ellipse); + registerShape('sector', Sector); + registerShape('ring', Ring); + registerShape('polygon', Polygon); + registerShape('polyline', Polyline); + registerShape('rect', Rect); + registerShape('line', Line); + registerShape('bezierCurve', BezierCurve); + registerShape('arc', Arc); + + var graphic = /*#__PURE__*/Object.freeze({ + __proto__: null, + extendShape: extendShape, + extendPath: extendPath, + registerShape: registerShape, + getShapeClass: getShapeClass, + makePath: makePath, + makeImage: makeImage, + mergePath: mergePath$1, + resizePath: resizePath, + subPixelOptimizeLine: subPixelOptimizeLine$1, + subPixelOptimizeRect: subPixelOptimizeRect$1, + subPixelOptimize: subPixelOptimize$1, + updateProps: updateProps, + initProps: initProps, + removeElement: removeElement, + removeElementWithFadeOut: removeElementWithFadeOut, + isElementRemoved: isElementRemoved, + getTransform: getTransform, + applyTransform: applyTransform$1, + transformDirection: transformDirection, + groupTransition: groupTransition, + clipPointsByRect: clipPointsByRect, + clipRectByRect: clipRectByRect, + createIcon: createIcon, + linePolygonIntersect: linePolygonIntersect, + lineLineIntersect: lineLineIntersect, + Group: Group, + Image: ZRImage, + Text: ZRText, + Circle: Circle, + Ellipse: Ellipse, + Sector: Sector, + Ring: Ring, + Polygon: Polygon, + Polyline: Polyline, + Rect: Rect, + Line: Line, + BezierCurve: BezierCurve, + Arc: Arc, + IncrementalDisplayable: IncrementalDisplayable, + CompoundPath: CompoundPath, + LinearGradient: LinearGradient, + RadialGradient: RadialGradient, + BoundingRect: BoundingRect, + OrientedBoundingRect: OrientedBoundingRect, + Point: Point, + Path: Path + }); + + var EMPTY_OBJ = {}; + function setLabelText(label, labelTexts) { + for (var i = 0; i < SPECIAL_STATES.length; i++) { + var stateName = SPECIAL_STATES[i]; + var text = labelTexts[stateName]; + var state = label.ensureState(stateName); + state.style = state.style || {}; + state.style.text = text; + } + + var oldStates = label.currentStates.slice(); + label.clearStates(true); + label.setStyle({ + text: labelTexts.normal + }); + label.useStates(oldStates, true); + } + + function getLabelText(opt, stateModels, interpolatedValue) { + var labelFetcher = opt.labelFetcher; + var labelDataIndex = opt.labelDataIndex; + var labelDimIndex = opt.labelDimIndex; + var normalModel = stateModels.normal; + var baseText; + + if (labelFetcher) { + baseText = labelFetcher.getFormattedLabel(labelDataIndex, 'normal', null, labelDimIndex, normalModel && normalModel.get('formatter'), interpolatedValue != null ? { + interpolatedValue: interpolatedValue + } : null); + } + + if (baseText == null) { + baseText = isFunction(opt.defaultText) ? opt.defaultText(labelDataIndex, opt, interpolatedValue) : opt.defaultText; + } + + var statesText = { + normal: baseText + }; + + for (var i = 0; i < SPECIAL_STATES.length; i++) { + var stateName = SPECIAL_STATES[i]; + var stateModel = stateModels[stateName]; + statesText[stateName] = retrieve2(labelFetcher ? labelFetcher.getFormattedLabel(labelDataIndex, stateName, null, labelDimIndex, stateModel && stateModel.get('formatter')) : null, baseText); + } + + return statesText; + } + + function setLabelStyle(targetEl, labelStatesModels, opt, stateSpecified) { + opt = opt || EMPTY_OBJ; + var isSetOnText = targetEl instanceof ZRText; + var needsCreateText = false; + + for (var i = 0; i < DISPLAY_STATES.length; i++) { + var stateModel = labelStatesModels[DISPLAY_STATES[i]]; + + if (stateModel && stateModel.getShallow('show')) { + needsCreateText = true; + break; + } + } + + var textContent = isSetOnText ? targetEl : targetEl.getTextContent(); + + if (needsCreateText) { + if (!isSetOnText) { + if (!textContent) { + textContent = new ZRText(); + targetEl.setTextContent(textContent); + } + + if (targetEl.stateProxy) { + textContent.stateProxy = targetEl.stateProxy; + } + } + + var labelStatesTexts = getLabelText(opt, labelStatesModels); + var normalModel = labelStatesModels.normal; + var showNormal = !!normalModel.getShallow('show'); + var normalStyle = createTextStyle(normalModel, stateSpecified && stateSpecified.normal, opt, false, !isSetOnText); + normalStyle.text = labelStatesTexts.normal; + + if (!isSetOnText) { + targetEl.setTextConfig(createTextConfig(normalModel, opt, false)); + } + + for (var i = 0; i < SPECIAL_STATES.length; i++) { + var stateName = SPECIAL_STATES[i]; + var stateModel = labelStatesModels[stateName]; + + if (stateModel) { + var stateObj = textContent.ensureState(stateName); + var stateShow = !!retrieve2(stateModel.getShallow('show'), showNormal); + + if (stateShow !== showNormal) { + stateObj.ignore = !stateShow; + } + + stateObj.style = createTextStyle(stateModel, stateSpecified && stateSpecified[stateName], opt, true, !isSetOnText); + stateObj.style.text = labelStatesTexts[stateName]; + + if (!isSetOnText) { + var targetElEmphasisState = targetEl.ensureState(stateName); + targetElEmphasisState.textConfig = createTextConfig(stateModel, opt, true); + } + } + } + + textContent.silent = !!normalModel.getShallow('silent'); + + if (textContent.style.x != null) { + normalStyle.x = textContent.style.x; + } + + if (textContent.style.y != null) { + normalStyle.y = textContent.style.y; + } + + textContent.ignore = !showNormal; + textContent.useStyle(normalStyle); + textContent.dirty(); + + if (opt.enableTextSetter) { + labelInner(textContent).setLabelText = function (interpolatedValue) { + var labelStatesTexts = getLabelText(opt, labelStatesModels, interpolatedValue); + setLabelText(textContent, labelStatesTexts); + }; + } + } else if (textContent) { + textContent.ignore = true; + } + + targetEl.dirty(); + } + function getLabelStatesModels(itemModel, labelName) { + labelName = labelName || 'label'; + var statesModels = { + normal: itemModel.getModel(labelName) + }; + + for (var i = 0; i < SPECIAL_STATES.length; i++) { + var stateName = SPECIAL_STATES[i]; + statesModels[stateName] = itemModel.getModel([stateName, labelName]); + } + + return statesModels; + } + function createTextStyle(textStyleModel, specifiedTextStyle, opt, isNotNormal, isAttached) { + var textStyle = {}; + setTextStyleCommon(textStyle, textStyleModel, opt, isNotNormal, isAttached); + specifiedTextStyle && extend(textStyle, specifiedTextStyle); + return textStyle; + } + function createTextConfig(textStyleModel, opt, isNotNormal) { + opt = opt || {}; + var textConfig = {}; + var labelPosition; + var labelRotate = textStyleModel.getShallow('rotate'); + var labelDistance = retrieve2(textStyleModel.getShallow('distance'), isNotNormal ? null : 5); + var labelOffset = textStyleModel.getShallow('offset'); + labelPosition = textStyleModel.getShallow('position') || (isNotNormal ? null : 'inside'); + labelPosition === 'outside' && (labelPosition = opt.defaultOutsidePosition || 'top'); + + if (labelPosition != null) { + textConfig.position = labelPosition; + } + + if (labelOffset != null) { + textConfig.offset = labelOffset; + } + + if (labelRotate != null) { + labelRotate *= Math.PI / 180; + textConfig.rotation = labelRotate; + } + + if (labelDistance != null) { + textConfig.distance = labelDistance; + } + + textConfig.outsideFill = textStyleModel.get('color') === 'inherit' ? opt.inheritColor || null : 'auto'; + return textConfig; + } + + function setTextStyleCommon(textStyle, textStyleModel, opt, isNotNormal, isAttached) { + opt = opt || EMPTY_OBJ; + var ecModel = textStyleModel.ecModel; + var globalTextStyle = ecModel && ecModel.option.textStyle; + var richItemNames = getRichItemNames(textStyleModel); + var richResult; + + if (richItemNames) { + richResult = {}; + + for (var name_1 in richItemNames) { + if (richItemNames.hasOwnProperty(name_1)) { + var richTextStyle = textStyleModel.getModel(['rich', name_1]); + setTokenTextStyle(richResult[name_1] = {}, richTextStyle, globalTextStyle, opt, isNotNormal, isAttached, false, true); + } + } + } + + if (richResult) { + textStyle.rich = richResult; + } + + var overflow = textStyleModel.get('overflow'); + + if (overflow) { + textStyle.overflow = overflow; + } + + var margin = textStyleModel.get('minMargin'); + + if (margin != null) { + textStyle.margin = margin; + } + + setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isNotNormal, isAttached, true, false); + } + + function getRichItemNames(textStyleModel) { + var richItemNameMap; + + while (textStyleModel && textStyleModel !== textStyleModel.ecModel) { + var rich = (textStyleModel.option || EMPTY_OBJ).rich; + + if (rich) { + richItemNameMap = richItemNameMap || {}; + var richKeys = keys(rich); + + for (var i = 0; i < richKeys.length; i++) { + var richKey = richKeys[i]; + richItemNameMap[richKey] = 1; + } + } + + textStyleModel = textStyleModel.parentModel; + } + + return richItemNameMap; + } + + var TEXT_PROPS_WITH_GLOBAL = ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily', 'textShadowColor', 'textShadowBlur', 'textShadowOffsetX', 'textShadowOffsetY']; + var TEXT_PROPS_SELF = ['align', 'lineHeight', 'width', 'height', 'tag', 'verticalAlign']; + var TEXT_PROPS_BOX = ['padding', 'borderWidth', 'borderRadius', 'borderDashOffset', 'backgroundColor', 'borderColor', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY']; + + function setTokenTextStyle(textStyle, textStyleModel, globalTextStyle, opt, isNotNormal, isAttached, isBlock, inRich) { + globalTextStyle = !isNotNormal && globalTextStyle || EMPTY_OBJ; + var inheritColor = opt && opt.inheritColor; + var fillColor = textStyleModel.getShallow('color'); + var strokeColor = textStyleModel.getShallow('textBorderColor'); + var opacity = retrieve2(textStyleModel.getShallow('opacity'), globalTextStyle.opacity); + + if (fillColor === 'inherit' || fillColor === 'auto') { + if ("development" !== 'production') { + if (fillColor === 'auto') { + deprecateReplaceLog('color: \'auto\'', 'color: \'inherit\''); + } + } + + if (inheritColor) { + fillColor = inheritColor; + } else { + fillColor = null; + } + } + + if (strokeColor === 'inherit' || strokeColor === 'auto') { + if ("development" !== 'production') { + if (strokeColor === 'auto') { + deprecateReplaceLog('color: \'auto\'', 'color: \'inherit\''); + } + } + + if (inheritColor) { + strokeColor = inheritColor; + } else { + strokeColor = null; + } + } + + if (!isAttached) { + fillColor = fillColor || globalTextStyle.color; + strokeColor = strokeColor || globalTextStyle.textBorderColor; + } + + if (fillColor != null) { + textStyle.fill = fillColor; + } + + if (strokeColor != null) { + textStyle.stroke = strokeColor; + } + + var textBorderWidth = retrieve2(textStyleModel.getShallow('textBorderWidth'), globalTextStyle.textBorderWidth); + + if (textBorderWidth != null) { + textStyle.lineWidth = textBorderWidth; + } + + var textBorderType = retrieve2(textStyleModel.getShallow('textBorderType'), globalTextStyle.textBorderType); + + if (textBorderType != null) { + textStyle.lineDash = textBorderType; + } + + var textBorderDashOffset = retrieve2(textStyleModel.getShallow('textBorderDashOffset'), globalTextStyle.textBorderDashOffset); + + if (textBorderDashOffset != null) { + textStyle.lineDashOffset = textBorderDashOffset; + } + + if (!isNotNormal && opacity == null && !inRich) { + opacity = opt && opt.defaultOpacity; + } + + if (opacity != null) { + textStyle.opacity = opacity; + } + + if (!isNotNormal && !isAttached) { + if (textStyle.fill == null && opt.inheritColor) { + textStyle.fill = opt.inheritColor; + } + } + + for (var i = 0; i < TEXT_PROPS_WITH_GLOBAL.length; i++) { + var key = TEXT_PROPS_WITH_GLOBAL[i]; + var val = retrieve2(textStyleModel.getShallow(key), globalTextStyle[key]); + + if (val != null) { + textStyle[key] = val; + } + } + + for (var i = 0; i < TEXT_PROPS_SELF.length; i++) { + var key = TEXT_PROPS_SELF[i]; + var val = textStyleModel.getShallow(key); + + if (val != null) { + textStyle[key] = val; + } + } + + if (textStyle.verticalAlign == null) { + var baseline = textStyleModel.getShallow('baseline'); + + if (baseline != null) { + textStyle.verticalAlign = baseline; + } + } + + if (!isBlock || !opt.disableBox) { + for (var i = 0; i < TEXT_PROPS_BOX.length; i++) { + var key = TEXT_PROPS_BOX[i]; + var val = textStyleModel.getShallow(key); + + if (val != null) { + textStyle[key] = val; + } + } + + var borderType = textStyleModel.getShallow('borderType'); + + if (borderType != null) { + textStyle.borderDash = borderType; + } + + if ((textStyle.backgroundColor === 'auto' || textStyle.backgroundColor === 'inherit') && inheritColor) { + if ("development" !== 'production') { + if (textStyle.backgroundColor === 'auto') { + deprecateReplaceLog('backgroundColor: \'auto\'', 'backgroundColor: \'inherit\''); + } + } + + textStyle.backgroundColor = inheritColor; + } + + if ((textStyle.borderColor === 'auto' || textStyle.borderColor === 'inherit') && inheritColor) { + if ("development" !== 'production') { + if (textStyle.borderColor === 'auto') { + deprecateReplaceLog('borderColor: \'auto\'', 'borderColor: \'inherit\''); + } + } + + textStyle.borderColor = inheritColor; + } + } + } + + function getFont(opt, ecModel) { + var gTextStyleModel = ecModel && ecModel.getModel('textStyle'); + return trim([opt.fontStyle || gTextStyleModel && gTextStyleModel.getShallow('fontStyle') || '', opt.fontWeight || gTextStyleModel && gTextStyleModel.getShallow('fontWeight') || '', (opt.fontSize || gTextStyleModel && gTextStyleModel.getShallow('fontSize') || 12) + 'px', opt.fontFamily || gTextStyleModel && gTextStyleModel.getShallow('fontFamily') || 'sans-serif'].join(' ')); + } + var labelInner = makeInner(); + function setLabelValueAnimation(label, labelStatesModels, value, getDefaultText) { + if (!label) { + return; + } + + var obj = labelInner(label); + obj.prevValue = obj.value; + obj.value = value; + var normalLabelModel = labelStatesModels.normal; + obj.valueAnimation = normalLabelModel.get('valueAnimation'); + + if (obj.valueAnimation) { + obj.precision = normalLabelModel.get('precision'); + obj.defaultInterpolatedText = getDefaultText; + obj.statesModels = labelStatesModels; + } + } + function animateLabelValue(textEl, dataIndex, data, animatableModel, labelFetcher) { + var labelInnerStore = labelInner(textEl); + + if (!labelInnerStore.valueAnimation) { + return; + } + + var defaultInterpolatedText = labelInnerStore.defaultInterpolatedText; + var currValue = retrieve2(labelInnerStore.interpolatedValue, labelInnerStore.prevValue); + var targetValue = labelInnerStore.value; + + function during(percent) { + var interpolated = interpolateRawValues(data, labelInnerStore.precision, currValue, targetValue, percent); + labelInnerStore.interpolatedValue = percent === 1 ? null : interpolated; + var labelText = getLabelText({ + labelDataIndex: dataIndex, + labelFetcher: labelFetcher, + defaultText: defaultInterpolatedText ? defaultInterpolatedText(interpolated) : interpolated + '' + }, labelInnerStore.statesModels, interpolated); + setLabelText(textEl, labelText); + } + + (currValue == null ? initProps : updateProps)(textEl, {}, animatableModel, dataIndex, null, during); + } + + var PATH_COLOR = ['textStyle', 'color']; + var tmpRichText = new ZRText(); + + var TextStyleMixin = function () { + function TextStyleMixin() {} + + TextStyleMixin.prototype.getTextColor = function (isEmphasis) { + var ecModel = this.ecModel; + return this.getShallow('color') || (!isEmphasis && ecModel ? ecModel.get(PATH_COLOR) : null); + }; + + TextStyleMixin.prototype.getFont = function () { + return getFont({ + fontStyle: this.getShallow('fontStyle'), + fontWeight: this.getShallow('fontWeight'), + fontSize: this.getShallow('fontSize'), + fontFamily: this.getShallow('fontFamily') + }, this.ecModel); + }; + + TextStyleMixin.prototype.getTextRect = function (text) { + tmpRichText.useStyle({ + text: text, + fontStyle: this.getShallow('fontStyle'), + fontWeight: this.getShallow('fontWeight'), + fontSize: this.getShallow('fontSize'), + fontFamily: this.getShallow('fontFamily'), + verticalAlign: this.getShallow('verticalAlign') || this.getShallow('baseline'), + padding: this.getShallow('padding'), + lineHeight: this.getShallow('lineHeight'), + rich: this.getShallow('rich') + }); + tmpRichText.update(); + return tmpRichText.getBoundingRect(); + }; + + return TextStyleMixin; + }(); + + var LINE_STYLE_KEY_MAP = [['lineWidth', 'width'], ['stroke', 'color'], ['opacity'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['shadowColor'], ['lineDash', 'type'], ['lineDashOffset', 'dashOffset'], ['lineCap', 'cap'], ['lineJoin', 'join'], ['miterLimit']]; + var getLineStyle = makeStyleMapper(LINE_STYLE_KEY_MAP); + + var LineStyleMixin = function () { + function LineStyleMixin() {} + + LineStyleMixin.prototype.getLineStyle = function (excludes) { + return getLineStyle(this, excludes); + }; + + return LineStyleMixin; + }(); + + var ITEM_STYLE_KEY_MAP = [['fill', 'color'], ['stroke', 'borderColor'], ['lineWidth', 'borderWidth'], ['opacity'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['shadowColor'], ['lineDash', 'borderType'], ['lineDashOffset', 'borderDashOffset'], ['lineCap', 'borderCap'], ['lineJoin', 'borderJoin'], ['miterLimit', 'borderMiterLimit']]; + var getItemStyle = makeStyleMapper(ITEM_STYLE_KEY_MAP); + + var ItemStyleMixin = function () { + function ItemStyleMixin() {} + + ItemStyleMixin.prototype.getItemStyle = function (excludes, includes) { + return getItemStyle(this, excludes, includes); + }; + + return ItemStyleMixin; + }(); + + var Model = function () { + function Model(option, parentModel, ecModel) { + this.parentModel = parentModel; + this.ecModel = ecModel; + this.option = option; + } + + Model.prototype.init = function (option, parentModel, ecModel) { + var rest = []; + + for (var _i = 3; _i < arguments.length; _i++) { + rest[_i - 3] = arguments[_i]; + } + }; + + Model.prototype.mergeOption = function (option, ecModel) { + merge(this.option, option, true); + }; + + Model.prototype.get = function (path, ignoreParent) { + if (path == null) { + return this.option; + } + + return this._doGet(this.parsePath(path), !ignoreParent && this.parentModel); + }; + + Model.prototype.getShallow = function (key, ignoreParent) { + var option = this.option; + var val = option == null ? option : option[key]; + + if (val == null && !ignoreParent) { + var parentModel = this.parentModel; + + if (parentModel) { + val = parentModel.getShallow(key); + } + } + + return val; + }; + + Model.prototype.getModel = function (path, parentModel) { + var hasPath = path != null; + var pathFinal = hasPath ? this.parsePath(path) : null; + var obj = hasPath ? this._doGet(pathFinal) : this.option; + parentModel = parentModel || this.parentModel && this.parentModel.getModel(this.resolveParentPath(pathFinal)); + return new Model(obj, parentModel, this.ecModel); + }; + + Model.prototype.isEmpty = function () { + return this.option == null; + }; + + Model.prototype.restoreData = function () {}; + + Model.prototype.clone = function () { + var Ctor = this.constructor; + return new Ctor(clone(this.option)); + }; + + Model.prototype.parsePath = function (path) { + if (typeof path === 'string') { + return path.split('.'); + } + + return path; + }; + + Model.prototype.resolveParentPath = function (path) { + return path; + }; + + Model.prototype.isAnimationEnabled = function () { + if (!env.node && this.option) { + if (this.option.animation != null) { + return !!this.option.animation; + } else if (this.parentModel) { + return this.parentModel.isAnimationEnabled(); + } + } + }; + + Model.prototype._doGet = function (pathArr, parentModel) { + var obj = this.option; + + if (!pathArr) { + return obj; + } + + for (var i = 0; i < pathArr.length; i++) { + if (!pathArr[i]) { + continue; + } + + obj = obj && typeof obj === 'object' ? obj[pathArr[i]] : null; + + if (obj == null) { + break; + } + } + + if (obj == null && parentModel) { + obj = parentModel._doGet(this.resolveParentPath(pathArr), parentModel.parentModel); + } + + return obj; + }; + + return Model; + }(); + enableClassExtend(Model); + enableClassCheck(Model); + mixin(Model, LineStyleMixin); + mixin(Model, ItemStyleMixin); + mixin(Model, AreaStyleMixin); + mixin(Model, TextStyleMixin); + + var base = Math.round(Math.random() * 10); + function getUID(type) { + return [type || '', base++].join('_'); + } + function enableSubTypeDefaulter(target) { + var subTypeDefaulters = {}; + + target.registerSubTypeDefaulter = function (componentType, defaulter) { + var componentTypeInfo = parseClassType(componentType); + subTypeDefaulters[componentTypeInfo.main] = defaulter; + }; + + target.determineSubType = function (componentType, option) { + var type = option.type; + + if (!type) { + var componentTypeMain = parseClassType(componentType).main; + + if (target.hasSubTypes(componentType) && subTypeDefaulters[componentTypeMain]) { + type = subTypeDefaulters[componentTypeMain](option); + } + } + + return type; + }; + } + function enableTopologicalTravel(entity, dependencyGetter) { + entity.topologicalTravel = function (targetNameList, fullNameList, callback, context) { + if (!targetNameList.length) { + return; + } + + var result = makeDepndencyGraph(fullNameList); + var graph = result.graph; + var noEntryList = result.noEntryList; + var targetNameSet = {}; + each(targetNameList, function (name) { + targetNameSet[name] = true; + }); + + while (noEntryList.length) { + var currComponentType = noEntryList.pop(); + var currVertex = graph[currComponentType]; + var isInTargetNameSet = !!targetNameSet[currComponentType]; + + if (isInTargetNameSet) { + callback.call(context, currComponentType, currVertex.originalDeps.slice()); + delete targetNameSet[currComponentType]; + } + + each(currVertex.successor, isInTargetNameSet ? removeEdgeAndAdd : removeEdge); + } + + each(targetNameSet, function () { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = makePrintable('Circle dependency may exists: ', targetNameSet, targetNameList, fullNameList); + } + + throw new Error(errMsg); + }); + + function removeEdge(succComponentType) { + graph[succComponentType].entryCount--; + + if (graph[succComponentType].entryCount === 0) { + noEntryList.push(succComponentType); + } + } + + function removeEdgeAndAdd(succComponentType) { + targetNameSet[succComponentType] = true; + removeEdge(succComponentType); + } + }; + + function makeDepndencyGraph(fullNameList) { + var graph = {}; + var noEntryList = []; + each(fullNameList, function (name) { + var thisItem = createDependencyGraphItem(graph, name); + var originalDeps = thisItem.originalDeps = dependencyGetter(name); + var availableDeps = getAvailableDependencies(originalDeps, fullNameList); + thisItem.entryCount = availableDeps.length; + + if (thisItem.entryCount === 0) { + noEntryList.push(name); + } + + each(availableDeps, function (dependentName) { + if (indexOf(thisItem.predecessor, dependentName) < 0) { + thisItem.predecessor.push(dependentName); + } + + var thatItem = createDependencyGraphItem(graph, dependentName); + + if (indexOf(thatItem.successor, dependentName) < 0) { + thatItem.successor.push(name); + } + }); + }); + return { + graph: graph, + noEntryList: noEntryList + }; + } + + function createDependencyGraphItem(graph, name) { + if (!graph[name]) { + graph[name] = { + predecessor: [], + successor: [] + }; + } + + return graph[name]; + } + + function getAvailableDependencies(originalDeps, fullNameList) { + var availableDeps = []; + each(originalDeps, function (dep) { + indexOf(fullNameList, dep) >= 0 && availableDeps.push(dep); + }); + return availableDeps; + } + } + function inheritDefaultOption(superOption, subOption) { + return merge(merge({}, superOption, true), subOption, true); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var langEN = { + time: { + month: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + monthAbbr: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + dayOfWeek: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + dayOfWeekAbbr: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] + }, + legend: { + selector: { + all: 'All', + inverse: 'Inv' + } + }, + toolbox: { + brush: { + title: { + rect: 'Box Select', + polygon: 'Lasso Select', + lineX: 'Horizontally Select', + lineY: 'Vertically Select', + keep: 'Keep Selections', + clear: 'Clear Selections' + } + }, + dataView: { + title: 'Data View', + lang: ['Data View', 'Close', 'Refresh'] + }, + dataZoom: { + title: { + zoom: 'Zoom', + back: 'Zoom Reset' + } + }, + magicType: { + title: { + line: 'Switch to Line Chart', + bar: 'Switch to Bar Chart', + stack: 'Stack', + tiled: 'Tile' + } + }, + restore: { + title: 'Restore' + }, + saveAsImage: { + title: 'Save as Image', + lang: ['Right Click to Save Image'] + } + }, + series: { + typeNames: { + pie: 'Pie chart', + bar: 'Bar chart', + line: 'Line chart', + scatter: 'Scatter plot', + effectScatter: 'Ripple scatter plot', + radar: 'Radar chart', + tree: 'Tree', + treemap: 'Treemap', + boxplot: 'Boxplot', + candlestick: 'Candlestick', + k: 'K line chart', + heatmap: 'Heat map', + map: 'Map', + parallel: 'Parallel coordinate map', + lines: 'Line graph', + graph: 'Relationship graph', + sankey: 'Sankey diagram', + funnel: 'Funnel chart', + gauge: 'Guage', + pictorialBar: 'Pictorial bar', + themeRiver: 'Theme River Map', + sunburst: 'Sunburst' + } + }, + aria: { + general: { + withTitle: 'This is a chart about "{title}"', + withoutTitle: 'This is a chart' + }, + series: { + single: { + prefix: '', + withName: ' with type {seriesType} named {seriesName}.', + withoutName: ' with type {seriesType}.' + }, + multiple: { + prefix: '. It consists of {seriesCount} series count.', + withName: ' The {seriesId} series is a {seriesType} representing {seriesName}.', + withoutName: ' The {seriesId} series is a {seriesType}.', + separator: { + middle: '', + end: '' + } + } + }, + data: { + allData: 'The data is as follows: ', + partialData: 'The first {displayCnt} items are: ', + withName: 'the data for {name} is {value}', + withoutName: '{value}', + separator: { + middle: ', ', + end: '. ' + } + } + } + }; + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var langZH = { + time: { + month: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], + monthAbbr: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], + dayOfWeek: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'], + dayOfWeekAbbr: ['日', '一', '二', '三', '四', '五', '六'] + }, + legend: { + selector: { + all: '全选', + inverse: '反选' + } + }, + 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: '' + } + } + } + }; + + var LOCALE_ZH = 'ZH'; + var LOCALE_EN = 'EN'; + var DEFAULT_LOCALE = LOCALE_EN; + var localeStorage = {}; + var localeModels = {}; + var SYSTEM_LANG = !env.domSupported ? DEFAULT_LOCALE : function () { + var langStr = (document.documentElement.lang || navigator.language || navigator.browserLanguage).toUpperCase(); + return langStr.indexOf(LOCALE_ZH) > -1 ? LOCALE_ZH : DEFAULT_LOCALE; + }(); + function registerLocale(locale, localeObj) { + locale = locale.toUpperCase(); + localeModels[locale] = new Model(localeObj); + localeStorage[locale] = localeObj; + } + function createLocaleObject(locale) { + if (isString(locale)) { + var localeObj = localeStorage[locale.toUpperCase()] || {}; + + if (locale === LOCALE_ZH || locale === LOCALE_EN) { + return clone(localeObj); + } else { + return merge(clone(localeObj), clone(localeStorage[DEFAULT_LOCALE]), false); + } + } else { + return merge(clone(locale), clone(localeStorage[DEFAULT_LOCALE]), false); + } + } + function getLocaleModel(lang) { + return localeModels[lang]; + } + function getDefaultLocaleModel() { + return localeModels[DEFAULT_LOCALE]; + } + registerLocale(LOCALE_EN, langEN); + registerLocale(LOCALE_ZH, langZH); + + var ONE_SECOND = 1000; + var ONE_MINUTE = ONE_SECOND * 60; + var ONE_HOUR = ONE_MINUTE * 60; + var ONE_DAY = ONE_HOUR * 24; + var ONE_YEAR = ONE_DAY * 365; + var defaultLeveledFormatter = { + year: '{yyyy}', + month: '{MMM}', + day: '{d}', + hour: '{HH}:{mm}', + minute: '{HH}:{mm}', + second: '{HH}:{mm}:{ss}', + millisecond: '{hh}:{mm}:{ss} {SSS}', + none: '{yyyy}-{MM}-{dd} {hh}:{mm}:{ss} {SSS}' + }; + var fullDayFormatter = '{yyyy}-{MM}-{dd}'; + var fullLeveledFormatter = { + year: '{yyyy}', + month: '{yyyy}-{MM}', + day: fullDayFormatter, + hour: fullDayFormatter + ' ' + defaultLeveledFormatter.hour, + minute: fullDayFormatter + ' ' + defaultLeveledFormatter.minute, + second: fullDayFormatter + ' ' + defaultLeveledFormatter.second, + millisecond: defaultLeveledFormatter.none + }; + var primaryTimeUnits = ['year', 'month', 'day', 'hour', 'minute', 'second', 'millisecond']; + var timeUnits = ['year', 'half-year', 'quarter', 'month', 'week', 'half-week', 'day', 'half-day', 'quarter-day', 'hour', 'minute', 'second', 'millisecond']; + function pad(str, len) { + str += ''; + return '0000'.substr(0, len - str.length) + str; + } + function getPrimaryTimeUnit(timeUnit) { + switch (timeUnit) { + case 'half-year': + case 'quarter': + return 'month'; + + case 'week': + case 'half-week': + return 'day'; + + case 'half-day': + case 'quarter-day': + return 'hour'; + + default: + return timeUnit; + } + } + function isPrimaryTimeUnit(timeUnit) { + return timeUnit === getPrimaryTimeUnit(timeUnit); + } + function getDefaultFormatPrecisionOfInterval(timeUnit) { + switch (timeUnit) { + case 'year': + case 'month': + return 'day'; + + case 'millisecond': + return 'millisecond'; + + default: + return 'second'; + } + } + function format(time, template, isUTC, lang) { + var date = parseDate(time); + var y = date[fullYearGetterName(isUTC)](); + var M = date[monthGetterName(isUTC)]() + 1; + var q = Math.floor((M - 1) / 4) + 1; + var d = date[dateGetterName(isUTC)](); + var e = date['get' + (isUTC ? 'UTC' : '') + 'Day'](); + var H = date[hoursGetterName(isUTC)](); + var h = (H - 1) % 12 + 1; + var m = date[minutesGetterName(isUTC)](); + var s = date[secondsGetterName(isUTC)](); + var S = date[millisecondsGetterName(isUTC)](); + var localeModel = lang instanceof Model ? lang : getLocaleModel(lang || SYSTEM_LANG) || getDefaultLocaleModel(); + var timeModel = localeModel.getModel('time'); + var month = timeModel.get('month'); + var monthAbbr = timeModel.get('monthAbbr'); + var dayOfWeek = timeModel.get('dayOfWeek'); + var dayOfWeekAbbr = timeModel.get('dayOfWeekAbbr'); + return (template || '').replace(/{yyyy}/g, y + '').replace(/{yy}/g, y % 100 + '').replace(/{Q}/g, q + '').replace(/{MMMM}/g, month[M - 1]).replace(/{MMM}/g, monthAbbr[M - 1]).replace(/{MM}/g, pad(M, 2)).replace(/{M}/g, M + '').replace(/{dd}/g, pad(d, 2)).replace(/{d}/g, d + '').replace(/{eeee}/g, dayOfWeek[e]).replace(/{ee}/g, dayOfWeekAbbr[e]).replace(/{e}/g, e + '').replace(/{HH}/g, pad(H, 2)).replace(/{H}/g, H + '').replace(/{hh}/g, pad(h + '', 2)).replace(/{h}/g, h + '').replace(/{mm}/g, pad(m, 2)).replace(/{m}/g, m + '').replace(/{ss}/g, pad(s, 2)).replace(/{s}/g, s + '').replace(/{SSS}/g, pad(S, 3)).replace(/{S}/g, S + ''); + } + function leveledFormat(tick, idx, formatter, lang, isUTC) { + var template = null; + + if (typeof formatter === 'string') { + template = formatter; + } else if (typeof formatter === 'function') { + template = formatter(tick.value, idx, { + level: tick.level + }); + } else { + var defaults$1 = extend({}, defaultLeveledFormatter); + + if (tick.level > 0) { + for (var i = 0; i < primaryTimeUnits.length; ++i) { + defaults$1[primaryTimeUnits[i]] = "{primary|" + defaults$1[primaryTimeUnits[i]] + "}"; + } + } + + var mergedFormatter = formatter ? formatter.inherit === false ? formatter : defaults(formatter, defaults$1) : defaults$1; + var unit = getUnitFromValue(tick.value, isUTC); + + if (mergedFormatter[unit]) { + template = mergedFormatter[unit]; + } else if (mergedFormatter.inherit) { + var targetId = timeUnits.indexOf(unit); + + for (var i = targetId - 1; i >= 0; --i) { + if (mergedFormatter[unit]) { + template = mergedFormatter[unit]; + break; + } + } + + template = template || defaults$1.none; + } + + if (isArray(template)) { + var levelId = tick.level == null ? 0 : tick.level >= 0 ? tick.level : template.length + tick.level; + levelId = Math.min(levelId, template.length - 1); + template = template[levelId]; + } + } + + return format(new Date(tick.value), template, isUTC, lang); + } + function getUnitFromValue(value, isUTC) { + var date = parseDate(value); + var M = date[monthGetterName(isUTC)]() + 1; + var d = date[dateGetterName(isUTC)](); + var h = date[hoursGetterName(isUTC)](); + var m = date[minutesGetterName(isUTC)](); + var s = date[secondsGetterName(isUTC)](); + var S = date[millisecondsGetterName(isUTC)](); + var isSecond = S === 0; + var isMinute = isSecond && s === 0; + var isHour = isMinute && m === 0; + var isDay = isHour && h === 0; + var isMonth = isDay && d === 1; + var isYear = isMonth && M === 1; + + if (isYear) { + return 'year'; + } else if (isMonth) { + return 'month'; + } else if (isDay) { + return 'day'; + } else if (isHour) { + return 'hour'; + } else if (isMinute) { + return 'minute'; + } else if (isSecond) { + return 'second'; + } else { + return 'millisecond'; + } + } + function getUnitValue(value, unit, isUTC) { + var date = typeof value === 'number' ? parseDate(value) : value; + unit = unit || getUnitFromValue(value, isUTC); + + switch (unit) { + case 'year': + return date[fullYearGetterName(isUTC)](); + + case 'half-year': + return date[monthGetterName(isUTC)]() >= 6 ? 1 : 0; + + case 'quarter': + return Math.floor((date[monthGetterName(isUTC)]() + 1) / 4); + + case 'month': + return date[monthGetterName(isUTC)](); + + case 'day': + return date[dateGetterName(isUTC)](); + + case 'half-day': + return date[hoursGetterName(isUTC)]() / 24; + + case 'hour': + return date[hoursGetterName(isUTC)](); + + case 'minute': + return date[minutesGetterName(isUTC)](); + + case 'second': + return date[secondsGetterName(isUTC)](); + + case 'millisecond': + return date[millisecondsGetterName(isUTC)](); + } + } + function fullYearGetterName(isUTC) { + return isUTC ? 'getUTCFullYear' : 'getFullYear'; + } + function monthGetterName(isUTC) { + return isUTC ? 'getUTCMonth' : 'getMonth'; + } + function dateGetterName(isUTC) { + return isUTC ? 'getUTCDate' : 'getDate'; + } + function hoursGetterName(isUTC) { + return isUTC ? 'getUTCHours' : 'getHours'; + } + function minutesGetterName(isUTC) { + return isUTC ? 'getUTCMinutes' : 'getMinutes'; + } + function secondsGetterName(isUTC) { + return isUTC ? 'getUTCSeconds' : 'getSeconds'; + } + function millisecondsGetterName(isUTC) { + return isUTC ? 'getUTCSeconds' : 'getSeconds'; + } + function fullYearSetterName(isUTC) { + return isUTC ? 'setUTCFullYear' : 'setFullYear'; + } + function monthSetterName(isUTC) { + return isUTC ? 'setUTCMonth' : 'setMonth'; + } + function dateSetterName(isUTC) { + return isUTC ? 'setUTCDate' : 'setDate'; + } + function hoursSetterName(isUTC) { + return isUTC ? 'setUTCHours' : 'setHours'; + } + function minutesSetterName(isUTC) { + return isUTC ? 'setUTCMinutes' : 'setMinutes'; + } + function secondsSetterName(isUTC) { + return isUTC ? 'setUTCSeconds' : 'setSeconds'; + } + function millisecondsSetterName(isUTC) { + return isUTC ? 'setUTCSeconds' : 'setSeconds'; + } + + function getTextRect(text, font, align, verticalAlign, padding, rich, truncate, lineHeight) { + deprecateLog('getTextRect is deprecated.'); + var textEl = new ZRText({ + style: { + text: text, + font: font, + align: align, + verticalAlign: verticalAlign, + padding: padding, + rich: rich, + overflow: truncate ? 'truncate' : null, + lineHeight: lineHeight + } + }); + return textEl.getBoundingRect(); + } + + function addCommas(x) { + if (!isNumeric(x)) { + return isString(x) ? x : '-'; + } + + var parts = (x + '').split('.'); + return parts[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,') + (parts.length > 1 ? '.' + parts[1] : ''); + } + function toCamelCase(str, upperCaseFirst) { + str = (str || '').toLowerCase().replace(/-(.)/g, function (match, group1) { + return group1.toUpperCase(); + }); + + if (upperCaseFirst && str) { + str = str.charAt(0).toUpperCase() + str.slice(1); + } + + return str; + } + var normalizeCssArray$1 = normalizeCssArray; + var replaceReg = /([&<>"'])/g; + var replaceMap = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + '\'': ''' + }; + function encodeHTML(source) { + return source == null ? '' : (source + '').replace(replaceReg, function (str, c) { + return replaceMap[c]; + }); + } + function makeValueReadable(value, valueType, useUTC) { + var USER_READABLE_DEFUALT_TIME_PATTERN = 'yyyy-MM-dd hh:mm:ss'; + + function stringToUserReadable(str) { + return str && trim(str) ? str : '-'; + } + + function isNumberUserReadable(num) { + return !!(num != null && !isNaN(num) && isFinite(num)); + } + + var isTypeTime = valueType === 'time'; + var isValueDate = value instanceof Date; + + if (isTypeTime || isValueDate) { + var date = isTypeTime ? parseDate(value) : value; + + if (!isNaN(+date)) { + return format(date, USER_READABLE_DEFUALT_TIME_PATTERN, useUTC); + } else if (isValueDate) { + return '-'; + } + } + + if (valueType === 'ordinal') { + return isStringSafe(value) ? stringToUserReadable(value) : isNumber(value) ? isNumberUserReadable(value) ? value + '' : '-' : '-'; + } + + var numericResult = numericToNumber(value); + return isNumberUserReadable(numericResult) ? addCommas(numericResult) : isStringSafe(value) ? stringToUserReadable(value) : '-'; + } + var TPL_VAR_ALIAS = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; + + var wrapVar = function (varName, seriesIdx) { + return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}'; + }; + + function formatTpl(tpl, paramsList, encode) { + if (!isArray(paramsList)) { + paramsList = [paramsList]; + } + + var seriesLen = paramsList.length; + + if (!seriesLen) { + return ''; + } + + var $vars = paramsList[0].$vars || []; + + for (var i = 0; i < $vars.length; i++) { + var alias = TPL_VAR_ALIAS[i]; + tpl = tpl.replace(wrapVar(alias), wrapVar(alias, 0)); + } + + for (var seriesIdx = 0; seriesIdx < seriesLen; seriesIdx++) { + for (var k = 0; k < $vars.length; k++) { + var val = paramsList[seriesIdx][$vars[k]]; + tpl = tpl.replace(wrapVar(TPL_VAR_ALIAS[k], seriesIdx), encode ? encodeHTML(val) : val); + } + } + + return tpl; + } + function formatTplSimple(tpl, param, encode) { + each(param, function (value, key) { + tpl = tpl.replace('{' + key + '}', encode ? encodeHTML(value) : value); + }); + return tpl; + } + function getTooltipMarker(inOpt, extraCssText) { + var opt = isString(inOpt) ? { + color: inOpt, + extraCssText: extraCssText + } : inOpt || {}; + var color = opt.color; + var type = opt.type; + extraCssText = opt.extraCssText; + var renderMode = opt.renderMode || 'html'; + + if (!color) { + return ''; + } + + if (renderMode === 'html') { + return type === 'subItem' ? '' : ''; + } else { + var markerId = opt.markerId || 'markerX'; + return { + renderMode: renderMode, + content: '{' + markerId + '|} ', + style: type === 'subItem' ? { + width: 4, + height: 4, + borderRadius: 2, + backgroundColor: color + } : { + width: 10, + height: 10, + borderRadius: 5, + backgroundColor: color + } + }; + } + } + function formatTime(tpl, value, isUTC) { + if ("development" !== 'production') { + deprecateReplaceLog('echarts.format.formatTime', 'echarts.time.format'); + } + + if (tpl === 'week' || tpl === 'month' || tpl === 'quarter' || tpl === 'half-year' || tpl === 'year') { + tpl = 'MM-dd\nyyyy'; + } + + var date = parseDate(value); + var utc = isUTC ? 'UTC' : ''; + var y = date['get' + utc + 'FullYear'](); + var M = date['get' + utc + 'Month']() + 1; + var d = date['get' + utc + 'Date'](); + var h = date['get' + utc + 'Hours'](); + var m = date['get' + utc + 'Minutes'](); + var s = date['get' + utc + 'Seconds'](); + var S = date['get' + utc + 'Milliseconds'](); + tpl = tpl.replace('MM', pad(M, 2)).replace('M', M).replace('yyyy', y).replace('yy', y % 100 + '').replace('dd', pad(d, 2)).replace('d', d).replace('hh', pad(h, 2)).replace('h', h).replace('mm', pad(m, 2)).replace('m', m).replace('ss', pad(s, 2)).replace('s', s).replace('SSS', pad(S, 3)); + return tpl; + } + function capitalFirst(str) { + return str ? str.charAt(0).toUpperCase() + str.substr(1) : str; + } + function convertToColorString(color, defaultColor) { + defaultColor = defaultColor || 'transparent'; + return isString(color) ? color : isObject(color) ? color.colorStops && (color.colorStops[0] || {}).color || defaultColor : defaultColor; + } + function windowOpen(link, target) { + if (target === '_blank' || target === 'blank') { + var blank = window.open(); + blank.opener = null; + blank.location.href = link; + } else { + window.open(link, target); + } + } + + var each$1 = each; + var LOCATION_PARAMS = ['left', 'right', 'top', 'bottom', 'width', 'height']; + var HV_NAMES = [['width', 'left', 'right'], ['height', 'top', 'bottom']]; + + function boxLayout(orient, group, gap, maxWidth, maxHeight) { + var x = 0; + var y = 0; + + if (maxWidth == null) { + maxWidth = Infinity; + } + + if (maxHeight == null) { + maxHeight = Infinity; + } + + var currentLineMaxSize = 0; + group.eachChild(function (child, idx) { + var rect = child.getBoundingRect(); + var nextChild = group.childAt(idx + 1); + var nextChildRect = nextChild && nextChild.getBoundingRect(); + var nextX; + var nextY; + + if (orient === 'horizontal') { + var moveX = rect.width + (nextChildRect ? -nextChildRect.x + rect.x : 0); + nextX = x + moveX; + + if (nextX > maxWidth || child.newline) { + x = 0; + nextX = moveX; + y += currentLineMaxSize + gap; + currentLineMaxSize = rect.height; + } else { + currentLineMaxSize = Math.max(currentLineMaxSize, rect.height); + } + } else { + var moveY = rect.height + (nextChildRect ? -nextChildRect.y + rect.y : 0); + nextY = y + moveY; + + if (nextY > maxHeight || child.newline) { + x += currentLineMaxSize + gap; + y = 0; + nextY = moveY; + currentLineMaxSize = rect.width; + } else { + currentLineMaxSize = Math.max(currentLineMaxSize, rect.width); + } + } + + if (child.newline) { + return; + } + + child.x = x; + child.y = y; + child.markRedraw(); + orient === 'horizontal' ? x = nextX + gap : y = nextY + gap; + }); + } + + var box = boxLayout; + var vbox = curry(boxLayout, 'vertical'); + var hbox = curry(boxLayout, 'horizontal'); + function getAvailableSize(positionInfo, containerRect, margin) { + var containerWidth = containerRect.width; + var containerHeight = containerRect.height; + var x = parsePercent$1(positionInfo.left, containerWidth); + var y = parsePercent$1(positionInfo.top, containerHeight); + var x2 = parsePercent$1(positionInfo.right, containerWidth); + var y2 = parsePercent$1(positionInfo.bottom, containerHeight); + (isNaN(x) || isNaN(parseFloat(positionInfo.left))) && (x = 0); + (isNaN(x2) || isNaN(parseFloat(positionInfo.right))) && (x2 = containerWidth); + (isNaN(y) || isNaN(parseFloat(positionInfo.top))) && (y = 0); + (isNaN(y2) || isNaN(parseFloat(positionInfo.bottom))) && (y2 = containerHeight); + margin = normalizeCssArray$1(margin || 0); + return { + width: Math.max(x2 - x - margin[1] - margin[3], 0), + height: Math.max(y2 - y - margin[0] - margin[2], 0) + }; + } + function getLayoutRect(positionInfo, containerRect, margin) { + margin = normalizeCssArray$1(margin || 0); + var containerWidth = containerRect.width; + var containerHeight = containerRect.height; + var left = parsePercent$1(positionInfo.left, containerWidth); + var top = parsePercent$1(positionInfo.top, containerHeight); + var right = parsePercent$1(positionInfo.right, containerWidth); + var bottom = parsePercent$1(positionInfo.bottom, containerHeight); + var width = parsePercent$1(positionInfo.width, containerWidth); + var height = parsePercent$1(positionInfo.height, containerHeight); + var verticalMargin = margin[2] + margin[0]; + var horizontalMargin = margin[1] + margin[3]; + var aspect = positionInfo.aspect; + + if (isNaN(width)) { + width = containerWidth - right - horizontalMargin - left; + } + + if (isNaN(height)) { + height = containerHeight - bottom - verticalMargin - top; + } + + if (aspect != null) { + if (isNaN(width) && isNaN(height)) { + if (aspect > containerWidth / containerHeight) { + width = containerWidth * 0.8; + } else { + height = containerHeight * 0.8; + } + } + + if (isNaN(width)) { + width = aspect * height; + } + + if (isNaN(height)) { + height = width / aspect; + } + } + + if (isNaN(left)) { + left = containerWidth - right - width - horizontalMargin; + } + + if (isNaN(top)) { + top = containerHeight - bottom - height - verticalMargin; + } + + switch (positionInfo.left || positionInfo.right) { + case 'center': + left = containerWidth / 2 - width / 2 - margin[3]; + break; + + case 'right': + left = containerWidth - width - horizontalMargin; + break; + } + + switch (positionInfo.top || positionInfo.bottom) { + case 'middle': + case 'center': + top = containerHeight / 2 - height / 2 - margin[0]; + break; + + case 'bottom': + top = containerHeight - height - verticalMargin; + break; + } + + left = left || 0; + top = top || 0; + + if (isNaN(width)) { + width = containerWidth - horizontalMargin - left - (right || 0); + } + + if (isNaN(height)) { + height = containerHeight - verticalMargin - top - (bottom || 0); + } + + var rect = new BoundingRect(left + margin[3], top + margin[0], width, height); + rect.margin = margin; + return rect; + } + function positionElement(el, positionInfo, containerRect, margin, opt) { + var h = !opt || !opt.hv || opt.hv[0]; + var v = !opt || !opt.hv || opt.hv[1]; + var boundingMode = opt && opt.boundingMode || 'all'; + + if (!h && !v) { + return; + } + + var rect; + + if (boundingMode === 'raw') { + rect = el.type === 'group' ? new BoundingRect(0, 0, +positionInfo.width || 0, +positionInfo.height || 0) : el.getBoundingRect(); + } else { + rect = el.getBoundingRect(); + + if (el.needLocalTransform()) { + var transform = el.getLocalTransform(); + rect = rect.clone(); + rect.applyTransform(transform); + } + } + + var layoutRect = getLayoutRect(defaults({ + width: rect.width, + height: rect.height + }, positionInfo), containerRect, margin); + var dx = h ? layoutRect.x - rect.x : 0; + var dy = v ? layoutRect.y - rect.y : 0; + + if (boundingMode === 'raw') { + el.x = dx; + el.y = dy; + } else { + el.x += dx; + el.y += dy; + } + + el.markRedraw(); + } + function sizeCalculable(option, hvIdx) { + return option[HV_NAMES[hvIdx][0]] != null || option[HV_NAMES[hvIdx][1]] != null && option[HV_NAMES[hvIdx][2]] != null; + } + function fetchLayoutMode(ins) { + var layoutMode = ins.layoutMode || ins.constructor.layoutMode; + return isObject(layoutMode) ? layoutMode : layoutMode ? { + type: layoutMode + } : null; + } + function mergeLayoutParam(targetOption, newOption, opt) { + var ignoreSize = opt && opt.ignoreSize; + !isArray(ignoreSize) && (ignoreSize = [ignoreSize, ignoreSize]); + var hResult = merge(HV_NAMES[0], 0); + var vResult = merge(HV_NAMES[1], 1); + copy(HV_NAMES[0], targetOption, hResult); + copy(HV_NAMES[1], targetOption, vResult); + + function merge(names, hvIdx) { + var newParams = {}; + var newValueCount = 0; + var merged = {}; + var mergedValueCount = 0; + var enoughParamNumber = 2; + each$1(names, function (name) { + merged[name] = targetOption[name]; + }); + each$1(names, function (name) { + hasProp(newOption, name) && (newParams[name] = merged[name] = newOption[name]); + hasValue(newParams, name) && newValueCount++; + hasValue(merged, name) && mergedValueCount++; + }); + + if (ignoreSize[hvIdx]) { + if (hasValue(newOption, names[1])) { + merged[names[2]] = null; + } else if (hasValue(newOption, names[2])) { + merged[names[1]] = null; + } + + return merged; + } + + if (mergedValueCount === enoughParamNumber || !newValueCount) { + return merged; + } else if (newValueCount >= enoughParamNumber) { + return newParams; + } else { + for (var i = 0; i < names.length; i++) { + var name_1 = names[i]; + + if (!hasProp(newParams, name_1) && hasProp(targetOption, name_1)) { + newParams[name_1] = targetOption[name_1]; + break; + } + } + + return newParams; + } + } + + function hasProp(obj, name) { + return obj.hasOwnProperty(name); + } + + function hasValue(obj, name) { + return obj[name] != null && obj[name] !== 'auto'; + } + + function copy(names, target, source) { + each$1(names, function (name) { + target[name] = source[name]; + }); + } + } + function getLayoutParams(source) { + return copyLayoutParams({}, source); + } + function copyLayoutParams(target, source) { + source && target && each$1(LOCATION_PARAMS, function (name) { + source.hasOwnProperty(name) && (target[name] = source[name]); + }); + return target; + } + + var inner = makeInner(); + + var ComponentModel = function (_super) { + __extends(ComponentModel, _super); + + function ComponentModel(option, parentModel, ecModel) { + var _this = _super.call(this, option, parentModel, ecModel) || this; + + _this.uid = getUID('ec_cpt_model'); + return _this; + } + + ComponentModel.prototype.init = function (option, parentModel, ecModel) { + this.mergeDefaultAndTheme(option, ecModel); + }; + + ComponentModel.prototype.mergeDefaultAndTheme = function (option, ecModel) { + var layoutMode = fetchLayoutMode(this); + var inputPositionParams = layoutMode ? getLayoutParams(option) : {}; + var themeModel = ecModel.getTheme(); + merge(option, themeModel.get(this.mainType)); + merge(option, this.getDefaultOption()); + + if (layoutMode) { + mergeLayoutParam(option, inputPositionParams, layoutMode); + } + }; + + ComponentModel.prototype.mergeOption = function (option, ecModel) { + merge(this.option, option, true); + var layoutMode = fetchLayoutMode(this); + + if (layoutMode) { + mergeLayoutParam(this.option, option, layoutMode); + } + }; + + ComponentModel.prototype.optionUpdated = function (newCptOption, isInit) {}; + + ComponentModel.prototype.getDefaultOption = function () { + var ctor = this.constructor; + + if (!isExtendedClass(ctor)) { + return ctor.defaultOption; + } + + var fields = inner(this); + + if (!fields.defaultOption) { + var optList = []; + var clz = ctor; + + while (clz) { + var opt = clz.prototype.defaultOption; + opt && optList.push(opt); + clz = clz.superClass; + } + + var defaultOption = {}; + + for (var i = optList.length - 1; i >= 0; i--) { + defaultOption = merge(defaultOption, optList[i], true); + } + + fields.defaultOption = defaultOption; + } + + return fields.defaultOption; + }; + + ComponentModel.prototype.getReferringComponents = function (mainType, opt) { + var indexKey = mainType + 'Index'; + var idKey = mainType + 'Id'; + return queryReferringComponents(this.ecModel, mainType, { + index: this.get(indexKey, true), + id: this.get(idKey, true) + }, opt); + }; + + ComponentModel.prototype.getBoxLayoutParams = function () { + var boxLayoutModel = this; + return { + left: boxLayoutModel.get('left'), + top: boxLayoutModel.get('top'), + right: boxLayoutModel.get('right'), + bottom: boxLayoutModel.get('bottom'), + width: boxLayoutModel.get('width'), + height: boxLayoutModel.get('height') + }; + }; + + ComponentModel.protoInitialize = function () { + var proto = ComponentModel.prototype; + proto.type = 'component'; + proto.id = ''; + proto.name = ''; + proto.mainType = ''; + proto.subType = ''; + proto.componentIndex = 0; + }(); + + return ComponentModel; + }(Model); + + mountExtend(ComponentModel, Model); + enableClassManagement(ComponentModel); + enableSubTypeDefaulter(ComponentModel); + enableTopologicalTravel(ComponentModel, getDependencies); + + function getDependencies(componentType) { + var deps = []; + each(ComponentModel.getClassesByMainType(componentType), function (clz) { + deps = deps.concat(clz.dependencies || clz.prototype.dependencies || []); + }); + deps = map(deps, function (type) { + return parseClassType(type).main; + }); + + if (componentType !== 'dataset' && indexOf(deps, 'dataset') <= 0) { + deps.unshift('dataset'); + } + + return deps; + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var platform = ''; + + if (typeof navigator !== 'undefined') { + platform = navigator.platform || ''; + } + + var decalColor = 'rgba(0, 0, 0, 0.2)'; + var globalDefault = { + darkMode: 'auto', + color: ['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'], + gradientColor: ['#f6efa6', '#d88273', '#bf444c'], + aria: { + decal: { + decals: [{ + color: decalColor, + dashArrayX: [1, 0], + dashArrayY: [2, 5], + symbolSize: 1, + rotation: Math.PI / 6 + }, { + color: decalColor, + symbol: 'circle', + dashArrayX: [[8, 8], [0, 8, 8, 0]], + dashArrayY: [6, 0], + symbolSize: 0.8 + }, { + color: decalColor, + dashArrayX: [1, 0], + dashArrayY: [4, 3], + rotation: -Math.PI / 4 + }, { + color: decalColor, + dashArrayX: [[6, 6], [0, 6, 6, 0]], + dashArrayY: [6, 0] + }, { + color: decalColor, + dashArrayX: [[1, 0], [1, 6]], + dashArrayY: [1, 0, 6, 0], + rotation: Math.PI / 4 + }, { + color: decalColor, + symbol: 'triangle', + dashArrayX: [[9, 9], [0, 9, 9, 0]], + dashArrayY: [7, 2], + symbolSize: 0.75 + }] + } + }, + textStyle: { + fontFamily: platform.match(/^Win/) ? 'Microsoft YaHei' : 'sans-serif', + fontSize: 12, + fontStyle: 'normal', + fontWeight: 'normal' + }, + blendMode: null, + stateAnimation: { + duration: 300, + easing: 'cubicOut' + }, + animation: 'auto', + animationDuration: 1000, + animationDurationUpdate: 500, + animationEasing: 'cubicInOut', + animationEasingUpdate: 'cubicInOut', + animationThreshold: 2000, + progressiveThreshold: 3000, + progressive: 400, + hoverLayerThreshold: 3000, + useUTC: false + }; + + var VISUAL_DIMENSIONS = createHashMap(['tooltip', 'label', 'itemName', 'itemId', 'seriesName']); + var SOURCE_FORMAT_ORIGINAL = 'original'; + var SOURCE_FORMAT_ARRAY_ROWS = 'arrayRows'; + var SOURCE_FORMAT_OBJECT_ROWS = 'objectRows'; + var SOURCE_FORMAT_KEYED_COLUMNS = 'keyedColumns'; + var SOURCE_FORMAT_TYPED_ARRAY = 'typedArray'; + var SOURCE_FORMAT_UNKNOWN = 'unknown'; + var SERIES_LAYOUT_BY_COLUMN = 'column'; + var SERIES_LAYOUT_BY_ROW = 'row'; + + var BE_ORDINAL = { + Must: 1, + Might: 2, + Not: 3 + }; + var innerGlobalModel = makeInner(); + function resetSourceDefaulter(ecModel) { + innerGlobalModel(ecModel).datasetMap = createHashMap(); + } + function makeSeriesEncodeForAxisCoordSys(coordDimensions, seriesModel, source) { + var encode = {}; + var datasetModel = querySeriesUpstreamDatasetModel(seriesModel); + + if (!datasetModel || !coordDimensions) { + return encode; + } + + var encodeItemName = []; + var encodeSeriesName = []; + var ecModel = seriesModel.ecModel; + var datasetMap = innerGlobalModel(ecModel).datasetMap; + var key = datasetModel.uid + '_' + source.seriesLayoutBy; + var baseCategoryDimIndex; + var categoryWayValueDimStart; + coordDimensions = coordDimensions.slice(); + each(coordDimensions, function (coordDimInfoLoose, coordDimIdx) { + var coordDimInfo = isObject(coordDimInfoLoose) ? coordDimInfoLoose : coordDimensions[coordDimIdx] = { + name: coordDimInfoLoose + }; + + if (coordDimInfo.type === 'ordinal' && baseCategoryDimIndex == null) { + baseCategoryDimIndex = coordDimIdx; + categoryWayValueDimStart = getDataDimCountOnCoordDim(coordDimInfo); + } + + encode[coordDimInfo.name] = []; + }); + var datasetRecord = datasetMap.get(key) || datasetMap.set(key, { + categoryWayDim: categoryWayValueDimStart, + valueWayDim: 0 + }); + each(coordDimensions, function (coordDimInfo, coordDimIdx) { + var coordDimName = coordDimInfo.name; + var count = getDataDimCountOnCoordDim(coordDimInfo); + + if (baseCategoryDimIndex == null) { + var start = datasetRecord.valueWayDim; + pushDim(encode[coordDimName], start, count); + pushDim(encodeSeriesName, start, count); + datasetRecord.valueWayDim += count; + } else if (baseCategoryDimIndex === coordDimIdx) { + pushDim(encode[coordDimName], 0, count); + pushDim(encodeItemName, 0, count); + } else { + var start = datasetRecord.categoryWayDim; + pushDim(encode[coordDimName], start, count); + pushDim(encodeSeriesName, start, count); + datasetRecord.categoryWayDim += count; + } + }); + + function pushDim(dimIdxArr, idxFrom, idxCount) { + for (var i = 0; i < idxCount; i++) { + dimIdxArr.push(idxFrom + i); + } + } + + function getDataDimCountOnCoordDim(coordDimInfo) { + var dimsDef = coordDimInfo.dimsDef; + return dimsDef ? dimsDef.length : 1; + } + + encodeItemName.length && (encode.itemName = encodeItemName); + encodeSeriesName.length && (encode.seriesName = encodeSeriesName); + return encode; + } + function makeSeriesEncodeForNameBased(seriesModel, source, dimCount) { + var encode = {}; + var datasetModel = querySeriesUpstreamDatasetModel(seriesModel); + + if (!datasetModel) { + return encode; + } + + var sourceFormat = source.sourceFormat; + var dimensionsDefine = source.dimensionsDefine; + var potentialNameDimIndex; + + if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS || sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) { + each(dimensionsDefine, function (dim, idx) { + if ((isObject(dim) ? dim.name : dim) === 'name') { + potentialNameDimIndex = idx; + } + }); + } + + var idxResult = function () { + var idxRes0 = {}; + var idxRes1 = {}; + var guessRecords = []; + + for (var i = 0, len = Math.min(5, dimCount); i < len; i++) { + var guessResult = doGuessOrdinal(source.data, sourceFormat, source.seriesLayoutBy, dimensionsDefine, source.startIndex, i); + guessRecords.push(guessResult); + var isPureNumber = guessResult === BE_ORDINAL.Not; + + if (isPureNumber && idxRes0.v == null && i !== potentialNameDimIndex) { + idxRes0.v = i; + } + + if (idxRes0.n == null || idxRes0.n === idxRes0.v || !isPureNumber && guessRecords[idxRes0.n] === BE_ORDINAL.Not) { + idxRes0.n = i; + } + + if (fulfilled(idxRes0) && guessRecords[idxRes0.n] !== BE_ORDINAL.Not) { + return idxRes0; + } + + if (!isPureNumber) { + if (guessResult === BE_ORDINAL.Might && idxRes1.v == null && i !== potentialNameDimIndex) { + idxRes1.v = i; + } + + if (idxRes1.n == null || idxRes1.n === idxRes1.v) { + idxRes1.n = i; + } + } + } + + function fulfilled(idxResult) { + return idxResult.v != null && idxResult.n != null; + } + + return fulfilled(idxRes0) ? idxRes0 : fulfilled(idxRes1) ? idxRes1 : null; + }(); + + if (idxResult) { + encode.value = [idxResult.v]; + var nameDimIndex = potentialNameDimIndex != null ? potentialNameDimIndex : idxResult.n; + encode.itemName = [nameDimIndex]; + encode.seriesName = [nameDimIndex]; + } + + return encode; + } + function querySeriesUpstreamDatasetModel(seriesModel) { + var thisData = seriesModel.get('data', true); + + if (!thisData) { + return queryReferringComponents(seriesModel.ecModel, 'dataset', { + index: seriesModel.get('datasetIndex', true), + id: seriesModel.get('datasetId', true) + }, SINGLE_REFERRING).models[0]; + } + } + function queryDatasetUpstreamDatasetModels(datasetModel) { + if (!datasetModel.get('transform', true) && !datasetModel.get('fromTransformResult', true)) { + return []; + } + + return queryReferringComponents(datasetModel.ecModel, 'dataset', { + index: datasetModel.get('fromDatasetIndex', true), + id: datasetModel.get('fromDatasetId', true) + }, SINGLE_REFERRING).models; + } + function guessOrdinal(source, dimIndex) { + return doGuessOrdinal(source.data, source.sourceFormat, source.seriesLayoutBy, source.dimensionsDefine, source.startIndex, dimIndex); + } + + function doGuessOrdinal(data, sourceFormat, seriesLayoutBy, dimensionsDefine, startIndex, dimIndex) { + var result; + var maxLoop = 5; + + if (isTypedArray(data)) { + return BE_ORDINAL.Not; + } + + var dimName; + var dimType; + + if (dimensionsDefine) { + var dimDefItem = dimensionsDefine[dimIndex]; + + if (isObject(dimDefItem)) { + dimName = dimDefItem.name; + dimType = dimDefItem.type; + } else if (isString(dimDefItem)) { + dimName = dimDefItem; + } + } + + if (dimType != null) { + return dimType === 'ordinal' ? BE_ORDINAL.Must : BE_ORDINAL.Not; + } + + if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) { + var dataArrayRows = data; + + if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) { + var sample = dataArrayRows[dimIndex]; + + for (var i = 0; i < (sample || []).length && i < maxLoop; i++) { + if ((result = detectValue(sample[startIndex + i])) != null) { + return result; + } + } + } else { + for (var i = 0; i < dataArrayRows.length && i < maxLoop; i++) { + var row = dataArrayRows[startIndex + i]; + + if (row && (result = detectValue(row[dimIndex])) != null) { + return result; + } + } + } + } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) { + var dataObjectRows = data; + + if (!dimName) { + return BE_ORDINAL.Not; + } + + for (var i = 0; i < dataObjectRows.length && i < maxLoop; i++) { + var item = dataObjectRows[i]; + + if (item && (result = detectValue(item[dimName])) != null) { + return result; + } + } + } else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) { + var dataKeyedColumns = data; + + if (!dimName) { + return BE_ORDINAL.Not; + } + + var sample = dataKeyedColumns[dimName]; + + if (!sample || isTypedArray(sample)) { + return BE_ORDINAL.Not; + } + + for (var i = 0; i < sample.length && i < maxLoop; i++) { + if ((result = detectValue(sample[i])) != null) { + return result; + } + } + } else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) { + var dataOriginal = data; + + for (var i = 0; i < dataOriginal.length && i < maxLoop; i++) { + var item = dataOriginal[i]; + var val = getDataItemValue(item); + + if (!isArray(val)) { + return BE_ORDINAL.Not; + } + + if ((result = detectValue(val[dimIndex])) != null) { + return result; + } + } + } + + function detectValue(val) { + var beStr = isString(val); + + if (val != null && isFinite(val) && val !== '') { + return beStr ? BE_ORDINAL.Might : BE_ORDINAL.Not; + } else if (beStr && val !== '-') { + return BE_ORDINAL.Must; + } + } + + return BE_ORDINAL.Not; + } + + var internalOptionCreatorMap = createHashMap(); + function registerInternalOptionCreator(mainType, creator) { + assert(internalOptionCreatorMap.get(mainType) == null && creator); + internalOptionCreatorMap.set(mainType, creator); + } + function concatInternalOptions(ecModel, mainType, newCmptOptionList) { + var internalOptionCreator = internalOptionCreatorMap.get(mainType); + + if (!internalOptionCreator) { + return newCmptOptionList; + } + + var internalOptions = internalOptionCreator(ecModel); + + if (!internalOptions) { + return newCmptOptionList; + } + + if ("development" !== 'production') { + for (var i = 0; i < internalOptions.length; i++) { + assert(isComponentIdInternal(internalOptions[i])); + } + } + + return newCmptOptionList.concat(internalOptions); + } + + var innerColor = makeInner(); + var innerDecal = makeInner(); + + var PaletteMixin = function () { + function PaletteMixin() {} + + PaletteMixin.prototype.getColorFromPalette = function (name, scope, requestNum) { + var defaultPalette = normalizeToArray(this.get('color', true)); + var layeredPalette = this.get('colorLayer', true); + return getFromPalette(this, innerColor, defaultPalette, layeredPalette, name, scope, requestNum); + }; + + PaletteMixin.prototype.clearColorPalette = function () { + clearPalette(this, innerColor); + }; + + return PaletteMixin; + }(); + + function getDecalFromPalette(ecModel, name, scope, requestNum) { + var defaultDecals = normalizeToArray(ecModel.get(['aria', 'decal', 'decals'])); + return getFromPalette(ecModel, innerDecal, defaultDecals, null, name, scope, requestNum); + } + + function getNearestPalette(palettes, requestColorNum) { + var paletteNum = palettes.length; + + for (var i = 0; i < paletteNum; i++) { + if (palettes[i].length > requestColorNum) { + return palettes[i]; + } + } + + return palettes[paletteNum - 1]; + } + + function getFromPalette(that, inner, defaultPalette, layeredPalette, name, scope, requestNum) { + scope = scope || that; + var scopeFields = inner(scope); + var paletteIdx = scopeFields.paletteIdx || 0; + var paletteNameMap = scopeFields.paletteNameMap = scopeFields.paletteNameMap || {}; + + if (paletteNameMap.hasOwnProperty(name)) { + return paletteNameMap[name]; + } + + var palette = requestNum == null || !layeredPalette ? defaultPalette : getNearestPalette(layeredPalette, requestNum); + palette = palette || defaultPalette; + + if (!palette || !palette.length) { + return; + } + + var pickedPaletteItem = palette[paletteIdx]; + + if (name) { + paletteNameMap[name] = pickedPaletteItem; + } + + scopeFields.paletteIdx = (paletteIdx + 1) % palette.length; + return pickedPaletteItem; + } + + function clearPalette(that, inner) { + inner(that).paletteIdx = 0; + inner(that).paletteNameMap = {}; + } + + var reCreateSeriesIndices; + var assertSeriesInitialized; + var initBase; + var OPTION_INNER_KEY = '\0_ec_inner'; + var OPTION_INNER_VALUE = 1; + + var GlobalModel = function (_super) { + __extends(GlobalModel, _super); + + function GlobalModel() { + return _super !== null && _super.apply(this, arguments) || this; + } + + GlobalModel.prototype.init = function (option, parentModel, ecModel, theme, locale, optionManager) { + theme = theme || {}; + this.option = null; + this._theme = new Model(theme); + this._locale = new Model(locale); + this._optionManager = optionManager; + }; + + GlobalModel.prototype.setOption = function (option, opts, optionPreprocessorFuncs) { + if ("development" !== 'production') { + assert(option != null, 'option is null/undefined'); + assert(option[OPTION_INNER_KEY] !== OPTION_INNER_VALUE, 'please use chart.getOption()'); + } + + var innerOpt = normalizeSetOptionInput(opts); + + this._optionManager.setOption(option, optionPreprocessorFuncs, innerOpt); + + this._resetOption(null, innerOpt); + }; + + GlobalModel.prototype.resetOption = function (type, opt) { + return this._resetOption(type, normalizeSetOptionInput(opt)); + }; + + GlobalModel.prototype._resetOption = function (type, opt) { + var optionChanged = false; + var optionManager = this._optionManager; + + if (!type || type === 'recreate') { + var baseOption = optionManager.mountOption(type === 'recreate'); + + if (!this.option || type === 'recreate') { + initBase(this, baseOption); + } else { + this.restoreData(); + + this._mergeOption(baseOption, opt); + } + + optionChanged = true; + } + + if (type === 'timeline' || type === 'media') { + this.restoreData(); + } + + if (!type || type === 'recreate' || type === 'timeline') { + var timelineOption = optionManager.getTimelineOption(this); + + if (timelineOption) { + optionChanged = true; + + this._mergeOption(timelineOption, opt); + } + } + + if (!type || type === 'recreate' || type === 'media') { + var mediaOptions = optionManager.getMediaOption(this); + + if (mediaOptions.length) { + each(mediaOptions, function (mediaOption) { + optionChanged = true; + + this._mergeOption(mediaOption, opt); + }, this); + } + } + + return optionChanged; + }; + + GlobalModel.prototype.mergeOption = function (option) { + this._mergeOption(option, null); + }; + + GlobalModel.prototype._mergeOption = function (newOption, opt) { + var option = this.option; + var componentsMap = this._componentsMap; + var componentsCount = this._componentsCount; + var newCmptTypes = []; + var newCmptTypeMap = createHashMap(); + var replaceMergeMainTypeMap = opt && opt.replaceMergeMainTypeMap; + resetSourceDefaulter(this); + each(newOption, function (componentOption, mainType) { + if (componentOption == null) { + return; + } + + if (!ComponentModel.hasClass(mainType)) { + option[mainType] = option[mainType] == null ? clone(componentOption) : merge(option[mainType], componentOption, true); + } else if (mainType) { + newCmptTypes.push(mainType); + newCmptTypeMap.set(mainType, true); + } + }); + + if (replaceMergeMainTypeMap) { + replaceMergeMainTypeMap.each(function (val, mainTypeInReplaceMerge) { + if (ComponentModel.hasClass(mainTypeInReplaceMerge) && !newCmptTypeMap.get(mainTypeInReplaceMerge)) { + newCmptTypes.push(mainTypeInReplaceMerge); + newCmptTypeMap.set(mainTypeInReplaceMerge, true); + } + }); + } + + ComponentModel.topologicalTravel(newCmptTypes, ComponentModel.getAllClassMainTypes(), visitComponent, this); + + function visitComponent(mainType) { + var newCmptOptionList = concatInternalOptions(this, mainType, normalizeToArray(newOption[mainType])); + var oldCmptList = componentsMap.get(mainType); + var mergeMode = !oldCmptList ? 'replaceAll' : replaceMergeMainTypeMap && replaceMergeMainTypeMap.get(mainType) ? 'replaceMerge' : 'normalMerge'; + var mappingResult = mappingToExists(oldCmptList, newCmptOptionList, mergeMode); + setComponentTypeToKeyInfo(mappingResult, mainType, ComponentModel); + option[mainType] = null; + componentsMap.set(mainType, null); + componentsCount.set(mainType, 0); + var optionsByMainType = []; + var cmptsByMainType = []; + var cmptsCountByMainType = 0; + each(mappingResult, function (resultItem, index) { + var componentModel = resultItem.existing; + var newCmptOption = resultItem.newOption; + + if (!newCmptOption) { + if (componentModel) { + componentModel.mergeOption({}, this); + componentModel.optionUpdated({}, false); + } + } else { + var ComponentModelClass = ComponentModel.getClass(mainType, resultItem.keyInfo.subType, true); + + if (componentModel && componentModel.constructor === ComponentModelClass) { + componentModel.name = resultItem.keyInfo.name; + componentModel.mergeOption(newCmptOption, this); + componentModel.optionUpdated(newCmptOption, false); + } else { + var extraOpt = extend({ + componentIndex: index + }, resultItem.keyInfo); + componentModel = new ComponentModelClass(newCmptOption, this, this, extraOpt); + extend(componentModel, extraOpt); + + if (resultItem.brandNew) { + componentModel.__requireNewView = true; + } + + componentModel.init(newCmptOption, this, this); + componentModel.optionUpdated(null, true); + } + } + + if (componentModel) { + optionsByMainType.push(componentModel.option); + cmptsByMainType.push(componentModel); + cmptsCountByMainType++; + } else { + optionsByMainType.push(void 0); + cmptsByMainType.push(void 0); + } + }, this); + option[mainType] = optionsByMainType; + componentsMap.set(mainType, cmptsByMainType); + componentsCount.set(mainType, cmptsCountByMainType); + + if (mainType === 'series') { + reCreateSeriesIndices(this); + } + } + + if (!this._seriesIndices) { + reCreateSeriesIndices(this); + } + }; + + GlobalModel.prototype.getOption = function () { + var option = clone(this.option); + each(option, function (optInMainType, mainType) { + if (ComponentModel.hasClass(mainType)) { + var opts = normalizeToArray(optInMainType); + var realLen = opts.length; + var metNonInner = false; + + for (var i = realLen - 1; i >= 0; i--) { + if (opts[i] && !isComponentIdInternal(opts[i])) { + metNonInner = true; + } else { + opts[i] = null; + !metNonInner && realLen--; + } + } + + opts.length = realLen; + option[mainType] = opts; + } + }); + delete option[OPTION_INNER_KEY]; + return option; + }; + + GlobalModel.prototype.getTheme = function () { + return this._theme; + }; + + GlobalModel.prototype.getLocaleModel = function () { + return this._locale; + }; + + GlobalModel.prototype.getLocale = function (localePosition) { + var locale = this.getLocaleModel(); + return locale.get(localePosition); + }; + + GlobalModel.prototype.setUpdatePayload = function (payload) { + this._payload = payload; + }; + + GlobalModel.prototype.getUpdatePayload = function () { + return this._payload; + }; + + GlobalModel.prototype.getComponent = function (mainType, idx) { + var list = this._componentsMap.get(mainType); + + if (list) { + var cmpt = list[idx || 0]; + + if (cmpt) { + return cmpt; + } else if (idx == null) { + for (var i = 0; i < list.length; i++) { + if (list[i]) { + return list[i]; + } + } + } + } + }; + + GlobalModel.prototype.queryComponents = function (condition) { + var mainType = condition.mainType; + + if (!mainType) { + return []; + } + + var index = condition.index; + var id = condition.id; + var name = condition.name; + + var cmpts = this._componentsMap.get(mainType); + + if (!cmpts || !cmpts.length) { + return []; + } + + var result; + + if (index != null) { + result = []; + each(normalizeToArray(index), function (idx) { + cmpts[idx] && result.push(cmpts[idx]); + }); + } else if (id != null) { + result = queryByIdOrName('id', id, cmpts); + } else if (name != null) { + result = queryByIdOrName('name', name, cmpts); + } else { + result = filter(cmpts, function (cmpt) { + return !!cmpt; + }); + } + + return filterBySubType(result, condition); + }; + + GlobalModel.prototype.findComponents = function (condition) { + var query = condition.query; + var mainType = condition.mainType; + var queryCond = getQueryCond(query); + var result = queryCond ? this.queryComponents(queryCond) : filter(this._componentsMap.get(mainType), function (cmpt) { + return !!cmpt; + }); + return doFilter(filterBySubType(result, condition)); + + function getQueryCond(q) { + var indexAttr = mainType + 'Index'; + var idAttr = mainType + 'Id'; + var nameAttr = mainType + 'Name'; + return q && (q[indexAttr] != null || q[idAttr] != null || q[nameAttr] != null) ? { + mainType: mainType, + index: q[indexAttr], + id: q[idAttr], + name: q[nameAttr] + } : null; + } + + function doFilter(res) { + return condition.filter ? filter(res, condition.filter) : res; + } + }; + + GlobalModel.prototype.eachComponent = function (mainType, cb, context) { + var componentsMap = this._componentsMap; + + if (isFunction(mainType)) { + var ctxForAll_1 = cb; + var cbForAll_1 = mainType; + componentsMap.each(function (cmpts, componentType) { + for (var i = 0; cmpts && i < cmpts.length; i++) { + var cmpt = cmpts[i]; + cmpt && cbForAll_1.call(ctxForAll_1, componentType, cmpt, cmpt.componentIndex); + } + }); + } else { + var cmpts = isString(mainType) ? componentsMap.get(mainType) : isObject(mainType) ? this.findComponents(mainType) : null; + + for (var i = 0; cmpts && i < cmpts.length; i++) { + var cmpt = cmpts[i]; + cmpt && cb.call(context, cmpt, cmpt.componentIndex); + } + } + }; + + GlobalModel.prototype.getSeriesByName = function (name) { + var nameStr = convertOptionIdName(name, null); + return filter(this._componentsMap.get('series'), function (oneSeries) { + return !!oneSeries && nameStr != null && oneSeries.name === nameStr; + }); + }; + + GlobalModel.prototype.getSeriesByIndex = function (seriesIndex) { + return this._componentsMap.get('series')[seriesIndex]; + }; + + GlobalModel.prototype.getSeriesByType = function (subType) { + return filter(this._componentsMap.get('series'), function (oneSeries) { + return !!oneSeries && oneSeries.subType === subType; + }); + }; + + GlobalModel.prototype.getSeries = function () { + return filter(this._componentsMap.get('series').slice(), function (oneSeries) { + return !!oneSeries; + }); + }; + + GlobalModel.prototype.getSeriesCount = function () { + return this._componentsCount.get('series'); + }; + + GlobalModel.prototype.eachSeries = function (cb, context) { + assertSeriesInitialized(this); + each(this._seriesIndices, function (rawSeriesIndex) { + var series = this._componentsMap.get('series')[rawSeriesIndex]; + + cb.call(context, series, rawSeriesIndex); + }, this); + }; + + GlobalModel.prototype.eachRawSeries = function (cb, context) { + each(this._componentsMap.get('series'), function (series) { + series && cb.call(context, series, series.componentIndex); + }); + }; + + GlobalModel.prototype.eachSeriesByType = function (subType, cb, context) { + assertSeriesInitialized(this); + each(this._seriesIndices, function (rawSeriesIndex) { + var series = this._componentsMap.get('series')[rawSeriesIndex]; + + if (series.subType === subType) { + cb.call(context, series, rawSeriesIndex); + } + }, this); + }; + + GlobalModel.prototype.eachRawSeriesByType = function (subType, cb, context) { + return each(this.getSeriesByType(subType), cb, context); + }; + + GlobalModel.prototype.isSeriesFiltered = function (seriesModel) { + assertSeriesInitialized(this); + return this._seriesIndicesMap.get(seriesModel.componentIndex) == null; + }; + + GlobalModel.prototype.getCurrentSeriesIndices = function () { + return (this._seriesIndices || []).slice(); + }; + + GlobalModel.prototype.filterSeries = function (cb, context) { + assertSeriesInitialized(this); + var newSeriesIndices = []; + each(this._seriesIndices, function (seriesRawIdx) { + var series = this._componentsMap.get('series')[seriesRawIdx]; + + cb.call(context, series, seriesRawIdx) && newSeriesIndices.push(seriesRawIdx); + }, this); + this._seriesIndices = newSeriesIndices; + this._seriesIndicesMap = createHashMap(newSeriesIndices); + }; + + GlobalModel.prototype.restoreData = function (payload) { + reCreateSeriesIndices(this); + var componentsMap = this._componentsMap; + var componentTypes = []; + componentsMap.each(function (components, componentType) { + if (ComponentModel.hasClass(componentType)) { + componentTypes.push(componentType); + } + }); + ComponentModel.topologicalTravel(componentTypes, ComponentModel.getAllClassMainTypes(), function (componentType) { + each(componentsMap.get(componentType), function (component) { + if (component && (componentType !== 'series' || !isNotTargetSeries(component, payload))) { + component.restoreData(); + } + }); + }); + }; + + GlobalModel.internalField = function () { + reCreateSeriesIndices = function (ecModel) { + var seriesIndices = ecModel._seriesIndices = []; + each(ecModel._componentsMap.get('series'), function (series) { + series && seriesIndices.push(series.componentIndex); + }); + ecModel._seriesIndicesMap = createHashMap(seriesIndices); + }; + + assertSeriesInitialized = function (ecModel) { + if ("development" !== 'production') { + if (!ecModel._seriesIndices) { + throw new Error('Option should contains series.'); + } + } + }; + + initBase = function (ecModel, baseOption) { + ecModel.option = {}; + ecModel.option[OPTION_INNER_KEY] = OPTION_INNER_VALUE; + ecModel._componentsMap = createHashMap({ + series: [] + }); + ecModel._componentsCount = createHashMap(); + var airaOption = baseOption.aria; + + if (isObject(airaOption) && airaOption.enabled == null) { + airaOption.enabled = true; + } + + mergeTheme(baseOption, ecModel._theme.option); + merge(baseOption, globalDefault, false); + + ecModel._mergeOption(baseOption, null); + }; + }(); + + return GlobalModel; + }(Model); + + function isNotTargetSeries(seriesModel, payload) { + if (payload) { + var index = payload.seriesIndex; + var id = payload.seriesId; + var name_1 = payload.seriesName; + return index != null && seriesModel.componentIndex !== index || id != null && seriesModel.id !== id || name_1 != null && seriesModel.name !== name_1; + } + } + + function mergeTheme(option, theme) { + var notMergeColorLayer = option.color && !option.colorLayer; + each(theme, function (themeItem, name) { + if (name === 'colorLayer' && notMergeColorLayer) { + return; + } + + if (!ComponentModel.hasClass(name)) { + if (typeof themeItem === 'object') { + option[name] = !option[name] ? clone(themeItem) : merge(option[name], themeItem, false); + } else { + if (option[name] == null) { + option[name] = themeItem; + } + } + } + }); + } + + function queryByIdOrName(attr, idOrName, cmpts) { + if (isArray(idOrName)) { + var keyMap_1 = createHashMap(); + each(idOrName, function (idOrNameItem) { + if (idOrNameItem != null) { + var idName = convertOptionIdName(idOrNameItem, null); + idName != null && keyMap_1.set(idOrNameItem, true); + } + }); + return filter(cmpts, function (cmpt) { + return cmpt && keyMap_1.get(cmpt[attr]); + }); + } else { + var idName_1 = convertOptionIdName(idOrName, null); + return filter(cmpts, function (cmpt) { + return cmpt && idName_1 != null && cmpt[attr] === idName_1; + }); + } + } + + function filterBySubType(components, condition) { + return condition.hasOwnProperty('subType') ? filter(components, function (cmpt) { + return cmpt && cmpt.subType === condition.subType; + }) : components; + } + + function normalizeSetOptionInput(opts) { + var replaceMergeMainTypeMap = createHashMap(); + opts && each(normalizeToArray(opts.replaceMerge), function (mainType) { + if ("development" !== 'production') { + assert(ComponentModel.hasClass(mainType), '"' + mainType + '" is not valid component main type in "replaceMerge"'); + } + + replaceMergeMainTypeMap.set(mainType, true); + }); + return { + replaceMergeMainTypeMap: replaceMergeMainTypeMap + }; + } + + mixin(GlobalModel, PaletteMixin); + + var availableMethods = ['getDom', 'getZr', 'getWidth', 'getHeight', 'getDevicePixelRatio', 'dispatchAction', 'isDisposed', 'on', 'off', 'getDataURL', 'getConnectedDataURL', 'getOption', 'getId', 'updateLabelLayout']; + + var ExtensionAPI = function () { + function ExtensionAPI(ecInstance) { + each(availableMethods, function (methodName) { + this[methodName] = bind(ecInstance[methodName], ecInstance); + }, this); + } + + return ExtensionAPI; + }(); + + var coordinateSystemCreators = {}; + + var CoordinateSystemManager = function () { + function CoordinateSystemManager() { + this._coordinateSystems = []; + } + + CoordinateSystemManager.prototype.create = function (ecModel, api) { + var coordinateSystems = []; + each(coordinateSystemCreators, function (creater, type) { + var list = creater.create(ecModel, api); + coordinateSystems = coordinateSystems.concat(list || []); + }); + this._coordinateSystems = coordinateSystems; + }; + + CoordinateSystemManager.prototype.update = function (ecModel, api) { + each(this._coordinateSystems, function (coordSys) { + coordSys.update && coordSys.update(ecModel, api); + }); + }; + + CoordinateSystemManager.prototype.getCoordinateSystems = function () { + return this._coordinateSystems.slice(); + }; + + CoordinateSystemManager.register = function (type, creator) { + coordinateSystemCreators[type] = creator; + }; + + CoordinateSystemManager.get = function (type) { + return coordinateSystemCreators[type]; + }; + + return CoordinateSystemManager; + }(); + + var QUERY_REG = /^(min|max)?(.+)$/; + + var OptionManager = function () { + function OptionManager(api) { + this._timelineOptions = []; + this._mediaList = []; + this._currentMediaIndices = []; + this._api = api; + } + + OptionManager.prototype.setOption = function (rawOption, optionPreprocessorFuncs, opt) { + if (rawOption) { + each(normalizeToArray(rawOption.series), function (series) { + series && series.data && isTypedArray(series.data) && setAsPrimitive(series.data); + }); + each(normalizeToArray(rawOption.dataset), function (dataset) { + dataset && dataset.source && isTypedArray(dataset.source) && setAsPrimitive(dataset.source); + }); + } + + rawOption = clone(rawOption); + var optionBackup = this._optionBackup; + var newParsedOption = parseRawOption(rawOption, optionPreprocessorFuncs, !optionBackup); + this._newBaseOption = newParsedOption.baseOption; + + if (optionBackup) { + if (newParsedOption.timelineOptions.length) { + optionBackup.timelineOptions = newParsedOption.timelineOptions; + } + + if (newParsedOption.mediaList.length) { + optionBackup.mediaList = newParsedOption.mediaList; + } + + if (newParsedOption.mediaDefault) { + optionBackup.mediaDefault = newParsedOption.mediaDefault; + } + } else { + this._optionBackup = newParsedOption; + } + }; + + OptionManager.prototype.mountOption = function (isRecreate) { + var optionBackup = this._optionBackup; + this._timelineOptions = optionBackup.timelineOptions; + this._mediaList = optionBackup.mediaList; + this._mediaDefault = optionBackup.mediaDefault; + this._currentMediaIndices = []; + return clone(isRecreate ? optionBackup.baseOption : this._newBaseOption); + }; + + OptionManager.prototype.getTimelineOption = function (ecModel) { + var option; + var timelineOptions = this._timelineOptions; + + if (timelineOptions.length) { + var timelineModel = ecModel.getComponent('timeline'); + + if (timelineModel) { + option = clone(timelineOptions[timelineModel.getCurrentIndex()]); + } + } + + return option; + }; + + OptionManager.prototype.getMediaOption = function (ecModel) { + var ecWidth = this._api.getWidth(); + + var ecHeight = this._api.getHeight(); + + var mediaList = this._mediaList; + var mediaDefault = this._mediaDefault; + var indices = []; + var result = []; + + if (!mediaList.length && !mediaDefault) { + return result; + } + + for (var i = 0, len = mediaList.length; i < len; i++) { + if (applyMediaQuery(mediaList[i].query, ecWidth, ecHeight)) { + indices.push(i); + } + } + + if (!indices.length && mediaDefault) { + indices = [-1]; + } + + if (indices.length && !indicesEquals(indices, this._currentMediaIndices)) { + result = map(indices, function (index) { + return clone(index === -1 ? mediaDefault.option : mediaList[index].option); + }); + } + + this._currentMediaIndices = indices; + return result; + }; + + return OptionManager; + }(); + + function parseRawOption(rawOption, optionPreprocessorFuncs, isNew) { + var mediaList = []; + var mediaDefault; + var baseOption; + var declaredBaseOption = rawOption.baseOption; + var timelineOnRoot = rawOption.timeline; + var timelineOptionsOnRoot = rawOption.options; + var mediaOnRoot = rawOption.media; + var hasMedia = !!rawOption.media; + var hasTimeline = !!(timelineOptionsOnRoot || timelineOnRoot || declaredBaseOption && declaredBaseOption.timeline); + + if (declaredBaseOption) { + baseOption = declaredBaseOption; + + if (!baseOption.timeline) { + baseOption.timeline = timelineOnRoot; + } + } else { + if (hasTimeline || hasMedia) { + rawOption.options = rawOption.media = null; + } + + baseOption = rawOption; + } + + if (hasMedia) { + if (isArray(mediaOnRoot)) { + each(mediaOnRoot, function (singleMedia) { + if ("development" !== 'production') { + if (singleMedia && !singleMedia.option && isObject(singleMedia.query) && isObject(singleMedia.query.option)) { + error('Illegal media option. Must be like { media: [ { query: {}, option: {} } ] }'); + } + } + + if (singleMedia && singleMedia.option) { + if (singleMedia.query) { + mediaList.push(singleMedia); + } else if (!mediaDefault) { + mediaDefault = singleMedia; + } + } + }); + } else { + if ("development" !== 'production') { + error('Illegal media option. Must be an array. Like { media: [ {...}, {...} ] }'); + } + } + } + + doPreprocess(baseOption); + each(timelineOptionsOnRoot, function (option) { + return doPreprocess(option); + }); + each(mediaList, function (media) { + return doPreprocess(media.option); + }); + + function doPreprocess(option) { + each(optionPreprocessorFuncs, function (preProcess) { + preProcess(option, isNew); + }); + } + + return { + baseOption: baseOption, + timelineOptions: timelineOptionsOnRoot || [], + mediaDefault: mediaDefault, + mediaList: mediaList + }; + } + + function applyMediaQuery(query, ecWidth, ecHeight) { + var realMap = { + width: ecWidth, + height: ecHeight, + aspectratio: ecWidth / ecHeight + }; + var applicatable = true; + each(query, function (value, attr) { + var matched = attr.match(QUERY_REG); + + if (!matched || !matched[1] || !matched[2]) { + return; + } + + var operator = matched[1]; + var realAttr = matched[2].toLowerCase(); + + if (!compare(realMap[realAttr], value, operator)) { + applicatable = false; + } + }); + return applicatable; + } + + function compare(real, expect, operator) { + if (operator === 'min') { + return real >= expect; + } else if (operator === 'max') { + return real <= expect; + } else { + return real === expect; + } + } + + function indicesEquals(indices1, indices2) { + return indices1.join(',') === indices2.join(','); + } + + var each$2 = each; + var isObject$1 = isObject; + var POSSIBLE_STYLES = ['areaStyle', 'lineStyle', 'nodeStyle', 'linkStyle', 'chordStyle', 'label', 'labelLine']; + + function compatEC2ItemStyle(opt) { + var itemStyleOpt = opt && opt.itemStyle; + + if (!itemStyleOpt) { + return; + } + + for (var i = 0, len = POSSIBLE_STYLES.length; i < len; i++) { + var styleName = POSSIBLE_STYLES[i]; + var normalItemStyleOpt = itemStyleOpt.normal; + var emphasisItemStyleOpt = itemStyleOpt.emphasis; + + if (normalItemStyleOpt && normalItemStyleOpt[styleName]) { + if ("development" !== 'production') { + deprecateReplaceLog("itemStyle.normal." + styleName, styleName); + } + + opt[styleName] = opt[styleName] || {}; + + if (!opt[styleName].normal) { + opt[styleName].normal = normalItemStyleOpt[styleName]; + } else { + merge(opt[styleName].normal, normalItemStyleOpt[styleName]); + } + + normalItemStyleOpt[styleName] = null; + } + + if (emphasisItemStyleOpt && emphasisItemStyleOpt[styleName]) { + if ("development" !== 'production') { + deprecateReplaceLog("itemStyle.emphasis." + styleName, "emphasis." + styleName); + } + + opt[styleName] = opt[styleName] || {}; + + if (!opt[styleName].emphasis) { + opt[styleName].emphasis = emphasisItemStyleOpt[styleName]; + } else { + merge(opt[styleName].emphasis, emphasisItemStyleOpt[styleName]); + } + + emphasisItemStyleOpt[styleName] = null; + } + } + } + + function convertNormalEmphasis(opt, optType, useExtend) { + if (opt && opt[optType] && (opt[optType].normal || opt[optType].emphasis)) { + var normalOpt = opt[optType].normal; + var emphasisOpt = opt[optType].emphasis; + + if (normalOpt) { + if ("development" !== 'production') { + deprecateLog("'normal' hierarchy in " + optType + " has been removed since 4.0. All style properties are configured in " + optType + " directly now."); + } + + if (useExtend) { + opt[optType].normal = opt[optType].emphasis = null; + defaults(opt[optType], normalOpt); + } else { + opt[optType] = normalOpt; + } + } + + if (emphasisOpt) { + if ("development" !== 'production') { + deprecateLog(optType + ".emphasis has been changed to emphasis." + optType + " since 4.0"); + } + + opt.emphasis = opt.emphasis || {}; + opt.emphasis[optType] = emphasisOpt; + + if (emphasisOpt.focus) { + opt.emphasis.focus = emphasisOpt.focus; + } + + if (emphasisOpt.blurScope) { + opt.emphasis.blurScope = emphasisOpt.blurScope; + } + } + } + } + + function removeEC3NormalStatus(opt) { + convertNormalEmphasis(opt, 'itemStyle'); + convertNormalEmphasis(opt, 'lineStyle'); + convertNormalEmphasis(opt, 'areaStyle'); + convertNormalEmphasis(opt, 'label'); + convertNormalEmphasis(opt, 'labelLine'); + convertNormalEmphasis(opt, 'upperLabel'); + convertNormalEmphasis(opt, 'edgeLabel'); + } + + function compatTextStyle(opt, propName) { + var labelOptSingle = isObject$1(opt) && opt[propName]; + var textStyle = isObject$1(labelOptSingle) && labelOptSingle.textStyle; + + if (textStyle) { + if ("development" !== 'production') { + deprecateLog("textStyle hierarchy in " + propName + " has been removed since 4.0. All textStyle properties are configured in " + propName + " directly now."); + } + + for (var i = 0, len = TEXT_STYLE_OPTIONS.length; i < len; i++) { + var textPropName = TEXT_STYLE_OPTIONS[i]; + + if (textStyle.hasOwnProperty(textPropName)) { + labelOptSingle[textPropName] = textStyle[textPropName]; + } + } + } + } + + function compatEC3CommonStyles(opt) { + if (opt) { + removeEC3NormalStatus(opt); + compatTextStyle(opt, 'label'); + opt.emphasis && compatTextStyle(opt.emphasis, 'label'); + } + } + + function processSeries(seriesOpt) { + if (!isObject$1(seriesOpt)) { + return; + } + + compatEC2ItemStyle(seriesOpt); + removeEC3NormalStatus(seriesOpt); + compatTextStyle(seriesOpt, 'label'); + compatTextStyle(seriesOpt, 'upperLabel'); + compatTextStyle(seriesOpt, 'edgeLabel'); + + if (seriesOpt.emphasis) { + compatTextStyle(seriesOpt.emphasis, 'label'); + compatTextStyle(seriesOpt.emphasis, 'upperLabel'); + compatTextStyle(seriesOpt.emphasis, 'edgeLabel'); + } + + var markPoint = seriesOpt.markPoint; + + if (markPoint) { + compatEC2ItemStyle(markPoint); + compatEC3CommonStyles(markPoint); + } + + var markLine = seriesOpt.markLine; + + if (markLine) { + compatEC2ItemStyle(markLine); + compatEC3CommonStyles(markLine); + } + + var markArea = seriesOpt.markArea; + + if (markArea) { + compatEC3CommonStyles(markArea); + } + + var data = seriesOpt.data; + + if (seriesOpt.type === 'graph') { + data = data || seriesOpt.nodes; + var edgeData = seriesOpt.links || seriesOpt.edges; + + if (edgeData && !isTypedArray(edgeData)) { + for (var i = 0; i < edgeData.length; i++) { + compatEC3CommonStyles(edgeData[i]); + } + } + + each(seriesOpt.categories, function (opt) { + removeEC3NormalStatus(opt); + }); + } + + if (data && !isTypedArray(data)) { + for (var i = 0; i < data.length; i++) { + compatEC3CommonStyles(data[i]); + } + } + + markPoint = seriesOpt.markPoint; + + if (markPoint && markPoint.data) { + var mpData = markPoint.data; + + for (var i = 0; i < mpData.length; i++) { + compatEC3CommonStyles(mpData[i]); + } + } + + markLine = seriesOpt.markLine; + + if (markLine && markLine.data) { + var mlData = markLine.data; + + for (var i = 0; i < mlData.length; i++) { + if (isArray(mlData[i])) { + compatEC3CommonStyles(mlData[i][0]); + compatEC3CommonStyles(mlData[i][1]); + } else { + compatEC3CommonStyles(mlData[i]); + } + } + } + + if (seriesOpt.type === 'gauge') { + compatTextStyle(seriesOpt, 'axisLabel'); + compatTextStyle(seriesOpt, 'title'); + compatTextStyle(seriesOpt, 'detail'); + } else if (seriesOpt.type === 'treemap') { + convertNormalEmphasis(seriesOpt.breadcrumb, 'itemStyle'); + each(seriesOpt.levels, function (opt) { + removeEC3NormalStatus(opt); + }); + } else if (seriesOpt.type === 'tree') { + removeEC3NormalStatus(seriesOpt.leaves); + } + } + + function toArr(o) { + return isArray(o) ? o : o ? [o] : []; + } + + function toObj(o) { + return (isArray(o) ? o[0] : o) || {}; + } + + function globalCompatStyle(option, isTheme) { + each$2(toArr(option.series), function (seriesOpt) { + isObject$1(seriesOpt) && processSeries(seriesOpt); + }); + var axes = ['xAxis', 'yAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'parallelAxis', 'radar']; + isTheme && axes.push('valueAxis', 'categoryAxis', 'logAxis', 'timeAxis'); + each$2(axes, function (axisName) { + each$2(toArr(option[axisName]), function (axisOpt) { + if (axisOpt) { + compatTextStyle(axisOpt, 'axisLabel'); + compatTextStyle(axisOpt.axisPointer, 'label'); + } + }); + }); + each$2(toArr(option.parallel), function (parallelOpt) { + var parallelAxisDefault = parallelOpt && parallelOpt.parallelAxisDefault; + compatTextStyle(parallelAxisDefault, 'axisLabel'); + compatTextStyle(parallelAxisDefault && parallelAxisDefault.axisPointer, 'label'); + }); + each$2(toArr(option.calendar), function (calendarOpt) { + convertNormalEmphasis(calendarOpt, 'itemStyle'); + compatTextStyle(calendarOpt, 'dayLabel'); + compatTextStyle(calendarOpt, 'monthLabel'); + compatTextStyle(calendarOpt, 'yearLabel'); + }); + each$2(toArr(option.radar), function (radarOpt) { + compatTextStyle(radarOpt, 'name'); + + if (radarOpt.name && radarOpt.axisName == null) { + radarOpt.axisName = radarOpt.name; + delete radarOpt.name; + + if ("development" !== 'production') { + deprecateLog('name property in radar component has been changed to axisName'); + } + } + + if (radarOpt.nameGap != null && radarOpt.axisNameGap == null) { + radarOpt.axisNameGap = radarOpt.nameGap; + delete radarOpt.nameGap; + + if ("development" !== 'production') { + deprecateLog('nameGap property in radar component has been changed to axisNameGap'); + } + } + }); + each$2(toArr(option.geo), function (geoOpt) { + if (isObject$1(geoOpt)) { + compatEC3CommonStyles(geoOpt); + each$2(toArr(geoOpt.regions), function (regionObj) { + compatEC3CommonStyles(regionObj); + }); + } + }); + each$2(toArr(option.timeline), function (timelineOpt) { + compatEC3CommonStyles(timelineOpt); + convertNormalEmphasis(timelineOpt, 'label'); + convertNormalEmphasis(timelineOpt, 'itemStyle'); + convertNormalEmphasis(timelineOpt, 'controlStyle', true); + var data = timelineOpt.data; + isArray(data) && each(data, function (item) { + if (isObject(item)) { + convertNormalEmphasis(item, 'label'); + convertNormalEmphasis(item, 'itemStyle'); + } + }); + }); + each$2(toArr(option.toolbox), function (toolboxOpt) { + convertNormalEmphasis(toolboxOpt, 'iconStyle'); + each$2(toolboxOpt.feature, function (featureOpt) { + convertNormalEmphasis(featureOpt, 'iconStyle'); + }); + }); + compatTextStyle(toObj(option.axisPointer), 'label'); + compatTextStyle(toObj(option.tooltip).axisPointer, 'label'); + } + + function get(opt, path) { + var pathArr = path.split(','); + var obj = opt; + + for (var i = 0; i < pathArr.length; i++) { + obj = obj && obj[pathArr[i]]; + + if (obj == null) { + break; + } + } + + return obj; + } + + function set$1(opt, path, val, overwrite) { + var pathArr = path.split(','); + var obj = opt; + var key; + var i = 0; + + for (; i < pathArr.length - 1; i++) { + key = pathArr[i]; + + if (obj[key] == null) { + obj[key] = {}; + } + + obj = obj[key]; + } + + if (overwrite || obj[pathArr[i]] == null) { + obj[pathArr[i]] = val; + } + } + + function compatLayoutProperties(option) { + option && each(LAYOUT_PROPERTIES, function (prop) { + if (prop[0] in option && !(prop[1] in option)) { + option[prop[1]] = option[prop[0]]; + } + }); + } + + var LAYOUT_PROPERTIES = [['x', 'left'], ['y', 'top'], ['x2', 'right'], ['y2', 'bottom']]; + var COMPATITABLE_COMPONENTS = ['grid', 'geo', 'parallel', 'legend', 'toolbox', 'title', 'visualMap', 'dataZoom', 'timeline']; + var BAR_ITEM_STYLE_MAP = [['borderRadius', 'barBorderRadius'], ['borderColor', 'barBorderColor'], ['borderWidth', 'barBorderWidth']]; + + function compatBarItemStyle(option) { + var itemStyle = option && option.itemStyle; + + if (itemStyle) { + for (var i = 0; i < BAR_ITEM_STYLE_MAP.length; i++) { + var oldName = BAR_ITEM_STYLE_MAP[i][1]; + var newName = BAR_ITEM_STYLE_MAP[i][0]; + + if (itemStyle[oldName] != null) { + itemStyle[newName] = itemStyle[oldName]; + + if ("development" !== 'production') { + deprecateReplaceLog(oldName, newName); + } + } + } + } + } + + function compatPieLabel(option) { + if (!option) { + return; + } + + if (option.alignTo === 'edge' && option.margin != null && option.edgeDistance == null) { + if ("development" !== 'production') { + deprecateReplaceLog('label.margin', 'label.edgeDistance', 'pie'); + } + + option.edgeDistance = option.margin; + } + } + + function compatSunburstState(option) { + if (!option) { + return; + } + + if (option.downplay && !option.blur) { + option.blur = option.downplay; + + if ("development" !== 'production') { + deprecateReplaceLog('downplay', 'blur', 'sunburst'); + } + } + } + + function compatGraphFocus(option) { + if (!option) { + return; + } + + if (option.focusNodeAdjacency != null) { + option.emphasis = option.emphasis || {}; + + if (option.emphasis.focus == null) { + if ("development" !== 'production') { + deprecateReplaceLog('focusNodeAdjacency', 'emphasis: { focus: \'adjacency\'}', 'graph/sankey'); + } + + option.emphasis.focus = 'adjacency'; + } + } + } + + function traverseTree(data, cb) { + if (data) { + for (var i = 0; i < data.length; i++) { + cb(data[i]); + data[i] && traverseTree(data[i].children, cb); + } + } + } + + function globalBackwardCompat(option, isTheme) { + globalCompatStyle(option, isTheme); + option.series = normalizeToArray(option.series); + each(option.series, function (seriesOpt) { + if (!isObject(seriesOpt)) { + return; + } + + var seriesType = seriesOpt.type; + + if (seriesType === 'line') { + if (seriesOpt.clipOverflow != null) { + seriesOpt.clip = seriesOpt.clipOverflow; + + if ("development" !== 'production') { + deprecateReplaceLog('clipOverflow', 'clip', 'line'); + } + } + } else if (seriesType === 'pie' || seriesType === 'gauge') { + if (seriesOpt.clockWise != null) { + seriesOpt.clockwise = seriesOpt.clockWise; + + if ("development" !== 'production') { + deprecateReplaceLog('clockWise', 'clockwise'); + } + } + + compatPieLabel(seriesOpt.label); + var data = seriesOpt.data; + + if (data && !isTypedArray(data)) { + for (var i = 0; i < data.length; i++) { + compatPieLabel(data[i]); + } + } + + if (seriesOpt.hoverOffset != null) { + seriesOpt.emphasis = seriesOpt.emphasis || {}; + + if (seriesOpt.emphasis.scaleSize = null) { + if ("development" !== 'production') { + deprecateReplaceLog('hoverOffset', 'emphasis.scaleSize'); + } + + seriesOpt.emphasis.scaleSize = seriesOpt.hoverOffset; + } + } + } else if (seriesType === 'gauge') { + var pointerColor = get(seriesOpt, 'pointer.color'); + pointerColor != null && set$1(seriesOpt, 'itemStyle.color', pointerColor); + } else if (seriesType === 'bar') { + compatBarItemStyle(seriesOpt); + compatBarItemStyle(seriesOpt.backgroundStyle); + compatBarItemStyle(seriesOpt.emphasis); + var data = seriesOpt.data; + + if (data && !isTypedArray(data)) { + for (var i = 0; i < data.length; i++) { + if (typeof data[i] === 'object') { + compatBarItemStyle(data[i]); + compatBarItemStyle(data[i] && data[i].emphasis); + } + } + } + } else if (seriesType === 'sunburst') { + var highlightPolicy = seriesOpt.highlightPolicy; + + if (highlightPolicy) { + seriesOpt.emphasis = seriesOpt.emphasis || {}; + + if (!seriesOpt.emphasis.focus) { + seriesOpt.emphasis.focus = highlightPolicy; + + if ("development" !== 'production') { + deprecateReplaceLog('highlightPolicy', 'emphasis.focus', 'sunburst'); + } + } + } + + compatSunburstState(seriesOpt); + traverseTree(seriesOpt.data, compatSunburstState); + } else if (seriesType === 'graph' || seriesType === 'sankey') { + compatGraphFocus(seriesOpt); + } else if (seriesType === 'map') { + if (seriesOpt.mapType && !seriesOpt.map) { + if ("development" !== 'production') { + deprecateReplaceLog('mapType', 'map', 'map'); + } + + seriesOpt.map = seriesOpt.mapType; + } + + if (seriesOpt.mapLocation) { + if ("development" !== 'production') { + deprecateLog('`mapLocation` is not used anymore.'); + } + + defaults(seriesOpt, seriesOpt.mapLocation); + } + } + + if (seriesOpt.hoverAnimation != null) { + seriesOpt.emphasis = seriesOpt.emphasis || {}; + + if (seriesOpt.emphasis && seriesOpt.emphasis.scale == null) { + if ("development" !== 'production') { + deprecateReplaceLog('hoverAnimation', 'emphasis.scale'); + } + + seriesOpt.emphasis.scale = seriesOpt.hoverAnimation; + } + } + + compatLayoutProperties(seriesOpt); + }); + + if (option.dataRange) { + option.visualMap = option.dataRange; + } + + each(COMPATITABLE_COMPONENTS, function (componentName) { + var options = option[componentName]; + + if (options) { + if (!isArray(options)) { + options = [options]; + } + + each(options, function (option) { + compatLayoutProperties(option); + }); + } + }); + } + + function dataStack(ecModel) { + var stackInfoMap = createHashMap(); + ecModel.eachSeries(function (seriesModel) { + var stack = seriesModel.get('stack'); + + if (stack) { + var stackInfoList = stackInfoMap.get(stack) || stackInfoMap.set(stack, []); + var data = seriesModel.getData(); + var stackInfo = { + stackResultDimension: data.getCalculationInfo('stackResultDimension'), + stackedOverDimension: data.getCalculationInfo('stackedOverDimension'), + stackedDimension: data.getCalculationInfo('stackedDimension'), + stackedByDimension: data.getCalculationInfo('stackedByDimension'), + isStackedByIndex: data.getCalculationInfo('isStackedByIndex'), + data: data, + seriesModel: seriesModel + }; + + if (!stackInfo.stackedDimension || !(stackInfo.isStackedByIndex || stackInfo.stackedByDimension)) { + return; + } + + stackInfoList.length && data.setCalculationInfo('stackedOnSeries', stackInfoList[stackInfoList.length - 1].seriesModel); + stackInfoList.push(stackInfo); + } + }); + stackInfoMap.each(calculateStack); + } + + function calculateStack(stackInfoList) { + each(stackInfoList, function (targetStackInfo, idxInStack) { + var resultVal = []; + var resultNaN = [NaN, NaN]; + var dims = [targetStackInfo.stackResultDimension, targetStackInfo.stackedOverDimension]; + var targetData = targetStackInfo.data; + var isStackedByIndex = targetStackInfo.isStackedByIndex; + var newData = targetData.map(dims, function (v0, v1, dataIndex) { + var sum = targetData.get(targetStackInfo.stackedDimension, dataIndex); + + if (isNaN(sum)) { + return resultNaN; + } + + var byValue; + var stackedDataRawIndex; + + if (isStackedByIndex) { + stackedDataRawIndex = targetData.getRawIndex(dataIndex); + } else { + byValue = targetData.get(targetStackInfo.stackedByDimension, dataIndex); + } + + var stackedOver = NaN; + + for (var j = idxInStack - 1; j >= 0; j--) { + var stackInfo = stackInfoList[j]; + + if (!isStackedByIndex) { + stackedDataRawIndex = stackInfo.data.rawIndexOf(stackInfo.stackedByDimension, byValue); + } + + if (stackedDataRawIndex >= 0) { + var val = stackInfo.data.getByRawIndex(stackInfo.stackResultDimension, stackedDataRawIndex); + + if (sum >= 0 && val > 0 || sum <= 0 && val < 0) { + sum += val; + stackedOver = val; + break; + } + } + } + + resultVal[0] = sum; + resultVal[1] = stackedOver; + return resultVal; + }); + targetData.hostModel.setData(newData); + targetStackInfo.data = newData; + }); + } + + var SourceImpl = function () { + function SourceImpl(fields) { + this.data = fields.data || (fields.sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS ? {} : []); + this.sourceFormat = fields.sourceFormat || SOURCE_FORMAT_UNKNOWN; + this.seriesLayoutBy = fields.seriesLayoutBy || SERIES_LAYOUT_BY_COLUMN; + this.startIndex = fields.startIndex || 0; + this.dimensionsDefine = fields.dimensionsDefine; + this.dimensionsDetectedCount = fields.dimensionsDetectedCount; + this.encodeDefine = fields.encodeDefine; + this.metaRawOption = fields.metaRawOption; + } + + return SourceImpl; + }(); + + function isSourceInstance(val) { + return val instanceof SourceImpl; + } + function createSource(sourceData, thisMetaRawOption, sourceFormat, encodeDefine) { + sourceFormat = sourceFormat || detectSourceFormat(sourceData); + var seriesLayoutBy = thisMetaRawOption.seriesLayoutBy; + var determined = determineSourceDimensions(sourceData, sourceFormat, seriesLayoutBy, thisMetaRawOption.sourceHeader, thisMetaRawOption.dimensions); + var source = new SourceImpl({ + data: sourceData, + sourceFormat: sourceFormat, + seriesLayoutBy: seriesLayoutBy, + dimensionsDefine: determined.dimensionsDefine, + startIndex: determined.startIndex, + dimensionsDetectedCount: determined.dimensionsDetectedCount, + encodeDefine: makeEncodeDefine(encodeDefine), + metaRawOption: clone(thisMetaRawOption) + }); + return source; + } + function createSourceFromSeriesDataOption(data) { + return new SourceImpl({ + data: data, + sourceFormat: isTypedArray(data) ? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL + }); + } + function cloneSourceShallow(source) { + return new SourceImpl({ + data: source.data, + sourceFormat: source.sourceFormat, + seriesLayoutBy: source.seriesLayoutBy, + dimensionsDefine: clone(source.dimensionsDefine), + startIndex: source.startIndex, + dimensionsDetectedCount: source.dimensionsDetectedCount, + encodeDefine: makeEncodeDefine(source.encodeDefine) + }); + } + + function makeEncodeDefine(encodeDefine) { + return encodeDefine ? createHashMap(encodeDefine) : null; + } + + function detectSourceFormat(data) { + var sourceFormat = SOURCE_FORMAT_UNKNOWN; + + if (isTypedArray(data)) { + sourceFormat = SOURCE_FORMAT_TYPED_ARRAY; + } else if (isArray(data)) { + if (data.length === 0) { + sourceFormat = SOURCE_FORMAT_ARRAY_ROWS; + } + + for (var i = 0, len = data.length; i < len; i++) { + var item = data[i]; + + if (item == null) { + continue; + } else if (isArray(item)) { + sourceFormat = SOURCE_FORMAT_ARRAY_ROWS; + break; + } else if (isObject(item)) { + sourceFormat = SOURCE_FORMAT_OBJECT_ROWS; + break; + } + } + } else if (isObject(data)) { + for (var key in data) { + if (hasOwn(data, key) && isArrayLike(data[key])) { + sourceFormat = SOURCE_FORMAT_KEYED_COLUMNS; + break; + } + } + } + + return sourceFormat; + } + + function determineSourceDimensions(data, sourceFormat, seriesLayoutBy, sourceHeader, dimensionsDefine) { + var dimensionsDetectedCount; + var startIndex; + + if (!data) { + return { + dimensionsDefine: normalizeDimensionsOption(dimensionsDefine), + startIndex: startIndex, + dimensionsDetectedCount: dimensionsDetectedCount + }; + } + + if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) { + var dataArrayRows = data; + + if (sourceHeader === 'auto' || sourceHeader == null) { + arrayRowsTravelFirst(function (val) { + if (val != null && val !== '-') { + if (isString(val)) { + startIndex == null && (startIndex = 1); + } else { + startIndex = 0; + } + } + }, seriesLayoutBy, dataArrayRows, 10); + } else { + startIndex = isNumber(sourceHeader) ? sourceHeader : sourceHeader ? 1 : 0; + } + + if (!dimensionsDefine && startIndex === 1) { + dimensionsDefine = []; + arrayRowsTravelFirst(function (val, index) { + dimensionsDefine[index] = val != null ? val + '' : ''; + }, seriesLayoutBy, dataArrayRows, Infinity); + } + + dimensionsDetectedCount = dimensionsDefine ? dimensionsDefine.length : seriesLayoutBy === SERIES_LAYOUT_BY_ROW ? dataArrayRows.length : dataArrayRows[0] ? dataArrayRows[0].length : null; + } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) { + if (!dimensionsDefine) { + dimensionsDefine = objectRowsCollectDimensions(data); + } + } else if (sourceFormat === SOURCE_FORMAT_KEYED_COLUMNS) { + if (!dimensionsDefine) { + dimensionsDefine = []; + each(data, function (colArr, key) { + dimensionsDefine.push(key); + }); + } + } else if (sourceFormat === SOURCE_FORMAT_ORIGINAL) { + var value0 = getDataItemValue(data[0]); + dimensionsDetectedCount = isArray(value0) && value0.length || 1; + } else if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) { + if ("development" !== 'production') { + assert(!!dimensionsDefine, 'dimensions must be given if data is TypedArray.'); + } + } + + return { + startIndex: startIndex, + dimensionsDefine: normalizeDimensionsOption(dimensionsDefine), + dimensionsDetectedCount: dimensionsDetectedCount + }; + } + + function objectRowsCollectDimensions(data) { + var firstIndex = 0; + var obj; + + while (firstIndex < data.length && !(obj = data[firstIndex++])) {} + + if (obj) { + var dimensions_1 = []; + each(obj, function (value, key) { + dimensions_1.push(key); + }); + return dimensions_1; + } + } + + function normalizeDimensionsOption(dimensionsDefine) { + if (!dimensionsDefine) { + return; + } + + var nameMap = createHashMap(); + return map(dimensionsDefine, function (rawItem, index) { + rawItem = isObject(rawItem) ? rawItem : { + name: rawItem + }; + var item = { + name: rawItem.name, + displayName: rawItem.displayName, + type: rawItem.type + }; + + if (item.name == null) { + return item; + } + + item.name += ''; + + if (item.displayName == null) { + item.displayName = item.name; + } + + var exist = nameMap.get(item.name); + + if (!exist) { + nameMap.set(item.name, { + count: 1 + }); + } else { + item.name += '-' + exist.count++; + } + + return item; + }); + } + + function arrayRowsTravelFirst(cb, seriesLayoutBy, data, maxLoop) { + if (seriesLayoutBy === SERIES_LAYOUT_BY_ROW) { + for (var i = 0; i < data.length && i < maxLoop; i++) { + cb(data[i] ? data[i][0] : null, i); + } + } else { + var value0 = data[0] || []; + + for (var i = 0; i < value0.length && i < maxLoop; i++) { + cb(value0[i], i); + } + } + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var _a, _b, _c; + var providerMethods; + var mountMethods; + + var DefaultDataProvider = function () { + function DefaultDataProvider(sourceParam, dimSize) { + var source = !isSourceInstance(sourceParam) ? createSourceFromSeriesDataOption(sourceParam) : sourceParam; + this._source = source; + var data = this._data = source.data; + + if (source.sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) { + if ("development" !== 'production') { + if (dimSize == null) { + throw new Error('Typed array data must specify dimension size'); + } + } + + this._offset = 0; + this._dimSize = dimSize; + this._data = data; + } + + mountMethods(this, data, source); + } + + DefaultDataProvider.prototype.getSource = function () { + return this._source; + }; + + DefaultDataProvider.prototype.count = function () { + return 0; + }; + + DefaultDataProvider.prototype.getItem = function (idx, out) { + return; + }; + + DefaultDataProvider.prototype.appendData = function (newData) {}; + + DefaultDataProvider.prototype.clean = function () {}; + + DefaultDataProvider.protoInitialize = function () { + var proto = DefaultDataProvider.prototype; + proto.pure = false; + proto.persistent = true; + }(); + + DefaultDataProvider.internalField = function () { + var _a; + + mountMethods = function (provider, data, source) { + var sourceFormat = source.sourceFormat; + var seriesLayoutBy = source.seriesLayoutBy; + var startIndex = source.startIndex; + var dimsDef = source.dimensionsDefine; + var methods = providerMethods[getMethodMapKey(sourceFormat, seriesLayoutBy)]; + + if ("development" !== 'production') { + assert(methods, 'Invalide sourceFormat: ' + sourceFormat); + } + + extend(provider, methods); + + if (sourceFormat === SOURCE_FORMAT_TYPED_ARRAY) { + provider.getItem = getItemForTypedArray; + provider.count = countForTypedArray; + provider.fillStorage = fillStorageForTypedArray; + } else { + var rawItemGetter = getRawSourceItemGetter(sourceFormat, seriesLayoutBy); + provider.getItem = bind(rawItemGetter, null, data, startIndex, dimsDef); + var rawCounter = getRawSourceDataCounter(sourceFormat, seriesLayoutBy); + provider.count = bind(rawCounter, null, data, startIndex, dimsDef); + } + }; + + var getItemForTypedArray = function (idx, out) { + idx = idx - this._offset; + out = out || []; + var data = this._data; + var dimSize = this._dimSize; + var offset = dimSize * idx; + + for (var i = 0; i < dimSize; i++) { + out[i] = data[offset + i]; + } + + return out; + }; + + var fillStorageForTypedArray = function (start, end, storage, extent) { + var data = this._data; + var dimSize = this._dimSize; + + for (var dim = 0; dim < dimSize; dim++) { + var dimExtent = extent[dim]; + var min = dimExtent[0] == null ? Infinity : dimExtent[0]; + var max = dimExtent[1] == null ? -Infinity : dimExtent[1]; + var count = end - start; + var arr = storage[dim]; + + for (var i = 0; i < count; i++) { + var val = data[i * dimSize + dim]; + arr[start + i] = val; + val < min && (min = val); + val > max && (max = val); + } + + dimExtent[0] = min; + dimExtent[1] = max; + } + }; + + var countForTypedArray = function () { + return this._data ? this._data.length / this._dimSize : 0; + }; + + providerMethods = (_a = {}, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = { + pure: true, + appendData: appendDataSimply + }, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = { + pure: true, + appendData: function () { + throw new Error('Do not support appendData when set seriesLayoutBy: "row".'); + } + }, _a[SOURCE_FORMAT_OBJECT_ROWS] = { + pure: true, + appendData: appendDataSimply + }, _a[SOURCE_FORMAT_KEYED_COLUMNS] = { + pure: true, + appendData: function (newData) { + var data = this._data; + each(newData, function (newCol, key) { + var oldCol = data[key] || (data[key] = []); + + for (var i = 0; i < (newCol || []).length; i++) { + oldCol.push(newCol[i]); + } + }); + } + }, _a[SOURCE_FORMAT_ORIGINAL] = { + appendData: appendDataSimply + }, _a[SOURCE_FORMAT_TYPED_ARRAY] = { + persistent: false, + pure: true, + appendData: function (newData) { + if ("development" !== 'production') { + assert(isTypedArray(newData), 'Added data must be TypedArray if data in initialization is TypedArray'); + } + + this._data = newData; + }, + clean: function () { + this._offset += this.count(); + this._data = null; + } + }, _a); + + function appendDataSimply(newData) { + for (var i = 0; i < newData.length; i++) { + this._data.push(newData[i]); + } + } + }(); + + return DefaultDataProvider; + }(); + + var getItemSimply = function (rawData, startIndex, dimsDef, idx) { + return rawData[idx]; + }; + + var rawSourceItemGetterMap = (_a = {}, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = function (rawData, startIndex, dimsDef, idx) { + return rawData[idx + startIndex]; + }, _a[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = function (rawData, startIndex, dimsDef, idx) { + idx += startIndex; + var item = []; + var data = rawData; + + for (var i = 0; i < data.length; i++) { + var row = data[i]; + item.push(row ? row[idx] : null); + } + + return item; + }, _a[SOURCE_FORMAT_OBJECT_ROWS] = getItemSimply, _a[SOURCE_FORMAT_KEYED_COLUMNS] = function (rawData, startIndex, dimsDef, idx) { + var item = []; + + for (var i = 0; i < dimsDef.length; i++) { + var dimName = dimsDef[i].name; + + if ("development" !== 'production') { + if (dimName == null) { + throw new Error(); + } + } + + var col = rawData[dimName]; + item.push(col ? col[idx] : null); + } + + return item; + }, _a[SOURCE_FORMAT_ORIGINAL] = getItemSimply, _a); + function getRawSourceItemGetter(sourceFormat, seriesLayoutBy) { + var method = rawSourceItemGetterMap[getMethodMapKey(sourceFormat, seriesLayoutBy)]; + + if ("development" !== 'production') { + assert(method, 'Do not suppport get item on "' + sourceFormat + '", "' + seriesLayoutBy + '".'); + } + + return method; + } + + var countSimply = function (rawData, startIndex, dimsDef) { + return rawData.length; + }; + + var rawSourceDataCounterMap = (_b = {}, _b[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_COLUMN] = function (rawData, startIndex, dimsDef) { + return Math.max(0, rawData.length - startIndex); + }, _b[SOURCE_FORMAT_ARRAY_ROWS + '_' + SERIES_LAYOUT_BY_ROW] = function (rawData, startIndex, dimsDef) { + var row = rawData[0]; + return row ? Math.max(0, row.length - startIndex) : 0; + }, _b[SOURCE_FORMAT_OBJECT_ROWS] = countSimply, _b[SOURCE_FORMAT_KEYED_COLUMNS] = function (rawData, startIndex, dimsDef) { + var dimName = dimsDef[0].name; + + if ("development" !== 'production') { + if (dimName == null) { + throw new Error(); + } + } + + var col = rawData[dimName]; + return col ? col.length : 0; + }, _b[SOURCE_FORMAT_ORIGINAL] = countSimply, _b); + function getRawSourceDataCounter(sourceFormat, seriesLayoutBy) { + var method = rawSourceDataCounterMap[getMethodMapKey(sourceFormat, seriesLayoutBy)]; + + if ("development" !== 'production') { + assert(method, 'Do not suppport count on "' + sourceFormat + '", "' + seriesLayoutBy + '".'); + } + + return method; + } + + var getRawValueSimply = function (dataItem, dimIndex, dimName) { + return dimIndex != null ? dataItem[dimIndex] : dataItem; + }; + + var rawSourceValueGetterMap = (_c = {}, _c[SOURCE_FORMAT_ARRAY_ROWS] = getRawValueSimply, _c[SOURCE_FORMAT_OBJECT_ROWS] = function (dataItem, dimIndex, dimName) { + return dimIndex != null ? dataItem[dimName] : dataItem; + }, _c[SOURCE_FORMAT_KEYED_COLUMNS] = getRawValueSimply, _c[SOURCE_FORMAT_ORIGINAL] = function (dataItem, dimIndex, dimName) { + var value = getDataItemValue(dataItem); + return dimIndex == null || !(value instanceof Array) ? value : value[dimIndex]; + }, _c[SOURCE_FORMAT_TYPED_ARRAY] = getRawValueSimply, _c); + function getRawSourceValueGetter(sourceFormat) { + var method = rawSourceValueGetterMap[sourceFormat]; + + if ("development" !== 'production') { + assert(method, 'Do not suppport get value on "' + sourceFormat + '".'); + } + + return method; + } + + function getMethodMapKey(sourceFormat, seriesLayoutBy) { + return sourceFormat === SOURCE_FORMAT_ARRAY_ROWS ? sourceFormat + '_' + seriesLayoutBy : sourceFormat; + } + + function retrieveRawValue(data, dataIndex, dim) { + if (!data) { + return; + } + + var dataItem = data.getRawDataItem(dataIndex); + + if (dataItem == null) { + return; + } + + var sourceFormat = data.getProvider().getSource().sourceFormat; + var dimName; + var dimIndex; + var dimInfo = data.getDimensionInfo(dim); + + if (dimInfo) { + dimName = dimInfo.name; + dimIndex = dimInfo.index; + } + + return getRawSourceValueGetter(sourceFormat)(dataItem, dimIndex, dimName); + } + + var DIMENSION_LABEL_REG = /\{@(.+?)\}/g; + + var DataFormatMixin = function () { + function DataFormatMixin() {} + + DataFormatMixin.prototype.getDataParams = function (dataIndex, dataType) { + var data = this.getData(dataType); + var rawValue = this.getRawValue(dataIndex, dataType); + var rawDataIndex = data.getRawIndex(dataIndex); + var name = data.getName(dataIndex); + var itemOpt = data.getRawDataItem(dataIndex); + var style = data.getItemVisual(dataIndex, 'style'); + var color = style && style[data.getItemVisual(dataIndex, 'drawType') || 'fill']; + var borderColor = style && style.stroke; + var mainType = this.mainType; + var isSeries = mainType === 'series'; + var userOutput = data.userOutput; + return { + componentType: mainType, + componentSubType: this.subType, + componentIndex: this.componentIndex, + seriesType: isSeries ? this.subType : null, + seriesIndex: this.seriesIndex, + seriesId: isSeries ? this.id : null, + seriesName: isSeries ? this.name : null, + name: name, + dataIndex: rawDataIndex, + data: itemOpt, + dataType: dataType, + value: rawValue, + color: color, + borderColor: borderColor, + dimensionNames: userOutput ? userOutput.dimensionNames : null, + encode: userOutput ? userOutput.encode : null, + $vars: ['seriesName', 'name', 'value'] + }; + }; + + DataFormatMixin.prototype.getFormattedLabel = function (dataIndex, status, dataType, labelDimIndex, formatter, extendParams) { + status = status || 'normal'; + var data = this.getData(dataType); + var params = this.getDataParams(dataIndex, dataType); + + if (extendParams) { + params.value = extendParams.interpolatedValue; + } + + if (labelDimIndex != null && isArray(params.value)) { + params.value = params.value[labelDimIndex]; + } + + if (!formatter) { + var itemModel = data.getItemModel(dataIndex); + formatter = itemModel.get(status === 'normal' ? ['label', 'formatter'] : [status, 'label', 'formatter']); + } + + if (typeof formatter === 'function') { + params.status = status; + params.dimensionIndex = labelDimIndex; + return formatter(params); + } else if (typeof formatter === 'string') { + var str = formatTpl(formatter, params); + return str.replace(DIMENSION_LABEL_REG, function (origin, dimStr) { + var len = dimStr.length; + var dimLoose = dimStr.charAt(0) === '[' && dimStr.charAt(len - 1) === ']' ? +dimStr.slice(1, len - 1) : dimStr; + var val = retrieveRawValue(data, dataIndex, dimLoose); + + if (extendParams && isArray(extendParams.interpolatedValue)) { + var dimInfo = data.getDimensionInfo(dimLoose); + + if (dimInfo) { + val = extendParams.interpolatedValue[dimInfo.index]; + } + } + + return val != null ? val + '' : ''; + }); + } + }; + + DataFormatMixin.prototype.getRawValue = function (idx, dataType) { + return retrieveRawValue(this.getData(dataType), idx); + }; + + DataFormatMixin.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + return; + }; + + return DataFormatMixin; + }(); + function normalizeTooltipFormatResult(result) { + var markupText; + var markupFragment; + + if (isObject(result)) { + if (result.type) { + markupFragment = result; + } else { + if ("development" !== 'production') { + console.warn('The return type of `formatTooltip` is not supported: ' + makePrintable(result)); + } + } + } else { + markupText = result; + } + + return { + markupText: markupText, + markupFragment: markupFragment + }; + } + + function createTask(define) { + return new Task(define); + } + + var Task = function () { + function Task(define) { + define = define || {}; + this._reset = define.reset; + this._plan = define.plan; + this._count = define.count; + this._onDirty = define.onDirty; + this._dirty = true; + } + + Task.prototype.perform = function (performArgs) { + var upTask = this._upstream; + var skip = performArgs && performArgs.skip; + + if (this._dirty && upTask) { + var context = this.context; + context.data = context.outputData = upTask.context.outputData; + } + + if (this.__pipeline) { + this.__pipeline.currentTask = this; + } + + var planResult; + + if (this._plan && !skip) { + planResult = this._plan(this.context); + } + + var lastModBy = normalizeModBy(this._modBy); + var lastModDataCount = this._modDataCount || 0; + var modBy = normalizeModBy(performArgs && performArgs.modBy); + var modDataCount = performArgs && performArgs.modDataCount || 0; + + if (lastModBy !== modBy || lastModDataCount !== modDataCount) { + planResult = 'reset'; + } + + function normalizeModBy(val) { + !(val >= 1) && (val = 1); + return val; + } + + var forceFirstProgress; + + if (this._dirty || planResult === 'reset') { + this._dirty = false; + forceFirstProgress = this._doReset(skip); + } + + this._modBy = modBy; + this._modDataCount = modDataCount; + var step = performArgs && performArgs.step; + + if (upTask) { + if ("development" !== 'production') { + assert(upTask._outputDueEnd != null); + } + + this._dueEnd = upTask._outputDueEnd; + } else { + if ("development" !== 'production') { + assert(!this._progress || this._count); + } + + this._dueEnd = this._count ? this._count(this.context) : Infinity; + } + + if (this._progress) { + var start = this._dueIndex; + var end = Math.min(step != null ? this._dueIndex + step : Infinity, this._dueEnd); + + if (!skip && (forceFirstProgress || start < end)) { + var progress = this._progress; + + if (isArray(progress)) { + for (var i = 0; i < progress.length; i++) { + this._doProgress(progress[i], start, end, modBy, modDataCount); + } + } else { + this._doProgress(progress, start, end, modBy, modDataCount); + } + } + + this._dueIndex = end; + var outputDueEnd = this._settedOutputEnd != null ? this._settedOutputEnd : end; + + if ("development" !== 'production') { + assert(outputDueEnd >= this._outputDueEnd); + } + + this._outputDueEnd = outputDueEnd; + } else { + this._dueIndex = this._outputDueEnd = this._settedOutputEnd != null ? this._settedOutputEnd : this._dueEnd; + } + + return this.unfinished(); + }; + + Task.prototype.dirty = function () { + this._dirty = true; + this._onDirty && this._onDirty(this.context); + }; + + Task.prototype._doProgress = function (progress, start, end, modBy, modDataCount) { + iterator.reset(start, end, modBy, modDataCount); + this._callingProgress = progress; + + this._callingProgress({ + start: start, + end: end, + count: end - start, + next: iterator.next + }, this.context); + }; + + Task.prototype._doReset = function (skip) { + this._dueIndex = this._outputDueEnd = this._dueEnd = 0; + this._settedOutputEnd = null; + var progress; + var forceFirstProgress; + + if (!skip && this._reset) { + progress = this._reset(this.context); + + if (progress && progress.progress) { + forceFirstProgress = progress.forceFirstProgress; + progress = progress.progress; + } + + if (isArray(progress) && !progress.length) { + progress = null; + } + } + + this._progress = progress; + this._modBy = this._modDataCount = null; + var downstream = this._downstream; + downstream && downstream.dirty(); + return forceFirstProgress; + }; + + Task.prototype.unfinished = function () { + return this._progress && this._dueIndex < this._dueEnd; + }; + + Task.prototype.pipe = function (downTask) { + if ("development" !== 'production') { + assert(downTask && !downTask._disposed && downTask !== this); + } + + if (this._downstream !== downTask || this._dirty) { + this._downstream = downTask; + downTask._upstream = this; + downTask.dirty(); + } + }; + + Task.prototype.dispose = function () { + if (this._disposed) { + return; + } + + this._upstream && (this._upstream._downstream = null); + this._downstream && (this._downstream._upstream = null); + this._dirty = false; + this._disposed = true; + }; + + Task.prototype.getUpstream = function () { + return this._upstream; + }; + + Task.prototype.getDownstream = function () { + return this._downstream; + }; + + Task.prototype.setOutputEnd = function (end) { + this._outputDueEnd = this._settedOutputEnd = end; + }; + + return Task; + }(); + + var iterator = function () { + var end; + var current; + var modBy; + var modDataCount; + var winCount; + var it = { + reset: function (s, e, sStep, sCount) { + current = s; + end = e; + modBy = sStep; + modDataCount = sCount; + winCount = Math.ceil(modDataCount / modBy); + it.next = modBy > 1 && modDataCount > 0 ? modNext : sequentialNext; + } + }; + return it; + + function sequentialNext() { + return current < end ? current++ : null; + } + + function modNext() { + var dataIndex = current % winCount * modBy + Math.ceil(current / winCount); + var result = current >= end ? null : dataIndex < modDataCount ? dataIndex : current; + current++; + return result; + } + }(); + + function parseDataValue(value, opt) { + var dimType = opt && opt.type; + + if (dimType === 'ordinal') { + var ordinalMeta = opt && opt.ordinalMeta; + return ordinalMeta ? ordinalMeta.parseAndCollect(value) : value; + } + + if (dimType === 'time' && typeof value !== 'number' && value != null && value !== '-') { + value = +parseDate(value); + } + + return value == null || value === '' ? NaN : +value; + } + var valueParserMap = createHashMap({ + 'number': function (val) { + return parseFloat(val); + }, + 'time': function (val) { + return +parseDate(val); + }, + 'trim': function (val) { + return typeof val === 'string' ? trim(val) : val; + } + }); + function getRawValueParser(type) { + return valueParserMap.get(type); + } + var ORDER_COMPARISON_OP_MAP = { + lt: function (lval, rval) { + return lval < rval; + }, + lte: function (lval, rval) { + return lval <= rval; + }, + gt: function (lval, rval) { + return lval > rval; + }, + gte: function (lval, rval) { + return lval >= rval; + } + }; + + var FilterOrderComparator = function () { + function FilterOrderComparator(op, rval) { + if (typeof rval !== 'number') { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = 'rvalue of "<", ">", "<=", ">=" can only be number in filter.'; + } + + throwError(errMsg); + } + + this._opFn = ORDER_COMPARISON_OP_MAP[op]; + this._rvalFloat = numericToNumber(rval); + } + + FilterOrderComparator.prototype.evaluate = function (lval) { + return typeof lval === 'number' ? this._opFn(lval, this._rvalFloat) : this._opFn(numericToNumber(lval), this._rvalFloat); + }; + + return FilterOrderComparator; + }(); + + var SortOrderComparator = function () { + function SortOrderComparator(order, incomparable) { + var isDesc = order === 'desc'; + this._resultLT = isDesc ? 1 : -1; + + if (incomparable == null) { + incomparable = isDesc ? 'min' : 'max'; + } + + this._incomparable = incomparable === 'min' ? -Infinity : Infinity; + } + + SortOrderComparator.prototype.evaluate = function (lval, rval) { + var lvalTypeof = typeof lval; + var rvalTypeof = typeof rval; + var lvalFloat = lvalTypeof === 'number' ? lval : numericToNumber(lval); + var rvalFloat = rvalTypeof === 'number' ? rval : numericToNumber(rval); + var lvalNotNumeric = isNaN(lvalFloat); + var rvalNotNumeric = isNaN(rvalFloat); + + if (lvalNotNumeric) { + lvalFloat = this._incomparable; + } + + if (rvalNotNumeric) { + rvalFloat = this._incomparable; + } + + if (lvalNotNumeric && rvalNotNumeric) { + var lvalIsStr = lvalTypeof === 'string'; + var rvalIsStr = rvalTypeof === 'string'; + + if (lvalIsStr) { + lvalFloat = rvalIsStr ? lval : 0; + } + + if (rvalIsStr) { + rvalFloat = lvalIsStr ? rval : 0; + } + } + + return lvalFloat < rvalFloat ? this._resultLT : lvalFloat > rvalFloat ? -this._resultLT : 0; + }; + + return SortOrderComparator; + }(); + + var FilterEqualityComparator = function () { + function FilterEqualityComparator(isEq, rval) { + this._rval = rval; + this._isEQ = isEq; + this._rvalTypeof = typeof rval; + this._rvalFloat = numericToNumber(rval); + } + + FilterEqualityComparator.prototype.evaluate = function (lval) { + var eqResult = lval === this._rval; + + if (!eqResult) { + var lvalTypeof = typeof lval; + + if (lvalTypeof !== this._rvalTypeof && (lvalTypeof === 'number' || this._rvalTypeof === 'number')) { + eqResult = numericToNumber(lval) === this._rvalFloat; + } + } + + return this._isEQ ? eqResult : !eqResult; + }; + + return FilterEqualityComparator; + }(); + + function createFilterComparator(op, rval) { + return op === 'eq' || op === 'ne' ? new FilterEqualityComparator(op === 'eq', rval) : hasOwn(ORDER_COMPARISON_OP_MAP, op) ? new FilterOrderComparator(op, rval) : null; + } + + var ExternalSource = function () { + function ExternalSource() {} + + ExternalSource.prototype.getRawData = function () { + throw new Error('not supported'); + }; + + ExternalSource.prototype.getRawDataItem = function (dataIndex) { + throw new Error('not supported'); + }; + + ExternalSource.prototype.cloneRawData = function () { + return; + }; + + ExternalSource.prototype.getDimensionInfo = function (dim) { + return; + }; + + ExternalSource.prototype.cloneAllDimensionInfo = function () { + return; + }; + + ExternalSource.prototype.count = function () { + return; + }; + + ExternalSource.prototype.retrieveValue = function (dataIndex, dimIndex) { + return; + }; + + ExternalSource.prototype.retrieveValueFromItem = function (dataItem, dimIndex) { + return; + }; + + ExternalSource.prototype.convertValue = function (rawVal, dimInfo) { + return parseDataValue(rawVal, dimInfo); + }; + + return ExternalSource; + }(); + + function createExternalSource(internalSource, externalTransform) { + var extSource = new ExternalSource(); + var data = internalSource.data; + var sourceFormat = extSource.sourceFormat = internalSource.sourceFormat; + var sourceHeaderCount = internalSource.startIndex; + var errMsg = ''; + + if (internalSource.seriesLayoutBy !== SERIES_LAYOUT_BY_COLUMN) { + if ("development" !== 'production') { + errMsg = '`seriesLayoutBy` of upstream dataset can only be "column" in data transform.'; + } + + throwError(errMsg); + } + + var dimensions = []; + var dimsByName = {}; + var dimsDef = internalSource.dimensionsDefine; + + if (dimsDef) { + each(dimsDef, function (dimDef, idx) { + var name = dimDef.name; + var dimDefExt = { + index: idx, + name: name, + displayName: dimDef.displayName + }; + dimensions.push(dimDefExt); + + if (name != null) { + var errMsg_1 = ''; + + if (hasOwn(dimsByName, name)) { + if ("development" !== 'production') { + errMsg_1 = 'dimension name "' + name + '" duplicated.'; + } + + throwError(errMsg_1); + } + + dimsByName[name] = dimDefExt; + } + }); + } else { + for (var i = 0; i < internalSource.dimensionsDetectedCount || 0; i++) { + dimensions.push({ + index: i + }); + } + } + + var rawItemGetter = getRawSourceItemGetter(sourceFormat, SERIES_LAYOUT_BY_COLUMN); + + if (externalTransform.__isBuiltIn) { + extSource.getRawDataItem = function (dataIndex) { + return rawItemGetter(data, sourceHeaderCount, dimensions, dataIndex); + }; + + extSource.getRawData = bind(getRawData, null, internalSource); + } + + extSource.cloneRawData = bind(cloneRawData, null, internalSource); + var rawCounter = getRawSourceDataCounter(sourceFormat, SERIES_LAYOUT_BY_COLUMN); + extSource.count = bind(rawCounter, null, data, sourceHeaderCount, dimensions); + var rawValueGetter = getRawSourceValueGetter(sourceFormat); + + extSource.retrieveValue = function (dataIndex, dimIndex) { + var rawItem = rawItemGetter(data, sourceHeaderCount, dimensions, dataIndex); + return retrieveValueFromItem(rawItem, dimIndex); + }; + + var retrieveValueFromItem = extSource.retrieveValueFromItem = function (dataItem, dimIndex) { + if (dataItem == null) { + return; + } + + var dimDef = dimensions[dimIndex]; + + if (dimDef) { + return rawValueGetter(dataItem, dimIndex, dimDef.name); + } + }; + + extSource.getDimensionInfo = bind(getDimensionInfo, null, dimensions, dimsByName); + extSource.cloneAllDimensionInfo = bind(cloneAllDimensionInfo, null, dimensions); + return extSource; + } + + function getRawData(upstream) { + var sourceFormat = upstream.sourceFormat; + + if (!isSupportedSourceFormat(sourceFormat)) { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = '`getRawData` is not supported in source format ' + sourceFormat; + } + + throwError(errMsg); + } + + return upstream.data; + } + + function cloneRawData(upstream) { + var sourceFormat = upstream.sourceFormat; + var data = upstream.data; + + if (!isSupportedSourceFormat(sourceFormat)) { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = '`cloneRawData` is not supported in source format ' + sourceFormat; + } + + throwError(errMsg); + } + + if (sourceFormat === SOURCE_FORMAT_ARRAY_ROWS) { + var result = []; + + for (var i = 0, len = data.length; i < len; i++) { + result.push(data[i].slice()); + } + + return result; + } else if (sourceFormat === SOURCE_FORMAT_OBJECT_ROWS) { + var result = []; + + for (var i = 0, len = data.length; i < len; i++) { + result.push(extend({}, data[i])); + } + + return result; + } + } + + function getDimensionInfo(dimensions, dimsByName, dim) { + if (dim == null) { + return; + } + + if (typeof dim === 'number' || !isNaN(dim) && !hasOwn(dimsByName, dim)) { + return dimensions[dim]; + } else if (hasOwn(dimsByName, dim)) { + return dimsByName[dim]; + } + } + + function cloneAllDimensionInfo(dimensions) { + return clone(dimensions); + } + + var externalTransformMap = createHashMap(); + function registerExternalTransform(externalTransform) { + externalTransform = clone(externalTransform); + var type = externalTransform.type; + var errMsg = ''; + + if (!type) { + if ("development" !== 'production') { + errMsg = 'Must have a `type` when `registerTransform`.'; + } + + throwError(errMsg); + } + + var typeParsed = type.split(':'); + + if (typeParsed.length !== 2) { + if ("development" !== 'production') { + errMsg = 'Name must include namespace like "ns:regression".'; + } + + throwError(errMsg); + } + + var isBuiltIn = false; + + if (typeParsed[0] === 'echarts') { + type = typeParsed[1]; + isBuiltIn = true; + } + + externalTransform.__isBuiltIn = isBuiltIn; + externalTransformMap.set(type, externalTransform); + } + function applyDataTransform(rawTransOption, sourceList, infoForPrint) { + var pipedTransOption = normalizeToArray(rawTransOption); + var pipeLen = pipedTransOption.length; + var errMsg = ''; + + if (!pipeLen) { + if ("development" !== 'production') { + errMsg = 'If `transform` declared, it should at least contain one transform.'; + } + + throwError(errMsg); + } + + for (var i = 0, len = pipeLen; i < len; i++) { + var transOption = pipedTransOption[i]; + sourceList = applySingleDataTransform(transOption, sourceList, infoForPrint, pipeLen === 1 ? null : i); + + if (i !== len - 1) { + sourceList.length = Math.max(sourceList.length, 1); + } + } + + return sourceList; + } + + function applySingleDataTransform(transOption, upSourceList, infoForPrint, pipeIndex) { + var errMsg = ''; + + if (!upSourceList.length) { + if ("development" !== 'production') { + errMsg = 'Must have at least one upstream dataset.'; + } + + throwError(errMsg); + } + + if (!isObject(transOption)) { + if ("development" !== 'production') { + errMsg = 'transform declaration must be an object rather than ' + typeof transOption + '.'; + } + + throwError(errMsg); + } + + var transType = transOption.type; + var externalTransform = externalTransformMap.get(transType); + + if (!externalTransform) { + if ("development" !== 'production') { + errMsg = 'Can not find transform on type "' + transType + '".'; + } + + throwError(errMsg); + } + + var extUpSourceList = map(upSourceList, function (upSource) { + return createExternalSource(upSource, externalTransform); + }); + var resultList = normalizeToArray(externalTransform.transform({ + upstream: extUpSourceList[0], + upstreamList: extUpSourceList, + config: clone(transOption.config) + })); + + if ("development" !== 'production') { + if (transOption.print) { + var printStrArr = map(resultList, function (extSource) { + var pipeIndexStr = pipeIndex != null ? ' === pipe index: ' + pipeIndex : ''; + return ['=== dataset index: ' + infoForPrint.datasetIndex + pipeIndexStr + ' ===', '- transform result data:', makePrintable(extSource.data), '- transform result dimensions:', makePrintable(extSource.dimensions)].join('\n'); + }).join('\n'); + consoleLog(printStrArr); + } + } + + return map(resultList, function (result, resultIndex) { + var errMsg = ''; + + if (!isObject(result)) { + if ("development" !== 'production') { + errMsg = 'A transform should not return some empty results.'; + } + + throwError(errMsg); + } + + if (!result.data) { + if ("development" !== 'production') { + errMsg = 'Transform result data should be not be null or undefined'; + } + + throwError(errMsg); + } + + var sourceFormat = detectSourceFormat(result.data); + + if (!isSupportedSourceFormat(sourceFormat)) { + if ("development" !== 'production') { + errMsg = 'Transform result data should be array rows or object rows.'; + } + + throwError(errMsg); + } + + var resultMetaRawOption; + var firstUpSource = upSourceList[0]; + + if (firstUpSource && resultIndex === 0 && !result.dimensions) { + var startIndex = firstUpSource.startIndex; + + if (startIndex) { + result.data = firstUpSource.data.slice(0, startIndex).concat(result.data); + } + + resultMetaRawOption = { + seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN, + sourceHeader: startIndex, + dimensions: firstUpSource.metaRawOption.dimensions + }; + } else { + resultMetaRawOption = { + seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN, + sourceHeader: 0, + dimensions: result.dimensions + }; + } + + return createSource(result.data, resultMetaRawOption, null, null); + }); + } + + function isSupportedSourceFormat(sourceFormat) { + return sourceFormat === SOURCE_FORMAT_ARRAY_ROWS || sourceFormat === SOURCE_FORMAT_OBJECT_ROWS; + } + + var SourceManager = function () { + function SourceManager(sourceHost) { + this._sourceList = []; + this._upstreamSignList = []; + this._versionSignBase = 0; + this._sourceHost = sourceHost; + } + + SourceManager.prototype.dirty = function () { + this._setLocalSource([], []); + }; + + SourceManager.prototype._setLocalSource = function (sourceList, upstreamSignList) { + this._sourceList = sourceList; + this._upstreamSignList = upstreamSignList; + this._versionSignBase++; + + if (this._versionSignBase > 9e10) { + this._versionSignBase = 0; + } + }; + + SourceManager.prototype._getVersionSign = function () { + return this._sourceHost.uid + '_' + this._versionSignBase; + }; + + SourceManager.prototype.prepareSource = function () { + if (this._isDirty()) { + this._createSource(); + } + }; + + SourceManager.prototype._createSource = function () { + this._setLocalSource([], []); + + var sourceHost = this._sourceHost; + + var upSourceMgrList = this._getUpstreamSourceManagers(); + + var hasUpstream = !!upSourceMgrList.length; + var resultSourceList; + var upstreamSignList; + + if (isSeries(sourceHost)) { + var seriesModel = sourceHost; + var data = void 0; + var sourceFormat = void 0; + var upSource = void 0; + + if (hasUpstream) { + var upSourceMgr = upSourceMgrList[0]; + upSourceMgr.prepareSource(); + upSource = upSourceMgr.getSource(); + data = upSource.data; + sourceFormat = upSource.sourceFormat; + upstreamSignList = [upSourceMgr._getVersionSign()]; + } else { + data = seriesModel.get('data', true); + sourceFormat = isTypedArray(data) ? SOURCE_FORMAT_TYPED_ARRAY : SOURCE_FORMAT_ORIGINAL; + upstreamSignList = []; + } + + var newMetaRawOption = this._getSourceMetaRawOption(); + + var upMetaRawOption = upSource ? upSource.metaRawOption : null; + var seriesLayoutBy = retrieve2(newMetaRawOption.seriesLayoutBy, upMetaRawOption ? upMetaRawOption.seriesLayoutBy : null); + var sourceHeader = retrieve2(newMetaRawOption.sourceHeader, upMetaRawOption ? upMetaRawOption.sourceHeader : null); + var dimensions = retrieve2(newMetaRawOption.dimensions, upMetaRawOption ? upMetaRawOption.dimensions : null); + resultSourceList = [createSource(data, { + seriesLayoutBy: seriesLayoutBy, + sourceHeader: sourceHeader, + dimensions: dimensions + }, sourceFormat, seriesModel.get('encode', true))]; + } else { + var datasetModel = sourceHost; + + if (hasUpstream) { + var result = this._applyTransform(upSourceMgrList); + + resultSourceList = result.sourceList; + upstreamSignList = result.upstreamSignList; + } else { + var sourceData = datasetModel.get('source', true); + resultSourceList = [createSource(sourceData, this._getSourceMetaRawOption(), null, null)]; + upstreamSignList = []; + } + } + + if ("development" !== 'production') { + assert(resultSourceList && upstreamSignList); + } + + this._setLocalSource(resultSourceList, upstreamSignList); + }; + + SourceManager.prototype._applyTransform = function (upMgrList) { + var datasetModel = this._sourceHost; + var transformOption = datasetModel.get('transform', true); + var fromTransformResult = datasetModel.get('fromTransformResult', true); + + if ("development" !== 'production') { + assert(fromTransformResult != null || transformOption != null); + } + + if (fromTransformResult != null) { + var errMsg = ''; + + if (upMgrList.length !== 1) { + if ("development" !== 'production') { + errMsg = 'When using `fromTransformResult`, there should be only one upstream dataset'; + } + + doThrow(errMsg); + } + } + + var sourceList; + var upSourceList = []; + var upstreamSignList = []; + each(upMgrList, function (upMgr) { + upMgr.prepareSource(); + var upSource = upMgr.getSource(fromTransformResult || 0); + var errMsg = ''; + + if (fromTransformResult != null && !upSource) { + if ("development" !== 'production') { + errMsg = 'Can not retrieve result by `fromTransformResult`: ' + fromTransformResult; + } + + doThrow(errMsg); + } + + upSourceList.push(upSource); + upstreamSignList.push(upMgr._getVersionSign()); + }); + + if (transformOption) { + sourceList = applyDataTransform(transformOption, upSourceList, { + datasetIndex: datasetModel.componentIndex + }); + } else if (fromTransformResult != null) { + sourceList = [cloneSourceShallow(upSourceList[0])]; + } + + return { + sourceList: sourceList, + upstreamSignList: upstreamSignList + }; + }; + + SourceManager.prototype._isDirty = function () { + var sourceList = this._sourceList; + + if (!sourceList.length) { + return true; + } + + var upSourceMgrList = this._getUpstreamSourceManagers(); + + for (var i = 0; i < upSourceMgrList.length; i++) { + var upSrcMgr = upSourceMgrList[i]; + + if (upSrcMgr._isDirty() || this._upstreamSignList[i] !== upSrcMgr._getVersionSign()) { + return true; + } + } + }; + + SourceManager.prototype.getSource = function (sourceIndex) { + return this._sourceList[sourceIndex || 0]; + }; + + SourceManager.prototype._getUpstreamSourceManagers = function () { + var sourceHost = this._sourceHost; + + if (isSeries(sourceHost)) { + var datasetModel = querySeriesUpstreamDatasetModel(sourceHost); + return !datasetModel ? [] : [datasetModel.getSourceManager()]; + } else { + return map(queryDatasetUpstreamDatasetModels(sourceHost), function (datasetModel) { + return datasetModel.getSourceManager(); + }); + } + }; + + SourceManager.prototype._getSourceMetaRawOption = function () { + var sourceHost = this._sourceHost; + var seriesLayoutBy; + var sourceHeader; + var dimensions; + + if (isSeries(sourceHost)) { + seriesLayoutBy = sourceHost.get('seriesLayoutBy', true); + sourceHeader = sourceHost.get('sourceHeader', true); + dimensions = sourceHost.get('dimensions', true); + } else if (!this._getUpstreamSourceManagers().length) { + var model = sourceHost; + seriesLayoutBy = model.get('seriesLayoutBy', true); + sourceHeader = model.get('sourceHeader', true); + dimensions = model.get('dimensions', true); + } + + return { + seriesLayoutBy: seriesLayoutBy, + sourceHeader: sourceHeader, + dimensions: dimensions + }; + }; + + return SourceManager; + }(); + function disableTransformOptionMerge(datasetModel) { + var transformOption = datasetModel.option.transform; + transformOption && setAsPrimitive(datasetModel.option.transform); + } + + function isSeries(sourceHost) { + return sourceHost.mainType === 'series'; + } + + function doThrow(errMsg) { + throw new Error(errMsg); + } + + var TOOLTIP_LINE_HEIGHT_CSS = 'line-height:1'; + + function getTooltipTextStyle(textStyle, renderMode) { + var nameFontColor = textStyle.color || '#6e7079'; + var nameFontSize = textStyle.fontSize || 12; + var nameFontWeight = textStyle.fontWeight || '400'; + var valueFontColor = textStyle.color || '#464646'; + var valueFontSize = textStyle.fontSize || 14; + var valueFontWeight = textStyle.fontWeight || '900'; + + if (renderMode === 'html') { + return { + nameStyle: "font-size:" + nameFontSize + "px;color:" + nameFontColor + ";font-weight:" + nameFontWeight, + valueStyle: "font-size:" + valueFontSize + "px;color:" + valueFontColor + ";font-weight:" + valueFontWeight + }; + } else { + return { + nameStyle: { + fontSize: nameFontSize, + fill: nameFontColor, + fontWeight: nameFontWeight + }, + valueStyle: { + fontSize: valueFontSize, + fill: valueFontColor, + fontWeight: valueFontWeight + } + }; + } + } + + var HTML_GAPS = [0, 10, 20, 30]; + var RICH_TEXT_GAPS = ['', '\n', '\n\n', '\n\n\n']; + function createTooltipMarkup(type, option) { + option.type = type; + return option; + } + + function getBuilder(fragment) { + return hasOwn(builderMap, fragment.type) && builderMap[fragment.type]; + } + + var builderMap = { + section: { + planLayout: function (fragment) { + var subBlockLen = fragment.blocks.length; + var thisBlockHasInnerGap = subBlockLen > 1 || subBlockLen > 0 && !fragment.noHeader; + var thisGapLevelBetweenSubBlocks = 0; + each(fragment.blocks, function (subBlock) { + getBuilder(subBlock).planLayout(subBlock); + var subGapLevel = subBlock.__gapLevelBetweenSubBlocks; + + if (subGapLevel >= thisGapLevelBetweenSubBlocks) { + thisGapLevelBetweenSubBlocks = subGapLevel + (thisBlockHasInnerGap && (!subGapLevel || subBlock.type === 'section' && !subBlock.noHeader) ? 1 : 0); + } + }); + fragment.__gapLevelBetweenSubBlocks = thisGapLevelBetweenSubBlocks; + }, + build: function (ctx, fragment, topMarginForOuterGap, toolTipTextStyle) { + var noHeader = fragment.noHeader; + var gaps = getGap(fragment); + var subMarkupText = buildSubBlocks(ctx, fragment, noHeader ? topMarginForOuterGap : gaps.html, toolTipTextStyle); + + if (noHeader) { + return subMarkupText; + } + + var displayableHeader = makeValueReadable(fragment.header, 'ordinal', ctx.useUTC); + var nameStyle = getTooltipTextStyle(toolTipTextStyle, ctx.renderMode).nameStyle; + + if (ctx.renderMode === 'richText') { + return wrapInlineNameRichText(ctx, displayableHeader, nameStyle) + gaps.richText + subMarkupText; + } else { + return wrapBlockHTML("
                " + encodeHTML(displayableHeader) + '
                ' + subMarkupText, topMarginForOuterGap); + } + } + }, + nameValue: { + planLayout: function (fragment) { + fragment.__gapLevelBetweenSubBlocks = 0; + }, + build: function (ctx, fragment, topMarginForOuterGap, toolTipTextStyle) { + var renderMode = ctx.renderMode; + var noName = fragment.noName; + var noValue = fragment.noValue; + var noMarker = !fragment.markerType; + var name = fragment.name; + var value = fragment.value; + var useUTC = ctx.useUTC; + + if (noName && noValue) { + return; + } + + var markerStr = noMarker ? '' : ctx.markupStyleCreator.makeTooltipMarker(fragment.markerType, fragment.markerColor || '#333', renderMode); + var readableName = noName ? '' : makeValueReadable(name, 'ordinal', useUTC); + var valueTypeOption = fragment.valueType; + var readableValueList = noValue ? [] : isArray(value) ? map(value, function (val, idx) { + return makeValueReadable(val, isArray(valueTypeOption) ? valueTypeOption[idx] : valueTypeOption, useUTC); + }) : [makeValueReadable(value, isArray(valueTypeOption) ? valueTypeOption[0] : valueTypeOption, useUTC)]; + var valueAlignRight = !noMarker || !noName; + var valueCloseToMarker = !noMarker && noName; + + var _a = getTooltipTextStyle(toolTipTextStyle, renderMode), + nameStyle = _a.nameStyle, + valueStyle = _a.valueStyle; + + return renderMode === 'richText' ? (noMarker ? '' : markerStr) + (noName ? '' : wrapInlineNameRichText(ctx, readableName, nameStyle)) + (noValue ? '' : wrapInlineValueRichText(ctx, readableValueList, valueAlignRight, valueCloseToMarker, valueStyle)) : wrapBlockHTML((noMarker ? '' : markerStr) + (noName ? '' : wrapInlineNameHTML(readableName, !noMarker, nameStyle)) + (noValue ? '' : wrapInlineValueHTML(readableValueList, valueAlignRight, valueCloseToMarker, valueStyle)), topMarginForOuterGap); + } + } + }; + + function buildSubBlocks(ctx, fragment, topMarginForOuterGap, tooltipTextStyle) { + var subMarkupTextList = []; + var subBlocks = fragment.blocks || []; + assert(!subBlocks || isArray(subBlocks)); + subBlocks = subBlocks || []; + var orderMode = ctx.orderMode; + + if (fragment.sortBlocks && orderMode) { + subBlocks = subBlocks.slice(); + var orderMap = { + valueAsc: 'asc', + valueDesc: 'desc' + }; + + if (hasOwn(orderMap, orderMode)) { + var comparator_1 = new SortOrderComparator(orderMap[orderMode], null); + subBlocks.sort(function (a, b) { + return comparator_1.evaluate(a.sortParam, b.sortParam); + }); + } else if (orderMode === 'seriesDesc') { + subBlocks.reverse(); + } + } + + var gaps = getGap(fragment); + each(subBlocks, function (subBlock, idx) { + var subMarkupText = getBuilder(subBlock).build(ctx, subBlock, idx > 0 ? gaps.html : 0, tooltipTextStyle); + subMarkupText != null && subMarkupTextList.push(subMarkupText); + }); + + if (!subMarkupTextList.length) { + return; + } + + return ctx.renderMode === 'richText' ? subMarkupTextList.join(gaps.richText) : wrapBlockHTML(subMarkupTextList.join(''), topMarginForOuterGap); + } + + function buildTooltipMarkup(fragment, markupStyleCreator, renderMode, orderMode, useUTC, toolTipTextStyle) { + if (!fragment) { + return; + } + + var builder = getBuilder(fragment); + builder.planLayout(fragment); + var ctx = { + useUTC: useUTC, + renderMode: renderMode, + orderMode: orderMode, + markupStyleCreator: markupStyleCreator + }; + return builder.build(ctx, fragment, 0, toolTipTextStyle); + } + + function getGap(fragment) { + var gapLevelBetweenSubBlocks = fragment.__gapLevelBetweenSubBlocks; + return { + html: HTML_GAPS[gapLevelBetweenSubBlocks], + richText: RICH_TEXT_GAPS[gapLevelBetweenSubBlocks] + }; + } + + function wrapBlockHTML(encodedContent, topGap) { + var clearfix = '
                '; + var marginCSS = "margin: " + topGap + "px 0 0"; + return "
                " + encodedContent + clearfix + '
                '; + } + + function wrapInlineNameHTML(name, leftHasMarker, style) { + var marginCss = leftHasMarker ? 'margin-left:2px' : ''; + return "" + encodeHTML(name) + ''; + } + + function wrapInlineValueHTML(valueList, alignRight, valueCloseToMarker, style) { + var paddingStr = valueCloseToMarker ? '10px' : '20px'; + var alignCSS = alignRight ? "float:right;margin-left:" + paddingStr : ''; + return "" + map(valueList, function (value) { + return encodeHTML(value); + }).join('  ') + ''; + } + + function wrapInlineNameRichText(ctx, name, style) { + return ctx.markupStyleCreator.wrapRichTextStyle(name, style); + } + + function wrapInlineValueRichText(ctx, valueList, alignRight, valueCloseToMarker, style) { + var styles = [style]; + var paddingLeft = valueCloseToMarker ? 10 : 20; + alignRight && styles.push({ + padding: [0, 0, 0, paddingLeft], + align: 'right' + }); + return ctx.markupStyleCreator.wrapRichTextStyle(valueList.join(' '), styles); + } + + function retrieveVisualColorForTooltipMarker(series, dataIndex) { + var style = series.getData().getItemVisual(dataIndex, 'style'); + var color = style[series.visualDrawType]; + return convertToColorString(color); + } + function getPaddingFromTooltipModel(model, renderMode) { + var padding = model.get('padding'); + return padding != null ? padding : renderMode === 'richText' ? [8, 10] : 10; + } + + var TooltipMarkupStyleCreator = function () { + function TooltipMarkupStyleCreator() { + this.richTextStyles = {}; + this._nextStyleNameId = getRandomIdBase(); + } + + TooltipMarkupStyleCreator.prototype._generateStyleName = function () { + return '__EC_aUTo_' + this._nextStyleNameId++; + }; + + TooltipMarkupStyleCreator.prototype.makeTooltipMarker = function (markerType, colorStr, renderMode) { + var markerId = renderMode === 'richText' ? this._generateStyleName() : null; + var marker = getTooltipMarker({ + color: colorStr, + type: markerType, + renderMode: renderMode, + markerId: markerId + }); + + if (isString(marker)) { + return marker; + } else { + if ("development" !== 'production') { + assert(markerId); + } + + this.richTextStyles[markerId] = marker.style; + return marker.content; + } + }; + + TooltipMarkupStyleCreator.prototype.wrapRichTextStyle = function (text, styles) { + var finalStl = {}; + + if (isArray(styles)) { + each(styles, function (stl) { + return extend(finalStl, stl); + }); + } else { + extend(finalStl, styles); + } + + var styleName = this._generateStyleName(); + + this.richTextStyles[styleName] = finalStl; + return "{" + styleName + "|" + text + "}"; + }; + + return TooltipMarkupStyleCreator; + }(); + + function defaultSeriesFormatTooltip(opt) { + var series = opt.series; + var dataIndex = opt.dataIndex; + var multipleSeries = opt.multipleSeries; + var data = series.getData(); + var tooltipDims = data.mapDimensionsAll('defaultedTooltip'); + var tooltipDimLen = tooltipDims.length; + var value = series.getRawValue(dataIndex); + var isValueArr = isArray(value); + var markerColor = retrieveVisualColorForTooltipMarker(series, dataIndex); + var inlineValue; + var inlineValueType; + var subBlocks; + var sortParam; + + if (tooltipDimLen > 1 || isValueArr && !tooltipDimLen) { + var formatArrResult = formatTooltipArrayValue(value, series, dataIndex, tooltipDims, markerColor); + inlineValue = formatArrResult.inlineValues; + inlineValueType = formatArrResult.inlineValueTypes; + subBlocks = formatArrResult.blocks; + sortParam = formatArrResult.inlineValues[0]; + } else if (tooltipDimLen) { + var dimInfo = data.getDimensionInfo(tooltipDims[0]); + sortParam = inlineValue = retrieveRawValue(data, dataIndex, tooltipDims[0]); + inlineValueType = dimInfo.type; + } else { + sortParam = inlineValue = isValueArr ? value[0] : value; + } + + var seriesNameSpecified = isNameSpecified(series); + var seriesName = seriesNameSpecified && series.name || ''; + var itemName = data.getName(dataIndex); + var inlineName = multipleSeries ? seriesName : itemName; + return createTooltipMarkup('section', { + header: seriesName, + noHeader: multipleSeries || !seriesNameSpecified, + sortParam: sortParam, + blocks: [createTooltipMarkup('nameValue', { + markerType: 'item', + markerColor: markerColor, + name: inlineName, + noName: !trim(inlineName), + value: inlineValue, + valueType: inlineValueType + })].concat(subBlocks || []) + }); + } + + function formatTooltipArrayValue(value, series, dataIndex, tooltipDims, colorStr) { + var data = series.getData(); + var isValueMultipleLine = reduce(value, function (isValueMultipleLine, val, idx) { + var dimItem = data.getDimensionInfo(idx); + return isValueMultipleLine = isValueMultipleLine || dimItem && dimItem.tooltip !== false && dimItem.displayName != null; + }, false); + var inlineValues = []; + var inlineValueTypes = []; + var blocks = []; + tooltipDims.length ? each(tooltipDims, function (dim) { + setEachItem(retrieveRawValue(data, dataIndex, dim), dim); + }) : each(value, setEachItem); + + function setEachItem(val, dim) { + var dimInfo = data.getDimensionInfo(dim); + + if (!dimInfo || dimInfo.otherDims.tooltip === false) { + return; + } + + if (isValueMultipleLine) { + blocks.push(createTooltipMarkup('nameValue', { + markerType: 'subItem', + markerColor: colorStr, + name: dimInfo.displayName, + value: val, + valueType: dimInfo.type + })); + } else { + inlineValues.push(val); + inlineValueTypes.push(dimInfo.type); + } + } + + return { + inlineValues: inlineValues, + inlineValueTypes: inlineValueTypes, + blocks: blocks + }; + } + + var inner$1 = makeInner(); + + function getSelectionKey(data, dataIndex) { + return data.getName(dataIndex) || data.getId(dataIndex); + } + + var SeriesModel = function (_super) { + __extends(SeriesModel, _super); + + function SeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this._selectedDataIndicesMap = {}; + return _this; + } + + SeriesModel.prototype.init = function (option, parentModel, ecModel) { + this.seriesIndex = this.componentIndex; + this.dataTask = createTask({ + count: dataTaskCount, + reset: dataTaskReset + }); + this.dataTask.context = { + model: this + }; + this.mergeDefaultAndTheme(option, ecModel); + var sourceManager = inner$1(this).sourceManager = new SourceManager(this); + sourceManager.prepareSource(); + var data = this.getInitialData(option, ecModel); + wrapData(data, this); + this.dataTask.context.data = data; + + if ("development" !== 'production') { + assert(data, 'getInitialData returned invalid data.'); + } + + inner$1(this).dataBeforeProcessed = data; + autoSeriesName(this); + + this._initSelectedMapFromData(data); + }; + + SeriesModel.prototype.mergeDefaultAndTheme = function (option, ecModel) { + var layoutMode = fetchLayoutMode(this); + var inputPositionParams = layoutMode ? getLayoutParams(option) : {}; + var themeSubType = this.subType; + + if (ComponentModel.hasClass(themeSubType)) { + themeSubType += 'Series'; + } + + merge(option, ecModel.getTheme().get(this.subType)); + merge(option, this.getDefaultOption()); + defaultEmphasis(option, 'label', ['show']); + this.fillDataTextStyle(option.data); + + if (layoutMode) { + mergeLayoutParam(option, inputPositionParams, layoutMode); + } + }; + + SeriesModel.prototype.mergeOption = function (newSeriesOption, ecModel) { + newSeriesOption = merge(this.option, newSeriesOption, true); + this.fillDataTextStyle(newSeriesOption.data); + var layoutMode = fetchLayoutMode(this); + + if (layoutMode) { + mergeLayoutParam(this.option, newSeriesOption, layoutMode); + } + + var sourceManager = inner$1(this).sourceManager; + sourceManager.dirty(); + sourceManager.prepareSource(); + var data = this.getInitialData(newSeriesOption, ecModel); + wrapData(data, this); + this.dataTask.dirty(); + this.dataTask.context.data = data; + inner$1(this).dataBeforeProcessed = data; + autoSeriesName(this); + + this._initSelectedMapFromData(data); + }; + + SeriesModel.prototype.fillDataTextStyle = function (data) { + if (data && !isTypedArray(data)) { + var props = ['show']; + + for (var i = 0; i < data.length; i++) { + if (data[i] && data[i].label) { + defaultEmphasis(data[i], 'label', props); + } + } + } + }; + + SeriesModel.prototype.getInitialData = function (option, ecModel) { + return; + }; + + SeriesModel.prototype.appendData = function (params) { + var data = this.getRawData(); + data.appendData(params.data); + }; + + SeriesModel.prototype.getData = function (dataType) { + var task = getCurrentTask(this); + + if (task) { + var data = task.context.data; + return dataType == null ? data : data.getLinkedData(dataType); + } else { + return inner$1(this).data; + } + }; + + SeriesModel.prototype.getAllData = function () { + var mainData = this.getData(); + return mainData && mainData.getLinkedDataAll ? mainData.getLinkedDataAll() : [{ + data: mainData + }]; + }; + + SeriesModel.prototype.setData = function (data) { + var task = getCurrentTask(this); + + if (task) { + var context = task.context; + context.outputData = data; + + if (task !== this.dataTask) { + context.data = data; + } + } + + inner$1(this).data = data; + }; + + SeriesModel.prototype.getSource = function () { + return inner$1(this).sourceManager.getSource(); + }; + + SeriesModel.prototype.getRawData = function () { + return inner$1(this).dataBeforeProcessed; + }; + + SeriesModel.prototype.getBaseAxis = function () { + var coordSys = this.coordinateSystem; + return coordSys && coordSys.getBaseAxis && coordSys.getBaseAxis(); + }; + + SeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + return defaultSeriesFormatTooltip({ + series: this, + dataIndex: dataIndex, + multipleSeries: multipleSeries + }); + }; + + SeriesModel.prototype.isAnimationEnabled = function () { + if (env.node) { + return false; + } + + var animationEnabled = this.getShallow('animation'); + + if (animationEnabled) { + if (this.getData().count() > this.getShallow('animationThreshold')) { + animationEnabled = false; + } + } + + return !!animationEnabled; + }; + + SeriesModel.prototype.restoreData = function () { + this.dataTask.dirty(); + }; + + SeriesModel.prototype.getColorFromPalette = function (name, scope, requestColorNum) { + var ecModel = this.ecModel; + var color = PaletteMixin.prototype.getColorFromPalette.call(this, name, scope, requestColorNum); + + if (!color) { + color = ecModel.getColorFromPalette(name, scope, requestColorNum); + } + + return color; + }; + + SeriesModel.prototype.coordDimToDataDim = function (coordDim) { + return this.getRawData().mapDimensionsAll(coordDim); + }; + + SeriesModel.prototype.getProgressive = function () { + return this.get('progressive'); + }; + + SeriesModel.prototype.getProgressiveThreshold = function () { + return this.get('progressiveThreshold'); + }; + + SeriesModel.prototype.select = function (innerDataIndices, dataType) { + this._innerSelect(this.getData(dataType), innerDataIndices); + }; + + SeriesModel.prototype.unselect = function (innerDataIndices, dataType) { + var selectedMap = this.option.selectedMap; + + if (!selectedMap) { + return; + } + + var data = this.getData(dataType); + + for (var i = 0; i < innerDataIndices.length; i++) { + var dataIndex = innerDataIndices[i]; + var nameOrId = getSelectionKey(data, dataIndex); + selectedMap[nameOrId] = false; + this._selectedDataIndicesMap[nameOrId] = -1; + } + }; + + SeriesModel.prototype.toggleSelect = function (innerDataIndices, dataType) { + var tmpArr = []; + + for (var i = 0; i < innerDataIndices.length; i++) { + tmpArr[0] = innerDataIndices[i]; + this.isSelected(innerDataIndices[i], dataType) ? this.unselect(tmpArr, dataType) : this.select(tmpArr, dataType); + } + }; + + SeriesModel.prototype.getSelectedDataIndices = function () { + var selectedDataIndicesMap = this._selectedDataIndicesMap; + var nameOrIds = keys(selectedDataIndicesMap); + var dataIndices = []; + + for (var i = 0; i < nameOrIds.length; i++) { + var dataIndex = selectedDataIndicesMap[nameOrIds[i]]; + + if (dataIndex >= 0) { + dataIndices.push(dataIndex); + } + } + + return dataIndices; + }; + + SeriesModel.prototype.isSelected = function (dataIndex, dataType) { + var selectedMap = this.option.selectedMap; + + if (!selectedMap) { + return false; + } + + var data = this.getData(dataType); + var nameOrId = getSelectionKey(data, dataIndex); + return selectedMap[nameOrId] || false; + }; + + SeriesModel.prototype._innerSelect = function (data, innerDataIndices) { + var _a, _b; + + var selectedMode = this.option.selectedMode; + var len = innerDataIndices.length; + + if (!selectedMode || !len) { + return; + } + + if (selectedMode === 'multiple') { + var selectedMap = this.option.selectedMap || (this.option.selectedMap = {}); + + for (var i = 0; i < len; i++) { + var dataIndex = innerDataIndices[i]; + var nameOrId = getSelectionKey(data, dataIndex); + selectedMap[nameOrId] = true; + this._selectedDataIndicesMap[nameOrId] = data.getRawIndex(dataIndex); + } + } else if (selectedMode === 'single' || selectedMode === true) { + var lastDataIndex = innerDataIndices[len - 1]; + var nameOrId = getSelectionKey(data, lastDataIndex); + this.option.selectedMap = (_a = {}, _a[nameOrId] = true, _a); + this._selectedDataIndicesMap = (_b = {}, _b[nameOrId] = data.getRawIndex(lastDataIndex), _b); + } + }; + + SeriesModel.prototype._initSelectedMapFromData = function (data) { + if (this.option.selectedMap) { + return; + } + + var dataIndices = []; + + if (data.hasItemOption) { + data.each(function (idx) { + var rawItem = data.getRawDataItem(idx); + + if (typeof rawItem === 'object' && rawItem.selected) { + dataIndices.push(idx); + } + }); + } + + if (dataIndices.length > 0) { + this._innerSelect(data, dataIndices); + } + }; + + SeriesModel.registerClass = function (clz) { + return ComponentModel.registerClass(clz); + }; + + SeriesModel.protoInitialize = function () { + var proto = SeriesModel.prototype; + proto.type = 'series.__base__'; + proto.seriesIndex = 0; + proto.useColorPaletteOnData = false; + proto.ignoreStyleOnData = false; + proto.hasSymbolVisual = false; + proto.defaultSymbol = 'circle'; + proto.visualStyleAccessPath = 'itemStyle'; + proto.visualDrawType = 'fill'; + }(); + + return SeriesModel; + }(ComponentModel); + + mixin(SeriesModel, DataFormatMixin); + mixin(SeriesModel, PaletteMixin); + mountExtend(SeriesModel, ComponentModel); + + function autoSeriesName(seriesModel) { + var name = seriesModel.name; + + if (!isNameSpecified(seriesModel)) { + seriesModel.name = getSeriesAutoName(seriesModel) || name; + } + } + + function getSeriesAutoName(seriesModel) { + var data = seriesModel.getRawData(); + var dataDims = data.mapDimensionsAll('seriesName'); + var nameArr = []; + each(dataDims, function (dataDim) { + var dimInfo = data.getDimensionInfo(dataDim); + dimInfo.displayName && nameArr.push(dimInfo.displayName); + }); + return nameArr.join(' '); + } + + function dataTaskCount(context) { + return context.model.getRawData().count(); + } + + function dataTaskReset(context) { + var seriesModel = context.model; + seriesModel.setData(seriesModel.getRawData().cloneShallow()); + return dataTaskProgress; + } + + function dataTaskProgress(param, context) { + if (context.outputData && param.end > context.outputData.count()) { + context.model.getRawData().cloneShallow(context.outputData); + } + } + + function wrapData(data, seriesModel) { + each(__spreadArrays(data.CHANGABLE_METHODS, data.DOWNSAMPLE_METHODS), function (methodName) { + data.wrapMethod(methodName, curry(onDataChange, seriesModel)); + }); + } + + function onDataChange(seriesModel, newList) { + var task = getCurrentTask(seriesModel); + + if (task) { + task.setOutputEnd((newList || this).count()); + } + + return newList; + } + + function getCurrentTask(seriesModel) { + var scheduler = (seriesModel.ecModel || {}).scheduler; + var pipeline = scheduler && scheduler.getPipeline(seriesModel.uid); + + if (pipeline) { + var task = pipeline.currentTask; + + if (task) { + var agentStubMap = task.agentStubMap; + + if (agentStubMap) { + task = agentStubMap.get(seriesModel.uid); + } + } + + return task; + } + } + + var ComponentView = function () { + function ComponentView() { + this.group = new Group(); + this.uid = getUID('viewComponent'); + } + + ComponentView.prototype.init = function (ecModel, api) {}; + + ComponentView.prototype.render = function (model, ecModel, api, payload) {}; + + ComponentView.prototype.dispose = function (ecModel, api) {}; + + ComponentView.prototype.updateView = function (model, ecModel, api, payload) {}; + + ComponentView.prototype.updateLayout = function (model, ecModel, api, payload) {}; + + ComponentView.prototype.updateVisual = function (model, ecModel, api, payload) {}; + + ComponentView.prototype.blurSeries = function (seriesModels, ecModel) {}; + + return ComponentView; + }(); + enableClassExtend(ComponentView); + enableClassManagement(ComponentView); + + function createRenderPlanner() { + var inner = makeInner(); + return function (seriesModel) { + var fields = inner(seriesModel); + var pipelineContext = seriesModel.pipelineContext; + var originalLarge = !!fields.large; + var originalProgressive = !!fields.progressiveRender; + var large = fields.large = !!(pipelineContext && pipelineContext.large); + var progressive = fields.progressiveRender = !!(pipelineContext && pipelineContext.progressiveRender); + return !!(originalLarge !== large || originalProgressive !== progressive) && 'reset'; + }; + } + + var inner$2 = makeInner(); + var renderPlanner = createRenderPlanner(); + + var ChartView = function () { + function ChartView() { + this.group = new Group(); + this.uid = getUID('viewChart'); + this.renderTask = createTask({ + plan: renderTaskPlan, + reset: renderTaskReset + }); + this.renderTask.context = { + view: this + }; + } + + ChartView.prototype.init = function (ecModel, api) {}; + + ChartView.prototype.render = function (seriesModel, ecModel, api, payload) {}; + + ChartView.prototype.highlight = function (seriesModel, ecModel, api, payload) { + toggleHighlight(seriesModel.getData(), payload, 'emphasis'); + }; + + ChartView.prototype.downplay = function (seriesModel, ecModel, api, payload) { + toggleHighlight(seriesModel.getData(), payload, 'normal'); + }; + + ChartView.prototype.remove = function (ecModel, api) { + this.group.removeAll(); + }; + + ChartView.prototype.dispose = function (ecModel, api) {}; + + ChartView.prototype.updateView = function (seriesModel, ecModel, api, payload) { + this.render(seriesModel, ecModel, api, payload); + }; + + ChartView.prototype.updateLayout = function (seriesModel, ecModel, api, payload) { + this.render(seriesModel, ecModel, api, payload); + }; + + ChartView.prototype.updateVisual = function (seriesModel, ecModel, api, payload) { + this.render(seriesModel, ecModel, api, payload); + }; + + ChartView.markUpdateMethod = function (payload, methodName) { + inner$2(payload).updateMethod = methodName; + }; + + ChartView.protoInitialize = function () { + var proto = ChartView.prototype; + proto.type = 'chart'; + }(); + + return ChartView; + }(); + + function elSetState(el, state, highlightDigit) { + if (el) { + (state === 'emphasis' ? enterEmphasis : leaveEmphasis)(el, highlightDigit); + } + } + + function toggleHighlight(data, payload, state) { + var dataIndex = queryDataIndex(data, payload); + var highlightDigit = payload && payload.highlightKey != null ? getHighlightDigit(payload.highlightKey) : null; + + if (dataIndex != null) { + each(normalizeToArray(dataIndex), function (dataIdx) { + elSetState(data.getItemGraphicEl(dataIdx), state, highlightDigit); + }); + } else { + data.eachItemGraphicEl(function (el) { + elSetState(el, state, highlightDigit); + }); + } + } + + enableClassExtend(ChartView, ['dispose']); + enableClassManagement(ChartView); + + function renderTaskPlan(context) { + return renderPlanner(context.model); + } + + function renderTaskReset(context) { + var seriesModel = context.model; + var ecModel = context.ecModel; + var api = context.api; + var payload = context.payload; + var progressiveRender = seriesModel.pipelineContext.progressiveRender; + var view = context.view; + var updateMethod = payload && inner$2(payload).updateMethod; + var methodName = progressiveRender ? 'incrementalPrepareRender' : updateMethod && view[updateMethod] ? updateMethod : 'render'; + + if (methodName !== 'render') { + view[methodName](seriesModel, ecModel, api, payload); + } + + return progressMethodMap[methodName]; + } + + var progressMethodMap = { + incrementalPrepareRender: { + progress: function (params, context) { + context.view.incrementalRender(params, context.model, context.ecModel, context.api, context.payload); + } + }, + render: { + forceFirstProgress: true, + progress: function (params, context) { + context.view.render(context.model, context.ecModel, context.api, context.payload); + } + } + }; + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var ORIGIN_METHOD = '\0__throttleOriginMethod'; + var RATE = '\0__throttleRate'; + var THROTTLE_TYPE = '\0__throttleType'; + function throttle(fn, delay, debounce) { + var currCall; + var lastCall = 0; + var lastExec = 0; + var timer = null; + var diff; + var scope; + var args; + var debounceNextCall; + delay = delay || 0; + + function exec() { + lastExec = new Date().getTime(); + timer = null; + fn.apply(scope, args || []); + } + + var cb = function () { + var cbArgs = []; + + for (var _i = 0; _i < arguments.length; _i++) { + cbArgs[_i] = arguments[_i]; + } + + currCall = new Date().getTime(); + scope = this; + args = cbArgs; + var thisDelay = debounceNextCall || delay; + var thisDebounce = debounceNextCall || debounce; + debounceNextCall = null; + diff = currCall - (thisDebounce ? lastCall : lastExec) - thisDelay; + clearTimeout(timer); + + if (thisDebounce) { + timer = setTimeout(exec, thisDelay); + } else { + if (diff >= 0) { + exec(); + } else { + timer = setTimeout(exec, -diff); + } + } + + lastCall = currCall; + }; + + cb.clear = function () { + if (timer) { + clearTimeout(timer); + timer = null; + } + }; + + cb.debounceNextCall = function (debounceDelay) { + debounceNextCall = debounceDelay; + }; + + return cb; + } + function createOrUpdate(obj, fnAttr, rate, throttleType) { + var fn = obj[fnAttr]; + + if (!fn) { + return; + } + + var originFn = fn[ORIGIN_METHOD] || fn; + var lastThrottleType = fn[THROTTLE_TYPE]; + var lastRate = fn[RATE]; + + if (lastRate !== rate || lastThrottleType !== throttleType) { + if (rate == null || !throttleType) { + return obj[fnAttr] = originFn; + } + + fn = obj[fnAttr] = throttle(originFn, rate, throttleType === 'debounce'); + fn[ORIGIN_METHOD] = originFn; + fn[THROTTLE_TYPE] = throttleType; + fn[RATE] = rate; + } + + return fn; + } + function clear(obj, fnAttr) { + var fn = obj[fnAttr]; + + if (fn && fn[ORIGIN_METHOD]) { + obj[fnAttr] = fn[ORIGIN_METHOD]; + } + } + + var inner$3 = makeInner(); + var defaultStyleMappers = { + itemStyle: makeStyleMapper(ITEM_STYLE_KEY_MAP, true), + lineStyle: makeStyleMapper(LINE_STYLE_KEY_MAP, true) + }; + var defaultColorKey = { + lineStyle: 'stroke', + itemStyle: 'fill' + }; + + function getStyleMapper(seriesModel, stylePath) { + var styleMapper = seriesModel.visualStyleMapper || defaultStyleMappers[stylePath]; + + if (!styleMapper) { + console.warn("Unkown style type '" + stylePath + "'."); + return defaultStyleMappers.itemStyle; + } + + return styleMapper; + } + + function getDefaultColorKey(seriesModel, stylePath) { + var colorKey = seriesModel.visualDrawType || defaultColorKey[stylePath]; + + if (!colorKey) { + console.warn("Unkown style type '" + stylePath + "'."); + return 'fill'; + } + + return colorKey; + } + + var seriesStyleTask = { + createOnAllSeries: true, + performRawSeries: true, + reset: function (seriesModel, ecModel) { + var data = seriesModel.getData(); + var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle'; + var styleModel = seriesModel.getModel(stylePath); + var getStyle = getStyleMapper(seriesModel, stylePath); + var globalStyle = getStyle(styleModel); + var decalOption = styleModel.getShallow('decal'); + + if (decalOption) { + data.setVisual('decal', decalOption); + decalOption.dirty = true; + } + + var colorKey = getDefaultColorKey(seriesModel, stylePath); + var color = globalStyle[colorKey]; + var colorCallback = isFunction(color) ? color : null; + + if (!globalStyle[colorKey] || colorCallback) { + globalStyle[colorKey] = seriesModel.getColorFromPalette(seriesModel.name, null, ecModel.getSeriesCount()); + data.setVisual('colorFromPalette', true); + } + + data.setVisual('style', globalStyle); + data.setVisual('drawType', colorKey); + + if (!ecModel.isSeriesFiltered(seriesModel) && colorCallback) { + data.setVisual('colorFromPalette', false); + return { + dataEach: function (data, idx) { + var dataParams = seriesModel.getDataParams(idx); + var itemStyle = extend({}, globalStyle); + itemStyle[colorKey] = colorCallback(dataParams); + data.setItemVisual(idx, 'style', itemStyle); + } + }; + } + } + }; + var sharedModel = new Model(); + var dataStyleTask = { + createOnAllSeries: true, + performRawSeries: true, + reset: function (seriesModel, ecModel) { + if (seriesModel.ignoreStyleOnData || ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + var data = seriesModel.getData(); + var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle'; + var getStyle = getStyleMapper(seriesModel, stylePath); + var colorKey = data.getVisual('drawType'); + return { + dataEach: data.hasItemOption ? function (data, idx) { + var rawItem = data.getRawDataItem(idx); + + if (rawItem && rawItem[stylePath]) { + sharedModel.option = rawItem[stylePath]; + var style = getStyle(sharedModel); + var existsStyle = data.ensureUniqueItemVisual(idx, 'style'); + extend(existsStyle, style); + + if (sharedModel.option.decal) { + data.setItemVisual(idx, 'decal', sharedModel.option.decal); + sharedModel.option.decal.dirty = true; + } + + if (colorKey in style) { + data.setItemVisual(idx, 'colorFromPalette', false); + } + } + } : null + }; + } + }; + var dataColorPaletteTask = { + performRawSeries: true, + overallReset: function (ecModel) { + var paletteScopeGroupByType = createHashMap(); + ecModel.eachSeries(function (seriesModel) { + if (!seriesModel.useColorPaletteOnData) { + return; + } + + var colorScope = paletteScopeGroupByType.get(seriesModel.type); + + if (!colorScope) { + colorScope = {}; + paletteScopeGroupByType.set(seriesModel.type, colorScope); + } + + inner$3(seriesModel).scope = colorScope; + }); + ecModel.eachSeries(function (seriesModel) { + if (!seriesModel.useColorPaletteOnData || ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + var dataAll = seriesModel.getRawData(); + var idxMap = {}; + var data = seriesModel.getData(); + var colorScope = inner$3(seriesModel).scope; + var stylePath = seriesModel.visualStyleAccessPath || 'itemStyle'; + var colorKey = getDefaultColorKey(seriesModel, stylePath); + data.each(function (idx) { + var rawIdx = data.getRawIndex(idx); + idxMap[rawIdx] = idx; + }); + dataAll.each(function (rawIdx) { + var idx = idxMap[rawIdx]; + var fromPalette = data.getItemVisual(idx, 'colorFromPalette'); + + if (fromPalette) { + var itemStyle = data.ensureUniqueItemVisual(idx, 'style'); + var name_1 = dataAll.getName(rawIdx) || rawIdx + ''; + var dataCount = dataAll.count(); + itemStyle[colorKey] = seriesModel.getColorFromPalette(name_1, colorScope, dataCount); + } + }); + }); + } + }; + + var PI$3 = Math.PI; + function defaultLoading(api, opts) { + opts = opts || {}; + defaults(opts, { + text: 'loading', + textColor: '#000', + fontSize: 12, + fontWeight: 'normal', + fontStyle: 'normal', + fontFamily: 'sans-serif', + maskColor: 'rgba(255, 255, 255, 0.8)', + showSpinner: true, + color: '#5470c6', + spinnerRadius: 10, + lineWidth: 5, + zlevel: 0 + }); + var group = new Group(); + var mask = new Rect({ + style: { + fill: opts.maskColor + }, + zlevel: opts.zlevel, + z: 10000 + }); + group.add(mask); + var textContent = new ZRText({ + style: { + text: opts.text, + fill: opts.textColor, + fontSize: opts.fontSize, + fontWeight: opts.fontWeight, + fontStyle: opts.fontStyle, + fontFamily: opts.fontFamily + } + }); + var labelRect = new Rect({ + style: { + fill: 'none' + }, + textContent: textContent, + textConfig: { + position: 'right', + distance: 10 + }, + zlevel: opts.zlevel, + z: 10001 + }); + group.add(labelRect); + var arc; + + if (opts.showSpinner) { + arc = new Arc({ + shape: { + startAngle: -PI$3 / 2, + endAngle: -PI$3 / 2 + 0.1, + r: opts.spinnerRadius + }, + style: { + stroke: opts.color, + lineCap: 'round', + lineWidth: opts.lineWidth + }, + zlevel: opts.zlevel, + z: 10001 + }); + arc.animateShape(true).when(1000, { + endAngle: PI$3 * 3 / 2 + }).start('circularInOut'); + arc.animateShape(true).when(1000, { + startAngle: PI$3 * 3 / 2 + }).delay(300).start('circularInOut'); + group.add(arc); + } + + group.resize = function () { + var textWidth = textContent.getBoundingRect().width; + var r = opts.showSpinner ? opts.spinnerRadius : 0; + var cx = (api.getWidth() - r * 2 - (opts.showSpinner && textWidth ? 10 : 0) - textWidth) / 2 - (opts.showSpinner && textWidth ? 0 : 5 + textWidth / 2) + (opts.showSpinner ? 0 : textWidth / 2) + (textWidth ? 0 : r); + var cy = api.getHeight() / 2; + opts.showSpinner && arc.setShape({ + cx: cx, + cy: cy + }); + labelRect.setShape({ + x: cx - r, + y: cy - r, + width: r * 2, + height: r * 2 + }); + mask.setShape({ + x: 0, + y: 0, + width: api.getWidth(), + height: api.getHeight() + }); + }; + + group.resize(); + return group; + } + + var Scheduler = function () { + function Scheduler(ecInstance, api, dataProcessorHandlers, visualHandlers) { + this._stageTaskMap = createHashMap(); + this.ecInstance = ecInstance; + this.api = api; + dataProcessorHandlers = this._dataProcessorHandlers = dataProcessorHandlers.slice(); + visualHandlers = this._visualHandlers = visualHandlers.slice(); + this._allHandlers = dataProcessorHandlers.concat(visualHandlers); + } + + Scheduler.prototype.restoreData = function (ecModel, payload) { + ecModel.restoreData(payload); + + this._stageTaskMap.each(function (taskRecord) { + var overallTask = taskRecord.overallTask; + overallTask && overallTask.dirty(); + }); + }; + + Scheduler.prototype.getPerformArgs = function (task, isBlock) { + if (!task.__pipeline) { + return; + } + + var pipeline = this._pipelineMap.get(task.__pipeline.id); + + var pCtx = pipeline.context; + var incremental = !isBlock && pipeline.progressiveEnabled && (!pCtx || pCtx.progressiveRender) && task.__idxInPipeline > pipeline.blockIndex; + var step = incremental ? pipeline.step : null; + var modDataCount = pCtx && pCtx.modDataCount; + var modBy = modDataCount != null ? Math.ceil(modDataCount / step) : null; + return { + step: step, + modBy: modBy, + modDataCount: modDataCount + }; + }; + + Scheduler.prototype.getPipeline = function (pipelineId) { + return this._pipelineMap.get(pipelineId); + }; + + Scheduler.prototype.updateStreamModes = function (seriesModel, view) { + var pipeline = this._pipelineMap.get(seriesModel.uid); + + var data = seriesModel.getData(); + var dataLen = data.count(); + var progressiveRender = pipeline.progressiveEnabled && view.incrementalPrepareRender && dataLen >= pipeline.threshold; + var large = seriesModel.get('large') && dataLen >= seriesModel.get('largeThreshold'); + var modDataCount = seriesModel.get('progressiveChunkMode') === 'mod' ? dataLen : null; + seriesModel.pipelineContext = pipeline.context = { + progressiveRender: progressiveRender, + modDataCount: modDataCount, + large: large + }; + }; + + Scheduler.prototype.restorePipelines = function (ecModel) { + var scheduler = this; + var pipelineMap = scheduler._pipelineMap = createHashMap(); + ecModel.eachSeries(function (seriesModel) { + var progressive = seriesModel.getProgressive(); + var pipelineId = seriesModel.uid; + pipelineMap.set(pipelineId, { + id: pipelineId, + head: null, + tail: null, + threshold: seriesModel.getProgressiveThreshold(), + progressiveEnabled: progressive && !(seriesModel.preventIncremental && seriesModel.preventIncremental()), + blockIndex: -1, + step: Math.round(progressive || 700), + count: 0 + }); + + scheduler._pipe(seriesModel, seriesModel.dataTask); + }); + }; + + Scheduler.prototype.prepareStageTasks = function () { + var stageTaskMap = this._stageTaskMap; + var ecModel = this.api.getModel(); + var api = this.api; + each(this._allHandlers, function (handler) { + var record = stageTaskMap.get(handler.uid) || stageTaskMap.set(handler.uid, {}); + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = '"reset" and "overallReset" must not be both specified.'; + } + + assert(!(handler.reset && handler.overallReset), errMsg); + handler.reset && this._createSeriesStageTask(handler, record, ecModel, api); + handler.overallReset && this._createOverallStageTask(handler, record, ecModel, api); + }, this); + }; + + Scheduler.prototype.prepareView = function (view, model, ecModel, api) { + var renderTask = view.renderTask; + var context = renderTask.context; + context.model = model; + context.ecModel = ecModel; + context.api = api; + renderTask.__block = !view.incrementalPrepareRender; + + this._pipe(model, renderTask); + }; + + Scheduler.prototype.performDataProcessorTasks = function (ecModel, payload) { + this._performStageTasks(this._dataProcessorHandlers, ecModel, payload, { + block: true + }); + }; + + Scheduler.prototype.performVisualTasks = function (ecModel, payload, opt) { + this._performStageTasks(this._visualHandlers, ecModel, payload, opt); + }; + + Scheduler.prototype._performStageTasks = function (stageHandlers, ecModel, payload, opt) { + opt = opt || {}; + var unfinished = false; + var scheduler = this; + each(stageHandlers, function (stageHandler, idx) { + if (opt.visualType && opt.visualType !== stageHandler.visualType) { + return; + } + + var stageHandlerRecord = scheduler._stageTaskMap.get(stageHandler.uid); + + var seriesTaskMap = stageHandlerRecord.seriesTaskMap; + var overallTask = stageHandlerRecord.overallTask; + + if (overallTask) { + var overallNeedDirty_1; + var agentStubMap = overallTask.agentStubMap; + agentStubMap.each(function (stub) { + if (needSetDirty(opt, stub)) { + stub.dirty(); + overallNeedDirty_1 = true; + } + }); + overallNeedDirty_1 && overallTask.dirty(); + scheduler.updatePayload(overallTask, payload); + var performArgs_1 = scheduler.getPerformArgs(overallTask, opt.block); + agentStubMap.each(function (stub) { + stub.perform(performArgs_1); + }); + + if (overallTask.perform(performArgs_1)) { + unfinished = true; + } + } else if (seriesTaskMap) { + seriesTaskMap.each(function (task, pipelineId) { + if (needSetDirty(opt, task)) { + task.dirty(); + } + + var performArgs = scheduler.getPerformArgs(task, opt.block); + performArgs.skip = !stageHandler.performRawSeries && ecModel.isSeriesFiltered(task.context.model); + scheduler.updatePayload(task, payload); + + if (task.perform(performArgs)) { + unfinished = true; + } + }); + } + }); + + function needSetDirty(opt, task) { + return opt.setDirty && (!opt.dirtyMap || opt.dirtyMap.get(task.__pipeline.id)); + } + + this.unfinished = unfinished || this.unfinished; + }; + + Scheduler.prototype.performSeriesTasks = function (ecModel) { + var unfinished; + ecModel.eachSeries(function (seriesModel) { + unfinished = seriesModel.dataTask.perform() || unfinished; + }); + this.unfinished = unfinished || this.unfinished; + }; + + Scheduler.prototype.plan = function () { + this._pipelineMap.each(function (pipeline) { + var task = pipeline.tail; + + do { + if (task.__block) { + pipeline.blockIndex = task.__idxInPipeline; + break; + } + + task = task.getUpstream(); + } while (task); + }); + }; + + Scheduler.prototype.updatePayload = function (task, payload) { + payload !== 'remain' && (task.context.payload = payload); + }; + + Scheduler.prototype._createSeriesStageTask = function (stageHandler, stageHandlerRecord, ecModel, api) { + var scheduler = this; + var oldSeriesTaskMap = stageHandlerRecord.seriesTaskMap; + var newSeriesTaskMap = stageHandlerRecord.seriesTaskMap = createHashMap(); + var seriesType = stageHandler.seriesType; + var getTargetSeries = stageHandler.getTargetSeries; + + if (stageHandler.createOnAllSeries) { + ecModel.eachRawSeries(create); + } else if (seriesType) { + ecModel.eachRawSeriesByType(seriesType, create); + } else if (getTargetSeries) { + getTargetSeries(ecModel, api).each(create); + } + + function create(seriesModel) { + var pipelineId = seriesModel.uid; + var task = newSeriesTaskMap.set(pipelineId, oldSeriesTaskMap && oldSeriesTaskMap.get(pipelineId) || createTask({ + plan: seriesTaskPlan, + reset: seriesTaskReset, + count: seriesTaskCount + })); + task.context = { + model: seriesModel, + ecModel: ecModel, + api: api, + useClearVisual: stageHandler.isVisual && !stageHandler.isLayout, + plan: stageHandler.plan, + reset: stageHandler.reset, + scheduler: scheduler + }; + + scheduler._pipe(seriesModel, task); + } + }; + + Scheduler.prototype._createOverallStageTask = function (stageHandler, stageHandlerRecord, ecModel, api) { + var scheduler = this; + var overallTask = stageHandlerRecord.overallTask = stageHandlerRecord.overallTask || createTask({ + reset: overallTaskReset + }); + overallTask.context = { + ecModel: ecModel, + api: api, + overallReset: stageHandler.overallReset, + scheduler: scheduler + }; + var oldAgentStubMap = overallTask.agentStubMap; + var newAgentStubMap = overallTask.agentStubMap = createHashMap(); + var seriesType = stageHandler.seriesType; + var getTargetSeries = stageHandler.getTargetSeries; + var overallProgress = true; + var shouldOverallTaskDirty = false; + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = '"createOnAllSeries" do not supported for "overallReset", ' + 'becuase it will block all streams.'; + } + + assert(!stageHandler.createOnAllSeries, errMsg); + + if (seriesType) { + ecModel.eachRawSeriesByType(seriesType, createStub); + } else if (getTargetSeries) { + getTargetSeries(ecModel, api).each(createStub); + } else { + overallProgress = false; + each(ecModel.getSeries(), createStub); + } + + function createStub(seriesModel) { + var pipelineId = seriesModel.uid; + var stub = newAgentStubMap.set(pipelineId, oldAgentStubMap && oldAgentStubMap.get(pipelineId) || (shouldOverallTaskDirty = true, createTask({ + reset: stubReset, + onDirty: stubOnDirty + }))); + stub.context = { + model: seriesModel, + overallProgress: overallProgress + }; + stub.agent = overallTask; + stub.__block = overallProgress; + + scheduler._pipe(seriesModel, stub); + } + + if (shouldOverallTaskDirty) { + overallTask.dirty(); + } + }; + + Scheduler.prototype._pipe = function (seriesModel, task) { + var pipelineId = seriesModel.uid; + + var pipeline = this._pipelineMap.get(pipelineId); + + !pipeline.head && (pipeline.head = task); + pipeline.tail && pipeline.tail.pipe(task); + pipeline.tail = task; + task.__idxInPipeline = pipeline.count++; + task.__pipeline = pipeline; + }; + + Scheduler.wrapStageHandler = function (stageHandler, visualType) { + if (isFunction(stageHandler)) { + stageHandler = { + overallReset: stageHandler, + seriesType: detectSeriseType(stageHandler) + }; + } + + stageHandler.uid = getUID('stageHandler'); + visualType && (stageHandler.visualType = visualType); + return stageHandler; + }; + return Scheduler; + }(); + + function overallTaskReset(context) { + context.overallReset(context.ecModel, context.api, context.payload); + } + + function stubReset(context) { + return context.overallProgress && stubProgress; + } + + function stubProgress() { + this.agent.dirty(); + this.getDownstream().dirty(); + } + + function stubOnDirty() { + this.agent && this.agent.dirty(); + } + + function seriesTaskPlan(context) { + return context.plan ? context.plan(context.model, context.ecModel, context.api, context.payload) : null; + } + + function seriesTaskReset(context) { + if (context.useClearVisual) { + context.data.clearAllVisual(); + } + + var resetDefines = context.resetDefines = normalizeToArray(context.reset(context.model, context.ecModel, context.api, context.payload)); + return resetDefines.length > 1 ? map(resetDefines, function (v, idx) { + return makeSeriesTaskProgress(idx); + }) : singleSeriesTaskProgress; + } + + var singleSeriesTaskProgress = makeSeriesTaskProgress(0); + + function makeSeriesTaskProgress(resetDefineIdx) { + return function (params, context) { + var data = context.data; + var resetDefine = context.resetDefines[resetDefineIdx]; + + if (resetDefine && resetDefine.dataEach) { + for (var i = params.start; i < params.end; i++) { + resetDefine.dataEach(data, i); + } + } else if (resetDefine && resetDefine.progress) { + resetDefine.progress(params, data); + } + }; + } + + function seriesTaskCount(context) { + return context.data.count(); + } + + function detectSeriseType(legacyFunc) { + seriesType = null; + + try { + legacyFunc(ecModelMock, apiMock); + } catch (e) {} + + return seriesType; + } + + var ecModelMock = {}; + var apiMock = {}; + var seriesType; + mockMethods(ecModelMock, GlobalModel); + mockMethods(apiMock, ExtensionAPI); + + ecModelMock.eachSeriesByType = ecModelMock.eachRawSeriesByType = function (type) { + seriesType = type; + }; + + ecModelMock.eachComponent = function (cond) { + if (cond.mainType === 'series' && cond.subType) { + seriesType = cond.subType; + } + }; + + function mockMethods(target, Clz) { + for (var name_1 in Clz.prototype) { + target[name_1] = noop; + } + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var colorAll = ['#37A2DA', '#32C5E9', '#67E0E3', '#9FE6B8', '#FFDB5C', '#ff9f7f', '#fb7293', '#E062AE', '#E690D1', '#e7bcf3', '#9d96f5', '#8378EA', '#96BFFF']; + var lightTheme = { + color: colorAll, + colorLayer: [['#37A2DA', '#ffd85c', '#fd7b5f'], ['#37A2DA', '#67E0E3', '#FFDB5C', '#ff9f7f', '#E062AE', '#9d96f5'], ['#37A2DA', '#32C5E9', '#9FE6B8', '#FFDB5C', '#ff9f7f', '#fb7293', '#e7bcf3', '#8378EA', '#96BFFF'], colorAll] + }; + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var contrastColor = '#B9B8CE'; + var backgroundColor = '#100C2A'; + + var axisCommon = function () { + return { + axisLine: { + lineStyle: { + color: contrastColor + } + }, + splitLine: { + lineStyle: { + color: '#484753' + } + }, + splitArea: { + areaStyle: { + color: ['rgba(255,255,255,0.02)', 'rgba(255,255,255,0.05)'] + } + }, + minorSplitLine: { + lineStyle: { + color: '#20203B' + } + } + }; + }; + + var colorPalette = ['#4992ff', '#7cffb2', '#fddd60', '#ff6e76', '#58d9f9', '#05c091', '#ff8a45', '#8d48e3', '#dd79ff']; + var theme = { + darkMode: true, + color: colorPalette, + backgroundColor: backgroundColor, + axisPointer: { + lineStyle: { + color: '#817f91' + }, + crossStyle: { + color: '#817f91' + }, + label: { + color: '#fff' + } + }, + legend: { + textStyle: { + color: contrastColor + } + }, + textStyle: { + color: contrastColor + }, + title: { + textStyle: { + color: '#EEF1FA' + }, + subtextStyle: { + color: '#B9B8CE' + } + }, + toolbox: { + iconStyle: { + borderColor: contrastColor + } + }, + dataZoom: { + borderColor: '#71708A', + textStyle: { + color: contrastColor + }, + brushStyle: { + color: 'rgba(135,163,206,0.3)' + }, + handleStyle: { + color: '#353450', + borderColor: '#C5CBE3' + }, + moveHandleStyle: { + color: '#B0B6C3', + opacity: 0.3 + }, + fillerColor: 'rgba(135,163,206,0.2)', + emphasis: { + handleStyle: { + borderColor: '#91B7F2', + color: '#4D587D' + }, + moveHandleStyle: { + color: '#636D9A', + opacity: 0.7 + } + }, + dataBackground: { + lineStyle: { + color: '#71708A', + width: 1 + }, + areaStyle: { + color: '#71708A' + } + }, + selectedDataBackground: { + lineStyle: { + color: '#87A3CE' + }, + areaStyle: { + color: '#87A3CE' + } + } + }, + visualMap: { + textStyle: { + color: contrastColor + } + }, + timeline: { + lineStyle: { + color: contrastColor + }, + label: { + color: contrastColor + }, + controlStyle: { + color: contrastColor, + borderColor: contrastColor + } + }, + calendar: { + itemStyle: { + color: backgroundColor + }, + dayLabel: { + color: contrastColor + }, + monthLabel: { + color: contrastColor + }, + yearLabel: { + color: contrastColor + } + }, + timeAxis: axisCommon(), + logAxis: axisCommon(), + valueAxis: axisCommon(), + categoryAxis: axisCommon(), + line: { + symbol: 'circle' + }, + graph: { + color: colorPalette + }, + gauge: { + title: { + color: contrastColor + }, + axisLine: { + lineStyle: { + color: [[1, 'rgba(207,212,219,0.2)']] + } + }, + axisLabel: { + color: contrastColor + }, + detail: { + color: '#EEF1FA' + } + }, + candlestick: { + itemStyle: { + color: '#f64e56', + color0: '#54ea92', + borderColor: '#f64e56', + borderColor0: '#54ea92' + } + } + }; + theme.categoryAxis.splitLine.show = false; + + function parseXML(svg) { + if (isString(svg)) { + var parser = new DOMParser(); + svg = parser.parseFromString(svg, 'text/xml'); + } + var svgNode = svg; + if (svgNode.nodeType === 9) { + svgNode = svgNode.firstChild; + } + while (svgNode.nodeName.toLowerCase() !== 'svg' || svgNode.nodeType !== 1) { + svgNode = svgNode.nextSibling; + } + return svgNode; + } + + var storage = createHashMap(); + var mapDataStorage = { + registerMap: function (mapName, rawDef, rawSpecialAreas) { + var records; + + if (isArray(rawDef)) { + records = rawDef; + } else if (rawDef.svg) { + records = [{ + type: 'svg', + source: rawDef.svg, + specialAreas: rawDef.specialAreas + }]; + } else { + var geoSource = rawDef.geoJson || rawDef.geoJSON; + + if (geoSource && !rawDef.features) { + rawSpecialAreas = rawDef.specialAreas; + rawDef = geoSource; + } + + records = [{ + type: 'geoJSON', + source: rawDef, + specialAreas: rawSpecialAreas + }]; + } + + each(records, function (record) { + var type = record.type; + type === 'geoJson' && (type = record.type = 'geoJSON'); + var parse = parsers[type]; + + if ("development" !== 'production') { + assert(parse, 'Illegal map type: ' + type); + } + + parse(record); + }); + return storage.set(mapName, records); + }, + retrieveMap: function (mapName) { + return storage.get(mapName); + } + }; + var parsers = { + geoJSON: function (record) { + var source = record.source; + record.geoJSON = !isString(source) ? source : typeof JSON !== 'undefined' && JSON.parse ? JSON.parse(source) : new Function('return (' + source + ');')(); + }, + svg: function (record) { + record.svgXML = parseXML(record.source); + } + }; + + var ECEventProcessor = function () { + function ECEventProcessor() {} + + ECEventProcessor.prototype.normalizeQuery = function (query) { + var cptQuery = {}; + var dataQuery = {}; + var otherQuery = {}; + + if (isString(query)) { + var condCptType = parseClassType(query); + cptQuery.mainType = condCptType.main || null; + cptQuery.subType = condCptType.sub || null; + } else { + var suffixes_1 = ['Index', 'Name', 'Id']; + var dataKeys_1 = { + name: 1, + dataIndex: 1, + dataType: 1 + }; + each(query, function (val, key) { + var reserved = false; + + for (var i = 0; i < suffixes_1.length; i++) { + var propSuffix = suffixes_1[i]; + var suffixPos = key.lastIndexOf(propSuffix); + + if (suffixPos > 0 && suffixPos === key.length - propSuffix.length) { + var mainType = key.slice(0, suffixPos); + + if (mainType !== 'data') { + cptQuery.mainType = mainType; + cptQuery[propSuffix.toLowerCase()] = val; + reserved = true; + } + } + } + + if (dataKeys_1.hasOwnProperty(key)) { + dataQuery[key] = val; + reserved = true; + } + + if (!reserved) { + otherQuery[key] = val; + } + }); + } + + return { + cptQuery: cptQuery, + dataQuery: dataQuery, + otherQuery: otherQuery + }; + }; + + ECEventProcessor.prototype.filter = function (eventType, query) { + var eventInfo = this.eventInfo; + + if (!eventInfo) { + return true; + } + + var targetEl = eventInfo.targetEl; + var packedEvent = eventInfo.packedEvent; + var model = eventInfo.model; + var view = eventInfo.view; + + if (!model || !view) { + return true; + } + + var cptQuery = query.cptQuery; + var dataQuery = query.dataQuery; + return check(cptQuery, model, 'mainType') && check(cptQuery, model, 'subType') && check(cptQuery, model, 'index', 'componentIndex') && check(cptQuery, model, 'name') && check(cptQuery, model, 'id') && check(dataQuery, packedEvent, 'name') && check(dataQuery, packedEvent, 'dataIndex') && check(dataQuery, packedEvent, 'dataType') && (!view.filterForExposedEvent || view.filterForExposedEvent(eventType, query.otherQuery, targetEl, packedEvent)); + + function check(query, host, prop, propOnHost) { + return query[prop] == null || host[propOnHost || prop] === query[prop]; + } + }; + + ECEventProcessor.prototype.afterTrigger = function () { + this.eventInfo = null; + }; + + return ECEventProcessor; + }(); + + var seriesSymbolTask = { + createOnAllSeries: true, + performRawSeries: true, + reset: function (seriesModel, ecModel) { + var data = seriesModel.getData(); + + if (seriesModel.legendSymbol) { + data.setVisual('legendSymbol', seriesModel.legendSymbol); + } + + if (!seriesModel.hasSymbolVisual) { + return; + } + + var symbolType = seriesModel.get('symbol'); + var symbolSize = seriesModel.get('symbolSize'); + var keepAspect = seriesModel.get('symbolKeepAspect'); + var symbolRotate = seriesModel.get('symbolRotate'); + var hasSymbolTypeCallback = isFunction(symbolType); + var hasSymbolSizeCallback = isFunction(symbolSize); + var hasSymbolRotateCallback = isFunction(symbolRotate); + var hasCallback = hasSymbolTypeCallback || hasSymbolSizeCallback || hasSymbolRotateCallback; + var seriesSymbol = !hasSymbolTypeCallback && symbolType ? symbolType : seriesModel.defaultSymbol; + var seriesSymbolSize = !hasSymbolSizeCallback ? symbolSize : null; + var seriesSymbolRotate = !hasSymbolRotateCallback ? symbolRotate : null; + data.setVisual({ + legendSymbol: seriesModel.legendSymbol || seriesSymbol, + symbol: seriesSymbol, + symbolSize: seriesSymbolSize, + symbolKeepAspect: keepAspect, + symbolRotate: seriesSymbolRotate + }); + + if (ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + function dataEach(data, idx) { + var rawValue = seriesModel.getRawValue(idx); + var params = seriesModel.getDataParams(idx); + hasSymbolTypeCallback && data.setItemVisual(idx, 'symbol', symbolType(rawValue, params)); + hasSymbolSizeCallback && data.setItemVisual(idx, 'symbolSize', symbolSize(rawValue, params)); + hasSymbolRotateCallback && data.setItemVisual(idx, 'symbolRotate', symbolRotate(rawValue, params)); + } + + return { + dataEach: hasCallback ? dataEach : null + }; + } + }; + var dataSymbolTask = { + createOnAllSeries: true, + performRawSeries: true, + reset: function (seriesModel, ecModel) { + if (!seriesModel.hasSymbolVisual) { + return; + } + + if (ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + var data = seriesModel.getData(); + + function dataEach(data, idx) { + var itemModel = data.getItemModel(idx); + var itemSymbolType = itemModel.getShallow('symbol', true); + var itemSymbolSize = itemModel.getShallow('symbolSize', true); + var itemSymbolRotate = itemModel.getShallow('symbolRotate', true); + var itemSymbolKeepAspect = itemModel.getShallow('symbolKeepAspect', true); + + if (itemSymbolType != null) { + data.setItemVisual(idx, 'symbol', itemSymbolType); + } + + if (itemSymbolSize != null) { + data.setItemVisual(idx, 'symbolSize', itemSymbolSize); + } + + if (itemSymbolRotate != null) { + data.setItemVisual(idx, 'symbolRotate', itemSymbolRotate); + } + + if (itemSymbolKeepAspect != null) { + data.setItemVisual(idx, 'symbolKeepAspect', itemSymbolKeepAspect); + } + } + + return { + dataEach: data.hasItemOption ? dataEach : null + }; + } + }; + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function getItemVisualFromData(data, dataIndex, key) { + switch (key) { + case 'color': + var style = data.getItemVisual(dataIndex, 'style'); + return style[data.getVisual('drawType')]; + + case 'opacity': + return data.getItemVisual(dataIndex, 'style').opacity; + + case 'symbol': + case 'symbolSize': + case 'liftZ': + return data.getItemVisual(dataIndex, key); + + default: + if ("development" !== 'production') { + console.warn("Unknown visual type " + key); + } + + } + } + function getVisualFromData(data, key) { + switch (key) { + case 'color': + var style = data.getVisual('style'); + return style[data.getVisual('drawType')]; + + case 'opacity': + return data.getVisual('style').opacity; + + case 'symbol': + case 'symbolSize': + case 'liftZ': + return data.getVisual(key); + + default: + if ("development" !== 'production') { + console.warn("Unknown visual type " + key); + } + + } + } + function setItemVisualFromData(data, dataIndex, key, value) { + switch (key) { + case 'color': + var style = data.ensureUniqueItemVisual(dataIndex, 'style'); + style[data.getVisual('drawType')] = value; + data.setItemVisual(dataIndex, 'colorFromPalette', false); + break; + + case 'opacity': + data.ensureUniqueItemVisual(dataIndex, 'style').opacity = value; + break; + + case 'symbol': + case 'symbolSize': + case 'liftZ': + data.setItemVisual(dataIndex, key, value); + break; + + default: + if ("development" !== 'production') { + console.warn("Unknown visual type " + key); + } + + } + } + + var PI2$6 = Math.PI * 2; + var CMD$3 = PathProxy.CMD; + var DEFAULT_SEARCH_SPACE = ['top', 'right', 'bottom', 'left']; + + function getCandidateAnchor(pos, distance, rect, outPt, outDir) { + var width = rect.width; + var height = rect.height; + + switch (pos) { + case 'top': + outPt.set(rect.x + width / 2, rect.y - distance); + outDir.set(0, -1); + break; + + case 'bottom': + outPt.set(rect.x + width / 2, rect.y + height + distance); + outDir.set(0, 1); + break; + + case 'left': + outPt.set(rect.x - distance, rect.y + height / 2); + outDir.set(-1, 0); + break; + + case 'right': + outPt.set(rect.x + width + distance, rect.y + height / 2); + outDir.set(1, 0); + break; + } + } + + function projectPointToArc(cx, cy, r, startAngle, endAngle, anticlockwise, x, y, out) { + x -= cx; + y -= cy; + var d = Math.sqrt(x * x + y * y); + x /= d; + y /= d; + var ox = x * r + cx; + var oy = y * r + cy; + + if (Math.abs(startAngle - endAngle) % PI2$6 < 1e-4) { + out[0] = ox; + out[1] = oy; + return d - r; + } + + if (anticlockwise) { + var tmp = startAngle; + startAngle = normalizeRadian(endAngle); + endAngle = normalizeRadian(tmp); + } else { + startAngle = normalizeRadian(startAngle); + endAngle = normalizeRadian(endAngle); + } + + if (startAngle > endAngle) { + endAngle += PI2$6; + } + + var angle = Math.atan2(y, x); + + if (angle < 0) { + angle += PI2$6; + } + + if (angle >= startAngle && angle <= endAngle || angle + PI2$6 >= startAngle && angle + PI2$6 <= endAngle) { + out[0] = ox; + out[1] = oy; + return d - r; + } + + var x1 = r * Math.cos(startAngle) + cx; + var y1 = r * Math.sin(startAngle) + cy; + var x2 = r * Math.cos(endAngle) + cx; + var y2 = r * Math.sin(endAngle) + cy; + var d1 = (x1 - x) * (x1 - x) + (y1 - y) * (y1 - y); + var d2 = (x2 - x) * (x2 - x) + (y2 - y) * (y2 - y); + + if (d1 < d2) { + out[0] = x1; + out[1] = y1; + return Math.sqrt(d1); + } else { + out[0] = x2; + out[1] = y2; + return Math.sqrt(d2); + } + } + + function projectPointToLine(x1, y1, x2, y2, x, y, out, limitToEnds) { + var dx = x - x1; + var dy = y - y1; + var dx1 = x2 - x1; + var dy1 = y2 - y1; + var lineLen = Math.sqrt(dx1 * dx1 + dy1 * dy1); + dx1 /= lineLen; + dy1 /= lineLen; + var projectedLen = dx * dx1 + dy * dy1; + var t = projectedLen / lineLen; + + if (limitToEnds) { + t = Math.min(Math.max(t, 0), 1); + } + + t *= lineLen; + var ox = out[0] = x1 + t * dx1; + var oy = out[1] = y1 + t * dy1; + return Math.sqrt((ox - x) * (ox - x) + (oy - y) * (oy - y)); + } + + function projectPointToRect(x1, y1, width, height, x, y, out) { + if (width < 0) { + x1 = x1 + width; + width = -width; + } + + if (height < 0) { + y1 = y1 + height; + height = -height; + } + + var x2 = x1 + width; + var y2 = y1 + height; + var ox = out[0] = Math.min(Math.max(x, x1), x2); + var oy = out[1] = Math.min(Math.max(y, y1), y2); + return Math.sqrt((ox - x) * (ox - x) + (oy - y) * (oy - y)); + } + + var tmpPt = []; + + function nearestPointOnRect(pt, rect, out) { + var dist = projectPointToRect(rect.x, rect.y, rect.width, rect.height, pt.x, pt.y, tmpPt); + out.set(tmpPt[0], tmpPt[1]); + return dist; + } + + function nearestPointOnPath(pt, path, out) { + var xi = 0; + var yi = 0; + var x0 = 0; + var y0 = 0; + var x1; + var y1; + var minDist = Infinity; + var data = path.data; + var x = pt.x; + var y = pt.y; + + for (var i = 0; i < data.length;) { + var cmd = data[i++]; + + if (i === 1) { + xi = data[i]; + yi = data[i + 1]; + x0 = xi; + y0 = yi; + } + + var d = minDist; + + switch (cmd) { + case CMD$3.M: + x0 = data[i++]; + y0 = data[i++]; + xi = x0; + yi = y0; + break; + + case CMD$3.L: + d = projectPointToLine(xi, yi, data[i], data[i + 1], x, y, tmpPt, true); + xi = data[i++]; + yi = data[i++]; + break; + + case CMD$3.C: + d = cubicProjectPoint(xi, yi, data[i++], data[i++], data[i++], data[i++], data[i], data[i + 1], x, y, tmpPt); + xi = data[i++]; + yi = data[i++]; + break; + + case CMD$3.Q: + d = quadraticProjectPoint(xi, yi, data[i++], data[i++], data[i], data[i + 1], x, y, tmpPt); + xi = data[i++]; + yi = data[i++]; + break; + + case CMD$3.A: + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var theta = data[i++]; + var dTheta = data[i++]; + i += 1; + var anticlockwise = !!(1 - data[i++]); + x1 = Math.cos(theta) * rx + cx; + y1 = Math.sin(theta) * ry + cy; + + if (i <= 1) { + x0 = x1; + y0 = y1; + } + + var _x = (x - cx) * ry / rx + cx; + + d = projectPointToArc(cx, cy, ry, theta, theta + dTheta, anticlockwise, _x, y, tmpPt); + xi = Math.cos(theta + dTheta) * rx + cx; + yi = Math.sin(theta + dTheta) * ry + cy; + break; + + case CMD$3.R: + x0 = xi = data[i++]; + y0 = yi = data[i++]; + var width = data[i++]; + var height = data[i++]; + d = projectPointToRect(x0, y0, width, height, x, y, tmpPt); + break; + + case CMD$3.Z: + d = projectPointToLine(xi, yi, x0, y0, x, y, tmpPt, true); + xi = x0; + yi = y0; + break; + } + + if (d < minDist) { + minDist = d; + out.set(tmpPt[0], tmpPt[1]); + } + } + + return minDist; + } + + var pt0 = new Point(); + var pt1 = new Point(); + var pt2 = new Point(); + var dir = new Point(); + var dir2 = new Point(); + function updateLabelLinePoints(target, labelLineModel) { + if (!target) { + return; + } + + var labelLine = target.getTextGuideLine(); + var label = target.getTextContent(); + + if (!(label && labelLine)) { + return; + } + + var labelGuideConfig = target.textGuideLineConfig || {}; + var points = [[0, 0], [0, 0], [0, 0]]; + var searchSpace = labelGuideConfig.candidates || DEFAULT_SEARCH_SPACE; + var labelRect = label.getBoundingRect().clone(); + labelRect.applyTransform(label.getComputedTransform()); + var minDist = Infinity; + var anchorPoint = labelGuideConfig.anchor; + var targetTransform = target.getComputedTransform(); + var targetInversedTransform = targetTransform && invert([], targetTransform); + var len = labelLineModel.get('length2') || 0; + + if (anchorPoint) { + pt2.copy(anchorPoint); + } + + for (var i = 0; i < searchSpace.length; i++) { + var candidate = searchSpace[i]; + getCandidateAnchor(candidate, 0, labelRect, pt0, dir); + Point.scaleAndAdd(pt1, pt0, dir, len); + pt1.transform(targetInversedTransform); + var boundingRect = target.getBoundingRect(); + var dist = anchorPoint ? anchorPoint.distance(pt1) : target instanceof Path ? nearestPointOnPath(pt1, target.path, pt2) : nearestPointOnRect(pt1, boundingRect, pt2); + + if (dist < minDist) { + minDist = dist; + pt1.transform(targetTransform); + pt2.transform(targetTransform); + pt2.toArray(points[0]); + pt1.toArray(points[1]); + pt0.toArray(points[2]); + } + } + + limitTurnAngle(points, labelLineModel.get('minTurnAngle')); + labelLine.setShape({ + points: points + }); + } + var tmpArr = []; + var tmpProjPoint = new Point(); + function limitTurnAngle(linePoints, minTurnAngle) { + if (!(minTurnAngle <= 180 && minTurnAngle > 0)) { + return; + } + + minTurnAngle = minTurnAngle / 180 * Math.PI; + pt0.fromArray(linePoints[0]); + pt1.fromArray(linePoints[1]); + pt2.fromArray(linePoints[2]); + Point.sub(dir, pt0, pt1); + Point.sub(dir2, pt2, pt1); + var len1 = dir.len(); + var len2 = dir2.len(); + + if (len1 < 1e-3 || len2 < 1e-3) { + return; + } + + dir.scale(1 / len1); + dir2.scale(1 / len2); + var angleCos = dir.dot(dir2); + var minTurnAngleCos = Math.cos(minTurnAngle); + + if (minTurnAngleCos < angleCos) { + var d = projectPointToLine(pt1.x, pt1.y, pt2.x, pt2.y, pt0.x, pt0.y, tmpArr, false); + tmpProjPoint.fromArray(tmpArr); + tmpProjPoint.scaleAndAdd(dir2, d / Math.tan(Math.PI - minTurnAngle)); + var t = pt2.x !== pt1.x ? (tmpProjPoint.x - pt1.x) / (pt2.x - pt1.x) : (tmpProjPoint.y - pt1.y) / (pt2.y - pt1.y); + + if (isNaN(t)) { + return; + } + + if (t < 0) { + Point.copy(tmpProjPoint, pt1); + } else if (t > 1) { + Point.copy(tmpProjPoint, pt2); + } + + tmpProjPoint.toArray(linePoints[1]); + } + } + function limitSurfaceAngle(linePoints, surfaceNormal, maxSurfaceAngle) { + if (!(maxSurfaceAngle <= 180 && maxSurfaceAngle > 0)) { + return; + } + + maxSurfaceAngle = maxSurfaceAngle / 180 * Math.PI; + pt0.fromArray(linePoints[0]); + pt1.fromArray(linePoints[1]); + pt2.fromArray(linePoints[2]); + Point.sub(dir, pt1, pt0); + Point.sub(dir2, pt2, pt1); + var len1 = dir.len(); + var len2 = dir2.len(); + + if (len1 < 1e-3 || len2 < 1e-3) { + return; + } + + dir.scale(1 / len1); + dir2.scale(1 / len2); + var angleCos = dir.dot(surfaceNormal); + var maxSurfaceAngleCos = Math.cos(maxSurfaceAngle); + + if (angleCos < maxSurfaceAngleCos) { + var d = projectPointToLine(pt1.x, pt1.y, pt2.x, pt2.y, pt0.x, pt0.y, tmpArr, false); + tmpProjPoint.fromArray(tmpArr); + var HALF_PI = Math.PI / 2; + var angle2 = Math.acos(dir2.dot(surfaceNormal)); + var newAngle = HALF_PI + angle2 - maxSurfaceAngle; + + if (newAngle >= HALF_PI) { + Point.copy(tmpProjPoint, pt2); + } else { + tmpProjPoint.scaleAndAdd(dir2, d / Math.tan(Math.PI / 2 - newAngle)); + var t = pt2.x !== pt1.x ? (tmpProjPoint.x - pt1.x) / (pt2.x - pt1.x) : (tmpProjPoint.y - pt1.y) / (pt2.y - pt1.y); + + if (isNaN(t)) { + return; + } + + if (t < 0) { + Point.copy(tmpProjPoint, pt1); + } else if (t > 1) { + Point.copy(tmpProjPoint, pt2); + } + } + + tmpProjPoint.toArray(linePoints[1]); + } + } + + function setLabelLineState(labelLine, ignore, stateName, stateModel) { + var isNormal = stateName === 'normal'; + var stateObj = isNormal ? labelLine : labelLine.ensureState(stateName); + stateObj.ignore = ignore; + var smooth = stateModel.get('smooth'); + + if (smooth && smooth === true) { + smooth = 0.3; + } + + stateObj.shape = stateObj.shape || {}; + + if (smooth > 0) { + stateObj.shape.smooth = smooth; + } + + var styleObj = stateModel.getModel('lineStyle').getLineStyle(); + isNormal ? labelLine.useStyle(styleObj) : stateObj.style = styleObj; + } + + function buildLabelLinePath(path, shape) { + var smooth = shape.smooth; + var points = shape.points; + + if (!points) { + return; + } + + path.moveTo(points[0][0], points[0][1]); + + if (smooth > 0 && points.length >= 3) { + var len1 = dist(points[0], points[1]); + var len2 = dist(points[1], points[2]); + + if (!len1 || !len2) { + path.lineTo(points[1][0], points[1][1]); + path.lineTo(points[2][0], points[2][1]); + return; + } + + var moveLen = Math.min(len1, len2) * smooth; + var midPoint0 = lerp([], points[1], points[0], moveLen / len1); + var midPoint2 = lerp([], points[1], points[2], moveLen / len2); + var midPoint1 = lerp([], midPoint0, midPoint2, 0.5); + path.bezierCurveTo(midPoint0[0], midPoint0[1], midPoint0[0], midPoint0[1], midPoint1[0], midPoint1[1]); + path.bezierCurveTo(midPoint2[0], midPoint2[1], midPoint2[0], midPoint2[1], points[2][0], points[2][1]); + } else { + for (var i = 1; i < points.length; i++) { + path.lineTo(points[i][0], points[i][1]); + } + } + } + + function setLabelLineStyle(targetEl, statesModels, defaultStyle) { + var labelLine = targetEl.getTextGuideLine(); + var label = targetEl.getTextContent(); + + if (!label) { + if (labelLine) { + targetEl.removeTextGuideLine(); + } + + return; + } + + var normalModel = statesModels.normal; + var showNormal = normalModel.get('show'); + var labelIgnoreNormal = label.ignore; + + for (var i = 0; i < DISPLAY_STATES.length; i++) { + var stateName = DISPLAY_STATES[i]; + var stateModel = statesModels[stateName]; + var isNormal = stateName === 'normal'; + + if (stateModel) { + var stateShow = stateModel.get('show'); + var isLabelIgnored = isNormal ? labelIgnoreNormal : retrieve2(label.states[stateName] && label.states[stateName].ignore, labelIgnoreNormal); + + if (isLabelIgnored || !retrieve2(stateShow, showNormal)) { + var stateObj = isNormal ? labelLine : labelLine && labelLine.states.normal; + + if (stateObj) { + stateObj.ignore = true; + } + + continue; + } + + if (!labelLine) { + labelLine = new Polyline(); + targetEl.setTextGuideLine(labelLine); + + if (!isNormal && (labelIgnoreNormal || !showNormal)) { + setLabelLineState(labelLine, true, 'normal', statesModels.normal); + } + + if (targetEl.stateProxy) { + labelLine.stateProxy = targetEl.stateProxy; + } + } + + setLabelLineState(labelLine, false, stateName, stateModel); + } + } + + if (labelLine) { + defaults(labelLine.style, defaultStyle); + labelLine.style.fill = null; + var showAbove = normalModel.get('showAbove'); + var labelLineConfig = targetEl.textGuideLineConfig = targetEl.textGuideLineConfig || {}; + labelLineConfig.showAbove = showAbove || false; + labelLine.buildPath = buildLabelLinePath; + } + } + function getLabelLineStatesModels(itemModel, labelLineName) { + labelLineName = labelLineName || 'labelLine'; + var statesModels = { + normal: itemModel.getModel(labelLineName) + }; + + for (var i = 0; i < SPECIAL_STATES.length; i++) { + var stateName = SPECIAL_STATES[i]; + statesModels[stateName] = itemModel.getModel([stateName, labelLineName]); + } + + return statesModels; + } + + function prepareLayoutList(input) { + var list = []; + + for (var i = 0; i < input.length; i++) { + var rawItem = input[i]; + + if (rawItem.defaultAttr.ignore) { + continue; + } + + var label = rawItem.label; + var transform = label.getComputedTransform(); + var localRect = label.getBoundingRect(); + var isAxisAligned = !transform || transform[1] < 1e-5 && transform[2] < 1e-5; + var minMargin = label.style.margin || 0; + var globalRect = localRect.clone(); + globalRect.applyTransform(transform); + globalRect.x -= minMargin / 2; + globalRect.y -= minMargin / 2; + globalRect.width += minMargin; + globalRect.height += minMargin; + var obb = isAxisAligned ? new OrientedBoundingRect(localRect, transform) : null; + list.push({ + label: label, + labelLine: rawItem.labelLine, + rect: globalRect, + localRect: localRect, + obb: obb, + priority: rawItem.priority, + defaultAttr: rawItem.defaultAttr, + layoutOption: rawItem.computedLayoutOption, + axisAligned: isAxisAligned, + transform: transform + }); + } + + return list; + } + + function shiftLayout(list, xyDim, sizeDim, minBound, maxBound, balanceShift) { + var len = list.length; + + if (len < 2) { + return; + } + + list.sort(function (a, b) { + return a.rect[xyDim] - b.rect[xyDim]; + }); + var lastPos = 0; + var delta; + var adjusted = false; + var totalShifts = 0; + + for (var i = 0; i < len; i++) { + var item = list[i]; + var rect = item.rect; + delta = rect[xyDim] - lastPos; + + if (delta < 0) { + rect[xyDim] -= delta; + item.label[xyDim] -= delta; + adjusted = true; + } + + var shift = Math.max(-delta, 0); + totalShifts += shift; + lastPos = rect[xyDim] + rect[sizeDim]; + } + + if (totalShifts > 0 && balanceShift) { + shiftList(-totalShifts / len, 0, len); + } + + var first = list[0]; + var last = list[len - 1]; + var minGap; + var maxGap; + updateMinMaxGap(); + minGap < 0 && squeezeGaps(-minGap, 0.8); + maxGap < 0 && squeezeGaps(maxGap, 0.8); + updateMinMaxGap(); + takeBoundsGap(minGap, maxGap, 1); + takeBoundsGap(maxGap, minGap, -1); + updateMinMaxGap(); + + if (minGap < 0) { + squeezeWhenBailout(-minGap); + } + + if (maxGap < 0) { + squeezeWhenBailout(maxGap); + } + + function updateMinMaxGap() { + minGap = first.rect[xyDim] - minBound; + maxGap = maxBound - last.rect[xyDim] - last.rect[sizeDim]; + } + + function takeBoundsGap(gapThisBound, gapOtherBound, moveDir) { + if (gapThisBound < 0) { + var moveFromMaxGap = Math.min(gapOtherBound, -gapThisBound); + + if (moveFromMaxGap > 0) { + shiftList(moveFromMaxGap * moveDir, 0, len); + var remained = moveFromMaxGap + gapThisBound; + + if (remained < 0) { + squeezeGaps(-remained * moveDir, 1); + } + } else { + squeezeGaps(-gapThisBound * moveDir, 1); + } + } + } + + function shiftList(delta, start, end) { + if (delta !== 0) { + adjusted = true; + } + + for (var i = start; i < end; i++) { + var item = list[i]; + var rect = item.rect; + rect[xyDim] += delta; + item.label[xyDim] += delta; + } + } + + function squeezeGaps(delta, maxSqeezePercent) { + var gaps = []; + var totalGaps = 0; + + for (var i = 1; i < len; i++) { + var prevItemRect = list[i - 1].rect; + var gap = Math.max(list[i].rect[xyDim] - prevItemRect[xyDim] - prevItemRect[sizeDim], 0); + gaps.push(gap); + totalGaps += gap; + } + + if (!totalGaps) { + return; + } + + var squeezePercent = Math.min(Math.abs(delta) / totalGaps, maxSqeezePercent); + + if (delta > 0) { + for (var i = 0; i < len - 1; i++) { + var movement = gaps[i] * squeezePercent; + shiftList(movement, 0, i + 1); + } + } else { + for (var i = len - 1; i > 0; i--) { + var movement = gaps[i - 1] * squeezePercent; + shiftList(-movement, i, len); + } + } + } + + function squeezeWhenBailout(delta) { + var dir = delta < 0 ? -1 : 1; + delta = Math.abs(delta); + var moveForEachLabel = Math.ceil(delta / (len - 1)); + + for (var i = 0; i < len - 1; i++) { + if (dir > 0) { + shiftList(moveForEachLabel, 0, i + 1); + } else { + shiftList(-moveForEachLabel, len - i - 1, len); + } + + delta -= moveForEachLabel; + + if (delta <= 0) { + return; + } + } + } + + return adjusted; + } + + function shiftLayoutOnX(list, leftBound, rightBound, balanceShift) { + return shiftLayout(list, 'x', 'width', leftBound, rightBound, balanceShift); + } + function shiftLayoutOnY(list, topBound, bottomBound, balanceShift) { + return shiftLayout(list, 'y', 'height', topBound, bottomBound, balanceShift); + } + function hideOverlap(labelList) { + var displayedLabels = []; + labelList.sort(function (a, b) { + return b.priority - a.priority; + }); + var globalRect = new BoundingRect(0, 0, 0, 0); + + function hideEl(el) { + if (!el.ignore) { + var emphasisState = el.ensureState('emphasis'); + + if (emphasisState.ignore == null) { + emphasisState.ignore = false; + } + } + + el.ignore = true; + } + + for (var i = 0; i < labelList.length; i++) { + var labelItem = labelList[i]; + var isAxisAligned = labelItem.axisAligned; + var localRect = labelItem.localRect; + var transform = labelItem.transform; + var label = labelItem.label; + var labelLine = labelItem.labelLine; + globalRect.copy(labelItem.rect); + globalRect.width -= 0.1; + globalRect.height -= 0.1; + globalRect.x += 0.05; + globalRect.y += 0.05; + var obb = labelItem.obb; + var overlapped = false; + + for (var j = 0; j < displayedLabels.length; j++) { + var existsTextCfg = displayedLabels[j]; + + if (!globalRect.intersect(existsTextCfg.rect)) { + continue; + } + + if (isAxisAligned && existsTextCfg.axisAligned) { + overlapped = true; + break; + } + + if (!existsTextCfg.obb) { + existsTextCfg.obb = new OrientedBoundingRect(existsTextCfg.localRect, existsTextCfg.transform); + } + + if (!obb) { + obb = new OrientedBoundingRect(localRect, transform); + } + + if (obb.intersect(existsTextCfg.obb)) { + overlapped = true; + break; + } + } + + if (overlapped) { + hideEl(label); + labelLine && hideEl(labelLine); + } else { + label.attr('ignore', labelItem.defaultAttr.ignore); + labelLine && labelLine.attr('ignore', labelItem.defaultAttr.labelGuideIgnore); + displayedLabels.push(labelItem); + } + } + } + + function cloneArr(points) { + if (points) { + var newPoints = []; + + for (var i = 0; i < points.length; i++) { + newPoints.push(points[i].slice()); + } + + return newPoints; + } + } + + function prepareLayoutCallbackParams(labelItem, hostEl) { + var label = labelItem.label; + var labelLine = hostEl && hostEl.getTextGuideLine(); + return { + dataIndex: labelItem.dataIndex, + dataType: labelItem.dataType, + seriesIndex: labelItem.seriesModel.seriesIndex, + text: labelItem.label.style.text, + rect: labelItem.hostRect, + labelRect: labelItem.rect, + align: label.style.align, + verticalAlign: label.style.verticalAlign, + labelLinePoints: cloneArr(labelLine && labelLine.shape.points) + }; + } + + var LABEL_OPTION_TO_STYLE_KEYS = ['align', 'verticalAlign', 'width', 'height', 'fontSize']; + var dummyTransformable = new Transformable(); + var labelLayoutInnerStore = makeInner(); + var labelLineAnimationStore = makeInner(); + + function extendWithKeys(target, source, keys) { + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + + if (source[key] != null) { + target[key] = source[key]; + } + } + } + + var LABEL_LAYOUT_PROPS = ['x', 'y', 'rotation']; + + var LabelManager = function () { + function LabelManager() { + this._labelList = []; + this._chartViewList = []; + } + + LabelManager.prototype.clearLabels = function () { + this._labelList = []; + this._chartViewList = []; + }; + + LabelManager.prototype._addLabel = function (dataIndex, dataType, seriesModel, label, layoutOption) { + var labelStyle = label.style; + var hostEl = label.__hostTarget; + var textConfig = hostEl.textConfig || {}; + var labelTransform = label.getComputedTransform(); + var labelRect = label.getBoundingRect().plain(); + BoundingRect.applyTransform(labelRect, labelRect, labelTransform); + + if (labelTransform) { + dummyTransformable.setLocalTransform(labelTransform); + } else { + dummyTransformable.x = dummyTransformable.y = dummyTransformable.rotation = dummyTransformable.originX = dummyTransformable.originY = 0; + dummyTransformable.scaleX = dummyTransformable.scaleY = 1; + } + + var host = label.__hostTarget; + var hostRect; + + if (host) { + hostRect = host.getBoundingRect().plain(); + var transform = host.getComputedTransform(); + BoundingRect.applyTransform(hostRect, hostRect, transform); + } + + var labelGuide = hostRect && host.getTextGuideLine(); + + this._labelList.push({ + label: label, + labelLine: labelGuide, + seriesModel: seriesModel, + dataIndex: dataIndex, + dataType: dataType, + layoutOption: layoutOption, + computedLayoutOption: null, + rect: labelRect, + hostRect: hostRect, + priority: hostRect ? hostRect.width * hostRect.height : 0, + defaultAttr: { + ignore: label.ignore, + labelGuideIgnore: labelGuide && labelGuide.ignore, + x: dummyTransformable.x, + y: dummyTransformable.y, + rotation: dummyTransformable.rotation, + style: { + x: labelStyle.x, + y: labelStyle.y, + align: labelStyle.align, + verticalAlign: labelStyle.verticalAlign, + width: labelStyle.width, + height: labelStyle.height, + fontSize: labelStyle.fontSize + }, + cursor: label.cursor, + attachedPos: textConfig.position, + attachedRot: textConfig.rotation + } + }); + }; + + LabelManager.prototype.addLabelsOfSeries = function (chartView) { + var _this = this; + + this._chartViewList.push(chartView); + + var seriesModel = chartView.__model; + var layoutOption = seriesModel.get('labelLayout'); + + if (!(isFunction(layoutOption) || keys(layoutOption).length)) { + return; + } + + chartView.group.traverse(function (child) { + if (child.ignore) { + return true; + } + + var textEl = child.getTextContent(); + var ecData = getECData(child); + + if (textEl && !textEl.disableLabelLayout) { + _this._addLabel(ecData.dataIndex, ecData.dataType, seriesModel, textEl, layoutOption); + } + }); + }; + + LabelManager.prototype.updateLayoutConfig = function (api) { + var width = api.getWidth(); + var height = api.getHeight(); + + function createDragHandler(el, labelLineModel) { + return function () { + updateLabelLinePoints(el, labelLineModel); + }; + } + + for (var i = 0; i < this._labelList.length; i++) { + var labelItem = this._labelList[i]; + var label = labelItem.label; + var hostEl = label.__hostTarget; + var defaultLabelAttr = labelItem.defaultAttr; + var layoutOption = void 0; + + if (typeof labelItem.layoutOption === 'function') { + layoutOption = labelItem.layoutOption(prepareLayoutCallbackParams(labelItem, hostEl)); + } else { + layoutOption = labelItem.layoutOption; + } + + layoutOption = layoutOption || {}; + labelItem.computedLayoutOption = layoutOption; + var degreeToRadian = Math.PI / 180; + + if (hostEl) { + hostEl.setTextConfig({ + local: false, + position: layoutOption.x != null || layoutOption.y != null ? null : defaultLabelAttr.attachedPos, + rotation: layoutOption.rotate != null ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.attachedRot, + offset: [layoutOption.dx || 0, layoutOption.dy || 0] + }); + } + + var needsUpdateLabelLine = false; + + if (layoutOption.x != null) { + label.x = parsePercent$1(layoutOption.x, width); + label.setStyle('x', 0); + needsUpdateLabelLine = true; + } else { + label.x = defaultLabelAttr.x; + label.setStyle('x', defaultLabelAttr.style.x); + } + + if (layoutOption.y != null) { + label.y = parsePercent$1(layoutOption.y, height); + label.setStyle('y', 0); + needsUpdateLabelLine = true; + } else { + label.y = defaultLabelAttr.y; + label.setStyle('y', defaultLabelAttr.style.y); + } + + if (layoutOption.labelLinePoints) { + var guideLine = hostEl.getTextGuideLine(); + + if (guideLine) { + guideLine.setShape({ + points: layoutOption.labelLinePoints + }); + needsUpdateLabelLine = false; + } + } + + var labelLayoutStore = labelLayoutInnerStore(label); + labelLayoutStore.needsUpdateLabelLine = needsUpdateLabelLine; + label.rotation = layoutOption.rotate != null ? layoutOption.rotate * degreeToRadian : defaultLabelAttr.rotation; + + for (var k = 0; k < LABEL_OPTION_TO_STYLE_KEYS.length; k++) { + var key = LABEL_OPTION_TO_STYLE_KEYS[k]; + label.setStyle(key, layoutOption[key] != null ? layoutOption[key] : defaultLabelAttr.style[key]); + } + + if (layoutOption.draggable) { + label.draggable = true; + label.cursor = 'move'; + + if (hostEl) { + var hostModel = labelItem.seriesModel; + + if (labelItem.dataIndex != null) { + var data = labelItem.seriesModel.getData(labelItem.dataType); + hostModel = data.getItemModel(labelItem.dataIndex); + } + + label.on('drag', createDragHandler(hostEl, hostModel.getModel('labelLine'))); + } + } else { + label.off('drag'); + label.cursor = defaultLabelAttr.cursor; + } + } + }; + + LabelManager.prototype.layout = function (api) { + var width = api.getWidth(); + var height = api.getHeight(); + var labelList = prepareLayoutList(this._labelList); + var labelsNeedsAdjustOnX = filter(labelList, function (item) { + return item.layoutOption.moveOverlap === 'shiftX'; + }); + var labelsNeedsAdjustOnY = filter(labelList, function (item) { + return item.layoutOption.moveOverlap === 'shiftY'; + }); + shiftLayoutOnX(labelsNeedsAdjustOnX, 0, width); + shiftLayoutOnY(labelsNeedsAdjustOnY, 0, height); + var labelsNeedsHideOverlap = filter(labelList, function (item) { + return item.layoutOption.hideOverlap; + }); + hideOverlap(labelsNeedsHideOverlap); + }; + + LabelManager.prototype.processLabelsOverall = function () { + var _this = this; + + each(this._chartViewList, function (chartView) { + var seriesModel = chartView.__model; + var ignoreLabelLineUpdate = chartView.ignoreLabelLineUpdate; + var animationEnabled = seriesModel.isAnimationEnabled(); + chartView.group.traverse(function (child) { + if (child.ignore) { + return true; + } + + var needsUpdateLabelLine = !ignoreLabelLineUpdate; + var label = child.getTextContent(); + + if (!needsUpdateLabelLine && label) { + needsUpdateLabelLine = labelLayoutInnerStore(label).needsUpdateLabelLine; + } + + if (needsUpdateLabelLine) { + _this._updateLabelLine(child, seriesModel); + } + + if (animationEnabled) { + _this._animateLabels(child, seriesModel); + } + }); + }); + }; + + LabelManager.prototype._updateLabelLine = function (el, seriesModel) { + var textEl = el.getTextContent(); + var ecData = getECData(el); + var dataIndex = ecData.dataIndex; + + if (textEl && dataIndex != null) { + var data = seriesModel.getData(ecData.dataType); + var itemModel = data.getItemModel(dataIndex); + var defaultStyle = {}; + var visualStyle = data.getItemVisual(dataIndex, 'style'); + var visualType = data.getVisual('drawType'); + defaultStyle.stroke = visualStyle[visualType]; + var labelLineModel = itemModel.getModel('labelLine'); + setLabelLineStyle(el, getLabelLineStatesModels(itemModel), defaultStyle); + updateLabelLinePoints(el, labelLineModel); + } + }; + + LabelManager.prototype._animateLabels = function (el, seriesModel) { + var textEl = el.getTextContent(); + var guideLine = el.getTextGuideLine(); + + if (textEl && !textEl.ignore && !textEl.invisible && !el.disableLabelAnimation && !isElementRemoved(el)) { + var layoutStore = labelLayoutInnerStore(textEl); + var oldLayout = layoutStore.oldLayout; + var ecData = getECData(el); + var dataIndex = ecData.dataIndex; + var newProps = { + x: textEl.x, + y: textEl.y, + rotation: textEl.rotation + }; + var data = seriesModel.getData(ecData.dataType); + + if (!oldLayout) { + textEl.attr(newProps); + + if (!labelInner(textEl).valueAnimation) { + var oldOpacity = retrieve2(textEl.style.opacity, 1); + textEl.style.opacity = 0; + initProps(textEl, { + style: { + opacity: oldOpacity + } + }, seriesModel, dataIndex); + } + } else { + textEl.attr(oldLayout); + var prevStates = el.prevStates; + + if (prevStates) { + if (indexOf(prevStates, 'select') >= 0) { + textEl.attr(layoutStore.oldLayoutSelect); + } + + if (indexOf(prevStates, 'emphasis') >= 0) { + textEl.attr(layoutStore.oldLayoutEmphasis); + } + } + + updateProps(textEl, newProps, seriesModel, dataIndex); + } + + layoutStore.oldLayout = newProps; + + if (textEl.states.select) { + var layoutSelect = layoutStore.oldLayoutSelect = {}; + extendWithKeys(layoutSelect, newProps, LABEL_LAYOUT_PROPS); + extendWithKeys(layoutSelect, textEl.states.select, LABEL_LAYOUT_PROPS); + } + + if (textEl.states.emphasis) { + var layoutEmphasis = layoutStore.oldLayoutEmphasis = {}; + extendWithKeys(layoutEmphasis, newProps, LABEL_LAYOUT_PROPS); + extendWithKeys(layoutEmphasis, textEl.states.emphasis, LABEL_LAYOUT_PROPS); + } + + animateLabelValue(textEl, dataIndex, data, seriesModel, seriesModel); + } + + if (guideLine && !guideLine.ignore && !guideLine.invisible) { + var layoutStore = labelLineAnimationStore(guideLine); + var oldLayout = layoutStore.oldLayout; + var newLayout = { + points: guideLine.shape.points + }; + + if (!oldLayout) { + guideLine.setShape(newLayout); + guideLine.style.strokePercent = 0; + initProps(guideLine, { + style: { + strokePercent: 1 + } + }, seriesModel); + } else { + guideLine.attr({ + shape: oldLayout + }); + updateProps(guideLine, { + shape: newLayout + }, seriesModel); + } + + layoutStore.oldLayout = newLayout; + } + }; + + return LabelManager; + }(); + + function createLegacyDataSelectAction(seriesType, ecRegisterAction) { + function getSeriesIndices(ecModel, payload) { + var seriesIndices = []; + ecModel.eachComponent({ + mainType: 'series', + subType: seriesType, + query: payload + }, function (seriesModel) { + seriesIndices.push(seriesModel.seriesIndex); + }); + return seriesIndices; + } + + each([[seriesType + 'ToggleSelect', 'toggleSelect'], [seriesType + 'Select', 'select'], [seriesType + 'UnSelect', 'unselect']], function (eventsMap) { + ecRegisterAction(eventsMap[0], function (payload, ecModel, api) { + payload = extend({}, payload); + + if ("development" !== 'production') { + deprecateReplaceLog(payload.type, eventsMap[1]); + } + + api.dispatchAction(extend(payload, { + type: eventsMap[1], + seriesIndex: getSeriesIndices(ecModel, payload) + })); + }); + }); + } + + function handleSeriesLegacySelectEvents(type, eventPostfix, ecIns, ecModel, payload) { + var legacyEventName = type + eventPostfix; + + if (!ecIns.isSilent(legacyEventName)) { + if ("development" !== 'production') { + deprecateLog("event " + legacyEventName + " is deprecated."); + } + + ecModel.eachComponent({ + mainType: 'series', + subType: 'pie' + }, function (seriesModel) { + var seriesIndex = seriesModel.seriesIndex; + var selected = payload.selected; + + for (var i = 0; i < selected.length; i++) { + if (selected[i].seriesIndex === seriesIndex) { + var data = seriesModel.getData(); + var dataIndex = queryDataIndex(data, payload.fromActionPayload); + ecIns.trigger(legacyEventName, { + type: legacyEventName, + seriesId: seriesModel.id, + name: isArray(dataIndex) ? data.getName(dataIndex[0]) : data.getName(dataIndex), + selected: extend({}, seriesModel.option.selectedMap) + }); + } + } + }); + } + } + + function handleLegacySelectEvents(messageCenter, ecIns, api) { + messageCenter.on('selectchanged', function (params) { + var ecModel = api.getModel(); + + if (params.isFromClick) { + handleSeriesLegacySelectEvents('map', 'selectchanged', ecIns, ecModel, params); + handleSeriesLegacySelectEvents('pie', 'selectchanged', ecIns, ecModel, params); + } else if (params.fromAction === 'select') { + handleSeriesLegacySelectEvents('map', 'selected', ecIns, ecModel, params); + handleSeriesLegacySelectEvents('pie', 'selected', ecIns, ecModel, params); + } else if (params.fromAction === 'unselect') { + handleSeriesLegacySelectEvents('map', 'unselected', ecIns, ecModel, params); + handleSeriesLegacySelectEvents('pie', 'unselected', ecIns, ecModel, params); + } + }); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function findEventDispatcher(target, det, returnFirstMatch) { + var found; + + while (target) { + if (det(target)) { + found = target; + + if (returnFirstMatch) { + break; + } + } + + target = target.__hostTarget || target.parent; + } + + return found; + } + + var wmUniqueIndex = Math.round(Math.random() * 9); + var WeakMap = (function () { + function WeakMap() { + this._id = '__ec_inner_' + wmUniqueIndex++; + } + WeakMap.prototype.get = function (key) { + return this._guard(key)[this._id]; + }; + WeakMap.prototype.set = function (key, value) { + var target = this._guard(key); + if (typeof Object.defineProperty === 'function') { + Object.defineProperty(target, this._id, { + value: value, + enumerable: false, + configurable: true + }); + } + else { + target[this._id] = value; + } + return this; + }; + WeakMap.prototype["delete"] = function (key) { + if (this.has(key)) { + delete this._guard(key)[this._id]; + return true; + } + return false; + }; + WeakMap.prototype.has = function (key) { + return !!this._guard(key)[this._id]; + }; + WeakMap.prototype._guard = function (key) { + if (key !== Object(key)) { + throw TypeError('Value of WeakMap is not a non-null object.'); + } + return key; + }; + return WeakMap; + }()); + + var Triangle = Path.extend({ + type: 'triangle', + shape: { + cx: 0, + cy: 0, + width: 0, + height: 0 + }, + buildPath: function (path, shape) { + var cx = shape.cx; + var cy = shape.cy; + var width = shape.width / 2; + var height = shape.height / 2; + path.moveTo(cx, cy - height); + path.lineTo(cx + width, cy + height); + path.lineTo(cx - width, cy + height); + path.closePath(); + } + }); + var Diamond = Path.extend({ + type: 'diamond', + shape: { + cx: 0, + cy: 0, + width: 0, + height: 0 + }, + buildPath: function (path, shape) { + var cx = shape.cx; + var cy = shape.cy; + var width = shape.width / 2; + var height = shape.height / 2; + path.moveTo(cx, cy - height); + path.lineTo(cx + width, cy); + path.lineTo(cx, cy + height); + path.lineTo(cx - width, cy); + path.closePath(); + } + }); + var Pin = Path.extend({ + type: 'pin', + shape: { + x: 0, + y: 0, + width: 0, + height: 0 + }, + buildPath: function (path, shape) { + var x = shape.x; + var y = shape.y; + var w = shape.width / 5 * 3; + var h = Math.max(w, shape.height); + var r = w / 2; + var dy = r * r / (h - r); + var cy = y - h + r + dy; + var angle = Math.asin(dy / r); + var dx = Math.cos(angle) * r; + var tanX = Math.sin(angle); + var tanY = Math.cos(angle); + var cpLen = r * 0.6; + var cpLen2 = r * 0.7; + path.moveTo(x - dx, cy + dy); + path.arc(x, cy, r, Math.PI - angle, Math.PI * 2 + angle); + path.bezierCurveTo(x + dx - tanX * cpLen, cy + dy + tanY * cpLen, x, y - cpLen2, x, y); + path.bezierCurveTo(x, y - cpLen2, x - dx + tanX * cpLen, cy + dy + tanY * cpLen, x - dx, cy + dy); + path.closePath(); + } + }); + var Arrow = Path.extend({ + type: 'arrow', + shape: { + x: 0, + y: 0, + width: 0, + height: 0 + }, + buildPath: function (ctx, shape) { + var height = shape.height; + var width = shape.width; + var x = shape.x; + var y = shape.y; + var dx = width / 3 * 2; + ctx.moveTo(x, y); + ctx.lineTo(x + dx, y + height); + ctx.lineTo(x, y + height / 4 * 3); + ctx.lineTo(x - dx, y + height); + ctx.lineTo(x, y); + ctx.closePath(); + } + }); + var symbolCtors = { + line: Rect, + rect: Rect, + roundRect: Rect, + square: Rect, + circle: Circle, + diamond: Diamond, + pin: Pin, + arrow: Arrow, + triangle: Triangle + }; + var symbolShapeMakers = { + line: function (x, y, w, h, shape) { + var thickness = 2; + shape.x = x; + shape.y = y + h / 2 - thickness / 2; + shape.width = w; + shape.height = thickness; + }, + rect: function (x, y, w, h, shape) { + shape.x = x; + shape.y = y; + shape.width = w; + shape.height = h; + }, + roundRect: function (x, y, w, h, shape) { + shape.x = x; + shape.y = y; + shape.width = w; + shape.height = h; + shape.r = Math.min(w, h) / 4; + }, + square: function (x, y, w, h, shape) { + var size = Math.min(w, h); + shape.x = x; + shape.y = y; + shape.width = size; + shape.height = size; + }, + circle: function (x, y, w, h, shape) { + shape.cx = x + w / 2; + shape.cy = y + h / 2; + shape.r = Math.min(w, h) / 2; + }, + diamond: function (x, y, w, h, shape) { + shape.cx = x + w / 2; + shape.cy = y + h / 2; + shape.width = w; + shape.height = h; + }, + pin: function (x, y, w, h, shape) { + shape.x = x + w / 2; + shape.y = y + h / 2; + shape.width = w; + shape.height = h; + }, + arrow: function (x, y, w, h, shape) { + shape.x = x + w / 2; + shape.y = y + h / 2; + shape.width = w; + shape.height = h; + }, + triangle: function (x, y, w, h, shape) { + shape.cx = x + w / 2; + shape.cy = y + h / 2; + shape.width = w; + shape.height = h; + } + }; + var symbolBuildProxies = {}; + each(symbolCtors, function (Ctor, name) { + symbolBuildProxies[name] = new Ctor(); + }); + var SymbolClz = Path.extend({ + type: 'symbol', + shape: { + symbolType: '', + x: 0, + y: 0, + width: 0, + height: 0 + }, + calculateTextPosition: function (out, config, rect) { + var res = calculateTextPosition(out, config, rect); + var shape = this.shape; + + if (shape && shape.symbolType === 'pin' && config.position === 'inside') { + res.y = rect.y + rect.height * 0.4; + } + + return res; + }, + buildPath: function (ctx, shape, inBundle) { + var symbolType = shape.symbolType; + + if (symbolType !== 'none') { + var proxySymbol = symbolBuildProxies[symbolType]; + + if (!proxySymbol) { + symbolType = 'rect'; + proxySymbol = symbolBuildProxies[symbolType]; + } + + symbolShapeMakers[symbolType](shape.x, shape.y, shape.width, shape.height, proxySymbol.shape); + proxySymbol.buildPath(ctx, proxySymbol.shape, inBundle); + } + } + }); + + function symbolPathSetColor(color, innerColor) { + if (this.type !== 'image') { + var symbolStyle = this.style; + + if (this.__isEmptyBrush) { + symbolStyle.stroke = color; + symbolStyle.fill = innerColor || '#fff'; + symbolStyle.lineWidth = 2; + } else { + symbolStyle.fill = color; + } + + this.markRedraw(); + } + } + + function createSymbol(symbolType, x, y, w, h, color, keepAspect) { + var isEmpty = symbolType.indexOf('empty') === 0; + + if (isEmpty) { + symbolType = symbolType.substr(5, 1).toLowerCase() + symbolType.substr(6); + } + + var symbolPath; + + if (symbolType.indexOf('image://') === 0) { + symbolPath = makeImage(symbolType.slice(8), new BoundingRect(x, y, w, h), keepAspect ? 'center' : 'cover'); + } else if (symbolType.indexOf('path://') === 0) { + symbolPath = makePath(symbolType.slice(7), {}, new BoundingRect(x, y, w, h), keepAspect ? 'center' : 'cover'); + } else { + symbolPath = new SymbolClz({ + shape: { + symbolType: symbolType, + x: x, + y: y, + width: w, + height: h + } + }); + } + + symbolPath.__isEmptyBrush = isEmpty; + symbolPath.setColor = symbolPathSetColor; + + if (color) { + symbolPath.setColor(color); + } + + return symbolPath; + } + + function createLinearGradient(ctx, obj, rect) { + var x = obj.x == null ? 0 : obj.x; + var x2 = obj.x2 == null ? 1 : obj.x2; + var y = obj.y == null ? 0 : obj.y; + var y2 = obj.y2 == null ? 0 : obj.y2; + if (!obj.global) { + x = x * rect.width + rect.x; + x2 = x2 * rect.width + rect.x; + y = y * rect.height + rect.y; + y2 = y2 * rect.height + rect.y; + } + x = isNaN(x) ? 0 : x; + x2 = isNaN(x2) ? 1 : x2; + y = isNaN(y) ? 0 : y; + y2 = isNaN(y2) ? 0 : y2; + var canvasGradient = ctx.createLinearGradient(x, y, x2, y2); + return canvasGradient; + } + function createRadialGradient(ctx, obj, rect) { + var width = rect.width; + var height = rect.height; + var min = Math.min(width, height); + var x = obj.x == null ? 0.5 : obj.x; + var y = obj.y == null ? 0.5 : obj.y; + var r = obj.r == null ? 0.5 : obj.r; + if (!obj.global) { + x = x * width + rect.x; + y = y * height + rect.y; + r = r * min; + } + var canvasGradient = ctx.createRadialGradient(x, y, 0, x, y, r); + return canvasGradient; + } + function getCanvasGradient(ctx, obj, rect) { + var canvasGradient = obj.type === 'radial' + ? createRadialGradient(ctx, obj, rect) + : createLinearGradient(ctx, obj, rect); + var colorStops = obj.colorStops; + for (var i = 0; i < colorStops.length; i++) { + canvasGradient.addColorStop(colorStops[i].offset, colorStops[i].color); + } + return canvasGradient; + } + function isClipPathChanged(clipPaths, prevClipPaths) { + if (clipPaths === prevClipPaths || (!clipPaths && !prevClipPaths)) { + return false; + } + if (!clipPaths || !prevClipPaths || (clipPaths.length !== prevClipPaths.length)) { + return true; + } + for (var i = 0; i < clipPaths.length; i++) { + if (clipPaths[i] !== prevClipPaths[i]) { + return true; + } + } + return false; + } + + function normalizeLineDash(lineType, lineWidth) { + if (!lineType || lineType === 'solid' || !(lineWidth > 0)) { + return null; + } + lineWidth = lineWidth || 1; + return lineType === 'dashed' + ? [4 * lineWidth, 2 * lineWidth] + : lineType === 'dotted' + ? [lineWidth] + : isNumber(lineType) + ? [lineType] : isArray(lineType) ? lineType : null; + } + + var pathProxyForDraw = new PathProxy(true); + function styleHasStroke(style) { + var stroke = style.stroke; + return !(stroke == null || stroke === 'none' || !(style.lineWidth > 0)); + } + function styleHasFill(style) { + var fill = style.fill; + return fill != null && fill !== 'none'; + } + function doFillPath(ctx, style) { + if (style.fillOpacity != null && style.fillOpacity !== 1) { + var originalGlobalAlpha = ctx.globalAlpha; + ctx.globalAlpha = style.fillOpacity * style.opacity; + ctx.fill(); + ctx.globalAlpha = originalGlobalAlpha; + } + else { + ctx.fill(); + } + } + function doStrokePath(ctx, style) { + if (style.strokeOpacity != null && style.strokeOpacity !== 1) { + var originalGlobalAlpha = ctx.globalAlpha; + ctx.globalAlpha = style.strokeOpacity * style.opacity; + ctx.stroke(); + ctx.globalAlpha = originalGlobalAlpha; + } + else { + ctx.stroke(); + } + } + function createCanvasPattern(ctx, pattern, el) { + var image = createOrUpdateImage(pattern.image, pattern.__image, el); + if (isImageReady(image)) { + var canvasPattern = ctx.createPattern(image, pattern.repeat || 'repeat'); + if (typeof DOMMatrix === 'function') { + var matrix = new DOMMatrix(); + matrix.rotateSelf(0, 0, (pattern.rotation || 0) / Math.PI * 180); + matrix.scaleSelf((pattern.scaleX || 1), (pattern.scaleY || 1)); + matrix.translateSelf((pattern.x || 0), (pattern.y || 0)); + canvasPattern.setTransform(matrix); + } + return canvasPattern; + } + } + function brushPath(ctx, el, style, inBatch) { + var hasStroke = styleHasStroke(style); + var hasFill = styleHasFill(style); + var strokePercent = style.strokePercent; + var strokePart = strokePercent < 1; + var firstDraw = !el.path; + if ((!el.silent || strokePart) && firstDraw) { + el.createPathProxy(); + } + var path = el.path || pathProxyForDraw; + if (!inBatch) { + var fill = style.fill; + var stroke = style.stroke; + var hasFillGradient = hasFill && !!fill.colorStops; + var hasStrokeGradient = hasStroke && !!stroke.colorStops; + var hasFillPattern = hasFill && !!fill.image; + var hasStrokePattern = hasStroke && !!stroke.image; + var fillGradient = void 0; + var strokeGradient = void 0; + var fillPattern = void 0; + var strokePattern = void 0; + var rect = void 0; + if (hasFillGradient || hasStrokeGradient) { + rect = el.getBoundingRect(); + } + if (hasFillGradient) { + fillGradient = el.__dirty + ? getCanvasGradient(ctx, fill, rect) + : el.__canvasFillGradient; + el.__canvasFillGradient = fillGradient; + } + if (hasStrokeGradient) { + strokeGradient = el.__dirty + ? getCanvasGradient(ctx, stroke, rect) + : el.__canvasStrokeGradient; + el.__canvasStrokeGradient = strokeGradient; + } + if (hasFillPattern) { + fillPattern = (el.__dirty || !el.__canvasFillPattern) + ? createCanvasPattern(ctx, fill, el) + : el.__canvasFillPattern; + el.__canvasFillPattern = fillPattern; + } + if (hasStrokePattern) { + strokePattern = (el.__dirty || !el.__canvasStrokePattern) + ? createCanvasPattern(ctx, stroke, el) + : el.__canvasStrokePattern; + el.__canvasStrokePattern = fillPattern; + } + if (hasFillGradient) { + ctx.fillStyle = fillGradient; + } + else if (hasFillPattern) { + if (fillPattern) { + ctx.fillStyle = fillPattern; + } + else { + hasFill = false; + } + } + if (hasStrokeGradient) { + ctx.strokeStyle = strokeGradient; + } + else if (hasStrokePattern) { + if (strokePattern) { + ctx.strokeStyle = strokePattern; + } + else { + hasStroke = false; + } + } + } + var lineDash = style.lineDash && style.lineWidth > 0 && normalizeLineDash(style.lineDash, style.lineWidth); + var lineDashOffset = style.lineDashOffset; + var ctxLineDash = !!ctx.setLineDash; + var scale = el.getGlobalScale(); + path.setScale(scale[0], scale[1], el.segmentIgnoreThreshold); + if (lineDash) { + var lineScale_1 = (style.strokeNoScale && el.getLineScale) ? el.getLineScale() : 1; + if (lineScale_1 && lineScale_1 !== 1) { + lineDash = map(lineDash, function (rawVal) { + return rawVal / lineScale_1; + }); + lineDashOffset /= lineScale_1; + } + } + var needsRebuild = true; + if (firstDraw || (el.__dirty & Path.SHAPE_CHANGED_BIT) + || (lineDash && !ctxLineDash && hasStroke)) { + path.setDPR(ctx.dpr); + if (strokePart) { + path.setContext(null); + } + else { + path.setContext(ctx); + needsRebuild = false; + } + path.reset(); + if (lineDash && !ctxLineDash) { + path.setLineDash(lineDash); + path.setLineDashOffset(lineDashOffset); + } + el.buildPath(path, el.shape, inBatch); + path.toStatic(); + el.pathUpdated(); + } + if (needsRebuild) { + path.rebuildPath(ctx, strokePart ? strokePercent : 1); + } + if (lineDash && ctxLineDash) { + ctx.setLineDash(lineDash); + ctx.lineDashOffset = lineDashOffset; + } + if (!inBatch) { + if (style.strokeFirst) { + if (hasStroke) { + doStrokePath(ctx, style); + } + if (hasFill) { + doFillPath(ctx, style); + } + } + else { + if (hasFill) { + doFillPath(ctx, style); + } + if (hasStroke) { + doStrokePath(ctx, style); + } + } + } + if (lineDash && ctxLineDash) { + ctx.setLineDash([]); + } + } + function brushImage(ctx, el, style) { + var image = el.__image = createOrUpdateImage(style.image, el.__image, el, el.onload); + if (!image || !isImageReady(image)) { + return; + } + var x = style.x || 0; + var y = style.y || 0; + var width = el.getWidth(); + var height = el.getHeight(); + var aspect = image.width / image.height; + if (width == null && height != null) { + width = height * aspect; + } + else if (height == null && width != null) { + height = width / aspect; + } + else if (width == null && height == null) { + width = image.width; + height = image.height; + } + if (style.sWidth && style.sHeight) { + var sx = style.sx || 0; + var sy = style.sy || 0; + ctx.drawImage(image, sx, sy, style.sWidth, style.sHeight, x, y, width, height); + } + else if (style.sx && style.sy) { + var sx = style.sx; + var sy = style.sy; + var sWidth = width - sx; + var sHeight = height - sy; + ctx.drawImage(image, sx, sy, sWidth, sHeight, x, y, width, height); + } + else { + ctx.drawImage(image, x, y, width, height); + } + } + function brushText(ctx, el, style) { + var text = style.text; + text != null && (text += ''); + if (text) { + ctx.font = style.font || DEFAULT_FONT; + ctx.textAlign = style.textAlign; + ctx.textBaseline = style.textBaseline; + var hasLineDash = void 0; + if (ctx.setLineDash) { + var lineDash = style.lineDash && style.lineWidth > 0 && normalizeLineDash(style.lineDash, style.lineWidth); + var lineDashOffset = style.lineDashOffset; + if (lineDash) { + var lineScale_2 = (style.strokeNoScale && el.getLineScale) ? el.getLineScale() : 1; + if (lineScale_2 && lineScale_2 !== 1) { + lineDash = map(lineDash, function (rawVal) { + return rawVal / lineScale_2; + }); + lineDashOffset /= lineScale_2; + } + ctx.setLineDash(lineDash); + ctx.lineDashOffset = lineDashOffset; + hasLineDash = true; + } + } + if (style.strokeFirst) { + if (styleHasStroke(style)) { + ctx.strokeText(text, style.x, style.y); + } + if (styleHasFill(style)) { + ctx.fillText(text, style.x, style.y); + } + } + else { + if (styleHasFill(style)) { + ctx.fillText(text, style.x, style.y); + } + if (styleHasStroke(style)) { + ctx.strokeText(text, style.x, style.y); + } + } + if (hasLineDash) { + ctx.setLineDash([]); + } + } + } + var SHADOW_NUMBER_PROPS = ['shadowBlur', 'shadowOffsetX', 'shadowOffsetY']; + var STROKE_PROPS = [ + ['lineCap', 'butt'], ['lineJoin', 'miter'], ['miterLimit', 10] + ]; + function bindCommonProps(ctx, style, prevStyle, forceSetAll, scope) { + var styleChanged = false; + if (!forceSetAll) { + prevStyle = prevStyle || {}; + if (style === prevStyle) { + return false; + } + } + if (forceSetAll || style.opacity !== prevStyle.opacity) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx.globalAlpha = style.opacity == null ? DEFAULT_COMMON_STYLE.opacity : style.opacity; + } + if (forceSetAll || style.blend !== prevStyle.blend) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx.globalCompositeOperation = style.blend || DEFAULT_COMMON_STYLE.blend; + } + for (var i = 0; i < SHADOW_NUMBER_PROPS.length; i++) { + var propName = SHADOW_NUMBER_PROPS[i]; + if (forceSetAll || style[propName] !== prevStyle[propName]) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx[propName] = ctx.dpr * (style[propName] || 0); + } + } + if (forceSetAll || style.shadowColor !== prevStyle.shadowColor) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx.shadowColor = style.shadowColor || DEFAULT_COMMON_STYLE.shadowColor; + } + return styleChanged; + } + function bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetAll, scope) { + var style = getStyle(el, scope.inHover); + var prevStyle = forceSetAll + ? null + : (prevEl && getStyle(prevEl, scope.inHover) || {}); + if (style === prevStyle) { + return false; + } + var styleChanged = bindCommonProps(ctx, style, prevStyle, forceSetAll, scope); + if (forceSetAll || style.fill !== prevStyle.fill) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx.fillStyle = style.fill; + } + if (forceSetAll || style.stroke !== prevStyle.stroke) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx.strokeStyle = style.stroke; + } + if (forceSetAll || style.opacity !== prevStyle.opacity) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx.globalAlpha = style.opacity == null ? 1 : style.opacity; + } + if (el.hasStroke()) { + var lineWidth = style.lineWidth; + var newLineWidth = lineWidth / ((style.strokeNoScale && el && el.getLineScale) ? el.getLineScale() : 1); + if (ctx.lineWidth !== newLineWidth) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx.lineWidth = newLineWidth; + } + } + for (var i = 0; i < STROKE_PROPS.length; i++) { + var prop = STROKE_PROPS[i]; + var propName = prop[0]; + if (forceSetAll || style[propName] !== prevStyle[propName]) { + if (!styleChanged) { + flushPathDrawn(ctx, scope); + styleChanged = true; + } + ctx[propName] = style[propName] || prop[1]; + } + } + return styleChanged; + } + function bindImageStyle(ctx, el, prevEl, forceSetAll, scope) { + return bindCommonProps(ctx, getStyle(el, scope.inHover), prevEl && getStyle(prevEl, scope.inHover), forceSetAll, scope); + } + function setContextTransform(ctx, el) { + var m = el.transform; + var dpr = ctx.dpr || 1; + if (m) { + ctx.setTransform(dpr * m[0], dpr * m[1], dpr * m[2], dpr * m[3], dpr * m[4], dpr * m[5]); + } + else { + ctx.setTransform(dpr, 0, 0, dpr, 0, 0); + } + } + function updateClipStatus(clipPaths, ctx, scope) { + var allClipped = false; + for (var i = 0; i < clipPaths.length; i++) { + var clipPath = clipPaths[i]; + allClipped = allClipped || clipPath.isZeroArea(); + setContextTransform(ctx, clipPath); + ctx.beginPath(); + clipPath.buildPath(ctx, clipPath.shape); + ctx.clip(); + } + scope.allClipped = allClipped; + } + function isTransformChanged(m0, m1) { + if (m0 && m1) { + return m0[0] !== m1[0] + || m0[1] !== m1[1] + || m0[2] !== m1[2] + || m0[3] !== m1[3] + || m0[4] !== m1[4] + || m0[5] !== m1[5]; + } + else if (!m0 && !m1) { + return false; + } + return true; + } + var DRAW_TYPE_PATH = 1; + var DRAW_TYPE_IMAGE = 2; + var DRAW_TYPE_TEXT = 3; + var DRAW_TYPE_INCREMENTAL = 4; + function canPathBatch(style) { + var hasFill = styleHasFill(style); + var hasStroke = styleHasStroke(style); + return !(style.lineDash + || !(+hasFill ^ +hasStroke) + || (hasFill && typeof style.fill !== 'string') + || (hasStroke && typeof style.stroke !== 'string') + || style.strokePercent < 1 + || style.strokeOpacity < 1 + || style.fillOpacity < 1); + } + function flushPathDrawn(ctx, scope) { + scope.batchFill && ctx.fill(); + scope.batchStroke && ctx.stroke(); + scope.batchFill = ''; + scope.batchStroke = ''; + } + function getStyle(el, inHover) { + return inHover ? (el.__hoverStyle || el.style) : el.style; + } + function brushSingle(ctx, el) { + brush(ctx, el, { inHover: false, viewWidth: 0, viewHeight: 0 }, true); + } + function brush(ctx, el, scope, isLast) { + var m = el.transform; + if (!el.shouldBePainted(scope.viewWidth, scope.viewHeight, false, false)) { + el.__dirty &= ~Element.REDARAW_BIT; + el.__isRendered = false; + return; + } + var clipPaths = el.__clipPaths; + var prevElClipPaths = scope.prevElClipPaths; + var forceSetTransform = false; + var forceSetStyle = false; + if (!prevElClipPaths || isClipPathChanged(clipPaths, prevElClipPaths)) { + if (prevElClipPaths && prevElClipPaths.length) { + flushPathDrawn(ctx, scope); + ctx.restore(); + forceSetStyle = forceSetTransform = true; + scope.prevElClipPaths = null; + scope.allClipped = false; + scope.prevEl = null; + } + if (clipPaths && clipPaths.length) { + flushPathDrawn(ctx, scope); + ctx.save(); + updateClipStatus(clipPaths, ctx, scope); + forceSetTransform = true; + } + scope.prevElClipPaths = clipPaths; + } + if (scope.allClipped) { + el.__isRendered = false; + return; + } + el.beforeBrush && el.beforeBrush(); + el.innerBeforeBrush(); + var prevEl = scope.prevEl; + if (!prevEl) { + forceSetStyle = forceSetTransform = true; + } + var canBatchPath = el instanceof Path + && el.autoBatch + && canPathBatch(el.style); + if (forceSetTransform || isTransformChanged(m, prevEl.transform)) { + flushPathDrawn(ctx, scope); + setContextTransform(ctx, el); + } + else if (!canBatchPath) { + flushPathDrawn(ctx, scope); + } + var style = getStyle(el, scope.inHover); + if (el instanceof Path) { + if (scope.lastDrawType !== DRAW_TYPE_PATH) { + forceSetStyle = true; + scope.lastDrawType = DRAW_TYPE_PATH; + } + bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetStyle, scope); + if (!canBatchPath || (!scope.batchFill && !scope.batchStroke)) { + ctx.beginPath(); + } + brushPath(ctx, el, style, canBatchPath); + if (canBatchPath) { + scope.batchFill = style.fill || ''; + scope.batchStroke = style.stroke || ''; + } + } + else { + if (el instanceof TSpan) { + if (scope.lastDrawType !== DRAW_TYPE_TEXT) { + forceSetStyle = true; + scope.lastDrawType = DRAW_TYPE_TEXT; + } + bindPathAndTextCommonStyle(ctx, el, prevEl, forceSetStyle, scope); + brushText(ctx, el, style); + } + else if (el instanceof ZRImage) { + if (scope.lastDrawType !== DRAW_TYPE_IMAGE) { + forceSetStyle = true; + scope.lastDrawType = DRAW_TYPE_IMAGE; + } + bindImageStyle(ctx, el, prevEl, forceSetStyle, scope); + brushImage(ctx, el, style); + } + else if (el instanceof IncrementalDisplayable) { + if (scope.lastDrawType !== DRAW_TYPE_INCREMENTAL) { + forceSetStyle = true; + scope.lastDrawType = DRAW_TYPE_INCREMENTAL; + } + brushIncremental(ctx, el, scope); + } + } + if (canBatchPath && isLast) { + flushPathDrawn(ctx, scope); + } + el.innerAfterBrush(); + el.afterBrush && el.afterBrush(); + scope.prevEl = el; + el.__dirty = 0; + el.__isRendered = true; + } + function brushIncremental(ctx, el, scope) { + var displayables = el.getDisplayables(); + var temporalDisplayables = el.getTemporalDisplayables(); + ctx.save(); + var innerScope = { + prevElClipPaths: null, + prevEl: null, + allClipped: false, + viewWidth: scope.viewWidth, + viewHeight: scope.viewHeight, + inHover: scope.inHover + }; + var i; + var len; + for (i = el.getCursor(), len = displayables.length; i < len; i++) { + var displayable = displayables[i]; + displayable.beforeBrush && displayable.beforeBrush(); + displayable.innerBeforeBrush(); + brush(ctx, displayable, innerScope, i === len - 1); + displayable.innerAfterBrush(); + displayable.afterBrush && displayable.afterBrush(); + innerScope.prevEl = displayable; + } + for (var i_1 = 0, len_1 = temporalDisplayables.length; i_1 < len_1; i_1++) { + var displayable = temporalDisplayables[i_1]; + displayable.beforeBrush && displayable.beforeBrush(); + displayable.innerBeforeBrush(); + brush(ctx, displayable, innerScope, i_1 === len_1 - 1); + displayable.innerAfterBrush(); + displayable.afterBrush && displayable.afterBrush(); + innerScope.prevEl = displayable; + } + el.clearTemporalDisplayables(); + el.notClear = true; + ctx.restore(); + } + + var decalMap = new WeakMap(); + var decalCache = new LRU(100); + var decalKeys = ['symbol', 'symbolSize', 'symbolKeepAspect', 'color', 'backgroundColor', 'dashArrayX', 'dashArrayY', 'maxTileWidth', 'maxTileHeight']; + function createOrUpdatePatternFromDecal(decalObject, api) { + if (decalObject === 'none') { + return null; + } + + var dpr = api.getDevicePixelRatio(); + var zr = api.getZr(); + var isSVG = zr.painter.type === 'svg'; + + if (decalObject.dirty) { + decalMap["delete"](decalObject); + } + + var oldPattern = decalMap.get(decalObject); + + if (oldPattern) { + return oldPattern; + } + + var decalOpt = defaults(decalObject, { + symbol: 'rect', + symbolSize: 1, + symbolKeepAspect: true, + color: 'rgba(0, 0, 0, 0.2)', + backgroundColor: null, + dashArrayX: 5, + dashArrayY: 5, + rotation: 0, + maxTileWidth: 512, + maxTileHeight: 512 + }); + + if (decalOpt.backgroundColor === 'none') { + decalOpt.backgroundColor = null; + } + + var pattern = { + repeat: 'repeat' + }; + setPatternnSource(pattern); + pattern.rotation = decalOpt.rotation; + pattern.scaleX = pattern.scaleY = isSVG ? 1 : 1 / dpr; + decalMap.set(decalObject, pattern); + decalObject.dirty = false; + return pattern; + + function setPatternnSource(pattern) { + var keys = [dpr]; + var isValidKey = true; + + for (var i = 0; i < decalKeys.length; ++i) { + var value = decalOpt[decalKeys[i]]; + var valueType = typeof value; + + if (value != null && !isArray(value) && valueType !== 'string' && valueType !== 'number' && valueType !== 'boolean') { + isValidKey = false; + break; + } + + keys.push(value); + } + + var cacheKey; + + if (isValidKey) { + cacheKey = keys.join(',') + (isSVG ? '-svg' : ''); + var cache = decalCache.get(cacheKey); + + if (cache) { + isSVG ? pattern.svgElement = cache : pattern.image = cache; + } + } + + var dashArrayX = normalizeDashArrayX(decalOpt.dashArrayX); + var dashArrayY = normalizeDashArrayY(decalOpt.dashArrayY); + var symbolArray = normalizeSymbolArray(decalOpt.symbol); + var lineBlockLengthsX = getLineBlockLengthX(dashArrayX); + var lineBlockLengthY = getLineBlockLengthY(dashArrayY); + var canvas = !isSVG && createCanvas(); + var svgRoot = isSVG && zr.painter.createSVGElement('g'); + var pSize = getPatternSize(); + var ctx; + + if (canvas) { + canvas.width = pSize.width * dpr; + canvas.height = pSize.height * dpr; + ctx = canvas.getContext('2d'); + } + + brushDecal(); + + if (isValidKey) { + decalCache.put(cacheKey, canvas || svgRoot); + } + + pattern.image = canvas; + pattern.svgElement = svgRoot; + pattern.svgWidth = pSize.width; + pattern.svgHeight = pSize.height; + + function getPatternSize() { + var width = 1; + + for (var i = 0, xlen = lineBlockLengthsX.length; i < xlen; ++i) { + width = getLeastCommonMultiple(width, lineBlockLengthsX[i]); + } + + var symbolRepeats = 1; + + for (var i = 0, xlen = symbolArray.length; i < xlen; ++i) { + symbolRepeats = getLeastCommonMultiple(symbolRepeats, symbolArray[i].length); + } + + width *= symbolRepeats; + var height = lineBlockLengthY * lineBlockLengthsX.length * symbolArray.length; + + if ("development" !== 'production') { + var warn = function (attrName) { + console.warn("Calculated decal size is greater than " + attrName + " due to decal option settings so " + attrName + " is used for the decal size. Please consider changing the decal option to make a smaller decal or set " + attrName + " to be larger to avoid incontinuity."); + }; + + if (width > decalOpt.maxTileWidth) { + warn('maxTileWidth'); + } + + if (height > decalOpt.maxTileHeight) { + warn('maxTileHeight'); + } + } + + return { + width: Math.max(1, Math.min(width, decalOpt.maxTileWidth)), + height: Math.max(1, Math.min(height, decalOpt.maxTileHeight)) + }; + } + + function brushDecal() { + if (ctx) { + ctx.clearRect(0, 0, canvas.width, canvas.height); + + if (decalOpt.backgroundColor) { + ctx.fillStyle = decalOpt.backgroundColor; + ctx.fillRect(0, 0, canvas.width, canvas.height); + } + } + + var ySum = 0; + + for (var i = 0; i < dashArrayY.length; ++i) { + ySum += dashArrayY[i]; + } + + if (ySum <= 0) { + return; + } + + var y = -lineBlockLengthY; + var yId = 0; + var yIdTotal = 0; + var xId0 = 0; + + while (y < pSize.height) { + if (yId % 2 === 0) { + var symbolYId = yIdTotal / 2 % symbolArray.length; + var x = 0; + var xId1 = 0; + var xId1Total = 0; + + while (x < pSize.width * 2) { + var xSum = 0; + + for (var i = 0; i < dashArrayX[xId0].length; ++i) { + xSum += dashArrayX[xId0][i]; + } + + if (xSum <= 0) { + break; + } + + if (xId1 % 2 === 0) { + var size = (1 - decalOpt.symbolSize) * 0.5; + var left = x + dashArrayX[xId0][xId1] * size; + var top_1 = y + dashArrayY[yId] * size; + var width = dashArrayX[xId0][xId1] * decalOpt.symbolSize; + var height = dashArrayY[yId] * decalOpt.symbolSize; + var symbolXId = xId1Total / 2 % symbolArray[symbolYId].length; + brushSymbol(left, top_1, width, height, symbolArray[symbolYId][symbolXId]); + } + + x += dashArrayX[xId0][xId1]; + ++xId1Total; + ++xId1; + + if (xId1 === dashArrayX[xId0].length) { + xId1 = 0; + } + } + + ++xId0; + + if (xId0 === dashArrayX.length) { + xId0 = 0; + } + } + + y += dashArrayY[yId]; + ++yIdTotal; + ++yId; + + if (yId === dashArrayY.length) { + yId = 0; + } + } + + function brushSymbol(x, y, width, height, symbolType) { + var scale = isSVG ? 1 : dpr; + var symbol = createSymbol(symbolType, x * scale, y * scale, width * scale, height * scale, decalOpt.color, decalOpt.symbolKeepAspect); + + if (isSVG) { + svgRoot.appendChild(zr.painter.paintOne(symbol)); + } else { + brushSingle(ctx, symbol); + } + } + } + } + } + + function normalizeSymbolArray(symbol) { + if (!symbol || symbol.length === 0) { + return [['rect']]; + } + + if (typeof symbol === 'string') { + return [[symbol]]; + } + + var isAllString = true; + + for (var i = 0; i < symbol.length; ++i) { + if (typeof symbol[i] !== 'string') { + isAllString = false; + break; + } + } + + if (isAllString) { + return normalizeSymbolArray([symbol]); + } + + var result = []; + + for (var i = 0; i < symbol.length; ++i) { + if (typeof symbol[i] === 'string') { + result.push([symbol[i]]); + } else { + result.push(symbol[i]); + } + } + + return result; + } + + function normalizeDashArrayX(dash) { + if (!dash || dash.length === 0) { + return [[0, 0]]; + } + + if (typeof dash === 'number') { + var dashValue = Math.ceil(dash); + return [[dashValue, dashValue]]; + } + + var isAllNumber = true; + + for (var i = 0; i < dash.length; ++i) { + if (typeof dash[i] !== 'number') { + isAllNumber = false; + break; + } + } + + if (isAllNumber) { + return normalizeDashArrayX([dash]); + } + + var result = []; + + for (var i = 0; i < dash.length; ++i) { + if (typeof dash[i] === 'number') { + var dashValue = Math.ceil(dash[i]); + result.push([dashValue, dashValue]); + } else { + var dashValue = map(dash[i], function (n) { + return Math.ceil(n); + }); + + if (dashValue.length % 2 === 1) { + result.push(dashValue.concat(dashValue)); + } else { + result.push(dashValue); + } + } + } + + return result; + } + + function normalizeDashArrayY(dash) { + if (!dash || typeof dash === 'object' && dash.length === 0) { + return [0, 0]; + } + + if (typeof dash === 'number') { + var dashValue_1 = Math.ceil(dash); + return [dashValue_1, dashValue_1]; + } + + var dashValue = map(dash, function (n) { + return Math.ceil(n); + }); + return dash.length % 2 ? dashValue.concat(dashValue) : dashValue; + } + + function getLineBlockLengthX(dash) { + return map(dash, function (line) { + return getLineBlockLengthY(line); + }); + } + + function getLineBlockLengthY(dash) { + var blockLength = 0; + + for (var i = 0; i < dash.length; ++i) { + blockLength += dash[i]; + } + + if (dash.length % 2 === 1) { + return blockLength * 2; + } + + return blockLength; + } + + function decalVisual(ecModel, api) { + ecModel.eachRawSeries(function (seriesModel) { + if (ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + var data = seriesModel.getData(); + + if (data.hasItemVisual()) { + data.each(function (idx) { + var decal = data.getItemVisual(idx, 'decal'); + + if (decal) { + var itemStyle = data.ensureUniqueItemVisual(idx, 'style'); + itemStyle.decal = createOrUpdatePatternFromDecal(decal, api); + } + }); + } + + var decal = data.getVisual('decal'); + + if (decal) { + var style = data.getVisual('style'); + style.decal = createOrUpdatePatternFromDecal(decal, api); + } + }); + } + + var assert$1 = assert; + var each$3 = each; + var isFunction$1 = isFunction; + var isObject$2 = isObject; + var indexOf$1 = indexOf; + var hasWindow = typeof window !== 'undefined'; + var version$1 = '5.0.1'; + var dependencies = { + zrender: '5.0.3' + }; + var TEST_FRAME_REMAIN_TIME = 1; + var PRIORITY_PROCESSOR_SERIES_FILTER = 800; + var PRIORITY_PROCESSOR_DATASTACK = 900; + var PRIORITY_PROCESSOR_FILTER = 1000; + var PRIORITY_PROCESSOR_DEFAULT = 2000; + var PRIORITY_PROCESSOR_STATISTIC = 5000; + var PRIORITY_VISUAL_LAYOUT = 1000; + var PRIORITY_VISUAL_PROGRESSIVE_LAYOUT = 1100; + var PRIORITY_VISUAL_GLOBAL = 2000; + var PRIORITY_VISUAL_CHART = 3000; + var PRIORITY_VISUAL_COMPONENT = 4000; + var PRIORITY_VISUAL_CHART_DATA_CUSTOM = 4500; + var PRIORITY_VISUAL_POST_CHART_LAYOUT = 4600; + var PRIORITY_VISUAL_BRUSH = 5000; + var PRIORITY_VISUAL_ARIA = 6000; + var PRIORITY_VISUAL_DECAL = 7000; + var PRIORITY = { + PROCESSOR: { + FILTER: PRIORITY_PROCESSOR_FILTER, + SERIES_FILTER: PRIORITY_PROCESSOR_SERIES_FILTER, + STATISTIC: PRIORITY_PROCESSOR_STATISTIC + }, + VISUAL: { + LAYOUT: PRIORITY_VISUAL_LAYOUT, + PROGRESSIVE_LAYOUT: PRIORITY_VISUAL_PROGRESSIVE_LAYOUT, + GLOBAL: PRIORITY_VISUAL_GLOBAL, + CHART: PRIORITY_VISUAL_CHART, + POST_CHART_LAYOUT: PRIORITY_VISUAL_POST_CHART_LAYOUT, + COMPONENT: PRIORITY_VISUAL_COMPONENT, + BRUSH: PRIORITY_VISUAL_BRUSH, + CHART_ITEM: PRIORITY_VISUAL_CHART_DATA_CUSTOM, + ARIA: PRIORITY_VISUAL_ARIA, + DECAL: PRIORITY_VISUAL_DECAL + } + }; + var IN_MAIN_PROCESS_KEY = '__flagInMainProcess'; + var OPTION_UPDATED_KEY = '__optionUpdated'; + var STATUS_NEEDS_UPDATE_KEY = '__needsUpdateStatus'; + var ACTION_REG = /^[a-zA-Z0-9_]+$/; + var CONNECT_STATUS_KEY = '__connectUpdateStatus'; + var CONNECT_STATUS_PENDING = 0; + var CONNECT_STATUS_UPDATING = 1; + var CONNECT_STATUS_UPDATED = 2; + + function createRegisterEventWithLowercaseECharts(method) { + return function () { + var args = []; + + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + + if (this.isDisposed()) { + disposedWarning(this.id); + return; + } + + return toLowercaseNameAndCallEventful(this, method, args); + }; + } + + function createRegisterEventWithLowercaseMessageCenter(method) { + return function () { + var args = []; + + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + + return toLowercaseNameAndCallEventful(this, method, args); + }; + } + + function toLowercaseNameAndCallEventful(host, method, args) { + args[0] = args[0] && args[0].toLowerCase(); + return Eventful.prototype[method].apply(host, args); + } + + var MessageCenter = function (_super) { + __extends(MessageCenter, _super); + + function MessageCenter() { + return _super !== null && _super.apply(this, arguments) || this; + } + + return MessageCenter; + }(Eventful); + + var messageCenterProto = MessageCenter.prototype; + messageCenterProto.on = createRegisterEventWithLowercaseMessageCenter('on'); + messageCenterProto.off = createRegisterEventWithLowercaseMessageCenter('off'); + var prepare; + var prepareView; + var updateDirectly; + var updateMethods; + var doConvertPixel; + var updateStreamModes; + var doDispatchAction; + var flushPendingActions; + var triggerUpdatedEvent; + var bindRenderedEvent; + var bindMouseEvent; + var clearColorPalette; + var render; + var renderComponents; + var renderSeries; + var performPostUpdateFuncs; + var createExtensionAPI; + var enableConnect; + var setTransitionOpt; + var markStatusToUpdate; + var applyChangedStates; + + var ECharts = function (_super) { + __extends(ECharts, _super); + + function ECharts(dom, theme, opts) { + var _this = _super.call(this, new ECEventProcessor()) || this; + + _this._chartsViews = []; + _this._chartsMap = {}; + _this._componentsViews = []; + _this._componentsMap = {}; + _this._pendingActions = []; + opts = opts || {}; + + if (typeof theme === 'string') { + theme = themeStorage[theme]; + } + + _this._dom = dom; + var defaultRenderer = 'canvas'; + var defaultUseDirtyRect = false; + + if ("development" !== 'production') { + var root = hasWindow ? window : global; + defaultRenderer = root.__ECHARTS__DEFAULT__RENDERER__ || defaultRenderer; + var devUseDirtyRect = root.__ECHARTS__DEFAULT__USE_DIRTY_RECT__; + defaultUseDirtyRect = devUseDirtyRect == null ? defaultUseDirtyRect : devUseDirtyRect; + } + + var zr = _this._zr = init(dom, { + renderer: opts.renderer || defaultRenderer, + devicePixelRatio: opts.devicePixelRatio, + width: opts.width, + height: opts.height, + useDirtyRect: opts.useDirtyRect == null ? defaultUseDirtyRect : opts.useDirtyRect + }); + _this._throttledZrFlush = throttle(bind(zr.flush, zr), 17); + theme = clone(theme); + theme && globalBackwardCompat(theme, true); + _this._theme = theme; + _this._locale = createLocaleObject(opts.locale || SYSTEM_LANG); + _this._coordSysMgr = new CoordinateSystemManager(); + var api = _this._api = createExtensionAPI(_this); + + function prioritySortFunc(a, b) { + return a.__prio - b.__prio; + } + + sort(visualFuncs, prioritySortFunc); + sort(dataProcessorFuncs, prioritySortFunc); + _this._scheduler = new Scheduler(_this, api, dataProcessorFuncs, visualFuncs); + _this._messageCenter = new MessageCenter(); + _this._labelManager = new LabelManager(); + + _this._initEvents(); + + _this.resize = bind(_this.resize, _this); + zr.animation.on('frame', _this._onframe, _this); + bindRenderedEvent(zr, _this); + bindMouseEvent(zr, _this); + setAsPrimitive(_this); + return _this; + } + + ECharts.prototype._onframe = function () { + if (this._disposed) { + return; + } + + applyChangedStates(this); + var scheduler = this._scheduler; + + if (this[OPTION_UPDATED_KEY]) { + var silent = this[OPTION_UPDATED_KEY].silent; + this[IN_MAIN_PROCESS_KEY] = true; + prepare(this); + updateMethods.update.call(this); + + this._zr.flush(); + + this[IN_MAIN_PROCESS_KEY] = false; + this[OPTION_UPDATED_KEY] = false; + flushPendingActions.call(this, silent); + triggerUpdatedEvent.call(this, silent); + } else if (scheduler.unfinished) { + var remainTime = TEST_FRAME_REMAIN_TIME; + var ecModel = this._model; + var api = this._api; + scheduler.unfinished = false; + + do { + var startTime = +new Date(); + scheduler.performSeriesTasks(ecModel); + scheduler.performDataProcessorTasks(ecModel); + updateStreamModes(this, ecModel); + scheduler.performVisualTasks(ecModel); + renderSeries(this, this._model, api, 'remain'); + remainTime -= +new Date() - startTime; + } while (remainTime > 0 && scheduler.unfinished); + + if (!scheduler.unfinished) { + this._zr.flush(); + } + } + }; + + ECharts.prototype.getDom = function () { + return this._dom; + }; + + ECharts.prototype.getId = function () { + return this.id; + }; + + ECharts.prototype.getZr = function () { + return this._zr; + }; + + ECharts.prototype.setOption = function (option, notMerge, lazyUpdate) { + if ("development" !== 'production') { + assert$1(!this[IN_MAIN_PROCESS_KEY], '`setOption` should not be called during main process.'); + } + + if (this._disposed) { + disposedWarning(this.id); + return; + } + + var silent; + var replaceMerge; + var transitionOpt; + + if (isObject$2(notMerge)) { + lazyUpdate = notMerge.lazyUpdate; + silent = notMerge.silent; + replaceMerge = notMerge.replaceMerge; + transitionOpt = notMerge.transition; + notMerge = notMerge.notMerge; + } + + this[IN_MAIN_PROCESS_KEY] = true; + + if (!this._model || notMerge) { + var optionManager = new OptionManager(this._api); + var theme = this._theme; + var ecModel = this._model = new GlobalModel(); + ecModel.scheduler = this._scheduler; + ecModel.init(null, null, null, theme, this._locale, optionManager); + } + + this._model.setOption(option, { + replaceMerge: replaceMerge + }, optionPreprocessorFuncs); + + setTransitionOpt(this, transitionOpt); + + if (lazyUpdate) { + this[OPTION_UPDATED_KEY] = { + silent: silent + }; + this[IN_MAIN_PROCESS_KEY] = false; + this.getZr().wakeUp(); + } else { + prepare(this); + updateMethods.update.call(this); + + this._zr.flush(); + + this[OPTION_UPDATED_KEY] = false; + this[IN_MAIN_PROCESS_KEY] = false; + flushPendingActions.call(this, silent); + triggerUpdatedEvent.call(this, silent); + } + }; + + ECharts.prototype.setTheme = function () { + console.error('ECharts#setTheme() is DEPRECATED in ECharts 3.0'); + }; + + ECharts.prototype.getModel = function () { + return this._model; + }; + + ECharts.prototype.getOption = function () { + return this._model && this._model.getOption(); + }; + + ECharts.prototype.getWidth = function () { + return this._zr.getWidth(); + }; + + ECharts.prototype.getHeight = function () { + return this._zr.getHeight(); + }; + + ECharts.prototype.getDevicePixelRatio = function () { + return this._zr.painter.dpr || hasWindow && window.devicePixelRatio || 1; + }; + + ECharts.prototype.getRenderedCanvas = function (opts) { + if (!env.canvasSupported) { + return; + } + + opts = extend({}, opts || {}); + opts.pixelRatio = opts.pixelRatio || 1; + opts.backgroundColor = opts.backgroundColor || this._model.get('backgroundColor'); + var zr = this._zr; + return zr.painter.getRenderedCanvas(opts); + }; + + ECharts.prototype.getSvgDataURL = function () { + if (!env.svgSupported) { + return; + } + + var zr = this._zr; + var list = zr.storage.getDisplayList(); + each(list, function (el) { + el.stopAnimation(null, true); + }); + return zr.painter.toDataURL(); + }; + + ECharts.prototype.getDataURL = function (opts) { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + opts = opts || {}; + var excludeComponents = opts.excludeComponents; + var ecModel = this._model; + var excludesComponentViews = []; + var self = this; + each$3(excludeComponents, function (componentType) { + ecModel.eachComponent({ + mainType: componentType + }, function (component) { + var view = self._componentsMap[component.__viewId]; + + if (!view.group.ignore) { + excludesComponentViews.push(view); + view.group.ignore = true; + } + }); + }); + var url = this._zr.painter.getType() === 'svg' ? this.getSvgDataURL() : this.getRenderedCanvas(opts).toDataURL('image/' + (opts && opts.type || 'png')); + each$3(excludesComponentViews, function (view) { + view.group.ignore = false; + }); + return url; + }; + + ECharts.prototype.getConnectedDataURL = function (opts) { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + if (!env.canvasSupported) { + return; + } + + var isSvg = opts.type === 'svg'; + var groupId = this.group; + var mathMin = Math.min; + var mathMax = Math.max; + var MAX_NUMBER = Infinity; + + if (connectedGroups[groupId]) { + var left_1 = MAX_NUMBER; + var top_1 = MAX_NUMBER; + var right_1 = -MAX_NUMBER; + var bottom_1 = -MAX_NUMBER; + var canvasList_1 = []; + var dpr_1 = opts && opts.pixelRatio || 1; + each(instances$1, function (chart, id) { + if (chart.group === groupId) { + var canvas = isSvg ? chart.getZr().painter.getSvgDom().innerHTML : chart.getRenderedCanvas(clone(opts)); + var boundingRect = chart.getDom().getBoundingClientRect(); + left_1 = mathMin(boundingRect.left, left_1); + top_1 = mathMin(boundingRect.top, top_1); + right_1 = mathMax(boundingRect.right, right_1); + bottom_1 = mathMax(boundingRect.bottom, bottom_1); + canvasList_1.push({ + dom: canvas, + left: boundingRect.left, + top: boundingRect.top + }); + } + }); + left_1 *= dpr_1; + top_1 *= dpr_1; + right_1 *= dpr_1; + bottom_1 *= dpr_1; + var width = right_1 - left_1; + var height = bottom_1 - top_1; + var targetCanvas = createCanvas(); + var zr_1 = init(targetCanvas, { + renderer: isSvg ? 'svg' : 'canvas' + }); + zr_1.resize({ + width: width, + height: height + }); + + if (isSvg) { + var content_1 = ''; + each$3(canvasList_1, function (item) { + var x = item.left - left_1; + var y = item.top - top_1; + content_1 += '' + item.dom + ''; + }); + zr_1.painter.getSvgRoot().innerHTML = content_1; + + if (opts.connectedBackgroundColor) { + zr_1.painter.setBackgroundColor(opts.connectedBackgroundColor); + } + + zr_1.refreshImmediately(); + return zr_1.painter.toDataURL(); + } else { + if (opts.connectedBackgroundColor) { + zr_1.add(new Rect({ + shape: { + x: 0, + y: 0, + width: width, + height: height + }, + style: { + fill: opts.connectedBackgroundColor + } + })); + } + + each$3(canvasList_1, function (item) { + var img = new ZRImage({ + style: { + x: item.left * dpr_1 - left_1, + y: item.top * dpr_1 - top_1, + image: item.dom + } + }); + zr_1.add(img); + }); + zr_1.refreshImmediately(); + return targetCanvas.toDataURL('image/' + (opts && opts.type || 'png')); + } + } else { + return this.getDataURL(opts); + } + }; + + ECharts.prototype.convertToPixel = function (finder, value) { + return doConvertPixel(this, 'convertToPixel', finder, value); + }; + + ECharts.prototype.convertFromPixel = function (finder, value) { + return doConvertPixel(this, 'convertFromPixel', finder, value); + }; + + ECharts.prototype.containPixel = function (finder, value) { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + var ecModel = this._model; + var result; + var findResult = parseFinder(ecModel, finder); + each(findResult, function (models, key) { + key.indexOf('Models') >= 0 && each(models, function (model) { + var coordSys = model.coordinateSystem; + + if (coordSys && coordSys.containPoint) { + result = result || !!coordSys.containPoint(value); + } else if (key === 'seriesModels') { + var view = this._chartsMap[model.__viewId]; + + if (view && view.containPoint) { + result = result || view.containPoint(value, model); + } else { + if ("development" !== 'production') { + console.warn(key + ': ' + (view ? 'The found component do not support containPoint.' : 'No view mapping to the found component.')); + } + } + } else { + if ("development" !== 'production') { + console.warn(key + ': containPoint is not supported'); + } + } + }, this); + }, this); + return !!result; + }; + + ECharts.prototype.getVisual = function (finder, visualType) { + var ecModel = this._model; + var parsedFinder = parseFinder(ecModel, finder, { + defaultMainType: 'series' + }); + var seriesModel = parsedFinder.seriesModel; + + if ("development" !== 'production') { + if (!seriesModel) { + console.warn('There is no specified seires model'); + } + } + + var data = seriesModel.getData(); + var dataIndexInside = parsedFinder.hasOwnProperty('dataIndexInside') ? parsedFinder.dataIndexInside : parsedFinder.hasOwnProperty('dataIndex') ? data.indexOfRawIndex(parsedFinder.dataIndex) : null; + return dataIndexInside != null ? getItemVisualFromData(data, dataIndexInside, visualType) : getVisualFromData(data, visualType); + }; + + ECharts.prototype.getViewOfComponentModel = function (componentModel) { + return this._componentsMap[componentModel.__viewId]; + }; + + ECharts.prototype.getViewOfSeriesModel = function (seriesModel) { + return this._chartsMap[seriesModel.__viewId]; + }; + + ECharts.prototype._initEvents = function () { + var _this = this; + + each$3(MOUSE_EVENT_NAMES, function (eveName) { + var handler = function (e) { + var ecModel = _this.getModel(); + + var el = e.target; + var params; + var isGlobalOut = eveName === 'globalout'; + + if (isGlobalOut) { + params = {}; + } else { + el && findEventDispatcher(el, function (parent) { + var ecData = getECData(parent); + + if (ecData && ecData.dataIndex != null) { + var dataModel = ecData.dataModel || ecModel.getSeriesByIndex(ecData.seriesIndex); + params = dataModel && dataModel.getDataParams(ecData.dataIndex, ecData.dataType) || {}; + return true; + } else if (ecData.eventData) { + params = extend({}, ecData.eventData); + return true; + } + }, true); + } + + if (params) { + var componentType = params.componentType; + var componentIndex = params.componentIndex; + + if (componentType === 'markLine' || componentType === 'markPoint' || componentType === 'markArea') { + componentType = 'series'; + componentIndex = params.seriesIndex; + } + + var model = componentType && componentIndex != null && ecModel.getComponent(componentType, componentIndex); + var view = model && _this[model.mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId]; + + if ("development" !== 'production') { + if (!isGlobalOut && !(model && view)) { + console.warn('model or view can not be found by params'); + } + } + + params.event = e; + params.type = eveName; + _this._$eventProcessor.eventInfo = { + targetEl: el, + packedEvent: params, + model: model, + view: view + }; + + _this.trigger(eveName, params); + } + }; + + handler.zrEventfulCallAtLast = true; + + _this._zr.on(eveName, handler, _this); + }); + each$3(eventActionMap, function (actionType, eventType) { + _this._messageCenter.on(eventType, function (event) { + this.trigger(eventType, event); + }, _this); + }); + each$3(['selectchanged'], function (eventType) { + _this._messageCenter.on(eventType, function (event) { + this.trigger(eventType, event); + }, _this); + }); + handleLegacySelectEvents(this._messageCenter, this, this._api); + }; + + ECharts.prototype.isDisposed = function () { + return this._disposed; + }; + + ECharts.prototype.clear = function () { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + this.setOption({ + series: [] + }, true); + }; + + ECharts.prototype.dispose = function () { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + this._disposed = true; + setAttribute(this.getDom(), DOM_ATTRIBUTE_KEY, ''); + var api = this._api; + var ecModel = this._model; + each$3(this._componentsViews, function (component) { + component.dispose(ecModel, api); + }); + each$3(this._chartsViews, function (chart) { + chart.dispose(ecModel, api); + }); + + this._zr.dispose(); + + delete instances$1[this.id]; + }; + + ECharts.prototype.resize = function (opts) { + if ("development" !== 'production') { + assert$1(!this[IN_MAIN_PROCESS_KEY], '`resize` should not be called during main process.'); + } + + if (this._disposed) { + disposedWarning(this.id); + return; + } + + this._zr.resize(opts); + + var ecModel = this._model; + this._loadingFX && this._loadingFX.resize(); + + if (!ecModel) { + return; + } + + var optionChanged = ecModel.resetOption('media'); + var silent = opts && opts.silent; + this[IN_MAIN_PROCESS_KEY] = true; + optionChanged && prepare(this); + updateMethods.update.call(this, { + type: 'resize', + animation: { + duration: 0 + } + }); + this[IN_MAIN_PROCESS_KEY] = false; + flushPendingActions.call(this, silent); + triggerUpdatedEvent.call(this, silent); + }; + + ECharts.prototype.showLoading = function (name, cfg) { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + if (isObject$2(name)) { + cfg = name; + name = ''; + } + + name = name || 'default'; + this.hideLoading(); + + if (!loadingEffects[name]) { + if ("development" !== 'production') { + console.warn('Loading effects ' + name + ' not exists.'); + } + + return; + } + + var el = loadingEffects[name](this._api, cfg); + var zr = this._zr; + this._loadingFX = el; + zr.add(el); + }; + + ECharts.prototype.hideLoading = function () { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + this._loadingFX && this._zr.remove(this._loadingFX); + this._loadingFX = null; + }; + + ECharts.prototype.makeActionFromEvent = function (eventObj) { + var payload = extend({}, eventObj); + payload.type = eventActionMap[eventObj.type]; + return payload; + }; + + ECharts.prototype.dispatchAction = function (payload, opt) { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + if (!isObject$2(opt)) { + opt = { + silent: !!opt + }; + } + + if (!actions[payload.type]) { + return; + } + + if (!this._model) { + return; + } + + if (this[IN_MAIN_PROCESS_KEY]) { + this._pendingActions.push(payload); + + return; + } + + var silent = opt.silent; + doDispatchAction.call(this, payload, silent); + var flush = opt.flush; + + if (flush) { + this._zr.flush(); + } else if (flush !== false && env.browser.weChat) { + this._throttledZrFlush(); + } + + flushPendingActions.call(this, silent); + triggerUpdatedEvent.call(this, silent); + }; + + ECharts.prototype.updateLabelLayout = function () { + var labelManager = this._labelManager; + labelManager.updateLayoutConfig(this._api); + labelManager.layout(this._api); + labelManager.processLabelsOverall(); + }; + + ECharts.prototype.appendData = function (params) { + if (this._disposed) { + disposedWarning(this.id); + return; + } + + var seriesIndex = params.seriesIndex; + var ecModel = this.getModel(); + var seriesModel = ecModel.getSeriesByIndex(seriesIndex); + + if ("development" !== 'production') { + assert$1(params.data && seriesModel); + } + + seriesModel.appendData(params); + this._scheduler.unfinished = true; + this.getZr().wakeUp(); + }; + + ECharts.internalField = function () { + prepare = function (ecIns) { + var scheduler = ecIns._scheduler; + scheduler.restorePipelines(ecIns._model); + scheduler.prepareStageTasks(); + prepareView(ecIns, true); + prepareView(ecIns, false); + scheduler.plan(); + }; + + prepareView = function (ecIns, isComponent) { + var ecModel = ecIns._model; + var scheduler = ecIns._scheduler; + var viewList = isComponent ? ecIns._componentsViews : ecIns._chartsViews; + var viewMap = isComponent ? ecIns._componentsMap : ecIns._chartsMap; + var zr = ecIns._zr; + var api = ecIns._api; + + for (var i = 0; i < viewList.length; i++) { + viewList[i].__alive = false; + } + + isComponent ? ecModel.eachComponent(function (componentType, model) { + componentType !== 'series' && doPrepare(model); + }) : ecModel.eachSeries(doPrepare); + + function doPrepare(model) { + var requireNewView = model.__requireNewView; + model.__requireNewView = false; + var viewId = '_ec_' + model.id + '_' + model.type; + var view = !requireNewView && viewMap[viewId]; + + if (!view) { + var classType = parseClassType(model.type); + var Clazz = isComponent ? ComponentView.getClass(classType.main, classType.sub) : ChartView.getClass(classType.sub); + + if ("development" !== 'production') { + assert$1(Clazz, classType.sub + ' does not exist.'); + } + + view = new Clazz(); + view.init(ecModel, api); + viewMap[viewId] = view; + viewList.push(view); + zr.add(view.group); + } + + model.__viewId = view.__id = viewId; + view.__alive = true; + view.__model = model; + view.group.__ecComponentInfo = { + mainType: model.mainType, + index: model.componentIndex + }; + !isComponent && scheduler.prepareView(view, model, ecModel, api); + } + + for (var i = 0; i < viewList.length;) { + var view = viewList[i]; + + if (!view.__alive) { + !isComponent && view.renderTask.dispose(); + zr.remove(view.group); + view.dispose(ecModel, api); + viewList.splice(i, 1); + + if (viewMap[view.__id] === view) { + delete viewMap[view.__id]; + } + + view.__id = view.group.__ecComponentInfo = null; + } else { + i++; + } + } + }; + + updateDirectly = function (ecIns, method, payload, mainType, subType) { + var ecModel = ecIns._model; + ecModel.setUpdatePayload(payload); + + if (!mainType) { + each$3([].concat(ecIns._componentsViews).concat(ecIns._chartsViews), callView); + return; + } + + var query = {}; + query[mainType + 'Id'] = payload[mainType + 'Id']; + query[mainType + 'Index'] = payload[mainType + 'Index']; + query[mainType + 'Name'] = payload[mainType + 'Name']; + var condition = { + mainType: mainType, + query: query + }; + subType && (condition.subType = subType); + var excludeSeriesId = payload.excludeSeriesId; + var excludeSeriesIdMap; + + if (excludeSeriesId != null) { + excludeSeriesIdMap = createHashMap(); + each$3(normalizeToArray(excludeSeriesId), function (id) { + var modelId = convertOptionIdName(id, null); + + if (modelId != null) { + excludeSeriesIdMap.set(modelId, true); + } + }); + } + + ecModel && ecModel.eachComponent(condition, function (model) { + if (!excludeSeriesIdMap || excludeSeriesIdMap.get(model.id) == null) { + if (isHighDownPayload(payload) && !payload.notBlur) { + if (model instanceof SeriesModel) { + toggleSeriesBlurStateFromPayload(model, payload, ecIns._api); + } + } else if (isSelectChangePayload(payload)) { + if (model instanceof SeriesModel) { + toggleSelectionFromPayload(model, payload, ecIns._api); + updateSeriesElementSelection(model); + markStatusToUpdate(ecIns); + } + } + + callView(ecIns[mainType === 'series' ? '_chartsMap' : '_componentsMap'][model.__viewId]); + } + }, ecIns); + + function callView(view) { + view && view.__alive && view[method] && view[method](view.__model, ecModel, ecIns._api, payload); + } + }; + + updateMethods = { + prepareAndUpdate: function (payload) { + prepare(this); + updateMethods.update.call(this, payload); + }, + update: function (payload) { + var ecModel = this._model; + var api = this._api; + var zr = this._zr; + var coordSysMgr = this._coordSysMgr; + var scheduler = this._scheduler; + + if (!ecModel) { + return; + } + + ecModel.setUpdatePayload(payload); + scheduler.restoreData(ecModel, payload); + scheduler.performSeriesTasks(ecModel); + coordSysMgr.create(ecModel, api); + scheduler.performDataProcessorTasks(ecModel, payload); + updateStreamModes(this, ecModel); + coordSysMgr.update(ecModel, api); + clearColorPalette(ecModel); + scheduler.performVisualTasks(ecModel, payload); + render(this, ecModel, api, payload); + var backgroundColor = ecModel.get('backgroundColor') || 'transparent'; + var darkMode = ecModel.get('darkMode'); + + if (!env.canvasSupported) { + var colorArr = parse(backgroundColor); + backgroundColor = stringify(colorArr, 'rgb'); + + if (colorArr[3] === 0) { + backgroundColor = 'transparent'; + } + } else { + zr.setBackgroundColor(backgroundColor); + + if (darkMode != null && darkMode !== 'auto') { + zr.setDarkMode(darkMode); + } + } + + performPostUpdateFuncs(ecModel, api); + }, + updateTransform: function (payload) { + var _this = this; + + var ecModel = this._model; + var api = this._api; + + if (!ecModel) { + return; + } + + ecModel.setUpdatePayload(payload); + var componentDirtyList = []; + ecModel.eachComponent(function (componentType, componentModel) { + if (componentType === 'series') { + return; + } + + var componentView = _this.getViewOfComponentModel(componentModel); + + if (componentView && componentView.__alive) { + if (componentView.updateTransform) { + var result = componentView.updateTransform(componentModel, ecModel, api, payload); + result && result.update && componentDirtyList.push(componentView); + } else { + componentDirtyList.push(componentView); + } + } + }); + var seriesDirtyMap = createHashMap(); + ecModel.eachSeries(function (seriesModel) { + var chartView = _this._chartsMap[seriesModel.__viewId]; + + if (chartView.updateTransform) { + var result = chartView.updateTransform(seriesModel, ecModel, api, payload); + result && result.update && seriesDirtyMap.set(seriesModel.uid, 1); + } else { + seriesDirtyMap.set(seriesModel.uid, 1); + } + }); + clearColorPalette(ecModel); + + this._scheduler.performVisualTasks(ecModel, payload, { + setDirty: true, + dirtyMap: seriesDirtyMap + }); + + renderSeries(this, ecModel, api, payload, seriesDirtyMap); + performPostUpdateFuncs(ecModel, this._api); + }, + updateView: function (payload) { + var ecModel = this._model; + + if (!ecModel) { + return; + } + + ecModel.setUpdatePayload(payload); + ChartView.markUpdateMethod(payload, 'updateView'); + clearColorPalette(ecModel); + + this._scheduler.performVisualTasks(ecModel, payload, { + setDirty: true + }); + + render(this, this._model, this._api, payload); + performPostUpdateFuncs(ecModel, this._api); + }, + updateVisual: function (payload) { + var _this = this; + + var ecModel = this._model; + + if (!ecModel) { + return; + } + + ecModel.setUpdatePayload(payload); + ecModel.eachSeries(function (seriesModel) { + seriesModel.getData().clearAllVisual(); + }); + ChartView.markUpdateMethod(payload, 'updateVisual'); + clearColorPalette(ecModel); + + this._scheduler.performVisualTasks(ecModel, payload, { + visualType: 'visual', + setDirty: true + }); + + ecModel.eachComponent(function (componentType, componentModel) { + if (componentType !== 'series') { + var componentView = _this.getViewOfComponentModel(componentModel); + + componentView && componentView.__alive && componentView.updateVisual(componentModel, ecModel, _this._api, payload); + } + }); + ecModel.eachSeries(function (seriesModel) { + var chartView = _this._chartsMap[seriesModel.__viewId]; + chartView.updateVisual(seriesModel, ecModel, _this._api, payload); + }); + performPostUpdateFuncs(ecModel, this._api); + }, + updateLayout: function (payload) { + updateMethods.update.call(this, payload); + } + }; + + doConvertPixel = function (ecIns, methodName, finder, value) { + if (ecIns._disposed) { + disposedWarning(ecIns.id); + return; + } + + var ecModel = ecIns._model; + + var coordSysList = ecIns._coordSysMgr.getCoordinateSystems(); + + var result; + var parsedFinder = parseFinder(ecModel, finder); + + for (var i = 0; i < coordSysList.length; i++) { + var coordSys = coordSysList[i]; + + if (coordSys[methodName] && (result = coordSys[methodName](ecModel, parsedFinder, value)) != null) { + return result; + } + } + + if ("development" !== 'production') { + console.warn('No coordinate system that supports ' + methodName + ' found by the given finder.'); + } + }; + + updateStreamModes = function (ecIns, ecModel) { + var chartsMap = ecIns._chartsMap; + var scheduler = ecIns._scheduler; + ecModel.eachSeries(function (seriesModel) { + scheduler.updateStreamModes(seriesModel, chartsMap[seriesModel.__viewId]); + }); + }; + + doDispatchAction = function (payload, silent) { + var _this = this; + + var ecModel = this.getModel(); + var payloadType = payload.type; + var escapeConnect = payload.escapeConnect; + var actionWrap = actions[payloadType]; + var actionInfo = actionWrap.actionInfo; + var cptTypeTmp = (actionInfo.update || 'update').split(':'); + var updateMethod = cptTypeTmp.pop(); + var cptType = cptTypeTmp[0] != null && parseClassType(cptTypeTmp[0]); + this[IN_MAIN_PROCESS_KEY] = true; + var payloads = [payload]; + var batched = false; + + if (payload.batch) { + batched = true; + payloads = map(payload.batch, function (item) { + item = defaults(extend({}, item), payload); + item.batch = null; + return item; + }); + } + + var eventObjBatch = []; + var eventObj; + var isSelectChange = isSelectChangePayload(payload); + var isStatusChange = isHighDownPayload(payload) || isSelectChange; + each$3(payloads, function (batchItem) { + eventObj = actionWrap.action(batchItem, _this._model, _this._api); + eventObj = eventObj || extend({}, batchItem); + eventObj.type = actionInfo.event || eventObj.type; + eventObjBatch.push(eventObj); + + if (isStatusChange) { + updateDirectly(_this, updateMethod, batchItem, 'series'); + markStatusToUpdate(_this); + } else if (cptType) { + updateDirectly(_this, updateMethod, batchItem, cptType.main, cptType.sub); + } + }); + + if (updateMethod !== 'none' && !isStatusChange && !cptType) { + if (this[OPTION_UPDATED_KEY]) { + prepare(this); + updateMethods.update.call(this, payload); + this[OPTION_UPDATED_KEY] = false; + } else { + updateMethods[updateMethod].call(this, payload); + } + } + + if (batched) { + eventObj = { + type: actionInfo.event || payloadType, + escapeConnect: escapeConnect, + batch: eventObjBatch + }; + } else { + eventObj = eventObjBatch[0]; + } + + this[IN_MAIN_PROCESS_KEY] = false; + + if (!silent) { + var messageCenter = this._messageCenter; + messageCenter.trigger(eventObj.type, eventObj); + + if (isSelectChange) { + var newObj = { + type: 'selectchanged', + escapeConnect: escapeConnect, + selected: getAllSelectedIndices(ecModel), + isFromClick: payload.isFromClick || false, + fromAction: payload.type, + fromActionPayload: payload + }; + messageCenter.trigger(newObj.type, newObj); + } + } + }; + + flushPendingActions = function (silent) { + var pendingActions = this._pendingActions; + + while (pendingActions.length) { + var payload = pendingActions.shift(); + doDispatchAction.call(this, payload, silent); + } + }; + + triggerUpdatedEvent = function (silent) { + !silent && this.trigger('updated'); + }; + + bindRenderedEvent = function (zr, ecIns) { + zr.on('rendered', function (params) { + ecIns.trigger('rendered', params); + + if (zr.animation.isFinished() && !ecIns[OPTION_UPDATED_KEY] && !ecIns._scheduler.unfinished && !ecIns._pendingActions.length) { + ecIns.trigger('finished'); + } + }); + }; + + bindMouseEvent = function (zr, ecIns) { + zr.on('mouseover', function (e) { + var el = e.target; + var dispatcher = findEventDispatcher(el, isHighDownDispatcher); + + if (dispatcher) { + var ecData = getECData(dispatcher); + toggleSeriesBlurState(ecData.seriesIndex, ecData.focus, ecData.blurScope, ecIns._api, true); + enterEmphasisWhenMouseOver(dispatcher, e); + markStatusToUpdate(ecIns); + } + }).on('mouseout', function (e) { + var el = e.target; + var dispatcher = findEventDispatcher(el, isHighDownDispatcher); + + if (dispatcher) { + var ecData = getECData(dispatcher); + toggleSeriesBlurState(ecData.seriesIndex, ecData.focus, ecData.blurScope, ecIns._api, false); + leaveEmphasisWhenMouseOut(dispatcher, e); + markStatusToUpdate(ecIns); + } + }).on('click', function (e) { + var el = e.target; + var dispatcher = findEventDispatcher(el, function (target) { + return getECData(target).dataIndex != null; + }, true); + + if (dispatcher) { + var actionType = dispatcher.selected ? 'unselect' : 'select'; + var ecData = getECData(dispatcher); + + ecIns._api.dispatchAction({ + type: actionType, + dataType: ecData.dataType, + dataIndexInside: ecData.dataIndex, + seriesIndex: ecData.seriesIndex, + isFromClick: true + }); + } + }); + }; + + clearColorPalette = function (ecModel) { + ecModel.clearColorPalette(); + ecModel.eachSeries(function (seriesModel) { + seriesModel.clearColorPalette(); + }); + }; + + render = function (ecIns, ecModel, api, payload) { + renderComponents(ecIns, ecModel, api, payload); + each$3(ecIns._chartsViews, function (chart) { + chart.__alive = false; + }); + renderSeries(ecIns, ecModel, api, payload); + each$3(ecIns._chartsViews, function (chart) { + if (!chart.__alive) { + chart.remove(ecModel, api); + } + }); + }; + + renderComponents = function (ecIns, ecModel, api, payload, dirtyList) { + each$3(dirtyList || ecIns._componentsViews, function (componentView) { + var componentModel = componentView.__model; + clearStates(componentModel, componentView); + componentView.render(componentModel, ecModel, api, payload); + updateZ(componentModel, componentView); + updateStates(componentModel, componentView); + }); + }; + + renderSeries = function (ecIns, ecModel, api, payload, dirtyMap) { + var scheduler = ecIns._scheduler; + var labelManager = ecIns._labelManager; + labelManager.clearLabels(); + var unfinished = false; + ecModel.eachSeries(function (seriesModel) { + var chartView = ecIns._chartsMap[seriesModel.__viewId]; + chartView.__alive = true; + var renderTask = chartView.renderTask; + scheduler.updatePayload(renderTask, payload); + clearStates(seriesModel, chartView); + + if (dirtyMap && dirtyMap.get(seriesModel.uid)) { + renderTask.dirty(); + } + + if (renderTask.perform(scheduler.getPerformArgs(renderTask))) { + unfinished = true; + } + + seriesModel.__transientTransitionOpt = null; + chartView.group.silent = !!seriesModel.get('silent'); + updateBlend(seriesModel, chartView); + updateSeriesElementSelection(seriesModel); + labelManager.addLabelsOfSeries(chartView); + }); + scheduler.unfinished = unfinished || scheduler.unfinished; + labelManager.updateLayoutConfig(api); + labelManager.layout(api); + labelManager.processLabelsOverall(); + ecModel.eachSeries(function (seriesModel) { + var chartView = ecIns._chartsMap[seriesModel.__viewId]; + updateZ(seriesModel, chartView); + updateStates(seriesModel, chartView); + }); + updateHoverLayerStatus(ecIns, ecModel); + }; + + performPostUpdateFuncs = function (ecModel, api) { + each$3(postUpdateFuncs, function (func) { + func(ecModel, api); + }); + }; + + markStatusToUpdate = function (ecIns) { + ecIns[STATUS_NEEDS_UPDATE_KEY] = true; + ecIns.getZr().wakeUp(); + }; + + applyChangedStates = function (ecIns) { + if (!ecIns[STATUS_NEEDS_UPDATE_KEY]) { + return; + } + + ecIns.getZr().storage.traverse(function (el) { + if (isElementRemoved(el)) { + return; + } + + applyElementStates(el); + }); + ecIns[STATUS_NEEDS_UPDATE_KEY] = false; + }; + + function applyElementStates(el) { + var newStates = []; + var oldStates = el.currentStates; + + for (var i = 0; i < oldStates.length; i++) { + var stateName = oldStates[i]; + + if (!(stateName === 'emphasis' || stateName === 'blur' || stateName === 'select')) { + newStates.push(stateName); + } + } + + if (el.selected && el.states.select) { + newStates.push('select'); + } + + if (el.hoverState === HOVER_STATE_EMPHASIS && el.states.emphasis) { + newStates.push('emphasis'); + } else if (el.hoverState === HOVER_STATE_BLUR && el.states.blur) { + newStates.push('blur'); + } + + el.useStates(newStates); + } + + function updateHoverLayerStatus(ecIns, ecModel) { + var zr = ecIns._zr; + var storage = zr.storage; + var elCount = 0; + storage.traverse(function (el) { + if (!el.isGroup) { + elCount++; + } + }); + + if (elCount > ecModel.get('hoverLayerThreshold') && !env.node && !env.worker) { + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.preventUsingHoverLayer) { + return; + } + + var chartView = ecIns._chartsMap[seriesModel.__viewId]; + + if (chartView.__alive) { + chartView.group.traverse(function (el) { + if (el.states.emphasis) { + el.states.emphasis.hoverLayer = true; + } + }); + } + }); + } + } + + function updateBlend(seriesModel, chartView) { + var blendMode = seriesModel.get('blendMode') || null; + + if ("development" !== 'production') { + if (!env.canvasSupported && blendMode && blendMode !== 'source-over') { + console.warn('Only canvas support blendMode'); + } + } + + chartView.group.traverse(function (el) { + if (!el.isGroup) { + el.style.blend = blendMode; + } + + if (el.eachPendingDisplayable) { + el.eachPendingDisplayable(function (displayable) { + displayable.style.blend = blendMode; + }); + } + }); + } + + function updateZ(model, view) { + if (model.preventAutoZ) { + return; + } + + var z = model.get('z'); + var zlevel = model.get('zlevel'); + view.group.traverse(function (el) { + if (!el.isGroup) { + z != null && (el.z = z); + zlevel != null && (el.zlevel = zlevel); + var label = el.getTextContent(); + var labelLine = el.getTextGuideLine(); + + if (label) { + label.z = el.z; + label.zlevel = el.zlevel; + label.z2 = el.z2 + 2; + } + + if (labelLine) { + var showAbove = el.textGuideLineConfig && el.textGuideLineConfig.showAbove; + labelLine.z = el.z; + labelLine.zlevel = el.zlevel; + labelLine.z2 = el.z2 + (showAbove ? 1 : -1); + } + } + }); + } + + function clearStates(model, view) { + view.group.traverse(function (el) { + if (isElementRemoved(el)) { + return; + } + + var textContent = el.getTextContent(); + var textGuide = el.getTextGuideLine(); + + if (el.stateTransition) { + el.stateTransition = null; + } + + if (textContent && textContent.stateTransition) { + textContent.stateTransition = null; + } + + if (textGuide && textGuide.stateTransition) { + textGuide.stateTransition = null; + } + + if (el.hasState()) { + el.prevStates = el.currentStates; + el.clearStates(); + } else if (el.prevStates) { + el.prevStates = null; + } + }); + } + + function updateStates(model, view) { + var stateAnimationModel = model.getModel('stateAnimation'); + var enableAnimation = model.isAnimationEnabled(); + var duration = stateAnimationModel.get('duration'); + var stateTransition = duration > 0 ? { + duration: duration, + delay: stateAnimationModel.get('delay'), + easing: stateAnimationModel.get('easing') + } : null; + view.group.traverse(function (el) { + if (el.states && el.states.emphasis) { + if (isElementRemoved(el)) { + return; + } + + if (el instanceof Path) { + savePathStates(el); + } + + if (el.__dirty) { + var prevStates = el.prevStates; + + if (prevStates) { + el.useStates(prevStates); + } + } + + if (enableAnimation) { + el.stateTransition = stateTransition; + var textContent = el.getTextContent(); + var textGuide = el.getTextGuideLine(); + + if (textContent) { + textContent.stateTransition = stateTransition; + } + + if (textGuide) { + textGuide.stateTransition = stateTransition; + } + } + + if (el.__dirty) { + applyElementStates(el); + } + } + }); + } + + createExtensionAPI = function (ecIns) { + return new (function (_super) { + __extends(class_1, _super); + + function class_1() { + return _super !== null && _super.apply(this, arguments) || this; + } + + class_1.prototype.getCoordinateSystems = function () { + return ecIns._coordSysMgr.getCoordinateSystems(); + }; + + class_1.prototype.getComponentByElement = function (el) { + while (el) { + var modelInfo = el.__ecComponentInfo; + + if (modelInfo != null) { + return ecIns._model.getComponent(modelInfo.mainType, modelInfo.index); + } + + el = el.parent; + } + }; + + class_1.prototype.enterEmphasis = function (el, highlightDigit) { + enterEmphasis(el, highlightDigit); + markStatusToUpdate(ecIns); + }; + + class_1.prototype.leaveEmphasis = function (el, highlightDigit) { + leaveEmphasis(el, highlightDigit); + markStatusToUpdate(ecIns); + }; + + class_1.prototype.enterBlur = function (el) { + enterBlur(el); + markStatusToUpdate(ecIns); + }; + + class_1.prototype.leaveBlur = function (el) { + leaveBlur(el); + markStatusToUpdate(ecIns); + }; + + class_1.prototype.enterSelect = function (el) { + enterSelect(el); + markStatusToUpdate(ecIns); + }; + + class_1.prototype.leaveSelect = function (el) { + leaveSelect(el); + markStatusToUpdate(ecIns); + }; + + class_1.prototype.getModel = function () { + return ecIns.getModel(); + }; + + class_1.prototype.getViewOfComponentModel = function (componentModel) { + return ecIns.getViewOfComponentModel(componentModel); + }; + + class_1.prototype.getViewOfSeriesModel = function (seriesModel) { + return ecIns.getViewOfSeriesModel(seriesModel); + }; + + return class_1; + }(ExtensionAPI))(ecIns); + }; + + enableConnect = function (chart) { + function updateConnectedChartsStatus(charts, status) { + for (var i = 0; i < charts.length; i++) { + var otherChart = charts[i]; + otherChart[CONNECT_STATUS_KEY] = status; + } + } + + each$3(eventActionMap, function (actionType, eventType) { + chart._messageCenter.on(eventType, function (event) { + if (connectedGroups[chart.group] && chart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_PENDING) { + if (event && event.escapeConnect) { + return; + } + + var action_1 = chart.makeActionFromEvent(event); + var otherCharts_1 = []; + each$3(instances$1, function (otherChart) { + if (otherChart !== chart && otherChart.group === chart.group) { + otherCharts_1.push(otherChart); + } + }); + updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_PENDING); + each$3(otherCharts_1, function (otherChart) { + if (otherChart[CONNECT_STATUS_KEY] !== CONNECT_STATUS_UPDATING) { + otherChart.dispatchAction(action_1); + } + }); + updateConnectedChartsStatus(otherCharts_1, CONNECT_STATUS_UPDATED); + } + }); + }); + }; + + setTransitionOpt = function (chart, transitionOpt) { + var ecModel = chart._model; + each(normalizeToArray(transitionOpt), function (transOpt) { + var errMsg; + var fromOpt = transOpt.from; + var toOpt = transOpt.to; + + if (toOpt == null) { + if ("development" !== 'production') { + errMsg = '`transition.to` must be specified.'; + } + + throwError(errMsg); + } + + var finderOpt = { + includeMainTypes: ['series'], + enableAll: false, + enableNone: false + }; + var fromResult = fromOpt ? parseFinder(ecModel, fromOpt, finderOpt) : null; + var toResult = parseFinder(ecModel, toOpt, finderOpt); + var toSeries = toResult.seriesModel; + + if (toSeries == null) { + errMsg = ''; + + if ("development" !== 'production') { + errMsg = '`transition` is only supported on series.'; + } + } + + if (fromResult && fromResult.seriesModel !== toSeries) { + errMsg = ''; + + if ("development" !== 'production') { + errMsg = '`transition.from` and `transition.to` must be specified to the same series.'; + } + } + + if (errMsg != null) { + throwError(errMsg); + } + + toSeries.__transientTransitionOpt = { + from: fromOpt ? fromOpt.dimension : null, + to: toOpt.dimension, + dividingMethod: transOpt.dividingMethod + }; + }); + }; + }(); + + return ECharts; + }(Eventful); + + var echartsProto = ECharts.prototype; + echartsProto.on = createRegisterEventWithLowercaseECharts('on'); + echartsProto.off = createRegisterEventWithLowercaseECharts('off'); + + echartsProto.one = function (eventName, cb, ctx) { + var self = this; + deprecateLog('ECharts#one is deprecated.'); + + function wrapped() { + var args2 = []; + + for (var _i = 0; _i < arguments.length; _i++) { + args2[_i] = arguments[_i]; + } + + cb && cb.apply && cb.apply(this, args2); + self.off(eventName, wrapped); + } + this.on.call(this, eventName, wrapped, ctx); + }; + + var MOUSE_EVENT_NAMES = ['click', 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mousedown', 'mouseup', 'globalout', 'contextmenu']; + + function disposedWarning(id) { + if ("development" !== 'production') { + console.warn('Instance ' + id + ' has been disposed'); + } + } + + var actions = {}; + var eventActionMap = {}; + var dataProcessorFuncs = []; + var optionPreprocessorFuncs = []; + var postInitFuncs = []; + var postUpdateFuncs = []; + var visualFuncs = []; + var themeStorage = {}; + var loadingEffects = {}; + var instances$1 = {}; + var connectedGroups = {}; + var idBase = +new Date() - 0; + var groupIdBase = +new Date() - 0; + var DOM_ATTRIBUTE_KEY = '_echarts_instance_'; + function init$1(dom, theme, opts) { + if ("development" !== 'production') { + if (!dom) { + throw new Error('Initialize failed: invalid dom.'); + } + } + + var existInstance = getInstanceByDom(dom); + + if (existInstance) { + if ("development" !== 'production') { + console.warn('There is a chart instance already initialized on the dom.'); + } + + return existInstance; + } + + if ("development" !== 'production') { + if (isDom(dom) && dom.nodeName.toUpperCase() !== 'CANVAS' && (!dom.clientWidth && (!opts || opts.width == null) || !dom.clientHeight && (!opts || opts.height == null))) { + console.warn('Can\'t get DOM width or height. Please check ' + 'dom.clientWidth and dom.clientHeight. They should not be 0.' + 'For example, you may need to call this in the callback ' + 'of window.onload.'); + } + } + + var chart = new ECharts(dom, theme, opts); + chart.id = 'ec_' + idBase++; + instances$1[chart.id] = chart; + setAttribute(dom, DOM_ATTRIBUTE_KEY, chart.id); + enableConnect(chart); + each$3(postInitFuncs, function (postInitFunc) { + postInitFunc(chart); + }); + return chart; + } + function connect(groupId) { + if (isArray(groupId)) { + var charts = groupId; + groupId = null; + each$3(charts, function (chart) { + if (chart.group != null) { + groupId = chart.group; + } + }); + groupId = groupId || 'g_' + groupIdBase++; + each$3(charts, function (chart) { + chart.group = groupId; + }); + } + + connectedGroups[groupId] = true; + return groupId; + } + function disConnect(groupId) { + connectedGroups[groupId] = false; + } + var disconnect = disConnect; + function dispose$1(chart) { + if (typeof chart === 'string') { + chart = instances$1[chart]; + } else if (!(chart instanceof ECharts)) { + chart = getInstanceByDom(chart); + } + + if (chart instanceof ECharts && !chart.isDisposed()) { + chart.dispose(); + } + } + function getInstanceByDom(dom) { + return instances$1[getAttribute(dom, DOM_ATTRIBUTE_KEY)]; + } + function getInstanceById(key) { + return instances$1[key]; + } + function registerTheme(name, theme) { + themeStorage[name] = theme; + } + function registerPreprocessor(preprocessorFunc) { + if (indexOf$1(optionPreprocessorFuncs, preprocessorFunc) < 0) { + optionPreprocessorFuncs.push(preprocessorFunc); + } + } + function registerProcessor(priority, processor) { + normalizeRegister(dataProcessorFuncs, priority, processor, PRIORITY_PROCESSOR_DEFAULT); + } + function registerPostInit(postInitFunc) { + if (indexOf$1(postInitFuncs, postInitFunc) < 0) { + postInitFunc && postInitFuncs.push(postInitFunc); + } + } + function registerPostUpdate(postUpdateFunc) { + if (indexOf$1(postUpdateFuncs, postUpdateFunc) < 0) { + postUpdateFunc && postUpdateFuncs.push(postUpdateFunc); + } + } + function registerAction(actionInfo, eventName, action) { + if (typeof eventName === 'function') { + action = eventName; + eventName = ''; + } + + var actionType = isObject$2(actionInfo) ? actionInfo.type : [actionInfo, actionInfo = { + event: eventName + }][0]; + actionInfo.event = (actionInfo.event || actionType).toLowerCase(); + eventName = actionInfo.event; + + if (eventActionMap[eventName]) { + return; + } + + assert$1(ACTION_REG.test(actionType) && ACTION_REG.test(eventName)); + + if (!actions[actionType]) { + actions[actionType] = { + action: action, + actionInfo: actionInfo + }; + } + + eventActionMap[eventName] = actionType; + } + function registerCoordinateSystem(type, coordSysCreator) { + CoordinateSystemManager.register(type, coordSysCreator); + } + function getCoordinateSystemDimensions(type) { + var coordSysCreator = CoordinateSystemManager.get(type); + + if (coordSysCreator) { + return coordSysCreator.getDimensionsInfo ? coordSysCreator.getDimensionsInfo() : coordSysCreator.dimensions.slice(); + } + } + + function registerLayout(priority, layoutTask) { + normalizeRegister(visualFuncs, priority, layoutTask, PRIORITY_VISUAL_LAYOUT, 'layout'); + } + + function registerVisual(priority, visualTask) { + normalizeRegister(visualFuncs, priority, visualTask, PRIORITY_VISUAL_CHART, 'visual'); + } + var registeredTasks = []; + + function normalizeRegister(targetList, priority, fn, defaultPriority, visualType) { + if (isFunction$1(priority) || isObject$2(priority)) { + fn = priority; + priority = defaultPriority; + } + + if ("development" !== 'production') { + if (isNaN(priority) || priority == null) { + throw new Error('Illegal priority'); + } + + each$3(targetList, function (wrap) { + assert$1(wrap.__raw !== fn); + }); + } + + if (indexOf$1(registeredTasks, fn) >= 0) { + return; + } + + registeredTasks.push(fn); + var stageHandler = Scheduler.wrapStageHandler(fn, visualType); + stageHandler.__prio = priority; + stageHandler.__raw = fn; + targetList.push(stageHandler); + } + + function registerLoading(name, loadingFx) { + loadingEffects[name] = loadingFx; + } + function setCanvasCreator(creator) { + $override('createCanvas', creator); + } + function registerMap(mapName, geoJson, specialAreas) { + mapDataStorage.registerMap(mapName, geoJson, specialAreas); + } + function getMap(mapName) { + var records = mapDataStorage.retrieveMap(mapName); + return records && records[0] && { + geoJson: records[0].geoJSON, + specialAreas: records[0].specialAreas + }; + } + var registerTransform = registerExternalTransform; + registerVisual(PRIORITY_VISUAL_GLOBAL, seriesStyleTask); + registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataStyleTask); + registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataColorPaletteTask); + registerVisual(PRIORITY_VISUAL_GLOBAL, seriesSymbolTask); + registerVisual(PRIORITY_VISUAL_CHART_DATA_CUSTOM, dataSymbolTask); + registerVisual(PRIORITY_VISUAL_DECAL, decalVisual); + registerPreprocessor(globalBackwardCompat); + registerProcessor(PRIORITY_PROCESSOR_DATASTACK, dataStack); + registerLoading('default', defaultLoading); + registerAction({ + type: HIGHLIGHT_ACTION_TYPE, + event: HIGHLIGHT_ACTION_TYPE, + update: HIGHLIGHT_ACTION_TYPE + }, noop); + registerAction({ + type: DOWNPLAY_ACTION_TYPE, + event: DOWNPLAY_ACTION_TYPE, + update: DOWNPLAY_ACTION_TYPE + }, noop); + registerAction({ + type: SELECT_ACTION_TYPE, + event: SELECT_ACTION_TYPE, + update: SELECT_ACTION_TYPE + }, noop); + registerAction({ + type: UNSELECT_ACTION_TYPE, + event: UNSELECT_ACTION_TYPE, + update: UNSELECT_ACTION_TYPE + }, noop); + registerAction({ + type: TOGGLE_SELECT_ACTION_TYPE, + event: TOGGLE_SELECT_ACTION_TYPE, + update: TOGGLE_SELECT_ACTION_TYPE + }, noop); + registerTheme('light', lightTheme); + registerTheme('dark', theme); + var dataTool = {}; + + var extensions = []; + var extensionRegisters = { + registerPreprocessor: registerPreprocessor, + registerProcessor: registerProcessor, + registerPostInit: registerPostInit, + registerPostUpdate: registerPostUpdate, + registerAction: registerAction, + registerCoordinateSystem: registerCoordinateSystem, + registerLayout: registerLayout, + registerVisual: registerVisual, + registerTransform: registerTransform, + registerLoading: registerLoading, + registerMap: registerMap, + PRIORITY: PRIORITY, + ComponentModel: ComponentModel, + ComponentView: ComponentView, + SeriesModel: SeriesModel, + ChartView: ChartView, + registerComponentModel: function (ComponentModelClass) { + ComponentModel.registerClass(ComponentModelClass); + }, + registerComponentView: function (ComponentViewClass) { + ComponentView.registerClass(ComponentViewClass); + }, + registerSeriesModel: function (SeriesModelClass) { + SeriesModel.registerClass(SeriesModelClass); + }, + registerChartView: function (ChartViewClass) { + ChartView.registerClass(ChartViewClass); + }, + registerSubTypeDefaulter: function (componentType, defaulter) { + ComponentModel.registerSubTypeDefaulter(componentType, defaulter); + }, + registerPainter: function (painterType, PainterCtor) { + registerPainter(painterType, PainterCtor); + } + }; + function use(ext) { + if (isArray(ext)) { + each(ext, function (singleExt) { + use(singleExt); + }); + return; + } + + if (indexOf(extensions, ext) >= 0) { + return; + } + + extensions.push(ext); + + if (isFunction(ext)) { + ext = { + install: ext + }; + } + + ext.install(extensionRegisters); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function dataIndexMapValueLength(valNumOrArrLengthMoreThan2) { + return valNumOrArrLengthMoreThan2 == null ? 0 : valNumOrArrLengthMoreThan2.length || 1; + } + + function defaultKeyGetter(item) { + return item; + } + + var DataDiffer = function () { + function DataDiffer(oldArr, newArr, oldKeyGetter, newKeyGetter, context, diffMode) { + this._old = oldArr; + this._new = newArr; + this._oldKeyGetter = oldKeyGetter || defaultKeyGetter; + this._newKeyGetter = newKeyGetter || defaultKeyGetter; + this.context = context; + this._diffModeMultiple = diffMode === 'multiple'; + } + + DataDiffer.prototype.add = function (func) { + this._add = func; + return this; + }; + + DataDiffer.prototype.update = function (func) { + this._update = func; + return this; + }; + + DataDiffer.prototype.updateManyToOne = function (func) { + this._updateManyToOne = func; + return this; + }; + + DataDiffer.prototype.updateOneToMany = function (func) { + this._updateOneToMany = func; + return this; + }; + + DataDiffer.prototype.remove = function (func) { + this._remove = func; + return this; + }; + + DataDiffer.prototype.execute = function () { + this[this._diffModeMultiple ? '_executeMultiple' : '_executeOneToOne'](); + }; + + DataDiffer.prototype._executeOneToOne = function () { + var oldArr = this._old; + var newArr = this._new; + var newDataIndexMap = {}; + var oldDataKeyArr = new Array(oldArr.length); + var newDataKeyArr = new Array(newArr.length); + + this._initIndexMap(oldArr, null, oldDataKeyArr, '_oldKeyGetter'); + + this._initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter'); + + for (var i = 0; i < oldArr.length; i++) { + var oldKey = oldDataKeyArr[i]; + var newIdxMapVal = newDataIndexMap[oldKey]; + var newIdxMapValLen = dataIndexMapValueLength(newIdxMapVal); + + if (newIdxMapValLen > 1) { + var newIdx = newIdxMapVal.shift(); + + if (newIdxMapVal.length === 1) { + newDataIndexMap[oldKey] = newIdxMapVal[0]; + } + + this._update && this._update(newIdx, i); + } else if (newIdxMapValLen === 1) { + newDataIndexMap[oldKey] = null; + this._update && this._update(newIdxMapVal, i); + } else { + this._remove && this._remove(i); + } + } + + this._performRestAdd(newDataKeyArr, newDataIndexMap); + }; + + DataDiffer.prototype._executeMultiple = function () { + var oldArr = this._old; + var newArr = this._new; + var oldDataIndexMap = {}; + var newDataIndexMap = {}; + var oldDataKeyArr = []; + var newDataKeyArr = []; + + this._initIndexMap(oldArr, oldDataIndexMap, oldDataKeyArr, '_oldKeyGetter'); + + this._initIndexMap(newArr, newDataIndexMap, newDataKeyArr, '_newKeyGetter'); + + for (var i = 0; i < oldDataKeyArr.length; i++) { + var oldKey = oldDataKeyArr[i]; + var oldIdxMapVal = oldDataIndexMap[oldKey]; + var newIdxMapVal = newDataIndexMap[oldKey]; + var oldIdxMapValLen = dataIndexMapValueLength(oldIdxMapVal); + var newIdxMapValLen = dataIndexMapValueLength(newIdxMapVal); + + if (oldIdxMapValLen > 1 && newIdxMapValLen === 1) { + this._updateManyToOne && this._updateManyToOne(newIdxMapVal, oldIdxMapVal); + newDataIndexMap[oldKey] = null; + } else if (oldIdxMapValLen === 1 && newIdxMapValLen > 1) { + this._updateOneToMany && this._updateOneToMany(newIdxMapVal, oldIdxMapVal); + newDataIndexMap[oldKey] = null; + } else if (oldIdxMapValLen === 1 && newIdxMapValLen === 1) { + this._update && this._update(newIdxMapVal, oldIdxMapVal); + newDataIndexMap[oldKey] = null; + } else if (oldIdxMapValLen > 1) { + for (var i_1 = 0; i_1 < oldIdxMapValLen; i_1++) { + this._remove && this._remove(oldIdxMapVal[i_1]); + } + } else { + this._remove && this._remove(oldIdxMapVal); + } + } + + this._performRestAdd(newDataKeyArr, newDataIndexMap); + }; + + DataDiffer.prototype._performRestAdd = function (newDataKeyArr, newDataIndexMap) { + for (var i = 0; i < newDataKeyArr.length; i++) { + var newKey = newDataKeyArr[i]; + var newIdxMapVal = newDataIndexMap[newKey]; + var idxMapValLen = dataIndexMapValueLength(newIdxMapVal); + + if (idxMapValLen > 1) { + for (var j = 0; j < idxMapValLen; j++) { + this._add && this._add(newIdxMapVal[j]); + } + } else if (idxMapValLen === 1) { + this._add && this._add(newIdxMapVal); + } + + newDataIndexMap[newKey] = null; + } + }; + + DataDiffer.prototype._initIndexMap = function (arr, map, keyArr, keyGetterName) { + var cbModeMultiple = this._diffModeMultiple; + + for (var i = 0; i < arr.length; i++) { + var key = '_ec_' + this[keyGetterName](arr[i], i); + + if (!cbModeMultiple) { + keyArr[i] = key; + } + + if (!map) { + continue; + } + + var idxMapVal = map[key]; + var idxMapValLen = dataIndexMapValueLength(idxMapVal); + + if (idxMapValLen === 0) { + map[key] = i; + + if (cbModeMultiple) { + keyArr.push(key); + } + } else if (idxMapValLen === 1) { + map[key] = [idxMapVal, i]; + } else { + idxMapVal.push(i); + } + } + }; + + return DataDiffer; + }(); + + function summarizeDimensions(data) { + var summary = {}; + var encode = summary.encode = {}; + var notExtraCoordDimMap = createHashMap(); + var defaultedLabel = []; + var defaultedTooltip = []; + var userOutput = summary.userOutput = { + dimensionNames: data.dimensions.slice(), + encode: {} + }; + each(data.dimensions, function (dimName) { + var dimItem = data.getDimensionInfo(dimName); + var coordDim = dimItem.coordDim; + + if (coordDim) { + if ("development" !== 'production') { + assert(VISUAL_DIMENSIONS.get(coordDim) == null); + } + + var coordDimIndex = dimItem.coordDimIndex; + getOrCreateEncodeArr(encode, coordDim)[coordDimIndex] = dimName; + + if (!dimItem.isExtraCoord) { + notExtraCoordDimMap.set(coordDim, 1); + + if (mayLabelDimType(dimItem.type)) { + defaultedLabel[0] = dimName; + } + + getOrCreateEncodeArr(userOutput.encode, coordDim)[coordDimIndex] = dimItem.index; + } + + if (dimItem.defaultTooltip) { + defaultedTooltip.push(dimName); + } + } + + VISUAL_DIMENSIONS.each(function (v, otherDim) { + var encodeArr = getOrCreateEncodeArr(encode, otherDim); + var dimIndex = dimItem.otherDims[otherDim]; + + if (dimIndex != null && dimIndex !== false) { + encodeArr[dimIndex] = dimItem.name; + } + }); + }); + var dataDimsOnCoord = []; + var encodeFirstDimNotExtra = {}; + notExtraCoordDimMap.each(function (v, coordDim) { + var dimArr = encode[coordDim]; + encodeFirstDimNotExtra[coordDim] = dimArr[0]; + dataDimsOnCoord = dataDimsOnCoord.concat(dimArr); + }); + summary.dataDimsOnCoord = dataDimsOnCoord; + summary.encodeFirstDimNotExtra = encodeFirstDimNotExtra; + var encodeLabel = encode.label; + + if (encodeLabel && encodeLabel.length) { + defaultedLabel = encodeLabel.slice(); + } + + var encodeTooltip = encode.tooltip; + + if (encodeTooltip && encodeTooltip.length) { + defaultedTooltip = encodeTooltip.slice(); + } else if (!defaultedTooltip.length) { + defaultedTooltip = defaultedLabel.slice(); + } + + encode.defaultedLabel = defaultedLabel; + encode.defaultedTooltip = defaultedTooltip; + return summary; + } + + function getOrCreateEncodeArr(encode, dim) { + if (!encode.hasOwnProperty(dim)) { + encode[dim] = []; + } + + return encode[dim]; + } + + function getDimensionTypeByAxis(axisType) { + return axisType === 'category' ? 'ordinal' : axisType === 'time' ? 'time' : 'float'; + } + + function mayLabelDimType(dimType) { + return !(dimType === 'ordinal' || dimType === 'time'); + } + + var DataDimensionInfo = function () { + function DataDimensionInfo(opt) { + this.otherDims = {}; + + if (opt != null) { + extend(this, opt); + } + } + + return DataDimensionInfo; + }(); + + var mathFloor = Math.floor; + var isObject$3 = isObject; + var map$1 = map; + var UNDEFINED = 'undefined'; + var INDEX_NOT_FOUND = -1; + var ID_PREFIX = 'e\0\0'; + var dataCtors = { + 'float': typeof Float64Array === UNDEFINED ? Array : Float64Array, + 'int': typeof Int32Array === UNDEFINED ? Array : Int32Array, + 'ordinal': Array, + 'number': Array, + 'time': Array + }; + var CtorUint32Array = typeof Uint32Array === UNDEFINED ? Array : Uint32Array; + var CtorInt32Array = typeof Int32Array === UNDEFINED ? Array : Int32Array; + var CtorUint16Array = typeof Uint16Array === UNDEFINED ? Array : Uint16Array; + var TRANSFERABLE_PROPERTIES = ['hasItemOption', '_nameList', '_idList', '_invertedIndicesMap', '_rawData', '_dimValueGetter', '_count', '_rawCount', '_nameDimIdx', '_idDimIdx', '_nameRepeatCount']; + var CLONE_PROPERTIES = ['_extent', '_approximateExtent', '_rawExtent']; + var defaultDimValueGetters; + var prepareInvertedIndex; + var getIndicesCtor; + var prepareStorage; + var getRawIndexWithoutIndices; + var getRawIndexWithIndices; + var getId; + var getIdNameFromStore; + var makeIdFromName; + var normalizeDimensions; + var validateDimensions; + var cloneListForMapAndSample; + var getInitialExtent; + var setItemDataAndSeriesIndex; + var transferProperties; + + var List = function () { + function List(dimensions, hostModel) { + this.type = 'list'; + this._count = 0; + this._rawCount = 0; + this._storage = {}; + this._storageArr = []; + this._nameList = []; + this._idList = []; + this._visual = {}; + this._layout = {}; + this._itemVisuals = []; + this._itemLayouts = []; + this._graphicEls = []; + this._rawExtent = {}; + this._extent = {}; + this._approximateExtent = {}; + this._calculationInfo = {}; + this.hasItemOption = true; + this.TRANSFERABLE_METHODS = ['cloneShallow', 'downSample', 'lttbDownSample', 'map']; + this.CHANGABLE_METHODS = ['filterSelf', 'selectRange']; + this.DOWNSAMPLE_METHODS = ['downSample', 'lttbDownSample']; + this.getRawIndex = getRawIndexWithoutIndices; + dimensions = dimensions || ['x', 'y']; + var dimensionInfos = {}; + var dimensionNames = []; + var invertedIndicesMap = {}; + + for (var i = 0; i < dimensions.length; i++) { + var dimInfoInput = dimensions[i]; + var dimensionInfo = isString(dimInfoInput) ? new DataDimensionInfo({ + name: dimInfoInput + }) : !(dimInfoInput instanceof DataDimensionInfo) ? new DataDimensionInfo(dimInfoInput) : dimInfoInput; + var dimensionName = dimensionInfo.name; + dimensionInfo.type = dimensionInfo.type || 'float'; + + if (!dimensionInfo.coordDim) { + dimensionInfo.coordDim = dimensionName; + dimensionInfo.coordDimIndex = 0; + } + + var otherDims = dimensionInfo.otherDims = dimensionInfo.otherDims || {}; + dimensionNames.push(dimensionName); + dimensionInfos[dimensionName] = dimensionInfo; + dimensionInfo.index = i; + + if (dimensionInfo.createInvertedIndices) { + invertedIndicesMap[dimensionName] = []; + } + + if (otherDims.itemName === 0) { + this._nameDimIdx = i; + this._nameOrdinalMeta = dimensionInfo.ordinalMeta; + } + + if (otherDims.itemId === 0) { + this._idDimIdx = i; + this._idOrdinalMeta = dimensionInfo.ordinalMeta; + } + } + + this.dimensions = dimensionNames; + this._dimensionInfos = dimensionInfos; + this.hostModel = hostModel; + this._dimensionsSummary = summarizeDimensions(this); + this._invertedIndicesMap = invertedIndicesMap; + this.userOutput = this._dimensionsSummary.userOutput; + } + + List.prototype.getDimension = function (dim) { + if (typeof dim === 'number' || !isNaN(dim) && !this._dimensionInfos.hasOwnProperty(dim)) { + dim = this.dimensions[dim]; + } + + return dim; + }; + + List.prototype.getDimensionInfo = function (dim) { + return this._dimensionInfos[this.getDimension(dim)]; + }; + + List.prototype.getDimensionsOnCoord = function () { + return this._dimensionsSummary.dataDimsOnCoord.slice(); + }; + + List.prototype.mapDimension = function (coordDim, idx) { + var dimensionsSummary = this._dimensionsSummary; + + if (idx == null) { + return dimensionsSummary.encodeFirstDimNotExtra[coordDim]; + } + + var dims = dimensionsSummary.encode[coordDim]; + return dims ? dims[idx] : null; + }; + + List.prototype.mapDimensionsAll = function (coordDim) { + var dimensionsSummary = this._dimensionsSummary; + var dims = dimensionsSummary.encode[coordDim]; + return (dims || []).slice(); + }; + + List.prototype.initData = function (data, nameList, dimValueGetter) { + var notProvider = isSourceInstance(data) || isArrayLike(data); + var provider = notProvider ? new DefaultDataProvider(data, this.dimensions.length) : data; + + if ("development" !== 'production') { + assert(notProvider || isFunction(provider.getItem) && isFunction(provider.count), 'Inavlid data provider.'); + } + + this._rawData = provider; + var sourceFormat = provider.getSource().sourceFormat; + this._storage = {}; + this._indices = null; + this._dontMakeIdFromName = this._idDimIdx != null || sourceFormat === SOURCE_FORMAT_TYPED_ARRAY || !!provider.fillStorage; + this._nameList = (nameList || []).slice(); + this._idList = []; + this._nameRepeatCount = {}; + + if (!dimValueGetter) { + this.hasItemOption = false; + } + + this.defaultDimValueGetter = defaultDimValueGetters[sourceFormat]; + this._dimValueGetter = dimValueGetter = dimValueGetter || this.defaultDimValueGetter; + this._dimValueGetterArrayRows = defaultDimValueGetters.arrayRows; + this._rawExtent = {}; + + this._initDataFromProvider(0, provider.count()); + + if (provider.pure) { + this.hasItemOption = false; + } + }; + + List.prototype.getProvider = function () { + return this._rawData; + }; + + List.prototype.appendData = function (data) { + if ("development" !== 'production') { + assert(!this._indices, 'appendData can only be called on raw data.'); + } + + var rawData = this._rawData; + var start = this.count(); + rawData.appendData(data); + var end = rawData.count(); + + if (!rawData.persistent) { + end += start; + } + + this._initDataFromProvider(start, end, true); + }; + + List.prototype.appendValues = function (values, names) { + var storage = this._storage; + var dimensions = this.dimensions; + var dimLen = dimensions.length; + var rawExtent = this._rawExtent; + var start = this.count(); + var end = start + Math.max(values.length, names ? names.length : 0); + + for (var i = 0; i < dimLen; i++) { + var dim = dimensions[i]; + + if (!rawExtent[dim]) { + rawExtent[dim] = getInitialExtent(); + } + + prepareStorage(storage, this._dimensionInfos[dim], end, true); + } + + var rawExtentArr = map$1(dimensions, function (dim) { + return rawExtent[dim]; + }); + var storageArr = this._storageArr = map$1(dimensions, function (dim) { + return storage[dim]; + }); + var emptyDataItem = []; + + for (var idx = start; idx < end; idx++) { + var sourceIdx = idx - start; + + for (var dimIdx = 0; dimIdx < dimLen; dimIdx++) { + var dim = dimensions[dimIdx]; + + var val = this._dimValueGetterArrayRows(values[sourceIdx] || emptyDataItem, dim, sourceIdx, dimIdx); + + storageArr[dimIdx][idx] = val; + var dimRawExtent = rawExtentArr[dimIdx]; + val < dimRawExtent[0] && (dimRawExtent[0] = val); + val > dimRawExtent[1] && (dimRawExtent[1] = val); + } + + if (names) { + this._nameList[idx] = names[sourceIdx]; + + if (!this._dontMakeIdFromName) { + makeIdFromName(this, idx); + } + } + } + + this._rawCount = this._count = end; + this._extent = {}; + prepareInvertedIndex(this); + }; + + List.prototype._initDataFromProvider = function (start, end, append) { + if (start >= end) { + return; + } + + var rawData = this._rawData; + var storage = this._storage; + var dimensions = this.dimensions; + var dimLen = dimensions.length; + var dimensionInfoMap = this._dimensionInfos; + var nameList = this._nameList; + var idList = this._idList; + var rawExtent = this._rawExtent; + var sourceFormat = rawData.getSource().sourceFormat; + var isFormatOriginal = sourceFormat === SOURCE_FORMAT_ORIGINAL; + + for (var i = 0; i < dimLen; i++) { + var dim = dimensions[i]; + + if (!rawExtent[dim]) { + rawExtent[dim] = getInitialExtent(); + } + + prepareStorage(storage, dimensionInfoMap[dim], end, append); + } + + var storageArr = this._storageArr = map$1(dimensions, function (dim) { + return storage[dim]; + }); + var rawExtentArr = map$1(dimensions, function (dim) { + return rawExtent[dim]; + }); + + if (rawData.fillStorage) { + rawData.fillStorage(start, end, storageArr, rawExtentArr); + } else { + var dataItem = []; + + for (var idx = start; idx < end; idx++) { + dataItem = rawData.getItem(idx, dataItem); + + for (var dimIdx = 0; dimIdx < dimLen; dimIdx++) { + var dim = dimensions[dimIdx]; + var dimStorage = storageArr[dimIdx]; + + var val = this._dimValueGetter(dataItem, dim, idx, dimIdx); + + dimStorage[idx] = val; + var dimRawExtent = rawExtentArr[dimIdx]; + val < dimRawExtent[0] && (dimRawExtent[0] = val); + val > dimRawExtent[1] && (dimRawExtent[1] = val); + } + + if (isFormatOriginal && !rawData.pure && dataItem) { + var itemName = dataItem.name; + + if (nameList[idx] == null && itemName != null) { + nameList[idx] = convertOptionIdName(itemName, null); + } + + var itemId = dataItem.id; + + if (idList[idx] == null && itemId != null) { + idList[idx] = convertOptionIdName(itemId, null); + } + } + + if (!this._dontMakeIdFromName) { + makeIdFromName(this, idx); + } + } + } + + if (!rawData.persistent && rawData.clean) { + rawData.clean(); + } + + this._rawCount = this._count = end; + this._extent = {}; + prepareInvertedIndex(this); + }; + + List.prototype.count = function () { + return this._count; + }; + + List.prototype.getIndices = function () { + var newIndices; + var indices = this._indices; + + if (indices) { + var Ctor = indices.constructor; + var thisCount = this._count; + + if (Ctor === Array) { + newIndices = new Ctor(thisCount); + + for (var i = 0; i < thisCount; i++) { + newIndices[i] = indices[i]; + } + } else { + newIndices = new Ctor(indices.buffer, 0, thisCount); + } + } else { + var Ctor = getIndicesCtor(this); + newIndices = new Ctor(this.count()); + + for (var i = 0; i < newIndices.length; i++) { + newIndices[i] = i; + } + } + + return newIndices; + }; + + List.prototype.getByDimIdx = function (dimIdx, idx) { + if (!(idx >= 0 && idx < this._count)) { + return NaN; + } + + var dimStore = this._storageArr[dimIdx]; + return dimStore ? dimStore[this.getRawIndex(idx)] : NaN; + }; + + List.prototype.get = function (dim, idx) { + if (!(idx >= 0 && idx < this._count)) { + return NaN; + } + + var dimStore = this._storage[dim]; + return dimStore ? dimStore[this.getRawIndex(idx)] : NaN; + }; + + List.prototype.getByRawIndex = function (dim, rawIdx) { + if (!(rawIdx >= 0 && rawIdx < this._rawCount)) { + return NaN; + } + + var dimStore = this._storage[dim]; + return dimStore ? dimStore[rawIdx] : NaN; + }; + + List.prototype.getValues = function (dimensions, idx) { + var values = []; + + if (!isArray(dimensions)) { + idx = dimensions; + dimensions = this.dimensions; + } + + for (var i = 0, len = dimensions.length; i < len; i++) { + values.push(this.get(dimensions[i], idx)); + } + + return values; + }; + + List.prototype.hasValue = function (idx) { + var dataDimsOnCoord = this._dimensionsSummary.dataDimsOnCoord; + + for (var i = 0, len = dataDimsOnCoord.length; i < len; i++) { + if (isNaN(this.get(dataDimsOnCoord[i], idx))) { + return false; + } + } + + return true; + }; + + List.prototype.getDataExtent = function (dim) { + dim = this.getDimension(dim); + var dimData = this._storage[dim]; + var initialExtent = getInitialExtent(); + + if (!dimData) { + return initialExtent; + } + + var currEnd = this.count(); + var useRaw = !this._indices; + var dimExtent; + + if (useRaw) { + return this._rawExtent[dim].slice(); + } + + dimExtent = this._extent[dim]; + + if (dimExtent) { + return dimExtent.slice(); + } + + dimExtent = initialExtent; + var min = dimExtent[0]; + var max = dimExtent[1]; + + for (var i = 0; i < currEnd; i++) { + var rawIdx = this.getRawIndex(i); + var value = dimData[rawIdx]; + value < min && (min = value); + value > max && (max = value); + } + + dimExtent = [min, max]; + this._extent[dim] = dimExtent; + return dimExtent; + }; + + List.prototype.getApproximateExtent = function (dim) { + dim = this.getDimension(dim); + return this._approximateExtent[dim] || this.getDataExtent(dim); + }; + + List.prototype.setApproximateExtent = function (extent, dim) { + dim = this.getDimension(dim); + this._approximateExtent[dim] = extent.slice(); + }; + + List.prototype.getCalculationInfo = function (key) { + return this._calculationInfo[key]; + }; + + List.prototype.setCalculationInfo = function (key, value) { + isObject$3(key) ? extend(this._calculationInfo, key) : this._calculationInfo[key] = value; + }; + + List.prototype.getSum = function (dim) { + var dimData = this._storage[dim]; + var sum = 0; + + if (dimData) { + for (var i = 0, len = this.count(); i < len; i++) { + var value = this.get(dim, i); + + if (!isNaN(value)) { + sum += value; + } + } + } + + return sum; + }; + + List.prototype.getMedian = function (dim) { + var dimDataArray = []; + this.each(dim, function (val) { + if (!isNaN(val)) { + dimDataArray.push(val); + } + }); + var sortedDimDataArray = dimDataArray.sort(function (a, b) { + return a - b; + }); + var len = this.count(); + return len === 0 ? 0 : len % 2 === 1 ? sortedDimDataArray[(len - 1) / 2] : (sortedDimDataArray[len / 2] + sortedDimDataArray[len / 2 - 1]) / 2; + }; + + List.prototype.rawIndexOf = function (dim, value) { + var invertedIndices = dim && this._invertedIndicesMap[dim]; + + if ("development" !== 'production') { + if (!invertedIndices) { + throw new Error('Do not supported yet'); + } + } + + var rawIndex = invertedIndices[value]; + + if (rawIndex == null || isNaN(rawIndex)) { + return INDEX_NOT_FOUND; + } + + return rawIndex; + }; + + List.prototype.indexOfName = function (name) { + for (var i = 0, len = this.count(); i < len; i++) { + if (this.getName(i) === name) { + return i; + } + } + + return -1; + }; + + List.prototype.indexOfRawIndex = function (rawIndex) { + if (rawIndex >= this._rawCount || rawIndex < 0) { + return -1; + } + + if (!this._indices) { + return rawIndex; + } + + var indices = this._indices; + var rawDataIndex = indices[rawIndex]; + + if (rawDataIndex != null && rawDataIndex < this._count && rawDataIndex === rawIndex) { + return rawIndex; + } + + var left = 0; + var right = this._count - 1; + + while (left <= right) { + var mid = (left + right) / 2 | 0; + + if (indices[mid] < rawIndex) { + left = mid + 1; + } else if (indices[mid] > rawIndex) { + right = mid - 1; + } else { + return mid; + } + } + + return -1; + }; + + List.prototype.indicesOfNearest = function (dim, value, maxDistance) { + var storage = this._storage; + var dimData = storage[dim]; + var nearestIndices = []; + + if (!dimData) { + return nearestIndices; + } + + if (maxDistance == null) { + maxDistance = Infinity; + } + + var minDist = Infinity; + var minDiff = -1; + var nearestIndicesLen = 0; + + for (var i = 0, len = this.count(); i < len; i++) { + var dataIndex = this.getRawIndex(i); + var diff = value - dimData[dataIndex]; + var dist = Math.abs(diff); + + if (dist <= maxDistance) { + if (dist < minDist || dist === minDist && diff >= 0 && minDiff < 0) { + minDist = dist; + minDiff = diff; + nearestIndicesLen = 0; + } + + if (diff === minDiff) { + nearestIndices[nearestIndicesLen++] = i; + } + } + } + + nearestIndices.length = nearestIndicesLen; + return nearestIndices; + }; + + List.prototype.getRawDataItem = function (idx) { + if (!this._rawData.persistent) { + var val = []; + + for (var i = 0; i < this.dimensions.length; i++) { + var dim = this.dimensions[i]; + val.push(this.get(dim, idx)); + } + + return val; + } else { + return this._rawData.getItem(this.getRawIndex(idx)); + } + }; + + List.prototype.getName = function (idx) { + var rawIndex = this.getRawIndex(idx); + var name = this._nameList[rawIndex]; + + if (name == null && this._nameDimIdx != null) { + name = getIdNameFromStore(this, this._nameDimIdx, this._nameOrdinalMeta, rawIndex); + } + + if (name == null) { + name = ''; + } + + return name; + }; + + List.prototype.getId = function (idx) { + return getId(this, this.getRawIndex(idx)); + }; + + List.prototype.each = function (dims, cb, ctx, ctxCompat) { + + var _this = this; + + if (!this._count) { + return; + } + + if (typeof dims === 'function') { + ctxCompat = ctx; + ctx = cb; + cb = dims; + dims = []; + } + + var fCtx = ctx || ctxCompat || this; + var dimNames = map$1(normalizeDimensions(dims), this.getDimension, this); + + if ("development" !== 'production') { + validateDimensions(this, dimNames); + } + + var dimSize = dimNames.length; + var dimIndices = map$1(dimNames, function (dimName) { + return _this._dimensionInfos[dimName].index; + }); + var storageArr = this._storageArr; + + for (var i = 0, len = this.count(); i < len; i++) { + var rawIdx = this.getRawIndex(i); + + switch (dimSize) { + case 0: + cb.call(fCtx, i); + break; + + case 1: + cb.call(fCtx, storageArr[dimIndices[0]][rawIdx], i); + break; + + case 2: + cb.call(fCtx, storageArr[dimIndices[0]][rawIdx], storageArr[dimIndices[1]][rawIdx], i); + break; + + default: + var k = 0; + var value = []; + + for (; k < dimSize; k++) { + value[k] = storageArr[dimIndices[k]][rawIdx]; + } + + value[k] = i; + cb.apply(fCtx, value); + } + } + }; + + List.prototype.filterSelf = function (dims, cb, ctx, ctxCompat) { + + var _this = this; + + if (!this._count) { + return; + } + + if (typeof dims === 'function') { + ctxCompat = ctx; + ctx = cb; + cb = dims; + dims = []; + } + + var fCtx = ctx || ctxCompat || this; + var dimNames = map$1(normalizeDimensions(dims), this.getDimension, this); + + if ("development" !== 'production') { + validateDimensions(this, dimNames); + } + + var count = this.count(); + var Ctor = getIndicesCtor(this); + var newIndices = new Ctor(count); + var value = []; + var dimSize = dimNames.length; + var offset = 0; + var dimIndices = map$1(dimNames, function (dimName) { + return _this._dimensionInfos[dimName].index; + }); + var dim0 = dimIndices[0]; + var storageArr = this._storageArr; + + for (var i = 0; i < count; i++) { + var keep = void 0; + var rawIdx = this.getRawIndex(i); + + if (dimSize === 0) { + keep = cb.call(fCtx, i); + } else if (dimSize === 1) { + var val = storageArr[dim0][rawIdx]; + keep = cb.call(fCtx, val, i); + } else { + var k = 0; + + for (; k < dimSize; k++) { + value[k] = storageArr[dimIndices[k]][rawIdx]; + } + + value[k] = i; + keep = cb.apply(fCtx, value); + } + + if (keep) { + newIndices[offset++] = rawIdx; + } + } + + if (offset < count) { + this._indices = newIndices; + } + + this._count = offset; + this._extent = {}; + this.getRawIndex = this._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices; + return this; + }; + + List.prototype.selectRange = function (range) { + + var _this = this; + + var len = this._count; + + if (!len) { + return; + } + + var dimensions = []; + + for (var dim in range) { + if (range.hasOwnProperty(dim)) { + dimensions.push(dim); + } + } + + if ("development" !== 'production') { + validateDimensions(this, dimensions); + } + + var dimSize = dimensions.length; + + if (!dimSize) { + return; + } + + var originalCount = this.count(); + var Ctor = getIndicesCtor(this); + var newIndices = new Ctor(originalCount); + var offset = 0; + var dim0 = dimensions[0]; + var dimIndices = map$1(dimensions, function (dimName) { + return _this._dimensionInfos[dimName].index; + }); + var min = range[dim0][0]; + var max = range[dim0][1]; + var storageArr = this._storageArr; + var quickFinished = false; + + if (!this._indices) { + var idx = 0; + + if (dimSize === 1) { + var dimStorage = storageArr[dimIndices[0]]; + + for (var i = 0; i < len; i++) { + var val = dimStorage[i]; + + if (val >= min && val <= max || isNaN(val)) { + newIndices[offset++] = idx; + } + + idx++; + } + + quickFinished = true; + } else if (dimSize === 2) { + var dimStorage = storageArr[dimIndices[0]]; + var dimStorage2 = storageArr[dimIndices[1]]; + var min2 = range[dimensions[1]][0]; + var max2 = range[dimensions[1]][1]; + + for (var i = 0; i < len; i++) { + var val = dimStorage[i]; + var val2 = dimStorage2[i]; + + if ((val >= min && val <= max || isNaN(val)) && (val2 >= min2 && val2 <= max2 || isNaN(val2))) { + newIndices[offset++] = idx; + } + + idx++; + } + + quickFinished = true; + } + } + + if (!quickFinished) { + if (dimSize === 1) { + for (var i = 0; i < originalCount; i++) { + var rawIndex = this.getRawIndex(i); + var val = storageArr[dimIndices[0]][rawIndex]; + + if (val >= min && val <= max || isNaN(val)) { + newIndices[offset++] = rawIndex; + } + } + } else { + for (var i = 0; i < originalCount; i++) { + var keep = true; + var rawIndex = this.getRawIndex(i); + + for (var k = 0; k < dimSize; k++) { + var dimk = dimensions[k]; + var val = storageArr[dimIndices[k]][rawIndex]; + + if (val < range[dimk][0] || val > range[dimk][1]) { + keep = false; + } + } + + if (keep) { + newIndices[offset++] = this.getRawIndex(i); + } + } + } + } + + if (offset < originalCount) { + this._indices = newIndices; + } + + this._count = offset; + this._extent = {}; + this.getRawIndex = this._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices; + return this; + }; + + List.prototype.mapArray = function (dims, cb, ctx, ctxCompat) { + + if (typeof dims === 'function') { + ctxCompat = ctx; + ctx = cb; + cb = dims; + dims = []; + } + + ctx = ctx || ctxCompat || this; + var result = []; + this.each(dims, function () { + result.push(cb && cb.apply(this, arguments)); + }, ctx); + return result; + }; + + List.prototype.map = function (dims, cb, ctx, ctxCompat) { + + var fCtx = ctx || ctxCompat || this; + var dimNames = map$1(normalizeDimensions(dims), this.getDimension, this); + + if ("development" !== 'production') { + validateDimensions(this, dimNames); + } + + var list = cloneListForMapAndSample(this, dimNames); + var storage = list._storage; + list._indices = this._indices; + list.getRawIndex = list._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices; + var tmpRetValue = []; + var dimSize = dimNames.length; + var dataCount = this.count(); + var values = []; + var rawExtent = list._rawExtent; + + for (var dataIndex = 0; dataIndex < dataCount; dataIndex++) { + for (var dimIndex = 0; dimIndex < dimSize; dimIndex++) { + values[dimIndex] = this.get(dimNames[dimIndex], dataIndex); + } + + values[dimSize] = dataIndex; + var retValue = cb && cb.apply(fCtx, values); + + if (retValue != null) { + if (typeof retValue !== 'object') { + tmpRetValue[0] = retValue; + retValue = tmpRetValue; + } + + var rawIndex = this.getRawIndex(dataIndex); + + for (var i = 0; i < retValue.length; i++) { + var dim = dimNames[i]; + var val = retValue[i]; + var rawExtentOnDim = rawExtent[dim]; + var dimStore = storage[dim]; + + if (dimStore) { + dimStore[rawIndex] = val; + } + + if (val < rawExtentOnDim[0]) { + rawExtentOnDim[0] = val; + } + + if (val > rawExtentOnDim[1]) { + rawExtentOnDim[1] = val; + } + } + } + } + + return list; + }; + + List.prototype.downSample = function (dimension, rate, sampleValue, sampleIndex) { + var list = cloneListForMapAndSample(this, [dimension]); + var targetStorage = list._storage; + var frameValues = []; + var frameSize = mathFloor(1 / rate); + var dimStore = targetStorage[dimension]; + var len = this.count(); + var rawExtentOnDim = list._rawExtent[dimension]; + var newIndices = new (getIndicesCtor(this))(len); + var offset = 0; + + for (var i = 0; i < len; i += frameSize) { + if (frameSize > len - i) { + frameSize = len - i; + frameValues.length = frameSize; + } + + for (var k = 0; k < frameSize; k++) { + var dataIdx = this.getRawIndex(i + k); + frameValues[k] = dimStore[dataIdx]; + } + + var value = sampleValue(frameValues); + var sampleFrameIdx = this.getRawIndex(Math.min(i + sampleIndex(frameValues, value) || 0, len - 1)); + dimStore[sampleFrameIdx] = value; + + if (value < rawExtentOnDim[0]) { + rawExtentOnDim[0] = value; + } + + if (value > rawExtentOnDim[1]) { + rawExtentOnDim[1] = value; + } + + newIndices[offset++] = sampleFrameIdx; + } + + list._count = offset; + list._indices = newIndices; + list.getRawIndex = getRawIndexWithIndices; + return list; + }; + + List.prototype.lttbDownSample = function (valueDimension, rate) { + var list = cloneListForMapAndSample(this, []); + var targetStorage = list._storage; + var dimStore = targetStorage[valueDimension]; + var len = this.count(); + var newIndices = new (getIndicesCtor(this))(len); + var sampledIndex = 0; + var frameSize = mathFloor(1 / rate); + var currentRawIndex = this.getRawIndex(0); + var maxArea; + var area; + var nextRawIndex; + newIndices[sampledIndex++] = currentRawIndex; + + for (var i = 1; i < len - 1; i += frameSize) { + var nextFrameStart = Math.min(i + frameSize, len - 1); + var nextFrameEnd = Math.min(i + frameSize * 2, len); + var avgX = (nextFrameEnd + nextFrameStart) / 2; + var avgY = 0; + + for (var idx = nextFrameStart; idx < nextFrameEnd; idx++) { + var rawIndex = this.getRawIndex(idx); + var y = dimStore[rawIndex]; + + if (isNaN(y)) { + continue; + } + + avgY += y; + } + + avgY /= nextFrameEnd - nextFrameStart; + var frameStart = i; + var frameEnd = Math.min(i + frameSize, len); + var pointAX = i - 1; + var pointAY = dimStore[currentRawIndex]; + maxArea = -1; + nextRawIndex = frameStart; + + for (var idx = frameStart; idx < frameEnd; idx++) { + var rawIndex = this.getRawIndex(idx); + var y = dimStore[rawIndex]; + + if (isNaN(y)) { + continue; + } + + area = Math.abs((pointAX - avgX) * (y - pointAY) - (pointAX - idx) * (avgY - pointAY)); + + if (area > maxArea) { + maxArea = area; + nextRawIndex = rawIndex; + } + } + + newIndices[sampledIndex++] = nextRawIndex; + currentRawIndex = nextRawIndex; + } + + newIndices[sampledIndex++] = this.getRawIndex(len - 1); + list._count = sampledIndex; + list._indices = newIndices; + list.getRawIndex = getRawIndexWithIndices; + return list; + }; + + List.prototype.getItemModel = function (idx) { + var hostModel = this.hostModel; + var dataItem = this.getRawDataItem(idx); + return new Model(dataItem, hostModel, hostModel && hostModel.ecModel); + }; + + List.prototype.diff = function (otherList) { + var thisList = this; + return new DataDiffer(otherList ? otherList.getIndices() : [], this.getIndices(), function (idx) { + return getId(otherList, idx); + }, function (idx) { + return getId(thisList, idx); + }); + }; + + List.prototype.getVisual = function (key) { + var visual = this._visual; + return visual && visual[key]; + }; + + List.prototype.setVisual = function (kvObj, val) { + this._visual = this._visual || {}; + + if (isObject$3(kvObj)) { + extend(this._visual, kvObj); + } else { + this._visual[kvObj] = val; + } + }; + + List.prototype.getItemVisual = function (idx, key) { + var itemVisual = this._itemVisuals[idx]; + var val = itemVisual && itemVisual[key]; + + if (val == null) { + return this.getVisual(key); + } + + return val; + }; + + List.prototype.hasItemVisual = function () { + return this._itemVisuals.length > 0; + }; + + List.prototype.ensureUniqueItemVisual = function (idx, key) { + var itemVisuals = this._itemVisuals; + var itemVisual = itemVisuals[idx]; + + if (!itemVisual) { + itemVisual = itemVisuals[idx] = {}; + } + + var val = itemVisual[key]; + + if (val == null) { + val = this.getVisual(key); + + if (isArray(val)) { + val = val.slice(); + } else if (isObject$3(val)) { + val = extend({}, val); + } + + itemVisual[key] = val; + } + + return val; + }; + + List.prototype.setItemVisual = function (idx, key, value) { + var itemVisual = this._itemVisuals[idx] || {}; + this._itemVisuals[idx] = itemVisual; + + if (isObject$3(key)) { + extend(itemVisual, key); + } else { + itemVisual[key] = value; + } + }; + + List.prototype.clearAllVisual = function () { + this._visual = {}; + this._itemVisuals = []; + }; + + List.prototype.setLayout = function (key, val) { + if (isObject$3(key)) { + for (var name_1 in key) { + if (key.hasOwnProperty(name_1)) { + this.setLayout(name_1, key[name_1]); + } + } + + return; + } + + this._layout[key] = val; + }; + + List.prototype.getLayout = function (key) { + return this._layout[key]; + }; + + List.prototype.getItemLayout = function (idx) { + return this._itemLayouts[idx]; + }; + + List.prototype.setItemLayout = function (idx, layout, merge) { + this._itemLayouts[idx] = merge ? extend(this._itemLayouts[idx] || {}, layout) : layout; + }; + + List.prototype.clearItemLayouts = function () { + this._itemLayouts.length = 0; + }; + + List.prototype.setItemGraphicEl = function (idx, el) { + var hostModel = this.hostModel; + + if (el) { + var ecData = getECData(el); + ecData.dataIndex = idx; + ecData.dataType = this.dataType; + ecData.seriesIndex = hostModel && hostModel.seriesIndex; + + if (el.type === 'group') { + el.traverse(setItemDataAndSeriesIndex, el); + } + } + + this._graphicEls[idx] = el; + }; + + List.prototype.getItemGraphicEl = function (idx) { + return this._graphicEls[idx]; + }; + + List.prototype.eachItemGraphicEl = function (cb, context) { + each(this._graphicEls, function (el, idx) { + if (el) { + cb && cb.call(context, el, idx); + } + }); + }; + + List.prototype.cloneShallow = function (list) { + if (!list) { + var dimensionInfoList = map$1(this.dimensions, this.getDimensionInfo, this); + list = new List(dimensionInfoList, this.hostModel); + } + + list._storage = this._storage; + list._storageArr = this._storageArr; + transferProperties(list, this); + + if (this._indices) { + var Ctor = this._indices.constructor; + + if (Ctor === Array) { + var thisCount = this._indices.length; + list._indices = new Ctor(thisCount); + + for (var i = 0; i < thisCount; i++) { + list._indices[i] = this._indices[i]; + } + } else { + list._indices = new Ctor(this._indices); + } + } else { + list._indices = null; + } + + list.getRawIndex = list._indices ? getRawIndexWithIndices : getRawIndexWithoutIndices; + return list; + }; + + List.prototype.wrapMethod = function (methodName, injectFunction) { + var originalMethod = this[methodName]; + + if (typeof originalMethod !== 'function') { + return; + } + + this.__wrappedMethods = this.__wrappedMethods || []; + + this.__wrappedMethods.push(methodName); + + this[methodName] = function () { + var res = originalMethod.apply(this, arguments); + return injectFunction.apply(this, [res].concat(slice(arguments))); + }; + }; + + List.internalField = function () { + defaultDimValueGetters = { + arrayRows: getDimValueSimply, + objectRows: function (dataItem, dimName, dataIndex, dimIndex) { + return parseDataValue(dataItem[dimName], this._dimensionInfos[dimName]); + }, + keyedColumns: getDimValueSimply, + original: function (dataItem, dimName, dataIndex, dimIndex) { + var value = dataItem && (dataItem.value == null ? dataItem : dataItem.value); + + if (!this._rawData.pure && isDataItemOption(dataItem)) { + this.hasItemOption = true; + } + + return parseDataValue(value instanceof Array ? value[dimIndex] : value, this._dimensionInfos[dimName]); + }, + typedArray: function (dataItem, dimName, dataIndex, dimIndex) { + return dataItem[dimIndex]; + } + }; + + function getDimValueSimply(dataItem, dimName, dataIndex, dimIndex) { + return parseDataValue(dataItem[dimIndex], this._dimensionInfos[dimName]); + } + + prepareInvertedIndex = function (list) { + var invertedIndicesMap = list._invertedIndicesMap; + each(invertedIndicesMap, function (invertedIndices, dim) { + var dimInfo = list._dimensionInfos[dim]; + var ordinalMeta = dimInfo.ordinalMeta; + + if (ordinalMeta) { + invertedIndices = invertedIndicesMap[dim] = new CtorInt32Array(ordinalMeta.categories.length); + + for (var i = 0; i < invertedIndices.length; i++) { + invertedIndices[i] = INDEX_NOT_FOUND; + } + + for (var i = 0; i < list._count; i++) { + invertedIndices[list.get(dim, i)] = i; + } + } + }); + }; + + getIdNameFromStore = function (list, dimIdx, ordinalMeta, rawIndex) { + var val; + var chunk = list._storageArr[dimIdx]; + + if (chunk) { + val = chunk[rawIndex]; + + if (ordinalMeta && ordinalMeta.categories.length) { + val = ordinalMeta.categories[val]; + } + } + + return convertOptionIdName(val, null); + }; + + getIndicesCtor = function (list) { + return list._rawCount > 65535 ? CtorUint32Array : CtorUint16Array; + }; + + prepareStorage = function (storage, dimInfo, end, append) { + var DataCtor = dataCtors[dimInfo.type]; + var dim = dimInfo.name; + + if (append) { + var oldStore = storage[dim]; + var oldLen = oldStore && oldStore.length; + + if (!(oldLen === end)) { + var newStore = new DataCtor(end); + + for (var j = 0; j < oldLen; j++) { + newStore[j] = oldStore[j]; + } + + storage[dim] = newStore; + } + } else { + storage[dim] = new DataCtor(end); + } + }; + + getRawIndexWithoutIndices = function (idx) { + return idx; + }; + + getRawIndexWithIndices = function (idx) { + if (idx < this._count && idx >= 0) { + return this._indices[idx]; + } + + return -1; + }; + + getId = function (list, rawIndex) { + var id = list._idList[rawIndex]; + + if (id == null && list._idDimIdx != null) { + id = getIdNameFromStore(list, list._idDimIdx, list._idOrdinalMeta, rawIndex); + } + + if (id == null) { + id = ID_PREFIX + rawIndex; + } + + return id; + }; + + normalizeDimensions = function (dimensions) { + if (!isArray(dimensions)) { + dimensions = dimensions != null ? [dimensions] : []; + } + + return dimensions; + }; + + validateDimensions = function (list, dims) { + for (var i = 0; i < dims.length; i++) { + if (!list._dimensionInfos[dims[i]]) { + console.error('Unkown dimension ' + dims[i]); + } + } + }; + + cloneListForMapAndSample = function (original, excludeDimensions) { + var allDimensions = original.dimensions; + var list = new List(map$1(allDimensions, original.getDimensionInfo, original), original.hostModel); + transferProperties(list, original); + var storage = list._storage = {}; + var originalStorage = original._storage; + var storageArr = list._storageArr = []; + + for (var i = 0; i < allDimensions.length; i++) { + var dim = allDimensions[i]; + + if (originalStorage[dim]) { + if (indexOf(excludeDimensions, dim) >= 0) { + storage[dim] = cloneChunk(originalStorage[dim]); + list._rawExtent[dim] = getInitialExtent(); + list._extent[dim] = null; + } else { + storage[dim] = originalStorage[dim]; + } + + storageArr.push(storage[dim]); + } + } + + return list; + }; + + function cloneChunk(originalChunk) { + var Ctor = originalChunk.constructor; + return Ctor === Array ? originalChunk.slice() : new Ctor(originalChunk); + } + + getInitialExtent = function () { + return [Infinity, -Infinity]; + }; + + setItemDataAndSeriesIndex = function (child) { + var childECData = getECData(child); + var thisECData = getECData(this); + childECData.seriesIndex = thisECData.seriesIndex; + childECData.dataIndex = thisECData.dataIndex; + childECData.dataType = thisECData.dataType; + }; + + transferProperties = function (target, source) { + each(TRANSFERABLE_PROPERTIES.concat(source.__wrappedMethods || []), function (propName) { + if (source.hasOwnProperty(propName)) { + target[propName] = source[propName]; + } + }); + target.__wrappedMethods = source.__wrappedMethods; + each(CLONE_PROPERTIES, function (propName) { + target[propName] = clone(source[propName]); + }); + target._calculationInfo = extend({}, source._calculationInfo); + }; + + makeIdFromName = function (list, idx) { + var nameList = list._nameList; + var idList = list._idList; + var nameDimIdx = list._nameDimIdx; + var idDimIdx = list._idDimIdx; + var name = nameList[idx]; + var id = idList[idx]; + + if (name == null && nameDimIdx != null) { + nameList[idx] = name = getIdNameFromStore(list, nameDimIdx, list._nameOrdinalMeta, idx); + } + + if (id == null && idDimIdx != null) { + idList[idx] = id = getIdNameFromStore(list, idDimIdx, list._idOrdinalMeta, idx); + } + + if (id == null && name != null) { + var nameRepeatCount = list._nameRepeatCount; + var nmCnt = nameRepeatCount[name] = (nameRepeatCount[name] || 0) + 1; + id = name; + + if (nmCnt > 1) { + id += '__ec__' + nmCnt; + } + + idList[idx] = id; + } + }; + }(); + + return List; + }(); + + function completeDimensions(sysDims, source, opt) { + if (!isSourceInstance(source)) { + source = createSourceFromSeriesDataOption(source); + } + + opt = opt || {}; + sysDims = (sysDims || []).slice(); + var dimsDef = (opt.dimsDef || []).slice(); + var dataDimNameMap = createHashMap(); + var coordDimNameMap = createHashMap(); + var result = []; + var dimCount = getDimCount(source, sysDims, dimsDef, opt.dimCount); + + for (var i = 0; i < dimCount; i++) { + var dimDefItemRaw = dimsDef[i]; + var dimDefItem = dimsDef[i] = extend({}, isObject(dimDefItemRaw) ? dimDefItemRaw : { + name: dimDefItemRaw + }); + var userDimName = dimDefItem.name; + var resultItem = result[i] = new DataDimensionInfo(); + + if (userDimName != null && dataDimNameMap.get(userDimName) == null) { + resultItem.name = resultItem.displayName = userDimName; + dataDimNameMap.set(userDimName, i); + } + + dimDefItem.type != null && (resultItem.type = dimDefItem.type); + dimDefItem.displayName != null && (resultItem.displayName = dimDefItem.displayName); + } + + var encodeDef = opt.encodeDef; + + if (!encodeDef && opt.encodeDefaulter) { + encodeDef = opt.encodeDefaulter(source, dimCount); + } + + var encodeDefMap = createHashMap(encodeDef); + encodeDefMap.each(function (dataDimsRaw, coordDim) { + var dataDims = normalizeToArray(dataDimsRaw).slice(); + + if (dataDims.length === 1 && !isString(dataDims[0]) && dataDims[0] < 0) { + encodeDefMap.set(coordDim, false); + return; + } + + var validDataDims = encodeDefMap.set(coordDim, []); + each(dataDims, function (resultDimIdxOrName, idx) { + var resultDimIdx = isString(resultDimIdxOrName) ? dataDimNameMap.get(resultDimIdxOrName) : resultDimIdxOrName; + + if (resultDimIdx != null && resultDimIdx < dimCount) { + validDataDims[idx] = resultDimIdx; + applyDim(result[resultDimIdx], coordDim, idx); + } + }); + }); + var availDimIdx = 0; + each(sysDims, function (sysDimItemRaw) { + var coordDim; + var sysDimItemDimsDef; + var sysDimItemOtherDims; + var sysDimItem; + + if (isString(sysDimItemRaw)) { + coordDim = sysDimItemRaw; + sysDimItem = {}; + } else { + sysDimItem = sysDimItemRaw; + coordDim = sysDimItem.name; + var ordinalMeta = sysDimItem.ordinalMeta; + sysDimItem.ordinalMeta = null; + sysDimItem = clone(sysDimItem); + sysDimItem.ordinalMeta = ordinalMeta; + sysDimItemDimsDef = sysDimItem.dimsDef; + sysDimItemOtherDims = sysDimItem.otherDims; + sysDimItem.name = sysDimItem.coordDim = sysDimItem.coordDimIndex = sysDimItem.dimsDef = sysDimItem.otherDims = null; + } + + var dataDims = encodeDefMap.get(coordDim); + + if (dataDims === false) { + return; + } + + dataDims = normalizeToArray(dataDims); + + if (!dataDims.length) { + for (var i = 0; i < (sysDimItemDimsDef && sysDimItemDimsDef.length || 1); i++) { + while (availDimIdx < result.length && result[availDimIdx].coordDim != null) { + availDimIdx++; + } + + availDimIdx < result.length && dataDims.push(availDimIdx++); + } + } + + each(dataDims, function (resultDimIdx, coordDimIndex) { + var resultItem = result[resultDimIdx]; + applyDim(defaults(resultItem, sysDimItem), coordDim, coordDimIndex); + + if (resultItem.name == null && sysDimItemDimsDef) { + var sysDimItemDimsDefItem = sysDimItemDimsDef[coordDimIndex]; + !isObject(sysDimItemDimsDefItem) && (sysDimItemDimsDefItem = { + name: sysDimItemDimsDefItem + }); + resultItem.name = resultItem.displayName = sysDimItemDimsDefItem.name; + resultItem.defaultTooltip = sysDimItemDimsDefItem.defaultTooltip; + } + + sysDimItemOtherDims && defaults(resultItem.otherDims, sysDimItemOtherDims); + }); + }); + + function applyDim(resultItem, coordDim, coordDimIndex) { + if (VISUAL_DIMENSIONS.get(coordDim) != null) { + resultItem.otherDims[coordDim] = coordDimIndex; + } else { + resultItem.coordDim = coordDim; + resultItem.coordDimIndex = coordDimIndex; + coordDimNameMap.set(coordDim, true); + } + } + + var generateCoord = opt.generateCoord; + var generateCoordCount = opt.generateCoordCount; + var fromZero = generateCoordCount != null; + generateCoordCount = generateCoord ? generateCoordCount || 1 : 0; + var extra = generateCoord || 'value'; + + for (var resultDimIdx = 0; resultDimIdx < dimCount; resultDimIdx++) { + var resultItem = result[resultDimIdx] = result[resultDimIdx] || new DataDimensionInfo(); + var coordDim = resultItem.coordDim; + + if (coordDim == null) { + resultItem.coordDim = genName(extra, coordDimNameMap, fromZero); + resultItem.coordDimIndex = 0; + + if (!generateCoord || generateCoordCount <= 0) { + resultItem.isExtraCoord = true; + } + + generateCoordCount--; + } + + resultItem.name == null && (resultItem.name = genName(resultItem.coordDim, dataDimNameMap, false)); + + if (resultItem.type == null && (guessOrdinal(source, resultDimIdx) === BE_ORDINAL.Must || resultItem.isExtraCoord && (resultItem.otherDims.itemName != null || resultItem.otherDims.seriesName != null))) { + resultItem.type = 'ordinal'; + } + } + + return result; + } + + function getDimCount(source, sysDims, dimsDef, optDimCount) { + var dimCount = Math.max(source.dimensionsDetectedCount || 1, sysDims.length, dimsDef.length, optDimCount || 0); + each(sysDims, function (sysDimItem) { + var sysDimItemDimsDef; + + if (isObject(sysDimItem) && (sysDimItemDimsDef = sysDimItem.dimsDef)) { + dimCount = Math.max(dimCount, sysDimItemDimsDef.length); + } + }); + return dimCount; + } + + function genName(name, map, fromZero) { + if (fromZero || map.get(name) != null) { + var i = 0; + + while (map.get(name + i) != null) { + i++; + } + + name += i; + } + + map.set(name, true); + return name; + } + + function createDimensions(source, opt) { + opt = opt || {}; + return completeDimensions(opt.coordDimensions || [], source, { + dimsDef: opt.dimensionsDefine || source.dimensionsDefine, + encodeDef: opt.encodeDefine || source.encodeDefine, + dimCount: opt.dimensionsCount, + encodeDefaulter: opt.encodeDefaulter, + generateCoord: opt.generateCoord, + generateCoordCount: opt.generateCoordCount + }); + } + + var CoordSysInfo = function () { + function CoordSysInfo(coordSysName) { + this.coordSysDims = []; + this.axisMap = createHashMap(); + this.categoryAxisMap = createHashMap(); + this.coordSysName = coordSysName; + } + + return CoordSysInfo; + }(); + + function getCoordSysInfoBySeries(seriesModel) { + var coordSysName = seriesModel.get('coordinateSystem'); + var result = new CoordSysInfo(coordSysName); + var fetch = fetchers[coordSysName]; + + if (fetch) { + fetch(seriesModel, result, result.axisMap, result.categoryAxisMap); + return result; + } + } + var fetchers = { + cartesian2d: function (seriesModel, result, axisMap, categoryAxisMap) { + var xAxisModel = seriesModel.getReferringComponents('xAxis', SINGLE_REFERRING).models[0]; + var yAxisModel = seriesModel.getReferringComponents('yAxis', SINGLE_REFERRING).models[0]; + + if ("development" !== 'production') { + if (!xAxisModel) { + throw new Error('xAxis "' + retrieve(seriesModel.get('xAxisIndex'), seriesModel.get('xAxisId'), 0) + '" not found'); + } + + if (!yAxisModel) { + throw new Error('yAxis "' + retrieve(seriesModel.get('xAxisIndex'), seriesModel.get('yAxisId'), 0) + '" not found'); + } + } + + result.coordSysDims = ['x', 'y']; + axisMap.set('x', xAxisModel); + axisMap.set('y', yAxisModel); + + if (isCategory(xAxisModel)) { + categoryAxisMap.set('x', xAxisModel); + result.firstCategoryDimIndex = 0; + } + + if (isCategory(yAxisModel)) { + categoryAxisMap.set('y', yAxisModel); + result.firstCategoryDimIndex == null && (result.firstCategoryDimIndex = 1); + } + }, + singleAxis: function (seriesModel, result, axisMap, categoryAxisMap) { + var singleAxisModel = seriesModel.getReferringComponents('singleAxis', SINGLE_REFERRING).models[0]; + + if ("development" !== 'production') { + if (!singleAxisModel) { + throw new Error('singleAxis should be specified.'); + } + } + + result.coordSysDims = ['single']; + axisMap.set('single', singleAxisModel); + + if (isCategory(singleAxisModel)) { + categoryAxisMap.set('single', singleAxisModel); + result.firstCategoryDimIndex = 0; + } + }, + polar: function (seriesModel, result, axisMap, categoryAxisMap) { + var polarModel = seriesModel.getReferringComponents('polar', SINGLE_REFERRING).models[0]; + var radiusAxisModel = polarModel.findAxisModel('radiusAxis'); + var angleAxisModel = polarModel.findAxisModel('angleAxis'); + + if ("development" !== 'production') { + if (!angleAxisModel) { + throw new Error('angleAxis option not found'); + } + + if (!radiusAxisModel) { + throw new Error('radiusAxis option not found'); + } + } + + result.coordSysDims = ['radius', 'angle']; + axisMap.set('radius', radiusAxisModel); + axisMap.set('angle', angleAxisModel); + + if (isCategory(radiusAxisModel)) { + categoryAxisMap.set('radius', radiusAxisModel); + result.firstCategoryDimIndex = 0; + } + + if (isCategory(angleAxisModel)) { + categoryAxisMap.set('angle', angleAxisModel); + result.firstCategoryDimIndex == null && (result.firstCategoryDimIndex = 1); + } + }, + geo: function (seriesModel, result, axisMap, categoryAxisMap) { + result.coordSysDims = ['lng', 'lat']; + }, + parallel: function (seriesModel, result, axisMap, categoryAxisMap) { + var ecModel = seriesModel.ecModel; + var parallelModel = ecModel.getComponent('parallel', seriesModel.get('parallelIndex')); + var coordSysDims = result.coordSysDims = parallelModel.dimensions.slice(); + each(parallelModel.parallelAxisIndex, function (axisIndex, index) { + var axisModel = ecModel.getComponent('parallelAxis', axisIndex); + var axisDim = coordSysDims[index]; + axisMap.set(axisDim, axisModel); + + if (isCategory(axisModel)) { + categoryAxisMap.set(axisDim, axisModel); + + if (result.firstCategoryDimIndex == null) { + result.firstCategoryDimIndex = index; + } + } + }); + } + }; + + function isCategory(axisModel) { + return axisModel.get('type') === 'category'; + } + + function enableDataStack(seriesModel, dimensionInfoList, opt) { + opt = opt || {}; + var byIndex = opt.byIndex; + var stackedCoordDimension = opt.stackedCoordDimension; + var mayStack = !!(seriesModel && seriesModel.get('stack')); + var stackedByDimInfo; + var stackedDimInfo; + var stackResultDimension; + var stackedOverDimension; + each(dimensionInfoList, function (dimensionInfo, index) { + if (isString(dimensionInfo)) { + dimensionInfoList[index] = dimensionInfo = { + name: dimensionInfo + }; + } + + if (mayStack && !dimensionInfo.isExtraCoord) { + if (!byIndex && !stackedByDimInfo && dimensionInfo.ordinalMeta) { + stackedByDimInfo = dimensionInfo; + } + + if (!stackedDimInfo && dimensionInfo.type !== 'ordinal' && dimensionInfo.type !== 'time' && (!stackedCoordDimension || stackedCoordDimension === dimensionInfo.coordDim)) { + stackedDimInfo = dimensionInfo; + } + } + }); + + if (stackedDimInfo && !byIndex && !stackedByDimInfo) { + byIndex = true; + } + + if (stackedDimInfo) { + stackResultDimension = '__\0ecstackresult'; + stackedOverDimension = '__\0ecstackedover'; + + if (stackedByDimInfo) { + stackedByDimInfo.createInvertedIndices = true; + } + + var stackedDimCoordDim_1 = stackedDimInfo.coordDim; + var stackedDimType = stackedDimInfo.type; + var stackedDimCoordIndex_1 = 0; + each(dimensionInfoList, function (dimensionInfo) { + if (dimensionInfo.coordDim === stackedDimCoordDim_1) { + stackedDimCoordIndex_1++; + } + }); + dimensionInfoList.push({ + name: stackResultDimension, + coordDim: stackedDimCoordDim_1, + coordDimIndex: stackedDimCoordIndex_1, + type: stackedDimType, + isExtraCoord: true, + isCalculationCoord: true + }); + stackedDimCoordIndex_1++; + dimensionInfoList.push({ + name: stackedOverDimension, + coordDim: stackedOverDimension, + coordDimIndex: stackedDimCoordIndex_1, + type: stackedDimType, + isExtraCoord: true, + isCalculationCoord: true + }); + } + + return { + stackedDimension: stackedDimInfo && stackedDimInfo.name, + stackedByDimension: stackedByDimInfo && stackedByDimInfo.name, + isStackedByIndex: byIndex, + stackedOverDimension: stackedOverDimension, + stackResultDimension: stackResultDimension + }; + } + function isDimensionStacked(data, stackedDim) { + return !!stackedDim && stackedDim === data.getCalculationInfo('stackedDimension'); + } + function getStackedDimension(data, targetDim) { + return isDimensionStacked(data, targetDim) ? data.getCalculationInfo('stackResultDimension') : targetDim; + } + + function createListFromArray(source, seriesModel, opt) { + opt = opt || {}; + + if (!isSourceInstance(source)) { + source = createSourceFromSeriesDataOption(source); + } + + var coordSysName = seriesModel.get('coordinateSystem'); + var registeredCoordSys = CoordinateSystemManager.get(coordSysName); + var coordSysInfo = getCoordSysInfoBySeries(seriesModel); + var coordSysDimDefs; + + if (coordSysInfo && coordSysInfo.coordSysDims) { + coordSysDimDefs = map(coordSysInfo.coordSysDims, function (dim) { + var dimInfo = { + name: dim + }; + var axisModel = coordSysInfo.axisMap.get(dim); + + if (axisModel) { + var axisType = axisModel.get('type'); + dimInfo.type = getDimensionTypeByAxis(axisType); + } + + return dimInfo; + }); + } + + if (!coordSysDimDefs) { + coordSysDimDefs = registeredCoordSys && (registeredCoordSys.getDimensionsInfo ? registeredCoordSys.getDimensionsInfo() : registeredCoordSys.dimensions.slice()) || ['x', 'y']; + } + + var useEncodeDefaulter = opt.useEncodeDefaulter; + var dimInfoList = createDimensions(source, { + coordDimensions: coordSysDimDefs, + generateCoord: opt.generateCoord, + encodeDefaulter: isFunction(useEncodeDefaulter) ? useEncodeDefaulter : useEncodeDefaulter ? curry(makeSeriesEncodeForAxisCoordSys, coordSysDimDefs, seriesModel) : null + }); + var firstCategoryDimIndex; + var hasNameEncode; + coordSysInfo && each(dimInfoList, function (dimInfo, dimIndex) { + var coordDim = dimInfo.coordDim; + var categoryAxisModel = coordSysInfo.categoryAxisMap.get(coordDim); + + if (categoryAxisModel) { + if (firstCategoryDimIndex == null) { + firstCategoryDimIndex = dimIndex; + } + + dimInfo.ordinalMeta = categoryAxisModel.getOrdinalMeta(); + + if (opt.createInvertedIndices) { + dimInfo.createInvertedIndices = true; + } + } + + if (dimInfo.otherDims.itemName != null) { + hasNameEncode = true; + } + }); + + if (!hasNameEncode && firstCategoryDimIndex != null) { + dimInfoList[firstCategoryDimIndex].otherDims.itemName = 0; + } + + var stackCalculationInfo = enableDataStack(seriesModel, dimInfoList); + var list = new List(dimInfoList, seriesModel); + list.setCalculationInfo(stackCalculationInfo); + var dimValueGetter = firstCategoryDimIndex != null && isNeedCompleteOrdinalData(source) ? function (itemOpt, dimName, dataIndex, dimIndex) { + return dimIndex === firstCategoryDimIndex ? dataIndex : this.defaultDimValueGetter(itemOpt, dimName, dataIndex, dimIndex); + } : null; + list.hasItemOption = false; + list.initData(source, null, dimValueGetter); + return list; + } + + function isNeedCompleteOrdinalData(source) { + if (source.sourceFormat === SOURCE_FORMAT_ORIGINAL) { + var sampleItem = firstDataNotNull(source.data || []); + return sampleItem != null && !isArray(getDataItemValue(sampleItem)); + } + } + + function firstDataNotNull(data) { + var i = 0; + + while (i < data.length && data[i] == null) { + i++; + } + + return data[i]; + } + + var Scale = function () { + function Scale(setting) { + this._setting = setting || {}; + this._extent = [Infinity, -Infinity]; + } + + Scale.prototype.getSetting = function (name) { + return this._setting[name]; + }; + + Scale.prototype.unionExtent = function (other) { + var extent = this._extent; + other[0] < extent[0] && (extent[0] = other[0]); + other[1] > extent[1] && (extent[1] = other[1]); + }; + + Scale.prototype.unionExtentFromData = function (data, dim) { + this.unionExtent(data.getApproximateExtent(dim)); + }; + + Scale.prototype.getExtent = function () { + return this._extent.slice(); + }; + + Scale.prototype.setExtent = function (start, end) { + var thisExtent = this._extent; + + if (!isNaN(start)) { + thisExtent[0] = start; + } + + if (!isNaN(end)) { + thisExtent[1] = end; + } + }; + + Scale.prototype.isInExtentRange = function (value) { + return this._extent[0] <= value && this._extent[1] >= value; + }; + + Scale.prototype.isBlank = function () { + return this._isBlank; + }; + + Scale.prototype.setBlank = function (isBlank) { + this._isBlank = isBlank; + }; + + return Scale; + }(); + + enableClassManagement(Scale); + + var OrdinalMeta = function () { + function OrdinalMeta(opt) { + this.categories = opt.categories || []; + this._needCollect = opt.needCollect; + this._deduplication = opt.deduplication; + } + + OrdinalMeta.createByAxisModel = function (axisModel) { + var option = axisModel.option; + var data = option.data; + var categories = data && map(data, getName); + return new OrdinalMeta({ + categories: categories, + needCollect: !categories, + deduplication: option.dedplication !== false + }); + }; + + OrdinalMeta.prototype.getOrdinal = function (category) { + return this._getOrCreateMap().get(category); + }; + + OrdinalMeta.prototype.parseAndCollect = function (category) { + var index; + var needCollect = this._needCollect; + + if (typeof category !== 'string' && !needCollect) { + return category; + } + + if (needCollect && !this._deduplication) { + index = this.categories.length; + this.categories[index] = category; + return index; + } + + var map = this._getOrCreateMap(); + + index = map.get(category); + + if (index == null) { + if (needCollect) { + index = this.categories.length; + this.categories[index] = category; + map.set(category, index); + } else { + index = NaN; + } + } + + return index; + }; + + OrdinalMeta.prototype._getOrCreateMap = function () { + return this._map || (this._map = createHashMap(this.categories)); + }; + + return OrdinalMeta; + }(); + + function getName(obj) { + if (isObject(obj) && obj.value != null) { + return obj.value; + } else { + return obj + ''; + } + } + + var roundNumber = round; + function intervalScaleNiceTicks(extent, splitNumber, minInterval, maxInterval) { + var result = {}; + var span = extent[1] - extent[0]; + var interval = result.interval = nice(span / splitNumber, true); + + if (minInterval != null && interval < minInterval) { + interval = result.interval = minInterval; + } + + if (maxInterval != null && interval > maxInterval) { + interval = result.interval = maxInterval; + } + + var precision = result.intervalPrecision = getIntervalPrecision(interval); + var niceTickExtent = result.niceTickExtent = [roundNumber(Math.ceil(extent[0] / interval) * interval, precision), roundNumber(Math.floor(extent[1] / interval) * interval, precision)]; + fixExtent(niceTickExtent, extent); + return result; + } + function getIntervalPrecision(interval) { + return getPrecisionSafe(interval) + 2; + } + + function clamp(niceTickExtent, idx, extent) { + niceTickExtent[idx] = Math.max(Math.min(niceTickExtent[idx], extent[1]), extent[0]); + } + + function fixExtent(niceTickExtent, extent) { + !isFinite(niceTickExtent[0]) && (niceTickExtent[0] = extent[0]); + !isFinite(niceTickExtent[1]) && (niceTickExtent[1] = extent[1]); + clamp(niceTickExtent, 0, extent); + clamp(niceTickExtent, 1, extent); + + if (niceTickExtent[0] > niceTickExtent[1]) { + niceTickExtent[0] = niceTickExtent[1]; + } + } + function contain$1(val, extent) { + return val >= extent[0] && val <= extent[1]; + } + function normalize$1(val, extent) { + if (extent[1] === extent[0]) { + return 0.5; + } + + return (val - extent[0]) / (extent[1] - extent[0]); + } + function scale$2(val, extent) { + return val * (extent[1] - extent[0]) + extent[0]; + } + + var OrdinalScale = function (_super) { + __extends(OrdinalScale, _super); + + function OrdinalScale(setting) { + var _this = _super.call(this, setting) || this; + + _this.type = 'ordinal'; + + var ordinalMeta = _this.getSetting('ordinalMeta'); + + if (!ordinalMeta) { + ordinalMeta = new OrdinalMeta({}); + } + + if (isArray(ordinalMeta)) { + ordinalMeta = new OrdinalMeta({ + categories: map(ordinalMeta, function (item) { + return isObject(item) ? item.value : item; + }) + }); + } + + _this._ordinalMeta = ordinalMeta; + _this._extent = _this.getSetting('extent') || [0, ordinalMeta.categories.length - 1]; + return _this; + } + + OrdinalScale.prototype.parse = function (val) { + return typeof val === 'string' ? this._ordinalMeta.getOrdinal(val) : Math.round(val); + }; + + OrdinalScale.prototype.contain = function (rank) { + rank = this.parse(rank); + return contain$1(rank, this._extent) && this._ordinalMeta.categories[rank] != null; + }; + + OrdinalScale.prototype.normalize = function (val) { + val = this._getTickNumber(this.parse(val)); + return normalize$1(val, this._extent); + }; + + OrdinalScale.prototype.scale = function (val) { + val = Math.round(scale$2(val, this._extent)); + return this.getRawOrdinalNumber(val); + }; + + OrdinalScale.prototype.getTicks = function () { + var ticks = []; + var extent = this._extent; + var rank = extent[0]; + + while (rank <= extent[1]) { + ticks.push({ + value: rank + }); + rank++; + } + + return ticks; + }; + + OrdinalScale.prototype.getMinorTicks = function (splitNumber) { + return; + }; + + OrdinalScale.prototype.setSortInfo = function (info) { + if (info == null) { + this._ordinalNumbersByTick = this._ticksByOrdinalNumber = null; + return; + } + + var infoOrdinalNumbers = info.ordinalNumbers; + var ordinalsByTick = this._ordinalNumbersByTick = []; + var ticksByOrdinal = this._ticksByOrdinalNumber = []; + var tickNum = 0; + var allCategoryLen = this._ordinalMeta.categories.length; + + for (var len = Math.min(allCategoryLen, infoOrdinalNumbers.length); tickNum < len; ++tickNum) { + var ordinalNumber = infoOrdinalNumbers[tickNum]; + ordinalsByTick[tickNum] = ordinalNumber; + ticksByOrdinal[ordinalNumber] = tickNum; + } + + var unusedOrdinal = 0; + + for (; tickNum < allCategoryLen; ++tickNum) { + while (ticksByOrdinal[unusedOrdinal] != null) { + unusedOrdinal++; + } + ordinalsByTick.push(unusedOrdinal); + ticksByOrdinal[unusedOrdinal] = tickNum; + } + }; + + OrdinalScale.prototype._getTickNumber = function (ordinal) { + var ticksByOrdinalNumber = this._ticksByOrdinalNumber; + return ticksByOrdinalNumber && ordinal >= 0 && ordinal < ticksByOrdinalNumber.length ? ticksByOrdinalNumber[ordinal] : ordinal; + }; + + OrdinalScale.prototype.getRawOrdinalNumber = function (tickNumber) { + var ordinalNumbersByTick = this._ordinalNumbersByTick; + return ordinalNumbersByTick && tickNumber >= 0 && tickNumber < ordinalNumbersByTick.length ? ordinalNumbersByTick[tickNumber] : tickNumber; + }; + + OrdinalScale.prototype.getLabel = function (tick) { + if (!this.isBlank()) { + var ordinalNumber = this.getRawOrdinalNumber(tick.value); + var cateogry = this._ordinalMeta.categories[ordinalNumber]; + return cateogry == null ? '' : cateogry + ''; + } + }; + + OrdinalScale.prototype.count = function () { + return this._extent[1] - this._extent[0] + 1; + }; + + OrdinalScale.prototype.unionExtentFromData = function (data, dim) { + this.unionExtent(data.getApproximateExtent(dim)); + }; + + OrdinalScale.prototype.isInExtentRange = function (value) { + value = this._getTickNumber(value); + return this._extent[0] <= value && this._extent[1] >= value; + }; + + OrdinalScale.prototype.getOrdinalMeta = function () { + return this._ordinalMeta; + }; + + OrdinalScale.prototype.niceTicks = function () {}; + + OrdinalScale.prototype.niceExtent = function () {}; + + OrdinalScale.type = 'ordinal'; + return OrdinalScale; + }(Scale); + + Scale.registerClass(OrdinalScale); + + var roundNumber$1 = round; + + var IntervalScale = function (_super) { + __extends(IntervalScale, _super); + + function IntervalScale() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = 'interval'; + _this._interval = 0; + _this._intervalPrecision = 2; + return _this; + } + + IntervalScale.prototype.parse = function (val) { + return val; + }; + + IntervalScale.prototype.contain = function (val) { + return contain$1(val, this._extent); + }; + + IntervalScale.prototype.normalize = function (val) { + return normalize$1(val, this._extent); + }; + + IntervalScale.prototype.scale = function (val) { + return scale$2(val, this._extent); + }; + + IntervalScale.prototype.setExtent = function (start, end) { + var thisExtent = this._extent; + + if (!isNaN(start)) { + thisExtent[0] = parseFloat(start); + } + + if (!isNaN(end)) { + thisExtent[1] = parseFloat(end); + } + }; + + IntervalScale.prototype.unionExtent = function (other) { + var extent = this._extent; + other[0] < extent[0] && (extent[0] = other[0]); + other[1] > extent[1] && (extent[1] = other[1]); + this.setExtent(extent[0], extent[1]); + }; + + IntervalScale.prototype.getInterval = function () { + return this._interval; + }; + + IntervalScale.prototype.setInterval = function (interval) { + this._interval = interval; + this._niceExtent = this._extent.slice(); + this._intervalPrecision = getIntervalPrecision(interval); + }; + + IntervalScale.prototype.getTicks = function (expandToNicedExtent) { + var interval = this._interval; + var extent = this._extent; + var niceTickExtent = this._niceExtent; + var intervalPrecision = this._intervalPrecision; + var ticks = []; + + if (!interval) { + return ticks; + } + + var safeLimit = 10000; + + if (extent[0] < niceTickExtent[0]) { + if (expandToNicedExtent) { + ticks.push({ + value: roundNumber$1(niceTickExtent[0] - interval, intervalPrecision) + }); + } else { + ticks.push({ + value: extent[0] + }); + } + } + + var tick = niceTickExtent[0]; + + while (tick <= niceTickExtent[1]) { + ticks.push({ + value: tick + }); + tick = roundNumber$1(tick + interval, intervalPrecision); + + if (tick === ticks[ticks.length - 1].value) { + break; + } + + if (ticks.length > safeLimit) { + return []; + } + } + + var lastNiceTick = ticks.length ? ticks[ticks.length - 1].value : niceTickExtent[1]; + + if (extent[1] > lastNiceTick) { + if (expandToNicedExtent) { + ticks.push({ + value: roundNumber$1(lastNiceTick + interval, intervalPrecision) + }); + } else { + ticks.push({ + value: extent[1] + }); + } + } + + return ticks; + }; + + IntervalScale.prototype.getMinorTicks = function (splitNumber) { + var ticks = this.getTicks(true); + var minorTicks = []; + var extent = this.getExtent(); + + for (var i = 1; i < ticks.length; i++) { + var nextTick = ticks[i]; + var prevTick = ticks[i - 1]; + var count = 0; + var minorTicksGroup = []; + var interval = nextTick.value - prevTick.value; + var minorInterval = interval / splitNumber; + + while (count < splitNumber - 1) { + var minorTick = roundNumber$1(prevTick.value + (count + 1) * minorInterval); + + if (minorTick > extent[0] && minorTick < extent[1]) { + minorTicksGroup.push(minorTick); + } + + count++; + } + + minorTicks.push(minorTicksGroup); + } + + return minorTicks; + }; + + IntervalScale.prototype.getLabel = function (data, opt) { + if (data == null) { + return ''; + } + + var precision = opt && opt.precision; + + if (precision == null) { + precision = getPrecisionSafe(data.value) || 0; + } else if (precision === 'auto') { + precision = this._intervalPrecision; + } + + var dataNum = roundNumber$1(data.value, precision, true); + return addCommas(dataNum); + }; + + IntervalScale.prototype.niceTicks = function (splitNumber, minInterval, maxInterval) { + splitNumber = splitNumber || 5; + var extent = this._extent; + var span = extent[1] - extent[0]; + + if (!isFinite(span)) { + return; + } + + if (span < 0) { + span = -span; + extent.reverse(); + } + + var result = intervalScaleNiceTicks(extent, splitNumber, minInterval, maxInterval); + this._intervalPrecision = result.intervalPrecision; + this._interval = result.interval; + this._niceExtent = result.niceTickExtent; + }; + + IntervalScale.prototype.niceExtent = function (opt) { + var extent = this._extent; + + if (extent[0] === extent[1]) { + if (extent[0] !== 0) { + var expandSize = extent[0]; + + if (!opt.fixMax) { + extent[1] += expandSize / 2; + extent[0] -= expandSize / 2; + } else { + extent[0] -= expandSize / 2; + } + } else { + extent[1] = 1; + } + } + + var span = extent[1] - extent[0]; + + if (!isFinite(span)) { + extent[0] = 0; + extent[1] = 1; + } + + this.niceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval); + var interval = this._interval; + + if (!opt.fixMin) { + extent[0] = roundNumber$1(Math.floor(extent[0] / interval) * interval); + } + + if (!opt.fixMax) { + extent[1] = roundNumber$1(Math.ceil(extent[1] / interval) * interval); + } + }; + + IntervalScale.type = 'interval'; + return IntervalScale; + }(Scale); + + Scale.registerClass(IntervalScale); + + var STACK_PREFIX = '__ec_stack_'; + var LARGE_BAR_MIN_WIDTH = 0.5; + var LargeArr = typeof Float32Array !== 'undefined' ? Float32Array : Array; + + function getSeriesStackId(seriesModel) { + return seriesModel.get('stack') || STACK_PREFIX + seriesModel.seriesIndex; + } + + function getAxisKey(axis) { + return axis.dim + axis.index; + } + + function getLayoutOnAxis(opt) { + var params = []; + var baseAxis = opt.axis; + var axisKey = 'axis0'; + + if (baseAxis.type !== 'category') { + return; + } + + var bandWidth = baseAxis.getBandWidth(); + + for (var i = 0; i < opt.count || 0; i++) { + params.push(defaults({ + bandWidth: bandWidth, + axisKey: axisKey, + stackId: STACK_PREFIX + i + }, opt)); + } + + var widthAndOffsets = doCalBarWidthAndOffset(params); + var result = []; + + for (var i = 0; i < opt.count; i++) { + var item = widthAndOffsets[axisKey][STACK_PREFIX + i]; + item.offsetCenter = item.offset + item.width / 2; + result.push(item); + } + + return result; + } + function prepareLayoutBarSeries(seriesType, ecModel) { + var seriesModels = []; + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + if (isOnCartesian(seriesModel) && !isInLargeMode(seriesModel)) { + seriesModels.push(seriesModel); + } + }); + return seriesModels; + } + + function getValueAxesMinGaps(barSeries) { + var axisValues = {}; + each(barSeries, function (seriesModel) { + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + + if (baseAxis.type !== 'time' && baseAxis.type !== 'value') { + return; + } + + var data = seriesModel.getData(); + var key = baseAxis.dim + '_' + baseAxis.index; + var dim = data.mapDimension(baseAxis.dim); + + for (var i = 0, cnt = data.count(); i < cnt; ++i) { + var value = data.get(dim, i); + + if (!axisValues[key]) { + axisValues[key] = [value]; + } else { + axisValues[key].push(value); + } + } + }); + var axisMinGaps = {}; + + for (var key in axisValues) { + if (axisValues.hasOwnProperty(key)) { + var valuesInAxis = axisValues[key]; + + if (valuesInAxis) { + valuesInAxis.sort(function (a, b) { + return a - b; + }); + var min = null; + + for (var j = 1; j < valuesInAxis.length; ++j) { + var delta = valuesInAxis[j] - valuesInAxis[j - 1]; + + if (delta > 0) { + min = min === null ? delta : Math.min(min, delta); + } + } + + axisMinGaps[key] = min; + } + } + } + + return axisMinGaps; + } + + function makeColumnLayout(barSeries) { + var axisMinGaps = getValueAxesMinGaps(barSeries); + var seriesInfoList = []; + each(barSeries, function (seriesModel) { + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + var axisExtent = baseAxis.getExtent(); + var bandWidth; + + if (baseAxis.type === 'category') { + bandWidth = baseAxis.getBandWidth(); + } else if (baseAxis.type === 'value' || baseAxis.type === 'time') { + var key = baseAxis.dim + '_' + baseAxis.index; + var minGap = axisMinGaps[key]; + var extentSpan = Math.abs(axisExtent[1] - axisExtent[0]); + var scale = baseAxis.scale.getExtent(); + var scaleSpan = Math.abs(scale[1] - scale[0]); + bandWidth = minGap ? extentSpan / scaleSpan * minGap : extentSpan; + } else { + var data = seriesModel.getData(); + bandWidth = Math.abs(axisExtent[1] - axisExtent[0]) / data.count(); + } + + var barWidth = parsePercent$1(seriesModel.get('barWidth'), bandWidth); + var barMaxWidth = parsePercent$1(seriesModel.get('barMaxWidth'), bandWidth); + var barMinWidth = parsePercent$1(seriesModel.get('barMinWidth') || 1, bandWidth); + var barGap = seriesModel.get('barGap'); + var barCategoryGap = seriesModel.get('barCategoryGap'); + seriesInfoList.push({ + bandWidth: bandWidth, + barWidth: barWidth, + barMaxWidth: barMaxWidth, + barMinWidth: barMinWidth, + barGap: barGap, + barCategoryGap: barCategoryGap, + axisKey: getAxisKey(baseAxis), + stackId: getSeriesStackId(seriesModel) + }); + }); + return doCalBarWidthAndOffset(seriesInfoList); + } + + function doCalBarWidthAndOffset(seriesInfoList) { + var columnsMap = {}; + each(seriesInfoList, function (seriesInfo, idx) { + var axisKey = seriesInfo.axisKey; + var bandWidth = seriesInfo.bandWidth; + var columnsOnAxis = columnsMap[axisKey] || { + bandWidth: bandWidth, + remainedWidth: bandWidth, + autoWidthCount: 0, + categoryGap: null, + gap: '20%', + stacks: {} + }; + var stacks = columnsOnAxis.stacks; + columnsMap[axisKey] = columnsOnAxis; + var stackId = seriesInfo.stackId; + + if (!stacks[stackId]) { + columnsOnAxis.autoWidthCount++; + } + + stacks[stackId] = stacks[stackId] || { + width: 0, + maxWidth: 0 + }; + var barWidth = seriesInfo.barWidth; + + if (barWidth && !stacks[stackId].width) { + stacks[stackId].width = barWidth; + barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth); + columnsOnAxis.remainedWidth -= barWidth; + } + + var barMaxWidth = seriesInfo.barMaxWidth; + barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth); + var barMinWidth = seriesInfo.barMinWidth; + barMinWidth && (stacks[stackId].minWidth = barMinWidth); + var barGap = seriesInfo.barGap; + barGap != null && (columnsOnAxis.gap = barGap); + var barCategoryGap = seriesInfo.barCategoryGap; + barCategoryGap != null && (columnsOnAxis.categoryGap = barCategoryGap); + }); + var result = {}; + each(columnsMap, function (columnsOnAxis, coordSysName) { + result[coordSysName] = {}; + var stacks = columnsOnAxis.stacks; + var bandWidth = columnsOnAxis.bandWidth; + var categoryGapPercent = columnsOnAxis.categoryGap; + + if (categoryGapPercent == null) { + var columnCount = keys(stacks).length; + categoryGapPercent = Math.max(35 - columnCount * 4, 15) + '%'; + } + + var categoryGap = parsePercent$1(categoryGapPercent, bandWidth); + var barGapPercent = parsePercent$1(columnsOnAxis.gap, 1); + var remainedWidth = columnsOnAxis.remainedWidth; + var autoWidthCount = columnsOnAxis.autoWidthCount; + var autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); + each(stacks, function (column) { + var maxWidth = column.maxWidth; + var minWidth = column.minWidth; + + if (!column.width) { + var finalWidth = autoWidth; + + if (maxWidth && maxWidth < finalWidth) { + finalWidth = Math.min(maxWidth, remainedWidth); + } + + if (minWidth && minWidth > finalWidth) { + finalWidth = minWidth; + } + + if (finalWidth !== autoWidth) { + column.width = finalWidth; + remainedWidth -= finalWidth + barGapPercent * finalWidth; + autoWidthCount--; + } + } else { + var finalWidth = column.width; + + if (maxWidth) { + finalWidth = Math.min(finalWidth, maxWidth); + } + + if (minWidth) { + finalWidth = Math.max(finalWidth, minWidth); + } + + column.width = finalWidth; + remainedWidth -= finalWidth + barGapPercent * finalWidth; + autoWidthCount--; + } + }); + autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); + var widthSum = 0; + var lastColumn; + each(stacks, function (column, idx) { + if (!column.width) { + column.width = autoWidth; + } + + lastColumn = column; + widthSum += column.width * (1 + barGapPercent); + }); + + if (lastColumn) { + widthSum -= lastColumn.width * barGapPercent; + } + + var offset = -widthSum / 2; + each(stacks, function (column, stackId) { + result[coordSysName][stackId] = result[coordSysName][stackId] || { + bandWidth: bandWidth, + offset: offset, + width: column.width + }; + offset += column.width * (1 + barGapPercent); + }); + }); + return result; + } + + function retrieveColumnLayout(barWidthAndOffset, axis, seriesModel) { + if (barWidthAndOffset && axis) { + var result = barWidthAndOffset[getAxisKey(axis)]; + + if (result != null && seriesModel != null) { + return result[getSeriesStackId(seriesModel)]; + } + + return result; + } + } + function layout(seriesType, ecModel) { + var seriesModels = prepareLayoutBarSeries(seriesType, ecModel); + var barWidthAndOffset = makeColumnLayout(seriesModels); + var lastStackCoords = {}; + each(seriesModels, function (seriesModel) { + var data = seriesModel.getData(); + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + var stackId = getSeriesStackId(seriesModel); + var columnLayoutInfo = barWidthAndOffset[getAxisKey(baseAxis)][stackId]; + var columnOffset = columnLayoutInfo.offset; + var columnWidth = columnLayoutInfo.width; + var valueAxis = cartesian.getOtherAxis(baseAxis); + var barMinHeight = seriesModel.get('barMinHeight') || 0; + lastStackCoords[stackId] = lastStackCoords[stackId] || []; + data.setLayout({ + bandWidth: columnLayoutInfo.bandWidth, + offset: columnOffset, + size: columnWidth + }); + var valueDim = data.mapDimension(valueAxis.dim); + var baseDim = data.mapDimension(baseAxis.dim); + var stacked = isDimensionStacked(data, valueDim); + var isValueAxisH = valueAxis.isHorizontal(); + var valueAxisStart = getValueAxisStart(baseAxis, valueAxis); + + for (var idx = 0, len = data.count(); idx < len; idx++) { + var value = data.get(valueDim, idx); + var baseValue = data.get(baseDim, idx); + var sign = value >= 0 ? 'p' : 'n'; + var baseCoord = valueAxisStart; + + if (stacked) { + if (!lastStackCoords[stackId][baseValue]) { + lastStackCoords[stackId][baseValue] = { + p: valueAxisStart, + n: valueAxisStart + }; + } + + baseCoord = lastStackCoords[stackId][baseValue][sign]; + } + + var x = void 0; + var y = void 0; + var width = void 0; + var height = void 0; + + if (isValueAxisH) { + var coord = cartesian.dataToPoint([value, baseValue]); + x = baseCoord; + y = coord[1] + columnOffset; + width = coord[0] - valueAxisStart; + height = columnWidth; + + if (Math.abs(width) < barMinHeight) { + width = (width < 0 ? -1 : 1) * barMinHeight; + } + + if (!isNaN(width)) { + stacked && (lastStackCoords[stackId][baseValue][sign] += width); + } + } else { + var coord = cartesian.dataToPoint([baseValue, value]); + x = coord[0] + columnOffset; + y = baseCoord; + width = columnWidth; + height = coord[1] - valueAxisStart; + + if (Math.abs(height) < barMinHeight) { + height = (height <= 0 ? -1 : 1) * barMinHeight; + } + + if (!isNaN(height)) { + stacked && (lastStackCoords[stackId][baseValue][sign] += height); + } + } + + data.setItemLayout(idx, { + x: x, + y: y, + width: width, + height: height + }); + } + }); + } + var largeLayout = { + seriesType: 'bar', + plan: createRenderPlanner(), + reset: function (seriesModel) { + if (!isOnCartesian(seriesModel) || !isInLargeMode(seriesModel)) { + return; + } + + var data = seriesModel.getData(); + var cartesian = seriesModel.coordinateSystem; + var coordLayout = cartesian.master.getRect(); + var baseAxis = cartesian.getBaseAxis(); + var valueAxis = cartesian.getOtherAxis(baseAxis); + var valueDim = data.mapDimension(valueAxis.dim); + var baseDim = data.mapDimension(baseAxis.dim); + var valueAxisHorizontal = valueAxis.isHorizontal(); + var valueDimIdx = valueAxisHorizontal ? 0 : 1; + var barWidth = retrieveColumnLayout(makeColumnLayout([seriesModel]), baseAxis, seriesModel).width; + + if (!(barWidth > LARGE_BAR_MIN_WIDTH)) { + barWidth = LARGE_BAR_MIN_WIDTH; + } + + return { + progress: function (params, data) { + var count = params.count; + var largePoints = new LargeArr(count * 2); + var largeBackgroundPoints = new LargeArr(count * 2); + var largeDataIndices = new LargeArr(count); + var dataIndex; + var coord = []; + var valuePair = []; + var pointsOffset = 0; + var idxOffset = 0; + + while ((dataIndex = params.next()) != null) { + valuePair[valueDimIdx] = data.get(valueDim, dataIndex); + valuePair[1 - valueDimIdx] = data.get(baseDim, dataIndex); + coord = cartesian.dataToPoint(valuePair, null, coord); + largeBackgroundPoints[pointsOffset] = valueAxisHorizontal ? coordLayout.x + coordLayout.width : coord[0]; + largePoints[pointsOffset++] = coord[0]; + largeBackgroundPoints[pointsOffset] = valueAxisHorizontal ? coord[1] : coordLayout.y + coordLayout.height; + largePoints[pointsOffset++] = coord[1]; + largeDataIndices[idxOffset++] = dataIndex; + } + + data.setLayout({ + largePoints: largePoints, + largeDataIndices: largeDataIndices, + largeBackgroundPoints: largeBackgroundPoints, + barWidth: barWidth, + valueAxisStart: getValueAxisStart(baseAxis, valueAxis), + backgroundStart: valueAxisHorizontal ? coordLayout.x : coordLayout.y, + valueAxisHorizontal: valueAxisHorizontal + }); + } + }; + } + }; + + function isOnCartesian(seriesModel) { + return seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'cartesian2d'; + } + + function isInLargeMode(seriesModel) { + return seriesModel.pipelineContext && seriesModel.pipelineContext.large; + } + + function getValueAxisStart(baseAxis, valueAxis, stacked) { + return valueAxis.toGlobalCoord(valueAxis.dataToCoord(valueAxis.type === 'log' ? 1 : 0)); + } + + var bisect = function (a, x, lo, hi) { + while (lo < hi) { + var mid = lo + hi >>> 1; + + if (a[mid][1] < x) { + lo = mid + 1; + } else { + hi = mid; + } + } + + return lo; + }; + + var TimeScale = function (_super) { + __extends(TimeScale, _super); + + function TimeScale(settings) { + var _this = _super.call(this, settings) || this; + + _this.type = 'time'; + return _this; + } + + TimeScale.prototype.getLabel = function (tick) { + var useUTC = this.getSetting('useUTC'); + return format(tick.value, fullLeveledFormatter[getDefaultFormatPrecisionOfInterval(getPrimaryTimeUnit(this._minLevelUnit))] || fullLeveledFormatter.second, useUTC, this.getSetting('locale')); + }; + + TimeScale.prototype.getFormattedLabel = function (tick, idx, labelFormatter) { + var isUTC = this.getSetting('useUTC'); + var lang = this.getSetting('locale'); + return leveledFormat(tick, idx, labelFormatter, lang, isUTC); + }; + + TimeScale.prototype.getTicks = function (expandToNicedExtent) { + var interval = this._interval; + var extent = this._extent; + var ticks = []; + + if (!interval) { + return ticks; + } + + ticks.push({ + value: extent[0], + level: 0 + }); + var useUTC = this.getSetting('useUTC'); + var innerTicks = getIntervalTicks(this._minLevelUnit, this._approxInterval, useUTC, extent); + ticks = ticks.concat(innerTicks); + ticks.push({ + value: extent[1], + level: 0 + }); + return ticks; + }; + + TimeScale.prototype.niceExtent = function (opt) { + var extent = this._extent; + + if (extent[0] === extent[1]) { + extent[0] -= ONE_DAY; + extent[1] += ONE_DAY; + } + + if (extent[1] === -Infinity && extent[0] === Infinity) { + var d = new Date(); + extent[1] = +new Date(d.getFullYear(), d.getMonth(), d.getDate()); + extent[0] = extent[1] - ONE_DAY; + } + + this.niceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval); + }; + + TimeScale.prototype.niceTicks = function (approxTickNum, minInterval, maxInterval) { + approxTickNum = approxTickNum || 10; + var extent = this._extent; + var span = extent[1] - extent[0]; + this._approxInterval = span / approxTickNum; + + if (minInterval != null && this._approxInterval < minInterval) { + this._approxInterval = minInterval; + } + + if (maxInterval != null && this._approxInterval > maxInterval) { + this._approxInterval = maxInterval; + } + + var scaleIntervalsLen = scaleIntervals.length; + var idx = Math.min(bisect(scaleIntervals, this._approxInterval, 0, scaleIntervalsLen), scaleIntervalsLen - 1); + this._interval = scaleIntervals[idx][1]; + this._minLevelUnit = scaleIntervals[Math.max(idx - 1, 0)][0]; + }; + + TimeScale.prototype.parse = function (val) { + return typeof val === 'number' ? val : +parseDate(val); + }; + + TimeScale.prototype.contain = function (val) { + return contain$1(this.parse(val), this._extent); + }; + + TimeScale.prototype.normalize = function (val) { + return normalize$1(this.parse(val), this._extent); + }; + + TimeScale.prototype.scale = function (val) { + return scale$2(val, this._extent); + }; + + TimeScale.type = 'time'; + return TimeScale; + }(IntervalScale); + + var scaleIntervals = [['second', ONE_SECOND], ['minute', ONE_MINUTE], ['hour', ONE_HOUR], ['quarter-day', ONE_HOUR * 6], ['half-day', ONE_HOUR * 12], ['day', ONE_DAY * 1.2], ['half-week', ONE_DAY * 3.5], ['week', ONE_DAY * 7], ['month', ONE_DAY * 31], ['quarter', ONE_DAY * 95], ['half-year', ONE_YEAR / 2], ['year', ONE_YEAR]]; + + function isUnitValueSame(unit, valueA, valueB, isUTC) { + var dateA = parseDate(valueA); + var dateB = parseDate(valueB); + + var isSame = function (unit) { + return getUnitValue(dateA, unit, isUTC) === getUnitValue(dateB, unit, isUTC); + }; + + var isSameYear = function () { + return isSame('year'); + }; + + var isSameMonth = function () { + return isSameYear() && isSame('month'); + }; + + var isSameDay = function () { + return isSameMonth() && isSame('day'); + }; + + var isSameHour = function () { + return isSameDay() && isSame('hour'); + }; + + var isSameMinute = function () { + return isSameHour() && isSame('minute'); + }; + + var isSameSecond = function () { + return isSameMinute() && isSame('second'); + }; + + var isSameMilliSecond = function () { + return isSameSecond() && isSame('millisecond'); + }; + + switch (unit) { + case 'year': + return isSameYear(); + + case 'month': + return isSameMonth(); + + case 'day': + return isSameDay(); + + case 'hour': + return isSameHour(); + + case 'minute': + return isSameMinute(); + + case 'second': + return isSameSecond(); + + case 'millisecond': + return isSameMilliSecond(); + } + } + + function getDateInterval(approxInterval, daysInMonth) { + approxInterval /= ONE_DAY; + return approxInterval > 16 ? 16 : approxInterval > 7.5 ? 7 : approxInterval > 3.5 ? 4 : approxInterval > 1.5 ? 2 : 1; + } + + function getMonthInterval(approxInterval) { + var APPROX_ONE_MONTH = 30 * ONE_DAY; + approxInterval /= APPROX_ONE_MONTH; + return approxInterval > 6 ? 6 : approxInterval > 3 ? 3 : approxInterval > 2 ? 2 : 1; + } + + function getHourInterval(approxInterval) { + approxInterval /= ONE_HOUR; + return approxInterval > 12 ? 12 : approxInterval > 6 ? 6 : approxInterval > 3.5 ? 4 : approxInterval > 2 ? 2 : 1; + } + + function getMinutesAndSecondsInterval(approxInterval, isMinutes) { + approxInterval /= isMinutes ? ONE_MINUTE : ONE_SECOND; + return approxInterval > 30 ? 30 : approxInterval > 20 ? 20 : approxInterval > 15 ? 15 : approxInterval > 10 ? 10 : approxInterval > 5 ? 5 : approxInterval > 2 ? 2 : 1; + } + + function getMillisecondsInterval(approxInterval) { + return nice(approxInterval, true); + } + + function getFirstTimestampOfUnit(date, unitName, isUTC) { + var outDate = new Date(date); + + switch (getPrimaryTimeUnit(unitName)) { + case 'year': + case 'month': + outDate[monthSetterName(isUTC)](0); + + case 'day': + outDate[dateSetterName(isUTC)](1); + + case 'hour': + outDate[hoursSetterName(isUTC)](0); + + case 'minute': + outDate[minutesSetterName(isUTC)](0); + + case 'second': + outDate[secondsSetterName(isUTC)](0); + outDate[millisecondsSetterName(isUTC)](0); + } + + return outDate.getTime(); + } + + function getIntervalTicks(bottomUnitName, approxInterval, isUTC, extent) { + var safeLimit = 10000; + var unitNames = timeUnits; + var iter = 0; + + function addTicksInSpan(interval, minTimestamp, maxTimestamp, getMethodName, setMethodName, isDate, out) { + var date = new Date(minTimestamp); + var dateTime = minTimestamp; + var d = date[getMethodName](); + + while (dateTime < maxTimestamp && dateTime <= extent[1]) { + out.push({ + value: dateTime + }); + d += interval; + date[setMethodName](d); + dateTime = date.getTime(); + } + + out.push({ + value: dateTime, + notAdd: true + }); + } + + function addLevelTicks(unitName, lastLevelTicks, levelTicks) { + var newAddedTicks = []; + var isFirstLevel = !lastLevelTicks.length; + + if (isUnitValueSame(getPrimaryTimeUnit(unitName), extent[0], extent[1], isUTC)) { + return; + } + + if (isFirstLevel) { + lastLevelTicks = [{ + value: getFirstTimestampOfUnit(new Date(extent[0]), unitName, isUTC) + }, { + value: extent[1] + }]; + } + + for (var i = 0; i < lastLevelTicks.length - 1; i++) { + var startTick = lastLevelTicks[i].value; + var endTick = lastLevelTicks[i + 1].value; + + if (startTick === endTick) { + continue; + } + + var interval = void 0; + var getterName = void 0; + var setterName = void 0; + var isDate = false; + + switch (unitName) { + case 'year': + interval = Math.max(1, Math.round(approxInterval / ONE_DAY / 365)); + getterName = fullYearGetterName(isUTC); + setterName = fullYearSetterName(isUTC); + break; + + case 'half-year': + case 'quarter': + case 'month': + interval = getMonthInterval(approxInterval); + getterName = monthGetterName(isUTC); + setterName = monthSetterName(isUTC); + break; + + case 'week': + case 'half-week': + case 'day': + interval = getDateInterval(approxInterval); + getterName = dateGetterName(isUTC); + setterName = dateSetterName(isUTC); + isDate = true; + break; + + case 'half-day': + case 'quarter-day': + case 'hour': + interval = getHourInterval(approxInterval); + getterName = hoursGetterName(isUTC); + setterName = hoursSetterName(isUTC); + break; + + case 'minute': + interval = getMinutesAndSecondsInterval(approxInterval, true); + getterName = minutesGetterName(isUTC); + setterName = minutesSetterName(isUTC); + break; + + case 'second': + interval = getMinutesAndSecondsInterval(approxInterval, false); + getterName = secondsGetterName(isUTC); + setterName = secondsSetterName(isUTC); + break; + + case 'millisecond': + interval = getMillisecondsInterval(approxInterval); + getterName = millisecondsGetterName(isUTC); + setterName = millisecondsSetterName(isUTC); + break; + } + + addTicksInSpan(interval, startTick, endTick, getterName, setterName, isDate, newAddedTicks); + + if (unitName === 'year' && levelTicks.length > 1 && i === 0) { + levelTicks.unshift({ + value: levelTicks[0].value - interval + }); + } + } + + for (var i = 0; i < newAddedTicks.length; i++) { + levelTicks.push(newAddedTicks[i]); + } + + return newAddedTicks; + } + + var levelsTicks = []; + var currentLevelTicks = []; + var tickCount = 0; + var lastLevelTickCount = 0; + + for (var i = 0; i < unitNames.length && iter++ < safeLimit; ++i) { + var primaryTimeUnit = getPrimaryTimeUnit(unitNames[i]); + + if (!isPrimaryTimeUnit(unitNames[i])) { + continue; + } + + addLevelTicks(unitNames[i], levelsTicks[levelsTicks.length - 1] || [], currentLevelTicks); + var nextPrimaryTimeUnit = unitNames[i + 1] ? getPrimaryTimeUnit(unitNames[i + 1]) : null; + + if (primaryTimeUnit !== nextPrimaryTimeUnit) { + if (currentLevelTicks.length) { + lastLevelTickCount = tickCount; + currentLevelTicks.sort(function (a, b) { + return a.value - b.value; + }); + var levelTicksRemoveDuplicated = []; + + for (var i_1 = 0; i_1 < currentLevelTicks.length; ++i_1) { + var tickValue = currentLevelTicks[i_1].value; + + if (i_1 === 0 || currentLevelTicks[i_1 - 1].value !== tickValue) { + levelTicksRemoveDuplicated.push(currentLevelTicks[i_1]); + + if (tickValue >= extent[0] && tickValue <= extent[1]) { + tickCount++; + } + } + } + + var targetTickNum = (extent[1] - extent[0]) / approxInterval; + + if (tickCount > targetTickNum * 1.5 && lastLevelTickCount > targetTickNum / 1.5) { + break; + } + + levelsTicks.push(levelTicksRemoveDuplicated); + + if (tickCount > targetTickNum || bottomUnitName === unitNames[i]) { + break; + } + } + + currentLevelTicks = []; + } + } + + if ("development" !== 'production') { + if (iter >= safeLimit) { + warn('Exceed safe limit.'); + } + } + + var levelsTicksInExtent = filter(map(levelsTicks, function (levelTicks) { + return filter(levelTicks, function (tick) { + return tick.value >= extent[0] && tick.value <= extent[1] && !tick.notAdd; + }); + }), function (levelTicks) { + return levelTicks.length > 0; + }); + var ticks = []; + var maxLevel = levelsTicksInExtent.length - 1; + + for (var i = 0; i < levelsTicksInExtent.length; ++i) { + var levelTicks = levelsTicksInExtent[i]; + + for (var k = 0; k < levelTicks.length; ++k) { + ticks.push({ + value: levelTicks[k].value, + level: maxLevel - i + }); + } + } + + ticks.sort(function (a, b) { + return a.value - b.value; + }); + var result = []; + + for (var i = 0; i < ticks.length; ++i) { + if (i === 0 || ticks[i].value !== ticks[i - 1].value) { + result.push(ticks[i]); + } + } + + return result; + } + + Scale.registerClass(TimeScale); + + var scaleProto = Scale.prototype; + var intervalScaleProto = IntervalScale.prototype; + var getPrecisionSafe$1 = getPrecisionSafe; + var roundingErrorFix = round; + var mathFloor$1 = Math.floor; + var mathCeil = Math.ceil; + var mathPow$1 = Math.pow; + var mathLog = Math.log; + + var LogScale = function (_super) { + __extends(LogScale, _super); + + function LogScale() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = 'log'; + _this.base = 10; + _this._originalScale = new IntervalScale(); + _this._interval = 0; + return _this; + } + + LogScale.prototype.getTicks = function (expandToNicedExtent) { + var originalScale = this._originalScale; + var extent = this._extent; + var originalExtent = originalScale.getExtent(); + var ticks = intervalScaleProto.getTicks.call(this, expandToNicedExtent); + return map(ticks, function (tick) { + var val = tick.value; + var powVal = round(mathPow$1(this.base, val)); + powVal = val === extent[0] && this._fixMin ? fixRoundingError(powVal, originalExtent[0]) : powVal; + powVal = val === extent[1] && this._fixMax ? fixRoundingError(powVal, originalExtent[1]) : powVal; + return { + value: powVal + }; + }, this); + }; + + LogScale.prototype.setExtent = function (start, end) { + var base = this.base; + start = mathLog(start) / mathLog(base); + end = mathLog(end) / mathLog(base); + intervalScaleProto.setExtent.call(this, start, end); + }; + + LogScale.prototype.getExtent = function () { + var base = this.base; + var extent = scaleProto.getExtent.call(this); + extent[0] = mathPow$1(base, extent[0]); + extent[1] = mathPow$1(base, extent[1]); + var originalScale = this._originalScale; + var originalExtent = originalScale.getExtent(); + this._fixMin && (extent[0] = fixRoundingError(extent[0], originalExtent[0])); + this._fixMax && (extent[1] = fixRoundingError(extent[1], originalExtent[1])); + return extent; + }; + + LogScale.prototype.unionExtent = function (extent) { + this._originalScale.unionExtent(extent); + + var base = this.base; + extent[0] = mathLog(extent[0]) / mathLog(base); + extent[1] = mathLog(extent[1]) / mathLog(base); + scaleProto.unionExtent.call(this, extent); + }; + + LogScale.prototype.unionExtentFromData = function (data, dim) { + this.unionExtent(data.getApproximateExtent(dim)); + }; + + LogScale.prototype.niceTicks = function (approxTickNum) { + approxTickNum = approxTickNum || 10; + var extent = this._extent; + var span = extent[1] - extent[0]; + + if (span === Infinity || span <= 0) { + return; + } + + var interval = quantity(span); + var err = approxTickNum / span * interval; + + if (err <= 0.5) { + interval *= 10; + } + + while (!isNaN(interval) && Math.abs(interval) < 1 && Math.abs(interval) > 0) { + interval *= 10; + } + + var niceExtent = [round(mathCeil(extent[0] / interval) * interval), round(mathFloor$1(extent[1] / interval) * interval)]; + this._interval = interval; + this._niceExtent = niceExtent; + }; + + LogScale.prototype.niceExtent = function (opt) { + intervalScaleProto.niceExtent.call(this, opt); + this._fixMin = opt.fixMin; + this._fixMax = opt.fixMax; + }; + + LogScale.prototype.parse = function (val) { + return val; + }; + + LogScale.prototype.contain = function (val) { + val = mathLog(val) / mathLog(this.base); + return contain$1(val, this._extent); + }; + + LogScale.prototype.normalize = function (val) { + val = mathLog(val) / mathLog(this.base); + return normalize$1(val, this._extent); + }; + + LogScale.prototype.scale = function (val) { + val = scale$2(val, this._extent); + return mathPow$1(this.base, val); + }; + + LogScale.type = 'log'; + return LogScale; + }(Scale); + + var proto = LogScale.prototype; + proto.getMinorTicks = intervalScaleProto.getMinorTicks; + proto.getLabel = intervalScaleProto.getLabel; + + function fixRoundingError(val, originalVal) { + return roundingErrorFix(val, getPrecisionSafe$1(originalVal)); + } + + Scale.registerClass(LogScale); + + var ScaleRawExtentInfo = function () { + function ScaleRawExtentInfo(scale, model, originalExtent) { + this._prepareParams(scale, model, originalExtent); + } + + ScaleRawExtentInfo.prototype._prepareParams = function (scale, model, dataExtent) { + if (dataExtent[1] < dataExtent[0]) { + dataExtent = [NaN, NaN]; + } + + this._dataMin = dataExtent[0]; + this._dataMax = dataExtent[1]; + var isOrdinal = this._isOrdinal = scale.type === 'ordinal'; + this._needCrossZero = model.getNeedCrossZero && model.getNeedCrossZero(); + var modelMinRaw = this._modelMinRaw = model.get('min', true); + + if (isFunction(modelMinRaw)) { + this._modelMinNum = parseAxisModelMinMax(scale, modelMinRaw({ + min: dataExtent[0], + max: dataExtent[1] + })); + } else if (modelMinRaw !== 'dataMin') { + this._modelMinNum = parseAxisModelMinMax(scale, modelMinRaw); + } + + var modelMaxRaw = this._modelMaxRaw = model.get('max', true); + + if (isFunction(modelMaxRaw)) { + this._modelMaxNum = parseAxisModelMinMax(scale, modelMaxRaw({ + min: dataExtent[0], + max: dataExtent[1] + })); + } else if (modelMaxRaw !== 'dataMax') { + this._modelMaxNum = parseAxisModelMinMax(scale, modelMaxRaw); + } + + if (isOrdinal) { + this._axisDataLen = model.getCategories().length; + } else { + var boundaryGap = model.get('boundaryGap'); + var boundaryGapArr = isArray(boundaryGap) ? boundaryGap : [boundaryGap || 0, boundaryGap || 0]; + + if (typeof boundaryGapArr[0] === 'boolean' || typeof boundaryGapArr[1] === 'boolean') { + if ("development" !== 'production') { + console.warn('Boolean type for boundaryGap is only ' + 'allowed for ordinal axis. Please use string in ' + 'percentage instead, e.g., "20%". Currently, ' + 'boundaryGap is set to be 0.'); + } + + this._boundaryGapInner = [0, 0]; + } else { + this._boundaryGapInner = [parsePercent(boundaryGapArr[0], 1), parsePercent(boundaryGapArr[1], 1)]; + } + } + }; + + ScaleRawExtentInfo.prototype.calculate = function () { + var isOrdinal = this._isOrdinal; + var dataMin = this._dataMin; + var dataMax = this._dataMax; + var axisDataLen = this._axisDataLen; + var boundaryGapInner = this._boundaryGapInner; + var span = !isOrdinal ? dataMax - dataMin || Math.abs(dataMin) : null; + var min = this._modelMinRaw === 'dataMin' ? dataMin : this._modelMinNum; + var max = this._modelMaxRaw === 'dataMax' ? dataMax : this._modelMaxNum; + var minFixed = min != null; + var maxFixed = max != null; + + if (min == null) { + min = isOrdinal ? axisDataLen ? 0 : NaN : dataMin - boundaryGapInner[0] * span; + } + + if (max == null) { + max = isOrdinal ? axisDataLen ? axisDataLen - 1 : NaN : dataMax + boundaryGapInner[1] * span; + } + + (min == null || !isFinite(min)) && (min = NaN); + (max == null || !isFinite(max)) && (max = NaN); + + if (min > max) { + min = NaN; + max = NaN; + } + + var isBlank = eqNaN(min) || eqNaN(max) || isOrdinal && !axisDataLen; + + if (this._needCrossZero) { + if (min > 0 && max > 0 && !minFixed) { + min = 0; + } + + if (min < 0 && max < 0 && !maxFixed) { + max = 0; + } + } + + var determinedMin = this._determinedMin; + var determinedMax = this._determinedMax; + + if (determinedMin != null) { + min = determinedMin; + minFixed = true; + } + + if (determinedMax != null) { + max = determinedMax; + maxFixed = true; + } + + return { + min: min, + max: max, + minFixed: minFixed, + maxFixed: maxFixed, + isBlank: isBlank + }; + }; + + ScaleRawExtentInfo.prototype.modifyDataMinMax = function (minMaxName, val) { + if ("development" !== 'production') { + assert(!this.frozen); + } + + this[DATA_MIN_MAX_ATTR[minMaxName]] = val; + }; + + ScaleRawExtentInfo.prototype.setDeterminedMinMax = function (minMaxName, val) { + var attr = DETERMINED_MIN_MAX_ATTR[minMaxName]; + + if ("development" !== 'production') { + assert(!this.frozen && this[attr] == null); + } + + this[attr] = val; + }; + + ScaleRawExtentInfo.prototype.freeze = function () { + this.frozen = true; + }; + + return ScaleRawExtentInfo; + }(); + var DETERMINED_MIN_MAX_ATTR = { + min: '_determinedMin', + max: '_determinedMax' + }; + var DATA_MIN_MAX_ATTR = { + min: '_dataMin', + max: '_dataMax' + }; + function ensureScaleRawExtentInfo(scale, model, originalExtent) { + var rawExtentInfo = scale.rawExtentInfo; + + if (rawExtentInfo) { + return rawExtentInfo; + } + + rawExtentInfo = new ScaleRawExtentInfo(scale, model, originalExtent); + scale.rawExtentInfo = rawExtentInfo; + return rawExtentInfo; + } + function parseAxisModelMinMax(scale, minMax) { + return minMax == null ? null : eqNaN(minMax) ? NaN : scale.parse(minMax); + } + + function getScaleExtent(scale, model) { + var scaleType = scale.type; + var rawExtentResult = ensureScaleRawExtentInfo(scale, model, scale.getExtent()).calculate(); + scale.setBlank(rawExtentResult.isBlank); + var min = rawExtentResult.min; + var max = rawExtentResult.max; + var ecModel = model.ecModel; + + if (ecModel && scaleType === 'time') { + var barSeriesModels = prepareLayoutBarSeries('bar', ecModel); + var isBaseAxisAndHasBarSeries_1 = false; + each(barSeriesModels, function (seriesModel) { + isBaseAxisAndHasBarSeries_1 = isBaseAxisAndHasBarSeries_1 || seriesModel.getBaseAxis() === model.axis; + }); + + if (isBaseAxisAndHasBarSeries_1) { + var barWidthAndOffset = makeColumnLayout(barSeriesModels); + var adjustedScale = adjustScaleForOverflow(min, max, model, barWidthAndOffset); + min = adjustedScale.min; + max = adjustedScale.max; + } + } + + return { + extent: [min, max], + fixMin: rawExtentResult.minFixed, + fixMax: rawExtentResult.maxFixed + }; + } + + function adjustScaleForOverflow(min, max, model, barWidthAndOffset) { + var axisExtent = model.axis.getExtent(); + var axisLength = axisExtent[1] - axisExtent[0]; + var barsOnCurrentAxis = retrieveColumnLayout(barWidthAndOffset, model.axis); + + if (barsOnCurrentAxis === undefined) { + return { + min: min, + max: max + }; + } + + var minOverflow = Infinity; + each(barsOnCurrentAxis, function (item) { + minOverflow = Math.min(item.offset, minOverflow); + }); + var maxOverflow = -Infinity; + each(barsOnCurrentAxis, function (item) { + maxOverflow = Math.max(item.offset + item.width, maxOverflow); + }); + minOverflow = Math.abs(minOverflow); + maxOverflow = Math.abs(maxOverflow); + var totalOverFlow = minOverflow + maxOverflow; + var oldRange = max - min; + var oldRangePercentOfNew = 1 - (minOverflow + maxOverflow) / axisLength; + var overflowBuffer = oldRange / oldRangePercentOfNew - oldRange; + max += overflowBuffer * (maxOverflow / totalOverFlow); + min -= overflowBuffer * (minOverflow / totalOverFlow); + return { + min: min, + max: max + }; + } + + function niceScaleExtent(scale, model) { + var extentInfo = getScaleExtent(scale, model); + var extent = extentInfo.extent; + var splitNumber = model.get('splitNumber'); + + if (scale instanceof LogScale) { + scale.base = model.get('logBase'); + } + + var scaleType = scale.type; + scale.setExtent(extent[0], extent[1]); + scale.niceExtent({ + splitNumber: splitNumber, + fixMin: extentInfo.fixMin, + fixMax: extentInfo.fixMax, + minInterval: scaleType === 'interval' || scaleType === 'time' ? model.get('minInterval') : null, + maxInterval: scaleType === 'interval' || scaleType === 'time' ? model.get('maxInterval') : null + }); + var interval = model.get('interval'); + + if (interval != null) { + scale.setInterval && scale.setInterval(interval); + } + } + function createScaleByModel(model, axisType) { + axisType = axisType || model.get('type'); + + if (axisType) { + switch (axisType) { + case 'category': + return new OrdinalScale({ + ordinalMeta: model.getOrdinalMeta ? model.getOrdinalMeta() : model.getCategories(), + extent: [Infinity, -Infinity] + }); + + case 'time': + return new TimeScale({ + locale: model.ecModel.getLocaleModel(), + useUTC: model.ecModel.get('useUTC') + }); + + default: + return new (Scale.getClass(axisType) || IntervalScale)(); + } + } + } + function ifAxisCrossZero(axis) { + var dataExtent = axis.scale.getExtent(); + var min = dataExtent[0]; + var max = dataExtent[1]; + return !(min > 0 && max > 0 || min < 0 && max < 0); + } + function makeLabelFormatter(axis) { + var labelFormatter = axis.getLabelModel().get('formatter'); + var categoryTickStart = axis.type === 'category' ? axis.scale.getExtent()[0] : null; + + if (axis.scale.type === 'time') { + return function (tpl) { + return function (tick, idx) { + return axis.scale.getFormattedLabel(tick, idx, tpl); + }; + }(labelFormatter); + } else if (typeof labelFormatter === 'string') { + return function (tpl) { + return function (tick) { + var label = axis.scale.getLabel(tick); + var text = tpl.replace('{value}', label != null ? label : ''); + return text; + }; + }(labelFormatter); + } else if (typeof labelFormatter === 'function') { + return function (cb) { + return function (tick, idx) { + if (categoryTickStart != null) { + idx = tick.value - categoryTickStart; + } + + return cb(getAxisRawValue(axis, tick), idx, tick.level != null ? { + level: tick.level + } : null); + }; + }(labelFormatter); + } else { + return function (tick) { + return axis.scale.getLabel(tick); + }; + } + } + function getAxisRawValue(axis, tick) { + return axis.type === 'category' ? axis.scale.getLabel(tick) : tick.value; + } + function estimateLabelUnionRect(axis) { + var axisModel = axis.model; + var scale = axis.scale; + + if (!axisModel.get(['axisLabel', 'show']) || scale.isBlank()) { + return; + } + + var realNumberScaleTicks; + var tickCount; + var categoryScaleExtent = scale.getExtent(); + + if (scale instanceof OrdinalScale) { + tickCount = scale.count(); + } else { + realNumberScaleTicks = scale.getTicks(); + tickCount = realNumberScaleTicks.length; + } + + var axisLabelModel = axis.getLabelModel(); + var labelFormatter = makeLabelFormatter(axis); + var rect; + var step = 1; + + if (tickCount > 40) { + step = Math.ceil(tickCount / 40); + } + + for (var i = 0; i < tickCount; i += step) { + var tick = realNumberScaleTicks ? realNumberScaleTicks[i] : { + value: categoryScaleExtent[0] + i + }; + var label = labelFormatter(tick, i); + var unrotatedSingleRect = axisLabelModel.getTextRect(label); + var singleRect = rotateTextRect(unrotatedSingleRect, axisLabelModel.get('rotate') || 0); + rect ? rect.union(singleRect) : rect = singleRect; + } + + return rect; + } + + function rotateTextRect(textRect, rotate) { + var rotateRadians = rotate * Math.PI / 180; + var beforeWidth = textRect.width; + var beforeHeight = textRect.height; + var afterWidth = beforeWidth * Math.abs(Math.cos(rotateRadians)) + Math.abs(beforeHeight * Math.sin(rotateRadians)); + var afterHeight = beforeWidth * Math.abs(Math.sin(rotateRadians)) + Math.abs(beforeHeight * Math.cos(rotateRadians)); + var rotatedRect = new BoundingRect(textRect.x, textRect.y, afterWidth, afterHeight); + return rotatedRect; + } + + function getOptionCategoryInterval(model) { + var interval = model.get('interval'); + return interval == null ? 'auto' : interval; + } + function shouldShowAllLabels(axis) { + return axis.type === 'category' && getOptionCategoryInterval(axis.getLabelModel()) === 0; + } + function getDataDimensionsOnAxis(data, axisDim) { + var dataDimMap = {}; + each(data.mapDimensionsAll(axisDim), function (dataDim) { + dataDimMap[getStackedDimension(data, dataDim)] = true; + }); + return keys(dataDimMap); + } + function unionAxisExtentFromData(dataExtent, data, axisDim) { + if (data) { + each(getDataDimensionsOnAxis(data, axisDim), function (dim) { + var seriesExtent = data.getApproximateExtent(dim); + seriesExtent[0] < dataExtent[0] && (dataExtent[0] = seriesExtent[0]); + seriesExtent[1] > dataExtent[1] && (dataExtent[1] = seriesExtent[1]); + }); + } + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var AxisModelCommonMixin = function () { + function AxisModelCommonMixin() {} + + AxisModelCommonMixin.prototype.getNeedCrossZero = function () { + var option = this.option; + return !option.scale; + }; + + AxisModelCommonMixin.prototype.getCoordSysModel = function () { + return; + }; + + return AxisModelCommonMixin; + }(); + + function createList(seriesModel) { + return createListFromArray(seriesModel.getSource(), seriesModel); + } + var dataStack$1 = { + isDimensionStacked: isDimensionStacked, + enableDataStack: enableDataStack, + getStackedDimension: getStackedDimension + }; + function createScale(dataExtent, option) { + var axisModel = option; + + if (!(option instanceof Model)) { + axisModel = new Model(option); + } + + var scale = createScaleByModel(axisModel); + scale.setExtent(dataExtent[0], dataExtent[1]); + niceScaleExtent(scale, axisModel); + return scale; + } + function mixinAxisModelCommonMethods(Model) { + mixin(Model, AxisModelCommonMixin); + } + function createTextStyle$1(textStyleModel, opts) { + opts = opts || {}; + return createTextStyle(textStyleModel, null, null, opts.state !== 'normal'); + } + + var helper = /*#__PURE__*/Object.freeze({ + __proto__: null, + createList: createList, + getLayoutRect: getLayoutRect, + dataStack: dataStack$1, + createScale: createScale, + mixinAxisModelCommonMethods: mixinAxisModelCommonMethods, + getECData: getECData, + createTextStyle: createTextStyle$1, + createDimensions: createDimensions, + createSymbol: createSymbol, + enableHoverEmphasis: enableHoverEmphasis + }); + + var EPSILON$3 = 1e-8; + function isAroundEqual$1(a, b) { + return Math.abs(a - b) < EPSILON$3; + } + function contain$2(points, x, y) { + var w = 0; + var p = points[0]; + if (!p) { + return false; + } + for (var i = 1; i < points.length; i++) { + var p2 = points[i]; + w += windingLine(p[0], p[1], p2[0], p2[1], x, y); + p = p2; + } + var p0 = points[0]; + if (!isAroundEqual$1(p[0], p0[0]) || !isAroundEqual$1(p[1], p0[1])) { + w += windingLine(p[0], p[1], p0[0], p0[1], x, y); + } + return w !== 0; + } + + var Region = function () { + function Region(name, geometries, cp) { + this.name = name; + this.geometries = geometries; + + if (!cp) { + var rect = this.getBoundingRect(); + cp = [rect.x + rect.width / 2, rect.y + rect.height / 2]; + } else { + cp = [cp[0], cp[1]]; + } + + this.center = cp; + } + + Region.prototype.getBoundingRect = function () { + var rect = this._rect; + + if (rect) { + return rect; + } + + var MAX_NUMBER = Number.MAX_VALUE; + var min$1 = [MAX_NUMBER, MAX_NUMBER]; + var max$1 = [-MAX_NUMBER, -MAX_NUMBER]; + var min2 = []; + var max2 = []; + var geometries = this.geometries; + var i = 0; + + for (; i < geometries.length; i++) { + if (geometries[i].type !== 'polygon') { + continue; + } + + var exterior = geometries[i].exterior; + fromPoints(exterior, min2, max2); + min(min$1, min$1, min2); + max(max$1, max$1, max2); + } + + if (i === 0) { + min$1[0] = min$1[1] = max$1[0] = max$1[1] = 0; + } + + return this._rect = new BoundingRect(min$1[0], min$1[1], max$1[0] - min$1[0], max$1[1] - min$1[1]); + }; + + Region.prototype.contain = function (coord) { + var rect = this.getBoundingRect(); + var geometries = this.geometries; + + if (!rect.contain(coord[0], coord[1])) { + return false; + } + + loopGeo: for (var i = 0, len = geometries.length; i < len; i++) { + if (geometries[i].type !== 'polygon') { + continue; + } + + var exterior = geometries[i].exterior; + var interiors = geometries[i].interiors; + + if (contain$2(exterior, coord[0], coord[1])) { + for (var k = 0; k < (interiors ? interiors.length : 0); k++) { + if (contain$2(interiors[k], coord[0], coord[1])) { + continue loopGeo; + } + } + + return true; + } + } + + return false; + }; + + Region.prototype.transformTo = function (x, y, width, height) { + var rect = this.getBoundingRect(); + var aspect = rect.width / rect.height; + + if (!width) { + width = aspect * height; + } else if (!height) { + height = width / aspect; + } + + var target = new BoundingRect(x, y, width, height); + var transform = rect.calculateTransform(target); + var geometries = this.geometries; + + for (var i = 0; i < geometries.length; i++) { + if (geometries[i].type !== 'polygon') { + continue; + } + + var exterior = geometries[i].exterior; + var interiors = geometries[i].interiors; + + for (var p = 0; p < exterior.length; p++) { + applyTransform(exterior[p], exterior[p], transform); + } + + for (var h = 0; h < (interiors ? interiors.length : 0); h++) { + for (var p = 0; p < interiors[h].length; p++) { + applyTransform(interiors[h][p], interiors[h][p], transform); + } + } + } + + rect = this._rect; + rect.copy(target); + this.center = [rect.x + rect.width / 2, rect.y + rect.height / 2]; + }; + + Region.prototype.cloneShallow = function (name) { + name == null && (name = this.name); + var newRegion = new Region(name, this.geometries, this.center); + newRegion._rect = this._rect; + newRegion.transformTo = null; + return newRegion; + }; + + return Region; + }(); + + function decode(json) { + if (!json.UTF8Encoding) { + return json; + } + + var jsonCompressed = json; + var encodeScale = jsonCompressed.UTF8Scale; + + if (encodeScale == null) { + encodeScale = 1024; + } + + var features = jsonCompressed.features; + + for (var f = 0; f < features.length; f++) { + var feature = features[f]; + var geometry = feature.geometry; + + if (geometry.type === 'Polygon') { + var coordinates = geometry.coordinates; + + for (var c = 0; c < coordinates.length; c++) { + coordinates[c] = decodePolygon(coordinates[c], geometry.encodeOffsets[c], encodeScale); + } + } else if (geometry.type === 'MultiPolygon') { + var coordinates = geometry.coordinates; + + for (var c = 0; c < coordinates.length; c++) { + var coordinate = coordinates[c]; + + for (var c2 = 0; c2 < coordinate.length; c2++) { + coordinate[c2] = decodePolygon(coordinate[c2], geometry.encodeOffsets[c][c2], encodeScale); + } + } + } + } + + jsonCompressed.UTF8Encoding = false; + return jsonCompressed; + } + + function decodePolygon(coordinate, encodeOffsets, encodeScale) { + var result = []; + var prevX = encodeOffsets[0]; + var prevY = encodeOffsets[1]; + + for (var i = 0; i < coordinate.length; i += 2) { + var x = coordinate.charCodeAt(i) - 64; + var y = coordinate.charCodeAt(i + 1) - 64; + x = x >> 1 ^ -(x & 1); + y = y >> 1 ^ -(y & 1); + x += prevX; + y += prevY; + prevX = x; + prevY = y; + result.push([x / encodeScale, y / encodeScale]); + } + + return result; + } + + function parseGeoJSON(geoJson, nameProperty) { + geoJson = decode(geoJson); + return map(filter(geoJson.features, function (featureObj) { + return featureObj.geometry && featureObj.properties && featureObj.geometry.coordinates.length > 0; + }), function (featureObj) { + var properties = featureObj.properties; + var geo = featureObj.geometry; + var geometries = []; + + if (geo.type === 'Polygon') { + var coordinates = geo.coordinates; + geometries.push({ + type: 'polygon', + exterior: coordinates[0], + interiors: coordinates.slice(1) + }); + } + + if (geo.type === 'MultiPolygon') { + var coordinates = geo.coordinates; + each(coordinates, function (item) { + if (item[0]) { + geometries.push({ + type: 'polygon', + exterior: item[0], + interiors: item.slice(1) + }); + } + }); + } + + var region = new Region(properties[nameProperty || 'name'], geometries, properties.cp); + region.properties = properties; + return region; + }); + } + + var number = /*#__PURE__*/Object.freeze({ + __proto__: null, + linearMap: linearMap, + round: round, + asc: asc, + getPrecision: getPrecision, + getPrecisionSafe: getPrecisionSafe, + getPixelPrecision: getPixelPrecision, + getPercentWithPrecision: getPercentWithPrecision, + MAX_SAFE_INTEGER: MAX_SAFE_INTEGER, + remRadian: remRadian, + isRadianAroundZero: isRadianAroundZero, + parseDate: parseDate, + quantity: quantity, + quantityExponent: quantityExponent, + nice: nice, + quantile: quantile, + reformIntervals: reformIntervals, + isNumeric: isNumeric, + numericToNumber: numericToNumber + }); + + var time = /*#__PURE__*/Object.freeze({ + __proto__: null, + parse: parseDate, + format: format + }); + + var graphic$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + extendShape: extendShape, + extendPath: extendPath, + makePath: makePath, + makeImage: makeImage, + mergePath: mergePath$1, + resizePath: resizePath, + createIcon: createIcon, + updateProps: updateProps, + initProps: initProps, + getTransform: getTransform, + clipPointsByRect: clipPointsByRect, + clipRectByRect: clipRectByRect, + registerShape: registerShape, + getShapeClass: getShapeClass, + Group: Group, + Image: ZRImage, + Text: ZRText, + Circle: Circle, + Ellipse: Ellipse, + Sector: Sector, + Ring: Ring, + Polygon: Polygon, + Polyline: Polyline, + Rect: Rect, + Line: Line, + BezierCurve: BezierCurve, + Arc: Arc, + IncrementalDisplayable: IncrementalDisplayable, + CompoundPath: CompoundPath, + LinearGradient: LinearGradient, + RadialGradient: RadialGradient, + BoundingRect: BoundingRect + }); + + var format$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + addCommas: addCommas, + toCamelCase: toCamelCase, + normalizeCssArray: normalizeCssArray$1, + encodeHTML: encodeHTML, + formatTpl: formatTpl, + getTooltipMarker: getTooltipMarker, + formatTime: formatTime, + capitalFirst: capitalFirst, + truncateText: truncateText, + getTextRect: getTextRect + }); + + var util$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + map: map, + each: each, + indexOf: indexOf, + inherits: inherits, + reduce: reduce, + filter: filter, + bind: bind, + curry: curry, + isArray: isArray, + isString: isString, + isObject: isObject, + isFunction: isFunction, + extend: extend, + defaults: defaults, + clone: clone, + merge: merge + }); + + var inner$4 = makeInner(); + function createAxisLabels(axis) { + return axis.type === 'category' ? makeCategoryLabels(axis) : makeRealNumberLabels(axis); + } + function createAxisTicks(axis, tickModel) { + return axis.type === 'category' ? makeCategoryTicks(axis, tickModel) : { + ticks: map(axis.scale.getTicks(), function (tick) { + return tick.value; + }) + }; + } + + function makeCategoryLabels(axis) { + var labelModel = axis.getLabelModel(); + var result = makeCategoryLabelsActually(axis, labelModel); + return !labelModel.get('show') || axis.scale.isBlank() ? { + labels: [], + labelCategoryInterval: result.labelCategoryInterval + } : result; + } + + function makeCategoryLabelsActually(axis, labelModel) { + var labelsCache = getListCache(axis, 'labels'); + var optionLabelInterval = getOptionCategoryInterval(labelModel); + var result = listCacheGet(labelsCache, optionLabelInterval); + + if (result) { + return result; + } + + var labels; + var numericLabelInterval; + + if (isFunction(optionLabelInterval)) { + labels = makeLabelsByCustomizedCategoryInterval(axis, optionLabelInterval); + } else { + numericLabelInterval = optionLabelInterval === 'auto' ? makeAutoCategoryInterval(axis) : optionLabelInterval; + labels = makeLabelsByNumericCategoryInterval(axis, numericLabelInterval); + } + + return listCacheSet(labelsCache, optionLabelInterval, { + labels: labels, + labelCategoryInterval: numericLabelInterval + }); + } + + function makeCategoryTicks(axis, tickModel) { + var ticksCache = getListCache(axis, 'ticks'); + var optionTickInterval = getOptionCategoryInterval(tickModel); + var result = listCacheGet(ticksCache, optionTickInterval); + + if (result) { + return result; + } + + var ticks; + var tickCategoryInterval; + + if (!tickModel.get('show') || axis.scale.isBlank()) { + ticks = []; + } + + if (isFunction(optionTickInterval)) { + ticks = makeLabelsByCustomizedCategoryInterval(axis, optionTickInterval, true); + } else if (optionTickInterval === 'auto') { + var labelsResult = makeCategoryLabelsActually(axis, axis.getLabelModel()); + tickCategoryInterval = labelsResult.labelCategoryInterval; + ticks = map(labelsResult.labels, function (labelItem) { + return labelItem.tickValue; + }); + } else { + tickCategoryInterval = optionTickInterval; + ticks = makeLabelsByNumericCategoryInterval(axis, tickCategoryInterval, true); + } + + return listCacheSet(ticksCache, optionTickInterval, { + ticks: ticks, + tickCategoryInterval: tickCategoryInterval + }); + } + + function makeRealNumberLabels(axis) { + var ticks = axis.scale.getTicks(); + var labelFormatter = makeLabelFormatter(axis); + return { + labels: map(ticks, function (tick, idx) { + return { + formattedLabel: labelFormatter(tick, idx), + rawLabel: axis.scale.getLabel(tick), + tickValue: tick.value + }; + }) + }; + } + + function getListCache(axis, prop) { + return inner$4(axis)[prop] || (inner$4(axis)[prop] = []); + } + + function listCacheGet(cache, key) { + for (var i = 0; i < cache.length; i++) { + if (cache[i].key === key) { + return cache[i].value; + } + } + } + + function listCacheSet(cache, key, value) { + cache.push({ + key: key, + value: value + }); + return value; + } + + function makeAutoCategoryInterval(axis) { + var result = inner$4(axis).autoInterval; + return result != null ? result : inner$4(axis).autoInterval = axis.calculateCategoryInterval(); + } + + function calculateCategoryInterval(axis) { + var params = fetchAutoCategoryIntervalCalculationParams(axis); + var labelFormatter = makeLabelFormatter(axis); + var rotation = (params.axisRotate - params.labelRotate) / 180 * Math.PI; + var ordinalScale = axis.scale; + var ordinalExtent = ordinalScale.getExtent(); + var tickCount = ordinalScale.count(); + + if (ordinalExtent[1] - ordinalExtent[0] < 1) { + return 0; + } + + var step = 1; + + if (tickCount > 40) { + step = Math.max(1, Math.floor(tickCount / 40)); + } + + var tickValue = ordinalExtent[0]; + var unitSpan = axis.dataToCoord(tickValue + 1) - axis.dataToCoord(tickValue); + var unitW = Math.abs(unitSpan * Math.cos(rotation)); + var unitH = Math.abs(unitSpan * Math.sin(rotation)); + var maxW = 0; + var maxH = 0; + + for (; tickValue <= ordinalExtent[1]; tickValue += step) { + var width = 0; + var height = 0; + var rect = getBoundingRect(labelFormatter({ + value: tickValue + }), params.font, 'center', 'top'); + width = rect.width * 1.3; + height = rect.height * 1.3; + maxW = Math.max(maxW, width, 7); + maxH = Math.max(maxH, height, 7); + } + + var dw = maxW / unitW; + var dh = maxH / unitH; + isNaN(dw) && (dw = Infinity); + isNaN(dh) && (dh = Infinity); + var interval = Math.max(0, Math.floor(Math.min(dw, dh))); + var cache = inner$4(axis.model); + var axisExtent = axis.getExtent(); + var lastAutoInterval = cache.lastAutoInterval; + var lastTickCount = cache.lastTickCount; + + if (lastAutoInterval != null && lastTickCount != null && Math.abs(lastAutoInterval - interval) <= 1 && Math.abs(lastTickCount - tickCount) <= 1 && lastAutoInterval > interval && cache.axisExtent0 === axisExtent[0] && cache.axisExtent1 === axisExtent[1]) { + interval = lastAutoInterval; + } else { + cache.lastTickCount = tickCount; + cache.lastAutoInterval = interval; + cache.axisExtent0 = axisExtent[0]; + cache.axisExtent1 = axisExtent[1]; + } + + return interval; + } + + function fetchAutoCategoryIntervalCalculationParams(axis) { + var labelModel = axis.getLabelModel(); + return { + axisRotate: axis.getRotate ? axis.getRotate() : axis.isHorizontal && !axis.isHorizontal() ? 90 : 0, + labelRotate: labelModel.get('rotate') || 0, + font: labelModel.getFont() + }; + } + + function makeLabelsByNumericCategoryInterval(axis, categoryInterval, onlyTick) { + var labelFormatter = makeLabelFormatter(axis); + var ordinalScale = axis.scale; + var ordinalExtent = ordinalScale.getExtent(); + var labelModel = axis.getLabelModel(); + var result = []; + var step = Math.max((categoryInterval || 0) + 1, 1); + var startTick = ordinalExtent[0]; + var tickCount = ordinalScale.count(); + + if (startTick !== 0 && step > 1 && tickCount / step > 2) { + startTick = Math.round(Math.ceil(startTick / step) * step); + } + + var showAllLabel = shouldShowAllLabels(axis); + var includeMinLabel = labelModel.get('showMinLabel') || showAllLabel; + var includeMaxLabel = labelModel.get('showMaxLabel') || showAllLabel; + + if (includeMinLabel && startTick !== ordinalExtent[0]) { + addItem(ordinalExtent[0]); + } + + var tickValue = startTick; + + for (; tickValue <= ordinalExtent[1]; tickValue += step) { + addItem(tickValue); + } + + if (includeMaxLabel && tickValue - step !== ordinalExtent[1]) { + addItem(ordinalExtent[1]); + } + + function addItem(tickValue) { + var tickObj = { + value: tickValue + }; + result.push(onlyTick ? tickValue : { + formattedLabel: labelFormatter(tickObj), + rawLabel: ordinalScale.getLabel(tickObj), + tickValue: tickValue + }); + } + + return result; + } + + function makeLabelsByCustomizedCategoryInterval(axis, categoryInterval, onlyTick) { + var ordinalScale = axis.scale; + var labelFormatter = makeLabelFormatter(axis); + var result = []; + each(ordinalScale.getTicks(), function (tick) { + var rawLabel = ordinalScale.getLabel(tick); + var tickValue = tick.value; + + if (categoryInterval(tick.value, rawLabel)) { + result.push(onlyTick ? tickValue : { + formattedLabel: labelFormatter(tick), + rawLabel: rawLabel, + tickValue: tickValue + }); + } + }); + return result; + } + + var NORMALIZED_EXTENT = [0, 1]; + + var Axis = function () { + function Axis(dim, scale, extent) { + this.onBand = false; + this.inverse = false; + this.dim = dim; + this.scale = scale; + this._extent = extent || [0, 0]; + } + + Axis.prototype.contain = function (coord) { + var extent = this._extent; + var min = Math.min(extent[0], extent[1]); + var max = Math.max(extent[0], extent[1]); + return coord >= min && coord <= max; + }; + + Axis.prototype.containData = function (data) { + return this.scale.contain(data); + }; + + Axis.prototype.getExtent = function () { + return this._extent.slice(); + }; + + Axis.prototype.getPixelPrecision = function (dataExtent) { + return getPixelPrecision(dataExtent || this.scale.getExtent(), this._extent); + }; + + Axis.prototype.setExtent = function (start, end) { + var extent = this._extent; + extent[0] = start; + extent[1] = end; + }; + + Axis.prototype.dataToCoord = function (data, clamp) { + var extent = this._extent; + var scale = this.scale; + data = scale.normalize(data); + + if (this.onBand && scale.type === 'ordinal') { + extent = extent.slice(); + fixExtentWithBands(extent, scale.count()); + } + + return linearMap(data, NORMALIZED_EXTENT, extent, clamp); + }; + + Axis.prototype.coordToData = function (coord, clamp) { + var extent = this._extent; + var scale = this.scale; + + if (this.onBand && scale.type === 'ordinal') { + extent = extent.slice(); + fixExtentWithBands(extent, scale.count()); + } + + var t = linearMap(coord, extent, NORMALIZED_EXTENT, clamp); + return this.scale.scale(t); + }; + + Axis.prototype.pointToData = function (point, clamp) { + return; + }; + + Axis.prototype.getTicksCoords = function (opt) { + opt = opt || {}; + var tickModel = opt.tickModel || this.getTickModel(); + var result = createAxisTicks(this, tickModel); + var ticks = result.ticks; + var ticksCoords = map(ticks, function (tickVal) { + return { + coord: this.dataToCoord(this.scale.type === 'ordinal' ? this.scale.getRawOrdinalNumber(tickVal) : tickVal), + tickValue: tickVal + }; + }, this); + var alignWithLabel = tickModel.get('alignWithLabel'); + fixOnBandTicksCoords(this, ticksCoords, alignWithLabel, opt.clamp); + return ticksCoords; + }; + + Axis.prototype.getMinorTicksCoords = function () { + if (this.scale.type === 'ordinal') { + return []; + } + + var minorTickModel = this.model.getModel('minorTick'); + var splitNumber = minorTickModel.get('splitNumber'); + + if (!(splitNumber > 0 && splitNumber < 100)) { + splitNumber = 5; + } + + var minorTicks = this.scale.getMinorTicks(splitNumber); + var minorTicksCoords = map(minorTicks, function (minorTicksGroup) { + return map(minorTicksGroup, function (minorTick) { + return { + coord: this.dataToCoord(minorTick), + tickValue: minorTick + }; + }, this); + }, this); + return minorTicksCoords; + }; + + Axis.prototype.getViewLabels = function () { + return createAxisLabels(this).labels; + }; + + Axis.prototype.getLabelModel = function () { + return this.model.getModel('axisLabel'); + }; + + Axis.prototype.getTickModel = function () { + return this.model.getModel('axisTick'); + }; + + Axis.prototype.getBandWidth = function () { + var axisExtent = this._extent; + var dataExtent = this.scale.getExtent(); + var len = dataExtent[1] - dataExtent[0] + (this.onBand ? 1 : 0); + len === 0 && (len = 1); + var size = Math.abs(axisExtent[1] - axisExtent[0]); + return Math.abs(size) / len; + }; + + Axis.prototype.calculateCategoryInterval = function () { + return calculateCategoryInterval(this); + }; + + return Axis; + }(); + + function fixExtentWithBands(extent, nTick) { + var size = extent[1] - extent[0]; + var len = nTick; + var margin = size / len / 2; + extent[0] += margin; + extent[1] -= margin; + } + + function fixOnBandTicksCoords(axis, ticksCoords, alignWithLabel, clamp) { + var ticksLen = ticksCoords.length; + + if (!axis.onBand || alignWithLabel || !ticksLen) { + return; + } + + var axisExtent = axis.getExtent(); + var last; + var diffSize; + + if (ticksLen === 1) { + ticksCoords[0].coord = axisExtent[0]; + last = ticksCoords[1] = { + coord: axisExtent[0] + }; + } else { + var crossLen = ticksCoords[ticksLen - 1].tickValue - ticksCoords[0].tickValue; + var shift_1 = (ticksCoords[ticksLen - 1].coord - ticksCoords[0].coord) / crossLen; + each(ticksCoords, function (ticksItem) { + ticksItem.coord -= shift_1 / 2; + }); + var dataExtent = axis.scale.getExtent(); + diffSize = 1 + dataExtent[1] - ticksCoords[ticksLen - 1].tickValue; + last = { + coord: ticksCoords[ticksLen - 1].coord + shift_1 * diffSize + }; + ticksCoords.push(last); + } + + var inverse = axisExtent[0] > axisExtent[1]; + + if (littleThan(ticksCoords[0].coord, axisExtent[0])) { + clamp ? ticksCoords[0].coord = axisExtent[0] : ticksCoords.shift(); + } + + if (clamp && littleThan(axisExtent[0], ticksCoords[0].coord)) { + ticksCoords.unshift({ + coord: axisExtent[0] + }); + } + + if (littleThan(axisExtent[1], last.coord)) { + clamp ? last.coord = axisExtent[1] : ticksCoords.pop(); + } + + if (clamp && littleThan(last.coord, axisExtent[1])) { + ticksCoords.push({ + coord: axisExtent[1] + }); + } + + function littleThan(a, b) { + a = round(a); + b = round(b); + return inverse ? a > b : a < b; + } + } + + function extendComponentModel(proto) { + var Model = ComponentModel.extend(proto); + ComponentModel.registerClass(Model); + return Model; + } + function extendComponentView(proto) { + var View = ComponentView.extend(proto); + ComponentView.registerClass(View); + return View; + } + function extendSeriesModel(proto) { + var Model = SeriesModel.extend(proto); + SeriesModel.registerClass(Model); + return Model; + } + function extendChartView(proto) { + var View = ChartView.extend(proto); + ChartView.registerClass(View); + return View; + } + + function createElement(name) { + return document.createElementNS('http://www.w3.org/2000/svg', name); + } + + function diff(oldArr, newArr, equals) { + if (!equals) { + equals = function (a, b) { + return a === b; + }; + } + oldArr = oldArr.slice(); + newArr = newArr.slice(); + var newLen = newArr.length; + var oldLen = oldArr.length; + var editLength = 1; + var maxEditLength = newLen + oldLen; + var bestPath = [{ newPos: -1, components: [] }]; + var oldPos = extractCommon(bestPath[0], newArr, oldArr, 0, equals); + if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) { + var indices = []; + for (var i = 0; i < newArr.length; i++) { + indices.push(i); + } + return [{ + indices: indices, + count: newArr.length, + added: false, + removed: false + }]; + } + function execEditLength() { + for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) { + var basePath; + var addPath = bestPath[diagonalPath - 1]; + var removePath = bestPath[diagonalPath + 1]; + var oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; + if (addPath) { + bestPath[diagonalPath - 1] = undefined; + } + var canAdd = addPath && addPath.newPos + 1 < newLen; + var canRemove = removePath && 0 <= oldPos && oldPos < oldLen; + if (!canAdd && !canRemove) { + bestPath[diagonalPath] = undefined; + continue; + } + if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) { + basePath = clonePath(removePath); + pushComponent(basePath.components, false, true); + } + else { + basePath = addPath; + basePath.newPos++; + pushComponent(basePath.components, true, false); + } + oldPos = extractCommon(basePath, newArr, oldArr, diagonalPath, equals); + if (basePath.newPos + 1 >= newLen && oldPos + 1 >= oldLen) { + return buildValues(basePath.components); + } + else { + bestPath[diagonalPath] = basePath; + } + } + editLength++; + } + while (editLength <= maxEditLength) { + var ret = execEditLength(); + if (ret) { + return ret; + } + } + } + function extractCommon(basePath, newArr, oldArr, diagonalPath, equals) { + var newLen = newArr.length; + var oldLen = oldArr.length; + var newPos = basePath.newPos; + var oldPos = newPos - diagonalPath; + var commonCount = 0; + while (newPos + 1 < newLen && oldPos + 1 < oldLen && equals(newArr[newPos + 1], oldArr[oldPos + 1])) { + newPos++; + oldPos++; + commonCount++; + } + if (commonCount) { + basePath.components.push({ + count: commonCount, + added: false, + removed: false, + indices: [] + }); + } + basePath.newPos = newPos; + return oldPos; + } + function pushComponent(components, added, removed) { + var last = components[components.length - 1]; + if (last && last.added === added && last.removed === removed) { + components[components.length - 1] = { + count: last.count + 1, + added: added, + removed: removed, + indices: [] + }; + } + else { + components.push({ + count: 1, + added: added, + removed: removed, + indices: [] + }); + } + } + function buildValues(components) { + var componentPos = 0; + var componentLen = components.length; + var newPos = 0; + var oldPos = 0; + for (; componentPos < componentLen; componentPos++) { + var component = components[componentPos]; + if (!component.removed) { + var indices = []; + for (var i = newPos; i < newPos + component.count; i++) { + indices.push(i); + } + component.indices = indices; + newPos += component.count; + if (!component.added) { + oldPos += component.count; + } + } + else { + for (var i = oldPos; i < oldPos + component.count; i++) { + component.indices.push(i); + } + oldPos += component.count; + } + } + return components; + } + function clonePath(path) { + return { newPos: path.newPos, components: path.components.slice(0) }; + } + function arrayDiff(oldArr, newArr, equal) { + return diff(oldArr, newArr, equal); + } + + var NONE = 'none'; + var mathRound = Math.round; + var mathSin$4 = Math.sin; + var mathCos$4 = Math.cos; + var PI$4 = Math.PI; + var PI2$7 = Math.PI * 2; + var degree = 180 / PI$4; + var EPSILON$4 = 1e-4; + function round3(val) { + return mathRound(val * 1e3) / 1e3; + } + function round4(val) { + return mathRound(val * 1e4) / 1e4; + } + function isAroundZero$1(val) { + return val < EPSILON$4 && val > -EPSILON$4; + } + function pathHasFill(style) { + var fill = style.fill; + return fill != null && fill !== NONE; + } + function pathHasStroke(style) { + var stroke = style.stroke; + return stroke != null && stroke !== NONE; + } + function setTransform(svgEl, m) { + if (m) { + attr(svgEl, 'transform', 'matrix(' + + round3(m[0]) + ',' + + round3(m[1]) + ',' + + round3(m[2]) + ',' + + round3(m[3]) + ',' + + round4(m[4]) + ',' + + round4(m[5]) + + ')'); + } + } + function attr(el, key, val) { + if (!val || val.type !== 'linear' && val.type !== 'radial') { + el.setAttribute(key, val); + } + } + function attrXLink(el, key, val) { + el.setAttributeNS('http://www.w3.org/1999/xlink', key, val); + } + function attrXML(el, key, val) { + el.setAttributeNS('http://www.w3.org/XML/1998/namespace', key, val); + } + function bindStyle(svgEl, style, el) { + var opacity = style.opacity == null ? 1 : style.opacity; + if (el instanceof ZRImage) { + svgEl.style.opacity = opacity + ''; + return; + } + if (pathHasFill(style)) { + var fill = style.fill; + fill = fill === 'transparent' ? NONE : fill; + attr(svgEl, 'fill', fill); + attr(svgEl, 'fill-opacity', (style.fillOpacity != null ? style.fillOpacity * opacity : opacity) + ''); + } + else { + attr(svgEl, 'fill', NONE); + } + if (pathHasStroke(style)) { + var stroke = style.stroke; + stroke = stroke === 'transparent' ? NONE : stroke; + attr(svgEl, 'stroke', stroke); + var strokeWidth = style.lineWidth; + var strokeScale_1 = style.strokeNoScale + ? el.getLineScale() + : 1; + attr(svgEl, 'stroke-width', (strokeScale_1 ? strokeWidth / strokeScale_1 : 0) + ''); + attr(svgEl, 'paint-order', style.strokeFirst ? 'stroke' : 'fill'); + attr(svgEl, 'stroke-opacity', (style.strokeOpacity != null ? style.strokeOpacity * opacity : opacity) + ''); + var lineDash = style.lineDash && strokeWidth > 0 && normalizeLineDash(style.lineDash, strokeWidth); + if (lineDash) { + var lineDashOffset = style.lineDashOffset; + if (strokeScale_1 && strokeScale_1 !== 1) { + lineDash = map(lineDash, function (rawVal) { + return rawVal / strokeScale_1; + }); + if (lineDashOffset) { + lineDashOffset /= strokeScale_1; + lineDashOffset = mathRound(lineDashOffset); + } + } + attr(svgEl, 'stroke-dasharray', lineDash.join(',')); + attr(svgEl, 'stroke-dashoffset', (lineDashOffset || 0) + ''); + } + else { + attr(svgEl, 'stroke-dasharray', ''); + } + style.lineCap && attr(svgEl, 'stroke-linecap', style.lineCap); + style.lineJoin && attr(svgEl, 'stroke-linejoin', style.lineJoin); + style.miterLimit && attr(svgEl, 'stroke-miterlimit', style.miterLimit + ''); + } + else { + attr(svgEl, 'stroke', NONE); + } + } + var SVGPathRebuilder = (function () { + function SVGPathRebuilder() { + } + SVGPathRebuilder.prototype.reset = function () { + this._d = []; + this._str = ''; + }; + SVGPathRebuilder.prototype.moveTo = function (x, y) { + this._add('M', x, y); + }; + SVGPathRebuilder.prototype.lineTo = function (x, y) { + this._add('L', x, y); + }; + SVGPathRebuilder.prototype.bezierCurveTo = function (x, y, x2, y2, x3, y3) { + this._add('C', x, y, x2, y2, x3, y3); + }; + SVGPathRebuilder.prototype.quadraticCurveTo = function (x, y, x2, y2) { + this._add('Q', x, y, x2, y2); + }; + SVGPathRebuilder.prototype.arc = function (cx, cy, r, startAngle, endAngle, anticlockwise) { + this.ellipse(cx, cy, r, r, 0, startAngle, endAngle, anticlockwise); + }; + SVGPathRebuilder.prototype.ellipse = function (cx, cy, rx, ry, psi, startAngle, endAngle, anticlockwise) { + var firstCmd = this._d.length === 0; + var dTheta = endAngle - startAngle; + var clockwise = !anticlockwise; + var dThetaPositive = Math.abs(dTheta); + var isCircle = isAroundZero$1(dThetaPositive - PI2$7) + || (clockwise ? dTheta >= PI2$7 : -dTheta >= PI2$7); + var unifiedTheta = dTheta > 0 ? dTheta % PI2$7 : (dTheta % PI2$7 + PI2$7); + var large = false; + if (isCircle) { + large = true; + } + else if (isAroundZero$1(dThetaPositive)) { + large = false; + } + else { + large = (unifiedTheta >= PI$4) === !!clockwise; + } + var x0 = round4(cx + rx * mathCos$4(startAngle)); + var y0 = round4(cy + ry * mathSin$4(startAngle)); + if (isCircle) { + if (clockwise) { + dTheta = PI2$7 - 1e-4; + } + else { + dTheta = -PI2$7 + 1e-4; + } + large = true; + if (firstCmd) { + this._d.push('M', x0, y0); + } + } + var x = round4(cx + rx * mathCos$4(startAngle + dTheta)); + var y = round4(cy + ry * mathSin$4(startAngle + dTheta)); + if (isNaN(x0) || isNaN(y0) || isNaN(rx) || isNaN(ry) || isNaN(psi) || isNaN(degree) || isNaN(x) || isNaN(y)) { + return ''; + } + this._d.push('A', round4(rx), round4(ry), mathRound(psi * degree), +large, +clockwise, x, y); + }; + SVGPathRebuilder.prototype.rect = function (x, y, w, h) { + this._add('M', x, y); + this._add('L', x + w, y); + this._add('L', x + w, y + h); + this._add('L', x, y + h); + this._add('L', x, y); + }; + SVGPathRebuilder.prototype.closePath = function () { + if (this._d.length > 0) { + this._add('Z'); + } + }; + SVGPathRebuilder.prototype._add = function (cmd, a, b, c, d, e, f, g, h) { + this._d.push(cmd); + for (var i = 1; i < arguments.length; i++) { + var val = arguments[i]; + if (isNaN(val)) { + this._invalid = true; + return; + } + this._d.push(round4(val)); + } + }; + SVGPathRebuilder.prototype.generateStr = function () { + this._str = this._invalid ? '' : this._d.join(' '); + this._d = []; + }; + SVGPathRebuilder.prototype.getStr = function () { + return this._str; + }; + return SVGPathRebuilder; + }()); + var svgPath = { + brush: function (el) { + var style = el.style; + var svgEl = el.__svgEl; + if (!svgEl) { + svgEl = createElement('path'); + el.__svgEl = svgEl; + } + if (!el.path) { + el.createPathProxy(); + } + var path = el.path; + if (el.shapeChanged()) { + path.beginPath(); + el.buildPath(path, el.shape); + el.pathUpdated(); + } + var pathVersion = path.getVersion(); + var elExt = el; + var svgPathBuilder = elExt.__svgPathBuilder; + if (elExt.__svgPathVersion !== pathVersion || !svgPathBuilder || el.style.strokePercent < 1) { + if (!svgPathBuilder) { + svgPathBuilder = elExt.__svgPathBuilder = new SVGPathRebuilder(); + } + svgPathBuilder.reset(); + path.rebuildPath(svgPathBuilder, el.style.strokePercent); + svgPathBuilder.generateStr(); + elExt.__svgPathVersion = pathVersion; + } + attr(svgEl, 'd', svgPathBuilder.getStr()); + bindStyle(svgEl, style, el); + setTransform(svgEl, el.transform); + } + }; + var svgImage = { + brush: function (el) { + var style = el.style; + var image = style.image; + if (image instanceof HTMLImageElement) { + image = image.src; + } + else if (image instanceof HTMLCanvasElement) { + image = image.toDataURL(); + } + if (!image) { + return; + } + var x = style.x || 0; + var y = style.y || 0; + var dw = style.width; + var dh = style.height; + var svgEl = el.__svgEl; + if (!svgEl) { + svgEl = createElement('image'); + el.__svgEl = svgEl; + } + if (image !== el.__imageSrc) { + attrXLink(svgEl, 'href', image); + el.__imageSrc = image; + } + attr(svgEl, 'width', dw + ''); + attr(svgEl, 'height', dh + ''); + attr(svgEl, 'x', x + ''); + attr(svgEl, 'y', y + ''); + bindStyle(svgEl, style, el); + setTransform(svgEl, el.transform); + } + }; + var TEXT_ALIGN_TO_ANCHOR = { + left: 'start', + right: 'end', + center: 'middle', + middle: 'middle' + }; + function adjustTextY$1(y, lineHeight, textBaseline) { + if (textBaseline === 'top') { + y += lineHeight / 2; + } + else if (textBaseline === 'bottom') { + y -= lineHeight / 2; + } + return y; + } + var svgText = { + brush: function (el) { + var style = el.style; + var text = style.text; + text != null && (text += ''); + if (!text || isNaN(style.x) || isNaN(style.y)) { + return; + } + var textSvgEl = el.__svgEl; + if (!textSvgEl) { + textSvgEl = createElement('text'); + attrXML(textSvgEl, 'xml:space', 'preserve'); + el.__svgEl = textSvgEl; + } + var font = style.font || DEFAULT_FONT; + var textSvgElStyle = textSvgEl.style; + textSvgElStyle.font = font; + textSvgEl.textContent = text; + bindStyle(textSvgEl, style, el); + setTransform(textSvgEl, el.transform); + var x = style.x || 0; + var y = adjustTextY$1(style.y || 0, getLineHeight(font), style.textBaseline); + var textAlign = TEXT_ALIGN_TO_ANCHOR[style.textAlign] + || style.textAlign; + attr(textSvgEl, 'dominant-baseline', 'central'); + attr(textSvgEl, 'text-anchor', textAlign); + attr(textSvgEl, 'x', x + ''); + attr(textSvgEl, 'y', y + ''); + } + }; + + var MARK_UNUSED = '0'; + var MARK_USED = '1'; + var Definable = (function () { + function Definable(zrId, svgRoot, tagNames, markLabel, domName) { + this.nextId = 0; + this._domName = '_dom'; + this.createElement = createElement; + this._zrId = zrId; + this._svgRoot = svgRoot; + this._tagNames = typeof tagNames === 'string' ? [tagNames] : tagNames; + this._markLabel = markLabel; + if (domName) { + this._domName = domName; + } + } + Definable.prototype.getDefs = function (isForceCreating) { + var svgRoot = this._svgRoot; + var defs = this._svgRoot.getElementsByTagName('defs'); + if (defs.length === 0) { + if (isForceCreating) { + var defs_1 = svgRoot.insertBefore(this.createElement('defs'), svgRoot.firstChild); + if (!defs_1.contains) { + defs_1.contains = function (el) { + var children = defs_1.children; + if (!children) { + return false; + } + for (var i = children.length - 1; i >= 0; --i) { + if (children[i] === el) { + return true; + } + } + return false; + }; + } + return defs_1; + } + else { + return null; + } + } + else { + return defs[0]; + } + }; + Definable.prototype.doUpdate = function (target, onUpdate) { + if (!target) { + return; + } + var defs = this.getDefs(false); + if (target[this._domName] && defs.contains(target[this._domName])) { + if (typeof onUpdate === 'function') { + onUpdate(target); + } + } + else { + var dom = this.add(target); + if (dom) { + target[this._domName] = dom; + } + } + }; + Definable.prototype.add = function (target) { + return null; + }; + Definable.prototype.addDom = function (dom) { + var defs = this.getDefs(true); + if (dom.parentNode !== defs) { + defs.appendChild(dom); + } + }; + Definable.prototype.removeDom = function (target) { + var defs = this.getDefs(false); + if (defs && target[this._domName]) { + defs.removeChild(target[this._domName]); + target[this._domName] = null; + } + }; + Definable.prototype.getDoms = function () { + var defs = this.getDefs(false); + if (!defs) { + return []; + } + var doms = []; + each(this._tagNames, function (tagName) { + var tags = defs.getElementsByTagName(tagName); + for (var i = 0; i < tags.length; i++) { + doms.push(tags[i]); + } + }); + return doms; + }; + Definable.prototype.markAllUnused = function () { + var doms = this.getDoms(); + var that = this; + each(doms, function (dom) { + dom[that._markLabel] = MARK_UNUSED; + }); + }; + Definable.prototype.markDomUsed = function (dom) { + dom && (dom[this._markLabel] = MARK_USED); + }; + Definable.prototype.markDomUnused = function (dom) { + dom && (dom[this._markLabel] = MARK_UNUSED); + }; + Definable.prototype.isDomUnused = function (dom) { + return dom && dom[this._markLabel] !== MARK_USED; + }; + Definable.prototype.removeUnused = function () { + var _this = this; + var defs = this.getDefs(false); + if (!defs) { + return; + } + var doms = this.getDoms(); + each(doms, function (dom) { + if (_this.isDomUnused(dom)) { + defs.removeChild(dom); + } + }); + }; + Definable.prototype.getSvgProxy = function (displayable) { + if (displayable instanceof Path) { + return svgPath; + } + else if (displayable instanceof ZRImage) { + return svgImage; + } + else if (displayable instanceof TSpan) { + return svgText; + } + else { + return svgPath; + } + }; + Definable.prototype.getSvgElement = function (displayable) { + return displayable.__svgEl; + }; + return Definable; + }()); + + function isLinearGradient(value) { + return value.type === 'linear'; + } + function isRadialGradient(value) { + return value.type === 'radial'; + } + function isGradient(value) { + return value && (value.type === 'linear' + || value.type === 'radial'); + } + var GradientManager = (function (_super) { + __extends(GradientManager, _super); + function GradientManager(zrId, svgRoot) { + return _super.call(this, zrId, svgRoot, ['linearGradient', 'radialGradient'], '__gradient_in_use__') || this; + } + GradientManager.prototype.addWithoutUpdate = function (svgElement, displayable) { + if (displayable && displayable.style) { + var that_1 = this; + each(['fill', 'stroke'], function (fillOrStroke) { + var value = displayable.style[fillOrStroke]; + if (isGradient(value)) { + var gradient = value; + var defs = that_1.getDefs(true); + var dom = void 0; + if (gradient.__dom) { + dom = gradient.__dom; + if (!defs.contains(gradient.__dom)) { + that_1.addDom(dom); + } + } + else { + dom = that_1.add(gradient); + } + that_1.markUsed(displayable); + var id = dom.getAttribute('id'); + svgElement.setAttribute(fillOrStroke, 'url(#' + id + ')'); + } + }); + } + }; + GradientManager.prototype.add = function (gradient) { + var dom; + if (isLinearGradient(gradient)) { + dom = this.createElement('linearGradient'); + } + else if (isRadialGradient(gradient)) { + dom = this.createElement('radialGradient'); + } + else { + logError('Illegal gradient type.'); + return null; + } + gradient.id = gradient.id || this.nextId++; + dom.setAttribute('id', 'zr' + this._zrId + + '-gradient-' + gradient.id); + this.updateDom(gradient, dom); + this.addDom(dom); + return dom; + }; + GradientManager.prototype.update = function (gradient) { + if (!isGradient(gradient)) { + return; + } + var that = this; + this.doUpdate(gradient, function () { + var dom = gradient.__dom; + if (!dom) { + return; + } + var tagName = dom.tagName; + var type = gradient.type; + if (type === 'linear' && tagName === 'linearGradient' + || type === 'radial' && tagName === 'radialGradient') { + that.updateDom(gradient, gradient.__dom); + } + else { + that.removeDom(gradient); + that.add(gradient); + } + }); + }; + GradientManager.prototype.updateDom = function (gradient, dom) { + if (isLinearGradient(gradient)) { + dom.setAttribute('x1', gradient.x + ''); + dom.setAttribute('y1', gradient.y + ''); + dom.setAttribute('x2', gradient.x2 + ''); + dom.setAttribute('y2', gradient.y2 + ''); + } + else if (isRadialGradient(gradient)) { + dom.setAttribute('cx', gradient.x + ''); + dom.setAttribute('cy', gradient.y + ''); + dom.setAttribute('r', gradient.r + ''); + } + else { + logError('Illegal gradient type.'); + return; + } + if (gradient.global) { + dom.setAttribute('gradientUnits', 'userSpaceOnUse'); + } + else { + dom.setAttribute('gradientUnits', 'objectBoundingBox'); + } + dom.innerHTML = ''; + var colors = gradient.colorStops; + for (var i = 0, len = colors.length; i < len; ++i) { + var stop_1 = this.createElement('stop'); + stop_1.setAttribute('offset', colors[i].offset * 100 + '%'); + var color$1 = colors[i].color; + if (color$1.indexOf('rgba') > -1) { + var opacity = parse(color$1)[3]; + var hex = toHex(color$1); + stop_1.setAttribute('stop-color', '#' + hex); + stop_1.setAttribute('stop-opacity', opacity + ''); + } + else { + stop_1.setAttribute('stop-color', colors[i].color); + } + dom.appendChild(stop_1); + } + gradient.__dom = dom; + }; + GradientManager.prototype.markUsed = function (displayable) { + if (displayable.style) { + var gradient = displayable.style.fill; + if (gradient && gradient.__dom) { + _super.prototype.markDomUsed.call(this, gradient.__dom); + } + gradient = displayable.style.stroke; + if (gradient && gradient.__dom) { + _super.prototype.markDomUsed.call(this, gradient.__dom); + } + } + }; + return GradientManager; + }(Definable)); + + function isPattern(value) { + return value && (!!value.image || !!value.svgElement); + } + var patternDomMap = new WeakMap(); + var PatternManager = (function (_super) { + __extends(PatternManager, _super); + function PatternManager(zrId, svgRoot) { + return _super.call(this, zrId, svgRoot, ['pattern'], '__pattern_in_use__') || this; + } + PatternManager.prototype.addWithoutUpdate = function (svgElement, displayable) { + if (displayable && displayable.style) { + var that_1 = this; + each(['fill', 'stroke'], function (fillOrStroke) { + var pattern = displayable.style[fillOrStroke]; + if (isPattern(pattern)) { + var defs = that_1.getDefs(true); + var dom = patternDomMap.get(pattern); + if (dom) { + if (!defs.contains(dom)) { + that_1.addDom(dom); + } + } + else { + dom = that_1.add(pattern); + } + that_1.markUsed(displayable); + var id = dom.getAttribute('id'); + svgElement.setAttribute(fillOrStroke, 'url(#' + id + ')'); + } + }); + } + }; + PatternManager.prototype.add = function (pattern) { + if (!isPattern(pattern)) { + return; + } + var dom = this.createElement('pattern'); + pattern.id = pattern.id == null ? this.nextId++ : pattern.id; + dom.setAttribute('id', 'zr' + this._zrId + + '-pattern-' + pattern.id); + dom.setAttribute('x', '0'); + dom.setAttribute('y', '0'); + dom.setAttribute('patternUnits', 'userSpaceOnUse'); + this.updateDom(pattern, dom); + this.addDom(dom); + return dom; + }; + PatternManager.prototype.update = function (pattern) { + if (!isPattern(pattern)) { + return; + } + var that = this; + this.doUpdate(pattern, function () { + var dom = patternDomMap.get(pattern); + that.updateDom(pattern, dom); + }); + }; + PatternManager.prototype.updateDom = function (pattern, patternDom) { + var svgElement = pattern.svgElement; + if (svgElement instanceof SVGElement) { + if (svgElement.parentNode !== patternDom) { + patternDom.innerHTML = ''; + patternDom.appendChild(svgElement); + patternDom.setAttribute('width', pattern.svgWidth + ''); + patternDom.setAttribute('height', pattern.svgHeight + ''); + } + } + else { + var img = void 0; + var prevImage = patternDom.getElementsByTagName('image'); + if (prevImage.length) { + if (pattern.image) { + img = prevImage[0]; + } + else { + patternDom.removeChild(prevImage[0]); + return; + } + } + else if (pattern.image) { + img = this.createElement('image'); + } + if (img) { + var imageSrc = void 0; + if (typeof pattern.image === 'string') { + imageSrc = pattern.image; + } + else if (pattern.image instanceof HTMLImageElement) { + imageSrc = pattern.image.src; + } + else if (pattern.image instanceof HTMLCanvasElement) { + imageSrc = pattern.image.toDataURL(); + } + if (imageSrc) { + img.setAttribute('href', imageSrc); + img.setAttribute('x', '0'); + img.setAttribute('y', '0'); + var hostEl = { + dirty: function () { } + }; + var createdImage = createOrUpdateImage(imageSrc, img, hostEl, function (img) { + patternDom.setAttribute('width', img.width + ''); + patternDom.setAttribute('height', img.height + ''); + }); + if (createdImage && createdImage.width && createdImage.height) { + patternDom.setAttribute('width', createdImage.width + ''); + patternDom.setAttribute('height', createdImage.height + ''); + } + patternDom.appendChild(img); + } + } + } + var x = pattern.x || 0; + var y = pattern.y || 0; + var rotation = (pattern.rotation || 0) / Math.PI * 180; + var scaleX = pattern.scaleX || 1; + var scaleY = pattern.scaleY || 1; + var transform = "translate(" + x + ", " + y + ") rotate(" + rotation + ") scale(" + scaleX + ", " + scaleY + ")"; + patternDom.setAttribute('patternTransform', transform); + patternDomMap.set(pattern, patternDom); + }; + PatternManager.prototype.markUsed = function (displayable) { + if (displayable.style) { + if (isPattern(displayable.style.fill)) { + _super.prototype.markDomUsed.call(this, patternDomMap.get(displayable.style.fill)); + } + if (isPattern(displayable.style.stroke)) { + _super.prototype.markDomUsed.call(this, patternDomMap.get(displayable.style.stroke)); + } + } + }; + return PatternManager; + }(Definable)); + + function generateClipPathsKey(clipPaths) { + var key = []; + if (clipPaths) { + for (var i = 0; i < clipPaths.length; i++) { + var clipPath = clipPaths[i]; + key.push(clipPath.id); + } + } + return key.join(','); + } + function hasClipPath(displayable) { + var clipPaths = displayable.__clipPaths; + return clipPaths && clipPaths.length > 0; + } + var ClippathManager = (function (_super) { + __extends(ClippathManager, _super); + function ClippathManager(zrId, svgRoot) { + var _this = _super.call(this, zrId, svgRoot, 'clipPath', '__clippath_in_use__') || this; + _this._refGroups = {}; + _this._keyDuplicateCount = {}; + return _this; + } + ClippathManager.prototype.markAllUnused = function () { + _super.prototype.markAllUnused.call(this); + for (var key in this._refGroups) { + this.markDomUnused(this._refGroups[key]); + } + this._keyDuplicateCount = {}; + }; + ClippathManager.prototype._getClipPathGroup = function (displayable, prevDisplayable) { + if (!hasClipPath(displayable)) { + return; + } + var clipPaths = displayable.__clipPaths; + var keyDuplicateCount = this._keyDuplicateCount; + var clipPathKey = generateClipPathsKey(clipPaths); + if (isClipPathChanged(clipPaths, prevDisplayable && prevDisplayable.__clipPaths)) { + keyDuplicateCount[clipPathKey] = keyDuplicateCount[clipPathKey] || 0; + keyDuplicateCount[clipPathKey] && (clipPathKey += '-' + keyDuplicateCount[clipPathKey]); + keyDuplicateCount[clipPathKey]++; + } + return this._refGroups[clipPathKey] + || (this._refGroups[clipPathKey] = this.createElement('g')); + }; + ClippathManager.prototype.update = function (displayable, prevDisplayable) { + var clipGroup = this._getClipPathGroup(displayable, prevDisplayable); + if (clipGroup) { + this.markDomUsed(clipGroup); + this.updateDom(clipGroup, displayable.__clipPaths); + } + return clipGroup; + }; + ClippathManager.prototype.updateDom = function (parentEl, clipPaths) { + if (clipPaths && clipPaths.length > 0) { + var defs = this.getDefs(true); + var clipPath = clipPaths[0]; + var clipPathEl = void 0; + var id = void 0; + if (clipPath._dom) { + id = clipPath._dom.getAttribute('id'); + clipPathEl = clipPath._dom; + if (!defs.contains(clipPathEl)) { + defs.appendChild(clipPathEl); + } + } + else { + id = 'zr' + this._zrId + '-clip-' + this.nextId; + ++this.nextId; + clipPathEl = this.createElement('clipPath'); + clipPathEl.setAttribute('id', id); + defs.appendChild(clipPathEl); + clipPath._dom = clipPathEl; + } + var svgProxy = this.getSvgProxy(clipPath); + svgProxy.brush(clipPath); + var pathEl = this.getSvgElement(clipPath); + clipPathEl.innerHTML = ''; + clipPathEl.appendChild(pathEl); + parentEl.setAttribute('clip-path', 'url(#' + id + ')'); + if (clipPaths.length > 1) { + this.updateDom(clipPathEl, clipPaths.slice(1)); + } + } + else { + if (parentEl) { + parentEl.setAttribute('clip-path', 'none'); + } + } + }; + ClippathManager.prototype.markUsed = function (displayable) { + var _this = this; + if (displayable.__clipPaths) { + each(displayable.__clipPaths, function (clipPath) { + if (clipPath._dom) { + _super.prototype.markDomUsed.call(_this, clipPath._dom); + } + }); + } + }; + ClippathManager.prototype.removeUnused = function () { + _super.prototype.removeUnused.call(this); + var newRefGroupsMap = {}; + for (var key in this._refGroups) { + var group = this._refGroups[key]; + if (!this.isDomUnused(group)) { + newRefGroupsMap[key] = group; + } + else if (group.parentNode) { + group.parentNode.removeChild(group); + } + } + this._refGroups = newRefGroupsMap; + }; + return ClippathManager; + }(Definable)); + + var ShadowManager = (function (_super) { + __extends(ShadowManager, _super); + function ShadowManager(zrId, svgRoot) { + var _this = _super.call(this, zrId, svgRoot, ['filter'], '__filter_in_use__', '_shadowDom') || this; + _this._shadowDomMap = {}; + _this._shadowDomPool = []; + return _this; + } + ShadowManager.prototype._getFromPool = function () { + var shadowDom = this._shadowDomPool.pop(); + if (!shadowDom) { + shadowDom = this.createElement('filter'); + shadowDom.setAttribute('id', 'zr' + this._zrId + '-shadow-' + this.nextId++); + var domChild = this.createElement('feDropShadow'); + shadowDom.appendChild(domChild); + this.addDom(shadowDom); + } + return shadowDom; + }; + ShadowManager.prototype.update = function (svgElement, displayable) { + var style = displayable.style; + if (hasShadow(style)) { + var shadowKey = getShadowKey(displayable); + var shadowDom = displayable._shadowDom = this._shadowDomMap[shadowKey]; + if (!shadowDom) { + shadowDom = this._getFromPool(); + this._shadowDomMap[shadowKey] = shadowDom; + } + this.updateDom(svgElement, displayable, shadowDom); + } + else { + this.remove(svgElement, displayable); + } + }; + ShadowManager.prototype.remove = function (svgElement, displayable) { + if (displayable._shadowDom != null) { + displayable._shadowDom = null; + svgElement.style.filter = ''; + } + }; + ShadowManager.prototype.updateDom = function (svgElement, displayable, shadowDom) { + var domChild = shadowDom.children[0]; + var style = displayable.style; + var globalScale = displayable.getGlobalScale(); + var scaleX = globalScale[0]; + var scaleY = globalScale[1]; + if (!scaleX || !scaleY) { + return; + } + var offsetX = style.shadowOffsetX || 0; + var offsetY = style.shadowOffsetY || 0; + var blur = style.shadowBlur; + var color = style.shadowColor; + domChild.setAttribute('dx', offsetX / scaleX + ''); + domChild.setAttribute('dy', offsetY / scaleY + ''); + domChild.setAttribute('flood-color', color); + var stdDx = blur / 2 / scaleX; + var stdDy = blur / 2 / scaleY; + var stdDeviation = stdDx + ' ' + stdDy; + domChild.setAttribute('stdDeviation', stdDeviation); + shadowDom.setAttribute('x', '-100%'); + shadowDom.setAttribute('y', '-100%'); + shadowDom.setAttribute('width', '300%'); + shadowDom.setAttribute('height', '300%'); + displayable._shadowDom = shadowDom; + var id = shadowDom.getAttribute('id'); + svgElement.style.filter = 'url(#' + id + ')'; + }; + ShadowManager.prototype.removeUnused = function () { + var defs = this.getDefs(false); + if (!defs) { + return; + } + var shadowDomsPool = this._shadowDomPool; + for (var key in this._shadowDomMap) { + var dom = this._shadowDomMap[key]; + shadowDomsPool.push(dom); + } + this._shadowDomMap = {}; + }; + return ShadowManager; + }(Definable)); + function hasShadow(style) { + return style + && (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY); + } + function getShadowKey(displayable) { + var style = displayable.style; + var globalScale = displayable.getGlobalScale(); + return [ + style.shadowColor, + (style.shadowBlur || 0).toFixed(2), + (style.shadowOffsetX || 0).toFixed(2), + (style.shadowOffsetY || 0).toFixed(2), + globalScale[0], + globalScale[1] + ].join(','); + } + + function parseInt10(val) { + return parseInt(val, 10); + } + function getSvgProxy(el) { + if (el instanceof Path) { + return svgPath; + } + else if (el instanceof ZRImage) { + return svgImage; + } + else if (el instanceof TSpan) { + return svgText; + } + else { + return svgPath; + } + } + function checkParentAvailable(parent, child) { + return child && parent && child.parentNode !== parent; + } + function insertAfter(parent, child, prevSibling) { + if (checkParentAvailable(parent, child) && prevSibling) { + var nextSibling = prevSibling.nextSibling; + nextSibling ? parent.insertBefore(child, nextSibling) + : parent.appendChild(child); + } + } + function prepend(parent, child) { + if (checkParentAvailable(parent, child)) { + var firstChild = parent.firstChild; + firstChild ? parent.insertBefore(child, firstChild) + : parent.appendChild(child); + } + } + function remove(parent, child) { + if (child && parent && child.parentNode === parent) { + parent.removeChild(child); + } + } + function removeFromMyParent(child) { + if (child && child.parentNode) { + child.parentNode.removeChild(child); + } + } + function getSvgElement(displayable) { + return displayable.__svgEl; + } + var SVGPainter = (function () { + function SVGPainter(root, storage, opts, zrId) { + this.type = 'svg'; + this.refreshHover = createMethodNotSupport('refreshHover'); + this.pathToImage = createMethodNotSupport('pathToImage'); + this.configLayer = createMethodNotSupport('configLayer'); + this.root = root; + this.storage = storage; + this._opts = opts = extend({}, opts || {}); + var svgDom = createElement('svg'); + svgDom.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.w3.org/2000/svg'); + svgDom.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink', 'http://www.w3.org/1999/xlink'); + svgDom.setAttribute('version', '1.1'); + svgDom.setAttribute('baseProfile', 'full'); + svgDom.style.cssText = 'user-select:none;position:absolute;left:0;top:0;'; + var bgRoot = createElement('g'); + svgDom.appendChild(bgRoot); + var svgRoot = createElement('g'); + svgDom.appendChild(svgRoot); + this._gradientManager = new GradientManager(zrId, svgRoot); + this._patternManager = new PatternManager(zrId, svgRoot); + this._clipPathManager = new ClippathManager(zrId, svgRoot); + this._shadowManager = new ShadowManager(zrId, svgRoot); + var viewport = document.createElement('div'); + viewport.style.cssText = 'overflow:hidden;position:relative'; + this._svgDom = svgDom; + this._svgRoot = svgRoot; + this._backgroundRoot = bgRoot; + this._viewport = viewport; + root.appendChild(viewport); + viewport.appendChild(svgDom); + this.resize(opts.width, opts.height); + this._visibleList = []; + } + SVGPainter.prototype.getType = function () { + return 'svg'; + }; + SVGPainter.prototype.getViewportRoot = function () { + return this._viewport; + }; + SVGPainter.prototype.getSvgDom = function () { + return this._svgDom; + }; + SVGPainter.prototype.getSvgRoot = function () { + return this._svgRoot; + }; + SVGPainter.prototype.getViewportRootOffset = function () { + var viewportRoot = this.getViewportRoot(); + if (viewportRoot) { + return { + offsetLeft: viewportRoot.offsetLeft || 0, + offsetTop: viewportRoot.offsetTop || 0 + }; + } + }; + SVGPainter.prototype.refresh = function () { + var list = this.storage.getDisplayList(true); + this._paintList(list); + }; + SVGPainter.prototype.setBackgroundColor = function (backgroundColor) { + if (this._backgroundRoot && this._backgroundNode) { + this._backgroundRoot.removeChild(this._backgroundNode); + } + var bgNode = createElement('rect'); + bgNode.setAttribute('width', this.getWidth()); + bgNode.setAttribute('height', this.getHeight()); + bgNode.setAttribute('x', 0); + bgNode.setAttribute('y', 0); + bgNode.setAttribute('id', 0); + bgNode.style.fill = backgroundColor; + this._backgroundRoot.appendChild(bgNode); + this._backgroundNode = bgNode; + }; + SVGPainter.prototype.createSVGElement = function (tag) { + return createElement(tag); + }; + SVGPainter.prototype.paintOne = function (el) { + var svgProxy = getSvgProxy(el); + svgProxy && svgProxy.brush(el); + return getSvgElement(el); + }; + SVGPainter.prototype._paintList = function (list) { + var gradientManager = this._gradientManager; + var patternManager = this._patternManager; + var clipPathManager = this._clipPathManager; + var shadowManager = this._shadowManager; + gradientManager.markAllUnused(); + patternManager.markAllUnused(); + clipPathManager.markAllUnused(); + shadowManager.markAllUnused(); + var svgRoot = this._svgRoot; + var visibleList = this._visibleList; + var listLen = list.length; + var newVisibleList = []; + for (var i = 0; i < listLen; i++) { + var displayable = list[i]; + var svgProxy = getSvgProxy(displayable); + var svgElement = getSvgElement(displayable); + if (!displayable.invisible) { + if (displayable.__dirty || !svgElement) { + svgProxy && svgProxy.brush(displayable); + svgElement = getSvgElement(displayable); + if (svgElement && displayable.style) { + gradientManager.update(displayable.style.fill); + gradientManager.update(displayable.style.stroke); + patternManager.update(displayable.style.fill); + patternManager.update(displayable.style.stroke); + shadowManager.update(svgElement, displayable); + } + displayable.__dirty = 0; + } + if (svgElement) { + newVisibleList.push(displayable); + } + } + } + var diff = arrayDiff(visibleList, newVisibleList); + var prevSvgElement; + var topPrevSvgElement; + for (var i = 0; i < diff.length; i++) { + var item = diff[i]; + if (item.removed) { + for (var k = 0; k < item.count; k++) { + var displayable = visibleList[item.indices[k]]; + var svgElement = getSvgElement(displayable); + hasClipPath(displayable) ? removeFromMyParent(svgElement) + : remove(svgRoot, svgElement); + } + } + } + var prevDisplayable; + var currentClipGroup; + for (var i = 0; i < diff.length; i++) { + var item = diff[i]; + var isAdd = item.added; + if (item.removed) { + continue; + } + for (var k = 0; k < item.count; k++) { + var displayable = newVisibleList[item.indices[k]]; + var clipGroup = clipPathManager.update(displayable, prevDisplayable); + if (clipGroup !== currentClipGroup) { + prevSvgElement = topPrevSvgElement; + if (clipGroup) { + prevSvgElement ? insertAfter(svgRoot, clipGroup, prevSvgElement) + : prepend(svgRoot, clipGroup); + topPrevSvgElement = clipGroup; + prevSvgElement = null; + } + currentClipGroup = clipGroup; + } + var svgElement = getSvgElement(displayable); + prevSvgElement + ? insertAfter(currentClipGroup || svgRoot, svgElement, prevSvgElement) + : prepend(currentClipGroup || svgRoot, svgElement); + prevSvgElement = svgElement || prevSvgElement; + if (!currentClipGroup) { + topPrevSvgElement = prevSvgElement; + } + gradientManager.markUsed(displayable); + gradientManager.addWithoutUpdate(svgElement, displayable); + patternManager.markUsed(displayable); + patternManager.addWithoutUpdate(svgElement, displayable); + clipPathManager.markUsed(displayable); + prevDisplayable = displayable; + } + } + gradientManager.removeUnused(); + patternManager.removeUnused(); + clipPathManager.removeUnused(); + shadowManager.removeUnused(); + this._visibleList = newVisibleList; + }; + SVGPainter.prototype._getDefs = function (isForceCreating) { + var svgRoot = this._svgDom; + var defs = svgRoot.getElementsByTagName('defs'); + if (defs.length === 0) { + if (isForceCreating) { + var defs_1 = svgRoot.insertBefore(createElement('defs'), svgRoot.firstChild); + if (!defs_1.contains) { + defs_1.contains = function (el) { + var children = defs_1.children; + if (!children) { + return false; + } + for (var i = children.length - 1; i >= 0; --i) { + if (children[i] === el) { + return true; + } + } + return false; + }; + } + return defs_1; + } + else { + return null; + } + } + else { + return defs[0]; + } + }; + SVGPainter.prototype.resize = function (width, height) { + var viewport = this._viewport; + viewport.style.display = 'none'; + var opts = this._opts; + width != null && (opts.width = width); + height != null && (opts.height = height); + width = this._getSize(0); + height = this._getSize(1); + viewport.style.display = ''; + if (this._width !== width || this._height !== height) { + this._width = width; + this._height = height; + var viewportStyle = viewport.style; + viewportStyle.width = width + 'px'; + viewportStyle.height = height + 'px'; + var svgRoot = this._svgDom; + svgRoot.setAttribute('width', width + ''); + svgRoot.setAttribute('height', height + ''); + } + if (this._backgroundNode) { + this._backgroundNode.setAttribute('width', width); + this._backgroundNode.setAttribute('height', height); + } + }; + SVGPainter.prototype.getWidth = function () { + return this._width; + }; + SVGPainter.prototype.getHeight = function () { + return this._height; + }; + SVGPainter.prototype._getSize = function (whIdx) { + var opts = this._opts; + var wh = ['width', 'height'][whIdx]; + var cwh = ['clientWidth', 'clientHeight'][whIdx]; + var plt = ['paddingLeft', 'paddingTop'][whIdx]; + var prb = ['paddingRight', 'paddingBottom'][whIdx]; + if (opts[wh] != null && opts[wh] !== 'auto') { + return parseFloat(opts[wh]); + } + var root = this.root; + var stl = document.defaultView.getComputedStyle(root); + return ((root[cwh] || parseInt10(stl[wh]) || parseInt10(root.style[wh])) + - (parseInt10(stl[plt]) || 0) + - (parseInt10(stl[prb]) || 0)) | 0; + }; + SVGPainter.prototype.dispose = function () { + this.root.innerHTML = ''; + this._svgRoot + = this._backgroundRoot + = this._svgDom + = this._backgroundNode + = this._viewport + = this.storage + = null; + }; + SVGPainter.prototype.clear = function () { + var viewportNode = this._viewport; + if (viewportNode && viewportNode.parentNode) { + viewportNode.parentNode.removeChild(viewportNode); + } + }; + SVGPainter.prototype.toDataURL = function () { + this.refresh(); + var svgDom = this._svgDom; + var outerHTML = svgDom.outerHTML + || (svgDom.parentNode && svgDom.parentNode).innerHTML; + var html = encodeURIComponent(outerHTML.replace(/>\n\r<')); + return 'data:image/svg+xml;charset=UTF-8,' + html; + }; + return SVGPainter; + }()); + function createMethodNotSupport(method) { + return function () { + logError('In SVG mode painter not support method "' + method + '"'); + }; + } + + function install(registers) { + registers.registerPainter('svg', SVGPainter); + } + + function returnFalse() { + return false; + } + function createDom(id, painter, dpr) { + var newDom = createCanvas(); + var width = painter.getWidth(); + var height = painter.getHeight(); + var newDomStyle = newDom.style; + if (newDomStyle) { + newDomStyle.position = 'absolute'; + newDomStyle.left = '0'; + newDomStyle.top = '0'; + newDomStyle.width = width + 'px'; + newDomStyle.height = height + 'px'; + newDom.setAttribute('data-zr-dom-id', id); + } + newDom.width = width * dpr; + newDom.height = height * dpr; + return newDom; + } + var Layer = (function (_super) { + __extends(Layer, _super); + function Layer(id, painter, dpr) { + var _this = _super.call(this) || this; + _this.motionBlur = false; + _this.lastFrameAlpha = 0.7; + _this.dpr = 1; + _this.virtual = false; + _this.config = {}; + _this.incremental = false; + _this.zlevel = 0; + _this.maxRepaintRectCount = 5; + _this.__dirty = true; + _this.__firstTimePaint = true; + _this.__used = false; + _this.__drawIndex = 0; + _this.__startIndex = 0; + _this.__endIndex = 0; + _this.__prevStartIndex = null; + _this.__prevEndIndex = null; + var dom; + dpr = dpr || devicePixelRatio; + if (typeof id === 'string') { + dom = createDom(id, painter, dpr); + } + else if (isObject(id)) { + dom = id; + id = dom.id; + } + _this.id = id; + _this.dom = dom; + var domStyle = dom.style; + if (domStyle) { + dom.onselectstart = returnFalse; + domStyle.webkitUserSelect = 'none'; + domStyle.userSelect = 'none'; + domStyle.webkitTapHighlightColor = 'rgba(0,0,0,0)'; + domStyle['-webkit-touch-callout'] = 'none'; + domStyle.padding = '0'; + domStyle.margin = '0'; + domStyle.borderWidth = '0'; + } + _this.domBack = null; + _this.ctxBack = null; + _this.painter = painter; + _this.config = null; + _this.dpr = dpr; + return _this; + } + Layer.prototype.getElementCount = function () { + return this.__endIndex - this.__startIndex; + }; + Layer.prototype.afterBrush = function () { + this.__prevStartIndex = this.__startIndex; + this.__prevEndIndex = this.__endIndex; + }; + Layer.prototype.initContext = function () { + this.ctx = this.dom.getContext('2d'); + this.ctx.dpr = this.dpr; + }; + Layer.prototype.setUnpainted = function () { + this.__firstTimePaint = true; + }; + Layer.prototype.createBackBuffer = function () { + var dpr = this.dpr; + this.domBack = createDom('back-' + this.id, this.painter, dpr); + this.ctxBack = this.domBack.getContext('2d'); + if (dpr !== 1) { + this.ctxBack.scale(dpr, dpr); + } + }; + Layer.prototype.createRepaintRects = function (displayList, prevList, viewWidth, viewHeight) { + if (this.__firstTimePaint) { + this.__firstTimePaint = false; + return null; + } + var mergedRepaintRects = []; + var maxRepaintRectCount = this.maxRepaintRectCount; + var full = false; + var pendingRect = new BoundingRect(0, 0, 0, 0); + function addRectToMergePool(rect) { + if (!rect.isFinite() || rect.isZero()) { + return; + } + if (mergedRepaintRects.length === 0) { + var boundingRect = new BoundingRect(0, 0, 0, 0); + boundingRect.copy(rect); + mergedRepaintRects.push(boundingRect); + } + else { + var isMerged = false; + var minDeltaArea = Infinity; + var bestRectToMergeIdx = 0; + for (var i = 0; i < mergedRepaintRects.length; ++i) { + var mergedRect = mergedRepaintRects[i]; + if (mergedRect.intersect(rect)) { + var pendingRect_1 = new BoundingRect(0, 0, 0, 0); + pendingRect_1.copy(mergedRect); + pendingRect_1.union(rect); + mergedRepaintRects[i] = pendingRect_1; + isMerged = true; + break; + } + else if (full) { + pendingRect.copy(rect); + pendingRect.union(mergedRect); + var aArea = rect.width * rect.height; + var bArea = mergedRect.width * mergedRect.height; + var pendingArea = pendingRect.width * pendingRect.height; + var deltaArea = pendingArea - aArea - bArea; + if (deltaArea < minDeltaArea) { + minDeltaArea = deltaArea; + bestRectToMergeIdx = i; + } + } + } + if (full) { + mergedRepaintRects[bestRectToMergeIdx].union(rect); + isMerged = true; + } + if (!isMerged) { + var boundingRect = new BoundingRect(0, 0, 0, 0); + boundingRect.copy(rect); + mergedRepaintRects.push(boundingRect); + } + if (!full) { + full = mergedRepaintRects.length >= maxRepaintRectCount; + } + } + } + for (var i = this.__startIndex; i < this.__endIndex; ++i) { + var el = displayList[i]; + if (el) { + var shouldPaint = el.shouldBePainted(viewWidth, viewHeight, true, true); + var prevRect = el.__isRendered && ((el.__dirty & Element.REDARAW_BIT) || !shouldPaint) + ? el.getPrevPaintRect() + : null; + if (prevRect) { + addRectToMergePool(prevRect); + } + var curRect = shouldPaint && ((el.__dirty & Element.REDARAW_BIT) || !el.__isRendered) + ? el.getPaintRect() + : null; + if (curRect) { + addRectToMergePool(curRect); + } + } + } + for (var i = this.__prevStartIndex; i < this.__prevEndIndex; ++i) { + var el = prevList[i]; + var shouldPaint = el.shouldBePainted(viewWidth, viewHeight, true, true); + if (el && (!shouldPaint || !el.__zr) && el.__isRendered) { + var prevRect = el.getPrevPaintRect(); + if (prevRect) { + addRectToMergePool(prevRect); + } + } + } + var hasIntersections; + do { + hasIntersections = false; + for (var i = 0; i < mergedRepaintRects.length;) { + if (mergedRepaintRects[i].isZero()) { + mergedRepaintRects.splice(i, 1); + continue; + } + for (var j = i + 1; j < mergedRepaintRects.length;) { + if (mergedRepaintRects[i].intersect(mergedRepaintRects[j])) { + hasIntersections = true; + mergedRepaintRects[i].union(mergedRepaintRects[j]); + mergedRepaintRects.splice(j, 1); + } + else { + j++; + } + } + i++; + } + } while (hasIntersections); + this._paintRects = mergedRepaintRects; + return mergedRepaintRects; + }; + Layer.prototype.debugGetPaintRects = function () { + return (this._paintRects || []).slice(); + }; + Layer.prototype.resize = function (width, height) { + var dpr = this.dpr; + var dom = this.dom; + var domStyle = dom.style; + var domBack = this.domBack; + if (domStyle) { + domStyle.width = width + 'px'; + domStyle.height = height + 'px'; + } + dom.width = width * dpr; + dom.height = height * dpr; + if (domBack) { + domBack.width = width * dpr; + domBack.height = height * dpr; + if (dpr !== 1) { + this.ctxBack.scale(dpr, dpr); + } + } + }; + Layer.prototype.clear = function (clearAll, clearColor, repaintRects) { + var dom = this.dom; + var ctx = this.ctx; + var width = dom.width; + var height = dom.height; + clearColor = clearColor || this.clearColor; + var haveMotionBLur = this.motionBlur && !clearAll; + var lastFrameAlpha = this.lastFrameAlpha; + var dpr = this.dpr; + var self = this; + if (haveMotionBLur) { + if (!this.domBack) { + this.createBackBuffer(); + } + this.ctxBack.globalCompositeOperation = 'copy'; + this.ctxBack.drawImage(dom, 0, 0, width / dpr, height / dpr); + } + var domBack = this.domBack; + function doClear(x, y, width, height) { + ctx.clearRect(x, y, width, height); + if (clearColor && clearColor !== 'transparent') { + var clearColorGradientOrPattern = void 0; + if (isGradientObject(clearColor)) { + clearColorGradientOrPattern = clearColor.__canvasGradient + || getCanvasGradient(ctx, clearColor, { + x: 0, + y: 0, + width: width, + height: height + }); + clearColor.__canvasGradient = clearColorGradientOrPattern; + } + else if (isPatternObject(clearColor)) { + clearColorGradientOrPattern = createCanvasPattern(ctx, clearColor, { + dirty: function () { + self.setUnpainted(); + self.__painter.refresh(); + } + }); + } + ctx.save(); + ctx.fillStyle = clearColorGradientOrPattern || clearColor; + ctx.fillRect(x, y, width, height); + ctx.restore(); + } + if (haveMotionBLur) { + ctx.save(); + ctx.globalAlpha = lastFrameAlpha; + ctx.drawImage(domBack, x, y, width, height); + ctx.restore(); + } + } + if (!repaintRects || haveMotionBLur) { + doClear(0, 0, width, height); + } + else if (repaintRects.length) { + each(repaintRects, function (rect) { + doClear(rect.x * dpr, rect.y * dpr, rect.width * dpr, rect.height * dpr); + }); + } + }; + return Layer; + }(Eventful)); + + var HOVER_LAYER_ZLEVEL = 1e5; + var CANVAS_ZLEVEL = 314159; + var EL_AFTER_INCREMENTAL_INC = 0.01; + var INCREMENTAL_INC = 0.001; + function parseInt10$1(val) { + return parseInt(val, 10); + } + function isLayerValid(layer) { + if (!layer) { + return false; + } + if (layer.__builtin__) { + return true; + } + if (typeof (layer.resize) !== 'function' + || typeof (layer.refresh) !== 'function') { + return false; + } + return true; + } + function createRoot(width, height) { + var domRoot = document.createElement('div'); + domRoot.style.cssText = [ + 'position:relative', + 'width:' + width + 'px', + 'height:' + height + 'px', + 'padding:0', + 'margin:0', + 'border-width:0' + ].join(';') + ';'; + return domRoot; + } + var CanvasPainter = (function () { + function CanvasPainter(root, storage, opts, id) { + this.type = 'canvas'; + this._zlevelList = []; + this._prevDisplayList = []; + this._layers = {}; + this._layerConfig = {}; + this._needsManuallyCompositing = false; + this.type = 'canvas'; + var singleCanvas = !root.nodeName + || root.nodeName.toUpperCase() === 'CANVAS'; + this._opts = opts = extend({}, opts || {}); + this.dpr = opts.devicePixelRatio || devicePixelRatio; + this._singleCanvas = singleCanvas; + this.root = root; + var rootStyle = root.style; + if (rootStyle) { + rootStyle.webkitTapHighlightColor = 'transparent'; + rootStyle.webkitUserSelect = 'none'; + rootStyle.userSelect = 'none'; + rootStyle['-webkit-touch-callout'] = 'none'; + root.innerHTML = ''; + } + this.storage = storage; + var zlevelList = this._zlevelList; + this._prevDisplayList = []; + var layers = this._layers; + if (!singleCanvas) { + this._width = this._getSize(0); + this._height = this._getSize(1); + var domRoot = this._domRoot = createRoot(this._width, this._height); + root.appendChild(domRoot); + } + else { + var rootCanvas = root; + var width = rootCanvas.width; + var height = rootCanvas.height; + if (opts.width != null) { + width = opts.width; + } + if (opts.height != null) { + height = opts.height; + } + this.dpr = opts.devicePixelRatio || 1; + rootCanvas.width = width * this.dpr; + rootCanvas.height = height * this.dpr; + this._width = width; + this._height = height; + var mainLayer = new Layer(rootCanvas, this, this.dpr); + mainLayer.__builtin__ = true; + mainLayer.initContext(); + layers[CANVAS_ZLEVEL] = mainLayer; + mainLayer.zlevel = CANVAS_ZLEVEL; + zlevelList.push(CANVAS_ZLEVEL); + this._domRoot = root; + } + } + CanvasPainter.prototype.getType = function () { + return 'canvas'; + }; + CanvasPainter.prototype.isSingleCanvas = function () { + return this._singleCanvas; + }; + CanvasPainter.prototype.getViewportRoot = function () { + return this._domRoot; + }; + CanvasPainter.prototype.getViewportRootOffset = function () { + var viewportRoot = this.getViewportRoot(); + if (viewportRoot) { + return { + offsetLeft: viewportRoot.offsetLeft || 0, + offsetTop: viewportRoot.offsetTop || 0 + }; + } + }; + CanvasPainter.prototype.refresh = function (paintAll) { + var list = this.storage.getDisplayList(true); + var prevList = this._prevDisplayList; + var zlevelList = this._zlevelList; + this._redrawId = Math.random(); + this._paintList(list, prevList, paintAll, this._redrawId); + for (var i = 0; i < zlevelList.length; i++) { + var z = zlevelList[i]; + var layer = this._layers[z]; + if (!layer.__builtin__ && layer.refresh) { + var clearColor = i === 0 ? this._backgroundColor : null; + layer.refresh(clearColor); + } + } + if (this._opts.useDirtyRect) { + this._prevDisplayList = list.slice(); + } + return this; + }; + CanvasPainter.prototype.refreshHover = function () { + this._paintHoverList(this.storage.getDisplayList(false)); + }; + CanvasPainter.prototype._paintHoverList = function (list) { + var len = list.length; + var hoverLayer = this._hoverlayer; + hoverLayer && hoverLayer.clear(); + if (!len) { + return; + } + var scope = { + inHover: true, + viewWidth: this._width, + viewHeight: this._height + }; + var ctx; + for (var i = 0; i < len; i++) { + var el = list[i]; + if (el.__inHover) { + if (!hoverLayer) { + hoverLayer = this._hoverlayer = this.getLayer(HOVER_LAYER_ZLEVEL); + } + if (!ctx) { + ctx = hoverLayer.ctx; + ctx.save(); + } + brush(ctx, el, scope, i === len - 1); + } + } + if (ctx) { + ctx.restore(); + } + }; + CanvasPainter.prototype.getHoverLayer = function () { + return this.getLayer(HOVER_LAYER_ZLEVEL); + }; + CanvasPainter.prototype.paintOne = function (ctx, el) { + brushSingle(ctx, el); + }; + CanvasPainter.prototype._paintList = function (list, prevList, paintAll, redrawId) { + if (this._redrawId !== redrawId) { + return; + } + paintAll = paintAll || false; + this._updateLayerStatus(list); + var _a = this._doPaintList(list, prevList, paintAll), finished = _a.finished, needsRefreshHover = _a.needsRefreshHover; + if (this._needsManuallyCompositing) { + this._compositeManually(); + } + if (needsRefreshHover) { + this._paintHoverList(list); + } + if (!finished) { + var self_1 = this; + requestAnimationFrame$1(function () { + self_1._paintList(list, prevList, paintAll, redrawId); + }); + } + else { + this.eachLayer(function (layer) { + layer.afterBrush && layer.afterBrush(); + }); + } + }; + CanvasPainter.prototype._compositeManually = function () { + var ctx = this.getLayer(CANVAS_ZLEVEL).ctx; + var width = this._domRoot.width; + var height = this._domRoot.height; + ctx.clearRect(0, 0, width, height); + this.eachBuiltinLayer(function (layer) { + if (layer.virtual) { + ctx.drawImage(layer.dom, 0, 0, width, height); + } + }); + }; + CanvasPainter.prototype._doPaintList = function (list, prevList, paintAll) { + var _this = this; + var layerList = []; + var useDirtyRect = this._opts.useDirtyRect; + for (var zi = 0; zi < this._zlevelList.length; zi++) { + var zlevel = this._zlevelList[zi]; + var layer = this._layers[zlevel]; + if (layer.__builtin__ + && layer !== this._hoverlayer + && (layer.__dirty || paintAll)) { + layerList.push(layer); + } + } + var finished = true; + var needsRefreshHover = false; + var _loop_1 = function (k) { + var layer = layerList[k]; + var ctx = layer.ctx; + var repaintRects = useDirtyRect + && layer.createRepaintRects(list, prevList, this_1._width, this_1._height); + ctx.save(); + var start = paintAll ? layer.__startIndex : layer.__drawIndex; + var useTimer = !paintAll && layer.incremental && Date.now; + var startTime = useTimer && Date.now(); + var clearColor = layer.zlevel === this_1._zlevelList[0] + ? this_1._backgroundColor : null; + if (layer.__startIndex === layer.__endIndex) { + layer.clear(false, clearColor, repaintRects); + } + else if (start === layer.__startIndex) { + var firstEl = list[start]; + if (!firstEl.incremental || !firstEl.notClear || paintAll) { + layer.clear(false, clearColor, repaintRects); + } + } + if (start === -1) { + console.error('For some unknown reason. drawIndex is -1'); + start = layer.__startIndex; + } + var i; + var repaint = function (repaintRect) { + var scope = { + inHover: false, + allClipped: false, + prevEl: null, + viewWidth: _this._width, + viewHeight: _this._height + }; + for (i = start; i < layer.__endIndex; i++) { + var el = list[i]; + if (el.__inHover) { + needsRefreshHover = true; + } + _this._doPaintEl(el, layer, useDirtyRect, repaintRect, scope, i === layer.__endIndex - 1); + if (useTimer) { + var dTime = Date.now() - startTime; + if (dTime > 15) { + break; + } + } + } + if (scope.prevElClipPaths) { + ctx.restore(); + } + }; + if (repaintRects) { + if (repaintRects.length === 0) { + i = layer.__endIndex; + } + else { + var dpr = this_1.dpr; + for (var r = 0; r < repaintRects.length; ++r) { + var rect = repaintRects[r]; + ctx.save(); + ctx.beginPath(); + ctx.rect(rect.x * dpr, rect.y * dpr, rect.width * dpr, rect.height * dpr); + ctx.clip(); + repaint(rect); + ctx.restore(); + } + } + } + else { + ctx.save(); + repaint(); + ctx.restore(); + } + layer.__drawIndex = i; + if (layer.__drawIndex < layer.__endIndex) { + finished = false; + } + }; + var this_1 = this; + for (var k = 0; k < layerList.length; k++) { + _loop_1(k); + } + if (env.wxa) { + each(this._layers, function (layer) { + if (layer && layer.ctx && layer.ctx.draw) { + layer.ctx.draw(); + } + }); + } + return { + finished: finished, + needsRefreshHover: needsRefreshHover + }; + }; + CanvasPainter.prototype._doPaintEl = function (el, currentLayer, useDirtyRect, repaintRect, scope, isLast) { + var ctx = currentLayer.ctx; + if (useDirtyRect) { + var paintRect = el.getPaintRect(); + if (!repaintRect || paintRect && paintRect.intersect(repaintRect)) { + brush(ctx, el, scope, isLast); + el.setPrevPaintRect(paintRect); + } + } + else { + brush(ctx, el, scope, isLast); + } + }; + CanvasPainter.prototype.getLayer = function (zlevel, virtual) { + if (this._singleCanvas && !this._needsManuallyCompositing) { + zlevel = CANVAS_ZLEVEL; + } + var layer = this._layers[zlevel]; + if (!layer) { + layer = new Layer('zr_' + zlevel, this, this.dpr); + layer.zlevel = zlevel; + layer.__builtin__ = true; + if (this._layerConfig[zlevel]) { + merge(layer, this._layerConfig[zlevel], true); + } + else if (this._layerConfig[zlevel - EL_AFTER_INCREMENTAL_INC]) { + merge(layer, this._layerConfig[zlevel - EL_AFTER_INCREMENTAL_INC], true); + } + if (virtual) { + layer.virtual = virtual; + } + this.insertLayer(zlevel, layer); + layer.initContext(); + } + return layer; + }; + CanvasPainter.prototype.insertLayer = function (zlevel, layer) { + var layersMap = this._layers; + var zlevelList = this._zlevelList; + var len = zlevelList.length; + var domRoot = this._domRoot; + var prevLayer = null; + var i = -1; + if (layersMap[zlevel]) { + logError('ZLevel ' + zlevel + ' has been used already'); + return; + } + if (!isLayerValid(layer)) { + logError('Layer of zlevel ' + zlevel + ' is not valid'); + return; + } + if (len > 0 && zlevel > zlevelList[0]) { + for (i = 0; i < len - 1; i++) { + if (zlevelList[i] < zlevel + && zlevelList[i + 1] > zlevel) { + break; + } + } + prevLayer = layersMap[zlevelList[i]]; + } + zlevelList.splice(i + 1, 0, zlevel); + layersMap[zlevel] = layer; + if (!layer.virtual) { + if (prevLayer) { + var prevDom = prevLayer.dom; + if (prevDom.nextSibling) { + domRoot.insertBefore(layer.dom, prevDom.nextSibling); + } + else { + domRoot.appendChild(layer.dom); + } + } + else { + if (domRoot.firstChild) { + domRoot.insertBefore(layer.dom, domRoot.firstChild); + } + else { + domRoot.appendChild(layer.dom); + } + } + } + layer.__painter = this; + }; + CanvasPainter.prototype.eachLayer = function (cb, context) { + var zlevelList = this._zlevelList; + for (var i = 0; i < zlevelList.length; i++) { + var z = zlevelList[i]; + cb.call(context, this._layers[z], z); + } + }; + CanvasPainter.prototype.eachBuiltinLayer = function (cb, context) { + var zlevelList = this._zlevelList; + for (var i = 0; i < zlevelList.length; i++) { + var z = zlevelList[i]; + var layer = this._layers[z]; + if (layer.__builtin__) { + cb.call(context, layer, z); + } + } + }; + CanvasPainter.prototype.eachOtherLayer = function (cb, context) { + var zlevelList = this._zlevelList; + for (var i = 0; i < zlevelList.length; i++) { + var z = zlevelList[i]; + var layer = this._layers[z]; + if (!layer.__builtin__) { + cb.call(context, layer, z); + } + } + }; + CanvasPainter.prototype.getLayers = function () { + return this._layers; + }; + CanvasPainter.prototype._updateLayerStatus = function (list) { + this.eachBuiltinLayer(function (layer, z) { + layer.__dirty = layer.__used = false; + }); + function updatePrevLayer(idx) { + if (prevLayer) { + if (prevLayer.__endIndex !== idx) { + prevLayer.__dirty = true; + } + prevLayer.__endIndex = idx; + } + } + if (this._singleCanvas) { + for (var i_1 = 1; i_1 < list.length; i_1++) { + var el = list[i_1]; + if (el.zlevel !== list[i_1 - 1].zlevel || el.incremental) { + this._needsManuallyCompositing = true; + break; + } + } + } + var prevLayer = null; + var incrementalLayerCount = 0; + var prevZlevel; + var i; + for (i = 0; i < list.length; i++) { + var el = list[i]; + var zlevel = el.zlevel; + var layer = void 0; + if (prevZlevel !== zlevel) { + prevZlevel = zlevel; + incrementalLayerCount = 0; + } + if (el.incremental) { + layer = this.getLayer(zlevel + INCREMENTAL_INC, this._needsManuallyCompositing); + layer.incremental = true; + incrementalLayerCount = 1; + } + else { + layer = this.getLayer(zlevel + (incrementalLayerCount > 0 ? EL_AFTER_INCREMENTAL_INC : 0), this._needsManuallyCompositing); + } + if (!layer.__builtin__) { + logError('ZLevel ' + zlevel + ' has been used by unkown layer ' + layer.id); + } + if (layer !== prevLayer) { + layer.__used = true; + if (layer.__startIndex !== i) { + layer.__dirty = true; + } + layer.__startIndex = i; + if (!layer.incremental) { + layer.__drawIndex = i; + } + else { + layer.__drawIndex = -1; + } + updatePrevLayer(i); + prevLayer = layer; + } + if ((el.__dirty & Element.REDARAW_BIT) && !el.__inHover) { + layer.__dirty = true; + if (layer.incremental && layer.__drawIndex < 0) { + layer.__drawIndex = i; + } + } + } + updatePrevLayer(i); + this.eachBuiltinLayer(function (layer, z) { + if (!layer.__used && layer.getElementCount() > 0) { + layer.__dirty = true; + layer.__startIndex = layer.__endIndex = layer.__drawIndex = 0; + } + if (layer.__dirty && layer.__drawIndex < 0) { + layer.__drawIndex = layer.__startIndex; + } + }); + }; + CanvasPainter.prototype.clear = function () { + this.eachBuiltinLayer(this._clearLayer); + return this; + }; + CanvasPainter.prototype._clearLayer = function (layer) { + layer.clear(); + }; + CanvasPainter.prototype.setBackgroundColor = function (backgroundColor) { + this._backgroundColor = backgroundColor; + each(this._layers, function (layer) { + layer.setUnpainted(); + }); + }; + CanvasPainter.prototype.configLayer = function (zlevel, config) { + if (config) { + var layerConfig = this._layerConfig; + if (!layerConfig[zlevel]) { + layerConfig[zlevel] = config; + } + else { + merge(layerConfig[zlevel], config, true); + } + for (var i = 0; i < this._zlevelList.length; i++) { + var _zlevel = this._zlevelList[i]; + if (_zlevel === zlevel || _zlevel === zlevel + EL_AFTER_INCREMENTAL_INC) { + var layer = this._layers[_zlevel]; + merge(layer, layerConfig[zlevel], true); + } + } + } + }; + CanvasPainter.prototype.delLayer = function (zlevel) { + var layers = this._layers; + var zlevelList = this._zlevelList; + var layer = layers[zlevel]; + if (!layer) { + return; + } + layer.dom.parentNode.removeChild(layer.dom); + delete layers[zlevel]; + zlevelList.splice(indexOf(zlevelList, zlevel), 1); + }; + CanvasPainter.prototype.resize = function (width, height) { + if (!this._domRoot.style) { + if (width == null || height == null) { + return; + } + this._width = width; + this._height = height; + this.getLayer(CANVAS_ZLEVEL).resize(width, height); + } + else { + var domRoot = this._domRoot; + domRoot.style.display = 'none'; + var opts = this._opts; + width != null && (opts.width = width); + height != null && (opts.height = height); + width = this._getSize(0); + height = this._getSize(1); + domRoot.style.display = ''; + if (this._width !== width || height !== this._height) { + domRoot.style.width = width + 'px'; + domRoot.style.height = height + 'px'; + for (var id in this._layers) { + if (this._layers.hasOwnProperty(id)) { + this._layers[id].resize(width, height); + } + } + this.refresh(true); + } + this._width = width; + this._height = height; + } + return this; + }; + CanvasPainter.prototype.clearLayer = function (zlevel) { + var layer = this._layers[zlevel]; + if (layer) { + layer.clear(); + } + }; + CanvasPainter.prototype.dispose = function () { + this.root.innerHTML = ''; + this.root = + this.storage = + this._domRoot = + this._layers = null; + }; + CanvasPainter.prototype.getRenderedCanvas = function (opts) { + opts = opts || {}; + if (this._singleCanvas && !this._compositeManually) { + return this._layers[CANVAS_ZLEVEL].dom; + } + var imageLayer = new Layer('image', this, opts.pixelRatio || this.dpr); + var ctx = imageLayer.ctx; + imageLayer.initContext(); + imageLayer.clear(false, opts.backgroundColor || this._backgroundColor); + if (opts.pixelRatio <= this.dpr) { + this.refresh(); + var width_1 = imageLayer.dom.width; + var height_1 = imageLayer.dom.height; + var ctx_1 = imageLayer.ctx; + this.eachLayer(function (layer) { + if (layer.__builtin__) { + ctx_1.drawImage(layer.dom, 0, 0, width_1, height_1); + } + else if (layer.renderToCanvas) { + imageLayer.ctx.save(); + layer.renderToCanvas(imageLayer.ctx); + imageLayer.ctx.restore(); + } + }); + } + else { + var scope = { + inHover: false, + viewWidth: this._width, + viewHeight: this._height + }; + var displayList = this.storage.getDisplayList(true); + for (var i = 0, len = displayList.length; i < len; i++) { + var el = displayList[i]; + brush(ctx, el, scope, i === len - 1); + } + } + return imageLayer.dom; + }; + CanvasPainter.prototype.getWidth = function () { + return this._width; + }; + CanvasPainter.prototype.getHeight = function () { + return this._height; + }; + CanvasPainter.prototype._getSize = function (whIdx) { + var opts = this._opts; + var wh = ['width', 'height'][whIdx]; + var cwh = ['clientWidth', 'clientHeight'][whIdx]; + var plt = ['paddingLeft', 'paddingTop'][whIdx]; + var prb = ['paddingRight', 'paddingBottom'][whIdx]; + if (opts[wh] != null && opts[wh] !== 'auto') { + return parseFloat(opts[wh]); + } + var root = this.root; + var stl = document.defaultView.getComputedStyle(root); + return ((root[cwh] || parseInt10$1(stl[wh]) || parseInt10$1(root.style[wh])) + - (parseInt10$1(stl[plt]) || 0) + - (parseInt10$1(stl[prb]) || 0)) | 0; + }; + CanvasPainter.prototype.pathToImage = function (path, dpr) { + dpr = dpr || this.dpr; + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + var rect = path.getBoundingRect(); + var style = path.style; + var shadowBlurSize = style.shadowBlur * dpr; + var shadowOffsetX = style.shadowOffsetX * dpr; + var shadowOffsetY = style.shadowOffsetY * dpr; + var lineWidth = path.hasStroke() ? style.lineWidth : 0; + var leftMargin = Math.max(lineWidth / 2, -shadowOffsetX + shadowBlurSize); + var rightMargin = Math.max(lineWidth / 2, shadowOffsetX + shadowBlurSize); + var topMargin = Math.max(lineWidth / 2, -shadowOffsetY + shadowBlurSize); + var bottomMargin = Math.max(lineWidth / 2, shadowOffsetY + shadowBlurSize); + var width = rect.width + leftMargin + rightMargin; + var height = rect.height + topMargin + bottomMargin; + canvas.width = width * dpr; + canvas.height = height * dpr; + ctx.scale(dpr, dpr); + ctx.clearRect(0, 0, width, height); + ctx.dpr = dpr; + var pathTransform = { + x: path.x, + y: path.y, + scaleX: path.scaleX, + scaleY: path.scaleY, + rotation: path.rotation, + originX: path.originX, + originY: path.originY + }; + path.x = leftMargin - rect.x; + path.y = topMargin - rect.y; + path.rotation = 0; + path.scaleX = 1; + path.scaleY = 1; + path.updateTransform(); + if (path) { + brush(ctx, path, { + inHover: false, + viewWidth: this._width, + viewHeight: this._height + }, true); + } + var imgShape = new ZRImage({ + style: { + x: 0, + y: 0, + image: canvas + } + }); + extend(path, pathTransform); + return imgShape; + }; + return CanvasPainter; + }()); + + function install$1(registers) { + registers.registerPainter('canvas', CanvasPainter); + } + + var LineSeriesModel = function (_super) { + __extends(LineSeriesModel, _super); + + function LineSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = LineSeriesModel.type; + _this.hasSymbolVisual = true; + _this.legendSymbol = 'line'; + return _this; + } + + LineSeriesModel.prototype.getInitialData = function (option) { + if ("development" !== 'production') { + var coordSys = option.coordinateSystem; + + if (coordSys !== 'polar' && coordSys !== 'cartesian2d') { + throw new Error('Line not support coordinateSystem besides cartesian and polar'); + } + } + + return createListFromArray(this.getSource(), this, { + useEncodeDefaulter: true + }); + }; + + LineSeriesModel.type = 'series.line'; + LineSeriesModel.dependencies = ['grid', 'polar']; + LineSeriesModel.defaultOption = { + zlevel: 0, + z: 3, + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + clip: true, + label: { + position: 'top' + }, + endLabel: { + show: false, + valueAnimation: true, + distance: 8 + }, + lineStyle: { + width: 2, + type: 'solid' + }, + emphasis: { + scale: true, + lineStyle: { + width: 'bolder' + } + }, + step: false, + smooth: false, + smoothMonotone: null, + symbol: 'emptyCircle', + symbolSize: 4, + symbolRotate: null, + showSymbol: true, + showAllSymbol: 'auto', + connectNulls: false, + sampling: 'none', + animationEasing: 'linear', + progressive: 0, + hoverLayerThreshold: Infinity + }; + return LineSeriesModel; + }(SeriesModel); + + function getDefaultLabel(data, dataIndex) { + var labelDims = data.mapDimensionsAll('defaultedLabel'); + var len = labelDims.length; + + if (len === 1) { + var rawVal = retrieveRawValue(data, dataIndex, labelDims[0]); + return rawVal != null ? rawVal + '' : null; + } else if (len) { + var vals = []; + + for (var i = 0; i < labelDims.length; i++) { + vals.push(retrieveRawValue(data, dataIndex, labelDims[i])); + } + + return vals.join(' '); + } + } + function getDefaultInterpolatedLabel(data, interpolatedValue) { + var labelDims = data.mapDimensionsAll('defaultedLabel'); + + if (!isArray(interpolatedValue)) { + return interpolatedValue + ''; + } + + var vals = []; + + for (var i = 0; i < labelDims.length; i++) { + var dimInfo = data.getDimensionInfo(labelDims[i]); + + if (dimInfo) { + vals.push(interpolatedValue[dimInfo.index]); + } + } + + return vals.join(' '); + } + + var Symbol = function (_super) { + __extends(Symbol, _super); + + function Symbol(data, idx, seriesScope, opts) { + var _this = _super.call(this) || this; + + _this.updateData(data, idx, seriesScope, opts); + + return _this; + } + + Symbol.prototype._createSymbol = function (symbolType, data, idx, symbolSize, keepAspect) { + this.removeAll(); + var symbolPath = createSymbol(symbolType, -1, -1, 2, 2, null, keepAspect); + symbolPath.attr({ + z2: 100, + culling: true, + scaleX: symbolSize[0] / 2, + scaleY: symbolSize[1] / 2 + }); + symbolPath.drift = driftSymbol; + this._symbolType = symbolType; + this.add(symbolPath); + }; + + Symbol.prototype.stopSymbolAnimation = function (toLastFrame) { + this.childAt(0).stopAnimation(null, toLastFrame); + }; + + Symbol.prototype.getSymbolPath = function () { + return this.childAt(0); + }; + + Symbol.prototype.highlight = function () { + enterEmphasis(this.childAt(0)); + }; + + Symbol.prototype.downplay = function () { + leaveEmphasis(this.childAt(0)); + }; + + Symbol.prototype.setZ = function (zlevel, z) { + var symbolPath = this.childAt(0); + symbolPath.zlevel = zlevel; + symbolPath.z = z; + }; + + Symbol.prototype.setDraggable = function (draggable) { + var symbolPath = this.childAt(0); + symbolPath.draggable = draggable; + symbolPath.cursor = draggable ? 'move' : symbolPath.cursor; + }; + + Symbol.prototype.updateData = function (data, idx, seriesScope, opts) { + this.silent = false; + var symbolType = data.getItemVisual(idx, 'symbol') || 'circle'; + var seriesModel = data.hostModel; + var symbolSize = Symbol.getSymbolSize(data, idx); + var isInit = symbolType !== this._symbolType; + var disableAnimation = opts && opts.disableAnimation; + + if (isInit) { + var keepAspect = data.getItemVisual(idx, 'symbolKeepAspect'); + + this._createSymbol(symbolType, data, idx, symbolSize, keepAspect); + } else { + var symbolPath = this.childAt(0); + symbolPath.silent = false; + var target = { + scaleX: symbolSize[0] / 2, + scaleY: symbolSize[1] / 2 + }; + disableAnimation ? symbolPath.attr(target) : updateProps(symbolPath, target, seriesModel, idx); + } + + this._updateCommon(data, idx, symbolSize, seriesScope, opts); + + if (isInit) { + var symbolPath = this.childAt(0); + + if (!disableAnimation) { + var target = { + scaleX: this._sizeX, + scaleY: this._sizeY, + style: { + opacity: symbolPath.style.opacity + } + }; + symbolPath.scaleX = symbolPath.scaleY = 0; + symbolPath.style.opacity = 0; + initProps(symbolPath, target, seriesModel, idx); + } + } + + if (disableAnimation) { + this.childAt(0).stopAnimation('remove'); + } + + this._seriesModel = seriesModel; + }; + + Symbol.prototype._updateCommon = function (data, idx, symbolSize, seriesScope, opts) { + var symbolPath = this.childAt(0); + var seriesModel = data.hostModel; + var emphasisItemStyle; + var blurItemStyle; + var selectItemStyle; + var focus; + var blurScope; + var symbolOffset; + var labelStatesModels; + var hoverScale; + var cursorStyle; + + if (seriesScope) { + emphasisItemStyle = seriesScope.emphasisItemStyle; + blurItemStyle = seriesScope.blurItemStyle; + selectItemStyle = seriesScope.selectItemStyle; + focus = seriesScope.focus; + blurScope = seriesScope.blurScope; + symbolOffset = seriesScope.symbolOffset; + labelStatesModels = seriesScope.labelStatesModels; + hoverScale = seriesScope.hoverScale; + cursorStyle = seriesScope.cursorStyle; + } + + if (!seriesScope || data.hasItemOption) { + var itemModel = seriesScope && seriesScope.itemModel ? seriesScope.itemModel : data.getItemModel(idx); + var emphasisModel = itemModel.getModel('emphasis'); + emphasisItemStyle = emphasisModel.getModel('itemStyle').getItemStyle(); + selectItemStyle = itemModel.getModel(['select', 'itemStyle']).getItemStyle(); + blurItemStyle = itemModel.getModel(['blur', 'itemStyle']).getItemStyle(); + focus = emphasisModel.get('focus'); + blurScope = emphasisModel.get('blurScope'); + symbolOffset = itemModel.getShallow('symbolOffset'); + labelStatesModels = getLabelStatesModels(itemModel); + hoverScale = emphasisModel.getShallow('scale'); + cursorStyle = itemModel.getShallow('cursor'); + } + + var symbolRotate = data.getItemVisual(idx, 'symbolRotate'); + symbolPath.attr('rotation', (symbolRotate || 0) * Math.PI / 180 || 0); + + if (symbolOffset) { + symbolPath.x = parsePercent$1(symbolOffset[0], symbolSize[0]); + symbolPath.y = parsePercent$1(symbolOffset[1], symbolSize[1]); + } + + cursorStyle && symbolPath.attr('cursor', cursorStyle); + var symbolStyle = data.getItemVisual(idx, 'style'); + var visualColor = symbolStyle.fill; + + if (symbolPath instanceof ZRImage) { + var pathStyle = symbolPath.style; + symbolPath.useStyle(extend({ + image: pathStyle.image, + x: pathStyle.x, + y: pathStyle.y, + width: pathStyle.width, + height: pathStyle.height + }, symbolStyle)); + } else { + if (symbolPath.__isEmptyBrush) { + symbolPath.useStyle(extend({}, symbolStyle)); + } else { + symbolPath.useStyle(symbolStyle); + } + + symbolPath.style.decal = null; + symbolPath.setColor(visualColor, opts && opts.symbolInnerColor); + symbolPath.style.strokeNoScale = true; + } + + var liftZ = data.getItemVisual(idx, 'liftZ'); + var z2Origin = this._z2; + + if (liftZ != null) { + if (z2Origin == null) { + this._z2 = symbolPath.z2; + symbolPath.z2 += liftZ; + } + } else if (z2Origin != null) { + symbolPath.z2 = z2Origin; + this._z2 = null; + } + + var useNameLabel = opts && opts.useNameLabel; + setLabelStyle(symbolPath, labelStatesModels, { + labelFetcher: seriesModel, + labelDataIndex: idx, + defaultText: getLabelDefaultText, + inheritColor: visualColor, + defaultOpacity: symbolStyle.opacity + }); + + function getLabelDefaultText(idx) { + return useNameLabel ? data.getName(idx) : getDefaultLabel(data, idx); + } + + this._sizeX = symbolSize[0] / 2; + this._sizeY = symbolSize[1] / 2; + var emphasisState = symbolPath.ensureState('emphasis'); + emphasisState.style = emphasisItemStyle; + symbolPath.ensureState('select').style = selectItemStyle; + symbolPath.ensureState('blur').style = blurItemStyle; + + if (hoverScale) { + var scaleRatio = Math.max(1.1, 3 / this._sizeY); + emphasisState.scaleX = this._sizeX * scaleRatio; + emphasisState.scaleY = this._sizeY * scaleRatio; + } + + this.setSymbolScale(1); + enableHoverEmphasis(this, focus, blurScope); + }; + + Symbol.prototype.setSymbolScale = function (scale) { + this.scaleX = this.scaleY = scale; + }; + + Symbol.prototype.fadeOut = function (cb, opt) { + var symbolPath = this.childAt(0); + var seriesModel = this._seriesModel; + var dataIndex = getECData(this).dataIndex; + var animationOpt = opt && opt.animation; + this.silent = symbolPath.silent = true; + + if (opt && opt.fadeLabel) { + var textContent = symbolPath.getTextContent(); + + if (textContent) { + removeElement(textContent, { + style: { + opacity: 0 + } + }, seriesModel, { + dataIndex: dataIndex, + removeOpt: animationOpt, + cb: function () { + symbolPath.removeTextContent(); + } + }); + } + } else { + symbolPath.removeTextContent(); + } + + removeElement(symbolPath, { + style: { + opacity: 0 + }, + scaleX: 0, + scaleY: 0 + }, seriesModel, { + dataIndex: dataIndex, + cb: cb, + removeOpt: animationOpt + }); + }; + + Symbol.getSymbolSize = function (data, idx) { + var symbolSize = data.getItemVisual(idx, 'symbolSize'); + return symbolSize instanceof Array ? symbolSize.slice() : [+symbolSize, +symbolSize]; + }; + + return Symbol; + }(Group); + + function driftSymbol(dx, dy) { + this.parent.drift(dx, dy); + } + + function symbolNeedsDraw(data, point, idx, opt) { + return point && !isNaN(point[0]) && !isNaN(point[1]) && !(opt.isIgnore && opt.isIgnore(idx)) && !(opt.clipShape && !opt.clipShape.contain(point[0], point[1])) && data.getItemVisual(idx, 'symbol') !== 'none'; + } + + function normalizeUpdateOpt(opt) { + if (opt != null && !isObject(opt)) { + opt = { + isIgnore: opt + }; + } + + return opt || {}; + } + + function makeSeriesScope(data) { + var seriesModel = data.hostModel; + var emphasisModel = seriesModel.getModel('emphasis'); + return { + emphasisItemStyle: emphasisModel.getModel('itemStyle').getItemStyle(), + blurItemStyle: seriesModel.getModel(['blur', 'itemStyle']).getItemStyle(), + selectItemStyle: seriesModel.getModel(['select', 'itemStyle']).getItemStyle(), + focus: emphasisModel.get('focus'), + blurScope: emphasisModel.get('blurScope'), + symbolRotate: seriesModel.get('symbolRotate'), + symbolOffset: seriesModel.get('symbolOffset'), + hoverScale: emphasisModel.get('scale'), + labelStatesModels: getLabelStatesModels(seriesModel), + cursorStyle: seriesModel.get('cursor') + }; + } + + var SymbolDraw = function () { + function SymbolDraw(SymbolCtor) { + this.group = new Group(); + this._SymbolCtor = SymbolCtor || Symbol; + } + + SymbolDraw.prototype.updateData = function (data, opt) { + opt = normalizeUpdateOpt(opt); + var group = this.group; + var seriesModel = data.hostModel; + var oldData = this._data; + var SymbolCtor = this._SymbolCtor; + var disableAnimation = opt.disableAnimation; + var seriesScope = makeSeriesScope(data); + var symbolUpdateOpt = { + disableAnimation: disableAnimation + }; + + var getSymbolPoint = opt.getSymbolPoint || function (idx) { + return data.getItemLayout(idx); + }; + + if (!oldData) { + group.removeAll(); + } + + data.diff(oldData).add(function (newIdx) { + var point = getSymbolPoint(newIdx); + + if (symbolNeedsDraw(data, point, newIdx, opt)) { + var symbolEl = new SymbolCtor(data, newIdx, seriesScope, symbolUpdateOpt); + symbolEl.setPosition(point); + data.setItemGraphicEl(newIdx, symbolEl); + group.add(symbolEl); + } + }).update(function (newIdx, oldIdx) { + var symbolEl = oldData.getItemGraphicEl(oldIdx); + var point = getSymbolPoint(newIdx); + + if (!symbolNeedsDraw(data, point, newIdx, opt)) { + group.remove(symbolEl); + return; + } + + if (!symbolEl) { + symbolEl = new SymbolCtor(data, newIdx); + symbolEl.setPosition(point); + } else { + symbolEl.updateData(data, newIdx, seriesScope, symbolUpdateOpt); + var target = { + x: point[0], + y: point[1] + }; + disableAnimation ? symbolEl.attr(target) : updateProps(symbolEl, target, seriesModel); + } + + group.add(symbolEl); + data.setItemGraphicEl(newIdx, symbolEl); + }).remove(function (oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + el && el.fadeOut(function () { + group.remove(el); + }); + }).execute(); + this._getSymbolPoint = getSymbolPoint; + this._data = data; + }; + + SymbolDraw.prototype.isPersistent = function () { + return true; + }; + + SymbolDraw.prototype.updateLayout = function () { + var _this = this; + + var data = this._data; + + if (data) { + data.eachItemGraphicEl(function (el, idx) { + var point = _this._getSymbolPoint(idx); + + el.setPosition(point); + el.markRedraw(); + }); + } + }; + + SymbolDraw.prototype.incrementalPrepareUpdate = function (data) { + this._seriesScope = makeSeriesScope(data); + this._data = null; + this.group.removeAll(); + }; + + SymbolDraw.prototype.incrementalUpdate = function (taskParams, data, opt) { + opt = normalizeUpdateOpt(opt); + + function updateIncrementalAndHover(el) { + if (!el.isGroup) { + el.incremental = true; + el.ensureState('emphasis').hoverLayer = true; + } + } + + for (var idx = taskParams.start; idx < taskParams.end; idx++) { + var point = data.getItemLayout(idx); + + if (symbolNeedsDraw(data, point, idx, opt)) { + var el = new this._SymbolCtor(data, idx, this._seriesScope); + el.traverse(updateIncrementalAndHover); + el.setPosition(point); + this.group.add(el); + data.setItemGraphicEl(idx, el); + } + } + }; + + SymbolDraw.prototype.remove = function (enableAnimation) { + var group = this.group; + var data = this._data; + + if (data && enableAnimation) { + data.eachItemGraphicEl(function (el) { + el.fadeOut(function () { + group.remove(el); + }); + }); + } else { + group.removeAll(); + } + }; + return SymbolDraw; + }(); + + function prepareDataCoordInfo(coordSys, data, valueOrigin) { + var baseAxis = coordSys.getBaseAxis(); + var valueAxis = coordSys.getOtherAxis(baseAxis); + var valueStart = getValueStart(valueAxis, valueOrigin); + var baseAxisDim = baseAxis.dim; + var valueAxisDim = valueAxis.dim; + var valueDim = data.mapDimension(valueAxisDim); + var baseDim = data.mapDimension(baseAxisDim); + var baseDataOffset = valueAxisDim === 'x' || valueAxisDim === 'radius' ? 1 : 0; + var dims = map(coordSys.dimensions, function (coordDim) { + return data.mapDimension(coordDim); + }); + var stacked = false; + var stackResultDim = data.getCalculationInfo('stackResultDimension'); + + if (isDimensionStacked(data, dims[0])) { + stacked = true; + dims[0] = stackResultDim; + } + + if (isDimensionStacked(data, dims[1])) { + stacked = true; + dims[1] = stackResultDim; + } + + return { + dataDimsForPoint: dims, + valueStart: valueStart, + valueAxisDim: valueAxisDim, + baseAxisDim: baseAxisDim, + stacked: !!stacked, + valueDim: valueDim, + baseDim: baseDim, + baseDataOffset: baseDataOffset, + stackedOverDimension: data.getCalculationInfo('stackedOverDimension') + }; + } + + function getValueStart(valueAxis, valueOrigin) { + var valueStart = 0; + var extent = valueAxis.scale.getExtent(); + + if (valueOrigin === 'start') { + valueStart = extent[0]; + } else if (valueOrigin === 'end') { + valueStart = extent[1]; + } else { + if (extent[0] > 0) { + valueStart = extent[0]; + } else if (extent[1] < 0) { + valueStart = extent[1]; + } + } + + return valueStart; + } + + function getStackedOnPoint(dataCoordInfo, coordSys, data, idx) { + var value = NaN; + + if (dataCoordInfo.stacked) { + value = data.get(data.getCalculationInfo('stackedOverDimension'), idx); + } + + if (isNaN(value)) { + value = dataCoordInfo.valueStart; + } + + var baseDataOffset = dataCoordInfo.baseDataOffset; + var stackedData = []; + stackedData[baseDataOffset] = data.get(dataCoordInfo.baseDim, idx); + stackedData[1 - baseDataOffset] = value; + return coordSys.dataToPoint(stackedData); + } + + var supportFloat32Array = typeof Float32Array !== 'undefined'; + var Float32ArrayCtor = !supportFloat32Array ? Array : Float32Array; + function createFloat32Array(arg) { + if (isArray(arg)) { + return supportFloat32Array ? new Float32Array(arg) : arg; + } + + return new Float32ArrayCtor(arg); + } + + function diffData(oldData, newData) { + var diffResult = []; + newData.diff(oldData).add(function (idx) { + diffResult.push({ + cmd: '+', + idx: idx + }); + }).update(function (newIdx, oldIdx) { + diffResult.push({ + cmd: '=', + idx: oldIdx, + idx1: newIdx + }); + }).remove(function (idx) { + diffResult.push({ + cmd: '-', + idx: idx + }); + }).execute(); + return diffResult; + } + + function lineAnimationDiff(oldData, newData, oldStackedOnPoints, newStackedOnPoints, oldCoordSys, newCoordSys, oldValueOrigin, newValueOrigin) { + var diff = diffData(oldData, newData); + var currPoints = []; + var nextPoints = []; + var currStackedPoints = []; + var nextStackedPoints = []; + var status = []; + var sortedIndices = []; + var rawIndices = []; + var newDataOldCoordInfo = prepareDataCoordInfo(oldCoordSys, newData, oldValueOrigin); + var oldDataNewCoordInfo = prepareDataCoordInfo(newCoordSys, oldData, newValueOrigin); + var oldPoints = oldData.getLayout('points') || []; + var newPoints = newData.getLayout('points') || []; + + for (var i = 0; i < diff.length; i++) { + var diffItem = diff[i]; + var pointAdded = true; + var oldIdx2 = void 0; + var newIdx2 = void 0; + + switch (diffItem.cmd) { + case '=': + oldIdx2 = diffItem.idx * 2; + newIdx2 = diffItem.idx1 * 2; + var currentX = oldPoints[oldIdx2]; + var currentY = oldPoints[oldIdx2 + 1]; + var nextX = newPoints[newIdx2]; + var nextY = newPoints[newIdx2 + 1]; + + if (isNaN(currentX) || isNaN(currentY)) { + currentX = nextX; + currentY = nextY; + } + + currPoints.push(currentX, currentY); + nextPoints.push(nextX, nextY); + currStackedPoints.push(oldStackedOnPoints[oldIdx2], oldStackedOnPoints[oldIdx2 + 1]); + nextStackedPoints.push(newStackedOnPoints[newIdx2], newStackedOnPoints[newIdx2 + 1]); + rawIndices.push(newData.getRawIndex(diffItem.idx1)); + break; + + case '+': + var newIdx = diffItem.idx; + var newDataDimsForPoint = newDataOldCoordInfo.dataDimsForPoint; + var oldPt = oldCoordSys.dataToPoint([newData.get(newDataDimsForPoint[0], newIdx), newData.get(newDataDimsForPoint[1], newIdx)]); + newIdx2 = newIdx * 2; + currPoints.push(oldPt[0], oldPt[1]); + nextPoints.push(newPoints[newIdx2], newPoints[newIdx2 + 1]); + var stackedOnPoint = getStackedOnPoint(newDataOldCoordInfo, oldCoordSys, newData, newIdx); + currStackedPoints.push(stackedOnPoint[0], stackedOnPoint[1]); + nextStackedPoints.push(newStackedOnPoints[newIdx2], newStackedOnPoints[newIdx2 + 1]); + rawIndices.push(newData.getRawIndex(newIdx)); + break; + + case '-': + var oldIdx = diffItem.idx; + var rawIndex = oldData.getRawIndex(oldIdx); + var oldDataDimsForPoint = oldDataNewCoordInfo.dataDimsForPoint; + oldIdx2 = oldIdx * 2; + + if (rawIndex !== oldIdx) { + var newPt = newCoordSys.dataToPoint([oldData.get(oldDataDimsForPoint[0], oldIdx), oldData.get(oldDataDimsForPoint[1], oldIdx)]); + var newStackedOnPt = getStackedOnPoint(oldDataNewCoordInfo, newCoordSys, oldData, oldIdx); + currPoints.push(oldPoints[oldIdx2], oldPoints[oldIdx2 + 1]); + nextPoints.push(newPt[0], newPt[1]); + currStackedPoints.push(oldStackedOnPoints[oldIdx2], oldStackedOnPoints[oldIdx2 + 1]); + nextStackedPoints.push(newStackedOnPt[0], newStackedOnPt[1]); + rawIndices.push(rawIndex); + } else { + pointAdded = false; + } + + } + + if (pointAdded) { + status.push(diffItem); + sortedIndices.push(sortedIndices.length); + } + } + + sortedIndices.sort(function (a, b) { + return rawIndices[a] - rawIndices[b]; + }); + var len = currPoints.length; + var sortedCurrPoints = createFloat32Array(len); + var sortedNextPoints = createFloat32Array(len); + var sortedCurrStackedPoints = createFloat32Array(len); + var sortedNextStackedPoints = createFloat32Array(len); + var sortedStatus = []; + + for (var i = 0; i < sortedIndices.length; i++) { + var idx = sortedIndices[i]; + var i2 = i * 2; + var idx2 = idx * 2; + sortedCurrPoints[i2] = currPoints[idx2]; + sortedCurrPoints[i2 + 1] = currPoints[idx2 + 1]; + sortedNextPoints[i2] = nextPoints[idx2]; + sortedNextPoints[i2 + 1] = nextPoints[idx2 + 1]; + sortedCurrStackedPoints[i2] = currStackedPoints[idx2]; + sortedCurrStackedPoints[i2 + 1] = currStackedPoints[idx2 + 1]; + sortedNextStackedPoints[i2] = nextStackedPoints[idx2]; + sortedNextStackedPoints[i2 + 1] = nextStackedPoints[idx2 + 1]; + sortedStatus[i] = status[idx]; + } + + return { + current: sortedCurrPoints, + next: sortedNextPoints, + stackedOnCurrent: sortedCurrStackedPoints, + stackedOnNext: sortedNextStackedPoints, + status: sortedStatus + }; + } + + var mathMin$5 = Math.min; + var mathMax$5 = Math.max; + + function isPointNull(x, y) { + return isNaN(x) || isNaN(y); + } + + function drawSegment(ctx, points, start, segLen, allLen, dir, smooth, smoothMonotone, connectNulls) { + var prevX; + var prevY; + var cpx0; + var cpy0; + var cpx1; + var cpy1; + var idx = start; + var k = 0; + + for (; k < segLen; k++) { + var x = points[idx * 2]; + var y = points[idx * 2 + 1]; + + if (idx >= allLen || idx < 0) { + break; + } + + if (isPointNull(x, y)) { + if (connectNulls) { + idx += dir; + continue; + } + + break; + } + + if (idx === start) { + ctx[dir > 0 ? 'moveTo' : 'lineTo'](x, y); + cpx0 = x; + cpy0 = y; + } else { + var dx = x - prevX; + var dy = y - prevY; + + if (dx * dx + dy * dy < 0.5) { + idx += dir; + continue; + } + + if (smooth > 0) { + var nextIdx = idx + dir; + var nextX = points[nextIdx * 2]; + var nextY = points[nextIdx * 2 + 1]; + var tmpK = k + 1; + + if (connectNulls) { + while (isPointNull(nextX, nextY) && tmpK < segLen) { + tmpK++; + nextIdx += dir; + nextX = points[nextIdx * 2]; + nextY = points[nextIdx * 2 + 1]; + } + } + + var ratioNextSeg = 0.5; + var vx = 0; + var vy = 0; + var nextCpx0 = void 0; + var nextCpy0 = void 0; + + if (tmpK >= segLen || isPointNull(nextX, nextY)) { + cpx1 = x; + cpy1 = y; + } else { + vx = nextX - prevX; + vy = nextY - prevY; + var dx0 = x - prevX; + var dx1 = nextX - x; + var dy0 = y - prevY; + var dy1 = nextY - y; + var lenPrevSeg = void 0; + var lenNextSeg = void 0; + + if (smoothMonotone === 'x') { + lenPrevSeg = Math.abs(dx0); + lenNextSeg = Math.abs(dx1); + cpx1 = x - lenPrevSeg * smooth; + cpy1 = y; + nextCpx0 = x + lenPrevSeg * smooth; + nextCpy0 = y; + } else if (smoothMonotone === 'y') { + lenPrevSeg = Math.abs(dy0); + lenNextSeg = Math.abs(dy1); + cpx1 = x; + cpy1 = y - lenPrevSeg * smooth; + nextCpx0 = x; + nextCpy0 = y + lenPrevSeg * smooth; + } else { + lenPrevSeg = Math.sqrt(dx0 * dx0 + dy0 * dy0); + lenNextSeg = Math.sqrt(dx1 * dx1 + dy1 * dy1); + ratioNextSeg = lenNextSeg / (lenNextSeg + lenPrevSeg); + cpx1 = x - vx * smooth * (1 - ratioNextSeg); + cpy1 = y - vy * smooth * (1 - ratioNextSeg); + nextCpx0 = x + vx * smooth * ratioNextSeg; + nextCpy0 = y + vy * smooth * ratioNextSeg; + nextCpx0 = mathMin$5(nextCpx0, mathMax$5(nextX, x)); + nextCpy0 = mathMin$5(nextCpy0, mathMax$5(nextY, y)); + nextCpx0 = mathMax$5(nextCpx0, mathMin$5(nextX, x)); + nextCpy0 = mathMax$5(nextCpy0, mathMin$5(nextY, y)); + vx = nextCpx0 - x; + vy = nextCpy0 - y; + cpx1 = x - vx * lenPrevSeg / lenNextSeg; + cpy1 = y - vy * lenPrevSeg / lenNextSeg; + cpx1 = mathMin$5(cpx1, mathMax$5(prevX, x)); + cpy1 = mathMin$5(cpy1, mathMax$5(prevY, y)); + cpx1 = mathMax$5(cpx1, mathMin$5(prevX, x)); + cpy1 = mathMax$5(cpy1, mathMin$5(prevY, y)); + vx = x - cpx1; + vy = y - cpy1; + nextCpx0 = x + vx * lenNextSeg / lenPrevSeg; + nextCpy0 = y + vy * lenNextSeg / lenPrevSeg; + } + } + + ctx.bezierCurveTo(cpx0, cpy0, cpx1, cpy1, x, y); + cpx0 = nextCpx0; + cpy0 = nextCpy0; + } else { + ctx.lineTo(x, y); + } + } + + prevX = x; + prevY = y; + idx += dir; + } + + return k; + } + + var ECPolylineShape = function () { + function ECPolylineShape() { + this.smooth = 0; + this.smoothConstraint = true; + } + + return ECPolylineShape; + }(); + + var ECPolyline = function (_super) { + __extends(ECPolyline, _super); + + function ECPolyline(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'ec-polyline'; + return _this; + } + + ECPolyline.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + + ECPolyline.prototype.getDefaultShape = function () { + return new ECPolylineShape(); + }; + + ECPolyline.prototype.buildPath = function (ctx, shape) { + var points = shape.points; + var i = 0; + var len = points.length / 2; + + if (shape.connectNulls) { + for (; len > 0; len--) { + if (!isPointNull(points[len * 2 - 2], points[len * 2 - 1])) { + break; + } + } + + for (; i < len; i++) { + if (!isPointNull(points[i * 2], points[i * 2 + 1])) { + break; + } + } + } + + while (i < len) { + i += drawSegment(ctx, points, i, len, len, 1, shape.smooth, shape.smoothMonotone, shape.connectNulls) + 1; + } + }; + + ECPolyline.prototype.getPointOn = function (xOrY, dim) { + if (!this.path) { + this.createPathProxy(); + this.buildPath(this.path, this.shape); + } + + var path = this.path; + var data = path.data; + var CMD = PathProxy.CMD; + var x0; + var y0; + var isDimX = dim === 'x'; + var roots = []; + + for (var i = 0; i < data.length;) { + var cmd = data[i++]; + var x = void 0; + var y = void 0; + var x2 = void 0; + var y2 = void 0; + var x3 = void 0; + var y3 = void 0; + var t = void 0; + + switch (cmd) { + case CMD.M: + x0 = data[i++]; + y0 = data[i++]; + break; + + case CMD.L: + x = data[i++]; + y = data[i++]; + t = isDimX ? (xOrY - x0) / (x - x0) : (xOrY - y0) / (y - y0); + + if (t <= 1 && t >= 0) { + var val = isDimX ? (y - y0) * t + y0 : (x - x0) * t + x0; + return isDimX ? [xOrY, val] : [val, xOrY]; + } + + x0 = x; + y0 = y; + break; + + case CMD.C: + x = data[i++]; + y = data[i++]; + x2 = data[i++]; + y2 = data[i++]; + x3 = data[i++]; + y3 = data[i++]; + var nRoot = isDimX ? cubicRootAt(x0, x, x2, x3, xOrY, roots) : cubicRootAt(y0, y, y2, y3, xOrY, roots); + + if (nRoot > 0) { + for (var i_1 = 0; i_1 < nRoot; i_1++) { + var t_1 = roots[i_1]; + + if (t_1 <= 1 && t_1 >= 0) { + var val = isDimX ? cubicAt(y0, y, y2, y3, t_1) : cubicAt(x0, x, x2, x3, t_1); + return isDimX ? [xOrY, val] : [val, xOrY]; + } + } + } + + x0 = x3; + y0 = y3; + break; + } + } + }; + + return ECPolyline; + }(Path); + + var ECPolygonShape = function (_super) { + __extends(ECPolygonShape, _super); + + function ECPolygonShape() { + return _super !== null && _super.apply(this, arguments) || this; + } + + return ECPolygonShape; + }(ECPolylineShape); + + var ECPolygon = function (_super) { + __extends(ECPolygon, _super); + + function ECPolygon(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'ec-polygon'; + return _this; + } + + ECPolygon.prototype.getDefaultShape = function () { + return new ECPolygonShape(); + }; + + ECPolygon.prototype.buildPath = function (ctx, shape) { + var points = shape.points; + var stackedOnPoints = shape.stackedOnPoints; + var i = 0; + var len = points.length / 2; + var smoothMonotone = shape.smoothMonotone; + + if (shape.connectNulls) { + for (; len > 0; len--) { + if (!isPointNull(points[len * 2 - 2], points[len * 2 - 1])) { + break; + } + } + + for (; i < len; i++) { + if (!isPointNull(points[i * 2], points[i * 2 + 1])) { + break; + } + } + } + + while (i < len) { + var k = drawSegment(ctx, points, i, len, len, 1, shape.smooth, smoothMonotone, shape.connectNulls); + drawSegment(ctx, stackedOnPoints, i + k - 1, k, len, -1, shape.stackedOnSmooth, smoothMonotone, shape.connectNulls); + i += k + 1; + ctx.closePath(); + } + }; + + return ECPolygon; + }(Path); + + function createGridClipPath(cartesian, hasAnimation, seriesModel, done, during) { + var rect = cartesian.getArea(); + var x = rect.x; + var y = rect.y; + var width = rect.width; + var height = rect.height; + var lineWidth = seriesModel.get(['lineStyle', 'width']) || 2; + x -= lineWidth / 2; + y -= lineWidth / 2; + width += lineWidth; + height += lineWidth; + x = Math.floor(x); + width = Math.round(width); + var clipPath = new Rect({ + shape: { + x: x, + y: y, + width: width, + height: height + } + }); + + if (hasAnimation) { + var baseAxis = cartesian.getBaseAxis(); + var isHorizontal = baseAxis.isHorizontal(); + var isAxisInversed = baseAxis.inverse; + + if (isHorizontal) { + if (isAxisInversed) { + clipPath.shape.x += width; + } + + clipPath.shape.width = 0; + } else { + if (!isAxisInversed) { + clipPath.shape.y += height; + } + + clipPath.shape.height = 0; + } + + var duringCb = typeof during === 'function' ? function (percent) { + during(percent, clipPath); + } : null; + initProps(clipPath, { + shape: { + width: width, + height: height, + x: x, + y: y + } + }, seriesModel, null, done, duringCb); + } + + return clipPath; + } + + function createPolarClipPath(polar, hasAnimation, seriesModel) { + var sectorArea = polar.getArea(); + var r0 = round(sectorArea.r0, 1); + var r = round(sectorArea.r, 1); + var clipPath = new Sector({ + shape: { + cx: round(polar.cx, 1), + cy: round(polar.cy, 1), + r0: r0, + r: r, + startAngle: sectorArea.startAngle, + endAngle: sectorArea.endAngle, + clockwise: sectorArea.clockwise + } + }); + + if (hasAnimation) { + var isRadial = polar.getBaseAxis().dim === 'angle'; + + if (isRadial) { + clipPath.shape.endAngle = sectorArea.startAngle; + } else { + clipPath.shape.r = r0; + } + + initProps(clipPath, { + shape: { + endAngle: sectorArea.endAngle, + r: r + } + }, seriesModel); + } + + return clipPath; + } + + function createClipPath(coordSys, hasAnimation, seriesModel, done, during) { + if (!coordSys) { + return null; + } else if (coordSys.type === 'polar') { + return createPolarClipPath(coordSys, hasAnimation, seriesModel); + } else if (coordSys.type === 'cartesian2d') { + return createGridClipPath(coordSys, hasAnimation, seriesModel, done, during); + } + + return null; + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function isCoordinateSystemType(coordSys, type) { + return coordSys.type === type; + } + + function isPointsSame(points1, points2) { + if (points1.length !== points2.length) { + return; + } + + for (var i = 0; i < points1.length; i++) { + if (points1[i] !== points2[i]) { + return; + } + } + + return true; + } + + function bboxFromPoints(points) { + var minX = Infinity; + var minY = Infinity; + var maxX = -Infinity; + var maxY = -Infinity; + + for (var i = 0; i < points.length;) { + var x = points[i++]; + var y = points[i++]; + + if (!isNaN(x)) { + minX = Math.min(x, minX); + maxX = Math.max(x, maxX); + } + + if (!isNaN(y)) { + minY = Math.min(y, minY); + maxY = Math.max(y, maxY); + } + } + + return [[minX, minY], [maxX, maxY]]; + } + + function getBoundingDiff(points1, points2) { + var _a = bboxFromPoints(points1), + min1 = _a[0], + max1 = _a[1]; + + var _b = bboxFromPoints(points2), + min2 = _b[0], + max2 = _b[1]; + + return Math.max(Math.abs(min1[0] - min2[0]), Math.abs(min1[1] - min2[1]), Math.abs(max1[0] - max2[0]), Math.abs(max1[1] - max2[1])); + } + + function getSmooth(smooth) { + return typeof smooth === 'number' ? smooth : smooth ? 0.5 : 0; + } + + function getStackedOnPoints(coordSys, data, dataCoordInfo) { + if (!dataCoordInfo.valueDim) { + return []; + } + + var len = data.count(); + var points = createFloat32Array(len * 2); + + for (var idx = 0; idx < len; idx++) { + var pt = getStackedOnPoint(dataCoordInfo, coordSys, data, idx); + points[idx * 2] = pt[0]; + points[idx * 2 + 1] = pt[1]; + } + + return points; + } + + function turnPointsIntoStep(points, coordSys, stepTurnAt) { + var baseAxis = coordSys.getBaseAxis(); + var baseIndex = baseAxis.dim === 'x' || baseAxis.dim === 'radius' ? 0 : 1; + var stepPoints = []; + var i = 0; + var stepPt = []; + var pt = []; + var nextPt = []; + + for (; i < points.length - 2; i += 2) { + nextPt[0] = points[i + 2]; + nextPt[1] = points[i + 3]; + pt[0] = points[i]; + pt[1] = points[i + 1]; + stepPoints.push(pt[0], pt[1]); + + switch (stepTurnAt) { + case 'end': + stepPt[baseIndex] = nextPt[baseIndex]; + stepPt[1 - baseIndex] = pt[1 - baseIndex]; + stepPoints.push(stepPt[0], stepPt[1]); + break; + + case 'middle': + var middle = (pt[baseIndex] + nextPt[baseIndex]) / 2; + var stepPt2 = []; + stepPt[baseIndex] = stepPt2[baseIndex] = middle; + stepPt[1 - baseIndex] = pt[1 - baseIndex]; + stepPt2[1 - baseIndex] = nextPt[1 - baseIndex]; + stepPoints.push(stepPt[0], stepPt[1]); + stepPoints.push(stepPt2[0], stepPt2[1]); + break; + + default: + stepPt[baseIndex] = pt[baseIndex]; + stepPt[1 - baseIndex] = nextPt[1 - baseIndex]; + stepPoints.push(stepPt[0], stepPt[1]); + } + } + + stepPoints.push(points[i++], points[i++]); + return stepPoints; + } + + function getVisualGradient(data, coordSys) { + var visualMetaList = data.getVisual('visualMeta'); + + if (!visualMetaList || !visualMetaList.length || !data.count()) { + return; + } + + if (coordSys.type !== 'cartesian2d') { + if ("development" !== 'production') { + console.warn('Visual map on line style is only supported on cartesian2d.'); + } + + return; + } + + var coordDim; + var visualMeta; + + for (var i = visualMetaList.length - 1; i >= 0; i--) { + var dimIndex = visualMetaList[i].dimension; + var dimName = data.dimensions[dimIndex]; + var dimInfo = data.getDimensionInfo(dimName); + coordDim = dimInfo && dimInfo.coordDim; + + if (coordDim === 'x' || coordDim === 'y') { + visualMeta = visualMetaList[i]; + break; + } + } + + if (!visualMeta) { + if ("development" !== 'production') { + console.warn('Visual map on line style only support x or y dimension.'); + } + + return; + } + + var axis = coordSys.getAxis(coordDim); + var colorStops = map(visualMeta.stops, function (stop) { + return { + offset: 0, + coord: axis.toGlobalCoord(axis.dataToCoord(stop.value)), + color: stop.color + }; + }); + var stopLen = colorStops.length; + var outerColors = visualMeta.outerColors.slice(); + + if (stopLen && colorStops[0].coord > colorStops[stopLen - 1].coord) { + colorStops.reverse(); + outerColors.reverse(); + } + + var tinyExtent = 10; + var minCoord = colorStops[0].coord - tinyExtent; + var maxCoord = colorStops[stopLen - 1].coord + tinyExtent; + var coordSpan = maxCoord - minCoord; + + if (coordSpan < 1e-3) { + return 'transparent'; + } + + each(colorStops, function (stop) { + stop.offset = (stop.coord - minCoord) / coordSpan; + }); + colorStops.push({ + offset: stopLen ? colorStops[stopLen - 1].offset : 0.5, + color: outerColors[1] || 'transparent' + }); + colorStops.unshift({ + offset: stopLen ? colorStops[0].offset : 0.5, + color: outerColors[0] || 'transparent' + }); + var gradient = new LinearGradient(0, 0, 0, 0, colorStops, true); + gradient[coordDim] = minCoord; + gradient[coordDim + '2'] = maxCoord; + return gradient; + } + + function getIsIgnoreFunc(seriesModel, data, coordSys) { + var showAllSymbol = seriesModel.get('showAllSymbol'); + var isAuto = showAllSymbol === 'auto'; + + if (showAllSymbol && !isAuto) { + return; + } + + var categoryAxis = coordSys.getAxesByScale('ordinal')[0]; + + if (!categoryAxis) { + return; + } + + if (isAuto && canShowAllSymbolForCategory(categoryAxis, data)) { + return; + } + + var categoryDataDim = data.mapDimension(categoryAxis.dim); + var labelMap = {}; + each(categoryAxis.getViewLabels(), function (labelItem) { + var ordinalNumber = categoryAxis.scale.getRawOrdinalNumber(labelItem.tickValue); + labelMap[ordinalNumber] = 1; + }); + return function (dataIndex) { + return !labelMap.hasOwnProperty(data.get(categoryDataDim, dataIndex)); + }; + } + + function canShowAllSymbolForCategory(categoryAxis, data) { + var axisExtent = categoryAxis.getExtent(); + var availSize = Math.abs(axisExtent[1] - axisExtent[0]) / categoryAxis.scale.count(); + isNaN(availSize) && (availSize = 0); + var dataLen = data.count(); + var step = Math.max(1, Math.round(dataLen / 5)); + + for (var dataIndex = 0; dataIndex < dataLen; dataIndex += step) { + if (Symbol.getSymbolSize(data, dataIndex)[categoryAxis.isHorizontal() ? 1 : 0] * 1.5 > availSize) { + return false; + } + } + + return true; + } + + function isPointNull$1(x, y) { + return isNaN(x) || isNaN(y); + } + + function getLastIndexNotNull(points) { + var len = points.length / 2; + + for (; len > 0; len--) { + if (!isPointNull$1(points[len * 2 - 2], points[len * 2 - 1])) { + break; + } + } + + return len - 1; + } + + function getPointAtIndex(points, idx) { + return [points[idx * 2], points[idx * 2 + 1]]; + } + + function getIndexRange(points, xOrY, dim) { + var len = points.length / 2; + var dimIdx = dim === 'x' ? 0 : 1; + var a; + var b; + var prevIndex = 0; + var nextIndex = -1; + + for (var i = 0; i < len; i++) { + b = points[i * 2 + dimIdx]; + + if (isNaN(b) || isNaN(points[i * 2 + 1 - dimIdx])) { + continue; + } + + if (i === 0) { + a = b; + continue; + } + + if (a <= xOrY && b >= xOrY || a >= xOrY && b <= xOrY) { + nextIndex = i; + break; + } + + prevIndex = i; + a = b; + } + + return { + range: [prevIndex, nextIndex], + t: (xOrY - a) / (b - a) + }; + } + + function createLineClipPath(lineView, coordSys, hasAnimation, seriesModel) { + if (isCoordinateSystemType(coordSys, 'cartesian2d')) { + var endLabelModel_1 = seriesModel.getModel('endLabel'); + var showEndLabel = endLabelModel_1.get('show'); + var valueAnimation_1 = endLabelModel_1.get('valueAnimation'); + var data_1 = seriesModel.getData(); + var labelAnimationRecord_1 = { + lastFrameIndex: 0 + }; + var during = showEndLabel ? function (percent, clipRect) { + lineView._endLabelOnDuring(percent, clipRect, data_1, labelAnimationRecord_1, valueAnimation_1, endLabelModel_1, coordSys); + } : null; + var isHorizontal = coordSys.getBaseAxis().isHorizontal(); + var clipPath = createGridClipPath(coordSys, hasAnimation, seriesModel, function () { + var endLabel = lineView._endLabel; + + if (endLabel && hasAnimation) { + if (labelAnimationRecord_1.originalX != null) { + endLabel.attr({ + x: labelAnimationRecord_1.originalX, + y: labelAnimationRecord_1.originalY + }); + } + } + }, during); + + if (!seriesModel.get('clip', true)) { + var rectShape = clipPath.shape; + var expandSize = Math.max(rectShape.width, rectShape.height); + + if (isHorizontal) { + rectShape.y -= expandSize; + rectShape.height += expandSize * 2; + } else { + rectShape.x -= expandSize; + rectShape.width += expandSize * 2; + } + } + + if (during) { + during(1, clipPath); + } + + return clipPath; + } else { + if ("development" !== 'production') { + if (seriesModel.get(['endLabel', 'show'])) { + console.warn('endLabel is not supported for lines in polar systems.'); + } + } + + return createPolarClipPath(coordSys, hasAnimation, seriesModel); + } + } + + function getEndLabelStateSpecified(endLabelModel, coordSys) { + var baseAxis = coordSys.getBaseAxis(); + var isHorizontal = baseAxis.isHorizontal(); + var isBaseInversed = baseAxis.inverse; + var align = isHorizontal ? isBaseInversed ? 'right' : 'left' : 'center'; + var verticalAlign = isHorizontal ? 'middle' : isBaseInversed ? 'top' : 'bottom'; + return { + normal: { + align: endLabelModel.get('align') || align, + verticalAlign: endLabelModel.get('verticalAlign') || verticalAlign + } + }; + } + + var LineView = function (_super) { + __extends(LineView, _super); + + function LineView() { + return _super !== null && _super.apply(this, arguments) || this; + } + + LineView.prototype.init = function () { + var lineGroup = new Group(); + var symbolDraw = new SymbolDraw(); + this.group.add(symbolDraw.group); + this._symbolDraw = symbolDraw; + this._lineGroup = lineGroup; + }; + + LineView.prototype.render = function (seriesModel, ecModel, api) { + var _this = this; + + var coordSys = seriesModel.coordinateSystem; + var group = this.group; + var data = seriesModel.getData(); + var lineStyleModel = seriesModel.getModel('lineStyle'); + var areaStyleModel = seriesModel.getModel('areaStyle'); + var points = data.getLayout('points') || []; + var isCoordSysPolar = coordSys.type === 'polar'; + var prevCoordSys = this._coordSys; + var symbolDraw = this._symbolDraw; + var polyline = this._polyline; + var polygon = this._polygon; + var lineGroup = this._lineGroup; + var hasAnimation = seriesModel.get('animation'); + var isAreaChart = !areaStyleModel.isEmpty(); + var valueOrigin = areaStyleModel.get('origin'); + var dataCoordInfo = prepareDataCoordInfo(coordSys, data, valueOrigin); + var stackedOnPoints = isAreaChart && getStackedOnPoints(coordSys, data, dataCoordInfo); + var showSymbol = seriesModel.get('showSymbol'); + var isIgnoreFunc = showSymbol && !isCoordSysPolar && getIsIgnoreFunc(seriesModel, data, coordSys); + var oldData = this._data; + oldData && oldData.eachItemGraphicEl(function (el, idx) { + if (el.__temp) { + group.remove(el); + oldData.setItemGraphicEl(idx, null); + } + }); + + if (!showSymbol) { + symbolDraw.remove(); + } + + group.add(lineGroup); + var step = !isCoordSysPolar ? seriesModel.get('step') : false; + var clipShapeForSymbol; + + if (coordSys && coordSys.getArea && seriesModel.get('clip', true)) { + clipShapeForSymbol = coordSys.getArea(); + + if (clipShapeForSymbol.width != null) { + clipShapeForSymbol.x -= 0.1; + clipShapeForSymbol.y -= 0.1; + clipShapeForSymbol.width += 0.2; + clipShapeForSymbol.height += 0.2; + } else if (clipShapeForSymbol.r0) { + clipShapeForSymbol.r0 -= 0.5; + clipShapeForSymbol.r += 0.5; + } + } + + this._clipShapeForSymbol = clipShapeForSymbol; + + if (!(polyline && prevCoordSys.type === coordSys.type && step === this._step)) { + showSymbol && symbolDraw.updateData(data, { + isIgnore: isIgnoreFunc, + clipShape: clipShapeForSymbol, + disableAnimation: true, + getSymbolPoint: function (idx) { + return [points[idx * 2], points[idx * 2 + 1]]; + } + }); + hasAnimation && this._initSymbolLabelAnimation(data, coordSys, clipShapeForSymbol); + + if (step) { + points = turnPointsIntoStep(points, coordSys, step); + + if (stackedOnPoints) { + stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step); + } + } + + polyline = this._newPolyline(points); + + if (isAreaChart) { + polygon = this._newPolygon(points, stackedOnPoints); + } + + if (!isCoordSysPolar) { + this._initOrUpdateEndLabel(seriesModel, coordSys); + } + + lineGroup.setClipPath(createLineClipPath(this, coordSys, true, seriesModel)); + } else { + if (isAreaChart && !polygon) { + polygon = this._newPolygon(points, stackedOnPoints); + } else if (polygon && !isAreaChart) { + lineGroup.remove(polygon); + polygon = this._polygon = null; + } + + if (!isCoordSysPolar) { + this._initOrUpdateEndLabel(seriesModel, coordSys); + } + + lineGroup.setClipPath(createLineClipPath(this, coordSys, false, seriesModel)); + showSymbol && symbolDraw.updateData(data, { + isIgnore: isIgnoreFunc, + clipShape: clipShapeForSymbol, + disableAnimation: true, + getSymbolPoint: function (idx) { + return [points[idx * 2], points[idx * 2 + 1]]; + } + }); + + if (!isPointsSame(this._stackedOnPoints, stackedOnPoints) || !isPointsSame(this._points, points)) { + if (hasAnimation) { + this._doUpdateAnimation(data, stackedOnPoints, coordSys, api, step, valueOrigin); + } else { + if (step) { + points = turnPointsIntoStep(points, coordSys, step); + + if (stackedOnPoints) { + stackedOnPoints = turnPointsIntoStep(stackedOnPoints, coordSys, step); + } + } + + polyline.setShape({ + points: points + }); + polygon && polygon.setShape({ + points: points, + stackedOnPoints: stackedOnPoints + }); + } + } + } + + var visualColor = getVisualGradient(data, coordSys) || data.getVisual('style')[data.getVisual('drawType')]; + var focus = seriesModel.get(['emphasis', 'focus']); + var blurScope = seriesModel.get(['emphasis', 'blurScope']); + polyline.useStyle(defaults(lineStyleModel.getLineStyle(), { + fill: 'none', + stroke: visualColor, + lineJoin: 'bevel' + })); + setStatesStylesFromModel(polyline, seriesModel, 'lineStyle'); + + if (polyline.style.lineWidth > 0 && seriesModel.get(['emphasis', 'lineStyle', 'width']) === 'bolder') { + var emphasisLineStyle = polyline.getState('emphasis').style; + emphasisLineStyle.lineWidth = polyline.style.lineWidth + 1; + } + + getECData(polyline).seriesIndex = seriesModel.seriesIndex; + enableHoverEmphasis(polyline, focus, blurScope); + var smooth = getSmooth(seriesModel.get('smooth')); + var smoothMonotone = seriesModel.get('smoothMonotone'); + var connectNulls = seriesModel.get('connectNulls'); + polyline.setShape({ + smooth: smooth, + smoothMonotone: smoothMonotone, + connectNulls: connectNulls + }); + + if (polygon) { + var stackedOnSeries = data.getCalculationInfo('stackedOnSeries'); + var stackedOnSmooth = 0; + polygon.useStyle(defaults(areaStyleModel.getAreaStyle(), { + fill: visualColor, + opacity: 0.7, + lineJoin: 'bevel', + decal: data.getVisual('style').decal + })); + + if (stackedOnSeries) { + stackedOnSmooth = getSmooth(stackedOnSeries.get('smooth')); + } + + polygon.setShape({ + smooth: smooth, + stackedOnSmooth: stackedOnSmooth, + smoothMonotone: smoothMonotone, + connectNulls: connectNulls + }); + setStatesStylesFromModel(polygon, seriesModel, 'areaStyle'); + getECData(polygon).seriesIndex = seriesModel.seriesIndex; + enableHoverEmphasis(polygon, focus, blurScope); + } + + var changePolyState = function (toState) { + _this._changePolyState(toState); + }; + + data.eachItemGraphicEl(function (el) { + el && (el.onHoverStateChange = changePolyState); + }); + this._polyline.onHoverStateChange = changePolyState; + this._data = data; + this._coordSys = coordSys; + this._stackedOnPoints = stackedOnPoints; + this._points = points; + this._step = step; + this._valueOrigin = valueOrigin; + }; + + LineView.prototype.dispose = function () {}; + + LineView.prototype.highlight = function (seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(); + var dataIndex = queryDataIndex(data, payload); + + this._changePolyState('emphasis'); + + if (!(dataIndex instanceof Array) && dataIndex != null && dataIndex >= 0) { + var points = data.getLayout('points'); + var symbol = data.getItemGraphicEl(dataIndex); + + if (!symbol) { + var x = points[dataIndex * 2]; + var y = points[dataIndex * 2 + 1]; + + if (isNaN(x) || isNaN(y)) { + return; + } + + if (this._clipShapeForSymbol && !this._clipShapeForSymbol.contain(x, y)) { + return; + } + + symbol = new Symbol(data, dataIndex); + symbol.x = x; + symbol.y = y; + symbol.setZ(seriesModel.get('zlevel'), seriesModel.get('z')); + symbol.__temp = true; + data.setItemGraphicEl(dataIndex, symbol); + symbol.stopSymbolAnimation(true); + this.group.add(symbol); + } + + symbol.highlight(); + } else { + ChartView.prototype.highlight.call(this, seriesModel, ecModel, api, payload); + } + }; + + LineView.prototype.downplay = function (seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(); + var dataIndex = queryDataIndex(data, payload); + + this._changePolyState('normal'); + + if (dataIndex != null && dataIndex >= 0) { + var symbol = data.getItemGraphicEl(dataIndex); + + if (symbol) { + if (symbol.__temp) { + data.setItemGraphicEl(dataIndex, null); + this.group.remove(symbol); + } else { + symbol.downplay(); + } + } + } else { + ChartView.prototype.downplay.call(this, seriesModel, ecModel, api, payload); + } + }; + + LineView.prototype._changePolyState = function (toState) { + var polygon = this._polygon; + setStatesFlag(this._polyline, toState); + polygon && setStatesFlag(polygon, toState); + }; + + LineView.prototype._newPolyline = function (points) { + var polyline = this._polyline; + + if (polyline) { + this._lineGroup.remove(polyline); + } + + polyline = new ECPolyline({ + shape: { + points: points + }, + segmentIgnoreThreshold: 2, + z2: 10 + }); + + this._lineGroup.add(polyline); + + this._polyline = polyline; + return polyline; + }; + + LineView.prototype._newPolygon = function (points, stackedOnPoints) { + var polygon = this._polygon; + + if (polygon) { + this._lineGroup.remove(polygon); + } + + polygon = new ECPolygon({ + shape: { + points: points, + stackedOnPoints: stackedOnPoints + }, + segmentIgnoreThreshold: 2 + }); + + this._lineGroup.add(polygon); + + this._polygon = polygon; + return polygon; + }; + + LineView.prototype._initSymbolLabelAnimation = function (data, coordSys, clipShape) { + var isHorizontalOrRadial; + var isCoordSysPolar; + var baseAxis = coordSys.getBaseAxis(); + var isAxisInverse = baseAxis.inverse; + + if (coordSys.type === 'cartesian2d') { + isHorizontalOrRadial = baseAxis.isHorizontal(); + isCoordSysPolar = false; + } else if (coordSys.type === 'polar') { + isHorizontalOrRadial = baseAxis.dim === 'angle'; + isCoordSysPolar = true; + } + + var seriesModel = data.hostModel; + var seriesDuration = seriesModel.get('animationDuration'); + + if (typeof seriesDuration === 'function') { + seriesDuration = seriesDuration(null); + } + + var seriesDalay = seriesModel.get('animationDelay') || 0; + var seriesDalayValue = typeof seriesDalay === 'function' ? seriesDalay(null) : seriesDalay; + data.eachItemGraphicEl(function (symbol, idx) { + var el = symbol; + + if (el) { + var point = [symbol.x, symbol.y]; + var start = void 0; + var end = void 0; + var current = void 0; + + if (isCoordSysPolar) { + var polarClip = clipShape; + var coord = coordSys.pointToCoord(point); + + if (isHorizontalOrRadial) { + start = polarClip.startAngle; + end = polarClip.endAngle; + current = -coord[1] / 180 * Math.PI; + } else { + start = polarClip.r0; + end = polarClip.r; + current = coord[0]; + } + } else { + var gridClip = clipShape; + + if (isHorizontalOrRadial) { + start = gridClip.x; + end = gridClip.x + gridClip.width; + current = symbol.x; + } else { + start = gridClip.y + gridClip.height; + end = gridClip.y; + current = symbol.y; + } + } + + var ratio = end === start ? 0 : (current - start) / (end - start); + + if (isAxisInverse) { + ratio = 1 - ratio; + } + + var delay = typeof seriesDalay === 'function' ? seriesDalay(idx) : seriesDuration * ratio + seriesDalayValue; + var symbolPath = el.getSymbolPath(); + var text = symbolPath.getTextContent(); + el.attr({ + scaleX: 0, + scaleY: 0 + }); + el.animateTo({ + scaleX: 1, + scaleY: 1 + }, { + duration: 200, + delay: delay + }); + + if (text) { + text.animateFrom({ + style: { + opacity: 0 + } + }, { + duration: 300, + delay: delay + }); + } + + symbolPath.disableLabelAnimation = true; + } + }); + }; + + LineView.prototype._initOrUpdateEndLabel = function (seriesModel, coordSys) { + var endLabelModel = seriesModel.getModel('endLabel'); + + if (endLabelModel.get('show')) { + var data_2 = seriesModel.getData(); + var polyline = this._polyline; + var endLabel = this._endLabel; + + if (!endLabel) { + endLabel = this._endLabel = new ZRText({ + z2: 200 + }); + endLabel.ignoreClip = true; + polyline.setTextContent(this._endLabel); + polyline.disableLabelAnimation = true; + } + + var dataIndex = getLastIndexNotNull(data_2.getLayout('points')); + + if (dataIndex >= 0) { + setLabelStyle(polyline, getLabelStatesModels(seriesModel, 'endLabel'), { + labelFetcher: seriesModel, + labelDataIndex: dataIndex, + defaultText: function (dataIndex, opt, interpolatedValue) { + return interpolatedValue != null ? getDefaultInterpolatedLabel(data_2, interpolatedValue) : getDefaultLabel(data_2, dataIndex); + }, + enableTextSetter: true + }, getEndLabelStateSpecified(endLabelModel, coordSys)); + polyline.textConfig.position = null; + } + } else if (this._endLabel) { + this._polyline.removeTextContent(); + + this._endLabel = null; + } + }; + + LineView.prototype._endLabelOnDuring = function (percent, clipRect, data, animationRecord, valueAnimation, endLabelModel, coordSys) { + var endLabel = this._endLabel; + var polyline = this._polyline; + + if (endLabel) { + if (percent < 1 && animationRecord.originalX == null) { + animationRecord.originalX = endLabel.x; + animationRecord.originalY = endLabel.y; + } + + var points = data.getLayout('points'); + var seriesModel = data.hostModel; + var connectNulls = seriesModel.get('connectNulls'); + var precision = endLabelModel.get('precision'); + var distance = endLabelModel.get('distance') || 0; + var baseAxis = coordSys.getBaseAxis(); + var isHorizontal = baseAxis.isHorizontal(); + var isBaseInversed = baseAxis.inverse; + var clipShape = clipRect.shape; + var xOrY = isBaseInversed ? isHorizontal ? clipShape.x : clipShape.y + clipShape.height : isHorizontal ? clipShape.x + clipShape.width : clipShape.y; + var distanceX = (isHorizontal ? distance : 0) * (isBaseInversed ? -1 : 1); + var distanceY = (isHorizontal ? 0 : -distance) * (isBaseInversed ? -1 : 1); + var dim = isHorizontal ? 'x' : 'y'; + var dataIndexRange = getIndexRange(points, xOrY, dim); + var indices = dataIndexRange.range; + var diff = indices[1] - indices[0]; + var value = void 0; + + if (diff >= 1) { + if (diff > 1 && !connectNulls) { + var pt = getPointAtIndex(points, indices[0]); + endLabel.attr({ + x: pt[0] + distanceX, + y: pt[1] + distanceY + }); + valueAnimation && (value = seriesModel.getRawValue(indices[0])); + } else { + var pt = polyline.getPointOn(xOrY, dim); + pt && endLabel.attr({ + x: pt[0] + distanceX, + y: pt[1] + distanceY + }); + var startValue = seriesModel.getRawValue(indices[0]); + var endValue = seriesModel.getRawValue(indices[1]); + valueAnimation && (value = interpolateRawValues(data, precision, startValue, endValue, dataIndexRange.t)); + } + + animationRecord.lastFrameIndex = indices[0]; + } else { + var idx = percent === 1 || animationRecord.lastFrameIndex > 0 ? indices[0] : 0; + var pt = getPointAtIndex(points, idx); + valueAnimation && (value = seriesModel.getRawValue(idx)); + endLabel.attr({ + x: pt[0] + distanceX, + y: pt[1] + distanceY + }); + } + + if (valueAnimation) { + labelInner(endLabel).setLabelText(value); + } + } + }; + + LineView.prototype._doUpdateAnimation = function (data, stackedOnPoints, coordSys, api, step, valueOrigin) { + var polyline = this._polyline; + var polygon = this._polygon; + var seriesModel = data.hostModel; + var diff = lineAnimationDiff(this._data, data, this._stackedOnPoints, stackedOnPoints, this._coordSys, coordSys, this._valueOrigin, valueOrigin); + var current = diff.current; + var stackedOnCurrent = diff.stackedOnCurrent; + var next = diff.next; + var stackedOnNext = diff.stackedOnNext; + + if (step) { + current = turnPointsIntoStep(diff.current, coordSys, step); + stackedOnCurrent = turnPointsIntoStep(diff.stackedOnCurrent, coordSys, step); + next = turnPointsIntoStep(diff.next, coordSys, step); + stackedOnNext = turnPointsIntoStep(diff.stackedOnNext, coordSys, step); + } + + if (getBoundingDiff(current, next) > 3000 || polygon && getBoundingDiff(stackedOnCurrent, stackedOnNext) > 3000) { + polyline.setShape({ + points: next + }); + + if (polygon) { + polygon.setShape({ + points: next, + stackedOnPoints: stackedOnNext + }); + } + + return; + } + + polyline.shape.__points = diff.current; + polyline.shape.points = current; + var target = { + shape: { + points: next + } + }; + + if (diff.current !== current) { + target.shape.__points = diff.next; + } + + polyline.stopAnimation(); + updateProps(polyline, target, seriesModel); + + if (polygon) { + polygon.setShape({ + points: current, + stackedOnPoints: stackedOnCurrent + }); + polygon.stopAnimation(); + updateProps(polygon, { + shape: { + stackedOnPoints: stackedOnNext + } + }, seriesModel); + + if (polyline.shape.points !== polygon.shape.points) { + polygon.shape.points = polyline.shape.points; + } + } + + var updatedDataInfo = []; + var diffStatus = diff.status; + + for (var i = 0; i < diffStatus.length; i++) { + var cmd = diffStatus[i].cmd; + + if (cmd === '=') { + var el = data.getItemGraphicEl(diffStatus[i].idx1); + + if (el) { + updatedDataInfo.push({ + el: el, + ptIdx: i + }); + } + } + } + + if (polyline.animators && polyline.animators.length) { + polyline.animators[0].during(function () { + polygon && polygon.dirtyShape(); + var points = polyline.shape.__points; + + for (var i = 0; i < updatedDataInfo.length; i++) { + var el = updatedDataInfo[i].el; + var offset = updatedDataInfo[i].ptIdx * 2; + el.x = points[offset]; + el.y = points[offset + 1]; + el.markRedraw(); + } + }); + } + }; + + LineView.prototype.remove = function (ecModel) { + var group = this.group; + var oldData = this._data; + + this._lineGroup.removeAll(); + + this._symbolDraw.remove(true); + + oldData && oldData.eachItemGraphicEl(function (el, idx) { + if (el.__temp) { + group.remove(el); + oldData.setItemGraphicEl(idx, null); + } + }); + this._polyline = this._polygon = this._coordSys = this._points = this._stackedOnPoints = this._endLabel = this._data = null; + }; + + LineView.type = 'line'; + return LineView; + }(ChartView); + + function pointsLayout(seriesType, forceStoreInTypedArray) { + return { + seriesType: seriesType, + plan: createRenderPlanner(), + reset: function (seriesModel) { + var data = seriesModel.getData(); + var coordSys = seriesModel.coordinateSystem; + var pipelineContext = seriesModel.pipelineContext; + var useTypedArray = forceStoreInTypedArray || pipelineContext.large; + + if (!coordSys) { + return; + } + + var dims = map(coordSys.dimensions, function (dim) { + return data.mapDimension(dim); + }).slice(0, 2); + var dimLen = dims.length; + var stackResultDim = data.getCalculationInfo('stackResultDimension'); + + if (isDimensionStacked(data, dims[0])) { + dims[0] = stackResultDim; + } + + if (isDimensionStacked(data, dims[1])) { + dims[1] = stackResultDim; + } + + var dimInfo0 = data.getDimensionInfo(dims[0]); + var dimInfo1 = data.getDimensionInfo(dims[1]); + var dimIdx0 = dimInfo0 && dimInfo0.index; + var dimIdx1 = dimInfo1 && dimInfo1.index; + return dimLen && { + progress: function (params, data) { + var segCount = params.end - params.start; + var points = useTypedArray && createFloat32Array(segCount * dimLen); + var tmpIn = []; + var tmpOut = []; + + for (var i = params.start, offset = 0; i < params.end; i++) { + var point = void 0; + + if (dimLen === 1) { + var x = data.getByDimIdx(dimIdx0, i); + point = coordSys.dataToPoint(x, null, tmpOut); + } else { + tmpIn[0] = data.getByDimIdx(dimIdx0, i); + tmpIn[1] = data.getByDimIdx(dimIdx1, i); + point = coordSys.dataToPoint(tmpIn, null, tmpOut); + } + + if (useTypedArray) { + points[offset++] = point[0]; + points[offset++] = point[1]; + } else { + data.setItemLayout(i, point.slice()); + } + } + + useTypedArray && data.setLayout('points', points); + } + }; + } + }; + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var samplers = { + average: function (frame) { + var sum = 0; + var count = 0; + + for (var i = 0; i < frame.length; i++) { + if (!isNaN(frame[i])) { + sum += frame[i]; + count++; + } + } + + return count === 0 ? NaN : sum / count; + }, + sum: function (frame) { + var sum = 0; + + for (var i = 0; i < frame.length; i++) { + sum += frame[i] || 0; + } + + return sum; + }, + max: function (frame) { + var max = -Infinity; + + for (var i = 0; i < frame.length; i++) { + frame[i] > max && (max = frame[i]); + } + + return isFinite(max) ? max : NaN; + }, + min: function (frame) { + var min = Infinity; + + for (var i = 0; i < frame.length; i++) { + frame[i] < min && (min = frame[i]); + } + + return isFinite(min) ? min : NaN; + }, + nearest: function (frame) { + return frame[0]; + } + }; + + var indexSampler = function (frame) { + return Math.round(frame.length / 2); + }; + + function dataSample(seriesType) { + return { + seriesType: seriesType, + reset: function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var sampling = seriesModel.get('sampling'); + var coordSys = seriesModel.coordinateSystem; + var count = data.count(); + + if (count > 10 && coordSys.type === 'cartesian2d' && sampling) { + var baseAxis = coordSys.getBaseAxis(); + var valueAxis = coordSys.getOtherAxis(baseAxis); + var extent = baseAxis.getExtent(); + var dpr = api.getDevicePixelRatio(); + var size = Math.abs(extent[1] - extent[0]) * (dpr || 1); + var rate = Math.round(count / size); + + if (rate > 1) { + if (sampling === 'lttb') { + seriesModel.setData(data.lttbDownSample(data.mapDimension(valueAxis.dim), 1 / rate)); + } + + var sampler = void 0; + + if (typeof sampling === 'string') { + sampler = samplers[sampling]; + } else if (typeof sampling === 'function') { + sampler = sampling; + } + + if (sampler) { + seriesModel.setData(data.downSample(data.mapDimension(valueAxis.dim), 1 / rate, sampler, indexSampler)); + } + } + } + } + }; + } + + function install$2(registers) { + registers.registerChartView(LineView); + registers.registerSeriesModel(LineSeriesModel); + registers.registerLayout(pointsLayout('line', true)); + registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, dataSample('line')); + } + + var BaseBarSeriesModel = function (_super) { + __extends(BaseBarSeriesModel, _super); + + function BaseBarSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = BaseBarSeriesModel.type; + return _this; + } + + BaseBarSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createListFromArray(this.getSource(), this, { + useEncodeDefaulter: true + }); + }; + + BaseBarSeriesModel.prototype.getMarkerPosition = function (value) { + var coordSys = this.coordinateSystem; + + if (coordSys) { + var pt = coordSys.dataToPoint(coordSys.clampData(value)); + var data = this.getData(); + var offset = data.getLayout('offset'); + var size = data.getLayout('size'); + var offsetIndex = coordSys.getBaseAxis().isHorizontal() ? 0 : 1; + pt[offsetIndex] += offset + size / 2; + return pt; + } + + return [NaN, NaN]; + }; + + BaseBarSeriesModel.type = 'series.__base_bar__'; + BaseBarSeriesModel.defaultOption = { + zlevel: 0, + z: 2, + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + barMinHeight: 0, + barMinAngle: 0, + large: false, + largeThreshold: 400, + progressive: 3e3, + progressiveChunkMode: 'mod' + }; + return BaseBarSeriesModel; + }(SeriesModel); + + SeriesModel.registerClass(BaseBarSeriesModel); + + var BarSeriesModel = function (_super) { + __extends(BarSeriesModel, _super); + + function BarSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = BarSeriesModel.type; + return _this; + } + + BarSeriesModel.prototype.getInitialData = function () { + return createListFromArray(this.getSource(), this, { + useEncodeDefaulter: true, + createInvertedIndices: !!this.get('realtimeSort', true) || null + }); + }; + + BarSeriesModel.prototype.getProgressive = function () { + return this.get('large') ? this.get('progressive') : false; + }; + + BarSeriesModel.prototype.getProgressiveThreshold = function () { + var progressiveThreshold = this.get('progressiveThreshold'); + var largeThreshold = this.get('largeThreshold'); + + if (largeThreshold > progressiveThreshold) { + progressiveThreshold = largeThreshold; + } + + return progressiveThreshold; + }; + + BarSeriesModel.prototype.brushSelector = function (dataIndex, data, selectors) { + return selectors.rect(data.getItemLayout(dataIndex)); + }; + + BarSeriesModel.type = 'series.bar'; + BarSeriesModel.dependencies = ['grid', 'polar']; + BarSeriesModel.defaultOption = inheritDefaultOption(BaseBarSeriesModel.defaultOption, { + clip: true, + roundCap: false, + showBackground: false, + backgroundStyle: { + color: 'rgba(180, 180, 180, 0.2)', + borderColor: null, + borderWidth: 0, + borderType: 'solid', + borderRadius: 0, + shadowBlur: 0, + shadowColor: null, + shadowOffsetX: 0, + shadowOffsetY: 0, + opacity: 1 + }, + select: { + itemStyle: { + borderColor: '#212121' + } + }, + realtimeSort: false + }); + return BarSeriesModel; + }(BaseBarSeriesModel); + + var SausageShape = function () { + function SausageShape() { + this.cx = 0; + this.cy = 0; + this.r0 = 0; + this.r = 0; + this.startAngle = 0; + this.endAngle = Math.PI * 2; + this.clockwise = true; + } + + return SausageShape; + }(); + + var SausagePath = function (_super) { + __extends(SausagePath, _super); + + function SausagePath(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'sausage'; + return _this; + } + + SausagePath.prototype.getDefaultShape = function () { + return new SausageShape(); + }; + + SausagePath.prototype.buildPath = function (ctx, shape) { + var x = shape.cx; + var y = shape.cy; + var r0 = Math.max(shape.r0 || 0, 0); + var r = Math.max(shape.r, 0); + var dr = (r - r0) * 0.5; + var rCenter = r0 + dr; + var startAngle = shape.startAngle; + var endAngle = shape.endAngle; + var clockwise = shape.clockwise; + var unitStartX = Math.cos(startAngle); + var unitStartY = Math.sin(startAngle); + var unitEndX = Math.cos(endAngle); + var unitEndY = Math.sin(endAngle); + var lessThanCircle = clockwise ? endAngle - startAngle < Math.PI * 2 : startAngle - endAngle < Math.PI * 2; + + if (lessThanCircle) { + ctx.moveTo(unitStartX * r0 + x, unitStartY * r0 + y); + ctx.arc(unitStartX * rCenter + x, unitStartY * rCenter + y, dr, -Math.PI + startAngle, startAngle, !clockwise); + } + + ctx.arc(x, y, r, startAngle, endAngle, !clockwise); + ctx.moveTo(unitEndX * r + x, unitEndY * r + y); + ctx.arc(unitEndX * rCenter + x, unitEndY * rCenter + y, dr, endAngle - Math.PI * 2, endAngle - Math.PI, !clockwise); + + if (r0 !== 0) { + ctx.arc(x, y, r0, endAngle, startAngle, clockwise); + ctx.moveTo(unitStartX * r0 + x, unitEndY * r0 + y); + } + + ctx.closePath(); + }; + + return SausagePath; + }(Path); + + var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'borderWidth']; + var BAR_BORDER_RADIUS_QUERY = ['itemStyle', 'borderRadius']; + var _eventPos = [0, 0]; + var mathMax$6 = Math.max; + var mathMin$6 = Math.min; + + function getClipArea(coord, data) { + var coordSysClipArea = coord.getArea && coord.getArea(); + + if (isCoordinateSystemType(coord, 'cartesian2d')) { + var baseAxis = coord.getBaseAxis(); + + if (baseAxis.type !== 'category' || !baseAxis.onBand) { + var expandWidth = data.getLayout('bandWidth'); + + if (baseAxis.isHorizontal()) { + coordSysClipArea.x -= expandWidth; + coordSysClipArea.width += expandWidth * 2; + } else { + coordSysClipArea.y -= expandWidth; + coordSysClipArea.height += expandWidth * 2; + } + } + } + + return coordSysClipArea; + } + + var BarView = function (_super) { + __extends(BarView, _super); + + function BarView() { + var _this = _super.call(this) || this; + + _this.type = BarView.type; + _this._isFirstFrame = true; + return _this; + } + + BarView.prototype.render = function (seriesModel, ecModel, api, payload) { + this._model = seriesModel; + + this._removeOnRenderedListener(api); + + this._updateDrawMode(seriesModel); + + var coordinateSystemType = seriesModel.get('coordinateSystem'); + + if (coordinateSystemType === 'cartesian2d' || coordinateSystemType === 'polar') { + this._isLargeDraw ? this._renderLarge(seriesModel, ecModel, api) : this._renderNormal(seriesModel, ecModel, api, payload); + } else if ("development" !== 'production') { + warn('Only cartesian2d and polar supported for bar.'); + } + }; + + BarView.prototype.incrementalPrepareRender = function (seriesModel) { + this._clear(); + + this._updateDrawMode(seriesModel); + + this._updateLargeClip(seriesModel); + }; + + BarView.prototype.incrementalRender = function (params, seriesModel) { + this._incrementalRenderLarge(params, seriesModel); + }; + + BarView.prototype._updateDrawMode = function (seriesModel) { + var isLargeDraw = seriesModel.pipelineContext.large; + + if (this._isLargeDraw == null || isLargeDraw !== this._isLargeDraw) { + this._isLargeDraw = isLargeDraw; + + this._clear(); + } + }; + + BarView.prototype._renderNormal = function (seriesModel, ecModel, api, payload) { + var group = this.group; + var data = seriesModel.getData(); + var oldData = this._data; + var coord = seriesModel.coordinateSystem; + var baseAxis = coord.getBaseAxis(); + var isHorizontalOrRadial; + + if (coord.type === 'cartesian2d') { + isHorizontalOrRadial = baseAxis.isHorizontal(); + } else if (coord.type === 'polar') { + isHorizontalOrRadial = baseAxis.dim === 'angle'; + } + + var animationModel = seriesModel.isAnimationEnabled() ? seriesModel : null; + var realtimeSortCfg = shouldRealtimeSort(seriesModel, coord); + + if (realtimeSortCfg) { + this._enableRealtimeSort(realtimeSortCfg, data, api); + } + + var needsClip = seriesModel.get('clip', true) || realtimeSortCfg; + var coordSysClipArea = getClipArea(coord, data); + group.removeClipPath(); + var roundCap = seriesModel.get('roundCap', true); + var drawBackground = seriesModel.get('showBackground', true); + var backgroundModel = seriesModel.getModel('backgroundStyle'); + var barBorderRadius = backgroundModel.get('borderRadius') || 0; + var bgEls = []; + var oldBgEls = this._backgroundEls; + var isInitSort = payload && payload.isInitSort; + var isChangeOrder = payload && payload.type === 'changeAxisOrder'; + + function createBackground(dataIndex) { + var bgLayout = getLayout[coord.type](data, dataIndex); + var bgEl = createBackgroundEl(coord, isHorizontalOrRadial, bgLayout); + bgEl.useStyle(backgroundModel.getItemStyle()); + + if (coord.type === 'cartesian2d') { + bgEl.setShape('r', barBorderRadius); + } + + bgEls[dataIndex] = bgEl; + return bgEl; + } + data.diff(oldData).add(function (dataIndex) { + var itemModel = data.getItemModel(dataIndex); + var layout = getLayout[coord.type](data, dataIndex, itemModel); + + if (drawBackground) { + createBackground(dataIndex); + } + + if (!data.hasValue(dataIndex)) { + return; + } + + var isClipped = false; + + if (needsClip) { + isClipped = clip[coord.type](coordSysClipArea, layout); + } + + var el = elementCreator[coord.type](seriesModel, data, dataIndex, layout, isHorizontalOrRadial, animationModel, baseAxis.model, false, roundCap); + updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar'); + + if (isInitSort) { + el.attr({ + shape: layout + }); + } else if (realtimeSortCfg) { + updateRealtimeAnimation(realtimeSortCfg, animationModel, el, layout, dataIndex, isHorizontalOrRadial, false, false); + } else { + initProps(el, { + shape: layout + }, seriesModel, dataIndex); + } + + data.setItemGraphicEl(dataIndex, el); + group.add(el); + el.ignore = isClipped; + }).update(function (newIndex, oldIndex) { + var itemModel = data.getItemModel(newIndex); + var layout = getLayout[coord.type](data, newIndex, itemModel); + + if (drawBackground) { + var bgEl = void 0; + + if (oldBgEls.length === 0) { + bgEl = createBackground(oldIndex); + } else { + bgEl = oldBgEls[oldIndex]; + bgEl.useStyle(backgroundModel.getItemStyle()); + + if (coord.type === 'cartesian2d') { + bgEl.setShape('r', barBorderRadius); + } + + bgEls[newIndex] = bgEl; + } + + var bgLayout = getLayout[coord.type](data, newIndex); + var shape = createBackgroundShape(isHorizontalOrRadial, bgLayout, coord); + updateProps(bgEl, { + shape: shape + }, animationModel, newIndex); + } + + var el = oldData.getItemGraphicEl(oldIndex); + + if (!data.hasValue(newIndex)) { + group.remove(el); + el = null; + return; + } + + var isClipped = false; + + if (needsClip) { + isClipped = clip[coord.type](coordSysClipArea, layout); + + if (isClipped) { + group.remove(el); + } + } + + if (!el) { + el = elementCreator[coord.type](seriesModel, data, newIndex, layout, isHorizontalOrRadial, animationModel, baseAxis.model, !!el, roundCap); + } + + if (!isChangeOrder) { + updateStyle(el, data, newIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar'); + } + + if (isInitSort) { + el.attr({ + shape: layout + }); + } else if (realtimeSortCfg) { + updateRealtimeAnimation(realtimeSortCfg, animationModel, el, layout, newIndex, isHorizontalOrRadial, true, isChangeOrder); + } else { + updateProps(el, { + shape: layout + }, seriesModel, newIndex, null); + } + + data.setItemGraphicEl(newIndex, el); + el.ignore = isClipped; + group.add(el); + }).remove(function (dataIndex) { + var el = oldData.getItemGraphicEl(dataIndex); + el && removeElementWithFadeOut(el, seriesModel, dataIndex); + }).execute(); + var bgGroup = this._backgroundGroup || (this._backgroundGroup = new Group()); + bgGroup.removeAll(); + + for (var i = 0; i < bgEls.length; ++i) { + bgGroup.add(bgEls[i]); + } + + group.add(bgGroup); + this._backgroundEls = bgEls; + this._data = data; + }; + + BarView.prototype._renderLarge = function (seriesModel, ecModel, api) { + this._clear(); + + createLarge(seriesModel, this.group); + + this._updateLargeClip(seriesModel); + }; + + BarView.prototype._incrementalRenderLarge = function (params, seriesModel) { + this._removeBackground(); + + createLarge(seriesModel, this.group, true); + }; + + BarView.prototype._updateLargeClip = function (seriesModel) { + var clipPath = seriesModel.get('clip', true) ? createClipPath(seriesModel.coordinateSystem, false, seriesModel) : null; + + if (clipPath) { + this.group.setClipPath(clipPath); + } else { + this.group.removeClipPath(); + } + }; + + BarView.prototype._enableRealtimeSort = function (realtimeSortCfg, data, api) { + var _this = this; + + if (!data.count()) { + return; + } + + var baseAxis = realtimeSortCfg.baseAxis; + + if (this._isFirstFrame) { + this._dispatchInitSort(data, realtimeSortCfg, api); + + this._isFirstFrame = false; + } else { + var orderMapping_1 = function (idx) { + var el = data.getItemGraphicEl(idx); + + if (el) { + var shape = el.shape; + return (baseAxis.isHorizontal() ? Math.abs(shape.height) : Math.abs(shape.width)) || 0; + } else { + return 0; + } + }; + + this._onRendered = function () { + _this._updateSortWithinSameData(data, orderMapping_1, baseAxis, api); + }; + + api.getZr().on('rendered', this._onRendered); + } + }; + + BarView.prototype._dataSort = function (data, baseAxis, orderMapping) { + var info = []; + data.each(data.mapDimension(baseAxis.dim), function (ordinalNumber, dataIdx) { + var mappedValue = orderMapping(dataIdx); + mappedValue = mappedValue == null ? NaN : mappedValue; + info.push({ + dataIndex: dataIdx, + mappedValue: mappedValue, + ordinalNumber: ordinalNumber + }); + }); + info.sort(function (a, b) { + return b.mappedValue - a.mappedValue; + }); + return { + ordinalNumbers: map(info, function (item) { + return item.ordinalNumber; + }) + }; + }; + + BarView.prototype._isOrderChangedWithinSameData = function (data, orderMapping, baseAxis) { + var scale = baseAxis.scale; + var ordinalDataDim = data.mapDimension(baseAxis.dim); + var lastValue = Number.MAX_VALUE; + + for (var tickNum = 0, len = scale.getOrdinalMeta().categories.length; tickNum < len; ++tickNum) { + var rawIdx = data.rawIndexOf(ordinalDataDim, scale.getRawOrdinalNumber(tickNum)); + var value = rawIdx < 0 ? Number.MIN_VALUE : orderMapping(data.indexOfRawIndex(rawIdx)); + + if (value > lastValue) { + return true; + } + + lastValue = value; + } + + return false; + }; + + BarView.prototype._isOrderDifferentInView = function (orderInfo, baseAxis) { + var scale = baseAxis.scale; + var extent = scale.getExtent(); + var tickNum = Math.max(0, extent[0]); + var tickMax = Math.min(extent[1], scale.getOrdinalMeta().categories.length - 1); + + for (; tickNum <= tickMax; ++tickNum) { + if (orderInfo.ordinalNumbers[tickNum] !== scale.getRawOrdinalNumber(tickNum)) { + return true; + } + } + }; + + BarView.prototype._updateSortWithinSameData = function (data, orderMapping, baseAxis, api) { + if (!this._isOrderChangedWithinSameData(data, orderMapping, baseAxis)) { + return; + } + + var sortInfo = this._dataSort(data, baseAxis, orderMapping); + + if (this._isOrderDifferentInView(sortInfo, baseAxis)) { + this._removeOnRenderedListener(api); + + api.dispatchAction({ + type: 'changeAxisOrder', + componentType: baseAxis.dim + 'Axis', + axisId: baseAxis.index, + sortInfo: sortInfo + }); + } + }; + + BarView.prototype._dispatchInitSort = function (data, realtimeSortCfg, api) { + var baseAxis = realtimeSortCfg.baseAxis; + + var sortResult = this._dataSort(data, baseAxis, function (dataIdx) { + return data.get(data.mapDimension(realtimeSortCfg.otherAxis.dim), dataIdx); + }); + + api.dispatchAction({ + type: 'changeAxisOrder', + componentType: baseAxis.dim + 'Axis', + isInitSort: true, + axisId: baseAxis.index, + sortInfo: sortResult, + animation: { + duration: 0 + } + }); + }; + + BarView.prototype.remove = function (ecModel, api) { + this._clear(this._model); + + this._removeOnRenderedListener(api); + }; + + BarView.prototype.dispose = function (ecModel, api) { + this._removeOnRenderedListener(api); + }; + + BarView.prototype._removeOnRenderedListener = function (api) { + if (this._onRendered) { + api.getZr().off('rendered', this._onRendered); + this._onRendered = null; + } + }; + + BarView.prototype._clear = function (model) { + var group = this.group; + var data = this._data; + + if (model && model.isAnimationEnabled() && data && !this._isLargeDraw) { + this._removeBackground(); + + this._backgroundEls = []; + data.eachItemGraphicEl(function (el) { + removeElementWithFadeOut(el, model, getECData(el).dataIndex); + }); + } else { + group.removeAll(); + } + + this._data = null; + this._isFirstFrame = true; + }; + + BarView.prototype._removeBackground = function () { + this.group.remove(this._backgroundGroup); + this._backgroundGroup = null; + }; + + BarView.type = 'bar'; + return BarView; + }(ChartView); + + var clip = { + cartesian2d: function (coordSysBoundingRect, layout) { + var signWidth = layout.width < 0 ? -1 : 1; + var signHeight = layout.height < 0 ? -1 : 1; + + if (signWidth < 0) { + layout.x += layout.width; + layout.width = -layout.width; + } + + if (signHeight < 0) { + layout.y += layout.height; + layout.height = -layout.height; + } + + var coordSysX2 = coordSysBoundingRect.x + coordSysBoundingRect.width; + var coordSysY2 = coordSysBoundingRect.y + coordSysBoundingRect.height; + var x = mathMax$6(layout.x, coordSysBoundingRect.x); + var x2 = mathMin$6(layout.x + layout.width, coordSysX2); + var y = mathMax$6(layout.y, coordSysBoundingRect.y); + var y2 = mathMin$6(layout.y + layout.height, coordSysY2); + var xClipped = x2 < x; + var yClipped = y2 < y; + layout.x = xClipped && x > coordSysX2 ? x2 : x; + layout.y = yClipped && y > coordSysY2 ? y2 : y; + layout.width = xClipped ? 0 : x2 - x; + layout.height = yClipped ? 0 : y2 - y; + + if (signWidth < 0) { + layout.x += layout.width; + layout.width = -layout.width; + } + + if (signHeight < 0) { + layout.y += layout.height; + layout.height = -layout.height; + } + + return xClipped || yClipped; + }, + polar: function (coordSysClipArea, layout) { + var signR = layout.r0 <= layout.r ? 1 : -1; + + if (signR < 0) { + var tmp = layout.r; + layout.r = layout.r0; + layout.r0 = tmp; + } + + var r = mathMin$6(layout.r, coordSysClipArea.r); + var r0 = mathMax$6(layout.r0, coordSysClipArea.r0); + layout.r = r; + layout.r0 = r0; + var clipped = r - r0 < 0; + + if (signR < 0) { + var tmp = layout.r; + layout.r = layout.r0; + layout.r0 = tmp; + } + + return clipped; + } + }; + var elementCreator = { + cartesian2d: function (seriesModel, data, newIndex, layout, isHorizontal, animationModel, axisModel, isUpdate, roundCap) { + var rect = new Rect({ + shape: extend({}, layout), + z2: 1 + }); + rect.__dataIndex = newIndex; + rect.name = 'item'; + + if (animationModel) { + var rectShape = rect.shape; + var animateProperty = isHorizontal ? 'height' : 'width'; + rectShape[animateProperty] = 0; + } + + return rect; + }, + polar: function (seriesModel, data, newIndex, layout, isRadial, animationModel, axisModel, isUpdate, roundCap) { + var clockwise = layout.startAngle < layout.endAngle; + var ShapeClass = !isRadial && roundCap ? SausagePath : Sector; + var sector = new ShapeClass({ + shape: defaults({ + clockwise: clockwise + }, layout), + z2: 1 + }); + sector.name = 'item'; + + if (animationModel) { + var sectorShape = sector.shape; + var animateProperty = isRadial ? 'r' : 'endAngle'; + var animateTarget = {}; + sectorShape[animateProperty] = isRadial ? 0 : layout.startAngle; + animateTarget[animateProperty] = layout[animateProperty]; + (isUpdate ? updateProps : initProps)(sector, { + shape: animateTarget + }, animationModel); + } + + return sector; + } + }; + + function shouldRealtimeSort(seriesModel, coordSys) { + var realtimeSortOption = seriesModel.get('realtimeSort', true); + var baseAxis = coordSys.getBaseAxis(); + + if ("development" !== 'production') { + if (realtimeSortOption) { + if (baseAxis.type !== 'category') { + warn('`realtimeSort` will not work because this bar series is not based on a category axis.'); + } + + if (coordSys.type !== 'cartesian2d') { + warn('`realtimeSort` will not work because this bar series is not on cartesian2d.'); + } + } + } + + if (realtimeSortOption && baseAxis.type === 'category' && coordSys.type === 'cartesian2d') { + return { + baseAxis: baseAxis, + otherAxis: coordSys.getOtherAxis(baseAxis) + }; + } + } + + function updateRealtimeAnimation(realtimeSortCfg, seriesAnimationModel, el, layout, newIndex, isHorizontal, isUpdate, isChangeOrder) { + var seriesTarget; + var axisTarget; + + if (isHorizontal) { + axisTarget = { + x: layout.x, + width: layout.width + }; + seriesTarget = { + y: layout.y, + height: layout.height + }; + } else { + axisTarget = { + y: layout.y, + height: layout.height + }; + seriesTarget = { + x: layout.x, + width: layout.width + }; + } + + if (!isChangeOrder) { + (isUpdate ? updateProps : initProps)(el, { + shape: seriesTarget + }, seriesAnimationModel, newIndex, null); + } + + var axisAnimationModel = seriesAnimationModel ? realtimeSortCfg.baseAxis.model : null; + (isUpdate ? updateProps : initProps)(el, { + shape: axisTarget + }, axisAnimationModel, newIndex); + } + + var getLayout = { + cartesian2d: function (data, dataIndex, itemModel) { + var layout = data.getItemLayout(dataIndex); + var fixedLineWidth = itemModel ? getLineWidth(itemModel, layout) : 0; + var signX = layout.width > 0 ? 1 : -1; + var signY = layout.height > 0 ? 1 : -1; + return { + x: layout.x + signX * fixedLineWidth / 2, + y: layout.y + signY * fixedLineWidth / 2, + width: layout.width - signX * fixedLineWidth, + height: layout.height - signY * fixedLineWidth + }; + }, + polar: function (data, dataIndex, itemModel) { + var layout = data.getItemLayout(dataIndex); + return { + cx: layout.cx, + cy: layout.cy, + r0: layout.r0, + r: layout.r, + startAngle: layout.startAngle, + endAngle: layout.endAngle + }; + } + }; + + function isZeroOnPolar(layout) { + return layout.startAngle != null && layout.endAngle != null && layout.startAngle === layout.endAngle; + } + + function updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontal, isPolar) { + var style = data.getItemVisual(dataIndex, 'style'); + + if (!isPolar) { + el.setShape('r', itemModel.get(BAR_BORDER_RADIUS_QUERY) || 0); + } + + el.useStyle(style); + var cursorStyle = itemModel.getShallow('cursor'); + cursorStyle && el.attr('cursor', cursorStyle); + + if (!isPolar) { + var labelPositionOutside = isHorizontal ? layout.height > 0 ? 'bottom' : 'top' : layout.width > 0 ? 'left' : 'right'; + var labelStatesModels = getLabelStatesModels(itemModel); + setLabelStyle(el, labelStatesModels, { + labelFetcher: seriesModel, + labelDataIndex: dataIndex, + defaultText: getDefaultLabel(seriesModel.getData(), dataIndex), + inheritColor: style.fill, + defaultOpacity: style.opacity, + defaultOutsidePosition: labelPositionOutside + }); + var label = el.getTextContent(); + setLabelValueAnimation(label, labelStatesModels, seriesModel.getRawValue(dataIndex), function (value) { + return getDefaultInterpolatedLabel(data, value); + }); + } + + var emphasisModel = itemModel.getModel(['emphasis']); + enableHoverEmphasis(el, emphasisModel.get('focus'), emphasisModel.get('blurScope')); + setStatesStylesFromModel(el, itemModel); + + if (isZeroOnPolar(layout)) { + el.style.fill = 'none'; + el.style.stroke = 'none'; + each(el.states, function (state) { + if (state.style) { + state.style.fill = state.style.stroke = 'none'; + } + }); + } + } + + function getLineWidth(itemModel, rawLayout) { + var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0; + var width = isNaN(rawLayout.width) ? Number.MAX_VALUE : Math.abs(rawLayout.width); + var height = isNaN(rawLayout.height) ? Number.MAX_VALUE : Math.abs(rawLayout.height); + return Math.min(lineWidth, width, height); + } + + var LagePathShape = function () { + function LagePathShape() {} + + return LagePathShape; + }(); + + var LargePath = function (_super) { + __extends(LargePath, _super); + + function LargePath(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'largeBar'; + return _this; + } + + LargePath.prototype.getDefaultShape = function () { + return new LagePathShape(); + }; + + LargePath.prototype.buildPath = function (ctx, shape) { + var points = shape.points; + var startPoint = this.__startPoint; + var baseDimIdx = this.__baseDimIdx; + + for (var i = 0; i < points.length; i += 2) { + startPoint[baseDimIdx] = points[i + baseDimIdx]; + ctx.moveTo(startPoint[0], startPoint[1]); + ctx.lineTo(points[i], points[i + 1]); + } + }; + + return LargePath; + }(Path); + + function createLarge(seriesModel, group, incremental) { + var data = seriesModel.getData(); + var startPoint = []; + var baseDimIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0; + startPoint[1 - baseDimIdx] = data.getLayout('valueAxisStart'); + var largeDataIndices = data.getLayout('largeDataIndices'); + var barWidth = data.getLayout('barWidth'); + var backgroundModel = seriesModel.getModel('backgroundStyle'); + var drawBackground = seriesModel.get('showBackground', true); + + if (drawBackground) { + var points = data.getLayout('largeBackgroundPoints'); + var backgroundStartPoint = []; + backgroundStartPoint[1 - baseDimIdx] = data.getLayout('backgroundStart'); + var bgEl = new LargePath({ + shape: { + points: points + }, + incremental: !!incremental, + silent: true, + z2: 0 + }); + bgEl.__startPoint = backgroundStartPoint; + bgEl.__baseDimIdx = baseDimIdx; + bgEl.__largeDataIndices = largeDataIndices; + bgEl.__barWidth = barWidth; + setLargeBackgroundStyle(bgEl, backgroundModel, data); + group.add(bgEl); + } + + var el = new LargePath({ + shape: { + points: data.getLayout('largePoints') + }, + incremental: !!incremental + }); + el.__startPoint = startPoint; + el.__baseDimIdx = baseDimIdx; + el.__largeDataIndices = largeDataIndices; + el.__barWidth = barWidth; + group.add(el); + setLargeStyle(el, seriesModel, data); + getECData(el).seriesIndex = seriesModel.seriesIndex; + + if (!seriesModel.get('silent')) { + el.on('mousedown', largePathUpdateDataIndex); + el.on('mousemove', largePathUpdateDataIndex); + } + } + + var largePathUpdateDataIndex = throttle(function (event) { + var largePath = this; + var dataIndex = largePathFindDataIndex(largePath, event.offsetX, event.offsetY); + getECData(largePath).dataIndex = dataIndex >= 0 ? dataIndex : null; + }, 30, false); + + function largePathFindDataIndex(largePath, x, y) { + var baseDimIdx = largePath.__baseDimIdx; + var valueDimIdx = 1 - baseDimIdx; + var points = largePath.shape.points; + var largeDataIndices = largePath.__largeDataIndices; + var barWidthHalf = Math.abs(largePath.__barWidth / 2); + var startValueVal = largePath.__startPoint[valueDimIdx]; + _eventPos[0] = x; + _eventPos[1] = y; + var pointerBaseVal = _eventPos[baseDimIdx]; + var pointerValueVal = _eventPos[1 - baseDimIdx]; + var baseLowerBound = pointerBaseVal - barWidthHalf; + var baseUpperBound = pointerBaseVal + barWidthHalf; + + for (var i = 0, len = points.length / 2; i < len; i++) { + var ii = i * 2; + var barBaseVal = points[ii + baseDimIdx]; + var barValueVal = points[ii + valueDimIdx]; + + if (barBaseVal >= baseLowerBound && barBaseVal <= baseUpperBound && (startValueVal <= barValueVal ? pointerValueVal >= startValueVal && pointerValueVal <= barValueVal : pointerValueVal >= barValueVal && pointerValueVal <= startValueVal)) { + return largeDataIndices[i]; + } + } + + return -1; + } + + function setLargeStyle(el, seriesModel, data) { + var globalStyle = data.getVisual('style'); + el.useStyle(extend({}, globalStyle)); + el.style.fill = null; + el.style.stroke = globalStyle.fill; + el.style.lineWidth = data.getLayout('barWidth'); + } + + function setLargeBackgroundStyle(el, backgroundModel, data) { + var borderColor = backgroundModel.get('borderColor') || backgroundModel.get('color'); + var itemStyle = backgroundModel.getItemStyle(); + el.useStyle(itemStyle); + el.style.fill = null; + el.style.stroke = borderColor; + el.style.lineWidth = data.getLayout('barWidth'); + } + + function createBackgroundShape(isHorizontalOrRadial, layout, coord) { + if (isCoordinateSystemType(coord, 'cartesian2d')) { + var rectShape = layout; + var coordLayout = coord.getArea(); + return { + x: isHorizontalOrRadial ? rectShape.x : coordLayout.x, + y: isHorizontalOrRadial ? coordLayout.y : rectShape.y, + width: isHorizontalOrRadial ? rectShape.width : coordLayout.width, + height: isHorizontalOrRadial ? coordLayout.height : rectShape.height + }; + } else { + var coordLayout = coord.getArea(); + var sectorShape = layout; + return { + cx: coordLayout.cx, + cy: coordLayout.cy, + r0: isHorizontalOrRadial ? coordLayout.r0 : sectorShape.r0, + r: isHorizontalOrRadial ? coordLayout.r : sectorShape.r, + startAngle: isHorizontalOrRadial ? sectorShape.startAngle : 0, + endAngle: isHorizontalOrRadial ? sectorShape.endAngle : Math.PI * 2 + }; + } + } + + function createBackgroundEl(coord, isHorizontalOrRadial, layout) { + var ElementClz = coord.type === 'polar' ? Sector : Rect; + return new ElementClz({ + shape: createBackgroundShape(isHorizontalOrRadial, layout, coord), + silent: true, + z2: 0 + }); + } + + function install$3(registers) { + registers.registerChartView(BarView); + registers.registerSeriesModel(BarSeriesModel); + registers.registerLayout(registers.PRIORITY.VISUAL.LAYOUT, curry(layout, 'bar')); + registers.registerLayout(registers.PRIORITY.VISUAL.PROGRESSIVE_LAYOUT, largeLayout); + registers.registerVisual({ + seriesType: 'bar', + reset: function (seriesModel) { + seriesModel.getData().setVisual('legendSymbol', 'roundRect'); + } + }); + registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, dataSample('bar')); + registers.registerAction({ + type: 'changeAxisOrder', + event: 'changeAxisOrder', + update: 'update' + }, function (payload, ecModel) { + var componentType = payload.componentType || 'series'; + ecModel.eachComponent({ + mainType: componentType, + query: payload + }, function (componentModel) { + if (payload.sortInfo) { + componentModel.axis.setCategorySortInfo(payload.sortInfo); + } + }); + }); + } + + var PI2$8 = Math.PI * 2; + var RADIAN = Math.PI / 180; + + function getViewRect(seriesModel, api) { + return getLayoutRect(seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + } + + function pieLayout(seriesType, ecModel, api) { + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + var data = seriesModel.getData(); + var valueDim = data.mapDimension('value'); + var viewRect = getViewRect(seriesModel, api); + var center = seriesModel.get('center'); + var radius = seriesModel.get('radius'); + + if (!isArray(radius)) { + radius = [0, radius]; + } + + if (!isArray(center)) { + center = [center, center]; + } + + var width = parsePercent$1(viewRect.width, api.getWidth()); + var height = parsePercent$1(viewRect.height, api.getHeight()); + var size = Math.min(width, height); + var cx = parsePercent$1(center[0], width) + viewRect.x; + var cy = parsePercent$1(center[1], height) + viewRect.y; + var r0 = parsePercent$1(radius[0], size / 2); + var r = parsePercent$1(radius[1], size / 2); + var startAngle = -seriesModel.get('startAngle') * RADIAN; + var minAngle = seriesModel.get('minAngle') * RADIAN; + var validDataCount = 0; + data.each(valueDim, function (value) { + !isNaN(value) && validDataCount++; + }); + var sum = data.getSum(valueDim); + var unitRadian = Math.PI / (sum || validDataCount) * 2; + var clockwise = seriesModel.get('clockwise'); + var roseType = seriesModel.get('roseType'); + var stillShowZeroSum = seriesModel.get('stillShowZeroSum'); + var extent = data.getDataExtent(valueDim); + extent[0] = 0; + var restAngle = PI2$8; + var valueSumLargerThanMinAngle = 0; + var currentAngle = startAngle; + var dir = clockwise ? 1 : -1; + data.setLayout({ + viewRect: viewRect, + r: r + }); + data.each(valueDim, function (value, idx) { + var angle; + + if (isNaN(value)) { + data.setItemLayout(idx, { + angle: NaN, + startAngle: NaN, + endAngle: NaN, + clockwise: clockwise, + cx: cx, + cy: cy, + r0: r0, + r: roseType ? NaN : r + }); + return; + } + + if (roseType !== 'area') { + angle = sum === 0 && stillShowZeroSum ? unitRadian : value * unitRadian; + } else { + angle = PI2$8 / validDataCount; + } + + if (angle < minAngle) { + angle = minAngle; + restAngle -= minAngle; + } else { + valueSumLargerThanMinAngle += value; + } + + var endAngle = currentAngle + dir * angle; + data.setItemLayout(idx, { + angle: angle, + startAngle: currentAngle, + endAngle: endAngle, + clockwise: clockwise, + cx: cx, + cy: cy, + r0: r0, + r: roseType ? linearMap(value, extent, [r0, r]) : r + }); + currentAngle = endAngle; + }); + + if (restAngle < PI2$8 && validDataCount) { + if (restAngle <= 1e-3) { + var angle_1 = PI2$8 / validDataCount; + data.each(valueDim, function (value, idx) { + if (!isNaN(value)) { + var layout_1 = data.getItemLayout(idx); + layout_1.angle = angle_1; + layout_1.startAngle = startAngle + dir * idx * angle_1; + layout_1.endAngle = startAngle + dir * (idx + 1) * angle_1; + } + }); + } else { + unitRadian = restAngle / valueSumLargerThanMinAngle; + currentAngle = startAngle; + data.each(valueDim, function (value, idx) { + if (!isNaN(value)) { + var layout_2 = data.getItemLayout(idx); + var angle = layout_2.angle === minAngle ? minAngle : value * unitRadian; + layout_2.startAngle = currentAngle; + layout_2.endAngle = currentAngle + dir * angle; + currentAngle += dir * angle; + } + }); + } + } + }); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function dataFilter(seriesType) { + return { + seriesType: seriesType, + reset: function (seriesModel, ecModel) { + var legendModels = ecModel.findComponents({ + mainType: 'legend' + }); + + if (!legendModels || !legendModels.length) { + return; + } + + var data = seriesModel.getData(); + data.filterSelf(function (idx) { + var name = data.getName(idx); + + for (var i = 0; i < legendModels.length; i++) { + if (!legendModels[i].isSelected(name)) { + return false; + } + } + + return true; + }); + } + }; + } + + var RADIAN$1 = Math.PI / 180; + + function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight, viewLeft, viewTop, farthestX) { + if (list.length < 2) { + return; + } + + function recalculateXOnSemiToAlignOnEllipseCurve(semi) { + var rB = semi.rB; + var rB2 = rB * rB; + + for (var i = 0; i < semi.list.length; i++) { + var item = semi.list[i]; + var dy = Math.abs(item.label.y - cy); + var rA = r + item.len; + var rA2 = rA * rA; + var dx = Math.sqrt((1 - Math.abs(dy * dy / rB2)) * rA2); + item.label.x = cx + (dx + item.len2) * dir; + } + } + + function recalculateX(items) { + var topSemi = { + list: [], + maxY: 0 + }; + var bottomSemi = { + list: [], + maxY: 0 + }; + + for (var i = 0; i < items.length; i++) { + if (items[i].labelAlignTo !== 'none') { + continue; + } + + var item = items[i]; + var semi = item.label.y > cy ? bottomSemi : topSemi; + var dy = Math.abs(item.label.y - cy); + + if (dy > semi.maxY) { + var dx = item.label.x - cx - item.len2 * dir; + var rA = r + item.len; + var rB = dx < rA ? Math.sqrt(dy * dy / (1 - dx * dx / rA / rA)) : rA; + semi.rB = rB; + semi.maxY = dy; + } + + semi.list.push(item); + } + + recalculateXOnSemiToAlignOnEllipseCurve(topSemi); + recalculateXOnSemiToAlignOnEllipseCurve(bottomSemi); + } + + var len = list.length; + + for (var i = 0; i < len; i++) { + if (list[i].position === 'outer' && list[i].labelAlignTo === 'labelLine') { + var dx = list[i].label.x - farthestX; + list[i].linePoints[1][0] += dx; + list[i].label.x = farthestX; + } + } + + if (shiftLayoutOnY(list, viewTop, viewTop + viewHeight)) { + recalculateX(list); + } + } + + function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop) { + var leftList = []; + var rightList = []; + var leftmostX = Number.MAX_VALUE; + var rightmostX = -Number.MAX_VALUE; + + for (var i = 0; i < labelLayoutList.length; i++) { + var label = labelLayoutList[i].label; + + if (isPositionCenter(labelLayoutList[i])) { + continue; + } + + if (label.x < cx) { + leftmostX = Math.min(leftmostX, label.x); + leftList.push(labelLayoutList[i]); + } else { + rightmostX = Math.max(rightmostX, label.x); + rightList.push(labelLayoutList[i]); + } + } + + adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight, viewLeft, viewTop, rightmostX); + adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight, viewLeft, viewTop, leftmostX); + + for (var i = 0; i < labelLayoutList.length; i++) { + var layout = labelLayoutList[i]; + var label = layout.label; + + if (isPositionCenter(layout)) { + continue; + } + + var linePoints = layout.linePoints; + + if (linePoints) { + var isAlignToEdge = layout.labelAlignTo === 'edge'; + var realTextWidth = layout.rect.width; + var targetTextWidth = void 0; + + if (isAlignToEdge) { + if (label.x < cx) { + targetTextWidth = linePoints[2][0] - layout.labelDistance - viewLeft - layout.edgeDistance; + } else { + targetTextWidth = viewLeft + viewWidth - layout.edgeDistance - linePoints[2][0] - layout.labelDistance; + } + } else { + if (label.x < cx) { + targetTextWidth = label.x - viewLeft - layout.bleedMargin; + } else { + targetTextWidth = viewLeft + viewWidth - label.x - layout.bleedMargin; + } + } + + if (targetTextWidth < layout.rect.width) { + layout.label.style.width = targetTextWidth; + + if (layout.labelAlignTo === 'edge') { + realTextWidth = targetTextWidth; + } + } + + var dist = linePoints[1][0] - linePoints[2][0]; + + if (isAlignToEdge) { + if (label.x < cx) { + linePoints[2][0] = viewLeft + layout.edgeDistance + realTextWidth + layout.labelDistance; + } else { + linePoints[2][0] = viewLeft + viewWidth - layout.edgeDistance - realTextWidth - layout.labelDistance; + } + } else { + if (label.x < cx) { + linePoints[2][0] = label.x + layout.labelDistance; + } else { + linePoints[2][0] = label.x - layout.labelDistance; + } + + linePoints[1][0] = linePoints[2][0] + dist; + } + + linePoints[1][1] = linePoints[2][1] = label.y; + } + } + } + + function isPositionCenter(sectorShape) { + return sectorShape.position === 'center'; + } + + function pieLabelLayout(seriesModel) { + var data = seriesModel.getData(); + var labelLayoutList = []; + var cx; + var cy; + var hasLabelRotate = false; + var minShowLabelRadian = (seriesModel.get('minShowLabelAngle') || 0) * RADIAN$1; + var viewRect = data.getLayout('viewRect'); + var r = data.getLayout('r'); + var viewWidth = viewRect.width; + var viewLeft = viewRect.x; + var viewTop = viewRect.y; + var viewHeight = viewRect.height; + + function setNotShow(el) { + el.ignore = true; + } + + function isLabelShown(label) { + if (!label.ignore) { + return true; + } + + for (var key in label.states) { + if (label.states[key].ignore === false) { + return true; + } + } + + return false; + } + + data.each(function (idx) { + var sector = data.getItemGraphicEl(idx); + var sectorShape = sector.shape; + var label = sector.getTextContent(); + var labelLine = sector.getTextGuideLine(); + var itemModel = data.getItemModel(idx); + var labelModel = itemModel.getModel('label'); + var labelPosition = labelModel.get('position') || itemModel.get(['emphasis', 'label', 'position']); + var labelDistance = labelModel.get('distanceToLabelLine'); + var labelAlignTo = labelModel.get('alignTo'); + var edgeDistance = parsePercent$1(labelModel.get('edgeDistance'), viewWidth); + var bleedMargin = labelModel.get('bleedMargin'); + var labelLineModel = itemModel.getModel('labelLine'); + var labelLineLen = labelLineModel.get('length'); + labelLineLen = parsePercent$1(labelLineLen, viewWidth); + var labelLineLen2 = labelLineModel.get('length2'); + labelLineLen2 = parsePercent$1(labelLineLen2, viewWidth); + + if (Math.abs(sectorShape.endAngle - sectorShape.startAngle) < minShowLabelRadian) { + each(label.states, setNotShow); + label.ignore = true; + return; + } + + if (!isLabelShown(label)) { + return; + } + + var midAngle = (sectorShape.startAngle + sectorShape.endAngle) / 2; + var nx = Math.cos(midAngle); + var ny = Math.sin(midAngle); + var textX; + var textY; + var linePoints; + var textAlign; + cx = sectorShape.cx; + cy = sectorShape.cy; + var isLabelInside = labelPosition === 'inside' || labelPosition === 'inner'; + + if (labelPosition === 'center') { + textX = sectorShape.cx; + textY = sectorShape.cy; + textAlign = 'center'; + } else { + var x1 = (isLabelInside ? (sectorShape.r + sectorShape.r0) / 2 * nx : sectorShape.r * nx) + cx; + var y1 = (isLabelInside ? (sectorShape.r + sectorShape.r0) / 2 * ny : sectorShape.r * ny) + cy; + textX = x1 + nx * 3; + textY = y1 + ny * 3; + + if (!isLabelInside) { + var x2 = x1 + nx * (labelLineLen + r - sectorShape.r); + var y2 = y1 + ny * (labelLineLen + r - sectorShape.r); + var x3 = x2 + (nx < 0 ? -1 : 1) * labelLineLen2; + var y3 = y2; + + if (labelAlignTo === 'edge') { + textX = nx < 0 ? viewLeft + edgeDistance : viewLeft + viewWidth - edgeDistance; + } else { + textX = x3 + (nx < 0 ? -labelDistance : labelDistance); + } + + textY = y3; + linePoints = [[x1, y1], [x2, y2], [x3, y3]]; + } + + textAlign = isLabelInside ? 'center' : labelAlignTo === 'edge' ? nx > 0 ? 'right' : 'left' : nx > 0 ? 'left' : 'right'; + } + + var labelRotate; + var rotate = labelModel.get('rotate'); + + if (typeof rotate === 'number') { + labelRotate = rotate * (Math.PI / 180); + } else { + labelRotate = rotate ? nx < 0 ? -midAngle + Math.PI : -midAngle : 0; + } + + hasLabelRotate = !!labelRotate; + label.x = textX; + label.y = textY; + label.rotation = labelRotate; + label.setStyle({ + verticalAlign: 'middle' + }); + + if (!isLabelInside) { + var textRect = label.getBoundingRect().clone(); + textRect.applyTransform(label.getComputedTransform()); + var margin = (label.style.margin || 0) + 2.1; + textRect.y -= margin / 2; + textRect.height += margin; + labelLayoutList.push({ + label: label, + labelLine: labelLine, + position: labelPosition, + len: labelLineLen, + len2: labelLineLen2, + minTurnAngle: labelLineModel.get('minTurnAngle'), + maxSurfaceAngle: labelLineModel.get('maxSurfaceAngle'), + surfaceNormal: new Point(nx, ny), + linePoints: linePoints, + textAlign: textAlign, + labelDistance: labelDistance, + labelAlignTo: labelAlignTo, + edgeDistance: edgeDistance, + bleedMargin: bleedMargin, + rect: textRect + }); + } else { + label.setStyle({ + align: textAlign + }); + var selectState = label.states.select; + + if (selectState) { + selectState.x += label.x; + selectState.y += label.y; + } + } + + sector.setTextConfig({ + inside: isLabelInside + }); + }); + + if (!hasLabelRotate && seriesModel.get('avoidLabelOverlap')) { + avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop); + } + + for (var i = 0; i < labelLayoutList.length; i++) { + var layout = labelLayoutList[i]; + var label = layout.label; + var labelLine = layout.labelLine; + var notShowLabel = isNaN(label.x) || isNaN(label.y); + + if (label) { + label.setStyle({ + align: layout.textAlign + }); + + if (notShowLabel) { + each(label.states, setNotShow); + label.ignore = true; + } + + var selectState = label.states.select; + + if (selectState) { + selectState.x += label.x; + selectState.y += label.y; + } + } + + if (labelLine) { + var linePoints = layout.linePoints; + + if (notShowLabel || !linePoints) { + each(labelLine.states, setNotShow); + labelLine.ignore = true; + } else { + limitTurnAngle(linePoints, layout.minTurnAngle); + limitSurfaceAngle(linePoints, layout.surfaceNormal, layout.maxSurfaceAngle); + labelLine.setShape({ + points: linePoints + }); + label.__hostTarget.textGuideLineConfig = { + anchor: new Point(linePoints[0][0], linePoints[0][1]) + }; + } + } + } + } + + function getSectorCornerRadius(model, shape) { + var cornerRadius = model.get('borderRadius'); + + if (cornerRadius == null) { + return null; + } + + if (!isArray(cornerRadius)) { + cornerRadius = [cornerRadius, cornerRadius]; + } + + return { + innerCornerRadius: parsePercent(cornerRadius[0], shape.r0), + cornerRadius: parsePercent(cornerRadius[1], shape.r) + }; + } + + var PiePiece = function (_super) { + __extends(PiePiece, _super); + + function PiePiece(data, idx, startAngle) { + var _this = _super.call(this) || this; + + _this.z2 = 2; + var polyline = new Polyline(); + var text = new ZRText(); + + _this.setTextGuideLine(polyline); + + _this.setTextContent(text); + + _this.updateData(data, idx, startAngle, true); + + return _this; + } + + PiePiece.prototype.updateData = function (data, idx, startAngle, firstCreate) { + var sector = this; + var seriesModel = data.hostModel; + var itemModel = data.getItemModel(idx); + var emphasisModel = itemModel.getModel('emphasis'); + var layout = data.getItemLayout(idx); + var sectorShape = extend(getSectorCornerRadius(itemModel.getModel('itemStyle'), layout) || {}, layout); + + if (firstCreate) { + sector.setShape(sectorShape); + var animationType = seriesModel.getShallow('animationType'); + + if (animationType === 'scale') { + sector.shape.r = layout.r0; + initProps(sector, { + shape: { + r: layout.r + } + }, seriesModel, idx); + } else { + if (startAngle != null) { + sector.setShape({ + startAngle: startAngle, + endAngle: startAngle + }); + initProps(sector, { + shape: { + startAngle: layout.startAngle, + endAngle: layout.endAngle + } + }, seriesModel, idx); + } else { + sector.shape.endAngle = layout.startAngle; + updateProps(sector, { + shape: { + endAngle: layout.endAngle + } + }, seriesModel, idx); + } + } + } else { + updateProps(sector, { + shape: sectorShape + }, seriesModel, idx); + } + + sector.useStyle(data.getItemVisual(idx, 'style')); + setStatesStylesFromModel(sector, itemModel); + var midAngle = (layout.startAngle + layout.endAngle) / 2; + var offset = seriesModel.get('selectedOffset'); + var dx = Math.cos(midAngle) * offset; + var dy = Math.sin(midAngle) * offset; + var cursorStyle = itemModel.getShallow('cursor'); + cursorStyle && sector.attr('cursor', cursorStyle); + + this._updateLabel(seriesModel, data, idx); + + sector.ensureState('emphasis').shape = __assign({ + r: layout.r + (emphasisModel.get('scale') ? emphasisModel.get('scaleSize') || 0 : 0) + }, getSectorCornerRadius(emphasisModel.getModel('itemStyle'), layout)); + extend(sector.ensureState('select'), { + x: dx, + y: dy, + shape: getSectorCornerRadius(itemModel.getModel(['select', 'itemStyle']), layout) + }); + extend(sector.ensureState('blur'), { + shape: getSectorCornerRadius(itemModel.getModel(['blur', 'itemStyle']), layout) + }); + var labelLine = sector.getTextGuideLine(); + var labelText = sector.getTextContent(); + extend(labelLine.ensureState('select'), { + x: dx, + y: dy + }); + extend(labelText.ensureState('select'), { + x: dx, + y: dy + }); + enableHoverEmphasis(this, emphasisModel.get('focus'), emphasisModel.get('blurScope')); + }; + + PiePiece.prototype._updateLabel = function (seriesModel, data, idx) { + var sector = this; + var itemModel = data.getItemModel(idx); + var labelLineModel = itemModel.getModel('labelLine'); + var style = data.getItemVisual(idx, 'style'); + var visualColor = style && style.fill; + var visualOpacity = style && style.opacity; + setLabelStyle(sector, getLabelStatesModels(itemModel), { + labelFetcher: data.hostModel, + labelDataIndex: idx, + inheritColor: visualColor, + defaultOpacity: visualOpacity, + defaultText: seriesModel.getFormattedLabel(idx, 'normal') || data.getName(idx) + }); + var labelText = sector.getTextContent(); + sector.setTextConfig({ + position: null, + rotation: null + }); + labelText.attr({ + z2: 10 + }); + setLabelLineStyle(this, getLabelLineStatesModels(itemModel), { + stroke: visualColor, + opacity: retrieve3(labelLineModel.get(['lineStyle', 'opacity']), visualOpacity, 1) + }); + }; + + return PiePiece; + }(Sector); + + var PieView = function (_super) { + __extends(PieView, _super); + + function PieView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.ignoreLabelLineUpdate = true; + return _this; + } + + PieView.prototype.init = function () { + var sectorGroup = new Group(); + this._sectorGroup = sectorGroup; + }; + + PieView.prototype.render = function (seriesModel, ecModel, api, payload) { + var data = seriesModel.getData(); + var oldData = this._data; + var group = this.group; + var startAngle; + + if (!oldData && data.count() > 0) { + var shape = data.getItemLayout(0); + + for (var s = 1; isNaN(shape && shape.startAngle) && s < data.count(); ++s) { + shape = data.getItemLayout(s); + } + + if (shape) { + startAngle = shape.startAngle; + } + } + + data.diff(oldData).add(function (idx) { + var piePiece = new PiePiece(data, idx, startAngle); + data.setItemGraphicEl(idx, piePiece); + group.add(piePiece); + }).update(function (newIdx, oldIdx) { + var piePiece = oldData.getItemGraphicEl(oldIdx); + piePiece.updateData(data, newIdx, startAngle); + piePiece.off('click'); + group.add(piePiece); + data.setItemGraphicEl(newIdx, piePiece); + }).remove(function (idx) { + var piePiece = oldData.getItemGraphicEl(idx); + removeElementWithFadeOut(piePiece, seriesModel, idx); + }).execute(); + pieLabelLayout(seriesModel); + + if (seriesModel.get('animationTypeUpdate') !== 'expansion') { + this._data = data; + } + }; + + PieView.prototype.dispose = function () {}; + + PieView.prototype.containPoint = function (point, seriesModel) { + var data = seriesModel.getData(); + var itemLayout = data.getItemLayout(0); + + if (itemLayout) { + var dx = point[0] - itemLayout.cx; + var dy = point[1] - itemLayout.cy; + var radius = Math.sqrt(dx * dx + dy * dy); + return radius <= itemLayout.r && radius >= itemLayout.r0; + } + }; + + PieView.type = 'pie'; + return PieView; + }(ChartView); + + function createListSimply(seriesModel, opt, nameList) { + opt = isArray(opt) && { + coordDimensions: opt + } || extend({}, opt); + var source = seriesModel.getSource(); + var dimensionsInfo = createDimensions(source, opt); + var list = new List(dimensionsInfo, seriesModel); + list.initData(source, nameList); + return list; + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var LegendVisualProvider = function () { + function LegendVisualProvider(getDataWithEncodedVisual, getRawData) { + this._getDataWithEncodedVisual = getDataWithEncodedVisual; + this._getRawData = getRawData; + } + + LegendVisualProvider.prototype.getAllNames = function () { + var rawData = this._getRawData(); + + return rawData.mapArray(rawData.getName); + }; + + LegendVisualProvider.prototype.containName = function (name) { + var rawData = this._getRawData(); + + return rawData.indexOfName(name) >= 0; + }; + + LegendVisualProvider.prototype.indexOfName = function (name) { + var dataWithEncodedVisual = this._getDataWithEncodedVisual(); + + return dataWithEncodedVisual.indexOfName(name); + }; + + LegendVisualProvider.prototype.getItemVisual = function (dataIndex, key) { + var dataWithEncodedVisual = this._getDataWithEncodedVisual(); + + return dataWithEncodedVisual.getItemVisual(dataIndex, key); + }; + + return LegendVisualProvider; + }(); + + var PieSeriesModel = function (_super) { + __extends(PieSeriesModel, _super); + + function PieSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.useColorPaletteOnData = true; + return _this; + } + + PieSeriesModel.prototype.init = function (option) { + _super.prototype.init.apply(this, arguments); + + this.legendVisualProvider = new LegendVisualProvider(bind(this.getData, this), bind(this.getRawData, this)); + + this._defaultLabelLine(option); + }; + + PieSeriesModel.prototype.mergeOption = function () { + _super.prototype.mergeOption.apply(this, arguments); + }; + + PieSeriesModel.prototype.getInitialData = function () { + return createListSimply(this, { + coordDimensions: ['value'], + encodeDefaulter: curry(makeSeriesEncodeForNameBased, this) + }); + }; + + PieSeriesModel.prototype.getDataParams = function (dataIndex) { + var data = this.getData(); + + var params = _super.prototype.getDataParams.call(this, dataIndex); + + var valueList = []; + data.each(data.mapDimension('value'), function (value) { + valueList.push(value); + }); + params.percent = getPercentWithPrecision(valueList, dataIndex, data.hostModel.get('percentPrecision')); + params.$vars.push('percent'); + return params; + }; + + PieSeriesModel.prototype._defaultLabelLine = function (option) { + defaultEmphasis(option, 'labelLine', ['show']); + var labelLineNormalOpt = option.labelLine; + var labelLineEmphasisOpt = option.emphasis.labelLine; + labelLineNormalOpt.show = labelLineNormalOpt.show && option.label.show; + labelLineEmphasisOpt.show = labelLineEmphasisOpt.show && option.emphasis.label.show; + }; + + PieSeriesModel.type = 'series.pie'; + PieSeriesModel.defaultOption = { + zlevel: 0, + z: 2, + legendHoverLink: true, + center: ['50%', '50%'], + radius: [0, '75%'], + clockwise: true, + startAngle: 90, + minAngle: 0, + minShowLabelAngle: 0, + selectedOffset: 10, + percentPrecision: 2, + stillShowZeroSum: true, + left: 0, + top: 0, + right: 0, + bottom: 0, + width: null, + height: null, + label: { + rotate: 0, + show: true, + overflow: 'truncate', + position: 'outer', + alignTo: 'none', + edgeDistance: '25%', + bleedMargin: 10, + distanceToLabelLine: 5 + }, + labelLine: { + show: true, + length: 15, + length2: 15, + smooth: false, + minTurnAngle: 90, + maxSurfaceAngle: 90, + lineStyle: { + width: 1, + type: 'solid' + } + }, + itemStyle: { + borderWidth: 1 + }, + labelLayout: { + hideOverlap: true + }, + emphasis: { + scale: true, + scaleSize: 5 + }, + avoidLabelOverlap: true, + animationType: 'expansion', + animationDuration: 1000, + animationTypeUpdate: 'transition', + animationEasingUpdate: 'cubicInOut', + animationDurationUpdate: 500, + animationEasing: 'cubicInOut' + }; + return PieSeriesModel; + }(SeriesModel); + + function install$4(registers) { + registers.registerChartView(PieView); + registers.registerSeriesModel(PieSeriesModel); + createLegacyDataSelectAction('pie', registers.registerAction); + registers.registerLayout(curry(pieLayout, 'pie')); + registers.registerProcessor(dataFilter('pie')); + } + + var ScatterSeriesModel = function (_super) { + __extends(ScatterSeriesModel, _super); + + function ScatterSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ScatterSeriesModel.type; + _this.hasSymbolVisual = true; + return _this; + } + + ScatterSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createListFromArray(this.getSource(), this, { + useEncodeDefaulter: true + }); + }; + + ScatterSeriesModel.prototype.getProgressive = function () { + var progressive = this.option.progressive; + + if (progressive == null) { + return this.option.large ? 5e3 : this.get('progressive'); + } + + return progressive; + }; + + ScatterSeriesModel.prototype.getProgressiveThreshold = function () { + var progressiveThreshold = this.option.progressiveThreshold; + + if (progressiveThreshold == null) { + return this.option.large ? 1e4 : this.get('progressiveThreshold'); + } + + return progressiveThreshold; + }; + + ScatterSeriesModel.prototype.brushSelector = function (dataIndex, data, selectors) { + return selectors.point(data.getItemLayout(dataIndex)); + }; + + ScatterSeriesModel.type = 'series.scatter'; + ScatterSeriesModel.dependencies = ['grid', 'polar', 'geo', 'singleAxis', 'calendar']; + ScatterSeriesModel.defaultOption = { + coordinateSystem: 'cartesian2d', + zlevel: 0, + z: 2, + legendHoverLink: true, + symbolSize: 10, + large: false, + largeThreshold: 2000, + itemStyle: { + opacity: 0.8 + }, + emphasis: { + scale: true + }, + clip: true, + select: { + itemStyle: { + borderColor: '#212121' + } + } + }; + return ScatterSeriesModel; + }(SeriesModel); + + var BOOST_SIZE_THRESHOLD = 4; + + var LargeSymbolPathShape = function () { + function LargeSymbolPathShape() {} + + return LargeSymbolPathShape; + }(); + + var LargeSymbolPath = function (_super) { + __extends(LargeSymbolPath, _super); + + function LargeSymbolPath(opts) { + return _super.call(this, opts) || this; + } + + LargeSymbolPath.prototype.getDefaultShape = function () { + return new LargeSymbolPathShape(); + }; + + LargeSymbolPath.prototype.buildPath = function (path, shape) { + var points = shape.points; + var size = shape.size; + var symbolProxy = this.symbolProxy; + var symbolProxyShape = symbolProxy.shape; + var ctx = path.getContext ? path.getContext() : path; + var canBoost = ctx && size[0] < BOOST_SIZE_THRESHOLD; + + if (canBoost) { + this._ctx = ctx; + return; + } + + this._ctx = null; + + for (var i = 0; i < points.length;) { + var x = points[i++]; + var y = points[i++]; + + if (isNaN(x) || isNaN(y)) { + continue; + } + + if (this.softClipShape && !this.softClipShape.contain(x, y)) { + continue; + } + + symbolProxyShape.x = x - size[0] / 2; + symbolProxyShape.y = y - size[1] / 2; + symbolProxyShape.width = size[0]; + symbolProxyShape.height = size[1]; + symbolProxy.buildPath(path, symbolProxyShape, true); + } + }; + + LargeSymbolPath.prototype.afterBrush = function () { + var shape = this.shape; + var points = shape.points; + var size = shape.size; + var ctx = this._ctx; + + if (!ctx) { + return; + } + + for (var i = 0; i < points.length;) { + var x = points[i++]; + var y = points[i++]; + + if (isNaN(x) || isNaN(y)) { + continue; + } + + if (this.softClipShape && !this.softClipShape.contain(x, y)) { + continue; + } + + ctx.fillRect(x - size[0] / 2, y - size[1] / 2, size[0], size[1]); + } + }; + + LargeSymbolPath.prototype.findDataIndex = function (x, y) { + var shape = this.shape; + var points = shape.points; + var size = shape.size; + var w = Math.max(size[0], 4); + var h = Math.max(size[1], 4); + + for (var idx = points.length / 2 - 1; idx >= 0; idx--) { + var i = idx * 2; + var x0 = points[i] - w / 2; + var y0 = points[i + 1] - h / 2; + + if (x >= x0 && y >= y0 && x <= x0 + w && y <= y0 + h) { + return idx; + } + } + + return -1; + }; + + return LargeSymbolPath; + }(Path); + + var LargeSymbolDraw = function () { + function LargeSymbolDraw() { + this.group = new Group(); + } + + LargeSymbolDraw.prototype.isPersistent = function () { + return !this._incremental; + }; + + LargeSymbolDraw.prototype.updateData = function (data, opt) { + this.group.removeAll(); + var symbolEl = new LargeSymbolPath({ + rectHover: true, + cursor: 'default' + }); + symbolEl.setShape({ + points: data.getLayout('points') + }); + + this._setCommon(symbolEl, data, false, opt); + + this.group.add(symbolEl); + this._incremental = null; + }; + + LargeSymbolDraw.prototype.updateLayout = function (data) { + if (this._incremental) { + return; + } + + var points = data.getLayout('points'); + this.group.eachChild(function (child) { + if (child.startIndex != null) { + var len = (child.endIndex - child.startIndex) * 2; + var byteOffset = child.startIndex * 4 * 2; + points = new Float32Array(points.buffer, byteOffset, len); + } + + child.setShape('points', points); + }); + }; + + LargeSymbolDraw.prototype.incrementalPrepareUpdate = function (data) { + this.group.removeAll(); + + this._clearIncremental(); + + if (data.count() > 2e6) { + if (!this._incremental) { + this._incremental = new IncrementalDisplayable({ + silent: true + }); + } + + this.group.add(this._incremental); + } else { + this._incremental = null; + } + }; + + LargeSymbolDraw.prototype.incrementalUpdate = function (taskParams, data, opt) { + var symbolEl; + + if (this._incremental) { + symbolEl = new LargeSymbolPath(); + + this._incremental.addDisplayable(symbolEl, true); + } else { + symbolEl = new LargeSymbolPath({ + rectHover: true, + cursor: 'default', + startIndex: taskParams.start, + endIndex: taskParams.end + }); + symbolEl.incremental = true; + this.group.add(symbolEl); + } + + symbolEl.setShape({ + points: data.getLayout('points') + }); + + this._setCommon(symbolEl, data, !!this._incremental, opt); + }; + + LargeSymbolDraw.prototype._setCommon = function (symbolEl, data, isIncremental, opt) { + var hostModel = data.hostModel; + opt = opt || {}; + var size = data.getVisual('symbolSize'); + symbolEl.setShape('size', size instanceof Array ? size : [size, size]); + symbolEl.softClipShape = opt.clipShape || null; + symbolEl.symbolProxy = createSymbol(data.getVisual('symbol'), 0, 0, 0, 0); + symbolEl.setColor = symbolEl.symbolProxy.setColor; + var extrudeShadow = symbolEl.shape.size[0] < BOOST_SIZE_THRESHOLD; + symbolEl.useStyle(hostModel.getModel('itemStyle').getItemStyle(extrudeShadow ? ['color', 'shadowBlur', 'shadowColor'] : ['color'])); + var globalStyle = data.getVisual('style'); + var visualColor = globalStyle && globalStyle.fill; + + if (visualColor) { + symbolEl.setColor(visualColor); + } + + if (!isIncremental) { + var ecData_1 = getECData(symbolEl); + ecData_1.seriesIndex = hostModel.seriesIndex; + symbolEl.on('mousemove', function (e) { + ecData_1.dataIndex = null; + var dataIndex = symbolEl.findDataIndex(e.offsetX, e.offsetY); + + if (dataIndex >= 0) { + ecData_1.dataIndex = dataIndex + (symbolEl.startIndex || 0); + } + }); + } + }; + + LargeSymbolDraw.prototype.remove = function () { + this._clearIncremental(); + + this._incremental = null; + this.group.removeAll(); + }; + + LargeSymbolDraw.prototype._clearIncremental = function () { + var incremental = this._incremental; + + if (incremental) { + incremental.clearDisplaybles(); + } + }; + + return LargeSymbolDraw; + }(); + + var ScatterView = function (_super) { + __extends(ScatterView, _super); + + function ScatterView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ScatterView.type; + return _this; + } + + ScatterView.prototype.render = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + + var symbolDraw = this._updateSymbolDraw(data, seriesModel); + + symbolDraw.updateData(data, { + clipShape: this._getClipShape(seriesModel) + }); + this._finished = true; + }; + + ScatterView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + + var symbolDraw = this._updateSymbolDraw(data, seriesModel); + + symbolDraw.incrementalPrepareUpdate(data); + this._finished = false; + }; + + ScatterView.prototype.incrementalRender = function (taskParams, seriesModel, ecModel) { + this._symbolDraw.incrementalUpdate(taskParams, seriesModel.getData(), { + clipShape: this._getClipShape(seriesModel) + }); + + this._finished = taskParams.end === seriesModel.getData().count(); + }; + + ScatterView.prototype.updateTransform = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + this.group.dirty(); + + if (!this._finished || data.count() > 1e4 || !this._symbolDraw.isPersistent()) { + return { + update: true + }; + } else { + var res = pointsLayout('').reset(seriesModel, ecModel, api); + + if (res.progress) { + res.progress({ + start: 0, + end: data.count(), + count: data.count() + }, data); + } + + this._symbolDraw.updateLayout(data); + } + }; + + ScatterView.prototype._getClipShape = function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var clipArea = coordSys && coordSys.getArea && coordSys.getArea(); + return seriesModel.get('clip', true) ? clipArea : null; + }; + + ScatterView.prototype._updateSymbolDraw = function (data, seriesModel) { + var symbolDraw = this._symbolDraw; + var pipelineContext = seriesModel.pipelineContext; + var isLargeDraw = pipelineContext.large; + + if (!symbolDraw || isLargeDraw !== this._isLargeDraw) { + symbolDraw && symbolDraw.remove(); + symbolDraw = this._symbolDraw = isLargeDraw ? new LargeSymbolDraw() : new SymbolDraw(); + this._isLargeDraw = isLargeDraw; + this.group.removeAll(); + } + + this.group.add(symbolDraw.group); + return symbolDraw; + }; + + ScatterView.prototype.remove = function (ecModel, api) { + this._symbolDraw && this._symbolDraw.remove(true); + this._symbolDraw = null; + }; + + ScatterView.prototype.dispose = function () {}; + + ScatterView.type = 'scatter'; + return ScatterView; + }(ChartView); + + var GridModel = function (_super) { + __extends(GridModel, _super); + + function GridModel() { + return _super !== null && _super.apply(this, arguments) || this; + } + + GridModel.type = 'grid'; + GridModel.dependencies = ['xAxis', 'yAxis']; + GridModel.layoutMode = 'box'; + GridModel.defaultOption = { + show: false, + zlevel: 0, + z: 0, + left: '10%', + top: 60, + right: '10%', + bottom: 70, + containLabel: false, + backgroundColor: 'rgba(0,0,0,0)', + borderWidth: 1, + borderColor: '#ccc' + }; + return GridModel; + }(ComponentModel); + + var CartesianAxisModel = function (_super) { + __extends(CartesianAxisModel, _super); + + function CartesianAxisModel() { + return _super !== null && _super.apply(this, arguments) || this; + } + + CartesianAxisModel.prototype.getCoordSysModel = function () { + return this.getReferringComponents('grid', SINGLE_REFERRING).models[0]; + }; + + CartesianAxisModel.type = 'cartesian2dAxis'; + return CartesianAxisModel; + }(ComponentModel); + mixin(CartesianAxisModel, AxisModelCommonMixin); + + var defaultOption = { + show: true, + zlevel: 0, + z: 0, + inverse: false, + name: '', + nameLocation: 'end', + nameRotate: null, + nameTruncate: { + maxWidth: null, + ellipsis: '...', + placeholder: '.' + }, + nameTextStyle: {}, + nameGap: 15, + silent: false, + triggerEvent: false, + tooltip: { + show: false + }, + axisPointer: {}, + axisLine: { + show: true, + onZero: true, + onZeroAxisIndex: null, + lineStyle: { + color: '#6E7079', + width: 1, + type: 'solid' + }, + symbol: ['none', 'none'], + symbolSize: [10, 15] + }, + axisTick: { + show: true, + inside: false, + length: 5, + lineStyle: { + width: 1 + } + }, + axisLabel: { + show: true, + inside: false, + rotate: 0, + showMinLabel: null, + showMaxLabel: null, + margin: 8, + fontSize: 12 + }, + splitLine: { + show: true, + lineStyle: { + color: ['#E0E6F1'], + width: 1, + type: 'solid' + } + }, + splitArea: { + show: false, + areaStyle: { + color: ['rgba(250,250,250,0.2)', 'rgba(210,219,238,0.2)'] + } + } + }; + var categoryAxis = merge({ + boundaryGap: true, + deduplication: null, + splitLine: { + show: false + }, + axisTick: { + alignWithLabel: false, + interval: 'auto' + }, + axisLabel: { + interval: 'auto' + } + }, defaultOption); + var valueAxis = merge({ + boundaryGap: [0, 0], + axisLine: { + show: 'auto' + }, + axisTick: { + show: 'auto' + }, + splitNumber: 5, + minorTick: { + show: false, + splitNumber: 5, + length: 3, + lineStyle: {} + }, + minorSplitLine: { + show: false, + lineStyle: { + color: '#F4F7FD', + width: 1 + } + } + }, defaultOption); + var timeAxis = merge({ + scale: true, + splitNumber: 6, + axisLabel: { + showMinLabel: false, + showMaxLabel: false, + rich: { + primary: { + fontWeight: 'bold' + } + } + }, + splitLine: { + show: false + } + }, valueAxis); + var logAxis = defaults({ + scale: true, + logBase: 10 + }, valueAxis); + var axisDefault = { + category: categoryAxis, + value: valueAxis, + time: timeAxis, + log: logAxis + }; + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var AXIS_TYPES = { + value: 1, + category: 1, + time: 1, + log: 1 + }; + + function axisModelCreator(registers, axisName, BaseAxisModelClass, extraDefaultOption) { + each(AXIS_TYPES, function (v, axisType) { + var defaultOption = merge(merge({}, axisDefault[axisType], true), extraDefaultOption, true); + + var AxisModel = function (_super) { + __extends(AxisModel, _super); + + function AxisModel() { + var args = []; + + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + + var _this = _super.apply(this, args) || this; + + _this.type = axisName + 'Axis.' + axisType; + return _this; + } + + AxisModel.prototype.mergeDefaultAndTheme = function (option, ecModel) { + var layoutMode = fetchLayoutMode(this); + var inputPositionParams = layoutMode ? getLayoutParams(option) : {}; + var themeModel = ecModel.getTheme(); + merge(option, themeModel.get(axisType + 'Axis')); + merge(option, this.getDefaultOption()); + option.type = getAxisType(option); + + if (layoutMode) { + mergeLayoutParam(option, inputPositionParams, layoutMode); + } + }; + + AxisModel.prototype.optionUpdated = function () { + var thisOption = this.option; + + if (thisOption.type === 'category') { + this.__ordinalMeta = OrdinalMeta.createByAxisModel(this); + } + }; + + AxisModel.prototype.getCategories = function (rawData) { + var option = this.option; + + if (option.type === 'category') { + if (rawData) { + return option.data; + } + + return this.__ordinalMeta.categories; + } + }; + + AxisModel.prototype.getOrdinalMeta = function () { + return this.__ordinalMeta; + }; + + AxisModel.type = axisName + 'Axis.' + axisType; + AxisModel.defaultOption = defaultOption; + return AxisModel; + }(BaseAxisModelClass); + + registers.registerComponentModel(AxisModel); + }); + registers.registerSubTypeDefaulter(axisName + 'Axis', getAxisType); + } + + function getAxisType(option) { + return option.type || (option.data ? 'category' : 'value'); + } + + var Cartesian = function () { + function Cartesian(name) { + this.type = 'cartesian'; + this._dimList = []; + this._axes = {}; + this.name = name || ''; + } + + Cartesian.prototype.getAxis = function (dim) { + return this._axes[dim]; + }; + + Cartesian.prototype.getAxes = function () { + return map(this._dimList, function (dim) { + return this._axes[dim]; + }, this); + }; + + Cartesian.prototype.getAxesByScale = function (scaleType) { + scaleType = scaleType.toLowerCase(); + return filter(this.getAxes(), function (axis) { + return axis.scale.type === scaleType; + }); + }; + + Cartesian.prototype.addAxis = function (axis) { + var dim = axis.dim; + this._axes[dim] = axis; + + this._dimList.push(dim); + }; + + return Cartesian; + }(); + + var cartesian2DDimensions = ['x', 'y']; + + function canCalculateAffineTransform(scale) { + return scale.type === 'interval' || scale.type === 'time'; + } + + var Cartesian2D = function (_super) { + __extends(Cartesian2D, _super); + + function Cartesian2D() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = 'cartesian2d'; + _this.dimensions = cartesian2DDimensions; + return _this; + } + + Cartesian2D.prototype.calcAffineTransform = function () { + this._transform = this._invTransform = null; + var xAxisScale = this.getAxis('x').scale; + var yAxisScale = this.getAxis('y').scale; + + if (!canCalculateAffineTransform(xAxisScale) || !canCalculateAffineTransform(yAxisScale)) { + return; + } + + var xScaleExtent = xAxisScale.getExtent(); + var yScaleExtent = yAxisScale.getExtent(); + var start = this.dataToPoint([xScaleExtent[0], yScaleExtent[0]]); + var end = this.dataToPoint([xScaleExtent[1], yScaleExtent[1]]); + var xScaleSpan = xScaleExtent[1] - xScaleExtent[0]; + var yScaleSpan = yScaleExtent[1] - yScaleExtent[0]; + + if (!xScaleSpan || !yScaleSpan) { + return; + } + + var scaleX = (end[0] - start[0]) / xScaleSpan; + var scaleY = (end[1] - start[1]) / yScaleSpan; + var translateX = start[0] - xScaleExtent[0] * scaleX; + var translateY = start[1] - yScaleExtent[0] * scaleY; + var m = this._transform = [scaleX, 0, 0, scaleY, translateX, translateY]; + this._invTransform = invert([], m); + }; + + Cartesian2D.prototype.getBaseAxis = function () { + return this.getAxesByScale('ordinal')[0] || this.getAxesByScale('time')[0] || this.getAxis('x'); + }; + + Cartesian2D.prototype.containPoint = function (point) { + var axisX = this.getAxis('x'); + var axisY = this.getAxis('y'); + return axisX.contain(axisX.toLocalCoord(point[0])) && axisY.contain(axisY.toLocalCoord(point[1])); + }; + + Cartesian2D.prototype.containData = function (data) { + return this.getAxis('x').containData(data[0]) && this.getAxis('y').containData(data[1]); + }; + + Cartesian2D.prototype.dataToPoint = function (data, reserved, out) { + out = out || []; + var xVal = data[0]; + var yVal = data[1]; + + if (this._transform && xVal != null && isFinite(xVal) && yVal != null && isFinite(yVal)) { + return applyTransform(out, data, this._transform); + } + + var xAxis = this.getAxis('x'); + var yAxis = this.getAxis('y'); + out[0] = xAxis.toGlobalCoord(xAxis.dataToCoord(xVal)); + out[1] = yAxis.toGlobalCoord(yAxis.dataToCoord(yVal)); + return out; + }; + + Cartesian2D.prototype.clampData = function (data, out) { + var xScale = this.getAxis('x').scale; + var yScale = this.getAxis('y').scale; + var xAxisExtent = xScale.getExtent(); + var yAxisExtent = yScale.getExtent(); + var x = xScale.parse(data[0]); + var y = yScale.parse(data[1]); + out = out || []; + out[0] = Math.min(Math.max(Math.min(xAxisExtent[0], xAxisExtent[1]), x), Math.max(xAxisExtent[0], xAxisExtent[1])); + out[1] = Math.min(Math.max(Math.min(yAxisExtent[0], yAxisExtent[1]), y), Math.max(yAxisExtent[0], yAxisExtent[1])); + return out; + }; + + Cartesian2D.prototype.pointToData = function (point, out) { + out = out || []; + + if (this._invTransform) { + return applyTransform(out, point, this._invTransform); + } + + var xAxis = this.getAxis('x'); + var yAxis = this.getAxis('y'); + out[0] = xAxis.coordToData(xAxis.toLocalCoord(point[0])); + out[1] = yAxis.coordToData(yAxis.toLocalCoord(point[1])); + return out; + }; + + Cartesian2D.prototype.getOtherAxis = function (axis) { + return this.getAxis(axis.dim === 'x' ? 'y' : 'x'); + }; + + Cartesian2D.prototype.getArea = function () { + var xExtent = this.getAxis('x').getGlobalExtent(); + var yExtent = this.getAxis('y').getGlobalExtent(); + var x = Math.min(xExtent[0], xExtent[1]); + var y = Math.min(yExtent[0], yExtent[1]); + var width = Math.max(xExtent[0], xExtent[1]) - x; + var height = Math.max(yExtent[0], yExtent[1]) - y; + return new BoundingRect(x, y, width, height); + }; + + return Cartesian2D; + }(Cartesian); + + var Axis2D = function (_super) { + __extends(Axis2D, _super); + + function Axis2D(dim, scale, coordExtent, axisType, position) { + var _this = _super.call(this, dim, scale, coordExtent) || this; + + _this.index = 0; + _this.type = axisType || 'value'; + _this.position = position || 'bottom'; + return _this; + } + + Axis2D.prototype.isHorizontal = function () { + var position = this.position; + return position === 'top' || position === 'bottom'; + }; + + Axis2D.prototype.getGlobalExtent = function (asc) { + var ret = this.getExtent(); + ret[0] = this.toGlobalCoord(ret[0]); + ret[1] = this.toGlobalCoord(ret[1]); + asc && ret[0] > ret[1] && ret.reverse(); + return ret; + }; + + Axis2D.prototype.pointToData = function (point, clamp) { + return this.coordToData(this.toLocalCoord(point[this.dim === 'x' ? 0 : 1]), clamp); + }; + + Axis2D.prototype.setCategorySortInfo = function (info) { + if (this.type !== 'category') { + return false; + } + + this.model.option.categorySortInfo = info; + this.scale.setSortInfo(info); + }; + + return Axis2D; + }(Axis); + + function layout$1(gridModel, axisModel, opt) { + opt = opt || {}; + var grid = gridModel.coordinateSystem; + var axis = axisModel.axis; + var layout = {}; + var otherAxisOnZeroOf = axis.getAxesOnZeroOf()[0]; + var rawAxisPosition = axis.position; + var axisPosition = otherAxisOnZeroOf ? 'onZero' : rawAxisPosition; + var axisDim = axis.dim; + var rect = grid.getRect(); + var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height]; + var idx = { + left: 0, + right: 1, + top: 0, + bottom: 1, + onZero: 2 + }; + var axisOffset = axisModel.get('offset') || 0; + var posBound = axisDim === 'x' ? [rectBound[2] - axisOffset, rectBound[3] + axisOffset] : [rectBound[0] - axisOffset, rectBound[1] + axisOffset]; + + if (otherAxisOnZeroOf) { + var onZeroCoord = otherAxisOnZeroOf.toGlobalCoord(otherAxisOnZeroOf.dataToCoord(0)); + posBound[idx.onZero] = Math.max(Math.min(onZeroCoord, posBound[1]), posBound[0]); + } + + layout.position = [axisDim === 'y' ? posBound[idx[axisPosition]] : rectBound[0], axisDim === 'x' ? posBound[idx[axisPosition]] : rectBound[3]]; + layout.rotation = Math.PI / 2 * (axisDim === 'x' ? 0 : 1); + var dirMap = { + top: -1, + bottom: 1, + left: -1, + right: 1 + }; + layout.labelDirection = layout.tickDirection = layout.nameDirection = dirMap[rawAxisPosition]; + layout.labelOffset = otherAxisOnZeroOf ? posBound[idx[rawAxisPosition]] - posBound[idx.onZero] : 0; + + if (axisModel.get(['axisTick', 'inside'])) { + layout.tickDirection = -layout.tickDirection; + } + + if (retrieve(opt.labelInside, axisModel.get(['axisLabel', 'inside']))) { + layout.labelDirection = -layout.labelDirection; + } + + var labelRotate = axisModel.get(['axisLabel', 'rotate']); + layout.labelRotate = axisPosition === 'top' ? -labelRotate : labelRotate; + layout.z2 = 1; + return layout; + } + function isCartesian2DSeries(seriesModel) { + return seriesModel.get('coordinateSystem') === 'cartesian2d'; + } + function findAxisModels(seriesModel) { + var axisModelMap = { + xAxisModel: null, + yAxisModel: null + }; + each(axisModelMap, function (v, key) { + var axisType = key.replace(/Model$/, ''); + var axisModel = seriesModel.getReferringComponents(axisType, SINGLE_REFERRING).models[0]; + + if ("development" !== 'production') { + if (!axisModel) { + throw new Error(axisType + ' "' + retrieve3(seriesModel.get(axisType + 'Index'), seriesModel.get(axisType + 'Id'), 0) + '" not found'); + } + } + + axisModelMap[key] = axisModel; + }); + return axisModelMap; + } + + var Grid = function () { + function Grid(gridModel, ecModel, api) { + this.type = 'grid'; + this._coordsMap = {}; + this._coordsList = []; + this._axesMap = {}; + this._axesList = []; + this.axisPointerEnabled = true; + this.dimensions = cartesian2DDimensions; + + this._initCartesian(gridModel, ecModel, api); + + this.model = gridModel; + } + + Grid.prototype.getRect = function () { + return this._rect; + }; + + Grid.prototype.update = function (ecModel, api) { + var axesMap = this._axesMap; + + this._updateScale(ecModel, this.model); + + each(axesMap.x, function (xAxis) { + niceScaleExtent(xAxis.scale, xAxis.model); + }); + each(axesMap.y, function (yAxis) { + niceScaleExtent(yAxis.scale, yAxis.model); + }); + var onZeroRecords = {}; + each(axesMap.x, function (xAxis) { + fixAxisOnZero(axesMap, 'y', xAxis, onZeroRecords); + }); + each(axesMap.y, function (yAxis) { + fixAxisOnZero(axesMap, 'x', yAxis, onZeroRecords); + }); + this.resize(this.model, api); + }; + + Grid.prototype.resize = function (gridModel, api, ignoreContainLabel) { + var boxLayoutParams = gridModel.getBoxLayoutParams(); + var isContainLabel = !ignoreContainLabel && gridModel.get('containLabel'); + var gridRect = getLayoutRect(boxLayoutParams, { + width: api.getWidth(), + height: api.getHeight() + }); + this._rect = gridRect; + var axesList = this._axesList; + adjustAxes(); + + if (isContainLabel) { + each(axesList, function (axis) { + if (!axis.model.get(['axisLabel', 'inside'])) { + var labelUnionRect = estimateLabelUnionRect(axis); + + if (labelUnionRect) { + var dim = axis.isHorizontal() ? 'height' : 'width'; + var margin = axis.model.get(['axisLabel', 'margin']); + gridRect[dim] -= labelUnionRect[dim] + margin; + + if (axis.position === 'top') { + gridRect.y += labelUnionRect.height + margin; + } else if (axis.position === 'left') { + gridRect.x += labelUnionRect.width + margin; + } + } + } + }); + adjustAxes(); + } + + each(this._coordsList, function (coord) { + coord.calcAffineTransform(); + }); + + function adjustAxes() { + each(axesList, function (axis) { + var isHorizontal = axis.isHorizontal(); + var extent = isHorizontal ? [0, gridRect.width] : [0, gridRect.height]; + var idx = axis.inverse ? 1 : 0; + axis.setExtent(extent[idx], extent[1 - idx]); + updateAxisTransform(axis, isHorizontal ? gridRect.x : gridRect.y); + }); + } + }; + + Grid.prototype.getAxis = function (dim, axisIndex) { + var axesMapOnDim = this._axesMap[dim]; + + if (axesMapOnDim != null) { + return axesMapOnDim[axisIndex || 0]; + } + }; + + Grid.prototype.getAxes = function () { + return this._axesList.slice(); + }; + + Grid.prototype.getCartesian = function (xAxisIndex, yAxisIndex) { + if (xAxisIndex != null && yAxisIndex != null) { + var key = 'x' + xAxisIndex + 'y' + yAxisIndex; + return this._coordsMap[key]; + } + + if (isObject(xAxisIndex)) { + yAxisIndex = xAxisIndex.yAxisIndex; + xAxisIndex = xAxisIndex.xAxisIndex; + } + + for (var i = 0, coordList = this._coordsList; i < coordList.length; i++) { + if (coordList[i].getAxis('x').index === xAxisIndex || coordList[i].getAxis('y').index === yAxisIndex) { + return coordList[i]; + } + } + }; + + Grid.prototype.getCartesians = function () { + return this._coordsList.slice(); + }; + + Grid.prototype.convertToPixel = function (ecModel, finder, value) { + var target = this._findConvertTarget(finder); + + return target.cartesian ? target.cartesian.dataToPoint(value) : target.axis ? target.axis.toGlobalCoord(target.axis.dataToCoord(value)) : null; + }; + + Grid.prototype.convertFromPixel = function (ecModel, finder, value) { + var target = this._findConvertTarget(finder); + + return target.cartesian ? target.cartesian.pointToData(value) : target.axis ? target.axis.coordToData(target.axis.toLocalCoord(value)) : null; + }; + + Grid.prototype._findConvertTarget = function (finder) { + var seriesModel = finder.seriesModel; + var xAxisModel = finder.xAxisModel || seriesModel && seriesModel.getReferringComponents('xAxis', SINGLE_REFERRING).models[0]; + var yAxisModel = finder.yAxisModel || seriesModel && seriesModel.getReferringComponents('yAxis', SINGLE_REFERRING).models[0]; + var gridModel = finder.gridModel; + var coordsList = this._coordsList; + var cartesian; + var axis; + + if (seriesModel) { + cartesian = seriesModel.coordinateSystem; + indexOf(coordsList, cartesian) < 0 && (cartesian = null); + } else if (xAxisModel && yAxisModel) { + cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex); + } else if (xAxisModel) { + axis = this.getAxis('x', xAxisModel.componentIndex); + } else if (yAxisModel) { + axis = this.getAxis('y', yAxisModel.componentIndex); + } else if (gridModel) { + var grid = gridModel.coordinateSystem; + + if (grid === this) { + cartesian = this._coordsList[0]; + } + } + + return { + cartesian: cartesian, + axis: axis + }; + }; + + Grid.prototype.containPoint = function (point) { + var coord = this._coordsList[0]; + + if (coord) { + return coord.containPoint(point); + } + }; + + Grid.prototype._initCartesian = function (gridModel, ecModel, api) { + var _this = this; + + var grid = this; + var axisPositionUsed = { + left: false, + right: false, + top: false, + bottom: false + }; + var axesMap = { + x: {}, + y: {} + }; + var axesCount = { + x: 0, + y: 0 + }; + ecModel.eachComponent('xAxis', createAxisCreator('x'), this); + ecModel.eachComponent('yAxis', createAxisCreator('y'), this); + + if (!axesCount.x || !axesCount.y) { + this._axesMap = {}; + this._axesList = []; + return; + } + + this._axesMap = axesMap; + each(axesMap.x, function (xAxis, xAxisIndex) { + each(axesMap.y, function (yAxis, yAxisIndex) { + var key = 'x' + xAxisIndex + 'y' + yAxisIndex; + var cartesian = new Cartesian2D(key); + cartesian.master = _this; + cartesian.model = gridModel; + _this._coordsMap[key] = cartesian; + + _this._coordsList.push(cartesian); + + cartesian.addAxis(xAxis); + cartesian.addAxis(yAxis); + }); + }); + + function createAxisCreator(dimName) { + return function (axisModel, idx) { + if (!isAxisUsedInTheGrid(axisModel, gridModel)) { + return; + } + + var axisPosition = axisModel.get('position'); + + if (dimName === 'x') { + if (axisPosition !== 'top' && axisPosition !== 'bottom') { + axisPosition = axisPositionUsed.bottom ? 'top' : 'bottom'; + } + } else { + if (axisPosition !== 'left' && axisPosition !== 'right') { + axisPosition = axisPositionUsed.left ? 'right' : 'left'; + } + } + + axisPositionUsed[axisPosition] = true; + var axis = new Axis2D(dimName, createScaleByModel(axisModel), [0, 0], axisModel.get('type'), axisPosition); + var isCategory = axis.type === 'category'; + axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.inverse = axisModel.get('inverse'); + axisModel.axis = axis; + axis.model = axisModel; + axis.grid = grid; + axis.index = idx; + + grid._axesList.push(axis); + + axesMap[dimName][idx] = axis; + axesCount[dimName]++; + }; + } + }; + + Grid.prototype._updateScale = function (ecModel, gridModel) { + each(this._axesList, function (axis) { + axis.scale.setExtent(Infinity, -Infinity); + + if (axis.type === 'category') { + var categorySortInfo = axis.model.get('categorySortInfo'); + axis.scale.setSortInfo(categorySortInfo); + } + }); + ecModel.eachSeries(function (seriesModel) { + if (isCartesian2DSeries(seriesModel)) { + var axesModelMap = findAxisModels(seriesModel); + var xAxisModel = axesModelMap.xAxisModel; + var yAxisModel = axesModelMap.yAxisModel; + + if (!isAxisUsedInTheGrid(xAxisModel, gridModel) || !isAxisUsedInTheGrid(yAxisModel, gridModel)) { + return; + } + + var cartesian = this.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex); + var data = seriesModel.getData(); + var xAxis = cartesian.getAxis('x'); + var yAxis = cartesian.getAxis('y'); + + if (data.type === 'list') { + unionExtent(data, xAxis); + unionExtent(data, yAxis); + } + } + }, this); + + function unionExtent(data, axis) { + each(getDataDimensionsOnAxis(data, axis.dim), function (dim) { + axis.scale.unionExtentFromData(data, dim); + }); + } + }; + + Grid.prototype.getTooltipAxes = function (dim) { + var baseAxes = []; + var otherAxes = []; + each(this.getCartesians(), function (cartesian) { + var baseAxis = dim != null && dim !== 'auto' ? cartesian.getAxis(dim) : cartesian.getBaseAxis(); + var otherAxis = cartesian.getOtherAxis(baseAxis); + indexOf(baseAxes, baseAxis) < 0 && baseAxes.push(baseAxis); + indexOf(otherAxes, otherAxis) < 0 && otherAxes.push(otherAxis); + }); + return { + baseAxes: baseAxes, + otherAxes: otherAxes + }; + }; + + Grid.create = function (ecModel, api) { + var grids = []; + ecModel.eachComponent('grid', function (gridModel, idx) { + var grid = new Grid(gridModel, ecModel, api); + grid.name = 'grid_' + idx; + grid.resize(gridModel, api, true); + gridModel.coordinateSystem = grid; + grids.push(grid); + }); + ecModel.eachSeries(function (seriesModel) { + if (!isCartesian2DSeries(seriesModel)) { + return; + } + + var axesModelMap = findAxisModels(seriesModel); + var xAxisModel = axesModelMap.xAxisModel; + var yAxisModel = axesModelMap.yAxisModel; + var gridModel = xAxisModel.getCoordSysModel(); + + if ("development" !== 'production') { + if (!gridModel) { + throw new Error('Grid "' + retrieve3(xAxisModel.get('gridIndex'), xAxisModel.get('gridId'), 0) + '" not found'); + } + + if (xAxisModel.getCoordSysModel() !== yAxisModel.getCoordSysModel()) { + throw new Error('xAxis and yAxis must use the same grid'); + } + } + + var grid = gridModel.coordinateSystem; + seriesModel.coordinateSystem = grid.getCartesian(xAxisModel.componentIndex, yAxisModel.componentIndex); + }); + return grids; + }; + + Grid.dimensions = cartesian2DDimensions; + return Grid; + }(); + + function isAxisUsedInTheGrid(axisModel, gridModel) { + return axisModel.getCoordSysModel() === gridModel; + } + + function fixAxisOnZero(axesMap, otherAxisDim, axis, onZeroRecords) { + axis.getAxesOnZeroOf = function () { + return otherAxisOnZeroOf ? [otherAxisOnZeroOf] : []; + }; + + var otherAxes = axesMap[otherAxisDim]; + var otherAxisOnZeroOf; + var axisModel = axis.model; + var onZero = axisModel.get(['axisLine', 'onZero']); + var onZeroAxisIndex = axisModel.get(['axisLine', 'onZeroAxisIndex']); + + if (!onZero) { + return; + } + + if (onZeroAxisIndex != null) { + if (canOnZeroToAxis(otherAxes[onZeroAxisIndex])) { + otherAxisOnZeroOf = otherAxes[onZeroAxisIndex]; + } + } else { + for (var idx in otherAxes) { + if (otherAxes.hasOwnProperty(idx) && canOnZeroToAxis(otherAxes[idx]) && !onZeroRecords[getOnZeroRecordKey(otherAxes[idx])]) { + otherAxisOnZeroOf = otherAxes[idx]; + break; + } + } + } + + if (otherAxisOnZeroOf) { + onZeroRecords[getOnZeroRecordKey(otherAxisOnZeroOf)] = true; + } + + function getOnZeroRecordKey(axis) { + return axis.dim + '_' + axis.index; + } + } + + function canOnZeroToAxis(axis) { + return axis && axis.type !== 'category' && axis.type !== 'time' && ifAxisCrossZero(axis); + } + + function updateAxisTransform(axis, coordBase) { + var axisExtent = axis.getExtent(); + var axisExtentSum = axisExtent[0] + axisExtent[1]; + axis.toGlobalCoord = axis.dim === 'x' ? function (coord) { + return coord + coordBase; + } : function (coord) { + return axisExtentSum - coord + coordBase; + }; + axis.toLocalCoord = axis.dim === 'x' ? function (coord) { + return coord - coordBase; + } : function (coord) { + return axisExtentSum - coord + coordBase; + }; + } + + var PI$5 = Math.PI; + + var AxisBuilder = function () { + function AxisBuilder(axisModel, opt) { + this.group = new Group(); + this.opt = opt; + this.axisModel = axisModel; + defaults(opt, { + labelOffset: 0, + nameDirection: 1, + tickDirection: 1, + labelDirection: 1, + silent: true, + handleAutoShown: function () { + return true; + } + }); + var transformGroup = new Group({ + x: opt.position[0], + y: opt.position[1], + rotation: opt.rotation + }); + transformGroup.updateTransform(); + this._transformGroup = transformGroup; + } + + AxisBuilder.prototype.hasBuilder = function (name) { + return !!builders[name]; + }; + + AxisBuilder.prototype.add = function (name) { + builders[name](this.opt, this.axisModel, this.group, this._transformGroup); + }; + + AxisBuilder.prototype.getGroup = function () { + return this.group; + }; + + AxisBuilder.innerTextLayout = function (axisRotation, textRotation, direction) { + var rotationDiff = remRadian(textRotation - axisRotation); + var textAlign; + var textVerticalAlign; + + if (isRadianAroundZero(rotationDiff)) { + textVerticalAlign = direction > 0 ? 'top' : 'bottom'; + textAlign = 'center'; + } else if (isRadianAroundZero(rotationDiff - PI$5)) { + textVerticalAlign = direction > 0 ? 'bottom' : 'top'; + textAlign = 'center'; + } else { + textVerticalAlign = 'middle'; + + if (rotationDiff > 0 && rotationDiff < PI$5) { + textAlign = direction > 0 ? 'right' : 'left'; + } else { + textAlign = direction > 0 ? 'left' : 'right'; + } + } + + return { + rotation: rotationDiff, + textAlign: textAlign, + textVerticalAlign: textVerticalAlign + }; + }; + + AxisBuilder.makeAxisEventDataBase = function (axisModel) { + var eventData = { + componentType: axisModel.mainType, + componentIndex: axisModel.componentIndex + }; + eventData[axisModel.mainType + 'Index'] = axisModel.componentIndex; + return eventData; + }; + + AxisBuilder.isLabelSilent = function (axisModel) { + var tooltipOpt = axisModel.get('tooltip'); + return axisModel.get('silent') || !(axisModel.get('triggerEvent') || tooltipOpt && tooltipOpt.show); + }; + + return AxisBuilder; + }(); + var builders = { + axisLine: function (opt, axisModel, group, transformGroup) { + var shown = axisModel.get(['axisLine', 'show']); + + if (shown === 'auto' && opt.handleAutoShown) { + shown = opt.handleAutoShown('axisLine'); + } + + if (!shown) { + return; + } + + var extent = axisModel.axis.getExtent(); + var matrix = transformGroup.transform; + var pt1 = [extent[0], 0]; + var pt2 = [extent[1], 0]; + + if (matrix) { + applyTransform(pt1, pt1, matrix); + applyTransform(pt2, pt2, matrix); + } + + var lineStyle = extend({ + lineCap: 'round' + }, axisModel.getModel(['axisLine', 'lineStyle']).getLineStyle()); + var line = new Line({ + subPixelOptimize: true, + shape: { + x1: pt1[0], + y1: pt1[1], + x2: pt2[0], + y2: pt2[1] + }, + style: lineStyle, + strokeContainThreshold: opt.strokeContainThreshold || 5, + silent: true, + z2: 1 + }); + line.anid = 'line'; + group.add(line); + var arrows = axisModel.get(['axisLine', 'symbol']); + var arrowSize = axisModel.get(['axisLine', 'symbolSize']); + var arrowOffset = axisModel.get(['axisLine', 'symbolOffset']) || 0; + + if (typeof arrowOffset === 'number') { + arrowOffset = [arrowOffset, arrowOffset]; + } + + if (arrows != null) { + if (typeof arrows === 'string') { + arrows = [arrows, arrows]; + } + + if (typeof arrowSize === 'string' || typeof arrowSize === 'number') { + arrowSize = [arrowSize, arrowSize]; + } + + var symbolWidth_1 = arrowSize[0]; + var symbolHeight_1 = arrowSize[1]; + each([{ + rotate: opt.rotation + Math.PI / 2, + offset: arrowOffset[0], + r: 0 + }, { + rotate: opt.rotation - Math.PI / 2, + offset: arrowOffset[1], + r: Math.sqrt((pt1[0] - pt2[0]) * (pt1[0] - pt2[0]) + (pt1[1] - pt2[1]) * (pt1[1] - pt2[1])) + }], function (point, index) { + if (arrows[index] !== 'none' && arrows[index] != null) { + var symbol = createSymbol(arrows[index], -symbolWidth_1 / 2, -symbolHeight_1 / 2, symbolWidth_1, symbolHeight_1, lineStyle.stroke, true); + var r = point.r + point.offset; + symbol.attr({ + rotation: point.rotate, + x: pt1[0] + r * Math.cos(opt.rotation), + y: pt1[1] - r * Math.sin(opt.rotation), + silent: true, + z2: 11 + }); + group.add(symbol); + } + }); + } + }, + axisTickLabel: function (opt, axisModel, group, transformGroup) { + var ticksEls = buildAxisMajorTicks(group, transformGroup, axisModel, opt); + var labelEls = buildAxisLabel(group, transformGroup, axisModel, opt); + fixMinMaxLabelShow(axisModel, labelEls, ticksEls); + buildAxisMinorTicks(group, transformGroup, axisModel, opt.tickDirection); + }, + axisName: function (opt, axisModel, group, transformGroup) { + var name = retrieve(opt.axisName, axisModel.get('name')); + + if (!name) { + return; + } + + var nameLocation = axisModel.get('nameLocation'); + var nameDirection = opt.nameDirection; + var textStyleModel = axisModel.getModel('nameTextStyle'); + var gap = axisModel.get('nameGap') || 0; + var extent = axisModel.axis.getExtent(); + var gapSignal = extent[0] > extent[1] ? -1 : 1; + var pos = [nameLocation === 'start' ? extent[0] - gapSignal * gap : nameLocation === 'end' ? extent[1] + gapSignal * gap : (extent[0] + extent[1]) / 2, isNameLocationCenter(nameLocation) ? opt.labelOffset + nameDirection * gap : 0]; + var labelLayout; + var nameRotation = axisModel.get('nameRotate'); + + if (nameRotation != null) { + nameRotation = nameRotation * PI$5 / 180; + } + + var axisNameAvailableWidth; + + if (isNameLocationCenter(nameLocation)) { + labelLayout = AxisBuilder.innerTextLayout(opt.rotation, nameRotation != null ? nameRotation : opt.rotation, nameDirection); + } else { + labelLayout = endTextLayout(opt.rotation, nameLocation, nameRotation || 0, extent); + axisNameAvailableWidth = opt.axisNameAvailableWidth; + + if (axisNameAvailableWidth != null) { + axisNameAvailableWidth = Math.abs(axisNameAvailableWidth / Math.sin(labelLayout.rotation)); + !isFinite(axisNameAvailableWidth) && (axisNameAvailableWidth = null); + } + } + + var textFont = textStyleModel.getFont(); + var truncateOpt = axisModel.get('nameTruncate', true) || {}; + var ellipsis = truncateOpt.ellipsis; + var maxWidth = retrieve(opt.nameTruncateMaxWidth, truncateOpt.maxWidth, axisNameAvailableWidth); + var tooltipOpt = axisModel.get('tooltip', true); + var mainType = axisModel.mainType; + var formatterParams = { + componentType: mainType, + name: name, + $vars: ['name'] + }; + formatterParams[mainType + 'Index'] = axisModel.componentIndex; + var textEl = new ZRText({ + x: pos[0], + y: pos[1], + rotation: labelLayout.rotation, + silent: AxisBuilder.isLabelSilent(axisModel), + style: createTextStyle(textStyleModel, { + text: name, + font: textFont, + overflow: 'truncate', + width: maxWidth, + ellipsis: ellipsis, + fill: textStyleModel.getTextColor() || axisModel.get(['axisLine', 'lineStyle', 'color']), + align: textStyleModel.get('align') || labelLayout.textAlign, + verticalAlign: textStyleModel.get('verticalAlign') || labelLayout.textVerticalAlign + }), + z2: 1 + }); + textEl.tooltip = tooltipOpt && tooltipOpt.show ? extend({ + content: name, + formatter: function () { + return name; + }, + formatterParams: formatterParams + }, tooltipOpt) : null; + textEl.__fullText = name; + textEl.anid = 'name'; + + if (axisModel.get('triggerEvent')) { + var eventData = AxisBuilder.makeAxisEventDataBase(axisModel); + eventData.targetType = 'axisName'; + eventData.name = name; + getECData(textEl).eventData = eventData; + } + + transformGroup.add(textEl); + textEl.updateTransform(); + group.add(textEl); + textEl.decomposeTransform(); + } + }; + + function endTextLayout(rotation, textPosition, textRotate, extent) { + var rotationDiff = remRadian(textRotate - rotation); + var textAlign; + var textVerticalAlign; + var inverse = extent[0] > extent[1]; + var onLeft = textPosition === 'start' && !inverse || textPosition !== 'start' && inverse; + + if (isRadianAroundZero(rotationDiff - PI$5 / 2)) { + textVerticalAlign = onLeft ? 'bottom' : 'top'; + textAlign = 'center'; + } else if (isRadianAroundZero(rotationDiff - PI$5 * 1.5)) { + textVerticalAlign = onLeft ? 'top' : 'bottom'; + textAlign = 'center'; + } else { + textVerticalAlign = 'middle'; + + if (rotationDiff < PI$5 * 1.5 && rotationDiff > PI$5 / 2) { + textAlign = onLeft ? 'left' : 'right'; + } else { + textAlign = onLeft ? 'right' : 'left'; + } + } + + return { + rotation: rotationDiff, + textAlign: textAlign, + textVerticalAlign: textVerticalAlign + }; + } + + function fixMinMaxLabelShow(axisModel, labelEls, tickEls) { + if (shouldShowAllLabels(axisModel.axis)) { + return; + } + + var showMinLabel = axisModel.get(['axisLabel', 'showMinLabel']); + var showMaxLabel = axisModel.get(['axisLabel', 'showMaxLabel']); + labelEls = labelEls || []; + tickEls = tickEls || []; + var firstLabel = labelEls[0]; + var nextLabel = labelEls[1]; + var lastLabel = labelEls[labelEls.length - 1]; + var prevLabel = labelEls[labelEls.length - 2]; + var firstTick = tickEls[0]; + var nextTick = tickEls[1]; + var lastTick = tickEls[tickEls.length - 1]; + var prevTick = tickEls[tickEls.length - 2]; + + if (showMinLabel === false) { + ignoreEl(firstLabel); + ignoreEl(firstTick); + } else if (isTwoLabelOverlapped(firstLabel, nextLabel)) { + if (showMinLabel) { + ignoreEl(nextLabel); + ignoreEl(nextTick); + } else { + ignoreEl(firstLabel); + ignoreEl(firstTick); + } + } + + if (showMaxLabel === false) { + ignoreEl(lastLabel); + ignoreEl(lastTick); + } else if (isTwoLabelOverlapped(prevLabel, lastLabel)) { + if (showMaxLabel) { + ignoreEl(prevLabel); + ignoreEl(prevTick); + } else { + ignoreEl(lastLabel); + ignoreEl(lastTick); + } + } + } + + function ignoreEl(el) { + el && (el.ignore = true); + } + + function isTwoLabelOverlapped(current, next) { + var firstRect = current && current.getBoundingRect().clone(); + var nextRect = next && next.getBoundingRect().clone(); + + if (!firstRect || !nextRect) { + return; + } + + var mRotationBack = identity([]); + rotate(mRotationBack, mRotationBack, -current.rotation); + firstRect.applyTransform(mul$1([], mRotationBack, current.getLocalTransform())); + nextRect.applyTransform(mul$1([], mRotationBack, next.getLocalTransform())); + return firstRect.intersect(nextRect); + } + + function isNameLocationCenter(nameLocation) { + return nameLocation === 'middle' || nameLocation === 'center'; + } + + function createTicks(ticksCoords, tickTransform, tickEndCoord, tickLineStyle, anidPrefix) { + var tickEls = []; + var pt1 = []; + var pt2 = []; + + for (var i = 0; i < ticksCoords.length; i++) { + var tickCoord = ticksCoords[i].coord; + pt1[0] = tickCoord; + pt1[1] = 0; + pt2[0] = tickCoord; + pt2[1] = tickEndCoord; + + if (tickTransform) { + applyTransform(pt1, pt1, tickTransform); + applyTransform(pt2, pt2, tickTransform); + } + + var tickEl = new Line({ + subPixelOptimize: true, + shape: { + x1: pt1[0], + y1: pt1[1], + x2: pt2[0], + y2: pt2[1] + }, + style: tickLineStyle, + z2: 2, + autoBatch: true, + silent: true + }); + tickEl.anid = anidPrefix + '_' + ticksCoords[i].tickValue; + tickEls.push(tickEl); + } + + return tickEls; + } + + function buildAxisMajorTicks(group, transformGroup, axisModel, opt) { + var axis = axisModel.axis; + var tickModel = axisModel.getModel('axisTick'); + var shown = tickModel.get('show'); + + if (shown === 'auto' && opt.handleAutoShown) { + shown = opt.handleAutoShown('axisTick'); + } + + if (!shown || axis.scale.isBlank()) { + return; + } + + var lineStyleModel = tickModel.getModel('lineStyle'); + var tickEndCoord = opt.tickDirection * tickModel.get('length'); + var ticksCoords = axis.getTicksCoords(); + var ticksEls = createTicks(ticksCoords, transformGroup.transform, tickEndCoord, defaults(lineStyleModel.getLineStyle(), { + stroke: axisModel.get(['axisLine', 'lineStyle', 'color']) + }), 'ticks'); + + for (var i = 0; i < ticksEls.length; i++) { + group.add(ticksEls[i]); + } + + return ticksEls; + } + + function buildAxisMinorTicks(group, transformGroup, axisModel, tickDirection) { + var axis = axisModel.axis; + var minorTickModel = axisModel.getModel('minorTick'); + + if (!minorTickModel.get('show') || axis.scale.isBlank()) { + return; + } + + var minorTicksCoords = axis.getMinorTicksCoords(); + + if (!minorTicksCoords.length) { + return; + } + + var lineStyleModel = minorTickModel.getModel('lineStyle'); + var tickEndCoord = tickDirection * minorTickModel.get('length'); + var minorTickLineStyle = defaults(lineStyleModel.getLineStyle(), defaults(axisModel.getModel('axisTick').getLineStyle(), { + stroke: axisModel.get(['axisLine', 'lineStyle', 'color']) + })); + + for (var i = 0; i < minorTicksCoords.length; i++) { + var minorTicksEls = createTicks(minorTicksCoords[i], transformGroup.transform, tickEndCoord, minorTickLineStyle, 'minorticks_' + i); + + for (var k = 0; k < minorTicksEls.length; k++) { + group.add(minorTicksEls[k]); + } + } + } + + function buildAxisLabel(group, transformGroup, axisModel, opt) { + var axis = axisModel.axis; + var show = retrieve(opt.axisLabelShow, axisModel.get(['axisLabel', 'show'])); + + if (!show || axis.scale.isBlank()) { + return; + } + + var labelModel = axisModel.getModel('axisLabel'); + var labelMargin = labelModel.get('margin'); + var labels = axis.getViewLabels(); + var labelRotation = (retrieve(opt.labelRotate, labelModel.get('rotate')) || 0) * PI$5 / 180; + var labelLayout = AxisBuilder.innerTextLayout(opt.rotation, labelRotation, opt.labelDirection); + var rawCategoryData = axisModel.getCategories && axisModel.getCategories(true); + var labelEls = []; + var silent = AxisBuilder.isLabelSilent(axisModel); + var triggerEvent = axisModel.get('triggerEvent'); + each(labels, function (labelItem, index) { + var tickValue = axis.scale.type === 'ordinal' ? axis.scale.getRawOrdinalNumber(labelItem.tickValue) : labelItem.tickValue; + var formattedLabel = labelItem.formattedLabel; + var rawLabel = labelItem.rawLabel; + var itemLabelModel = labelModel; + + if (rawCategoryData && rawCategoryData[tickValue]) { + var rawCategoryItem = rawCategoryData[tickValue]; + + if (isObject(rawCategoryItem) && rawCategoryItem.textStyle) { + itemLabelModel = new Model(rawCategoryItem.textStyle, labelModel, axisModel.ecModel); + } + } + + var textColor = itemLabelModel.getTextColor() || axisModel.get(['axisLine', 'lineStyle', 'color']); + var tickCoord = axis.dataToCoord(tickValue); + var textEl = new ZRText({ + x: tickCoord, + y: opt.labelOffset + opt.labelDirection * labelMargin, + rotation: labelLayout.rotation, + silent: silent, + z2: 10, + style: createTextStyle(itemLabelModel, { + text: formattedLabel, + align: itemLabelModel.getShallow('align', true) || labelLayout.textAlign, + verticalAlign: itemLabelModel.getShallow('verticalAlign', true) || itemLabelModel.getShallow('baseline', true) || labelLayout.textVerticalAlign, + fill: typeof textColor === 'function' ? textColor(axis.type === 'category' ? rawLabel : axis.type === 'value' ? tickValue + '' : tickValue, index) : textColor + }) + }); + textEl.anid = 'label_' + tickValue; + + if (triggerEvent) { + var eventData = AxisBuilder.makeAxisEventDataBase(axisModel); + eventData.targetType = 'axisLabel'; + eventData.value = rawLabel; + getECData(textEl).eventData = eventData; + } + + transformGroup.add(textEl); + textEl.updateTransform(); + labelEls.push(textEl); + group.add(textEl); + textEl.decomposeTransform(); + }); + return labelEls; + } + + function collect(ecModel, api) { + var result = { + axesInfo: {}, + seriesInvolved: false, + coordSysAxesInfo: {}, + coordSysMap: {} + }; + collectAxesInfo(result, ecModel, api); + result.seriesInvolved && collectSeriesInfo(result, ecModel); + return result; + } + + function collectAxesInfo(result, ecModel, api) { + var globalTooltipModel = ecModel.getComponent('tooltip'); + var globalAxisPointerModel = ecModel.getComponent('axisPointer'); + var linksOption = globalAxisPointerModel.get('link', true) || []; + var linkGroups = []; + each(api.getCoordinateSystems(), function (coordSys) { + if (!coordSys.axisPointerEnabled) { + return; + } + + var coordSysKey = makeKey(coordSys.model); + var axesInfoInCoordSys = result.coordSysAxesInfo[coordSysKey] = {}; + result.coordSysMap[coordSysKey] = coordSys; + var coordSysModel = coordSys.model; + var baseTooltipModel = coordSysModel.getModel('tooltip', globalTooltipModel); + each(coordSys.getAxes(), curry(saveTooltipAxisInfo, false, null)); + + if (coordSys.getTooltipAxes && globalTooltipModel && baseTooltipModel.get('show')) { + var triggerAxis = baseTooltipModel.get('trigger') === 'axis'; + var cross = baseTooltipModel.get(['axisPointer', 'type']) === 'cross'; + var tooltipAxes = coordSys.getTooltipAxes(baseTooltipModel.get(['axisPointer', 'axis'])); + + if (triggerAxis || cross) { + each(tooltipAxes.baseAxes, curry(saveTooltipAxisInfo, cross ? 'cross' : true, triggerAxis)); + } + + if (cross) { + each(tooltipAxes.otherAxes, curry(saveTooltipAxisInfo, 'cross', false)); + } + } + + function saveTooltipAxisInfo(fromTooltip, triggerTooltip, axis) { + var axisPointerModel = axis.model.getModel('axisPointer', globalAxisPointerModel); + var axisPointerShow = axisPointerModel.get('show'); + + if (!axisPointerShow || axisPointerShow === 'auto' && !fromTooltip && !isHandleTrigger(axisPointerModel)) { + return; + } + + if (triggerTooltip == null) { + triggerTooltip = axisPointerModel.get('triggerTooltip'); + } + + axisPointerModel = fromTooltip ? makeAxisPointerModel(axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip) : axisPointerModel; + var snap = axisPointerModel.get('snap'); + var axisKey = makeKey(axis.model); + var involveSeries = triggerTooltip || snap || axis.type === 'category'; + var axisInfo = result.axesInfo[axisKey] = { + key: axisKey, + axis: axis, + coordSys: coordSys, + axisPointerModel: axisPointerModel, + triggerTooltip: triggerTooltip, + involveSeries: involveSeries, + snap: snap, + useHandle: isHandleTrigger(axisPointerModel), + seriesModels: [], + linkGroup: null + }; + axesInfoInCoordSys[axisKey] = axisInfo; + result.seriesInvolved = result.seriesInvolved || involveSeries; + var groupIndex = getLinkGroupIndex(linksOption, axis); + + if (groupIndex != null) { + var linkGroup = linkGroups[groupIndex] || (linkGroups[groupIndex] = { + axesInfo: {} + }); + linkGroup.axesInfo[axisKey] = axisInfo; + linkGroup.mapper = linksOption[groupIndex].mapper; + axisInfo.linkGroup = linkGroup; + } + } + }); + } + + function makeAxisPointerModel(axis, baseTooltipModel, globalAxisPointerModel, ecModel, fromTooltip, triggerTooltip) { + var tooltipAxisPointerModel = baseTooltipModel.getModel('axisPointer'); + var fields = ['type', 'snap', 'lineStyle', 'shadowStyle', 'label', 'animation', 'animationDurationUpdate', 'animationEasingUpdate', 'z']; + var volatileOption = {}; + each(fields, function (field) { + volatileOption[field] = clone(tooltipAxisPointerModel.get(field)); + }); + volatileOption.snap = axis.type !== 'category' && !!triggerTooltip; + + if (tooltipAxisPointerModel.get('type') === 'cross') { + volatileOption.type = 'line'; + } + + var labelOption = volatileOption.label || (volatileOption.label = {}); + labelOption.show == null && (labelOption.show = false); + + if (fromTooltip === 'cross') { + var tooltipAxisPointerLabelShow = tooltipAxisPointerModel.get(['label', 'show']); + labelOption.show = tooltipAxisPointerLabelShow != null ? tooltipAxisPointerLabelShow : true; + + if (!triggerTooltip) { + var crossStyle = volatileOption.lineStyle = tooltipAxisPointerModel.get('crossStyle'); + crossStyle && defaults(labelOption, crossStyle.textStyle); + } + } + + return axis.model.getModel('axisPointer', new Model(volatileOption, globalAxisPointerModel, ecModel)); + } + + function collectSeriesInfo(result, ecModel) { + ecModel.eachSeries(function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var seriesTooltipTrigger = seriesModel.get(['tooltip', 'trigger'], true); + var seriesTooltipShow = seriesModel.get(['tooltip', 'show'], true); + + if (!coordSys || seriesTooltipTrigger === 'none' || seriesTooltipTrigger === false || seriesTooltipTrigger === 'item' || seriesTooltipShow === false || seriesModel.get(['axisPointer', 'show'], true) === false) { + return; + } + + each(result.coordSysAxesInfo[makeKey(coordSys.model)], function (axisInfo) { + var axis = axisInfo.axis; + + if (coordSys.getAxis(axis.dim) === axis) { + axisInfo.seriesModels.push(seriesModel); + axisInfo.seriesDataCount == null && (axisInfo.seriesDataCount = 0); + axisInfo.seriesDataCount += seriesModel.getData().count(); + } + }); + }); + } + + function getLinkGroupIndex(linksOption, axis) { + var axisModel = axis.model; + var dim = axis.dim; + + for (var i = 0; i < linksOption.length; i++) { + var linkOption = linksOption[i] || {}; + + if (checkPropInLink(linkOption[dim + 'AxisId'], axisModel.id) || checkPropInLink(linkOption[dim + 'AxisIndex'], axisModel.componentIndex) || checkPropInLink(linkOption[dim + 'AxisName'], axisModel.name)) { + return i; + } + } + } + + function checkPropInLink(linkPropValue, axisPropValue) { + return linkPropValue === 'all' || isArray(linkPropValue) && indexOf(linkPropValue, axisPropValue) >= 0 || linkPropValue === axisPropValue; + } + + function fixValue(axisModel) { + var axisInfo = getAxisInfo(axisModel); + + if (!axisInfo) { + return; + } + + var axisPointerModel = axisInfo.axisPointerModel; + var scale = axisInfo.axis.scale; + var option = axisPointerModel.option; + var status = axisPointerModel.get('status'); + var value = axisPointerModel.get('value'); + + if (value != null) { + value = scale.parse(value); + } + + var useHandle = isHandleTrigger(axisPointerModel); + + if (status == null) { + option.status = useHandle ? 'show' : 'hide'; + } + + var extent = scale.getExtent().slice(); + extent[0] > extent[1] && extent.reverse(); + + if (value == null || value > extent[1]) { + value = extent[1]; + } + + if (value < extent[0]) { + value = extent[0]; + } + + option.value = value; + + if (useHandle) { + option.status = axisInfo.axis.scale.isBlank() ? 'hide' : 'show'; + } + } + function getAxisInfo(axisModel) { + var coordSysAxesInfo = (axisModel.ecModel.getComponent('axisPointer') || {}).coordSysAxesInfo; + return coordSysAxesInfo && coordSysAxesInfo.axesInfo[makeKey(axisModel)]; + } + function getAxisPointerModel(axisModel) { + var axisInfo = getAxisInfo(axisModel); + return axisInfo && axisInfo.axisPointerModel; + } + + function isHandleTrigger(axisPointerModel) { + return !!axisPointerModel.get(['handle', 'show']); + } + + function makeKey(model) { + return model.type + '||' + model.id; + } + + var axisPointerClazz = {}; + + var AxisView = function (_super) { + __extends(AxisView, _super); + + function AxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = AxisView.type; + return _this; + } + + AxisView.prototype.render = function (axisModel, ecModel, api, payload) { + this.axisPointerClass && fixValue(axisModel); + + _super.prototype.render.apply(this, arguments); + + this._doUpdateAxisPointerClass(axisModel, api, true); + }; + + AxisView.prototype.updateAxisPointer = function (axisModel, ecModel, api, payload) { + this._doUpdateAxisPointerClass(axisModel, api, false); + }; + + AxisView.prototype.remove = function (ecModel, api) { + var axisPointer = this._axisPointer; + axisPointer && axisPointer.remove(api); + }; + + AxisView.prototype.dispose = function (ecModel, api) { + this._disposeAxisPointer(api); + + _super.prototype.dispose.apply(this, arguments); + }; + + AxisView.prototype._doUpdateAxisPointerClass = function (axisModel, api, forceRender) { + var Clazz = AxisView.getAxisPointerClass(this.axisPointerClass); + + if (!Clazz) { + return; + } + + var axisPointerModel = getAxisPointerModel(axisModel); + axisPointerModel ? (this._axisPointer || (this._axisPointer = new Clazz())).render(axisModel, axisPointerModel, api, forceRender) : this._disposeAxisPointer(api); + }; + + AxisView.prototype._disposeAxisPointer = function (api) { + this._axisPointer && this._axisPointer.dispose(api); + this._axisPointer = null; + }; + + AxisView.registerAxisPointerClass = function (type, clazz) { + if ("development" !== 'production') { + if (axisPointerClazz[type]) { + throw new Error('axisPointer ' + type + ' exists'); + } + } + + axisPointerClazz[type] = clazz; + }; + + AxisView.getAxisPointerClass = function (type) { + return type && axisPointerClazz[type]; + }; + AxisView.type = 'axis'; + return AxisView; + }(ComponentView); + + var inner$5 = makeInner(); + function rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, gridModel) { + var axis = axisModel.axis; + + if (axis.scale.isBlank()) { + return; + } + + var splitAreaModel = axisModel.getModel('splitArea'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var areaColors = areaStyleModel.get('color'); + var gridRect = gridModel.coordinateSystem.getRect(); + var ticksCoords = axis.getTicksCoords({ + tickModel: splitAreaModel, + clamp: true + }); + + if (!ticksCoords.length) { + return; + } + + var areaColorsLen = areaColors.length; + var lastSplitAreaColors = inner$5(axisView).splitAreaColors; + var newSplitAreaColors = createHashMap(); + var colorIndex = 0; + + if (lastSplitAreaColors) { + for (var i = 0; i < ticksCoords.length; i++) { + var cIndex = lastSplitAreaColors.get(ticksCoords[i].tickValue); + + if (cIndex != null) { + colorIndex = (cIndex + (areaColorsLen - 1) * i) % areaColorsLen; + break; + } + } + } + + var prev = axis.toGlobalCoord(ticksCoords[0].coord); + var areaStyle = areaStyleModel.getAreaStyle(); + areaColors = isArray(areaColors) ? areaColors : [areaColors]; + + for (var i = 1; i < ticksCoords.length; i++) { + var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord); + var x = void 0; + var y = void 0; + var width = void 0; + var height = void 0; + + if (axis.isHorizontal()) { + x = prev; + y = gridRect.y; + width = tickCoord - x; + height = gridRect.height; + prev = x + width; + } else { + x = gridRect.x; + y = prev; + width = gridRect.width; + height = tickCoord - y; + prev = y + height; + } + + var tickValue = ticksCoords[i - 1].tickValue; + tickValue != null && newSplitAreaColors.set(tickValue, colorIndex); + axisGroup.add(new Rect({ + anid: tickValue != null ? 'area_' + tickValue : null, + shape: { + x: x, + y: y, + width: width, + height: height + }, + style: defaults({ + fill: areaColors[colorIndex] + }, areaStyle), + autoBatch: true, + silent: true + })); + colorIndex = (colorIndex + 1) % areaColorsLen; + } + + inner$5(axisView).splitAreaColors = newSplitAreaColors; + } + function rectCoordAxisHandleRemove(axisView) { + inner$5(axisView).splitAreaColors = null; + } + + var axisBuilderAttrs = ['axisLine', 'axisTickLabel', 'axisName']; + var selfBuilderAttrs = ['splitArea', 'splitLine', 'minorSplitLine']; + + var CartesianAxisView = function (_super) { + __extends(CartesianAxisView, _super); + + function CartesianAxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CartesianAxisView.type; + _this.axisPointerClass = 'CartesianAxisPointer'; + return _this; + } + + CartesianAxisView.prototype.render = function (axisModel, ecModel, api, payload) { + this.group.removeAll(); + var oldAxisGroup = this._axisGroup; + this._axisGroup = new Group(); + this.group.add(this._axisGroup); + + if (!axisModel.get('show')) { + return; + } + + var gridModel = axisModel.getCoordSysModel(); + var layout = layout$1(gridModel, axisModel); + var axisBuilder = new AxisBuilder(axisModel, extend({ + handleAutoShown: function (elementType) { + var cartesians = gridModel.coordinateSystem.getCartesians(); + + for (var i = 0; i < cartesians.length; i++) { + var otherAxisType = cartesians[i].getOtherAxis(axisModel.axis).type; + + if (otherAxisType === 'value' || otherAxisType === 'log') { + return true; + } + } + + return false; + } + }, layout)); + each(axisBuilderAttrs, axisBuilder.add, axisBuilder); + + this._axisGroup.add(axisBuilder.getGroup()); + + each(selfBuilderAttrs, function (name) { + if (axisModel.get([name, 'show'])) { + axisElementBuilders[name](this, this._axisGroup, axisModel, gridModel); + } + }, this); + groupTransition(oldAxisGroup, this._axisGroup, axisModel); + + _super.prototype.render.call(this, axisModel, ecModel, api, payload); + }; + + CartesianAxisView.prototype.remove = function () { + rectCoordAxisHandleRemove(this); + }; + + CartesianAxisView.type = 'cartesianAxis'; + return CartesianAxisView; + }(AxisView); + + var axisElementBuilders = { + splitLine: function (axisView, axisGroup, axisModel, gridModel) { + var axis = axisModel.axis; + + if (axis.scale.isBlank()) { + return; + } + + var splitLineModel = axisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + lineColors = isArray(lineColors) ? lineColors : [lineColors]; + var gridRect = gridModel.coordinateSystem.getRect(); + var isHorizontal = axis.isHorizontal(); + var lineCount = 0; + var ticksCoords = axis.getTicksCoords({ + tickModel: splitLineModel + }); + var p1 = []; + var p2 = []; + var lineStyle = lineStyleModel.getLineStyle(); + + for (var i = 0; i < ticksCoords.length; i++) { + var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord); + + if (isHorizontal) { + p1[0] = tickCoord; + p1[1] = gridRect.y; + p2[0] = tickCoord; + p2[1] = gridRect.y + gridRect.height; + } else { + p1[0] = gridRect.x; + p1[1] = tickCoord; + p2[0] = gridRect.x + gridRect.width; + p2[1] = tickCoord; + } + + var colorIndex = lineCount++ % lineColors.length; + var tickValue = ticksCoords[i].tickValue; + axisGroup.add(new Line({ + anid: tickValue != null ? 'line_' + ticksCoords[i].tickValue : null, + subPixelOptimize: true, + autoBatch: true, + shape: { + x1: p1[0], + y1: p1[1], + x2: p2[0], + y2: p2[1] + }, + style: defaults({ + stroke: lineColors[colorIndex] + }, lineStyle), + silent: true + })); + } + }, + minorSplitLine: function (axisView, axisGroup, axisModel, gridModel) { + var axis = axisModel.axis; + var minorSplitLineModel = axisModel.getModel('minorSplitLine'); + var lineStyleModel = minorSplitLineModel.getModel('lineStyle'); + var gridRect = gridModel.coordinateSystem.getRect(); + var isHorizontal = axis.isHorizontal(); + var minorTicksCoords = axis.getMinorTicksCoords(); + + if (!minorTicksCoords.length) { + return; + } + + var p1 = []; + var p2 = []; + var lineStyle = lineStyleModel.getLineStyle(); + + for (var i = 0; i < minorTicksCoords.length; i++) { + for (var k = 0; k < minorTicksCoords[i].length; k++) { + var tickCoord = axis.toGlobalCoord(minorTicksCoords[i][k].coord); + + if (isHorizontal) { + p1[0] = tickCoord; + p1[1] = gridRect.y; + p2[0] = tickCoord; + p2[1] = gridRect.y + gridRect.height; + } else { + p1[0] = gridRect.x; + p1[1] = tickCoord; + p2[0] = gridRect.x + gridRect.width; + p2[1] = tickCoord; + } + + axisGroup.add(new Line({ + anid: 'minor_line_' + minorTicksCoords[i][k].tickValue, + subPixelOptimize: true, + autoBatch: true, + shape: { + x1: p1[0], + y1: p1[1], + x2: p2[0], + y2: p2[1] + }, + style: lineStyle, + silent: true + })); + } + } + }, + splitArea: function (axisView, axisGroup, axisModel, gridModel) { + rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, gridModel); + } + }; + + var CartesianXAxisView = function (_super) { + __extends(CartesianXAxisView, _super); + + function CartesianXAxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CartesianXAxisView.type; + return _this; + } + + CartesianXAxisView.type = 'xAxis'; + return CartesianXAxisView; + }(CartesianAxisView); + + var CartesianYAxisView = function (_super) { + __extends(CartesianYAxisView, _super); + + function CartesianYAxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CartesianXAxisView.type; + return _this; + } + + CartesianYAxisView.type = 'yAxis'; + return CartesianYAxisView; + }(CartesianAxisView); + + var GridView = function (_super) { + __extends(GridView, _super); + + function GridView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = 'grid'; + return _this; + } + + GridView.prototype.render = function (gridModel, ecModel) { + this.group.removeAll(); + + if (gridModel.get('show')) { + this.group.add(new Rect({ + shape: gridModel.coordinateSystem.getRect(), + style: defaults({ + fill: gridModel.get('backgroundColor') + }, gridModel.getItemStyle()), + silent: true, + z2: -1 + })); + } + }; + + GridView.type = 'grid'; + return GridView; + }(ComponentView); + + var extraOption = { + offset: 0 + }; + function install$5(registers) { + registers.registerComponentView(GridView); + registers.registerComponentModel(GridModel); + registers.registerCoordinateSystem('cartesian2d', Grid); + axisModelCreator(registers, 'x', CartesianAxisModel, extraOption); + axisModelCreator(registers, 'y', CartesianAxisModel, extraOption); + registers.registerComponentView(CartesianXAxisView); + registers.registerComponentView(CartesianYAxisView); + registers.registerPreprocessor(function (option) { + if (option.xAxis && option.yAxis && !option.grid) { + option.grid = {}; + } + }); + } + + function install$6(registers) { + use(install$5); + registers.registerSeriesModel(ScatterSeriesModel); + registers.registerChartView(ScatterView); + registers.registerLayout(pointsLayout('scatter')); + } + + function radarLayout(ecModel) { + ecModel.eachSeriesByType('radar', function (seriesModel) { + var data = seriesModel.getData(); + var points = []; + var coordSys = seriesModel.coordinateSystem; + + if (!coordSys) { + return; + } + + var axes = coordSys.getIndicatorAxes(); + each(axes, function (axis, axisIndex) { + data.each(data.mapDimension(axes[axisIndex].dim), function (val, dataIndex) { + points[dataIndex] = points[dataIndex] || []; + var point = coordSys.dataToPoint(val, axisIndex); + points[dataIndex][axisIndex] = isValidPoint(point) ? point : getValueMissingPoint(coordSys); + }); + }); + data.each(function (idx) { + var firstPoint = find(points[idx], function (point) { + return isValidPoint(point); + }) || getValueMissingPoint(coordSys); + points[idx].push(firstPoint.slice()); + data.setItemLayout(idx, points[idx]); + }); + }); + } + + function isValidPoint(point) { + return !isNaN(point[0]) && !isNaN(point[1]); + } + + function getValueMissingPoint(coordSys) { + return [coordSys.cx, coordSys.cy]; + } + + function radarBackwardCompat(option) { + var polarOptArr = option.polar; + + if (polarOptArr) { + if (!isArray(polarOptArr)) { + polarOptArr = [polarOptArr]; + } + + var polarNotRadar_1 = []; + each(polarOptArr, function (polarOpt, idx) { + if (polarOpt.indicator) { + if (polarOpt.type && !polarOpt.shape) { + polarOpt.shape = polarOpt.type; + } + + option.radar = option.radar || []; + + if (!isArray(option.radar)) { + option.radar = [option.radar]; + } + + option.radar.push(polarOpt); + } else { + polarNotRadar_1.push(polarOpt); + } + }); + option.polar = polarNotRadar_1; + } + + each(option.series, function (seriesOpt) { + if (seriesOpt && seriesOpt.type === 'radar' && seriesOpt.polarIndex) { + seriesOpt.radarIndex = seriesOpt.polarIndex; + } + }); + } + + function normalizeSymbolSize(symbolSize) { + if (!isArray(symbolSize)) { + symbolSize = [+symbolSize, +symbolSize]; + } + + return symbolSize; + } + + var RadarView = function (_super) { + __extends(RadarView, _super); + + function RadarView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = RadarView.type; + return _this; + } + + RadarView.prototype.render = function (seriesModel, ecModel, api) { + var polar = seriesModel.coordinateSystem; + var group = this.group; + var data = seriesModel.getData(); + var oldData = this._data; + + function createSymbol$1(data, idx) { + var symbolType = data.getItemVisual(idx, 'symbol') || 'circle'; + + if (symbolType === 'none') { + return; + } + + var symbolSize = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize')); + var symbolPath = createSymbol(symbolType, -1, -1, 2, 2); + var symbolRotate = data.getItemVisual(idx, 'symbolRotate') || 0; + symbolPath.attr({ + style: { + strokeNoScale: true + }, + z2: 100, + scaleX: symbolSize[0] / 2, + scaleY: symbolSize[1] / 2, + rotation: symbolRotate * Math.PI / 180 || 0 + }); + return symbolPath; + } + + function updateSymbols(oldPoints, newPoints, symbolGroup, data, idx, isInit) { + symbolGroup.removeAll(); + + for (var i = 0; i < newPoints.length - 1; i++) { + var symbolPath = createSymbol$1(data, idx); + + if (symbolPath) { + symbolPath.__dimIdx = i; + + if (oldPoints[i]) { + symbolPath.setPosition(oldPoints[i]); + graphic[isInit ? 'initProps' : 'updateProps'](symbolPath, { + x: newPoints[i][0], + y: newPoints[i][1] + }, seriesModel, idx); + } else { + symbolPath.setPosition(newPoints[i]); + } + + symbolGroup.add(symbolPath); + } + } + } + + function getInitialPoints(points) { + return map(points, function (pt) { + return [polar.cx, polar.cy]; + }); + } + + data.diff(oldData).add(function (idx) { + var points = data.getItemLayout(idx); + + if (!points) { + return; + } + + var polygon = new Polygon(); + var polyline = new Polyline(); + var target = { + shape: { + points: points + } + }; + polygon.shape.points = getInitialPoints(points); + polyline.shape.points = getInitialPoints(points); + initProps(polygon, target, seriesModel, idx); + initProps(polyline, target, seriesModel, idx); + var itemGroup = new Group(); + var symbolGroup = new Group(); + itemGroup.add(polyline); + itemGroup.add(polygon); + itemGroup.add(symbolGroup); + updateSymbols(polyline.shape.points, points, symbolGroup, data, idx, true); + data.setItemGraphicEl(idx, itemGroup); + }).update(function (newIdx, oldIdx) { + var itemGroup = oldData.getItemGraphicEl(oldIdx); + var polyline = itemGroup.childAt(0); + var polygon = itemGroup.childAt(1); + var symbolGroup = itemGroup.childAt(2); + var target = { + shape: { + points: data.getItemLayout(newIdx) + } + }; + + if (!target.shape.points) { + return; + } + + updateSymbols(polyline.shape.points, target.shape.points, symbolGroup, data, newIdx, false); + updateProps(polyline, target, seriesModel); + updateProps(polygon, target, seriesModel); + data.setItemGraphicEl(newIdx, itemGroup); + }).remove(function (idx) { + group.remove(oldData.getItemGraphicEl(idx)); + }).execute(); + data.eachItemGraphicEl(function (itemGroup, idx) { + var itemModel = data.getItemModel(idx); + var polyline = itemGroup.childAt(0); + var polygon = itemGroup.childAt(1); + var symbolGroup = itemGroup.childAt(2); + var itemStyle = data.getItemVisual(idx, 'style'); + var color = itemStyle.fill; + group.add(itemGroup); + polyline.useStyle(defaults(itemModel.getModel('lineStyle').getLineStyle(), { + fill: 'none', + stroke: color + })); + setStatesStylesFromModel(polyline, itemModel, 'lineStyle'); + setStatesStylesFromModel(polygon, itemModel, 'areaStyle'); + var areaStyleModel = itemModel.getModel('areaStyle'); + var polygonIgnore = areaStyleModel.isEmpty() && areaStyleModel.parentModel.isEmpty(); + polygon.ignore = polygonIgnore; + each(['emphasis', 'select', 'blur'], function (stateName) { + var stateModel = itemModel.getModel([stateName, 'areaStyle']); + var stateIgnore = stateModel.isEmpty() && stateModel.parentModel.isEmpty(); + polygon.ensureState(stateName).ignore = stateIgnore && polygonIgnore; + }); + polygon.useStyle(defaults(areaStyleModel.getAreaStyle(), { + fill: color, + opacity: 0.7, + decal: itemStyle.decal + })); + var emphasisModel = itemModel.getModel('emphasis'); + var itemHoverStyle = emphasisModel.getModel('itemStyle').getItemStyle(); + symbolGroup.eachChild(function (symbolPath) { + if (symbolPath instanceof ZRImage) { + var pathStyle = symbolPath.style; + symbolPath.useStyle(extend({ + image: pathStyle.image, + x: pathStyle.x, + y: pathStyle.y, + width: pathStyle.width, + height: pathStyle.height + }, itemStyle)); + } else { + symbolPath.useStyle(itemStyle); + symbolPath.setColor(color); + } + + var pathEmphasisState = symbolPath.ensureState('emphasis'); + pathEmphasisState.style = clone(itemHoverStyle); + var defaultText = data.get(data.dimensions[symbolPath.__dimIdx], idx); + (defaultText == null || isNaN(defaultText)) && (defaultText = ''); + setLabelStyle(symbolPath, getLabelStatesModels(itemModel), { + labelFetcher: data.hostModel, + labelDataIndex: idx, + labelDimIndex: symbolPath.__dimIdx, + defaultText: defaultText, + inheritColor: color, + defaultOpacity: itemStyle.opacity + }); + }); + enableHoverEmphasis(itemGroup, emphasisModel.get('focus'), emphasisModel.get('blurScope')); + }); + this._data = data; + }; + + RadarView.prototype.remove = function () { + this.group.removeAll(); + this._data = null; + }; + + RadarView.type = 'radar'; + return RadarView; + }(ChartView); + + var RadarSeriesModel = function (_super) { + __extends(RadarSeriesModel, _super); + + function RadarSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = RadarSeriesModel.type; + _this.useColorPaletteOnData = true; + _this.hasSymbolVisual = true; + return _this; + } + + RadarSeriesModel.prototype.init = function (option) { + _super.prototype.init.apply(this, arguments); + + this.legendVisualProvider = new LegendVisualProvider(bind(this.getData, this), bind(this.getRawData, this)); + }; + + RadarSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createListSimply(this, { + generateCoord: 'indicator_', + generateCoordCount: Infinity + }); + }; + + RadarSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + var data = this.getData(); + var coordSys = this.coordinateSystem; + var indicatorAxes = coordSys.getIndicatorAxes(); + var name = this.getData().getName(dataIndex); + var nameToDisplay = name === '' ? this.name : name; + var markerColor = retrieveVisualColorForTooltipMarker(this, dataIndex); + return createTooltipMarkup('section', { + header: nameToDisplay, + sortBlocks: true, + blocks: map(indicatorAxes, function (axis) { + var val = data.get(data.mapDimension(axis.dim), dataIndex); + return createTooltipMarkup('nameValue', { + markerType: 'subItem', + markerColor: markerColor, + name: axis.name, + value: val, + sortParam: val + }); + }) + }); + }; + + RadarSeriesModel.prototype.getTooltipPosition = function (dataIndex) { + if (dataIndex != null) { + var data_1 = this.getData(); + var coordSys = this.coordinateSystem; + var values = data_1.getValues(map(coordSys.dimensions, function (dim) { + return data_1.mapDimension(dim); + }), dataIndex); + + for (var i = 0, len = values.length; i < len; i++) { + if (!isNaN(values[i])) { + var indicatorAxes = coordSys.getIndicatorAxes(); + return coordSys.coordToPoint(indicatorAxes[i].dataToCoord(values[i]), i); + } + } + } + }; + + RadarSeriesModel.type = 'series.radar'; + RadarSeriesModel.dependencies = ['radar']; + RadarSeriesModel.defaultOption = { + zlevel: 0, + z: 2, + coordinateSystem: 'radar', + legendHoverLink: true, + radarIndex: 0, + lineStyle: { + width: 2, + type: 'solid' + }, + label: { + position: 'top' + }, + symbol: 'emptyCircle', + symbolSize: 4 + }; + return RadarSeriesModel; + }(SeriesModel); + + var valueAxisDefault = axisDefault.value; + + function defaultsShow(opt, show) { + return defaults({ + show: show + }, opt); + } + + var RadarModel = function (_super) { + __extends(RadarModel, _super); + + function RadarModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = RadarModel.type; + return _this; + } + + RadarModel.prototype.optionUpdated = function () { + var boundaryGap = this.get('boundaryGap'); + var splitNumber = this.get('splitNumber'); + var scale = this.get('scale'); + var axisLine = this.get('axisLine'); + var axisTick = this.get('axisTick'); + var axisLabel = this.get('axisLabel'); + var nameTextStyle = this.get('axisName'); + var showName = this.get(['axisName', 'show']); + var nameFormatter = this.get(['axisName', 'formatter']); + var nameGap = this.get('axisNameGap'); + var triggerEvent = this.get('triggerEvent'); + var indicatorModels = map(this.get('indicator') || [], function (indicatorOpt) { + if (indicatorOpt.max != null && indicatorOpt.max > 0 && !indicatorOpt.min) { + indicatorOpt.min = 0; + } else if (indicatorOpt.min != null && indicatorOpt.min < 0 && !indicatorOpt.max) { + indicatorOpt.max = 0; + } + + var iNameTextStyle = nameTextStyle; + + if (indicatorOpt.color != null) { + iNameTextStyle = defaults({ + color: indicatorOpt.color + }, nameTextStyle); + } + + var innerIndicatorOpt = merge(clone(indicatorOpt), { + boundaryGap: boundaryGap, + splitNumber: splitNumber, + scale: scale, + axisLine: axisLine, + axisTick: axisTick, + axisLabel: axisLabel, + name: indicatorOpt.text, + nameLocation: 'end', + nameGap: nameGap, + nameTextStyle: iNameTextStyle, + triggerEvent: triggerEvent + }, false); + + if (!showName) { + innerIndicatorOpt.name = ''; + } + + if (typeof nameFormatter === 'string') { + var indName = innerIndicatorOpt.name; + innerIndicatorOpt.name = nameFormatter.replace('{value}', indName != null ? indName : ''); + } else if (typeof nameFormatter === 'function') { + innerIndicatorOpt.name = nameFormatter(innerIndicatorOpt.name, innerIndicatorOpt); + } + + var model = new Model(innerIndicatorOpt, null, this.ecModel); + mixin(model, AxisModelCommonMixin.prototype); + model.mainType = 'radar'; + model.componentIndex = this.componentIndex; + return model; + }, this); + this._indicatorModels = indicatorModels; + }; + + RadarModel.prototype.getIndicatorModels = function () { + return this._indicatorModels; + }; + + RadarModel.type = 'radar'; + RadarModel.defaultOption = { + zlevel: 0, + z: 0, + center: ['50%', '50%'], + radius: '75%', + startAngle: 90, + axisName: { + show: true + }, + boundaryGap: [0, 0], + splitNumber: 5, + axisNameGap: 15, + scale: false, + shape: 'polygon', + axisLine: merge({ + lineStyle: { + color: '#bbb' + } + }, valueAxisDefault.axisLine), + axisLabel: defaultsShow(valueAxisDefault.axisLabel, false), + axisTick: defaultsShow(valueAxisDefault.axisTick, false), + splitLine: defaultsShow(valueAxisDefault.splitLine, true), + splitArea: defaultsShow(valueAxisDefault.splitArea, true), + indicator: [] + }; + return RadarModel; + }(ComponentModel); + + var axisBuilderAttrs$1 = ['axisLine', 'axisTickLabel', 'axisName']; + + var RadarView$1 = function (_super) { + __extends(RadarView, _super); + + function RadarView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = RadarView.type; + return _this; + } + + RadarView.prototype.render = function (radarModel, ecModel, api) { + var group = this.group; + group.removeAll(); + + this._buildAxes(radarModel); + + this._buildSplitLineAndArea(radarModel); + }; + + RadarView.prototype._buildAxes = function (radarModel) { + var radar = radarModel.coordinateSystem; + var indicatorAxes = radar.getIndicatorAxes(); + var axisBuilders = map(indicatorAxes, function (indicatorAxis) { + var axisBuilder = new AxisBuilder(indicatorAxis.model, { + position: [radar.cx, radar.cy], + rotation: indicatorAxis.angle, + labelDirection: -1, + tickDirection: -1, + nameDirection: 1 + }); + return axisBuilder; + }); + each(axisBuilders, function (axisBuilder) { + each(axisBuilderAttrs$1, axisBuilder.add, axisBuilder); + this.group.add(axisBuilder.getGroup()); + }, this); + }; + + RadarView.prototype._buildSplitLineAndArea = function (radarModel) { + var radar = radarModel.coordinateSystem; + var indicatorAxes = radar.getIndicatorAxes(); + + if (!indicatorAxes.length) { + return; + } + + var shape = radarModel.get('shape'); + var splitLineModel = radarModel.getModel('splitLine'); + var splitAreaModel = radarModel.getModel('splitArea'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var showSplitLine = splitLineModel.get('show'); + var showSplitArea = splitAreaModel.get('show'); + var splitLineColors = lineStyleModel.get('color'); + var splitAreaColors = areaStyleModel.get('color'); + var splitLineColorsArr = isArray(splitLineColors) ? splitLineColors : [splitLineColors]; + var splitAreaColorsArr = isArray(splitAreaColors) ? splitAreaColors : [splitAreaColors]; + var splitLines = []; + var splitAreas = []; + + function getColorIndex(areaOrLine, areaOrLineColorList, idx) { + var colorIndex = idx % areaOrLineColorList.length; + areaOrLine[colorIndex] = areaOrLine[colorIndex] || []; + return colorIndex; + } + + if (shape === 'circle') { + var ticksRadius = indicatorAxes[0].getTicksCoords(); + var cx = radar.cx; + var cy = radar.cy; + + for (var i = 0; i < ticksRadius.length; i++) { + if (showSplitLine) { + var colorIndex = getColorIndex(splitLines, splitLineColorsArr, i); + splitLines[colorIndex].push(new Circle({ + shape: { + cx: cx, + cy: cy, + r: ticksRadius[i].coord + } + })); + } + + if (showSplitArea && i < ticksRadius.length - 1) { + var colorIndex = getColorIndex(splitAreas, splitAreaColorsArr, i); + splitAreas[colorIndex].push(new Ring({ + shape: { + cx: cx, + cy: cy, + r0: ticksRadius[i].coord, + r: ticksRadius[i + 1].coord + } + })); + } + } + } else { + var realSplitNumber_1; + var axesTicksPoints = map(indicatorAxes, function (indicatorAxis, idx) { + var ticksCoords = indicatorAxis.getTicksCoords(); + realSplitNumber_1 = realSplitNumber_1 == null ? ticksCoords.length - 1 : Math.min(ticksCoords.length - 1, realSplitNumber_1); + return map(ticksCoords, function (tickCoord) { + return radar.coordToPoint(tickCoord.coord, idx); + }); + }); + var prevPoints = []; + + for (var i = 0; i <= realSplitNumber_1; i++) { + var points = []; + + for (var j = 0; j < indicatorAxes.length; j++) { + points.push(axesTicksPoints[j][i]); + } + + if (points[0]) { + points.push(points[0].slice()); + } else { + if ("development" !== 'production') { + console.error('Can\'t draw value axis ' + i); + } + } + + if (showSplitLine) { + var colorIndex = getColorIndex(splitLines, splitLineColorsArr, i); + splitLines[colorIndex].push(new Polyline({ + shape: { + points: points + } + })); + } + + if (showSplitArea && prevPoints) { + var colorIndex = getColorIndex(splitAreas, splitAreaColorsArr, i - 1); + splitAreas[colorIndex].push(new Polygon({ + shape: { + points: points.concat(prevPoints) + } + })); + } + + prevPoints = points.slice().reverse(); + } + } + + var lineStyle = lineStyleModel.getLineStyle(); + var areaStyle = areaStyleModel.getAreaStyle(); + each(splitAreas, function (splitAreas, idx) { + this.group.add(mergePath$1(splitAreas, { + style: defaults({ + stroke: 'none', + fill: splitAreaColorsArr[idx % splitAreaColorsArr.length] + }, areaStyle), + silent: true + })); + }, this); + each(splitLines, function (splitLines, idx) { + this.group.add(mergePath$1(splitLines, { + style: defaults({ + fill: 'none', + stroke: splitLineColorsArr[idx % splitLineColorsArr.length] + }, lineStyle), + silent: true + })); + }, this); + }; + + RadarView.type = 'radar'; + return RadarView; + }(ComponentView); + + var IndicatorAxis = function (_super) { + __extends(IndicatorAxis, _super); + + function IndicatorAxis(dim, scale, radiusExtent) { + var _this = _super.call(this, dim, scale, radiusExtent) || this; + + _this.type = 'value'; + _this.angle = 0; + _this.name = ''; + return _this; + } + + return IndicatorAxis; + }(Axis); + + var Radar = function () { + function Radar(radarModel, ecModel, api) { + this.dimensions = []; + this._model = radarModel; + this._indicatorAxes = map(radarModel.getIndicatorModels(), function (indicatorModel, idx) { + var dim = 'indicator_' + idx; + var indicatorAxis = new IndicatorAxis(dim, new IntervalScale()); + indicatorAxis.name = indicatorModel.get('name'); + indicatorAxis.model = indicatorModel; + indicatorModel.axis = indicatorAxis; + this.dimensions.push(dim); + return indicatorAxis; + }, this); + this.resize(radarModel, api); + } + + Radar.prototype.getIndicatorAxes = function () { + return this._indicatorAxes; + }; + + Radar.prototype.dataToPoint = function (value, indicatorIndex) { + var indicatorAxis = this._indicatorAxes[indicatorIndex]; + return this.coordToPoint(indicatorAxis.dataToCoord(value), indicatorIndex); + }; + + Radar.prototype.coordToPoint = function (coord, indicatorIndex) { + var indicatorAxis = this._indicatorAxes[indicatorIndex]; + var angle = indicatorAxis.angle; + var x = this.cx + coord * Math.cos(angle); + var y = this.cy - coord * Math.sin(angle); + return [x, y]; + }; + + Radar.prototype.pointToData = function (pt) { + var dx = pt[0] - this.cx; + var dy = pt[1] - this.cy; + var radius = Math.sqrt(dx * dx + dy * dy); + dx /= radius; + dy /= radius; + var radian = Math.atan2(-dy, dx); + var minRadianDiff = Infinity; + var closestAxis; + var closestAxisIdx = -1; + + for (var i = 0; i < this._indicatorAxes.length; i++) { + var indicatorAxis = this._indicatorAxes[i]; + var diff = Math.abs(radian - indicatorAxis.angle); + + if (diff < minRadianDiff) { + closestAxis = indicatorAxis; + closestAxisIdx = i; + minRadianDiff = diff; + } + } + + return [closestAxisIdx, +(closestAxis && closestAxis.coordToData(radius))]; + }; + + Radar.prototype.resize = function (radarModel, api) { + var center = radarModel.get('center'); + var viewWidth = api.getWidth(); + var viewHeight = api.getHeight(); + var viewSize = Math.min(viewWidth, viewHeight) / 2; + this.cx = parsePercent$1(center[0], viewWidth); + this.cy = parsePercent$1(center[1], viewHeight); + this.startAngle = radarModel.get('startAngle') * Math.PI / 180; + var radius = radarModel.get('radius'); + + if (typeof radius === 'string' || typeof radius === 'number') { + radius = [0, radius]; + } + + this.r0 = parsePercent$1(radius[0], viewSize); + this.r = parsePercent$1(radius[1], viewSize); + each(this._indicatorAxes, function (indicatorAxis, idx) { + indicatorAxis.setExtent(this.r0, this.r); + var angle = this.startAngle + idx * Math.PI * 2 / this._indicatorAxes.length; + angle = Math.atan2(Math.sin(angle), Math.cos(angle)); + indicatorAxis.angle = angle; + }, this); + }; + + Radar.prototype.update = function (ecModel, api) { + var indicatorAxes = this._indicatorAxes; + var radarModel = this._model; + each(indicatorAxes, function (indicatorAxis) { + indicatorAxis.scale.setExtent(Infinity, -Infinity); + }); + ecModel.eachSeriesByType('radar', function (radarSeries, idx) { + if (radarSeries.get('coordinateSystem') !== 'radar' || ecModel.getComponent('radar', radarSeries.get('radarIndex')) !== radarModel) { + return; + } + + var data = radarSeries.getData(); + each(indicatorAxes, function (indicatorAxis) { + indicatorAxis.scale.unionExtentFromData(data, data.mapDimension(indicatorAxis.dim)); + }); + }, this); + var splitNumber = radarModel.get('splitNumber'); + + function increaseInterval(interval) { + var exp10 = Math.pow(10, Math.floor(Math.log(interval) / Math.LN10)); + var f = interval / exp10; + + if (f === 2) { + f = 5; + } else { + f *= 2; + } + + return f * exp10; + } + + each(indicatorAxes, function (indicatorAxis, idx) { + var rawExtent = getScaleExtent(indicatorAxis.scale, indicatorAxis.model).extent; + niceScaleExtent(indicatorAxis.scale, indicatorAxis.model); + var axisModel = indicatorAxis.model; + var scale = indicatorAxis.scale; + var fixedMin = parseAxisModelMinMax(scale, axisModel.get('min', true)); + var fixedMax = parseAxisModelMinMax(scale, axisModel.get('max', true)); + var interval = scale.getInterval(); + + if (fixedMin != null && fixedMax != null) { + scale.setExtent(+fixedMin, +fixedMax); + scale.setInterval((fixedMax - fixedMin) / splitNumber); + } else if (fixedMin != null) { + var max = void 0; + + do { + max = fixedMin + interval * splitNumber; + scale.setExtent(+fixedMin, max); + scale.setInterval(interval); + interval = increaseInterval(interval); + } while (max < rawExtent[1] && isFinite(max) && isFinite(rawExtent[1])); + } else if (fixedMax != null) { + var min = void 0; + + do { + min = fixedMax - interval * splitNumber; + scale.setExtent(min, +fixedMax); + scale.setInterval(interval); + interval = increaseInterval(interval); + } while (min > rawExtent[0] && isFinite(min) && isFinite(rawExtent[0])); + } else { + var nicedSplitNumber = scale.getTicks().length - 1; + + if (nicedSplitNumber > splitNumber) { + interval = increaseInterval(interval); + } + + var max = Math.ceil(rawExtent[1] / interval) * interval; + var min = round(max - interval * splitNumber); + scale.setExtent(min, max); + scale.setInterval(interval); + } + }); + }; + + Radar.prototype.convertToPixel = function (ecModel, finder, value) { + console.warn('Not implemented.'); + return null; + }; + + Radar.prototype.convertFromPixel = function (ecModel, finder, pixel) { + console.warn('Not implemented.'); + return null; + }; + + Radar.prototype.containPoint = function (point) { + console.warn('Not implemented.'); + return false; + }; + + Radar.create = function (ecModel, api) { + var radarList = []; + ecModel.eachComponent('radar', function (radarModel) { + var radar = new Radar(radarModel, ecModel, api); + radarList.push(radar); + radarModel.coordinateSystem = radar; + }); + ecModel.eachSeriesByType('radar', function (radarSeries) { + if (radarSeries.get('coordinateSystem') === 'radar') { + radarSeries.coordinateSystem = radarList[radarSeries.get('radarIndex') || 0]; + } + }); + return radarList; + }; + + Radar.dimensions = []; + return Radar; + }(); + + function install$7(registers) { + registers.registerCoordinateSystem('radar', Radar); + registers.registerComponentModel(RadarModel); + registers.registerComponentView(RadarView$1); + } + + function install$8(registers) { + use(install$7); + registers.registerChartView(RadarView); + registers.registerSeriesModel(RadarSeriesModel); + registers.registerLayout(radarLayout); + registers.registerProcessor(dataFilter('radar')); + registers.registerPreprocessor(radarBackwardCompat); + } + + var ATTR = '\0_ec_interaction_mutex'; + function take(zr, resourceKey, userKey) { + var store = getStore(zr); + store[resourceKey] = userKey; + } + function release(zr, resourceKey, userKey) { + var store = getStore(zr); + var uKey = store[resourceKey]; + + if (uKey === userKey) { + store[resourceKey] = null; + } + } + function isTaken(zr, resourceKey) { + return !!getStore(zr)[resourceKey]; + } + + function getStore(zr) { + return zr[ATTR] || (zr[ATTR] = {}); + } + + registerAction({ + type: 'takeGlobalCursor', + event: 'globalCursorTaken', + update: 'update' + }, function () {}); + + var RoamController = function (_super) { + __extends(RoamController, _super); + + function RoamController(zr) { + var _this = _super.call(this) || this; + + _this._zr = zr; + var mousedownHandler = bind(_this._mousedownHandler, _this); + var mousemoveHandler = bind(_this._mousemoveHandler, _this); + var mouseupHandler = bind(_this._mouseupHandler, _this); + var mousewheelHandler = bind(_this._mousewheelHandler, _this); + var pinchHandler = bind(_this._pinchHandler, _this); + + _this.enable = function (controlType, opt) { + this.disable(); + this._opt = defaults(clone(opt) || {}, { + zoomOnMouseWheel: true, + moveOnMouseMove: true, + moveOnMouseWheel: false, + preventDefaultMouseMove: true + }); + + if (controlType == null) { + controlType = true; + } + + if (controlType === true || controlType === 'move' || controlType === 'pan') { + zr.on('mousedown', mousedownHandler); + zr.on('mousemove', mousemoveHandler); + zr.on('mouseup', mouseupHandler); + } + + if (controlType === true || controlType === 'scale' || controlType === 'zoom') { + zr.on('mousewheel', mousewheelHandler); + zr.on('pinch', pinchHandler); + } + }; + + _this.disable = function () { + zr.off('mousedown', mousedownHandler); + zr.off('mousemove', mousemoveHandler); + zr.off('mouseup', mouseupHandler); + zr.off('mousewheel', mousewheelHandler); + zr.off('pinch', pinchHandler); + }; + + return _this; + } + + RoamController.prototype.isDragging = function () { + return this._dragging; + }; + + RoamController.prototype.isPinching = function () { + return this._pinching; + }; + + RoamController.prototype.setPointerChecker = function (pointerChecker) { + this.pointerChecker = pointerChecker; + }; + + RoamController.prototype.dispose = function () { + this.disable(); + }; + + RoamController.prototype._mousedownHandler = function (e) { + if (isMiddleOrRightButtonOnMouseUpDown(e) || e.target && e.target.draggable) { + return; + } + + var x = e.offsetX; + var y = e.offsetY; + + if (this.pointerChecker && this.pointerChecker(e, x, y)) { + this._x = x; + this._y = y; + this._dragging = true; + } + }; + + RoamController.prototype._mousemoveHandler = function (e) { + if (!this._dragging || !isAvailableBehavior('moveOnMouseMove', e, this._opt) || e.gestureEvent === 'pinch' || isTaken(this._zr, 'globalPan')) { + return; + } + + var x = e.offsetX; + var y = e.offsetY; + var oldX = this._x; + var oldY = this._y; + var dx = x - oldX; + var dy = y - oldY; + this._x = x; + this._y = y; + this._opt.preventDefaultMouseMove && stop(e.event); + trigger(this, 'pan', 'moveOnMouseMove', e, { + dx: dx, + dy: dy, + oldX: oldX, + oldY: oldY, + newX: x, + newY: y, + isAvailableBehavior: null + }); + }; + + RoamController.prototype._mouseupHandler = function (e) { + if (!isMiddleOrRightButtonOnMouseUpDown(e)) { + this._dragging = false; + } + }; + + RoamController.prototype._mousewheelHandler = function (e) { + var shouldZoom = isAvailableBehavior('zoomOnMouseWheel', e, this._opt); + var shouldMove = isAvailableBehavior('moveOnMouseWheel', e, this._opt); + var wheelDelta = e.wheelDelta; + var absWheelDeltaDelta = Math.abs(wheelDelta); + var originX = e.offsetX; + var originY = e.offsetY; + + if (wheelDelta === 0 || !shouldZoom && !shouldMove) { + return; + } + + if (shouldZoom) { + var factor = absWheelDeltaDelta > 3 ? 1.4 : absWheelDeltaDelta > 1 ? 1.2 : 1.1; + var scale = wheelDelta > 0 ? factor : 1 / factor; + checkPointerAndTrigger(this, 'zoom', 'zoomOnMouseWheel', e, { + scale: scale, + originX: originX, + originY: originY, + isAvailableBehavior: null + }); + } + + if (shouldMove) { + var absDelta = Math.abs(wheelDelta); + var scrollDelta = (wheelDelta > 0 ? 1 : -1) * (absDelta > 3 ? 0.4 : absDelta > 1 ? 0.15 : 0.05); + checkPointerAndTrigger(this, 'scrollMove', 'moveOnMouseWheel', e, { + scrollDelta: scrollDelta, + originX: originX, + originY: originY, + isAvailableBehavior: null + }); + } + }; + + RoamController.prototype._pinchHandler = function (e) { + if (isTaken(this._zr, 'globalPan')) { + return; + } + + var scale = e.pinchScale > 1 ? 1.1 : 1 / 1.1; + checkPointerAndTrigger(this, 'zoom', null, e, { + scale: scale, + originX: e.pinchX, + originY: e.pinchY, + isAvailableBehavior: null + }); + }; + + return RoamController; + }(Eventful); + + function checkPointerAndTrigger(controller, eventName, behaviorToCheck, e, contollerEvent) { + if (controller.pointerChecker && controller.pointerChecker(e, contollerEvent.originX, contollerEvent.originY)) { + stop(e.event); + trigger(controller, eventName, behaviorToCheck, e, contollerEvent); + } + } + + function trigger(controller, eventName, behaviorToCheck, e, contollerEvent) { + contollerEvent.isAvailableBehavior = bind(isAvailableBehavior, null, behaviorToCheck, e); + controller.trigger(eventName, contollerEvent); + } + + function isAvailableBehavior(behaviorToCheck, e, settings) { + var setting = settings[behaviorToCheck]; + return !behaviorToCheck || setting && (!isString(setting) || e.event[setting + 'Key']); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function updateViewOnPan(controllerHost, dx, dy) { + var target = controllerHost.target; + target.x += dx; + target.y += dy; + target.dirty(); + } + function updateViewOnZoom(controllerHost, zoomDelta, zoomX, zoomY) { + var target = controllerHost.target; + var zoomLimit = controllerHost.zoomLimit; + var newZoom = controllerHost.zoom = controllerHost.zoom || 1; + newZoom *= zoomDelta; + + if (zoomLimit) { + var zoomMin = zoomLimit.min || 0; + var zoomMax = zoomLimit.max || Infinity; + newZoom = Math.max(Math.min(zoomMax, newZoom), zoomMin); + } + + var zoomScale = newZoom / controllerHost.zoom; + controllerHost.zoom = newZoom; + target.x -= (zoomX - target.x) * (zoomScale - 1); + target.y -= (zoomY - target.y) * (zoomScale - 1); + target.scaleX *= zoomScale; + target.scaleY *= zoomScale; + target.dirty(); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var IRRELEVANT_EXCLUDES = { + 'axisPointer': 1, + 'tooltip': 1, + 'brush': 1 + }; + function onIrrelevantElement(e, api, targetCoordSysModel) { + var model = api.getComponentByElement(e.topTarget); + var coordSys = model && model.coordinateSystem; + return model && model !== targetCoordSysModel && !IRRELEVANT_EXCLUDES.hasOwnProperty(model.mainType) && coordSys && coordSys.model !== targetCoordSysModel; + } + + var geoCoord = [126, 25]; + var points$1 = [[[0, 3.5], [7, 11.2], [15, 11.9], [30, 7], [42, 0.7], [52, 0.7], [56, 7.7], [59, 0.7], [64, 0.7], [64, 0], [5, 0], [0, 3.5]], [[13, 16.1], [19, 14.7], [16, 21.7], [11, 23.1], [13, 16.1]], [[12, 32.2], [14, 38.5], [15, 38.5], [13, 32.2], [12, 32.2]], [[16, 47.6], [12, 53.2], [13, 53.2], [18, 47.6], [16, 47.6]], [[6, 64.4], [8, 70], [9, 70], [8, 64.4], [6, 64.4]], [[23, 82.6], [29, 79.8], [30, 79.8], [25, 82.6], [23, 82.6]], [[37, 70.7], [43, 62.3], [44, 62.3], [39, 70.7], [37, 70.7]], [[48, 51.1], [51, 45.5], [53, 45.5], [50, 51.1], [48, 51.1]], [[51, 35], [51, 28.7], [53, 28.7], [53, 35], [51, 35]], [[52, 22.4], [55, 17.5], [56, 17.5], [53, 22.4], [52, 22.4]], [[58, 12.6], [62, 7], [63, 7], [60, 12.6], [58, 12.6]], [[0, 3.5], [0, 93.1], [64, 93.1], [64, 0], [63, 0], [63, 92.4], [1, 92.4], [1, 3.5], [0, 3.5]]]; + + for (var i = 0; i < points$1.length; i++) { + for (var k = 0; k < points$1[i].length; k++) { + points$1[i][k][0] /= 10.5; + points$1[i][k][1] /= -10.5 / 0.75; + points$1[i][k][0] += geoCoord[0]; + points$1[i][k][1] += geoCoord[1]; + } + } + + function fixNanhai(mapType, regions) { + if (mapType === 'china') { + regions.push(new Region('南海诸岛', map(points$1, function (exterior) { + return { + type: 'polygon', + exterior: exterior + }; + }), geoCoord)); + } + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var coordsOffsetMap = { + '南海诸岛': [32, 80], + '广东': [0, -10], + '香港': [10, 5], + '澳门': [-10, 10], + '天津': [5, 5] + }; + function fixTextCoords(mapType, region) { + if (mapType === 'china') { + var coordFix = coordsOffsetMap[region.name]; + + if (coordFix) { + var cp = region.center; + cp[0] += coordFix[0] / 10.5; + cp[1] += -coordFix[1] / (10.5 / 0.75); + } + } + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var geoCoordMap = { + 'Russia': [100, 60], + 'United States': [-99, 38], + 'United States of America': [-99, 38] + }; + function fixGeoCoords(mapType, region) { + if (mapType === 'world') { + var geoCoord = geoCoordMap[region.name]; + + if (geoCoord) { + var cp = region.center; + cp[0] = geoCoord[0]; + cp[1] = geoCoord[1]; + } + } + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var points$2 = [[[123.45165252685547, 25.73527164402261], [123.49731445312499, 25.73527164402261], [123.49731445312499, 25.750734064600884], [123.45165252685547, 25.750734064600884], [123.45165252685547, 25.73527164402261]]]; + function fixDiaoyuIsland(mapType, region) { + if (mapType === 'china' && region.name === '台湾') { + region.geometries.push({ + type: 'polygon', + exterior: points$2[0] + }); + } + } + + var inner$6 = makeInner(); + var geoJSONLoader = { + load: function (mapName, mapRecord, nameProperty) { + var parsed = inner$6(mapRecord).parsed; + + if (parsed) { + return parsed; + } + + var specialAreas = mapRecord.specialAreas || {}; + var geoJSON = mapRecord.geoJSON; + var regions; + + try { + regions = geoJSON ? parseGeoJSON(geoJSON, nameProperty) : []; + } catch (e) { + throw new Error('Invalid geoJson format\n' + e.message); + } + + fixNanhai(mapName, regions); + each(regions, function (region) { + var regionName = region.name; + fixTextCoords(mapName, region); + fixGeoCoords(mapName, region); + fixDiaoyuIsland(mapName, region); + var specialArea = specialAreas[regionName]; + + if (specialArea) { + region.transformTo(specialArea.left, specialArea.top, specialArea.width, specialArea.height); + } + }); + return inner$6(mapRecord).parsed = { + regions: regions, + boundingRect: getBoundingRect$1(regions) + }; + } + }; + + function getBoundingRect$1(regions) { + var rect; + + for (var i = 0; i < regions.length; i++) { + var regionRect = regions[i].getBoundingRect(); + rect = rect || regionRect.clone(); + rect.union(regionRect); + } + + return rect; + } + + var DILIMITER_REG = /[\s,]+/; + var nodeParsers; + var SVGParser = (function () { + function SVGParser() { + this._defs = {}; + this._root = null; + this._isDefine = false; + this._isText = false; + } + SVGParser.prototype.parse = function (xml, opt) { + opt = opt || {}; + var svg = parseXML(xml); + if (!svg) { + throw new Error('Illegal svg'); + } + var root = new Group(); + this._root = root; + var viewBox = svg.getAttribute('viewBox') || ''; + var width = parseFloat((svg.getAttribute('width') || opt.width)); + var height = parseFloat((svg.getAttribute('height') || opt.height)); + isNaN(width) && (width = null); + isNaN(height) && (height = null); + parseAttributes(svg, root, null, true); + var child = svg.firstChild; + while (child) { + this._parseNode(child, root); + child = child.nextSibling; + } + var viewBoxRect; + var viewBoxTransform; + if (viewBox) { + var viewBoxArr = trim(viewBox).split(DILIMITER_REG); + if (viewBoxArr.length >= 4) { + viewBoxRect = { + x: parseFloat((viewBoxArr[0] || 0)), + y: parseFloat((viewBoxArr[1] || 0)), + width: parseFloat(viewBoxArr[2]), + height: parseFloat(viewBoxArr[3]) + }; + } + } + if (viewBoxRect && width != null && height != null) { + viewBoxTransform = makeViewBoxTransform(viewBoxRect, width, height); + if (!opt.ignoreViewBox) { + var elRoot = root; + root = new Group(); + root.add(elRoot); + elRoot.scaleX = elRoot.scaleY = viewBoxTransform.scale; + elRoot.x = viewBoxTransform.x; + elRoot.y = viewBoxTransform.y; + } + } + if (!opt.ignoreRootClip && width != null && height != null) { + root.setClipPath(new Rect({ + shape: { x: 0, y: 0, width: width, height: height } + })); + } + return { + root: root, + width: width, + height: height, + viewBoxRect: viewBoxRect, + viewBoxTransform: viewBoxTransform + }; + }; + SVGParser.prototype._parseNode = function (xmlNode, parentGroup) { + var nodeName = xmlNode.nodeName.toLowerCase(); + if (nodeName === 'defs') { + this._isDefine = true; + } + else if (nodeName === 'text') { + this._isText = true; + } + var el; + if (this._isDefine) { + var parser = defineParsers[nodeName]; + if (parser) { + var def = parser.call(this, xmlNode); + var id = xmlNode.getAttribute('id'); + if (id) { + this._defs[id] = def; + } + } + } + else { + var parser = nodeParsers[nodeName]; + if (parser) { + el = parser.call(this, xmlNode, parentGroup); + parentGroup.add(el); + } + } + if (el) { + var child = xmlNode.firstChild; + while (child) { + if (child.nodeType === 1) { + this._parseNode(child, el); + } + if (child.nodeType === 3 && this._isText) { + this._parseText(child, el); + } + child = child.nextSibling; + } + } + if (nodeName === 'defs') { + this._isDefine = false; + } + else if (nodeName === 'text') { + this._isText = false; + } + }; + SVGParser.prototype._parseText = function (xmlNode, parentGroup) { + if (xmlNode.nodeType === 1) { + var dx = xmlNode.getAttribute('dx') || 0; + var dy = xmlNode.getAttribute('dy') || 0; + this._textX += parseFloat(dx); + this._textY += parseFloat(dy); + } + var text = new TSpan({ + style: { + text: xmlNode.textContent + }, + x: this._textX || 0, + y: this._textY || 0 + }); + inheritStyle(parentGroup, text); + parseAttributes(xmlNode, text, this._defs); + var textStyle = text.style; + var fontSize = textStyle.fontSize; + if (fontSize && fontSize < 9) { + textStyle.fontSize = 9; + text.scaleX *= fontSize / 9; + text.scaleY *= fontSize / 9; + } + var font = (textStyle.fontSize || textStyle.fontFamily) && [ + textStyle.fontStyle, + textStyle.fontWeight, + (textStyle.fontSize || 12) + 'px', + textStyle.fontFamily || 'sans-serif' + ].join(' '); + textStyle.font = font; + var rect = text.getBoundingRect(); + this._textX += rect.width; + parentGroup.add(text); + return text; + }; + SVGParser.internalField = (function () { + nodeParsers = { + 'g': function (xmlNode, parentGroup) { + var g = new Group(); + inheritStyle(parentGroup, g); + parseAttributes(xmlNode, g, this._defs); + return g; + }, + 'rect': function (xmlNode, parentGroup) { + var rect = new Rect(); + inheritStyle(parentGroup, rect); + parseAttributes(xmlNode, rect, this._defs); + rect.setShape({ + x: parseFloat(xmlNode.getAttribute('x') || '0'), + y: parseFloat(xmlNode.getAttribute('y') || '0'), + width: parseFloat(xmlNode.getAttribute('width') || '0'), + height: parseFloat(xmlNode.getAttribute('height') || '0') + }); + return rect; + }, + 'circle': function (xmlNode, parentGroup) { + var circle = new Circle(); + inheritStyle(parentGroup, circle); + parseAttributes(xmlNode, circle, this._defs); + circle.setShape({ + cx: parseFloat(xmlNode.getAttribute('cx') || '0'), + cy: parseFloat(xmlNode.getAttribute('cy') || '0'), + r: parseFloat(xmlNode.getAttribute('r') || '0') + }); + return circle; + }, + 'line': function (xmlNode, parentGroup) { + var line = new Line(); + inheritStyle(parentGroup, line); + parseAttributes(xmlNode, line, this._defs); + line.setShape({ + x1: parseFloat(xmlNode.getAttribute('x1') || '0'), + y1: parseFloat(xmlNode.getAttribute('y1') || '0'), + x2: parseFloat(xmlNode.getAttribute('x2') || '0'), + y2: parseFloat(xmlNode.getAttribute('y2') || '0') + }); + return line; + }, + 'ellipse': function (xmlNode, parentGroup) { + var ellipse = new Ellipse(); + inheritStyle(parentGroup, ellipse); + parseAttributes(xmlNode, ellipse, this._defs); + ellipse.setShape({ + cx: parseFloat(xmlNode.getAttribute('cx') || '0'), + cy: parseFloat(xmlNode.getAttribute('cy') || '0'), + rx: parseFloat(xmlNode.getAttribute('rx') || '0'), + ry: parseFloat(xmlNode.getAttribute('ry') || '0') + }); + return ellipse; + }, + 'polygon': function (xmlNode, parentGroup) { + var pointsStr = xmlNode.getAttribute('points'); + var pointsArr; + if (pointsStr) { + pointsArr = parsePoints(pointsStr); + } + var polygon = new Polygon({ + shape: { + points: pointsArr || [] + } + }); + inheritStyle(parentGroup, polygon); + parseAttributes(xmlNode, polygon, this._defs); + return polygon; + }, + 'polyline': function (xmlNode, parentGroup) { + var path = new Path(); + inheritStyle(parentGroup, path); + parseAttributes(xmlNode, path, this._defs); + var pointsStr = xmlNode.getAttribute('points'); + var pointsArr; + if (pointsStr) { + pointsArr = parsePoints(pointsStr); + } + var polyline = new Polyline({ + shape: { + points: pointsArr || [] + } + }); + return polyline; + }, + 'image': function (xmlNode, parentGroup) { + var img = new ZRImage(); + inheritStyle(parentGroup, img); + parseAttributes(xmlNode, img, this._defs); + img.setStyle({ + image: xmlNode.getAttribute('xlink:href'), + x: +xmlNode.getAttribute('x'), + y: +xmlNode.getAttribute('y'), + width: +xmlNode.getAttribute('width'), + height: +xmlNode.getAttribute('height') + }); + return img; + }, + 'text': function (xmlNode, parentGroup) { + var x = xmlNode.getAttribute('x') || '0'; + var y = xmlNode.getAttribute('y') || '0'; + var dx = xmlNode.getAttribute('dx') || '0'; + var dy = xmlNode.getAttribute('dy') || '0'; + this._textX = parseFloat(x) + parseFloat(dx); + this._textY = parseFloat(y) + parseFloat(dy); + var g = new Group(); + inheritStyle(parentGroup, g); + parseAttributes(xmlNode, g, this._defs); + return g; + }, + 'tspan': function (xmlNode, parentGroup) { + var x = xmlNode.getAttribute('x'); + var y = xmlNode.getAttribute('y'); + if (x != null) { + this._textX = parseFloat(x); + } + if (y != null) { + this._textY = parseFloat(y); + } + var dx = xmlNode.getAttribute('dx') || 0; + var dy = xmlNode.getAttribute('dy') || 0; + var g = new Group(); + inheritStyle(parentGroup, g); + parseAttributes(xmlNode, g, this._defs); + this._textX += dx; + this._textY += dy; + return g; + }, + 'path': function (xmlNode, parentGroup) { + var d = xmlNode.getAttribute('d') || ''; + var path = createFromString(d); + inheritStyle(parentGroup, path); + parseAttributes(xmlNode, path, this._defs); + return path; + } + }; + })(); + return SVGParser; + }()); + var defineParsers = { + 'lineargradient': function (xmlNode) { + var x1 = parseInt(xmlNode.getAttribute('x1') || '0', 10); + var y1 = parseInt(xmlNode.getAttribute('y1') || '0', 10); + var x2 = parseInt(xmlNode.getAttribute('x2') || '10', 10); + var y2 = parseInt(xmlNode.getAttribute('y2') || '0', 10); + var gradient = new LinearGradient(x1, y1, x2, y2); + _parseGradientColorStops(xmlNode, gradient); + return gradient; + } + }; + function _parseGradientColorStops(xmlNode, gradient) { + var stop = xmlNode.firstChild; + while (stop) { + if (stop.nodeType === 1) { + var offsetStr = stop.getAttribute('offset'); + var offset = void 0; + if (offsetStr.indexOf('%') > 0) { + offset = parseInt(offsetStr, 10) / 100; + } + else if (offsetStr) { + offset = parseFloat(offsetStr); + } + else { + offset = 0; + } + var stopColor = stop.getAttribute('stop-color') || '#000000'; + gradient.colorStops.push({ + offset: offset, + color: stopColor + }); + } + stop = stop.nextSibling; + } + } + function inheritStyle(parent, child) { + if (parent && parent.__inheritedStyle) { + if (!child.__inheritedStyle) { + child.__inheritedStyle = {}; + } + defaults(child.__inheritedStyle, parent.__inheritedStyle); + } + } + function parsePoints(pointsString) { + var list = trim(pointsString).split(DILIMITER_REG); + var points = []; + for (var i = 0; i < list.length; i += 2) { + var x = parseFloat(list[i]); + var y = parseFloat(list[i + 1]); + points.push([x, y]); + } + return points; + } + var attributesMap = { + 'fill': 'fill', + 'stroke': 'stroke', + 'stroke-width': 'lineWidth', + 'opacity': 'opacity', + 'fill-opacity': 'fillOpacity', + 'stroke-opacity': 'strokeOpacity', + 'stroke-dasharray': 'lineDash', + 'stroke-dashoffset': 'lineDashOffset', + 'stroke-linecap': 'lineCap', + 'stroke-linejoin': 'lineJoin', + 'stroke-miterlimit': 'miterLimit', + 'font-family': 'fontFamily', + 'font-size': 'fontSize', + 'font-style': 'fontStyle', + 'font-weight': 'fontWeight', + 'text-align': 'textAlign', + 'alignment-baseline': 'textBaseline' + }; + function parseAttributes(xmlNode, el, defs, onlyInlineStyle) { + var disp = el; + var zrStyle = disp.__inheritedStyle || {}; + if (xmlNode.nodeType === 1) { + parseTransformAttribute(xmlNode, el); + extend(zrStyle, parseStyleAttribute(xmlNode)); + if (!onlyInlineStyle) { + for (var svgAttrName in attributesMap) { + if (attributesMap.hasOwnProperty(svgAttrName)) { + var attrValue = xmlNode.getAttribute(svgAttrName); + if (attrValue != null) { + zrStyle[attributesMap[svgAttrName]] = attrValue; + } + } + } + } + } + disp.style = disp.style || {}; + zrStyle.fill != null && (disp.style.fill = getPaint(zrStyle.fill, defs)); + zrStyle.stroke != null && (disp.style.stroke = getPaint(zrStyle.stroke, defs)); + each([ + 'lineWidth', 'opacity', 'fillOpacity', 'strokeOpacity', 'miterLimit', 'fontSize' + ], function (propName) { + zrStyle[propName] != null && (disp.style[propName] = parseFloat(zrStyle[propName])); + }); + if (!zrStyle.textBaseline || zrStyle.textBaseline === 'auto') { + zrStyle.textBaseline = 'alphabetic'; + } + if (zrStyle.textBaseline === 'alphabetic') { + zrStyle.textBaseline = 'bottom'; + } + if (zrStyle.textAlign === 'start') { + zrStyle.textAlign = 'left'; + } + if (zrStyle.textAlign === 'end') { + zrStyle.textAlign = 'right'; + } + each(['lineDashOffset', 'lineCap', 'lineJoin', + 'fontWeight', 'fontFamily', 'fontStyle', 'textAlign', 'textBaseline' + ], function (propName) { + zrStyle[propName] != null && (disp.style[propName] = zrStyle[propName]); + }); + if (zrStyle.lineDash) { + disp.style.lineDash = map(trim(zrStyle.lineDash).split(DILIMITER_REG), function (str) { + return parseFloat(str); + }); + } + disp.__inheritedStyle = zrStyle; + } + var urlRegex = /url\(\s*#(.*?)\)/; + function getPaint(str, defs) { + var urlMatch = defs && str && str.match(urlRegex); + if (urlMatch) { + var url = trim(urlMatch[1]); + var def = defs[url]; + return def; + } + return str; + } + var transformRegex = /(translate|scale|rotate|skewX|skewY|matrix)\(([\-\s0-9\.e,]*)\)/g; + function parseTransformAttribute(xmlNode, node) { + var transform = xmlNode.getAttribute('transform'); + if (transform) { + transform = transform.replace(/,/g, ' '); + var transformOps_1 = []; + var m = null; + transform.replace(transformRegex, function (str, type, value) { + transformOps_1.push(type, value); + return ''; + }); + for (var i = transformOps_1.length - 1; i > 0; i -= 2) { + var value = transformOps_1[i]; + var type = transformOps_1[i - 1]; + var valueArr = void 0; + m = m || create$1(); + switch (type) { + case 'translate': + valueArr = trim(value).split(DILIMITER_REG); + translate(m, m, [parseFloat(valueArr[0]), parseFloat(valueArr[1] || '0')]); + break; + case 'scale': + valueArr = trim(value).split(DILIMITER_REG); + scale$1(m, m, [parseFloat(valueArr[0]), parseFloat(valueArr[1] || valueArr[0])]); + break; + case 'rotate': + valueArr = trim(value).split(DILIMITER_REG); + rotate(m, m, parseFloat(valueArr[0])); + break; + case 'skew': + valueArr = trim(value).split(DILIMITER_REG); + console.warn('Skew transform is not supported yet'); + break; + case 'matrix': + valueArr = trim(value).split(DILIMITER_REG); + m[0] = parseFloat(valueArr[0]); + m[1] = parseFloat(valueArr[1]); + m[2] = parseFloat(valueArr[2]); + m[3] = parseFloat(valueArr[3]); + m[4] = parseFloat(valueArr[4]); + m[5] = parseFloat(valueArr[5]); + break; + } + } + node.setLocalTransform(m); + } + } + var styleRegex = /([^\s:;]+)\s*:\s*([^:;]+)/g; + function parseStyleAttribute(xmlNode) { + var style = xmlNode.getAttribute('style'); + var result = {}; + if (!style) { + return result; + } + var styleList = {}; + styleRegex.lastIndex = 0; + var styleRegResult; + while ((styleRegResult = styleRegex.exec(style)) != null) { + styleList[styleRegResult[1]] = styleRegResult[2]; + } + for (var svgAttrName in attributesMap) { + if (attributesMap.hasOwnProperty(svgAttrName) && styleList[svgAttrName] != null) { + result[attributesMap[svgAttrName]] = styleList[svgAttrName]; + } + } + return result; + } + function makeViewBoxTransform(viewBoxRect, width, height) { + var scaleX = width / viewBoxRect.width; + var scaleY = height / viewBoxRect.height; + var scale = Math.min(scaleX, scaleY); + return { + scale: scale, + x: -(viewBoxRect.x + viewBoxRect.width / 2) * scale + width / 2, + y: -(viewBoxRect.y + viewBoxRect.height / 2) * scale + height / 2 + }; + } + function parseSVG(xml, opt) { + var parser = new SVGParser(); + return parser.parse(xml, opt); + } + + var inner$7 = makeInner(); + var geoSVGLoader = { + load: function (mapName, mapRecord) { + var originRoot = inner$7(mapRecord).originRoot; + + if (originRoot) { + return { + root: originRoot, + boundingRect: inner$7(mapRecord).boundingRect + }; + } + + var graphic = buildGraphic(mapRecord); + inner$7(mapRecord).originRoot = graphic.root; + inner$7(mapRecord).boundingRect = graphic.boundingRect; + return graphic; + }, + makeGraphic: function (mapName, mapRecord, hostKey) { + var field = inner$7(mapRecord); + var rootMap = field.rootMap || (field.rootMap = createHashMap()); + var root = rootMap.get(hostKey); + + if (root) { + return root; + } + + var originRoot = field.originRoot; + var boundingRect = field.boundingRect; + + if (!field.originRootHostKey) { + field.originRootHostKey = hostKey; + root = originRoot; + } else { + root = buildGraphic(mapRecord, boundingRect).root; + } + + return rootMap.set(hostKey, root); + }, + removeGraphic: function (mapName, mapRecord, hostKey) { + var field = inner$7(mapRecord); + var rootMap = field.rootMap; + rootMap && rootMap.removeKey(hostKey); + + if (hostKey === field.originRootHostKey) { + field.originRootHostKey = null; + } + } + }; + + function buildGraphic(mapRecord, boundingRect) { + var svgXML = mapRecord.svgXML; + var result; + var root; + + try { + result = svgXML && parseSVG(svgXML, { + ignoreViewBox: true, + ignoreRootClip: true + }) || {}; + root = result.root; + assert(root != null); + } catch (e) { + throw new Error('Invalid svg format\n' + e.message); + } + + var svgWidth = result.width; + var svgHeight = result.height; + var viewBoxRect = result.viewBoxRect; + + if (!boundingRect) { + boundingRect = svgWidth == null || svgHeight == null ? root.getBoundingRect() : new BoundingRect(0, 0, 0, 0); + + if (svgWidth != null) { + boundingRect.width = svgWidth; + } + + if (svgHeight != null) { + boundingRect.height = svgHeight; + } + } + + if (viewBoxRect) { + var viewBoxTransform = makeViewBoxTransform(viewBoxRect, boundingRect.width, boundingRect.height); + var elRoot = root; + root = new Group(); + root.add(elRoot); + elRoot.scaleX = elRoot.scaleY = viewBoxTransform.scale; + elRoot.x = viewBoxTransform.x; + elRoot.y = viewBoxTransform.y; + } + + root.setClipPath(new Rect({ + shape: boundingRect.plain() + })); + return { + root: root, + boundingRect: boundingRect + }; + } + + var loaders = { + geoJSON: geoJSONLoader, + svg: geoSVGLoader + }; + var geoSourceManager = { + load: function (mapName, nameMap, nameProperty) { + var regions = []; + var regionsMap = createHashMap(); + var nameCoordMap = createHashMap(); + var boundingRect; + var mapRecords = retrieveMap(mapName); + each(mapRecords, function (record) { + var singleSource = loaders[record.type].load(mapName, record, nameProperty); + each(singleSource.regions, function (region) { + var regionName = region.name; + + if (nameMap && nameMap.hasOwnProperty(regionName)) { + region = region.cloneShallow(regionName = nameMap[regionName]); + } + + regions.push(region); + regionsMap.set(regionName, region); + nameCoordMap.set(regionName, region.center); + }); + var rect = singleSource.boundingRect; + + if (rect) { + boundingRect ? boundingRect.union(rect) : boundingRect = rect.clone(); + } + }); + return { + regions: regions, + regionsMap: regionsMap, + nameCoordMap: nameCoordMap, + boundingRect: boundingRect || new BoundingRect(0, 0, 0, 0) + }; + }, + makeGraphic: function (mapName, hostKey) { + var mapRecords = retrieveMap(mapName); + var results = []; + each(mapRecords, function (record) { + var method = loaders[record.type].makeGraphic; + method && results.push(method(mapName, record, hostKey)); + }); + return results; + }, + removeGraphic: function (mapName, hostKey) { + var mapRecords = retrieveMap(mapName); + each(mapRecords, function (record) { + var method = loaders[record.type].makeGraphic; + method && method(mapName, record, hostKey); + }); + } + }; + + function mapNotExistsError(mapName) { + if ("development" !== 'production') { + console.error('Map ' + mapName + ' not exists. The GeoJSON of the map must be provided.'); + } + } + + function retrieveMap(mapName) { + var mapRecords = mapDataStorage.retrieveMap(mapName) || []; + + if ("development" !== 'production') { + if (!mapRecords.length) { + mapNotExistsError(mapName); + } + } + + return mapRecords; + } + + function getFixedItemStyle(model) { + var itemStyle = model.getItemStyle(); + var areaColor = model.get('areaColor'); + + if (areaColor != null) { + itemStyle.fill = areaColor; + } + + return itemStyle; + } + + var MapDraw = function () { + function MapDraw(api) { + var group = new Group(); + this.uid = getUID('ec_map_draw'); + this._controller = new RoamController(api.getZr()); + this._controllerHost = { + target: group + }; + this.group = group; + group.add(this._regionsGroup = new Group()); + group.add(this._backgroundGroup = new Group()); + } + + MapDraw.prototype.draw = function (mapOrGeoModel, ecModel, api, fromView, payload) { + var isGeo = mapOrGeoModel.mainType === 'geo'; + var data = mapOrGeoModel.getData && mapOrGeoModel.getData(); + isGeo && ecModel.eachComponent({ + mainType: 'series', + subType: 'map' + }, function (mapSeries) { + if (!data && mapSeries.getHostGeoModel() === mapOrGeoModel) { + data = mapSeries.getData(); + } + }); + var geo = mapOrGeoModel.coordinateSystem; + + this._updateBackground(geo); + + var regionsGroup = this._regionsGroup; + var group = this.group; + var transformInfo = geo.getTransformInfo(); + var isFirstDraw = !regionsGroup.childAt(0) || payload; + var targetScaleX; + var targetScaleY; + + if (isFirstDraw) { + group.transform = transformInfo.roamTransform; + group.decomposeTransform(); + group.dirty(); + } else { + var target = new Transformable(); + target.transform = transformInfo.roamTransform; + target.decomposeTransform(); + var props = { + scaleX: target.scaleX, + scaleY: target.scaleY, + x: target.x, + y: target.y + }; + targetScaleX = target.scaleX; + targetScaleY = target.scaleY; + updateProps(group, props, mapOrGeoModel); + } + + regionsGroup.removeAll(); + var nameMap = createHashMap(); + var isVisualEncodedByVisualMap = data && data.getVisual('visualMeta') && data.getVisual('visualMeta').length > 0; + each(geo.regions, function (region) { + var regionGroup = nameMap.get(region.name) || nameMap.set(region.name, new Group()); + var compoundPath = new CompoundPath({ + segmentIgnoreThreshold: 1, + shape: { + paths: [] + } + }); + regionGroup.add(compoundPath); + var regionModel = mapOrGeoModel.getRegionModel(region.name) || mapOrGeoModel; + var itemStyleModel = regionModel.getModel('itemStyle'); + var emphasisModel = regionModel.getModel('emphasis'); + var emphasisItemStyleModel = emphasisModel.getModel('itemStyle'); + var blurItemStyleModel = regionModel.getModel(['blur', 'itemStyle']); + var selectItemStyleModel = regionModel.getModel(['select', 'itemStyle']); + var itemStyle = getFixedItemStyle(itemStyleModel); + var emphasisItemStyle = getFixedItemStyle(emphasisItemStyleModel); + var blurItemStyle = getFixedItemStyle(blurItemStyleModel); + var selectItemStyle = getFixedItemStyle(selectItemStyleModel); + var dataIdx; + + if (data) { + dataIdx = data.indexOfName(region.name); + var style = data.getItemVisual(dataIdx, 'style'); + var decal = data.getItemVisual(dataIdx, 'decal'); + + if (isVisualEncodedByVisualMap && style.fill) { + itemStyle.fill = style.fill; + } + + if (decal) { + itemStyle.decal = createOrUpdatePatternFromDecal(decal, api); + } + } + + var sx = transformInfo.rawScaleX; + var sy = transformInfo.rawScaleY; + var offsetX = transformInfo.rawX; + var offsetY = transformInfo.rawY; + + var transformPoint = function (point) { + return [point[0] * sx + offsetX, point[1] * sy + offsetY]; + }; + + each(region.geometries, function (geometry) { + if (geometry.type !== 'polygon') { + return; + } + + var points = []; + + for (var i = 0; i < geometry.exterior.length; ++i) { + points.push(transformPoint(geometry.exterior[i])); + } + + compoundPath.shape.paths.push(new Polygon({ + segmentIgnoreThreshold: 1, + shape: { + points: points + } + })); + + for (var i = 0; i < (geometry.interiors ? geometry.interiors.length : 0); ++i) { + var interior = geometry.interiors[i]; + var points_1 = []; + + for (var j = 0; j < interior.length; ++j) { + points_1.push(transformPoint(interior[j])); + } + + compoundPath.shape.paths.push(new Polygon({ + segmentIgnoreThreshold: 1, + shape: { + points: points_1 + } + })); + } + }); + compoundPath.setStyle(itemStyle); + compoundPath.style.strokeNoScale = true; + compoundPath.culling = true; + compoundPath.ensureState('emphasis').style = emphasisItemStyle; + compoundPath.ensureState('blur').style = blurItemStyle; + compoundPath.ensureState('select').style = selectItemStyle; + var showLabel = false; + + for (var i = 0; i < DISPLAY_STATES.length; i++) { + var stateName = DISPLAY_STATES[i]; + + if (regionModel.get(stateName === 'normal' ? ['label', 'show'] : [stateName, 'label', 'show'])) { + showLabel = true; + break; + } + } + + var isDataNaN = data && isNaN(data.get(data.mapDimension('value'), dataIdx)); + var itemLayout = data && data.getItemLayout(dataIdx); + + if (isGeo || isDataNaN && showLabel || itemLayout && itemLayout.showLabel) { + var query = !isGeo ? dataIdx : region.name; + var labelFetcher = void 0; + + if (!data || dataIdx >= 0) { + labelFetcher = mapOrGeoModel; + } + + var centerPt = transformPoint(region.center); + var textEl = new ZRText({ + x: centerPt[0], + y: centerPt[1], + scaleX: 1 / group.scaleX, + scaleY: 1 / group.scaleY, + z2: 10, + silent: true + }); + setLabelStyle(textEl, getLabelStatesModels(regionModel), { + labelFetcher: labelFetcher, + labelDataIndex: query, + defaultText: region.name + }, { + normal: { + align: 'center', + verticalAlign: 'middle' + } + }); + compoundPath.setTextContent(textEl); + compoundPath.setTextConfig({ + local: true + }); + compoundPath.disableLabelAnimation = true; + + if (!isFirstDraw) { + updateProps(textEl, { + scaleX: 1 / targetScaleX, + scaleY: 1 / targetScaleY + }, mapOrGeoModel); + } + } + + if (data) { + data.setItemGraphicEl(dataIdx, regionGroup); + } else { + var regionModel_1 = mapOrGeoModel.getRegionModel(region.name); + getECData(compoundPath).eventData = { + componentType: 'geo', + componentIndex: mapOrGeoModel.componentIndex, + geoIndex: mapOrGeoModel.componentIndex, + name: region.name, + region: regionModel_1 && regionModel_1.option || {} + }; + } + + var groupRegions = regionGroup.__regions || (regionGroup.__regions = []); + groupRegions.push(region); + regionGroup.highDownSilentOnTouch = !!mapOrGeoModel.get('selectedMode'); + enableHoverEmphasis(regionGroup, emphasisModel.get('focus'), emphasisModel.get('blurScope')); + regionsGroup.add(regionGroup); + }); + + this._updateController(mapOrGeoModel, ecModel, api); + + this._updateMapSelectHandler(mapOrGeoModel, regionsGroup, api, fromView); + }; + + MapDraw.prototype.remove = function () { + this._regionsGroup.removeAll(); + + this._backgroundGroup.removeAll(); + + this._controller.dispose(); + + this._mapName && geoSourceManager.removeGraphic(this._mapName, this.uid); + this._mapName = null; + this._controllerHost = null; + }; + + MapDraw.prototype._updateBackground = function (geo) { + var mapName = geo.map; + + if (this._mapName !== mapName) { + each(geoSourceManager.makeGraphic(mapName, this.uid), function (root) { + this._backgroundGroup.add(root); + }, this); + } + + this._mapName = mapName; + }; + + MapDraw.prototype._updateController = function (mapOrGeoModel, ecModel, api) { + var geo = mapOrGeoModel.coordinateSystem; + var controller = this._controller; + var controllerHost = this._controllerHost; + controllerHost.zoomLimit = mapOrGeoModel.get('scaleLimit'); + controllerHost.zoom = geo.getZoom(); + controller.enable(mapOrGeoModel.get('roam') || false); + var mainType = mapOrGeoModel.mainType; + + function makeActionBase() { + var action = { + type: 'geoRoam', + componentType: mainType + }; + action[mainType + 'Id'] = mapOrGeoModel.id; + return action; + } + + controller.off('pan').on('pan', function (e) { + this._mouseDownFlag = false; + updateViewOnPan(controllerHost, e.dx, e.dy); + api.dispatchAction(extend(makeActionBase(), { + dx: e.dx, + dy: e.dy + })); + }, this); + controller.off('zoom').on('zoom', function (e) { + this._mouseDownFlag = false; + updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY); + api.dispatchAction(extend(makeActionBase(), { + zoom: e.scale, + originX: e.originX, + originY: e.originY + })); + var group = this.group; + + this._regionsGroup.traverse(function (el) { + var textContent = el.getTextContent(); + + if (textContent) { + textContent.scaleX = 1 / group.scaleX; + textContent.scaleY = 1 / group.scaleY; + textContent.markRedraw(); + } + }); + }, this); + controller.setPointerChecker(function (e, x, y) { + return geo.getViewRectAfterRoam().contain(x, y) && !onIrrelevantElement(e, api, mapOrGeoModel); + }); + }; + + MapDraw.prototype._updateMapSelectHandler = function (mapOrGeoModel, regionsGroup, api, fromView) { + var mapDraw = this; + regionsGroup.off('mousedown'); + + if (mapOrGeoModel.get('selectedMode')) { + regionsGroup.on('mousedown', function () { + mapDraw._mouseDownFlag = true; + }); + regionsGroup.on('click', function (e) { + if (!mapDraw._mouseDownFlag) { + return; + } + + mapDraw._mouseDownFlag = false; + }); + } + }; + + return MapDraw; + }(); + + var MapView = function (_super) { + __extends(MapView, _super); + + function MapView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MapView.type; + return _this; + } + + MapView.prototype.render = function (mapModel, ecModel, api, payload) { + if (payload && payload.type === 'mapToggleSelect' && payload.from === this.uid) { + return; + } + + var group = this.group; + group.removeAll(); + + if (mapModel.getHostGeoModel()) { + return; + } + + if (!(payload && payload.type === 'geoRoam' && payload.componentType === 'series' && payload.seriesId === mapModel.id)) { + if (mapModel.needsDrawMap) { + var mapDraw = this._mapDraw || new MapDraw(api); + group.add(mapDraw.group); + mapDraw.draw(mapModel, ecModel, api, this, payload); + this._mapDraw = mapDraw; + } else { + this._mapDraw && this._mapDraw.remove(); + this._mapDraw = null; + } + } else { + var mapDraw = this._mapDraw; + mapDraw && group.add(mapDraw.group); + } + + mapModel.get('showLegendSymbol') && ecModel.getComponent('legend') && this._renderSymbols(mapModel, ecModel, api); + }; + + MapView.prototype.remove = function () { + this._mapDraw && this._mapDraw.remove(); + this._mapDraw = null; + this.group.removeAll(); + }; + + MapView.prototype.dispose = function () { + this._mapDraw && this._mapDraw.remove(); + this._mapDraw = null; + }; + + MapView.prototype._renderSymbols = function (mapModel, ecModel, api) { + var originalData = mapModel.originalData; + var group = this.group; + originalData.each(originalData.mapDimension('value'), function (value, originalDataIndex) { + if (isNaN(value)) { + return; + } + + var layout = originalData.getItemLayout(originalDataIndex); + + if (!layout || !layout.point) { + return; + } + + var point = layout.point; + var offset = layout.offset; + var circle = new Circle({ + style: { + fill: mapModel.getData().getVisual('style').fill + }, + shape: { + cx: point[0] + offset * 9, + cy: point[1], + r: 3 + }, + silent: true, + z2: 8 + (!offset ? Z2_EMPHASIS_LIFT + 1 : 0) + }); + + if (!offset) { + var fullData = mapModel.mainSeries.getData(); + var name_1 = originalData.getName(originalDataIndex); + var fullIndex_1 = fullData.indexOfName(name_1); + var itemModel = originalData.getItemModel(originalDataIndex); + var labelModel = itemModel.getModel('label'); + var regionGroup = fullData.getItemGraphicEl(fullIndex_1); + setLabelStyle(circle, getLabelStatesModels(itemModel), { + labelFetcher: { + getFormattedLabel: function (idx, state) { + return mapModel.getFormattedLabel(fullIndex_1, state); + } + } + }); + circle.disableLabelAnimation = true; + + if (!labelModel.get('position')) { + circle.setTextConfig({ + position: 'bottom' + }); + } + + regionGroup.onHoverStateChange = function (toState) { + circle.useState(toState); + }; + } + + group.add(circle); + }); + }; + + MapView.type = 'map'; + return MapView; + }(ChartView); + + var MapSeries = function (_super) { + __extends(MapSeries, _super); + + function MapSeries() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MapSeries.type; + _this.needsDrawMap = false; + _this.seriesGroup = []; + + _this.getTooltipPosition = function (dataIndex) { + if (dataIndex != null) { + var name_1 = this.getData().getName(dataIndex); + var geo = this.coordinateSystem; + var region = geo.getRegion(name_1); + return region && geo.dataToPoint(region.center); + } + }; + + return _this; + } + + MapSeries.prototype.getInitialData = function (option) { + var data = createListSimply(this, { + coordDimensions: ['value'], + encodeDefaulter: curry(makeSeriesEncodeForNameBased, this) + }); + var dataNameMap = createHashMap(); + var toAppendNames = []; + + for (var i = 0, len = data.count(); i < len; i++) { + var name_2 = data.getName(i); + dataNameMap.set(name_2, true); + } + + var geoSource = geoSourceManager.load(this.getMapType(), this.option.nameMap, this.option.nameProperty); + each(geoSource.regions, function (region) { + var name = region.name; + + if (!dataNameMap.get(name)) { + toAppendNames.push(name); + } + }); + data.appendValues([], toAppendNames); + return data; + }; + + MapSeries.prototype.getHostGeoModel = function () { + var geoIndex = this.option.geoIndex; + return geoIndex != null ? this.ecModel.getComponent('geo', geoIndex) : null; + }; + + MapSeries.prototype.getMapType = function () { + return (this.getHostGeoModel() || this).option.map; + }; + + MapSeries.prototype.getRawValue = function (dataIndex) { + var data = this.getData(); + return data.get(data.mapDimension('value'), dataIndex); + }; + + MapSeries.prototype.getRegionModel = function (regionName) { + var data = this.getData(); + return data.getItemModel(data.indexOfName(regionName)); + }; + + MapSeries.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + var data = this.getData(); + var value = this.getRawValue(dataIndex); + var name = data.getName(dataIndex); + var seriesGroup = this.seriesGroup; + var seriesNames = []; + + for (var i = 0; i < seriesGroup.length; i++) { + var otherIndex = seriesGroup[i].originalData.indexOfName(name); + var valueDim = data.mapDimension('value'); + + if (!isNaN(seriesGroup[i].originalData.get(valueDim, otherIndex))) { + seriesNames.push(seriesGroup[i].name); + } + } + + return createTooltipMarkup('section', { + header: seriesNames.join(', '), + noHeader: !seriesNames.length, + blocks: [createTooltipMarkup('nameValue', { + name: name, + value: value + })] + }); + }; + + MapSeries.prototype.setZoom = function (zoom) { + this.option.zoom = zoom; + }; + + MapSeries.prototype.setCenter = function (center) { + this.option.center = center; + }; + + MapSeries.type = 'series.map'; + MapSeries.dependencies = ['geo']; + MapSeries.layoutMode = 'box'; + MapSeries.defaultOption = { + zlevel: 0, + z: 2, + coordinateSystem: 'geo', + map: '', + left: 'center', + top: 'center', + aspectScale: 0.75, + showLegendSymbol: true, + boundingCoords: null, + center: null, + zoom: 1, + scaleLimit: null, + selectedMode: true, + label: { + show: false, + color: '#000' + }, + itemStyle: { + borderWidth: 0.5, + borderColor: '#444', + areaColor: '#eee' + }, + emphasis: { + label: { + show: true, + color: 'rgb(100,0,0)' + }, + itemStyle: { + areaColor: 'rgba(255,215,0,0.8)' + } + }, + select: { + label: { + show: true, + color: 'rgb(100,0,0)' + }, + itemStyle: { + color: 'rgba(255,215,0,0.8)' + } + }, + nameProperty: 'name' + }; + return MapSeries; + }(SeriesModel); + + function dataStatistics(datas, statisticType) { + var dataNameMap = {}; + each(datas, function (data) { + data.each(data.mapDimension('value'), function (value, idx) { + var mapKey = 'ec-' + data.getName(idx); + dataNameMap[mapKey] = dataNameMap[mapKey] || []; + + if (!isNaN(value)) { + dataNameMap[mapKey].push(value); + } + }); + }); + return datas[0].map(datas[0].mapDimension('value'), function (value, idx) { + var mapKey = 'ec-' + datas[0].getName(idx); + var sum = 0; + var min = Infinity; + var max = -Infinity; + var len = dataNameMap[mapKey].length; + + for (var i = 0; i < len; i++) { + min = Math.min(min, dataNameMap[mapKey][i]); + max = Math.max(max, dataNameMap[mapKey][i]); + sum += dataNameMap[mapKey][i]; + } + + var result; + + if (statisticType === 'min') { + result = min; + } else if (statisticType === 'max') { + result = max; + } else if (statisticType === 'average') { + result = sum / len; + } else { + result = sum; + } + + return len === 0 ? NaN : result; + }); + } + + function mapDataStatistic(ecModel) { + var seriesGroups = {}; + ecModel.eachSeriesByType('map', function (seriesModel) { + var hostGeoModel = seriesModel.getHostGeoModel(); + var key = hostGeoModel ? 'o' + hostGeoModel.id : 'i' + seriesModel.getMapType(); + (seriesGroups[key] = seriesGroups[key] || []).push(seriesModel); + }); + each(seriesGroups, function (seriesList, key) { + var data = dataStatistics(map(seriesList, function (seriesModel) { + return seriesModel.getData(); + }), seriesList[0].get('mapValueCalculation')); + + for (var i = 0; i < seriesList.length; i++) { + seriesList[i].originalData = seriesList[i].getData(); + } + + for (var i = 0; i < seriesList.length; i++) { + seriesList[i].seriesGroup = seriesList; + seriesList[i].needsDrawMap = i === 0 && !seriesList[i].getHostGeoModel(); + seriesList[i].setData(data.cloneShallow()); + seriesList[i].mainSeries = seriesList[0]; + } + }); + } + + function mapSymbolLayout(ecModel) { + var processedMapType = {}; + ecModel.eachSeriesByType('map', function (mapSeries) { + var mapType = mapSeries.getMapType(); + + if (mapSeries.getHostGeoModel() || processedMapType[mapType]) { + return; + } + + var mapSymbolOffsets = {}; + each(mapSeries.seriesGroup, function (subMapSeries) { + var geo = subMapSeries.coordinateSystem; + var data = subMapSeries.originalData; + + if (subMapSeries.get('showLegendSymbol') && ecModel.getComponent('legend')) { + data.each(data.mapDimension('value'), function (value, idx) { + var name = data.getName(idx); + var region = geo.getRegion(name); + + if (!region || isNaN(value)) { + return; + } + + var offset = mapSymbolOffsets[name] || 0; + var point = geo.dataToPoint(region.center); + mapSymbolOffsets[name] = offset + 1; + data.setItemLayout(idx, { + point: point, + offset: offset + }); + }); + } + }); + var data = mapSeries.getData(); + data.each(function (idx) { + var name = data.getName(idx); + var layout = data.getItemLayout(idx) || {}; + layout.showLabel = !mapSymbolOffsets[name]; + data.setItemLayout(idx, layout); + }); + processedMapType[mapType] = true; + }); + } + + function install$9(registers) { + registers.registerChartView(MapView); + registers.registerSeriesModel(MapSeries); + registers.registerLayout(mapSymbolLayout); + registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, mapDataStatistic); + createLegacyDataSelectAction('map', registers.registerAction); + } + + function init$2(inRoot) { + var root = inRoot; + root.hierNode = { + defaultAncestor: null, + ancestor: root, + prelim: 0, + modifier: 0, + change: 0, + shift: 0, + i: 0, + thread: null + }; + var nodes = [root]; + var node; + var children; + + while (node = nodes.pop()) { + children = node.children; + + if (node.isExpand && children.length) { + var n = children.length; + + for (var i = n - 1; i >= 0; i--) { + var child = children[i]; + child.hierNode = { + defaultAncestor: null, + ancestor: child, + prelim: 0, + modifier: 0, + change: 0, + shift: 0, + i: i, + thread: null + }; + nodes.push(child); + } + } + } + } + function firstWalk(node, separation) { + var children = node.isExpand ? node.children : []; + var siblings = node.parentNode.children; + var subtreeW = node.hierNode.i ? siblings[node.hierNode.i - 1] : null; + + if (children.length) { + executeShifts(node); + var midPoint = (children[0].hierNode.prelim + children[children.length - 1].hierNode.prelim) / 2; + + if (subtreeW) { + node.hierNode.prelim = subtreeW.hierNode.prelim + separation(node, subtreeW); + node.hierNode.modifier = node.hierNode.prelim - midPoint; + } else { + node.hierNode.prelim = midPoint; + } + } else if (subtreeW) { + node.hierNode.prelim = subtreeW.hierNode.prelim + separation(node, subtreeW); + } + + node.parentNode.hierNode.defaultAncestor = apportion(node, subtreeW, node.parentNode.hierNode.defaultAncestor || siblings[0], separation); + } + function secondWalk(node) { + var nodeX = node.hierNode.prelim + node.parentNode.hierNode.modifier; + node.setLayout({ + x: nodeX + }, true); + node.hierNode.modifier += node.parentNode.hierNode.modifier; + } + function separation(cb) { + return arguments.length ? cb : defaultSeparation; + } + function radialCoordinate(rad, r) { + rad -= Math.PI / 2; + return { + x: r * Math.cos(rad), + y: r * Math.sin(rad) + }; + } + function getViewRect$1(seriesModel, api) { + return getLayoutRect(seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + } + + function executeShifts(node) { + var children = node.children; + var n = children.length; + var shift = 0; + var change = 0; + + while (--n >= 0) { + var child = children[n]; + child.hierNode.prelim += shift; + child.hierNode.modifier += shift; + change += child.hierNode.change; + shift += child.hierNode.shift + change; + } + } + + function apportion(subtreeV, subtreeW, ancestor, separation) { + if (subtreeW) { + var nodeOutRight = subtreeV; + var nodeInRight = subtreeV; + var nodeOutLeft = nodeInRight.parentNode.children[0]; + var nodeInLeft = subtreeW; + var sumOutRight = nodeOutRight.hierNode.modifier; + var sumInRight = nodeInRight.hierNode.modifier; + var sumOutLeft = nodeOutLeft.hierNode.modifier; + var sumInLeft = nodeInLeft.hierNode.modifier; + + while (nodeInLeft = nextRight(nodeInLeft), nodeInRight = nextLeft(nodeInRight), nodeInLeft && nodeInRight) { + nodeOutRight = nextRight(nodeOutRight); + nodeOutLeft = nextLeft(nodeOutLeft); + nodeOutRight.hierNode.ancestor = subtreeV; + var shift = nodeInLeft.hierNode.prelim + sumInLeft - nodeInRight.hierNode.prelim - sumInRight + separation(nodeInLeft, nodeInRight); + + if (shift > 0) { + moveSubtree(nextAncestor(nodeInLeft, subtreeV, ancestor), subtreeV, shift); + sumInRight += shift; + sumOutRight += shift; + } + + sumInLeft += nodeInLeft.hierNode.modifier; + sumInRight += nodeInRight.hierNode.modifier; + sumOutRight += nodeOutRight.hierNode.modifier; + sumOutLeft += nodeOutLeft.hierNode.modifier; + } + + if (nodeInLeft && !nextRight(nodeOutRight)) { + nodeOutRight.hierNode.thread = nodeInLeft; + nodeOutRight.hierNode.modifier += sumInLeft - sumOutRight; + } + + if (nodeInRight && !nextLeft(nodeOutLeft)) { + nodeOutLeft.hierNode.thread = nodeInRight; + nodeOutLeft.hierNode.modifier += sumInRight - sumOutLeft; + ancestor = subtreeV; + } + } + + return ancestor; + } + + function nextRight(node) { + var children = node.children; + return children.length && node.isExpand ? children[children.length - 1] : node.hierNode.thread; + } + + function nextLeft(node) { + var children = node.children; + return children.length && node.isExpand ? children[0] : node.hierNode.thread; + } + + function nextAncestor(nodeInLeft, node, ancestor) { + return nodeInLeft.hierNode.ancestor.parentNode === node.parentNode ? nodeInLeft.hierNode.ancestor : ancestor; + } + + function moveSubtree(wl, wr, shift) { + var change = shift / (wr.hierNode.i - wl.hierNode.i); + wr.hierNode.change -= change; + wr.hierNode.shift += shift; + wr.hierNode.modifier += shift; + wr.hierNode.prelim += shift; + wl.hierNode.change += change; + } + + function defaultSeparation(node1, node2) { + return node1.parentNode === node2.parentNode ? 1 : 2; + } + + var v2ApplyTransform = applyTransform; + + var View = function (_super) { + __extends(View, _super); + + function View(name) { + var _this = _super.call(this) || this; + + _this.type = 'view'; + _this.dimensions = ['x', 'y']; + _this._roamTransformable = new Transformable(); + _this._rawTransformable = new Transformable(); + _this.name = name; + return _this; + } + + View.prototype.setBoundingRect = function (x, y, width, height) { + this._rect = new BoundingRect(x, y, width, height); + return this._rect; + }; + + View.prototype.getBoundingRect = function () { + return this._rect; + }; + + View.prototype.setViewRect = function (x, y, width, height) { + this.transformTo(x, y, width, height); + this._viewRect = new BoundingRect(x, y, width, height); + }; + + View.prototype.transformTo = function (x, y, width, height) { + var rect = this.getBoundingRect(); + var rawTransform = this._rawTransformable; + rawTransform.transform = rect.calculateTransform(new BoundingRect(x, y, width, height)); + rawTransform.decomposeTransform(); + + this._updateTransform(); + }; + + View.prototype.setCenter = function (centerCoord) { + if (!centerCoord) { + return; + } + + this._center = centerCoord; + + this._updateCenterAndZoom(); + }; + + View.prototype.setZoom = function (zoom) { + zoom = zoom || 1; + var zoomLimit = this.zoomLimit; + + if (zoomLimit) { + if (zoomLimit.max != null) { + zoom = Math.min(zoomLimit.max, zoom); + } + + if (zoomLimit.min != null) { + zoom = Math.max(zoomLimit.min, zoom); + } + } + + this._zoom = zoom; + + this._updateCenterAndZoom(); + }; + + View.prototype.getDefaultCenter = function () { + var rawRect = this.getBoundingRect(); + var cx = rawRect.x + rawRect.width / 2; + var cy = rawRect.y + rawRect.height / 2; + return [cx, cy]; + }; + + View.prototype.getCenter = function () { + return this._center || this.getDefaultCenter(); + }; + + View.prototype.getZoom = function () { + return this._zoom || 1; + }; + + View.prototype.getRoamTransform = function () { + return this._roamTransformable.getLocalTransform(); + }; + + View.prototype._updateCenterAndZoom = function () { + var rawTransformMatrix = this._rawTransformable.getLocalTransform(); + + var roamTransform = this._roamTransformable; + var defaultCenter = this.getDefaultCenter(); + var center = this.getCenter(); + var zoom = this.getZoom(); + center = applyTransform([], center, rawTransformMatrix); + defaultCenter = applyTransform([], defaultCenter, rawTransformMatrix); + roamTransform.originX = center[0]; + roamTransform.originY = center[1]; + roamTransform.x = defaultCenter[0] - center[0]; + roamTransform.y = defaultCenter[1] - center[1]; + roamTransform.scaleX = roamTransform.scaleY = zoom; + + this._updateTransform(); + }; + + View.prototype._updateTransform = function () { + var roamTransformable = this._roamTransformable; + var rawTransformable = this._rawTransformable; + rawTransformable.parent = roamTransformable; + roamTransformable.updateTransform(); + rawTransformable.updateTransform(); + copy$1(this.transform || (this.transform = []), rawTransformable.transform || create$1()); + this._rawTransform = rawTransformable.getLocalTransform(); + this.invTransform = this.invTransform || []; + invert(this.invTransform, this.transform); + this.decomposeTransform(); + }; + + View.prototype.getTransformInfo = function () { + var roamTransform = this._roamTransformable.transform; + var rawTransformable = this._rawTransformable; + return { + roamTransform: roamTransform ? slice(roamTransform) : create$1(), + rawScaleX: rawTransformable.scaleX, + rawScaleY: rawTransformable.scaleY, + rawX: rawTransformable.x, + rawY: rawTransformable.y + }; + }; + + View.prototype.getViewRect = function () { + return this._viewRect; + }; + + View.prototype.getViewRectAfterRoam = function () { + var rect = this.getBoundingRect().clone(); + rect.applyTransform(this.transform); + return rect; + }; + + View.prototype.dataToPoint = function (data, noRoam, out) { + var transform = noRoam ? this._rawTransform : this.transform; + out = out || []; + return transform ? v2ApplyTransform(out, data, transform) : copy(out, data); + }; + + View.prototype.pointToData = function (point) { + var invTransform = this.invTransform; + return invTransform ? v2ApplyTransform([], point, invTransform) : [point[0], point[1]]; + }; + + View.prototype.convertToPixel = function (ecModel, finder, value) { + var coordSys = getCoordSys(finder); + return coordSys === this ? coordSys.dataToPoint(value) : null; + }; + + View.prototype.convertFromPixel = function (ecModel, finder, pixel) { + var coordSys = getCoordSys(finder); + return coordSys === this ? coordSys.pointToData(pixel) : null; + }; + + View.prototype.containPoint = function (point) { + return this.getViewRectAfterRoam().contain(point[0], point[1]); + }; + + View.dimensions = ['x', 'y']; + return View; + }(Transformable); + + function getCoordSys(finder) { + var seriesModel = finder.seriesModel; + return seriesModel ? seriesModel.coordinateSystem : null; + } + + var TreeEdgeShape = function () { + function TreeEdgeShape() { + this.parentPoint = []; + this.childPoints = []; + } + + return TreeEdgeShape; + }(); + + var TreePath = function (_super) { + __extends(TreePath, _super); + + function TreePath(opts) { + return _super.call(this, opts) || this; + } + + TreePath.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + + TreePath.prototype.getDefaultShape = function () { + return new TreeEdgeShape(); + }; + + TreePath.prototype.buildPath = function (ctx, shape) { + var childPoints = shape.childPoints; + var childLen = childPoints.length; + var parentPoint = shape.parentPoint; + var firstChildPos = childPoints[0]; + var lastChildPos = childPoints[childLen - 1]; + + if (childLen === 1) { + ctx.moveTo(parentPoint[0], parentPoint[1]); + ctx.lineTo(firstChildPos[0], firstChildPos[1]); + return; + } + + var orient = shape.orient; + var forkDim = orient === 'TB' || orient === 'BT' ? 0 : 1; + var otherDim = 1 - forkDim; + var forkPosition = parsePercent$1(shape.forkPosition, 1); + var tmpPoint = []; + tmpPoint[forkDim] = parentPoint[forkDim]; + tmpPoint[otherDim] = parentPoint[otherDim] + (lastChildPos[otherDim] - parentPoint[otherDim]) * forkPosition; + ctx.moveTo(parentPoint[0], parentPoint[1]); + ctx.lineTo(tmpPoint[0], tmpPoint[1]); + ctx.moveTo(firstChildPos[0], firstChildPos[1]); + tmpPoint[forkDim] = firstChildPos[forkDim]; + ctx.lineTo(tmpPoint[0], tmpPoint[1]); + tmpPoint[forkDim] = lastChildPos[forkDim]; + ctx.lineTo(tmpPoint[0], tmpPoint[1]); + ctx.lineTo(lastChildPos[0], lastChildPos[1]); + + for (var i = 1; i < childLen - 1; i++) { + var point = childPoints[i]; + ctx.moveTo(point[0], point[1]); + tmpPoint[forkDim] = point[forkDim]; + ctx.lineTo(tmpPoint[0], tmpPoint[1]); + } + }; + + return TreePath; + }(Path); + + var TreeView = function (_super) { + __extends(TreeView, _super); + + function TreeView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TreeView.type; + _this._mainGroup = new Group(); + return _this; + } + + TreeView.prototype.init = function (ecModel, api) { + this._controller = new RoamController(api.getZr()); + this._controllerHost = { + target: this.group + }; + this.group.add(this._mainGroup); + }; + + TreeView.prototype.render = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var layoutInfo = seriesModel.layoutInfo; + var group = this._mainGroup; + var layout = seriesModel.get('layout'); + + if (layout === 'radial') { + group.x = layoutInfo.x + layoutInfo.width / 2; + group.y = layoutInfo.y + layoutInfo.height / 2; + } else { + group.x = layoutInfo.x; + group.y = layoutInfo.y; + } + + this._updateViewCoordSys(seriesModel); + + this._updateController(seriesModel, ecModel, api); + + var oldData = this._data; + data.diff(oldData).add(function (newIdx) { + if (symbolNeedsDraw$1(data, newIdx)) { + updateNode(data, newIdx, null, group, seriesModel); + } + }).update(function (newIdx, oldIdx) { + var symbolEl = oldData.getItemGraphicEl(oldIdx); + + if (!symbolNeedsDraw$1(data, newIdx)) { + symbolEl && removeNode(oldData, oldIdx, symbolEl, group, seriesModel); + return; + } + + updateNode(data, newIdx, symbolEl, group, seriesModel); + }).remove(function (oldIdx) { + var symbolEl = oldData.getItemGraphicEl(oldIdx); + + if (symbolEl) { + removeNode(oldData, oldIdx, symbolEl, group, seriesModel); + } + }).execute(); + this._nodeScaleRatio = seriesModel.get('nodeScaleRatio'); + + this._updateNodeAndLinkScale(seriesModel); + + if (seriesModel.get('expandAndCollapse') === true) { + data.eachItemGraphicEl(function (el, dataIndex) { + el.off('click').on('click', function () { + api.dispatchAction({ + type: 'treeExpandAndCollapse', + seriesId: seriesModel.id, + dataIndex: dataIndex + }); + }); + }); + } + + this._data = data; + }; + + TreeView.prototype._updateViewCoordSys = function (seriesModel) { + var data = seriesModel.getData(); + var points = []; + data.each(function (idx) { + var layout = data.getItemLayout(idx); + + if (layout && !isNaN(layout.x) && !isNaN(layout.y)) { + points.push([+layout.x, +layout.y]); + } + }); + var min = []; + var max = []; + fromPoints(points, min, max); + var oldMin = this._min; + var oldMax = this._max; + + if (max[0] - min[0] === 0) { + min[0] = oldMin ? oldMin[0] : min[0] - 1; + max[0] = oldMax ? oldMax[0] : max[0] + 1; + } + + if (max[1] - min[1] === 0) { + min[1] = oldMin ? oldMin[1] : min[1] - 1; + max[1] = oldMax ? oldMax[1] : max[1] + 1; + } + + var viewCoordSys = seriesModel.coordinateSystem = new View(); + viewCoordSys.zoomLimit = seriesModel.get('scaleLimit'); + viewCoordSys.setBoundingRect(min[0], min[1], max[0] - min[0], max[1] - min[1]); + viewCoordSys.setCenter(seriesModel.get('center')); + viewCoordSys.setZoom(seriesModel.get('zoom')); + this.group.attr({ + x: viewCoordSys.x, + y: viewCoordSys.y, + scaleX: viewCoordSys.scaleX, + scaleY: viewCoordSys.scaleY + }); + this._min = min; + this._max = max; + }; + + TreeView.prototype._updateController = function (seriesModel, ecModel, api) { + var _this = this; + + var controller = this._controller; + var controllerHost = this._controllerHost; + var group = this.group; + controller.setPointerChecker(function (e, x, y) { + var rect = group.getBoundingRect(); + rect.applyTransform(group.transform); + return rect.contain(x, y) && !onIrrelevantElement(e, api, seriesModel); + }); + controller.enable(seriesModel.get('roam')); + controllerHost.zoomLimit = seriesModel.get('scaleLimit'); + controllerHost.zoom = seriesModel.coordinateSystem.getZoom(); + controller.off('pan').off('zoom').on('pan', function (e) { + updateViewOnPan(controllerHost, e.dx, e.dy); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'treeRoam', + dx: e.dx, + dy: e.dy + }); + }).on('zoom', function (e) { + updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'treeRoam', + zoom: e.scale, + originX: e.originX, + originY: e.originY + }); + + _this._updateNodeAndLinkScale(seriesModel); + + api.updateLabelLayout(); + }); + }; + + TreeView.prototype._updateNodeAndLinkScale = function (seriesModel) { + var data = seriesModel.getData(); + + var nodeScale = this._getNodeGlobalScale(seriesModel); + + data.eachItemGraphicEl(function (el, idx) { + el.setSymbolScale(nodeScale); + }); + }; + + TreeView.prototype._getNodeGlobalScale = function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys.type !== 'view') { + return 1; + } + + var nodeScaleRatio = this._nodeScaleRatio; + var groupZoom = coordSys.scaleX || 1; + var roamZoom = coordSys.getZoom(); + var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1; + return nodeScale / groupZoom; + }; + + TreeView.prototype.dispose = function () { + this._controller && this._controller.dispose(); + this._controllerHost = null; + }; + + TreeView.prototype.remove = function () { + this._mainGroup.removeAll(); + + this._data = null; + }; + + TreeView.type = 'tree'; + return TreeView; + }(ChartView); + + function symbolNeedsDraw$1(data, dataIndex) { + var layout = data.getItemLayout(dataIndex); + return layout && !isNaN(layout.x) && !isNaN(layout.y); + } + + function updateNode(data, dataIndex, symbolEl, group, seriesModel) { + var isInit = !symbolEl; + var node = data.tree.getNodeByDataIndex(dataIndex); + var itemModel = node.getModel(); + var visualColor = node.getVisual('style').fill; + var symbolInnerColor = node.isExpand === false && node.children.length !== 0 ? visualColor : '#fff'; + var virtualRoot = data.tree.root; + var source = node.parentNode === virtualRoot ? node : node.parentNode || node; + var sourceSymbolEl = data.getItemGraphicEl(source.dataIndex); + var sourceLayout = source.getLayout(); + var sourceOldLayout = sourceSymbolEl ? { + x: sourceSymbolEl.__oldX, + y: sourceSymbolEl.__oldY, + rawX: sourceSymbolEl.__radialOldRawX, + rawY: sourceSymbolEl.__radialOldRawY + } : sourceLayout; + var targetLayout = node.getLayout(); + + if (isInit) { + symbolEl = new Symbol(data, dataIndex, null, { + symbolInnerColor: symbolInnerColor, + useNameLabel: true + }); + symbolEl.x = sourceOldLayout.x; + symbolEl.y = sourceOldLayout.y; + } else { + symbolEl.updateData(data, dataIndex, null, { + symbolInnerColor: symbolInnerColor, + useNameLabel: true + }); + } + + symbolEl.__radialOldRawX = symbolEl.__radialRawX; + symbolEl.__radialOldRawY = symbolEl.__radialRawY; + symbolEl.__radialRawX = targetLayout.rawX; + symbolEl.__radialRawY = targetLayout.rawY; + group.add(symbolEl); + data.setItemGraphicEl(dataIndex, symbolEl); + symbolEl.__oldX = symbolEl.x; + symbolEl.__oldY = symbolEl.y; + updateProps(symbolEl, { + x: targetLayout.x, + y: targetLayout.y + }, seriesModel); + var symbolPath = symbolEl.getSymbolPath(); + + if (seriesModel.get('layout') === 'radial') { + var realRoot = virtualRoot.children[0]; + var rootLayout = realRoot.getLayout(); + var length_1 = realRoot.children.length; + var rad = void 0; + var isLeft = void 0; + + if (targetLayout.x === rootLayout.x && node.isExpand === true) { + var center = { + x: (realRoot.children[0].getLayout().x + realRoot.children[length_1 - 1].getLayout().x) / 2, + y: (realRoot.children[0].getLayout().y + realRoot.children[length_1 - 1].getLayout().y) / 2 + }; + rad = Math.atan2(center.y - rootLayout.y, center.x - rootLayout.x); + + if (rad < 0) { + rad = Math.PI * 2 + rad; + } + + isLeft = center.x < rootLayout.x; + + if (isLeft) { + rad = rad - Math.PI; + } + } else { + rad = Math.atan2(targetLayout.y - rootLayout.y, targetLayout.x - rootLayout.x); + + if (rad < 0) { + rad = Math.PI * 2 + rad; + } + + if (node.children.length === 0 || node.children.length !== 0 && node.isExpand === false) { + isLeft = targetLayout.x < rootLayout.x; + + if (isLeft) { + rad = rad - Math.PI; + } + } else { + isLeft = targetLayout.x > rootLayout.x; + + if (!isLeft) { + rad = rad - Math.PI; + } + } + } + + var textPosition = isLeft ? 'left' : 'right'; + var normalLabelModel = itemModel.getModel('label'); + var rotate = normalLabelModel.get('rotate'); + var labelRotateRadian = rotate * (Math.PI / 180); + var textContent = symbolPath.getTextContent(); + + if (textContent) { + symbolPath.setTextConfig({ + position: normalLabelModel.get('position') || textPosition, + rotation: rotate == null ? -rad : labelRotateRadian, + origin: 'center' + }); + textContent.setStyle('verticalAlign', 'middle'); + } + } + + var focus = itemModel.get(['emphasis', 'focus']); + var focusDataIndices = focus === 'ancestor' ? node.getAncestorsIndices() : focus === 'descendant' ? node.getDescendantIndices() : null; + + if (focusDataIndices) { + getECData(symbolEl).focus = focusDataIndices; + } + + drawEdge(seriesModel, node, virtualRoot, symbolEl, sourceOldLayout, sourceLayout, targetLayout, group); + + if (symbolEl.__edge) { + symbolEl.onHoverStateChange = function (toState) { + if (toState !== 'blur') { + var parentEl = node.parentNode && data.getItemGraphicEl(node.parentNode.dataIndex); + + if (!(parentEl && parentEl.hoverState === HOVER_STATE_BLUR)) { + setStatesFlag(symbolEl.__edge, toState); + } + } + }; + } + } + + function drawEdge(seriesModel, node, virtualRoot, symbolEl, sourceOldLayout, sourceLayout, targetLayout, group) { + var itemModel = node.getModel(); + var edgeShape = seriesModel.get('edgeShape'); + var layout = seriesModel.get('layout'); + var orient = seriesModel.getOrient(); + var curvature = seriesModel.get(['lineStyle', 'curveness']); + var edgeForkPosition = seriesModel.get('edgeForkPosition'); + var lineStyle = itemModel.getModel('lineStyle').getLineStyle(); + var edge = symbolEl.__edge; + + if (edgeShape === 'curve') { + if (node.parentNode && node.parentNode !== virtualRoot) { + if (!edge) { + edge = symbolEl.__edge = new BezierCurve({ + shape: getEdgeShape(layout, orient, curvature, sourceOldLayout, sourceOldLayout) + }); + } + + updateProps(edge, { + shape: getEdgeShape(layout, orient, curvature, sourceLayout, targetLayout) + }, seriesModel); + } + } else if (edgeShape === 'polyline') { + if (layout === 'orthogonal') { + if (node !== virtualRoot && node.children && node.children.length !== 0 && node.isExpand === true) { + var children = node.children; + var childPoints = []; + + for (var i = 0; i < children.length; i++) { + var childLayout = children[i].getLayout(); + childPoints.push([childLayout.x, childLayout.y]); + } + + if (!edge) { + edge = symbolEl.__edge = new TreePath({ + shape: { + parentPoint: [targetLayout.x, targetLayout.y], + childPoints: [[targetLayout.x, targetLayout.y]], + orient: orient, + forkPosition: edgeForkPosition + } + }); + } + + updateProps(edge, { + shape: { + parentPoint: [targetLayout.x, targetLayout.y], + childPoints: childPoints + } + }, seriesModel); + } + } else { + if ("development" !== 'production') { + throw new Error('The polyline edgeShape can only be used in orthogonal layout'); + } + } + } + + if (edge) { + edge.useStyle(defaults({ + strokeNoScale: true, + fill: null + }, lineStyle)); + setStatesStylesFromModel(edge, itemModel, 'lineStyle'); + setDefaultStateProxy(edge); + group.add(edge); + } + } + + function removeNode(data, dataIndex, symbolEl, group, seriesModel) { + var node = data.tree.getNodeByDataIndex(dataIndex); + var virtualRoot = data.tree.root; + var source = node.parentNode === virtualRoot ? node : node.parentNode || node; + var sourceLayout; + + while (sourceLayout = source.getLayout(), sourceLayout == null) { + source = source.parentNode === virtualRoot ? source : source.parentNode || source; + } + + var removeAnimationOpt = { + duration: seriesModel.get('animationDurationUpdate'), + easing: seriesModel.get('animationEasingUpdate') + }; + removeElement(symbolEl, { + x: sourceLayout.x + 1, + y: sourceLayout.y + 1 + }, seriesModel, { + cb: function () { + group.remove(symbolEl); + data.setItemGraphicEl(dataIndex, null); + }, + removeOpt: removeAnimationOpt + }); + symbolEl.fadeOut(null, { + fadeLabel: true, + animation: removeAnimationOpt + }); + var sourceSymbolEl = data.getItemGraphicEl(source.dataIndex); + var sourceEdge = sourceSymbolEl.__edge; + var edge = symbolEl.__edge || (source.isExpand === false || source.children.length === 1 ? sourceEdge : undefined); + var edgeShape = seriesModel.get('edgeShape'); + var layoutOpt = seriesModel.get('layout'); + var orient = seriesModel.get('orient'); + var curvature = seriesModel.get(['lineStyle', 'curveness']); + + if (edge) { + if (edgeShape === 'curve') { + removeElement(edge, { + shape: getEdgeShape(layoutOpt, orient, curvature, sourceLayout, sourceLayout), + style: { + opacity: 0 + } + }, seriesModel, { + cb: function () { + group.remove(edge); + }, + removeOpt: removeAnimationOpt + }); + } else if (edgeShape === 'polyline' && seriesModel.get('layout') === 'orthogonal') { + removeElement(edge, { + shape: { + parentPoint: [sourceLayout.x, sourceLayout.y], + childPoints: [[sourceLayout.x, sourceLayout.y]] + }, + style: { + opacity: 0 + } + }, seriesModel, { + cb: function () { + group.remove(edge); + }, + removeOpt: removeAnimationOpt + }); + } + } + } + + function getEdgeShape(layoutOpt, orient, curvature, sourceLayout, targetLayout) { + var cpx1; + var cpy1; + var cpx2; + var cpy2; + var x1; + var x2; + var y1; + var y2; + + if (layoutOpt === 'radial') { + x1 = sourceLayout.rawX; + y1 = sourceLayout.rawY; + x2 = targetLayout.rawX; + y2 = targetLayout.rawY; + var radialCoor1 = radialCoordinate(x1, y1); + var radialCoor2 = radialCoordinate(x1, y1 + (y2 - y1) * curvature); + var radialCoor3 = radialCoordinate(x2, y2 + (y1 - y2) * curvature); + var radialCoor4 = radialCoordinate(x2, y2); + return { + x1: radialCoor1.x || 0, + y1: radialCoor1.y || 0, + x2: radialCoor4.x || 0, + y2: radialCoor4.y || 0, + cpx1: radialCoor2.x || 0, + cpy1: radialCoor2.y || 0, + cpx2: radialCoor3.x || 0, + cpy2: radialCoor3.y || 0 + }; + } else { + x1 = sourceLayout.x; + y1 = sourceLayout.y; + x2 = targetLayout.x; + y2 = targetLayout.y; + + if (orient === 'LR' || orient === 'RL') { + cpx1 = x1 + (x2 - x1) * curvature; + cpy1 = y1; + cpx2 = x2 + (x1 - x2) * curvature; + cpy2 = y2; + } + + if (orient === 'TB' || orient === 'BT') { + cpx1 = x1; + cpy1 = y1 + (y2 - y1) * curvature; + cpx2 = x2; + cpy2 = y2 + (y1 - y2) * curvature; + } + } + + return { + x1: x1, + y1: y1, + x2: x2, + y2: y2, + cpx1: cpx1, + cpy1: cpy1, + cpx2: cpx2, + cpy2: cpy2 + }; + } + + var inner$8 = makeInner(); + + function linkList(opt) { + var mainData = opt.mainData; + var datas = opt.datas; + + if (!datas) { + datas = { + main: mainData + }; + opt.datasAttr = { + main: 'data' + }; + } + + opt.datas = opt.mainData = null; + linkAll(mainData, datas, opt); + each(datas, function (data) { + each(mainData.TRANSFERABLE_METHODS, function (methodName) { + data.wrapMethod(methodName, curry(transferInjection, opt)); + }); + }); + mainData.wrapMethod('cloneShallow', curry(cloneShallowInjection, opt)); + each(mainData.CHANGABLE_METHODS, function (methodName) { + mainData.wrapMethod(methodName, curry(changeInjection, opt)); + }); + assert(datas[mainData.dataType] === mainData); + } + + function transferInjection(opt, res) { + if (isMainData(this)) { + var datas = extend({}, inner$8(this).datas); + datas[this.dataType] = res; + linkAll(res, datas, opt); + } else { + linkSingle(res, this.dataType, inner$8(this).mainData, opt); + } + + return res; + } + + function changeInjection(opt, res) { + opt.struct && opt.struct.update(); + return res; + } + + function cloneShallowInjection(opt, res) { + each(inner$8(res).datas, function (data, dataType) { + data !== res && linkSingle(data.cloneShallow(), dataType, res, opt); + }); + return res; + } + + function getLinkedData(dataType) { + var mainData = inner$8(this).mainData; + return dataType == null || mainData == null ? mainData : inner$8(mainData).datas[dataType]; + } + + function getLinkedDataAll() { + var mainData = inner$8(this).mainData; + return mainData == null ? [{ + data: mainData + }] : map(keys(inner$8(mainData).datas), function (type) { + return { + type: type, + data: inner$8(mainData).datas[type] + }; + }); + } + + function isMainData(data) { + return inner$8(data).mainData === data; + } + + function linkAll(mainData, datas, opt) { + inner$8(mainData).datas = {}; + each(datas, function (data, dataType) { + linkSingle(data, dataType, mainData, opt); + }); + } + + function linkSingle(data, dataType, mainData, opt) { + inner$8(mainData).datas[dataType] = data; + inner$8(data).mainData = mainData; + data.dataType = dataType; + + if (opt.struct) { + data[opt.structAttr] = opt.struct; + opt.struct[opt.datasAttr[dataType]] = data; + } + + data.getLinkedData = getLinkedData; + data.getLinkedDataAll = getLinkedDataAll; + } + + var TreeNode = function () { + function TreeNode(name, hostTree) { + this.depth = 0; + this.height = 0; + this.dataIndex = -1; + this.children = []; + this.viewChildren = []; + this.isExpand = false; + this.name = name || ''; + this.hostTree = hostTree; + } + + TreeNode.prototype.isRemoved = function () { + return this.dataIndex < 0; + }; + + TreeNode.prototype.eachNode = function (options, cb, context) { + if (typeof options === 'function') { + context = cb; + cb = options; + options = null; + } + + options = options || {}; + + if (isString(options)) { + options = { + order: options + }; + } + + var order = options.order || 'preorder'; + var children = this[options.attr || 'children']; + var suppressVisitSub; + order === 'preorder' && (suppressVisitSub = cb.call(context, this)); + + for (var i = 0; !suppressVisitSub && i < children.length; i++) { + children[i].eachNode(options, cb, context); + } + + order === 'postorder' && cb.call(context, this); + }; + + TreeNode.prototype.updateDepthAndHeight = function (depth) { + var height = 0; + this.depth = depth; + + for (var i = 0; i < this.children.length; i++) { + var child = this.children[i]; + child.updateDepthAndHeight(depth + 1); + + if (child.height > height) { + height = child.height; + } + } + + this.height = height + 1; + }; + + TreeNode.prototype.getNodeById = function (id) { + if (this.getId() === id) { + return this; + } + + for (var i = 0, children = this.children, len = children.length; i < len; i++) { + var res = children[i].getNodeById(id); + + if (res) { + return res; + } + } + }; + + TreeNode.prototype.contains = function (node) { + if (node === this) { + return true; + } + + for (var i = 0, children = this.children, len = children.length; i < len; i++) { + var res = children[i].contains(node); + + if (res) { + return res; + } + } + }; + + TreeNode.prototype.getAncestors = function (includeSelf) { + var ancestors = []; + var node = includeSelf ? this : this.parentNode; + + while (node) { + ancestors.push(node); + node = node.parentNode; + } + + ancestors.reverse(); + return ancestors; + }; + + TreeNode.prototype.getAncestorsIndices = function () { + var indices = []; + var currNode = this; + + while (currNode) { + indices.push(currNode.dataIndex); + currNode = currNode.parentNode; + } + + indices.reverse(); + return indices; + }; + + TreeNode.prototype.getDescendantIndices = function () { + var indices = []; + this.eachNode(function (childNode) { + indices.push(childNode.dataIndex); + }); + return indices; + }; + + TreeNode.prototype.getValue = function (dimension) { + var data = this.hostTree.data; + return data.get(data.getDimension(dimension || 'value'), this.dataIndex); + }; + + TreeNode.prototype.setLayout = function (layout, merge) { + this.dataIndex >= 0 && this.hostTree.data.setItemLayout(this.dataIndex, layout, merge); + }; + + TreeNode.prototype.getLayout = function () { + return this.hostTree.data.getItemLayout(this.dataIndex); + }; + + TreeNode.prototype.getModel = function (path) { + if (this.dataIndex < 0) { + return; + } + + var hostTree = this.hostTree; + var itemModel = hostTree.data.getItemModel(this.dataIndex); + return itemModel.getModel(path); + }; + + TreeNode.prototype.getLevelModel = function () { + return (this.hostTree.levelModels || [])[this.depth]; + }; + + TreeNode.prototype.setVisual = function (key, value) { + this.dataIndex >= 0 && this.hostTree.data.setItemVisual(this.dataIndex, key, value); + }; + + TreeNode.prototype.getVisual = function (key) { + return this.hostTree.data.getItemVisual(this.dataIndex, key); + }; + + TreeNode.prototype.getRawIndex = function () { + return this.hostTree.data.getRawIndex(this.dataIndex); + }; + + TreeNode.prototype.getId = function () { + return this.hostTree.data.getId(this.dataIndex); + }; + + TreeNode.prototype.isAncestorOf = function (node) { + var parent = node.parentNode; + + while (parent) { + if (parent === this) { + return true; + } + + parent = parent.parentNode; + } + + return false; + }; + + TreeNode.prototype.isDescendantOf = function (node) { + return node !== this && node.isAncestorOf(this); + }; + + return TreeNode; + }(); + + var Tree = function () { + function Tree(hostModel) { + this.type = 'tree'; + this._nodes = []; + this.hostModel = hostModel; + } + + Tree.prototype.eachNode = function (options, cb, context) { + this.root.eachNode(options, cb, context); + }; + + Tree.prototype.getNodeByDataIndex = function (dataIndex) { + var rawIndex = this.data.getRawIndex(dataIndex); + return this._nodes[rawIndex]; + }; + + Tree.prototype.getNodeById = function (name) { + return this.root.getNodeById(name); + }; + + Tree.prototype.update = function () { + var data = this.data; + var nodes = this._nodes; + + for (var i = 0, len = nodes.length; i < len; i++) { + nodes[i].dataIndex = -1; + } + + for (var i = 0, len = data.count(); i < len; i++) { + nodes[data.getRawIndex(i)].dataIndex = i; + } + }; + + Tree.prototype.clearLayouts = function () { + this.data.clearItemLayouts(); + }; + + Tree.createTree = function (dataRoot, hostModel, beforeLink) { + var tree = new Tree(hostModel); + var listData = []; + var dimMax = 1; + buildHierarchy(dataRoot); + + function buildHierarchy(dataNode, parentNode) { + var value = dataNode.value; + dimMax = Math.max(dimMax, isArray(value) ? value.length : 1); + listData.push(dataNode); + var node = new TreeNode(convertOptionIdName(dataNode.name, ''), tree); + parentNode ? addChild(node, parentNode) : tree.root = node; + + tree._nodes.push(node); + + var children = dataNode.children; + + if (children) { + for (var i = 0; i < children.length; i++) { + buildHierarchy(children[i], node); + } + } + } + + tree.root.updateDepthAndHeight(0); + var dimensionsInfo = createDimensions(listData, { + coordDimensions: ['value'], + dimensionsCount: dimMax + }); + var list = new List(dimensionsInfo, hostModel); + list.initData(listData); + beforeLink && beforeLink(list); + linkList({ + mainData: list, + struct: tree, + structAttr: 'tree' + }); + tree.update(); + return tree; + }; + + return Tree; + }(); + + function addChild(child, node) { + var children = node.children; + + if (child.parentNode === node) { + return; + } + + children.push(child); + child.parentNode = node; + } + + var TreeSeriesModel = function (_super) { + __extends(TreeSeriesModel, _super); + + function TreeSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.hasSymbolVisual = true; + _this.ignoreStyleOnData = true; + return _this; + } + + TreeSeriesModel.prototype.getInitialData = function (option) { + var root = { + name: option.name, + children: option.data + }; + var leaves = option.leaves || {}; + var leavesModel = new Model(leaves, this, this.ecModel); + var tree = Tree.createTree(root, this, beforeLink); + + function beforeLink(nodeData) { + nodeData.wrapMethod('getItemModel', function (model, idx) { + var node = tree.getNodeByDataIndex(idx); + + if (!node.children.length || !node.isExpand) { + model.parentModel = leavesModel; + } + + return model; + }); + } + + var treeDepth = 0; + tree.eachNode('preorder', function (node) { + if (node.depth > treeDepth) { + treeDepth = node.depth; + } + }); + var expandAndCollapse = option.expandAndCollapse; + var expandTreeDepth = expandAndCollapse && option.initialTreeDepth >= 0 ? option.initialTreeDepth : treeDepth; + tree.root.eachNode('preorder', function (node) { + var item = node.hostTree.data.getRawDataItem(node.dataIndex); + node.isExpand = item && item.collapsed != null ? !item.collapsed : node.depth <= expandTreeDepth; + }); + return tree.data; + }; + + TreeSeriesModel.prototype.getOrient = function () { + var orient = this.get('orient'); + + if (orient === 'horizontal') { + orient = 'LR'; + } else if (orient === 'vertical') { + orient = 'TB'; + } + + return orient; + }; + + TreeSeriesModel.prototype.setZoom = function (zoom) { + this.option.zoom = zoom; + }; + + TreeSeriesModel.prototype.setCenter = function (center) { + this.option.center = center; + }; + + TreeSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + var tree = this.getData().tree; + var realRoot = tree.root.children[0]; + var node = tree.getNodeByDataIndex(dataIndex); + var value = node.getValue(); + var name = node.name; + + while (node && node !== realRoot) { + name = node.parentNode.name + '.' + name; + node = node.parentNode; + } + + return createTooltipMarkup('nameValue', { + name: name, + value: value, + noValue: isNaN(value) || value == null + }); + }; + + TreeSeriesModel.type = 'series.tree'; + TreeSeriesModel.layoutMode = 'box'; + TreeSeriesModel.defaultOption = { + zlevel: 0, + z: 2, + coordinateSystem: 'view', + left: '12%', + top: '12%', + right: '12%', + bottom: '12%', + layout: 'orthogonal', + edgeShape: 'curve', + edgeForkPosition: '50%', + roam: false, + nodeScaleRatio: 0.4, + center: null, + zoom: 1, + orient: 'LR', + symbol: 'emptyCircle', + symbolSize: 7, + expandAndCollapse: true, + initialTreeDepth: 2, + lineStyle: { + color: '#ccc', + width: 1.5, + curveness: 0.5 + }, + itemStyle: { + color: 'lightsteelblue', + borderColor: '#c23531', + borderWidth: 1.5 + }, + label: { + show: true + }, + animationEasing: 'linear', + animationDuration: 700, + animationDurationUpdate: 500 + }; + return TreeSeriesModel; + }(SeriesModel); + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function eachAfter(root, callback, separation) { + var nodes = [root]; + var next = []; + var node; + + while (node = nodes.pop()) { + next.push(node); + + if (node.isExpand) { + var children = node.children; + + if (children.length) { + for (var i = 0; i < children.length; i++) { + nodes.push(children[i]); + } + } + } + } + + while (node = next.pop()) { + callback(node, separation); + } + } + + function eachBefore(root, callback) { + var nodes = [root]; + var node; + + while (node = nodes.pop()) { + callback(node); + + if (node.isExpand) { + var children = node.children; + + if (children.length) { + for (var i = children.length - 1; i >= 0; i--) { + nodes.push(children[i]); + } + } + } + } + } + + function treeLayout(ecModel, api) { + ecModel.eachSeriesByType('tree', function (seriesModel) { + commonLayout(seriesModel, api); + }); + } + + function commonLayout(seriesModel, api) { + var layoutInfo = getViewRect$1(seriesModel, api); + seriesModel.layoutInfo = layoutInfo; + var layout = seriesModel.get('layout'); + var width = 0; + var height = 0; + var separation$1 = null; + + if (layout === 'radial') { + width = 2 * Math.PI; + height = Math.min(layoutInfo.height, layoutInfo.width) / 2; + separation$1 = separation(function (node1, node2) { + return (node1.parentNode === node2.parentNode ? 1 : 2) / node1.depth; + }); + } else { + width = layoutInfo.width; + height = layoutInfo.height; + separation$1 = separation(); + } + + var virtualRoot = seriesModel.getData().tree.root; + var realRoot = virtualRoot.children[0]; + + if (realRoot) { + init$2(virtualRoot); + eachAfter(realRoot, firstWalk, separation$1); + virtualRoot.hierNode.modifier = -realRoot.hierNode.prelim; + eachBefore(realRoot, secondWalk); + var left_1 = realRoot; + var right_1 = realRoot; + var bottom_1 = realRoot; + eachBefore(realRoot, function (node) { + var x = node.getLayout().x; + + if (x < left_1.getLayout().x) { + left_1 = node; + } + + if (x > right_1.getLayout().x) { + right_1 = node; + } + + if (node.depth > bottom_1.depth) { + bottom_1 = node; + } + }); + var delta = left_1 === right_1 ? 1 : separation$1(left_1, right_1) / 2; + var tx_1 = delta - left_1.getLayout().x; + var kx_1 = 0; + var ky_1 = 0; + var coorX_1 = 0; + var coorY_1 = 0; + + if (layout === 'radial') { + kx_1 = width / (right_1.getLayout().x + delta + tx_1); + ky_1 = height / (bottom_1.depth - 1 || 1); + eachBefore(realRoot, function (node) { + coorX_1 = (node.getLayout().x + tx_1) * kx_1; + coorY_1 = (node.depth - 1) * ky_1; + var finalCoor = radialCoordinate(coorX_1, coorY_1); + node.setLayout({ + x: finalCoor.x, + y: finalCoor.y, + rawX: coorX_1, + rawY: coorY_1 + }, true); + }); + } else { + var orient_1 = seriesModel.getOrient(); + + if (orient_1 === 'RL' || orient_1 === 'LR') { + ky_1 = height / (right_1.getLayout().x + delta + tx_1); + kx_1 = width / (bottom_1.depth - 1 || 1); + eachBefore(realRoot, function (node) { + coorY_1 = (node.getLayout().x + tx_1) * ky_1; + coorX_1 = orient_1 === 'LR' ? (node.depth - 1) * kx_1 : width - (node.depth - 1) * kx_1; + node.setLayout({ + x: coorX_1, + y: coorY_1 + }, true); + }); + } else if (orient_1 === 'TB' || orient_1 === 'BT') { + kx_1 = width / (right_1.getLayout().x + delta + tx_1); + ky_1 = height / (bottom_1.depth - 1 || 1); + eachBefore(realRoot, function (node) { + coorX_1 = (node.getLayout().x + tx_1) * kx_1; + coorY_1 = orient_1 === 'TB' ? (node.depth - 1) * ky_1 : height - (node.depth - 1) * ky_1; + node.setLayout({ + x: coorX_1, + y: coorY_1 + }, true); + }); + } + } + } + } + + function treeVisual(ecModel) { + ecModel.eachSeriesByType('tree', function (seriesModel) { + var data = seriesModel.getData(); + var tree = data.tree; + tree.eachNode(function (node) { + var model = node.getModel(); + var style = model.getModel('itemStyle').getItemStyle(); + var existsStyle = data.ensureUniqueItemVisual(node.dataIndex, 'style'); + extend(existsStyle, style); + }); + }); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function updateCenterAndZoom(view, payload, zoomLimit) { + var previousZoom = view.getZoom(); + var center = view.getCenter(); + var zoom = payload.zoom; + var point = view.dataToPoint(center); + + if (payload.dx != null && payload.dy != null) { + point[0] -= payload.dx; + point[1] -= payload.dy; + view.setCenter(view.pointToData(point)); + } + + if (zoom != null) { + if (zoomLimit) { + var zoomMin = zoomLimit.min || 0; + var zoomMax = zoomLimit.max || Infinity; + zoom = Math.max(Math.min(previousZoom * zoom, zoomMax), zoomMin) / previousZoom; + } + + view.scaleX *= zoom; + view.scaleY *= zoom; + var fixX = (payload.originX - view.x) * (zoom - 1); + var fixY = (payload.originY - view.y) * (zoom - 1); + view.x -= fixX; + view.y -= fixY; + view.updateTransform(); + view.setCenter(view.pointToData(point)); + view.setZoom(zoom * previousZoom); + } + + return { + center: view.getCenter(), + zoom: view.getZoom() + }; + } + + function installTreeAction(registers) { + registers.registerAction({ + type: 'treeExpandAndCollapse', + event: 'treeExpandAndCollapse', + update: 'update' + }, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'series', + subType: 'tree', + query: payload + }, function (seriesModel) { + var dataIndex = payload.dataIndex; + var tree = seriesModel.getData().tree; + var node = tree.getNodeByDataIndex(dataIndex); + node.isExpand = !node.isExpand; + }); + }); + registers.registerAction({ + type: 'treeRoam', + event: 'treeRoam', + update: 'none' + }, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'series', + subType: 'tree', + query: payload + }, function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var res = updateCenterAndZoom(coordSys, payload); + seriesModel.setCenter && seriesModel.setCenter(res.center); + seriesModel.setZoom && seriesModel.setZoom(res.zoom); + }); + }); + } + + function install$a(registers) { + registers.registerChartView(TreeView); + registers.registerSeriesModel(TreeSeriesModel); + registers.registerLayout(treeLayout); + registers.registerVisual(treeVisual); + installTreeAction(registers); + } + + function retrieveTargetInfo(payload, validPayloadTypes, seriesModel) { + if (payload && indexOf(validPayloadTypes, payload.type) >= 0) { + var root = seriesModel.getData().tree.root; + var targetNode = payload.targetNode; + + if (typeof targetNode === 'string') { + targetNode = root.getNodeById(targetNode); + } + + if (targetNode && root.contains(targetNode)) { + return { + node: targetNode + }; + } + + var targetNodeId = payload.targetNodeId; + + if (targetNodeId != null && (targetNode = root.getNodeById(targetNodeId))) { + return { + node: targetNode + }; + } + } + } + function getPathToRoot(node) { + var path = []; + + while (node) { + node = node.parentNode; + node && path.push(node); + } + + return path.reverse(); + } + function aboveViewRoot(viewRoot, node) { + var viewPath = getPathToRoot(viewRoot); + return indexOf(viewPath, node) >= 0; + } + function wrapTreePathInfo(node, seriesModel) { + var treePathInfo = []; + + while (node) { + var nodeDataIndex = node.dataIndex; + treePathInfo.push({ + name: node.name, + dataIndex: nodeDataIndex, + value: seriesModel.getRawValue(nodeDataIndex) + }); + node = node.parentNode; + } + + treePathInfo.reverse(); + return treePathInfo; + } + + var noop$1 = function () {}; + + var actionTypes = ['treemapZoomToNode', 'treemapRender', 'treemapMove']; + function installTreemapAction(registers) { + for (var i = 0; i < actionTypes.length; i++) { + registers.registerAction({ + type: actionTypes[i], + update: 'updateView' + }, noop$1); + } + + registers.registerAction({ + type: 'treemapRootToNode', + update: 'updateView' + }, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'series', + subType: 'treemap', + query: payload + }, handleRootToNode); + + function handleRootToNode(model, index) { + var types = ['treemapZoomToNode', 'treemapRootToNode']; + var targetInfo = retrieveTargetInfo(payload, types, model); + + if (targetInfo) { + var originViewRoot = model.getViewRoot(); + + if (originViewRoot) { + payload.direction = aboveViewRoot(originViewRoot, targetInfo.node) ? 'rollUp' : 'drillDown'; + } + + model.resetViewRoot(targetInfo.node); + } + } + }); + } + + function enableAriaDecalForTree(seriesModel) { + var data = seriesModel.getData(); + var tree = data.tree; + var decalPaletteScope = {}; + tree.eachNode(function (node) { + var current = node; + + while (current && current.depth > 1) { + current = current.parentNode; + } + + var decal = getDecalFromPalette(seriesModel.ecModel, current.name || current.dataIndex + '', decalPaletteScope); + node.setVisual('decal', decal); + }); + } + + var TreemapSeriesModel = function (_super) { + __extends(TreemapSeriesModel, _super); + + function TreemapSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TreemapSeriesModel.type; + _this.preventUsingHoverLayer = true; + return _this; + } + + TreemapSeriesModel.prototype.getInitialData = function (option, ecModel) { + var root = { + name: option.name, + children: option.data + }; + completeTreeValue(root); + var levels = option.levels || []; + var designatedVisualItemStyle = this.designatedVisualItemStyle = {}; + var designatedVisualModel = new Model({ + itemStyle: designatedVisualItemStyle + }, this, ecModel); + levels = option.levels = setDefault(levels, ecModel); + var levelModels = map(levels || [], function (levelDefine) { + return new Model(levelDefine, designatedVisualModel, ecModel); + }, this); + var tree = Tree.createTree(root, this, beforeLink); + + function beforeLink(nodeData) { + nodeData.wrapMethod('getItemModel', function (model, idx) { + var node = tree.getNodeByDataIndex(idx); + var levelModel = levelModels[node.depth]; + model.parentModel = levelModel || designatedVisualModel; + return model; + }); + } + + return tree.data; + }; + + TreemapSeriesModel.prototype.optionUpdated = function () { + this.resetViewRoot(); + }; + + TreemapSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + var data = this.getData(); + var value = this.getRawValue(dataIndex); + var name = data.getName(dataIndex); + return createTooltipMarkup('nameValue', { + name: name, + value: value + }); + }; + + TreemapSeriesModel.prototype.getDataParams = function (dataIndex) { + var params = _super.prototype.getDataParams.apply(this, arguments); + + var node = this.getData().tree.getNodeByDataIndex(dataIndex); + params.treePathInfo = wrapTreePathInfo(node, this); + return params; + }; + + TreemapSeriesModel.prototype.setLayoutInfo = function (layoutInfo) { + this.layoutInfo = this.layoutInfo || {}; + extend(this.layoutInfo, layoutInfo); + }; + + TreemapSeriesModel.prototype.mapIdToIndex = function (id) { + var idIndexMap = this._idIndexMap; + + if (!idIndexMap) { + idIndexMap = this._idIndexMap = createHashMap(); + this._idIndexMapCount = 0; + } + + var index = idIndexMap.get(id); + + if (index == null) { + idIndexMap.set(id, index = this._idIndexMapCount++); + } + + return index; + }; + + TreemapSeriesModel.prototype.getViewRoot = function () { + return this._viewRoot; + }; + + TreemapSeriesModel.prototype.resetViewRoot = function (viewRoot) { + viewRoot ? this._viewRoot = viewRoot : viewRoot = this._viewRoot; + var root = this.getRawData().tree.root; + + if (!viewRoot || viewRoot !== root && !root.contains(viewRoot)) { + this._viewRoot = root; + } + }; + + TreemapSeriesModel.prototype.enableAriaDecal = function () { + enableAriaDecalForTree(this); + }; + + TreemapSeriesModel.type = 'series.treemap'; + TreemapSeriesModel.layoutMode = 'box'; + TreemapSeriesModel.defaultOption = { + progressive: 0, + left: 'center', + top: 'middle', + width: '80%', + height: '80%', + sort: true, + clipWindow: 'origin', + squareRatio: 0.5 * (1 + Math.sqrt(5)), + leafDepth: null, + drillDownIcon: '▶', + zoomToNodeRatio: 0.32 * 0.32, + roam: true, + nodeClick: 'zoomToNode', + animation: true, + animationDurationUpdate: 900, + animationEasing: 'quinticInOut', + breadcrumb: { + show: true, + height: 22, + left: 'center', + top: 'bottom', + emptyItemWidth: 25, + itemStyle: { + color: 'rgba(0,0,0,0.7)', + textStyle: { + color: '#fff' + } + } + }, + label: { + show: true, + distance: 0, + padding: 5, + position: 'inside', + color: '#fff', + overflow: 'truncate' + }, + upperLabel: { + show: false, + position: [0, '50%'], + height: 20, + overflow: 'truncate', + verticalAlign: 'middle' + }, + itemStyle: { + color: null, + colorAlpha: null, + colorSaturation: null, + borderWidth: 0, + gapWidth: 0, + borderColor: '#fff', + borderColorSaturation: null + }, + emphasis: { + upperLabel: { + show: true, + position: [0, '50%'], + ellipsis: true, + verticalAlign: 'middle' + } + }, + visualDimension: 0, + visualMin: null, + visualMax: null, + color: [], + colorAlpha: null, + colorSaturation: null, + colorMappingBy: 'index', + visibleMin: 10, + childrenVisibleMin: null, + levels: [] + }; + return TreemapSeriesModel; + }(SeriesModel); + + function completeTreeValue(dataNode) { + var sum = 0; + each(dataNode.children, function (child) { + completeTreeValue(child); + var childValue = child.value; + isArray(childValue) && (childValue = childValue[0]); + sum += childValue; + }); + var thisValue = dataNode.value; + + if (isArray(thisValue)) { + thisValue = thisValue[0]; + } + + if (thisValue == null || isNaN(thisValue)) { + thisValue = sum; + } + + if (thisValue < 0) { + thisValue = 0; + } + + isArray(dataNode.value) ? dataNode.value[0] = thisValue : dataNode.value = thisValue; + } + + function setDefault(levels, ecModel) { + var globalColorList = normalizeToArray(ecModel.get('color')); + var globalDecalList = normalizeToArray(ecModel.get(['aria', 'decal', 'decals'])); + + if (!globalColorList) { + return; + } + + levels = levels || []; + var hasColorDefine; + var hasDecalDefine; + each(levels, function (levelDefine) { + var model = new Model(levelDefine); + var modelColor = model.get('color'); + var modelDecal = model.get('decal'); + + if (model.get(['itemStyle', 'color']) || modelColor && modelColor !== 'none') { + hasColorDefine = true; + } + + if (model.get(['itemStyle', 'decal']) || modelDecal && modelDecal !== 'none') { + hasDecalDefine = true; + } + }); + var level0 = levels[0] || (levels[0] = {}); + + if (!hasColorDefine) { + level0.color = globalColorList.slice(); + } + + if (!hasDecalDefine && globalDecalList) { + level0.decal = globalDecalList.slice(); + } + + return levels; + } + + var TEXT_PADDING = 8; + var ITEM_GAP = 8; + var ARRAY_LENGTH = 5; + + var Breadcrumb = function () { + function Breadcrumb(containerGroup) { + this.group = new Group(); + containerGroup.add(this.group); + } + + Breadcrumb.prototype.render = function (seriesModel, api, targetNode, onSelect) { + var model = seriesModel.getModel('breadcrumb'); + var thisGroup = this.group; + thisGroup.removeAll(); + + if (!model.get('show') || !targetNode) { + return; + } + + var normalStyleModel = model.getModel('itemStyle'); + var textStyleModel = normalStyleModel.getModel('textStyle'); + var layoutParam = { + pos: { + left: model.get('left'), + right: model.get('right'), + top: model.get('top'), + bottom: model.get('bottom') + }, + box: { + width: api.getWidth(), + height: api.getHeight() + }, + emptyItemWidth: model.get('emptyItemWidth'), + totalWidth: 0, + renderList: [] + }; + + this._prepare(targetNode, layoutParam, textStyleModel); + + this._renderContent(seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect); + + positionElement(thisGroup, layoutParam.pos, layoutParam.box); + }; + + Breadcrumb.prototype._prepare = function (targetNode, layoutParam, textStyleModel) { + for (var node = targetNode; node; node = node.parentNode) { + var text = convertOptionIdName(node.getModel().get('name'), ''); + var textRect = textStyleModel.getTextRect(text); + var itemWidth = Math.max(textRect.width + TEXT_PADDING * 2, layoutParam.emptyItemWidth); + layoutParam.totalWidth += itemWidth + ITEM_GAP; + layoutParam.renderList.push({ + node: node, + text: text, + width: itemWidth + }); + } + }; + + Breadcrumb.prototype._renderContent = function (seriesModel, layoutParam, normalStyleModel, textStyleModel, onSelect) { + var lastX = 0; + var emptyItemWidth = layoutParam.emptyItemWidth; + var height = seriesModel.get(['breadcrumb', 'height']); + var availableSize = getAvailableSize(layoutParam.pos, layoutParam.box); + var totalWidth = layoutParam.totalWidth; + var renderList = layoutParam.renderList; + + for (var i = renderList.length - 1; i >= 0; i--) { + var item = renderList[i]; + var itemNode = item.node; + var itemWidth = item.width; + var text = item.text; + + if (totalWidth > availableSize.width) { + totalWidth -= itemWidth - emptyItemWidth; + itemWidth = emptyItemWidth; + text = null; + } + + var el = new Polygon({ + shape: { + points: makeItemPoints(lastX, 0, itemWidth, height, i === renderList.length - 1, i === 0) + }, + style: defaults(normalStyleModel.getItemStyle(), { + lineJoin: 'bevel' + }), + textContent: new ZRText({ + style: { + text: text, + fill: textStyleModel.getTextColor(), + font: textStyleModel.getFont() + } + }), + textConfig: { + position: 'inside' + }, + z: 10, + onclick: curry(onSelect, itemNode) + }); + el.disableLabelAnimation = true; + this.group.add(el); + packEventData(el, seriesModel, itemNode); + lastX += itemWidth + ITEM_GAP; + } + }; + + Breadcrumb.prototype.remove = function () { + this.group.removeAll(); + }; + + return Breadcrumb; + }(); + + function makeItemPoints(x, y, itemWidth, itemHeight, head, tail) { + var points = [[head ? x : x - ARRAY_LENGTH, y], [x + itemWidth, y], [x + itemWidth, y + itemHeight], [head ? x : x - ARRAY_LENGTH, y + itemHeight]]; + !tail && points.splice(2, 0, [x + itemWidth + ARRAY_LENGTH, y + itemHeight / 2]); + !head && points.push([x, y + itemHeight / 2]); + return points; + } + + function packEventData(el, seriesModel, itemNode) { + getECData(el).eventData = { + componentType: 'series', + componentSubType: 'treemap', + componentIndex: seriesModel.componentIndex, + seriesIndex: seriesModel.componentIndex, + seriesName: seriesModel.name, + seriesType: 'treemap', + selfType: 'breadcrumb', + nodeData: { + dataIndex: itemNode && itemNode.dataIndex, + name: itemNode && itemNode.name + }, + treePathInfo: itemNode && wrapTreePathInfo(itemNode, seriesModel) + }; + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var AnimationWrap = function () { + function AnimationWrap() { + this._storage = []; + this._elExistsMap = {}; + } + + AnimationWrap.prototype.add = function (el, target, duration, delay, easing) { + if (this._elExistsMap[el.id]) { + return false; + } + + this._elExistsMap[el.id] = true; + + this._storage.push({ + el: el, + target: target, + duration: duration, + delay: delay, + easing: easing + }); + + return true; + }; + + AnimationWrap.prototype.finished = function (callback) { + this._finishedCallback = callback; + return this; + }; + + AnimationWrap.prototype.start = function () { + var _this = this; + + var count = this._storage.length; + + var checkTerminate = function () { + count--; + + if (count <= 0) { + _this._storage.length = 0; + _this._elExistsMap = {}; + _this._finishedCallback && _this._finishedCallback(); + } + }; + + for (var i = 0, len = this._storage.length; i < len; i++) { + var item = this._storage[i]; + item.el.animateTo(item.target, { + duration: item.duration, + delay: item.delay, + easing: item.easing, + setToFinal: true, + done: checkTerminate, + aborted: checkTerminate + }); + } + + return this; + }; + + return AnimationWrap; + }(); + + function createWrap() { + return new AnimationWrap(); + } + + var Group$1 = Group; + var Rect$1 = Rect; + var DRAG_THRESHOLD = 3; + var PATH_LABEL_NOAMAL = 'label'; + var PATH_UPPERLABEL_NORMAL = 'upperLabel'; + var Z_BASE = 10; + var Z_BG = 1; + var Z_CONTENT = 2; + var getStateItemStyle = makeStyleMapper([['fill', 'color'], ['stroke', 'strokeColor'], ['lineWidth', 'strokeWidth'], ['shadowBlur'], ['shadowOffsetX'], ['shadowOffsetY'], ['shadowColor']]); + + var getItemStyleNormal = function (model) { + var itemStyle = getStateItemStyle(model); + itemStyle.stroke = itemStyle.fill = itemStyle.lineWidth = null; + return itemStyle; + }; + + var inner$9 = makeInner(); + + var TreemapView = function (_super) { + __extends(TreemapView, _super); + + function TreemapView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TreemapView.type; + _this._state = 'ready'; + _this._storage = createStorage(); + return _this; + } + + TreemapView.prototype.render = function (seriesModel, ecModel, api, payload) { + var models = ecModel.findComponents({ + mainType: 'series', + subType: 'treemap', + query: payload + }); + + if (indexOf(models, seriesModel) < 0) { + return; + } + + this.seriesModel = seriesModel; + this.api = api; + this.ecModel = ecModel; + var types = ['treemapZoomToNode', 'treemapRootToNode']; + var targetInfo = retrieveTargetInfo(payload, types, seriesModel); + var payloadType = payload && payload.type; + var layoutInfo = seriesModel.layoutInfo; + var isInit = !this._oldTree; + var thisStorage = this._storage; + var reRoot = payloadType === 'treemapRootToNode' && targetInfo && thisStorage ? { + rootNodeGroup: thisStorage.nodeGroup[targetInfo.node.getRawIndex()], + direction: payload.direction + } : null; + + var containerGroup = this._giveContainerGroup(layoutInfo); + + var renderResult = this._doRender(containerGroup, seriesModel, reRoot); + + !isInit && (!payloadType || payloadType === 'treemapZoomToNode' || payloadType === 'treemapRootToNode') ? this._doAnimation(containerGroup, renderResult, seriesModel, reRoot) : renderResult.renderFinally(); + + this._resetController(api); + + this._renderBreadcrumb(seriesModel, api, targetInfo); + }; + + TreemapView.prototype._giveContainerGroup = function (layoutInfo) { + var containerGroup = this._containerGroup; + + if (!containerGroup) { + containerGroup = this._containerGroup = new Group$1(); + + this._initEvents(containerGroup); + + this.group.add(containerGroup); + } + + containerGroup.x = layoutInfo.x; + containerGroup.y = layoutInfo.y; + return containerGroup; + }; + + TreemapView.prototype._doRender = function (containerGroup, seriesModel, reRoot) { + var thisTree = seriesModel.getData().tree; + var oldTree = this._oldTree; + var lastsForAnimation = createStorage(); + var thisStorage = createStorage(); + var oldStorage = this._storage; + var willInvisibleEls = []; + + function doRenderNode(thisNode, oldNode, parentGroup, depth) { + return renderNode(seriesModel, thisStorage, oldStorage, reRoot, lastsForAnimation, willInvisibleEls, thisNode, oldNode, parentGroup, depth); + } + + dualTravel(thisTree.root ? [thisTree.root] : [], oldTree && oldTree.root ? [oldTree.root] : [], containerGroup, thisTree === oldTree || !oldTree, 0); + var willDeleteEls = clearStorage(oldStorage); + this._oldTree = thisTree; + this._storage = thisStorage; + return { + lastsForAnimation: lastsForAnimation, + willDeleteEls: willDeleteEls, + renderFinally: renderFinally + }; + + function dualTravel(thisViewChildren, oldViewChildren, parentGroup, sameTree, depth) { + if (sameTree) { + oldViewChildren = thisViewChildren; + each(thisViewChildren, function (child, index) { + !child.isRemoved() && processNode(index, index); + }); + } else { + new DataDiffer(oldViewChildren, thisViewChildren, getKey, getKey).add(processNode).update(processNode).remove(curry(processNode, null)).execute(); + } + + function getKey(node) { + return node.getId(); + } + + function processNode(newIndex, oldIndex) { + var thisNode = newIndex != null ? thisViewChildren[newIndex] : null; + var oldNode = oldIndex != null ? oldViewChildren[oldIndex] : null; + var group = doRenderNode(thisNode, oldNode, parentGroup, depth); + group && dualTravel(thisNode && thisNode.viewChildren || [], oldNode && oldNode.viewChildren || [], group, sameTree, depth + 1); + } + } + + function clearStorage(storage) { + var willDeleteEls = createStorage(); + storage && each(storage, function (store, storageName) { + var delEls = willDeleteEls[storageName]; + each(store, function (el) { + el && (delEls.push(el), inner$9(el).willDelete = true); + }); + }); + return willDeleteEls; + } + + function renderFinally() { + each(willDeleteEls, function (els) { + each(els, function (el) { + el.parent && el.parent.remove(el); + }); + }); + each(willInvisibleEls, function (el) { + el.invisible = true; + el.dirty(); + }); + } + }; + + TreemapView.prototype._doAnimation = function (containerGroup, renderResult, seriesModel, reRoot) { + if (!seriesModel.get('animation')) { + return; + } + + var durationOption = seriesModel.get('animationDurationUpdate'); + var easingOption = seriesModel.get('animationEasing'); + var duration = (isFunction(durationOption) ? 0 : durationOption) || 0; + var easing = (isFunction(easingOption) ? null : easingOption) || 'cubicOut'; + var animationWrap = createWrap(); + each(renderResult.willDeleteEls, function (store, storageName) { + each(store, function (el, rawIndex) { + if (el.invisible) { + return; + } + + var parent = el.parent; + var target; + var innerStore = inner$9(parent); + + if (reRoot && reRoot.direction === 'drillDown') { + target = parent === reRoot.rootNodeGroup ? { + shape: { + x: 0, + y: 0, + width: innerStore.nodeWidth, + height: innerStore.nodeHeight + }, + style: { + opacity: 0 + } + } : { + style: { + opacity: 0 + } + }; + } else { + var targetX = 0; + var targetY = 0; + + if (!innerStore.willDelete) { + targetX = innerStore.nodeWidth / 2; + targetY = innerStore.nodeHeight / 2; + } + + target = storageName === 'nodeGroup' ? { + x: targetX, + y: targetY, + style: { + opacity: 0 + } + } : { + shape: { + x: targetX, + y: targetY, + width: 0, + height: 0 + }, + style: { + opacity: 0 + } + }; + } + + target && animationWrap.add(el, target, duration, 0, easing); + }); + }); + each(this._storage, function (store, storageName) { + each(store, function (el, rawIndex) { + var last = renderResult.lastsForAnimation[storageName][rawIndex]; + var target = {}; + + if (!last) { + return; + } + + if (el instanceof Group) { + if (last.oldX != null) { + target.x = el.x; + target.y = el.y; + el.x = last.oldX; + el.y = last.oldY; + } + } else { + if (last.oldShape) { + target.shape = extend({}, el.shape); + el.setShape(last.oldShape); + } + + if (last.fadein) { + el.setStyle('opacity', 0); + target.style = { + opacity: 1 + }; + } else if (el.style.opacity !== 1) { + target.style = { + opacity: 1 + }; + } + } + + animationWrap.add(el, target, duration, 0, easing); + }); + }, this); + this._state = 'animating'; + animationWrap.finished(bind(function () { + this._state = 'ready'; + renderResult.renderFinally(); + }, this)).start(); + }; + + TreemapView.prototype._resetController = function (api) { + var controller = this._controller; + + if (!controller) { + controller = this._controller = new RoamController(api.getZr()); + controller.enable(this.seriesModel.get('roam')); + controller.on('pan', bind(this._onPan, this)); + controller.on('zoom', bind(this._onZoom, this)); + } + + var rect = new BoundingRect(0, 0, api.getWidth(), api.getHeight()); + controller.setPointerChecker(function (e, x, y) { + return rect.contain(x, y); + }); + }; + + TreemapView.prototype._clearController = function () { + var controller = this._controller; + + if (controller) { + controller.dispose(); + controller = null; + } + }; + + TreemapView.prototype._onPan = function (e) { + if (this._state !== 'animating' && (Math.abs(e.dx) > DRAG_THRESHOLD || Math.abs(e.dy) > DRAG_THRESHOLD)) { + var root = this.seriesModel.getData().tree.root; + + if (!root) { + return; + } + + var rootLayout = root.getLayout(); + + if (!rootLayout) { + return; + } + + this.api.dispatchAction({ + type: 'treemapMove', + from: this.uid, + seriesId: this.seriesModel.id, + rootRect: { + x: rootLayout.x + e.dx, + y: rootLayout.y + e.dy, + width: rootLayout.width, + height: rootLayout.height + } + }); + } + }; + + TreemapView.prototype._onZoom = function (e) { + var mouseX = e.originX; + var mouseY = e.originY; + + if (this._state !== 'animating') { + var root = this.seriesModel.getData().tree.root; + + if (!root) { + return; + } + + var rootLayout = root.getLayout(); + + if (!rootLayout) { + return; + } + + var rect = new BoundingRect(rootLayout.x, rootLayout.y, rootLayout.width, rootLayout.height); + var layoutInfo = this.seriesModel.layoutInfo; + mouseX -= layoutInfo.x; + mouseY -= layoutInfo.y; + var m = create$1(); + translate(m, m, [-mouseX, -mouseY]); + scale$1(m, m, [e.scale, e.scale]); + translate(m, m, [mouseX, mouseY]); + rect.applyTransform(m); + this.api.dispatchAction({ + type: 'treemapRender', + from: this.uid, + seriesId: this.seriesModel.id, + rootRect: { + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + } + }); + } + }; + + TreemapView.prototype._initEvents = function (containerGroup) { + var _this = this; + + containerGroup.on('click', function (e) { + if (_this._state !== 'ready') { + return; + } + + var nodeClick = _this.seriesModel.get('nodeClick', true); + + if (!nodeClick) { + return; + } + + var targetInfo = _this.findTarget(e.offsetX, e.offsetY); + + if (!targetInfo) { + return; + } + + var node = targetInfo.node; + + if (node.getLayout().isLeafRoot) { + _this._rootToNode(targetInfo); + } else { + if (nodeClick === 'zoomToNode') { + _this._zoomToNode(targetInfo); + } else if (nodeClick === 'link') { + var itemModel = node.hostTree.data.getItemModel(node.dataIndex); + var link = itemModel.get('link', true); + var linkTarget = itemModel.get('target', true) || 'blank'; + link && windowOpen(link, linkTarget); + } + } + }, this); + }; + + TreemapView.prototype._renderBreadcrumb = function (seriesModel, api, targetInfo) { + var _this = this; + + if (!targetInfo) { + targetInfo = seriesModel.get('leafDepth', true) != null ? { + node: seriesModel.getViewRoot() + } : this.findTarget(api.getWidth() / 2, api.getHeight() / 2); + + if (!targetInfo) { + targetInfo = { + node: seriesModel.getData().tree.root + }; + } + } + + (this._breadcrumb || (this._breadcrumb = new Breadcrumb(this.group))).render(seriesModel, api, targetInfo.node, function (node) { + if (_this._state !== 'animating') { + aboveViewRoot(seriesModel.getViewRoot(), node) ? _this._rootToNode({ + node: node + }) : _this._zoomToNode({ + node: node + }); + } + }); + }; + + TreemapView.prototype.remove = function () { + this._clearController(); + + this._containerGroup && this._containerGroup.removeAll(); + this._storage = createStorage(); + this._state = 'ready'; + this._breadcrumb && this._breadcrumb.remove(); + }; + + TreemapView.prototype.dispose = function () { + this._clearController(); + }; + + TreemapView.prototype._zoomToNode = function (targetInfo) { + this.api.dispatchAction({ + type: 'treemapZoomToNode', + from: this.uid, + seriesId: this.seriesModel.id, + targetNode: targetInfo.node + }); + }; + + TreemapView.prototype._rootToNode = function (targetInfo) { + this.api.dispatchAction({ + type: 'treemapRootToNode', + from: this.uid, + seriesId: this.seriesModel.id, + targetNode: targetInfo.node + }); + }; + + TreemapView.prototype.findTarget = function (x, y) { + var targetInfo; + var viewRoot = this.seriesModel.getViewRoot(); + viewRoot.eachNode({ + attr: 'viewChildren', + order: 'preorder' + }, function (node) { + var bgEl = this._storage.background[node.getRawIndex()]; + + if (bgEl) { + var point = bgEl.transformCoordToLocal(x, y); + var shape = bgEl.shape; + + if (shape.x <= point[0] && point[0] <= shape.x + shape.width && shape.y <= point[1] && point[1] <= shape.y + shape.height) { + targetInfo = { + node: node, + offsetX: point[0], + offsetY: point[1] + }; + } else { + return false; + } + } + }, this); + return targetInfo; + }; + + TreemapView.type = 'treemap'; + return TreemapView; + }(ChartView); + + function createStorage() { + return { + nodeGroup: [], + background: [], + content: [] + }; + } + + function renderNode(seriesModel, thisStorage, oldStorage, reRoot, lastsForAnimation, willInvisibleEls, thisNode, oldNode, parentGroup, depth) { + if (!thisNode) { + return; + } + + var thisLayout = thisNode.getLayout(); + var data = seriesModel.getData(); + var nodeModel = thisNode.getModel(); + data.setItemGraphicEl(thisNode.dataIndex, null); + + if (!thisLayout || !thisLayout.isInView) { + return; + } + + var thisWidth = thisLayout.width; + var thisHeight = thisLayout.height; + var borderWidth = thisLayout.borderWidth; + var thisInvisible = thisLayout.invisible; + var thisRawIndex = thisNode.getRawIndex(); + var oldRawIndex = oldNode && oldNode.getRawIndex(); + var thisViewChildren = thisNode.viewChildren; + var upperHeight = thisLayout.upperHeight; + var isParent = thisViewChildren && thisViewChildren.length; + var itemStyleNormalModel = nodeModel.getModel('itemStyle'); + var itemStyleEmphasisModel = nodeModel.getModel(['emphasis', 'itemStyle']); + var itemStyleBlurModel = nodeModel.getModel(['blur', 'itemStyle']); + var itemStyleSelectModel = nodeModel.getModel(['select', 'itemStyle']); + var borderRadius = itemStyleNormalModel.get('borderRadius') || 0; + var group = giveGraphic('nodeGroup', Group$1); + + if (!group) { + return; + } + + parentGroup.add(group); + group.x = thisLayout.x || 0; + group.y = thisLayout.y || 0; + group.markRedraw(); + inner$9(group).nodeWidth = thisWidth; + inner$9(group).nodeHeight = thisHeight; + + if (thisLayout.isAboveViewRoot) { + return group; + } + + var bg = giveGraphic('background', Rect$1, depth, Z_BG); + bg && renderBackground(group, bg, isParent && thisLayout.upperLabelHeight); + var focus = nodeModel.get(['emphasis', 'focus']); + var blurScope = nodeModel.get(['emphasis', 'blurScope']); + var focusDataIndices = focus === 'ancestor' ? thisNode.getAncestorsIndices() : focus === 'descendant' ? thisNode.getDescendantIndices() : null; + + if (isParent) { + if (isHighDownDispatcher(group)) { + setAsHighDownDispatcher(group, false); + } + + if (bg) { + setAsHighDownDispatcher(bg, true); + data.setItemGraphicEl(thisNode.dataIndex, bg); + enableHoverFocus(bg, focusDataIndices || focus, blurScope); + } + } else { + var content = giveGraphic('content', Rect$1, depth, Z_CONTENT); + content && renderContent(group, content); + + if (bg && isHighDownDispatcher(bg)) { + setAsHighDownDispatcher(bg, false); + } + + setAsHighDownDispatcher(group, true); + data.setItemGraphicEl(thisNode.dataIndex, group); + enableHoverFocus(group, focusDataIndices || focus, blurScope); + } + + return group; + + function renderBackground(group, bg, useUpperLabel) { + var ecData = getECData(bg); + ecData.dataIndex = thisNode.dataIndex; + ecData.seriesIndex = seriesModel.seriesIndex; + bg.setShape({ + x: 0, + y: 0, + width: thisWidth, + height: thisHeight, + r: borderRadius + }); + + if (thisInvisible) { + processInvisible(bg); + } else { + bg.invisible = false; + var style = thisNode.getVisual('style'); + var visualBorderColor = style.stroke; + var normalStyle = getItemStyleNormal(itemStyleNormalModel); + normalStyle.fill = visualBorderColor; + var emphasisStyle = getStateItemStyle(itemStyleEmphasisModel); + emphasisStyle.fill = itemStyleEmphasisModel.get('borderColor'); + var blurStyle = getStateItemStyle(itemStyleBlurModel); + blurStyle.fill = itemStyleBlurModel.get('borderColor'); + var selectStyle = getStateItemStyle(itemStyleSelectModel); + selectStyle.fill = itemStyleSelectModel.get('borderColor'); + + if (useUpperLabel) { + var upperLabelWidth = thisWidth - 2 * borderWidth; + prepareText(bg, visualBorderColor, upperLabelWidth, upperHeight, style.opacity, { + x: borderWidth, + y: 0, + width: upperLabelWidth, + height: upperHeight + }); + } else { + bg.removeTextContent(); + } + + bg.setStyle(normalStyle); + bg.ensureState('emphasis').style = emphasisStyle; + bg.ensureState('blur').style = blurStyle; + bg.ensureState('select').style = selectStyle; + setDefaultStateProxy(bg); + } + + group.add(bg); + } + + function renderContent(group, content) { + var ecData = getECData(content); + ecData.dataIndex = thisNode.dataIndex; + ecData.seriesIndex = seriesModel.seriesIndex; + var contentWidth = Math.max(thisWidth - 2 * borderWidth, 0); + var contentHeight = Math.max(thisHeight - 2 * borderWidth, 0); + content.culling = true; + content.setShape({ + x: borderWidth, + y: borderWidth, + width: contentWidth, + height: contentHeight, + r: borderRadius + }); + + if (thisInvisible) { + processInvisible(content); + } else { + content.invisible = false; + var nodeStyle = thisNode.getVisual('style'); + var visualColor = nodeStyle.fill; + var normalStyle = getItemStyleNormal(itemStyleNormalModel); + normalStyle.fill = visualColor; + normalStyle.decal = nodeStyle.decal; + var emphasisStyle = getStateItemStyle(itemStyleEmphasisModel); + var blurStyle = getStateItemStyle(itemStyleBlurModel); + var selectStyle = getStateItemStyle(itemStyleSelectModel); + prepareText(content, visualColor, contentWidth, nodeStyle.opacity); + content.setStyle(normalStyle); + content.ensureState('emphasis').style = emphasisStyle; + content.ensureState('blur').style = blurStyle; + content.ensureState('select').style = selectStyle; + setDefaultStateProxy(content); + } + + group.add(content); + } + + function processInvisible(element) { + !element.invisible && willInvisibleEls.push(element); + } + + function prepareText(rectEl, visualColor, visualOpacity, width, height, upperLabelRect) { + var normalLabelModel = nodeModel.getModel(upperLabelRect ? PATH_UPPERLABEL_NORMAL : PATH_LABEL_NOAMAL); + var text = retrieve(seriesModel.getFormattedLabel(thisNode.dataIndex, 'normal', null, null, normalLabelModel.get('formatter')), convertOptionIdName(nodeModel.get('name'), null)); + + if (!upperLabelRect && thisLayout.isLeafRoot) { + var iconChar = seriesModel.get('drillDownIcon', true); + text = iconChar ? iconChar + ' ' + text : text; + } + + var isShow = normalLabelModel.getShallow('show'); + setLabelStyle(rectEl, getLabelStatesModels(nodeModel, upperLabelRect ? PATH_UPPERLABEL_NORMAL : PATH_LABEL_NOAMAL), { + defaultText: isShow ? text : null, + inheritColor: visualColor, + defaultOpacity: visualOpacity, + labelFetcher: seriesModel, + labelDataIndex: thisNode.dataIndex + }); + var textEl = rectEl.getTextContent(); + var textStyle = textEl.style; + var textPadding = normalizeCssArray(textStyle.padding || 0); + + if (upperLabelRect) { + rectEl.setTextConfig({ + layoutRect: upperLabelRect + }); + textEl.disableLabelLayout = true; + } + + textEl.beforeUpdate = function () { + var width = Math.max((upperLabelRect ? upperLabelRect.width : rectEl.shape.width) - textPadding[1] - textPadding[3], 0); + var height = Math.max((upperLabelRect ? upperLabelRect.height : rectEl.shape.height) - textPadding[0] - textPadding[2], 0); + + if (textStyle.width !== width || textStyle.height !== height) { + textEl.setStyle({ + width: width, + height: height + }); + } + }; + + textStyle.truncateMinChar = 2; + textStyle.lineOverflow = 'truncate'; + addDrillDownIcon(textStyle, upperLabelRect, thisLayout); + var textEmphasisState = textEl.getState('emphasis'); + addDrillDownIcon(textEmphasisState ? textEmphasisState.style : null, upperLabelRect, thisLayout); + } + + function addDrillDownIcon(style, upperLabelRect, thisLayout) { + var text = style ? style.text : null; + + if (!upperLabelRect && thisLayout.isLeafRoot && text != null) { + var iconChar = seriesModel.get('drillDownIcon', true); + style.text = iconChar ? iconChar + ' ' + text : text; + } + } + + function giveGraphic(storageName, Ctor, depth, z) { + var element = oldRawIndex != null && oldStorage[storageName][oldRawIndex]; + var lasts = lastsForAnimation[storageName]; + + if (element) { + oldStorage[storageName][oldRawIndex] = null; + prepareAnimationWhenHasOld(lasts, element); + } else if (!thisInvisible) { + element = new Ctor(); + + if (element instanceof Displayable) { + element.z = calculateZ(depth, z); + } + + prepareAnimationWhenNoOld(lasts, element); + } + + return thisStorage[storageName][thisRawIndex] = element; + } + + function prepareAnimationWhenHasOld(lasts, element) { + var lastCfg = lasts[thisRawIndex] = {}; + + if (element instanceof Group$1) { + lastCfg.oldX = element.x; + lastCfg.oldY = element.y; + } else { + lastCfg.oldShape = extend({}, element.shape); + } + } + + function prepareAnimationWhenNoOld(lasts, element) { + var lastCfg = lasts[thisRawIndex] = {}; + var parentNode = thisNode.parentNode; + var isGroup = element instanceof Group; + + if (parentNode && (!reRoot || reRoot.direction === 'drillDown')) { + var parentOldX = 0; + var parentOldY = 0; + var parentOldBg = lastsForAnimation.background[parentNode.getRawIndex()]; + + if (!reRoot && parentOldBg && parentOldBg.oldShape) { + parentOldX = parentOldBg.oldShape.width; + parentOldY = parentOldBg.oldShape.height; + } + + if (isGroup) { + lastCfg.oldX = 0; + lastCfg.oldY = parentOldY; + } else { + lastCfg.oldShape = { + x: parentOldX, + y: parentOldY, + width: 0, + height: 0 + }; + } + } + + lastCfg.fadein = !isGroup; + } + } + + function calculateZ(depth, zInLevel) { + var zb = depth * Z_BASE + zInLevel; + return (zb - 1) / zb; + } + + var each$4 = each; + var isObject$4 = isObject; + var CATEGORY_DEFAULT_VISUAL_INDEX = -1; + + var VisualMapping = function () { + function VisualMapping(option) { + var mappingMethod = option.mappingMethod; + var visualType = option.type; + var thisOption = this.option = clone(option); + this.type = visualType; + this.mappingMethod = mappingMethod; + this._normalizeData = normalizers[mappingMethod]; + var visualHandler = VisualMapping.visualHandlers[visualType]; + this.applyVisual = visualHandler.applyVisual; + this.getColorMapper = visualHandler.getColorMapper; + this._normalizedToVisual = visualHandler._normalizedToVisual[mappingMethod]; + + if (mappingMethod === 'piecewise') { + normalizeVisualRange(thisOption); + preprocessForPiecewise(thisOption); + } else if (mappingMethod === 'category') { + thisOption.categories ? preprocessForSpecifiedCategory(thisOption) : normalizeVisualRange(thisOption, true); + } else { + assert(mappingMethod !== 'linear' || thisOption.dataExtent); + normalizeVisualRange(thisOption); + } + } + + VisualMapping.prototype.mapValueToVisual = function (value) { + var normalized = this._normalizeData(value); + + return this._normalizedToVisual(normalized, value); + }; + + VisualMapping.prototype.getNormalizer = function () { + return bind(this._normalizeData, this); + }; + + VisualMapping.listVisualTypes = function () { + return keys(VisualMapping.visualHandlers); + }; + + VisualMapping.isValidType = function (visualType) { + return VisualMapping.visualHandlers.hasOwnProperty(visualType); + }; + + VisualMapping.eachVisual = function (visual, callback, context) { + if (isObject(visual)) { + each(visual, callback, context); + } else { + callback.call(context, visual); + } + }; + + VisualMapping.mapVisual = function (visual, callback, context) { + var isPrimary; + var newVisual = isArray(visual) ? [] : isObject(visual) ? {} : (isPrimary = true, null); + VisualMapping.eachVisual(visual, function (v, key) { + var newVal = callback.call(context, v, key); + isPrimary ? newVisual = newVal : newVisual[key] = newVal; + }); + return newVisual; + }; + + VisualMapping.retrieveVisuals = function (obj) { + var ret = {}; + var hasVisual; + obj && each$4(VisualMapping.visualHandlers, function (h, visualType) { + if (obj.hasOwnProperty(visualType)) { + ret[visualType] = obj[visualType]; + hasVisual = true; + } + }); + return hasVisual ? ret : null; + }; + + VisualMapping.prepareVisualTypes = function (visualTypes) { + if (isArray(visualTypes)) { + visualTypes = visualTypes.slice(); + } else if (isObject$4(visualTypes)) { + var types_1 = []; + each$4(visualTypes, function (item, type) { + types_1.push(type); + }); + visualTypes = types_1; + } else { + return []; + } + + visualTypes.sort(function (type1, type2) { + return type2 === 'color' && type1 !== 'color' && type1.indexOf('color') === 0 ? 1 : -1; + }); + return visualTypes; + }; + + VisualMapping.dependsOn = function (visualType1, visualType2) { + return visualType2 === 'color' ? !!(visualType1 && visualType1.indexOf(visualType2) === 0) : visualType1 === visualType2; + }; + + VisualMapping.findPieceIndex = function (value, pieceList, findClosestWhenOutside) { + var possibleI; + var abs = Infinity; + + for (var i = 0, len = pieceList.length; i < len; i++) { + var pieceValue = pieceList[i].value; + + if (pieceValue != null) { + if (pieceValue === value || typeof pieceValue === 'string' && pieceValue === value + '') { + return i; + } + + findClosestWhenOutside && updatePossible(pieceValue, i); + } + } + + for (var i = 0, len = pieceList.length; i < len; i++) { + var piece = pieceList[i]; + var interval = piece.interval; + var close_1 = piece.close; + + if (interval) { + if (interval[0] === -Infinity) { + if (littleThan(close_1[1], value, interval[1])) { + return i; + } + } else if (interval[1] === Infinity) { + if (littleThan(close_1[0], interval[0], value)) { + return i; + } + } else if (littleThan(close_1[0], interval[0], value) && littleThan(close_1[1], value, interval[1])) { + return i; + } + + findClosestWhenOutside && updatePossible(interval[0], i); + findClosestWhenOutside && updatePossible(interval[1], i); + } + } + + if (findClosestWhenOutside) { + return value === Infinity ? pieceList.length - 1 : value === -Infinity ? 0 : possibleI; + } + + function updatePossible(val, index) { + var newAbs = Math.abs(val - value); + + if (newAbs < abs) { + abs = newAbs; + possibleI = index; + } + } + }; + + VisualMapping.visualHandlers = { + color: { + applyVisual: makeApplyVisual('color'), + getColorMapper: function () { + var thisOption = this.option; + return bind(thisOption.mappingMethod === 'category' ? function (value, isNormalized) { + !isNormalized && (value = this._normalizeData(value)); + return doMapCategory.call(this, value); + } : function (value, isNormalized, out) { + var returnRGBArray = !!out; + !isNormalized && (value = this._normalizeData(value)); + out = fastLerp(value, thisOption.parsedVisual, out); + return returnRGBArray ? out : stringify(out, 'rgba'); + }, this); + }, + _normalizedToVisual: { + linear: function (normalized) { + return stringify(fastLerp(normalized, this.option.parsedVisual), 'rgba'); + }, + category: doMapCategory, + piecewise: function (normalized, value) { + var result = getSpecifiedVisual.call(this, value); + + if (result == null) { + result = stringify(fastLerp(normalized, this.option.parsedVisual), 'rgba'); + } + + return result; + }, + fixed: doMapFixed + } + }, + colorHue: makePartialColorVisualHandler(function (color$1, value) { + return modifyHSL(color$1, value); + }), + colorSaturation: makePartialColorVisualHandler(function (color$1, value) { + return modifyHSL(color$1, null, value); + }), + colorLightness: makePartialColorVisualHandler(function (color$1, value) { + return modifyHSL(color$1, null, null, value); + }), + colorAlpha: makePartialColorVisualHandler(function (color$1, value) { + return modifyAlpha(color$1, value); + }), + decal: { + applyVisual: makeApplyVisual('decal'), + _normalizedToVisual: { + linear: null, + category: doMapCategory, + piecewise: null, + fixed: null + } + }, + opacity: { + applyVisual: makeApplyVisual('opacity'), + _normalizedToVisual: createNormalizedToNumericVisual([0, 1]) + }, + liftZ: { + applyVisual: makeApplyVisual('liftZ'), + _normalizedToVisual: { + linear: doMapFixed, + category: doMapFixed, + piecewise: doMapFixed, + fixed: doMapFixed + } + }, + symbol: { + applyVisual: function (value, getter, setter) { + var symbolCfg = this.mapValueToVisual(value); + setter('symbol', symbolCfg); + }, + _normalizedToVisual: { + linear: doMapToArray, + category: doMapCategory, + piecewise: function (normalized, value) { + var result = getSpecifiedVisual.call(this, value); + + if (result == null) { + result = doMapToArray.call(this, normalized); + } + + return result; + }, + fixed: doMapFixed + } + }, + symbolSize: { + applyVisual: makeApplyVisual('symbolSize'), + _normalizedToVisual: createNormalizedToNumericVisual([0, 1]) + } + }; + return VisualMapping; + }(); + + function preprocessForPiecewise(thisOption) { + var pieceList = thisOption.pieceList; + thisOption.hasSpecialVisual = false; + each(pieceList, function (piece, index) { + piece.originIndex = index; + + if (piece.visual != null) { + thisOption.hasSpecialVisual = true; + } + }); + } + + function preprocessForSpecifiedCategory(thisOption) { + var categories = thisOption.categories; + var categoryMap = thisOption.categoryMap = {}; + var visual = thisOption.visual; + each$4(categories, function (cate, index) { + categoryMap[cate] = index; + }); + + if (!isArray(visual)) { + var visualArr_1 = []; + + if (isObject(visual)) { + each$4(visual, function (v, cate) { + var index = categoryMap[cate]; + visualArr_1[index != null ? index : CATEGORY_DEFAULT_VISUAL_INDEX] = v; + }); + } else { + visualArr_1[CATEGORY_DEFAULT_VISUAL_INDEX] = visual; + } + + visual = setVisualToOption(thisOption, visualArr_1); + } + + for (var i = categories.length - 1; i >= 0; i--) { + if (visual[i] == null) { + delete categoryMap[categories[i]]; + categories.pop(); + } + } + } + + function normalizeVisualRange(thisOption, isCategory) { + var visual = thisOption.visual; + var visualArr = []; + + if (isObject(visual)) { + each$4(visual, function (v) { + visualArr.push(v); + }); + } else if (visual != null) { + visualArr.push(visual); + } + + var doNotNeedPair = { + color: 1, + symbol: 1 + }; + + if (!isCategory && visualArr.length === 1 && !doNotNeedPair.hasOwnProperty(thisOption.type)) { + visualArr[1] = visualArr[0]; + } + + setVisualToOption(thisOption, visualArr); + } + + function makePartialColorVisualHandler(applyValue) { + return { + applyVisual: function (value, getter, setter) { + var colorChannel = this.mapValueToVisual(value); + setter('color', applyValue(getter('color'), colorChannel)); + }, + _normalizedToVisual: createNormalizedToNumericVisual([0, 1]) + }; + } + + function doMapToArray(normalized) { + var visual = this.option.visual; + return visual[Math.round(linearMap(normalized, [0, 1], [0, visual.length - 1], true))] || {}; + } + + function makeApplyVisual(visualType) { + return function (value, getter, setter) { + setter(visualType, this.mapValueToVisual(value)); + }; + } + + function doMapCategory(normalized) { + var visual = this.option.visual; + return visual[this.option.loop && normalized !== CATEGORY_DEFAULT_VISUAL_INDEX ? normalized % visual.length : normalized]; + } + + function doMapFixed() { + return this.option.visual[0]; + } + + function createNormalizedToNumericVisual(sourceExtent) { + return { + linear: function (normalized) { + return linearMap(normalized, sourceExtent, this.option.visual, true); + }, + category: doMapCategory, + piecewise: function (normalized, value) { + var result = getSpecifiedVisual.call(this, value); + + if (result == null) { + result = linearMap(normalized, sourceExtent, this.option.visual, true); + } + + return result; + }, + fixed: doMapFixed + }; + } + + function getSpecifiedVisual(value) { + var thisOption = this.option; + var pieceList = thisOption.pieceList; + + if (thisOption.hasSpecialVisual) { + var pieceIndex = VisualMapping.findPieceIndex(value, pieceList); + var piece = pieceList[pieceIndex]; + + if (piece && piece.visual) { + return piece.visual[this.type]; + } + } + } + + function setVisualToOption(thisOption, visualArr) { + thisOption.visual = visualArr; + + if (thisOption.type === 'color') { + thisOption.parsedVisual = map(visualArr, function (item) { + return parse(item); + }); + } + + return visualArr; + } + + var normalizers = { + linear: function (value) { + return linearMap(value, this.option.dataExtent, [0, 1], true); + }, + piecewise: function (value) { + var pieceList = this.option.pieceList; + var pieceIndex = VisualMapping.findPieceIndex(value, pieceList, true); + + if (pieceIndex != null) { + return linearMap(pieceIndex, [0, pieceList.length - 1], [0, 1], true); + } + }, + category: function (value) { + var index = this.option.categories ? this.option.categoryMap[value] : value; + return index == null ? CATEGORY_DEFAULT_VISUAL_INDEX : index; + }, + fixed: noop + }; + + function littleThan(close, a, b) { + return close ? a <= b : a < b; + } + + var ITEM_STYLE_NORMAL = 'itemStyle'; + var inner$a = makeInner(); + var treemapVisual = { + seriesType: 'treemap', + reset: function (seriesModel) { + var tree = seriesModel.getData().tree; + var root = tree.root; + + if (root.isRemoved()) { + return; + } + + travelTree(root, {}, seriesModel.getViewRoot().getAncestors(), seriesModel); + } + }; + + function travelTree(node, designatedVisual, viewRootAncestors, seriesModel) { + var nodeModel = node.getModel(); + var nodeLayout = node.getLayout(); + var data = node.hostTree.data; + + if (!nodeLayout || nodeLayout.invisible || !nodeLayout.isInView) { + return; + } + + var nodeItemStyleModel = nodeModel.getModel(ITEM_STYLE_NORMAL); + var visuals = buildVisuals(nodeItemStyleModel, designatedVisual, seriesModel); + var existsStyle = data.ensureUniqueItemVisual(node.dataIndex, 'style'); + var borderColor = nodeItemStyleModel.get('borderColor'); + var borderColorSaturation = nodeItemStyleModel.get('borderColorSaturation'); + var thisNodeColor; + + if (borderColorSaturation != null) { + thisNodeColor = calculateColor(visuals); + borderColor = calculateBorderColor(borderColorSaturation, thisNodeColor); + } + + existsStyle.stroke = borderColor; + var viewChildren = node.viewChildren; + + if (!viewChildren || !viewChildren.length) { + thisNodeColor = calculateColor(visuals); + existsStyle.fill = thisNodeColor; + } else { + var mapping_1 = buildVisualMapping(node, nodeModel, nodeLayout, nodeItemStyleModel, visuals, viewChildren); + each(viewChildren, function (child, index) { + if (child.depth >= viewRootAncestors.length || child === viewRootAncestors[child.depth]) { + var childVisual = mapVisual(nodeModel, visuals, child, index, mapping_1, seriesModel); + travelTree(child, childVisual, viewRootAncestors, seriesModel); + } + }); + } + } + + function buildVisuals(nodeItemStyleModel, designatedVisual, seriesModel) { + var visuals = extend({}, designatedVisual); + var designatedVisualItemStyle = seriesModel.designatedVisualItemStyle; + each(['color', 'colorAlpha', 'colorSaturation'], function (visualName) { + designatedVisualItemStyle[visualName] = designatedVisual[visualName]; + var val = nodeItemStyleModel.get(visualName); + designatedVisualItemStyle[visualName] = null; + val != null && (visuals[visualName] = val); + }); + return visuals; + } + + function calculateColor(visuals) { + var color = getValueVisualDefine(visuals, 'color'); + + if (color) { + var colorAlpha = getValueVisualDefine(visuals, 'colorAlpha'); + var colorSaturation = getValueVisualDefine(visuals, 'colorSaturation'); + + if (colorSaturation) { + color = modifyHSL(color, null, null, colorSaturation); + } + + if (colorAlpha) { + color = modifyAlpha(color, colorAlpha); + } + + return color; + } + } + + function calculateBorderColor(borderColorSaturation, thisNodeColor) { + return thisNodeColor != null ? modifyHSL(thisNodeColor, null, null, borderColorSaturation) : null; + } + + function getValueVisualDefine(visuals, name) { + var value = visuals[name]; + + if (value != null && value !== 'none') { + return value; + } + } + + function buildVisualMapping(node, nodeModel, nodeLayout, nodeItemStyleModel, visuals, viewChildren) { + if (!viewChildren || !viewChildren.length) { + return; + } + + var rangeVisual = getRangeVisual(nodeModel, 'color') || visuals.color != null && visuals.color !== 'none' && (getRangeVisual(nodeModel, 'colorAlpha') || getRangeVisual(nodeModel, 'colorSaturation')); + + if (!rangeVisual) { + return; + } + + var visualMin = nodeModel.get('visualMin'); + var visualMax = nodeModel.get('visualMax'); + var dataExtent = nodeLayout.dataExtent.slice(); + visualMin != null && visualMin < dataExtent[0] && (dataExtent[0] = visualMin); + visualMax != null && visualMax > dataExtent[1] && (dataExtent[1] = visualMax); + var colorMappingBy = nodeModel.get('colorMappingBy'); + var opt = { + type: rangeVisual.name, + dataExtent: dataExtent, + visual: rangeVisual.range + }; + + if (opt.type === 'color' && (colorMappingBy === 'index' || colorMappingBy === 'id')) { + opt.mappingMethod = 'category'; + opt.loop = true; + } else { + opt.mappingMethod = 'linear'; + } + + var mapping = new VisualMapping(opt); + inner$a(mapping).drColorMappingBy = colorMappingBy; + return mapping; + } + + function getRangeVisual(nodeModel, name) { + var range = nodeModel.get(name); + return isArray(range) && range.length ? { + name: name, + range: range + } : null; + } + + function mapVisual(nodeModel, visuals, child, index, mapping, seriesModel) { + var childVisuals = extend({}, visuals); + + if (mapping) { + var mappingType = mapping.type; + var colorMappingBy = mappingType === 'color' && inner$a(mapping).drColorMappingBy; + var value = colorMappingBy === 'index' ? index : colorMappingBy === 'id' ? seriesModel.mapIdToIndex(child.getId()) : child.getValue(nodeModel.get('visualDimension')); + childVisuals[mappingType] = mapping.mapValueToVisual(value); + } + + return childVisuals; + } + + var mathMax$7 = Math.max; + var mathMin$7 = Math.min; + var retrieveValue = retrieve; + var each$5 = each; + var PATH_BORDER_WIDTH = ['itemStyle', 'borderWidth']; + var PATH_GAP_WIDTH = ['itemStyle', 'gapWidth']; + var PATH_UPPER_LABEL_SHOW = ['upperLabel', 'show']; + var PATH_UPPER_LABEL_HEIGHT = ['upperLabel', 'height']; + var treemapLayout = { + seriesType: 'treemap', + reset: function (seriesModel, ecModel, api, payload) { + var ecWidth = api.getWidth(); + var ecHeight = api.getHeight(); + var seriesOption = seriesModel.option; + var layoutInfo = getLayoutRect(seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + var size = seriesOption.size || []; + var containerWidth = parsePercent$1(retrieveValue(layoutInfo.width, size[0]), ecWidth); + var containerHeight = parsePercent$1(retrieveValue(layoutInfo.height, size[1]), ecHeight); + var payloadType = payload && payload.type; + var types = ['treemapZoomToNode', 'treemapRootToNode']; + var targetInfo = retrieveTargetInfo(payload, types, seriesModel); + var rootRect = payloadType === 'treemapRender' || payloadType === 'treemapMove' ? payload.rootRect : null; + var viewRoot = seriesModel.getViewRoot(); + var viewAbovePath = getPathToRoot(viewRoot); + + if (payloadType !== 'treemapMove') { + var rootSize = payloadType === 'treemapZoomToNode' ? estimateRootSize(seriesModel, targetInfo, viewRoot, containerWidth, containerHeight) : rootRect ? [rootRect.width, rootRect.height] : [containerWidth, containerHeight]; + var sort_1 = seriesOption.sort; + + if (sort_1 && sort_1 !== 'asc' && sort_1 !== 'desc') { + sort_1 = 'desc'; + } + + var options = { + squareRatio: seriesOption.squareRatio, + sort: sort_1, + leafDepth: seriesOption.leafDepth + }; + viewRoot.hostTree.clearLayouts(); + var viewRootLayout_1 = { + x: 0, + y: 0, + width: rootSize[0], + height: rootSize[1], + area: rootSize[0] * rootSize[1] + }; + viewRoot.setLayout(viewRootLayout_1); + squarify(viewRoot, options, false, 0); + viewRootLayout_1 = viewRoot.getLayout(); + each$5(viewAbovePath, function (node, index) { + var childValue = (viewAbovePath[index + 1] || viewRoot).getValue(); + node.setLayout(extend({ + dataExtent: [childValue, childValue], + borderWidth: 0, + upperHeight: 0 + }, viewRootLayout_1)); + }); + } + + var treeRoot = seriesModel.getData().tree.root; + treeRoot.setLayout(calculateRootPosition(layoutInfo, rootRect, targetInfo), true); + seriesModel.setLayoutInfo(layoutInfo); + prunning(treeRoot, new BoundingRect(-layoutInfo.x, -layoutInfo.y, ecWidth, ecHeight), viewAbovePath, viewRoot, 0); + } + }; + + function squarify(node, options, hideChildren, depth) { + var width; + var height; + + if (node.isRemoved()) { + return; + } + + var thisLayout = node.getLayout(); + width = thisLayout.width; + height = thisLayout.height; + var nodeModel = node.getModel(); + var borderWidth = nodeModel.get(PATH_BORDER_WIDTH); + var halfGapWidth = nodeModel.get(PATH_GAP_WIDTH) / 2; + var upperLabelHeight = getUpperLabelHeight(nodeModel); + var upperHeight = Math.max(borderWidth, upperLabelHeight); + var layoutOffset = borderWidth - halfGapWidth; + var layoutOffsetUpper = upperHeight - halfGapWidth; + node.setLayout({ + borderWidth: borderWidth, + upperHeight: upperHeight, + upperLabelHeight: upperLabelHeight + }, true); + width = mathMax$7(width - 2 * layoutOffset, 0); + height = mathMax$7(height - layoutOffset - layoutOffsetUpper, 0); + var totalArea = width * height; + var viewChildren = initChildren(node, nodeModel, totalArea, options, hideChildren, depth); + + if (!viewChildren.length) { + return; + } + + var rect = { + x: layoutOffset, + y: layoutOffsetUpper, + width: width, + height: height + }; + var rowFixedLength = mathMin$7(width, height); + var best = Infinity; + var row = []; + row.area = 0; + + for (var i = 0, len = viewChildren.length; i < len;) { + var child = viewChildren[i]; + row.push(child); + row.area += child.getLayout().area; + var score = worst(row, rowFixedLength, options.squareRatio); + + if (score <= best) { + i++; + best = score; + } else { + row.area -= row.pop().getLayout().area; + position(row, rowFixedLength, rect, halfGapWidth, false); + rowFixedLength = mathMin$7(rect.width, rect.height); + row.length = row.area = 0; + best = Infinity; + } + } + + if (row.length) { + position(row, rowFixedLength, rect, halfGapWidth, true); + } + + if (!hideChildren) { + var childrenVisibleMin = nodeModel.get('childrenVisibleMin'); + + if (childrenVisibleMin != null && totalArea < childrenVisibleMin) { + hideChildren = true; + } + } + + for (var i = 0, len = viewChildren.length; i < len; i++) { + squarify(viewChildren[i], options, hideChildren, depth + 1); + } + } + + function initChildren(node, nodeModel, totalArea, options, hideChildren, depth) { + var viewChildren = node.children || []; + var orderBy = options.sort; + orderBy !== 'asc' && orderBy !== 'desc' && (orderBy = null); + var overLeafDepth = options.leafDepth != null && options.leafDepth <= depth; + + if (hideChildren && !overLeafDepth) { + return node.viewChildren = []; + } + + viewChildren = filter(viewChildren, function (child) { + return !child.isRemoved(); + }); + sort$1(viewChildren, orderBy); + var info = statistic(nodeModel, viewChildren, orderBy); + + if (info.sum === 0) { + return node.viewChildren = []; + } + + info.sum = filterByThreshold(nodeModel, totalArea, info.sum, orderBy, viewChildren); + + if (info.sum === 0) { + return node.viewChildren = []; + } + + for (var i = 0, len = viewChildren.length; i < len; i++) { + var area = viewChildren[i].getValue() / info.sum * totalArea; + viewChildren[i].setLayout({ + area: area + }); + } + + if (overLeafDepth) { + viewChildren.length && node.setLayout({ + isLeafRoot: true + }, true); + viewChildren.length = 0; + } + + node.viewChildren = viewChildren; + node.setLayout({ + dataExtent: info.dataExtent + }, true); + return viewChildren; + } + + function filterByThreshold(nodeModel, totalArea, sum, orderBy, orderedChildren) { + if (!orderBy) { + return sum; + } + + var visibleMin = nodeModel.get('visibleMin'); + var len = orderedChildren.length; + var deletePoint = len; + + for (var i = len - 1; i >= 0; i--) { + var value = orderedChildren[orderBy === 'asc' ? len - i - 1 : i].getValue(); + + if (value / sum * totalArea < visibleMin) { + deletePoint = i; + sum -= value; + } + } + + orderBy === 'asc' ? orderedChildren.splice(0, len - deletePoint) : orderedChildren.splice(deletePoint, len - deletePoint); + return sum; + } + + function sort$1(viewChildren, orderBy) { + if (orderBy) { + viewChildren.sort(function (a, b) { + var diff = orderBy === 'asc' ? a.getValue() - b.getValue() : b.getValue() - a.getValue(); + return diff === 0 ? orderBy === 'asc' ? a.dataIndex - b.dataIndex : b.dataIndex - a.dataIndex : diff; + }); + } + + return viewChildren; + } + + function statistic(nodeModel, children, orderBy) { + var sum = 0; + + for (var i = 0, len = children.length; i < len; i++) { + sum += children[i].getValue(); + } + + var dimension = nodeModel.get('visualDimension'); + var dataExtent; + + if (!children || !children.length) { + dataExtent = [NaN, NaN]; + } else if (dimension === 'value' && orderBy) { + dataExtent = [children[children.length - 1].getValue(), children[0].getValue()]; + orderBy === 'asc' && dataExtent.reverse(); + } else { + dataExtent = [Infinity, -Infinity]; + each$5(children, function (child) { + var value = child.getValue(dimension); + value < dataExtent[0] && (dataExtent[0] = value); + value > dataExtent[1] && (dataExtent[1] = value); + }); + } + + return { + sum: sum, + dataExtent: dataExtent + }; + } + + function worst(row, rowFixedLength, ratio) { + var areaMax = 0; + var areaMin = Infinity; + + for (var i = 0, area = void 0, len = row.length; i < len; i++) { + area = row[i].getLayout().area; + + if (area) { + area < areaMin && (areaMin = area); + area > areaMax && (areaMax = area); + } + } + + var squareArea = row.area * row.area; + var f = rowFixedLength * rowFixedLength * ratio; + return squareArea ? mathMax$7(f * areaMax / squareArea, squareArea / (f * areaMin)) : Infinity; + } + + function position(row, rowFixedLength, rect, halfGapWidth, flush) { + var idx0WhenH = rowFixedLength === rect.width ? 0 : 1; + var idx1WhenH = 1 - idx0WhenH; + var xy = ['x', 'y']; + var wh = ['width', 'height']; + var last = rect[xy[idx0WhenH]]; + var rowOtherLength = rowFixedLength ? row.area / rowFixedLength : 0; + + if (flush || rowOtherLength > rect[wh[idx1WhenH]]) { + rowOtherLength = rect[wh[idx1WhenH]]; + } + + for (var i = 0, rowLen = row.length; i < rowLen; i++) { + var node = row[i]; + var nodeLayout = {}; + var step = rowOtherLength ? node.getLayout().area / rowOtherLength : 0; + var wh1 = nodeLayout[wh[idx1WhenH]] = mathMax$7(rowOtherLength - 2 * halfGapWidth, 0); + var remain = rect[xy[idx0WhenH]] + rect[wh[idx0WhenH]] - last; + var modWH = i === rowLen - 1 || remain < step ? remain : step; + var wh0 = nodeLayout[wh[idx0WhenH]] = mathMax$7(modWH - 2 * halfGapWidth, 0); + nodeLayout[xy[idx1WhenH]] = rect[xy[idx1WhenH]] + mathMin$7(halfGapWidth, wh1 / 2); + nodeLayout[xy[idx0WhenH]] = last + mathMin$7(halfGapWidth, wh0 / 2); + last += modWH; + node.setLayout(nodeLayout, true); + } + + rect[xy[idx1WhenH]] += rowOtherLength; + rect[wh[idx1WhenH]] -= rowOtherLength; + } + + function estimateRootSize(seriesModel, targetInfo, viewRoot, containerWidth, containerHeight) { + var currNode = (targetInfo || {}).node; + var defaultSize = [containerWidth, containerHeight]; + + if (!currNode || currNode === viewRoot) { + return defaultSize; + } + + var parent; + var viewArea = containerWidth * containerHeight; + var area = viewArea * seriesModel.option.zoomToNodeRatio; + + while (parent = currNode.parentNode) { + var sum = 0; + var siblings = parent.children; + + for (var i = 0, len = siblings.length; i < len; i++) { + sum += siblings[i].getValue(); + } + + var currNodeValue = currNode.getValue(); + + if (currNodeValue === 0) { + return defaultSize; + } + + area *= sum / currNodeValue; + var parentModel = parent.getModel(); + var borderWidth = parentModel.get(PATH_BORDER_WIDTH); + var upperHeight = Math.max(borderWidth, getUpperLabelHeight(parentModel)); + area += 4 * borderWidth * borderWidth + (3 * borderWidth + upperHeight) * Math.pow(area, 0.5); + area > MAX_SAFE_INTEGER && (area = MAX_SAFE_INTEGER); + currNode = parent; + } + + area < viewArea && (area = viewArea); + var scale = Math.pow(area / viewArea, 0.5); + return [containerWidth * scale, containerHeight * scale]; + } + + function calculateRootPosition(layoutInfo, rootRect, targetInfo) { + if (rootRect) { + return { + x: rootRect.x, + y: rootRect.y + }; + } + + var defaultPosition = { + x: 0, + y: 0 + }; + + if (!targetInfo) { + return defaultPosition; + } + + var targetNode = targetInfo.node; + var layout = targetNode.getLayout(); + + if (!layout) { + return defaultPosition; + } + + var targetCenter = [layout.width / 2, layout.height / 2]; + var node = targetNode; + + while (node) { + var nodeLayout = node.getLayout(); + targetCenter[0] += nodeLayout.x; + targetCenter[1] += nodeLayout.y; + node = node.parentNode; + } + + return { + x: layoutInfo.width / 2 - targetCenter[0], + y: layoutInfo.height / 2 - targetCenter[1] + }; + } + + function prunning(node, clipRect, viewAbovePath, viewRoot, depth) { + var nodeLayout = node.getLayout(); + var nodeInViewAbovePath = viewAbovePath[depth]; + var isAboveViewRoot = nodeInViewAbovePath && nodeInViewAbovePath === node; + + if (nodeInViewAbovePath && !isAboveViewRoot || depth === viewAbovePath.length && node !== viewRoot) { + return; + } + + node.setLayout({ + isInView: true, + invisible: !isAboveViewRoot && !clipRect.intersect(nodeLayout), + isAboveViewRoot: isAboveViewRoot + }, true); + var childClipRect = new BoundingRect(clipRect.x - nodeLayout.x, clipRect.y - nodeLayout.y, clipRect.width, clipRect.height); + each$5(node.viewChildren || [], function (child) { + prunning(child, childClipRect, viewAbovePath, viewRoot, depth + 1); + }); + } + + function getUpperLabelHeight(model) { + return model.get(PATH_UPPER_LABEL_SHOW) ? model.get(PATH_UPPER_LABEL_HEIGHT) : 0; + } + + function install$b(registers) { + registers.registerSeriesModel(TreemapSeriesModel); + registers.registerChartView(TreemapView); + registers.registerVisual(treemapVisual); + registers.registerLayout(treemapLayout); + installTreemapAction(registers); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function categoryFilter(ecModel) { + var legendModels = ecModel.findComponents({ + mainType: 'legend' + }); + + if (!legendModels || !legendModels.length) { + return; + } + + ecModel.eachSeriesByType('graph', function (graphSeries) { + var categoriesData = graphSeries.getCategoriesData(); + var graph = graphSeries.getGraph(); + var data = graph.data; + var categoryNames = categoriesData.mapArray(categoriesData.getName); + data.filterSelf(function (idx) { + var model = data.getItemModel(idx); + var category = model.getShallow('category'); + + if (category != null) { + if (typeof category === 'number') { + category = categoryNames[category]; + } + + for (var i = 0; i < legendModels.length; i++) { + if (!legendModels[i].isSelected(category)) { + return false; + } + } + } + + return true; + }); + }); + } + + function categoryVisual(ecModel) { + var paletteScope = {}; + ecModel.eachSeriesByType('graph', function (seriesModel) { + var categoriesData = seriesModel.getCategoriesData(); + var data = seriesModel.getData(); + var categoryNameIdxMap = {}; + categoriesData.each(function (idx) { + var name = categoriesData.getName(idx); + categoryNameIdxMap['ec-' + name] = idx; + var itemModel = categoriesData.getItemModel(idx); + var style = itemModel.getModel('itemStyle').getItemStyle(); + + if (!style.fill) { + style.fill = seriesModel.getColorFromPalette(name, paletteScope); + } + + categoriesData.setItemVisual(idx, 'style', style); + var symbolVisualList = ['symbol', 'symbolSize', 'symbolKeepAspect']; + + for (var i = 0; i < symbolVisualList.length; i++) { + var symbolVisual = itemModel.getShallow(symbolVisualList[i], true); + + if (symbolVisual != null) { + categoriesData.setItemVisual(idx, symbolVisualList[i], symbolVisual); + } + } + }); + + if (categoriesData.count()) { + data.each(function (idx) { + var model = data.getItemModel(idx); + var categoryIdx = model.getShallow('category'); + + if (categoryIdx != null) { + if (typeof categoryIdx === 'string') { + categoryIdx = categoryNameIdxMap['ec-' + categoryIdx]; + } + + var categoryStyle = categoriesData.getItemVisual(categoryIdx, 'style'); + var style = data.ensureUniqueItemVisual(idx, 'style'); + extend(style, categoryStyle); + var visualList = ['symbol', 'symbolSize', 'symbolKeepAspect']; + + for (var i = 0; i < visualList.length; i++) { + data.setItemVisual(idx, visualList[i], categoriesData.getItemVisual(categoryIdx, visualList[i])); + } + } + }); + } + }); + } + + function normalize$2(a) { + if (!(a instanceof Array)) { + a = [a, a]; + } + + return a; + } + + function graphEdgeVisual(ecModel) { + ecModel.eachSeriesByType('graph', function (seriesModel) { + var graph = seriesModel.getGraph(); + var edgeData = seriesModel.getEdgeData(); + var symbolType = normalize$2(seriesModel.get('edgeSymbol')); + var symbolSize = normalize$2(seriesModel.get('edgeSymbolSize')); + edgeData.setVisual('fromSymbol', symbolType && symbolType[0]); + edgeData.setVisual('toSymbol', symbolType && symbolType[1]); + edgeData.setVisual('fromSymbolSize', symbolSize && symbolSize[0]); + edgeData.setVisual('toSymbolSize', symbolSize && symbolSize[1]); + edgeData.setVisual('style', seriesModel.getModel('lineStyle').getLineStyle()); + edgeData.each(function (idx) { + var itemModel = edgeData.getItemModel(idx); + var edge = graph.getEdgeByIndex(idx); + var symbolType = normalize$2(itemModel.getShallow('symbol', true)); + var symbolSize = normalize$2(itemModel.getShallow('symbolSize', true)); + var style = itemModel.getModel('lineStyle').getLineStyle(); + var existsStyle = edgeData.ensureUniqueItemVisual(idx, 'style'); + extend(existsStyle, style); + + switch (existsStyle.stroke) { + case 'source': + { + var nodeStyle = edge.node1.getVisual('style'); + existsStyle.stroke = nodeStyle && nodeStyle.fill; + break; + } + + case 'target': + { + var nodeStyle = edge.node2.getVisual('style'); + existsStyle.stroke = nodeStyle && nodeStyle.fill; + break; + } + } + + symbolType[0] && edge.setVisual('fromSymbol', symbolType[0]); + symbolType[1] && edge.setVisual('toSymbol', symbolType[1]); + symbolSize[0] && edge.setVisual('fromSymbolSize', symbolSize[0]); + symbolSize[1] && edge.setVisual('toSymbolSize', symbolSize[1]); + }); + }); + } + + var KEY_DELIMITER = '-->'; + + var getAutoCurvenessParams = function (seriesModel) { + return seriesModel.get('autoCurveness') || null; + }; + + var createCurveness = function (seriesModel, appendLength) { + var autoCurvenessParmas = getAutoCurvenessParams(seriesModel); + var length = 20; + var curvenessList = []; + + if (typeof autoCurvenessParmas === 'number') { + length = autoCurvenessParmas; + } else if (isArray(autoCurvenessParmas)) { + seriesModel.__curvenessList = autoCurvenessParmas; + return; + } + + if (appendLength > length) { + length = appendLength; + } + + var len = length % 2 ? length + 2 : length + 3; + curvenessList = []; + + for (var i = 0; i < len; i++) { + curvenessList.push((i % 2 ? i + 1 : i) / 10 * (i % 2 ? -1 : 1)); + } + + seriesModel.__curvenessList = curvenessList; + }; + + var getKeyOfEdges = function (n1, n2, seriesModel) { + var source = [n1.id, n1.dataIndex].join('.'); + var target = [n2.id, n2.dataIndex].join('.'); + return [seriesModel.uid, source, target].join(KEY_DELIMITER); + }; + + var getOppositeKey = function (key) { + var keys = key.split(KEY_DELIMITER); + return [keys[0], keys[2], keys[1]].join(KEY_DELIMITER); + }; + + var getEdgeFromMap = function (edge, seriesModel) { + var key = getKeyOfEdges(edge.node1, edge.node2, seriesModel); + return seriesModel.__edgeMap[key]; + }; + + var getTotalLengthBetweenNodes = function (edge, seriesModel) { + var len = getEdgeMapLengthWithKey(getKeyOfEdges(edge.node1, edge.node2, seriesModel), seriesModel); + var lenV = getEdgeMapLengthWithKey(getKeyOfEdges(edge.node2, edge.node1, seriesModel), seriesModel); + return len + lenV; + }; + + var getEdgeMapLengthWithKey = function (key, seriesModel) { + var edgeMap = seriesModel.__edgeMap; + return edgeMap[key] ? edgeMap[key].length : 0; + }; + + function initCurvenessList(seriesModel) { + if (!getAutoCurvenessParams(seriesModel)) { + return; + } + + seriesModel.__curvenessList = []; + seriesModel.__edgeMap = {}; + createCurveness(seriesModel); + } + function createEdgeMapForCurveness(n1, n2, seriesModel, index) { + if (!getAutoCurvenessParams(seriesModel)) { + return; + } + + var key = getKeyOfEdges(n1, n2, seriesModel); + var edgeMap = seriesModel.__edgeMap; + var oppositeEdges = edgeMap[getOppositeKey(key)]; + + if (edgeMap[key] && !oppositeEdges) { + edgeMap[key].isForward = true; + } else if (oppositeEdges && edgeMap[key]) { + oppositeEdges.isForward = true; + edgeMap[key].isForward = false; + } + + edgeMap[key] = edgeMap[key] || []; + edgeMap[key].push(index); + } + function getCurvenessForEdge(edge, seriesModel, index, needReverse) { + var autoCurvenessParams = getAutoCurvenessParams(seriesModel); + var isArrayParam = isArray(autoCurvenessParams); + + if (!autoCurvenessParams) { + return null; + } + + var edgeArray = getEdgeFromMap(edge, seriesModel); + + if (!edgeArray) { + return null; + } + + var edgeIndex = -1; + + for (var i = 0; i < edgeArray.length; i++) { + if (edgeArray[i] === index) { + edgeIndex = i; + break; + } + } + + var totalLen = getTotalLengthBetweenNodes(edge, seriesModel); + createCurveness(seriesModel, totalLen); + edge.lineStyle = edge.lineStyle || {}; + var curKey = getKeyOfEdges(edge.node1, edge.node2, seriesModel); + var curvenessList = seriesModel.__curvenessList; + var parityCorrection = isArrayParam ? 0 : totalLen % 2 ? 0 : 1; + + if (!edgeArray.isForward) { + var oppositeKey = getOppositeKey(curKey); + var len = getEdgeMapLengthWithKey(oppositeKey, seriesModel); + var resValue = curvenessList[edgeIndex + len + parityCorrection]; + + if (needReverse) { + if (isArrayParam) { + if (autoCurvenessParams && autoCurvenessParams[0] === 0) { + return (len + parityCorrection) % 2 ? resValue : -resValue; + } else { + return ((len % 2 ? 0 : 1) + parityCorrection) % 2 ? resValue : -resValue; + } + } else { + return (len + parityCorrection) % 2 ? resValue : -resValue; + } + } else { + return curvenessList[edgeIndex + len + parityCorrection]; + } + } else { + return curvenessList[parityCorrection + edgeIndex]; + } + } + + function simpleLayout(seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && coordSys.type !== 'view') { + return; + } + + var graph = seriesModel.getGraph(); + graph.eachNode(function (node) { + var model = node.getModel(); + node.setLayout([+model.get('x'), +model.get('y')]); + }); + simpleLayoutEdge(graph, seriesModel); + } + function simpleLayoutEdge(graph, seriesModel) { + graph.eachEdge(function (edge, index) { + var curveness = retrieve3(edge.getModel().get(['lineStyle', 'curveness']), -getCurvenessForEdge(edge, seriesModel, index, true), 0); + var p1 = clone$1(edge.node1.getLayout()); + var p2 = clone$1(edge.node2.getLayout()); + var points = [p1, p2]; + + if (+curveness) { + points.push([(p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * curveness, (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * curveness]); + } + + edge.setLayout(points); + }); + } + + function graphSimpleLayout(ecModel, api) { + ecModel.eachSeriesByType('graph', function (seriesModel) { + var layout = seriesModel.get('layout'); + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && coordSys.type !== 'view') { + var data_1 = seriesModel.getData(); + var dimensions_1 = []; + each(coordSys.dimensions, function (coordDim) { + dimensions_1 = dimensions_1.concat(data_1.mapDimensionsAll(coordDim)); + }); + + for (var dataIndex = 0; dataIndex < data_1.count(); dataIndex++) { + var value = []; + var hasValue = false; + + for (var i = 0; i < dimensions_1.length; i++) { + var val = data_1.get(dimensions_1[i], dataIndex); + + if (!isNaN(val)) { + hasValue = true; + } + + value.push(val); + } + + if (hasValue) { + data_1.setItemLayout(dataIndex, coordSys.dataToPoint(value)); + } else { + data_1.setItemLayout(dataIndex, [NaN, NaN]); + } + } + + simpleLayoutEdge(data_1.graph, seriesModel); + } else if (!layout || layout === 'none') { + simpleLayout(seriesModel); + } + }); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function getNodeGlobalScale(seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys.type !== 'view') { + return 1; + } + + var nodeScaleRatio = seriesModel.option.nodeScaleRatio; + var groupZoom = coordSys.scaleX; + var roamZoom = coordSys.getZoom(); + var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1; + return nodeScale / groupZoom; + } + function getSymbolSize(node) { + var symbolSize = node.getVisual('symbolSize'); + + if (symbolSize instanceof Array) { + symbolSize = (symbolSize[0] + symbolSize[1]) / 2; + } + + return +symbolSize; + } + + var PI$6 = Math.PI; + var _symbolRadiansHalf = []; + function circularLayout(seriesModel, basedOn) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && coordSys.type !== 'view') { + return; + } + + var rect = coordSys.getBoundingRect(); + var nodeData = seriesModel.getData(); + var graph = nodeData.graph; + var cx = rect.width / 2 + rect.x; + var cy = rect.height / 2 + rect.y; + var r = Math.min(rect.width, rect.height) / 2; + var count = nodeData.count(); + nodeData.setLayout({ + cx: cx, + cy: cy + }); + + if (!count) { + return; + } + + _layoutNodesBasedOn[basedOn](seriesModel, graph, nodeData, r, cx, cy, count); + + graph.eachEdge(function (edge, index) { + var curveness = retrieve3(edge.getModel().get(['lineStyle', 'curveness']), getCurvenessForEdge(edge, seriesModel, index), 0); + var p1 = clone$1(edge.node1.getLayout()); + var p2 = clone$1(edge.node2.getLayout()); + var cp1; + var x12 = (p1[0] + p2[0]) / 2; + var y12 = (p1[1] + p2[1]) / 2; + + if (+curveness) { + curveness *= 3; + cp1 = [cx * curveness + x12 * (1 - curveness), cy * curveness + y12 * (1 - curveness)]; + } + + edge.setLayout([p1, p2, cp1]); + }); + } + var _layoutNodesBasedOn = { + value: function (seriesModel, graph, nodeData, r, cx, cy, count) { + var angle = 0; + var sum = nodeData.getSum('value'); + var unitAngle = Math.PI * 2 / (sum || count); + graph.eachNode(function (node) { + var value = node.getValue('value'); + var radianHalf = unitAngle * (sum ? value : 1) / 2; + angle += radianHalf; + node.setLayout([r * Math.cos(angle) + cx, r * Math.sin(angle) + cy]); + angle += radianHalf; + }); + }, + symbolSize: function (seriesModel, graph, nodeData, r, cx, cy, count) { + var sumRadian = 0; + _symbolRadiansHalf.length = count; + var nodeScale = getNodeGlobalScale(seriesModel); + graph.eachNode(function (node) { + var symbolSize = getSymbolSize(node); + isNaN(symbolSize) && (symbolSize = 2); + symbolSize < 0 && (symbolSize = 0); + symbolSize *= nodeScale; + var symbolRadianHalf = Math.asin(symbolSize / 2 / r); + isNaN(symbolRadianHalf) && (symbolRadianHalf = PI$6 / 2); + _symbolRadiansHalf[node.dataIndex] = symbolRadianHalf; + sumRadian += symbolRadianHalf * 2; + }); + var halfRemainRadian = (2 * PI$6 - sumRadian) / count / 2; + var angle = 0; + graph.eachNode(function (node) { + var radianHalf = halfRemainRadian + _symbolRadiansHalf[node.dataIndex]; + angle += radianHalf; + node.setLayout([r * Math.cos(angle) + cx, r * Math.sin(angle) + cy]); + angle += radianHalf; + }); + } + }; + + function graphCircularLayout(ecModel) { + ecModel.eachSeriesByType('graph', function (seriesModel) { + if (seriesModel.get('layout') === 'circular') { + circularLayout(seriesModel, 'symbolSize'); + } + }); + } + + var scaleAndAdd$1 = scaleAndAdd; + function forceLayout(inNodes, inEdges, opts) { + var nodes = inNodes; + var edges = inEdges; + var rect = opts.rect; + var width = rect.width; + var height = rect.height; + var center = [rect.x + width / 2, rect.y + height / 2]; + var gravity = opts.gravity == null ? 0.1 : opts.gravity; + + for (var i = 0; i < nodes.length; i++) { + var n = nodes[i]; + + if (!n.p) { + n.p = create(width * (Math.random() - 0.5) + center[0], height * (Math.random() - 0.5) + center[1]); + } + + n.pp = clone$1(n.p); + n.edges = null; + } + + var initialFriction = opts.friction == null ? 0.6 : opts.friction; + var friction = initialFriction; + var beforeStepCallback; + var afterStepCallback; + return { + warmUp: function () { + friction = initialFriction * 0.8; + }, + setFixed: function (idx) { + nodes[idx].fixed = true; + }, + setUnfixed: function (idx) { + nodes[idx].fixed = false; + }, + beforeStep: function (cb) { + beforeStepCallback = cb; + }, + afterStep: function (cb) { + afterStepCallback = cb; + }, + step: function (cb) { + beforeStepCallback && beforeStepCallback(nodes, edges); + var v12 = []; + var nLen = nodes.length; + + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + + if (e.ignoreForceLayout) { + continue; + } + + var n1 = e.n1; + var n2 = e.n2; + sub(v12, n2.p, n1.p); + var d = len(v12) - e.d; + var w = n2.w / (n1.w + n2.w); + + if (isNaN(w)) { + w = 0; + } + + normalize(v12, v12); + !n1.fixed && scaleAndAdd$1(n1.p, n1.p, v12, w * d * friction); + !n2.fixed && scaleAndAdd$1(n2.p, n2.p, v12, -(1 - w) * d * friction); + } + + for (var i = 0; i < nLen; i++) { + var n = nodes[i]; + + if (!n.fixed) { + sub(v12, center, n.p); + scaleAndAdd$1(n.p, n.p, v12, gravity * friction); + } + } + + for (var i = 0; i < nLen; i++) { + var n1 = nodes[i]; + + for (var j = i + 1; j < nLen; j++) { + var n2 = nodes[j]; + sub(v12, n2.p, n1.p); + var d = len(v12); + + if (d === 0) { + set(v12, Math.random() - 0.5, Math.random() - 0.5); + d = 1; + } + + var repFact = (n1.rep + n2.rep) / d / d; + !n1.fixed && scaleAndAdd$1(n1.pp, n1.pp, v12, repFact); + !n2.fixed && scaleAndAdd$1(n2.pp, n2.pp, v12, -repFact); + } + } + + var v = []; + + for (var i = 0; i < nLen; i++) { + var n = nodes[i]; + + if (!n.fixed) { + sub(v, n.p, n.pp); + scaleAndAdd$1(n.p, n.p, v, friction); + copy(n.pp, n.p); + } + } + + friction = friction * 0.992; + var finished = friction < 0.01; + afterStepCallback && afterStepCallback(nodes, edges, finished); + cb && cb(finished); + } + }; + } + + function graphForceLayout(ecModel) { + ecModel.eachSeriesByType('graph', function (graphSeries) { + var coordSys = graphSeries.coordinateSystem; + + if (coordSys && coordSys.type !== 'view') { + return; + } + + if (graphSeries.get('layout') === 'force') { + var preservedPoints_1 = graphSeries.preservedPoints || {}; + var graph_1 = graphSeries.getGraph(); + var nodeData_1 = graph_1.data; + var edgeData = graph_1.edgeData; + var forceModel = graphSeries.getModel('force'); + var initLayout = forceModel.get('initLayout'); + + if (graphSeries.preservedPoints) { + nodeData_1.each(function (idx) { + var id = nodeData_1.getId(idx); + nodeData_1.setItemLayout(idx, preservedPoints_1[id] || [NaN, NaN]); + }); + } else if (!initLayout || initLayout === 'none') { + simpleLayout(graphSeries); + } else if (initLayout === 'circular') { + circularLayout(graphSeries, 'value'); + } + + var nodeDataExtent_1 = nodeData_1.getDataExtent('value'); + var edgeDataExtent_1 = edgeData.getDataExtent('value'); + var repulsion = forceModel.get('repulsion'); + var edgeLength = forceModel.get('edgeLength'); + var repulsionArr_1 = isArray(repulsion) ? repulsion : [repulsion, repulsion]; + var edgeLengthArr_1 = isArray(edgeLength) ? edgeLength : [edgeLength, edgeLength]; + edgeLengthArr_1 = [edgeLengthArr_1[1], edgeLengthArr_1[0]]; + var nodes_1 = nodeData_1.mapArray('value', function (value, idx) { + var point = nodeData_1.getItemLayout(idx); + var rep = linearMap(value, nodeDataExtent_1, repulsionArr_1); + + if (isNaN(rep)) { + rep = (repulsionArr_1[0] + repulsionArr_1[1]) / 2; + } + + return { + w: rep, + rep: rep, + fixed: nodeData_1.getItemModel(idx).get('fixed'), + p: !point || isNaN(point[0]) || isNaN(point[1]) ? null : point + }; + }); + var edges = edgeData.mapArray('value', function (value, idx) { + var edge = graph_1.getEdgeByIndex(idx); + var d = linearMap(value, edgeDataExtent_1, edgeLengthArr_1); + + if (isNaN(d)) { + d = (edgeLengthArr_1[0] + edgeLengthArr_1[1]) / 2; + } + + var edgeModel = edge.getModel(); + var curveness = retrieve3(edge.getModel().get(['lineStyle', 'curveness']), -getCurvenessForEdge(edge, graphSeries, idx, true), 0); + return { + n1: nodes_1[edge.node1.dataIndex], + n2: nodes_1[edge.node2.dataIndex], + d: d, + curveness: curveness, + ignoreForceLayout: edgeModel.get('ignoreForceLayout') + }; + }); + var rect = coordSys.getBoundingRect(); + var forceInstance = forceLayout(nodes_1, edges, { + rect: rect, + gravity: forceModel.get('gravity'), + friction: forceModel.get('friction') + }); + forceInstance.beforeStep(function (nodes, edges) { + for (var i = 0, l = nodes.length; i < l; i++) { + if (nodes[i].fixed) { + copy(nodes[i].p, graph_1.getNodeByIndex(i).getLayout()); + } + } + }); + forceInstance.afterStep(function (nodes, edges, stopped) { + for (var i = 0, l = nodes.length; i < l; i++) { + if (!nodes[i].fixed) { + graph_1.getNodeByIndex(i).setLayout(nodes[i].p); + } + + preservedPoints_1[nodeData_1.getId(i)] = nodes[i].p; + } + + for (var i = 0, l = edges.length; i < l; i++) { + var e = edges[i]; + var edge = graph_1.getEdgeByIndex(i); + var p1 = e.n1.p; + var p2 = e.n2.p; + var points = edge.getLayout(); + points = points ? points.slice() : []; + points[0] = points[0] || []; + points[1] = points[1] || []; + copy(points[0], p1); + copy(points[1], p2); + + if (+e.curveness) { + points[2] = [(p1[0] + p2[0]) / 2 - (p1[1] - p2[1]) * e.curveness, (p1[1] + p2[1]) / 2 - (p2[0] - p1[0]) * e.curveness]; + } + + edge.setLayout(points); + } + }); + graphSeries.forceLayout = forceInstance; + graphSeries.preservedPoints = preservedPoints_1; + forceInstance.step(); + } else { + graphSeries.forceLayout = null; + } + }); + } + + function getViewRect$2(seriesModel, api, aspect) { + var option = extend(seriesModel.getBoxLayoutParams(), { + aspect: aspect + }); + return getLayoutRect(option, { + width: api.getWidth(), + height: api.getHeight() + }); + } + + function createViewCoordSys(ecModel, api) { + var viewList = []; + ecModel.eachSeriesByType('graph', function (seriesModel) { + var coordSysType = seriesModel.get('coordinateSystem'); + + if (!coordSysType || coordSysType === 'view') { + var data_1 = seriesModel.getData(); + var positions = data_1.mapArray(function (idx) { + var itemModel = data_1.getItemModel(idx); + return [+itemModel.get('x'), +itemModel.get('y')]; + }); + var min = []; + var max = []; + fromPoints(positions, min, max); + + if (max[0] - min[0] === 0) { + max[0] += 1; + min[0] -= 1; + } + + if (max[1] - min[1] === 0) { + max[1] += 1; + min[1] -= 1; + } + + var aspect = (max[0] - min[0]) / (max[1] - min[1]); + var viewRect = getViewRect$2(seriesModel, api, aspect); + + if (isNaN(aspect)) { + min = [viewRect.x, viewRect.y]; + max = [viewRect.x + viewRect.width, viewRect.y + viewRect.height]; + } + + var bbWidth = max[0] - min[0]; + var bbHeight = max[1] - min[1]; + var viewWidth = viewRect.width; + var viewHeight = viewRect.height; + var viewCoordSys = seriesModel.coordinateSystem = new View(); + viewCoordSys.zoomLimit = seriesModel.get('scaleLimit'); + viewCoordSys.setBoundingRect(min[0], min[1], bbWidth, bbHeight); + viewCoordSys.setViewRect(viewRect.x, viewRect.y, viewWidth, viewHeight); + viewCoordSys.setCenter(seriesModel.get('center')); + viewCoordSys.setZoom(seriesModel.get('zoom')); + viewList.push(viewCoordSys); + } + }); + return viewList; + } + + var straightLineProto = Line.prototype; + var bezierCurveProto = BezierCurve.prototype; + + var StraightLineShape = function () { + function StraightLineShape() { + this.x1 = 0; + this.y1 = 0; + this.x2 = 0; + this.y2 = 0; + this.percent = 1; + } + + return StraightLineShape; + }(); + + var CurveShape = function (_super) { + __extends(CurveShape, _super); + + function CurveShape() { + return _super !== null && _super.apply(this, arguments) || this; + } + + return CurveShape; + }(StraightLineShape); + + function isStraightLine(shape) { + return isNaN(+shape.cpx1) || isNaN(+shape.cpy1); + } + + var ECLinePath = function (_super) { + __extends(ECLinePath, _super); + + function ECLinePath(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'ec-line'; + return _this; + } + + ECLinePath.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + + ECLinePath.prototype.getDefaultShape = function () { + return new StraightLineShape(); + }; + + ECLinePath.prototype.buildPath = function (ctx, shape) { + if (isStraightLine(shape)) { + straightLineProto.buildPath.call(this, ctx, shape); + } else { + bezierCurveProto.buildPath.call(this, ctx, shape); + } + }; + + ECLinePath.prototype.pointAt = function (t) { + if (isStraightLine(this.shape)) { + return straightLineProto.pointAt.call(this, t); + } else { + return bezierCurveProto.pointAt.call(this, t); + } + }; + + ECLinePath.prototype.tangentAt = function (t) { + var shape = this.shape; + var p = isStraightLine(shape) ? [shape.x2 - shape.x1, shape.y2 - shape.y1] : bezierCurveProto.tangentAt.call(this, t); + return normalize(p, p); + }; + + return ECLinePath; + }(Path); + + var SYMBOL_CATEGORIES = ['fromSymbol', 'toSymbol']; + + function makeSymbolTypeKey(symbolCategory) { + return '_' + symbolCategory + 'Type'; + } + + function createSymbol$1(name, lineData, idx) { + var symbolType = lineData.getItemVisual(idx, name); + + if (!symbolType || symbolType === 'none') { + return; + } + + var symbolSize = lineData.getItemVisual(idx, name + 'Size'); + var symbolRotate = lineData.getItemVisual(idx, name + 'Rotate'); + var symbolSizeArr = isArray(symbolSize) ? symbolSize : [symbolSize, symbolSize]; + var symbolPath = createSymbol(symbolType, -symbolSizeArr[0] / 2, -symbolSizeArr[1] / 2, symbolSizeArr[0], symbolSizeArr[1]); + symbolPath.__specifiedRotation = symbolRotate == null || isNaN(symbolRotate) ? void 0 : +symbolRotate * Math.PI / 180 || 0; + symbolPath.name = name; + return symbolPath; + } + + function createLine(points) { + var line = new ECLinePath({ + name: 'line', + subPixelOptimize: true + }); + setLinePoints(line.shape, points); + return line; + } + + function setLinePoints(targetShape, points) { + targetShape.x1 = points[0][0]; + targetShape.y1 = points[0][1]; + targetShape.x2 = points[1][0]; + targetShape.y2 = points[1][1]; + targetShape.percent = 1; + var cp1 = points[2]; + + if (cp1) { + targetShape.cpx1 = cp1[0]; + targetShape.cpy1 = cp1[1]; + } else { + targetShape.cpx1 = NaN; + targetShape.cpy1 = NaN; + } + } + + var Line$1 = function (_super) { + __extends(Line, _super); + + function Line(lineData, idx, seriesScope) { + var _this = _super.call(this) || this; + + _this._createLine(lineData, idx, seriesScope); + + return _this; + } + + Line.prototype._createLine = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + var linePoints = lineData.getItemLayout(idx); + var line = createLine(linePoints); + line.shape.percent = 0; + initProps(line, { + shape: { + percent: 1 + } + }, seriesModel, idx); + this.add(line); + each(SYMBOL_CATEGORIES, function (symbolCategory) { + var symbol = createSymbol$1(symbolCategory, lineData, idx); + this.add(symbol); + this[makeSymbolTypeKey(symbolCategory)] = lineData.getItemVisual(idx, symbolCategory); + }, this); + + this._updateCommonStl(lineData, idx, seriesScope); + }; + + Line.prototype.updateData = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + var line = this.childOfName('line'); + var linePoints = lineData.getItemLayout(idx); + var target = { + shape: {} + }; + setLinePoints(target.shape, linePoints); + updateProps(line, target, seriesModel, idx); + each(SYMBOL_CATEGORIES, function (symbolCategory) { + var symbolType = lineData.getItemVisual(idx, symbolCategory); + var key = makeSymbolTypeKey(symbolCategory); + + if (this[key] !== symbolType) { + this.remove(this.childOfName(symbolCategory)); + var symbol = createSymbol$1(symbolCategory, lineData, idx); + this.add(symbol); + } + + this[key] = symbolType; + }, this); + + this._updateCommonStl(lineData, idx, seriesScope); + }; + + Line.prototype.getLinePath = function () { + return this.childAt(0); + }; + + Line.prototype._updateCommonStl = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + var line = this.childOfName('line'); + var emphasisLineStyle = seriesScope && seriesScope.emphasisLineStyle; + var blurLineStyle = seriesScope && seriesScope.blurLineStyle; + var selectLineStyle = seriesScope && seriesScope.selectLineStyle; + var labelStatesModels = seriesScope && seriesScope.labelStatesModels; + + if (!seriesScope || lineData.hasItemOption) { + var itemModel = lineData.getItemModel(idx); + emphasisLineStyle = itemModel.getModel(['emphasis', 'lineStyle']).getLineStyle(); + blurLineStyle = itemModel.getModel(['blur', 'lineStyle']).getLineStyle(); + selectLineStyle = itemModel.getModel(['select', 'lineStyle']).getLineStyle(); + labelStatesModels = getLabelStatesModels(itemModel); + } + + var lineStyle = lineData.getItemVisual(idx, 'style'); + var visualColor = lineStyle.stroke; + line.useStyle(lineStyle); + line.style.fill = null; + line.style.strokeNoScale = true; + line.ensureState('emphasis').style = emphasisLineStyle; + line.ensureState('blur').style = blurLineStyle; + line.ensureState('select').style = selectLineStyle; + each(SYMBOL_CATEGORIES, function (symbolCategory) { + var symbol = this.childOfName(symbolCategory); + + if (symbol) { + symbol.setColor(visualColor); + symbol.style.opacity = lineStyle.opacity; + + for (var i = 0; i < SPECIAL_STATES.length; i++) { + var stateName = SPECIAL_STATES[i]; + var lineState = line.getState(stateName); + + if (lineState) { + var lineStateStyle = lineState.style || {}; + var state = symbol.ensureState(stateName); + var stateStyle = state.style || (state.style = {}); + + if (lineStateStyle.stroke != null) { + stateStyle[symbol.__isEmptyBrush ? 'stroke' : 'fill'] = lineStateStyle.stroke; + } + + if (lineStateStyle.opacity != null) { + stateStyle.opacity = lineStateStyle.opacity; + } + } + } + + symbol.markRedraw(); + } + }, this); + var rawVal = seriesModel.getRawValue(idx); + setLabelStyle(this, labelStatesModels, { + labelDataIndex: idx, + labelFetcher: { + getFormattedLabel: function (dataIndex, stateName) { + return seriesModel.getFormattedLabel(dataIndex, stateName, lineData.dataType); + } + }, + inheritColor: visualColor || '#000', + defaultOpacity: lineStyle.opacity, + defaultText: (rawVal == null ? lineData.getName(idx) : isFinite(rawVal) ? round(rawVal) : rawVal) + '' + }); + var label = this.getTextContent(); + + if (label) { + var labelNormalModel = labelStatesModels.normal; + label.__align = label.style.align; + label.__verticalAlign = label.style.verticalAlign; + label.__position = labelNormalModel.get('position') || 'middle'; + var distance = labelNormalModel.get('distance'); + + if (!isArray(distance)) { + distance = [distance, distance]; + } + + label.__labelDistance = distance; + } + + this.setTextConfig({ + position: null, + local: true, + inside: false + }); + enableHoverEmphasis(this); + }; + + Line.prototype.highlight = function () { + enterEmphasis(this); + }; + + Line.prototype.downplay = function () { + leaveEmphasis(this); + }; + + Line.prototype.updateLayout = function (lineData, idx) { + this.setLinePoints(lineData.getItemLayout(idx)); + }; + + Line.prototype.setLinePoints = function (points) { + var linePath = this.childOfName('line'); + setLinePoints(linePath.shape, points); + linePath.dirty(); + }; + + Line.prototype.beforeUpdate = function () { + var lineGroup = this; + var symbolFrom = lineGroup.childOfName('fromSymbol'); + var symbolTo = lineGroup.childOfName('toSymbol'); + var label = lineGroup.getTextContent(); + + if (!symbolFrom && !symbolTo && (!label || label.ignore)) { + return; + } + + var invScale = 1; + var parentNode = this.parent; + + while (parentNode) { + if (parentNode.scaleX) { + invScale /= parentNode.scaleX; + } + + parentNode = parentNode.parent; + } + + var line = lineGroup.childOfName('line'); + + if (!this.__dirty && !line.__dirty) { + return; + } + + var percent = line.shape.percent; + var fromPos = line.pointAt(0); + var toPos = line.pointAt(percent); + var d = sub([], toPos, fromPos); + normalize(d, d); + + function setSymbolRotation(symbol, percent) { + var specifiedRotation = symbol.__specifiedRotation; + + if (specifiedRotation == null) { + var tangent = line.tangentAt(percent); + symbol.attr('rotation', (percent === 1 ? -1 : 1) * Math.PI / 2 - Math.atan2(tangent[1], tangent[0])); + } else { + symbol.attr('rotation', specifiedRotation); + } + } + + if (symbolFrom) { + symbolFrom.setPosition(fromPos); + setSymbolRotation(symbolFrom, 0); + symbolFrom.scaleX = symbolFrom.scaleY = invScale * percent; + symbolFrom.markRedraw(); + } + + if (symbolTo) { + symbolTo.setPosition(toPos); + setSymbolRotation(symbolTo, 1); + symbolTo.scaleX = symbolTo.scaleY = invScale * percent; + symbolTo.markRedraw(); + } + + if (label && !label.ignore) { + label.x = label.y = 0; + label.originX = label.originY = 0; + var textAlign = void 0; + var textVerticalAlign = void 0; + var distance = label.__labelDistance; + var distanceX = distance[0] * invScale; + var distanceY = distance[1] * invScale; + var halfPercent = percent / 2; + var tangent = line.tangentAt(halfPercent); + var n = [tangent[1], -tangent[0]]; + var cp = line.pointAt(halfPercent); + + if (n[1] > 0) { + n[0] = -n[0]; + n[1] = -n[1]; + } + + var dir = tangent[0] < 0 ? -1 : 1; + + if (label.__position !== 'start' && label.__position !== 'end') { + var rotation = -Math.atan2(tangent[1], tangent[0]); + + if (toPos[0] < fromPos[0]) { + rotation = Math.PI + rotation; + } + + label.rotation = rotation; + } + + var dy = void 0; + + switch (label.__position) { + case 'insideStartTop': + case 'insideMiddleTop': + case 'insideEndTop': + case 'middle': + dy = -distanceY; + textVerticalAlign = 'bottom'; + break; + + case 'insideStartBottom': + case 'insideMiddleBottom': + case 'insideEndBottom': + dy = distanceY; + textVerticalAlign = 'top'; + break; + + default: + dy = 0; + textVerticalAlign = 'middle'; + } + + switch (label.__position) { + case 'end': + label.x = d[0] * distanceX + toPos[0]; + label.y = d[1] * distanceY + toPos[1]; + textAlign = d[0] > 0.8 ? 'left' : d[0] < -0.8 ? 'right' : 'center'; + textVerticalAlign = d[1] > 0.8 ? 'top' : d[1] < -0.8 ? 'bottom' : 'middle'; + break; + + case 'start': + label.x = -d[0] * distanceX + fromPos[0]; + label.y = -d[1] * distanceY + fromPos[1]; + textAlign = d[0] > 0.8 ? 'right' : d[0] < -0.8 ? 'left' : 'center'; + textVerticalAlign = d[1] > 0.8 ? 'bottom' : d[1] < -0.8 ? 'top' : 'middle'; + break; + + case 'insideStartTop': + case 'insideStart': + case 'insideStartBottom': + label.x = distanceX * dir + fromPos[0]; + label.y = fromPos[1] + dy; + textAlign = tangent[0] < 0 ? 'right' : 'left'; + label.originX = -distanceX * dir; + label.originY = -dy; + break; + + case 'insideMiddleTop': + case 'insideMiddle': + case 'insideMiddleBottom': + case 'middle': + label.x = cp[0]; + label.y = cp[1] + dy; + textAlign = 'center'; + label.originY = -dy; + break; + + case 'insideEndTop': + case 'insideEnd': + case 'insideEndBottom': + label.x = -distanceX * dir + toPos[0]; + label.y = toPos[1] + dy; + textAlign = tangent[0] >= 0 ? 'right' : 'left'; + label.originX = distanceX * dir; + label.originY = -dy; + break; + } + + label.scaleX = label.scaleY = invScale; + label.setStyle({ + verticalAlign: label.__verticalAlign || textVerticalAlign, + align: label.__align || textAlign + }); + } + }; + + return Line; + }(Group); + + var LineDraw = function () { + function LineDraw(LineCtor) { + this.group = new Group(); + this._LineCtor = LineCtor || Line$1; + } + + LineDraw.prototype.isPersistent = function () { + return true; + }; + + LineDraw.prototype.updateData = function (lineData) { + var _this = this; + + var lineDraw = this; + var group = lineDraw.group; + var oldLineData = lineDraw._lineData; + lineDraw._lineData = lineData; + + if (!oldLineData) { + group.removeAll(); + } + + var seriesScope = makeSeriesScope$1(lineData); + lineData.diff(oldLineData).add(function (idx) { + _this._doAdd(lineData, idx, seriesScope); + }).update(function (newIdx, oldIdx) { + _this._doUpdate(oldLineData, lineData, oldIdx, newIdx, seriesScope); + }).remove(function (idx) { + group.remove(oldLineData.getItemGraphicEl(idx)); + }).execute(); + }; + + LineDraw.prototype.updateLayout = function () { + var lineData = this._lineData; + + if (!lineData) { + return; + } + + lineData.eachItemGraphicEl(function (el, idx) { + el.updateLayout(lineData, idx); + }, this); + }; + + LineDraw.prototype.incrementalPrepareUpdate = function (lineData) { + this._seriesScope = makeSeriesScope$1(lineData); + this._lineData = null; + this.group.removeAll(); + }; + + LineDraw.prototype.incrementalUpdate = function (taskParams, lineData) { + function updateIncrementalAndHover(el) { + if (!el.isGroup && !isEffectObject(el)) { + el.incremental = true; + el.ensureState('emphasis').hoverLayer = true; + } + } + + for (var idx = taskParams.start; idx < taskParams.end; idx++) { + var itemLayout = lineData.getItemLayout(idx); + + if (lineNeedsDraw(itemLayout)) { + var el = new this._LineCtor(lineData, idx, this._seriesScope); + el.traverse(updateIncrementalAndHover); + this.group.add(el); + lineData.setItemGraphicEl(idx, el); + } + } + }; + + LineDraw.prototype.remove = function () { + this.group.removeAll(); + }; + + LineDraw.prototype._doAdd = function (lineData, idx, seriesScope) { + var itemLayout = lineData.getItemLayout(idx); + + if (!lineNeedsDraw(itemLayout)) { + return; + } + + var el = new this._LineCtor(lineData, idx, seriesScope); + lineData.setItemGraphicEl(idx, el); + this.group.add(el); + }; + + LineDraw.prototype._doUpdate = function (oldLineData, newLineData, oldIdx, newIdx, seriesScope) { + var itemEl = oldLineData.getItemGraphicEl(oldIdx); + + if (!lineNeedsDraw(newLineData.getItemLayout(newIdx))) { + this.group.remove(itemEl); + return; + } + + if (!itemEl) { + itemEl = new this._LineCtor(newLineData, newIdx, seriesScope); + } else { + itemEl.updateData(newLineData, newIdx, seriesScope); + } + + newLineData.setItemGraphicEl(newIdx, itemEl); + this.group.add(itemEl); + }; + + return LineDraw; + }(); + + function isEffectObject(el) { + return el.animators && el.animators.length > 0; + } + + function makeSeriesScope$1(lineData) { + var hostModel = lineData.hostModel; + return { + lineStyle: hostModel.getModel('lineStyle').getLineStyle(), + emphasisLineStyle: hostModel.getModel(['emphasis', 'lineStyle']).getLineStyle(), + blurLineStyle: hostModel.getModel(['blur', 'lineStyle']).getLineStyle(), + selectLineStyle: hostModel.getModel(['select', 'lineStyle']).getLineStyle(), + labelStatesModels: getLabelStatesModels(hostModel) + }; + } + + function isPointNaN(pt) { + return isNaN(pt[0]) || isNaN(pt[1]); + } + + function lineNeedsDraw(pts) { + return !isPointNaN(pts[0]) && !isPointNaN(pts[1]); + } + + var v1 = []; + var v2 = []; + var v3 = []; + var quadraticAt$1 = quadraticAt; + var v2DistSquare = distSquare; + var mathAbs$2 = Math.abs; + + function intersectCurveCircle(curvePoints, center, radius) { + var p0 = curvePoints[0]; + var p1 = curvePoints[1]; + var p2 = curvePoints[2]; + var d = Infinity; + var t; + var radiusSquare = radius * radius; + var interval = 0.1; + + for (var _t = 0.1; _t <= 0.9; _t += 0.1) { + v1[0] = quadraticAt$1(p0[0], p1[0], p2[0], _t); + v1[1] = quadraticAt$1(p0[1], p1[1], p2[1], _t); + var diff = mathAbs$2(v2DistSquare(v1, center) - radiusSquare); + + if (diff < d) { + d = diff; + t = _t; + } + } + + for (var i = 0; i < 32; i++) { + var next = t + interval; + v2[0] = quadraticAt$1(p0[0], p1[0], p2[0], t); + v2[1] = quadraticAt$1(p0[1], p1[1], p2[1], t); + v3[0] = quadraticAt$1(p0[0], p1[0], p2[0], next); + v3[1] = quadraticAt$1(p0[1], p1[1], p2[1], next); + var diff = v2DistSquare(v2, center) - radiusSquare; + + if (mathAbs$2(diff) < 1e-2) { + break; + } + + var nextDiff = v2DistSquare(v3, center) - radiusSquare; + interval /= 2; + + if (diff < 0) { + if (nextDiff >= 0) { + t = t + interval; + } else { + t = t - interval; + } + } else { + if (nextDiff >= 0) { + t = t - interval; + } else { + t = t + interval; + } + } + } + + return t; + } + + function adjustEdge(graph, scale) { + var tmp0 = []; + var quadraticSubdivide$1 = quadraticSubdivide; + var pts = [[], [], []]; + var pts2 = [[], []]; + var v = []; + scale /= 2; + graph.eachEdge(function (edge, idx) { + var linePoints = edge.getLayout(); + var fromSymbol = edge.getVisual('fromSymbol'); + var toSymbol = edge.getVisual('toSymbol'); + + if (!linePoints.__original) { + linePoints.__original = [clone$1(linePoints[0]), clone$1(linePoints[1])]; + + if (linePoints[2]) { + linePoints.__original.push(clone$1(linePoints[2])); + } + } + + var originalPoints = linePoints.__original; + + if (linePoints[2] != null) { + copy(pts[0], originalPoints[0]); + copy(pts[1], originalPoints[2]); + copy(pts[2], originalPoints[1]); + + if (fromSymbol && fromSymbol !== 'none') { + var symbolSize = getSymbolSize(edge.node1); + var t = intersectCurveCircle(pts, originalPoints[0], symbolSize * scale); + quadraticSubdivide$1(pts[0][0], pts[1][0], pts[2][0], t, tmp0); + pts[0][0] = tmp0[3]; + pts[1][0] = tmp0[4]; + quadraticSubdivide$1(pts[0][1], pts[1][1], pts[2][1], t, tmp0); + pts[0][1] = tmp0[3]; + pts[1][1] = tmp0[4]; + } + + if (toSymbol && toSymbol !== 'none') { + var symbolSize = getSymbolSize(edge.node2); + var t = intersectCurveCircle(pts, originalPoints[1], symbolSize * scale); + quadraticSubdivide$1(pts[0][0], pts[1][0], pts[2][0], t, tmp0); + pts[1][0] = tmp0[1]; + pts[2][0] = tmp0[2]; + quadraticSubdivide$1(pts[0][1], pts[1][1], pts[2][1], t, tmp0); + pts[1][1] = tmp0[1]; + pts[2][1] = tmp0[2]; + } + + copy(linePoints[0], pts[0]); + copy(linePoints[1], pts[2]); + copy(linePoints[2], pts[1]); + } else { + copy(pts2[0], originalPoints[0]); + copy(pts2[1], originalPoints[1]); + sub(v, pts2[1], pts2[0]); + normalize(v, v); + + if (fromSymbol && fromSymbol !== 'none') { + var symbolSize = getSymbolSize(edge.node1); + scaleAndAdd(pts2[0], pts2[0], v, symbolSize * scale); + } + + if (toSymbol && toSymbol !== 'none') { + var symbolSize = getSymbolSize(edge.node2); + scaleAndAdd(pts2[1], pts2[1], v, -symbolSize * scale); + } + + copy(linePoints[0], pts2[0]); + copy(linePoints[1], pts2[1]); + } + }); + } + + function isViewCoordSys(coordSys) { + return coordSys.type === 'view'; + } + + var GraphView = function (_super) { + __extends(GraphView, _super); + + function GraphView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GraphView.type; + return _this; + } + + GraphView.prototype.init = function (ecModel, api) { + var symbolDraw = new SymbolDraw(); + var lineDraw = new LineDraw(); + var group = this.group; + this._controller = new RoamController(api.getZr()); + this._controllerHost = { + target: group + }; + group.add(symbolDraw.group); + group.add(lineDraw.group); + this._symbolDraw = symbolDraw; + this._lineDraw = lineDraw; + this._firstRender = true; + }; + + GraphView.prototype.render = function (seriesModel, ecModel, api) { + var _this = this; + + var coordSys = seriesModel.coordinateSystem; + this._model = seriesModel; + var symbolDraw = this._symbolDraw; + var lineDraw = this._lineDraw; + var group = this.group; + + if (isViewCoordSys(coordSys)) { + var groupNewProp = { + x: coordSys.x, + y: coordSys.y, + scaleX: coordSys.scaleX, + scaleY: coordSys.scaleY + }; + + if (this._firstRender) { + group.attr(groupNewProp); + } else { + updateProps(group, groupNewProp, seriesModel); + } + } + + adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel)); + var data = seriesModel.getData(); + symbolDraw.updateData(data); + var edgeData = seriesModel.getEdgeData(); + lineDraw.updateData(edgeData); + + this._updateNodeAndLinkScale(); + + this._updateController(seriesModel, ecModel, api); + + clearTimeout(this._layoutTimeout); + var forceLayout = seriesModel.forceLayout; + var layoutAnimation = seriesModel.get(['force', 'layoutAnimation']); + + if (forceLayout) { + this._startForceLayoutIteration(forceLayout, layoutAnimation); + } + + data.graph.eachNode(function (node) { + var idx = node.dataIndex; + var el = node.getGraphicEl(); + var itemModel = node.getModel(); + el.off('drag').off('dragend'); + var draggable = itemModel.get('draggable'); + + if (draggable) { + el.on('drag', function () { + if (forceLayout) { + forceLayout.warmUp(); + !_this._layouting && _this._startForceLayoutIteration(forceLayout, layoutAnimation); + forceLayout.setFixed(idx); + data.setItemLayout(idx, [el.x, el.y]); + } + }).on('dragend', function () { + if (forceLayout) { + forceLayout.setUnfixed(idx); + } + }); + } + + el.setDraggable(draggable && !!forceLayout); + var focus = itemModel.get(['emphasis', 'focus']); + + if (focus === 'adjacency') { + getECData(el).focus = node.getAdjacentDataIndices(); + } + }); + data.graph.eachEdge(function (edge) { + var el = edge.getGraphicEl(); + var focus = edge.getModel().get(['emphasis', 'focus']); + + if (focus === 'adjacency') { + getECData(el).focus = { + edge: [edge.dataIndex], + node: [edge.node1.dataIndex, edge.node2.dataIndex] + }; + } + }); + var circularRotateLabel = seriesModel.get('layout') === 'circular' && seriesModel.get(['circular', 'rotateLabel']); + var cx = data.getLayout('cx'); + var cy = data.getLayout('cy'); + data.eachItemGraphicEl(function (el, idx) { + var itemModel = data.getItemModel(idx); + var labelRotate = itemModel.get(['label', 'rotate']) || 0; + var symbolPath = el.getSymbolPath(); + + if (circularRotateLabel) { + var pos = data.getItemLayout(idx); + var rad = Math.atan2(pos[1] - cy, pos[0] - cx); + + if (rad < 0) { + rad = Math.PI * 2 + rad; + } + + var isLeft = pos[0] < cx; + + if (isLeft) { + rad = rad - Math.PI; + } + + var textPosition = isLeft ? 'left' : 'right'; + symbolPath.setTextConfig({ + rotation: -rad, + position: textPosition, + origin: 'center' + }); + var emphasisState = symbolPath.ensureState('emphasis'); + extend(emphasisState.textConfig || (emphasisState.textConfig = {}), { + position: textPosition + }); + } else { + symbolPath.setTextConfig({ + rotation: labelRotate *= Math.PI / 180 + }); + } + }); + this._firstRender = false; + }; + + GraphView.prototype.dispose = function () { + this._controller && this._controller.dispose(); + this._controllerHost = null; + }; + + GraphView.prototype._startForceLayoutIteration = function (forceLayout, layoutAnimation) { + var self = this; + + (function step() { + forceLayout.step(function (stopped) { + self.updateLayout(self._model); + (self._layouting = !stopped) && (layoutAnimation ? self._layoutTimeout = setTimeout(step, 16) : step()); + }); + })(); + }; + + GraphView.prototype._updateController = function (seriesModel, ecModel, api) { + var _this = this; + + var controller = this._controller; + var controllerHost = this._controllerHost; + var group = this.group; + controller.setPointerChecker(function (e, x, y) { + var rect = group.getBoundingRect(); + rect.applyTransform(group.transform); + return rect.contain(x, y) && !onIrrelevantElement(e, api, seriesModel); + }); + + if (!isViewCoordSys(seriesModel.coordinateSystem)) { + controller.disable(); + return; + } + + controller.enable(seriesModel.get('roam')); + controllerHost.zoomLimit = seriesModel.get('scaleLimit'); + controllerHost.zoom = seriesModel.coordinateSystem.getZoom(); + controller.off('pan').off('zoom').on('pan', function (e) { + updateViewOnPan(controllerHost, e.dx, e.dy); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'graphRoam', + dx: e.dx, + dy: e.dy + }); + }).on('zoom', function (e) { + updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'graphRoam', + zoom: e.scale, + originX: e.originX, + originY: e.originY + }); + + _this._updateNodeAndLinkScale(); + + adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel)); + + _this._lineDraw.updateLayout(); + + api.updateLabelLayout(); + }); + }; + + GraphView.prototype._updateNodeAndLinkScale = function () { + var seriesModel = this._model; + var data = seriesModel.getData(); + var nodeScale = getNodeGlobalScale(seriesModel); + data.eachItemGraphicEl(function (el, idx) { + el.setSymbolScale(nodeScale); + }); + }; + + GraphView.prototype.updateLayout = function (seriesModel) { + adjustEdge(seriesModel.getGraph(), getNodeGlobalScale(seriesModel)); + + this._symbolDraw.updateLayout(); + + this._lineDraw.updateLayout(); + }; + + GraphView.prototype.remove = function (ecModel, api) { + this._symbolDraw && this._symbolDraw.remove(); + this._lineDraw && this._lineDraw.remove(); + }; + + GraphView.type = 'graph'; + return GraphView; + }(ChartView); + + function generateNodeKey(id) { + return '_EC_' + id; + } + + var Graph = function () { + function Graph(directed) { + this.type = 'graph'; + this.nodes = []; + this.edges = []; + this._nodesMap = {}; + this._edgesMap = {}; + this._directed = directed || false; + } + + Graph.prototype.isDirected = function () { + return this._directed; + }; + + Graph.prototype.addNode = function (id, dataIndex) { + id = id == null ? '' + dataIndex : '' + id; + var nodesMap = this._nodesMap; + + if (nodesMap[generateNodeKey(id)]) { + if ("development" !== 'production') { + console.error('Graph nodes have duplicate name or id'); + } + + return; + } + + var node = new GraphNode(id, dataIndex); + node.hostGraph = this; + this.nodes.push(node); + nodesMap[generateNodeKey(id)] = node; + return node; + }; + + Graph.prototype.getNodeByIndex = function (dataIndex) { + var rawIdx = this.data.getRawIndex(dataIndex); + return this.nodes[rawIdx]; + }; + + Graph.prototype.getNodeById = function (id) { + return this._nodesMap[generateNodeKey(id)]; + }; + + Graph.prototype.addEdge = function (n1, n2, dataIndex) { + var nodesMap = this._nodesMap; + var edgesMap = this._edgesMap; + + if (typeof n1 === 'number') { + n1 = this.nodes[n1]; + } + + if (typeof n2 === 'number') { + n2 = this.nodes[n2]; + } + + if (!(n1 instanceof GraphNode)) { + n1 = nodesMap[generateNodeKey(n1)]; + } + + if (!(n2 instanceof GraphNode)) { + n2 = nodesMap[generateNodeKey(n2)]; + } + + if (!n1 || !n2) { + return; + } + + var key = n1.id + '-' + n2.id; + var edge = new GraphEdge(n1, n2, dataIndex); + edge.hostGraph = this; + + if (this._directed) { + n1.outEdges.push(edge); + n2.inEdges.push(edge); + } + + n1.edges.push(edge); + + if (n1 !== n2) { + n2.edges.push(edge); + } + + this.edges.push(edge); + edgesMap[key] = edge; + return edge; + }; + + Graph.prototype.getEdgeByIndex = function (dataIndex) { + var rawIdx = this.edgeData.getRawIndex(dataIndex); + return this.edges[rawIdx]; + }; + + Graph.prototype.getEdge = function (n1, n2) { + if (n1 instanceof GraphNode) { + n1 = n1.id; + } + + if (n2 instanceof GraphNode) { + n2 = n2.id; + } + + var edgesMap = this._edgesMap; + + if (this._directed) { + return edgesMap[n1 + '-' + n2]; + } else { + return edgesMap[n1 + '-' + n2] || edgesMap[n2 + '-' + n1]; + } + }; + + Graph.prototype.eachNode = function (cb, context) { + var nodes = this.nodes; + var len = nodes.length; + + for (var i = 0; i < len; i++) { + if (nodes[i].dataIndex >= 0) { + cb.call(context, nodes[i], i); + } + } + }; + + Graph.prototype.eachEdge = function (cb, context) { + var edges = this.edges; + var len = edges.length; + + for (var i = 0; i < len; i++) { + if (edges[i].dataIndex >= 0 && edges[i].node1.dataIndex >= 0 && edges[i].node2.dataIndex >= 0) { + cb.call(context, edges[i], i); + } + } + }; + + Graph.prototype.breadthFirstTraverse = function (cb, startNode, direction, context) { + if (!(startNode instanceof GraphNode)) { + startNode = this._nodesMap[generateNodeKey(startNode)]; + } + + if (!startNode) { + return; + } + + var edgeType = direction === 'out' ? 'outEdges' : direction === 'in' ? 'inEdges' : 'edges'; + + for (var i = 0; i < this.nodes.length; i++) { + this.nodes[i].__visited = false; + } + + if (cb.call(context, startNode, null)) { + return; + } + + var queue = [startNode]; + + while (queue.length) { + var currentNode = queue.shift(); + var edges = currentNode[edgeType]; + + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + var otherNode = e.node1 === currentNode ? e.node2 : e.node1; + + if (!otherNode.__visited) { + if (cb.call(context, otherNode, currentNode)) { + return; + } + + queue.push(otherNode); + otherNode.__visited = true; + } + } + } + }; + + Graph.prototype.update = function () { + var data = this.data; + var edgeData = this.edgeData; + var nodes = this.nodes; + var edges = this.edges; + + for (var i = 0, len = nodes.length; i < len; i++) { + nodes[i].dataIndex = -1; + } + + for (var i = 0, len = data.count(); i < len; i++) { + nodes[data.getRawIndex(i)].dataIndex = i; + } + + edgeData.filterSelf(function (idx) { + var edge = edges[edgeData.getRawIndex(idx)]; + return edge.node1.dataIndex >= 0 && edge.node2.dataIndex >= 0; + }); + + for (var i = 0, len = edges.length; i < len; i++) { + edges[i].dataIndex = -1; + } + + for (var i = 0, len = edgeData.count(); i < len; i++) { + edges[edgeData.getRawIndex(i)].dataIndex = i; + } + }; + + Graph.prototype.clone = function () { + var graph = new Graph(this._directed); + var nodes = this.nodes; + var edges = this.edges; + + for (var i = 0; i < nodes.length; i++) { + graph.addNode(nodes[i].id, nodes[i].dataIndex); + } + + for (var i = 0; i < edges.length; i++) { + var e = edges[i]; + graph.addEdge(e.node1.id, e.node2.id, e.dataIndex); + } + + return graph; + }; + return Graph; + }(); + + var GraphNode = function () { + function GraphNode(id, dataIndex) { + this.inEdges = []; + this.outEdges = []; + this.edges = []; + this.dataIndex = -1; + this.id = id == null ? '' : id; + this.dataIndex = dataIndex == null ? -1 : dataIndex; + } + + GraphNode.prototype.degree = function () { + return this.edges.length; + }; + + GraphNode.prototype.inDegree = function () { + return this.inEdges.length; + }; + + GraphNode.prototype.outDegree = function () { + return this.outEdges.length; + }; + + GraphNode.prototype.getModel = function (path) { + if (this.dataIndex < 0) { + return; + } + + var graph = this.hostGraph; + var itemModel = graph.data.getItemModel(this.dataIndex); + return itemModel.getModel(path); + }; + + GraphNode.prototype.getAdjacentDataIndices = function () { + var dataIndices = { + edge: [], + node: [] + }; + + for (var i = 0; i < this.edges.length; i++) { + var adjacentEdge = this.edges[i]; + + if (adjacentEdge.dataIndex < 0) { + continue; + } + + dataIndices.edge.push(adjacentEdge.dataIndex); + dataIndices.node.push(adjacentEdge.node1.dataIndex, adjacentEdge.node2.dataIndex); + } + + return dataIndices; + }; + + return GraphNode; + }(); + + var GraphEdge = function () { + function GraphEdge(n1, n2, dataIndex) { + this.dataIndex = -1; + this.node1 = n1; + this.node2 = n2; + this.dataIndex = dataIndex == null ? -1 : dataIndex; + } + + GraphEdge.prototype.getModel = function (path) { + if (this.dataIndex < 0) { + return; + } + + var graph = this.hostGraph; + var itemModel = graph.edgeData.getItemModel(this.dataIndex); + return itemModel.getModel(path); + }; + + GraphEdge.prototype.getAdjacentDataIndices = function () { + return { + edge: [this.dataIndex], + node: [this.node1.dataIndex, this.node2.dataIndex] + }; + }; + + return GraphEdge; + }(); + + function createGraphDataProxyMixin(hostName, dataName) { + return { + getValue: function (dimension) { + var data = this[hostName][dataName]; + return data.get(data.getDimension(dimension || 'value'), this.dataIndex); + }, + setVisual: function (key, value) { + this.dataIndex >= 0 && this[hostName][dataName].setItemVisual(this.dataIndex, key, value); + }, + getVisual: function (key) { + return this[hostName][dataName].getItemVisual(this.dataIndex, key); + }, + setLayout: function (layout, merge) { + this.dataIndex >= 0 && this[hostName][dataName].setItemLayout(this.dataIndex, layout, merge); + }, + getLayout: function () { + return this[hostName][dataName].getItemLayout(this.dataIndex); + }, + getGraphicEl: function () { + return this[hostName][dataName].getItemGraphicEl(this.dataIndex); + }, + getRawIndex: function () { + return this[hostName][dataName].getRawIndex(this.dataIndex); + } + }; + } + mixin(GraphNode, createGraphDataProxyMixin('hostGraph', 'data')); + mixin(GraphEdge, createGraphDataProxyMixin('hostGraph', 'edgeData')); + + function createGraphFromNodeEdge(nodes, edges, seriesModel, directed, beforeLink) { + var graph = new Graph(directed); + + for (var i = 0; i < nodes.length; i++) { + graph.addNode(retrieve(nodes[i].id, nodes[i].name, i), i); + } + + var linkNameList = []; + var validEdges = []; + var linkCount = 0; + + for (var i = 0; i < edges.length; i++) { + var link = edges[i]; + var source = link.source; + var target = link.target; + + if (graph.addEdge(source, target, linkCount)) { + validEdges.push(link); + linkNameList.push(retrieve(convertOptionIdName(link.id, null), source + ' > ' + target)); + linkCount++; + } + } + + var coordSys = seriesModel.get('coordinateSystem'); + var nodeData; + + if (coordSys === 'cartesian2d' || coordSys === 'polar') { + nodeData = createListFromArray(nodes, seriesModel); + } else { + var coordSysCtor = CoordinateSystemManager.get(coordSys); + var coordDimensions = coordSysCtor ? coordSysCtor.dimensions || [] : []; + + if (indexOf(coordDimensions, 'value') < 0) { + coordDimensions.concat(['value']); + } + + var dimensionNames = createDimensions(nodes, { + coordDimensions: coordDimensions + }); + nodeData = new List(dimensionNames, seriesModel); + nodeData.initData(nodes); + } + + var edgeData = new List(['value'], seriesModel); + edgeData.initData(validEdges, linkNameList); + beforeLink && beforeLink(nodeData, edgeData); + linkList({ + mainData: nodeData, + struct: graph, + structAttr: 'graph', + datas: { + node: nodeData, + edge: edgeData + }, + datasAttr: { + node: 'data', + edge: 'edgeData' + } + }); + graph.update(); + return graph; + } + + var GraphSeriesModel = function (_super) { + __extends(GraphSeriesModel, _super); + + function GraphSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GraphSeriesModel.type; + _this.hasSymbolVisual = true; + return _this; + } + + GraphSeriesModel.prototype.init = function (option) { + _super.prototype.init.apply(this, arguments); + + var self = this; + + function getCategoriesData() { + return self._categoriesData; + } + + this.legendVisualProvider = new LegendVisualProvider(getCategoriesData, getCategoriesData); + this.fillDataTextStyle(option.edges || option.links); + + this._updateCategoriesData(); + }; + + GraphSeriesModel.prototype.mergeOption = function (option) { + _super.prototype.mergeOption.apply(this, arguments); + + this.fillDataTextStyle(option.edges || option.links); + + this._updateCategoriesData(); + }; + + GraphSeriesModel.prototype.mergeDefaultAndTheme = function (option) { + _super.prototype.mergeDefaultAndTheme.apply(this, arguments); + + defaultEmphasis(option, 'edgeLabel', ['show']); + }; + + GraphSeriesModel.prototype.getInitialData = function (option, ecModel) { + var edges = option.edges || option.links || []; + var nodes = option.data || option.nodes || []; + var self = this; + + if (nodes && edges) { + initCurvenessList(this); + var graph = createGraphFromNodeEdge(nodes, edges, this, true, beforeLink); + each(graph.edges, function (edge) { + createEdgeMapForCurveness(edge.node1, edge.node2, this, edge.dataIndex); + }, this); + return graph.data; + } + + function beforeLink(nodeData, edgeData) { + nodeData.wrapMethod('getItemModel', function (model) { + var categoriesModels = self._categoriesModels; + var categoryIdx = model.getShallow('category'); + var categoryModel = categoriesModels[categoryIdx]; + + if (categoryModel) { + categoryModel.parentModel = model.parentModel; + model.parentModel = categoryModel; + } + + return model; + }); + var oldGetModel = Model.prototype.getModel; + + function newGetModel(path, parentModel) { + var model = oldGetModel.call(this, path, parentModel); + model.resolveParentPath = resolveParentPath; + return model; + } + + edgeData.wrapMethod('getItemModel', function (model) { + model.resolveParentPath = resolveParentPath; + model.getModel = newGetModel; + return model; + }); + + function resolveParentPath(pathArr) { + if (pathArr && (pathArr[0] === 'label' || pathArr[1] === 'label')) { + var newPathArr = pathArr.slice(); + + if (pathArr[0] === 'label') { + newPathArr[0] = 'edgeLabel'; + } else if (pathArr[1] === 'label') { + newPathArr[1] = 'edgeLabel'; + } + + return newPathArr; + } + + return pathArr; + } + } + }; + + GraphSeriesModel.prototype.getGraph = function () { + return this.getData().graph; + }; + + GraphSeriesModel.prototype.getEdgeData = function () { + return this.getGraph().edgeData; + }; + + GraphSeriesModel.prototype.getCategoriesData = function () { + return this._categoriesData; + }; + + GraphSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + if (dataType === 'edge') { + var nodeData = this.getData(); + var params = this.getDataParams(dataIndex, dataType); + var edge = nodeData.graph.getEdgeByIndex(dataIndex); + var sourceName = nodeData.getName(edge.node1.dataIndex); + var targetName = nodeData.getName(edge.node2.dataIndex); + var nameArr = []; + sourceName != null && nameArr.push(sourceName); + targetName != null && nameArr.push(targetName); + return createTooltipMarkup('nameValue', { + name: nameArr.join(' > '), + value: params.value, + noValue: params.value == null + }); + } + + var nodeMarkup = defaultSeriesFormatTooltip({ + series: this, + dataIndex: dataIndex, + multipleSeries: multipleSeries + }); + return nodeMarkup; + }; + + GraphSeriesModel.prototype._updateCategoriesData = function () { + var categories = map(this.option.categories || [], function (category) { + return category.value != null ? category : extend({ + value: 0 + }, category); + }); + var categoriesData = new List(['value'], this); + categoriesData.initData(categories); + this._categoriesData = categoriesData; + this._categoriesModels = categoriesData.mapArray(function (idx) { + return categoriesData.getItemModel(idx); + }); + }; + + GraphSeriesModel.prototype.setZoom = function (zoom) { + this.option.zoom = zoom; + }; + + GraphSeriesModel.prototype.setCenter = function (center) { + this.option.center = center; + }; + + GraphSeriesModel.prototype.isAnimationEnabled = function () { + return _super.prototype.isAnimationEnabled.call(this) && !(this.get('layout') === 'force' && this.get(['force', 'layoutAnimation'])); + }; + + GraphSeriesModel.type = 'series.graph'; + GraphSeriesModel.dependencies = ['grid', 'polar', 'geo', 'singleAxis', 'calendar']; + GraphSeriesModel.defaultOption = { + zlevel: 0, + z: 2, + coordinateSystem: 'view', + legendHoverLink: true, + layout: null, + focusNodeAdjacency: false, + circular: { + rotateLabel: false + }, + force: { + initLayout: null, + repulsion: [0, 50], + gravity: 0.1, + friction: 0.6, + edgeLength: 30, + layoutAnimation: true + }, + left: 'center', + top: 'center', + symbol: 'circle', + symbolSize: 10, + edgeSymbol: ['none', 'none'], + edgeSymbolSize: 10, + edgeLabel: { + position: 'middle', + distance: 5 + }, + draggable: false, + roam: false, + center: null, + zoom: 1, + nodeScaleRatio: 0.6, + label: { + show: false, + formatter: '{b}' + }, + itemStyle: {}, + lineStyle: { + color: '#aaa', + width: 1, + opacity: 0.5 + }, + emphasis: { + scale: true, + label: { + show: true + } + }, + select: { + itemStyle: { + borderColor: '#212121' + } + } + }; + return GraphSeriesModel; + }(SeriesModel); + + var actionInfo = { + type: 'graphRoam', + event: 'graphRoam', + update: 'none' + }; + function install$c(registers) { + registers.registerChartView(GraphView); + registers.registerSeriesModel(GraphSeriesModel); + registers.registerProcessor(categoryFilter); + registers.registerVisual(categoryVisual); + registers.registerVisual(graphEdgeVisual); + registers.registerLayout(graphSimpleLayout); + registers.registerLayout(registers.PRIORITY.VISUAL.POST_CHART_LAYOUT, graphCircularLayout); + registers.registerLayout(graphForceLayout); + registers.registerCoordinateSystem('graphView', { + dimensions: View.dimensions, + create: createViewCoordSys + }); + registers.registerAction({ + type: 'focusNodeAdjacency', + event: 'focusNodeAdjacency', + update: 'series:focusNodeAdjacency' + }, function () {}); + registers.registerAction({ + type: 'unfocusNodeAdjacency', + event: 'unfocusNodeAdjacency', + update: 'series:unfocusNodeAdjacency' + }, function () {}); + registers.registerAction(actionInfo, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'series', + query: payload + }, function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var res = updateCenterAndZoom(coordSys, payload); + seriesModel.setCenter && seriesModel.setCenter(res.center); + seriesModel.setZoom && seriesModel.setZoom(res.zoom); + }); + }); + } + + var PointerShape = function () { + function PointerShape() { + this.angle = 0; + this.width = 10; + this.r = 10; + this.x = 0; + this.y = 0; + } + + return PointerShape; + }(); + + var PointerPath = function (_super) { + __extends(PointerPath, _super); + + function PointerPath(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'pointer'; + return _this; + } + + PointerPath.prototype.getDefaultShape = function () { + return new PointerShape(); + }; + + PointerPath.prototype.buildPath = function (ctx, shape) { + var mathCos = Math.cos; + var mathSin = Math.sin; + var r = shape.r; + var width = shape.width; + var angle = shape.angle; + var x = shape.x - mathCos(angle) * width * (width >= r / 3 ? 1 : 2); + var y = shape.y - mathSin(angle) * width * (width >= r / 3 ? 1 : 2); + angle = shape.angle - Math.PI / 2; + ctx.moveTo(x, y); + ctx.lineTo(shape.x + mathCos(angle) * width, shape.y + mathSin(angle) * width); + ctx.lineTo(shape.x + mathCos(shape.angle) * r, shape.y + mathSin(shape.angle) * r); + ctx.lineTo(shape.x - mathCos(angle) * width, shape.y - mathSin(angle) * width); + ctx.lineTo(x, y); + }; + + return PointerPath; + }(Path); + + function parsePosition(seriesModel, api) { + var center = seriesModel.get('center'); + var width = api.getWidth(); + var height = api.getHeight(); + var size = Math.min(width, height); + var cx = parsePercent$1(center[0], api.getWidth()); + var cy = parsePercent$1(center[1], api.getHeight()); + var r = parsePercent$1(seriesModel.get('radius'), size / 2); + return { + cx: cx, + cy: cy, + r: r + }; + } + + function formatLabel(value, labelFormatter) { + var label = value == null ? '' : value + ''; + + if (labelFormatter) { + if (typeof labelFormatter === 'string') { + label = labelFormatter.replace('{value}', label); + } else if (typeof labelFormatter === 'function') { + label = labelFormatter(value); + } + } + + return label; + } + + var PI2$9 = Math.PI * 2; + + var GaugeView = function (_super) { + __extends(GaugeView, _super); + + function GaugeView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GaugeView.type; + return _this; + } + + GaugeView.prototype.render = function (seriesModel, ecModel, api) { + this.group.removeAll(); + var colorList = seriesModel.get(['axisLine', 'lineStyle', 'color']); + var posInfo = parsePosition(seriesModel, api); + + this._renderMain(seriesModel, ecModel, api, colorList, posInfo); + + this._data = seriesModel.getData(); + }; + + GaugeView.prototype.dispose = function () {}; + + GaugeView.prototype._renderMain = function (seriesModel, ecModel, api, colorList, posInfo) { + var group = this.group; + var clockwise = seriesModel.get('clockwise'); + var startAngle = -seriesModel.get('startAngle') / 180 * Math.PI; + var endAngle = -seriesModel.get('endAngle') / 180 * Math.PI; + var axisLineModel = seriesModel.getModel('axisLine'); + var roundCap = axisLineModel.get('roundCap'); + var MainPath = roundCap ? SausagePath : Sector; + var showAxis = axisLineModel.get('show'); + var lineStyleModel = axisLineModel.getModel('lineStyle'); + var axisLineWidth = lineStyleModel.get('width'); + var angleRangeSpan = !((endAngle - startAngle) % PI2$9) && endAngle !== startAngle ? PI2$9 : (endAngle - startAngle) % PI2$9; + var prevEndAngle = startAngle; + + for (var i = 0; showAxis && i < colorList.length; i++) { + var percent = Math.min(Math.max(colorList[i][0], 0), 1); + endAngle = startAngle + angleRangeSpan * percent; + var sector = new MainPath({ + shape: { + startAngle: prevEndAngle, + endAngle: endAngle, + cx: posInfo.cx, + cy: posInfo.cy, + clockwise: clockwise, + r0: posInfo.r - axisLineWidth, + r: posInfo.r + }, + silent: true + }); + sector.setStyle({ + fill: colorList[i][1] + }); + sector.setStyle(lineStyleModel.getLineStyle(['color', 'width'])); + group.add(sector); + prevEndAngle = endAngle; + } + + var getColor = function (percent) { + if (percent <= 0) { + return colorList[0][1]; + } + + var i; + + for (i = 0; i < colorList.length; i++) { + if (colorList[i][0] >= percent && (i === 0 ? 0 : colorList[i - 1][0]) < percent) { + return colorList[i][1]; + } + } + + return colorList[i - 1][1]; + }; + + if (!clockwise) { + var tmp = startAngle; + startAngle = endAngle; + endAngle = tmp; + } + + this._renderTicks(seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise, axisLineWidth); + + this._renderTitleAndDetail(seriesModel, ecModel, api, getColor, posInfo); + + this._renderAnchor(seriesModel, posInfo); + + this._renderPointer(seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise, axisLineWidth); + }; + + GaugeView.prototype._renderTicks = function (seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise, axisLineWidth) { + var group = this.group; + var cx = posInfo.cx; + var cy = posInfo.cy; + var r = posInfo.r; + var minVal = +seriesModel.get('min'); + var maxVal = +seriesModel.get('max'); + var splitLineModel = seriesModel.getModel('splitLine'); + var tickModel = seriesModel.getModel('axisTick'); + var labelModel = seriesModel.getModel('axisLabel'); + var splitNumber = seriesModel.get('splitNumber'); + var subSplitNumber = tickModel.get('splitNumber'); + var splitLineLen = parsePercent$1(splitLineModel.get('length'), r); + var tickLen = parsePercent$1(tickModel.get('length'), r); + var angle = startAngle; + var step = (endAngle - startAngle) / splitNumber; + var subStep = step / subSplitNumber; + var splitLineStyle = splitLineModel.getModel('lineStyle').getLineStyle(); + var tickLineStyle = tickModel.getModel('lineStyle').getLineStyle(); + var splitLineDistance = splitLineModel.get('distance'); + var unitX; + var unitY; + + for (var i = 0; i <= splitNumber; i++) { + unitX = Math.cos(angle); + unitY = Math.sin(angle); + + if (splitLineModel.get('show')) { + var distance = splitLineDistance ? splitLineDistance + axisLineWidth : axisLineWidth; + var splitLine = new Line({ + shape: { + x1: unitX * (r - distance) + cx, + y1: unitY * (r - distance) + cy, + x2: unitX * (r - splitLineLen - distance) + cx, + y2: unitY * (r - splitLineLen - distance) + cy + }, + style: splitLineStyle, + silent: true + }); + + if (splitLineStyle.stroke === 'auto') { + splitLine.setStyle({ + stroke: getColor(i / splitNumber) + }); + } + + group.add(splitLine); + } + + if (labelModel.get('show')) { + var distance = labelModel.get('distance') + splitLineDistance; + var label = formatLabel(round(i / splitNumber * (maxVal - minVal) + minVal), labelModel.get('formatter')); + var autoColor = getColor(i / splitNumber); + group.add(new ZRText({ + style: createTextStyle(labelModel, { + text: label, + x: unitX * (r - splitLineLen - distance) + cx, + y: unitY * (r - splitLineLen - distance) + cy, + verticalAlign: unitY < -0.8 ? 'top' : unitY > 0.8 ? 'bottom' : 'middle', + align: unitX < -0.4 ? 'left' : unitX > 0.4 ? 'right' : 'center' + }, { + inheritColor: autoColor + }), + silent: true + })); + } + + if (tickModel.get('show') && i !== splitNumber) { + var distance = tickModel.get('distance'); + distance = distance ? distance + axisLineWidth : axisLineWidth; + + for (var j = 0; j <= subSplitNumber; j++) { + unitX = Math.cos(angle); + unitY = Math.sin(angle); + var tickLine = new Line({ + shape: { + x1: unitX * (r - distance) + cx, + y1: unitY * (r - distance) + cy, + x2: unitX * (r - tickLen - distance) + cx, + y2: unitY * (r - tickLen - distance) + cy + }, + silent: true, + style: tickLineStyle + }); + + if (tickLineStyle.stroke === 'auto') { + tickLine.setStyle({ + stroke: getColor((i + j / subSplitNumber) / splitNumber) + }); + } + + group.add(tickLine); + angle += subStep; + } + + angle -= subStep; + } else { + angle += step; + } + } + }; + + GaugeView.prototype._renderPointer = function (seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise, axisLineWidth) { + var group = this.group; + var oldData = this._data; + var oldProgressData = this._progressEls; + var progressList = []; + var showPointer = seriesModel.get(['pointer', 'show']); + var progressModel = seriesModel.getModel('progress'); + var showProgress = progressModel.get('show'); + var data = seriesModel.getData(); + var valueDim = data.mapDimension('value'); + var minVal = +seriesModel.get('min'); + var maxVal = +seriesModel.get('max'); + var valueExtent = [minVal, maxVal]; + var angleExtent = [startAngle, endAngle]; + + function createPointer(idx, angle) { + var itemModel = data.getItemModel(idx); + var pointerModel = itemModel.getModel('pointer'); + var pointerWidth = parsePercent$1(pointerModel.get('width'), posInfo.r); + var pointerLength = parsePercent$1(pointerModel.get('length'), posInfo.r); + var pointerStr = seriesModel.get(['pointer', 'icon']); + var pointerOffset = pointerModel.get('offsetCenter'); + var pointerOffsetX = parsePercent$1(pointerOffset[0], posInfo.r); + var pointerOffsetY = parsePercent$1(pointerOffset[1], posInfo.r); + var pointerKeepAspect = pointerModel.get('keepAspect'); + var pointer; + + if (pointerStr) { + pointer = createSymbol(pointerStr, pointerOffsetX - pointerWidth / 2, pointerOffsetY - pointerLength, pointerWidth, pointerLength, null, pointerKeepAspect); + } else { + pointer = new PointerPath({ + shape: { + angle: -Math.PI / 2, + width: pointerWidth, + r: pointerLength, + x: pointerOffsetX, + y: pointerOffsetY + } + }); + } + + pointer.rotation = -(angle + Math.PI / 2); + pointer.x = posInfo.cx; + pointer.y = posInfo.cy; + return pointer; + } + + function createProgress(idx, endAngle) { + var roundCap = progressModel.get('roundCap'); + var ProgressPath = roundCap ? SausagePath : Sector; + var isOverlap = progressModel.get('overlap'); + var progressWidth = isOverlap ? progressModel.get('width') : axisLineWidth / data.count(); + var r0 = isOverlap ? posInfo.r - progressWidth : posInfo.r - (idx + 1) * progressWidth; + var r = isOverlap ? posInfo.r : posInfo.r - idx * progressWidth; + var progress = new ProgressPath({ + shape: { + startAngle: startAngle, + endAngle: endAngle, + cx: posInfo.cx, + cy: posInfo.cy, + clockwise: clockwise, + r0: r0, + r: r + } + }); + isOverlap && (progress.z2 = maxVal - data.get(valueDim, idx) % maxVal); + return progress; + } + + if (showProgress || showPointer) { + data.diff(oldData).add(function (idx) { + if (showPointer) { + var pointer = createPointer(idx, startAngle); + initProps(pointer, { + rotation: -(linearMap(data.get(valueDim, idx), valueExtent, angleExtent, true) + Math.PI / 2) + }, seriesModel); + group.add(pointer); + data.setItemGraphicEl(idx, pointer); + } + + if (showProgress) { + var progress = createProgress(idx, startAngle); + var isClip = progressModel.get('clip'); + initProps(progress, { + shape: { + endAngle: linearMap(data.get(valueDim, idx), valueExtent, angleExtent, isClip) + } + }, seriesModel); + group.add(progress); + progressList[idx] = progress; + } + }).update(function (newIdx, oldIdx) { + if (showPointer) { + var previousPointer = oldData.getItemGraphicEl(oldIdx); + var previousRotate = previousPointer ? previousPointer.rotation : startAngle; + var pointer = createPointer(newIdx, previousRotate); + pointer.rotation = previousRotate; + updateProps(pointer, { + rotation: -(linearMap(data.get(valueDim, newIdx), valueExtent, angleExtent, true) + Math.PI / 2) + }, seriesModel); + group.add(pointer); + data.setItemGraphicEl(newIdx, pointer); + } + + if (showProgress) { + var previousProgress = oldProgressData[oldIdx]; + var previousEndAngle = previousProgress ? previousProgress.shape.endAngle : startAngle; + var progress = createProgress(newIdx, previousEndAngle); + var isClip = progressModel.get('clip'); + updateProps(progress, { + shape: { + endAngle: linearMap(data.get(valueDim, newIdx), valueExtent, angleExtent, isClip) + } + }, seriesModel); + group.add(progress); + progressList[newIdx] = progress; + } + }).execute(); + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + var emphasisModel = itemModel.getModel('emphasis'); + + if (showPointer) { + var pointer = data.getItemGraphicEl(idx); + pointer.useStyle(data.getItemVisual(idx, 'style')); + pointer.setStyle(itemModel.getModel(['pointer', 'itemStyle']).getItemStyle()); + + if (pointer.style.fill === 'auto') { + pointer.setStyle('fill', getColor(linearMap(data.get(valueDim, idx), valueExtent, [0, 1], true))); + } + + pointer.z2EmphasisLift = 0; + setStatesStylesFromModel(pointer, itemModel); + enableHoverEmphasis(pointer, emphasisModel.get('focus'), emphasisModel.get('blurScope')); + } + + if (showProgress) { + var progress = progressList[idx]; + progress.useStyle(data.getItemVisual(idx, 'style')); + progress.setStyle(itemModel.getModel(['progress', 'itemStyle']).getItemStyle()); + progress.z2EmphasisLift = 0; + setStatesStylesFromModel(progress, itemModel); + enableHoverEmphasis(progress, emphasisModel.get('focus'), emphasisModel.get('blurScope')); + } + }); + this._progressEls = progressList; + } + }; + + GaugeView.prototype._renderAnchor = function (seriesModel, posInfo) { + var anchorModel = seriesModel.getModel('anchor'); + var showAnchor = anchorModel.get('show'); + + if (showAnchor) { + var anchorSize = anchorModel.get('size'); + var anchorType = anchorModel.get('icon'); + var offsetCenter = anchorModel.get('offsetCenter'); + var anchorKeepAspect = anchorModel.get('keepAspect'); + var anchor = createSymbol(anchorType, posInfo.cx - anchorSize / 2 + parsePercent$1(offsetCenter[0], posInfo.r), posInfo.cy - anchorSize / 2 + parsePercent$1(offsetCenter[1], posInfo.r), anchorSize, anchorSize, null, anchorKeepAspect); + anchor.z2 = anchorModel.get('showAbove') ? 1 : 0; + anchor.setStyle(anchorModel.getModel('itemStyle').getItemStyle()); + this.group.add(anchor); + } + }; + + GaugeView.prototype._renderTitleAndDetail = function (seriesModel, ecModel, api, getColor, posInfo) { + var _this = this; + + var data = seriesModel.getData(); + var valueDim = data.mapDimension('value'); + var minVal = +seriesModel.get('min'); + var maxVal = +seriesModel.get('max'); + var contentGroup = new Group(); + var newTitleEls = []; + var newDetailEls = []; + var hasAnimation = seriesModel.isAnimationEnabled(); + data.diff(this._data).add(function (idx) { + newTitleEls[idx] = new ZRText({ + silent: true + }); + newDetailEls[idx] = new ZRText({ + silent: true + }); + }).update(function (idx, oldIdx) { + newTitleEls[idx] = _this._titleEls[oldIdx]; + newDetailEls[idx] = _this._detailEls[oldIdx]; + }).execute(); + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + var value = data.get(valueDim, idx); + var itemGroup = new Group(); + var autoColor = getColor(linearMap(value, [minVal, maxVal], [0, 1], true)); + var itemTitleModel = itemModel.getModel('title'); + + if (itemTitleModel.get('show')) { + var titleOffsetCenter = itemTitleModel.get('offsetCenter'); + var titleX = posInfo.cx + parsePercent$1(titleOffsetCenter[0], posInfo.r); + var titleY = posInfo.cy + parsePercent$1(titleOffsetCenter[1], posInfo.r); + var labelEl = newTitleEls[idx]; + labelEl.attr({ + style: createTextStyle(itemTitleModel, { + x: titleX, + y: titleY, + text: data.getName(idx), + align: 'center', + verticalAlign: 'middle' + }, { + inheritColor: autoColor + }) + }); + itemGroup.add(labelEl); + } + + var itemDetailModel = itemModel.getModel('detail'); + + if (itemDetailModel.get('show')) { + var detailOffsetCenter = itemDetailModel.get('offsetCenter'); + var detailX = posInfo.cx + parsePercent$1(detailOffsetCenter[0], posInfo.r); + var detailY = posInfo.cy + parsePercent$1(detailOffsetCenter[1], posInfo.r); + var width = parsePercent$1(itemDetailModel.get('width'), posInfo.r); + var height = parsePercent$1(itemDetailModel.get('height'), posInfo.r); + var detailColor = seriesModel.get(['progress', 'show']) ? data.getItemVisual(idx, 'style').fill : autoColor; + var labelEl = newDetailEls[idx]; + var formatter_1 = itemDetailModel.get('formatter'); + labelEl.attr({ + style: createTextStyle(itemDetailModel, { + x: detailX, + y: detailY, + text: formatLabel(value, formatter_1), + width: isNaN(width) ? null : width, + height: isNaN(height) ? null : height, + align: 'center', + verticalAlign: 'middle' + }, { + inheritColor: detailColor + }) + }); + setLabelValueAnimation(labelEl, { + normal: itemDetailModel + }, value, function (value) { + return formatLabel(value, formatter_1); + }); + hasAnimation && animateLabelValue(labelEl, idx, data, seriesModel, { + getFormattedLabel: function (labelDataIndex, status, dataType, labelDimIndex, fmt, extendParams) { + return formatLabel(extendParams ? extendParams.interpolatedValue : value, formatter_1); + } + }); + itemGroup.add(labelEl); + } + + contentGroup.add(itemGroup); + }); + this.group.add(contentGroup); + this._titleEls = newTitleEls; + this._detailEls = newDetailEls; + }; + + GaugeView.type = 'gauge'; + return GaugeView; + }(ChartView); + + var GaugeSeriesModel = function (_super) { + __extends(GaugeSeriesModel, _super); + + function GaugeSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GaugeSeriesModel.type; + _this.visualStyleAccessPath = 'itemStyle'; + _this.useColorPaletteOnData = true; + return _this; + } + + GaugeSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createListSimply(this, ['value']); + }; + + GaugeSeriesModel.type = 'series.gauge'; + GaugeSeriesModel.defaultOption = { + zlevel: 0, + z: 2, + center: ['50%', '50%'], + legendHoverLink: true, + radius: '75%', + startAngle: 225, + endAngle: -45, + clockwise: true, + min: 0, + max: 100, + splitNumber: 10, + axisLine: { + show: true, + roundCap: false, + lineStyle: { + color: [[1, '#E6EBF8']], + width: 10 + } + }, + progress: { + show: false, + overlap: true, + width: 10, + roundCap: false, + clip: true + }, + splitLine: { + show: true, + length: 10, + distance: 10, + lineStyle: { + color: '#63677A', + width: 3, + type: 'solid' + } + }, + axisTick: { + show: true, + splitNumber: 5, + length: 6, + distance: 10, + lineStyle: { + color: '#63677A', + width: 1, + type: 'solid' + } + }, + axisLabel: { + show: true, + distance: 15, + color: '#464646', + fontSize: 12 + }, + pointer: { + icon: null, + offsetCenter: [0, 0], + show: true, + length: '60%', + width: 6, + keepAspect: false + }, + anchor: { + show: false, + showAbove: false, + size: 6, + icon: 'circle', + offsetCenter: [0, 0], + keepAspect: false, + itemStyle: { + color: '#fff', + borderWidth: 0, + borderColor: '#5470c6' + } + }, + title: { + show: true, + offsetCenter: [0, '20%'], + color: '#464646', + fontSize: 16, + valueAnimation: false + }, + detail: { + show: true, + backgroundColor: 'rgba(0,0,0,0)', + borderWidth: 0, + borderColor: '#ccc', + width: 100, + height: null, + padding: [5, 10], + offsetCenter: [0, '40%'], + color: '#464646', + fontSize: 30, + fontWeight: 'bold', + lineHeight: 30, + valueAnimation: false + } + }; + return GaugeSeriesModel; + }(SeriesModel); + + function install$d(registers) { + registers.registerChartView(GaugeView); + registers.registerSeriesModel(GaugeSeriesModel); + } + + var opacityAccessPath = ['itemStyle', 'opacity']; + + var FunnelPiece = function (_super) { + __extends(FunnelPiece, _super); + + function FunnelPiece(data, idx) { + var _this = _super.call(this) || this; + + var polygon = _this; + var labelLine = new Polyline(); + var text = new ZRText(); + polygon.setTextContent(text); + + _this.setTextGuideLine(labelLine); + + _this.updateData(data, idx, true); + + return _this; + } + + FunnelPiece.prototype.updateData = function (data, idx, firstCreate) { + var polygon = this; + var seriesModel = data.hostModel; + var itemModel = data.getItemModel(idx); + var layout = data.getItemLayout(idx); + var emphasisModel = itemModel.getModel('emphasis'); + var opacity = itemModel.get(opacityAccessPath); + opacity = opacity == null ? 1 : opacity; + polygon.useStyle(data.getItemVisual(idx, 'style')); + polygon.style.lineJoin = 'round'; + + if (firstCreate) { + polygon.setShape({ + points: layout.points + }); + polygon.style.opacity = 0; + initProps(polygon, { + style: { + opacity: opacity + } + }, seriesModel, idx); + } else { + updateProps(polygon, { + style: { + opacity: opacity + }, + shape: { + points: layout.points + } + }, seriesModel, idx); + } + + setStatesStylesFromModel(polygon, itemModel); + + this._updateLabel(data, idx); + + enableHoverEmphasis(this, emphasisModel.get('focus'), emphasisModel.get('blurScope')); + }; + + FunnelPiece.prototype._updateLabel = function (data, idx) { + var polygon = this; + var labelLine = this.getTextGuideLine(); + var labelText = polygon.getTextContent(); + var seriesModel = data.hostModel; + var itemModel = data.getItemModel(idx); + var layout = data.getItemLayout(idx); + var labelLayout = layout.label; + var style = data.getItemVisual(idx, 'style'); + var visualColor = style.fill; + setLabelStyle(labelText, getLabelStatesModels(itemModel), { + labelFetcher: data.hostModel, + labelDataIndex: idx, + defaultOpacity: style.opacity, + defaultText: data.getName(idx) + }, { + normal: { + align: labelLayout.textAlign, + verticalAlign: labelLayout.verticalAlign + } + }); + polygon.setTextConfig({ + local: true, + inside: !!labelLayout.inside, + insideStroke: visualColor, + outsideFill: visualColor + }); + var linePoints = labelLayout.linePoints; + labelLine.setShape({ + points: linePoints + }); + polygon.textGuideLineConfig = { + anchor: linePoints ? new Point(linePoints[0][0], linePoints[0][1]) : null + }; + updateProps(labelText, { + style: { + x: labelLayout.x, + y: labelLayout.y + } + }, seriesModel, idx); + labelText.attr({ + rotation: labelLayout.rotation, + originX: labelLayout.x, + originY: labelLayout.y, + z2: 10 + }); + setLabelLineStyle(polygon, getLabelLineStatesModels(itemModel), { + stroke: visualColor + }); + }; + + return FunnelPiece; + }(Polygon); + + var FunnelView = function (_super) { + __extends(FunnelView, _super); + + function FunnelView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = FunnelView.type; + _this.ignoreLabelLineUpdate = true; + return _this; + } + + FunnelView.prototype.render = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var oldData = this._data; + var group = this.group; + data.diff(oldData).add(function (idx) { + var funnelPiece = new FunnelPiece(data, idx); + data.setItemGraphicEl(idx, funnelPiece); + group.add(funnelPiece); + }).update(function (newIdx, oldIdx) { + var piece = oldData.getItemGraphicEl(oldIdx); + piece.updateData(data, newIdx); + group.add(piece); + data.setItemGraphicEl(newIdx, piece); + }).remove(function (idx) { + var piece = oldData.getItemGraphicEl(idx); + removeElementWithFadeOut(piece, seriesModel, idx); + }).execute(); + this._data = data; + }; + + FunnelView.prototype.remove = function () { + this.group.removeAll(); + this._data = null; + }; + + FunnelView.prototype.dispose = function () {}; + + FunnelView.type = 'funnel'; + return FunnelView; + }(ChartView); + + var FunnelSeriesModel = function (_super) { + __extends(FunnelSeriesModel, _super); + + function FunnelSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = FunnelSeriesModel.type; + _this.useColorPaletteOnData = true; + return _this; + } + + FunnelSeriesModel.prototype.init = function (option) { + _super.prototype.init.apply(this, arguments); + + this.legendVisualProvider = new LegendVisualProvider(bind(this.getData, this), bind(this.getRawData, this)); + + this._defaultLabelLine(option); + }; + + FunnelSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createListSimply(this, { + coordDimensions: ['value'], + encodeDefaulter: curry(makeSeriesEncodeForNameBased, this) + }); + }; + + FunnelSeriesModel.prototype._defaultLabelLine = function (option) { + defaultEmphasis(option, 'labelLine', ['show']); + var labelLineNormalOpt = option.labelLine; + var labelLineEmphasisOpt = option.emphasis.labelLine; + labelLineNormalOpt.show = labelLineNormalOpt.show && option.label.show; + labelLineEmphasisOpt.show = labelLineEmphasisOpt.show && option.emphasis.label.show; + }; + + FunnelSeriesModel.prototype.getDataParams = function (dataIndex) { + var data = this.getData(); + + var params = _super.prototype.getDataParams.call(this, dataIndex); + + var valueDim = data.mapDimension('value'); + var sum = data.getSum(valueDim); + params.percent = !sum ? 0 : +(data.get(valueDim, dataIndex) / sum * 100).toFixed(2); + params.$vars.push('percent'); + return params; + }; + + FunnelSeriesModel.type = 'series.funnel'; + FunnelSeriesModel.defaultOption = { + zlevel: 0, + z: 2, + legendHoverLink: true, + left: 80, + top: 60, + right: 80, + bottom: 60, + minSize: '0%', + maxSize: '100%', + sort: 'descending', + orient: 'vertical', + gap: 0, + funnelAlign: 'center', + label: { + show: true, + position: 'outer' + }, + labelLine: { + show: true, + length: 20, + lineStyle: { + width: 1 + } + }, + itemStyle: { + borderColor: '#fff', + borderWidth: 1 + }, + emphasis: { + label: { + show: true + } + }, + select: { + itemStyle: { + borderColor: '#212121' + } + } + }; + return FunnelSeriesModel; + }(SeriesModel); + + function getViewRect$3(seriesModel, api) { + return getLayoutRect(seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + } + + function getSortedIndices(data, sort) { + var valueDim = data.mapDimension('value'); + var valueArr = data.mapArray(valueDim, function (val) { + return val; + }); + var indices = []; + var isAscending = sort === 'ascending'; + + for (var i = 0, len = data.count(); i < len; i++) { + indices[i] = i; + } + + if (typeof sort === 'function') { + indices.sort(sort); + } else if (sort !== 'none') { + indices.sort(function (a, b) { + return isAscending ? valueArr[a] - valueArr[b] : valueArr[b] - valueArr[a]; + }); + } + + return indices; + } + + function labelLayout(data) { + var seriesModel = data.hostModel; + var orient = seriesModel.get('orient'); + data.each(function (idx) { + var itemModel = data.getItemModel(idx); + var labelModel = itemModel.getModel('label'); + var labelPosition = labelModel.get('position'); + var labelLineModel = itemModel.getModel('labelLine'); + var layout = data.getItemLayout(idx); + var points = layout.points; + var isLabelInside = labelPosition === 'inner' || labelPosition === 'inside' || labelPosition === 'center' || labelPosition === 'insideLeft' || labelPosition === 'insideRight'; + var textAlign; + var textX; + var textY; + var linePoints; + + if (isLabelInside) { + if (labelPosition === 'insideLeft') { + textX = (points[0][0] + points[3][0]) / 2 + 5; + textY = (points[0][1] + points[3][1]) / 2; + textAlign = 'left'; + } else if (labelPosition === 'insideRight') { + textX = (points[1][0] + points[2][0]) / 2 - 5; + textY = (points[1][1] + points[2][1]) / 2; + textAlign = 'right'; + } else { + textX = (points[0][0] + points[1][0] + points[2][0] + points[3][0]) / 4; + textY = (points[0][1] + points[1][1] + points[2][1] + points[3][1]) / 4; + textAlign = 'center'; + } + + linePoints = [[textX, textY], [textX, textY]]; + } else { + var x1 = void 0; + var y1 = void 0; + var x2 = void 0; + var y2 = void 0; + var labelLineLen = labelLineModel.get('length'); + + if ("development" !== 'production') { + if (orient === 'vertical' && ['top', 'bottom'].indexOf(labelPosition) > -1) { + labelPosition = 'left'; + console.warn('Position error: Funnel chart on vertical orient dose not support top and bottom.'); + } + + if (orient === 'horizontal' && ['left', 'right'].indexOf(labelPosition) > -1) { + labelPosition = 'bottom'; + console.warn('Position error: Funnel chart on horizontal orient dose not support left and right.'); + } + } + + if (labelPosition === 'left') { + x1 = (points[3][0] + points[0][0]) / 2; + y1 = (points[3][1] + points[0][1]) / 2; + x2 = x1 - labelLineLen; + textX = x2 - 5; + textAlign = 'right'; + } else if (labelPosition === 'right') { + x1 = (points[1][0] + points[2][0]) / 2; + y1 = (points[1][1] + points[2][1]) / 2; + x2 = x1 + labelLineLen; + textX = x2 + 5; + textAlign = 'left'; + } else if (labelPosition === 'top') { + x1 = (points[3][0] + points[0][0]) / 2; + y1 = (points[3][1] + points[0][1]) / 2; + y2 = y1 - labelLineLen; + textY = y2 - 5; + textAlign = 'center'; + } else if (labelPosition === 'bottom') { + x1 = (points[1][0] + points[2][0]) / 2; + y1 = (points[1][1] + points[2][1]) / 2; + y2 = y1 + labelLineLen; + textY = y2 + 5; + textAlign = 'center'; + } else if (labelPosition === 'rightTop') { + x1 = orient === 'horizontal' ? points[3][0] : points[1][0]; + y1 = orient === 'horizontal' ? points[3][1] : points[1][1]; + + if (orient === 'horizontal') { + y2 = y1 - labelLineLen; + textY = y2 - 5; + textAlign = 'center'; + } else { + x2 = x1 + labelLineLen; + textX = x2 + 5; + textAlign = 'top'; + } + } else if (labelPosition === 'rightBottom') { + x1 = points[2][0]; + y1 = points[2][1]; + + if (orient === 'horizontal') { + y2 = y1 + labelLineLen; + textY = y2 + 5; + textAlign = 'center'; + } else { + x2 = x1 + labelLineLen; + textX = x2 + 5; + textAlign = 'bottom'; + } + } else if (labelPosition === 'leftTop') { + x1 = points[0][0]; + y1 = orient === 'horizontal' ? points[0][1] : points[1][1]; + + if (orient === 'horizontal') { + y2 = y1 - labelLineLen; + textY = y2 - 5; + textAlign = 'center'; + } else { + x2 = x1 - labelLineLen; + textX = x2 - 5; + textAlign = 'right'; + } + } else if (labelPosition === 'leftBottom') { + x1 = orient === 'horizontal' ? points[1][0] : points[3][0]; + y1 = orient === 'horizontal' ? points[1][1] : points[2][1]; + + if (orient === 'horizontal') { + y2 = y1 + labelLineLen; + textY = y2 + 5; + textAlign = 'center'; + } else { + x2 = x1 - labelLineLen; + textX = x2 - 5; + textAlign = 'right'; + } + } else { + x1 = (points[1][0] + points[2][0]) / 2; + y1 = (points[1][1] + points[2][1]) / 2; + + if (orient === 'horizontal') { + y2 = y1 + labelLineLen; + textY = y2 + 5; + textAlign = 'center'; + } else { + x2 = x1 + labelLineLen; + textX = x2 + 5; + textAlign = 'left'; + } + } + + if (orient === 'horizontal') { + x2 = x1; + textX = x2; + } else { + y2 = y1; + textY = y2; + } + + linePoints = [[x1, y1], [x2, y2]]; + } + + layout.label = { + linePoints: linePoints, + x: textX, + y: textY, + verticalAlign: 'middle', + textAlign: textAlign, + inside: isLabelInside + }; + }); + } + + function funnelLayout(ecModel, api) { + ecModel.eachSeriesByType('funnel', function (seriesModel) { + var data = seriesModel.getData(); + var valueDim = data.mapDimension('value'); + var sort = seriesModel.get('sort'); + var viewRect = getViewRect$3(seriesModel, api); + var orient = seriesModel.get('orient'); + var viewWidth = viewRect.width; + var viewHeight = viewRect.height; + var indices = getSortedIndices(data, sort); + var x = viewRect.x; + var y = viewRect.y; + var sizeExtent = orient === 'horizontal' ? [parsePercent$1(seriesModel.get('minSize'), viewHeight), parsePercent$1(seriesModel.get('maxSize'), viewHeight)] : [parsePercent$1(seriesModel.get('minSize'), viewWidth), parsePercent$1(seriesModel.get('maxSize'), viewWidth)]; + var dataExtent = data.getDataExtent(valueDim); + var min = seriesModel.get('min'); + var max = seriesModel.get('max'); + + if (min == null) { + min = Math.min(dataExtent[0], 0); + } + + if (max == null) { + max = dataExtent[1]; + } + + var funnelAlign = seriesModel.get('funnelAlign'); + var gap = seriesModel.get('gap'); + var viewSize = orient === 'horizontal' ? viewWidth : viewHeight; + var itemSize = (viewSize - gap * (data.count() - 1)) / data.count(); + + var getLinePoints = function (idx, offset) { + if (orient === 'horizontal') { + var val_1 = data.get(valueDim, idx) || 0; + var itemHeight = linearMap(val_1, [min, max], sizeExtent, true); + var y0 = void 0; + + switch (funnelAlign) { + case 'top': + y0 = y; + break; + + case 'center': + y0 = y + (viewHeight - itemHeight) / 2; + break; + + case 'bottom': + y0 = y + (viewHeight - itemHeight); + break; + } + + return [[offset, y0], [offset, y0 + itemHeight]]; + } + + var val = data.get(valueDim, idx) || 0; + var itemWidth = linearMap(val, [min, max], sizeExtent, true); + var x0; + + switch (funnelAlign) { + case 'left': + x0 = x; + break; + + case 'center': + x0 = x + (viewWidth - itemWidth) / 2; + break; + + case 'right': + x0 = x + viewWidth - itemWidth; + break; + } + + return [[x0, offset], [x0 + itemWidth, offset]]; + }; + + if (sort === 'ascending') { + itemSize = -itemSize; + gap = -gap; + + if (orient === 'horizontal') { + x += viewWidth; + } else { + y += viewHeight; + } + + indices = indices.reverse(); + } + + for (var i = 0; i < indices.length; i++) { + var idx = indices[i]; + var nextIdx = indices[i + 1]; + var itemModel = data.getItemModel(idx); + + if (orient === 'horizontal') { + var width = itemModel.get(['itemStyle', 'width']); + + if (width == null) { + width = itemSize; + } else { + width = parsePercent$1(width, viewWidth); + + if (sort === 'ascending') { + width = -width; + } + } + + var start = getLinePoints(idx, x); + var end = getLinePoints(nextIdx, x + width); + x += width + gap; + data.setItemLayout(idx, { + points: start.concat(end.slice().reverse()) + }); + } else { + var height = itemModel.get(['itemStyle', 'height']); + + if (height == null) { + height = itemSize; + } else { + height = parsePercent$1(height, viewHeight); + + if (sort === 'ascending') { + height = -height; + } + } + + var start = getLinePoints(idx, y); + var end = getLinePoints(nextIdx, y + height); + y += height + gap; + data.setItemLayout(idx, { + points: start.concat(end.slice().reverse()) + }); + } + } + + labelLayout(data); + }); + } + + function install$e(registers) { + registers.registerChartView(FunnelView); + registers.registerSeriesModel(FunnelSeriesModel); + registers.registerLayout(funnelLayout); + registers.registerProcessor(dataFilter('funnel')); + } + + var DEFAULT_SMOOTH = 0.3; + + var ParallelView = function (_super) { + __extends(ParallelView, _super); + + function ParallelView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ParallelView.type; + _this._dataGroup = new Group(); + _this._initialized = false; + return _this; + } + + ParallelView.prototype.init = function () { + this.group.add(this._dataGroup); + }; + + ParallelView.prototype.render = function (seriesModel, ecModel, api, payload) { + var dataGroup = this._dataGroup; + var data = seriesModel.getData(); + var oldData = this._data; + var coordSys = seriesModel.coordinateSystem; + var dimensions = coordSys.dimensions; + var seriesScope = makeSeriesScope$2(seriesModel); + data.diff(oldData).add(add).update(update).remove(remove).execute(); + + function add(newDataIndex) { + var line = addEl(data, dataGroup, newDataIndex, dimensions, coordSys); + updateElCommon(line, data, newDataIndex, seriesScope); + } + + function update(newDataIndex, oldDataIndex) { + var line = oldData.getItemGraphicEl(oldDataIndex); + var points = createLinePoints(data, newDataIndex, dimensions, coordSys); + data.setItemGraphicEl(newDataIndex, line); + updateProps(line, { + shape: { + points: points + } + }, seriesModel, newDataIndex); + updateElCommon(line, data, newDataIndex, seriesScope); + } + + function remove(oldDataIndex) { + var line = oldData.getItemGraphicEl(oldDataIndex); + dataGroup.remove(line); + } + + if (!this._initialized) { + this._initialized = true; + var clipPath = createGridClipShape(coordSys, seriesModel, function () { + setTimeout(function () { + dataGroup.removeClipPath(); + }); + }); + dataGroup.setClipPath(clipPath); + } + + this._data = data; + }; + + ParallelView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) { + this._initialized = true; + this._data = null; + + this._dataGroup.removeAll(); + }; + + ParallelView.prototype.incrementalRender = function (taskParams, seriesModel, ecModel) { + var data = seriesModel.getData(); + var coordSys = seriesModel.coordinateSystem; + var dimensions = coordSys.dimensions; + var seriesScope = makeSeriesScope$2(seriesModel); + + for (var dataIndex = taskParams.start; dataIndex < taskParams.end; dataIndex++) { + var line = addEl(data, this._dataGroup, dataIndex, dimensions, coordSys); + line.incremental = true; + updateElCommon(line, data, dataIndex, seriesScope); + } + }; + + ParallelView.prototype.remove = function () { + this._dataGroup && this._dataGroup.removeAll(); + this._data = null; + }; + + ParallelView.type = 'parallel'; + return ParallelView; + }(ChartView); + + function createGridClipShape(coordSys, seriesModel, cb) { + var parallelModel = coordSys.model; + var rect = coordSys.getRect(); + var rectEl = new Rect({ + shape: { + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + } + }); + var dim = parallelModel.get('layout') === 'horizontal' ? 'width' : 'height'; + rectEl.setShape(dim, 0); + initProps(rectEl, { + shape: { + width: rect.width, + height: rect.height + } + }, seriesModel, cb); + return rectEl; + } + + function createLinePoints(data, dataIndex, dimensions, coordSys) { + var points = []; + + for (var i = 0; i < dimensions.length; i++) { + var dimName = dimensions[i]; + var value = data.get(data.mapDimension(dimName), dataIndex); + + if (!isEmptyValue(value, coordSys.getAxis(dimName).type)) { + points.push(coordSys.dataToPoint(value, dimName)); + } + } + + return points; + } + + function addEl(data, dataGroup, dataIndex, dimensions, coordSys) { + var points = createLinePoints(data, dataIndex, dimensions, coordSys); + var line = new Polyline({ + shape: { + points: points + }, + z2: 10 + }); + dataGroup.add(line); + data.setItemGraphicEl(dataIndex, line); + return line; + } + + function makeSeriesScope$2(seriesModel) { + var smooth = seriesModel.get('smooth', true); + smooth === true && (smooth = DEFAULT_SMOOTH); + smooth = numericToNumber(smooth); + eqNaN(smooth) && (smooth = 0); + return { + smooth: smooth + }; + } + + function updateElCommon(el, data, dataIndex, seriesScope) { + el.useStyle(data.getItemVisual(dataIndex, 'style')); + el.style.fill = null; + el.setShape('smooth', seriesScope.smooth); + var itemModel = data.getItemModel(dataIndex); + var emphasisModel = itemModel.getModel('emphasis'); + setStatesStylesFromModel(el, itemModel, 'lineStyle'); + enableHoverEmphasis(el, emphasisModel.get('focus'), emphasisModel.get('blurScope')); + } + + function isEmptyValue(val, axisType) { + return axisType === 'category' ? val == null : val == null || isNaN(val); + } + + var ParallelSeriesModel = function (_super) { + __extends(ParallelSeriesModel, _super); + + function ParallelSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ParallelSeriesModel.type; + _this.visualStyleAccessPath = 'lineStyle'; + _this.visualDrawType = 'stroke'; + return _this; + } + + ParallelSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createListFromArray(this.getSource(), this, { + useEncodeDefaulter: bind(makeDefaultEncode, null, this) + }); + }; + + ParallelSeriesModel.prototype.getRawIndicesByActiveState = function (activeState) { + var coordSys = this.coordinateSystem; + var data = this.getData(); + var indices = []; + coordSys.eachActiveState(data, function (theActiveState, dataIndex) { + if (activeState === theActiveState) { + indices.push(data.getRawIndex(dataIndex)); + } + }); + return indices; + }; + + ParallelSeriesModel.type = 'series.parallel'; + ParallelSeriesModel.dependencies = ['parallel']; + ParallelSeriesModel.defaultOption = { + zlevel: 0, + z: 2, + coordinateSystem: 'parallel', + parallelIndex: 0, + label: { + show: false + }, + inactiveOpacity: 0.05, + activeOpacity: 1, + lineStyle: { + width: 1, + opacity: 0.45, + type: 'solid' + }, + emphasis: { + label: { + show: false + } + }, + progressive: 500, + smooth: false, + animationEasing: 'linear' + }; + return ParallelSeriesModel; + }(SeriesModel); + + function makeDefaultEncode(seriesModel) { + var parallelModel = seriesModel.ecModel.getComponent('parallel', seriesModel.get('parallelIndex')); + + if (!parallelModel) { + return; + } + + var encodeDefine = {}; + each(parallelModel.dimensions, function (axisDim) { + var dataDimIndex = convertDimNameToNumber(axisDim); + encodeDefine[axisDim] = dataDimIndex; + }); + return encodeDefine; + } + + function convertDimNameToNumber(dimName) { + return +dimName.replace('dim', ''); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var opacityAccessPath$1 = ['lineStyle', 'opacity']; + var parallelVisual = { + seriesType: 'parallel', + reset: function (seriesModel, ecModel) { + var coordSys = seriesModel.coordinateSystem; + var opacityMap = { + normal: seriesModel.get(['lineStyle', 'opacity']), + active: seriesModel.get('activeOpacity'), + inactive: seriesModel.get('inactiveOpacity') + }; + return { + progress: function (params, data) { + coordSys.eachActiveState(data, function (activeState, dataIndex) { + var opacity = opacityMap[activeState]; + + if (activeState === 'normal' && data.hasItemOption) { + var itemOpacity = data.getItemModel(dataIndex).get(opacityAccessPath$1, true); + itemOpacity != null && (opacity = itemOpacity); + } + + var existsStyle = data.ensureUniqueItemVisual(dataIndex, 'style'); + existsStyle.opacity = opacity; + }, params.start, params.end); + } + }; + } + }; + + function parallelPreprocessor(option) { + createParallelIfNeeded(option); + mergeAxisOptionFromParallel(option); + } + + function createParallelIfNeeded(option) { + if (option.parallel) { + return; + } + + var hasParallelSeries = false; + each(option.series, function (seriesOpt) { + if (seriesOpt && seriesOpt.type === 'parallel') { + hasParallelSeries = true; + } + }); + + if (hasParallelSeries) { + option.parallel = [{}]; + } + } + + function mergeAxisOptionFromParallel(option) { + var axes = normalizeToArray(option.parallelAxis); + each(axes, function (axisOption) { + if (!isObject(axisOption)) { + return; + } + + var parallelIndex = axisOption.parallelIndex || 0; + var parallelOption = normalizeToArray(option.parallel)[parallelIndex]; + + if (parallelOption && parallelOption.parallelAxisDefault) { + merge(axisOption, parallelOption.parallelAxisDefault, false); + } + }); + } + + var CLICK_THRESHOLD = 5; + + var ParallelView$1 = function (_super) { + __extends(ParallelView, _super); + + function ParallelView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ParallelView.type; + return _this; + } + + ParallelView.prototype.render = function (parallelModel, ecModel, api) { + this._model = parallelModel; + this._api = api; + + if (!this._handlers) { + this._handlers = {}; + each(handlers, function (handler, eventName) { + api.getZr().on(eventName, this._handlers[eventName] = bind(handler, this)); + }, this); + } + + createOrUpdate(this, '_throttledDispatchExpand', parallelModel.get('axisExpandRate'), 'fixRate'); + }; + + ParallelView.prototype.dispose = function (ecModel, api) { + each(this._handlers, function (handler, eventName) { + api.getZr().off(eventName, handler); + }); + this._handlers = null; + }; + + ParallelView.prototype._throttledDispatchExpand = function (opt) { + this._dispatchExpand(opt); + }; + + ParallelView.prototype._dispatchExpand = function (opt) { + opt && this._api.dispatchAction(extend({ + type: 'parallelAxisExpand' + }, opt)); + }; + + ParallelView.type = 'parallel'; + return ParallelView; + }(ComponentView); + + var handlers = { + mousedown: function (e) { + if (checkTrigger(this, 'click')) { + this._mouseDownPoint = [e.offsetX, e.offsetY]; + } + }, + mouseup: function (e) { + var mouseDownPoint = this._mouseDownPoint; + + if (checkTrigger(this, 'click') && mouseDownPoint) { + var point = [e.offsetX, e.offsetY]; + var dist = Math.pow(mouseDownPoint[0] - point[0], 2) + Math.pow(mouseDownPoint[1] - point[1], 2); + + if (dist > CLICK_THRESHOLD) { + return; + } + + var result = this._model.coordinateSystem.getSlidedAxisExpandWindow([e.offsetX, e.offsetY]); + + result.behavior !== 'none' && this._dispatchExpand({ + axisExpandWindow: result.axisExpandWindow + }); + } + + this._mouseDownPoint = null; + }, + mousemove: function (e) { + if (this._mouseDownPoint || !checkTrigger(this, 'mousemove')) { + return; + } + + var model = this._model; + var result = model.coordinateSystem.getSlidedAxisExpandWindow([e.offsetX, e.offsetY]); + var behavior = result.behavior; + behavior === 'jump' && this._throttledDispatchExpand.debounceNextCall(model.get('axisExpandDebounce')); + + this._throttledDispatchExpand(behavior === 'none' ? null : { + axisExpandWindow: result.axisExpandWindow, + animation: behavior === 'jump' ? null : { + duration: 0 + } + }); + } + }; + + function checkTrigger(view, triggerOn) { + var model = view._model; + return model.get('axisExpandable') && model.get('axisExpandTriggerOn') === triggerOn; + } + + var ParallelModel = function (_super) { + __extends(ParallelModel, _super); + + function ParallelModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ParallelModel.type; + return _this; + } + + ParallelModel.prototype.init = function () { + _super.prototype.init.apply(this, arguments); + + this.mergeOption({}); + }; + + ParallelModel.prototype.mergeOption = function (newOption) { + var thisOption = this.option; + newOption && merge(thisOption, newOption, true); + + this._initDimensions(); + }; + + ParallelModel.prototype.contains = function (model, ecModel) { + var parallelIndex = model.get('parallelIndex'); + return parallelIndex != null && ecModel.getComponent('parallel', parallelIndex) === this; + }; + + ParallelModel.prototype.setAxisExpand = function (opt) { + each(['axisExpandable', 'axisExpandCenter', 'axisExpandCount', 'axisExpandWidth', 'axisExpandWindow'], function (name) { + if (opt.hasOwnProperty(name)) { + this.option[name] = opt[name]; + } + }, this); + }; + + ParallelModel.prototype._initDimensions = function () { + var dimensions = this.dimensions = []; + var parallelAxisIndex = this.parallelAxisIndex = []; + var axisModels = filter(this.ecModel.queryComponents({ + mainType: 'parallelAxis' + }), function (axisModel) { + return (axisModel.get('parallelIndex') || 0) === this.componentIndex; + }, this); + each(axisModels, function (axisModel) { + dimensions.push('dim' + axisModel.get('dim')); + parallelAxisIndex.push(axisModel.componentIndex); + }); + }; + + ParallelModel.type = 'parallel'; + ParallelModel.dependencies = ['parallelAxis']; + ParallelModel.layoutMode = 'box'; + ParallelModel.defaultOption = { + zlevel: 0, + z: 0, + left: 80, + top: 60, + right: 80, + bottom: 60, + layout: 'horizontal', + axisExpandable: false, + axisExpandCenter: null, + axisExpandCount: 0, + axisExpandWidth: 50, + axisExpandRate: 17, + axisExpandDebounce: 50, + axisExpandSlideTriggerArea: [-0.15, 0.05, 0.4], + axisExpandTriggerOn: 'click', + parallelAxisDefault: null + }; + return ParallelModel; + }(ComponentModel); + + var ParallelAxis = function (_super) { + __extends(ParallelAxis, _super); + + function ParallelAxis(dim, scale, coordExtent, axisType, axisIndex) { + var _this = _super.call(this, dim, scale, coordExtent) || this; + + _this.type = axisType || 'value'; + _this.axisIndex = axisIndex; + return _this; + } + + ParallelAxis.prototype.isHorizontal = function () { + return this.coordinateSystem.getModel().get('layout') !== 'horizontal'; + }; + + return ParallelAxis; + }(Axis); + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function sliderMove(delta, handleEnds, extent, handleIndex, minSpan, maxSpan) { + delta = delta || 0; + var extentSpan = extent[1] - extent[0]; + + if (minSpan != null) { + minSpan = restrict(minSpan, [0, extentSpan]); + } + + if (maxSpan != null) { + maxSpan = Math.max(maxSpan, minSpan != null ? minSpan : 0); + } + + if (handleIndex === 'all') { + var handleSpan = Math.abs(handleEnds[1] - handleEnds[0]); + handleSpan = restrict(handleSpan, [0, extentSpan]); + minSpan = maxSpan = restrict(handleSpan, [minSpan, maxSpan]); + handleIndex = 0; + } + + handleEnds[0] = restrict(handleEnds[0], extent); + handleEnds[1] = restrict(handleEnds[1], extent); + var originalDistSign = getSpanSign(handleEnds, handleIndex); + handleEnds[handleIndex] += delta; + var extentMinSpan = minSpan || 0; + var realExtent = extent.slice(); + originalDistSign.sign < 0 ? realExtent[0] += extentMinSpan : realExtent[1] -= extentMinSpan; + handleEnds[handleIndex] = restrict(handleEnds[handleIndex], realExtent); + var currDistSign; + currDistSign = getSpanSign(handleEnds, handleIndex); + + if (minSpan != null && (currDistSign.sign !== originalDistSign.sign || currDistSign.span < minSpan)) { + handleEnds[1 - handleIndex] = handleEnds[handleIndex] + originalDistSign.sign * minSpan; + } + + currDistSign = getSpanSign(handleEnds, handleIndex); + + if (maxSpan != null && currDistSign.span > maxSpan) { + handleEnds[1 - handleIndex] = handleEnds[handleIndex] + currDistSign.sign * maxSpan; + } + + return handleEnds; + } + + function getSpanSign(handleEnds, handleIndex) { + var dist = handleEnds[handleIndex] - handleEnds[1 - handleIndex]; + return { + span: Math.abs(dist), + sign: dist > 0 ? -1 : dist < 0 ? 1 : handleIndex ? -1 : 1 + }; + } + + function restrict(value, extend) { + return Math.min(extend[1] != null ? extend[1] : Infinity, Math.max(extend[0] != null ? extend[0] : -Infinity, value)); + } + + var each$6 = each; + var mathMin$8 = Math.min; + var mathMax$8 = Math.max; + var mathFloor$2 = Math.floor; + var mathCeil$1 = Math.ceil; + var round$2 = round; + var PI$7 = Math.PI; + + var Parallel = function () { + function Parallel(parallelModel, ecModel, api) { + this.type = 'parallel'; + this._axesMap = createHashMap(); + this._axesLayout = {}; + this.dimensions = parallelModel.dimensions; + this._model = parallelModel; + + this._init(parallelModel, ecModel, api); + } + + Parallel.prototype._init = function (parallelModel, ecModel, api) { + var dimensions = parallelModel.dimensions; + var parallelAxisIndex = parallelModel.parallelAxisIndex; + each$6(dimensions, function (dim, idx) { + var axisIndex = parallelAxisIndex[idx]; + var axisModel = ecModel.getComponent('parallelAxis', axisIndex); + + var axis = this._axesMap.set(dim, new ParallelAxis(dim, createScaleByModel(axisModel), [0, 0], axisModel.get('type'), axisIndex)); + + var isCategory = axis.type === 'category'; + axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.inverse = axisModel.get('inverse'); + axisModel.axis = axis; + axis.model = axisModel; + axis.coordinateSystem = axisModel.coordinateSystem = this; + }, this); + }; + + Parallel.prototype.update = function (ecModel, api) { + this._updateAxesFromSeries(this._model, ecModel); + }; + + Parallel.prototype.containPoint = function (point) { + var layoutInfo = this._makeLayoutInfo(); + + var axisBase = layoutInfo.axisBase; + var layoutBase = layoutInfo.layoutBase; + var pixelDimIndex = layoutInfo.pixelDimIndex; + var pAxis = point[1 - pixelDimIndex]; + var pLayout = point[pixelDimIndex]; + return pAxis >= axisBase && pAxis <= axisBase + layoutInfo.axisLength && pLayout >= layoutBase && pLayout <= layoutBase + layoutInfo.layoutLength; + }; + + Parallel.prototype.getModel = function () { + return this._model; + }; + + Parallel.prototype._updateAxesFromSeries = function (parallelModel, ecModel) { + ecModel.eachSeries(function (seriesModel) { + if (!parallelModel.contains(seriesModel, ecModel)) { + return; + } + + var data = seriesModel.getData(); + each$6(this.dimensions, function (dim) { + var axis = this._axesMap.get(dim); + + axis.scale.unionExtentFromData(data, data.mapDimension(dim)); + niceScaleExtent(axis.scale, axis.model); + }, this); + }, this); + }; + + Parallel.prototype.resize = function (parallelModel, api) { + this._rect = getLayoutRect(parallelModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + + this._layoutAxes(); + }; + + Parallel.prototype.getRect = function () { + return this._rect; + }; + + Parallel.prototype._makeLayoutInfo = function () { + var parallelModel = this._model; + var rect = this._rect; + var xy = ['x', 'y']; + var wh = ['width', 'height']; + var layout = parallelModel.get('layout'); + var pixelDimIndex = layout === 'horizontal' ? 0 : 1; + var layoutLength = rect[wh[pixelDimIndex]]; + var layoutExtent = [0, layoutLength]; + var axisCount = this.dimensions.length; + var axisExpandWidth = restrict$1(parallelModel.get('axisExpandWidth'), layoutExtent); + var axisExpandCount = restrict$1(parallelModel.get('axisExpandCount') || 0, [0, axisCount]); + var axisExpandable = parallelModel.get('axisExpandable') && axisCount > 3 && axisCount > axisExpandCount && axisExpandCount > 1 && axisExpandWidth > 0 && layoutLength > 0; + var axisExpandWindow = parallelModel.get('axisExpandWindow'); + var winSize; + + if (!axisExpandWindow) { + winSize = restrict$1(axisExpandWidth * (axisExpandCount - 1), layoutExtent); + var axisExpandCenter = parallelModel.get('axisExpandCenter') || mathFloor$2(axisCount / 2); + axisExpandWindow = [axisExpandWidth * axisExpandCenter - winSize / 2]; + axisExpandWindow[1] = axisExpandWindow[0] + winSize; + } else { + winSize = restrict$1(axisExpandWindow[1] - axisExpandWindow[0], layoutExtent); + axisExpandWindow[1] = axisExpandWindow[0] + winSize; + } + + var axisCollapseWidth = (layoutLength - winSize) / (axisCount - axisExpandCount); + axisCollapseWidth < 3 && (axisCollapseWidth = 0); + var winInnerIndices = [mathFloor$2(round$2(axisExpandWindow[0] / axisExpandWidth, 1)) + 1, mathCeil$1(round$2(axisExpandWindow[1] / axisExpandWidth, 1)) - 1]; + var axisExpandWindow0Pos = axisCollapseWidth / axisExpandWidth * axisExpandWindow[0]; + return { + layout: layout, + pixelDimIndex: pixelDimIndex, + layoutBase: rect[xy[pixelDimIndex]], + layoutLength: layoutLength, + axisBase: rect[xy[1 - pixelDimIndex]], + axisLength: rect[wh[1 - pixelDimIndex]], + axisExpandable: axisExpandable, + axisExpandWidth: axisExpandWidth, + axisCollapseWidth: axisCollapseWidth, + axisExpandWindow: axisExpandWindow, + axisCount: axisCount, + winInnerIndices: winInnerIndices, + axisExpandWindow0Pos: axisExpandWindow0Pos + }; + }; + + Parallel.prototype._layoutAxes = function () { + var rect = this._rect; + var axes = this._axesMap; + var dimensions = this.dimensions; + + var layoutInfo = this._makeLayoutInfo(); + + var layout = layoutInfo.layout; + axes.each(function (axis) { + var axisExtent = [0, layoutInfo.axisLength]; + var idx = axis.inverse ? 1 : 0; + axis.setExtent(axisExtent[idx], axisExtent[1 - idx]); + }); + each$6(dimensions, function (dim, idx) { + var posInfo = (layoutInfo.axisExpandable ? layoutAxisWithExpand : layoutAxisWithoutExpand)(idx, layoutInfo); + var positionTable = { + horizontal: { + x: posInfo.position, + y: layoutInfo.axisLength + }, + vertical: { + x: 0, + y: posInfo.position + } + }; + var rotationTable = { + horizontal: PI$7 / 2, + vertical: 0 + }; + var position = [positionTable[layout].x + rect.x, positionTable[layout].y + rect.y]; + var rotation = rotationTable[layout]; + var transform = create$1(); + rotate(transform, transform, rotation); + translate(transform, transform, position); + this._axesLayout[dim] = { + position: position, + rotation: rotation, + transform: transform, + axisNameAvailableWidth: posInfo.axisNameAvailableWidth, + axisLabelShow: posInfo.axisLabelShow, + nameTruncateMaxWidth: posInfo.nameTruncateMaxWidth, + tickDirection: 1, + labelDirection: 1 + }; + }, this); + }; + + Parallel.prototype.getAxis = function (dim) { + return this._axesMap.get(dim); + }; + + Parallel.prototype.dataToPoint = function (value, dim) { + return this.axisCoordToPoint(this._axesMap.get(dim).dataToCoord(value), dim); + }; + + Parallel.prototype.eachActiveState = function (data, callback, start, end) { + start == null && (start = 0); + end == null && (end = data.count()); + var axesMap = this._axesMap; + var dimensions = this.dimensions; + var dataDimensions = []; + var axisModels = []; + each(dimensions, function (axisDim) { + dataDimensions.push(data.mapDimension(axisDim)); + axisModels.push(axesMap.get(axisDim).model); + }); + var hasActiveSet = this.hasAxisBrushed(); + + for (var dataIndex = start; dataIndex < end; dataIndex++) { + var activeState = void 0; + + if (!hasActiveSet) { + activeState = 'normal'; + } else { + activeState = 'active'; + var values = data.getValues(dataDimensions, dataIndex); + + for (var j = 0, lenj = dimensions.length; j < lenj; j++) { + var state = axisModels[j].getActiveState(values[j]); + + if (state === 'inactive') { + activeState = 'inactive'; + break; + } + } + } + + callback(activeState, dataIndex); + } + }; + + Parallel.prototype.hasAxisBrushed = function () { + var dimensions = this.dimensions; + var axesMap = this._axesMap; + var hasActiveSet = false; + + for (var j = 0, lenj = dimensions.length; j < lenj; j++) { + if (axesMap.get(dimensions[j]).model.getActiveState() !== 'normal') { + hasActiveSet = true; + } + } + + return hasActiveSet; + }; + + Parallel.prototype.axisCoordToPoint = function (coord, dim) { + var axisLayout = this._axesLayout[dim]; + return applyTransform$1([coord, 0], axisLayout.transform); + }; + + Parallel.prototype.getAxisLayout = function (dim) { + return clone(this._axesLayout[dim]); + }; + + Parallel.prototype.getSlidedAxisExpandWindow = function (point) { + var layoutInfo = this._makeLayoutInfo(); + + var pixelDimIndex = layoutInfo.pixelDimIndex; + var axisExpandWindow = layoutInfo.axisExpandWindow.slice(); + var winSize = axisExpandWindow[1] - axisExpandWindow[0]; + var extent = [0, layoutInfo.axisExpandWidth * (layoutInfo.axisCount - 1)]; + + if (!this.containPoint(point)) { + return { + behavior: 'none', + axisExpandWindow: axisExpandWindow + }; + } + + var pointCoord = point[pixelDimIndex] - layoutInfo.layoutBase - layoutInfo.axisExpandWindow0Pos; + var delta; + var behavior = 'slide'; + var axisCollapseWidth = layoutInfo.axisCollapseWidth; + + var triggerArea = this._model.get('axisExpandSlideTriggerArea'); + + var useJump = triggerArea[0] != null; + + if (axisCollapseWidth) { + if (useJump && axisCollapseWidth && pointCoord < winSize * triggerArea[0]) { + behavior = 'jump'; + delta = pointCoord - winSize * triggerArea[2]; + } else if (useJump && axisCollapseWidth && pointCoord > winSize * (1 - triggerArea[0])) { + behavior = 'jump'; + delta = pointCoord - winSize * (1 - triggerArea[2]); + } else { + (delta = pointCoord - winSize * triggerArea[1]) >= 0 && (delta = pointCoord - winSize * (1 - triggerArea[1])) <= 0 && (delta = 0); + } + + delta *= layoutInfo.axisExpandWidth / axisCollapseWidth; + delta ? sliderMove(delta, axisExpandWindow, extent, 'all') : behavior = 'none'; + } else { + var winSize2 = axisExpandWindow[1] - axisExpandWindow[0]; + var pos = extent[1] * pointCoord / winSize2; + axisExpandWindow = [mathMax$8(0, pos - winSize2 / 2)]; + axisExpandWindow[1] = mathMin$8(extent[1], axisExpandWindow[0] + winSize2); + axisExpandWindow[0] = axisExpandWindow[1] - winSize2; + } + + return { + axisExpandWindow: axisExpandWindow, + behavior: behavior + }; + }; + + return Parallel; + }(); + + function restrict$1(len, extent) { + return mathMin$8(mathMax$8(len, extent[0]), extent[1]); + } + + function layoutAxisWithoutExpand(axisIndex, layoutInfo) { + var step = layoutInfo.layoutLength / (layoutInfo.axisCount - 1); + return { + position: step * axisIndex, + axisNameAvailableWidth: step, + axisLabelShow: true + }; + } + + function layoutAxisWithExpand(axisIndex, layoutInfo) { + var layoutLength = layoutInfo.layoutLength; + var axisExpandWidth = layoutInfo.axisExpandWidth; + var axisCount = layoutInfo.axisCount; + var axisCollapseWidth = layoutInfo.axisCollapseWidth; + var winInnerIndices = layoutInfo.winInnerIndices; + var position; + var axisNameAvailableWidth = axisCollapseWidth; + var axisLabelShow = false; + var nameTruncateMaxWidth; + + if (axisIndex < winInnerIndices[0]) { + position = axisIndex * axisCollapseWidth; + nameTruncateMaxWidth = axisCollapseWidth; + } else if (axisIndex <= winInnerIndices[1]) { + position = layoutInfo.axisExpandWindow0Pos + axisIndex * axisExpandWidth - layoutInfo.axisExpandWindow[0]; + axisNameAvailableWidth = axisExpandWidth; + axisLabelShow = true; + } else { + position = layoutLength - (axisCount - 1 - axisIndex) * axisCollapseWidth; + nameTruncateMaxWidth = axisCollapseWidth; + } + + return { + position: position, + axisNameAvailableWidth: axisNameAvailableWidth, + axisLabelShow: axisLabelShow, + nameTruncateMaxWidth: nameTruncateMaxWidth + }; + } + + function createParallelCoordSys(ecModel, api) { + var coordSysList = []; + ecModel.eachComponent('parallel', function (parallelModel, idx) { + var coordSys = new Parallel(parallelModel, ecModel, api); + coordSys.name = 'parallel_' + idx; + coordSys.resize(parallelModel, api); + parallelModel.coordinateSystem = coordSys; + coordSys.model = parallelModel; + coordSysList.push(coordSys); + }); + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'parallel') { + var parallelModel = seriesModel.getReferringComponents('parallel', SINGLE_REFERRING).models[0]; + seriesModel.coordinateSystem = parallelModel.coordinateSystem; + } + }); + return coordSysList; + } + + var parallelCoordSysCreator = { + create: createParallelCoordSys + }; + + var ParallelAxisModel = function (_super) { + __extends(ParallelAxisModel, _super); + + function ParallelAxisModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ParallelAxisModel.type; + _this.activeIntervals = []; + return _this; + } + + ParallelAxisModel.prototype.getAreaSelectStyle = function () { + return makeStyleMapper([['fill', 'color'], ['lineWidth', 'borderWidth'], ['stroke', 'borderColor'], ['width', 'width'], ['opacity', 'opacity']])(this.getModel('areaSelectStyle')); + }; + + ParallelAxisModel.prototype.setActiveIntervals = function (intervals) { + var activeIntervals = this.activeIntervals = clone(intervals); + + if (activeIntervals) { + for (var i = activeIntervals.length - 1; i >= 0; i--) { + asc(activeIntervals[i]); + } + } + }; + + ParallelAxisModel.prototype.getActiveState = function (value) { + var activeIntervals = this.activeIntervals; + + if (!activeIntervals.length) { + return 'normal'; + } + + if (value == null || isNaN(+value)) { + return 'inactive'; + } + + if (activeIntervals.length === 1) { + var interval = activeIntervals[0]; + + if (interval[0] <= value && value <= interval[1]) { + return 'active'; + } + } else { + for (var i = 0, len = activeIntervals.length; i < len; i++) { + if (activeIntervals[i][0] <= value && value <= activeIntervals[i][1]) { + return 'active'; + } + } + } + + return 'inactive'; + }; + + return ParallelAxisModel; + }(ComponentModel); + + mixin(ParallelAxisModel, AxisModelCommonMixin); + + var BRUSH_PANEL_GLOBAL = true; + var mathMin$9 = Math.min; + var mathMax$9 = Math.max; + var mathPow$2 = Math.pow; + var COVER_Z = 10000; + var UNSELECT_THRESHOLD = 6; + var MIN_RESIZE_LINE_WIDTH = 6; + var MUTEX_RESOURCE_KEY = 'globalPan'; + var DIRECTION_MAP = { + w: [0, 0], + e: [0, 1], + n: [1, 0], + s: [1, 1] + }; + var CURSOR_MAP = { + w: 'ew', + e: 'ew', + n: 'ns', + s: 'ns', + ne: 'nesw', + sw: 'nesw', + nw: 'nwse', + se: 'nwse' + }; + var DEFAULT_BRUSH_OPT = { + brushStyle: { + lineWidth: 2, + stroke: 'rgba(210,219,238,0.3)', + fill: '#D2DBEE' + }, + transformable: true, + brushMode: 'single', + removeOnClick: false + }; + var baseUID = 0; + + var BrushController = function (_super) { + __extends(BrushController, _super); + + function BrushController(zr) { + var _this = _super.call(this) || this; + + _this._track = []; + _this._covers = []; + _this._handlers = {}; + + if ("development" !== 'production') { + assert(zr); + } + + _this._zr = zr; + _this.group = new Group(); + _this._uid = 'brushController_' + baseUID++; + each(pointerHandlers, function (handler, eventName) { + this._handlers[eventName] = bind(handler, this); + }, _this); + return _this; + } + + BrushController.prototype.enableBrush = function (brushOption) { + if ("development" !== 'production') { + assert(this._mounted); + } + + this._brushType && this._doDisableBrush(); + brushOption.brushType && this._doEnableBrush(brushOption); + return this; + }; + + BrushController.prototype._doEnableBrush = function (brushOption) { + var zr = this._zr; + + if (!this._enableGlobalPan) { + take(zr, MUTEX_RESOURCE_KEY, this._uid); + } + + each(this._handlers, function (handler, eventName) { + zr.on(eventName, handler); + }); + this._brushType = brushOption.brushType; + this._brushOption = merge(clone(DEFAULT_BRUSH_OPT), brushOption, true); + }; + + BrushController.prototype._doDisableBrush = function () { + var zr = this._zr; + release(zr, MUTEX_RESOURCE_KEY, this._uid); + each(this._handlers, function (handler, eventName) { + zr.off(eventName, handler); + }); + this._brushType = this._brushOption = null; + }; + + BrushController.prototype.setPanels = function (panelOpts) { + if (panelOpts && panelOpts.length) { + var panels_1 = this._panels = {}; + each(panelOpts, function (panelOpts) { + panels_1[panelOpts.panelId] = clone(panelOpts); + }); + } else { + this._panels = null; + } + + return this; + }; + + BrushController.prototype.mount = function (opt) { + opt = opt || {}; + + if ("development" !== 'production') { + this._mounted = true; + } + + this._enableGlobalPan = opt.enableGlobalPan; + var thisGroup = this.group; + + this._zr.add(thisGroup); + + thisGroup.attr({ + x: opt.x || 0, + y: opt.y || 0, + rotation: opt.rotation || 0, + scaleX: opt.scaleX || 1, + scaleY: opt.scaleY || 1 + }); + this._transform = thisGroup.getLocalTransform(); + return this; + }; + + BrushController.prototype.updateCovers = function (coverConfigList) { + if ("development" !== 'production') { + assert(this._mounted); + } + + coverConfigList = map(coverConfigList, function (coverConfig) { + return merge(clone(DEFAULT_BRUSH_OPT), coverConfig, true); + }); + var tmpIdPrefix = '\0-brush-index-'; + var oldCovers = this._covers; + var newCovers = this._covers = []; + var controller = this; + var creatingCover = this._creatingCover; + new DataDiffer(oldCovers, coverConfigList, oldGetKey, getKey).add(addOrUpdate).update(addOrUpdate).remove(remove).execute(); + return this; + + function getKey(brushOption, index) { + return (brushOption.id != null ? brushOption.id : tmpIdPrefix + index) + '-' + brushOption.brushType; + } + + function oldGetKey(cover, index) { + return getKey(cover.__brushOption, index); + } + + function addOrUpdate(newIndex, oldIndex) { + var newBrushInternal = coverConfigList[newIndex]; + + if (oldIndex != null && oldCovers[oldIndex] === creatingCover) { + newCovers[newIndex] = oldCovers[oldIndex]; + } else { + var cover = newCovers[newIndex] = oldIndex != null ? (oldCovers[oldIndex].__brushOption = newBrushInternal, oldCovers[oldIndex]) : endCreating(controller, createCover(controller, newBrushInternal)); + updateCoverAfterCreation(controller, cover); + } + } + + function remove(oldIndex) { + if (oldCovers[oldIndex] !== creatingCover) { + controller.group.remove(oldCovers[oldIndex]); + } + } + }; + + BrushController.prototype.unmount = function () { + if ("development" !== 'production') { + if (!this._mounted) { + return; + } + } + + this.enableBrush(false); + clearCovers(this); + + this._zr.remove(this.group); + + if ("development" !== 'production') { + this._mounted = false; + } + + return this; + }; + + BrushController.prototype.dispose = function () { + this.unmount(); + this.off(); + }; + + return BrushController; + }(Eventful); + + function createCover(controller, brushOption) { + var cover = coverRenderers[brushOption.brushType].createCover(controller, brushOption); + cover.__brushOption = brushOption; + updateZ(cover, brushOption); + controller.group.add(cover); + return cover; + } + + function endCreating(controller, creatingCover) { + var coverRenderer = getCoverRenderer(creatingCover); + + if (coverRenderer.endCreating) { + coverRenderer.endCreating(controller, creatingCover); + updateZ(creatingCover, creatingCover.__brushOption); + } + + return creatingCover; + } + + function updateCoverShape(controller, cover) { + var brushOption = cover.__brushOption; + getCoverRenderer(cover).updateCoverShape(controller, cover, brushOption.range, brushOption); + } + + function updateZ(cover, brushOption) { + var z = brushOption.z; + z == null && (z = COVER_Z); + cover.traverse(function (el) { + el.z = z; + el.z2 = z; + }); + } + + function updateCoverAfterCreation(controller, cover) { + getCoverRenderer(cover).updateCommon(controller, cover); + updateCoverShape(controller, cover); + } + + function getCoverRenderer(cover) { + return coverRenderers[cover.__brushOption.brushType]; + } + + function getPanelByPoint(controller, e, localCursorPoint) { + var panels = controller._panels; + + if (!panels) { + return BRUSH_PANEL_GLOBAL; + } + + var panel; + var transform = controller._transform; + each(panels, function (pn) { + pn.isTargetByCursor(e, localCursorPoint, transform) && (panel = pn); + }); + return panel; + } + + function getPanelByCover(controller, cover) { + var panels = controller._panels; + + if (!panels) { + return BRUSH_PANEL_GLOBAL; + } + + var panelId = cover.__brushOption.panelId; + return panelId != null ? panels[panelId] : BRUSH_PANEL_GLOBAL; + } + + function clearCovers(controller) { + var covers = controller._covers; + var originalLength = covers.length; + each(covers, function (cover) { + controller.group.remove(cover); + }, controller); + covers.length = 0; + return !!originalLength; + } + + function trigger$1(controller, opt) { + var areas = map(controller._covers, function (cover) { + var brushOption = cover.__brushOption; + var range = clone(brushOption.range); + return { + brushType: brushOption.brushType, + panelId: brushOption.panelId, + range: range + }; + }); + controller.trigger('brush', { + areas: areas, + isEnd: !!opt.isEnd, + removeOnClick: !!opt.removeOnClick + }); + } + + function shouldShowCover(controller) { + var track = controller._track; + + if (!track.length) { + return false; + } + + var p2 = track[track.length - 1]; + var p1 = track[0]; + var dx = p2[0] - p1[0]; + var dy = p2[1] - p1[1]; + var dist = mathPow$2(dx * dx + dy * dy, 0.5); + return dist > UNSELECT_THRESHOLD; + } + + function getTrackEnds(track) { + var tail = track.length - 1; + tail < 0 && (tail = 0); + return [track[0], track[tail]]; + } + + function createBaseRectCover(rectRangeConverter, controller, brushOption, edgeNameSequences) { + var cover = new Group(); + cover.add(new Rect({ + name: 'main', + style: makeStyle(brushOption), + silent: true, + draggable: true, + cursor: 'move', + drift: curry(driftRect, rectRangeConverter, controller, cover, ['n', 's', 'w', 'e']), + ondragend: curry(trigger$1, controller, { + isEnd: true + }) + })); + each(edgeNameSequences, function (nameSequence) { + cover.add(new Rect({ + name: nameSequence.join(''), + style: { + opacity: 0 + }, + draggable: true, + silent: true, + invisible: true, + drift: curry(driftRect, rectRangeConverter, controller, cover, nameSequence), + ondragend: curry(trigger$1, controller, { + isEnd: true + }) + })); + }); + return cover; + } + + function updateBaseRect(controller, cover, localRange, brushOption) { + var lineWidth = brushOption.brushStyle.lineWidth || 0; + var handleSize = mathMax$9(lineWidth, MIN_RESIZE_LINE_WIDTH); + var x = localRange[0][0]; + var y = localRange[1][0]; + var xa = x - lineWidth / 2; + var ya = y - lineWidth / 2; + var x2 = localRange[0][1]; + var y2 = localRange[1][1]; + var x2a = x2 - handleSize + lineWidth / 2; + var y2a = y2 - handleSize + lineWidth / 2; + var width = x2 - x; + var height = y2 - y; + var widtha = width + lineWidth; + var heighta = height + lineWidth; + updateRectShape(controller, cover, 'main', x, y, width, height); + + if (brushOption.transformable) { + updateRectShape(controller, cover, 'w', xa, ya, handleSize, heighta); + updateRectShape(controller, cover, 'e', x2a, ya, handleSize, heighta); + updateRectShape(controller, cover, 'n', xa, ya, widtha, handleSize); + updateRectShape(controller, cover, 's', xa, y2a, widtha, handleSize); + updateRectShape(controller, cover, 'nw', xa, ya, handleSize, handleSize); + updateRectShape(controller, cover, 'ne', x2a, ya, handleSize, handleSize); + updateRectShape(controller, cover, 'sw', xa, y2a, handleSize, handleSize); + updateRectShape(controller, cover, 'se', x2a, y2a, handleSize, handleSize); + } + } + + function updateCommon(controller, cover) { + var brushOption = cover.__brushOption; + var transformable = brushOption.transformable; + var mainEl = cover.childAt(0); + mainEl.useStyle(makeStyle(brushOption)); + mainEl.attr({ + silent: !transformable, + cursor: transformable ? 'move' : 'default' + }); + each([['w'], ['e'], ['n'], ['s'], ['s', 'e'], ['s', 'w'], ['n', 'e'], ['n', 'w']], function (nameSequence) { + var el = cover.childOfName(nameSequence.join('')); + var globalDir = nameSequence.length === 1 ? getGlobalDirection1(controller, nameSequence[0]) : getGlobalDirection2(controller, nameSequence); + el && el.attr({ + silent: !transformable, + invisible: !transformable, + cursor: transformable ? CURSOR_MAP[globalDir] + '-resize' : null + }); + }); + } + + function updateRectShape(controller, cover, name, x, y, w, h) { + var el = cover.childOfName(name); + el && el.setShape(pointsToRect(clipByPanel(controller, cover, [[x, y], [x + w, y + h]]))); + } + + function makeStyle(brushOption) { + return defaults({ + strokeNoScale: true + }, brushOption.brushStyle); + } + + function formatRectRange(x, y, x2, y2) { + var min = [mathMin$9(x, x2), mathMin$9(y, y2)]; + var max = [mathMax$9(x, x2), mathMax$9(y, y2)]; + return [[min[0], max[0]], [min[1], max[1]]]; + } + + function getTransform$1(controller) { + return getTransform(controller.group); + } + + function getGlobalDirection1(controller, localDirName) { + var map = { + w: 'left', + e: 'right', + n: 'top', + s: 'bottom' + }; + var inverseMap = { + left: 'w', + right: 'e', + top: 'n', + bottom: 's' + }; + var dir = transformDirection(map[localDirName], getTransform$1(controller)); + return inverseMap[dir]; + } + + function getGlobalDirection2(controller, localDirNameSeq) { + var globalDir = [getGlobalDirection1(controller, localDirNameSeq[0]), getGlobalDirection1(controller, localDirNameSeq[1])]; + (globalDir[0] === 'e' || globalDir[0] === 'w') && globalDir.reverse(); + return globalDir.join(''); + } + + function driftRect(rectRangeConverter, controller, cover, dirNameSequence, dx, dy) { + var brushOption = cover.__brushOption; + var rectRange = rectRangeConverter.toRectRange(brushOption.range); + var localDelta = toLocalDelta(controller, dx, dy); + each(dirNameSequence, function (dirName) { + var ind = DIRECTION_MAP[dirName]; + rectRange[ind[0]][ind[1]] += localDelta[ind[0]]; + }); + brushOption.range = rectRangeConverter.fromRectRange(formatRectRange(rectRange[0][0], rectRange[1][0], rectRange[0][1], rectRange[1][1])); + updateCoverAfterCreation(controller, cover); + trigger$1(controller, { + isEnd: false + }); + } + + function driftPolygon(controller, cover, dx, dy) { + var range = cover.__brushOption.range; + var localDelta = toLocalDelta(controller, dx, dy); + each(range, function (point) { + point[0] += localDelta[0]; + point[1] += localDelta[1]; + }); + updateCoverAfterCreation(controller, cover); + trigger$1(controller, { + isEnd: false + }); + } + + function toLocalDelta(controller, dx, dy) { + var thisGroup = controller.group; + var localD = thisGroup.transformCoordToLocal(dx, dy); + var localZero = thisGroup.transformCoordToLocal(0, 0); + return [localD[0] - localZero[0], localD[1] - localZero[1]]; + } + + function clipByPanel(controller, cover, data) { + var panel = getPanelByCover(controller, cover); + return panel && panel !== BRUSH_PANEL_GLOBAL ? panel.clipPath(data, controller._transform) : clone(data); + } + + function pointsToRect(points) { + var xmin = mathMin$9(points[0][0], points[1][0]); + var ymin = mathMin$9(points[0][1], points[1][1]); + var xmax = mathMax$9(points[0][0], points[1][0]); + var ymax = mathMax$9(points[0][1], points[1][1]); + return { + x: xmin, + y: ymin, + width: xmax - xmin, + height: ymax - ymin + }; + } + + function resetCursor(controller, e, localCursorPoint) { + if (!controller._brushType || isOutsideZrArea(controller, e.offsetX, e.offsetY)) { + return; + } + + var zr = controller._zr; + var covers = controller._covers; + var currPanel = getPanelByPoint(controller, e, localCursorPoint); + + if (!controller._dragging) { + for (var i = 0; i < covers.length; i++) { + var brushOption = covers[i].__brushOption; + + if (currPanel && (currPanel === BRUSH_PANEL_GLOBAL || brushOption.panelId === currPanel.panelId) && coverRenderers[brushOption.brushType].contain(covers[i], localCursorPoint[0], localCursorPoint[1])) { + return; + } + } + } + + currPanel && zr.setCursorStyle('crosshair'); + } + + function preventDefault(e) { + var rawE = e.event; + rawE.preventDefault && rawE.preventDefault(); + } + + function mainShapeContain(cover, x, y) { + return cover.childOfName('main').contain(x, y); + } + + function updateCoverByMouse(controller, e, localCursorPoint, isEnd) { + var creatingCover = controller._creatingCover; + var panel = controller._creatingPanel; + var thisBrushOption = controller._brushOption; + var eventParams; + + controller._track.push(localCursorPoint.slice()); + + if (shouldShowCover(controller) || creatingCover) { + if (panel && !creatingCover) { + thisBrushOption.brushMode === 'single' && clearCovers(controller); + var brushOption = clone(thisBrushOption); + brushOption.brushType = determineBrushType(brushOption.brushType, panel); + brushOption.panelId = panel === BRUSH_PANEL_GLOBAL ? null : panel.panelId; + creatingCover = controller._creatingCover = createCover(controller, brushOption); + + controller._covers.push(creatingCover); + } + + if (creatingCover) { + var coverRenderer = coverRenderers[determineBrushType(controller._brushType, panel)]; + var coverBrushOption = creatingCover.__brushOption; + coverBrushOption.range = coverRenderer.getCreatingRange(clipByPanel(controller, creatingCover, controller._track)); + + if (isEnd) { + endCreating(controller, creatingCover); + coverRenderer.updateCommon(controller, creatingCover); + } + + updateCoverShape(controller, creatingCover); + eventParams = { + isEnd: isEnd + }; + } + } else if (isEnd && thisBrushOption.brushMode === 'single' && thisBrushOption.removeOnClick) { + if (getPanelByPoint(controller, e, localCursorPoint) && clearCovers(controller)) { + eventParams = { + isEnd: isEnd, + removeOnClick: true + }; + } + } + + return eventParams; + } + + function determineBrushType(brushType, panel) { + if (brushType === 'auto') { + if ("development" !== 'production') { + assert(panel && panel.defaultBrushType, 'MUST have defaultBrushType when brushType is "atuo"'); + } + + return panel.defaultBrushType; + } + + return brushType; + } + + var pointerHandlers = { + mousedown: function (e) { + if (this._dragging) { + handleDragEnd(this, e); + } else if (!e.target || !e.target.draggable) { + preventDefault(e); + var localCursorPoint = this.group.transformCoordToLocal(e.offsetX, e.offsetY); + this._creatingCover = null; + var panel = this._creatingPanel = getPanelByPoint(this, e, localCursorPoint); + + if (panel) { + this._dragging = true; + this._track = [localCursorPoint.slice()]; + } + } + }, + mousemove: function (e) { + var x = e.offsetX; + var y = e.offsetY; + var localCursorPoint = this.group.transformCoordToLocal(x, y); + resetCursor(this, e, localCursorPoint); + + if (this._dragging) { + preventDefault(e); + var eventParams = updateCoverByMouse(this, e, localCursorPoint, false); + eventParams && trigger$1(this, eventParams); + } + }, + mouseup: function (e) { + handleDragEnd(this, e); + } + }; + + function handleDragEnd(controller, e) { + if (controller._dragging) { + preventDefault(e); + var x = e.offsetX; + var y = e.offsetY; + var localCursorPoint = controller.group.transformCoordToLocal(x, y); + var eventParams = updateCoverByMouse(controller, e, localCursorPoint, true); + controller._dragging = false; + controller._track = []; + controller._creatingCover = null; + eventParams && trigger$1(controller, eventParams); + } + } + + function isOutsideZrArea(controller, x, y) { + var zr = controller._zr; + return x < 0 || x > zr.getWidth() || y < 0 || y > zr.getHeight(); + } + + var coverRenderers = { + lineX: getLineRenderer(0), + lineY: getLineRenderer(1), + rect: { + createCover: function (controller, brushOption) { + function returnInput(range) { + return range; + } + + return createBaseRectCover({ + toRectRange: returnInput, + fromRectRange: returnInput + }, controller, brushOption, [['w'], ['e'], ['n'], ['s'], ['s', 'e'], ['s', 'w'], ['n', 'e'], ['n', 'w']]); + }, + getCreatingRange: function (localTrack) { + var ends = getTrackEnds(localTrack); + return formatRectRange(ends[1][0], ends[1][1], ends[0][0], ends[0][1]); + }, + updateCoverShape: function (controller, cover, localRange, brushOption) { + updateBaseRect(controller, cover, localRange, brushOption); + }, + updateCommon: updateCommon, + contain: mainShapeContain + }, + polygon: { + createCover: function (controller, brushOption) { + var cover = new Group(); + cover.add(new Polyline({ + name: 'main', + style: makeStyle(brushOption), + silent: true + })); + return cover; + }, + getCreatingRange: function (localTrack) { + return localTrack; + }, + endCreating: function (controller, cover) { + cover.remove(cover.childAt(0)); + cover.add(new Polygon({ + name: 'main', + draggable: true, + drift: curry(driftPolygon, controller, cover), + ondragend: curry(trigger$1, controller, { + isEnd: true + }) + })); + }, + updateCoverShape: function (controller, cover, localRange, brushOption) { + cover.childAt(0).setShape({ + points: clipByPanel(controller, cover, localRange) + }); + }, + updateCommon: updateCommon, + contain: mainShapeContain + } + }; + + function getLineRenderer(xyIndex) { + return { + createCover: function (controller, brushOption) { + return createBaseRectCover({ + toRectRange: function (range) { + var rectRange = [range, [0, 100]]; + xyIndex && rectRange.reverse(); + return rectRange; + }, + fromRectRange: function (rectRange) { + return rectRange[xyIndex]; + } + }, controller, brushOption, [[['w'], ['e']], [['n'], ['s']]][xyIndex]); + }, + getCreatingRange: function (localTrack) { + var ends = getTrackEnds(localTrack); + var min = mathMin$9(ends[0][xyIndex], ends[1][xyIndex]); + var max = mathMax$9(ends[0][xyIndex], ends[1][xyIndex]); + return [min, max]; + }, + updateCoverShape: function (controller, cover, localRange, brushOption) { + var otherExtent; + var panel = getPanelByCover(controller, cover); + + if (panel !== BRUSH_PANEL_GLOBAL && panel.getLinearBrushOtherExtent) { + otherExtent = panel.getLinearBrushOtherExtent(xyIndex); + } else { + var zr = controller._zr; + otherExtent = [0, [zr.getWidth(), zr.getHeight()][1 - xyIndex]]; + } + + var rectRange = [localRange, otherExtent]; + xyIndex && rectRange.reverse(); + updateBaseRect(controller, cover, rectRange, brushOption); + }, + updateCommon: updateCommon, + contain: mainShapeContain + }; + } + + function makeRectPanelClipPath(rect) { + rect = normalizeRect(rect); + return function (localPoints) { + return clipPointsByRect(localPoints, rect); + }; + } + function makeLinearBrushOtherExtent(rect, specifiedXYIndex) { + rect = normalizeRect(rect); + return function (xyIndex) { + var idx = specifiedXYIndex != null ? specifiedXYIndex : xyIndex; + var brushWidth = idx ? rect.width : rect.height; + var base = idx ? rect.x : rect.y; + return [base, base + (brushWidth || 0)]; + }; + } + function makeRectIsTargetByCursor(rect, api, targetModel) { + var boundingRect = normalizeRect(rect); + return function (e, localCursorPoint) { + return boundingRect.contain(localCursorPoint[0], localCursorPoint[1]) && !onIrrelevantElement(e, api, targetModel); + }; + } + + function normalizeRect(rect) { + return BoundingRect.create(rect); + } + + var elementList = ['axisLine', 'axisTickLabel', 'axisName']; + + var ParallelAxisView = function (_super) { + __extends(ParallelAxisView, _super); + + function ParallelAxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ParallelAxisView.type; + return _this; + } + + ParallelAxisView.prototype.init = function (ecModel, api) { + _super.prototype.init.apply(this, arguments); + + (this._brushController = new BrushController(api.getZr())).on('brush', bind(this._onBrush, this)); + }; + + ParallelAxisView.prototype.render = function (axisModel, ecModel, api, payload) { + if (fromAxisAreaSelect(axisModel, ecModel, payload)) { + return; + } + + this.axisModel = axisModel; + this.api = api; + this.group.removeAll(); + var oldAxisGroup = this._axisGroup; + this._axisGroup = new Group(); + this.group.add(this._axisGroup); + + if (!axisModel.get('show')) { + return; + } + + var coordSysModel = getCoordSysModel(axisModel, ecModel); + var coordSys = coordSysModel.coordinateSystem; + var areaSelectStyle = axisModel.getAreaSelectStyle(); + var areaWidth = areaSelectStyle.width; + var dim = axisModel.axis.dim; + var axisLayout = coordSys.getAxisLayout(dim); + var builderOpt = extend({ + strokeContainThreshold: areaWidth + }, axisLayout); + var axisBuilder = new AxisBuilder(axisModel, builderOpt); + each(elementList, axisBuilder.add, axisBuilder); + + this._axisGroup.add(axisBuilder.getGroup()); + + this._refreshBrushController(builderOpt, areaSelectStyle, axisModel, coordSysModel, areaWidth, api); + + groupTransition(oldAxisGroup, this._axisGroup, axisModel); + }; + + ParallelAxisView.prototype._refreshBrushController = function (builderOpt, areaSelectStyle, axisModel, coordSysModel, areaWidth, api) { + var extent = axisModel.axis.getExtent(); + var extentLen = extent[1] - extent[0]; + var extra = Math.min(30, Math.abs(extentLen) * 0.1); + var rect = BoundingRect.create({ + x: extent[0], + y: -areaWidth / 2, + width: extentLen, + height: areaWidth + }); + rect.x -= extra; + rect.width += 2 * extra; + + this._brushController.mount({ + enableGlobalPan: true, + rotation: builderOpt.rotation, + x: builderOpt.position[0], + y: builderOpt.position[1] + }).setPanels([{ + panelId: 'pl', + clipPath: makeRectPanelClipPath(rect), + isTargetByCursor: makeRectIsTargetByCursor(rect, api, coordSysModel), + getLinearBrushOtherExtent: makeLinearBrushOtherExtent(rect, 0) + }]).enableBrush({ + brushType: 'lineX', + brushStyle: areaSelectStyle, + removeOnClick: true + }).updateCovers(getCoverInfoList(axisModel)); + }; + + ParallelAxisView.prototype._onBrush = function (eventParam) { + var coverInfoList = eventParam.areas; + var axisModel = this.axisModel; + var axis = axisModel.axis; + var intervals = map(coverInfoList, function (coverInfo) { + return [axis.coordToData(coverInfo.range[0], true), axis.coordToData(coverInfo.range[1], true)]; + }); + + if (!axisModel.option.realtime === eventParam.isEnd || eventParam.removeOnClick) { + this.api.dispatchAction({ + type: 'axisAreaSelect', + parallelAxisId: axisModel.id, + intervals: intervals + }); + } + }; + + ParallelAxisView.prototype.dispose = function () { + this._brushController.dispose(); + }; + + ParallelAxisView.type = 'parallelAxis'; + return ParallelAxisView; + }(ComponentView); + + function fromAxisAreaSelect(axisModel, ecModel, payload) { + return payload && payload.type === 'axisAreaSelect' && ecModel.findComponents({ + mainType: 'parallelAxis', + query: payload + })[0] === axisModel; + } + + function getCoverInfoList(axisModel) { + var axis = axisModel.axis; + return map(axisModel.activeIntervals, function (interval) { + return { + brushType: 'lineX', + panelId: 'pl', + range: [axis.dataToCoord(interval[0], true), axis.dataToCoord(interval[1], true)] + }; + }); + } + + function getCoordSysModel(axisModel, ecModel) { + return ecModel.getComponent('parallel', axisModel.get('parallelIndex')); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var actionInfo$1 = { + type: 'axisAreaSelect', + event: 'axisAreaSelected' + }; + function installParallelActions(registers) { + registers.registerAction(actionInfo$1, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'parallelAxis', + query: payload + }, function (parallelAxisModel) { + parallelAxisModel.axis.model.setActiveIntervals(payload.intervals); + }); + }); + registers.registerAction('parallelAxisExpand', function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'parallel', + query: payload + }, function (parallelModel) { + parallelModel.setAxisExpand(payload); + }); + }); + } + + var defaultAxisOption = { + type: 'value', + areaSelectStyle: { + width: 20, + borderWidth: 1, + borderColor: 'rgba(160,197,232)', + color: 'rgba(160,197,232)', + opacity: 0.3 + }, + realtime: true, + z: 10 + }; + function install$f(registers) { + registers.registerComponentView(ParallelView$1); + registers.registerComponentModel(ParallelModel); + registers.registerCoordinateSystem('parallel', parallelCoordSysCreator); + registers.registerPreprocessor(parallelPreprocessor); + registers.registerComponentModel(ParallelAxisModel); + registers.registerComponentView(ParallelAxisView); + axisModelCreator(registers, 'parallel', ParallelAxisModel, defaultAxisOption); + installParallelActions(registers); + } + + function install$g(registers) { + use(install$f); + registers.registerChartView(ParallelView); + registers.registerSeriesModel(ParallelSeriesModel); + registers.registerVisual(registers.PRIORITY.VISUAL.BRUSH, parallelVisual); + } + + var SankeyPathShape = function () { + function SankeyPathShape() { + this.x1 = 0; + this.y1 = 0; + this.x2 = 0; + this.y2 = 0; + this.cpx1 = 0; + this.cpy1 = 0; + this.cpx2 = 0; + this.cpy2 = 0; + this.extent = 0; + } + + return SankeyPathShape; + }(); + + var SankeyPath = function (_super) { + __extends(SankeyPath, _super); + + function SankeyPath(opts) { + return _super.call(this, opts) || this; + } + + SankeyPath.prototype.getDefaultShape = function () { + return new SankeyPathShape(); + }; + + SankeyPath.prototype.buildPath = function (ctx, shape) { + var extent = shape.extent; + ctx.moveTo(shape.x1, shape.y1); + ctx.bezierCurveTo(shape.cpx1, shape.cpy1, shape.cpx2, shape.cpy2, shape.x2, shape.y2); + + if (shape.orient === 'vertical') { + ctx.lineTo(shape.x2 + extent, shape.y2); + ctx.bezierCurveTo(shape.cpx2 + extent, shape.cpy2, shape.cpx1 + extent, shape.cpy1, shape.x1 + extent, shape.y1); + } else { + ctx.lineTo(shape.x2, shape.y2 + extent); + ctx.bezierCurveTo(shape.cpx2, shape.cpy2 + extent, shape.cpx1, shape.cpy1 + extent, shape.x1, shape.y1 + extent); + } + + ctx.closePath(); + }; + + SankeyPath.prototype.highlight = function () { + enterEmphasis(this); + }; + + SankeyPath.prototype.downplay = function () { + leaveEmphasis(this); + }; + + return SankeyPath; + }(Path); + + var SankeyView = function (_super) { + __extends(SankeyView, _super); + + function SankeyView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SankeyView.type; + _this._focusAdjacencyDisabled = false; + return _this; + } + + SankeyView.prototype.render = function (seriesModel, ecModel, api) { + var sankeyView = this; + var graph = seriesModel.getGraph(); + var group = this.group; + var layoutInfo = seriesModel.layoutInfo; + var width = layoutInfo.width; + var height = layoutInfo.height; + var nodeData = seriesModel.getData(); + var edgeData = seriesModel.getData('edge'); + var orient = seriesModel.get('orient'); + this._model = seriesModel; + group.removeAll(); + group.x = layoutInfo.x; + group.y = layoutInfo.y; + graph.eachEdge(function (edge) { + var curve = new SankeyPath(); + var ecData = getECData(curve); + ecData.dataIndex = edge.dataIndex; + ecData.seriesIndex = seriesModel.seriesIndex; + ecData.dataType = 'edge'; + var edgeModel = edge.getModel(); + var lineStyleModel = edgeModel.getModel('lineStyle'); + var curvature = lineStyleModel.get('curveness'); + var n1Layout = edge.node1.getLayout(); + var node1Model = edge.node1.getModel(); + var dragX1 = node1Model.get('localX'); + var dragY1 = node1Model.get('localY'); + var n2Layout = edge.node2.getLayout(); + var node2Model = edge.node2.getModel(); + var dragX2 = node2Model.get('localX'); + var dragY2 = node2Model.get('localY'); + var edgeLayout = edge.getLayout(); + var x1; + var y1; + var x2; + var y2; + var cpx1; + var cpy1; + var cpx2; + var cpy2; + curve.shape.extent = Math.max(1, edgeLayout.dy); + curve.shape.orient = orient; + + if (orient === 'vertical') { + x1 = (dragX1 != null ? dragX1 * width : n1Layout.x) + edgeLayout.sy; + y1 = (dragY1 != null ? dragY1 * height : n1Layout.y) + n1Layout.dy; + x2 = (dragX2 != null ? dragX2 * width : n2Layout.x) + edgeLayout.ty; + y2 = dragY2 != null ? dragY2 * height : n2Layout.y; + cpx1 = x1; + cpy1 = y1 * (1 - curvature) + y2 * curvature; + cpx2 = x2; + cpy2 = y1 * curvature + y2 * (1 - curvature); + } else { + x1 = (dragX1 != null ? dragX1 * width : n1Layout.x) + n1Layout.dx; + y1 = (dragY1 != null ? dragY1 * height : n1Layout.y) + edgeLayout.sy; + x2 = dragX2 != null ? dragX2 * width : n2Layout.x; + y2 = (dragY2 != null ? dragY2 * height : n2Layout.y) + edgeLayout.ty; + cpx1 = x1 * (1 - curvature) + x2 * curvature; + cpy1 = y1; + cpx2 = x1 * curvature + x2 * (1 - curvature); + cpy2 = y2; + } + + curve.setShape({ + x1: x1, + y1: y1, + x2: x2, + y2: y2, + cpx1: cpx1, + cpy1: cpy1, + cpx2: cpx2, + cpy2: cpy2 + }); + curve.useStyle(lineStyleModel.getItemStyle()); + + switch (curve.style.fill) { + case 'source': + curve.style.fill = edge.node1.getVisual('color'); + curve.style.decal = edge.node1.getVisual('style').decal; + break; + + case 'target': + curve.style.fill = edge.node2.getVisual('color'); + curve.style.decal = edge.node2.getVisual('style').decal; + break; + + case 'gradient': + var sourceColor = edge.node1.getVisual('color'); + var targetColor = edge.node2.getVisual('color'); + + if (typeof sourceColor === 'string' && typeof targetColor === 'string') { + curve.style.fill = new LinearGradient(0, 0, 1, 0, [{ + color: sourceColor, + offset: 0 + }, { + color: targetColor, + offset: 1 + }]); + } + + } + + var emphasisModel = edgeModel.getModel('emphasis'); + setStatesStylesFromModel(curve, edgeModel, 'lineStyle', function (model) { + return model.getItemStyle(); + }); + group.add(curve); + edgeData.setItemGraphicEl(edge.dataIndex, curve); + var focus = emphasisModel.get('focus'); + enableHoverEmphasis(curve, focus === 'adjacency' ? edge.getAdjacentDataIndices() : focus, emphasisModel.get('blurScope')); + getECData(curve).dataType = 'edge'; + }); + graph.eachNode(function (node) { + var layout = node.getLayout(); + var itemModel = node.getModel(); + var dragX = itemModel.get('localX'); + var dragY = itemModel.get('localY'); + var emphasisModel = itemModel.getModel('emphasis'); + var rect = new Rect({ + shape: { + x: dragX != null ? dragX * width : layout.x, + y: dragY != null ? dragY * height : layout.y, + width: layout.dx, + height: layout.dy + }, + style: itemModel.getModel('itemStyle').getItemStyle() + }); + setLabelStyle(rect, getLabelStatesModels(itemModel), { + labelFetcher: seriesModel, + labelDataIndex: node.dataIndex, + defaultText: node.id + }); + rect.disableLabelAnimation = true; + rect.setStyle('fill', node.getVisual('color')); + rect.setStyle('decal', node.getVisual('style').decal); + setStatesStylesFromModel(rect, itemModel); + group.add(rect); + nodeData.setItemGraphicEl(node.dataIndex, rect); + getECData(rect).dataType = 'node'; + var focus = emphasisModel.get('focus'); + enableHoverEmphasis(rect, focus === 'adjacency' ? node.getAdjacentDataIndices() : focus, emphasisModel.get('blurScope')); + }); + nodeData.eachItemGraphicEl(function (el, dataIndex) { + var itemModel = nodeData.getItemModel(dataIndex); + + if (itemModel.get('draggable')) { + el.drift = function (dx, dy) { + sankeyView._focusAdjacencyDisabled = true; + this.shape.x += dx; + this.shape.y += dy; + this.dirty(); + api.dispatchAction({ + type: 'dragNode', + seriesId: seriesModel.id, + dataIndex: nodeData.getRawIndex(dataIndex), + localX: this.shape.x / width, + localY: this.shape.y / height + }); + }; + + el.ondragend = function () { + sankeyView._focusAdjacencyDisabled = false; + }; + + el.draggable = true; + el.cursor = 'move'; + } + }); + + if (!this._data && seriesModel.isAnimationEnabled()) { + group.setClipPath(createGridClipShape$1(group.getBoundingRect(), seriesModel, function () { + group.removeClipPath(); + })); + } + + this._data = seriesModel.getData(); + }; + + SankeyView.prototype.dispose = function () {}; + + SankeyView.type = 'sankey'; + return SankeyView; + }(ChartView); + + function createGridClipShape$1(rect, seriesModel, cb) { + var rectEl = new Rect({ + shape: { + x: rect.x - 10, + y: rect.y - 10, + width: 0, + height: rect.height + 20 + } + }); + initProps(rectEl, { + shape: { + width: rect.width + 20 + } + }, seriesModel, cb); + return rectEl; + } + + var SankeySeriesModel = function (_super) { + __extends(SankeySeriesModel, _super); + + function SankeySeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SankeySeriesModel.type; + return _this; + } + + SankeySeriesModel.prototype.getInitialData = function (option, ecModel) { + var links = option.edges || option.links; + var nodes = option.data || option.nodes; + var levels = option.levels; + this.levelModels = []; + var levelModels = this.levelModels; + + for (var i = 0; i < levels.length; i++) { + if (levels[i].depth != null && levels[i].depth >= 0) { + levelModels[levels[i].depth] = new Model(levels[i], this, ecModel); + } else { + if ("development" !== 'production') { + throw new Error('levels[i].depth is mandatory and should be natural number'); + } + } + } + + if (nodes && links) { + var graph = createGraphFromNodeEdge(nodes, links, this, true, beforeLink); + return graph.data; + } + + function beforeLink(nodeData, edgeData) { + nodeData.wrapMethod('getItemModel', function (model, idx) { + var seriesModel = model.parentModel; + var layout = seriesModel.getData().getItemLayout(idx); + + if (layout) { + var nodeDepth = layout.depth; + var levelModel = seriesModel.levelModels[nodeDepth]; + + if (levelModel) { + model.parentModel = levelModel; + } + } + + return model; + }); + edgeData.wrapMethod('getItemModel', function (model, idx) { + var seriesModel = model.parentModel; + var edge = seriesModel.getGraph().getEdgeByIndex(idx); + var layout = edge.node1.getLayout(); + + if (layout) { + var depth = layout.depth; + var levelModel = seriesModel.levelModels[depth]; + + if (levelModel) { + model.parentModel = levelModel; + } + } + + return model; + }); + } + }; + + SankeySeriesModel.prototype.setNodePosition = function (dataIndex, localPosition) { + var dataItem = this.option.data[dataIndex]; + dataItem.localX = localPosition[0]; + dataItem.localY = localPosition[1]; + }; + + SankeySeriesModel.prototype.getGraph = function () { + return this.getData().graph; + }; + + SankeySeriesModel.prototype.getEdgeData = function () { + return this.getGraph().edgeData; + }; + + SankeySeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + function noValue(val) { + return isNaN(val) || val == null; + } + + if (dataType === 'edge') { + var params = this.getDataParams(dataIndex, dataType); + var rawDataOpt = params.data; + var edgeValue = params.value; + var edgeName = rawDataOpt.source + ' -- ' + rawDataOpt.target; + return createTooltipMarkup('nameValue', { + name: edgeName, + value: edgeValue, + noValue: noValue(edgeValue) + }); + } else { + var node = this.getGraph().getNodeByIndex(dataIndex); + var value = node.getLayout().value; + var name_1 = this.getDataParams(dataIndex, dataType).data.name; + return createTooltipMarkup('nameValue', { + name: name_1 != null ? name_1 + '' : null, + value: value, + noValue: noValue(value) + }); + } + }; + + SankeySeriesModel.prototype.optionUpdated = function () { + var option = this.option; + + if (option.focusNodeAdjacency === true) { + option.focusNodeAdjacency = 'allEdges'; + } + }; + + SankeySeriesModel.prototype.getDataParams = function (dataIndex, dataType) { + var params = _super.prototype.getDataParams.call(this, dataIndex, dataType); + + if (params.value == null && dataType === 'node') { + var node = this.getGraph().getNodeByIndex(dataIndex); + var nodeValue = node.getLayout().value; + params.value = nodeValue; + } + + return params; + }; + + SankeySeriesModel.type = 'series.sankey'; + SankeySeriesModel.defaultOption = { + zlevel: 0, + z: 2, + coordinateSystem: 'view', + left: '5%', + top: '5%', + right: '20%', + bottom: '5%', + orient: 'horizontal', + nodeWidth: 20, + nodeGap: 8, + draggable: true, + focusNodeAdjacency: false, + layoutIterations: 32, + label: { + show: true, + position: 'right', + fontSize: 12 + }, + levels: [], + nodeAlign: 'justify', + lineStyle: { + color: '#314656', + opacity: 0.2, + curveness: 0.5 + }, + emphasis: { + label: { + show: true + }, + lineStyle: { + opacity: 0.5 + } + }, + select: { + itemStyle: { + borderColor: '#212121' + } + }, + animationEasing: 'linear', + animationDuration: 1000 + }; + return SankeySeriesModel; + }(SeriesModel); + + function sankeyLayout(ecModel, api) { + ecModel.eachSeriesByType('sankey', function (seriesModel) { + var nodeWidth = seriesModel.get('nodeWidth'); + var nodeGap = seriesModel.get('nodeGap'); + var layoutInfo = getViewRect$4(seriesModel, api); + seriesModel.layoutInfo = layoutInfo; + var width = layoutInfo.width; + var height = layoutInfo.height; + var graph = seriesModel.getGraph(); + var nodes = graph.nodes; + var edges = graph.edges; + computeNodeValues(nodes); + var filteredNodes = filter(nodes, function (node) { + return node.getLayout().value === 0; + }); + var iterations = filteredNodes.length !== 0 ? 0 : seriesModel.get('layoutIterations'); + var orient = seriesModel.get('orient'); + var nodeAlign = seriesModel.get('nodeAlign'); + layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient, nodeAlign); + }); + } + + function getViewRect$4(seriesModel, api) { + return getLayoutRect(seriesModel.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + } + + function layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient, nodeAlign) { + computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient, nodeAlign); + computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient); + computeEdgeDepths(nodes, orient); + } + + function computeNodeValues(nodes) { + each(nodes, function (node) { + var value1 = sum(node.outEdges, getEdgeValue); + var value2 = sum(node.inEdges, getEdgeValue); + var nodeRawValue = node.getValue() || 0; + var value = Math.max(value1, value2, nodeRawValue); + node.setLayout({ + value: value + }, true); + }); + } + + function computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient, nodeAlign) { + var remainEdges = []; + var indegreeArr = []; + var zeroIndegrees = []; + var nextTargetNode = []; + var x = 0; + + for (var i = 0; i < edges.length; i++) { + remainEdges[i] = 1; + } + + for (var i = 0; i < nodes.length; i++) { + indegreeArr[i] = nodes[i].inEdges.length; + + if (indegreeArr[i] === 0) { + zeroIndegrees.push(nodes[i]); + } + } + + var maxNodeDepth = -1; + + while (zeroIndegrees.length) { + for (var idx = 0; idx < zeroIndegrees.length; idx++) { + var node = zeroIndegrees[idx]; + var item = node.hostGraph.data.getRawDataItem(node.dataIndex); + var isItemDepth = item.depth != null && item.depth >= 0; + + if (isItemDepth && item.depth > maxNodeDepth) { + maxNodeDepth = item.depth; + } + + node.setLayout({ + depth: isItemDepth ? item.depth : x + }, true); + orient === 'vertical' ? node.setLayout({ + dy: nodeWidth + }, true) : node.setLayout({ + dx: nodeWidth + }, true); + + for (var edgeIdx = 0; edgeIdx < node.outEdges.length; edgeIdx++) { + var edge = node.outEdges[edgeIdx]; + var indexEdge = edges.indexOf(edge); + remainEdges[indexEdge] = 0; + var targetNode = edge.node2; + var nodeIndex = nodes.indexOf(targetNode); + + if (--indegreeArr[nodeIndex] === 0 && nextTargetNode.indexOf(targetNode) < 0) { + nextTargetNode.push(targetNode); + } + } + } + + ++x; + zeroIndegrees = nextTargetNode; + nextTargetNode = []; + } + + for (var i = 0; i < remainEdges.length; i++) { + if (remainEdges[i] === 1) { + throw new Error('Sankey is a DAG, the original data has cycle!'); + } + } + + var maxDepth = maxNodeDepth > x - 1 ? maxNodeDepth : x - 1; + + if (nodeAlign && nodeAlign !== 'left') { + adjustNodeWithNodeAlign(nodes, nodeAlign, orient, maxDepth); + } + + var kx = orient === 'vertical' ? (height - nodeWidth) / maxDepth : (width - nodeWidth) / maxDepth; + scaleNodeBreadths(nodes, kx, orient); + } + + function isNodeDepth(node) { + var item = node.hostGraph.data.getRawDataItem(node.dataIndex); + return item.depth != null && item.depth >= 0; + } + + function adjustNodeWithNodeAlign(nodes, nodeAlign, orient, maxDepth) { + if (nodeAlign === 'right') { + var nextSourceNode = []; + var remainNodes = nodes; + var nodeHeight = 0; + + while (remainNodes.length) { + for (var i = 0; i < remainNodes.length; i++) { + var node = remainNodes[i]; + node.setLayout({ + skNodeHeight: nodeHeight + }, true); + + for (var j = 0; j < node.inEdges.length; j++) { + var edge = node.inEdges[j]; + + if (nextSourceNode.indexOf(edge.node1) < 0) { + nextSourceNode.push(edge.node1); + } + } + } + + remainNodes = nextSourceNode; + nextSourceNode = []; + ++nodeHeight; + } + + each(nodes, function (node) { + if (!isNodeDepth(node)) { + node.setLayout({ + depth: Math.max(0, maxDepth - node.getLayout().skNodeHeight) + }, true); + } + }); + } else if (nodeAlign === 'justify') { + moveSinksRight(nodes, maxDepth); + } + } + + function moveSinksRight(nodes, maxDepth) { + each(nodes, function (node) { + if (!isNodeDepth(node) && !node.outEdges.length) { + node.setLayout({ + depth: maxDepth + }, true); + } + }); + } + + function scaleNodeBreadths(nodes, kx, orient) { + each(nodes, function (node) { + var nodeDepth = node.getLayout().depth * kx; + orient === 'vertical' ? node.setLayout({ + y: nodeDepth + }, true) : node.setLayout({ + x: nodeDepth + }, true); + }); + } + + function computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient) { + var nodesByBreadth = prepareNodesByBreadth(nodes, orient); + initializeNodeDepth(nodesByBreadth, edges, height, width, nodeGap, orient); + resolveCollisions(nodesByBreadth, nodeGap, height, width, orient); + + for (var alpha = 1; iterations > 0; iterations--) { + alpha *= 0.99; + relaxRightToLeft(nodesByBreadth, alpha, orient); + resolveCollisions(nodesByBreadth, nodeGap, height, width, orient); + relaxLeftToRight(nodesByBreadth, alpha, orient); + resolveCollisions(nodesByBreadth, nodeGap, height, width, orient); + } + } + + function prepareNodesByBreadth(nodes, orient) { + var nodesByBreadth = []; + var keyAttr = orient === 'vertical' ? 'y' : 'x'; + var groupResult = groupData(nodes, function (node) { + return node.getLayout()[keyAttr]; + }); + groupResult.keys.sort(function (a, b) { + return a - b; + }); + each(groupResult.keys, function (key) { + nodesByBreadth.push(groupResult.buckets.get(key)); + }); + return nodesByBreadth; + } + + function initializeNodeDepth(nodesByBreadth, edges, height, width, nodeGap, orient) { + var minKy = Infinity; + each(nodesByBreadth, function (nodes) { + var n = nodes.length; + var sum = 0; + each(nodes, function (node) { + sum += node.getLayout().value; + }); + var ky = orient === 'vertical' ? (width - (n - 1) * nodeGap) / sum : (height - (n - 1) * nodeGap) / sum; + + if (ky < minKy) { + minKy = ky; + } + }); + each(nodesByBreadth, function (nodes) { + each(nodes, function (node, i) { + var nodeDy = node.getLayout().value * minKy; + + if (orient === 'vertical') { + node.setLayout({ + x: i + }, true); + node.setLayout({ + dx: nodeDy + }, true); + } else { + node.setLayout({ + y: i + }, true); + node.setLayout({ + dy: nodeDy + }, true); + } + }); + }); + each(edges, function (edge) { + var edgeDy = +edge.getValue() * minKy; + edge.setLayout({ + dy: edgeDy + }, true); + }); + } + + function resolveCollisions(nodesByBreadth, nodeGap, height, width, orient) { + var keyAttr = orient === 'vertical' ? 'x' : 'y'; + each(nodesByBreadth, function (nodes) { + nodes.sort(function (a, b) { + return a.getLayout()[keyAttr] - b.getLayout()[keyAttr]; + }); + var nodeX; + var node; + var dy; + var y0 = 0; + var n = nodes.length; + var nodeDyAttr = orient === 'vertical' ? 'dx' : 'dy'; + + for (var i = 0; i < n; i++) { + node = nodes[i]; + dy = y0 - node.getLayout()[keyAttr]; + + if (dy > 0) { + nodeX = node.getLayout()[keyAttr] + dy; + orient === 'vertical' ? node.setLayout({ + x: nodeX + }, true) : node.setLayout({ + y: nodeX + }, true); + } + + y0 = node.getLayout()[keyAttr] + node.getLayout()[nodeDyAttr] + nodeGap; + } + + var viewWidth = orient === 'vertical' ? width : height; + dy = y0 - nodeGap - viewWidth; + + if (dy > 0) { + nodeX = node.getLayout()[keyAttr] - dy; + orient === 'vertical' ? node.setLayout({ + x: nodeX + }, true) : node.setLayout({ + y: nodeX + }, true); + y0 = nodeX; + + for (var i = n - 2; i >= 0; --i) { + node = nodes[i]; + dy = node.getLayout()[keyAttr] + node.getLayout()[nodeDyAttr] + nodeGap - y0; + + if (dy > 0) { + nodeX = node.getLayout()[keyAttr] - dy; + orient === 'vertical' ? node.setLayout({ + x: nodeX + }, true) : node.setLayout({ + y: nodeX + }, true); + } + + y0 = node.getLayout()[keyAttr]; + } + } + }); + } + + function relaxRightToLeft(nodesByBreadth, alpha, orient) { + each(nodesByBreadth.slice().reverse(), function (nodes) { + each(nodes, function (node) { + if (node.outEdges.length) { + var y = sum(node.outEdges, weightedTarget, orient) / sum(node.outEdges, getEdgeValue); + + if (isNaN(y)) { + var len = node.outEdges.length; + y = len ? sum(node.outEdges, centerTarget, orient) / len : 0; + } + + if (orient === 'vertical') { + var nodeX = node.getLayout().x + (y - center$1(node, orient)) * alpha; + node.setLayout({ + x: nodeX + }, true); + } else { + var nodeY = node.getLayout().y + (y - center$1(node, orient)) * alpha; + node.setLayout({ + y: nodeY + }, true); + } + } + }); + }); + } + + function weightedTarget(edge, orient) { + return center$1(edge.node2, orient) * edge.getValue(); + } + + function centerTarget(edge, orient) { + return center$1(edge.node2, orient); + } + + function weightedSource(edge, orient) { + return center$1(edge.node1, orient) * edge.getValue(); + } + + function centerSource(edge, orient) { + return center$1(edge.node1, orient); + } + + function center$1(node, orient) { + return orient === 'vertical' ? node.getLayout().x + node.getLayout().dx / 2 : node.getLayout().y + node.getLayout().dy / 2; + } + + function getEdgeValue(edge) { + return edge.getValue(); + } + + function sum(array, cb, orient) { + var sum = 0; + var len = array.length; + var i = -1; + + while (++i < len) { + var value = +cb(array[i], orient); + + if (!isNaN(value)) { + sum += value; + } + } + + return sum; + } + + function relaxLeftToRight(nodesByBreadth, alpha, orient) { + each(nodesByBreadth, function (nodes) { + each(nodes, function (node) { + if (node.inEdges.length) { + var y = sum(node.inEdges, weightedSource, orient) / sum(node.inEdges, getEdgeValue); + + if (isNaN(y)) { + var len = node.inEdges.length; + y = len ? sum(node.inEdges, centerSource, orient) / len : 0; + } + + if (orient === 'vertical') { + var nodeX = node.getLayout().x + (y - center$1(node, orient)) * alpha; + node.setLayout({ + x: nodeX + }, true); + } else { + var nodeY = node.getLayout().y + (y - center$1(node, orient)) * alpha; + node.setLayout({ + y: nodeY + }, true); + } + } + }); + }); + } + + function computeEdgeDepths(nodes, orient) { + var keyAttr = orient === 'vertical' ? 'x' : 'y'; + each(nodes, function (node) { + node.outEdges.sort(function (a, b) { + return a.node2.getLayout()[keyAttr] - b.node2.getLayout()[keyAttr]; + }); + node.inEdges.sort(function (a, b) { + return a.node1.getLayout()[keyAttr] - b.node1.getLayout()[keyAttr]; + }); + }); + each(nodes, function (node) { + var sy = 0; + var ty = 0; + each(node.outEdges, function (edge) { + edge.setLayout({ + sy: sy + }, true); + sy += edge.getLayout().dy; + }); + each(node.inEdges, function (edge) { + edge.setLayout({ + ty: ty + }, true); + ty += edge.getLayout().dy; + }); + }); + } + + function sankeyVisual(ecModel) { + ecModel.eachSeriesByType('sankey', function (seriesModel) { + var graph = seriesModel.getGraph(); + var nodes = graph.nodes; + + if (nodes.length) { + var minValue_1 = Infinity; + var maxValue_1 = -Infinity; + each(nodes, function (node) { + var nodeValue = node.getLayout().value; + + if (nodeValue < minValue_1) { + minValue_1 = nodeValue; + } + + if (nodeValue > maxValue_1) { + maxValue_1 = nodeValue; + } + }); + each(nodes, function (node) { + var mapping = new VisualMapping({ + type: 'color', + mappingMethod: 'linear', + dataExtent: [minValue_1, maxValue_1], + visual: seriesModel.get('color') + }); + var mapValueToColor = mapping.mapValueToVisual(node.getLayout().value); + var customColor = node.getModel().get(['itemStyle', 'color']); + + if (customColor != null) { + node.setVisual('color', customColor); + node.setVisual('style', { + fill: customColor + }); + } else { + node.setVisual('color', mapValueToColor); + node.setVisual('style', { + fill: mapValueToColor + }); + } + }); + } + }); + } + + function install$h(registers) { + registers.registerChartView(SankeyView); + registers.registerSeriesModel(SankeySeriesModel); + registers.registerLayout(sankeyLayout); + registers.registerVisual(sankeyVisual); + registers.registerAction({ + type: 'dragNode', + event: 'dragnode', + update: 'update' + }, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'series', + subType: 'sankey', + query: payload + }, function (seriesModel) { + seriesModel.setNodePosition(payload.dataIndex, [payload.localX, payload.localY]); + }); + }); + } + + var WhiskerBoxCommonMixin = function () { + function WhiskerBoxCommonMixin() {} + + WhiskerBoxCommonMixin.prototype.getInitialData = function (option, ecModel) { + var ordinalMeta; + var xAxisModel = ecModel.getComponent('xAxis', this.get('xAxisIndex')); + var yAxisModel = ecModel.getComponent('yAxis', this.get('yAxisIndex')); + var xAxisType = xAxisModel.get('type'); + var yAxisType = yAxisModel.get('type'); + var addOrdinal; + + if (xAxisType === 'category') { + option.layout = 'horizontal'; + ordinalMeta = xAxisModel.getOrdinalMeta(); + addOrdinal = true; + } else if (yAxisType === 'category') { + option.layout = 'vertical'; + ordinalMeta = yAxisModel.getOrdinalMeta(); + addOrdinal = true; + } else { + option.layout = option.layout || 'horizontal'; + } + + var coordDims = ['x', 'y']; + var baseAxisDimIndex = option.layout === 'horizontal' ? 0 : 1; + var baseAxisDim = this._baseAxisDim = coordDims[baseAxisDimIndex]; + var otherAxisDim = coordDims[1 - baseAxisDimIndex]; + var axisModels = [xAxisModel, yAxisModel]; + var baseAxisType = axisModels[baseAxisDimIndex].get('type'); + var otherAxisType = axisModels[1 - baseAxisDimIndex].get('type'); + var data = option.data; + + if (data && addOrdinal) { + var newOptionData_1 = []; + each(data, function (item, index) { + var newItem; + + if (isArray(item)) { + newItem = item.slice(); + item.unshift(index); + } else if (isArray(item.value)) { + newItem = item.value.slice(); + item.value.unshift(index); + } else { + newItem = item; + } + + newOptionData_1.push(newItem); + }); + option.data = newOptionData_1; + } + + var defaultValueDimensions = this.defaultValueDimensions; + var coordDimensions = [{ + name: baseAxisDim, + type: getDimensionTypeByAxis(baseAxisType), + ordinalMeta: ordinalMeta, + otherDims: { + tooltip: false, + itemName: 0 + }, + dimsDef: ['base'] + }, { + name: otherAxisDim, + type: getDimensionTypeByAxis(otherAxisType), + dimsDef: defaultValueDimensions.slice() + }]; + return createListSimply(this, { + coordDimensions: coordDimensions, + dimensionsCount: defaultValueDimensions.length + 1, + encodeDefaulter: curry(makeSeriesEncodeForAxisCoordSys, coordDimensions, this) + }); + }; + + WhiskerBoxCommonMixin.prototype.getBaseAxis = function () { + var dim = this._baseAxisDim; + return this.ecModel.getComponent(dim + 'Axis', this.get(dim + 'AxisIndex')).axis; + }; + + return WhiskerBoxCommonMixin; + }(); + + var BoxplotSeriesModel = function (_super) { + __extends(BoxplotSeriesModel, _super); + + function BoxplotSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = BoxplotSeriesModel.type; + _this.defaultValueDimensions = [{ + name: 'min', + defaultTooltip: true + }, { + name: 'Q1', + defaultTooltip: true + }, { + name: 'median', + defaultTooltip: true + }, { + name: 'Q3', + defaultTooltip: true + }, { + name: 'max', + defaultTooltip: true + }]; + _this.visualDrawType = 'stroke'; + return _this; + } + + BoxplotSeriesModel.type = 'series.boxplot'; + BoxplotSeriesModel.dependencies = ['xAxis', 'yAxis', 'grid']; + BoxplotSeriesModel.defaultOption = { + zlevel: 0, + z: 2, + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + layout: null, + boxWidth: [7, 50], + itemStyle: { + color: '#fff', + borderWidth: 1 + }, + emphasis: { + scale: true, + itemStyle: { + borderWidth: 2, + shadowBlur: 5, + shadowOffsetX: 1, + shadowOffsetY: 1, + shadowColor: 'rgba(0,0,0,0.2)' + } + }, + animationDuration: 800 + }; + return BoxplotSeriesModel; + }(SeriesModel); + + mixin(BoxplotSeriesModel, WhiskerBoxCommonMixin, true); + + var BoxplotView = function (_super) { + __extends(BoxplotView, _super); + + function BoxplotView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = BoxplotView.type; + return _this; + } + + BoxplotView.prototype.render = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var group = this.group; + var oldData = this._data; + + if (!this._data) { + group.removeAll(); + } + + var constDim = seriesModel.get('layout') === 'horizontal' ? 1 : 0; + data.diff(oldData).add(function (newIdx) { + if (data.hasValue(newIdx)) { + var itemLayout = data.getItemLayout(newIdx); + var symbolEl = createNormalBox(itemLayout, data, newIdx, constDim, true); + data.setItemGraphicEl(newIdx, symbolEl); + group.add(symbolEl); + } + }).update(function (newIdx, oldIdx) { + var symbolEl = oldData.getItemGraphicEl(oldIdx); + + if (!data.hasValue(newIdx)) { + group.remove(symbolEl); + return; + } + + var itemLayout = data.getItemLayout(newIdx); + + if (!symbolEl) { + symbolEl = createNormalBox(itemLayout, data, newIdx, constDim); + } else { + updateNormalBoxData(itemLayout, symbolEl, data, newIdx); + } + + group.add(symbolEl); + data.setItemGraphicEl(newIdx, symbolEl); + }).remove(function (oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + el && group.remove(el); + }).execute(); + this._data = data; + }; + + BoxplotView.prototype.remove = function (ecModel) { + var group = this.group; + var data = this._data; + this._data = null; + data && data.eachItemGraphicEl(function (el) { + el && group.remove(el); + }); + }; + + BoxplotView.type = 'boxplot'; + return BoxplotView; + }(ChartView); + + var BoxPathShape = function () { + function BoxPathShape() {} + + return BoxPathShape; + }(); + + var BoxPath = function (_super) { + __extends(BoxPath, _super); + + function BoxPath(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'boxplotBoxPath'; + return _this; + } + + BoxPath.prototype.getDefaultShape = function () { + return new BoxPathShape(); + }; + + BoxPath.prototype.buildPath = function (ctx, shape) { + var ends = shape.points; + var i = 0; + ctx.moveTo(ends[i][0], ends[i][1]); + i++; + + for (; i < 4; i++) { + ctx.lineTo(ends[i][0], ends[i][1]); + } + + ctx.closePath(); + + for (; i < ends.length; i++) { + ctx.moveTo(ends[i][0], ends[i][1]); + i++; + ctx.lineTo(ends[i][0], ends[i][1]); + } + }; + + return BoxPath; + }(Path); + + function createNormalBox(itemLayout, data, dataIndex, constDim, isInit) { + var ends = itemLayout.ends; + var el = new BoxPath({ + shape: { + points: isInit ? transInit(ends, constDim, itemLayout) : ends + } + }); + updateNormalBoxData(itemLayout, el, data, dataIndex, isInit); + return el; + } + + function updateNormalBoxData(itemLayout, el, data, dataIndex, isInit) { + var seriesModel = data.hostModel; + var updateMethod = graphic[isInit ? 'initProps' : 'updateProps']; + updateMethod(el, { + shape: { + points: itemLayout.ends + } + }, seriesModel, dataIndex); + el.useStyle(data.getItemVisual(dataIndex, 'style')); + el.style.strokeNoScale = true; + el.z2 = 100; + var itemModel = data.getItemModel(dataIndex); + setStatesStylesFromModel(el, itemModel); + enableHoverEmphasis(el, itemModel.get(['emphasis', 'focus']), itemModel.get(['emphasis', 'blurScope'])); + } + + function transInit(points, dim, itemLayout) { + return map(points, function (point) { + point = point.slice(); + point[dim] = itemLayout.initBaseline; + return point; + }); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function boxplotVisual(ecModel, api) { + ecModel.eachRawSeriesByType('boxplot', function (seriesModel) { + seriesModel.getData().setVisual('legendSymbol', 'roundRect'); + }); + } + + var each$7 = each; + function boxplotLayout(ecModel) { + var groupResult = groupSeriesByAxis(ecModel); + each$7(groupResult, function (groupItem) { + var seriesModels = groupItem.seriesModels; + + if (!seriesModels.length) { + return; + } + + calculateBase(groupItem); + each$7(seriesModels, function (seriesModel, idx) { + layoutSingleSeries(seriesModel, groupItem.boxOffsetList[idx], groupItem.boxWidthList[idx]); + }); + }); + } + + function groupSeriesByAxis(ecModel) { + var result = []; + var axisList = []; + ecModel.eachSeriesByType('boxplot', function (seriesModel) { + var baseAxis = seriesModel.getBaseAxis(); + var idx = indexOf(axisList, baseAxis); + + if (idx < 0) { + idx = axisList.length; + axisList[idx] = baseAxis; + result[idx] = { + axis: baseAxis, + seriesModels: [] + }; + } + + result[idx].seriesModels.push(seriesModel); + }); + return result; + } + + function calculateBase(groupItem) { + var extent; + var baseAxis = groupItem.axis; + var seriesModels = groupItem.seriesModels; + var seriesCount = seriesModels.length; + var boxWidthList = groupItem.boxWidthList = []; + var boxOffsetList = groupItem.boxOffsetList = []; + var boundList = []; + var bandWidth; + + if (baseAxis.type === 'category') { + bandWidth = baseAxis.getBandWidth(); + } else { + var maxDataCount_1 = 0; + each$7(seriesModels, function (seriesModel) { + maxDataCount_1 = Math.max(maxDataCount_1, seriesModel.getData().count()); + }); + extent = baseAxis.getExtent(), Math.abs(extent[1] - extent[0]) / maxDataCount_1; + } + + each$7(seriesModels, function (seriesModel) { + var boxWidthBound = seriesModel.get('boxWidth'); + + if (!isArray(boxWidthBound)) { + boxWidthBound = [boxWidthBound, boxWidthBound]; + } + + boundList.push([parsePercent$1(boxWidthBound[0], bandWidth) || 0, parsePercent$1(boxWidthBound[1], bandWidth) || 0]); + }); + var availableWidth = bandWidth * 0.8 - 2; + var boxGap = availableWidth / seriesCount * 0.3; + var boxWidth = (availableWidth - boxGap * (seriesCount - 1)) / seriesCount; + var base = boxWidth / 2 - availableWidth / 2; + each$7(seriesModels, function (seriesModel, idx) { + boxOffsetList.push(base); + base += boxGap + boxWidth; + boxWidthList.push(Math.min(Math.max(boxWidth, boundList[idx][0]), boundList[idx][1])); + }); + } + + function layoutSingleSeries(seriesModel, offset, boxWidth) { + var coordSys = seriesModel.coordinateSystem; + var data = seriesModel.getData(); + var halfWidth = boxWidth / 2; + var cDimIdx = seriesModel.get('layout') === 'horizontal' ? 0 : 1; + var vDimIdx = 1 - cDimIdx; + var coordDims = ['x', 'y']; + var cDim = data.mapDimension(coordDims[cDimIdx]); + var vDims = data.mapDimensionsAll(coordDims[vDimIdx]); + + if (cDim == null || vDims.length < 5) { + return; + } + + for (var dataIndex = 0; dataIndex < data.count(); dataIndex++) { + var axisDimVal = data.get(cDim, dataIndex); + var median = getPoint(axisDimVal, vDims[2], dataIndex); + var end1 = getPoint(axisDimVal, vDims[0], dataIndex); + var end2 = getPoint(axisDimVal, vDims[1], dataIndex); + var end4 = getPoint(axisDimVal, vDims[3], dataIndex); + var end5 = getPoint(axisDimVal, vDims[4], dataIndex); + var ends = []; + addBodyEnd(ends, end2, false); + addBodyEnd(ends, end4, true); + ends.push(end1, end2, end5, end4); + layEndLine(ends, end1); + layEndLine(ends, end5); + layEndLine(ends, median); + data.setItemLayout(dataIndex, { + initBaseline: median[vDimIdx], + ends: ends + }); + } + + function getPoint(axisDimVal, dim, dataIndex) { + var val = data.get(dim, dataIndex); + var p = []; + p[cDimIdx] = axisDimVal; + p[vDimIdx] = val; + var point; + + if (isNaN(axisDimVal) || isNaN(val)) { + point = [NaN, NaN]; + } else { + point = coordSys.dataToPoint(p); + point[cDimIdx] += offset; + } + + return point; + } + + function addBodyEnd(ends, point, start) { + var point1 = point.slice(); + var point2 = point.slice(); + point1[cDimIdx] += halfWidth; + point2[cDimIdx] -= halfWidth; + start ? ends.push(point1, point2) : ends.push(point2, point1); + } + + function layEndLine(ends, endCenter) { + var from = endCenter.slice(); + var to = endCenter.slice(); + from[cDimIdx] -= halfWidth; + to[cDimIdx] += halfWidth; + ends.push(from, to); + } + } + + function prepareBoxplotData(rawData, opt) { + opt = opt || {}; + var boxData = []; + var outliers = []; + var boundIQR = opt.boundIQR; + var useExtreme = boundIQR === 'none' || boundIQR === 0; + + for (var i = 0; i < rawData.length; i++) { + var ascList = asc(rawData[i].slice()); + var Q1 = quantile(ascList, 0.25); + var Q2 = quantile(ascList, 0.5); + var Q3 = quantile(ascList, 0.75); + var min = ascList[0]; + var max = ascList[ascList.length - 1]; + var bound = (boundIQR == null ? 1.5 : boundIQR) * (Q3 - Q1); + var low = useExtreme ? min : Math.max(min, Q1 - bound); + var high = useExtreme ? max : Math.min(max, Q3 + bound); + var itemNameFormatter = opt.itemNameFormatter; + var itemName = isFunction(itemNameFormatter) ? itemNameFormatter({ + value: i + }) : isString(itemNameFormatter) ? itemNameFormatter.replace('{value}', i + '') : i + ''; + boxData.push([itemName, low, Q1, Q2, Q3, high]); + + for (var j = 0; j < ascList.length; j++) { + var dataItem = ascList[j]; + + if (dataItem < low || dataItem > high) { + var outlier = [itemName, dataItem]; + outliers.push(outlier); + } + } + } + + return { + boxData: boxData, + outliers: outliers + }; + } + + var boxplotTransform = { + type: 'echarts:boxplot', + transform: function transform(params) { + var upstream = params.upstream; + + if (upstream.sourceFormat !== SOURCE_FORMAT_ARRAY_ROWS) { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = makePrintable('source data is not applicable for this boxplot transform. Expect number[][].'); + } + + throwError(errMsg); + } + + var result = prepareBoxplotData(upstream.getRawData(), params.config); + return [{ + dimensions: ['ItemName', 'Low', 'Q1', 'Q2', 'Q3', 'High'], + data: result.boxData + }, { + data: result.outliers + }]; + } + }; + + function install$i(registers) { + registers.registerSeriesModel(BoxplotSeriesModel); + registers.registerChartView(BoxplotView); + registers.registerVisual(boxplotVisual); + registers.registerLayout(boxplotLayout); + registers.registerTransform(boxplotTransform); + } + + var SKIP_PROPS = ['color', 'borderColor']; + + var CandlestickView = function (_super) { + __extends(CandlestickView, _super); + + function CandlestickView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CandlestickView.type; + return _this; + } + + CandlestickView.prototype.render = function (seriesModel, ecModel, api) { + this.group.removeClipPath(); + + this._updateDrawMode(seriesModel); + + this._isLargeDraw ? this._renderLarge(seriesModel) : this._renderNormal(seriesModel); + }; + + CandlestickView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) { + this._clear(); + + this._updateDrawMode(seriesModel); + }; + + CandlestickView.prototype.incrementalRender = function (params, seriesModel, ecModel, api) { + this._isLargeDraw ? this._incrementalRenderLarge(params, seriesModel) : this._incrementalRenderNormal(params, seriesModel); + }; + + CandlestickView.prototype._updateDrawMode = function (seriesModel) { + var isLargeDraw = seriesModel.pipelineContext.large; + + if (this._isLargeDraw == null || isLargeDraw !== this._isLargeDraw) { + this._isLargeDraw = isLargeDraw; + + this._clear(); + } + }; + + CandlestickView.prototype._renderNormal = function (seriesModel) { + var data = seriesModel.getData(); + var oldData = this._data; + var group = this.group; + var isSimpleBox = data.getLayout('isSimpleBox'); + var needsClip = seriesModel.get('clip', true); + var coord = seriesModel.coordinateSystem; + var clipArea = coord.getArea && coord.getArea(); + + if (!this._data) { + group.removeAll(); + } + + data.diff(oldData).add(function (newIdx) { + if (data.hasValue(newIdx)) { + var itemLayout = data.getItemLayout(newIdx); + + if (needsClip && isNormalBoxClipped(clipArea, itemLayout)) { + return; + } + + var el = createNormalBox$1(itemLayout, newIdx, true); + initProps(el, { + shape: { + points: itemLayout.ends + } + }, seriesModel, newIdx); + setBoxCommon(el, data, newIdx, isSimpleBox); + group.add(el); + data.setItemGraphicEl(newIdx, el); + } + }).update(function (newIdx, oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + + if (!data.hasValue(newIdx)) { + group.remove(el); + return; + } + + var itemLayout = data.getItemLayout(newIdx); + + if (needsClip && isNormalBoxClipped(clipArea, itemLayout)) { + group.remove(el); + return; + } + + if (!el) { + el = createNormalBox$1(itemLayout); + } else { + updateProps(el, { + shape: { + points: itemLayout.ends + } + }, seriesModel, newIdx); + } + + setBoxCommon(el, data, newIdx, isSimpleBox); + group.add(el); + data.setItemGraphicEl(newIdx, el); + }).remove(function (oldIdx) { + var el = oldData.getItemGraphicEl(oldIdx); + el && group.remove(el); + }).execute(); + this._data = data; + }; + + CandlestickView.prototype._renderLarge = function (seriesModel) { + this._clear(); + + createLarge$1(seriesModel, this.group); + var clipPath = seriesModel.get('clip', true) ? createClipPath(seriesModel.coordinateSystem, false, seriesModel) : null; + + if (clipPath) { + this.group.setClipPath(clipPath); + } else { + this.group.removeClipPath(); + } + }; + + CandlestickView.prototype._incrementalRenderNormal = function (params, seriesModel) { + var data = seriesModel.getData(); + var isSimpleBox = data.getLayout('isSimpleBox'); + var dataIndex; + + while ((dataIndex = params.next()) != null) { + var itemLayout = data.getItemLayout(dataIndex); + var el = createNormalBox$1(itemLayout); + setBoxCommon(el, data, dataIndex, isSimpleBox); + el.incremental = true; + this.group.add(el); + } + }; + + CandlestickView.prototype._incrementalRenderLarge = function (params, seriesModel) { + createLarge$1(seriesModel, this.group, true); + }; + + CandlestickView.prototype.remove = function (ecModel) { + this._clear(); + }; + + CandlestickView.prototype._clear = function () { + this.group.removeAll(); + this._data = null; + }; + + CandlestickView.type = 'candlestick'; + return CandlestickView; + }(ChartView); + + var NormalBoxPathShape = function () { + function NormalBoxPathShape() {} + + return NormalBoxPathShape; + }(); + + var NormalBoxPath = function (_super) { + __extends(NormalBoxPath, _super); + + function NormalBoxPath(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'normalCandlestickBox'; + return _this; + } + + NormalBoxPath.prototype.getDefaultShape = function () { + return new NormalBoxPathShape(); + }; + + NormalBoxPath.prototype.buildPath = function (ctx, shape) { + var ends = shape.points; + + if (this.__simpleBox) { + ctx.moveTo(ends[4][0], ends[4][1]); + ctx.lineTo(ends[6][0], ends[6][1]); + } else { + ctx.moveTo(ends[0][0], ends[0][1]); + ctx.lineTo(ends[1][0], ends[1][1]); + ctx.lineTo(ends[2][0], ends[2][1]); + ctx.lineTo(ends[3][0], ends[3][1]); + ctx.closePath(); + ctx.moveTo(ends[4][0], ends[4][1]); + ctx.lineTo(ends[5][0], ends[5][1]); + ctx.moveTo(ends[6][0], ends[6][1]); + ctx.lineTo(ends[7][0], ends[7][1]); + } + }; + + return NormalBoxPath; + }(Path); + + function createNormalBox$1(itemLayout, dataIndex, isInit) { + var ends = itemLayout.ends; + return new NormalBoxPath({ + shape: { + points: isInit ? transInit$1(ends, itemLayout) : ends + }, + z2: 100 + }); + } + + function isNormalBoxClipped(clipArea, itemLayout) { + var clipped = true; + + for (var i = 0; i < itemLayout.ends.length; i++) { + if (clipArea.contain(itemLayout.ends[i][0], itemLayout.ends[i][1])) { + clipped = false; + break; + } + } + + return clipped; + } + + function setBoxCommon(el, data, dataIndex, isSimpleBox) { + var itemModel = data.getItemModel(dataIndex); + el.useStyle(data.getItemVisual(dataIndex, 'style')); + el.style.strokeNoScale = true; + el.__simpleBox = isSimpleBox; + setStatesStylesFromModel(el, itemModel); + } + + function transInit$1(points, itemLayout) { + return map(points, function (point) { + point = point.slice(); + point[1] = itemLayout.initBaseline; + return point; + }); + } + + var LargeBoxPathShape = function () { + function LargeBoxPathShape() {} + + return LargeBoxPathShape; + }(); + + var LargeBoxPath = function (_super) { + __extends(LargeBoxPath, _super); + + function LargeBoxPath(opts) { + var _this = _super.call(this, opts) || this; + + _this.type = 'largeCandlestickBox'; + return _this; + } + + LargeBoxPath.prototype.getDefaultShape = function () { + return new LargeBoxPathShape(); + }; + + LargeBoxPath.prototype.buildPath = function (ctx, shape) { + var points = shape.points; + + for (var i = 0; i < points.length;) { + if (this.__sign === points[i++]) { + var x = points[i++]; + ctx.moveTo(x, points[i++]); + ctx.lineTo(x, points[i++]); + } else { + i += 3; + } + } + }; + + return LargeBoxPath; + }(Path); + + function createLarge$1(seriesModel, group, incremental) { + var data = seriesModel.getData(); + var largePoints = data.getLayout('largePoints'); + var elP = new LargeBoxPath({ + shape: { + points: largePoints + }, + __sign: 1 + }); + group.add(elP); + var elN = new LargeBoxPath({ + shape: { + points: largePoints + }, + __sign: -1 + }); + group.add(elN); + setLargeStyle$1(1, elP, seriesModel); + setLargeStyle$1(-1, elN, seriesModel); + + if (incremental) { + elP.incremental = true; + elN.incremental = true; + } + } + + function setLargeStyle$1(sign, el, seriesModel, data) { + var borderColor = seriesModel.get(['itemStyle', sign > 0 ? 'borderColor' : 'borderColor0']) || seriesModel.get(['itemStyle', sign > 0 ? 'color' : 'color0']); + var itemStyle = seriesModel.getModel('itemStyle').getItemStyle(SKIP_PROPS); + el.useStyle(itemStyle); + el.style.fill = null; + el.style.stroke = borderColor; + } + + var CandlestickSeriesModel = function (_super) { + __extends(CandlestickSeriesModel, _super); + + function CandlestickSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CandlestickSeriesModel.type; + _this.defaultValueDimensions = [{ + name: 'open', + defaultTooltip: true + }, { + name: 'close', + defaultTooltip: true + }, { + name: 'lowest', + defaultTooltip: true + }, { + name: 'highest', + defaultTooltip: true + }]; + return _this; + } + + CandlestickSeriesModel.prototype.getShadowDim = function () { + return 'open'; + }; + + CandlestickSeriesModel.prototype.brushSelector = function (dataIndex, data, selectors) { + var itemLayout = data.getItemLayout(dataIndex); + return itemLayout && selectors.rect(itemLayout.brushRect); + }; + + CandlestickSeriesModel.type = 'series.candlestick'; + CandlestickSeriesModel.dependencies = ['xAxis', 'yAxis', 'grid']; + CandlestickSeriesModel.defaultOption = { + zlevel: 0, + z: 2, + coordinateSystem: 'cartesian2d', + legendHoverLink: true, + layout: null, + clip: true, + itemStyle: { + color: '#eb5454', + color0: '#47b262', + borderColor: '#eb5454', + borderColor0: '#47b262', + borderWidth: 1 + }, + emphasis: { + scale: true, + itemStyle: { + borderWidth: 2 + } + }, + barMaxWidth: null, + barMinWidth: null, + barWidth: null, + large: true, + largeThreshold: 600, + progressive: 3e3, + progressiveThreshold: 1e4, + progressiveChunkMode: 'mod', + animationEasing: 'linear', + animationDuration: 300 + }; + return CandlestickSeriesModel; + }(SeriesModel); + + mixin(CandlestickSeriesModel, WhiskerBoxCommonMixin, true); + + function candlestickPreprocessor(option) { + if (!option || !isArray(option.series)) { + return; + } + + each(option.series, function (seriesItem) { + if (isObject(seriesItem) && seriesItem.type === 'k') { + seriesItem.type = 'candlestick'; + } + }); + } + + var positiveBorderColorQuery = ['itemStyle', 'borderColor']; + var negativeBorderColorQuery = ['itemStyle', 'borderColor0']; + var positiveColorQuery = ['itemStyle', 'color']; + var negativeColorQuery = ['itemStyle', 'color0']; + var candlestickVisual = { + seriesType: 'candlestick', + plan: createRenderPlanner(), + performRawSeries: true, + reset: function (seriesModel, ecModel) { + function getColor(sign, model) { + return model.get(sign > 0 ? positiveColorQuery : negativeColorQuery); + } + + function getBorderColor(sign, model) { + return model.get(sign > 0 ? positiveBorderColorQuery : negativeBorderColorQuery); + } + + var data = seriesModel.getData(); + data.setVisual('legendSymbol', 'roundRect'); + + if (ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + var isLargeRender = seriesModel.pipelineContext.large; + return !isLargeRender && { + progress: function (params, data) { + var dataIndex; + + while ((dataIndex = params.next()) != null) { + var itemModel = data.getItemModel(dataIndex); + var sign = data.getItemLayout(dataIndex).sign; + var style = itemModel.getItemStyle(); + style.fill = getColor(sign, itemModel); + style.stroke = getBorderColor(sign, itemModel) || style.fill; + var existsStyle = data.ensureUniqueItemVisual(dataIndex, 'style'); + extend(existsStyle, style); + } + } + }; + } + }; + + var LargeArr$1 = typeof Float32Array !== 'undefined' ? Float32Array : Array; + var candlestickLayout = { + seriesType: 'candlestick', + plan: createRenderPlanner(), + reset: function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var data = seriesModel.getData(); + var candleWidth = calculateCandleWidth(seriesModel, data); + var cDimIdx = 0; + var vDimIdx = 1; + var coordDims = ['x', 'y']; + var cDim = data.mapDimension(coordDims[cDimIdx]); + var vDims = data.mapDimensionsAll(coordDims[vDimIdx]); + var openDim = vDims[0]; + var closeDim = vDims[1]; + var lowestDim = vDims[2]; + var highestDim = vDims[3]; + data.setLayout({ + candleWidth: candleWidth, + isSimpleBox: candleWidth <= 1.3 + }); + + if (cDim == null || vDims.length < 4) { + return; + } + + return { + progress: seriesModel.pipelineContext.large ? largeProgress : normalProgress + }; + + function normalProgress(params, data) { + var dataIndex; + + while ((dataIndex = params.next()) != null) { + var axisDimVal = data.get(cDim, dataIndex); + var openVal = data.get(openDim, dataIndex); + var closeVal = data.get(closeDim, dataIndex); + var lowestVal = data.get(lowestDim, dataIndex); + var highestVal = data.get(highestDim, dataIndex); + var ocLow = Math.min(openVal, closeVal); + var ocHigh = Math.max(openVal, closeVal); + var ocLowPoint = getPoint(ocLow, axisDimVal); + var ocHighPoint = getPoint(ocHigh, axisDimVal); + var lowestPoint = getPoint(lowestVal, axisDimVal); + var highestPoint = getPoint(highestVal, axisDimVal); + var ends = []; + addBodyEnd(ends, ocHighPoint, 0); + addBodyEnd(ends, ocLowPoint, 1); + ends.push(subPixelOptimizePoint(highestPoint), subPixelOptimizePoint(ocHighPoint), subPixelOptimizePoint(lowestPoint), subPixelOptimizePoint(ocLowPoint)); + data.setItemLayout(dataIndex, { + sign: getSign(data, dataIndex, openVal, closeVal, closeDim), + initBaseline: openVal > closeVal ? ocHighPoint[vDimIdx] : ocLowPoint[vDimIdx], + ends: ends, + brushRect: makeBrushRect(lowestVal, highestVal, axisDimVal) + }); + } + + function getPoint(val, axisDimVal) { + var p = []; + p[cDimIdx] = axisDimVal; + p[vDimIdx] = val; + return isNaN(axisDimVal) || isNaN(val) ? [NaN, NaN] : coordSys.dataToPoint(p); + } + + function addBodyEnd(ends, point, start) { + var point1 = point.slice(); + var point2 = point.slice(); + point1[cDimIdx] = subPixelOptimize$1(point1[cDimIdx] + candleWidth / 2, 1, false); + point2[cDimIdx] = subPixelOptimize$1(point2[cDimIdx] - candleWidth / 2, 1, true); + start ? ends.push(point1, point2) : ends.push(point2, point1); + } + + function makeBrushRect(lowestVal, highestVal, axisDimVal) { + var pmin = getPoint(lowestVal, axisDimVal); + var pmax = getPoint(highestVal, axisDimVal); + pmin[cDimIdx] -= candleWidth / 2; + pmax[cDimIdx] -= candleWidth / 2; + return { + x: pmin[0], + y: pmin[1], + width: candleWidth , + height: pmax[1] - pmin[1] + }; + } + + function subPixelOptimizePoint(point) { + point[cDimIdx] = subPixelOptimize$1(point[cDimIdx], 1); + return point; + } + } + + function largeProgress(params, data) { + var points = new LargeArr$1(params.count * 4); + var offset = 0; + var point; + var tmpIn = []; + var tmpOut = []; + var dataIndex; + + while ((dataIndex = params.next()) != null) { + var axisDimVal = data.get(cDim, dataIndex); + var openVal = data.get(openDim, dataIndex); + var closeVal = data.get(closeDim, dataIndex); + var lowestVal = data.get(lowestDim, dataIndex); + var highestVal = data.get(highestDim, dataIndex); + + if (isNaN(axisDimVal) || isNaN(lowestVal) || isNaN(highestVal)) { + points[offset++] = NaN; + offset += 3; + continue; + } + + points[offset++] = getSign(data, dataIndex, openVal, closeVal, closeDim); + tmpIn[cDimIdx] = axisDimVal; + tmpIn[vDimIdx] = lowestVal; + point = coordSys.dataToPoint(tmpIn, null, tmpOut); + points[offset++] = point ? point[0] : NaN; + points[offset++] = point ? point[1] : NaN; + tmpIn[vDimIdx] = highestVal; + point = coordSys.dataToPoint(tmpIn, null, tmpOut); + points[offset++] = point ? point[1] : NaN; + } + + data.setLayout('largePoints', points); + } + } + }; + + function getSign(data, dataIndex, openVal, closeVal, closeDim) { + var sign; + + if (openVal > closeVal) { + sign = -1; + } else if (openVal < closeVal) { + sign = 1; + } else { + sign = dataIndex > 0 ? data.get(closeDim, dataIndex - 1) <= closeVal ? 1 : -1 : 1; + } + + return sign; + } + + function calculateCandleWidth(seriesModel, data) { + var baseAxis = seriesModel.getBaseAxis(); + var extent; + var bandWidth = baseAxis.type === 'category' ? baseAxis.getBandWidth() : (extent = baseAxis.getExtent(), Math.abs(extent[1] - extent[0]) / data.count()); + var barMaxWidth = parsePercent$1(retrieve2(seriesModel.get('barMaxWidth'), bandWidth), bandWidth); + var barMinWidth = parsePercent$1(retrieve2(seriesModel.get('barMinWidth'), 1), bandWidth); + var barWidth = seriesModel.get('barWidth'); + return barWidth != null ? parsePercent$1(barWidth, bandWidth) : Math.max(Math.min(bandWidth / 2, barMaxWidth), barMinWidth); + } + + function install$j(registers) { + registers.registerChartView(CandlestickView); + registers.registerSeriesModel(CandlestickSeriesModel); + registers.registerPreprocessor(candlestickPreprocessor); + registers.registerVisual(candlestickVisual); + registers.registerLayout(candlestickLayout); + } + + var EFFECT_RIPPLE_NUMBER = 3; + + function normalizeSymbolSize$1(symbolSize) { + if (!isArray(symbolSize)) { + symbolSize = [+symbolSize, +symbolSize]; + } + + return symbolSize; + } + + function updateRipplePath(rippleGroup, effectCfg) { + var color = effectCfg.rippleEffectColor || effectCfg.color; + rippleGroup.eachChild(function (ripplePath) { + ripplePath.attr({ + z: effectCfg.z, + zlevel: effectCfg.zlevel, + style: { + stroke: effectCfg.brushType === 'stroke' ? color : null, + fill: effectCfg.brushType === 'fill' ? color : null + } + }); + }); + } + + var EffectSymbol = function (_super) { + __extends(EffectSymbol, _super); + + function EffectSymbol(data, idx) { + var _this = _super.call(this) || this; + + var symbol = new Symbol(data, idx); + var rippleGroup = new Group(); + + _this.add(symbol); + + _this.add(rippleGroup); + + _this.updateData(data, idx); + + return _this; + } + + EffectSymbol.prototype.stopEffectAnimation = function () { + this.childAt(1).removeAll(); + }; + + EffectSymbol.prototype.startEffectAnimation = function (effectCfg) { + var symbolType = effectCfg.symbolType; + var color = effectCfg.color; + var rippleGroup = this.childAt(1); + + for (var i = 0; i < EFFECT_RIPPLE_NUMBER; i++) { + var ripplePath = createSymbol(symbolType, -1, -1, 2, 2, color); + ripplePath.attr({ + style: { + strokeNoScale: true + }, + z2: 99, + silent: true, + scaleX: 0.5, + scaleY: 0.5 + }); + var delay = -i / EFFECT_RIPPLE_NUMBER * effectCfg.period + effectCfg.effectOffset; + ripplePath.animate('', true).when(effectCfg.period, { + scale: [effectCfg.rippleScale / 2, effectCfg.rippleScale / 2] + }).delay(delay).start(); + ripplePath.animateStyle(true).when(effectCfg.period, { + opacity: 0 + }).delay(delay).start(); + rippleGroup.add(ripplePath); + } + + updateRipplePath(rippleGroup, effectCfg); + }; + + EffectSymbol.prototype.updateEffectAnimation = function (effectCfg) { + var oldEffectCfg = this._effectCfg; + var rippleGroup = this.childAt(1); + var DIFFICULT_PROPS = ['symbolType', 'period', 'rippleScale']; + + for (var i = 0; i < DIFFICULT_PROPS.length; i++) { + var propName = DIFFICULT_PROPS[i]; + + if (oldEffectCfg[propName] !== effectCfg[propName]) { + this.stopEffectAnimation(); + this.startEffectAnimation(effectCfg); + return; + } + } + + updateRipplePath(rippleGroup, effectCfg); + }; + + EffectSymbol.prototype.highlight = function () { + enterEmphasis(this); + }; + + EffectSymbol.prototype.downplay = function () { + leaveEmphasis(this); + }; + + EffectSymbol.prototype.updateData = function (data, idx) { + var _this = this; + + var seriesModel = data.hostModel; + this.childAt(0).updateData(data, idx); + var rippleGroup = this.childAt(1); + var itemModel = data.getItemModel(idx); + var symbolType = data.getItemVisual(idx, 'symbol'); + var symbolSize = normalizeSymbolSize$1(data.getItemVisual(idx, 'symbolSize')); + var symbolStyle = data.getItemVisual(idx, 'style'); + var color = symbolStyle && symbolStyle.fill; + rippleGroup.setScale(symbolSize); + rippleGroup.traverse(function (ripplePath) { + ripplePath.setStyle('fill', color); + }); + var symbolOffset = itemModel.getShallow('symbolOffset'); + + if (symbolOffset) { + rippleGroup.x = parsePercent$1(symbolOffset[0], symbolSize[0]); + rippleGroup.y = parsePercent$1(symbolOffset[1], symbolSize[1]); + } + + var symbolRotate = data.getItemVisual(idx, 'symbolRotate'); + rippleGroup.rotation = (symbolRotate || 0) * Math.PI / 180 || 0; + var effectCfg = {}; + effectCfg.showEffectOn = seriesModel.get('showEffectOn'); + effectCfg.rippleScale = itemModel.get(['rippleEffect', 'scale']); + effectCfg.brushType = itemModel.get(['rippleEffect', 'brushType']); + effectCfg.period = itemModel.get(['rippleEffect', 'period']) * 1000; + effectCfg.effectOffset = idx / data.count(); + effectCfg.z = seriesModel.getShallow('z') || 0; + effectCfg.zlevel = seriesModel.getShallow('zlevel') || 0; + effectCfg.symbolType = symbolType; + effectCfg.color = color; + effectCfg.rippleEffectColor = itemModel.get(['rippleEffect', 'color']); + this.off('mouseover').off('mouseout').off('emphasis').off('normal'); + + if (effectCfg.showEffectOn === 'render') { + this._effectCfg ? this.updateEffectAnimation(effectCfg) : this.startEffectAnimation(effectCfg); + this._effectCfg = effectCfg; + } else { + this._effectCfg = null; + this.stopEffectAnimation(); + + this.onHoverStateChange = function (toState) { + if (toState === 'emphasis') { + if (effectCfg.showEffectOn !== 'render') { + _this.startEffectAnimation(effectCfg); + } + } else if (toState === 'normal') { + if (effectCfg.showEffectOn !== 'render') { + _this.stopEffectAnimation(); + } + } + }; + } + + this._effectCfg = effectCfg; + enableHoverEmphasis(this); + }; + + EffectSymbol.prototype.fadeOut = function (cb) { + this.off('mouseover').off('mouseout'); + cb && cb(); + }; + return EffectSymbol; + }(Group); + + inherits(EffectSymbol, Group); + + var EffectScatterView = function (_super) { + __extends(EffectScatterView, _super); + + function EffectScatterView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = EffectScatterView.type; + return _this; + } + + EffectScatterView.prototype.init = function () { + this._symbolDraw = new SymbolDraw(EffectSymbol); + }; + + EffectScatterView.prototype.render = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var effectSymbolDraw = this._symbolDraw; + effectSymbolDraw.updateData(data); + this.group.add(effectSymbolDraw.group); + }; + + EffectScatterView.prototype.updateTransform = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + this.group.dirty(); + var res = pointsLayout('').reset(seriesModel, ecModel, api); + + if (res.progress) { + res.progress({ + start: 0, + end: data.count(), + count: data.count() + }, data); + } + + this._symbolDraw.updateLayout(); + }; + + EffectScatterView.prototype._updateGroupTransform = function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && coordSys.getRoamTransform) { + this.group.transform = clone$2(coordSys.getRoamTransform()); + this.group.decomposeTransform(); + } + }; + + EffectScatterView.prototype.remove = function (ecModel, api) { + this._symbolDraw && this._symbolDraw.remove(true); + }; + + EffectScatterView.type = 'effectScatter'; + return EffectScatterView; + }(ChartView); + + var EffectScatterSeriesModel = function (_super) { + __extends(EffectScatterSeriesModel, _super); + + function EffectScatterSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = EffectScatterSeriesModel.type; + _this.hasSymbolVisual = true; + return _this; + } + + EffectScatterSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createListFromArray(this.getSource(), this, { + useEncodeDefaulter: true + }); + }; + + EffectScatterSeriesModel.prototype.brushSelector = function (dataIndex, data, selectors) { + return selectors.point(data.getItemLayout(dataIndex)); + }; + + EffectScatterSeriesModel.type = 'series.effectScatter'; + EffectScatterSeriesModel.dependencies = ['grid', 'polar']; + EffectScatterSeriesModel.defaultOption = { + coordinateSystem: 'cartesian2d', + zlevel: 0, + z: 2, + legendHoverLink: true, + effectType: 'ripple', + progressive: 0, + showEffectOn: 'render', + rippleEffect: { + period: 4, + scale: 2.5, + brushType: 'fill' + }, + symbolSize: 10 + }; + return EffectScatterSeriesModel; + }(SeriesModel); + + function install$k(registers) { + registers.registerChartView(EffectScatterView); + registers.registerSeriesModel(EffectScatterSeriesModel); + registers.registerLayout(pointsLayout('effectScatter')); + } + + var EffectLine = function (_super) { + __extends(EffectLine, _super); + + function EffectLine(lineData, idx, seriesScope) { + var _this = _super.call(this) || this; + + _this.add(_this.createLine(lineData, idx, seriesScope)); + + _this._updateEffectSymbol(lineData, idx); + + return _this; + } + + EffectLine.prototype.createLine = function (lineData, idx, seriesScope) { + return new Line$1(lineData, idx, seriesScope); + }; + + EffectLine.prototype._updateEffectSymbol = function (lineData, idx) { + var itemModel = lineData.getItemModel(idx); + var effectModel = itemModel.getModel('effect'); + var size = effectModel.get('symbolSize'); + var symbolType = effectModel.get('symbol'); + + if (!isArray(size)) { + size = [size, size]; + } + + var lineStyle = lineData.getItemVisual(idx, 'style'); + var color = effectModel.get('color') || lineStyle && lineStyle.stroke; + var symbol = this.childAt(1); + + if (this._symbolType !== symbolType) { + this.remove(symbol); + symbol = createSymbol(symbolType, -0.5, -0.5, 1, 1, color); + symbol.z2 = 100; + symbol.culling = true; + this.add(symbol); + } + + if (!symbol) { + return; + } + + symbol.setStyle('shadowColor', color); + symbol.setStyle(effectModel.getItemStyle(['color'])); + symbol.scaleX = size[0]; + symbol.scaleY = size[1]; + symbol.setColor(color); + this._symbolType = symbolType; + this._symbolScale = size; + + this._updateEffectAnimation(lineData, effectModel, idx); + }; + + EffectLine.prototype._updateEffectAnimation = function (lineData, effectModel, idx) { + var symbol = this.childAt(1); + + if (!symbol) { + return; + } + + var self = this; + var points = lineData.getItemLayout(idx); + var period = effectModel.get('period') * 1000; + var loop = effectModel.get('loop'); + var constantSpeed = effectModel.get('constantSpeed'); + var delayExpr = retrieve(effectModel.get('delay'), function (idx) { + return idx / lineData.count() * period / 3; + }); + symbol.ignore = true; + + this._updateAnimationPoints(symbol, points); + + if (constantSpeed > 0) { + period = this._getLineLength(symbol) / constantSpeed * 1000; + } + + if (period !== this._period || loop !== this._loop) { + symbol.stopAnimation(); + + if (period > 0) { + var delayNum = void 0; + + if (typeof delayExpr === 'function') { + delayNum = delayExpr(idx); + } else { + delayNum = delayExpr; + } + + if (symbol.__t > 0) { + delayNum = -period * symbol.__t; + } + + symbol.__t = 0; + var animator = symbol.animate('', loop).when(period, { + __t: 1 + }).delay(delayNum).during(function () { + self._updateSymbolPosition(symbol); + }); + + if (!loop) { + animator.done(function () { + self.remove(symbol); + }); + } + + animator.start(); + } + } + + this._period = period; + this._loop = loop; + }; + + EffectLine.prototype._getLineLength = function (symbol) { + return dist(symbol.__p1, symbol.__cp1) + dist(symbol.__cp1, symbol.__p2); + }; + + EffectLine.prototype._updateAnimationPoints = function (symbol, points) { + symbol.__p1 = points[0]; + symbol.__p2 = points[1]; + symbol.__cp1 = points[2] || [(points[0][0] + points[1][0]) / 2, (points[0][1] + points[1][1]) / 2]; + }; + + EffectLine.prototype.updateData = function (lineData, idx, seriesScope) { + this.childAt(0).updateData(lineData, idx, seriesScope); + + this._updateEffectSymbol(lineData, idx); + }; + + EffectLine.prototype._updateSymbolPosition = function (symbol) { + var p1 = symbol.__p1; + var p2 = symbol.__p2; + var cp1 = symbol.__cp1; + var t = symbol.__t; + var pos = [symbol.x, symbol.y]; + var lastPos = pos.slice(); + var quadraticAt$1 = quadraticAt; + var quadraticDerivativeAt$1 = quadraticDerivativeAt; + pos[0] = quadraticAt$1(p1[0], cp1[0], p2[0], t); + pos[1] = quadraticAt$1(p1[1], cp1[1], p2[1], t); + var tx = quadraticDerivativeAt$1(p1[0], cp1[0], p2[0], t); + var ty = quadraticDerivativeAt$1(p1[1], cp1[1], p2[1], t); + symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2; + + if (this._symbolType === 'line' || this._symbolType === 'rect' || this._symbolType === 'roundRect') { + if (symbol.__lastT !== undefined && symbol.__lastT < symbol.__t) { + symbol.scaleY = dist(lastPos, pos) * 1.05; + + if (t === 1) { + pos[0] = lastPos[0] + (pos[0] - lastPos[0]) / 2; + pos[1] = lastPos[1] + (pos[1] - lastPos[1]) / 2; + } + } else if (symbol.__lastT === 1) { + symbol.scaleY = 2 * dist(p1, pos); + } else { + symbol.scaleY = this._symbolScale[1]; + } + } + + symbol.__lastT = symbol.__t; + symbol.ignore = false; + symbol.x = pos[0]; + symbol.y = pos[1]; + }; + + EffectLine.prototype.updateLayout = function (lineData, idx) { + this.childAt(0).updateLayout(lineData, idx); + var effectModel = lineData.getItemModel(idx).getModel('effect'); + + this._updateEffectAnimation(lineData, effectModel, idx); + }; + + return EffectLine; + }(Group); + + var Polyline$1 = function (_super) { + __extends(Polyline$1, _super); + + function Polyline$1(lineData, idx, seriesScope) { + var _this = _super.call(this) || this; + + _this._createPolyline(lineData, idx, seriesScope); + + return _this; + } + + Polyline$1.prototype._createPolyline = function (lineData, idx, seriesScope) { + var points = lineData.getItemLayout(idx); + var line = new Polyline({ + shape: { + points: points + } + }); + this.add(line); + + this._updateCommonStl(lineData, idx, seriesScope); + }; + + Polyline$1.prototype.updateData = function (lineData, idx, seriesScope) { + var seriesModel = lineData.hostModel; + var line = this.childAt(0); + var target = { + shape: { + points: lineData.getItemLayout(idx) + } + }; + updateProps(line, target, seriesModel, idx); + + this._updateCommonStl(lineData, idx, seriesScope); + }; + + Polyline$1.prototype._updateCommonStl = function (lineData, idx, seriesScope) { + var line = this.childAt(0); + var itemModel = lineData.getItemModel(idx); + var hoverLineStyle = seriesScope && seriesScope.emphasisLineStyle; + + if (!seriesScope || lineData.hasItemOption) { + hoverLineStyle = itemModel.getModel(['emphasis', 'lineStyle']).getLineStyle(); + } + + line.useStyle(lineData.getItemVisual(idx, 'style')); + line.style.fill = null; + line.style.strokeNoScale = true; + var lineEmphasisState = line.ensureState('emphasis'); + lineEmphasisState.style = hoverLineStyle; + enableHoverEmphasis(this); + }; + + Polyline$1.prototype.updateLayout = function (lineData, idx) { + var polyline = this.childAt(0); + polyline.setShape('points', lineData.getItemLayout(idx)); + }; + return Polyline$1; + }(Group); + + var EffectPolyline = function (_super) { + __extends(EffectPolyline, _super); + + function EffectPolyline() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this._lastFrame = 0; + _this._lastFramePercent = 0; + return _this; + } + + EffectPolyline.prototype.createLine = function (lineData, idx, seriesScope) { + return new Polyline$1(lineData, idx, seriesScope); + }; + + EffectPolyline.prototype._updateAnimationPoints = function (symbol, points) { + this._points = points; + var accLenArr = [0]; + var len = 0; + + for (var i = 1; i < points.length; i++) { + var p1 = points[i - 1]; + var p2 = points[i]; + len += dist(p1, p2); + accLenArr.push(len); + } + + if (len === 0) { + this._length = 0; + return; + } + + for (var i = 0; i < accLenArr.length; i++) { + accLenArr[i] /= len; + } + + this._offsets = accLenArr; + this._length = len; + }; + + EffectPolyline.prototype._getLineLength = function () { + return this._length; + }; + + EffectPolyline.prototype._updateSymbolPosition = function (symbol) { + var t = symbol.__t; + var points = this._points; + var offsets = this._offsets; + var len = points.length; + + if (!offsets) { + return; + } + + var lastFrame = this._lastFrame; + var frame; + + if (t < this._lastFramePercent) { + var start = Math.min(lastFrame + 1, len - 1); + + for (frame = start; frame >= 0; frame--) { + if (offsets[frame] <= t) { + break; + } + } + + frame = Math.min(frame, len - 2); + } else { + for (frame = lastFrame; frame < len; frame++) { + if (offsets[frame] > t) { + break; + } + } + + frame = Math.min(frame - 1, len - 2); + } + + var p = (t - offsets[frame]) / (offsets[frame + 1] - offsets[frame]); + var p0 = points[frame]; + var p1 = points[frame + 1]; + symbol.x = p0[0] * (1 - p) + p * p1[0]; + symbol.y = p0[1] * (1 - p) + p * p1[1]; + var tx = p1[0] - p0[0]; + var ty = p1[1] - p0[1]; + symbol.rotation = -Math.atan2(ty, tx) - Math.PI / 2; + this._lastFrame = frame; + this._lastFramePercent = t; + symbol.ignore = false; + }; + return EffectPolyline; + }(EffectLine); + + var LargeLinesPathShape = function () { + function LargeLinesPathShape() { + this.polyline = false; + this.curveness = 0; + this.segs = []; + } + + return LargeLinesPathShape; + }(); + + var LargeLinesPath = function (_super) { + __extends(LargeLinesPath, _super); + + function LargeLinesPath(opts) { + return _super.call(this, opts) || this; + } + + LargeLinesPath.prototype.getDefaultStyle = function () { + return { + stroke: '#000', + fill: null + }; + }; + + LargeLinesPath.prototype.getDefaultShape = function () { + return new LargeLinesPathShape(); + }; + + LargeLinesPath.prototype.buildPath = function (ctx, shape) { + var segs = shape.segs; + var curveness = shape.curveness; + + if (shape.polyline) { + for (var i = 0; i < segs.length;) { + var count = segs[i++]; + + if (count > 0) { + ctx.moveTo(segs[i++], segs[i++]); + + for (var k = 1; k < count; k++) { + ctx.lineTo(segs[i++], segs[i++]); + } + } + } + } else { + for (var i = 0; i < segs.length;) { + var x0 = segs[i++]; + var y0 = segs[i++]; + var x1 = segs[i++]; + var y1 = segs[i++]; + ctx.moveTo(x0, y0); + + if (curveness > 0) { + var x2 = (x0 + x1) / 2 - (y0 - y1) * curveness; + var y2 = (y0 + y1) / 2 - (x1 - x0) * curveness; + ctx.quadraticCurveTo(x2, y2, x1, y1); + } else { + ctx.lineTo(x1, y1); + } + } + } + }; + + LargeLinesPath.prototype.findDataIndex = function (x, y) { + var shape = this.shape; + var segs = shape.segs; + var curveness = shape.curveness; + var lineWidth = this.style.lineWidth; + + if (shape.polyline) { + var dataIndex = 0; + + for (var i = 0; i < segs.length;) { + var count = segs[i++]; + + if (count > 0) { + var x0 = segs[i++]; + var y0 = segs[i++]; + + for (var k = 1; k < count; k++) { + var x1 = segs[i++]; + var y1 = segs[i++]; + + if (containStroke(x0, y0, x1, y1, lineWidth, x, y)) { + return dataIndex; + } + } + } + + dataIndex++; + } + } else { + var dataIndex = 0; + + for (var i = 0; i < segs.length;) { + var x0 = segs[i++]; + var y0 = segs[i++]; + var x1 = segs[i++]; + var y1 = segs[i++]; + + if (curveness > 0) { + var x2 = (x0 + x1) / 2 - (y0 - y1) * curveness; + var y2 = (y0 + y1) / 2 - (x1 - x0) * curveness; + + if (containStroke$2(x0, y0, x2, y2, x1, y1, lineWidth, x, y)) { + return dataIndex; + } + } else { + if (containStroke(x0, y0, x1, y1, lineWidth, x, y)) { + return dataIndex; + } + } + + dataIndex++; + } + } + + return -1; + }; + + return LargeLinesPath; + }(Path); + + var LargeLineDraw = function () { + function LargeLineDraw() { + this.group = new Group(); + } + + LargeLineDraw.prototype.isPersistent = function () { + return !this._incremental; + }; + + LargeLineDraw.prototype.updateData = function (data) { + this.group.removeAll(); + var lineEl = new LargeLinesPath({ + rectHover: true, + cursor: 'default' + }); + lineEl.setShape({ + segs: data.getLayout('linesPoints') + }); + + this._setCommon(lineEl, data); + + this.group.add(lineEl); + this._incremental = null; + }; + + LargeLineDraw.prototype.incrementalPrepareUpdate = function (data) { + this.group.removeAll(); + + this._clearIncremental(); + + if (data.count() > 5e5) { + if (!this._incremental) { + this._incremental = new IncrementalDisplayable({ + silent: true + }); + } + + this.group.add(this._incremental); + } else { + this._incremental = null; + } + }; + + LargeLineDraw.prototype.incrementalUpdate = function (taskParams, data) { + var lineEl = new LargeLinesPath(); + lineEl.setShape({ + segs: data.getLayout('linesPoints') + }); + + this._setCommon(lineEl, data, !!this._incremental); + + if (!this._incremental) { + lineEl.rectHover = true; + lineEl.cursor = 'default'; + lineEl.__startIndex = taskParams.start; + this.group.add(lineEl); + } else { + this._incremental.addDisplayable(lineEl, true); + } + }; + + LargeLineDraw.prototype.remove = function () { + this._clearIncremental(); + + this._incremental = null; + this.group.removeAll(); + }; + + LargeLineDraw.prototype._setCommon = function (lineEl, data, isIncremental) { + var hostModel = data.hostModel; + lineEl.setShape({ + polyline: hostModel.get('polyline'), + curveness: hostModel.get(['lineStyle', 'curveness']) + }); + lineEl.useStyle(hostModel.getModel('lineStyle').getLineStyle()); + lineEl.style.strokeNoScale = true; + var style = data.getVisual('style'); + + if (style && style.stroke) { + lineEl.setStyle('stroke', style.stroke); + } + + lineEl.setStyle('fill', null); + + if (!isIncremental) { + var ecData_1 = getECData(lineEl); + ecData_1.seriesIndex = hostModel.seriesIndex; + lineEl.on('mousemove', function (e) { + ecData_1.dataIndex = null; + var dataIndex = lineEl.findDataIndex(e.offsetX, e.offsetY); + + if (dataIndex > 0) { + ecData_1.dataIndex = dataIndex + lineEl.__startIndex; + } + }); + } + }; + + LargeLineDraw.prototype._clearIncremental = function () { + var incremental = this._incremental; + + if (incremental) { + incremental.clearDisplaybles(); + } + }; + return LargeLineDraw; + }(); + + var linesLayout = { + seriesType: 'lines', + plan: createRenderPlanner(), + reset: function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + var isPolyline = seriesModel.get('polyline'); + var isLarge = seriesModel.pipelineContext.large; + return { + progress: function (params, lineData) { + var lineCoords = []; + + if (isLarge) { + var points = void 0; + var segCount = params.end - params.start; + + if (isPolyline) { + var totalCoordsCount = 0; + + for (var i = params.start; i < params.end; i++) { + totalCoordsCount += seriesModel.getLineCoordsCount(i); + } + + points = new Float32Array(segCount + totalCoordsCount * 2); + } else { + points = new Float32Array(segCount * 4); + } + + var offset = 0; + var pt = []; + + for (var i = params.start; i < params.end; i++) { + var len = seriesModel.getLineCoords(i, lineCoords); + + if (isPolyline) { + points[offset++] = len; + } + + for (var k = 0; k < len; k++) { + pt = coordSys.dataToPoint(lineCoords[k], false, pt); + points[offset++] = pt[0]; + points[offset++] = pt[1]; + } + } + + lineData.setLayout('linesPoints', points); + } else { + for (var i = params.start; i < params.end; i++) { + var itemModel = lineData.getItemModel(i); + var len = seriesModel.getLineCoords(i, lineCoords); + var pts = []; + + if (isPolyline) { + for (var j = 0; j < len; j++) { + pts.push(coordSys.dataToPoint(lineCoords[j])); + } + } else { + pts[0] = coordSys.dataToPoint(lineCoords[0]); + pts[1] = coordSys.dataToPoint(lineCoords[1]); + var curveness = itemModel.get(['lineStyle', 'curveness']); + + if (+curveness) { + pts[2] = [(pts[0][0] + pts[1][0]) / 2 - (pts[0][1] - pts[1][1]) * curveness, (pts[0][1] + pts[1][1]) / 2 - (pts[1][0] - pts[0][0]) * curveness]; + } + } + + lineData.setItemLayout(i, pts); + } + } + } + }; + } + }; + + var LinesView = function (_super) { + __extends(LinesView, _super); + + function LinesView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = LinesView.type; + return _this; + } + + LinesView.prototype.render = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + + var lineDraw = this._updateLineDraw(data, seriesModel); + + var zlevel = seriesModel.get('zlevel'); + var trailLength = seriesModel.get(['effect', 'trailLength']); + var zr = api.getZr(); + var isSvg = zr.painter.getType() === 'svg'; + + if (!isSvg) { + zr.painter.getLayer(zlevel).clear(true); + } + + if (this._lastZlevel != null && !isSvg) { + zr.configLayer(this._lastZlevel, { + motionBlur: false + }); + } + + if (this._showEffect(seriesModel) && trailLength) { + if ("development" !== 'production') { + var notInIndividual_1 = false; + ecModel.eachSeries(function (otherSeriesModel) { + if (otherSeriesModel !== seriesModel && otherSeriesModel.get('zlevel') === zlevel) { + notInIndividual_1 = true; + } + }); + notInIndividual_1 && console.warn('Lines with trail effect should have an individual zlevel'); + } + + if (!isSvg) { + zr.configLayer(zlevel, { + motionBlur: true, + lastFrameAlpha: Math.max(Math.min(trailLength / 10 + 0.9, 1), 0) + }); + } + } + + lineDraw.updateData(data); + var clipPath = seriesModel.get('clip', true) && createClipPath(seriesModel.coordinateSystem, false, seriesModel); + + if (clipPath) { + this.group.setClipPath(clipPath); + } else { + this.group.removeClipPath(); + } + + this._lastZlevel = zlevel; + this._finished = true; + }; + + LinesView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + + var lineDraw = this._updateLineDraw(data, seriesModel); + + lineDraw.incrementalPrepareUpdate(data); + + this._clearLayer(api); + + this._finished = false; + }; + + LinesView.prototype.incrementalRender = function (taskParams, seriesModel, ecModel) { + this._lineDraw.incrementalUpdate(taskParams, seriesModel.getData()); + + this._finished = taskParams.end === seriesModel.getData().count(); + }; + + LinesView.prototype.updateTransform = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var pipelineContext = seriesModel.pipelineContext; + + if (!this._finished || pipelineContext.large || pipelineContext.progressiveRender) { + return { + update: true + }; + } else { + var res = linesLayout.reset(seriesModel, ecModel, api); + + if (res.progress) { + res.progress({ + start: 0, + end: data.count(), + count: data.count() + }, data); + } + + this._lineDraw.updateLayout(); + + this._clearLayer(api); + } + }; + + LinesView.prototype._updateLineDraw = function (data, seriesModel) { + var lineDraw = this._lineDraw; + + var hasEffect = this._showEffect(seriesModel); + + var isPolyline = !!seriesModel.get('polyline'); + var pipelineContext = seriesModel.pipelineContext; + var isLargeDraw = pipelineContext.large; + + if ("development" !== 'production') { + if (hasEffect && isLargeDraw) { + console.warn('Large lines not support effect'); + } + } + + if (!lineDraw || hasEffect !== this._hasEffet || isPolyline !== this._isPolyline || isLargeDraw !== this._isLargeDraw) { + if (lineDraw) { + lineDraw.remove(); + } + + lineDraw = this._lineDraw = isLargeDraw ? new LargeLineDraw() : new LineDraw(isPolyline ? hasEffect ? EffectPolyline : Polyline$1 : hasEffect ? EffectLine : Line$1); + this._hasEffet = hasEffect; + this._isPolyline = isPolyline; + this._isLargeDraw = isLargeDraw; + this.group.removeAll(); + } + + this.group.add(lineDraw.group); + return lineDraw; + }; + + LinesView.prototype._showEffect = function (seriesModel) { + return !!seriesModel.get(['effect', 'show']); + }; + + LinesView.prototype._clearLayer = function (api) { + var zr = api.getZr(); + var isSvg = zr.painter.getType() === 'svg'; + + if (!isSvg && this._lastZlevel != null) { + zr.painter.getLayer(this._lastZlevel).clear(true); + } + }; + + LinesView.prototype.remove = function (ecModel, api) { + this._lineDraw && this._lineDraw.remove(); + this._lineDraw = null; + + this._clearLayer(api); + }; + + LinesView.type = 'lines'; + return LinesView; + }(ChartView); + + var Uint32Arr = typeof Uint32Array === 'undefined' ? Array : Uint32Array; + var Float64Arr = typeof Float64Array === 'undefined' ? Array : Float64Array; + + function compatEc2(seriesOpt) { + var data = seriesOpt.data; + + if (data && data[0] && data[0][0] && data[0][0].coord) { + if ("development" !== 'production') { + console.warn('Lines data configuration has been changed to' + ' { coords:[[1,2],[2,3]] }'); + } + + seriesOpt.data = map(data, function (itemOpt) { + var coords = [itemOpt[0].coord, itemOpt[1].coord]; + var target = { + coords: coords + }; + + if (itemOpt[0].name) { + target.fromName = itemOpt[0].name; + } + + if (itemOpt[1].name) { + target.toName = itemOpt[1].name; + } + + return mergeAll([target, itemOpt[0], itemOpt[1]]); + }); + } + } + + var LinesSeriesModel = function (_super) { + __extends(LinesSeriesModel, _super); + + function LinesSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = LinesSeriesModel.type; + _this.visualStyleAccessPath = 'lineStyle'; + _this.visualDrawType = 'stroke'; + return _this; + } + + LinesSeriesModel.prototype.init = function (option) { + option.data = option.data || []; + compatEc2(option); + + var result = this._processFlatCoordsArray(option.data); + + this._flatCoords = result.flatCoords; + this._flatCoordsOffset = result.flatCoordsOffset; + + if (result.flatCoords) { + option.data = new Float32Array(result.count); + } + + _super.prototype.init.apply(this, arguments); + }; + + LinesSeriesModel.prototype.mergeOption = function (option) { + compatEc2(option); + + if (option.data) { + var result = this._processFlatCoordsArray(option.data); + + this._flatCoords = result.flatCoords; + this._flatCoordsOffset = result.flatCoordsOffset; + + if (result.flatCoords) { + option.data = new Float32Array(result.count); + } + } + + _super.prototype.mergeOption.apply(this, arguments); + }; + + LinesSeriesModel.prototype.appendData = function (params) { + var result = this._processFlatCoordsArray(params.data); + + if (result.flatCoords) { + if (!this._flatCoords) { + this._flatCoords = result.flatCoords; + this._flatCoordsOffset = result.flatCoordsOffset; + } else { + this._flatCoords = concatArray(this._flatCoords, result.flatCoords); + this._flatCoordsOffset = concatArray(this._flatCoordsOffset, result.flatCoordsOffset); + } + + params.data = new Float32Array(result.count); + } + + this.getRawData().appendData(params.data); + }; + + LinesSeriesModel.prototype._getCoordsFromItemModel = function (idx) { + var itemModel = this.getData().getItemModel(idx); + var coords = itemModel.option instanceof Array ? itemModel.option : itemModel.getShallow('coords'); + + if ("development" !== 'production') { + if (!(coords instanceof Array && coords.length > 0 && coords[0] instanceof Array)) { + throw new Error('Invalid coords ' + JSON.stringify(coords) + '. Lines must have 2d coords array in data item.'); + } + } + + return coords; + }; + + LinesSeriesModel.prototype.getLineCoordsCount = function (idx) { + if (this._flatCoordsOffset) { + return this._flatCoordsOffset[idx * 2 + 1]; + } else { + return this._getCoordsFromItemModel(idx).length; + } + }; + + LinesSeriesModel.prototype.getLineCoords = function (idx, out) { + if (this._flatCoordsOffset) { + var offset = this._flatCoordsOffset[idx * 2]; + var len = this._flatCoordsOffset[idx * 2 + 1]; + + for (var i = 0; i < len; i++) { + out[i] = out[i] || []; + out[i][0] = this._flatCoords[offset + i * 2]; + out[i][1] = this._flatCoords[offset + i * 2 + 1]; + } + + return len; + } else { + var coords = this._getCoordsFromItemModel(idx); + + for (var i = 0; i < coords.length; i++) { + out[i] = out[i] || []; + out[i][0] = coords[i][0]; + out[i][1] = coords[i][1]; + } + + return coords.length; + } + }; + + LinesSeriesModel.prototype._processFlatCoordsArray = function (data) { + var startOffset = 0; + + if (this._flatCoords) { + startOffset = this._flatCoords.length; + } + + if (typeof data[0] === 'number') { + var len = data.length; + var coordsOffsetAndLenStorage = new Uint32Arr(len); + var coordsStorage = new Float64Arr(len); + var coordsCursor = 0; + var offsetCursor = 0; + var dataCount = 0; + + for (var i = 0; i < len;) { + dataCount++; + var count = data[i++]; + coordsOffsetAndLenStorage[offsetCursor++] = coordsCursor + startOffset; + coordsOffsetAndLenStorage[offsetCursor++] = count; + + for (var k = 0; k < count; k++) { + var x = data[i++]; + var y = data[i++]; + coordsStorage[coordsCursor++] = x; + coordsStorage[coordsCursor++] = y; + + if (i > len) { + if ("development" !== 'production') { + throw new Error('Invalid data format.'); + } + } + } + } + + return { + flatCoordsOffset: new Uint32Array(coordsOffsetAndLenStorage.buffer, 0, offsetCursor), + flatCoords: coordsStorage, + count: dataCount + }; + } + + return { + flatCoordsOffset: null, + flatCoords: null, + count: data.length + }; + }; + + LinesSeriesModel.prototype.getInitialData = function (option, ecModel) { + if ("development" !== 'production') { + var CoordSys = CoordinateSystemManager.get(option.coordinateSystem); + + if (!CoordSys) { + throw new Error('Unkown coordinate system ' + option.coordinateSystem); + } + } + + var lineData = new List(['value'], this); + lineData.hasItemOption = false; + lineData.initData(option.data, [], function (dataItem, dimName, dataIndex, dimIndex) { + if (dataItem instanceof Array) { + return NaN; + } else { + lineData.hasItemOption = true; + var value = dataItem.value; + + if (value != null) { + return value instanceof Array ? value[dimIndex] : value; + } + } + }); + return lineData; + }; + + LinesSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + var data = this.getData(); + var itemModel = data.getItemModel(dataIndex); + var name = itemModel.get('name'); + + if (name) { + return name; + } + + var fromName = itemModel.get('fromName'); + var toName = itemModel.get('toName'); + var nameArr = []; + fromName != null && nameArr.push(fromName); + toName != null && nameArr.push(toName); + return createTooltipMarkup('nameValue', { + name: nameArr.join(' > ') + }); + }; + + LinesSeriesModel.prototype.preventIncremental = function () { + return !!this.get(['effect', 'show']); + }; + + LinesSeriesModel.prototype.getProgressive = function () { + var progressive = this.option.progressive; + + if (progressive == null) { + return this.option.large ? 1e4 : this.get('progressive'); + } + + return progressive; + }; + + LinesSeriesModel.prototype.getProgressiveThreshold = function () { + var progressiveThreshold = this.option.progressiveThreshold; + + if (progressiveThreshold == null) { + return this.option.large ? 2e4 : this.get('progressiveThreshold'); + } + + return progressiveThreshold; + }; + + LinesSeriesModel.type = 'series.lines'; + LinesSeriesModel.dependencies = ['grid', 'polar', 'geo', 'calendar']; + LinesSeriesModel.defaultOption = { + coordinateSystem: 'geo', + zlevel: 0, + z: 2, + legendHoverLink: true, + xAxisIndex: 0, + yAxisIndex: 0, + symbol: ['none', 'none'], + symbolSize: [10, 10], + geoIndex: 0, + effect: { + show: false, + period: 4, + constantSpeed: 0, + symbol: 'circle', + symbolSize: 3, + loop: true, + trailLength: 0.2 + }, + large: false, + largeThreshold: 2000, + polyline: false, + clip: true, + label: { + show: false, + position: 'end' + }, + lineStyle: { + opacity: 0.5 + } + }; + return LinesSeriesModel; + }(SeriesModel); + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function normalize$3(a) { + if (!(a instanceof Array)) { + a = [a, a]; + } + + return a; + } + + var linesVisual = { + seriesType: 'lines', + reset: function (seriesModel) { + var symbolType = normalize$3(seriesModel.get('symbol')); + var symbolSize = normalize$3(seriesModel.get('symbolSize')); + var data = seriesModel.getData(); + data.setVisual('fromSymbol', symbolType && symbolType[0]); + data.setVisual('toSymbol', symbolType && symbolType[1]); + data.setVisual('fromSymbolSize', symbolSize && symbolSize[0]); + data.setVisual('toSymbolSize', symbolSize && symbolSize[1]); + + function dataEach(data, idx) { + var itemModel = data.getItemModel(idx); + var symbolType = normalize$3(itemModel.getShallow('symbol', true)); + var symbolSize = normalize$3(itemModel.getShallow('symbolSize', true)); + symbolType[0] && data.setItemVisual(idx, 'fromSymbol', symbolType[0]); + symbolType[1] && data.setItemVisual(idx, 'toSymbol', symbolType[1]); + symbolSize[0] && data.setItemVisual(idx, 'fromSymbolSize', symbolSize[0]); + symbolSize[1] && data.setItemVisual(idx, 'toSymbolSize', symbolSize[1]); + } + + return { + dataEach: data.hasItemOption ? dataEach : null + }; + } + }; + + function install$l(registers) { + registers.registerChartView(LinesView); + registers.registerSeriesModel(LinesSeriesModel); + registers.registerLayout(linesLayout); + registers.registerVisual(linesVisual); + } + + var GRADIENT_LEVELS = 256; + + var HeatmapLayer = function () { + function HeatmapLayer() { + this.blurSize = 30; + this.pointSize = 20; + this.maxOpacity = 1; + this.minOpacity = 0; + this._gradientPixels = { + inRange: null, + outOfRange: null + }; + var canvas = createCanvas(); + this.canvas = canvas; + } + + HeatmapLayer.prototype.update = function (data, width, height, normalize, colorFunc, isInRange) { + var brush = this._getBrush(); + + var gradientInRange = this._getGradient(colorFunc, 'inRange'); + + var gradientOutOfRange = this._getGradient(colorFunc, 'outOfRange'); + + var r = this.pointSize + this.blurSize; + var canvas = this.canvas; + var ctx = canvas.getContext('2d'); + var len = data.length; + canvas.width = width; + canvas.height = height; + + for (var i = 0; i < len; ++i) { + var p = data[i]; + var x = p[0]; + var y = p[1]; + var value = p[2]; + var alpha = normalize(value); + ctx.globalAlpha = alpha; + ctx.drawImage(brush, x - r, y - r); + } + + if (!canvas.width || !canvas.height) { + return canvas; + } + + var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + var pixels = imageData.data; + var offset = 0; + var pixelLen = pixels.length; + var minOpacity = this.minOpacity; + var maxOpacity = this.maxOpacity; + var diffOpacity = maxOpacity - minOpacity; + + while (offset < pixelLen) { + var alpha = pixels[offset + 3] / 256; + var gradientOffset = Math.floor(alpha * (GRADIENT_LEVELS - 1)) * 4; + + if (alpha > 0) { + var gradient = isInRange(alpha) ? gradientInRange : gradientOutOfRange; + alpha > 0 && (alpha = alpha * diffOpacity + minOpacity); + pixels[offset++] = gradient[gradientOffset]; + pixels[offset++] = gradient[gradientOffset + 1]; + pixels[offset++] = gradient[gradientOffset + 2]; + pixels[offset++] = gradient[gradientOffset + 3] * alpha * 256; + } else { + offset += 4; + } + } + + ctx.putImageData(imageData, 0, 0); + return canvas; + }; + + HeatmapLayer.prototype._getBrush = function () { + var brushCanvas = this._brushCanvas || (this._brushCanvas = createCanvas()); + var r = this.pointSize + this.blurSize; + var d = r * 2; + brushCanvas.width = d; + brushCanvas.height = d; + var ctx = brushCanvas.getContext('2d'); + ctx.clearRect(0, 0, d, d); + ctx.shadowOffsetX = d; + ctx.shadowBlur = this.blurSize; + ctx.shadowColor = '#000'; + ctx.beginPath(); + ctx.arc(-r, r, this.pointSize, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fill(); + return brushCanvas; + }; + + HeatmapLayer.prototype._getGradient = function (colorFunc, state) { + var gradientPixels = this._gradientPixels; + var pixelsSingleState = gradientPixels[state] || (gradientPixels[state] = new Uint8ClampedArray(256 * 4)); + var color = [0, 0, 0, 0]; + var off = 0; + + for (var i = 0; i < 256; i++) { + colorFunc[state](i / 255, true, color); + pixelsSingleState[off++] = color[0]; + pixelsSingleState[off++] = color[1]; + pixelsSingleState[off++] = color[2]; + pixelsSingleState[off++] = color[3]; + } + + return pixelsSingleState; + }; + + return HeatmapLayer; + }(); + + function getIsInPiecewiseRange(dataExtent, pieceList, selected) { + var dataSpan = dataExtent[1] - dataExtent[0]; + pieceList = map(pieceList, function (piece) { + return { + interval: [(piece.interval[0] - dataExtent[0]) / dataSpan, (piece.interval[1] - dataExtent[0]) / dataSpan] + }; + }); + var len = pieceList.length; + var lastIndex = 0; + return function (val) { + var i; + + for (i = lastIndex; i < len; i++) { + var interval = pieceList[i].interval; + + if (interval[0] <= val && val <= interval[1]) { + lastIndex = i; + break; + } + } + + if (i === len) { + for (i = lastIndex - 1; i >= 0; i--) { + var interval = pieceList[i].interval; + + if (interval[0] <= val && val <= interval[1]) { + lastIndex = i; + break; + } + } + } + + return i >= 0 && i < len && selected[i]; + }; + } + + function getIsInContinuousRange(dataExtent, range) { + var dataSpan = dataExtent[1] - dataExtent[0]; + range = [(range[0] - dataExtent[0]) / dataSpan, (range[1] - dataExtent[0]) / dataSpan]; + return function (val) { + return val >= range[0] && val <= range[1]; + }; + } + + function isGeoCoordSys(coordSys) { + var dimensions = coordSys.dimensions; + return dimensions[0] === 'lng' && dimensions[1] === 'lat'; + } + + var HeatmapView = function (_super) { + __extends(HeatmapView, _super); + + function HeatmapView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = HeatmapView.type; + return _this; + } + + HeatmapView.prototype.render = function (seriesModel, ecModel, api) { + var visualMapOfThisSeries; + ecModel.eachComponent('visualMap', function (visualMap) { + visualMap.eachTargetSeries(function (targetSeries) { + if (targetSeries === seriesModel) { + visualMapOfThisSeries = visualMap; + } + }); + }); + + if ("development" !== 'production') { + if (!visualMapOfThisSeries) { + throw new Error('Heatmap must use with visualMap'); + } + } + + this.group.removeAll(); + this._incrementalDisplayable = null; + var coordSys = seriesModel.coordinateSystem; + + if (coordSys.type === 'cartesian2d' || coordSys.type === 'calendar') { + this._renderOnCartesianAndCalendar(seriesModel, api, 0, seriesModel.getData().count()); + } else if (isGeoCoordSys(coordSys)) { + this._renderOnGeo(coordSys, seriesModel, visualMapOfThisSeries, api); + } + }; + + HeatmapView.prototype.incrementalPrepareRender = function (seriesModel, ecModel, api) { + this.group.removeAll(); + }; + + HeatmapView.prototype.incrementalRender = function (params, seriesModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys) { + if (isGeoCoordSys(coordSys)) { + this.render(seriesModel, ecModel, api); + } else { + this._renderOnCartesianAndCalendar(seriesModel, api, params.start, params.end, true); + } + } + }; + + HeatmapView.prototype._renderOnCartesianAndCalendar = function (seriesModel, api, start, end, incremental) { + var coordSys = seriesModel.coordinateSystem; + var width; + var height; + var xAxisExtent; + var yAxisExtent; + + if (isCoordinateSystemType(coordSys, 'cartesian2d')) { + var xAxis = coordSys.getAxis('x'); + var yAxis = coordSys.getAxis('y'); + + if ("development" !== 'production') { + if (!(xAxis.type === 'category' && yAxis.type === 'category')) { + throw new Error('Heatmap on cartesian must have two category axes'); + } + + if (!(xAxis.onBand && yAxis.onBand)) { + throw new Error('Heatmap on cartesian must have two axes with boundaryGap true'); + } + } + + width = xAxis.getBandWidth(); + height = yAxis.getBandWidth(); + xAxisExtent = xAxis.scale.getExtent(); + yAxisExtent = yAxis.scale.getExtent(); + } + + var group = this.group; + var data = seriesModel.getData(); + var emphasisStyle = seriesModel.getModel(['emphasis', 'itemStyle']).getItemStyle(); + var blurStyle = seriesModel.getModel(['blur', 'itemStyle']).getItemStyle(); + var selectStyle = seriesModel.getModel(['select', 'itemStyle']).getItemStyle(); + var labelStatesModels = getLabelStatesModels(seriesModel); + var focus = seriesModel.get(['emphasis', 'focus']); + var blurScope = seriesModel.get(['emphasis', 'blurScope']); + var dataDims = isCoordinateSystemType(coordSys, 'cartesian2d') ? [data.mapDimension('x'), data.mapDimension('y'), data.mapDimension('value')] : [data.mapDimension('time'), data.mapDimension('value')]; + + for (var idx = start; idx < end; idx++) { + var rect = void 0; + var style = data.getItemVisual(idx, 'style'); + + if (isCoordinateSystemType(coordSys, 'cartesian2d')) { + var dataDimX = data.get(dataDims[0], idx); + var dataDimY = data.get(dataDims[1], idx); + + if (isNaN(data.get(dataDims[2], idx)) || dataDimX < xAxisExtent[0] || dataDimX > xAxisExtent[1] || dataDimY < yAxisExtent[0] || dataDimY > yAxisExtent[1]) { + continue; + } + + var point = coordSys.dataToPoint([dataDimX, dataDimY]); + rect = new Rect({ + shape: { + x: Math.floor(Math.round(point[0]) - width / 2), + y: Math.floor(Math.round(point[1]) - height / 2), + width: Math.ceil(width), + height: Math.ceil(height) + }, + style: style + }); + } else { + if (isNaN(data.get(dataDims[1], idx))) { + continue; + } + + rect = new Rect({ + z2: 1, + shape: coordSys.dataToRect([data.get(dataDims[0], idx)]).contentShape, + style: style + }); + } + + var itemModel = data.getItemModel(idx); + + if (data.hasItemOption) { + var emphasisModel = itemModel.getModel('emphasis'); + emphasisStyle = emphasisModel.getModel('itemStyle').getItemStyle(); + blurStyle = itemModel.getModel(['blur', 'itemStyle']).getItemStyle(); + selectStyle = itemModel.getModel(['select', 'itemStyle']).getItemStyle(); + focus = emphasisModel.get('focus'); + blurScope = emphasisModel.get('blurScope'); + labelStatesModels = getLabelStatesModels(itemModel); + } + + var rawValue = seriesModel.getRawValue(idx); + var defaultText = '-'; + + if (rawValue && rawValue[2] != null) { + defaultText = rawValue[2] + ''; + } + + setLabelStyle(rect, labelStatesModels, { + labelFetcher: seriesModel, + labelDataIndex: idx, + defaultOpacity: style.opacity, + defaultText: defaultText + }); + rect.ensureState('emphasis').style = emphasisStyle; + rect.ensureState('blur').style = blurStyle; + rect.ensureState('select').style = selectStyle; + enableHoverEmphasis(rect, focus, blurScope); + rect.incremental = incremental; + + if (incremental) { + rect.states.emphasis.hoverLayer = true; + } + + group.add(rect); + data.setItemGraphicEl(idx, rect); + } + }; + + HeatmapView.prototype._renderOnGeo = function (geo, seriesModel, visualMapModel, api) { + var inRangeVisuals = visualMapModel.targetVisuals.inRange; + var outOfRangeVisuals = visualMapModel.targetVisuals.outOfRange; + var data = seriesModel.getData(); + var hmLayer = this._hmLayer || this._hmLayer || new HeatmapLayer(); + hmLayer.blurSize = seriesModel.get('blurSize'); + hmLayer.pointSize = seriesModel.get('pointSize'); + hmLayer.minOpacity = seriesModel.get('minOpacity'); + hmLayer.maxOpacity = seriesModel.get('maxOpacity'); + var rect = geo.getViewRect().clone(); + var roamTransform = geo.getRoamTransform(); + rect.applyTransform(roamTransform); + var x = Math.max(rect.x, 0); + var y = Math.max(rect.y, 0); + var x2 = Math.min(rect.width + rect.x, api.getWidth()); + var y2 = Math.min(rect.height + rect.y, api.getHeight()); + var width = x2 - x; + var height = y2 - y; + var dims = [data.mapDimension('lng'), data.mapDimension('lat'), data.mapDimension('value')]; + var points = data.mapArray(dims, function (lng, lat, value) { + var pt = geo.dataToPoint([lng, lat]); + pt[0] -= x; + pt[1] -= y; + pt.push(value); + return pt; + }); + var dataExtent = visualMapModel.getExtent(); + var isInRange = visualMapModel.type === 'visualMap.continuous' ? getIsInContinuousRange(dataExtent, visualMapModel.option.range) : getIsInPiecewiseRange(dataExtent, visualMapModel.getPieceList(), visualMapModel.option.selected); + hmLayer.update(points, width, height, inRangeVisuals.color.getNormalizer(), { + inRange: inRangeVisuals.color.getColorMapper(), + outOfRange: outOfRangeVisuals.color.getColorMapper() + }, isInRange); + var img = new ZRImage({ + style: { + width: width, + height: height, + x: x, + y: y, + image: hmLayer.canvas + }, + silent: true + }); + this.group.add(img); + }; + + HeatmapView.type = 'heatmap'; + return HeatmapView; + }(ChartView); + + var HeatmapSeriesModel = function (_super) { + __extends(HeatmapSeriesModel, _super); + + function HeatmapSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = HeatmapSeriesModel.type; + return _this; + } + + HeatmapSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createListFromArray(this.getSource(), this, { + generateCoord: 'value' + }); + }; + + HeatmapSeriesModel.prototype.preventIncremental = function () { + var coordSysCreator = CoordinateSystemManager.get(this.get('coordinateSystem')); + + if (coordSysCreator && coordSysCreator.dimensions) { + return coordSysCreator.dimensions[0] === 'lng' && coordSysCreator.dimensions[1] === 'lat'; + } + }; + + HeatmapSeriesModel.type = 'series.heatmap'; + HeatmapSeriesModel.dependencies = ['grid', 'geo', 'calendar']; + HeatmapSeriesModel.defaultOption = { + coordinateSystem: 'cartesian2d', + zlevel: 0, + z: 2, + geoIndex: 0, + blurSize: 30, + pointSize: 20, + maxOpacity: 1, + minOpacity: 0, + select: { + itemStyle: { + borderColor: '#212121' + } + } + }; + return HeatmapSeriesModel; + }(SeriesModel); + + function install$m(registers) { + registers.registerChartView(HeatmapView); + registers.registerSeriesModel(HeatmapSeriesModel); + } + + var BAR_BORDER_WIDTH_QUERY$1 = ['itemStyle', 'borderWidth']; + var LAYOUT_ATTRS = [{ + xy: 'x', + wh: 'width', + index: 0, + posDesc: ['left', 'right'] + }, { + xy: 'y', + wh: 'height', + index: 1, + posDesc: ['top', 'bottom'] + }]; + var pathForLineWidth = new Circle(); + + var PictorialBarView = function (_super) { + __extends(PictorialBarView, _super); + + function PictorialBarView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = PictorialBarView.type; + return _this; + } + + PictorialBarView.prototype.render = function (seriesModel, ecModel, api) { + var group = this.group; + var data = seriesModel.getData(); + var oldData = this._data; + var cartesian = seriesModel.coordinateSystem; + var baseAxis = cartesian.getBaseAxis(); + var isHorizontal = baseAxis.isHorizontal(); + var coordSysRect = cartesian.master.getRect(); + var opt = { + ecSize: { + width: api.getWidth(), + height: api.getHeight() + }, + seriesModel: seriesModel, + coordSys: cartesian, + coordSysExtent: [[coordSysRect.x, coordSysRect.x + coordSysRect.width], [coordSysRect.y, coordSysRect.y + coordSysRect.height]], + isHorizontal: isHorizontal, + valueDim: LAYOUT_ATTRS[+isHorizontal], + categoryDim: LAYOUT_ATTRS[1 - +isHorizontal] + }; + data.diff(oldData).add(function (dataIndex) { + if (!data.hasValue(dataIndex)) { + return; + } + + var itemModel = getItemModel(data, dataIndex); + var symbolMeta = getSymbolMeta(data, dataIndex, itemModel, opt); + var bar = createBar(data, opt, symbolMeta); + data.setItemGraphicEl(dataIndex, bar); + group.add(bar); + updateCommon$1(bar, opt, symbolMeta); + }).update(function (newIndex, oldIndex) { + var bar = oldData.getItemGraphicEl(oldIndex); + + if (!data.hasValue(newIndex)) { + group.remove(bar); + return; + } + + var itemModel = getItemModel(data, newIndex); + var symbolMeta = getSymbolMeta(data, newIndex, itemModel, opt); + var pictorialShapeStr = getShapeStr(data, symbolMeta); + + if (bar && pictorialShapeStr !== bar.__pictorialShapeStr) { + group.remove(bar); + data.setItemGraphicEl(newIndex, null); + bar = null; + } + + if (bar) { + updateBar(bar, opt, symbolMeta); + } else { + bar = createBar(data, opt, symbolMeta, true); + } + + data.setItemGraphicEl(newIndex, bar); + bar.__pictorialSymbolMeta = symbolMeta; + group.add(bar); + updateCommon$1(bar, opt, symbolMeta); + }).remove(function (dataIndex) { + var bar = oldData.getItemGraphicEl(dataIndex); + bar && removeBar(oldData, dataIndex, bar.__pictorialSymbolMeta.animationModel, bar); + }).execute(); + this._data = data; + return this.group; + }; + + PictorialBarView.prototype.remove = function (ecModel, api) { + var group = this.group; + var data = this._data; + + if (ecModel.get('animation')) { + if (data) { + data.eachItemGraphicEl(function (bar) { + removeBar(data, getECData(bar).dataIndex, ecModel, bar); + }); + } + } else { + group.removeAll(); + } + }; + + PictorialBarView.type = 'pictorialBar'; + return PictorialBarView; + }(ChartView); + + function getSymbolMeta(data, dataIndex, itemModel, opt) { + var layout = data.getItemLayout(dataIndex); + var symbolRepeat = itemModel.get('symbolRepeat'); + var symbolClip = itemModel.get('symbolClip'); + var symbolPosition = itemModel.get('symbolPosition') || 'start'; + var symbolRotate = itemModel.get('symbolRotate'); + var rotation = (symbolRotate || 0) * Math.PI / 180 || 0; + var symbolPatternSize = itemModel.get('symbolPatternSize') || 2; + var isAnimationEnabled = itemModel.isAnimationEnabled(); + var symbolMeta = { + dataIndex: dataIndex, + layout: layout, + itemModel: itemModel, + symbolType: data.getItemVisual(dataIndex, 'symbol') || 'circle', + style: data.getItemVisual(dataIndex, 'style'), + symbolClip: symbolClip, + symbolRepeat: symbolRepeat, + symbolRepeatDirection: itemModel.get('symbolRepeatDirection'), + symbolPatternSize: symbolPatternSize, + rotation: rotation, + animationModel: isAnimationEnabled ? itemModel : null, + hoverScale: isAnimationEnabled && itemModel.get(['emphasis', 'scale']), + z2: itemModel.getShallow('z', true) || 0 + }; + prepareBarLength(itemModel, symbolRepeat, layout, opt, symbolMeta); + prepareSymbolSize(data, dataIndex, layout, symbolRepeat, symbolClip, symbolMeta.boundingLength, symbolMeta.pxSign, symbolPatternSize, opt, symbolMeta); + prepareLineWidth(itemModel, symbolMeta.symbolScale, rotation, opt, symbolMeta); + var symbolSize = symbolMeta.symbolSize; + var symbolOffset = itemModel.get('symbolOffset'); + + if (isArray(symbolOffset)) { + symbolOffset = [parsePercent$1(symbolOffset[0], symbolSize[0]), parsePercent$1(symbolOffset[1], symbolSize[1])]; + } + + prepareLayoutInfo(itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset, symbolPosition, symbolMeta.valueLineWidth, symbolMeta.boundingLength, symbolMeta.repeatCutLength, opt, symbolMeta); + return symbolMeta; + } + + function prepareBarLength(itemModel, symbolRepeat, layout, opt, outputSymbolMeta) { + var valueDim = opt.valueDim; + var symbolBoundingData = itemModel.get('symbolBoundingData'); + var valueAxis = opt.coordSys.getOtherAxis(opt.coordSys.getBaseAxis()); + var zeroPx = valueAxis.toGlobalCoord(valueAxis.dataToCoord(0)); + var pxSignIdx = 1 - +(layout[valueDim.wh] <= 0); + var boundingLength; + + if (isArray(symbolBoundingData)) { + var symbolBoundingExtent = [convertToCoordOnAxis(valueAxis, symbolBoundingData[0]) - zeroPx, convertToCoordOnAxis(valueAxis, symbolBoundingData[1]) - zeroPx]; + symbolBoundingExtent[1] < symbolBoundingExtent[0] && symbolBoundingExtent.reverse(); + boundingLength = symbolBoundingExtent[pxSignIdx]; + } else if (symbolBoundingData != null) { + boundingLength = convertToCoordOnAxis(valueAxis, symbolBoundingData) - zeroPx; + } else if (symbolRepeat) { + boundingLength = opt.coordSysExtent[valueDim.index][pxSignIdx] - zeroPx; + } else { + boundingLength = layout[valueDim.wh]; + } + + outputSymbolMeta.boundingLength = boundingLength; + + if (symbolRepeat) { + outputSymbolMeta.repeatCutLength = layout[valueDim.wh]; + } + + outputSymbolMeta.pxSign = boundingLength > 0 ? 1 : boundingLength < 0 ? -1 : 0; + } + + function convertToCoordOnAxis(axis, value) { + return axis.toGlobalCoord(axis.dataToCoord(axis.scale.parse(value))); + } + + function prepareSymbolSize(data, dataIndex, layout, symbolRepeat, symbolClip, boundingLength, pxSign, symbolPatternSize, opt, outputSymbolMeta) { + var valueDim = opt.valueDim; + var categoryDim = opt.categoryDim; + var categorySize = Math.abs(layout[categoryDim.wh]); + var symbolSize = data.getItemVisual(dataIndex, 'symbolSize'); + var parsedSymbolSize; + + if (isArray(symbolSize)) { + parsedSymbolSize = symbolSize.slice(); + } else { + if (symbolSize == null) { + parsedSymbolSize = ['100%', '100%']; + } else { + parsedSymbolSize = [symbolSize, symbolSize]; + } + } + + parsedSymbolSize[categoryDim.index] = parsePercent$1(parsedSymbolSize[categoryDim.index], categorySize); + parsedSymbolSize[valueDim.index] = parsePercent$1(parsedSymbolSize[valueDim.index], symbolRepeat ? categorySize : Math.abs(boundingLength)); + outputSymbolMeta.symbolSize = parsedSymbolSize; + var symbolScale = outputSymbolMeta.symbolScale = [parsedSymbolSize[0] / symbolPatternSize, parsedSymbolSize[1] / symbolPatternSize]; + symbolScale[valueDim.index] *= (opt.isHorizontal ? -1 : 1) * pxSign; + } + + function prepareLineWidth(itemModel, symbolScale, rotation, opt, outputSymbolMeta) { + var valueLineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY$1) || 0; + + if (valueLineWidth) { + pathForLineWidth.attr({ + scaleX: symbolScale[0], + scaleY: symbolScale[1], + rotation: rotation + }); + pathForLineWidth.updateTransform(); + valueLineWidth /= pathForLineWidth.getLineScale(); + valueLineWidth *= symbolScale[opt.valueDim.index]; + } + + outputSymbolMeta.valueLineWidth = valueLineWidth; + } + + function prepareLayoutInfo(itemModel, symbolSize, layout, symbolRepeat, symbolClip, symbolOffset, symbolPosition, valueLineWidth, boundingLength, repeatCutLength, opt, outputSymbolMeta) { + var categoryDim = opt.categoryDim; + var valueDim = opt.valueDim; + var pxSign = outputSymbolMeta.pxSign; + var unitLength = Math.max(symbolSize[valueDim.index] + valueLineWidth, 0); + var pathLen = unitLength; + + if (symbolRepeat) { + var absBoundingLength = Math.abs(boundingLength); + var symbolMargin = retrieve(itemModel.get('symbolMargin'), '15%') + ''; + var hasEndGap = false; + + if (symbolMargin.lastIndexOf('!') === symbolMargin.length - 1) { + hasEndGap = true; + symbolMargin = symbolMargin.slice(0, symbolMargin.length - 1); + } + + var symbolMarginNumeric = parsePercent$1(symbolMargin, symbolSize[valueDim.index]); + var uLenWithMargin = Math.max(unitLength + symbolMarginNumeric * 2, 0); + var endFix = hasEndGap ? 0 : symbolMarginNumeric * 2; + var repeatSpecified = isNumeric(symbolRepeat); + var repeatTimes = repeatSpecified ? symbolRepeat : toIntTimes((absBoundingLength + endFix) / uLenWithMargin); + var mDiff = absBoundingLength - repeatTimes * unitLength; + symbolMarginNumeric = mDiff / 2 / (hasEndGap ? repeatTimes : repeatTimes - 1); + uLenWithMargin = unitLength + symbolMarginNumeric * 2; + endFix = hasEndGap ? 0 : symbolMarginNumeric * 2; + + if (!repeatSpecified && symbolRepeat !== 'fixed') { + repeatTimes = repeatCutLength ? toIntTimes((Math.abs(repeatCutLength) + endFix) / uLenWithMargin) : 0; + } + + pathLen = repeatTimes * uLenWithMargin - endFix; + outputSymbolMeta.repeatTimes = repeatTimes; + outputSymbolMeta.symbolMargin = symbolMarginNumeric; + } + + var sizeFix = pxSign * (pathLen / 2); + var pathPosition = outputSymbolMeta.pathPosition = []; + pathPosition[categoryDim.index] = layout[categoryDim.wh] / 2; + pathPosition[valueDim.index] = symbolPosition === 'start' ? sizeFix : symbolPosition === 'end' ? boundingLength - sizeFix : boundingLength / 2; + + if (symbolOffset) { + pathPosition[0] += symbolOffset[0]; + pathPosition[1] += symbolOffset[1]; + } + + var bundlePosition = outputSymbolMeta.bundlePosition = []; + bundlePosition[categoryDim.index] = layout[categoryDim.xy]; + bundlePosition[valueDim.index] = layout[valueDim.xy]; + var barRectShape = outputSymbolMeta.barRectShape = extend({}, layout); + barRectShape[valueDim.wh] = pxSign * Math.max(Math.abs(layout[valueDim.wh]), Math.abs(pathPosition[valueDim.index] + sizeFix)); + barRectShape[categoryDim.wh] = layout[categoryDim.wh]; + var clipShape = outputSymbolMeta.clipShape = {}; + clipShape[categoryDim.xy] = -layout[categoryDim.xy]; + clipShape[categoryDim.wh] = opt.ecSize[categoryDim.wh]; + clipShape[valueDim.xy] = 0; + clipShape[valueDim.wh] = layout[valueDim.wh]; + } + + function createPath(symbolMeta) { + var symbolPatternSize = symbolMeta.symbolPatternSize; + var path = createSymbol(symbolMeta.symbolType, -symbolPatternSize / 2, -symbolPatternSize / 2, symbolPatternSize, symbolPatternSize); + path.attr({ + culling: true + }); + path.type !== 'image' && path.setStyle({ + strokeNoScale: true + }); + return path; + } + + function createOrUpdateRepeatSymbols(bar, opt, symbolMeta, isUpdate) { + var bundle = bar.__pictorialBundle; + var symbolSize = symbolMeta.symbolSize; + var valueLineWidth = symbolMeta.valueLineWidth; + var pathPosition = symbolMeta.pathPosition; + var valueDim = opt.valueDim; + var repeatTimes = symbolMeta.repeatTimes || 0; + var index = 0; + var unit = symbolSize[opt.valueDim.index] + valueLineWidth + symbolMeta.symbolMargin * 2; + eachPath(bar, function (path) { + path.__pictorialAnimationIndex = index; + path.__pictorialRepeatTimes = repeatTimes; + + if (index < repeatTimes) { + updateAttr(path, null, makeTarget(index), symbolMeta, isUpdate); + } else { + updateAttr(path, null, { + scaleX: 0, + scaleY: 0 + }, symbolMeta, isUpdate, function () { + bundle.remove(path); + }); + } + + index++; + }); + + for (; index < repeatTimes; index++) { + var path = createPath(symbolMeta); + path.__pictorialAnimationIndex = index; + path.__pictorialRepeatTimes = repeatTimes; + bundle.add(path); + var target = makeTarget(index); + updateAttr(path, { + x: target.x, + y: target.y, + scaleX: 0, + scaleY: 0 + }, { + scaleX: target.scaleX, + scaleY: target.scaleY, + rotation: target.rotation + }, symbolMeta, isUpdate); + } + + function makeTarget(index) { + var position = pathPosition.slice(); + var pxSign = symbolMeta.pxSign; + var i = index; + + if (symbolMeta.symbolRepeatDirection === 'start' ? pxSign > 0 : pxSign < 0) { + i = repeatTimes - 1 - index; + } + + position[valueDim.index] = unit * (i - repeatTimes / 2 + 0.5) + pathPosition[valueDim.index]; + return { + x: position[0], + y: position[1], + scaleX: symbolMeta.symbolScale[0], + scaleY: symbolMeta.symbolScale[1], + rotation: symbolMeta.rotation + }; + } + } + + function createOrUpdateSingleSymbol(bar, opt, symbolMeta, isUpdate) { + var bundle = bar.__pictorialBundle; + var mainPath = bar.__pictorialMainPath; + + if (!mainPath) { + mainPath = bar.__pictorialMainPath = createPath(symbolMeta); + bundle.add(mainPath); + updateAttr(mainPath, { + x: symbolMeta.pathPosition[0], + y: symbolMeta.pathPosition[1], + scaleX: 0, + scaleY: 0, + rotation: symbolMeta.rotation + }, { + scaleX: symbolMeta.symbolScale[0], + scaleY: symbolMeta.symbolScale[1] + }, symbolMeta, isUpdate); + } else { + updateAttr(mainPath, null, { + x: symbolMeta.pathPosition[0], + y: symbolMeta.pathPosition[1], + scaleX: symbolMeta.symbolScale[0], + scaleY: symbolMeta.symbolScale[1], + rotation: symbolMeta.rotation + }, symbolMeta, isUpdate); + } + } + + function createOrUpdateBarRect(bar, symbolMeta, isUpdate) { + var rectShape = extend({}, symbolMeta.barRectShape); + var barRect = bar.__pictorialBarRect; + + if (!barRect) { + barRect = bar.__pictorialBarRect = new Rect({ + z2: 2, + shape: rectShape, + silent: true, + style: { + stroke: 'transparent', + fill: 'transparent', + lineWidth: 0 + } + }); + bar.add(barRect); + } else { + updateAttr(barRect, null, { + shape: rectShape + }, symbolMeta, isUpdate); + } + } + + function createOrUpdateClip(bar, opt, symbolMeta, isUpdate) { + if (symbolMeta.symbolClip) { + var clipPath = bar.__pictorialClipPath; + var clipShape = extend({}, symbolMeta.clipShape); + var valueDim = opt.valueDim; + var animationModel = symbolMeta.animationModel; + var dataIndex = symbolMeta.dataIndex; + + if (clipPath) { + updateProps(clipPath, { + shape: clipShape + }, animationModel, dataIndex); + } else { + clipShape[valueDim.wh] = 0; + clipPath = new Rect({ + shape: clipShape + }); + + bar.__pictorialBundle.setClipPath(clipPath); + + bar.__pictorialClipPath = clipPath; + var target = {}; + target[valueDim.wh] = symbolMeta.clipShape[valueDim.wh]; + graphic[isUpdate ? 'updateProps' : 'initProps'](clipPath, { + shape: target + }, animationModel, dataIndex); + } + } + } + + function getItemModel(data, dataIndex) { + var itemModel = data.getItemModel(dataIndex); + itemModel.getAnimationDelayParams = getAnimationDelayParams; + itemModel.isAnimationEnabled = isAnimationEnabled; + return itemModel; + } + + function getAnimationDelayParams(path) { + return { + index: path.__pictorialAnimationIndex, + count: path.__pictorialRepeatTimes + }; + } + + function isAnimationEnabled() { + return this.parentModel.isAnimationEnabled() && !!this.getShallow('animation'); + } + + function createBar(data, opt, symbolMeta, isUpdate) { + var bar = new Group(); + var bundle = new Group(); + bar.add(bundle); + bar.__pictorialBundle = bundle; + bundle.x = symbolMeta.bundlePosition[0]; + bundle.y = symbolMeta.bundlePosition[1]; + + if (symbolMeta.symbolRepeat) { + createOrUpdateRepeatSymbols(bar, opt, symbolMeta); + } else { + createOrUpdateSingleSymbol(bar, opt, symbolMeta); + } + + createOrUpdateBarRect(bar, symbolMeta, isUpdate); + createOrUpdateClip(bar, opt, symbolMeta, isUpdate); + bar.__pictorialShapeStr = getShapeStr(data, symbolMeta); + bar.__pictorialSymbolMeta = symbolMeta; + return bar; + } + + function updateBar(bar, opt, symbolMeta) { + var animationModel = symbolMeta.animationModel; + var dataIndex = symbolMeta.dataIndex; + var bundle = bar.__pictorialBundle; + updateProps(bundle, { + x: symbolMeta.bundlePosition[0], + y: symbolMeta.bundlePosition[1] + }, animationModel, dataIndex); + + if (symbolMeta.symbolRepeat) { + createOrUpdateRepeatSymbols(bar, opt, symbolMeta, true); + } else { + createOrUpdateSingleSymbol(bar, opt, symbolMeta, true); + } + + createOrUpdateBarRect(bar, symbolMeta, true); + createOrUpdateClip(bar, opt, symbolMeta, true); + } + + function removeBar(data, dataIndex, animationModel, bar) { + var labelRect = bar.__pictorialBarRect; + labelRect && labelRect.removeTextContent(); + var pathes = []; + eachPath(bar, function (path) { + pathes.push(path); + }); + bar.__pictorialMainPath && pathes.push(bar.__pictorialMainPath); + bar.__pictorialClipPath && (animationModel = null); + each(pathes, function (path) { + removeElement(path, { + scaleX: 0, + scaleY: 0 + }, animationModel, dataIndex, function () { + bar.parent && bar.parent.remove(bar); + }); + }); + data.setItemGraphicEl(dataIndex, null); + } + + function getShapeStr(data, symbolMeta) { + return [data.getItemVisual(symbolMeta.dataIndex, 'symbol') || 'none', !!symbolMeta.symbolRepeat, !!symbolMeta.symbolClip].join(':'); + } + + function eachPath(bar, cb, context) { + each(bar.__pictorialBundle.children(), function (el) { + el !== bar.__pictorialBarRect && cb.call(context, el); + }); + } + + function updateAttr(el, immediateAttrs, animationAttrs, symbolMeta, isUpdate, cb) { + immediateAttrs && el.attr(immediateAttrs); + + if (symbolMeta.symbolClip && !isUpdate) { + animationAttrs && el.attr(animationAttrs); + } else { + animationAttrs && graphic[isUpdate ? 'updateProps' : 'initProps'](el, animationAttrs, symbolMeta.animationModel, symbolMeta.dataIndex, cb); + } + } + + function updateCommon$1(bar, opt, symbolMeta) { + var dataIndex = symbolMeta.dataIndex; + var itemModel = symbolMeta.itemModel; + var emphasisModel = itemModel.getModel('emphasis'); + var emphasisStyle = emphasisModel.getModel('itemStyle').getItemStyle(); + var blurStyle = itemModel.getModel(['blur', 'itemStyle']).getItemStyle(); + var selectStyle = itemModel.getModel(['select', 'itemStyle']).getItemStyle(); + var cursorStyle = itemModel.getShallow('cursor'); + var focus = emphasisModel.get('focus'); + var blurScope = emphasisModel.get('blurScope'); + var hoverScale = emphasisModel.get('scale'); + eachPath(bar, function (path) { + if (path instanceof ZRImage) { + var pathStyle = path.style; + path.useStyle(extend({ + image: pathStyle.image, + x: pathStyle.x, + y: pathStyle.y, + width: pathStyle.width, + height: pathStyle.height + }, symbolMeta.style)); + } else { + path.useStyle(symbolMeta.style); + } + + var emphasisState = path.ensureState('emphasis'); + emphasisState.style = emphasisStyle; + + if (hoverScale) { + emphasisState.scaleX = path.scaleX * 1.1; + emphasisState.scaleY = path.scaleY * 1.1; + } + + path.ensureState('blur').style = blurStyle; + path.ensureState('select').style = selectStyle; + cursorStyle && (path.cursor = cursorStyle); + path.z2 = symbolMeta.z2; + }); + var barPositionOutside = opt.valueDim.posDesc[+(symbolMeta.boundingLength > 0)]; + var barRect = bar.__pictorialBarRect; + setLabelStyle(barRect, getLabelStatesModels(itemModel), { + labelFetcher: opt.seriesModel, + labelDataIndex: dataIndex, + defaultText: getDefaultLabel(opt.seriesModel.getData(), dataIndex), + inheritColor: symbolMeta.style.fill, + defaultOpacity: symbolMeta.style.opacity, + defaultOutsidePosition: barPositionOutside + }); + enableHoverEmphasis(bar, focus, blurScope); + } + + function toIntTimes(times) { + var roundedTimes = Math.round(times); + return Math.abs(times - roundedTimes) < 1e-4 ? roundedTimes : Math.ceil(times); + } + + var PictorialBarSeriesModel = function (_super) { + __extends(PictorialBarSeriesModel, _super); + + function PictorialBarSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = PictorialBarSeriesModel.type; + _this.hasSymbolVisual = true; + _this.defaultSymbol = 'roundRect'; + return _this; + } + + PictorialBarSeriesModel.prototype.getInitialData = function (option) { + option.stack = null; + return _super.prototype.getInitialData.apply(this, arguments); + }; + + PictorialBarSeriesModel.type = 'series.pictorialBar'; + PictorialBarSeriesModel.dependencies = ['grid']; + PictorialBarSeriesModel.defaultOption = inheritDefaultOption(BaseBarSeriesModel.defaultOption, { + symbol: 'circle', + symbolSize: null, + symbolRotate: null, + symbolPosition: null, + symbolOffset: null, + symbolMargin: null, + symbolRepeat: false, + symbolRepeatDirection: 'end', + symbolClip: false, + symbolBoundingData: null, + symbolPatternSize: 400, + barGap: '-100%', + progressive: 0, + emphasis: { + scale: false + }, + select: { + itemStyle: { + borderColor: '#212121' + } + } + }); + return PictorialBarSeriesModel; + }(BaseBarSeriesModel); + + function install$n(registers) { + registers.registerChartView(PictorialBarView); + registers.registerSeriesModel(PictorialBarSeriesModel); + registers.registerLayout(curry(layout, 'pictorialBar')); + } + + var ThemeRiverView = function (_super) { + __extends(ThemeRiverView, _super); + + function ThemeRiverView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ThemeRiverView.type; + _this._layers = []; + return _this; + } + + ThemeRiverView.prototype.render = function (seriesModel, ecModel, api) { + var data = seriesModel.getData(); + var self = this; + var group = this.group; + var layersSeries = seriesModel.getLayerSeries(); + var layoutInfo = data.getLayout('layoutInfo'); + var rect = layoutInfo.rect; + var boundaryGap = layoutInfo.boundaryGap; + group.x = 0; + group.y = rect.y + boundaryGap[0]; + + function keyGetter(item) { + return item.name; + } + + var dataDiffer = new DataDiffer(this._layersSeries || [], layersSeries, keyGetter, keyGetter); + var newLayersGroups = []; + dataDiffer.add(bind(process, this, 'add')).update(bind(process, this, 'update')).remove(bind(process, this, 'remove')).execute(); + + function process(status, idx, oldIdx) { + var oldLayersGroups = self._layers; + + if (status === 'remove') { + group.remove(oldLayersGroups[idx]); + return; + } + + var points0 = []; + var points1 = []; + var style; + var indices = layersSeries[idx].indices; + var j = 0; + + for (; j < indices.length; j++) { + var layout = data.getItemLayout(indices[j]); + var x = layout.x; + var y0 = layout.y0; + var y = layout.y; + points0.push(x, y0); + points1.push(x, y0 + y); + style = data.getItemVisual(indices[j], 'style'); + } + + var polygon; + var textLayout = data.getItemLayout(indices[0]); + var labelModel = seriesModel.getModel('label'); + var margin = labelModel.get('margin'); + var emphasisModel = seriesModel.getModel('emphasis'); + + if (status === 'add') { + var layerGroup = newLayersGroups[idx] = new Group(); + polygon = new ECPolygon({ + shape: { + points: points0, + stackedOnPoints: points1, + smooth: 0.4, + stackedOnSmooth: 0.4, + smoothConstraint: false + }, + z2: 0 + }); + layerGroup.add(polygon); + group.add(layerGroup); + + if (seriesModel.isAnimationEnabled()) { + polygon.setClipPath(createGridClipShape$2(polygon.getBoundingRect(), seriesModel, function () { + polygon.removeClipPath(); + })); + } + } else { + var layerGroup = oldLayersGroups[oldIdx]; + polygon = layerGroup.childAt(0); + group.add(layerGroup); + newLayersGroups[idx] = layerGroup; + updateProps(polygon, { + shape: { + points: points0, + stackedOnPoints: points1 + } + }, seriesModel); + } + + setLabelStyle(polygon, getLabelStatesModels(seriesModel), { + labelDataIndex: indices[j - 1], + defaultText: data.getName(indices[j - 1]), + inheritColor: style.fill + }, { + normal: { + verticalAlign: 'middle' + } + }); + polygon.setTextConfig({ + position: null, + local: true + }); + var labelEl = polygon.getTextContent(); + + if (labelEl) { + labelEl.x = textLayout.x - margin; + labelEl.y = textLayout.y0 + textLayout.y / 2; + } + + polygon.useStyle(style); + data.setItemGraphicEl(idx, polygon); + setStatesStylesFromModel(polygon, seriesModel); + enableHoverEmphasis(polygon, emphasisModel.get('focus'), emphasisModel.get('blurScope')); + } + + this._layersSeries = layersSeries; + this._layers = newLayersGroups; + }; + + ThemeRiverView.type = 'themeRiver'; + return ThemeRiverView; + }(ChartView); + + function createGridClipShape$2(rect, seriesModel, cb) { + var rectEl = new Rect({ + shape: { + x: rect.x - 10, + y: rect.y - 10, + width: 0, + height: rect.height + 20 + } + }); + initProps(rectEl, { + shape: { + x: rect.x - 50, + width: rect.width + 100, + height: rect.height + 20 + } + }, seriesModel, cb); + return rectEl; + } + + var DATA_NAME_INDEX = 2; + + var ThemeRiverSeriesModel = function (_super) { + __extends(ThemeRiverSeriesModel, _super); + + function ThemeRiverSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ThemeRiverSeriesModel.type; + _this.useColorPaletteOnData = true; + return _this; + } + + ThemeRiverSeriesModel.prototype.init = function (option) { + _super.prototype.init.apply(this, arguments); + + this.legendVisualProvider = new LegendVisualProvider(bind(this.getData, this), bind(this.getRawData, this)); + }; + + ThemeRiverSeriesModel.prototype.fixData = function (data) { + var rawDataLength = data.length; + var timeValueKeys = {}; + var groupResult = groupData(data, function (item) { + if (!timeValueKeys.hasOwnProperty(item[0] + '')) { + timeValueKeys[item[0] + ''] = -1; + } + + return item[2]; + }); + var layerData = []; + groupResult.buckets.each(function (items, key) { + layerData.push({ + name: key, + dataList: items + }); + }); + var layerNum = layerData.length; + + for (var k = 0; k < layerNum; ++k) { + var name_1 = layerData[k].name; + + for (var j = 0; j < layerData[k].dataList.length; ++j) { + var timeValue = layerData[k].dataList[j][0] + ''; + timeValueKeys[timeValue] = k; + } + + for (var timeValue in timeValueKeys) { + if (timeValueKeys.hasOwnProperty(timeValue) && timeValueKeys[timeValue] !== k) { + timeValueKeys[timeValue] = k; + data[rawDataLength] = [timeValue, 0, name_1]; + rawDataLength++; + } + } + } + + return data; + }; + + ThemeRiverSeriesModel.prototype.getInitialData = function (option, ecModel) { + var singleAxisModel = this.getReferringComponents('singleAxis', SINGLE_REFERRING).models[0]; + var axisType = singleAxisModel.get('type'); + var filterData = filter(option.data, function (dataItem) { + return dataItem[2] !== undefined; + }); + var data = this.fixData(filterData || []); + var nameList = []; + var nameMap = this.nameMap = createHashMap(); + var count = 0; + + for (var i = 0; i < data.length; ++i) { + nameList.push(data[i][DATA_NAME_INDEX]); + + if (!nameMap.get(data[i][DATA_NAME_INDEX])) { + nameMap.set(data[i][DATA_NAME_INDEX], count); + count++; + } + } + + var dimensionsInfo = createDimensions(data, { + coordDimensions: ['single'], + dimensionsDefine: [{ + name: 'time', + type: getDimensionTypeByAxis(axisType) + }, { + name: 'value', + type: 'float' + }, { + name: 'name', + type: 'ordinal' + }], + encodeDefine: { + single: 0, + value: 1, + itemName: 2 + } + }); + var list = new List(dimensionsInfo, this); + list.initData(data); + return list; + }; + + ThemeRiverSeriesModel.prototype.getLayerSeries = function () { + var data = this.getData(); + var lenCount = data.count(); + var indexArr = []; + + for (var i = 0; i < lenCount; ++i) { + indexArr[i] = i; + } + + var timeDim = data.mapDimension('single'); + var groupResult = groupData(indexArr, function (index) { + return data.get('name', index); + }); + var layerSeries = []; + groupResult.buckets.each(function (items, key) { + items.sort(function (index1, index2) { + return data.get(timeDim, index1) - data.get(timeDim, index2); + }); + layerSeries.push({ + name: key, + indices: items + }); + }); + return layerSeries; + }; + + ThemeRiverSeriesModel.prototype.getAxisTooltipData = function (dim, value, baseAxis) { + if (!isArray(dim)) { + dim = dim ? [dim] : []; + } + + var data = this.getData(); + var layerSeries = this.getLayerSeries(); + var indices = []; + var layerNum = layerSeries.length; + var nestestValue; + + for (var i = 0; i < layerNum; ++i) { + var minDist = Number.MAX_VALUE; + var nearestIdx = -1; + var pointNum = layerSeries[i].indices.length; + + for (var j = 0; j < pointNum; ++j) { + var theValue = data.get(dim[0], layerSeries[i].indices[j]); + var dist = Math.abs(theValue - value); + + if (dist <= minDist) { + nestestValue = theValue; + minDist = dist; + nearestIdx = layerSeries[i].indices[j]; + } + } + + indices.push(nearestIdx); + } + + return { + dataIndices: indices, + nestestValue: nestestValue + }; + }; + + ThemeRiverSeriesModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + var data = this.getData(); + var name = data.getName(dataIndex); + var value = data.get(data.mapDimension('value'), dataIndex); + return createTooltipMarkup('nameValue', { + name: name, + value: value + }); + }; + + ThemeRiverSeriesModel.type = 'series.themeRiver'; + ThemeRiverSeriesModel.dependencies = ['singleAxis']; + ThemeRiverSeriesModel.defaultOption = { + zlevel: 0, + z: 2, + coordinateSystem: 'singleAxis', + boundaryGap: ['10%', '10%'], + singleAxisIndex: 0, + animationEasing: 'linear', + label: { + margin: 4, + show: true, + position: 'left', + fontSize: 11 + }, + emphasis: { + label: { + show: true + } + } + }; + return ThemeRiverSeriesModel; + }(SeriesModel); + + function themeRiverLayout(ecModel, api) { + ecModel.eachSeriesByType('themeRiver', function (seriesModel) { + var data = seriesModel.getData(); + var single = seriesModel.coordinateSystem; + var layoutInfo = {}; + var rect = single.getRect(); + layoutInfo.rect = rect; + var boundaryGap = seriesModel.get('boundaryGap'); + var axis = single.getAxis(); + layoutInfo.boundaryGap = boundaryGap; + + if (axis.orient === 'horizontal') { + boundaryGap[0] = parsePercent$1(boundaryGap[0], rect.height); + boundaryGap[1] = parsePercent$1(boundaryGap[1], rect.height); + var height = rect.height - boundaryGap[0] - boundaryGap[1]; + doThemeRiverLayout(data, seriesModel, height); + } else { + boundaryGap[0] = parsePercent$1(boundaryGap[0], rect.width); + boundaryGap[1] = parsePercent$1(boundaryGap[1], rect.width); + var width = rect.width - boundaryGap[0] - boundaryGap[1]; + doThemeRiverLayout(data, seriesModel, width); + } + + data.setLayout('layoutInfo', layoutInfo); + }); + } + + function doThemeRiverLayout(data, seriesModel, height) { + if (!data.count()) { + return; + } + + var coordSys = seriesModel.coordinateSystem; + var layerSeries = seriesModel.getLayerSeries(); + var timeDim = data.mapDimension('single'); + var valueDim = data.mapDimension('value'); + var layerPoints = map(layerSeries, function (singleLayer) { + return map(singleLayer.indices, function (idx) { + var pt = coordSys.dataToPoint(data.get(timeDim, idx)); + pt[1] = data.get(valueDim, idx); + return pt; + }); + }); + var base = computeBaseline(layerPoints); + var baseLine = base.y0; + var ky = height / base.max; + var n = layerSeries.length; + var m = layerSeries[0].indices.length; + var baseY0; + + for (var j = 0; j < m; ++j) { + baseY0 = baseLine[j] * ky; + data.setItemLayout(layerSeries[0].indices[j], { + layerIndex: 0, + x: layerPoints[0][j][0], + y0: baseY0, + y: layerPoints[0][j][1] * ky + }); + + for (var i = 1; i < n; ++i) { + baseY0 += layerPoints[i - 1][j][1] * ky; + data.setItemLayout(layerSeries[i].indices[j], { + layerIndex: i, + x: layerPoints[i][j][0], + y0: baseY0, + y: layerPoints[i][j][1] * ky + }); + } + } + } + + function computeBaseline(data) { + var layerNum = data.length; + var pointNum = data[0].length; + var sums = []; + var y0 = []; + var max = 0; + + for (var i = 0; i < pointNum; ++i) { + var temp = 0; + + for (var j = 0; j < layerNum; ++j) { + temp += data[j][i][1]; + } + + if (temp > max) { + max = temp; + } + + sums.push(temp); + } + + for (var k = 0; k < pointNum; ++k) { + y0[k] = (max - sums[k]) / 2; + } + + max = 0; + + for (var l = 0; l < pointNum; ++l) { + var sum = sums[l] + y0[l]; + + if (sum > max) { + max = sum; + } + } + + return { + y0: y0, + max: max + }; + } + + function install$o(registers) { + registers.registerChartView(ThemeRiverView); + registers.registerSeriesModel(ThemeRiverSeriesModel); + registers.registerLayout(themeRiverLayout); + registers.registerProcessor(dataFilter('themeRiver')); + } + + var DEFAULT_SECTOR_Z = 2; + var DEFAULT_TEXT_Z = 4; + + var SunburstPiece = function (_super) { + __extends(SunburstPiece, _super); + + function SunburstPiece(node, seriesModel, ecModel, api) { + var _this = _super.call(this) || this; + + _this.z2 = DEFAULT_SECTOR_Z; + _this.textConfig = { + inside: true + }; + getECData(_this).seriesIndex = seriesModel.seriesIndex; + var text = new ZRText({ + z2: DEFAULT_TEXT_Z, + silent: node.getModel().get(['label', 'silent']) + }); + + _this.setTextContent(text); + + _this.updateData(true, node, seriesModel, ecModel, api); + + return _this; + } + + SunburstPiece.prototype.updateData = function (firstCreate, node, seriesModel, ecModel, api) { + this.node = node; + node.piece = this; + seriesModel = seriesModel || this._seriesModel; + ecModel = ecModel || this._ecModel; + var sector = this; + getECData(sector).dataIndex = node.dataIndex; + var itemModel = node.getModel(); + var emphasisModel = itemModel.getModel('emphasis'); + var layout = node.getLayout(); + var sectorShape = extend({}, layout); + sectorShape.label = null; + var normalStyle = node.getVisual('style'); + normalStyle.lineJoin = 'bevel'; + var decal = node.getVisual('decal'); + + if (decal) { + normalStyle.decal = createOrUpdatePatternFromDecal(decal, api); + } + + var cornerRadius = getSectorCornerRadius(itemModel.getModel('itemStyle'), sectorShape); + extend(sectorShape, cornerRadius); + each(SPECIAL_STATES, function (stateName) { + var state = sector.ensureState(stateName); + var itemStyleModel = itemModel.getModel([stateName, 'itemStyle']); + state.style = itemStyleModel.getItemStyle(); + var cornerRadius = getSectorCornerRadius(itemStyleModel, sectorShape); + + if (cornerRadius) { + state.shape = cornerRadius; + } + }); + + if (firstCreate) { + sector.setShape(sectorShape); + sector.shape.r = layout.r0; + updateProps(sector, { + shape: { + r: layout.r + } + }, seriesModel, node.dataIndex); + } else { + updateProps(sector, { + shape: sectorShape + }, seriesModel); + } + + sector.useStyle(normalStyle); + + this._updateLabel(seriesModel); + + var cursorStyle = itemModel.getShallow('cursor'); + cursorStyle && sector.attr('cursor', cursorStyle); + this._seriesModel = seriesModel || this._seriesModel; + this._ecModel = ecModel || this._ecModel; + var focus = emphasisModel.get('focus'); + var focusDataIndices = focus === 'ancestor' ? node.getAncestorsIndices() : focus === 'descendant' ? node.getDescendantIndices() : null; + enableHoverEmphasis(this, focusDataIndices || focus, emphasisModel.get('blurScope')); + }; + + SunburstPiece.prototype._updateLabel = function (seriesModel) { + var _this = this; + + var itemModel = this.node.getModel(); + var normalLabelModel = itemModel.getModel('label'); + var layout = this.node.getLayout(); + var angle = layout.endAngle - layout.startAngle; + var midAngle = (layout.startAngle + layout.endAngle) / 2; + var dx = Math.cos(midAngle); + var dy = Math.sin(midAngle); + var sector = this; + var label = sector.getTextContent(); + var dataIndex = this.node.dataIndex; + var labelMinAngle = normalLabelModel.get('minAngle') / 180 * Math.PI; + var isNormalShown = normalLabelModel.get('show') && !(labelMinAngle != null && Math.abs(angle) < labelMinAngle); + label.ignore = !isNormalShown; + each(DISPLAY_STATES, function (stateName) { + var labelStateModel = stateName === 'normal' ? itemModel.getModel('label') : itemModel.getModel([stateName, 'label']); + var isNormal = stateName === 'normal'; + var state = isNormal ? label : label.ensureState(stateName); + var text = seriesModel.getFormattedLabel(dataIndex, stateName); + + if (isNormal) { + text = text || _this.node.name; + } + + state.style = createTextStyle(labelStateModel, {}, null, stateName !== 'normal', true); + + if (text) { + state.style.text = text; + } + + var isShown = labelStateModel.get('show'); + + if (isShown != null && !isNormal) { + state.ignore = !isShown; + } + + var labelPosition = getLabelAttr(labelStateModel, 'position'); + var sectorState = isNormal ? sector : sector.states[stateName]; + var labelColor = sectorState.style.fill; + sectorState.textConfig = { + outsideFill: labelStateModel.get('color') === 'inherit' ? labelColor : null, + inside: labelPosition !== 'outside' + }; + var r; + var labelPadding = getLabelAttr(labelStateModel, 'distance') || 0; + var textAlign = getLabelAttr(labelStateModel, 'align'); + + if (labelPosition === 'outside') { + r = layout.r + labelPadding; + textAlign = midAngle > Math.PI / 2 ? 'right' : 'left'; + } else { + if (!textAlign || textAlign === 'center') { + r = (layout.r + layout.r0) / 2; + textAlign = 'center'; + } else if (textAlign === 'left') { + r = layout.r0 + labelPadding; + + if (midAngle > Math.PI / 2) { + textAlign = 'right'; + } + } else if (textAlign === 'right') { + r = layout.r - labelPadding; + + if (midAngle > Math.PI / 2) { + textAlign = 'left'; + } + } + } + + state.style.align = textAlign; + state.style.verticalAlign = getLabelAttr(labelStateModel, 'verticalAlign') || 'middle'; + state.x = r * dx + layout.cx; + state.y = r * dy + layout.cy; + var rotateType = getLabelAttr(labelStateModel, 'rotate'); + var rotate = 0; + + if (rotateType === 'radial') { + rotate = -midAngle; + + if (rotate < -Math.PI / 2) { + rotate += Math.PI; + } + } else if (rotateType === 'tangential') { + rotate = Math.PI / 2 - midAngle; + + if (rotate > Math.PI / 2) { + rotate -= Math.PI; + } else if (rotate < -Math.PI / 2) { + rotate += Math.PI; + } + } else if (typeof rotateType === 'number') { + rotate = rotateType * Math.PI / 180; + } + + state.rotation = rotate; + }); + + function getLabelAttr(model, name) { + var stateAttr = model.get(name); + + if (stateAttr == null) { + return normalLabelModel.get(name); + } + + return stateAttr; + } + + label.dirtyStyle(); + }; + + return SunburstPiece; + }(Sector); + + var ROOT_TO_NODE_ACTION = 'sunburstRootToNode'; + var HIGHLIGHT_ACTION = 'sunburstHighlight'; + var UNHIGHLIGHT_ACTION = 'sunburstUnhighlight'; + function installSunburstAction(registers) { + registers.registerAction({ + type: ROOT_TO_NODE_ACTION, + update: 'updateView' + }, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'series', + subType: 'sunburst', + query: payload + }, handleRootToNode); + + function handleRootToNode(model, index) { + var targetInfo = retrieveTargetInfo(payload, [ROOT_TO_NODE_ACTION], model); + + if (targetInfo) { + var originViewRoot = model.getViewRoot(); + + if (originViewRoot) { + payload.direction = aboveViewRoot(originViewRoot, targetInfo.node) ? 'rollUp' : 'drillDown'; + } + + model.resetViewRoot(targetInfo.node); + } + } + }); + registers.registerAction({ + type: HIGHLIGHT_ACTION, + update: 'none' + }, function (payload, ecModel, api) { + payload = extend({}, payload); + ecModel.eachComponent({ + mainType: 'series', + subType: 'sunburst', + query: payload + }, handleHighlight); + + function handleHighlight(model) { + var targetInfo = retrieveTargetInfo(payload, [HIGHLIGHT_ACTION], model); + + if (targetInfo) { + payload.dataIndex = targetInfo.node.dataIndex; + } + } + + if ("development" !== 'production') { + deprecateReplaceLog('highlight', 'sunburstHighlight'); + } + + api.dispatchAction(extend(payload, { + type: 'highlight' + })); + }); + registers.registerAction({ + type: UNHIGHLIGHT_ACTION, + update: 'updateView' + }, function (payload, ecModel, api) { + payload = extend({}, payload); + + if ("development" !== 'production') { + deprecateReplaceLog('downplay', 'sunburstUnhighlight'); + } + + api.dispatchAction(extend(payload, { + type: 'downplay' + })); + }); + } + + var SunburstView = function (_super) { + __extends(SunburstView, _super); + + function SunburstView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SunburstView.type; + return _this; + } + + SunburstView.prototype.render = function (seriesModel, ecModel, api, payload) { + var self = this; + this.seriesModel = seriesModel; + this.api = api; + this.ecModel = ecModel; + var data = seriesModel.getData(); + var virtualRoot = data.tree.root; + var newRoot = seriesModel.getViewRoot(); + var group = this.group; + var renderLabelForZeroData = seriesModel.get('renderLabelForZeroData'); + var newChildren = []; + newRoot.eachNode(function (node) { + newChildren.push(node); + }); + var oldChildren = this._oldChildren || []; + dualTravel(newChildren, oldChildren); + renderRollUp(virtualRoot, newRoot); + + this._initEvents(); + + this._oldChildren = newChildren; + + function dualTravel(newChildren, oldChildren) { + if (newChildren.length === 0 && oldChildren.length === 0) { + return; + } + + new DataDiffer(oldChildren, newChildren, getKey, getKey).add(processNode).update(processNode).remove(curry(processNode, null)).execute(); + + function getKey(node) { + return node.getId(); + } + + function processNode(newIdx, oldIdx) { + var newNode = newIdx == null ? null : newChildren[newIdx]; + var oldNode = oldIdx == null ? null : oldChildren[oldIdx]; + doRenderNode(newNode, oldNode); + } + } + + function doRenderNode(newNode, oldNode) { + if (!renderLabelForZeroData && newNode && !newNode.getValue()) { + newNode = null; + } + + if (newNode !== virtualRoot && oldNode !== virtualRoot) { + if (oldNode && oldNode.piece) { + if (newNode) { + oldNode.piece.updateData(false, newNode, seriesModel, ecModel, api); + data.setItemGraphicEl(newNode.dataIndex, oldNode.piece); + } else { + removeNode(oldNode); + } + } else if (newNode) { + var piece = new SunburstPiece(newNode, seriesModel, ecModel, api); + group.add(piece); + data.setItemGraphicEl(newNode.dataIndex, piece); + } + } + } + + function removeNode(node) { + if (!node) { + return; + } + + if (node.piece) { + group.remove(node.piece); + node.piece = null; + } + } + + function renderRollUp(virtualRoot, viewRoot) { + if (viewRoot.depth > 0) { + if (self.virtualPiece) { + self.virtualPiece.updateData(false, virtualRoot, seriesModel, ecModel, api); + } else { + self.virtualPiece = new SunburstPiece(virtualRoot, seriesModel, ecModel, api); + group.add(self.virtualPiece); + } + + viewRoot.piece.off('click'); + self.virtualPiece.on('click', function (e) { + self._rootToNode(viewRoot.parentNode); + }); + } else if (self.virtualPiece) { + group.remove(self.virtualPiece); + self.virtualPiece = null; + } + } + }; + + SunburstView.prototype._initEvents = function () { + var _this = this; + + this.group.off('click'); + this.group.on('click', function (e) { + var targetFound = false; + + var viewRoot = _this.seriesModel.getViewRoot(); + + viewRoot.eachNode(function (node) { + if (!targetFound && node.piece && node.piece === e.target) { + var nodeClick = node.getModel().get('nodeClick'); + + if (nodeClick === 'rootToNode') { + _this._rootToNode(node); + } else if (nodeClick === 'link') { + var itemModel = node.getModel(); + var link = itemModel.get('link'); + + if (link) { + var linkTarget = itemModel.get('target', true) || '_blank'; + windowOpen(link, linkTarget); + } + } + + targetFound = true; + } + }); + }); + }; + + SunburstView.prototype._rootToNode = function (node) { + if (node !== this.seriesModel.getViewRoot()) { + this.api.dispatchAction({ + type: ROOT_TO_NODE_ACTION, + from: this.uid, + seriesId: this.seriesModel.id, + targetNode: node + }); + } + }; + + SunburstView.prototype.containPoint = function (point, seriesModel) { + var treeRoot = seriesModel.getData(); + var itemLayout = treeRoot.getItemLayout(0); + + if (itemLayout) { + var dx = point[0] - itemLayout.cx; + var dy = point[1] - itemLayout.cy; + var radius = Math.sqrt(dx * dx + dy * dy); + return radius <= itemLayout.r && radius >= itemLayout.r0; + } + }; + + SunburstView.type = 'sunburst'; + return SunburstView; + }(ChartView); + + var SunburstSeriesModel = function (_super) { + __extends(SunburstSeriesModel, _super); + + function SunburstSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SunburstSeriesModel.type; + _this.ignoreStyleOnData = true; + return _this; + } + + SunburstSeriesModel.prototype.getInitialData = function (option, ecModel) { + var root = { + name: option.name, + children: option.data + }; + completeTreeValue$1(root); + var levelModels = map(option.levels || [], function (levelDefine) { + return new Model(levelDefine, this, ecModel); + }, this); + var tree = Tree.createTree(root, this, beforeLink); + + function beforeLink(nodeData) { + nodeData.wrapMethod('getItemModel', function (model, idx) { + var node = tree.getNodeByDataIndex(idx); + var levelModel = levelModels[node.depth]; + levelModel && (model.parentModel = levelModel); + return model; + }); + } + + return tree.data; + }; + + SunburstSeriesModel.prototype.optionUpdated = function () { + this.resetViewRoot(); + }; + + SunburstSeriesModel.prototype.getDataParams = function (dataIndex) { + var params = _super.prototype.getDataParams.apply(this, arguments); + + var node = this.getData().tree.getNodeByDataIndex(dataIndex); + params.treePathInfo = wrapTreePathInfo(node, this); + return params; + }; + + SunburstSeriesModel.prototype.getViewRoot = function () { + return this._viewRoot; + }; + + SunburstSeriesModel.prototype.resetViewRoot = function (viewRoot) { + viewRoot ? this._viewRoot = viewRoot : viewRoot = this._viewRoot; + var root = this.getRawData().tree.root; + + if (!viewRoot || viewRoot !== root && !root.contains(viewRoot)) { + this._viewRoot = root; + } + }; + + SunburstSeriesModel.prototype.enableAriaDecal = function () { + enableAriaDecalForTree(this); + }; + + SunburstSeriesModel.type = 'series.sunburst'; + SunburstSeriesModel.defaultOption = { + zlevel: 0, + z: 2, + center: ['50%', '50%'], + radius: [0, '75%'], + clockwise: true, + startAngle: 90, + minAngle: 0, + stillShowZeroSum: true, + nodeClick: 'rootToNode', + renderLabelForZeroData: false, + label: { + rotate: 'radial', + show: true, + opacity: 1, + align: 'center', + position: 'inside', + distance: 5, + silent: true + }, + itemStyle: { + borderWidth: 1, + borderColor: 'white', + borderType: 'solid', + shadowBlur: 0, + shadowColor: 'rgba(0, 0, 0, 0.2)', + shadowOffsetX: 0, + shadowOffsetY: 0, + opacity: 1 + }, + emphasis: { + focus: 'descendant' + }, + blur: { + itemStyle: { + opacity: 0.2 + }, + label: { + opacity: 0.1 + } + }, + animationType: 'expansion', + animationDuration: 1000, + animationDurationUpdate: 500, + data: [], + levels: [], + sort: 'desc' + }; + return SunburstSeriesModel; + }(SeriesModel); + + function completeTreeValue$1(dataNode) { + var sum = 0; + each(dataNode.children, function (child) { + completeTreeValue$1(child); + var childValue = child.value; + isArray(childValue) && (childValue = childValue[0]); + sum += childValue; + }); + var thisValue = dataNode.value; + + if (isArray(thisValue)) { + thisValue = thisValue[0]; + } + + if (thisValue == null || isNaN(thisValue)) { + thisValue = sum; + } + + if (thisValue < 0) { + thisValue = 0; + } + + isArray(dataNode.value) ? dataNode.value[0] = thisValue : dataNode.value = thisValue; + } + + var RADIAN$2 = Math.PI / 180; + function sunburstLayout(seriesType, ecModel, api) { + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + var center = seriesModel.get('center'); + var radius = seriesModel.get('radius'); + + if (!isArray(radius)) { + radius = [0, radius]; + } + + if (!isArray(center)) { + center = [center, center]; + } + + var width = api.getWidth(); + var height = api.getHeight(); + var size = Math.min(width, height); + var cx = parsePercent$1(center[0], width); + var cy = parsePercent$1(center[1], height); + var r0 = parsePercent$1(radius[0], size / 2); + var r = parsePercent$1(radius[1], size / 2); + var startAngle = -seriesModel.get('startAngle') * RADIAN$2; + var minAngle = seriesModel.get('minAngle') * RADIAN$2; + var virtualRoot = seriesModel.getData().tree.root; + var treeRoot = seriesModel.getViewRoot(); + var rootDepth = treeRoot.depth; + var sort = seriesModel.get('sort'); + + if (sort != null) { + initChildren$1(treeRoot, sort); + } + + var validDataCount = 0; + each(treeRoot.children, function (child) { + !isNaN(child.getValue()) && validDataCount++; + }); + var sum = treeRoot.getValue(); + var unitRadian = Math.PI / (sum || validDataCount) * 2; + var renderRollupNode = treeRoot.depth > 0; + var levels = treeRoot.height - (renderRollupNode ? -1 : 1); + var rPerLevel = (r - r0) / (levels || 1); + var clockwise = seriesModel.get('clockwise'); + var stillShowZeroSum = seriesModel.get('stillShowZeroSum'); + var dir = clockwise ? 1 : -1; + + var renderNode = function (node, startAngle) { + if (!node) { + return; + } + + var endAngle = startAngle; + + if (node !== virtualRoot) { + var value = node.getValue(); + var angle = sum === 0 && stillShowZeroSum ? unitRadian : value * unitRadian; + + if (angle < minAngle) { + angle = minAngle; + } + + endAngle = startAngle + dir * angle; + var depth = node.depth - rootDepth - (renderRollupNode ? -1 : 1); + var rStart = r0 + rPerLevel * depth; + var rEnd = r0 + rPerLevel * (depth + 1); + var itemModel = node.getModel(); + + if (itemModel.get('r0') != null) { + rStart = parsePercent$1(itemModel.get('r0'), size / 2); + } + + if (itemModel.get('r') != null) { + rEnd = parsePercent$1(itemModel.get('r'), size / 2); + } + + node.setLayout({ + angle: angle, + startAngle: startAngle, + endAngle: endAngle, + clockwise: clockwise, + cx: cx, + cy: cy, + r0: rStart, + r: rEnd + }); + } + + if (node.children && node.children.length) { + var siblingAngle_1 = 0; + each(node.children, function (node) { + siblingAngle_1 += renderNode(node, startAngle + siblingAngle_1); + }); + } + + return endAngle - startAngle; + }; + + if (renderRollupNode) { + var rStart = r0; + var rEnd = r0 + rPerLevel; + var angle = Math.PI * 2; + virtualRoot.setLayout({ + angle: angle, + startAngle: startAngle, + endAngle: startAngle + angle, + clockwise: clockwise, + cx: cx, + cy: cy, + r0: rStart, + r: rEnd + }); + } + + renderNode(treeRoot, startAngle); + }); + } + + function initChildren$1(node, sortOrder) { + var children = node.children || []; + node.children = sort$2(children, sortOrder); + + if (children.length) { + each(node.children, function (child) { + initChildren$1(child, sortOrder); + }); + } + } + + function sort$2(children, sortOrder) { + if (typeof sortOrder === 'function') { + var sortTargets = map(children, function (child, idx) { + var value = child.getValue(); + return { + params: { + depth: child.depth, + height: child.height, + dataIndex: child.dataIndex, + getValue: function () { + return value; + } + }, + index: idx + }; + }); + sortTargets.sort(function (a, b) { + return sortOrder(a.params, b.params); + }); + return map(sortTargets, function (target) { + return children[target.index]; + }); + } else { + var isAsc_1 = sortOrder === 'asc'; + return children.sort(function (a, b) { + var diff = (a.getValue() - b.getValue()) * (isAsc_1 ? 1 : -1); + return diff === 0 ? (a.dataIndex - b.dataIndex) * (isAsc_1 ? -1 : 1) : diff; + }); + } + } + + function sunburstVisual(ecModel) { + var paletteScope = {}; + + function pickColor(node, seriesModel, treeHeight) { + var current = node; + + while (current && current.depth > 1) { + current = current.parentNode; + } + + var color = seriesModel.getColorFromPalette(current.name || current.dataIndex + '', paletteScope); + + if (node.depth > 1 && typeof color === 'string') { + color = lift(color, (node.depth - 1) / (treeHeight - 1) * 0.5); + } + + return color; + } + + ecModel.eachSeriesByType('sunburst', function (seriesModel) { + var data = seriesModel.getData(); + var tree = data.tree; + tree.eachNode(function (node) { + var model = node.getModel(); + var style = model.getModel('itemStyle').getItemStyle(); + + if (!style.fill) { + style.fill = pickColor(node, seriesModel, tree.root.height); + } + + var existsStyle = data.ensureUniqueItemVisual(node.dataIndex, 'style'); + extend(existsStyle, style); + }); + }); + } + + function install$p(registers) { + registers.registerChartView(SunburstView); + registers.registerSeriesModel(SunburstSeriesModel); + registers.registerLayout(curry(sunburstLayout, 'sunburst')); + registers.registerProcessor(curry(dataFilter, 'sunburst')); + registers.registerVisual(sunburstVisual); + installSunburstAction(registers); + } + + function dataToCoordSize(dataSize, dataItem) { + dataItem = dataItem || [0, 0]; + return map(['x', 'y'], function (dim, dimIdx) { + var axis = this.getAxis(dim); + var val = dataItem[dimIdx]; + var halfSize = dataSize[dimIdx] / 2; + return axis.type === 'category' ? axis.getBandWidth() : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize)); + }, this); + } + + function cartesianPrepareCustom(coordSys) { + var rect = coordSys.master.getRect(); + return { + coordSys: { + type: 'cartesian2d', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + }, + api: { + coord: function (data) { + return coordSys.dataToPoint(data); + }, + size: bind(dataToCoordSize, coordSys) + } + }; + } + + function dataToCoordSize$1(dataSize, dataItem) { + dataItem = dataItem || [0, 0]; + return map([0, 1], function (dimIdx) { + var val = dataItem[dimIdx]; + var halfSize = dataSize[dimIdx] / 2; + var p1 = []; + var p2 = []; + p1[dimIdx] = val - halfSize; + p2[dimIdx] = val + halfSize; + p1[1 - dimIdx] = p2[1 - dimIdx] = dataItem[1 - dimIdx]; + return Math.abs(this.dataToPoint(p1)[dimIdx] - this.dataToPoint(p2)[dimIdx]); + }, this); + } + + function geoPrepareCustom(coordSys) { + var rect = coordSys.getBoundingRect(); + return { + coordSys: { + type: 'geo', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height, + zoom: coordSys.getZoom() + }, + api: { + coord: function (data) { + return coordSys.dataToPoint(data); + }, + size: bind(dataToCoordSize$1, coordSys) + } + }; + } + + function dataToCoordSize$2(dataSize, dataItem) { + var axis = this.getAxis(); + var val = dataItem instanceof Array ? dataItem[0] : dataItem; + var halfSize = (dataSize instanceof Array ? dataSize[0] : dataSize) / 2; + return axis.type === 'category' ? axis.getBandWidth() : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize)); + } + + function singlePrepareCustom(coordSys) { + var rect = coordSys.getRect(); + return { + coordSys: { + type: 'singleAxis', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height + }, + api: { + coord: function (val) { + return coordSys.dataToPoint(val); + }, + size: bind(dataToCoordSize$2, coordSys) + } + }; + } + + function dataToCoordSize$3(dataSize, dataItem) { + dataItem = dataItem || [0, 0]; + return map(['Radius', 'Angle'], function (dim, dimIdx) { + var getterName = 'get' + dim + 'Axis'; + var axis = this[getterName](); + var val = dataItem[dimIdx]; + var halfSize = dataSize[dimIdx] / 2; + var result = axis.type === 'category' ? axis.getBandWidth() : Math.abs(axis.dataToCoord(val - halfSize) - axis.dataToCoord(val + halfSize)); + + if (dim === 'Angle') { + result = result * Math.PI / 180; + } + + return result; + }, this); + } + + function polarPrepareCustom(coordSys) { + var radiusAxis = coordSys.getRadiusAxis(); + var angleAxis = coordSys.getAngleAxis(); + var radius = radiusAxis.getExtent(); + radius[0] > radius[1] && radius.reverse(); + return { + coordSys: { + type: 'polar', + cx: coordSys.cx, + cy: coordSys.cy, + r: radius[1], + r0: radius[0] + }, + api: { + coord: function (data) { + var radius = radiusAxis.dataToRadius(data[0]); + var angle = angleAxis.dataToAngle(data[1]); + var coord = coordSys.coordToPoint([radius, angle]); + coord.push(radius, angle * Math.PI / 180); + return coord; + }, + size: bind(dataToCoordSize$3, coordSys) + } + }; + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function calendarPrepareCustom(coordSys) { + var rect = coordSys.getRect(); + var rangeInfo = coordSys.getRangeInfo(); + return { + coordSys: { + type: 'calendar', + x: rect.x, + y: rect.y, + width: rect.width, + height: rect.height, + cellWidth: coordSys.getCellWidth(), + cellHeight: coordSys.getCellHeight(), + rangeInfo: { + start: rangeInfo.start, + end: rangeInfo.end, + weeks: rangeInfo.weeks, + dayCount: rangeInfo.allDay + } + }, + api: { + coord: function (data, clamp) { + return coordSys.dataToPoint(data, clamp); + } + } + }; + } + + var deprecatedLogs = {}; + function isEC4CompatibleStyle(style, elType, hasOwnTextContentOption, hasOwnTextConfig) { + return style && (style.legacy || style.legacy !== false && !hasOwnTextContentOption && !hasOwnTextConfig && elType !== 'tspan' && (elType === 'text' || hasOwn(style, 'text'))); + } + function convertFromEC4CompatibleStyle(hostStyle, elType, isNormal) { + var srcStyle = hostStyle; + var textConfig; + var textContent; + var textContentStyle; + + if (elType === 'text') { + textContentStyle = srcStyle; + } else { + textContentStyle = {}; + hasOwn(srcStyle, 'text') && (textContentStyle.text = srcStyle.text); + hasOwn(srcStyle, 'rich') && (textContentStyle.rich = srcStyle.rich); + hasOwn(srcStyle, 'textFill') && (textContentStyle.fill = srcStyle.textFill); + hasOwn(srcStyle, 'textStroke') && (textContentStyle.stroke = srcStyle.textStroke); + textContent = { + type: 'text', + style: textContentStyle, + silent: true + }; + textConfig = {}; + var hasOwnPos = hasOwn(srcStyle, 'textPosition'); + + if (isNormal) { + textConfig.position = hasOwnPos ? srcStyle.textPosition : 'inside'; + } else { + hasOwnPos && (textConfig.position = srcStyle.textPosition); + } + + hasOwn(srcStyle, 'textPosition') && (textConfig.position = srcStyle.textPosition); + hasOwn(srcStyle, 'textOffset') && (textConfig.offset = srcStyle.textOffset); + hasOwn(srcStyle, 'textRotation') && (textConfig.rotation = srcStyle.textRotation); + hasOwn(srcStyle, 'textDistance') && (textConfig.distance = srcStyle.textDistance); + } + + convertEC4CompatibleRichItem(textContentStyle, hostStyle); + each(textContentStyle.rich, function (richItem) { + convertEC4CompatibleRichItem(richItem, richItem); + }); + return { + textConfig: textConfig, + textContent: textContent + }; + } + + function convertEC4CompatibleRichItem(out, richItem) { + if (!richItem) { + return; + } + + richItem.font = richItem.textFont || richItem.font; + hasOwn(richItem, 'textStrokeWidth') && (out.lineWidth = richItem.textStrokeWidth); + hasOwn(richItem, 'textAlign') && (out.align = richItem.textAlign); + hasOwn(richItem, 'textVerticalAlign') && (out.verticalAlign = richItem.textVerticalAlign); + hasOwn(richItem, 'textLineHeight') && (out.lineHeight = richItem.textLineHeight); + hasOwn(richItem, 'textWidth') && (out.width = richItem.textWidth); + hasOwn(richItem, 'textHeight') && (out.height = richItem.textHeight); + hasOwn(richItem, 'textBackgroundColor') && (out.backgroundColor = richItem.textBackgroundColor); + hasOwn(richItem, 'textPadding') && (out.padding = richItem.textPadding); + hasOwn(richItem, 'textBorderColor') && (out.borderColor = richItem.textBorderColor); + hasOwn(richItem, 'textBorderWidth') && (out.borderWidth = richItem.textBorderWidth); + hasOwn(richItem, 'textBorderRadius') && (out.borderRadius = richItem.textBorderRadius); + hasOwn(richItem, 'textBoxShadowColor') && (out.shadowColor = richItem.textBoxShadowColor); + hasOwn(richItem, 'textBoxShadowBlur') && (out.shadowBlur = richItem.textBoxShadowBlur); + hasOwn(richItem, 'textBoxShadowOffsetX') && (out.shadowOffsetX = richItem.textBoxShadowOffsetX); + hasOwn(richItem, 'textBoxShadowOffsetY') && (out.shadowOffsetY = richItem.textBoxShadowOffsetY); + } + + function convertToEC4StyleForCustomSerise(itemStl, txStl, txCfg) { + var out = itemStl; + out.textPosition = out.textPosition || txCfg.position || 'inside'; + txCfg.offset != null && (out.textOffset = txCfg.offset); + txCfg.rotation != null && (out.textRotation = txCfg.rotation); + txCfg.distance != null && (out.textDistance = txCfg.distance); + var isInside = out.textPosition.indexOf('inside') >= 0; + var hostFill = itemStl.fill || '#000'; + convertToEC4RichItem(out, txStl); + var textFillNotSet = out.textFill == null; + + if (isInside) { + if (textFillNotSet) { + out.textFill = txCfg.insideFill || '#fff'; + !out.textStroke && txCfg.insideStroke && (out.textStroke = txCfg.insideStroke); + !out.textStroke && (out.textStroke = hostFill); + out.textStrokeWidth == null && (out.textStrokeWidth = 2); + } + } else { + if (textFillNotSet) { + out.textFill = txCfg.outsideFill || hostFill; + } + + !out.textStroke && txCfg.outsideStroke && (out.textStroke = txCfg.outsideStroke); + } + + out.text = txStl.text; + out.rich = txStl.rich; + each(txStl.rich, function (richItem) { + convertToEC4RichItem(richItem, richItem); + }); + return out; + } + + function convertToEC4RichItem(out, richItem) { + if (!richItem) { + return; + } + + hasOwn(richItem, 'fill') && (out.textFill = richItem.fill); + hasOwn(richItem, 'stroke') && (out.textStroke = richItem.fill); + hasOwn(richItem, 'lineWidth') && (out.textStrokeWidth = richItem.lineWidth); + hasOwn(richItem, 'font') && (out.font = richItem.font); + hasOwn(richItem, 'fontStyle') && (out.fontStyle = richItem.fontStyle); + hasOwn(richItem, 'fontWeight') && (out.fontWeight = richItem.fontWeight); + hasOwn(richItem, 'fontSize') && (out.fontSize = richItem.fontSize); + hasOwn(richItem, 'fontFamily') && (out.fontFamily = richItem.fontFamily); + hasOwn(richItem, 'align') && (out.textAlign = richItem.align); + hasOwn(richItem, 'verticalAlign') && (out.textVerticalAlign = richItem.verticalAlign); + hasOwn(richItem, 'lineHeight') && (out.textLineHeight = richItem.lineHeight); + hasOwn(richItem, 'width') && (out.textWidth = richItem.width); + hasOwn(richItem, 'height') && (out.textHeight = richItem.height); + hasOwn(richItem, 'backgroundColor') && (out.textBackgroundColor = richItem.backgroundColor); + hasOwn(richItem, 'padding') && (out.textPadding = richItem.padding); + hasOwn(richItem, 'borderColor') && (out.textBorderColor = richItem.borderColor); + hasOwn(richItem, 'borderWidth') && (out.textBorderWidth = richItem.borderWidth); + hasOwn(richItem, 'borderRadius') && (out.textBorderRadius = richItem.borderRadius); + hasOwn(richItem, 'shadowColor') && (out.textBoxShadowColor = richItem.shadowColor); + hasOwn(richItem, 'shadowBlur') && (out.textBoxShadowBlur = richItem.shadowBlur); + hasOwn(richItem, 'shadowOffsetX') && (out.textBoxShadowOffsetX = richItem.shadowOffsetX); + hasOwn(richItem, 'shadowOffsetY') && (out.textBoxShadowOffsetY = richItem.shadowOffsetY); + hasOwn(richItem, 'textShadowColor') && (out.textShadowColor = richItem.textShadowColor); + hasOwn(richItem, 'textShadowBlur') && (out.textShadowBlur = richItem.textShadowBlur); + hasOwn(richItem, 'textShadowOffsetX') && (out.textShadowOffsetX = richItem.textShadowOffsetX); + hasOwn(richItem, 'textShadowOffsetY') && (out.textShadowOffsetY = richItem.textShadowOffsetY); + } + + function warnDeprecated(deprecated, insteadApproach) { + if ("development" !== 'production') { + var key = deprecated + '^_^' + insteadApproach; + + if (!deprecatedLogs[key]) { + console.warn("[ECharts] DEPRECATED: \"" + deprecated + "\" has been deprecated. " + insteadApproach); + deprecatedLogs[key] = true; + } + } + } + + var CMD$4 = PathProxy.CMD; + var PI2$a = Math.PI * 2; + var PROP_XY = ['x', 'y']; + var PROP_WH = ['width', 'height']; + var tmpArr$1 = []; + function aroundEqual(a, b) { + return Math.abs(a - b) < 1e-5; + } + function pathToBezierCurves(path) { + var data = path.data; + var len = path.len(); + var bezierArray = []; + var currentSubpath; + var xi = 0; + var yi = 0; + var x0 = 0; + var y0 = 0; + function createNewSubpath(x, y) { + if (currentSubpath && currentSubpath.length > 2) { + bezierArray.push(currentSubpath); + } + currentSubpath = [x, y]; + } + function addLine(x0, y0, x1, y1) { + if (!(aroundEqual(x0, x1) && aroundEqual(y0, y1))) { + currentSubpath.push(x0, y0, x1, y1, x1, y1); + } + } + function addArc(startAngle, endAngle, cx, cy, rx, ry) { + var delta = Math.abs(endAngle - startAngle); + var len = Math.tan(delta / 4) * 4 / 3; + var dir = endAngle < startAngle ? -1 : 1; + var c1 = Math.cos(startAngle); + var s1 = Math.sin(startAngle); + var c2 = Math.cos(endAngle); + var s2 = Math.sin(endAngle); + var x1 = c1 * rx + cx; + var y1 = s1 * ry + cy; + var x4 = c2 * rx + cx; + var y4 = s2 * ry + cy; + var hx = rx * len * dir; + var hy = ry * len * dir; + currentSubpath.push(x1 - hx * s1, y1 + hy * c1, x4 + hx * s2, y4 - hy * c2, x4, y4); + } + var x1; + var y1; + var x2; + var y2; + for (var i = 0; i < len;) { + var cmd = data[i++]; + var isFirst = i === 1; + if (isFirst) { + xi = data[i]; + yi = data[i + 1]; + x0 = xi; + y0 = yi; + if (cmd === CMD$4.L || cmd === CMD$4.C || cmd === CMD$4.Q) { + currentSubpath = [x0, y0]; + } + } + switch (cmd) { + case CMD$4.M: + xi = x0 = data[i++]; + yi = y0 = data[i++]; + createNewSubpath(x0, y0); + break; + case CMD$4.L: + x1 = data[i++]; + y1 = data[i++]; + addLine(xi, yi, x1, y1); + xi = x1; + yi = y1; + break; + case CMD$4.C: + currentSubpath.push(data[i++], data[i++], data[i++], data[i++], xi = data[i++], yi = data[i++]); + break; + case CMD$4.Q: + x1 = data[i++]; + y1 = data[i++]; + x2 = data[i++]; + y2 = data[i++]; + currentSubpath.push(xi + 2 / 3 * (x1 - xi), yi + 2 / 3 * (y1 - yi), x2 + 2 / 3 * (x1 - x2), y2 + 2 / 3 * (y1 - y2), x2, y2); + xi = x2; + yi = y2; + break; + case CMD$4.A: + var cx = data[i++]; + var cy = data[i++]; + var rx = data[i++]; + var ry = data[i++]; + var startAngle = data[i++]; + var endAngle = data[i++] + startAngle; + i += 1; + var anticlockwise = !data[i++]; + x1 = Math.cos(startAngle) * rx + cx; + y1 = Math.sin(startAngle) * ry + cy; + if (isFirst) { + x0 = x1; + y0 = y1; + createNewSubpath(x0, y0); + } + else { + addLine(xi, yi, x1, y1); + } + xi = Math.cos(endAngle) * rx + cx; + yi = Math.sin(endAngle) * ry + cy; + var step = (anticlockwise ? -1 : 1) * Math.PI / 2; + for (var angle = startAngle; anticlockwise ? angle > endAngle : angle < endAngle; angle += step) { + var nextAngle = anticlockwise ? Math.max(angle + step, endAngle) + : Math.min(angle + step, endAngle); + addArc(angle, nextAngle, cx, cy, rx, ry); + } + break; + case CMD$4.R: + x0 = xi = data[i++]; + y0 = yi = data[i++]; + x1 = x0 + data[i++]; + y1 = y0 + data[i++]; + createNewSubpath(x1, y0); + addLine(x1, y0, x1, y1); + addLine(x1, y1, x0, y1); + addLine(x0, y1, x0, y0); + addLine(x0, y0, x1, y0); + break; + case CMD$4.Z: + currentSubpath && addLine(xi, yi, x0, y0); + xi = x0; + yi = y0; + break; + } + } + if (currentSubpath && currentSubpath.length > 2) { + bezierArray.push(currentSubpath); + } + return bezierArray; + } + function alignSubpath(subpath1, subpath2) { + var len1 = subpath1.length; + var len2 = subpath2.length; + if (len1 === len2) { + return [subpath1, subpath2]; + } + var shorterPath = len1 < len2 ? subpath1 : subpath2; + var shorterLen = Math.min(len1, len2); + var diff = Math.abs(len2 - len1) / 6; + var shorterBezierCount = (shorterLen - 2) / 6; + var eachCurveSubDivCount = Math.ceil(diff / shorterBezierCount) + 1; + var newSubpath = [shorterPath[0], shorterPath[1]]; + var remained = diff; + var tmpSegX = []; + var tmpSegY = []; + for (var i = 2; i < shorterLen;) { + var x0 = shorterPath[i - 2]; + var y0 = shorterPath[i - 1]; + var x1 = shorterPath[i++]; + var y1 = shorterPath[i++]; + var x2 = shorterPath[i++]; + var y2 = shorterPath[i++]; + var x3 = shorterPath[i++]; + var y3 = shorterPath[i++]; + if (remained <= 0) { + newSubpath.push(x1, y1, x2, y2, x3, y3); + continue; + } + var actualSubDivCount = Math.min(remained, eachCurveSubDivCount - 1) + 1; + for (var k = 1; k <= actualSubDivCount; k++) { + var p = k / actualSubDivCount; + cubicSubdivide(x0, x1, x2, x3, p, tmpSegX); + cubicSubdivide(y0, y1, y2, y3, p, tmpSegY); + x0 = tmpSegX[3]; + y0 = tmpSegY[3]; + newSubpath.push(tmpSegX[1], tmpSegY[1], tmpSegX[2], tmpSegY[2], x0, y0); + x1 = tmpSegX[5]; + y1 = tmpSegY[5]; + x2 = tmpSegX[6]; + y2 = tmpSegY[6]; + } + remained -= actualSubDivCount - 1; + } + return shorterPath === subpath1 ? [newSubpath, subpath2] : [subpath1, newSubpath]; + } + function createSubpath(lastSubpathSubpath, otherSubpath) { + var len = lastSubpathSubpath.length; + var lastX = lastSubpathSubpath[len - 2]; + var lastY = lastSubpathSubpath[len - 1]; + var newSubpath = []; + for (var i = 0; i < otherSubpath.length;) { + newSubpath[i++] = lastX; + newSubpath[i++] = lastY; + } + return newSubpath; + } + function alignBezierCurves(array1, array2) { + var _a; + var lastSubpath1; + var lastSubpath2; + var newArray1 = []; + var newArray2 = []; + for (var i = 0; i < Math.max(array1.length, array2.length); i++) { + var subpath1 = array1[i]; + var subpath2 = array2[i]; + var newSubpath1 = void 0; + var newSubpath2 = void 0; + if (!subpath1) { + newSubpath1 = createSubpath(lastSubpath1 || subpath2, subpath2); + newSubpath2 = subpath2; + } + else if (!subpath2) { + newSubpath2 = createSubpath(lastSubpath2 || subpath1, subpath1); + newSubpath1 = subpath1; + } + else { + _a = alignSubpath(subpath1, subpath2), newSubpath1 = _a[0], newSubpath2 = _a[1]; + lastSubpath1 = newSubpath1; + lastSubpath2 = newSubpath2; + } + newArray1.push(newSubpath1); + newArray2.push(newSubpath2); + } + return [newArray1, newArray2]; + } + function centroid(array) { + var signedArea = 0; + var cx = 0; + var cy = 0; + var len = array.length; + for (var i = 0, j = len - 2; i < len; j = i, i += 2) { + var x0 = array[j]; + var y0 = array[j + 1]; + var x1 = array[i]; + var y1 = array[i + 1]; + var a = x0 * y1 - x1 * y0; + signedArea += a; + cx += (x0 + x1) * a; + cy += (y0 + y1) * a; + } + if (signedArea === 0) { + return [array[0] || 0, array[1] || 0]; + } + return [cx / signedArea / 3, cy / signedArea / 3, signedArea]; + } + function findBestRingOffset(fromSubBeziers, toSubBeziers, fromCp, toCp) { + var bezierCount = (fromSubBeziers.length - 2) / 6; + var bestScore = Infinity; + var bestOffset = 0; + var len = fromSubBeziers.length; + var len2 = len - 2; + for (var offset = 0; offset < bezierCount; offset++) { + var cursorOffset = offset * 6; + var score = 0; + for (var k = 0; k < len; k += 2) { + var idx = k === 0 ? cursorOffset : ((cursorOffset + k - 2) % len2 + 2); + var x0 = fromSubBeziers[idx] - fromCp[0]; + var y0 = fromSubBeziers[idx + 1] - fromCp[1]; + var x1 = toSubBeziers[k] - toCp[0]; + var y1 = toSubBeziers[k + 1] - toCp[1]; + var dx = x1 - x0; + var dy = y1 - y0; + score += dx * dx + dy * dy; + } + if (score < bestScore) { + bestScore = score; + bestOffset = offset; + } + } + return bestOffset; + } + function reverse(array) { + var newArr = []; + var len = array.length; + for (var i = 0; i < len; i += 2) { + newArr[i] = array[len - i - 2]; + newArr[i + 1] = array[len - i - 1]; + } + return newArr; + } + function findBestMorphingRotation(fromArr, toArr, searchAngleIteration, searchAngleRange) { + var result = []; + var fromNeedsReverse; + for (var i = 0; i < fromArr.length; i++) { + var fromSubpathBezier = fromArr[i]; + var toSubpathBezier = toArr[i]; + var fromCp = centroid(fromSubpathBezier); + var toCp = centroid(toSubpathBezier); + if (fromNeedsReverse == null) { + fromNeedsReverse = fromCp[2] < 0 !== toCp[2] < 0; + } + var newFromSubpathBezier = []; + var newToSubpathBezier = []; + var bestAngle = 0; + var bestScore = Infinity; + var tmpArr_1 = []; + var len = fromSubpathBezier.length; + if (fromNeedsReverse) { + fromSubpathBezier = reverse(fromSubpathBezier); + } + var offset = findBestRingOffset(fromSubpathBezier, toSubpathBezier, fromCp, toCp) * 6; + var len2 = len - 2; + for (var k = 0; k < len2; k += 2) { + var idx = (offset + k) % len2 + 2; + newFromSubpathBezier[k + 2] = fromSubpathBezier[idx] - fromCp[0]; + newFromSubpathBezier[k + 3] = fromSubpathBezier[idx + 1] - fromCp[1]; + } + newFromSubpathBezier[0] = fromSubpathBezier[offset] - fromCp[0]; + newFromSubpathBezier[1] = fromSubpathBezier[offset + 1] - fromCp[1]; + if (searchAngleIteration > 0) { + var step = searchAngleRange / searchAngleIteration; + for (var angle = -searchAngleRange / 2; angle <= searchAngleRange / 2; angle += step) { + var sa = Math.sin(angle); + var ca = Math.cos(angle); + var score = 0; + for (var k = 0; k < fromSubpathBezier.length; k += 2) { + var x0 = newFromSubpathBezier[k]; + var y0 = newFromSubpathBezier[k + 1]; + var x1 = toSubpathBezier[k] - toCp[0]; + var y1 = toSubpathBezier[k + 1] - toCp[1]; + var newX1 = x1 * ca - y1 * sa; + var newY1 = x1 * sa + y1 * ca; + tmpArr_1[k] = newX1; + tmpArr_1[k + 1] = newY1; + var dx = newX1 - x0; + var dy = newY1 - y0; + score += dx * dx + dy * dy; + } + if (score < bestScore) { + bestScore = score; + bestAngle = angle; + for (var m = 0; m < tmpArr_1.length; m++) { + newToSubpathBezier[m] = tmpArr_1[m]; + } + } + } + } + else { + for (var i_1 = 0; i_1 < len; i_1 += 2) { + newToSubpathBezier[i_1] = toSubpathBezier[i_1] - toCp[0]; + newToSubpathBezier[i_1 + 1] = toSubpathBezier[i_1 + 1] - toCp[1]; + } + } + result.push({ + from: newFromSubpathBezier, + to: newToSubpathBezier, + fromCp: fromCp, + toCp: toCp, + rotation: -bestAngle + }); + } + return result; + } + function morphPath(fromPath, toPath, animationOpts) { + var fromPathProxy; + var toPathProxy; + if (!fromPath || !toPath) { + return toPath; + } + !fromPath.path && fromPath.createPathProxy(); + fromPathProxy = fromPath.path; + fromPathProxy.beginPath(); + fromPath.buildPath(fromPathProxy, fromPath.shape); + !toPath.path && toPath.createPathProxy(); + toPathProxy = toPath.path; + toPathProxy === fromPathProxy && (toPathProxy = new PathProxy(false)); + toPathProxy.beginPath(); + if (isIndividualMorphingPath(toPath)) { + toPath.__oldBuildPath(toPathProxy, toPath.shape); + } + else { + toPath.buildPath(toPathProxy, toPath.shape); + } + var _a = alignBezierCurves(pathToBezierCurves(fromPathProxy), pathToBezierCurves(toPathProxy)), fromBezierCurves = _a[0], toBezierCurves = _a[1]; + var morphingData = findBestMorphingRotation(fromBezierCurves, toBezierCurves, 10, Math.PI); + becomeIndividualMorphingPath(toPath, morphingData, 0); + var oldDone = animationOpts && animationOpts.done; + var oldAborted = animationOpts && animationOpts.aborted; + var oldDuring = animationOpts && animationOpts.during; + toPath.animateTo({ + __morphT: 1 + }, defaults({ + during: function (p) { + toPath.dirtyShape(); + oldDuring && oldDuring(p); + }, + done: function () { + restoreIndividualMorphingPath(toPath); + toPath.createPathProxy(); + toPath.dirtyShape(); + oldDone && oldDone(); + }, + aborted: function () { + oldAborted && oldAborted(); + } + }, animationOpts)); + return toPath; + } + function morphingPathBuildPath(path) { + var morphingData = this.__morphingData; + var t = this.__morphT; + var onet = 1 - t; + var newCp = []; + for (var i = 0; i < morphingData.length; i++) { + var item = morphingData[i]; + var from = item.from; + var to = item.to; + var angle = item.rotation * t; + var fromCp = item.fromCp; + var toCp = item.toCp; + var sa = Math.sin(angle); + var ca = Math.cos(angle); + lerp(newCp, fromCp, toCp, t); + for (var m = 0; m < from.length; m += 2) { + var x0 = from[m]; + var y0 = from[m + 1]; + var x1 = to[m]; + var y1 = to[m + 1]; + var x = x0 * onet + x1 * t; + var y = y0 * onet + y1 * t; + tmpArr$1[m] = (x * ca - y * sa) + newCp[0]; + tmpArr$1[m + 1] = (x * sa + y * ca) + newCp[1]; + } + for (var m = 0; m < from.length;) { + if (m === 0) { + path.moveTo(tmpArr$1[m++], tmpArr$1[m++]); + } + path.bezierCurveTo(tmpArr$1[m++], tmpArr$1[m++], tmpArr$1[m++], tmpArr$1[m++], tmpArr$1[m++], tmpArr$1[m++]); + } + } + } + function becomeIndividualMorphingPath(path, morphingData, morphT) { + if (isIndividualMorphingPath(path)) { + updateIndividualMorphingPath(path, morphingData, morphT); + return; + } + var morphingPath = path; + morphingPath.__oldBuildPath = morphingPath.buildPath; + morphingPath.buildPath = morphingPathBuildPath; + updateIndividualMorphingPath(morphingPath, morphingData, morphT); + } + function updateIndividualMorphingPath(morphingPath, morphingData, morphT) { + morphingPath.__morphingData = morphingData; + morphingPath.__morphT = morphT; + } + function restoreIndividualMorphingPath(path) { + if (isIndividualMorphingPath(path)) { + path.buildPath = path.__oldBuildPath; + path.__oldBuildPath = path.__morphingData = null; + } + } + function isIndividualMorphingPath(path) { + return path.__oldBuildPath != null; + } + function isCombiningPath(path) { + return !!path.__combiningSubList; + } + function isInAnyMorphing(path) { + return isIndividualMorphingPath(path) || isCombiningPath(path); + } + function combine(fromPathList, toPath, animationOpts, copyPropsIfDivided) { + var fromIndividuals = []; + var separateCount = 0; + for (var i = 0; i < fromPathList.length; i++) { + var fromPath = fromPathList[i]; + if (isCombiningPath(fromPath)) { + var fromCombiningSubList = fromPath.__combiningSubList; + for (var j = 0; j < fromCombiningSubList.length; j++) { + fromIndividuals.push(fromCombiningSubList[j]); + } + separateCount += fromCombiningSubList.length; + } + else { + fromIndividuals.push(fromPath); + separateCount++; + } + } + if (!separateCount) { + return; + } + var dividingMethod = animationOpts ? animationOpts.dividingMethod : null; + var toPathSplittedList = divideShape(toPath, separateCount, dividingMethod); + assert(toPathSplittedList.length === separateCount); + var oldDone = animationOpts && animationOpts.done; + var oldAborted = animationOpts && animationOpts.aborted; + var oldDuring = animationOpts && animationOpts.during; + var doneCount = 0; + var abortedCalled = false; + var morphAnimationOpts = defaults({ + during: function (p) { + oldDuring && oldDuring(p); + }, + done: function () { + doneCount++; + if (doneCount === toPathSplittedList.length) { + restoreCombiningPath(toPath); + oldDone && oldDone(); + } + }, + aborted: function () { + if (!abortedCalled) { + abortedCalled = true; + oldAborted && oldAborted(); + } + } + }, animationOpts); + for (var i = 0; i < separateCount; i++) { + var from = fromIndividuals[i]; + var to = toPathSplittedList[i]; + copyPropsIfDivided && copyPropsIfDivided(toPath, to, true); + morphPath(from, to, morphAnimationOpts); + } + becomeCombiningPath(toPath, toPathSplittedList); + return { + fromIndividuals: fromIndividuals, + toIndividuals: toPathSplittedList, + count: separateCount + }; + } + function becomeCombiningPath(path, combiningSubList) { + if (isCombiningPath(path)) { + updateCombiningPathSubList(path, combiningSubList); + return; + } + var combiningPath = path; + updateCombiningPathSubList(combiningPath, combiningSubList); + combiningPath.__oldAddSelfToZr = path.addSelfToZr; + combiningPath.__oldRemoveSelfFromZr = path.removeSelfFromZr; + combiningPath.addSelfToZr = combiningAddSelfToZr; + combiningPath.removeSelfFromZr = combiningRemoveSelfFromZr; + combiningPath.__oldBuildPath = combiningPath.buildPath; + combiningPath.buildPath = noop; + combiningPath.childrenRef = combiningChildrenRef; + } + function restoreCombiningPath(path) { + if (!isCombiningPath(path)) { + return; + } + var combiningPath = path; + updateCombiningPathSubList(combiningPath, null); + combiningPath.addSelfToZr = combiningPath.__oldAddSelfToZr; + combiningPath.removeSelfFromZr = combiningPath.__oldRemoveSelfFromZr; + combiningPath.buildPath = combiningPath.__oldBuildPath; + combiningPath.childrenRef = + combiningPath.__combiningSubList = + combiningPath.__oldAddSelfToZr = + combiningPath.__oldRemoveSelfFromZr = + combiningPath.__oldBuildPath = null; + } + function updateCombiningPathSubList(combiningPath, combiningSubList) { + if (combiningPath.__combiningSubList !== combiningSubList) { + combiningPathSubListAddRemoveWithZr(combiningPath, 'removeSelfFromZr'); + combiningPath.__combiningSubList = combiningSubList; + if (combiningSubList) { + for (var i = 0; i < combiningSubList.length; i++) { + combiningSubList[i].parent = combiningPath; + } + } + combiningPathSubListAddRemoveWithZr(combiningPath, 'addSelfToZr'); + } + } + function combiningAddSelfToZr(zr) { + this.__oldAddSelfToZr(zr); + combiningPathSubListAddRemoveWithZr(this, 'addSelfToZr'); + } + function combiningPathSubListAddRemoveWithZr(path, method) { + var combiningSubList = path.__combiningSubList; + var zr = path.__zr; + if (combiningSubList && zr) { + for (var i = 0; i < combiningSubList.length; i++) { + var child = combiningSubList[i]; + child[method](zr); + } + } + } + function combiningRemoveSelfFromZr(zr) { + this.__oldRemoveSelfFromZr(zr); + var combiningSubList = this.__combiningSubList; + for (var i = 0; i < combiningSubList.length; i++) { + var child = combiningSubList[i]; + child.removeSelfFromZr(zr); + } + } + function combiningChildrenRef() { + return this.__combiningSubList; + } + function separate(fromPath, toPathList, animationOpts, copyPropsIfDivided) { + var toPathListLen = toPathList.length; + var fromPathList; + var dividingMethod = animationOpts ? animationOpts.dividingMethod : null; + var copyProps = false; + if (isCombiningPath(fromPath)) { + var fromCombiningSubList = fromPath.__combiningSubList; + if (fromCombiningSubList.length === toPathListLen) { + fromPathList = fromCombiningSubList; + } + else { + fromPathList = divideShape(fromPath, toPathListLen, dividingMethod); + copyProps = true; + } + } + else { + fromPathList = divideShape(fromPath, toPathListLen, dividingMethod); + copyProps = true; + } + assert(fromPathList.length === toPathListLen); + for (var i = 0; i < toPathListLen; i++) { + if (copyProps && copyPropsIfDivided) { + copyPropsIfDivided(fromPath, fromPathList[i], false); + } + morphPath(fromPathList[i], toPathList[i], animationOpts); + } + return { + fromIndividuals: fromPathList, + toIndividuals: toPathList, + count: toPathListLen + }; + } + function divideShape(path, separateCount, dividingMethod) { + return dividingMethod === 'duplicate' + ? duplicateShape(path, separateCount) + : splitShape(path, separateCount); + } + function splitShape(path, separateCount) { + var resultPaths = []; + if (separateCount <= 0) { + return resultPaths; + } + if (separateCount === 1) { + return duplicateShape(path, separateCount); + } + if (path instanceof Rect) { + var toPathShape = path.shape; + var splitPropIdx = toPathShape.height > toPathShape.width ? 1 : 0; + var propWH = PROP_WH[splitPropIdx]; + var propXY = PROP_XY[splitPropIdx]; + var subWH = toPathShape[propWH] / separateCount; + var xyCurr = toPathShape[propXY]; + for (var i = 0; i < separateCount; i++, xyCurr += subWH) { + var subShape = { + x: toPathShape.x, + y: toPathShape.y, + width: toPathShape.width, + height: toPathShape.height + }; + subShape[propXY] = xyCurr; + subShape[propWH] = i < separateCount - 1 + ? subWH + : toPathShape[propXY] + toPathShape[propWH] - xyCurr; + var splitted = new Rect({ shape: subShape }); + resultPaths.push(splitted); + } + } + else if (path instanceof Sector) { + var toPathShape = path.shape; + var clockwise = toPathShape.clockwise; + var startAngle = toPathShape.startAngle; + var endAngle = toPathShape.endAngle; + var endAngleNormalized = normalizeRadian$1(startAngle, toPathShape.endAngle, clockwise); + var step = (endAngleNormalized - startAngle) / separateCount; + var angleCurr = startAngle; + for (var i = 0; i < separateCount; i++, angleCurr += step) { + var splitted = new Sector({ + shape: { + cx: toPathShape.cx, + cy: toPathShape.cy, + r: toPathShape.r, + r0: toPathShape.r0, + clockwise: clockwise, + startAngle: angleCurr, + endAngle: i === separateCount - 1 ? endAngle : angleCurr + step + } + }); + resultPaths.push(splitted); + } + } + else { + return duplicateShape(path, separateCount); + } + return resultPaths; + } + function duplicateShape(path, separateCount) { + var resultPaths = []; + if (separateCount <= 0) { + return resultPaths; + } + var ctor = path.constructor; + for (var i = 0; i < separateCount; i++) { + var sub = new ctor({ + shape: clone(path.shape) + }); + resultPaths.push(sub); + } + return resultPaths; + } + function normalizeRadian$1(start, end, clockwise) { + return end + PI2$a * (Math[clockwise ? 'ceil' : 'floor']((start - end) / PI2$a)); + } + + var inner$b = makeInner(); + var TRANSFORM_PROPS = { + x: 1, + y: 1, + scaleX: 1, + scaleY: 1, + originX: 1, + originY: 1, + rotation: 1 + }; + var transformPropNamesStr = keys(TRANSFORM_PROPS).join(', '); + var STYLE_VISUAL_TYPE = { + color: 'fill', + borderColor: 'stroke' + }; + var NON_STYLE_VISUAL_PROPS = { + symbol: 1, + symbolSize: 1, + symbolKeepAspect: 1, + legendSymbol: 1, + visualMeta: 1, + liftZ: 1, + decal: 1 + }; + var EMPHASIS = 'emphasis'; + var NORMAL = 'normal'; + var BLUR = 'blur'; + var SELECT = 'select'; + var STATES = [NORMAL, EMPHASIS, BLUR, SELECT]; + var PATH_ITEM_STYLE = { + normal: ['itemStyle'], + emphasis: [EMPHASIS, 'itemStyle'], + blur: [BLUR, 'itemStyle'], + select: [SELECT, 'itemStyle'] + }; + var PATH_LABEL = { + normal: ['label'], + emphasis: [EMPHASIS, 'label'], + blur: [BLUR, 'label'], + select: [SELECT, 'label'] + }; + var GROUP_DIFF_PREFIX = 'e\0\0'; + var attachedTxInfoTmp = { + normal: {}, + emphasis: {}, + blur: {}, + select: {} + }; + var LEGACY_TRANSFORM_PROPS = { + position: ['x', 'y'], + scale: ['scaleX', 'scaleY'], + origin: ['originX', 'originY'] + }; + var tmpTransformable = new Transformable(); + var prepareCustoms = { + cartesian2d: cartesianPrepareCustom, + geo: geoPrepareCustom, + singleAxis: singlePrepareCustom, + polar: polarPrepareCustom, + calendar: calendarPrepareCustom + }; + + var CustomSeriesModel = function (_super) { + __extends(CustomSeriesModel, _super); + + function CustomSeriesModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CustomSeriesModel.type; + return _this; + } + + CustomSeriesModel.prototype.optionUpdated = function () { + this.currentZLevel = this.get('zlevel', true); + this.currentZ = this.get('z', true); + }; + + CustomSeriesModel.prototype.getInitialData = function (option, ecModel) { + return createListFromArray(this.getSource(), this); + }; + + CustomSeriesModel.prototype.getDataParams = function (dataIndex, dataType, el) { + var params = _super.prototype.getDataParams.call(this, dataIndex, dataType); + + el && (params.info = inner$b(el).info); + return params; + }; + + CustomSeriesModel.type = 'series.custom'; + CustomSeriesModel.dependencies = ['grid', 'polar', 'geo', 'singleAxis', 'calendar']; + CustomSeriesModel.defaultOption = { + coordinateSystem: 'cartesian2d', + zlevel: 0, + z: 2, + legendHoverLink: true, + clip: false + }; + return CustomSeriesModel; + }(SeriesModel); + + var CustomSeriesView = function (_super) { + __extends(CustomSeriesView, _super); + + function CustomSeriesView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CustomSeriesView.type; + return _this; + } + + CustomSeriesView.prototype.render = function (customSeries, ecModel, api, payload) { + var oldData = this._data; + var data = customSeries.getData(); + var group = this.group; + var renderItem = makeRenderItem(customSeries, data, ecModel, api); + var transOpt = customSeries.__transientTransitionOpt; + + if (transOpt && (transOpt.from == null || transOpt.to == null)) { + oldData && oldData.each(function (oldIdx) { + doRemoveEl(oldData.getItemGraphicEl(oldIdx), customSeries, group); + }); + data.each(function (newIdx) { + createOrUpdateItem(api, null, newIdx, renderItem(newIdx, payload), customSeries, group, data, null); + }); + } else { + var morphPreparation_1 = new MorphPreparation(customSeries, transOpt); + var diffMode = transOpt ? 'multiple' : 'oneToOne'; + new DataDiffer(oldData ? oldData.getIndices() : [], data.getIndices(), createGetKey(oldData, diffMode, transOpt && transOpt.from), createGetKey(data, diffMode, transOpt && transOpt.to), null, diffMode).add(function (newIdx) { + createOrUpdateItem(api, null, newIdx, renderItem(newIdx, payload), customSeries, group, data, null); + }).remove(function (oldIdx) { + doRemoveEl(oldData.getItemGraphicEl(oldIdx), customSeries, group); + }).update(function (newIdx, oldIdx) { + morphPreparation_1.reset('oneToOne'); + var oldEl = oldData.getItemGraphicEl(oldIdx); + morphPreparation_1.findAndAddFrom(oldEl); + + if (morphPreparation_1.hasFrom()) { + removeElementDirectly(oldEl, group); + oldEl = null; + } + + createOrUpdateItem(api, oldEl, newIdx, renderItem(newIdx, payload), customSeries, group, data, morphPreparation_1); + morphPreparation_1.applyMorphing(); + }).updateManyToOne(function (newIdx, oldIndices) { + morphPreparation_1.reset('manyToOne'); + + for (var i = 0; i < oldIndices.length; i++) { + var oldEl = oldData.getItemGraphicEl(oldIndices[i]); + morphPreparation_1.findAndAddFrom(oldEl); + removeElementDirectly(oldEl, group); + } + + createOrUpdateItem(api, null, newIdx, renderItem(newIdx, payload), customSeries, group, data, morphPreparation_1); + morphPreparation_1.applyMorphing(); + }).updateOneToMany(function (newIndices, oldIdx) { + morphPreparation_1.reset('oneToMany'); + var newLen = newIndices.length; + var oldEl = oldData.getItemGraphicEl(oldIdx); + morphPreparation_1.findAndAddFrom(oldEl); + removeElementDirectly(oldEl, group); + + for (var i = 0; i < newLen; i++) { + createOrUpdateItem(api, null, newIndices[i], renderItem(newIndices[i], payload), customSeries, group, data, morphPreparation_1); + } + + morphPreparation_1.applyMorphing(); + }).execute(); + } + + var clipPath = customSeries.get('clip', true) ? createClipPath(customSeries.coordinateSystem, false, customSeries) : null; + + if (clipPath) { + group.setClipPath(clipPath); + } else { + group.removeClipPath(); + } + + this._data = data; + }; + + CustomSeriesView.prototype.incrementalPrepareRender = function (customSeries, ecModel, api) { + this.group.removeAll(); + this._data = null; + }; + + CustomSeriesView.prototype.incrementalRender = function (params, customSeries, ecModel, api, payload) { + var data = customSeries.getData(); + var renderItem = makeRenderItem(customSeries, data, ecModel, api); + + function setIncrementalAndHoverLayer(el) { + if (!el.isGroup) { + el.incremental = true; + el.ensureState('emphasis').hoverLayer = true; + } + } + + for (var idx = params.start; idx < params.end; idx++) { + var el = createOrUpdateItem(null, null, idx, renderItem(idx, payload), customSeries, this.group, data, null); + el.traverse(setIncrementalAndHoverLayer); + } + }; + + CustomSeriesView.prototype.filterForExposedEvent = function (eventType, query, targetEl, packedEvent) { + var elementName = query.element; + + if (elementName == null || targetEl.name === elementName) { + return true; + } + + while ((targetEl = targetEl.__hostTarget || targetEl.parent) && targetEl !== this.group) { + if (targetEl.name === elementName) { + return true; + } + } + + return false; + }; + + CustomSeriesView.type = 'custom'; + return CustomSeriesView; + }(ChartView); + + function createGetKey(data, diffMode, dimension) { + if (!data) { + return; + } + + if (diffMode === 'oneToOne') { + return function (rawIdx, dataIndex) { + return data.getId(dataIndex); + }; + } + + var diffByDimName = data.getDimension(dimension); + var dimInfo = data.getDimensionInfo(diffByDimName); + + if (!dimInfo) { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = dimension + " is not a valid dimension."; + } + + throwError(errMsg); + } + + var ordinalMeta = dimInfo.ordinalMeta; + return function (rawIdx, dataIndex) { + var key = data.get(diffByDimName, dataIndex); + + if (ordinalMeta) { + key = ordinalMeta.categories[key]; + } + + return key == null || eqNaN(key) ? rawIdx + '' : '_ec_' + key; + }; + } + + function createEl(elOption) { + var graphicType = elOption.type; + var el; + + if (graphicType === 'path') { + var shape = elOption.shape; + var pathRect = shape.width != null && shape.height != null ? { + x: shape.x || 0, + y: shape.y || 0, + width: shape.width, + height: shape.height + } : null; + var pathData = getPathData(shape); + el = makePath(pathData, null, pathRect, shape.layout || 'center'); + inner$b(el).customPathData = pathData; + } else if (graphicType === 'image') { + el = new ZRImage({}); + inner$b(el).customImagePath = elOption.style.image; + } else if (graphicType === 'text') { + el = new ZRText({}); + } else if (graphicType === 'group') { + el = new Group(); + } else if (graphicType === 'compoundPath') { + throw new Error('"compoundPath" is not supported yet.'); + } else { + var Clz = getShapeClass(graphicType); + + if (!Clz) { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = 'graphic type "' + graphicType + '" can not be found.'; + } + + throwError(errMsg); + } + + el = new Clz(); + } + + inner$b(el).customGraphicType = graphicType; + el.name = elOption.name; + el.z2EmphasisLift = 1; + el.z2SelectLift = 1; + return el; + } + + function updateElNormal(api, el, isMorphTo, dataIndex, elOption, styleOpt, attachedTxInfo, seriesModel, isInit, isTextContent) { + var transFromProps = {}; + var allPropsFinal = {}; + var elDisplayable = el.isGroup ? null : el; + !isMorphTo && prepareShapeOrExtraTransitionFrom('shape', el, null, elOption, transFromProps, isInit); + prepareShapeOrExtraAllPropsFinal('shape', elOption, allPropsFinal); + !isMorphTo && prepareShapeOrExtraTransitionFrom('extra', el, null, elOption, transFromProps, isInit); + prepareShapeOrExtraAllPropsFinal('extra', elOption, allPropsFinal); + !isMorphTo && prepareTransformTransitionFrom(el, null, elOption, transFromProps, isInit); + prepareTransformAllPropsFinal(elOption, allPropsFinal); + var txCfgOpt = attachedTxInfo && attachedTxInfo.normal.cfg; + + if (txCfgOpt) { + el.setTextConfig(txCfgOpt); + } + + if (el.type === 'text' && styleOpt) { + var textOptionStyle = styleOpt; + hasOwn(textOptionStyle, 'textFill') && (textOptionStyle.fill = textOptionStyle.textFill); + hasOwn(textOptionStyle, 'textStroke') && (textOptionStyle.stroke = textOptionStyle.textStroke); + } + + if (styleOpt) { + var decalPattern = void 0; + var decalObj = isPath$1(el) ? styleOpt.decal : null; + + if (api && decalObj) { + decalObj.dirty = true; + decalPattern = createOrUpdatePatternFromDecal(decalObj, api); + } + + styleOpt.__decalPattern = decalPattern; + } + + !isMorphTo && prepareStyleTransitionFrom(el, null, elOption, styleOpt, transFromProps, isInit); + + if (elDisplayable) { + hasOwn(elOption, 'invisible') && (elDisplayable.invisible = elOption.invisible); + } + + if (!isMorphTo) { + applyPropsFinal(el, allPropsFinal, styleOpt); + applyTransitionFrom(el, dataIndex, elOption, seriesModel, transFromProps, isInit); + } + + hasOwn(elOption, 'silent') && (el.silent = elOption.silent); + hasOwn(elOption, 'ignore') && (el.ignore = elOption.ignore); + + if (!isTextContent) { + hasOwn(elOption, 'info') && (inner$b(el).info = elOption.info); + } + + styleOpt ? el.dirty() : el.markRedraw(); + return isMorphTo ? allPropsFinal : null; + } + + function applyPropsFinal(el, allPropsFinal, styleOpt) { + var elDisplayable = el.isGroup ? null : el; + + if (elDisplayable && styleOpt) { + var decalPattern = styleOpt.__decalPattern; + var originalDecalObj = void 0; + + if (decalPattern) { + originalDecalObj = styleOpt.decal; + styleOpt.decal = decalPattern; + } + + elDisplayable.useStyle(styleOpt); + + if (decalPattern) { + styleOpt.decal = originalDecalObj; + } + + var animators = elDisplayable.animators; + + for (var i = 0; i < animators.length; i++) { + var animator = animators[i]; + + if (animator.targetName === 'style') { + animator.changeTarget(elDisplayable.style); + } + } + } + + allPropsFinal && el.attr(allPropsFinal); + } + + function applyTransitionFrom(el, dataIndex, elOption, seriesModel, transFromProps, isInit) { + if (transFromProps) { + var userDuring = elOption.during; + inner$b(el).userDuring = userDuring; + var cfgDuringCall = userDuring ? bind(duringCall, { + el: el, + userDuring: userDuring + }) : null; + var cfg = { + dataIndex: dataIndex, + isFrom: true, + during: cfgDuringCall + }; + isInit ? initProps(el, transFromProps, seriesModel, cfg) : updateProps(el, transFromProps, seriesModel, cfg); + } + } + + function prepareShapeOrExtraTransitionFrom(mainAttr, el, morphFromEl, elOption, transFromProps, isInit) { + var attrOpt = elOption[mainAttr]; + + if (!attrOpt) { + return; + } + + var elPropsInAttr = el[mainAttr]; + var transFromPropsInAttr; + var enterFrom = attrOpt.enterFrom; + + if (isInit && enterFrom) { + !transFromPropsInAttr && (transFromPropsInAttr = transFromProps[mainAttr] = {}); + var enterFromKeys = keys(enterFrom); + + for (var i = 0; i < enterFromKeys.length; i++) { + var key = enterFromKeys[i]; + transFromPropsInAttr[key] = enterFrom[key]; + } + } + + if (!isInit && elPropsInAttr && !(morphFromEl != null && mainAttr === 'shape')) { + if (attrOpt.transition) { + !transFromPropsInAttr && (transFromPropsInAttr = transFromProps[mainAttr] = {}); + var transitionKeys = normalizeToArray(attrOpt.transition); + + for (var i = 0; i < transitionKeys.length; i++) { + var key = transitionKeys[i]; + var elVal = elPropsInAttr[key]; + + if ("development" !== 'production') { + checkNonStyleTansitionRefer(key, attrOpt[key], elVal); + } + + transFromPropsInAttr[key] = elVal; + } + } else if (indexOf(elOption.transition, mainAttr) >= 0) { + !transFromPropsInAttr && (transFromPropsInAttr = transFromProps[mainAttr] = {}); + var elPropsInAttrKeys = keys(elPropsInAttr); + + for (var i = 0; i < elPropsInAttrKeys.length; i++) { + var key = elPropsInAttrKeys[i]; + var elVal = elPropsInAttr[key]; + + if (isNonStyleTransitionEnabled(attrOpt[key], elVal)) { + transFromPropsInAttr[key] = elVal; + } + } + } + } + + var leaveTo = attrOpt.leaveTo; + + if (leaveTo) { + var leaveToProps = getOrCreateLeaveToPropsFromEl(el); + var leaveToPropsInAttr = leaveToProps[mainAttr] || (leaveToProps[mainAttr] = {}); + var leaveToKeys = keys(leaveTo); + + for (var i = 0; i < leaveToKeys.length; i++) { + var key = leaveToKeys[i]; + leaveToPropsInAttr[key] = leaveTo[key]; + } + } + } + + function prepareShapeOrExtraAllPropsFinal(mainAttr, elOption, allProps) { + var attrOpt = elOption[mainAttr]; + + if (!attrOpt) { + return; + } + + var allPropsInAttr = allProps[mainAttr] = {}; + var keysInAttr = keys(attrOpt); + + for (var i = 0; i < keysInAttr.length; i++) { + var key = keysInAttr[i]; + allPropsInAttr[key] = cloneValue(attrOpt[key]); + } + } + + function prepareTransformTransitionFrom(el, morphFromEl, elOption, transFromProps, isInit) { + var enterFrom = elOption.enterFrom; + + if (isInit && enterFrom) { + var enterFromKeys = keys(enterFrom); + + for (var i = 0; i < enterFromKeys.length; i++) { + var key = enterFromKeys[i]; + + if ("development" !== 'production') { + checkTransformPropRefer(key, 'el.enterFrom'); + } + + transFromProps[key] = enterFrom[key]; + } + } + + if (!isInit) { + if (morphFromEl) { + var fromTransformable = calcOldElLocalTransformBasedOnNewElParent(morphFromEl, el); + setTransformPropToTransitionFrom(transFromProps, 'x', fromTransformable); + setTransformPropToTransitionFrom(transFromProps, 'y', fromTransformable); + setTransformPropToTransitionFrom(transFromProps, 'scaleX', fromTransformable); + setTransformPropToTransitionFrom(transFromProps, 'scaleY', fromTransformable); + setTransformPropToTransitionFrom(transFromProps, 'originX', fromTransformable); + setTransformPropToTransitionFrom(transFromProps, 'originY', fromTransformable); + setTransformPropToTransitionFrom(transFromProps, 'rotation', fromTransformable); + } else if (elOption.transition) { + var transitionKeys = normalizeToArray(elOption.transition); + + for (var i = 0; i < transitionKeys.length; i++) { + var key = transitionKeys[i]; + + if (key === 'style' || key === 'shape' || key === 'extra') { + continue; + } + + var elVal = el[key]; + + if ("development" !== 'production') { + checkTransformPropRefer(key, 'el.transition'); + checkNonStyleTansitionRefer(key, elOption[key], elVal); + } + + transFromProps[key] = elVal; + } + } else { + setTransformPropToTransitionFrom(transFromProps, 'x', el); + setTransformPropToTransitionFrom(transFromProps, 'y', el); + } + } + + var leaveTo = elOption.leaveTo; + + if (leaveTo) { + var leaveToProps = getOrCreateLeaveToPropsFromEl(el); + var leaveToKeys = keys(leaveTo); + + for (var i = 0; i < leaveToKeys.length; i++) { + var key = leaveToKeys[i]; + + if ("development" !== 'production') { + checkTransformPropRefer(key, 'el.leaveTo'); + } + + leaveToProps[key] = leaveTo[key]; + } + } + } + + function prepareTransformAllPropsFinal(elOption, allProps) { + setLagecyTransformProp(elOption, allProps, 'position'); + setLagecyTransformProp(elOption, allProps, 'scale'); + setLagecyTransformProp(elOption, allProps, 'origin'); + setTransformProp(elOption, allProps, 'x'); + setTransformProp(elOption, allProps, 'y'); + setTransformProp(elOption, allProps, 'scaleX'); + setTransformProp(elOption, allProps, 'scaleY'); + setTransformProp(elOption, allProps, 'originX'); + setTransformProp(elOption, allProps, 'originY'); + setTransformProp(elOption, allProps, 'rotation'); + } + + function prepareStyleTransitionFrom(el, morphFromEl, elOption, styleOpt, transFromProps, isInit) { + if (!styleOpt) { + return; + } + + var fromEl = morphFromEl || el; + var fromElStyle = fromEl.style; + var transFromStyleProps; + var enterFrom = styleOpt.enterFrom; + + if (isInit && enterFrom) { + var enterFromKeys = keys(enterFrom); + !transFromStyleProps && (transFromStyleProps = transFromProps.style = {}); + + for (var i = 0; i < enterFromKeys.length; i++) { + var key = enterFromKeys[i]; + transFromStyleProps[key] = enterFrom[key]; + } + } + + if (!isInit && fromElStyle) { + if (styleOpt.transition) { + var transitionKeys = normalizeToArray(styleOpt.transition); + !transFromStyleProps && (transFromStyleProps = transFromProps.style = {}); + + for (var i = 0; i < transitionKeys.length; i++) { + var key = transitionKeys[i]; + var elVal = fromElStyle[key]; + transFromStyleProps[key] = elVal; + } + } else if (el.getAnimationStyleProps && indexOf(elOption.transition, 'style') >= 0) { + var animationProps = el.getAnimationStyleProps(); + var animationStyleProps = animationProps ? animationProps.style : null; + + if (animationStyleProps) { + !transFromStyleProps && (transFromStyleProps = transFromProps.style = {}); + var styleKeys = keys(styleOpt); + + for (var i = 0; i < styleKeys.length; i++) { + var key = styleKeys[i]; + + if (animationStyleProps[key]) { + var elVal = fromElStyle[key]; + transFromStyleProps[key] = elVal; + } + } + } + } + } + + var leaveTo = styleOpt.leaveTo; + + if (leaveTo) { + var leaveToKeys = keys(leaveTo); + var leaveToProps = getOrCreateLeaveToPropsFromEl(el); + var leaveToStyleProps = leaveToProps.style || (leaveToProps.style = {}); + + for (var i = 0; i < leaveToKeys.length; i++) { + var key = leaveToKeys[i]; + leaveToStyleProps[key] = leaveTo[key]; + } + } + } + + function calcOldElLocalTransformBasedOnNewElParent(oldEl, newEl) { + if (!oldEl || oldEl === newEl || oldEl.parent === newEl.parent) { + return oldEl; + } + + var tmpM = tmpTransformable.transform || (tmpTransformable.transform = identity([])); + var oldGlobalTransform = oldEl.getComputedTransform(); + oldGlobalTransform ? copy$1(tmpM, oldGlobalTransform) : identity(tmpM); + var newParent = newEl.parent; + + if (newParent) { + newParent.getComputedTransform(); + } + + tmpTransformable.originX = oldEl.originX; + tmpTransformable.originY = oldEl.originY; + tmpTransformable.parent = newParent; + tmpTransformable.decomposeTransform(); + return tmpTransformable; + } + + var checkNonStyleTansitionRefer; + + if ("development" !== 'production') { + checkNonStyleTansitionRefer = function (propName, optVal, elVal) { + if (!isArrayLike(optVal)) { + assert(optVal != null && isFinite(optVal), 'Prop `' + propName + '` must refer to a finite number or ArrayLike for transition.'); + } else { + assert(optVal !== elVal, 'Prop `' + propName + '` must use different Array object each time for transition.'); + } + }; + } + + function isNonStyleTransitionEnabled(optVal, elVal) { + return !isArrayLike(optVal) ? optVal != null && isFinite(optVal) : optVal !== elVal; + } + + var checkTransformPropRefer; + + if ("development" !== 'production') { + checkTransformPropRefer = function (key, usedIn) { + assert(hasOwn(TRANSFORM_PROPS, key), 'Prop `' + key + '` is not a permitted in `' + usedIn + '`. ' + 'Only `' + keys(TRANSFORM_PROPS).join('`, `') + '` are permitted.'); + }; + } + + function getOrCreateLeaveToPropsFromEl(el) { + var innerEl = inner$b(el); + return innerEl.leaveToProps || (innerEl.leaveToProps = {}); + } + + var tmpDuringScope = {}; + var customDuringAPI = { + setTransform: function (key, val) { + if ("development" !== 'production') { + assert(hasOwn(TRANSFORM_PROPS, key), 'Only ' + transformPropNamesStr + ' available in `setTransform`.'); + } + + tmpDuringScope.el[key] = val; + return this; + }, + getTransform: function (key) { + if ("development" !== 'production') { + assert(hasOwn(TRANSFORM_PROPS, key), 'Only ' + transformPropNamesStr + ' available in `getTransform`.'); + } + + return tmpDuringScope.el[key]; + }, + setShape: function (key, val) { + if ("development" !== 'production') { + assertNotReserved(key); + } + + var shape = tmpDuringScope.el.shape || (tmpDuringScope.el.shape = {}); + shape[key] = val; + tmpDuringScope.isShapeDirty = true; + return this; + }, + getShape: function (key) { + if ("development" !== 'production') { + assertNotReserved(key); + } + + var shape = tmpDuringScope.el.shape; + + if (shape) { + return shape[key]; + } + }, + setStyle: function (key, val) { + if ("development" !== 'production') { + assertNotReserved(key); + } + + var style = tmpDuringScope.el.style; + + if (style) { + if ("development" !== 'production') { + if (eqNaN(val)) { + warn('style.' + key + ' must not be assigned with NaN.'); + } + } + + style[key] = val; + tmpDuringScope.isStyleDirty = true; + } + + return this; + }, + getStyle: function (key) { + if ("development" !== 'production') { + assertNotReserved(key); + } + + var style = tmpDuringScope.el.style; + + if (style) { + return style[key]; + } + }, + setExtra: function (key, val) { + if ("development" !== 'production') { + assertNotReserved(key); + } + + var extra = tmpDuringScope.el.extra || (tmpDuringScope.el.extra = {}); + extra[key] = val; + return this; + }, + getExtra: function (key) { + if ("development" !== 'production') { + assertNotReserved(key); + } + + var extra = tmpDuringScope.el.extra; + + if (extra) { + return extra[key]; + } + } + }; + + function assertNotReserved(key) { + if ("development" !== 'production') { + if (key === 'transition' || key === 'enterFrom' || key === 'leaveTo') { + throw new Error('key must not be "' + key + '"'); + } + } + } + + function duringCall() { + var scope = this; + var el = scope.el; + + if (!el) { + return; + } + + var newstUserDuring = inner$b(el).userDuring; + var scopeUserDuring = scope.userDuring; + + if (newstUserDuring !== scopeUserDuring) { + scope.el = scope.userDuring = null; + return; + } + + tmpDuringScope.el = el; + tmpDuringScope.isShapeDirty = false; + tmpDuringScope.isStyleDirty = false; + scopeUserDuring(customDuringAPI); + + if (tmpDuringScope.isShapeDirty && el.dirtyShape) { + el.dirtyShape(); + } + + if (tmpDuringScope.isStyleDirty && el.dirtyStyle) { + el.dirtyStyle(); + } + } + + function updateElOnState(state, el, elStateOpt, styleOpt, attachedTxInfo, isRoot, isTextContent) { + var elDisplayable = el.isGroup ? null : el; + var txCfgOpt = attachedTxInfo && attachedTxInfo[state].cfg; + + if (elDisplayable) { + var stateObj = elDisplayable.ensureState(state); + + if (styleOpt === false) { + var existingEmphasisState = elDisplayable.getState(state); + + if (existingEmphasisState) { + existingEmphasisState.style = null; + } + } else { + stateObj.style = styleOpt || null; + } + + if (txCfgOpt) { + stateObj.textConfig = txCfgOpt; + } + + setDefaultStateProxy(elDisplayable); + } + } + + function updateZ$1(el, elOption, seriesModel, attachedTxInfo) { + if (el.isGroup) { + return; + } + + var elDisplayable = el; + var currentZ = seriesModel.currentZ; + var currentZLevel = seriesModel.currentZLevel; + elDisplayable.z = currentZ; + elDisplayable.zlevel = currentZLevel; + var optZ2 = elOption.z2; + optZ2 != null && (elDisplayable.z2 = optZ2 || 0); + + for (var i = 0; i < STATES.length; i++) { + updateZForEachState(elDisplayable, elOption, STATES[i]); + } + } + + function updateZForEachState(elDisplayable, elOption, state) { + var isNormal = state === NORMAL; + var elStateOpt = isNormal ? elOption : retrieveStateOption(elOption, state); + var optZ2 = elStateOpt ? elStateOpt.z2 : null; + var stateObj; + + if (optZ2 != null) { + stateObj = isNormal ? elDisplayable : elDisplayable.ensureState(state); + stateObj.z2 = optZ2 || 0; + } + } + + function setLagecyTransformProp(elOption, targetProps, legacyName, fromTransformable) { + var legacyArr = elOption[legacyName]; + var xyName = LEGACY_TRANSFORM_PROPS[legacyName]; + + if (legacyArr) { + if (fromTransformable) { + targetProps[xyName[0]] = fromTransformable[xyName[0]]; + targetProps[xyName[1]] = fromTransformable[xyName[1]]; + } else { + targetProps[xyName[0]] = legacyArr[0]; + targetProps[xyName[1]] = legacyArr[1]; + } + } + } + + function setTransformProp(elOption, allProps, name, fromTransformable) { + if (elOption[name] != null) { + allProps[name] = fromTransformable ? fromTransformable[name] : elOption[name]; + } + } + + function setTransformPropToTransitionFrom(transitionFrom, name, fromTransformable) { + if (fromTransformable) { + transitionFrom[name] = fromTransformable[name]; + } + } + + function makeRenderItem(customSeries, data, ecModel, api) { + var renderItem = customSeries.get('renderItem'); + var coordSys = customSeries.coordinateSystem; + var prepareResult = {}; + + if (coordSys) { + if ("development" !== 'production') { + assert(renderItem, 'series.render is required.'); + assert(coordSys.prepareCustoms || prepareCustoms[coordSys.type], 'This coordSys does not support custom series.'); + } + + prepareResult = coordSys.prepareCustoms ? coordSys.prepareCustoms(coordSys) : prepareCustoms[coordSys.type](coordSys); + } + + var userAPI = defaults({ + getWidth: api.getWidth, + getHeight: api.getHeight, + getZr: api.getZr, + getDevicePixelRatio: api.getDevicePixelRatio, + value: value, + style: style, + ordinalRawValue: ordinalRawValue, + styleEmphasis: styleEmphasis, + visual: visual, + barLayout: barLayout, + currentSeriesIndices: currentSeriesIndices, + font: font + }, prepareResult.api || {}); + var userParams = { + context: {}, + seriesId: customSeries.id, + seriesName: customSeries.name, + seriesIndex: customSeries.seriesIndex, + coordSys: prepareResult.coordSys, + dataInsideLength: data.count(), + encode: wrapEncodeDef(customSeries.getData()) + }; + var currDataIndexInside; + var currItemModel; + var currItemStyleModels = {}; + var currLabelModels = {}; + var seriesItemStyleModels = {}; + var seriesLabelModels = {}; + + for (var i = 0; i < STATES.length; i++) { + var stateName = STATES[i]; + seriesItemStyleModels[stateName] = customSeries.getModel(PATH_ITEM_STYLE[stateName]); + seriesLabelModels[stateName] = customSeries.getModel(PATH_LABEL[stateName]); + } + + function getItemModel(dataIndexInside) { + return dataIndexInside === currDataIndexInside ? currItemModel || (currItemModel = data.getItemModel(dataIndexInside)) : data.getItemModel(dataIndexInside); + } + + function getItemStyleModel(dataIndexInside, state) { + return !data.hasItemOption ? seriesItemStyleModels[state] : dataIndexInside === currDataIndexInside ? currItemStyleModels[state] || (currItemStyleModels[state] = getItemModel(dataIndexInside).getModel(PATH_ITEM_STYLE[state])) : getItemModel(dataIndexInside).getModel(PATH_ITEM_STYLE[state]); + } + + function getLabelModel(dataIndexInside, state) { + return !data.hasItemOption ? seriesLabelModels[state] : dataIndexInside === currDataIndexInside ? currLabelModels[state] || (currLabelModels[state] = getItemModel(dataIndexInside).getModel(PATH_LABEL[state])) : getItemModel(dataIndexInside).getModel(PATH_LABEL[state]); + } + + return function (dataIndexInside, payload) { + currDataIndexInside = dataIndexInside; + currItemModel = null; + currItemStyleModels = {}; + currLabelModels = {}; + return renderItem && renderItem(defaults({ + dataIndexInside: dataIndexInside, + dataIndex: data.getRawIndex(dataIndexInside), + actionType: payload ? payload.type : null + }, userParams), userAPI); + }; + + function value(dim, dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + return data.get(data.getDimension(dim || 0), dataIndexInside); + } + + function ordinalRawValue(dim, dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + var dimInfo = data.getDimensionInfo(dim || 0); + + if (!dimInfo) { + return; + } + + var val = data.get(dimInfo.name, dataIndexInside); + var ordinalMeta = dimInfo && dimInfo.ordinalMeta; + return ordinalMeta ? ordinalMeta.categories[val] : val; + } + + function style(userProps, dataIndexInside) { + if ("development" !== 'production') { + warnDeprecated('api.style', 'Please write literal style directly instead.'); + } + + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + var style = data.getItemVisual(dataIndexInside, 'style'); + var visualColor = style && style.fill; + var opacity = style && style.opacity; + var itemStyle = getItemStyleModel(dataIndexInside, NORMAL).getItemStyle(); + visualColor != null && (itemStyle.fill = visualColor); + opacity != null && (itemStyle.opacity = opacity); + var opt = { + inheritColor: isString(visualColor) ? visualColor : '#000' + }; + var labelModel = getLabelModel(dataIndexInside, NORMAL); + var textStyle = createTextStyle(labelModel, null, opt, false, true); + textStyle.text = labelModel.getShallow('show') ? retrieve2(customSeries.getFormattedLabel(dataIndexInside, NORMAL), getDefaultLabel(data, dataIndexInside)) : null; + var textConfig = createTextConfig(labelModel, opt, false); + preFetchFromExtra(userProps, itemStyle); + itemStyle = convertToEC4StyleForCustomSerise(itemStyle, textStyle, textConfig); + userProps && applyUserPropsAfter(itemStyle, userProps); + itemStyle.legacy = true; + return itemStyle; + } + + function styleEmphasis(userProps, dataIndexInside) { + if ("development" !== 'production') { + warnDeprecated('api.styleEmphasis', 'Please write literal style directly instead.'); + } + + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + var itemStyle = getItemStyleModel(dataIndexInside, EMPHASIS).getItemStyle(); + var labelModel = getLabelModel(dataIndexInside, EMPHASIS); + var textStyle = createTextStyle(labelModel, null, null, true, true); + textStyle.text = labelModel.getShallow('show') ? retrieve3(customSeries.getFormattedLabel(dataIndexInside, EMPHASIS), customSeries.getFormattedLabel(dataIndexInside, NORMAL), getDefaultLabel(data, dataIndexInside)) : null; + var textConfig = createTextConfig(labelModel, null, true); + preFetchFromExtra(userProps, itemStyle); + itemStyle = convertToEC4StyleForCustomSerise(itemStyle, textStyle, textConfig); + userProps && applyUserPropsAfter(itemStyle, userProps); + itemStyle.legacy = true; + return itemStyle; + } + + function applyUserPropsAfter(itemStyle, extra) { + for (var key in extra) { + if (hasOwn(extra, key)) { + itemStyle[key] = extra[key]; + } + } + } + + function preFetchFromExtra(extra, itemStyle) { + if (extra) { + extra.textFill && (itemStyle.textFill = extra.textFill); + extra.textPosition && (itemStyle.textPosition = extra.textPosition); + } + } + + function visual(visualType, dataIndexInside) { + dataIndexInside == null && (dataIndexInside = currDataIndexInside); + + if (hasOwn(STYLE_VISUAL_TYPE, visualType)) { + var style_1 = data.getItemVisual(dataIndexInside, 'style'); + return style_1 ? style_1[STYLE_VISUAL_TYPE[visualType]] : null; + } + + if (hasOwn(NON_STYLE_VISUAL_PROPS, visualType)) { + return data.getItemVisual(dataIndexInside, visualType); + } + } + + function barLayout(opt) { + if (coordSys.type === 'cartesian2d') { + var baseAxis = coordSys.getBaseAxis(); + return getLayoutOnAxis(defaults({ + axis: baseAxis + }, opt)); + } + } + + function currentSeriesIndices() { + return ecModel.getCurrentSeriesIndices(); + } + + function font(opt) { + return getFont(opt, ecModel); + } + } + + function wrapEncodeDef(data) { + var encodeDef = {}; + each(data.dimensions, function (dimName, dataDimIndex) { + var dimInfo = data.getDimensionInfo(dimName); + + if (!dimInfo.isExtraCoord) { + var coordDim = dimInfo.coordDim; + var dataDims = encodeDef[coordDim] = encodeDef[coordDim] || []; + dataDims[dimInfo.coordDimIndex] = dataDimIndex; + } + }); + return encodeDef; + } + + function createOrUpdateItem(api, el, dataIndex, elOption, seriesModel, group, data, morphPreparation) { + if (!elOption) { + removeElementDirectly(el, group); + return; + } + + el = doCreateOrUpdateEl(api, el, dataIndex, elOption, seriesModel, group, true, morphPreparation); + el && data.setItemGraphicEl(dataIndex, el); + enableHoverEmphasis(el, elOption.focus, elOption.blurScope); + return el; + } + + function doCreateOrUpdateEl(api, el, dataIndex, elOption, seriesModel, group, isRoot, morphPreparation) { + if ("development" !== 'production') { + assert(elOption, 'should not have an null/undefined element setting'); + } + + var toBeReplacedIdx = -1; + + if (el && doesElNeedRecreate(el, elOption)) { + toBeReplacedIdx = group.childrenRef().indexOf(el); + el = null; + } + + var elIsNewCreated = !el; + + if (!el) { + el = createEl(elOption); + } else { + el.clearStates(); + } + + var canMorph = inner$b(el).canMorph = elOption.morph && isPath$1(el); + var thisElIsMorphTo = canMorph && morphPreparation && morphPreparation.hasFrom(); + var isInit = elIsNewCreated && !thisElIsMorphTo; + attachedTxInfoTmp.normal.cfg = attachedTxInfoTmp.normal.conOpt = attachedTxInfoTmp.emphasis.cfg = attachedTxInfoTmp.emphasis.conOpt = attachedTxInfoTmp.blur.cfg = attachedTxInfoTmp.blur.conOpt = attachedTxInfoTmp.select.cfg = attachedTxInfoTmp.select.conOpt = null; + attachedTxInfoTmp.isLegacy = false; + doCreateOrUpdateAttachedTx(el, dataIndex, elOption, seriesModel, isInit, attachedTxInfoTmp); + doCreateOrUpdateClipPath(el, dataIndex, elOption, seriesModel, isInit); + var pendingAllPropsFinal = updateElNormal(api, el, thisElIsMorphTo, dataIndex, elOption, elOption.style, attachedTxInfoTmp, seriesModel, isInit, false); + + if (thisElIsMorphTo) { + morphPreparation.addTo(el, elOption, dataIndex, pendingAllPropsFinal); + } + + for (var i = 0; i < STATES.length; i++) { + var stateName = STATES[i]; + + if (stateName !== NORMAL) { + var otherStateOpt = retrieveStateOption(elOption, stateName); + var otherStyleOpt = retrieveStyleOptionOnState(elOption, otherStateOpt, stateName); + updateElOnState(stateName, el, otherStateOpt, otherStyleOpt, attachedTxInfoTmp); + } + } + + updateZ$1(el, elOption, seriesModel); + + if (elOption.type === 'group') { + mergeChildren(api, el, dataIndex, elOption, seriesModel, morphPreparation); + } + + if (toBeReplacedIdx >= 0) { + group.replaceAt(el, toBeReplacedIdx); + } else { + group.add(el); + } + + return el; + } + + function doesElNeedRecreate(el, elOption) { + var elInner = inner$b(el); + var elOptionType = elOption.type; + var elOptionShape = elOption.shape; + var elOptionStyle = elOption.style; + return elOptionType != null && elOptionType !== elInner.customGraphicType || elOptionType === 'path' && hasOwnPathData(elOptionShape) && getPathData(elOptionShape) !== elInner.customPathData || elOptionType === 'image' && hasOwn(elOptionStyle, 'image') && elOptionStyle.image !== elInner.customImagePath; + } + + function doCreateOrUpdateClipPath(el, dataIndex, elOption, seriesModel, isInit) { + var clipPathOpt = elOption.clipPath; + + if (clipPathOpt === false) { + if (el && el.getClipPath()) { + el.removeClipPath(); + } + } else if (clipPathOpt) { + var clipPath = el.getClipPath(); + + if (clipPath && doesElNeedRecreate(clipPath, clipPathOpt)) { + clipPath = null; + } + + if (!clipPath) { + clipPath = createEl(clipPathOpt); + + if ("development" !== 'production') { + assert(clipPath instanceof Path, 'Only any type of `path` can be used in `clipPath`, rather than ' + clipPath.type + '.'); + } + + el.setClipPath(clipPath); + } + + updateElNormal(null, clipPath, null, dataIndex, clipPathOpt, null, null, seriesModel, isInit, false); + } + } + + function doCreateOrUpdateAttachedTx(el, dataIndex, elOption, seriesModel, isInit, attachedTxInfo) { + if (el.isGroup) { + return; + } + + processTxInfo(elOption, null, attachedTxInfo); + processTxInfo(elOption, EMPHASIS, attachedTxInfo); + var txConOptNormal = attachedTxInfo.normal.conOpt; + var txConOptEmphasis = attachedTxInfo.emphasis.conOpt; + var txConOptBlur = attachedTxInfo.blur.conOpt; + var txConOptSelect = attachedTxInfo.select.conOpt; + + if (txConOptNormal != null || txConOptEmphasis != null || txConOptSelect != null || txConOptBlur != null) { + var textContent = el.getTextContent(); + + if (txConOptNormal === false) { + textContent && el.removeTextContent(); + } else { + txConOptNormal = attachedTxInfo.normal.conOpt = txConOptNormal || { + type: 'text' + }; + + if (!textContent) { + textContent = createEl(txConOptNormal); + el.setTextContent(textContent); + } else { + textContent.clearStates(); + } + + var txConStlOptNormal = txConOptNormal && txConOptNormal.style; + updateElNormal(null, textContent, null, dataIndex, txConOptNormal, txConStlOptNormal, null, seriesModel, isInit, true); + + for (var i = 0; i < STATES.length; i++) { + var stateName = STATES[i]; + + if (stateName !== NORMAL) { + var txConOptOtherState = attachedTxInfo[stateName].conOpt; + updateElOnState(stateName, textContent, txConOptOtherState, retrieveStyleOptionOnState(txConOptNormal, txConOptOtherState, stateName), null); + } + } + + txConStlOptNormal ? textContent.dirty() : textContent.markRedraw(); + } + } + } + + function processTxInfo(elOption, state, attachedTxInfo) { + var stateOpt = !state ? elOption : retrieveStateOption(elOption, state); + var styleOpt = !state ? elOption.style : retrieveStyleOptionOnState(elOption, stateOpt, EMPHASIS); + var elType = elOption.type; + var txCfg = stateOpt ? stateOpt.textConfig : null; + var txConOptNormal = elOption.textContent; + var txConOpt = !txConOptNormal ? null : !state ? txConOptNormal : retrieveStateOption(txConOptNormal, state); + + if (styleOpt && (attachedTxInfo.isLegacy || isEC4CompatibleStyle(styleOpt, elType, !!txCfg, !!txConOpt))) { + attachedTxInfo.isLegacy = true; + var convertResult = convertFromEC4CompatibleStyle(styleOpt, elType, !state); + + if (!txCfg && convertResult.textConfig) { + txCfg = convertResult.textConfig; + } + + if (!txConOpt && convertResult.textContent) { + txConOpt = convertResult.textContent; + } + } + + if (!state && txConOpt) { + var txConOptNormal_1 = txConOpt; + !txConOptNormal_1.type && (txConOptNormal_1.type = 'text'); + + if ("development" !== 'production') { + txConOptNormal_1.type !== 'text' && assert(txConOptNormal_1.type === 'text', 'textContent.type must be "text"'); + } + } + + var info = !state ? attachedTxInfo.normal : attachedTxInfo[state]; + info.cfg = txCfg; + info.conOpt = txConOpt; + } + + function retrieveStateOption(elOption, state) { + return !state ? elOption : elOption ? elOption[state] : null; + } + + function retrieveStyleOptionOnState(stateOptionNormal, stateOption, state) { + var style = stateOption && stateOption.style; + + if (style == null && state === EMPHASIS && stateOptionNormal) { + style = stateOptionNormal.styleEmphasis; + } + + return style; + } + + function mergeChildren(api, el, dataIndex, elOption, seriesModel, morphPreparation) { + var newChildren = elOption.children; + var newLen = newChildren ? newChildren.length : 0; + var mergeChildren = elOption.$mergeChildren; + var byName = mergeChildren === 'byName' || elOption.diffChildrenByName; + var notMerge = mergeChildren === false; + + if (!newLen && !byName && !notMerge) { + return; + } + + if (byName) { + diffGroupChildren({ + api: api, + oldChildren: el.children() || [], + newChildren: newChildren || [], + dataIndex: dataIndex, + seriesModel: seriesModel, + group: el, + morphPreparation: morphPreparation + }); + return; + } + + notMerge && el.removeAll(); + var index = 0; + + for (; index < newLen; index++) { + newChildren[index] && doCreateOrUpdateEl(api, el.childAt(index), dataIndex, newChildren[index], seriesModel, el, false, morphPreparation); + } + + for (var i = el.childCount() - 1; i >= index; i--) { + doRemoveEl(el.childAt(i), seriesModel, el); + } + } + + function diffGroupChildren(context) { + new DataDiffer(context.oldChildren, context.newChildren, getKey, getKey, context).add(processAddUpdate).update(processAddUpdate).remove(processRemove).execute(); + } + + function getKey(item, idx) { + var name = item && item.name; + return name != null ? name : GROUP_DIFF_PREFIX + idx; + } + + function processAddUpdate(newIndex, oldIndex) { + var context = this.context; + var childOption = newIndex != null ? context.newChildren[newIndex] : null; + var child = oldIndex != null ? context.oldChildren[oldIndex] : null; + doCreateOrUpdateEl(context.api, child, context.dataIndex, childOption, context.seriesModel, context.group, false, context.morphPreparation); + } + + function processRemove(oldIndex) { + var context = this.context; + var child = context.oldChildren[oldIndex]; + doRemoveEl(child, context.seriesModel, context.group); + } + + function doRemoveEl(el, seriesModel, group) { + if (el) { + var leaveToProps = inner$b(el).leaveToProps; + leaveToProps ? updateProps(el, leaveToProps, seriesModel, { + cb: function () { + group.remove(el); + } + }) : group.remove(el); + } + } + + function getPathData(shape) { + return shape && (shape.pathData || shape.d); + } + + function hasOwnPathData(shape) { + return shape && (hasOwn(shape, 'pathData') || hasOwn(shape, 'd')); + } + + function isPath$1(el) { + return el && el instanceof Path; + } + + function removeElementDirectly(el, group) { + el && group.remove(el); + } + + var MorphPreparation = function () { + function MorphPreparation(seriesModel, transOpt) { + this._fromList = []; + this._toList = []; + this._toElOptionList = []; + this._allPropsFinalList = []; + this._toDataIndices = []; + this._morphConfigList = []; + this._seriesModel = seriesModel; + this._transOpt = transOpt; + } + + MorphPreparation.prototype.hasFrom = function () { + return !!this._fromList.length; + }; + + MorphPreparation.prototype.findAndAddFrom = function (el) { + if (!el) { + return; + } + + if (inner$b(el).canMorph) { + this._fromList.push(el); + } + + if (el.isGroup) { + var children = el.childrenRef(); + + for (var i = 0; i < children.length; i++) { + this.findAndAddFrom(children[i]); + } + } + }; + + MorphPreparation.prototype.addTo = function (path, elOption, dataIndex, allPropsFinal) { + if (path) { + this._toList.push(path); + + this._toElOptionList.push(elOption); + + this._toDataIndices.push(dataIndex); + + this._allPropsFinalList.push(allPropsFinal); + } + }; + + MorphPreparation.prototype.applyMorphing = function () { + var type = this._type; + var fromList = this._fromList; + var toList = this._toList; + var toListLen = toList.length; + var fromListLen = fromList.length; + + if (!fromListLen || !toListLen) { + return; + } + + if (type === 'oneToOne') { + for (var toIdx = 0; toIdx < toListLen; toIdx++) { + this._oneToOneForSingleTo(toIdx, toIdx); + } + } else if (type === 'manyToOne') { + var fromSingleSegLen = Math.max(1, Math.floor(fromListLen / toListLen)); + + for (var toIdx = 0, fromIdxStart = 0; toIdx < toListLen; toIdx++, fromIdxStart += fromSingleSegLen) { + var fromCount = toIdx + 1 >= toListLen ? fromListLen - fromIdxStart : fromSingleSegLen; + + this._manyToOneForSingleTo(toIdx, fromIdxStart >= fromListLen ? null : fromIdxStart, fromCount); + } + } else if (type === 'oneToMany') { + var toSingleSegLen = Math.max(1, Math.floor(toListLen / fromListLen)); + + for (var toIdxStart = 0, fromIdx = 0; toIdxStart < toListLen; toIdxStart += toSingleSegLen, fromIdx++) { + var toCount = toIdxStart + toSingleSegLen >= toListLen ? toListLen - toIdxStart : toSingleSegLen; + + this._oneToManyForSingleFrom(toIdxStart, toCount, fromIdx >= fromListLen ? null : fromIdx); + } + } + }; + + MorphPreparation.prototype._oneToOneForSingleTo = function (toIdx, fromIdx) { + var to = this._toList[toIdx]; + var toElOption = this._toElOptionList[toIdx]; + var toDataIndex = this._toDataIndices[toIdx]; + var allPropsFinal = this._allPropsFinalList[toIdx]; + var from = this._fromList[fromIdx]; + + var elAnimationConfig = this._getOrCreateMorphConfig(toDataIndex); + + var morphDuration = elAnimationConfig.duration; + + if (from && isCombiningPath(from)) { + applyPropsFinal(to, allPropsFinal, toElOption.style); + + if (morphDuration) { + var combineResult = combine([from], to, elAnimationConfig, copyPropsWhenDivided); + + this._processResultIndividuals(combineResult, toIdx, null); + } + } else { + var morphFrom = morphDuration && from && (from !== to || isInAnyMorphing(from)) ? from : null; + var transFromProps = {}; + prepareShapeOrExtraTransitionFrom('shape', to, morphFrom, toElOption, transFromProps, false); + prepareShapeOrExtraTransitionFrom('extra', to, morphFrom, toElOption, transFromProps, false); + prepareTransformTransitionFrom(to, morphFrom, toElOption, transFromProps, false); + prepareStyleTransitionFrom(to, morphFrom, toElOption, toElOption.style, transFromProps, false); + applyPropsFinal(to, allPropsFinal, toElOption.style); + + if (morphFrom) { + morphPath(morphFrom, to, elAnimationConfig); + } + + applyTransitionFrom(to, toDataIndex, toElOption, this._seriesModel, transFromProps, false); + } + }; + + MorphPreparation.prototype._manyToOneForSingleTo = function (toIdx, fromIdxStart, fromCount) { + var to = this._toList[toIdx]; + var toElOption = this._toElOptionList[toIdx]; + var allPropsFinal = this._allPropsFinalList[toIdx]; + applyPropsFinal(to, allPropsFinal, toElOption.style); + + var elAnimationConfig = this._getOrCreateMorphConfig(this._toDataIndices[toIdx]); + + if (elAnimationConfig.duration && fromIdxStart != null) { + var combineFromList = []; + + for (var fromIdx = fromIdxStart; fromIdx < fromCount; fromIdx++) { + combineFromList.push(this._fromList[fromIdx]); + } + + var combineResult = combine(combineFromList, to, elAnimationConfig, copyPropsWhenDivided); + + this._processResultIndividuals(combineResult, toIdx, null); + } + }; + + MorphPreparation.prototype._oneToManyForSingleFrom = function (toIdxStart, toCount, fromIdx) { + var from = fromIdx == null ? null : this._fromList[fromIdx]; + var toList = this._toList; + var separateToList = []; + + for (var toIdx = toIdxStart; toIdx < toCount; toIdx++) { + var to = toList[toIdx]; + applyPropsFinal(to, this._allPropsFinalList[toIdx], this._toElOptionList[toIdx].style); + separateToList.push(to); + } + + var elAnimationConfig = this._getOrCreateMorphConfig(this._toDataIndices[toIdxStart]); + + if (elAnimationConfig.duration && from) { + var separateResult = separate(from, separateToList, elAnimationConfig, copyPropsWhenDivided); + + this._processResultIndividuals(separateResult, toIdxStart, toCount); + } + }; + + MorphPreparation.prototype._processResultIndividuals = function (combineSeparateResult, toIdxStart, toCount) { + var isSeparate = toCount != null; + + for (var i = 0; i < combineSeparateResult.count; i++) { + var fromIndividual = combineSeparateResult.fromIndividuals[i]; + var toIndividual = combineSeparateResult.toIndividuals[i]; + var toIdx = toIdxStart + (isSeparate ? i : 0); + var toElOption = this._toElOptionList[toIdx]; + var dataIndex = this._toDataIndices[toIdx]; + var transFromProps = {}; + prepareTransformTransitionFrom(toIndividual, fromIndividual, toElOption, transFromProps, false); + prepareStyleTransitionFrom(toIndividual, fromIndividual, toElOption, toElOption.style, transFromProps, false); + applyTransitionFrom(toIndividual, dataIndex, toElOption, this._seriesModel, transFromProps, false); + } + }; + + MorphPreparation.prototype._getOrCreateMorphConfig = function (dataIndex) { + var morphConfigList = this._morphConfigList; + var config = morphConfigList[dataIndex]; + + if (config) { + return config; + } + + var duration; + var easing; + var delay; + var seriesModel = this._seriesModel; + var transOpt = this._transOpt; + + if (seriesModel.isAnimationEnabled()) { + var animationPayload = void 0; + + if (seriesModel && seriesModel.ecModel) { + var updatePayload = seriesModel.ecModel.getUpdatePayload(); + animationPayload = updatePayload && updatePayload.animation; + } + + if (animationPayload) { + duration = animationPayload.duration || 0; + easing = animationPayload.easing || 'cubicOut'; + delay = animationPayload.delay || 0; + } else { + easing = seriesModel.get('animationEasingUpdate'); + var delayOption = seriesModel.get('animationDelayUpdate'); + delay = isFunction(delayOption) ? delayOption(dataIndex) : delayOption; + var durationOption = seriesModel.get('animationDurationUpdate'); + duration = isFunction(durationOption) ? durationOption(dataIndex) : durationOption; + } + } + + config = { + duration: duration || 0, + delay: delay, + easing: easing, + dividingMethod: transOpt ? transOpt.dividingMethod : null + }; + morphConfigList[dataIndex] = config; + return config; + }; + + MorphPreparation.prototype.reset = function (type) { + this._type = type; + this._fromList.length = this._toList.length = this._toElOptionList.length = this._allPropsFinalList.length = this._toDataIndices.length = 0; + }; + + return MorphPreparation; + }(); + + function copyPropsWhenDivided(srcPath, tarPath, willClone) { + tarPath.style = willClone ? clone(srcPath.style) : srcPath.style; + tarPath.zlevel = srcPath.zlevel; + tarPath.z = srcPath.z; + tarPath.z2 = srcPath.z2; + } + + function install$q(registers) { + registers.registerChartView(CustomSeriesView); + registers.registerSeriesModel(CustomSeriesModel); + } + + var inner$c = makeInner(); + var clone$3 = clone; + var bind$1 = bind; + + var BaseAxisPointer = function () { + function BaseAxisPointer() { + this._dragging = false; + this.animationThreshold = 15; + } + + BaseAxisPointer.prototype.render = function (axisModel, axisPointerModel, api, forceRender) { + var value = axisPointerModel.get('value'); + var status = axisPointerModel.get('status'); + this._axisModel = axisModel; + this._axisPointerModel = axisPointerModel; + this._api = api; + + if (!forceRender && this._lastValue === value && this._lastStatus === status) { + return; + } + + this._lastValue = value; + this._lastStatus = status; + var group = this._group; + var handle = this._handle; + + if (!status || status === 'hide') { + group && group.hide(); + handle && handle.hide(); + return; + } + + group && group.show(); + handle && handle.show(); + var elOption = {}; + this.makeElOption(elOption, value, axisModel, axisPointerModel, api); + var graphicKey = elOption.graphicKey; + + if (graphicKey !== this._lastGraphicKey) { + this.clear(api); + } + + this._lastGraphicKey = graphicKey; + var moveAnimation = this._moveAnimation = this.determineAnimation(axisModel, axisPointerModel); + + if (!group) { + group = this._group = new Group(); + this.createPointerEl(group, elOption, axisModel, axisPointerModel); + this.createLabelEl(group, elOption, axisModel, axisPointerModel); + api.getZr().add(group); + } else { + var doUpdateProps = curry(updateProps$1, axisPointerModel, moveAnimation); + this.updatePointerEl(group, elOption, doUpdateProps); + this.updateLabelEl(group, elOption, doUpdateProps, axisPointerModel); + } + + updateMandatoryProps(group, axisPointerModel, true); + + this._renderHandle(value); + }; + + BaseAxisPointer.prototype.remove = function (api) { + this.clear(api); + }; + + BaseAxisPointer.prototype.dispose = function (api) { + this.clear(api); + }; + + BaseAxisPointer.prototype.determineAnimation = function (axisModel, axisPointerModel) { + var animation = axisPointerModel.get('animation'); + var axis = axisModel.axis; + var isCategoryAxis = axis.type === 'category'; + var useSnap = axisPointerModel.get('snap'); + + if (!useSnap && !isCategoryAxis) { + return false; + } + + if (animation === 'auto' || animation == null) { + var animationThreshold = this.animationThreshold; + + if (isCategoryAxis && axis.getBandWidth() > animationThreshold) { + return true; + } + + if (useSnap) { + var seriesDataCount = getAxisInfo(axisModel).seriesDataCount; + var axisExtent = axis.getExtent(); + return Math.abs(axisExtent[0] - axisExtent[1]) / seriesDataCount > animationThreshold; + } + + return false; + } + + return animation === true; + }; + + BaseAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) {}; + + BaseAxisPointer.prototype.createPointerEl = function (group, elOption, axisModel, axisPointerModel) { + var pointerOption = elOption.pointer; + + if (pointerOption) { + var pointerEl = inner$c(group).pointerEl = new graphic[pointerOption.type](clone$3(elOption.pointer)); + group.add(pointerEl); + } + }; + + BaseAxisPointer.prototype.createLabelEl = function (group, elOption, axisModel, axisPointerModel) { + if (elOption.label) { + var labelEl = inner$c(group).labelEl = new ZRText(clone$3(elOption.label)); + group.add(labelEl); + updateLabelShowHide(labelEl, axisPointerModel); + } + }; + + BaseAxisPointer.prototype.updatePointerEl = function (group, elOption, updateProps) { + var pointerEl = inner$c(group).pointerEl; + + if (pointerEl && elOption.pointer) { + pointerEl.setStyle(elOption.pointer.style); + updateProps(pointerEl, { + shape: elOption.pointer.shape + }); + } + }; + + BaseAxisPointer.prototype.updateLabelEl = function (group, elOption, updateProps, axisPointerModel) { + var labelEl = inner$c(group).labelEl; + + if (labelEl) { + labelEl.setStyle(elOption.label.style); + updateProps(labelEl, { + x: elOption.label.x, + y: elOption.label.y + }); + updateLabelShowHide(labelEl, axisPointerModel); + } + }; + + BaseAxisPointer.prototype._renderHandle = function (value) { + if (this._dragging || !this.updateHandleTransform) { + return; + } + + var axisPointerModel = this._axisPointerModel; + + var zr = this._api.getZr(); + + var handle = this._handle; + var handleModel = axisPointerModel.getModel('handle'); + var status = axisPointerModel.get('status'); + + if (!handleModel.get('show') || !status || status === 'hide') { + handle && zr.remove(handle); + this._handle = null; + return; + } + + var isInit; + + if (!this._handle) { + isInit = true; + handle = this._handle = createIcon(handleModel.get('icon'), { + cursor: 'move', + draggable: true, + onmousemove: function (e) { + stop(e.event); + }, + onmousedown: bind$1(this._onHandleDragMove, this, 0, 0), + drift: bind$1(this._onHandleDragMove, this), + ondragend: bind$1(this._onHandleDragEnd, this) + }); + zr.add(handle); + } + + updateMandatoryProps(handle, axisPointerModel, false); + handle.setStyle(handleModel.getItemStyle(null, ['color', 'borderColor', 'borderWidth', 'opacity', 'shadowColor', 'shadowBlur', 'shadowOffsetX', 'shadowOffsetY'])); + var handleSize = handleModel.get('size'); + + if (!isArray(handleSize)) { + handleSize = [handleSize, handleSize]; + } + + handle.scaleX = handleSize[0] / 2; + handle.scaleY = handleSize[1] / 2; + createOrUpdate(this, '_doDispatchAxisPointer', handleModel.get('throttle') || 0, 'fixRate'); + + this._moveHandleToValue(value, isInit); + }; + + BaseAxisPointer.prototype._moveHandleToValue = function (value, isInit) { + updateProps$1(this._axisPointerModel, !isInit && this._moveAnimation, this._handle, getHandleTransProps(this.getHandleTransform(value, this._axisModel, this._axisPointerModel))); + }; + + BaseAxisPointer.prototype._onHandleDragMove = function (dx, dy) { + var handle = this._handle; + + if (!handle) { + return; + } + + this._dragging = true; + var trans = this.updateHandleTransform(getHandleTransProps(handle), [dx, dy], this._axisModel, this._axisPointerModel); + this._payloadInfo = trans; + handle.stopAnimation(); + handle.attr(getHandleTransProps(trans)); + inner$c(handle).lastProp = null; + + this._doDispatchAxisPointer(); + }; + + BaseAxisPointer.prototype._doDispatchAxisPointer = function () { + var handle = this._handle; + + if (!handle) { + return; + } + + var payloadInfo = this._payloadInfo; + var axisModel = this._axisModel; + + this._api.dispatchAction({ + type: 'updateAxisPointer', + x: payloadInfo.cursorPoint[0], + y: payloadInfo.cursorPoint[1], + tooltipOption: payloadInfo.tooltipOption, + axesInfo: [{ + axisDim: axisModel.axis.dim, + axisIndex: axisModel.componentIndex + }] + }); + }; + + BaseAxisPointer.prototype._onHandleDragEnd = function () { + this._dragging = false; + var handle = this._handle; + + if (!handle) { + return; + } + + var value = this._axisPointerModel.get('value'); + + this._moveHandleToValue(value); + + this._api.dispatchAction({ + type: 'hideTip' + }); + }; + + BaseAxisPointer.prototype.clear = function (api) { + this._lastValue = null; + this._lastStatus = null; + var zr = api.getZr(); + var group = this._group; + var handle = this._handle; + + if (zr && group) { + this._lastGraphicKey = null; + group && zr.remove(group); + handle && zr.remove(handle); + this._group = null; + this._handle = null; + this._payloadInfo = null; + } + }; + + BaseAxisPointer.prototype.doClear = function () {}; + + BaseAxisPointer.prototype.buildLabel = function (xy, wh, xDimIndex) { + xDimIndex = xDimIndex || 0; + return { + x: xy[xDimIndex], + y: xy[1 - xDimIndex], + width: wh[xDimIndex], + height: wh[1 - xDimIndex] + }; + }; + + return BaseAxisPointer; + }(); + + function updateProps$1(animationModel, moveAnimation, el, props) { + if (!propsEqual(inner$c(el).lastProp, props)) { + inner$c(el).lastProp = props; + moveAnimation ? updateProps(el, props, animationModel) : (el.stopAnimation(), el.attr(props)); + } + } + + function propsEqual(lastProps, newProps) { + if (isObject(lastProps) && isObject(newProps)) { + var equals_1 = true; + each(newProps, function (item, key) { + equals_1 = equals_1 && propsEqual(lastProps[key], item); + }); + return !!equals_1; + } else { + return lastProps === newProps; + } + } + + function updateLabelShowHide(labelEl, axisPointerModel) { + labelEl[axisPointerModel.get(['label', 'show']) ? 'show' : 'hide'](); + } + + function getHandleTransProps(trans) { + return { + x: trans.x || 0, + y: trans.y || 0, + rotation: trans.rotation || 0 + }; + } + + function updateMandatoryProps(group, axisPointerModel, silent) { + var z = axisPointerModel.get('z'); + var zlevel = axisPointerModel.get('zlevel'); + group && group.traverse(function (el) { + if (el.type !== 'group') { + z != null && (el.z = z); + zlevel != null && (el.zlevel = zlevel); + el.silent = silent; + } + }); + } + + function buildElStyle(axisPointerModel) { + var axisPointerType = axisPointerModel.get('type'); + var styleModel = axisPointerModel.getModel(axisPointerType + 'Style'); + var style; + + if (axisPointerType === 'line') { + style = styleModel.getLineStyle(); + style.fill = null; + } else if (axisPointerType === 'shadow') { + style = styleModel.getAreaStyle(); + style.stroke = null; + } + + return style; + } + function buildLabelElOption(elOption, axisModel, axisPointerModel, api, labelPos) { + var value = axisPointerModel.get('value'); + var text = getValueLabel(value, axisModel.axis, axisModel.ecModel, axisPointerModel.get('seriesDataIndices'), { + precision: axisPointerModel.get(['label', 'precision']), + formatter: axisPointerModel.get(['label', 'formatter']) + }); + var labelModel = axisPointerModel.getModel('label'); + var paddings = normalizeCssArray$1(labelModel.get('padding') || 0); + var font = labelModel.getFont(); + var textRect = getBoundingRect(text, font); + var position = labelPos.position; + var width = textRect.width + paddings[1] + paddings[3]; + var height = textRect.height + paddings[0] + paddings[2]; + var align = labelPos.align; + align === 'right' && (position[0] -= width); + align === 'center' && (position[0] -= width / 2); + var verticalAlign = labelPos.verticalAlign; + verticalAlign === 'bottom' && (position[1] -= height); + verticalAlign === 'middle' && (position[1] -= height / 2); + confineInContainer(position, width, height, api); + var bgColor = labelModel.get('backgroundColor'); + + if (!bgColor || bgColor === 'auto') { + bgColor = axisModel.get(['axisLine', 'lineStyle', 'color']); + } + + elOption.label = { + x: position[0], + y: position[1], + style: createTextStyle(labelModel, { + text: text, + font: font, + fill: labelModel.getTextColor(), + padding: paddings, + backgroundColor: bgColor + }), + z2: 10 + }; + } + + function confineInContainer(position, width, height, api) { + var viewWidth = api.getWidth(); + var viewHeight = api.getHeight(); + position[0] = Math.min(position[0] + width, viewWidth) - width; + position[1] = Math.min(position[1] + height, viewHeight) - height; + position[0] = Math.max(position[0], 0); + position[1] = Math.max(position[1], 0); + } + + function getValueLabel(value, axis, ecModel, seriesDataIndices, opt) { + value = axis.scale.parse(value); + var text = axis.scale.getLabel({ + value: value + }, { + precision: opt.precision + }); + var formatter = opt.formatter; + + if (formatter) { + var params_1 = { + value: getAxisRawValue(axis, { + value: value + }), + axisDimension: axis.dim, + axisIndex: axis.index, + seriesData: [] + }; + each(seriesDataIndices, function (idxItem) { + var series = ecModel.getSeriesByIndex(idxItem.seriesIndex); + var dataIndex = idxItem.dataIndexInside; + var dataParams = series && series.getDataParams(dataIndex); + dataParams && params_1.seriesData.push(dataParams); + }); + + if (isString(formatter)) { + text = formatter.replace('{value}', text); + } else if (isFunction(formatter)) { + text = formatter(params_1); + } + } + + return text; + } + function getTransformedPosition(axis, value, layoutInfo) { + var transform = create$1(); + rotate(transform, transform, layoutInfo.rotation); + translate(transform, transform, layoutInfo.position); + return applyTransform$1([axis.dataToCoord(value), (layoutInfo.labelOffset || 0) + (layoutInfo.labelDirection || 1) * (layoutInfo.labelMargin || 0)], transform); + } + function buildCartesianSingleLabelElOption(value, elOption, layoutInfo, axisModel, axisPointerModel, api) { + var textLayout = AxisBuilder.innerTextLayout(layoutInfo.rotation, 0, layoutInfo.labelDirection); + layoutInfo.labelMargin = axisPointerModel.get(['label', 'margin']); + buildLabelElOption(elOption, axisModel, axisPointerModel, api, { + position: getTransformedPosition(axisModel.axis, value, layoutInfo), + align: textLayout.textAlign, + verticalAlign: textLayout.textVerticalAlign + }); + } + function makeLineShape(p1, p2, xDimIndex) { + xDimIndex = xDimIndex || 0; + return { + x1: p1[xDimIndex], + y1: p1[1 - xDimIndex], + x2: p2[xDimIndex], + y2: p2[1 - xDimIndex] + }; + } + function makeRectShape(xy, wh, xDimIndex) { + xDimIndex = xDimIndex || 0; + return { + x: xy[xDimIndex], + y: xy[1 - xDimIndex], + width: wh[xDimIndex], + height: wh[1 - xDimIndex] + }; + } + function makeSectorShape(cx, cy, r0, r, startAngle, endAngle) { + return { + cx: cx, + cy: cy, + r0: r0, + r: r, + startAngle: startAngle, + endAngle: endAngle, + clockwise: true + }; + } + + var CartesianAxisPointer = function (_super) { + __extends(CartesianAxisPointer, _super); + + function CartesianAxisPointer() { + return _super !== null && _super.apply(this, arguments) || this; + } + + CartesianAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) { + var axis = axisModel.axis; + var grid = axis.grid; + var axisPointerType = axisPointerModel.get('type'); + var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent(); + var pixelValue = axis.toGlobalCoord(axis.dataToCoord(value, true)); + + if (axisPointerType && axisPointerType !== 'none') { + var elStyle = buildElStyle(axisPointerModel); + var pointerOption = pointerShapeBuilder[axisPointerType](axis, pixelValue, otherExtent); + pointerOption.style = elStyle; + elOption.graphicKey = pointerOption.type; + elOption.pointer = pointerOption; + } + + var layoutInfo = layout$1(grid.model, axisModel); + buildCartesianSingleLabelElOption(value, elOption, layoutInfo, axisModel, axisPointerModel, api); + }; + + CartesianAxisPointer.prototype.getHandleTransform = function (value, axisModel, axisPointerModel) { + var layoutInfo = layout$1(axisModel.axis.grid.model, axisModel, { + labelInside: false + }); + layoutInfo.labelMargin = axisPointerModel.get(['handle', 'margin']); + var pos = getTransformedPosition(axisModel.axis, value, layoutInfo); + return { + x: pos[0], + y: pos[1], + rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0) + }; + }; + + CartesianAxisPointer.prototype.updateHandleTransform = function (transform, delta, axisModel, axisPointerModel) { + var axis = axisModel.axis; + var grid = axis.grid; + var axisExtent = axis.getGlobalExtent(true); + var otherExtent = getCartesian(grid, axis).getOtherAxis(axis).getGlobalExtent(); + var dimIndex = axis.dim === 'x' ? 0 : 1; + var currPosition = [transform.x, transform.y]; + currPosition[dimIndex] += delta[dimIndex]; + currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]); + currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]); + var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2; + var cursorPoint = [cursorOtherValue, cursorOtherValue]; + cursorPoint[dimIndex] = currPosition[dimIndex]; + var tooltipOptions = [{ + verticalAlign: 'middle' + }, { + align: 'center' + }]; + return { + x: currPosition[0], + y: currPosition[1], + rotation: transform.rotation, + cursorPoint: cursorPoint, + tooltipOption: tooltipOptions[dimIndex] + }; + }; + + return CartesianAxisPointer; + }(BaseAxisPointer); + + function getCartesian(grid, axis) { + var opt = {}; + opt[axis.dim + 'AxisIndex'] = axis.index; + return grid.getCartesian(opt); + } + + var pointerShapeBuilder = { + line: function (axis, pixelValue, otherExtent) { + var targetShape = makeLineShape([pixelValue, otherExtent[0]], [pixelValue, otherExtent[1]], getAxisDimIndex(axis)); + return { + type: 'Line', + subPixelOptimize: true, + shape: targetShape + }; + }, + shadow: function (axis, pixelValue, otherExtent) { + var bandWidth = Math.max(1, axis.getBandWidth()); + var span = otherExtent[1] - otherExtent[0]; + return { + type: 'Rect', + shape: makeRectShape([pixelValue - bandWidth / 2, otherExtent[0]], [bandWidth, span], getAxisDimIndex(axis)) + }; + } + }; + + function getAxisDimIndex(axis) { + return axis.dim === 'x' ? 0 : 1; + } + + var AxisPointerModel = function (_super) { + __extends(AxisPointerModel, _super); + + function AxisPointerModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = AxisPointerModel.type; + return _this; + } + + AxisPointerModel.type = 'axisPointer'; + AxisPointerModel.defaultOption = { + show: 'auto', + zlevel: 0, + z: 50, + type: 'line', + snap: false, + triggerTooltip: true, + value: null, + status: null, + link: [], + animation: null, + animationDurationUpdate: 200, + lineStyle: { + color: '#B9BEC9', + width: 1, + type: 'dashed' + }, + shadowStyle: { + color: 'rgba(210,219,238,0.2)' + }, + label: { + show: true, + formatter: null, + precision: 'auto', + margin: 3, + color: '#fff', + padding: [5, 7, 5, 7], + backgroundColor: 'auto', + borderColor: null, + borderWidth: 0, + borderRadius: 3 + }, + handle: { + show: false, + 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 + } + }; + return AxisPointerModel; + }(ComponentModel); + + var inner$d = makeInner(); + var each$8 = each; + function register(key, api, handler) { + if (env.node) { + return; + } + + var zr = api.getZr(); + inner$d(zr).records || (inner$d(zr).records = {}); + initGlobalListeners(zr, api); + var record = inner$d(zr).records[key] || (inner$d(zr).records[key] = {}); + record.handler = handler; + } + + function initGlobalListeners(zr, api) { + if (inner$d(zr).initialized) { + return; + } + + inner$d(zr).initialized = true; + useHandler('click', curry(doEnter, 'click')); + useHandler('mousemove', curry(doEnter, 'mousemove')); + useHandler('globalout', onLeave); + + function useHandler(eventType, cb) { + zr.on(eventType, function (e) { + var dis = makeDispatchAction(api); + each$8(inner$d(zr).records, function (record) { + record && cb(record, e, dis.dispatchAction); + }); + dispatchTooltipFinally(dis.pendings, api); + }); + } + } + + function dispatchTooltipFinally(pendings, api) { + var showLen = pendings.showTip.length; + var hideLen = pendings.hideTip.length; + var actuallyPayload; + + if (showLen) { + actuallyPayload = pendings.showTip[showLen - 1]; + } else if (hideLen) { + actuallyPayload = pendings.hideTip[hideLen - 1]; + } + + if (actuallyPayload) { + actuallyPayload.dispatchAction = null; + api.dispatchAction(actuallyPayload); + } + } + + function onLeave(record, e, dispatchAction) { + record.handler('leave', null, dispatchAction); + } + + function doEnter(currTrigger, record, e, dispatchAction) { + record.handler(currTrigger, e, dispatchAction); + } + + function makeDispatchAction(api) { + var pendings = { + showTip: [], + hideTip: [] + }; + + var dispatchAction = function (payload) { + var pendingList = pendings[payload.type]; + + if (pendingList) { + pendingList.push(payload); + } else { + payload.dispatchAction = dispatchAction; + api.dispatchAction(payload); + } + }; + + return { + dispatchAction: dispatchAction, + pendings: pendings + }; + } + + function unregister(key, api) { + if (env.node) { + return; + } + + var zr = api.getZr(); + var record = (inner$d(zr).records || {})[key]; + + if (record) { + inner$d(zr).records[key] = null; + } + } + + var AxisPointerView = function (_super) { + __extends(AxisPointerView, _super); + + function AxisPointerView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = AxisPointerView.type; + return _this; + } + + AxisPointerView.prototype.render = function (globalAxisPointerModel, ecModel, api) { + var globalTooltipModel = ecModel.getComponent('tooltip'); + var triggerOn = globalAxisPointerModel.get('triggerOn') || globalTooltipModel && globalTooltipModel.get('triggerOn') || 'mousemove|click'; + register('axisPointer', api, function (currTrigger, e, dispatchAction) { + if (triggerOn !== 'none' && (currTrigger === 'leave' || triggerOn.indexOf(currTrigger) >= 0)) { + dispatchAction({ + type: 'updateAxisPointer', + currTrigger: currTrigger, + x: e && e.offsetX, + y: e && e.offsetY + }); + } + }); + }; + + AxisPointerView.prototype.remove = function (ecModel, api) { + unregister('axisPointer', api); + }; + + AxisPointerView.prototype.dispose = function (ecModel, api) { + unregister('axisPointer', api); + }; + + AxisPointerView.type = 'axisPointer'; + return AxisPointerView; + }(ComponentView); + + function findPointFromSeries(finder, ecModel) { + var point = []; + var seriesIndex = finder.seriesIndex; + var seriesModel; + + if (seriesIndex == null || !(seriesModel = ecModel.getSeriesByIndex(seriesIndex))) { + return { + point: [] + }; + } + + var data = seriesModel.getData(); + var dataIndex = queryDataIndex(data, finder); + + if (dataIndex == null || dataIndex < 0 || isArray(dataIndex)) { + return { + point: [] + }; + } + + var el = data.getItemGraphicEl(dataIndex); + var coordSys = seriesModel.coordinateSystem; + + if (seriesModel.getTooltipPosition) { + point = seriesModel.getTooltipPosition(dataIndex) || []; + } else if (coordSys && coordSys.dataToPoint) { + if (finder.isStacked) { + var baseAxis = coordSys.getBaseAxis(); + var valueAxis = coordSys.getOtherAxis(baseAxis); + var valueAxisDim = valueAxis.dim; + var baseAxisDim = baseAxis.dim; + var baseDataOffset = valueAxisDim === 'x' || valueAxisDim === 'radius' ? 1 : 0; + var baseDim = data.mapDimension(baseAxisDim); + var stackedData = []; + stackedData[baseDataOffset] = data.get(baseDim, dataIndex); + stackedData[1 - baseDataOffset] = data.get(data.getCalculationInfo('stackResultDimension'), dataIndex); + point = coordSys.dataToPoint(stackedData) || []; + } else { + point = coordSys.dataToPoint(data.getValues(map(coordSys.dimensions, function (dim) { + return data.mapDimension(dim); + }), dataIndex)) || []; + } + } else if (el) { + var rect = el.getBoundingRect().clone(); + rect.applyTransform(el.transform); + point = [rect.x + rect.width / 2, rect.y + rect.height / 2]; + } + + return { + point: point, + el: el + }; + } + + var inner$e = makeInner(); + function axisTrigger(payload, ecModel, api) { + var currTrigger = payload.currTrigger; + var point = [payload.x, payload.y]; + var finder = payload; + var dispatchAction = payload.dispatchAction || bind(api.dispatchAction, api); + var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo; + + if (!coordSysAxesInfo) { + return; + } + + if (illegalPoint(point)) { + point = findPointFromSeries({ + seriesIndex: finder.seriesIndex, + dataIndex: finder.dataIndex + }, ecModel).point; + } + + var isIllegalPoint = illegalPoint(point); + var inputAxesInfo = finder.axesInfo; + var axesInfo = coordSysAxesInfo.axesInfo; + var shouldHide = currTrigger === 'leave' || illegalPoint(point); + var outputPayload = {}; + var showValueMap = {}; + var dataByCoordSys = { + list: [], + map: {} + }; + var updaters = { + showPointer: curry(showPointer, showValueMap), + showTooltip: curry(showTooltip, dataByCoordSys) + }; + each(coordSysAxesInfo.coordSysMap, function (coordSys, coordSysKey) { + var coordSysContainsPoint = isIllegalPoint || coordSys.containPoint(point); + each(coordSysAxesInfo.coordSysAxesInfo[coordSysKey], function (axisInfo, key) { + var axis = axisInfo.axis; + var inputAxisInfo = findInputAxisInfo(inputAxesInfo, axisInfo); + + if (!shouldHide && coordSysContainsPoint && (!inputAxesInfo || inputAxisInfo)) { + var val = inputAxisInfo && inputAxisInfo.value; + + if (val == null && !isIllegalPoint) { + val = axis.pointToData(point); + } + + val != null && processOnAxis(axisInfo, val, updaters, false, outputPayload); + } + }); + }); + var linkTriggers = {}; + each(axesInfo, function (tarAxisInfo, tarKey) { + var linkGroup = tarAxisInfo.linkGroup; + + if (linkGroup && !showValueMap[tarKey]) { + each(linkGroup.axesInfo, function (srcAxisInfo, srcKey) { + var srcValItem = showValueMap[srcKey]; + + if (srcAxisInfo !== tarAxisInfo && srcValItem) { + var val = srcValItem.value; + linkGroup.mapper && (val = tarAxisInfo.axis.scale.parse(linkGroup.mapper(val, makeMapperParam(srcAxisInfo), makeMapperParam(tarAxisInfo)))); + linkTriggers[tarAxisInfo.key] = val; + } + }); + } + }); + each(linkTriggers, function (val, tarKey) { + processOnAxis(axesInfo[tarKey], val, updaters, true, outputPayload); + }); + updateModelActually(showValueMap, axesInfo, outputPayload); + dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction); + dispatchHighDownActually(axesInfo, dispatchAction, api); + return outputPayload; + } + + function processOnAxis(axisInfo, newValue, updaters, noSnap, outputFinder) { + var axis = axisInfo.axis; + + if (axis.scale.isBlank() || !axis.containData(newValue)) { + return; + } + + if (!axisInfo.involveSeries) { + updaters.showPointer(axisInfo, newValue); + return; + } + + var payloadInfo = buildPayloadsBySeries(newValue, axisInfo); + var payloadBatch = payloadInfo.payloadBatch; + var snapToValue = payloadInfo.snapToValue; + + if (payloadBatch[0] && outputFinder.seriesIndex == null) { + extend(outputFinder, payloadBatch[0]); + } + + if (!noSnap && axisInfo.snap) { + if (axis.containData(snapToValue) && snapToValue != null) { + newValue = snapToValue; + } + } + + updaters.showPointer(axisInfo, newValue, payloadBatch); + updaters.showTooltip(axisInfo, payloadInfo, snapToValue); + } + + function buildPayloadsBySeries(value, axisInfo) { + var axis = axisInfo.axis; + var dim = axis.dim; + var snapToValue = value; + var payloadBatch = []; + var minDist = Number.MAX_VALUE; + var minDiff = -1; + each(axisInfo.seriesModels, function (series, idx) { + var dataDim = series.getData().mapDimensionsAll(dim); + var seriesNestestValue; + var dataIndices; + + if (series.getAxisTooltipData) { + var result = series.getAxisTooltipData(dataDim, value, axis); + dataIndices = result.dataIndices; + seriesNestestValue = result.nestestValue; + } else { + dataIndices = series.getData().indicesOfNearest(dataDim[0], value, axis.type === 'category' ? 0.5 : null); + + if (!dataIndices.length) { + return; + } + + seriesNestestValue = series.getData().get(dataDim[0], dataIndices[0]); + } + + if (seriesNestestValue == null || !isFinite(seriesNestestValue)) { + return; + } + + var diff = value - seriesNestestValue; + var dist = Math.abs(diff); + + if (dist <= minDist) { + if (dist < minDist || diff >= 0 && minDiff < 0) { + minDist = dist; + minDiff = diff; + snapToValue = seriesNestestValue; + payloadBatch.length = 0; + } + + each(dataIndices, function (dataIndex) { + payloadBatch.push({ + seriesIndex: series.seriesIndex, + dataIndexInside: dataIndex, + dataIndex: series.getData().getRawIndex(dataIndex) + }); + }); + } + }); + return { + payloadBatch: payloadBatch, + snapToValue: snapToValue + }; + } + + function showPointer(showValueMap, axisInfo, value, payloadBatch) { + showValueMap[axisInfo.key] = { + value: value, + payloadBatch: payloadBatch + }; + } + + function showTooltip(dataByCoordSys, axisInfo, payloadInfo, value) { + var payloadBatch = payloadInfo.payloadBatch; + var axis = axisInfo.axis; + var axisModel = axis.model; + var axisPointerModel = axisInfo.axisPointerModel; + + if (!axisInfo.triggerTooltip || !payloadBatch.length) { + return; + } + + var coordSysModel = axisInfo.coordSys.model; + var coordSysKey = makeKey(coordSysModel); + var coordSysItem = dataByCoordSys.map[coordSysKey]; + + if (!coordSysItem) { + coordSysItem = dataByCoordSys.map[coordSysKey] = { + coordSysId: coordSysModel.id, + coordSysIndex: coordSysModel.componentIndex, + coordSysType: coordSysModel.type, + coordSysMainType: coordSysModel.mainType, + dataByAxis: [] + }; + dataByCoordSys.list.push(coordSysItem); + } + + coordSysItem.dataByAxis.push({ + axisDim: axis.dim, + axisIndex: axisModel.componentIndex, + axisType: axisModel.type, + axisId: axisModel.id, + value: value, + valueLabelOpt: { + precision: axisPointerModel.get(['label', 'precision']), + formatter: axisPointerModel.get(['label', 'formatter']) + }, + seriesDataIndices: payloadBatch.slice() + }); + } + + function updateModelActually(showValueMap, axesInfo, outputPayload) { + var outputAxesInfo = outputPayload.axesInfo = []; + each(axesInfo, function (axisInfo, key) { + var option = axisInfo.axisPointerModel.option; + var valItem = showValueMap[key]; + + if (valItem) { + !axisInfo.useHandle && (option.status = 'show'); + option.value = valItem.value; + option.seriesDataIndices = (valItem.payloadBatch || []).slice(); + } else { + !axisInfo.useHandle && (option.status = 'hide'); + } + + option.status === 'show' && outputAxesInfo.push({ + axisDim: axisInfo.axis.dim, + axisIndex: axisInfo.axis.model.componentIndex, + value: option.value + }); + }); + } + + function dispatchTooltipActually(dataByCoordSys, point, payload, dispatchAction) { + if (illegalPoint(point) || !dataByCoordSys.list.length) { + dispatchAction({ + type: 'hideTip' + }); + return; + } + + var sampleItem = ((dataByCoordSys.list[0].dataByAxis[0] || {}).seriesDataIndices || [])[0] || {}; + dispatchAction({ + type: 'showTip', + escapeConnect: true, + x: point[0], + y: point[1], + tooltipOption: payload.tooltipOption, + position: payload.position, + dataIndexInside: sampleItem.dataIndexInside, + dataIndex: sampleItem.dataIndex, + seriesIndex: sampleItem.seriesIndex, + dataByCoordSys: dataByCoordSys.list + }); + } + + function dispatchHighDownActually(axesInfo, dispatchAction, api) { + var zr = api.getZr(); + var highDownKey = 'axisPointerLastHighlights'; + var lastHighlights = inner$e(zr)[highDownKey] || {}; + var newHighlights = inner$e(zr)[highDownKey] = {}; + each(axesInfo, function (axisInfo, key) { + var option = axisInfo.axisPointerModel.option; + option.status === 'show' && each(option.seriesDataIndices, function (batchItem) { + var key = batchItem.seriesIndex + ' | ' + batchItem.dataIndex; + newHighlights[key] = batchItem; + }); + }); + var toHighlight = []; + var toDownplay = []; + each(lastHighlights, function (batchItem, key) { + !newHighlights[key] && toDownplay.push(batchItem); + }); + each(newHighlights, function (batchItem, key) { + !lastHighlights[key] && toHighlight.push(batchItem); + }); + toDownplay.length && api.dispatchAction({ + type: 'downplay', + escapeConnect: true, + notBlur: true, + batch: toDownplay + }); + toHighlight.length && api.dispatchAction({ + type: 'highlight', + escapeConnect: true, + notBlur: true, + batch: toHighlight + }); + } + + function findInputAxisInfo(inputAxesInfo, axisInfo) { + for (var i = 0; i < (inputAxesInfo || []).length; i++) { + var inputAxisInfo = inputAxesInfo[i]; + + if (axisInfo.axis.dim === inputAxisInfo.axisDim && axisInfo.axis.model.componentIndex === inputAxisInfo.axisIndex) { + return inputAxisInfo; + } + } + } + + function makeMapperParam(axisInfo) { + var axisModel = axisInfo.axis.model; + var item = {}; + var dim = item.axisDim = axisInfo.axis.dim; + item.axisIndex = item[dim + 'AxisIndex'] = axisModel.componentIndex; + item.axisName = item[dim + 'AxisName'] = axisModel.name; + item.axisId = item[dim + 'AxisId'] = axisModel.id; + return item; + } + + function illegalPoint(point) { + return !point || point[0] == null || isNaN(point[0]) || point[1] == null || isNaN(point[1]); + } + + function install$r(registers) { + AxisView.registerAxisPointerClass('CartesianAxisPointer', CartesianAxisPointer); + registers.registerComponentModel(AxisPointerModel); + registers.registerComponentView(AxisPointerView); + registers.registerPreprocessor(function (option) { + if (option) { + (!option.axisPointer || option.axisPointer.length === 0) && (option.axisPointer = {}); + var link = option.axisPointer.link; + + if (link && !isArray(link)) { + option.axisPointer.link = [link]; + } + } + }); + registers.registerProcessor(registers.PRIORITY.PROCESSOR.STATISTIC, function (ecModel, api) { + ecModel.getComponent('axisPointer').coordSysAxesInfo = collect(ecModel, api); + }); + registers.registerAction({ + type: 'updateAxisPointer', + event: 'updateAxisPointer', + update: ':updateAxisPointer' + }, axisTrigger); + } + + function install$s(registers) { + use(install$5); + use(install$r); + } + + var PolarAxisPointer = function (_super) { + __extends(PolarAxisPointer, _super); + + function PolarAxisPointer() { + return _super !== null && _super.apply(this, arguments) || this; + } + + PolarAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) { + var axis = axisModel.axis; + + if (axis.dim === 'angle') { + this.animationThreshold = Math.PI / 18; + } + + var polar = axis.polar; + var otherAxis = polar.getOtherAxis(axis); + var otherExtent = otherAxis.getExtent(); + var coordValue = axis.dataToCoord(value); + var axisPointerType = axisPointerModel.get('type'); + + if (axisPointerType && axisPointerType !== 'none') { + var elStyle = buildElStyle(axisPointerModel); + var pointerOption = pointerShapeBuilder$1[axisPointerType](axis, polar, coordValue, otherExtent); + pointerOption.style = elStyle; + elOption.graphicKey = pointerOption.type; + elOption.pointer = pointerOption; + } + + var labelMargin = axisPointerModel.get(['label', 'margin']); + var labelPos = getLabelPosition(value, axisModel, axisPointerModel, polar, labelMargin); + buildLabelElOption(elOption, axisModel, axisPointerModel, api, labelPos); + }; + + return PolarAxisPointer; + }(BaseAxisPointer); + + function getLabelPosition(value, axisModel, axisPointerModel, polar, labelMargin) { + var axis = axisModel.axis; + var coord = axis.dataToCoord(value); + var axisAngle = polar.getAngleAxis().getExtent()[0]; + axisAngle = axisAngle / 180 * Math.PI; + var radiusExtent = polar.getRadiusAxis().getExtent(); + var position; + var align; + var verticalAlign; + + if (axis.dim === 'radius') { + var transform = create$1(); + rotate(transform, transform, axisAngle); + translate(transform, transform, [polar.cx, polar.cy]); + position = applyTransform$1([coord, -labelMargin], transform); + var labelRotation = axisModel.getModel('axisLabel').get('rotate') || 0; + var labelLayout = AxisBuilder.innerTextLayout(axisAngle, labelRotation * Math.PI / 180, -1); + align = labelLayout.textAlign; + verticalAlign = labelLayout.textVerticalAlign; + } else { + var r = radiusExtent[1]; + position = polar.coordToPoint([r + labelMargin, coord]); + var cx = polar.cx; + var cy = polar.cy; + align = Math.abs(position[0] - cx) / r < 0.3 ? 'center' : position[0] > cx ? 'left' : 'right'; + verticalAlign = Math.abs(position[1] - cy) / r < 0.3 ? 'middle' : position[1] > cy ? 'top' : 'bottom'; + } + + return { + position: position, + align: align, + verticalAlign: verticalAlign + }; + } + + var pointerShapeBuilder$1 = { + line: function (axis, polar, coordValue, otherExtent) { + return axis.dim === 'angle' ? { + type: 'Line', + shape: makeLineShape(polar.coordToPoint([otherExtent[0], coordValue]), polar.coordToPoint([otherExtent[1], coordValue])) + } : { + type: 'Circle', + shape: { + cx: polar.cx, + cy: polar.cy, + r: coordValue + } + }; + }, + shadow: function (axis, polar, coordValue, otherExtent) { + var bandWidth = Math.max(1, axis.getBandWidth()); + var radian = Math.PI / 180; + return axis.dim === 'angle' ? { + type: 'Sector', + shape: makeSectorShape(polar.cx, polar.cy, otherExtent[0], otherExtent[1], (-coordValue - bandWidth / 2) * radian, (-coordValue + bandWidth / 2) * radian) + } : { + type: 'Sector', + shape: makeSectorShape(polar.cx, polar.cy, coordValue - bandWidth / 2, coordValue + bandWidth / 2, 0, Math.PI * 2) + }; + } + }; + + var PolarModel = function (_super) { + __extends(PolarModel, _super); + + function PolarModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = PolarModel.type; + return _this; + } + + PolarModel.prototype.findAxisModel = function (axisType) { + var foundAxisModel; + var ecModel = this.ecModel; + ecModel.eachComponent(axisType, function (axisModel) { + if (axisModel.getCoordSysModel() === this) { + foundAxisModel = axisModel; + } + }, this); + return foundAxisModel; + }; + + PolarModel.type = 'polar'; + PolarModel.dependencies = ['radiusAxis', 'angleAxis']; + PolarModel.defaultOption = { + zlevel: 0, + z: 0, + center: ['50%', '50%'], + radius: '80%' + }; + return PolarModel; + }(ComponentModel); + + var PolarAxisModel = function (_super) { + __extends(PolarAxisModel, _super); + + function PolarAxisModel() { + return _super !== null && _super.apply(this, arguments) || this; + } + + PolarAxisModel.prototype.getCoordSysModel = function () { + return this.getReferringComponents('polar', SINGLE_REFERRING).models[0]; + }; + + PolarAxisModel.type = 'polarAxis'; + return PolarAxisModel; + }(ComponentModel); + + mixin(PolarAxisModel, AxisModelCommonMixin); + + var AngleAxisModel = function (_super) { + __extends(AngleAxisModel, _super); + + function AngleAxisModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = AngleAxisModel.type; + return _this; + } + + AngleAxisModel.type = 'angleAxis'; + return AngleAxisModel; + }(PolarAxisModel); + + var RadiusAxisModel = function (_super) { + __extends(RadiusAxisModel, _super); + + function RadiusAxisModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = RadiusAxisModel.type; + return _this; + } + + RadiusAxisModel.type = 'radiusAxis'; + return RadiusAxisModel; + }(PolarAxisModel); + + var RadiusAxis = function (_super) { + __extends(RadiusAxis, _super); + + function RadiusAxis(scale, radiusExtent) { + return _super.call(this, 'radius', scale, radiusExtent) || this; + } + + RadiusAxis.prototype.pointToData = function (point, clamp) { + return this.polar.pointToData(point, clamp)[this.dim === 'radius' ? 0 : 1]; + }; + + return RadiusAxis; + }(Axis); + + RadiusAxis.prototype.dataToRadius = Axis.prototype.dataToCoord; + RadiusAxis.prototype.radiusToData = Axis.prototype.coordToData; + + var inner$f = makeInner(); + + var AngleAxis = function (_super) { + __extends(AngleAxis, _super); + + function AngleAxis(scale, angleExtent) { + return _super.call(this, 'angle', scale, angleExtent || [0, 360]) || this; + } + + AngleAxis.prototype.pointToData = function (point, clamp) { + return this.polar.pointToData(point, clamp)[this.dim === 'radius' ? 0 : 1]; + }; + + AngleAxis.prototype.calculateCategoryInterval = function () { + var axis = this; + var labelModel = axis.getLabelModel(); + var ordinalScale = axis.scale; + var ordinalExtent = ordinalScale.getExtent(); + var tickCount = ordinalScale.count(); + + if (ordinalExtent[1] - ordinalExtent[0] < 1) { + return 0; + } + + var tickValue = ordinalExtent[0]; + var unitSpan = axis.dataToCoord(tickValue + 1) - axis.dataToCoord(tickValue); + var unitH = Math.abs(unitSpan); + var rect = getBoundingRect(tickValue == null ? '' : tickValue + '', labelModel.getFont(), 'center', 'top'); + var maxH = Math.max(rect.height, 7); + var dh = maxH / unitH; + isNaN(dh) && (dh = Infinity); + var interval = Math.max(0, Math.floor(dh)); + var cache = inner$f(axis.model); + var lastAutoInterval = cache.lastAutoInterval; + var lastTickCount = cache.lastTickCount; + + if (lastAutoInterval != null && lastTickCount != null && Math.abs(lastAutoInterval - interval) <= 1 && Math.abs(lastTickCount - tickCount) <= 1 && lastAutoInterval > interval) { + interval = lastAutoInterval; + } else { + cache.lastTickCount = tickCount; + cache.lastAutoInterval = interval; + } + + return interval; + }; + + return AngleAxis; + }(Axis); + + AngleAxis.prototype.dataToAngle = Axis.prototype.dataToCoord; + AngleAxis.prototype.angleToData = Axis.prototype.coordToData; + + var Polar = function () { + function Polar(name) { + this.dimensions = ['radius', 'angle']; + this.type = 'polar'; + this.cx = 0; + this.cy = 0; + this._radiusAxis = new RadiusAxis(); + this._angleAxis = new AngleAxis(); + this.axisPointerEnabled = true; + this.name = name || ''; + this._radiusAxis.polar = this._angleAxis.polar = this; + } + + Polar.prototype.containPoint = function (point) { + var coord = this.pointToCoord(point); + return this._radiusAxis.contain(coord[0]) && this._angleAxis.contain(coord[1]); + }; + + Polar.prototype.containData = function (data) { + return this._radiusAxis.containData(data[0]) && this._angleAxis.containData(data[1]); + }; + + Polar.prototype.getAxis = function (dim) { + var key = '_' + dim + 'Axis'; + return this[key]; + }; + + Polar.prototype.getAxes = function () { + return [this._radiusAxis, this._angleAxis]; + }; + + Polar.prototype.getAxesByScale = function (scaleType) { + var axes = []; + var angleAxis = this._angleAxis; + var radiusAxis = this._radiusAxis; + angleAxis.scale.type === scaleType && axes.push(angleAxis); + radiusAxis.scale.type === scaleType && axes.push(radiusAxis); + return axes; + }; + + Polar.prototype.getAngleAxis = function () { + return this._angleAxis; + }; + + Polar.prototype.getRadiusAxis = function () { + return this._radiusAxis; + }; + + Polar.prototype.getOtherAxis = function (axis) { + var angleAxis = this._angleAxis; + return axis === angleAxis ? this._radiusAxis : angleAxis; + }; + + Polar.prototype.getBaseAxis = function () { + return this.getAxesByScale('ordinal')[0] || this.getAxesByScale('time')[0] || this.getAngleAxis(); + }; + + Polar.prototype.getTooltipAxes = function (dim) { + var baseAxis = dim != null && dim !== 'auto' ? this.getAxis(dim) : this.getBaseAxis(); + return { + baseAxes: [baseAxis], + otherAxes: [this.getOtherAxis(baseAxis)] + }; + }; + + Polar.prototype.dataToPoint = function (data, clamp) { + return this.coordToPoint([this._radiusAxis.dataToRadius(data[0], clamp), this._angleAxis.dataToAngle(data[1], clamp)]); + }; + + Polar.prototype.pointToData = function (point, clamp) { + var coord = this.pointToCoord(point); + return [this._radiusAxis.radiusToData(coord[0], clamp), this._angleAxis.angleToData(coord[1], clamp)]; + }; + + Polar.prototype.pointToCoord = function (point) { + var dx = point[0] - this.cx; + var dy = point[1] - this.cy; + var angleAxis = this.getAngleAxis(); + var extent = angleAxis.getExtent(); + var minAngle = Math.min(extent[0], extent[1]); + var maxAngle = Math.max(extent[0], extent[1]); + angleAxis.inverse ? minAngle = maxAngle - 360 : maxAngle = minAngle + 360; + var radius = Math.sqrt(dx * dx + dy * dy); + dx /= radius; + dy /= radius; + var radian = Math.atan2(-dy, dx) / Math.PI * 180; + var dir = radian < minAngle ? 1 : -1; + + while (radian < minAngle || radian > maxAngle) { + radian += dir * 360; + } + + return [radius, radian]; + }; + + Polar.prototype.coordToPoint = function (coord) { + var radius = coord[0]; + var radian = coord[1] / 180 * Math.PI; + var x = Math.cos(radian) * radius + this.cx; + var y = -Math.sin(radian) * radius + this.cy; + return [x, y]; + }; + + Polar.prototype.getArea = function () { + var angleAxis = this.getAngleAxis(); + var radiusAxis = this.getRadiusAxis(); + var radiusExtent = radiusAxis.getExtent().slice(); + radiusExtent[0] > radiusExtent[1] && radiusExtent.reverse(); + var angleExtent = angleAxis.getExtent(); + var RADIAN = Math.PI / 180; + return { + cx: this.cx, + cy: this.cy, + r0: radiusExtent[0], + r: radiusExtent[1], + startAngle: -angleExtent[0] * RADIAN, + endAngle: -angleExtent[1] * RADIAN, + clockwise: angleAxis.inverse, + contain: function (x, y) { + var dx = x - this.cx; + var dy = y - this.cy; + var d2 = dx * dx + dy * dy; + var r = this.r; + var r0 = this.r0; + return d2 <= r * r && d2 >= r0 * r0; + } + }; + }; + + Polar.prototype.convertToPixel = function (ecModel, finder, value) { + var coordSys = getCoordSys$1(finder); + return coordSys === this ? this.dataToPoint(value) : null; + }; + + Polar.prototype.convertFromPixel = function (ecModel, finder, pixel) { + var coordSys = getCoordSys$1(finder); + return coordSys === this ? this.pointToData(pixel) : null; + }; + + return Polar; + }(); + + function getCoordSys$1(finder) { + var seriesModel = finder.seriesModel; + var polarModel = finder.polarModel; + return polarModel && polarModel.coordinateSystem || seriesModel && seriesModel.coordinateSystem; + } + + function resizePolar(polar, polarModel, api) { + var center = polarModel.get('center'); + var width = api.getWidth(); + var height = api.getHeight(); + polar.cx = parsePercent$1(center[0], width); + polar.cy = parsePercent$1(center[1], height); + var radiusAxis = polar.getRadiusAxis(); + var size = Math.min(width, height) / 2; + var radius = polarModel.get('radius'); + + if (radius == null) { + radius = [0, '100%']; + } else if (!isArray(radius)) { + radius = [0, radius]; + } + + var parsedRadius = [parsePercent$1(radius[0], size), parsePercent$1(radius[1], size)]; + radiusAxis.inverse ? radiusAxis.setExtent(parsedRadius[1], parsedRadius[0]) : radiusAxis.setExtent(parsedRadius[0], parsedRadius[1]); + } + + function updatePolarScale(ecModel, api) { + var polar = this; + var angleAxis = polar.getAngleAxis(); + var radiusAxis = polar.getRadiusAxis(); + angleAxis.scale.setExtent(Infinity, -Infinity); + radiusAxis.scale.setExtent(Infinity, -Infinity); + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.coordinateSystem === polar) { + var data_1 = seriesModel.getData(); + each(getDataDimensionsOnAxis(data_1, 'radius'), function (dim) { + radiusAxis.scale.unionExtentFromData(data_1, dim); + }); + each(getDataDimensionsOnAxis(data_1, 'angle'), function (dim) { + angleAxis.scale.unionExtentFromData(data_1, dim); + }); + } + }); + niceScaleExtent(angleAxis.scale, angleAxis.model); + niceScaleExtent(radiusAxis.scale, radiusAxis.model); + + if (angleAxis.type === 'category' && !angleAxis.onBand) { + var extent = angleAxis.getExtent(); + var diff = 360 / angleAxis.scale.count(); + angleAxis.inverse ? extent[1] += diff : extent[1] -= diff; + angleAxis.setExtent(extent[0], extent[1]); + } + } + + function isAngleAxisModel(axisModel) { + return axisModel.mainType === 'angleAxis'; + } + + function setAxis(axis, axisModel) { + axis.type = axisModel.get('type'); + axis.scale = createScaleByModel(axisModel); + axis.onBand = axisModel.get('boundaryGap') && axis.type === 'category'; + axis.inverse = axisModel.get('inverse'); + + if (isAngleAxisModel(axisModel)) { + axis.inverse = axis.inverse !== axisModel.get('clockwise'); + var startAngle = axisModel.get('startAngle'); + axis.setExtent(startAngle, startAngle + (axis.inverse ? -360 : 360)); + } + + axisModel.axis = axis; + axis.model = axisModel; + } + + var polarCreator = { + dimensions: Polar.prototype.dimensions, + create: function (ecModel, api) { + var polarList = []; + ecModel.eachComponent('polar', function (polarModel, idx) { + var polar = new Polar(idx + ''); + polar.update = updatePolarScale; + var radiusAxis = polar.getRadiusAxis(); + var angleAxis = polar.getAngleAxis(); + var radiusAxisModel = polarModel.findAxisModel('radiusAxis'); + var angleAxisModel = polarModel.findAxisModel('angleAxis'); + setAxis(radiusAxis, radiusAxisModel); + setAxis(angleAxis, angleAxisModel); + resizePolar(polar, polarModel, api); + polarList.push(polar); + polarModel.coordinateSystem = polar; + polar.model = polarModel; + }); + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'polar') { + var polarModel = seriesModel.getReferringComponents('polar', SINGLE_REFERRING).models[0]; + + if ("development" !== 'production') { + if (!polarModel) { + throw new Error('Polar "' + retrieve(seriesModel.get('polarIndex'), seriesModel.get('polarId'), 0) + '" not found'); + } + } + + seriesModel.coordinateSystem = polarModel.coordinateSystem; + } + }); + return polarList; + } + }; + + var elementList$1 = ['axisLine', 'axisLabel', 'axisTick', 'minorTick', 'splitLine', 'minorSplitLine', 'splitArea']; + + function getAxisLineShape(polar, rExtent, angle) { + rExtent[1] > rExtent[0] && (rExtent = rExtent.slice().reverse()); + var start = polar.coordToPoint([rExtent[0], angle]); + var end = polar.coordToPoint([rExtent[1], angle]); + return { + x1: start[0], + y1: start[1], + x2: end[0], + y2: end[1] + }; + } + + function getRadiusIdx(polar) { + var radiusAxis = polar.getRadiusAxis(); + return radiusAxis.inverse ? 0 : 1; + } + + function fixAngleOverlap(list) { + var firstItem = list[0]; + var lastItem = list[list.length - 1]; + + if (firstItem && lastItem && Math.abs(Math.abs(firstItem.coord - lastItem.coord) - 360) < 1e-4) { + list.pop(); + } + } + + var AngleAxisView = function (_super) { + __extends(AngleAxisView, _super); + + function AngleAxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = AngleAxisView.type; + _this.axisPointerClass = 'PolarAxisPointer'; + return _this; + } + + AngleAxisView.prototype.render = function (angleAxisModel, ecModel) { + this.group.removeAll(); + + if (!angleAxisModel.get('show')) { + return; + } + + var angleAxis = angleAxisModel.axis; + var polar = angleAxis.polar; + var radiusExtent = polar.getRadiusAxis().getExtent(); + var ticksAngles = angleAxis.getTicksCoords(); + var minorTickAngles = angleAxis.getMinorTicksCoords(); + var labels = map(angleAxis.getViewLabels(), function (labelItem) { + labelItem = clone(labelItem); + var scale = angleAxis.scale; + var tickValue = scale.type === 'ordinal' ? scale.getRawOrdinalNumber(labelItem.tickValue) : labelItem.tickValue; + labelItem.coord = angleAxis.dataToCoord(tickValue); + return labelItem; + }); + fixAngleOverlap(labels); + fixAngleOverlap(ticksAngles); + each(elementList$1, function (name) { + if (angleAxisModel.get([name, 'show']) && (!angleAxis.scale.isBlank() || name === 'axisLine')) { + angelAxisElementsBuilders[name](this.group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent, labels); + } + }, this); + }; + + AngleAxisView.type = 'angleAxis'; + return AngleAxisView; + }(AxisView); + + var angelAxisElementsBuilders = { + axisLine: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) { + var lineStyleModel = angleAxisModel.getModel(['axisLine', 'lineStyle']); + var rId = getRadiusIdx(polar); + var r0Id = rId ? 0 : 1; + var shape; + + if (radiusExtent[r0Id] === 0) { + shape = new Circle({ + shape: { + cx: polar.cx, + cy: polar.cy, + r: radiusExtent[rId] + }, + style: lineStyleModel.getLineStyle(), + z2: 1, + silent: true + }); + } else { + shape = new Ring({ + shape: { + cx: polar.cx, + cy: polar.cy, + r: radiusExtent[rId], + r0: radiusExtent[r0Id] + }, + style: lineStyleModel.getLineStyle(), + z2: 1, + silent: true + }); + } + + shape.style.fill = null; + group.add(shape); + }, + axisTick: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) { + var tickModel = angleAxisModel.getModel('axisTick'); + var tickLen = (tickModel.get('inside') ? -1 : 1) * tickModel.get('length'); + var radius = radiusExtent[getRadiusIdx(polar)]; + var lines = map(ticksAngles, function (tickAngleItem) { + return new Line({ + shape: getAxisLineShape(polar, [radius, radius + tickLen], tickAngleItem.coord) + }); + }); + group.add(mergePath$1(lines, { + style: defaults(tickModel.getModel('lineStyle').getLineStyle(), { + stroke: angleAxisModel.get(['axisLine', 'lineStyle', 'color']) + }) + })); + }, + minorTick: function (group, angleAxisModel, polar, tickAngles, minorTickAngles, radiusExtent) { + if (!minorTickAngles.length) { + return; + } + + var tickModel = angleAxisModel.getModel('axisTick'); + var minorTickModel = angleAxisModel.getModel('minorTick'); + var tickLen = (tickModel.get('inside') ? -1 : 1) * minorTickModel.get('length'); + var radius = radiusExtent[getRadiusIdx(polar)]; + var lines = []; + + for (var i = 0; i < minorTickAngles.length; i++) { + for (var k = 0; k < minorTickAngles[i].length; k++) { + lines.push(new Line({ + shape: getAxisLineShape(polar, [radius, radius + tickLen], minorTickAngles[i][k].coord) + })); + } + } + + group.add(mergePath$1(lines, { + style: defaults(minorTickModel.getModel('lineStyle').getLineStyle(), defaults(tickModel.getLineStyle(), { + stroke: angleAxisModel.get(['axisLine', 'lineStyle', 'color']) + })) + })); + }, + axisLabel: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent, labels) { + var rawCategoryData = angleAxisModel.getCategories(true); + var commonLabelModel = angleAxisModel.getModel('axisLabel'); + var labelMargin = commonLabelModel.get('margin'); + var triggerEvent = angleAxisModel.get('triggerEvent'); + each(labels, function (labelItem, idx) { + var labelModel = commonLabelModel; + var tickValue = labelItem.tickValue; + var r = radiusExtent[getRadiusIdx(polar)]; + var p = polar.coordToPoint([r + labelMargin, labelItem.coord]); + var cx = polar.cx; + var cy = polar.cy; + var labelTextAlign = Math.abs(p[0] - cx) / r < 0.3 ? 'center' : p[0] > cx ? 'left' : 'right'; + var labelTextVerticalAlign = Math.abs(p[1] - cy) / r < 0.3 ? 'middle' : p[1] > cy ? 'top' : 'bottom'; + + if (rawCategoryData && rawCategoryData[tickValue]) { + var rawCategoryItem = rawCategoryData[tickValue]; + + if (isObject(rawCategoryItem) && rawCategoryItem.textStyle) { + labelModel = new Model(rawCategoryItem.textStyle, commonLabelModel, commonLabelModel.ecModel); + } + } + + var textEl = new ZRText({ + silent: AxisBuilder.isLabelSilent(angleAxisModel), + style: createTextStyle(labelModel, { + x: p[0], + y: p[1], + fill: labelModel.getTextColor() || angleAxisModel.get(['axisLine', 'lineStyle', 'color']), + text: labelItem.formattedLabel, + align: labelTextAlign, + verticalAlign: labelTextVerticalAlign + }) + }); + group.add(textEl); + + if (triggerEvent) { + var eventData = AxisBuilder.makeAxisEventDataBase(angleAxisModel); + eventData.targetType = 'axisLabel'; + eventData.value = labelItem.rawLabel; + getECData(textEl).eventData = eventData; + } + }, this); + }, + splitLine: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) { + var splitLineModel = angleAxisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + var lineCount = 0; + lineColors = lineColors instanceof Array ? lineColors : [lineColors]; + var splitLines = []; + + for (var i = 0; i < ticksAngles.length; i++) { + var colorIndex = lineCount++ % lineColors.length; + splitLines[colorIndex] = splitLines[colorIndex] || []; + splitLines[colorIndex].push(new Line({ + shape: getAxisLineShape(polar, radiusExtent, ticksAngles[i].coord) + })); + } + + for (var i = 0; i < splitLines.length; i++) { + group.add(mergePath$1(splitLines[i], { + style: defaults({ + stroke: lineColors[i % lineColors.length] + }, lineStyleModel.getLineStyle()), + silent: true, + z: angleAxisModel.get('z') + })); + } + }, + minorSplitLine: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) { + if (!minorTickAngles.length) { + return; + } + + var minorSplitLineModel = angleAxisModel.getModel('minorSplitLine'); + var lineStyleModel = minorSplitLineModel.getModel('lineStyle'); + var lines = []; + + for (var i = 0; i < minorTickAngles.length; i++) { + for (var k = 0; k < minorTickAngles[i].length; k++) { + lines.push(new Line({ + shape: getAxisLineShape(polar, radiusExtent, minorTickAngles[i][k].coord) + })); + } + } + + group.add(mergePath$1(lines, { + style: lineStyleModel.getLineStyle(), + silent: true, + z: angleAxisModel.get('z') + })); + }, + splitArea: function (group, angleAxisModel, polar, ticksAngles, minorTickAngles, radiusExtent) { + if (!ticksAngles.length) { + return; + } + + var splitAreaModel = angleAxisModel.getModel('splitArea'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var areaColors = areaStyleModel.get('color'); + var lineCount = 0; + areaColors = areaColors instanceof Array ? areaColors : [areaColors]; + var splitAreas = []; + var RADIAN = Math.PI / 180; + var prevAngle = -ticksAngles[0].coord * RADIAN; + var r0 = Math.min(radiusExtent[0], radiusExtent[1]); + var r1 = Math.max(radiusExtent[0], radiusExtent[1]); + var clockwise = angleAxisModel.get('clockwise'); + + for (var i = 1, len = ticksAngles.length; i <= len; i++) { + var coord = i === len ? ticksAngles[0].coord : ticksAngles[i].coord; + var colorIndex = lineCount++ % areaColors.length; + splitAreas[colorIndex] = splitAreas[colorIndex] || []; + splitAreas[colorIndex].push(new Sector({ + shape: { + cx: polar.cx, + cy: polar.cy, + r0: r0, + r: r1, + startAngle: prevAngle, + endAngle: -coord * RADIAN, + clockwise: clockwise + }, + silent: true + })); + prevAngle = -coord * RADIAN; + } + + for (var i = 0; i < splitAreas.length; i++) { + group.add(mergePath$1(splitAreas[i], { + style: defaults({ + fill: areaColors[i % areaColors.length] + }, areaStyleModel.getAreaStyle()), + silent: true + })); + } + } + }; + + var axisBuilderAttrs$2 = ['axisLine', 'axisTickLabel', 'axisName']; + var selfBuilderAttrs$1 = ['splitLine', 'splitArea', 'minorSplitLine']; + + var RadiusAxisView = function (_super) { + __extends(RadiusAxisView, _super); + + function RadiusAxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = RadiusAxisView.type; + _this.axisPointerClass = 'PolarAxisPointer'; + return _this; + } + + RadiusAxisView.prototype.render = function (radiusAxisModel, ecModel) { + this.group.removeAll(); + + if (!radiusAxisModel.get('show')) { + return; + } + + var oldAxisGroup = this._axisGroup; + var newAxisGroup = this._axisGroup = new Group(); + this.group.add(newAxisGroup); + var radiusAxis = radiusAxisModel.axis; + var polar = radiusAxis.polar; + var angleAxis = polar.getAngleAxis(); + var ticksCoords = radiusAxis.getTicksCoords(); + var minorTicksCoords = radiusAxis.getMinorTicksCoords(); + var axisAngle = angleAxis.getExtent()[0]; + var radiusExtent = radiusAxis.getExtent(); + var layout = layoutAxis(polar, radiusAxisModel, axisAngle); + var axisBuilder = new AxisBuilder(radiusAxisModel, layout); + each(axisBuilderAttrs$2, axisBuilder.add, axisBuilder); + newAxisGroup.add(axisBuilder.getGroup()); + groupTransition(oldAxisGroup, newAxisGroup, radiusAxisModel); + each(selfBuilderAttrs$1, function (name) { + if (radiusAxisModel.get([name, 'show']) && !radiusAxis.scale.isBlank()) { + axisElementBuilders$1[name](this.group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords, minorTicksCoords); + } + }, this); + }; + + RadiusAxisView.type = 'radiusAxis'; + return RadiusAxisView; + }(AxisView); + + var axisElementBuilders$1 = { + splitLine: function (group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) { + var splitLineModel = radiusAxisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + var lineCount = 0; + lineColors = lineColors instanceof Array ? lineColors : [lineColors]; + var splitLines = []; + + for (var i = 0; i < ticksCoords.length; i++) { + var colorIndex = lineCount++ % lineColors.length; + splitLines[colorIndex] = splitLines[colorIndex] || []; + splitLines[colorIndex].push(new Circle({ + shape: { + cx: polar.cx, + cy: polar.cy, + r: ticksCoords[i].coord + } + })); + } + + for (var i = 0; i < splitLines.length; i++) { + group.add(mergePath$1(splitLines[i], { + style: defaults({ + stroke: lineColors[i % lineColors.length], + fill: null + }, lineStyleModel.getLineStyle()), + silent: true + })); + } + }, + minorSplitLine: function (group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords, minorTicksCoords) { + if (!minorTicksCoords.length) { + return; + } + + var minorSplitLineModel = radiusAxisModel.getModel('minorSplitLine'); + var lineStyleModel = minorSplitLineModel.getModel('lineStyle'); + var lines = []; + + for (var i = 0; i < minorTicksCoords.length; i++) { + for (var k = 0; k < minorTicksCoords[i].length; k++) { + lines.push(new Circle({ + shape: { + cx: polar.cx, + cy: polar.cy, + r: minorTicksCoords[i][k].coord + } + })); + } + } + + group.add(mergePath$1(lines, { + style: defaults({ + fill: null + }, lineStyleModel.getLineStyle()), + silent: true + })); + }, + splitArea: function (group, radiusAxisModel, polar, axisAngle, radiusExtent, ticksCoords) { + if (!ticksCoords.length) { + return; + } + + var splitAreaModel = radiusAxisModel.getModel('splitArea'); + var areaStyleModel = splitAreaModel.getModel('areaStyle'); + var areaColors = areaStyleModel.get('color'); + var lineCount = 0; + areaColors = areaColors instanceof Array ? areaColors : [areaColors]; + var splitAreas = []; + var prevRadius = ticksCoords[0].coord; + + for (var i = 1; i < ticksCoords.length; i++) { + var colorIndex = lineCount++ % areaColors.length; + splitAreas[colorIndex] = splitAreas[colorIndex] || []; + splitAreas[colorIndex].push(new Sector({ + shape: { + cx: polar.cx, + cy: polar.cy, + r0: prevRadius, + r: ticksCoords[i].coord, + startAngle: 0, + endAngle: Math.PI * 2 + }, + silent: true + })); + prevRadius = ticksCoords[i].coord; + } + + for (var i = 0; i < splitAreas.length; i++) { + group.add(mergePath$1(splitAreas[i], { + style: defaults({ + fill: areaColors[i % areaColors.length] + }, areaStyleModel.getAreaStyle()), + silent: true + })); + } + } + }; + + function layoutAxis(polar, radiusAxisModel, axisAngle) { + return { + position: [polar.cx, polar.cy], + rotation: axisAngle / 180 * Math.PI, + labelDirection: -1, + tickDirection: -1, + nameDirection: 1, + labelRotate: radiusAxisModel.getModel('axisLabel').get('rotate'), + z2: 1 + }; + } + + function getSeriesStackId$1(seriesModel) { + return seriesModel.get('stack') || '__ec_stack_' + seriesModel.seriesIndex; + } + + function getAxisKey$1(polar, axis) { + return axis.dim + polar.model.componentIndex; + } + + function barLayoutPolar(seriesType, ecModel, api) { + var lastStackCoords = {}; + var barWidthAndOffset = calRadialBar(filter(ecModel.getSeriesByType(seriesType), function (seriesModel) { + return !ecModel.isSeriesFiltered(seriesModel) && seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'polar'; + })); + ecModel.eachSeriesByType(seriesType, function (seriesModel) { + if (seriesModel.coordinateSystem.type !== 'polar') { + return; + } + + var data = seriesModel.getData(); + var polar = seriesModel.coordinateSystem; + var baseAxis = polar.getBaseAxis(); + var axisKey = getAxisKey$1(polar, baseAxis); + var stackId = getSeriesStackId$1(seriesModel); + var columnLayoutInfo = barWidthAndOffset[axisKey][stackId]; + var columnOffset = columnLayoutInfo.offset; + var columnWidth = columnLayoutInfo.width; + var valueAxis = polar.getOtherAxis(baseAxis); + var cx = seriesModel.coordinateSystem.cx; + var cy = seriesModel.coordinateSystem.cy; + var barMinHeight = seriesModel.get('barMinHeight') || 0; + var barMinAngle = seriesModel.get('barMinAngle') || 0; + lastStackCoords[stackId] = lastStackCoords[stackId] || []; + var valueDim = data.mapDimension(valueAxis.dim); + var baseDim = data.mapDimension(baseAxis.dim); + var stacked = isDimensionStacked(data, valueDim); + var clampLayout = baseAxis.dim !== 'radius' || !seriesModel.get('roundCap', true); + var valueAxisStart = valueAxis.dataToCoord(0); + + for (var idx = 0, len = data.count(); idx < len; idx++) { + var value = data.get(valueDim, idx); + var baseValue = data.get(baseDim, idx); + var sign = value >= 0 ? 'p' : 'n'; + var baseCoord = valueAxisStart; + + if (stacked) { + if (!lastStackCoords[stackId][baseValue]) { + lastStackCoords[stackId][baseValue] = { + p: valueAxisStart, + n: valueAxisStart + }; + } + + baseCoord = lastStackCoords[stackId][baseValue][sign]; + } + + var r0 = void 0; + var r = void 0; + var startAngle = void 0; + var endAngle = void 0; + + if (valueAxis.dim === 'radius') { + var radiusSpan = valueAxis.dataToCoord(value) - valueAxisStart; + var angle = baseAxis.dataToCoord(baseValue); + + if (Math.abs(radiusSpan) < barMinHeight) { + radiusSpan = (radiusSpan < 0 ? -1 : 1) * barMinHeight; + } + + r0 = baseCoord; + r = baseCoord + radiusSpan; + startAngle = angle - columnOffset; + endAngle = startAngle - columnWidth; + stacked && (lastStackCoords[stackId][baseValue][sign] = r); + } else { + var angleSpan = valueAxis.dataToCoord(value, clampLayout) - valueAxisStart; + var radius = baseAxis.dataToCoord(baseValue); + + if (Math.abs(angleSpan) < barMinAngle) { + angleSpan = (angleSpan < 0 ? -1 : 1) * barMinAngle; + } + + r0 = radius + columnOffset; + r = r0 + columnWidth; + startAngle = baseCoord; + endAngle = baseCoord + angleSpan; + stacked && (lastStackCoords[stackId][baseValue][sign] = endAngle); + } + + data.setItemLayout(idx, { + cx: cx, + cy: cy, + r0: r0, + r: r, + startAngle: -startAngle * Math.PI / 180, + endAngle: -endAngle * Math.PI / 180 + }); + } + }); + } + + function calRadialBar(barSeries) { + var columnsMap = {}; + each(barSeries, function (seriesModel, idx) { + var data = seriesModel.getData(); + var polar = seriesModel.coordinateSystem; + var baseAxis = polar.getBaseAxis(); + var axisKey = getAxisKey$1(polar, baseAxis); + var axisExtent = baseAxis.getExtent(); + var bandWidth = baseAxis.type === 'category' ? baseAxis.getBandWidth() : Math.abs(axisExtent[1] - axisExtent[0]) / data.count(); + var columnsOnAxis = columnsMap[axisKey] || { + bandWidth: bandWidth, + remainedWidth: bandWidth, + autoWidthCount: 0, + categoryGap: '20%', + gap: '30%', + stacks: {} + }; + var stacks = columnsOnAxis.stacks; + columnsMap[axisKey] = columnsOnAxis; + var stackId = getSeriesStackId$1(seriesModel); + + if (!stacks[stackId]) { + columnsOnAxis.autoWidthCount++; + } + + stacks[stackId] = stacks[stackId] || { + width: 0, + maxWidth: 0 + }; + var barWidth = parsePercent$1(seriesModel.get('barWidth'), bandWidth); + var barMaxWidth = parsePercent$1(seriesModel.get('barMaxWidth'), bandWidth); + var barGap = seriesModel.get('barGap'); + var barCategoryGap = seriesModel.get('barCategoryGap'); + + if (barWidth && !stacks[stackId].width) { + barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth); + stacks[stackId].width = barWidth; + columnsOnAxis.remainedWidth -= barWidth; + } + + barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth); + barGap != null && (columnsOnAxis.gap = barGap); + barCategoryGap != null && (columnsOnAxis.categoryGap = barCategoryGap); + }); + var result = {}; + each(columnsMap, function (columnsOnAxis, coordSysName) { + result[coordSysName] = {}; + var stacks = columnsOnAxis.stacks; + var bandWidth = columnsOnAxis.bandWidth; + var categoryGap = parsePercent$1(columnsOnAxis.categoryGap, bandWidth); + var barGapPercent = parsePercent$1(columnsOnAxis.gap, 1); + var remainedWidth = columnsOnAxis.remainedWidth; + var autoWidthCount = columnsOnAxis.autoWidthCount; + var autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); + each(stacks, function (column, stack) { + var maxWidth = column.maxWidth; + + if (maxWidth && maxWidth < autoWidth) { + maxWidth = Math.min(maxWidth, remainedWidth); + + if (column.width) { + maxWidth = Math.min(maxWidth, column.width); + } + + remainedWidth -= maxWidth; + column.width = maxWidth; + autoWidthCount--; + } + }); + autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); + autoWidth = Math.max(autoWidth, 0); + var widthSum = 0; + var lastColumn; + each(stacks, function (column, idx) { + if (!column.width) { + column.width = autoWidth; + } + + lastColumn = column; + widthSum += column.width * (1 + barGapPercent); + }); + + if (lastColumn) { + widthSum -= lastColumn.width * barGapPercent; + } + + var offset = -widthSum / 2; + each(stacks, function (column, stackId) { + result[coordSysName][stackId] = result[coordSysName][stackId] || { + offset: offset, + width: column.width + }; + offset += column.width * (1 + barGapPercent); + }); + }); + return result; + } + + var angleAxisExtraOption = { + startAngle: 90, + clockwise: true, + splitNumber: 12, + axisLabel: { + rotate: 0 + } + }; + var radiusAxisExtraOption = { + splitNumber: 5 + }; + + var PolarView = function (_super) { + __extends(PolarView, _super); + + function PolarView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = PolarView.type; + return _this; + } + + PolarView.type = 'polar'; + return PolarView; + }(ComponentView); + + function install$t(registers) { + use(install$r); + AxisView.registerAxisPointerClass('PolarAxisPointer', PolarAxisPointer); + registers.registerCoordinateSystem('polar', polarCreator); + registers.registerComponentModel(PolarModel); + registers.registerComponentView(PolarView); + axisModelCreator(registers, 'angle', AngleAxisModel, angleAxisExtraOption); + axisModelCreator(registers, 'radius', RadiusAxisModel, radiusAxisExtraOption); + registers.registerComponentView(AngleAxisView); + registers.registerComponentView(RadiusAxisView); + registers.registerLayout(curry(barLayoutPolar, 'bar')); + } + + var Geo = function (_super) { + __extends(Geo, _super); + + function Geo(name, map, nameMap, invertLongitute) { + var _this = _super.call(this, name) || this; + + _this.dimensions = ['lng', 'lat']; + _this.type = 'geo'; + _this.map = map; + var source = geoSourceManager.load(map, nameMap); + _this._nameCoordMap = source.nameCoordMap; + _this._regionsMap = source.regionsMap; + _this._invertLongitute = invertLongitute == null ? true : invertLongitute; + _this.regions = source.regions; + _this._rect = source.boundingRect; + return _this; + } + + Geo.prototype.containCoord = function (coord) { + var regions = this.regions; + + for (var i = 0; i < regions.length; i++) { + if (regions[i].contain(coord)) { + return true; + } + } + + return false; + }; + + Geo.prototype.transformTo = function (x, y, width, height) { + var rect = this.getBoundingRect(); + var invertLongitute = this._invertLongitute; + rect = rect.clone(); + + if (invertLongitute) { + rect.y = -rect.y - rect.height; + } + + var rawTransformable = this._rawTransformable; + rawTransformable.transform = rect.calculateTransform(new BoundingRect(x, y, width, height)); + rawTransformable.decomposeTransform(); + + if (invertLongitute) { + rawTransformable.scaleY = -rawTransformable.scaleY; + } + + rawTransformable.updateTransform(); + + this._updateTransform(); + }; + + Geo.prototype.getRegion = function (name) { + return this._regionsMap.get(name); + }; + + Geo.prototype.getRegionByCoord = function (coord) { + var regions = this.regions; + + for (var i = 0; i < regions.length; i++) { + if (regions[i].contain(coord)) { + return regions[i]; + } + } + }; + + Geo.prototype.addGeoCoord = function (name, geoCoord) { + this._nameCoordMap.set(name, geoCoord); + }; + + Geo.prototype.getGeoCoord = function (name) { + return this._nameCoordMap.get(name); + }; + + Geo.prototype.getBoundingRect = function () { + return this._rect; + }; + + Geo.prototype.dataToPoint = function (data, noRoam, out) { + if (typeof data === 'string') { + data = this.getGeoCoord(data); + } + + if (data) { + return View.prototype.dataToPoint.call(this, data, noRoam, out); + } + }; + + Geo.prototype.convertToPixel = function (ecModel, finder, value) { + var coordSys = getCoordSys$2(finder); + return coordSys === this ? coordSys.dataToPoint(value) : null; + }; + + Geo.prototype.convertFromPixel = function (ecModel, finder, pixel) { + var coordSys = getCoordSys$2(finder); + return coordSys === this ? coordSys.pointToData(pixel) : null; + }; + + return Geo; + }(View); + mixin(Geo, View); + + function getCoordSys$2(finder) { + var geoModel = finder.geoModel; + var seriesModel = finder.seriesModel; + return geoModel ? geoModel.coordinateSystem : seriesModel ? seriesModel.coordinateSystem || (seriesModel.getReferringComponents('geo', SINGLE_REFERRING).models[0] || {}).coordinateSystem : null; + } + + function resizeGeo(geoModel, api) { + var boundingCoords = geoModel.get('boundingCoords'); + + if (boundingCoords != null) { + var leftTop = boundingCoords[0]; + var rightBottom = boundingCoords[1]; + + if (isNaN(leftTop[0]) || isNaN(leftTop[1]) || isNaN(rightBottom[0]) || isNaN(rightBottom[1])) { + if ("development" !== 'production') { + console.error('Invalid boundingCoords'); + } + } else { + this.setBoundingRect(leftTop[0], leftTop[1], rightBottom[0] - leftTop[0], rightBottom[1] - leftTop[1]); + } + } + + var rect = this.getBoundingRect(); + var centerOption = geoModel.get('layoutCenter'); + var sizeOption = geoModel.get('layoutSize'); + var viewWidth = api.getWidth(); + var viewHeight = api.getHeight(); + var aspect = rect.width / rect.height * this.aspectScale; + var useCenterAndSize = false; + var center; + var size; + + if (centerOption && sizeOption) { + center = [parsePercent$1(centerOption[0], viewWidth), parsePercent$1(centerOption[1], viewHeight)]; + size = parsePercent$1(sizeOption, Math.min(viewWidth, viewHeight)); + + if (!isNaN(center[0]) && !isNaN(center[1]) && !isNaN(size)) { + useCenterAndSize = true; + } else { + if ("development" !== 'production') { + console.warn('Given layoutCenter or layoutSize data are invalid. Use left/top/width/height instead.'); + } + } + } + + var viewRect; + + if (useCenterAndSize) { + viewRect = {}; + + if (aspect > 1) { + viewRect.width = size; + viewRect.height = size / aspect; + } else { + viewRect.height = size; + viewRect.width = size * aspect; + } + + viewRect.y = center[1] - viewRect.height / 2; + viewRect.x = center[0] - viewRect.width / 2; + } else { + var boxLayoutOption = geoModel.getBoxLayoutParams(); + boxLayoutOption.aspect = aspect; + viewRect = getLayoutRect(boxLayoutOption, { + width: viewWidth, + height: viewHeight + }); + } + + this.setViewRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height); + this.setCenter(geoModel.get('center')); + this.setZoom(geoModel.get('zoom')); + } + + function setGeoCoords(geo, model) { + each(model.get('geoCoord'), function (geoCoord, name) { + geo.addGeoCoord(name, geoCoord); + }); + } + + var GeoCreator = function () { + function GeoCreator() { + this.dimensions = Geo.prototype.dimensions; + } + + GeoCreator.prototype.create = function (ecModel, api) { + var geoList = []; + ecModel.eachComponent('geo', function (geoModel, idx) { + var name = geoModel.get('map'); + var aspectScale = geoModel.get('aspectScale'); + var invertLongitute = true; + var mapRecords = mapDataStorage.retrieveMap(name); + + if (mapRecords && mapRecords[0] && mapRecords[0].type === 'svg') { + aspectScale == null && (aspectScale = 1); + invertLongitute = false; + } else { + aspectScale == null && (aspectScale = 0.75); + } + + var geo = new Geo(name + idx, name, geoModel.get('nameMap'), invertLongitute); + geo.aspectScale = aspectScale; + geo.zoomLimit = geoModel.get('scaleLimit'); + geoList.push(geo); + geoModel.coordinateSystem = geo; + geo.model = geoModel; + geo.resize = resizeGeo; + geo.resize(geoModel, api); + }); + ecModel.eachSeries(function (seriesModel) { + var coordSys = seriesModel.get('coordinateSystem'); + + if (coordSys === 'geo') { + var geoIndex = seriesModel.get('geoIndex') || 0; + seriesModel.coordinateSystem = geoList[geoIndex]; + } + }); + var mapModelGroupBySeries = {}; + ecModel.eachSeriesByType('map', function (seriesModel) { + if (!seriesModel.getHostGeoModel()) { + var mapType = seriesModel.getMapType(); + mapModelGroupBySeries[mapType] = mapModelGroupBySeries[mapType] || []; + mapModelGroupBySeries[mapType].push(seriesModel); + } + }); + each(mapModelGroupBySeries, function (mapSeries, mapType) { + var nameMapList = map(mapSeries, function (singleMapSeries) { + return singleMapSeries.get('nameMap'); + }); + var geo = new Geo(mapType, mapType, mergeAll(nameMapList)); + geo.zoomLimit = retrieve.apply(null, map(mapSeries, function (singleMapSeries) { + return singleMapSeries.get('scaleLimit'); + })); + geoList.push(geo); + geo.resize = resizeGeo; + geo.aspectScale = mapSeries[0].get('aspectScale'); + geo.resize(mapSeries[0], api); + each(mapSeries, function (singleMapSeries) { + singleMapSeries.coordinateSystem = geo; + setGeoCoords(geo, singleMapSeries); + }); + }); + return geoList; + }; + + GeoCreator.prototype.getFilledRegions = function (originRegionArr, mapName, nameMap) { + var regionsArr = (originRegionArr || []).slice(); + var dataNameMap = createHashMap(); + + for (var i = 0; i < regionsArr.length; i++) { + dataNameMap.set(regionsArr[i].name, regionsArr[i]); + } + + var source = geoSourceManager.load(mapName, nameMap); + each(source.regions, function (region) { + var name = region.name; + !dataNameMap.get(name) && regionsArr.push({ + name: name + }); + }); + return regionsArr; + }; + + return GeoCreator; + }(); + + var geoCreator = new GeoCreator(); + + var GeoModel = function (_super) { + __extends(GeoModel, _super); + + function GeoModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GeoModel.type; + return _this; + } + + GeoModel.prototype.init = function (option, parentModel, ecModel) { + _super.prototype.init.call(this, option, parentModel, ecModel); + + defaultEmphasis(option, 'label', ['show']); + }; + + GeoModel.prototype.optionUpdated = function () { + var option = this.option; + var self = this; + option.regions = geoCreator.getFilledRegions(option.regions, option.map, option.nameMap); + var selectedMap = {}; + this._optionModelMap = reduce(option.regions || [], function (optionModelMap, regionOpt) { + var regionName = regionOpt.name; + + if (regionName) { + optionModelMap.set(regionName, new Model(regionOpt, self)); + + if (regionOpt.selected) { + selectedMap[regionName] = true; + } + } + + return optionModelMap; + }, createHashMap()); + + if (!option.selectedMap) { + option.selectedMap = selectedMap; + } + }; + + GeoModel.prototype.getRegionModel = function (name) { + return this._optionModelMap.get(name) || new Model(null, this, this.ecModel); + }; + + GeoModel.prototype.getFormattedLabel = function (name, status) { + var regionModel = this.getRegionModel(name); + var formatter = status === 'normal' ? regionModel.get(['label', 'formatter']) : regionModel.get(['emphasis', 'label', 'formatter']); + var params = { + name: name + }; + + if (typeof formatter === 'function') { + params.status = status; + return formatter(params); + } else if (typeof formatter === 'string') { + return formatter.replace('{a}', name != null ? name : ''); + } + }; + + GeoModel.prototype.setZoom = function (zoom) { + this.option.zoom = zoom; + }; + + GeoModel.prototype.setCenter = function (center) { + this.option.center = center; + }; + + GeoModel.prototype.select = function (name) { + var option = this.option; + var selectedMode = option.selectedMode; + + if (!selectedMode) { + return; + } + + if (selectedMode !== 'multiple') { + option.selectedMap = null; + } + + var selectedMap = option.selectedMap || (option.selectedMap = {}); + selectedMap[name] = true; + }; + + GeoModel.prototype.unSelect = function (name) { + var selectedMap = this.option.selectedMap; + + if (selectedMap) { + selectedMap[name] = false; + } + }; + + GeoModel.prototype.toggleSelected = function (name) { + this[this.isSelected(name) ? 'unSelect' : 'select'](name); + }; + + GeoModel.prototype.isSelected = function (name) { + var selectedMap = this.option.selectedMap; + return !!(selectedMap && selectedMap[name]); + }; + + GeoModel.prototype._initSelectedMapFromData = function () {}; + + GeoModel.type = 'geo'; + GeoModel.layoutMode = 'box'; + GeoModel.defaultOption = { + zlevel: 0, + z: 0, + show: true, + left: 'center', + top: 'center', + aspectScale: null, + silent: false, + map: '', + boundingCoords: null, + center: null, + zoom: 1, + scaleLimit: null, + label: { + show: false, + color: '#000' + }, + itemStyle: { + borderWidth: 0.5, + borderColor: '#444', + color: '#eee' + }, + emphasis: { + label: { + show: true, + color: 'rgb(100,0,0)' + }, + itemStyle: { + color: 'rgba(255,215,0,0.8)' + } + }, + select: { + label: { + show: true, + color: 'rgb(100,0,0)' + }, + itemStyle: { + color: 'rgba(255,215,0,0.8)' + } + }, + regions: [] + }; + return GeoModel; + }(ComponentModel); + + var GeoView = function (_super) { + __extends(GeoView, _super); + + function GeoView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GeoView.type; + return _this; + } + + GeoView.prototype.init = function (ecModel, api) { + var mapDraw = new MapDraw(api); + this._mapDraw = mapDraw; + this.group.add(mapDraw.group); + this._api = api; + }; + + GeoView.prototype.render = function (geoModel, ecModel, api, payload) { + var mapDraw = this._mapDraw; + + if (geoModel.get('show')) { + mapDraw.draw(geoModel, ecModel, api, this, payload); + } else { + this._mapDraw.group.removeAll(); + } + + mapDraw.group.on('click', this._handleRegionClick, this); + mapDraw.group.silent = geoModel.get('silent'); + this._model = geoModel; + this.updateSelectStatus(geoModel, ecModel, api); + }; + + GeoView.prototype._handleRegionClick = function (e) { + var current = e.target; + var eventData; + + while (current && (eventData = getECData(current).eventData) == null) { + current = current.__hostTarget || current.parent; + } + + if (eventData) { + this._api.dispatchAction({ + type: 'geoToggleSelect', + geoId: this._model.id, + name: eventData.name + }); + } + }; + + GeoView.prototype.updateSelectStatus = function (model, ecModel, api) { + var _this = this; + + this._mapDraw.group.traverse(function (node) { + var eventData = getECData(node).eventData; + + if (eventData) { + _this._model.isSelected(eventData.name) ? api.enterSelect(node) : api.leaveSelect(node); + return true; + } + }); + }; + + GeoView.prototype.dispose = function () { + this._mapDraw && this._mapDraw.remove(); + }; + + GeoView.type = 'geo'; + return GeoView; + }(ComponentView); + + function install$u(registers) { + registers.registerCoordinateSystem('geo', geoCreator); + registers.registerComponentModel(GeoModel); + registers.registerComponentView(GeoView); + + function makeAction(method, actionInfo) { + actionInfo.update = 'geo:updateSelectStatus'; + registers.registerAction(actionInfo, function (payload, ecModel) { + var selected = {}; + ecModel.eachComponent({ + mainType: 'geo', + query: payload + }, function (geoModel) { + geoModel[method](payload.name); + var geo = geoModel.coordinateSystem; + each(geo.regions, function (region) { + selected[region.name] = geoModel.isSelected(region.name) || false; + }); + }); + return { + selected: selected, + name: payload.name + }; + }); + } + + makeAction('toggleSelected', { + type: 'geoToggleSelect', + event: 'geoselectchanged' + }); + makeAction('select', { + type: 'geoSelect', + event: 'geoselected' + }); + makeAction('unSelect', { + type: 'geoUnSelect', + event: 'geounselected' + }); + registers.registerAction({ + type: 'geoRoam', + event: 'geoRoam', + update: 'updateTransform' + }, function (payload, ecModel) { + var componentType = payload.componentType || 'series'; + ecModel.eachComponent({ + mainType: componentType, + query: payload + }, function (componentModel) { + var geo = componentModel.coordinateSystem; + + if (geo.type !== 'geo') { + return; + } + + var res = updateCenterAndZoom(geo, payload, componentModel.get('scaleLimit')); + componentModel.setCenter && componentModel.setCenter(res.center); + componentModel.setZoom && componentModel.setZoom(res.zoom); + + if (componentType === 'series') { + each(componentModel.seriesGroup, function (seriesModel) { + seriesModel.setCenter(res.center); + seriesModel.setZoom(res.zoom); + }); + } + }); + }); + } + + function layout$2(axisModel, opt) { + opt = opt || {}; + var single = axisModel.coordinateSystem; + var axis = axisModel.axis; + var layout = {}; + var axisPosition = axis.position; + var orient = axis.orient; + var rect = single.getRect(); + var rectBound = [rect.x, rect.x + rect.width, rect.y, rect.y + rect.height]; + var positionMap = { + horizontal: { + top: rectBound[2], + bottom: rectBound[3] + }, + vertical: { + left: rectBound[0], + right: rectBound[1] + } + }; + layout.position = [orient === 'vertical' ? positionMap.vertical[axisPosition] : rectBound[0], orient === 'horizontal' ? positionMap.horizontal[axisPosition] : rectBound[3]]; + var r = { + horizontal: 0, + vertical: 1 + }; + layout.rotation = Math.PI / 2 * r[orient]; + var directionMap = { + top: -1, + bottom: 1, + right: 1, + left: -1 + }; + layout.labelDirection = layout.tickDirection = layout.nameDirection = directionMap[axisPosition]; + + if (axisModel.get(['axisTick', 'inside'])) { + layout.tickDirection = -layout.tickDirection; + } + + if (retrieve(opt.labelInside, axisModel.get(['axisLabel', 'inside']))) { + layout.labelDirection = -layout.labelDirection; + } + + var labelRotation = opt.rotate; + labelRotation == null && (labelRotation = axisModel.get(['axisLabel', 'rotate'])); + layout.labelRotation = axisPosition === 'top' ? -labelRotation : labelRotation; + layout.z2 = 1; + return layout; + } + + var axisBuilderAttrs$3 = ['axisLine', 'axisTickLabel', 'axisName']; + var selfBuilderAttrs$2 = ['splitArea', 'splitLine']; + + var SingleAxisView = function (_super) { + __extends(SingleAxisView, _super); + + function SingleAxisView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SingleAxisView.type; + _this.axisPointerClass = 'SingleAxisPointer'; + return _this; + } + + SingleAxisView.prototype.render = function (axisModel, ecModel, api, payload) { + var group = this.group; + group.removeAll(); + var oldAxisGroup = this._axisGroup; + this._axisGroup = new Group(); + var layout = layout$2(axisModel); + var axisBuilder = new AxisBuilder(axisModel, layout); + each(axisBuilderAttrs$3, axisBuilder.add, axisBuilder); + group.add(this._axisGroup); + group.add(axisBuilder.getGroup()); + each(selfBuilderAttrs$2, function (name) { + if (axisModel.get([name, 'show'])) { + axisElementBuilders$2[name](this, this.group, this._axisGroup, axisModel); + } + }, this); + groupTransition(oldAxisGroup, this._axisGroup, axisModel); + + _super.prototype.render.call(this, axisModel, ecModel, api, payload); + }; + + SingleAxisView.prototype.remove = function () { + rectCoordAxisHandleRemove(this); + }; + + SingleAxisView.type = 'singleAxis'; + return SingleAxisView; + }(AxisView); + + var axisElementBuilders$2 = { + splitLine: function (axisView, group, axisGroup, axisModel) { + var axis = axisModel.axis; + + if (axis.scale.isBlank()) { + return; + } + + var splitLineModel = axisModel.getModel('splitLine'); + var lineStyleModel = splitLineModel.getModel('lineStyle'); + var lineColors = lineStyleModel.get('color'); + lineColors = lineColors instanceof Array ? lineColors : [lineColors]; + var gridRect = axisModel.coordinateSystem.getRect(); + var isHorizontal = axis.isHorizontal(); + var splitLines = []; + var lineCount = 0; + var ticksCoords = axis.getTicksCoords({ + tickModel: splitLineModel + }); + var p1 = []; + var p2 = []; + + for (var i = 0; i < ticksCoords.length; ++i) { + var tickCoord = axis.toGlobalCoord(ticksCoords[i].coord); + + if (isHorizontal) { + p1[0] = tickCoord; + p1[1] = gridRect.y; + p2[0] = tickCoord; + p2[1] = gridRect.y + gridRect.height; + } else { + p1[0] = gridRect.x; + p1[1] = tickCoord; + p2[0] = gridRect.x + gridRect.width; + p2[1] = tickCoord; + } + + var colorIndex = lineCount++ % lineColors.length; + splitLines[colorIndex] = splitLines[colorIndex] || []; + splitLines[colorIndex].push(new Line({ + subPixelOptimize: true, + shape: { + x1: p1[0], + y1: p1[1], + x2: p2[0], + y2: p2[1] + }, + silent: true + })); + } + + var lineStyle = lineStyleModel.getLineStyle(['color']); + + for (var i = 0; i < splitLines.length; ++i) { + group.add(mergePath$1(splitLines[i], { + style: defaults({ + stroke: lineColors[i % lineColors.length] + }, lineStyle), + silent: true + })); + } + }, + splitArea: function (axisView, group, axisGroup, axisModel) { + rectCoordAxisBuildSplitArea(axisView, axisGroup, axisModel, axisModel); + } + }; + + var SingleAxisModel = function (_super) { + __extends(SingleAxisModel, _super); + + function SingleAxisModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SingleAxisModel.type; + return _this; + } + + SingleAxisModel.prototype.getCoordSysModel = function () { + return this; + }; + + SingleAxisModel.type = 'singleAxis'; + SingleAxisModel.layoutMode = 'box'; + SingleAxisModel.defaultOption = { + left: '5%', + top: '5%', + right: '5%', + bottom: '5%', + type: 'value', + position: 'bottom', + orient: 'horizontal', + axisLine: { + show: true, + lineStyle: { + width: 1, + type: 'solid' + } + }, + tooltip: { + show: true + }, + axisTick: { + show: true, + length: 6, + lineStyle: { + width: 1 + } + }, + axisLabel: { + show: true, + interval: 'auto' + }, + splitLine: { + show: true, + lineStyle: { + type: 'dashed', + opacity: 0.2 + } + } + }; + return SingleAxisModel; + }(ComponentModel); + + mixin(SingleAxisModel, AxisModelCommonMixin.prototype); + + var SingleAxis = function (_super) { + __extends(SingleAxis, _super); + + function SingleAxis(dim, scale, coordExtent, axisType, position) { + var _this = _super.call(this, dim, scale, coordExtent) || this; + + _this.type = axisType || 'value'; + _this.position = position || 'bottom'; + return _this; + } + + SingleAxis.prototype.isHorizontal = function () { + var position = this.position; + return position === 'top' || position === 'bottom'; + }; + + SingleAxis.prototype.pointToData = function (point, clamp) { + return this.coordinateSystem.pointToData(point)[0]; + }; + + return SingleAxis; + }(Axis); + + var Single = function () { + function Single(axisModel, ecModel, api) { + this.type = 'single'; + this.dimension = 'single'; + this.dimensions = ['single']; + this.axisPointerEnabled = true; + this.model = axisModel; + + this._init(axisModel, ecModel, api); + } + + Single.prototype._init = function (axisModel, ecModel, api) { + var dim = this.dimension; + var axis = new SingleAxis(dim, createScaleByModel(axisModel), [0, 0], axisModel.get('type'), axisModel.get('position')); + var isCategory = axis.type === 'category'; + axis.onBand = isCategory && axisModel.get('boundaryGap'); + axis.inverse = axisModel.get('inverse'); + axis.orient = axisModel.get('orient'); + axisModel.axis = axis; + axis.model = axisModel; + axis.coordinateSystem = this; + this._axis = axis; + }; + + Single.prototype.update = function (ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.coordinateSystem === this) { + var data_1 = seriesModel.getData(); + each(data_1.mapDimensionsAll(this.dimension), function (dim) { + this._axis.scale.unionExtentFromData(data_1, dim); + }, this); + niceScaleExtent(this._axis.scale, this._axis.model); + } + }, this); + }; + + Single.prototype.resize = function (axisModel, api) { + this._rect = getLayoutRect({ + left: axisModel.get('left'), + top: axisModel.get('top'), + right: axisModel.get('right'), + bottom: axisModel.get('bottom'), + width: axisModel.get('width'), + height: axisModel.get('height') + }, { + width: api.getWidth(), + height: api.getHeight() + }); + + this._adjustAxis(); + }; + + Single.prototype.getRect = function () { + return this._rect; + }; + + Single.prototype._adjustAxis = function () { + var rect = this._rect; + var axis = this._axis; + var isHorizontal = axis.isHorizontal(); + var extent = isHorizontal ? [0, rect.width] : [0, rect.height]; + var idx = axis.reverse ? 1 : 0; + axis.setExtent(extent[idx], extent[1 - idx]); + + this._updateAxisTransform(axis, isHorizontal ? rect.x : rect.y); + }; + + Single.prototype._updateAxisTransform = function (axis, coordBase) { + var axisExtent = axis.getExtent(); + var extentSum = axisExtent[0] + axisExtent[1]; + var isHorizontal = axis.isHorizontal(); + axis.toGlobalCoord = isHorizontal ? function (coord) { + return coord + coordBase; + } : function (coord) { + return extentSum - coord + coordBase; + }; + axis.toLocalCoord = isHorizontal ? function (coord) { + return coord - coordBase; + } : function (coord) { + return extentSum - coord + coordBase; + }; + }; + + Single.prototype.getAxis = function () { + return this._axis; + }; + + Single.prototype.getBaseAxis = function () { + return this._axis; + }; + + Single.prototype.getAxes = function () { + return [this._axis]; + }; + + Single.prototype.getTooltipAxes = function () { + return { + baseAxes: [this.getAxis()], + otherAxes: [] + }; + }; + + Single.prototype.containPoint = function (point) { + var rect = this.getRect(); + var axis = this.getAxis(); + var orient = axis.orient; + + if (orient === 'horizontal') { + return axis.contain(axis.toLocalCoord(point[0])) && point[1] >= rect.y && point[1] <= rect.y + rect.height; + } else { + return axis.contain(axis.toLocalCoord(point[1])) && point[0] >= rect.y && point[0] <= rect.y + rect.height; + } + }; + + Single.prototype.pointToData = function (point) { + var axis = this.getAxis(); + return [axis.coordToData(axis.toLocalCoord(point[axis.orient === 'horizontal' ? 0 : 1]))]; + }; + + Single.prototype.dataToPoint = function (val) { + var axis = this.getAxis(); + var rect = this.getRect(); + var pt = []; + var idx = axis.orient === 'horizontal' ? 0 : 1; + + if (val instanceof Array) { + val = val[0]; + } + + pt[idx] = axis.toGlobalCoord(axis.dataToCoord(+val)); + pt[1 - idx] = idx === 0 ? rect.y + rect.height / 2 : rect.x + rect.width / 2; + return pt; + }; + + Single.prototype.convertToPixel = function (ecModel, finder, value) { + var coordSys = getCoordSys$3(finder); + return coordSys === this ? this.dataToPoint(value) : null; + }; + + Single.prototype.convertFromPixel = function (ecModel, finder, pixel) { + var coordSys = getCoordSys$3(finder); + return coordSys === this ? this.pointToData(pixel) : null; + }; + + return Single; + }(); + + function getCoordSys$3(finder) { + var seriesModel = finder.seriesModel; + var singleModel = finder.singleAxisModel; + return singleModel && singleModel.coordinateSystem || seriesModel && seriesModel.coordinateSystem; + } + + function create$2(ecModel, api) { + var singles = []; + ecModel.eachComponent('singleAxis', function (axisModel, idx) { + var single = new Single(axisModel, ecModel, api); + single.name = 'single_' + idx; + single.resize(axisModel, api); + axisModel.coordinateSystem = single; + singles.push(single); + }); + ecModel.eachSeries(function (seriesModel) { + if (seriesModel.get('coordinateSystem') === 'singleAxis') { + var singleAxisModel = seriesModel.getReferringComponents('singleAxis', SINGLE_REFERRING).models[0]; + seriesModel.coordinateSystem = singleAxisModel && singleAxisModel.coordinateSystem; + } + }); + return singles; + } + + var singleCreator = { + create: create$2, + dimensions: Single.prototype.dimensions + }; + + var XY = ['x', 'y']; + var WH = ['width', 'height']; + + var SingleAxisPointer = function (_super) { + __extends(SingleAxisPointer, _super); + + function SingleAxisPointer() { + return _super !== null && _super.apply(this, arguments) || this; + } + + SingleAxisPointer.prototype.makeElOption = function (elOption, value, axisModel, axisPointerModel, api) { + var axis = axisModel.axis; + var coordSys = axis.coordinateSystem; + var otherExtent = getGlobalExtent(coordSys, 1 - getPointDimIndex(axis)); + var pixelValue = coordSys.dataToPoint(value)[0]; + var axisPointerType = axisPointerModel.get('type'); + + if (axisPointerType && axisPointerType !== 'none') { + var elStyle = buildElStyle(axisPointerModel); + var pointerOption = pointerShapeBuilder$2[axisPointerType](axis, pixelValue, otherExtent); + pointerOption.style = elStyle; + elOption.graphicKey = pointerOption.type; + elOption.pointer = pointerOption; + } + + var layoutInfo = layout$2(axisModel); + buildCartesianSingleLabelElOption(value, elOption, layoutInfo, axisModel, axisPointerModel, api); + }; + + SingleAxisPointer.prototype.getHandleTransform = function (value, axisModel, axisPointerModel) { + var layoutInfo = layout$2(axisModel, { + labelInside: false + }); + layoutInfo.labelMargin = axisPointerModel.get(['handle', 'margin']); + var position = getTransformedPosition(axisModel.axis, value, layoutInfo); + return { + x: position[0], + y: position[1], + rotation: layoutInfo.rotation + (layoutInfo.labelDirection < 0 ? Math.PI : 0) + }; + }; + + SingleAxisPointer.prototype.updateHandleTransform = function (transform, delta, axisModel, axisPointerModel) { + var axis = axisModel.axis; + var coordSys = axis.coordinateSystem; + var dimIndex = getPointDimIndex(axis); + var axisExtent = getGlobalExtent(coordSys, dimIndex); + var currPosition = [transform.x, transform.y]; + currPosition[dimIndex] += delta[dimIndex]; + currPosition[dimIndex] = Math.min(axisExtent[1], currPosition[dimIndex]); + currPosition[dimIndex] = Math.max(axisExtent[0], currPosition[dimIndex]); + var otherExtent = getGlobalExtent(coordSys, 1 - dimIndex); + var cursorOtherValue = (otherExtent[1] + otherExtent[0]) / 2; + var cursorPoint = [cursorOtherValue, cursorOtherValue]; + cursorPoint[dimIndex] = currPosition[dimIndex]; + return { + x: currPosition[0], + y: currPosition[1], + rotation: transform.rotation, + cursorPoint: cursorPoint, + tooltipOption: { + verticalAlign: 'middle' + } + }; + }; + + return SingleAxisPointer; + }(BaseAxisPointer); + + var pointerShapeBuilder$2 = { + line: function (axis, pixelValue, otherExtent) { + var targetShape = makeLineShape([pixelValue, otherExtent[0]], [pixelValue, otherExtent[1]], getPointDimIndex(axis)); + return { + type: 'Line', + subPixelOptimize: true, + shape: targetShape + }; + }, + shadow: function (axis, pixelValue, otherExtent) { + var bandWidth = axis.getBandWidth(); + var span = otherExtent[1] - otherExtent[0]; + return { + type: 'Rect', + shape: makeRectShape([pixelValue - bandWidth / 2, otherExtent[0]], [bandWidth, span], getPointDimIndex(axis)) + }; + } + }; + + function getPointDimIndex(axis) { + return axis.isHorizontal() ? 0 : 1; + } + + function getGlobalExtent(coordSys, dimIndex) { + var rect = coordSys.getRect(); + return [rect[XY[dimIndex]], rect[XY[dimIndex]] + rect[WH[dimIndex]]]; + } + + var SingleView = function (_super) { + __extends(SingleView, _super); + + function SingleView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SingleView.type; + return _this; + } + + SingleView.type = 'single'; + return SingleView; + }(ComponentView); + + function install$v(registers) { + use(install$r); + AxisView.registerAxisPointerClass('SingleAxisPointer', SingleAxisPointer); + registers.registerComponentView(SingleView); + registers.registerComponentView(SingleAxisView); + registers.registerComponentModel(SingleAxisModel); + axisModelCreator(registers, 'single', SingleAxisModel, SingleAxisModel.defaultOption); + registers.registerCoordinateSystem('single', singleCreator); + } + + var CalendarModel = function (_super) { + __extends(CalendarModel, _super); + + function CalendarModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CalendarModel.type; + return _this; + } + + CalendarModel.prototype.init = function (option, parentModel, ecModel) { + var inputPositionParams = getLayoutParams(option); + + _super.prototype.init.apply(this, arguments); + + mergeAndNormalizeLayoutParams(option, inputPositionParams); + }; + + CalendarModel.prototype.mergeOption = function (option) { + _super.prototype.mergeOption.apply(this, arguments); + + mergeAndNormalizeLayoutParams(this.option, option); + }; + + CalendarModel.prototype.getCellSize = function () { + return this.option.cellSize; + }; + + CalendarModel.type = 'calendar'; + CalendarModel.defaultOption = { + zlevel: 0, + z: 2, + left: 80, + top: 60, + cellSize: 20, + orient: 'horizontal', + splitLine: { + show: true, + lineStyle: { + color: '#000', + width: 1, + type: 'solid' + } + }, + itemStyle: { + color: '#fff', + borderWidth: 1, + borderColor: '#ccc' + }, + dayLabel: { + show: true, + firstDay: 0, + position: 'start', + margin: '50%', + nameMap: 'en', + color: '#000' + }, + monthLabel: { + show: true, + position: 'start', + margin: 5, + align: 'center', + nameMap: 'en', + formatter: null, + color: '#000' + }, + yearLabel: { + show: true, + position: null, + margin: 30, + formatter: null, + color: '#ccc', + fontFamily: 'sans-serif', + fontWeight: 'bolder', + fontSize: 20 + } + }; + return CalendarModel; + }(ComponentModel); + + function mergeAndNormalizeLayoutParams(target, raw) { + var cellSize = target.cellSize; + var cellSizeArr; + + if (!isArray(cellSize)) { + cellSizeArr = target.cellSize = [cellSize, cellSize]; + } else { + cellSizeArr = cellSize; + } + + if (cellSizeArr.length === 1) { + cellSizeArr[1] = cellSizeArr[0]; + } + + var ignoreSize = map([0, 1], function (hvIdx) { + if (sizeCalculable(raw, hvIdx)) { + cellSizeArr[hvIdx] = 'auto'; + } + + return cellSizeArr[hvIdx] != null && cellSizeArr[hvIdx] !== 'auto'; + }); + mergeLayoutParam(target, raw, { + type: 'box', + ignoreSize: ignoreSize + }); + } + + var MONTH_TEXT = { + EN: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + CN: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'] + }; + var WEEK_TEXT = { + EN: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], + CN: ['日', '一', '二', '三', '四', '五', '六'] + }; + + var CalendarView = function (_super) { + __extends(CalendarView, _super); + + function CalendarView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = CalendarView.type; + return _this; + } + + CalendarView.prototype.render = function (calendarModel, ecModel, api) { + var group = this.group; + group.removeAll(); + var coordSys = calendarModel.coordinateSystem; + var rangeData = coordSys.getRangeInfo(); + var orient = coordSys.getOrient(); + + this._renderDayRect(calendarModel, rangeData, group); + + this._renderLines(calendarModel, rangeData, orient, group); + + this._renderYearText(calendarModel, rangeData, orient, group); + + this._renderMonthText(calendarModel, orient, group); + + this._renderWeekText(calendarModel, rangeData, orient, group); + }; + + CalendarView.prototype._renderDayRect = function (calendarModel, rangeData, group) { + var coordSys = calendarModel.coordinateSystem; + var itemRectStyleModel = calendarModel.getModel('itemStyle').getItemStyle(); + var sw = coordSys.getCellWidth(); + var sh = coordSys.getCellHeight(); + + for (var i = rangeData.start.time; i <= rangeData.end.time; i = coordSys.getNextNDay(i, 1).time) { + var point = coordSys.dataToRect([i], false).tl; + var rect = new Rect({ + shape: { + x: point[0], + y: point[1], + width: sw, + height: sh + }, + cursor: 'default', + style: itemRectStyleModel + }); + group.add(rect); + } + }; + + CalendarView.prototype._renderLines = function (calendarModel, rangeData, orient, group) { + var self = this; + var coordSys = calendarModel.coordinateSystem; + var lineStyleModel = calendarModel.getModel(['splitLine', 'lineStyle']).getLineStyle(); + var show = calendarModel.get(['splitLine', 'show']); + var lineWidth = lineStyleModel.lineWidth; + this._tlpoints = []; + this._blpoints = []; + this._firstDayOfMonth = []; + this._firstDayPoints = []; + var firstDay = rangeData.start; + + for (var i = 0; firstDay.time <= rangeData.end.time; i++) { + addPoints(firstDay.formatedDate); + + if (i === 0) { + firstDay = coordSys.getDateInfo(rangeData.start.y + '-' + rangeData.start.m); + } + + var date = firstDay.date; + date.setMonth(date.getMonth() + 1); + firstDay = coordSys.getDateInfo(date); + } + + addPoints(coordSys.getNextNDay(rangeData.end.time, 1).formatedDate); + + function addPoints(date) { + self._firstDayOfMonth.push(coordSys.getDateInfo(date)); + + self._firstDayPoints.push(coordSys.dataToRect([date], false).tl); + + var points = self._getLinePointsOfOneWeek(calendarModel, date, orient); + + self._tlpoints.push(points[0]); + + self._blpoints.push(points[points.length - 1]); + + show && self._drawSplitline(points, lineStyleModel, group); + } + + show && this._drawSplitline(self._getEdgesPoints(self._tlpoints, lineWidth, orient), lineStyleModel, group); + show && this._drawSplitline(self._getEdgesPoints(self._blpoints, lineWidth, orient), lineStyleModel, group); + }; + + CalendarView.prototype._getEdgesPoints = function (points, lineWidth, orient) { + var rs = [points[0].slice(), points[points.length - 1].slice()]; + var idx = orient === 'horizontal' ? 0 : 1; + rs[0][idx] = rs[0][idx] - lineWidth / 2; + rs[1][idx] = rs[1][idx] + lineWidth / 2; + return rs; + }; + + CalendarView.prototype._drawSplitline = function (points, lineStyle, group) { + var poyline = new Polyline({ + z2: 20, + shape: { + points: points + }, + style: lineStyle + }); + group.add(poyline); + }; + + CalendarView.prototype._getLinePointsOfOneWeek = function (calendarModel, date, orient) { + var coordSys = calendarModel.coordinateSystem; + var parsedDate = coordSys.getDateInfo(date); + var points = []; + + for (var i = 0; i < 7; i++) { + var tmpD = coordSys.getNextNDay(parsedDate.time, i); + var point = coordSys.dataToRect([tmpD.time], false); + points[2 * tmpD.day] = point.tl; + points[2 * tmpD.day + 1] = point[orient === 'horizontal' ? 'bl' : 'tr']; + } + + return points; + }; + + CalendarView.prototype._formatterLabel = function (formatter, params) { + if (typeof formatter === 'string' && formatter) { + return formatTplSimple(formatter, params); + } + + if (typeof formatter === 'function') { + return formatter(params); + } + + return params.nameMap; + }; + + CalendarView.prototype._yearTextPositionControl = function (textEl, point, orient, position, margin) { + var x = point[0]; + var y = point[1]; + var aligns = ['center', 'bottom']; + + if (position === 'bottom') { + y += margin; + aligns = ['center', 'top']; + } else if (position === 'left') { + x -= margin; + } else if (position === 'right') { + x += margin; + aligns = ['center', 'top']; + } else { + y -= margin; + } + + var rotate = 0; + + if (position === 'left' || position === 'right') { + rotate = Math.PI / 2; + } + + return { + rotation: rotate, + x: x, + y: y, + style: { + align: aligns[0], + verticalAlign: aligns[1] + } + }; + }; + + CalendarView.prototype._renderYearText = function (calendarModel, rangeData, orient, group) { + var yearLabel = calendarModel.getModel('yearLabel'); + + if (!yearLabel.get('show')) { + return; + } + + var margin = yearLabel.get('margin'); + var pos = yearLabel.get('position'); + + if (!pos) { + pos = orient !== 'horizontal' ? 'top' : 'left'; + } + + var points = [this._tlpoints[this._tlpoints.length - 1], this._blpoints[0]]; + var xc = (points[0][0] + points[1][0]) / 2; + var yc = (points[0][1] + points[1][1]) / 2; + var idx = orient === 'horizontal' ? 0 : 1; + var posPoints = { + top: [xc, points[idx][1]], + bottom: [xc, points[1 - idx][1]], + left: [points[1 - idx][0], yc], + right: [points[idx][0], yc] + }; + var name = rangeData.start.y; + + if (+rangeData.end.y > +rangeData.start.y) { + name = name + '-' + rangeData.end.y; + } + + var formatter = yearLabel.get('formatter'); + var params = { + start: rangeData.start.y, + end: rangeData.end.y, + nameMap: name + }; + + var content = this._formatterLabel(formatter, params); + + var yearText = new ZRText({ + z2: 30, + style: createTextStyle(yearLabel, { + text: content + }) + }); + yearText.attr(this._yearTextPositionControl(yearText, posPoints[pos], orient, pos, margin)); + group.add(yearText); + }; + + CalendarView.prototype._monthTextPositionControl = function (point, isCenter, orient, position, margin) { + var align = 'left'; + var vAlign = 'top'; + var x = point[0]; + var y = point[1]; + + if (orient === 'horizontal') { + y = y + margin; + + if (isCenter) { + align = 'center'; + } + + if (position === 'start') { + vAlign = 'bottom'; + } + } else { + x = x + margin; + + if (isCenter) { + vAlign = 'middle'; + } + + if (position === 'start') { + align = 'right'; + } + } + + return { + x: x, + y: y, + align: align, + verticalAlign: vAlign + }; + }; + + CalendarView.prototype._renderMonthText = function (calendarModel, orient, group) { + var monthLabel = calendarModel.getModel('monthLabel'); + + if (!monthLabel.get('show')) { + return; + } + + var nameMap = monthLabel.get('nameMap'); + var margin = monthLabel.get('margin'); + var pos = monthLabel.get('position'); + var align = monthLabel.get('align'); + var termPoints = [this._tlpoints, this._blpoints]; + + if (isString(nameMap)) { + nameMap = MONTH_TEXT[nameMap.toUpperCase()] || []; + } + + var idx = pos === 'start' ? 0 : 1; + var axis = orient === 'horizontal' ? 0 : 1; + margin = pos === 'start' ? -margin : margin; + var isCenter = align === 'center'; + + for (var i = 0; i < termPoints[idx].length - 1; i++) { + var tmp = termPoints[idx][i].slice(); + var firstDay = this._firstDayOfMonth[i]; + + if (isCenter) { + var firstDayPoints = this._firstDayPoints[i]; + tmp[axis] = (firstDayPoints[axis] + termPoints[0][i + 1][axis]) / 2; + } + + var formatter = monthLabel.get('formatter'); + var name_1 = nameMap[+firstDay.m - 1]; + var params = { + yyyy: firstDay.y, + yy: (firstDay.y + '').slice(2), + MM: firstDay.m, + M: +firstDay.m, + nameMap: name_1 + }; + + var content = this._formatterLabel(formatter, params); + + var monthText = new ZRText({ + z2: 30, + style: extend(createTextStyle(monthLabel, { + text: content + }), this._monthTextPositionControl(tmp, isCenter, orient, pos, margin)) + }); + group.add(monthText); + } + }; + + CalendarView.prototype._weekTextPositionControl = function (point, orient, position, margin, cellSize) { + var align = 'center'; + var vAlign = 'middle'; + var x = point[0]; + var y = point[1]; + var isStart = position === 'start'; + + if (orient === 'horizontal') { + x = x + margin + (isStart ? 1 : -1) * cellSize[0] / 2; + align = isStart ? 'right' : 'left'; + } else { + y = y + margin + (isStart ? 1 : -1) * cellSize[1] / 2; + vAlign = isStart ? 'bottom' : 'top'; + } + + return { + x: x, + y: y, + align: align, + verticalAlign: vAlign + }; + }; + + CalendarView.prototype._renderWeekText = function (calendarModel, rangeData, orient, group) { + var dayLabel = calendarModel.getModel('dayLabel'); + + if (!dayLabel.get('show')) { + return; + } + + var coordSys = calendarModel.coordinateSystem; + var pos = dayLabel.get('position'); + var nameMap = dayLabel.get('nameMap'); + var margin = dayLabel.get('margin'); + var firstDayOfWeek = coordSys.getFirstDayOfWeek(); + + if (isString(nameMap)) { + nameMap = WEEK_TEXT[nameMap.toUpperCase()] || []; + } + + var start = coordSys.getNextNDay(rangeData.end.time, 7 - rangeData.lweek).time; + var cellSize = [coordSys.getCellWidth(), coordSys.getCellHeight()]; + margin = parsePercent$1(margin, cellSize[orient === 'horizontal' ? 0 : 1]); + + if (pos === 'start') { + start = coordSys.getNextNDay(rangeData.start.time, -(7 + rangeData.fweek)).time; + margin = -margin; + } + + for (var i = 0; i < 7; i++) { + var tmpD = coordSys.getNextNDay(start, i); + var point = coordSys.dataToRect([tmpD.time], false).center; + var day = i; + day = Math.abs((i + firstDayOfWeek) % 7); + var weekText = new ZRText({ + z2: 30, + style: extend(createTextStyle(dayLabel, { + text: nameMap[day] + }), this._weekTextPositionControl(point, orient, pos, margin, cellSize)) + }); + group.add(weekText); + } + }; + + CalendarView.type = 'calendar'; + return CalendarView; + }(ComponentView); + + var PROXIMATE_ONE_DAY = 86400000; + + var Calendar = function () { + function Calendar(calendarModel, ecModel, api) { + this.type = 'calendar'; + this.dimensions = Calendar.dimensions; + this.getDimensionsInfo = Calendar.getDimensionsInfo; + this._model = calendarModel; + } + + Calendar.getDimensionsInfo = function () { + return [{ + name: 'time', + type: 'time' + }, 'value']; + }; + + Calendar.prototype.getRangeInfo = function () { + return this._rangeInfo; + }; + + Calendar.prototype.getModel = function () { + return this._model; + }; + + Calendar.prototype.getRect = function () { + return this._rect; + }; + + Calendar.prototype.getCellWidth = function () { + return this._sw; + }; + + Calendar.prototype.getCellHeight = function () { + return this._sh; + }; + + Calendar.prototype.getOrient = function () { + return this._orient; + }; + + Calendar.prototype.getFirstDayOfWeek = function () { + return this._firstDayOfWeek; + }; + + Calendar.prototype.getDateInfo = function (date) { + date = parseDate(date); + var y = date.getFullYear(); + var m = date.getMonth() + 1; + var mStr = m < 10 ? '0' + m : '' + m; + var d = date.getDate(); + var dStr = d < 10 ? '0' + d : '' + d; + var day = date.getDay(); + day = Math.abs((day + 7 - this.getFirstDayOfWeek()) % 7); + return { + y: y + '', + m: mStr, + d: dStr, + day: day, + time: date.getTime(), + formatedDate: y + '-' + mStr + '-' + dStr, + date: date + }; + }; + + Calendar.prototype.getNextNDay = function (date, n) { + n = n || 0; + + if (n === 0) { + return this.getDateInfo(date); + } + + date = new Date(this.getDateInfo(date).time); + date.setDate(date.getDate() + n); + return this.getDateInfo(date); + }; + + Calendar.prototype.update = function (ecModel, api) { + this._firstDayOfWeek = +this._model.getModel('dayLabel').get('firstDay'); + this._orient = this._model.get('orient'); + this._lineWidth = this._model.getModel('itemStyle').getItemStyle().lineWidth || 0; + this._rangeInfo = this._getRangeInfo(this._initRangeOption()); + var weeks = this._rangeInfo.weeks || 1; + var whNames = ['width', 'height']; + + var cellSize = this._model.getCellSize().slice(); + + var layoutParams = this._model.getBoxLayoutParams(); + + var cellNumbers = this._orient === 'horizontal' ? [weeks, 7] : [7, weeks]; + each([0, 1], function (idx) { + if (cellSizeSpecified(cellSize, idx)) { + layoutParams[whNames[idx]] = cellSize[idx] * cellNumbers[idx]; + } + }); + var whGlobal = { + width: api.getWidth(), + height: api.getHeight() + }; + var calendarRect = this._rect = getLayoutRect(layoutParams, whGlobal); + each([0, 1], function (idx) { + if (!cellSizeSpecified(cellSize, idx)) { + cellSize[idx] = calendarRect[whNames[idx]] / cellNumbers[idx]; + } + }); + + function cellSizeSpecified(cellSize, idx) { + return cellSize[idx] != null && cellSize[idx] !== 'auto'; + } + + this._sw = cellSize[0]; + this._sh = cellSize[1]; + }; + + Calendar.prototype.dataToPoint = function (data, clamp) { + isArray(data) && (data = data[0]); + clamp == null && (clamp = true); + var dayInfo = this.getDateInfo(data); + var range = this._rangeInfo; + var date = dayInfo.formatedDate; + + if (clamp && !(dayInfo.time >= range.start.time && dayInfo.time < range.end.time + PROXIMATE_ONE_DAY)) { + return [NaN, NaN]; + } + + var week = dayInfo.day; + + var nthWeek = this._getRangeInfo([range.start.time, date]).nthWeek; + + if (this._orient === 'vertical') { + return [this._rect.x + week * this._sw + this._sw / 2, this._rect.y + nthWeek * this._sh + this._sh / 2]; + } + + return [this._rect.x + nthWeek * this._sw + this._sw / 2, this._rect.y + week * this._sh + this._sh / 2]; + }; + + Calendar.prototype.pointToData = function (point) { + var date = this.pointToDate(point); + return date && date.time; + }; + + Calendar.prototype.dataToRect = function (data, clamp) { + var point = this.dataToPoint(data, clamp); + return { + contentShape: { + x: point[0] - (this._sw - this._lineWidth) / 2, + y: point[1] - (this._sh - this._lineWidth) / 2, + width: this._sw - this._lineWidth, + height: this._sh - this._lineWidth + }, + center: point, + tl: [point[0] - this._sw / 2, point[1] - this._sh / 2], + tr: [point[0] + this._sw / 2, point[1] - this._sh / 2], + br: [point[0] + this._sw / 2, point[1] + this._sh / 2], + bl: [point[0] - this._sw / 2, point[1] + this._sh / 2] + }; + }; + + Calendar.prototype.pointToDate = function (point) { + var nthX = Math.floor((point[0] - this._rect.x) / this._sw) + 1; + var nthY = Math.floor((point[1] - this._rect.y) / this._sh) + 1; + var range = this._rangeInfo.range; + + if (this._orient === 'vertical') { + return this._getDateByWeeksAndDay(nthY, nthX - 1, range); + } + + return this._getDateByWeeksAndDay(nthX, nthY - 1, range); + }; + + Calendar.prototype.convertToPixel = function (ecModel, finder, value) { + var coordSys = getCoordSys$4(finder); + return coordSys === this ? coordSys.dataToPoint(value) : null; + }; + + Calendar.prototype.convertFromPixel = function (ecModel, finder, pixel) { + var coordSys = getCoordSys$4(finder); + return coordSys === this ? coordSys.pointToData(pixel) : null; + }; + + Calendar.prototype.containPoint = function (point) { + console.warn('Not implemented.'); + return false; + }; + + Calendar.prototype._initRangeOption = function () { + var range = this._model.get('range'); + + var normalizedRange; + + if (isArray(range) && range.length === 1) { + range = range[0]; + } + + if (!isArray(range)) { + var rangeStr = range.toString(); + + if (/^\d{4}$/.test(rangeStr)) { + normalizedRange = [rangeStr + '-01-01', rangeStr + '-12-31']; + } + + if (/^\d{4}[\/|-]\d{1,2}$/.test(rangeStr)) { + var start = this.getDateInfo(rangeStr); + var firstDay = start.date; + firstDay.setMonth(firstDay.getMonth() + 1); + var end = this.getNextNDay(firstDay, -1); + normalizedRange = [start.formatedDate, end.formatedDate]; + } + + if (/^\d{4}[\/|-]\d{1,2}[\/|-]\d{1,2}$/.test(rangeStr)) { + normalizedRange = [rangeStr, rangeStr]; + } + } else { + normalizedRange = range; + } + + if (!normalizedRange) { + if ("development" !== 'production') { + logError('Invalid date range.'); + } + + return range; + } + + var tmp = this._getRangeInfo(normalizedRange); + + if (tmp.start.time > tmp.end.time) { + normalizedRange.reverse(); + } + + return normalizedRange; + }; + + Calendar.prototype._getRangeInfo = function (range) { + var parsedRange = [this.getDateInfo(range[0]), this.getDateInfo(range[1])]; + var reversed; + + if (parsedRange[0].time > parsedRange[1].time) { + reversed = true; + parsedRange.reverse(); + } + + var allDay = Math.floor(parsedRange[1].time / PROXIMATE_ONE_DAY) - Math.floor(parsedRange[0].time / PROXIMATE_ONE_DAY) + 1; + var date = new Date(parsedRange[0].time); + var startDateNum = date.getDate(); + var endDateNum = parsedRange[1].date.getDate(); + date.setDate(startDateNum + allDay - 1); + var dateNum = date.getDate(); + + if (dateNum !== endDateNum) { + var sign = date.getTime() - parsedRange[1].time > 0 ? 1 : -1; + + while ((dateNum = date.getDate()) !== endDateNum && (date.getTime() - parsedRange[1].time) * sign > 0) { + allDay -= sign; + date.setDate(dateNum - sign); + } + } + + var weeks = Math.floor((allDay + parsedRange[0].day + 6) / 7); + var nthWeek = reversed ? -weeks + 1 : weeks - 1; + reversed && parsedRange.reverse(); + return { + range: [parsedRange[0].formatedDate, parsedRange[1].formatedDate], + start: parsedRange[0], + end: parsedRange[1], + allDay: allDay, + weeks: weeks, + nthWeek: nthWeek, + fweek: parsedRange[0].day, + lweek: parsedRange[1].day + }; + }; + + Calendar.prototype._getDateByWeeksAndDay = function (nthWeek, day, range) { + var rangeInfo = this._getRangeInfo(range); + + if (nthWeek > rangeInfo.weeks || nthWeek === 0 && day < rangeInfo.fweek || nthWeek === rangeInfo.weeks && day > rangeInfo.lweek) { + return null; + } + + var nthDay = (nthWeek - 1) * 7 - rangeInfo.fweek + day; + var date = new Date(rangeInfo.start.time); + date.setDate(+rangeInfo.start.d + nthDay); + return this.getDateInfo(date); + }; + + Calendar.create = function (ecModel, api) { + var calendarList = []; + ecModel.eachComponent('calendar', function (calendarModel) { + var calendar = new Calendar(calendarModel, ecModel, api); + calendarList.push(calendar); + calendarModel.coordinateSystem = calendar; + }); + ecModel.eachSeries(function (calendarSeries) { + if (calendarSeries.get('coordinateSystem') === 'calendar') { + calendarSeries.coordinateSystem = calendarList[calendarSeries.get('calendarIndex') || 0]; + } + }); + return calendarList; + }; + + Calendar.dimensions = ['time', 'value']; + return Calendar; + }(); + + function getCoordSys$4(finder) { + var calendarModel = finder.calendarModel; + var seriesModel = finder.seriesModel; + var coordSys = calendarModel ? calendarModel.coordinateSystem : seriesModel ? seriesModel.coordinateSystem : null; + return coordSys; + } + + function install$w(registers) { + registers.registerComponentModel(CalendarModel); + registers.registerComponentView(CalendarView); + registers.registerCoordinateSystem('calendar', Calendar); + } + + var inner$g = makeInner(); + var _nonShapeGraphicElements = { + path: null, + compoundPath: null, + group: Group, + image: ZRImage, + text: ZRText + }; + + var preprocessor = function (option) { + var graphicOption = option.graphic; + + if (isArray(graphicOption)) { + if (!graphicOption[0] || !graphicOption[0].elements) { + option.graphic = [{ + elements: graphicOption + }]; + } else { + option.graphic = [option.graphic[0]]; + } + } else if (graphicOption && !graphicOption.elements) { + option.graphic = [{ + elements: [graphicOption] + }]; + } + }; + + var GraphicComponentModel = function (_super) { + __extends(GraphicComponentModel, _super); + + function GraphicComponentModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GraphicComponentModel.type; + return _this; + } + + GraphicComponentModel.prototype.mergeOption = function (option, ecModel) { + var elements = this.option.elements; + this.option.elements = null; + + _super.prototype.mergeOption.call(this, option, ecModel); + + this.option.elements = elements; + }; + + GraphicComponentModel.prototype.optionUpdated = function (newOption, isInit) { + var thisOption = this.option; + var newList = (isInit ? thisOption : newOption).elements; + var existList = thisOption.elements = isInit ? [] : thisOption.elements; + var flattenedList = []; + + this._flatten(newList, flattenedList, null); + + var mappingResult = mappingToExists(existList, flattenedList, 'normalMerge'); + var elOptionsToUpdate = this._elOptionsToUpdate = []; + each(mappingResult, function (resultItem, index) { + var newElOption = resultItem.newOption; + + if ("development" !== 'production') { + assert(isObject(newElOption) || resultItem.existing, 'Empty graphic option definition'); + } + + if (!newElOption) { + return; + } + + elOptionsToUpdate.push(newElOption); + setKeyInfoToNewElOption(resultItem, newElOption); + mergeNewElOptionToExist(existList, index, newElOption); + setLayoutInfoToExist(existList[index], newElOption); + }, this); + + for (var i = existList.length - 1; i >= 0; i--) { + if (existList[i] == null) { + existList.splice(i, 1); + } else { + delete existList[i].$action; + } + } + }; + + GraphicComponentModel.prototype._flatten = function (optionList, result, parentOption) { + each(optionList, function (option) { + if (!option) { + return; + } + + if (parentOption) { + option.parentOption = parentOption; + } + + result.push(option); + var children = option.children; + + if (option.type === 'group' && children) { + this._flatten(children, result, option); + } + + delete option.children; + }, this); + }; + + GraphicComponentModel.prototype.useElOptionsToUpdate = function () { + var els = this._elOptionsToUpdate; + this._elOptionsToUpdate = null; + return els; + }; + + GraphicComponentModel.type = 'graphic'; + GraphicComponentModel.defaultOption = { + elements: [] + }; + return GraphicComponentModel; + }(ComponentModel); + + var GraphicComponentView = function (_super) { + __extends(GraphicComponentView, _super); + + function GraphicComponentView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = GraphicComponentView.type; + return _this; + } + + GraphicComponentView.prototype.init = function () { + this._elMap = createHashMap(); + }; + + GraphicComponentView.prototype.render = function (graphicModel, ecModel, api) { + if (graphicModel !== this._lastGraphicModel) { + this._clear(); + } + + this._lastGraphicModel = graphicModel; + + this._updateElements(graphicModel); + + this._relocate(graphicModel, api); + }; + + GraphicComponentView.prototype._updateElements = function (graphicModel) { + var elOptionsToUpdate = graphicModel.useElOptionsToUpdate(); + + if (!elOptionsToUpdate) { + return; + } + + var elMap = this._elMap; + var rootGroup = this.group; + each(elOptionsToUpdate, function (elOption) { + var id = convertOptionIdName(elOption.id, null); + var elExisting = id != null ? elMap.get(id) : null; + var parentId = convertOptionIdName(elOption.parentId, null); + var targetElParent = parentId != null ? elMap.get(parentId) : rootGroup; + var elType = elOption.type; + var elOptionStyle = elOption.style; + + if (elType === 'text' && elOptionStyle) { + if (elOption.hv && elOption.hv[1]) { + elOptionStyle.textVerticalAlign = elOptionStyle.textBaseline = elOptionStyle.verticalAlign = elOptionStyle.align = null; + } + } + + var textContentOption = elOption.textContent; + var textConfig = elOption.textConfig; + + if (elOptionStyle && isEC4CompatibleStyle(elOptionStyle, elType, !!textConfig, !!textContentOption)) { + var convertResult = convertFromEC4CompatibleStyle(elOptionStyle, elType, true); + + if (!textConfig && convertResult.textConfig) { + textConfig = elOption.textConfig = convertResult.textConfig; + } + + if (!textContentOption && convertResult.textContent) { + textContentOption = convertResult.textContent; + } + } + + var elOptionCleaned = getCleanedElOption(elOption); + + if ("development" !== 'production') { + elExisting && assert(targetElParent === elExisting.parent, 'Changing parent is not supported.'); + } + + var $action = elOption.$action || 'merge'; + + if ($action === 'merge') { + elExisting ? elExisting.attr(elOptionCleaned) : createEl$1(id, targetElParent, elOptionCleaned, elMap); + } else if ($action === 'replace') { + removeEl(elExisting, elMap); + createEl$1(id, targetElParent, elOptionCleaned, elMap); + } else if ($action === 'remove') { + removeEl(elExisting, elMap); + } + + var el = elMap.get(id); + + if (el && textContentOption) { + if ($action === 'merge') { + var textContentExisting = el.getTextContent(); + textContentExisting ? textContentExisting.attr(textContentOption) : el.setTextContent(new ZRText(textContentOption)); + } else if ($action === 'replace') { + el.setTextContent(new ZRText(textContentOption)); + } + } + + if (el) { + var elInner = inner$g(el); + elInner.__ecGraphicWidthOption = elOption.width; + elInner.__ecGraphicHeightOption = elOption.height; + setEventData(el, graphicModel, elOption); + } + }); + }; + + GraphicComponentView.prototype._relocate = function (graphicModel, api) { + var elOptions = graphicModel.option.elements; + var rootGroup = this.group; + var elMap = this._elMap; + var apiWidth = api.getWidth(); + var apiHeight = api.getHeight(); + + for (var i = 0; i < elOptions.length; i++) { + var elOption = elOptions[i]; + var id = convertOptionIdName(elOption.id, null); + var el = id != null ? elMap.get(id) : null; + + if (!el || !el.isGroup) { + continue; + } + + var parentEl = el.parent; + var isParentRoot = parentEl === rootGroup; + var elInner = inner$g(el); + var parentElInner = inner$g(parentEl); + elInner.__ecGraphicWidth = parsePercent$1(elInner.__ecGraphicWidthOption, isParentRoot ? apiWidth : parentElInner.__ecGraphicWidth) || 0; + elInner.__ecGraphicHeight = parsePercent$1(elInner.__ecGraphicHeightOption, isParentRoot ? apiHeight : parentElInner.__ecGraphicHeight) || 0; + } + + for (var i = elOptions.length - 1; i >= 0; i--) { + var elOption = elOptions[i]; + var id = convertOptionIdName(elOption.id, null); + var el = id != null ? elMap.get(id) : null; + + if (!el) { + continue; + } + + var parentEl = el.parent; + var parentElInner = inner$g(parentEl); + var containerInfo = parentEl === rootGroup ? { + width: apiWidth, + height: apiHeight + } : { + width: parentElInner.__ecGraphicWidth, + height: parentElInner.__ecGraphicHeight + }; + positionElement(el, elOption, containerInfo, null, { + hv: elOption.hv, + boundingMode: elOption.bounding + }); + } + }; + + GraphicComponentView.prototype._clear = function () { + var elMap = this._elMap; + elMap.each(function (el) { + removeEl(el, elMap); + }); + this._elMap = createHashMap(); + }; + + GraphicComponentView.prototype.dispose = function () { + this._clear(); + }; + + GraphicComponentView.type = 'graphic'; + return GraphicComponentView; + }(ComponentView); + + function createEl$1(id, targetElParent, elOption, elMap) { + var graphicType = elOption.type; + + if ("development" !== 'production') { + assert(graphicType, 'graphic type MUST be set'); + } + + var Clz = hasOwn(_nonShapeGraphicElements, graphicType) ? _nonShapeGraphicElements[graphicType] : getShapeClass(graphicType); + + if ("development" !== 'production') { + assert(Clz, 'graphic type can not be found'); + } + + var el = new Clz(elOption); + targetElParent.add(el); + elMap.set(id, el); + inner$g(el).__ecGraphicId = id; + } + + function removeEl(elExisting, elMap) { + var existElParent = elExisting && elExisting.parent; + + if (existElParent) { + elExisting.type === 'group' && elExisting.traverse(function (el) { + removeEl(el, elMap); + }); + elMap.removeKey(inner$g(elExisting).__ecGraphicId); + existElParent.remove(elExisting); + } + } + + function getCleanedElOption(elOption) { + elOption = extend({}, elOption); + each(['id', 'parentId', '$action', 'hv', 'bounding', 'textContent'].concat(LOCATION_PARAMS), function (name) { + delete elOption[name]; + }); + return elOption; + } + + function isSetLoc(obj, props) { + var isSet; + each(props, function (prop) { + obj[prop] != null && obj[prop] !== 'auto' && (isSet = true); + }); + return isSet; + } + + function setKeyInfoToNewElOption(resultItem, newElOption) { + var existElOption = resultItem.existing; + newElOption.id = resultItem.keyInfo.id; + !newElOption.type && existElOption && (newElOption.type = existElOption.type); + + if (newElOption.parentId == null) { + var newElParentOption = newElOption.parentOption; + + if (newElParentOption) { + newElOption.parentId = newElParentOption.id; + } else if (existElOption) { + newElOption.parentId = existElOption.parentId; + } + } + + newElOption.parentOption = null; + } + + function mergeNewElOptionToExist(existList, index, newElOption) { + var newElOptCopy = extend({}, newElOption); + var existElOption = existList[index]; + var $action = newElOption.$action || 'merge'; + + if ($action === 'merge') { + if (existElOption) { + if ("development" !== 'production') { + var newType = newElOption.type; + assert(!newType || existElOption.type === newType, 'Please set $action: "replace" to change `type`'); + } + + merge(existElOption, newElOptCopy, true); + mergeLayoutParam(existElOption, newElOptCopy, { + ignoreSize: true + }); + copyLayoutParams(newElOption, existElOption); + } else { + existList[index] = newElOptCopy; + } + } else if ($action === 'replace') { + existList[index] = newElOptCopy; + } else if ($action === 'remove') { + existElOption && (existList[index] = null); + } + } + + function setLayoutInfoToExist(existItem, newElOption) { + if (!existItem) { + return; + } + + existItem.hv = newElOption.hv = [isSetLoc(newElOption, ['left', 'right']), isSetLoc(newElOption, ['top', 'bottom'])]; + + if (existItem.type === 'group') { + var existingGroupOpt = existItem; + var newGroupOpt = newElOption; + existingGroupOpt.width == null && (existingGroupOpt.width = newGroupOpt.width = 0); + existingGroupOpt.height == null && (existingGroupOpt.height = newGroupOpt.height = 0); + } + } + + function setEventData(el, graphicModel, elOption) { + var eventData = getECData(el).eventData; + + if (!el.silent && !el.ignore && !eventData) { + eventData = getECData(el).eventData = { + componentType: 'graphic', + componentIndex: graphicModel.componentIndex, + name: el.name + }; + } + + if (eventData) { + eventData.info = elOption.info; + } + } + + function install$x(registers) { + registers.registerComponentModel(GraphicComponentModel); + registers.registerComponentView(GraphicComponentView); + registers.registerPreprocessor(preprocessor); + } + + var DATA_ZOOM_AXIS_DIMENSIONS = ['x', 'y', 'radius', 'angle', 'single']; + var SERIES_COORDS = ['cartesian2d', 'polar', 'singleAxis']; + function isCoordSupported(seriesModel) { + var coordType = seriesModel.get('coordinateSystem'); + return indexOf(SERIES_COORDS, coordType) >= 0; + } + function getAxisMainType(axisDim) { + if ("development" !== 'production') { + assert(axisDim); + } + + return axisDim + 'Axis'; + } + function findEffectedDataZooms(ecModel, payload) { + var axisRecords = createHashMap(); + var effectedModels = []; + var effectedModelMap = createHashMap(); + ecModel.eachComponent({ + mainType: 'dataZoom', + query: payload + }, function (dataZoomModel) { + if (!effectedModelMap.get(dataZoomModel.uid)) { + addToEffected(dataZoomModel); + } + }); + var foundNewLink; + + do { + foundNewLink = false; + ecModel.eachComponent('dataZoom', processSingle); + } while (foundNewLink); + + function processSingle(dataZoomModel) { + if (!effectedModelMap.get(dataZoomModel.uid) && isLinked(dataZoomModel)) { + addToEffected(dataZoomModel); + foundNewLink = true; + } + } + + function addToEffected(dataZoom) { + effectedModelMap.set(dataZoom.uid, true); + effectedModels.push(dataZoom); + markAxisControlled(dataZoom); + } + + function isLinked(dataZoomModel) { + var isLink = false; + dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { + var axisIdxArr = axisRecords.get(axisDim); + + if (axisIdxArr && axisIdxArr[axisIndex]) { + isLink = true; + } + }); + return isLink; + } + + function markAxisControlled(dataZoomModel) { + dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { + (axisRecords.get(axisDim) || axisRecords.set(axisDim, []))[axisIndex] = true; + }); + } + + return effectedModels; + } + function collectReferCoordSysModelInfo(dataZoomModel) { + var ecModel = dataZoomModel.ecModel; + var coordSysInfoWrap = { + infoList: [], + infoMap: createHashMap() + }; + dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { + var axisModel = ecModel.getComponent(getAxisMainType(axisDim), axisIndex); + + if (!axisModel) { + return; + } + + var coordSysModel = axisModel.getCoordSysModel(); + + if (!coordSysModel) { + return; + } + + var coordSysUid = coordSysModel.uid; + var coordSysInfo = coordSysInfoWrap.infoMap.get(coordSysUid); + + if (!coordSysInfo) { + coordSysInfo = { + model: coordSysModel, + axisModels: [] + }; + coordSysInfoWrap.infoList.push(coordSysInfo); + coordSysInfoWrap.infoMap.set(coordSysUid, coordSysInfo); + } + + coordSysInfo.axisModels.push(axisModel); + }); + return coordSysInfoWrap; + } + + var DataZoomAxisInfo = function () { + function DataZoomAxisInfo() { + this.indexList = []; + this.indexMap = []; + } + + DataZoomAxisInfo.prototype.add = function (axisCmptIdx) { + if (!this.indexMap[axisCmptIdx]) { + this.indexList.push(axisCmptIdx); + this.indexMap[axisCmptIdx] = true; + } + }; + + return DataZoomAxisInfo; + }(); + + var DataZoomModel = function (_super) { + __extends(DataZoomModel, _super); + + function DataZoomModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = DataZoomModel.type; + _this._autoThrottle = true; + _this._noTarget = true; + _this._rangePropMode = ['percent', 'percent']; + return _this; + } + + DataZoomModel.prototype.init = function (option, parentModel, ecModel) { + var inputRawOption = retrieveRawOption(option); + this.settledOption = inputRawOption; + this.mergeDefaultAndTheme(option, ecModel); + + this._doInit(inputRawOption); + }; + + DataZoomModel.prototype.mergeOption = function (newOption) { + var inputRawOption = retrieveRawOption(newOption); + merge(this.option, newOption, true); + merge(this.settledOption, inputRawOption, true); + + this._doInit(inputRawOption); + }; + + DataZoomModel.prototype._doInit = function (inputRawOption) { + var thisOption = this.option; + + this._setDefaultThrottle(inputRawOption); + + this._updateRangeUse(inputRawOption); + + var settledOption = this.settledOption; + each([['start', 'startValue'], ['end', 'endValue']], function (names, index) { + if (this._rangePropMode[index] === 'value') { + thisOption[names[0]] = settledOption[names[0]] = null; + } + }, this); + + this._resetTarget(); + }; + + DataZoomModel.prototype._resetTarget = function () { + var optionOrient = this.get('orient', true); + var targetAxisIndexMap = this._targetAxisInfoMap = createHashMap(); + + var hasAxisSpecified = this._fillSpecifiedTargetAxis(targetAxisIndexMap); + + if (hasAxisSpecified) { + this._orient = optionOrient || this._makeAutoOrientByTargetAxis(); + } else { + this._orient = optionOrient || 'horizontal'; + + this._fillAutoTargetAxisByOrient(targetAxisIndexMap, this._orient); + } + + this._noTarget = true; + targetAxisIndexMap.each(function (axisInfo) { + if (axisInfo.indexList.length) { + this._noTarget = false; + } + }, this); + }; + + DataZoomModel.prototype._fillSpecifiedTargetAxis = function (targetAxisIndexMap) { + var hasAxisSpecified = false; + each(DATA_ZOOM_AXIS_DIMENSIONS, function (axisDim) { + var refering = this.getReferringComponents(getAxisMainType(axisDim), MULTIPLE_REFERRING); + + if (!refering.specified) { + return; + } + + hasAxisSpecified = true; + var axisInfo = new DataZoomAxisInfo(); + each(refering.models, function (axisModel) { + axisInfo.add(axisModel.componentIndex); + }); + targetAxisIndexMap.set(axisDim, axisInfo); + }, this); + return hasAxisSpecified; + }; + + DataZoomModel.prototype._fillAutoTargetAxisByOrient = function (targetAxisIndexMap, orient) { + var ecModel = this.ecModel; + var needAuto = true; + + if (needAuto) { + var axisDim = orient === 'vertical' ? 'y' : 'x'; + var axisModels = ecModel.findComponents({ + mainType: axisDim + 'Axis' + }); + setParallelAxis(axisModels, axisDim); + } + + if (needAuto) { + var axisModels = ecModel.findComponents({ + mainType: 'singleAxis', + filter: function (axisModel) { + return axisModel.get('orient', true) === orient; + } + }); + setParallelAxis(axisModels, 'single'); + } + + function setParallelAxis(axisModels, axisDim) { + var axisModel = axisModels[0]; + + if (!axisModel) { + return; + } + + var axisInfo = new DataZoomAxisInfo(); + axisInfo.add(axisModel.componentIndex); + targetAxisIndexMap.set(axisDim, axisInfo); + needAuto = false; + + if (axisDim === 'x' || axisDim === 'y') { + var gridModel_1 = axisModel.getReferringComponents('grid', SINGLE_REFERRING).models[0]; + gridModel_1 && each(axisModels, function (axModel) { + if (axisModel.componentIndex !== axModel.componentIndex && gridModel_1 === axModel.getReferringComponents('grid', SINGLE_REFERRING).models[0]) { + axisInfo.add(axModel.componentIndex); + } + }); + } + } + + if (needAuto) { + each(DATA_ZOOM_AXIS_DIMENSIONS, function (axisDim) { + if (!needAuto) { + return; + } + + var axisModels = ecModel.findComponents({ + mainType: getAxisMainType(axisDim), + filter: function (axisModel) { + return axisModel.get('type', true) === 'category'; + } + }); + + if (axisModels[0]) { + var axisInfo = new DataZoomAxisInfo(); + axisInfo.add(axisModels[0].componentIndex); + targetAxisIndexMap.set(axisDim, axisInfo); + needAuto = false; + } + }, this); + } + }; + + DataZoomModel.prototype._makeAutoOrientByTargetAxis = function () { + var dim; + this.eachTargetAxis(function (axisDim) { + !dim && (dim = axisDim); + }, this); + return dim === 'y' ? 'vertical' : 'horizontal'; + }; + + DataZoomModel.prototype._setDefaultThrottle = function (inputRawOption) { + if (inputRawOption.hasOwnProperty('throttle')) { + this._autoThrottle = false; + } + + if (this._autoThrottle) { + var globalOption = this.ecModel.option; + this.option.throttle = globalOption.animation && globalOption.animationDurationUpdate > 0 ? 100 : 20; + } + }; + + DataZoomModel.prototype._updateRangeUse = function (inputRawOption) { + var rangePropMode = this._rangePropMode; + var rangeModeInOption = this.get('rangeMode'); + each([['start', 'startValue'], ['end', 'endValue']], function (names, index) { + var percentSpecified = inputRawOption[names[0]] != null; + var valueSpecified = inputRawOption[names[1]] != null; + + if (percentSpecified && !valueSpecified) { + rangePropMode[index] = 'percent'; + } else if (!percentSpecified && valueSpecified) { + rangePropMode[index] = 'value'; + } else if (rangeModeInOption) { + rangePropMode[index] = rangeModeInOption[index]; + } else if (percentSpecified) { + rangePropMode[index] = 'percent'; + } + }); + }; + + DataZoomModel.prototype.noTarget = function () { + return this._noTarget; + }; + + DataZoomModel.prototype.getFirstTargetAxisModel = function () { + var firstAxisModel; + this.eachTargetAxis(function (axisDim, axisIndex) { + if (firstAxisModel == null) { + firstAxisModel = this.ecModel.getComponent(getAxisMainType(axisDim), axisIndex); + } + }, this); + return firstAxisModel; + }; + + DataZoomModel.prototype.eachTargetAxis = function (callback, context) { + this._targetAxisInfoMap.each(function (axisInfo, axisDim) { + each(axisInfo.indexList, function (axisIndex) { + callback.call(context, axisDim, axisIndex); + }); + }); + }; + + DataZoomModel.prototype.getAxisProxy = function (axisDim, axisIndex) { + var axisModel = this.getAxisModel(axisDim, axisIndex); + + if (axisModel) { + return axisModel.__dzAxisProxy; + } + }; + + DataZoomModel.prototype.getAxisModel = function (axisDim, axisIndex) { + if ("development" !== 'production') { + assert(axisDim && axisIndex != null); + } + + var axisInfo = this._targetAxisInfoMap.get(axisDim); + + if (axisInfo && axisInfo.indexMap[axisIndex]) { + return this.ecModel.getComponent(getAxisMainType(axisDim), axisIndex); + } + }; + + DataZoomModel.prototype.setRawRange = function (opt) { + var thisOption = this.option; + var settledOption = this.settledOption; + each([['start', 'startValue'], ['end', 'endValue']], function (names) { + if (opt[names[0]] != null || opt[names[1]] != null) { + thisOption[names[0]] = settledOption[names[0]] = opt[names[0]]; + thisOption[names[1]] = settledOption[names[1]] = opt[names[1]]; + } + }, this); + + this._updateRangeUse(opt); + }; + + DataZoomModel.prototype.setCalculatedRange = function (opt) { + var option = this.option; + each(['start', 'startValue', 'end', 'endValue'], function (name) { + option[name] = opt[name]; + }); + }; + + DataZoomModel.prototype.getPercentRange = function () { + var axisProxy = this.findRepresentativeAxisProxy(); + + if (axisProxy) { + return axisProxy.getDataPercentWindow(); + } + }; + + DataZoomModel.prototype.getValueRange = function (axisDim, axisIndex) { + if (axisDim == null && axisIndex == null) { + var axisProxy = this.findRepresentativeAxisProxy(); + + if (axisProxy) { + return axisProxy.getDataValueWindow(); + } + } else { + return this.getAxisProxy(axisDim, axisIndex).getDataValueWindow(); + } + }; + + DataZoomModel.prototype.findRepresentativeAxisProxy = function (axisModel) { + if (axisModel) { + return axisModel.__dzAxisProxy; + } + + var firstProxy; + + var axisDimList = this._targetAxisInfoMap.keys(); + + for (var i = 0; i < axisDimList.length; i++) { + var axisDim = axisDimList[i]; + + var axisInfo = this._targetAxisInfoMap.get(axisDim); + + for (var j = 0; j < axisInfo.indexList.length; j++) { + var proxy = this.getAxisProxy(axisDim, axisInfo.indexList[j]); + + if (proxy.hostedBy(this)) { + return proxy; + } + + if (!firstProxy) { + firstProxy = proxy; + } + } + } + + return firstProxy; + }; + + DataZoomModel.prototype.getRangePropMode = function () { + return this._rangePropMode.slice(); + }; + + DataZoomModel.prototype.getOrient = function () { + if ("development" !== 'production') { + assert(this._orient); + } + + return this._orient; + }; + + DataZoomModel.type = 'dataZoom'; + DataZoomModel.dependencies = ['xAxis', 'yAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'series', 'toolbox']; + DataZoomModel.defaultOption = { + zlevel: 0, + z: 4, + filterMode: 'filter', + start: 0, + end: 100 + }; + return DataZoomModel; + }(ComponentModel); + + function retrieveRawOption(option) { + var ret = {}; + each(['start', 'end', 'startValue', 'endValue', 'throttle'], function (name) { + option.hasOwnProperty(name) && (ret[name] = option[name]); + }); + return ret; + } + + var SelectDataZoomModel = function (_super) { + __extends(SelectDataZoomModel, _super); + + function SelectDataZoomModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SelectDataZoomModel.type; + return _this; + } + + SelectDataZoomModel.type = 'dataZoom.select'; + return SelectDataZoomModel; + }(DataZoomModel); + + var DataZoomView = function (_super) { + __extends(DataZoomView, _super); + + function DataZoomView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = DataZoomView.type; + return _this; + } + + DataZoomView.prototype.render = function (dataZoomModel, ecModel, api, payload) { + this.dataZoomModel = dataZoomModel; + this.ecModel = ecModel; + this.api = api; + }; + + DataZoomView.type = 'dataZoom'; + return DataZoomView; + }(ComponentView); + + var SelectDataZoomView = function (_super) { + __extends(SelectDataZoomView, _super); + + function SelectDataZoomView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SelectDataZoomView.type; + return _this; + } + + SelectDataZoomView.type = 'dataZoom.select'; + return SelectDataZoomView; + }(DataZoomView); + + var each$9 = each; + var asc$1 = asc; + + var AxisProxy = function () { + function AxisProxy(dimName, axisIndex, dataZoomModel, ecModel) { + this._dimName = dimName; + this._axisIndex = axisIndex; + this.ecModel = ecModel; + this._dataZoomModel = dataZoomModel; + } + + AxisProxy.prototype.hostedBy = function (dataZoomModel) { + return this._dataZoomModel === dataZoomModel; + }; + + AxisProxy.prototype.getDataValueWindow = function () { + return this._valueWindow.slice(); + }; + + AxisProxy.prototype.getDataPercentWindow = function () { + return this._percentWindow.slice(); + }; + + AxisProxy.prototype.getTargetSeriesModels = function () { + var seriesModels = []; + this.ecModel.eachSeries(function (seriesModel) { + if (isCoordSupported(seriesModel)) { + var axisMainType = getAxisMainType(this._dimName); + var axisModel = seriesModel.getReferringComponents(axisMainType, SINGLE_REFERRING).models[0]; + + if (axisModel && this._axisIndex === axisModel.componentIndex) { + seriesModels.push(seriesModel); + } + } + }, this); + return seriesModels; + }; + + AxisProxy.prototype.getAxisModel = function () { + return this.ecModel.getComponent(this._dimName + 'Axis', this._axisIndex); + }; + + AxisProxy.prototype.getMinMaxSpan = function () { + return clone(this._minMaxSpan); + }; + + AxisProxy.prototype.calculateDataWindow = function (opt) { + var dataExtent = this._dataExtent; + var axisModel = this.getAxisModel(); + var scale = axisModel.axis.scale; + + var rangePropMode = this._dataZoomModel.getRangePropMode(); + + var percentExtent = [0, 100]; + var percentWindow = []; + var valueWindow = []; + var hasPropModeValue; + each$9(['start', 'end'], function (prop, idx) { + var boundPercent = opt[prop]; + var boundValue = opt[prop + 'Value']; + + if (rangePropMode[idx] === 'percent') { + boundPercent == null && (boundPercent = percentExtent[idx]); + boundValue = scale.parse(linearMap(boundPercent, percentExtent, dataExtent)); + } else { + hasPropModeValue = true; + boundValue = boundValue == null ? dataExtent[idx] : scale.parse(boundValue); + boundPercent = linearMap(boundValue, dataExtent, percentExtent); + } + + valueWindow[idx] = boundValue; + percentWindow[idx] = boundPercent; + }); + asc$1(valueWindow); + asc$1(percentWindow); + var spans = this._minMaxSpan; + hasPropModeValue ? restrictSet(valueWindow, percentWindow, dataExtent, percentExtent, false) : restrictSet(percentWindow, valueWindow, percentExtent, dataExtent, true); + + function restrictSet(fromWindow, toWindow, fromExtent, toExtent, toValue) { + var suffix = toValue ? 'Span' : 'ValueSpan'; + sliderMove(0, fromWindow, fromExtent, 'all', spans['min' + suffix], spans['max' + suffix]); + + for (var i = 0; i < 2; i++) { + toWindow[i] = linearMap(fromWindow[i], fromExtent, toExtent, true); + toValue && (toWindow[i] = scale.parse(toWindow[i])); + } + } + + return { + valueWindow: valueWindow, + percentWindow: percentWindow + }; + }; + + AxisProxy.prototype.reset = function (dataZoomModel) { + if (dataZoomModel !== this._dataZoomModel) { + return; + } + + var targetSeries = this.getTargetSeriesModels(); + this._dataExtent = calculateDataExtent(this, this._dimName, targetSeries); + + this._updateMinMaxSpan(); + + var dataWindow = this.calculateDataWindow(dataZoomModel.settledOption); + this._valueWindow = dataWindow.valueWindow; + this._percentWindow = dataWindow.percentWindow; + + this._setAxisModel(); + }; + + AxisProxy.prototype.filterData = function (dataZoomModel, api) { + if (dataZoomModel !== this._dataZoomModel) { + return; + } + + var axisDim = this._dimName; + var seriesModels = this.getTargetSeriesModels(); + var filterMode = dataZoomModel.get('filterMode'); + var valueWindow = this._valueWindow; + + if (filterMode === 'none') { + return; + } + + each$9(seriesModels, function (seriesModel) { + var seriesData = seriesModel.getData(); + var dataDims = seriesData.mapDimensionsAll(axisDim); + + if (!dataDims.length) { + return; + } + + if (filterMode === 'weakFilter') { + seriesData.filterSelf(function (dataIndex) { + var leftOut; + var rightOut; + var hasValue; + + for (var i = 0; i < dataDims.length; i++) { + var value = seriesData.get(dataDims[i], dataIndex); + var thisHasValue = !isNaN(value); + var thisLeftOut = value < valueWindow[0]; + var thisRightOut = value > valueWindow[1]; + + if (thisHasValue && !thisLeftOut && !thisRightOut) { + return true; + } + + thisHasValue && (hasValue = true); + thisLeftOut && (leftOut = true); + thisRightOut && (rightOut = true); + } + + return hasValue && leftOut && rightOut; + }); + } else { + each$9(dataDims, function (dim) { + if (filterMode === 'empty') { + seriesModel.setData(seriesData = seriesData.map(dim, function (value) { + return !isInWindow(value) ? NaN : value; + })); + } else { + var range = {}; + range[dim] = valueWindow; + seriesData.selectRange(range); + } + }); + } + + each$9(dataDims, function (dim) { + seriesData.setApproximateExtent(valueWindow, dim); + }); + }); + + function isInWindow(value) { + return value >= valueWindow[0] && value <= valueWindow[1]; + } + }; + + AxisProxy.prototype._updateMinMaxSpan = function () { + var minMaxSpan = this._minMaxSpan = {}; + var dataZoomModel = this._dataZoomModel; + var dataExtent = this._dataExtent; + each$9(['min', 'max'], function (minMax) { + var percentSpan = dataZoomModel.get(minMax + 'Span'); + var valueSpan = dataZoomModel.get(minMax + 'ValueSpan'); + valueSpan != null && (valueSpan = this.getAxisModel().axis.scale.parse(valueSpan)); + + if (valueSpan != null) { + percentSpan = linearMap(dataExtent[0] + valueSpan, dataExtent, [0, 100], true); + } else if (percentSpan != null) { + valueSpan = linearMap(percentSpan, [0, 100], dataExtent, true) - dataExtent[0]; + } + + minMaxSpan[minMax + 'Span'] = percentSpan; + minMaxSpan[minMax + 'ValueSpan'] = valueSpan; + }, this); + }; + + AxisProxy.prototype._setAxisModel = function () { + var axisModel = this.getAxisModel(); + var percentWindow = this._percentWindow; + var valueWindow = this._valueWindow; + + if (!percentWindow) { + return; + } + + var precision = getPixelPrecision(valueWindow, [0, 500]); + precision = Math.min(precision, 20); + var rawExtentInfo = axisModel.axis.scale.rawExtentInfo; + + if (percentWindow[0] !== 0) { + rawExtentInfo.setDeterminedMinMax('min', +valueWindow[0].toFixed(precision)); + } + + if (percentWindow[1] !== 100) { + rawExtentInfo.setDeterminedMinMax('max', +valueWindow[1].toFixed(precision)); + } + + rawExtentInfo.freeze(); + }; + + return AxisProxy; + }(); + + function calculateDataExtent(axisProxy, axisDim, seriesModels) { + var dataExtent = [Infinity, -Infinity]; + each$9(seriesModels, function (seriesModel) { + unionAxisExtentFromData(dataExtent, seriesModel.getData(), axisDim); + }); + var axisModel = axisProxy.getAxisModel(); + var rawExtentResult = ensureScaleRawExtentInfo(axisModel.axis.scale, axisModel, dataExtent).calculate(); + return [rawExtentResult.min, rawExtentResult.max]; + } + + var dataZoomProcessor = { + getTargetSeries: function (ecModel) { + function eachAxisModel(cb) { + ecModel.eachComponent('dataZoom', function (dataZoomModel) { + dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { + var axisModel = ecModel.getComponent(getAxisMainType(axisDim), axisIndex); + cb(axisDim, axisIndex, axisModel, dataZoomModel); + }); + }); + } + + eachAxisModel(function (axisDim, axisIndex, axisModel, dataZoomModel) { + axisModel.__dzAxisProxy = null; + }); + var proxyList = []; + eachAxisModel(function (axisDim, axisIndex, axisModel, dataZoomModel) { + if (!axisModel.__dzAxisProxy) { + axisModel.__dzAxisProxy = new AxisProxy(axisDim, axisIndex, dataZoomModel, ecModel); + proxyList.push(axisModel.__dzAxisProxy); + } + }); + var seriesModelMap = createHashMap(); + each(proxyList, function (axisProxy) { + each(axisProxy.getTargetSeriesModels(), function (seriesModel) { + seriesModelMap.set(seriesModel.uid, seriesModel); + }); + }); + return seriesModelMap; + }, + overallReset: function (ecModel, api) { + ecModel.eachComponent('dataZoom', function (dataZoomModel) { + dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { + dataZoomModel.getAxisProxy(axisDim, axisIndex).reset(dataZoomModel); + }); + dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { + dataZoomModel.getAxisProxy(axisDim, axisIndex).filterData(dataZoomModel, api); + }); + }); + ecModel.eachComponent('dataZoom', function (dataZoomModel) { + var axisProxy = dataZoomModel.findRepresentativeAxisProxy(); + + if (axisProxy) { + var percentRange = axisProxy.getDataPercentWindow(); + var valueRange = axisProxy.getDataValueWindow(); + dataZoomModel.setCalculatedRange({ + start: percentRange[0], + end: percentRange[1], + startValue: valueRange[0], + endValue: valueRange[1] + }); + } + }); + } + }; + + function installDataZoomAction(registers) { + registers.registerAction('dataZoom', function (payload, ecModel) { + var effectedModels = findEffectedDataZooms(ecModel, payload); + each(effectedModels, function (dataZoomModel) { + dataZoomModel.setRawRange({ + start: payload.start, + end: payload.end, + startValue: payload.startValue, + endValue: payload.endValue + }); + }); + }); + } + + var installed = false; + function installCommon(registers) { + if (installed) { + return; + } + + installed = true; + registers.registerProcessor(registers.PRIORITY.PROCESSOR.FILTER, dataZoomProcessor); + installDataZoomAction(registers); + registers.registerSubTypeDefaulter('dataZoom', function () { + return 'slider'; + }); + } + + function install$y(registers) { + registers.registerComponentModel(SelectDataZoomModel); + registers.registerComponentView(SelectDataZoomView); + installCommon(registers); + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var ToolboxFeature = function () { + function ToolboxFeature() {} + + return ToolboxFeature; + }(); + var features = {}; + function registerFeature(name, ctor) { + features[name] = ctor; + } + function getFeature(name) { + return features[name]; + } + + var ToolboxModel = function (_super) { + __extends(ToolboxModel, _super); + + function ToolboxModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ToolboxModel.type; + return _this; + } + + ToolboxModel.prototype.optionUpdated = function () { + _super.prototype.optionUpdated.apply(this, arguments); + + var ecModel = this.ecModel; + each(this.option.feature, function (featureOpt, featureName) { + var Feature = getFeature(featureName); + + if (Feature) { + if (Feature.getDefaultOption) { + Feature.defaultOption = Feature.getDefaultOption(ecModel); + } + + merge(featureOpt, Feature.defaultOption); + } + }); + }; + + ToolboxModel.type = 'toolbox'; + ToolboxModel.layoutMode = { + type: 'box', + ignoreSize: true + }; + ToolboxModel.defaultOption = { + show: true, + 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: true, + iconStyle: { + borderColor: '#666', + color: 'none' + }, + emphasis: { + iconStyle: { + borderColor: '#3E98C5' + } + }, + tooltip: { + show: false + } + }; + return ToolboxModel; + }(ComponentModel); + + function layout$3(group, componentModel, api) { + var boxLayoutParams = componentModel.getBoxLayoutParams(); + var padding = componentModel.get('padding'); + var viewportSize = { + width: api.getWidth(), + height: api.getHeight() + }; + var rect = getLayoutRect(boxLayoutParams, viewportSize, padding); + box(componentModel.get('orient'), group, componentModel.get('itemGap'), rect.width, rect.height); + positionElement(group, boxLayoutParams, viewportSize, padding); + } + function makeBackground(rect, componentModel) { + var padding = normalizeCssArray$1(componentModel.get('padding')); + var style = componentModel.getItemStyle(['color', 'opacity']); + style.fill = componentModel.get('backgroundColor'); + rect = new Rect({ + shape: { + x: rect.x - padding[3], + y: rect.y - padding[0], + width: rect.width + padding[1] + padding[3], + height: rect.height + padding[0] + padding[2], + r: componentModel.get('borderRadius') + }, + style: style, + silent: true, + z2: -1 + }); + return rect; + } + + var ToolboxView = function (_super) { + __extends(ToolboxView, _super); + + function ToolboxView() { + return _super !== null && _super.apply(this, arguments) || this; + } + + ToolboxView.prototype.render = function (toolboxModel, ecModel, api, payload) { + var group = this.group; + group.removeAll(); + + if (!toolboxModel.get('show')) { + return; + } + + var itemSize = +toolboxModel.get('itemSize'); + var featureOpts = toolboxModel.get('feature') || {}; + var features = this._features || (this._features = {}); + var featureNames = []; + each(featureOpts, function (opt, name) { + featureNames.push(name); + }); + new DataDiffer(this._featureNames || [], featureNames).add(processFeature).update(processFeature).remove(curry(processFeature, null)).execute(); + this._featureNames = featureNames; + + function processFeature(newIndex, oldIndex) { + var featureName = featureNames[newIndex]; + var oldName = featureNames[oldIndex]; + var featureOpt = featureOpts[featureName]; + var featureModel = new Model(featureOpt, toolboxModel, toolboxModel.ecModel); + var feature; + + if (payload && payload.newTitle != null && payload.featureName === featureName) { + featureOpt.title = payload.newTitle; + } + + if (featureName && !oldName) { + if (isUserFeatureName(featureName)) { + feature = { + onclick: featureModel.option.onclick, + featureName: featureName + }; + } else { + var Feature = getFeature(featureName); + + if (!Feature) { + return; + } + + feature = new Feature(); + } + + features[featureName] = feature; + } else { + feature = features[oldName]; + + if (!feature) { + return; + } + } + + feature.uid = getUID('toolbox-feature'); + feature.model = featureModel; + feature.ecModel = ecModel; + feature.api = api; + + if (feature instanceof ToolboxFeature) { + if (!featureName && oldName) { + feature.dispose && feature.dispose(ecModel, api); + return; + } + + if (!featureModel.get('show') || feature.unusable) { + feature.remove && feature.remove(ecModel, api); + return; + } + } + + createIconPaths(featureModel, feature, featureName); + + featureModel.setIconStatus = function (iconName, status) { + var option = this.option; + var iconPaths = this.iconPaths; + option.iconStatus = option.iconStatus || {}; + option.iconStatus[iconName] = status; + + if (iconPaths[iconName]) { + (status === 'emphasis' ? enterEmphasis : leaveEmphasis)(iconPaths[iconName]); + } + }; + + if (feature instanceof ToolboxFeature) { + if (feature.render) { + feature.render(featureModel, ecModel, api, payload); + } + } + } + + function createIconPaths(featureModel, feature, featureName) { + var iconStyleModel = featureModel.getModel('iconStyle'); + var iconStyleEmphasisModel = featureModel.getModel(['emphasis', 'iconStyle']); + var icons = feature instanceof ToolboxFeature && feature.getIcons ? feature.getIcons() : featureModel.get('icon'); + var titles = featureModel.get('title') || {}; + var iconsMap; + var titlesMap; + + if (typeof icons === 'string') { + iconsMap = {}; + iconsMap[featureName] = icons; + } else { + iconsMap = icons; + } + + if (typeof titles === 'string') { + titlesMap = {}; + titlesMap[featureName] = titles; + } else { + titlesMap = titles; + } + + var iconPaths = featureModel.iconPaths = {}; + each(iconsMap, function (iconStr, iconName) { + var path = createIcon(iconStr, {}, { + x: -itemSize / 2, + y: -itemSize / 2, + width: itemSize, + height: itemSize + }); + path.setStyle(iconStyleModel.getItemStyle()); + var pathEmphasisState = path.ensureState('emphasis'); + pathEmphasisState.style = iconStyleEmphasisModel.getItemStyle(); + var textContent = new ZRText({ + style: { + text: titlesMap[iconName], + align: iconStyleEmphasisModel.get('textAlign'), + borderRadius: iconStyleEmphasisModel.get('textBorderRadius'), + padding: iconStyleEmphasisModel.get('textPadding'), + fill: null + }, + ignore: true + }); + path.setTextContent(textContent); + var tooltipModel = toolboxModel.getModel('tooltip'); + + if (tooltipModel && tooltipModel.get('show')) { + path.tooltip = extend({ + content: titlesMap[iconName], + formatter: tooltipModel.get('formatter', true) || function () { + return titlesMap[iconName]; + }, + formatterParams: { + componentType: 'toolbox', + name: iconName, + title: titlesMap[iconName], + $vars: ['name', 'title'] + }, + position: tooltipModel.get('position', true) || 'bottom' + }, tooltipModel.option); + } + + path.__title = titlesMap[iconName]; + path.on('mouseover', function () { + var hoverStyle = iconStyleEmphasisModel.getItemStyle(); + var defaultTextPosition = toolboxModel.get('orient') === 'vertical' ? toolboxModel.get('right') == null ? 'right' : 'left' : toolboxModel.get('bottom') == null ? 'bottom' : 'top'; + textContent.setStyle({ + fill: iconStyleEmphasisModel.get('textFill') || hoverStyle.fill || hoverStyle.stroke || '#000', + backgroundColor: iconStyleEmphasisModel.get('textBackgroundColor') + }); + path.setTextConfig({ + position: iconStyleEmphasisModel.get('textPosition') || defaultTextPosition + }); + textContent.ignore = !toolboxModel.get('showTitle'); + enterEmphasis(this); + }).on('mouseout', function () { + if (featureModel.get(['iconStatus', iconName]) !== 'emphasis') { + leaveEmphasis(this); + } + + textContent.hide(); + }); + (featureModel.get(['iconStatus', iconName]) === 'emphasis' ? enterEmphasis : leaveEmphasis)(path); + group.add(path); + path.on('click', bind(feature.onclick, feature, ecModel, api, iconName)); + iconPaths[iconName] = path; + }); + } + + layout$3(group, toolboxModel, api); + group.add(makeBackground(group.getBoundingRect(), toolboxModel)); + group.eachChild(function (icon) { + var titleText = icon.__title; + var emphasisState = icon.ensureState('emphasis'); + var emphasisTextConfig = emphasisState.textConfig || (emphasisState.textConfig = {}); + var textContent = icon.getTextContent(); + var emphasisTextState = textContent && textContent.states.emphasis; + + if (emphasisTextState && !isFunction(emphasisTextState) && titleText) { + var emphasisTextStyle = emphasisTextState.style || (emphasisTextState.style = {}); + var rect = getBoundingRect(titleText, ZRText.makeFont(emphasisTextStyle)); + var offsetX = icon.x + group.x; + var offsetY = icon.y + group.y + itemSize; + var needPutOnTop = false; + + if (offsetY + rect.height > api.getHeight()) { + emphasisTextConfig.position = 'top'; + needPutOnTop = true; + } + + var topOffset = needPutOnTop ? -5 - rect.height : itemSize + 8; + + if (offsetX + rect.width / 2 > api.getWidth()) { + emphasisTextConfig.position = ['100%', topOffset]; + emphasisTextStyle.align = 'right'; + } else if (offsetX - rect.width / 2 < 0) { + emphasisTextConfig.position = [0, topOffset]; + emphasisTextStyle.align = 'left'; + } + } + }); + }; + + ToolboxView.prototype.updateView = function (toolboxModel, ecModel, api, payload) { + each(this._features, function (feature) { + feature instanceof ToolboxFeature && feature.updateView && feature.updateView(feature.model, ecModel, api, payload); + }); + }; + + ToolboxView.prototype.remove = function (ecModel, api) { + each(this._features, function (feature) { + feature instanceof ToolboxFeature && feature.remove && feature.remove(ecModel, api); + }); + this.group.removeAll(); + }; + + ToolboxView.prototype.dispose = function (ecModel, api) { + each(this._features, function (feature) { + feature instanceof ToolboxFeature && feature.dispose && feature.dispose(ecModel, api); + }); + }; + + ToolboxView.type = 'toolbox'; + return ToolboxView; + }(ComponentView); + + function isUserFeatureName(featureName) { + return featureName.indexOf('my') === 0; + } + + var SaveAsImage = function (_super) { + __extends(SaveAsImage, _super); + + function SaveAsImage() { + return _super !== null && _super.apply(this, arguments) || this; + } + + SaveAsImage.prototype.onclick = function (ecModel, api) { + var model = this.model; + var title = model.get('name') || ecModel.get('title.0.text') || 'echarts'; + var isSvg = api.getZr().painter.getType() === 'svg'; + var type = isSvg ? 'svg' : model.get('type', true) || 'png'; + var url = api.getConnectedDataURL({ + type: type, + backgroundColor: model.get('backgroundColor', true) || ecModel.get('backgroundColor') || '#fff', + connectedBackgroundColor: model.get('connectedBackgroundColor'), + excludeComponents: model.get('excludeComponents'), + pixelRatio: model.get('pixelRatio') + }); + + if (typeof MouseEvent === 'function' && (env.browser.newEdge || !env.browser.ie && !env.browser.edge)) { + var $a = document.createElement('a'); + $a.download = title + '.' + type; + $a.target = '_blank'; + $a.href = url; + var evt = new MouseEvent('click', { + view: document.defaultView, + bubbles: true, + cancelable: false + }); + $a.dispatchEvent(evt); + } else { + if (window.navigator.msSaveOrOpenBlob || isSvg) { + var parts = url.split(','); + var base64Encoded = parts[0].indexOf('base64') > -1; + var bstr = isSvg ? decodeURIComponent(parts[1]) : parts[1]; + base64Encoded && (bstr = atob(bstr)); + var filename = title + '.' + type; + + if (window.navigator.msSaveOrOpenBlob) { + var n = bstr.length; + var u8arr = new Uint8Array(n); + + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + + var blob = new Blob([u8arr]); + window.navigator.msSaveOrOpenBlob(blob, filename); + } else { + var frame = document.createElement('iframe'); + document.body.appendChild(frame); + var cw = frame.contentWindow; + var doc = cw.document; + doc.open('image/svg+xml', 'replace'); + doc.write(bstr); + doc.close(); + cw.focus(); + doc.execCommand('SaveAs', true, filename); + document.body.removeChild(frame); + } + } else { + var lang = model.get('lang'); + var html = '' + '' + '' + ''; + var tab = window.open(); + tab.document.write(html); + tab.document.title = title; + } + } + }; + + SaveAsImage.getDefaultOption = function (ecModel) { + var defaultOption = { + show: true, + 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: ecModel.getLocale(['toolbox', 'saveAsImage', 'title']), + type: 'png', + connectedBackgroundColor: '#fff', + name: '', + excludeComponents: ['toolbox'], + pixelRatio: 1, + lang: ecModel.getLocale(['toolbox', 'saveAsImage', 'lang']) + }; + return defaultOption; + }; + + return SaveAsImage; + }(ToolboxFeature); + + SaveAsImage.prototype.unusable = !env.canvasSupported; + + var INNER_STACK_KEYWORD = '__ec_magicType_stack__'; + var radioTypes = [['line', 'bar'], ['stack']]; + + var MagicType = function (_super) { + __extends(MagicType, _super); + + function MagicType() { + return _super !== null && _super.apply(this, arguments) || this; + } + + MagicType.prototype.getIcons = function () { + var model = this.model; + var availableIcons = model.get('icon'); + var icons = {}; + each(model.get('type'), function (type) { + if (availableIcons[type]) { + icons[type] = availableIcons[type]; + } + }); + return icons; + }; + + MagicType.getDefaultOption = function (ecModel) { + var defaultOption = { + show: true, + 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' + }, + title: ecModel.getLocale(['toolbox', 'magicType', 'title']), + option: {}, + seriesIndex: {} + }; + return defaultOption; + }; + + MagicType.prototype.onclick = function (ecModel, api, type) { + var model = this.model; + var seriesIndex = model.get(['seriesIndex', type]); + + if (!seriesOptGenreator[type]) { + return; + } + + var newOption = { + series: [] + }; + + var generateNewSeriesTypes = function (seriesModel) { + var seriesType = seriesModel.subType; + var seriesId = seriesModel.id; + var newSeriesOpt = seriesOptGenreator[type](seriesType, seriesId, seriesModel, model); + + if (newSeriesOpt) { + defaults(newSeriesOpt, seriesModel.option); + newOption.series.push(newSeriesOpt); + } + + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && coordSys.type === 'cartesian2d' && (type === 'line' || type === 'bar')) { + var categoryAxis = coordSys.getAxesByScale('ordinal')[0]; + + if (categoryAxis) { + var axisDim = categoryAxis.dim; + var axisType = axisDim + 'Axis'; + var axisModel = seriesModel.getReferringComponents(axisType, SINGLE_REFERRING).models[0]; + var axisIndex = axisModel.componentIndex; + newOption[axisType] = newOption[axisType] || []; + + for (var i = 0; i <= axisIndex; i++) { + newOption[axisType][axisIndex] = newOption[axisType][axisIndex] || {}; + } + + newOption[axisType][axisIndex].boundaryGap = type === 'bar'; + } + } + }; + + each(radioTypes, function (radio) { + if (indexOf(radio, type) >= 0) { + each(radio, function (item) { + model.setIconStatus(item, 'normal'); + }); + } + }); + model.setIconStatus(type, 'emphasis'); + ecModel.eachComponent({ + mainType: 'series', + query: seriesIndex == null ? null : { + seriesIndex: seriesIndex + } + }, generateNewSeriesTypes); + var newTitle; + + if (type === 'stack') { + newTitle = merge({ + stack: model.option.title.tiled, + tiled: model.option.title.stack + }, model.option.title); + } + + api.dispatchAction({ + type: 'changeMagicType', + currentType: type, + newOption: newOption, + newTitle: newTitle, + featureName: 'magicType' + }); + }; + + return MagicType; + }(ToolboxFeature); + + var seriesOptGenreator = { + 'line': function (seriesType, seriesId, seriesModel, model) { + if (seriesType === 'bar') { + return merge({ + id: seriesId, + type: 'line', + data: seriesModel.get('data'), + stack: seriesModel.get('stack'), + markPoint: seriesModel.get('markPoint'), + markLine: seriesModel.get('markLine') + }, model.get(['option', 'line']) || {}, true); + } + }, + 'bar': function (seriesType, seriesId, seriesModel, model) { + if (seriesType === 'line') { + return merge({ + id: seriesId, + type: 'bar', + data: seriesModel.get('data'), + stack: seriesModel.get('stack'), + markPoint: seriesModel.get('markPoint'), + markLine: seriesModel.get('markLine') + }, model.get(['option', 'bar']) || {}, true); + } + }, + 'stack': function (seriesType, seriesId, seriesModel, model) { + var isStack = seriesModel.get('stack') === INNER_STACK_KEYWORD; + + if (seriesType === 'line' || seriesType === 'bar') { + model.setIconStatus('stack', isStack ? 'normal' : 'emphasis'); + return merge({ + id: seriesId, + stack: isStack ? '' : INNER_STACK_KEYWORD + }, model.get(['option', 'stack']) || {}, true); + } + } + }; + registerAction({ + type: 'changeMagicType', + event: 'magicTypeChanged', + update: 'prepareAndUpdate' + }, function (payload, ecModel) { + ecModel.mergeOption(payload.newOption); + }); + + var BLOCK_SPLITER = new Array(60).join('-'); + var ITEM_SPLITER = '\t'; + + function groupSeries(ecModel) { + var seriesGroupByCategoryAxis = {}; + var otherSeries = []; + var meta = []; + ecModel.eachRawSeries(function (seriesModel) { + var coordSys = seriesModel.coordinateSystem; + + if (coordSys && (coordSys.type === 'cartesian2d' || coordSys.type === 'polar')) { + var baseAxis = coordSys.getBaseAxis(); + + if (baseAxis.type === 'category') { + var key = baseAxis.dim + '_' + baseAxis.index; + + if (!seriesGroupByCategoryAxis[key]) { + seriesGroupByCategoryAxis[key] = { + categoryAxis: baseAxis, + valueAxis: coordSys.getOtherAxis(baseAxis), + series: [] + }; + meta.push({ + axisDim: baseAxis.dim, + axisIndex: baseAxis.index + }); + } + + seriesGroupByCategoryAxis[key].series.push(seriesModel); + } else { + otherSeries.push(seriesModel); + } + } else { + otherSeries.push(seriesModel); + } + }); + return { + seriesGroupByCategoryAxis: seriesGroupByCategoryAxis, + other: otherSeries, + meta: meta + }; + } + + function assembleSeriesWithCategoryAxis(groups) { + var tables = []; + each(groups, function (group, key) { + var categoryAxis = group.categoryAxis; + var valueAxis = group.valueAxis; + var valueAxisDim = valueAxis.dim; + var headers = [' '].concat(map(group.series, function (series) { + return series.name; + })); + var columns = [categoryAxis.model.getCategories()]; + each(group.series, function (series) { + var rawData = series.getRawData(); + columns.push(series.getRawData().mapArray(rawData.mapDimension(valueAxisDim), function (val) { + return val; + })); + }); + var lines = [headers.join(ITEM_SPLITER)]; + + for (var i = 0; i < columns[0].length; i++) { + var items = []; + + for (var j = 0; j < columns.length; j++) { + items.push(columns[j][i]); + } + + lines.push(items.join(ITEM_SPLITER)); + } + + tables.push(lines.join('\n')); + }); + return tables.join('\n\n' + BLOCK_SPLITER + '\n\n'); + } + + function assembleOtherSeries(series) { + return map(series, function (series) { + var data = series.getRawData(); + var lines = [series.name]; + var vals = []; + data.each(data.dimensions, function () { + var argLen = arguments.length; + var dataIndex = arguments[argLen - 1]; + var name = data.getName(dataIndex); + + for (var i = 0; i < argLen - 1; i++) { + vals[i] = arguments[i]; + } + + lines.push((name ? name + ITEM_SPLITER : '') + vals.join(ITEM_SPLITER)); + }); + return lines.join('\n'); + }).join('\n\n' + BLOCK_SPLITER + '\n\n'); + } + + function getContentFromModel(ecModel) { + var result = groupSeries(ecModel); + return { + value: filter([assembleSeriesWithCategoryAxis(result.seriesGroupByCategoryAxis), assembleOtherSeries(result.other)], function (str) { + return !!str.replace(/[\n\t\s]/g, ''); + }).join('\n\n' + BLOCK_SPLITER + '\n\n'), + meta: result.meta + }; + } + + function trim$1(str) { + return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + } + + function isTSVFormat(block) { + var firstLine = block.slice(0, block.indexOf('\n')); + + if (firstLine.indexOf(ITEM_SPLITER) >= 0) { + return true; + } + } + + var itemSplitRegex = new RegExp('[' + ITEM_SPLITER + ']+', 'g'); + + function parseTSVContents(tsv) { + var tsvLines = tsv.split(/\n+/g); + var headers = trim$1(tsvLines.shift()).split(itemSplitRegex); + var categories = []; + var series = map(headers, function (header) { + return { + name: header, + data: [] + }; + }); + + for (var i = 0; i < tsvLines.length; i++) { + var items = trim$1(tsvLines[i]).split(itemSplitRegex); + categories.push(items.shift()); + + for (var j = 0; j < items.length; j++) { + series[j] && (series[j].data[i] = items[j]); + } + } + + return { + series: series, + categories: categories + }; + } + + function parseListContents(str) { + var lines = str.split(/\n+/g); + var seriesName = trim$1(lines.shift()); + var data = []; + + for (var i = 0; i < lines.length; i++) { + var line = trim$1(lines[i]); + + if (!line) { + continue; + } + + var items = line.split(itemSplitRegex); + var name_1 = ''; + var value = void 0; + var hasName = false; + + if (isNaN(items[0])) { + hasName = true; + name_1 = items[0]; + items = items.slice(1); + data[i] = { + name: name_1, + value: [] + }; + value = data[i].value; + } else { + value = data[i] = []; + } + + for (var j = 0; j < items.length; j++) { + value.push(+items[j]); + } + + if (value.length === 1) { + hasName ? data[i].value = value[0] : data[i] = value[0]; + } + } + + return { + name: seriesName, + data: data + }; + } + + function parseContents(str, blockMetaList) { + var blocks = str.split(new RegExp('\n*' + BLOCK_SPLITER + '\n*', 'g')); + var newOption = { + series: [] + }; + each(blocks, function (block, idx) { + if (isTSVFormat(block)) { + var result = parseTSVContents(block); + var blockMeta = blockMetaList[idx]; + var axisKey = blockMeta.axisDim + 'Axis'; + + if (blockMeta) { + newOption[axisKey] = newOption[axisKey] || []; + newOption[axisKey][blockMeta.axisIndex] = { + data: result.categories + }; + newOption.series = newOption.series.concat(result.series); + } + } else { + var result = parseListContents(block); + newOption.series.push(result); + } + }); + return newOption; + } + + var DataView = function (_super) { + __extends(DataView, _super); + + function DataView() { + return _super !== null && _super.apply(this, arguments) || this; + } + + DataView.prototype.onclick = function (ecModel, api) { + var container = api.getDom(); + var model = this.model; + + if (this._dom) { + container.removeChild(this._dom); + } + + var root = document.createElement('div'); + root.style.cssText = 'position:absolute;left:5px;top:5px;bottom:5px;right:5px;'; + root.style.backgroundColor = model.get('backgroundColor') || '#fff'; + var header = document.createElement('h4'); + var lang = model.get('lang') || []; + header.innerHTML = lang[0] || model.get('title'); + header.style.cssText = 'margin: 10px 20px;'; + header.style.color = model.get('textColor'); + var viewMain = document.createElement('div'); + var textarea = document.createElement('textarea'); + viewMain.style.cssText = 'display:block;width:100%;overflow:auto;'; + var optionToContent = model.get('optionToContent'); + var contentToOption = model.get('contentToOption'); + var result = getContentFromModel(ecModel); + + if (typeof optionToContent === 'function') { + var htmlOrDom = optionToContent(api.getOption()); + + if (typeof htmlOrDom === 'string') { + viewMain.innerHTML = htmlOrDom; + } else if (isDom(htmlOrDom)) { + viewMain.appendChild(htmlOrDom); + } + } else { + viewMain.appendChild(textarea); + textarea.readOnly = model.get('readOnly'); + textarea.style.cssText = 'width:100%;height:100%;font-family:monospace;font-size:14px;line-height:1.6rem;'; + textarea.style.color = model.get('textColor'); + textarea.style.borderColor = model.get('textareaBorderColor'); + textarea.style.backgroundColor = model.get('textareaColor'); + textarea.value = result.value; + } + + var blockMetaList = result.meta; + var buttonContainer = document.createElement('div'); + buttonContainer.style.cssText = 'position:absolute;bottom:0;left:0;right:0;'; + var buttonStyle = 'float:right;margin-right:20px;border:none;' + 'cursor:pointer;padding:2px 5px;font-size:12px;border-radius:3px'; + var closeButton = document.createElement('div'); + var refreshButton = document.createElement('div'); + buttonStyle += ';background-color:' + model.get('buttonColor'); + buttonStyle += ';color:' + model.get('buttonTextColor'); + var self = this; + + function close() { + container.removeChild(root); + self._dom = null; + } + + addEventListener(closeButton, 'click', close); + addEventListener(refreshButton, 'click', function () { + if (contentToOption == null && optionToContent != null || contentToOption != null && optionToContent == null) { + if ("development" !== 'production') { + console.warn('It seems you have just provided one of `contentToOption` and `optionToContent` functions but missed the other one. Data change is ignored.'); + } + + close(); + return; + } + + var newOption; + + try { + if (typeof contentToOption === 'function') { + newOption = contentToOption(viewMain, api.getOption()); + } else { + newOption = parseContents(textarea.value, blockMetaList); + } + } catch (e) { + close(); + throw new Error('Data view format error ' + e); + } + + if (newOption) { + api.dispatchAction({ + type: 'changeDataView', + newOption: newOption + }); + } + + close(); + }); + closeButton.innerHTML = lang[1]; + refreshButton.innerHTML = lang[2]; + refreshButton.style.cssText = buttonStyle; + closeButton.style.cssText = buttonStyle; + !model.get('readOnly') && buttonContainer.appendChild(refreshButton); + buttonContainer.appendChild(closeButton); + root.appendChild(header); + root.appendChild(viewMain); + root.appendChild(buttonContainer); + viewMain.style.height = container.clientHeight - 80 + 'px'; + container.appendChild(root); + this._dom = root; + }; + + DataView.prototype.remove = function (ecModel, api) { + this._dom && api.getDom().removeChild(this._dom); + }; + + DataView.prototype.dispose = function (ecModel, api) { + this.remove(ecModel, api); + }; + + DataView.getDefaultOption = function (ecModel) { + var defaultOption = { + show: true, + readOnly: false, + 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: ecModel.getLocale(['toolbox', 'dataView', 'title']), + lang: ecModel.getLocale(['toolbox', 'dataView', 'lang']), + backgroundColor: '#fff', + textColor: '#000', + textareaColor: '#fff', + textareaBorderColor: '#333', + buttonColor: '#c23531', + buttonTextColor: '#fff' + }; + return defaultOption; + }; + + return DataView; + }(ToolboxFeature); + + function tryMergeDataOption(newData, originalData) { + return map(newData, function (newVal, idx) { + var original = originalData && originalData[idx]; + + if (isObject(original) && !isArray(original)) { + var newValIsObject = isObject(newVal) && !isArray(newVal); + + if (!newValIsObject) { + newVal = { + value: newVal + }; + } + + var shouldDeleteName = original.name != null && newVal.name == null; + newVal = defaults(newVal, original); + shouldDeleteName && delete newVal.name; + return newVal; + } else { + return newVal; + } + }); + } + + registerAction({ + type: 'changeDataView', + event: 'dataViewChanged', + update: 'prepareAndUpdate' + }, function (payload, ecModel) { + var newSeriesOptList = []; + each(payload.newOption.series, function (seriesOpt) { + var seriesModel = ecModel.getSeriesByName(seriesOpt.name)[0]; + + if (!seriesModel) { + newSeriesOptList.push(extend({ + type: 'scatter' + }, seriesOpt)); + } else { + var originalData = seriesModel.get('data'); + newSeriesOptList.push({ + name: seriesOpt.name, + data: tryMergeDataOption(seriesOpt.data, originalData) + }); + } + }); + ecModel.mergeOption(defaults({ + series: newSeriesOptList + }, payload.newOption)); + }); + + var each$a = each; + var inner$h = makeInner(); + function push(ecModel, newSnapshot) { + var storedSnapshots = getStoreSnapshots(ecModel); + each$a(newSnapshot, function (batchItem, dataZoomId) { + var i = storedSnapshots.length - 1; + + for (; i >= 0; i--) { + var snapshot = storedSnapshots[i]; + + if (snapshot[dataZoomId]) { + break; + } + } + + if (i < 0) { + var dataZoomModel = ecModel.queryComponents({ + mainType: 'dataZoom', + subType: 'select', + id: dataZoomId + })[0]; + + if (dataZoomModel) { + var percentRange = dataZoomModel.getPercentRange(); + storedSnapshots[0][dataZoomId] = { + dataZoomId: dataZoomId, + start: percentRange[0], + end: percentRange[1] + }; + } + } + }); + storedSnapshots.push(newSnapshot); + } + function pop(ecModel) { + var storedSnapshots = getStoreSnapshots(ecModel); + var head = storedSnapshots[storedSnapshots.length - 1]; + storedSnapshots.length > 1 && storedSnapshots.pop(); + var snapshot = {}; + each$a(head, function (batchItem, dataZoomId) { + for (var i = storedSnapshots.length - 1; i >= 0; i--) { + batchItem = storedSnapshots[i][dataZoomId]; + + if (batchItem) { + snapshot[dataZoomId] = batchItem; + break; + } + } + }); + return snapshot; + } + function clear$1(ecModel) { + inner$h(ecModel).snapshots = null; + } + function count(ecModel) { + return getStoreSnapshots(ecModel).length; + } + + function getStoreSnapshots(ecModel) { + var store = inner$h(ecModel); + + if (!store.snapshots) { + store.snapshots = [{}]; + } + + return store.snapshots; + } + + var RestoreOption = function (_super) { + __extends(RestoreOption, _super); + + function RestoreOption() { + return _super !== null && _super.apply(this, arguments) || this; + } + + RestoreOption.prototype.onclick = function (ecModel, api) { + clear$1(ecModel); + api.dispatchAction({ + type: 'restore', + from: this.uid + }); + }; + + RestoreOption.getDefaultOption = function (ecModel) { + var defaultOption = { + show: true, + 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: ecModel.getLocale(['toolbox', 'restore', 'title']) + }; + return defaultOption; + }; + + return RestoreOption; + }(ToolboxFeature); + + registerAction({ + type: 'restore', + event: 'restore', + update: 'prepareAndUpdate' + }, function (payload, ecModel) { + ecModel.resetOption('recreate'); + }); + + var COORD_CONVERTS = ['dataToPoint', 'pointToData']; + var INCLUDE_FINDER_MAIN_TYPES = ['grid', 'xAxis', 'yAxis', 'geo', 'graph', 'polar', 'radiusAxis', 'angleAxis', 'bmap']; + + var BrushTargetManager = function () { + function BrushTargetManager(finder, ecModel, opt) { + var _this = this; + + this._targetInfoList = []; + var foundCpts = parseFinder$1(ecModel, finder); + each(targetInfoBuilders, function (builder, type) { + if (!opt || !opt.include || indexOf(opt.include, type) >= 0) { + builder(foundCpts, _this._targetInfoList); + } + }); + } + + BrushTargetManager.prototype.setOutputRanges = function (areas, ecModel) { + this.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) { + (area.coordRanges || (area.coordRanges = [])).push(coordRange); + + if (!area.coordRange) { + area.coordRange = coordRange; + var result = coordConvert[area.brushType](0, coordSys, coordRange); + area.__rangeOffset = { + offset: diffProcessor[area.brushType](result.values, area.range, [1, 1]), + xyMinMax: result.xyMinMax + }; + } + }); + return areas; + }; + + BrushTargetManager.prototype.matchOutputRanges = function (areas, ecModel, cb) { + each(areas, function (area) { + var targetInfo = this.findTargetInfo(area, ecModel); + + if (targetInfo && targetInfo !== true) { + each(targetInfo.coordSyses, function (coordSys) { + var result = coordConvert[area.brushType](1, coordSys, area.range); + cb(area, result.values, coordSys, ecModel); + }); + } + }, this); + }; + + BrushTargetManager.prototype.setInputRanges = function (areas, ecModel) { + each(areas, function (area) { + var targetInfo = this.findTargetInfo(area, ecModel); + + if ("development" !== 'production') { + assert(!targetInfo || targetInfo === true || area.coordRange, 'coordRange must be specified when coord index specified.'); + assert(!targetInfo || targetInfo !== true || area.range, 'range must be specified in global brush.'); + } + + area.range = area.range || []; + + if (targetInfo && targetInfo !== true) { + area.panelId = targetInfo.panelId; + var result = coordConvert[area.brushType](0, targetInfo.coordSys, area.coordRange); + var rangeOffset = area.__rangeOffset; + area.range = rangeOffset ? diffProcessor[area.brushType](result.values, rangeOffset.offset, getScales(result.xyMinMax, rangeOffset.xyMinMax)) : result.values; + } + }, this); + }; + + BrushTargetManager.prototype.makePanelOpts = function (api, getDefaultBrushType) { + return map(this._targetInfoList, function (targetInfo) { + var rect = targetInfo.getPanelRect(); + return { + panelId: targetInfo.panelId, + defaultBrushType: getDefaultBrushType ? getDefaultBrushType(targetInfo) : null, + clipPath: makeRectPanelClipPath(rect), + isTargetByCursor: makeRectIsTargetByCursor(rect, api, targetInfo.coordSysModel), + getLinearBrushOtherExtent: makeLinearBrushOtherExtent(rect) + }; + }); + }; + + BrushTargetManager.prototype.controlSeries = function (area, seriesModel, ecModel) { + var targetInfo = this.findTargetInfo(area, ecModel); + return targetInfo === true || targetInfo && indexOf(targetInfo.coordSyses, seriesModel.coordinateSystem) >= 0; + }; + + BrushTargetManager.prototype.findTargetInfo = function (area, ecModel) { + var targetInfoList = this._targetInfoList; + var foundCpts = parseFinder$1(ecModel, area); + + for (var i = 0; i < targetInfoList.length; i++) { + var targetInfo = targetInfoList[i]; + var areaPanelId = area.panelId; + + if (areaPanelId) { + if (targetInfo.panelId === areaPanelId) { + return targetInfo; + } + } else { + for (var j = 0; j < targetInfoMatchers.length; j++) { + if (targetInfoMatchers[j](foundCpts, targetInfo)) { + return targetInfo; + } + } + } + } + + return true; + }; + + return BrushTargetManager; + }(); + + function formatMinMax(minMax) { + minMax[0] > minMax[1] && minMax.reverse(); + return minMax; + } + + function parseFinder$1(ecModel, finder) { + return parseFinder(ecModel, finder, { + includeMainTypes: INCLUDE_FINDER_MAIN_TYPES + }); + } + + var targetInfoBuilders = { + grid: function (foundCpts, targetInfoList) { + var xAxisModels = foundCpts.xAxisModels; + var yAxisModels = foundCpts.yAxisModels; + var gridModels = foundCpts.gridModels; + var gridModelMap = createHashMap(); + var xAxesHas = {}; + var yAxesHas = {}; + + if (!xAxisModels && !yAxisModels && !gridModels) { + return; + } + + each(xAxisModels, function (axisModel) { + var gridModel = axisModel.axis.grid.model; + gridModelMap.set(gridModel.id, gridModel); + xAxesHas[gridModel.id] = true; + }); + each(yAxisModels, function (axisModel) { + var gridModel = axisModel.axis.grid.model; + gridModelMap.set(gridModel.id, gridModel); + yAxesHas[gridModel.id] = true; + }); + each(gridModels, function (gridModel) { + gridModelMap.set(gridModel.id, gridModel); + xAxesHas[gridModel.id] = true; + yAxesHas[gridModel.id] = true; + }); + gridModelMap.each(function (gridModel) { + var grid = gridModel.coordinateSystem; + var cartesians = []; + each(grid.getCartesians(), function (cartesian, index) { + if (indexOf(xAxisModels, cartesian.getAxis('x').model) >= 0 || indexOf(yAxisModels, cartesian.getAxis('y').model) >= 0) { + cartesians.push(cartesian); + } + }); + targetInfoList.push({ + panelId: 'grid--' + gridModel.id, + gridModel: gridModel, + coordSysModel: gridModel, + coordSys: cartesians[0], + coordSyses: cartesians, + getPanelRect: panelRectBuilders.grid, + xAxisDeclared: xAxesHas[gridModel.id], + yAxisDeclared: yAxesHas[gridModel.id] + }); + }); + }, + geo: function (foundCpts, targetInfoList) { + each(foundCpts.geoModels, function (geoModel) { + var coordSys = geoModel.coordinateSystem; + targetInfoList.push({ + panelId: 'geo--' + geoModel.id, + geoModel: geoModel, + coordSysModel: geoModel, + coordSys: coordSys, + coordSyses: [coordSys], + getPanelRect: panelRectBuilders.geo + }); + }); + } + }; + var targetInfoMatchers = [function (foundCpts, targetInfo) { + var xAxisModel = foundCpts.xAxisModel; + var yAxisModel = foundCpts.yAxisModel; + var gridModel = foundCpts.gridModel; + !gridModel && xAxisModel && (gridModel = xAxisModel.axis.grid.model); + !gridModel && yAxisModel && (gridModel = yAxisModel.axis.grid.model); + return gridModel && gridModel === targetInfo.gridModel; + }, function (foundCpts, targetInfo) { + var geoModel = foundCpts.geoModel; + return geoModel && geoModel === targetInfo.geoModel; + }]; + var panelRectBuilders = { + grid: function () { + return this.coordSys.master.getRect().clone(); + }, + geo: function () { + var coordSys = this.coordSys; + var rect = coordSys.getBoundingRect().clone(); + rect.applyTransform(getTransform(coordSys)); + return rect; + } + }; + var coordConvert = { + lineX: curry(axisConvert, 0), + lineY: curry(axisConvert, 1), + rect: function (to, coordSys, rangeOrCoordRange) { + var xminymin = coordSys[COORD_CONVERTS[to]]([rangeOrCoordRange[0][0], rangeOrCoordRange[1][0]]); + var xmaxymax = coordSys[COORD_CONVERTS[to]]([rangeOrCoordRange[0][1], rangeOrCoordRange[1][1]]); + var values = [formatMinMax([xminymin[0], xmaxymax[0]]), formatMinMax([xminymin[1], xmaxymax[1]])]; + return { + values: values, + xyMinMax: values + }; + }, + polygon: function (to, coordSys, rangeOrCoordRange) { + var xyMinMax = [[Infinity, -Infinity], [Infinity, -Infinity]]; + var values = map(rangeOrCoordRange, function (item) { + var p = coordSys[COORD_CONVERTS[to]](item); + xyMinMax[0][0] = Math.min(xyMinMax[0][0], p[0]); + xyMinMax[1][0] = Math.min(xyMinMax[1][0], p[1]); + xyMinMax[0][1] = Math.max(xyMinMax[0][1], p[0]); + xyMinMax[1][1] = Math.max(xyMinMax[1][1], p[1]); + return p; + }); + return { + values: values, + xyMinMax: xyMinMax + }; + } + }; + + function axisConvert(axisNameIndex, to, coordSys, rangeOrCoordRange) { + if ("development" !== 'production') { + assert(coordSys.type === 'cartesian2d', 'lineX/lineY brush is available only in cartesian2d.'); + } + + var axis = coordSys.getAxis(['x', 'y'][axisNameIndex]); + var values = formatMinMax(map([0, 1], function (i) { + return to ? axis.coordToData(axis.toLocalCoord(rangeOrCoordRange[i])) : axis.toGlobalCoord(axis.dataToCoord(rangeOrCoordRange[i])); + })); + var xyMinMax = []; + xyMinMax[axisNameIndex] = values; + xyMinMax[1 - axisNameIndex] = [NaN, NaN]; + return { + values: values, + xyMinMax: xyMinMax + }; + } + + var diffProcessor = { + lineX: curry(axisDiffProcessor, 0), + lineY: curry(axisDiffProcessor, 1), + rect: function (values, refer, scales) { + return [[values[0][0] - scales[0] * refer[0][0], values[0][1] - scales[0] * refer[0][1]], [values[1][0] - scales[1] * refer[1][0], values[1][1] - scales[1] * refer[1][1]]]; + }, + polygon: function (values, refer, scales) { + return map(values, function (item, idx) { + return [item[0] - scales[0] * refer[idx][0], item[1] - scales[1] * refer[idx][1]]; + }); + } + }; + + function axisDiffProcessor(axisNameIndex, values, refer, scales) { + return [values[0] - scales[axisNameIndex] * refer[0], values[1] - scales[axisNameIndex] * refer[1]]; + } + + function getScales(xyMinMaxCurr, xyMinMaxOrigin) { + var sizeCurr = getSize(xyMinMaxCurr); + var sizeOrigin = getSize(xyMinMaxOrigin); + var scales = [sizeCurr[0] / sizeOrigin[0], sizeCurr[1] / sizeOrigin[1]]; + isNaN(scales[0]) && (scales[0] = 1); + isNaN(scales[1]) && (scales[1] = 1); + return scales; + } + + function getSize(xyMinMax) { + return xyMinMax ? [xyMinMax[0][1] - xyMinMax[0][0], xyMinMax[1][1] - xyMinMax[1][0]] : [NaN, NaN]; + } + + var each$b = each; + var DATA_ZOOM_ID_BASE = makeInternalComponentId('toolbox-dataZoom_'); + + var DataZoomFeature = function (_super) { + __extends(DataZoomFeature, _super); + + function DataZoomFeature() { + return _super !== null && _super.apply(this, arguments) || this; + } + + DataZoomFeature.prototype.render = function (featureModel, ecModel, api, payload) { + if (!this.brushController) { + this.brushController = new BrushController(api.getZr()); + this.brushController.on('brush', bind(this._onBrush, this)).mount(); + } + + updateZoomBtnStatus(featureModel, ecModel, this, payload, api); + updateBackBtnStatus(featureModel, ecModel); + }; + + DataZoomFeature.prototype.onclick = function (ecModel, api, type) { + handlers$1[type].call(this); + }; + + DataZoomFeature.prototype.remove = function (ecModel, api) { + this.brushController.unmount(); + }; + + DataZoomFeature.prototype.dispose = function (ecModel, api) { + this.brushController.dispose(); + }; + + DataZoomFeature.prototype._onBrush = function (eventParam) { + var areas = eventParam.areas; + + if (!eventParam.isEnd || !areas.length) { + return; + } + + var snapshot = {}; + var ecModel = this.ecModel; + this.brushController.updateCovers([]); + var brushTargetManager = new BrushTargetManager(makeAxisFinder(this.model), ecModel, { + include: ['grid'] + }); + brushTargetManager.matchOutputRanges(areas, ecModel, function (area, coordRange, coordSys) { + if (coordSys.type !== 'cartesian2d') { + return; + } + + var brushType = area.brushType; + + if (brushType === 'rect') { + setBatch('x', coordSys, coordRange[0]); + setBatch('y', coordSys, coordRange[1]); + } else { + setBatch({ + lineX: 'x', + lineY: 'y' + }[brushType], coordSys, coordRange); + } + }); + push(ecModel, snapshot); + + this._dispatchZoomAction(snapshot); + + function setBatch(dimName, coordSys, minMax) { + var axis = coordSys.getAxis(dimName); + var axisModel = axis.model; + var dataZoomModel = findDataZoom(dimName, axisModel, ecModel); + var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy(axisModel).getMinMaxSpan(); + + if (minMaxSpan.minValueSpan != null || minMaxSpan.maxValueSpan != null) { + minMax = sliderMove(0, minMax.slice(), axis.scale.getExtent(), 0, minMaxSpan.minValueSpan, minMaxSpan.maxValueSpan); + } + + dataZoomModel && (snapshot[dataZoomModel.id] = { + dataZoomId: dataZoomModel.id, + startValue: minMax[0], + endValue: minMax[1] + }); + } + + function findDataZoom(dimName, axisModel, ecModel) { + var found; + ecModel.eachComponent({ + mainType: 'dataZoom', + subType: 'select' + }, function (dzModel) { + var has = dzModel.getAxisModel(dimName, axisModel.componentIndex); + has && (found = dzModel); + }); + return found; + } + }; + + DataZoomFeature.prototype._dispatchZoomAction = function (snapshot) { + var batch = []; + each$b(snapshot, function (batchItem, dataZoomId) { + batch.push(clone(batchItem)); + }); + batch.length && this.api.dispatchAction({ + type: 'dataZoom', + from: this.uid, + batch: batch + }); + }; + + DataZoomFeature.getDefaultOption = function (ecModel) { + var defaultOption = { + show: true, + filterMode: 'filter', + 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: ecModel.getLocale(['toolbox', 'dataZoom', 'title']), + brushStyle: { + borderWidth: 0, + color: 'rgba(210,219,238,0.2)' + } + }; + return defaultOption; + }; + + return DataZoomFeature; + }(ToolboxFeature); + + var handlers$1 = { + zoom: function () { + var nextActive = !this.isZoomActive; + this.api.dispatchAction({ + type: 'takeGlobalCursor', + key: 'dataZoomSelect', + dataZoomSelectActive: nextActive + }); + }, + back: function () { + this._dispatchZoomAction(pop(this.ecModel)); + } + }; + + function makeAxisFinder(dzFeatureModel) { + var setting = { + xAxisIndex: dzFeatureModel.get('xAxisIndex', true), + yAxisIndex: dzFeatureModel.get('yAxisIndex', true), + xAxisId: dzFeatureModel.get('xAxisId', true), + yAxisId: dzFeatureModel.get('yAxisId', true) + }; + + if (setting.xAxisIndex == null && setting.xAxisId == null) { + setting.xAxisIndex = 'all'; + } + + if (setting.yAxisIndex == null && setting.yAxisId == null) { + setting.yAxisIndex = 'all'; + } + + return setting; + } + + function updateBackBtnStatus(featureModel, ecModel) { + featureModel.setIconStatus('back', count(ecModel) > 1 ? 'emphasis' : 'normal'); + } + + function updateZoomBtnStatus(featureModel, ecModel, view, payload, api) { + var zoomActive = view.isZoomActive; + + if (payload && payload.type === 'takeGlobalCursor') { + zoomActive = payload.key === 'dataZoomSelect' ? payload.dataZoomSelectActive : false; + } + + view.isZoomActive = zoomActive; + featureModel.setIconStatus('zoom', zoomActive ? 'emphasis' : 'normal'); + var brushTargetManager = new BrushTargetManager(makeAxisFinder(featureModel), ecModel, { + include: ['grid'] + }); + var panels = brushTargetManager.makePanelOpts(api, function (targetInfo) { + return targetInfo.xAxisDeclared && !targetInfo.yAxisDeclared ? 'lineX' : !targetInfo.xAxisDeclared && targetInfo.yAxisDeclared ? 'lineY' : 'rect'; + }); + view.brushController.setPanels(panels).enableBrush(zoomActive && panels.length ? { + brushType: 'auto', + brushStyle: featureModel.getModel('brushStyle').getItemStyle() + } : false); + } + + registerInternalOptionCreator('dataZoom', function (ecModel) { + var toolboxModel = ecModel.getComponent('toolbox', 0); + + if (!toolboxModel) { + return; + } + + var dzFeatureModel = toolboxModel.getModel(['feature', 'dataZoom']); + var dzOptions = []; + var finder = makeAxisFinder(dzFeatureModel); + var finderResult = parseFinder(ecModel, finder); + each$b(finderResult.xAxisModels, function (axisModel) { + return buildInternalOptions(axisModel, 'xAxis', 'xAxisIndex'); + }); + each$b(finderResult.yAxisModels, function (axisModel) { + return buildInternalOptions(axisModel, 'yAxis', 'yAxisIndex'); + }); + + function buildInternalOptions(axisModel, axisMainType, axisIndexPropName) { + var axisIndex = axisModel.componentIndex; + var newOpt = { + type: 'select', + $fromToolbox: true, + filterMode: dzFeatureModel.get('filterMode', true) || 'filter', + id: DATA_ZOOM_ID_BASE + axisMainType + axisIndex + }; + newOpt[axisIndexPropName] = axisIndex; + dzOptions.push(newOpt); + } + + return dzOptions; + }); + + function install$z(registers) { + registers.registerComponentModel(ToolboxModel); + registers.registerComponentView(ToolboxView); + registerFeature('saveAsImage', SaveAsImage); + registerFeature('magicType', MagicType); + registerFeature('dataView', DataView); + registerFeature('dataZoom', DataZoomFeature); + registerFeature('restore', RestoreOption); + use(install$y); + } + + var TooltipModel = function (_super) { + __extends(TooltipModel, _super); + + function TooltipModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TooltipModel.type; + return _this; + } + + TooltipModel.type = 'tooltip'; + TooltipModel.dependencies = ['axisPointer']; + TooltipModel.defaultOption = { + zlevel: 0, + z: 60, + show: true, + showContent: true, + trigger: 'item', + triggerOn: 'mousemove|click', + alwaysShowContent: false, + displayMode: 'single', + renderMode: 'auto', + confine: null, + showDelay: 0, + hideDelay: 100, + transitionDuration: 0.4, + enterable: false, + backgroundColor: '#fff', + shadowBlur: 10, + shadowColor: 'rgba(0, 0, 0, .2)', + shadowOffsetX: 1, + shadowOffsetY: 2, + borderRadius: 4, + borderWidth: 1, + padding: null, + extraCssText: '', + axisPointer: { + type: 'line', + axis: 'auto', + animation: 'auto', + animationDurationUpdate: 200, + animationEasingUpdate: 'exponentialOut', + crossStyle: { + color: '#999', + width: 1, + type: 'dashed', + textStyle: {} + } + }, + textStyle: { + color: '#666', + fontSize: 14 + } + }; + return TooltipModel; + }(ComponentModel); + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function shouldTooltipConfine(tooltipModel) { + var confineOption = tooltipModel.get('confine'); + return confineOption != null ? !!confineOption : tooltipModel.get('renderMode') === 'richText'; + } + + var vendors = ['-ms-', '-moz-', '-o-', '-webkit-', '']; + var gCssText = 'position:absolute;display:block;border-style:solid;white-space:nowrap;z-index:9999999;'; + + function mirrorPos(pos) { + pos = pos === 'left' ? 'right' : pos === 'right' ? 'left' : pos === 'top' ? 'bottom' : 'top'; + return pos; + } + + function assembleArrow(backgroundColor, borderColor, arrowPosition) { + if (!isString(arrowPosition) || arrowPosition === 'inside') { + return ''; + } + + borderColor = convertToColorString(borderColor); + var arrowPos = mirrorPos(arrowPosition); + var positionStyle = ''; + var transformStyle = ''; + + if (indexOf(['left', 'right'], arrowPos) > -1) { + positionStyle = arrowPos + ":-6px;top:50%;"; + transformStyle = "translateY(-50%) rotate(" + (arrowPos === 'left' ? -225 : -45) + "deg)"; + } else { + positionStyle = arrowPos + ":-6px;left:50%;"; + transformStyle = "translateX(-50%) rotate(" + (arrowPos === 'top' ? 225 : 45) + "deg)"; + } + + transformStyle = map(vendors, function (vendorPrefix) { + return vendorPrefix + 'transform:' + transformStyle; + }).join(';'); + var styleCss = ['position:absolute;width:10px;height:10px;', "" + positionStyle + transformStyle + ";", "border-bottom: " + borderColor + " solid 1px;", "border-right: " + borderColor + " solid 1px;", "background-color: " + backgroundColor + ";", 'box-shadow: 8px 8px 16px -3px #000;']; + return "
                "; + } + + function assembleTransition(duration, onlyFade) { + var transitionCurve = 'cubic-bezier(0.23, 1, 0.32, 1)'; + var transitionText = 'opacity ' + duration / 2 + 's ' + transitionCurve + ',' + 'visibility ' + duration / 2 + 's ' + transitionCurve; + + if (!onlyFade) { + transitionText += ',left ' + duration + 's ' + transitionCurve + ',top ' + duration + 's ' + transitionCurve; + } + + return map(vendors, function (vendorPrefix) { + return vendorPrefix + 'transition:' + transitionText; + }).join(';'); + } + + function assembleFont(textStyleModel) { + var cssText = []; + var fontSize = textStyleModel.get('fontSize'); + var color = textStyleModel.getTextColor(); + color && cssText.push('color:' + color); + cssText.push('font:' + textStyleModel.getFont()); + fontSize && cssText.push('line-height:' + Math.round(fontSize * 3 / 2) + 'px'); + var shadowColor = textStyleModel.get('textShadowColor'); + var shadowBlur = textStyleModel.get('textShadowBlur') || 0; + var shadowOffsetX = textStyleModel.get('textShadowOffsetX') || 0; + var shadowOffsetY = textStyleModel.get('textShadowOffsetY') || 0; + shadowColor && shadowBlur && cssText.push('text-shadow:' + shadowOffsetX + 'px ' + shadowOffsetY + 'px ' + shadowBlur + 'px ' + shadowColor); + each(['decoration', 'align'], function (name) { + var val = textStyleModel.get(name); + val && cssText.push('text-' + name + ':' + val); + }); + return cssText.join(';'); + } + + function assembleCssText(tooltipModel, enableTransition, onlyFade) { + var cssText = []; + var transitionDuration = tooltipModel.get('transitionDuration'); + var backgroundColor = tooltipModel.get('backgroundColor'); + var shadowBlur = tooltipModel.get('shadowBlur'); + var shadowColor = tooltipModel.get('shadowColor'); + var shadowOffsetX = tooltipModel.get('shadowOffsetX'); + var shadowOffsetY = tooltipModel.get('shadowOffsetY'); + var textStyleModel = tooltipModel.getModel('textStyle'); + var padding = getPaddingFromTooltipModel(tooltipModel, 'html'); + var boxShadow = shadowOffsetX + "px " + shadowOffsetY + "px " + shadowBlur + "px " + shadowColor; + cssText.push('box-shadow:' + boxShadow); + enableTransition && transitionDuration && cssText.push(assembleTransition(transitionDuration, onlyFade)); + + if (backgroundColor) { + if (env.canvasSupported) { + cssText.push('background-Color:' + backgroundColor); + } else { + cssText.push('background-Color:#' + toHex(backgroundColor)); + cssText.push('filter:alpha(opacity=70)'); + } + } + + each(['width', 'color', 'radius'], function (name) { + var borderName = 'border-' + name; + var camelCase = toCamelCase(borderName); + var val = tooltipModel.get(camelCase); + val != null && cssText.push(borderName + ':' + val + (name === 'color' ? '' : 'px')); + }); + cssText.push(assembleFont(textStyleModel)); + + if (padding != null) { + cssText.push('padding:' + normalizeCssArray$1(padding).join('px ') + 'px'); + } + + return cssText.join(';') + ';'; + } + + function makeStyleCoord(out, zr, appendToBody, zrX, zrY) { + var zrPainter = zr && zr.painter; + + if (appendToBody) { + var zrViewportRoot = zrPainter && zrPainter.getViewportRoot(); + + if (zrViewportRoot) { + transformLocalCoord(out, zrViewportRoot, document.body, zrX, zrY); + } + } else { + out[0] = zrX; + out[1] = zrY; + var viewportRootOffset = zrPainter && zrPainter.getViewportRootOffset(); + + if (viewportRootOffset) { + out[0] += viewportRootOffset.offsetLeft; + out[1] += viewportRootOffset.offsetTop; + } + } + + out[2] = out[0] / zr.getWidth(); + out[3] = out[1] / zr.getHeight(); + } + + var TooltipHTMLContent = function () { + function TooltipHTMLContent(container, api, opt) { + this._show = false; + this._styleCoord = [0, 0, 0, 0]; + this._enterable = true; + this._firstShow = true; + this._longHide = true; + + if (env.wxa) { + return null; + } + + var el = document.createElement('div'); + el.domBelongToZr = true; + this.el = el; + var zr = this._zr = api.getZr(); + var appendToBody = this._appendToBody = opt && opt.appendToBody; + makeStyleCoord(this._styleCoord, zr, appendToBody, api.getWidth() / 2, api.getHeight() / 2); + + if (appendToBody) { + document.body.appendChild(el); + } else { + container.appendChild(el); + } + + this._container = container; + var self = this; + + el.onmouseenter = function () { + if (self._enterable) { + clearTimeout(self._hideTimeout); + self._show = true; + } + + self._inContent = true; + }; + + el.onmousemove = function (e) { + e = e || window.event; + + if (!self._enterable) { + var handler = zr.handler; + var zrViewportRoot = zr.painter.getViewportRoot(); + normalizeEvent(zrViewportRoot, e, true); + handler.dispatch('mousemove', e); + } + }; + + el.onmouseleave = function () { + self._inContent = false; + + if (self._enterable) { + if (self._show) { + self.hideLater(self._hideDelay); + } + } + }; + } + + TooltipHTMLContent.prototype.update = function (tooltipModel) { + var container = this._container; + var stl = container.currentStyle || document.defaultView.getComputedStyle(container); + var domStyle = container.style; + + if (domStyle.position !== 'absolute' && stl.position !== 'absolute') { + domStyle.position = 'relative'; + } + + var alwaysShowContent = tooltipModel.get('alwaysShowContent'); + alwaysShowContent && this._moveIfResized(); + this.el.className = tooltipModel.get('className') || ''; + }; + + TooltipHTMLContent.prototype.show = function (tooltipModel, nearPointColor) { + clearTimeout(this._hideTimeout); + clearTimeout(this._longHideTimeout); + var el = this.el; + var styleCoord = this._styleCoord; + var offset = el.offsetHeight / 2; + nearPointColor = convertToColorString(nearPointColor); + el.style.cssText = gCssText + assembleCssText(tooltipModel, !this._firstShow, this._longHide) + ';left:' + styleCoord[0] + 'px;top:' + (styleCoord[1] - offset) + 'px;' + ("border-color: " + nearPointColor + ";") + (tooltipModel.get('extraCssText') || ''); + el.style.display = el.innerHTML ? 'block' : 'none'; + el.style.pointerEvents = this._enterable ? 'auto' : 'none'; + this._show = true; + this._firstShow = false; + this._longHide = false; + }; + + TooltipHTMLContent.prototype.setContent = function (content, markers, tooltipModel, borderColor, arrowPosition) { + if (content == null) { + return; + } + + var el = this.el; + + if (isString(arrowPosition) && tooltipModel.get('trigger') === 'item' && !shouldTooltipConfine(tooltipModel)) { + content += assembleArrow(tooltipModel.get('backgroundColor'), borderColor, arrowPosition); + } + + if (isString(content)) { + el.innerHTML = content; + } else if (content) { + el.innerHTML = ''; + + if (!isArray(content)) { + content = [content]; + } + + for (var i = 0; i < content.length; i++) { + if (isDom(content[i]) && content[i].parentNode !== el) { + el.appendChild(content[i]); + } + } + } + }; + + TooltipHTMLContent.prototype.setEnterable = function (enterable) { + this._enterable = enterable; + }; + + TooltipHTMLContent.prototype.getSize = function () { + var el = this.el; + return [el.clientWidth, el.clientHeight]; + }; + + TooltipHTMLContent.prototype.moveTo = function (zrX, zrY) { + var styleCoord = this._styleCoord; + makeStyleCoord(styleCoord, this._zr, this._appendToBody, zrX, zrY); + + if (styleCoord[0] != null && styleCoord[1] != null) { + var style = this.el.style; + style.left = styleCoord[0].toFixed(0) + 'px'; + style.top = styleCoord[1].toFixed(0) + 'px'; + } + }; + + TooltipHTMLContent.prototype._moveIfResized = function () { + var ratioX = this._styleCoord[2]; + var ratioY = this._styleCoord[3]; + this.moveTo(ratioX * this._zr.getWidth(), ratioY * this._zr.getHeight()); + }; + + TooltipHTMLContent.prototype.hide = function () { + var _this = this; + + this.el.style.visibility = 'hidden'; + this.el.style.opacity = '0'; + this._show = false; + this._longHideTimeout = setTimeout(function () { + return _this._longHide = true; + }, 500); + }; + + TooltipHTMLContent.prototype.hideLater = function (time) { + if (this._show && !(this._inContent && this._enterable)) { + if (time) { + this._hideDelay = time; + this._show = false; + this._hideTimeout = setTimeout(bind(this.hide, this), time); + } else { + this.hide(); + } + } + }; + + TooltipHTMLContent.prototype.isShow = function () { + return this._show; + }; + + TooltipHTMLContent.prototype.dispose = function () { + this.el.parentNode.removeChild(this.el); + }; + + TooltipHTMLContent.prototype.getOuterSize = function () { + var width = this.el.clientWidth; + var height = this.el.clientHeight; + + if (document.defaultView && document.defaultView.getComputedStyle) { + var stl = document.defaultView.getComputedStyle(this.el); + + if (stl) { + width += parseInt(stl.borderLeftWidth, 10) + parseInt(stl.borderRightWidth, 10); + height += parseInt(stl.borderTopWidth, 10) + parseInt(stl.borderBottomWidth, 10); + } + } + + return { + width: width, + height: height + }; + }; + + return TooltipHTMLContent; + }(); + + var TooltipRichContent = function () { + function TooltipRichContent(api) { + this._show = false; + this._styleCoord = [0, 0, 0, 0]; + this._enterable = true; + this._zr = api.getZr(); + makeStyleCoord$1(this._styleCoord, this._zr, api.getWidth() / 2, api.getHeight() / 2); + } + + TooltipRichContent.prototype.update = function (tooltipModel) { + var alwaysShowContent = tooltipModel.get('alwaysShowContent'); + alwaysShowContent && this._moveIfResized(); + }; + + TooltipRichContent.prototype.show = function () { + if (this._hideTimeout) { + clearTimeout(this._hideTimeout); + } + + this.el.show(); + this._show = true; + }; + + TooltipRichContent.prototype.setContent = function (content, markupStyleCreator, tooltipModel, borderColor, arrowPosition) { + if (isObject(content)) { + throwError("development" !== 'production' ? 'Passing DOM nodes as content is not supported in richText tooltip!' : ''); + } + + if (this.el) { + this._zr.remove(this.el); + } + + var textStyleModel = tooltipModel.getModel('textStyle'); + this.el = new ZRText({ + style: { + rich: markupStyleCreator.richTextStyles, + text: content, + lineHeight: 22, + backgroundColor: tooltipModel.get('backgroundColor'), + borderRadius: tooltipModel.get('borderRadius'), + borderWidth: 1, + borderColor: borderColor, + shadowColor: tooltipModel.get('shadowColor'), + shadowBlur: tooltipModel.get('shadowBlur'), + shadowOffsetX: tooltipModel.get('shadowOffsetX'), + shadowOffsetY: tooltipModel.get('shadowOffsetY'), + textShadowColor: textStyleModel.get('textShadowColor'), + textShadowBlur: textStyleModel.get('textShadowBlur') || 0, + textShadowOffsetX: textStyleModel.get('textShadowOffsetX') || 0, + textShadowOffsetY: textStyleModel.get('textShadowOffsetY') || 0, + fill: tooltipModel.get(['textStyle', 'color']), + padding: getPaddingFromTooltipModel(tooltipModel, 'richText'), + verticalAlign: 'top', + align: 'left' + }, + z: tooltipModel.get('z') + }); + + this._zr.add(this.el); + + var self = this; + this.el.on('mouseover', function () { + if (self._enterable) { + clearTimeout(self._hideTimeout); + self._show = true; + } + + self._inContent = true; + }); + this.el.on('mouseout', function () { + if (self._enterable) { + if (self._show) { + self.hideLater(self._hideDelay); + } + } + + self._inContent = false; + }); + }; + + TooltipRichContent.prototype.setEnterable = function (enterable) { + this._enterable = enterable; + }; + + TooltipRichContent.prototype.getSize = function () { + var el = this.el; + var bounding = this.el.getBoundingRect(); + var shadowOuterSize = calcShadowOuterSize(el.style); + return [bounding.width + shadowOuterSize.left + shadowOuterSize.right, bounding.height + shadowOuterSize.top + shadowOuterSize.bottom]; + }; + + TooltipRichContent.prototype.moveTo = function (x, y) { + var el = this.el; + + if (el) { + var styleCoord = this._styleCoord; + makeStyleCoord$1(styleCoord, this._zr, x, y); + x = styleCoord[0]; + y = styleCoord[1]; + var style = el.style; + var borderWidth = mathMaxWith0(style.borderWidth || 0); + var shadowOuterSize = calcShadowOuterSize(style); + el.x = x + borderWidth + shadowOuterSize.left; + el.y = y + borderWidth + shadowOuterSize.top; + el.markRedraw(); + } + }; + + TooltipRichContent.prototype._moveIfResized = function () { + var ratioX = this._styleCoord[2]; + var ratioY = this._styleCoord[3]; + this.moveTo(ratioX * this._zr.getWidth(), ratioY * this._zr.getHeight()); + }; + + TooltipRichContent.prototype.hide = function () { + if (this.el) { + this.el.hide(); + } + + this._show = false; + }; + + TooltipRichContent.prototype.hideLater = function (time) { + if (this._show && !(this._inContent && this._enterable)) { + if (time) { + this._hideDelay = time; + this._show = false; + this._hideTimeout = setTimeout(bind(this.hide, this), time); + } else { + this.hide(); + } + } + }; + + TooltipRichContent.prototype.isShow = function () { + return this._show; + }; + + TooltipRichContent.prototype.getOuterSize = function () { + var size = this.getSize(); + return { + width: size[0], + height: size[1] + }; + }; + + TooltipRichContent.prototype.dispose = function () { + this._zr.remove(this.el); + }; + + return TooltipRichContent; + }(); + + function mathMaxWith0(val) { + return Math.max(0, val); + } + + function calcShadowOuterSize(style) { + var shadowBlur = mathMaxWith0(style.shadowBlur || 0); + var shadowOffsetX = mathMaxWith0(style.shadowOffsetX || 0); + var shadowOffsetY = mathMaxWith0(style.shadowOffsetY || 0); + return { + left: mathMaxWith0(shadowBlur - shadowOffsetX), + right: mathMaxWith0(shadowBlur + shadowOffsetX), + top: mathMaxWith0(shadowBlur - shadowOffsetY), + bottom: mathMaxWith0(shadowBlur + shadowOffsetY) + }; + } + + function makeStyleCoord$1(out, zr, zrX, zrY) { + out[0] = zrX; + out[1] = zrY; + out[2] = out[0] / zr.getWidth(); + out[3] = out[1] / zr.getHeight(); + } + + var bind$2 = bind; + var each$c = each; + var parsePercent$3 = parsePercent$1; + var proxyRect = new Rect({ + shape: { + x: -1, + y: -1, + width: 2, + height: 2 + } + }); + + var TooltipView = function (_super) { + __extends(TooltipView, _super); + + function TooltipView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TooltipView.type; + return _this; + } + + TooltipView.prototype.init = function (ecModel, api) { + if (env.node) { + return; + } + + var tooltipModel = ecModel.getComponent('tooltip'); + var renderMode = tooltipModel.get('renderMode'); + this._renderMode = getTooltipRenderMode(renderMode); + this._tooltipContent = this._renderMode === 'richText' ? new TooltipRichContent(api) : new TooltipHTMLContent(api.getDom(), api, { + appendToBody: tooltipModel.get('appendToBody', true) + }); + }; + + TooltipView.prototype.render = function (tooltipModel, ecModel, api) { + if (env.node) { + return; + } + + this.group.removeAll(); + this._tooltipModel = tooltipModel; + this._ecModel = ecModel; + this._api = api; + this._alwaysShowContent = tooltipModel.get('alwaysShowContent'); + var tooltipContent = this._tooltipContent; + tooltipContent.update(tooltipModel); + tooltipContent.setEnterable(tooltipModel.get('enterable')); + + this._initGlobalListener(); + + this._keepShow(); + }; + + TooltipView.prototype._initGlobalListener = function () { + var tooltipModel = this._tooltipModel; + var triggerOn = tooltipModel.get('triggerOn'); + register('itemTooltip', this._api, bind$2(function (currTrigger, e, dispatchAction) { + if (triggerOn !== 'none') { + if (triggerOn.indexOf(currTrigger) >= 0) { + this._tryShow(e, dispatchAction); + } else if (currTrigger === 'leave') { + this._hide(dispatchAction); + } + } + }, this)); + }; + + TooltipView.prototype._keepShow = function () { + var tooltipModel = this._tooltipModel; + var ecModel = this._ecModel; + var api = this._api; + + if (this._lastX != null && this._lastY != null && tooltipModel.get('triggerOn') !== 'none') { + var self_1 = this; + clearTimeout(this._refreshUpdateTimeout); + this._refreshUpdateTimeout = setTimeout(function () { + !api.isDisposed() && self_1.manuallyShowTip(tooltipModel, ecModel, api, { + x: self_1._lastX, + y: self_1._lastY, + dataByCoordSys: self_1._lastDataByCoordSys + }); + }); + } + }; + + TooltipView.prototype.manuallyShowTip = function (tooltipModel, ecModel, api, payload) { + if (payload.from === this.uid || env.node) { + return; + } + + var dispatchAction = makeDispatchAction$1(payload, api); + this._ticket = ''; + var dataByCoordSys = payload.dataByCoordSys; + + if (payload.tooltip && payload.x != null && payload.y != null) { + var el = proxyRect; + el.x = payload.x; + el.y = payload.y; + el.update(); + el.tooltip = payload.tooltip; + + this._tryShow({ + offsetX: payload.x, + offsetY: payload.y, + target: el + }, dispatchAction); + } else if (dataByCoordSys) { + this._tryShow({ + offsetX: payload.x, + offsetY: payload.y, + position: payload.position, + dataByCoordSys: dataByCoordSys, + tooltipOption: payload.tooltipOption + }, dispatchAction); + } else if (payload.seriesIndex != null) { + if (this._manuallyAxisShowTip(tooltipModel, ecModel, api, payload)) { + return; + } + + var pointInfo = findPointFromSeries(payload, ecModel); + var cx = pointInfo.point[0]; + var cy = pointInfo.point[1]; + + if (cx != null && cy != null) { + this._tryShow({ + offsetX: cx, + offsetY: cy, + position: payload.position, + target: pointInfo.el + }, dispatchAction); + } + } else if (payload.x != null && payload.y != null) { + api.dispatchAction({ + type: 'updateAxisPointer', + x: payload.x, + y: payload.y + }); + + this._tryShow({ + offsetX: payload.x, + offsetY: payload.y, + position: payload.position, + target: api.getZr().findHover(payload.x, payload.y).target + }, dispatchAction); + } + }; + + TooltipView.prototype.manuallyHideTip = function (tooltipModel, ecModel, api, payload) { + var tooltipContent = this._tooltipContent; + + if (!this._alwaysShowContent && this._tooltipModel) { + tooltipContent.hideLater(this._tooltipModel.get('hideDelay')); + } + + this._lastX = this._lastY = this._lastDataByCoordSys = null; + + if (payload.from !== this.uid) { + this._hide(makeDispatchAction$1(payload, api)); + } + }; + + TooltipView.prototype._manuallyAxisShowTip = function (tooltipModel, ecModel, api, payload) { + var seriesIndex = payload.seriesIndex; + var dataIndex = payload.dataIndex; + var coordSysAxesInfo = ecModel.getComponent('axisPointer').coordSysAxesInfo; + + if (seriesIndex == null || dataIndex == null || coordSysAxesInfo == null) { + return; + } + + var seriesModel = ecModel.getSeriesByIndex(seriesIndex); + + if (!seriesModel) { + return; + } + + var data = seriesModel.getData(); + var tooltipCascadedModel = buildTooltipModel([data.getItemModel(dataIndex), seriesModel, (seriesModel.coordinateSystem || {}).model, tooltipModel]); + + if (tooltipCascadedModel.get('trigger') !== 'axis') { + return; + } + + api.dispatchAction({ + type: 'updateAxisPointer', + seriesIndex: seriesIndex, + dataIndex: dataIndex, + position: payload.position + }); + return true; + }; + + TooltipView.prototype._tryShow = function (e, dispatchAction) { + var el = e.target; + var tooltipModel = this._tooltipModel; + + if (!tooltipModel) { + return; + } + + this._lastX = e.offsetX; + this._lastY = e.offsetY; + var dataByCoordSys = e.dataByCoordSys; + + if (dataByCoordSys && dataByCoordSys.length) { + this._showAxisTooltip(dataByCoordSys, e); + } else if (el && findEventDispatcher(el, function (target) { + return getECData(target).dataIndex != null; + }, true)) { + this._lastDataByCoordSys = null; + + this._showSeriesItemTooltip(e, el, dispatchAction); + } else if (el && el.tooltip) { + this._lastDataByCoordSys = null; + + this._showComponentItemTooltip(e, el, dispatchAction); + } else { + this._lastDataByCoordSys = null; + + this._hide(dispatchAction); + } + }; + + TooltipView.prototype._showOrMove = function (tooltipModel, cb) { + var delay = tooltipModel.get('showDelay'); + cb = bind(cb, this); + clearTimeout(this._showTimout); + delay > 0 ? this._showTimout = setTimeout(cb, delay) : cb(); + }; + + TooltipView.prototype._showAxisTooltip = function (dataByCoordSys, e) { + var ecModel = this._ecModel; + var globalTooltipModel = this._tooltipModel; + var point = [e.offsetX, e.offsetY]; + var singleTooltipModel = buildTooltipModel([e.tooltipOption, globalTooltipModel]); + var renderMode = this._renderMode; + var cbParamsList = []; + var articleMarkup = createTooltipMarkup('section', { + blocks: [], + noHeader: true + }); + var markupTextArrLegacy = []; + var markupStyleCreator = new TooltipMarkupStyleCreator(); + each$c(dataByCoordSys, function (itemCoordSys) { + each$c(itemCoordSys.dataByAxis, function (axisItem) { + var axisModel = ecModel.getComponent(axisItem.axisDim + 'Axis', axisItem.axisIndex); + var axisValue = axisItem.value; + + if (!axisModel || axisValue == null) { + return; + } + + var axisValueLabel = getValueLabel(axisValue, axisModel.axis, ecModel, axisItem.seriesDataIndices, axisItem.valueLabelOpt); + var axisSectionMarkup = createTooltipMarkup('section', { + header: axisValueLabel, + noHeader: !trim(axisValueLabel), + sortBlocks: true, + blocks: [] + }); + articleMarkup.blocks.push(axisSectionMarkup); + each(axisItem.seriesDataIndices, function (idxItem) { + var series = ecModel.getSeriesByIndex(idxItem.seriesIndex); + var dataIndex = idxItem.dataIndexInside; + var cbParams = series.getDataParams(dataIndex); + cbParams.axisDim = axisItem.axisDim; + cbParams.axisIndex = axisItem.axisIndex; + cbParams.axisType = axisItem.axisType; + cbParams.axisId = axisItem.axisId; + cbParams.axisValue = getAxisRawValue(axisModel.axis, { + value: axisValue + }); + cbParams.axisValueLabel = axisValueLabel; + cbParams.marker = markupStyleCreator.makeTooltipMarker('item', convertToColorString(cbParams.color), renderMode); + var seriesTooltipResult = normalizeTooltipFormatResult(series.formatTooltip(dataIndex, true, null)); + + if (seriesTooltipResult.markupFragment) { + axisSectionMarkup.blocks.push(seriesTooltipResult.markupFragment); + } + + if (seriesTooltipResult.markupText) { + markupTextArrLegacy.push(seriesTooltipResult.markupText); + } + + cbParamsList.push(cbParams); + }); + }); + }); + articleMarkup.blocks.reverse(); + markupTextArrLegacy.reverse(); + var positionExpr = e.position; + var orderMode = singleTooltipModel.get('order'); + var builtMarkupText = buildTooltipMarkup(articleMarkup, markupStyleCreator, renderMode, orderMode, ecModel.get('useUTC'), singleTooltipModel.get('textStyle')); + builtMarkupText && markupTextArrLegacy.unshift(builtMarkupText); + var blockBreak = renderMode === 'richText' ? '\n\n' : '
                '; + var allMarkupText = markupTextArrLegacy.join(blockBreak); + + this._showOrMove(singleTooltipModel, function () { + if (this._updateContentNotChangedOnAxis(dataByCoordSys)) { + this._updatePosition(singleTooltipModel, positionExpr, point[0], point[1], this._tooltipContent, cbParamsList); + } else { + this._showTooltipContent(singleTooltipModel, allMarkupText, cbParamsList, Math.random() + '', point[0], point[1], positionExpr, null, markupStyleCreator); + } + }); + }; + + TooltipView.prototype._showSeriesItemTooltip = function (e, el, dispatchAction) { + var dispatcher = findEventDispatcher(el, function (target) { + return getECData(target).dataIndex != null; + }, true); + var ecModel = this._ecModel; + var ecData = getECData(dispatcher); + var seriesIndex = ecData.seriesIndex; + var seriesModel = ecModel.getSeriesByIndex(seriesIndex); + var dataModel = ecData.dataModel || seriesModel; + var dataIndex = ecData.dataIndex; + var dataType = ecData.dataType; + var data = dataModel.getData(dataType); + var renderMode = this._renderMode; + var tooltipModel = buildTooltipModel([data.getItemModel(dataIndex), dataModel, seriesModel && (seriesModel.coordinateSystem || {}).model, this._tooltipModel]); + var tooltipTrigger = tooltipModel.get('trigger'); + + if (tooltipTrigger != null && tooltipTrigger !== 'item') { + return; + } + + var params = dataModel.getDataParams(dataIndex, dataType); + var markupStyleCreator = new TooltipMarkupStyleCreator(); + params.marker = markupStyleCreator.makeTooltipMarker('item', convertToColorString(params.color), renderMode); + var seriesTooltipResult = normalizeTooltipFormatResult(dataModel.formatTooltip(dataIndex, false, dataType)); + var orderMode = tooltipModel.get('order'); + var markupText = seriesTooltipResult.markupFragment ? buildTooltipMarkup(seriesTooltipResult.markupFragment, markupStyleCreator, renderMode, orderMode, ecModel.get('useUTC'), tooltipModel.get('textStyle')) : seriesTooltipResult.markupText; + var asyncTicket = 'item_' + dataModel.name + '_' + dataIndex; + + this._showOrMove(tooltipModel, function () { + this._showTooltipContent(tooltipModel, markupText, params, asyncTicket, e.offsetX, e.offsetY, e.position, e.target, markupStyleCreator); + }); + + dispatchAction({ + type: 'showTip', + dataIndexInside: dataIndex, + dataIndex: data.getRawIndex(dataIndex), + seriesIndex: seriesIndex, + from: this.uid + }); + }; + + TooltipView.prototype._showComponentItemTooltip = function (e, el, dispatchAction) { + var tooltipOpt = el.tooltip; + + if (isString(tooltipOpt)) { + var content = tooltipOpt; + tooltipOpt = { + content: content, + formatter: content + }; + } + + var subTooltipModel = new Model(tooltipOpt, this._tooltipModel, this._ecModel); + var defaultHtml = subTooltipModel.get('content'); + var asyncTicket = Math.random() + ''; + var markupStyleCreator = new TooltipMarkupStyleCreator(); + + this._showOrMove(subTooltipModel, function () { + this._showTooltipContent(subTooltipModel, defaultHtml, subTooltipModel.get('formatterParams') || {}, asyncTicket, e.offsetX, e.offsetY, e.position, el, markupStyleCreator); + }); + + dispatchAction({ + type: 'showTip', + from: this.uid + }); + }; + + TooltipView.prototype._showTooltipContent = function (tooltipModel, defaultHtml, params, asyncTicket, x, y, positionExpr, el, markupStyleCreator) { + this._ticket = ''; + + if (!tooltipModel.get('showContent') || !tooltipModel.get('show')) { + return; + } + + var tooltipContent = this._tooltipContent; + var formatter = tooltipModel.get('formatter'); + positionExpr = positionExpr || tooltipModel.get('position'); + var html = defaultHtml; + + var nearPoint = this._getNearestPoint([x, y], params, tooltipModel.get('trigger'), tooltipModel.get('borderColor')); + + if (formatter && isString(formatter)) { + var useUTC = tooltipModel.ecModel.get('useUTC'); + var params0 = isArray(params) ? params[0] : params; + var isTimeAxis = params0 && params0.axisType && params0.axisType.indexOf('time') >= 0; + html = formatter; + + if (isTimeAxis) { + html = format(params0.axisValue, html, useUTC); + } + + html = formatTpl(html, params, true); + } else if (isFunction(formatter)) { + var callback = bind$2(function (cbTicket, html) { + if (cbTicket === this._ticket) { + tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPoint.color, positionExpr); + + this._updatePosition(tooltipModel, positionExpr, x, y, tooltipContent, params, el); + } + }, this); + this._ticket = asyncTicket; + html = formatter(params, asyncTicket, callback); + } + + tooltipContent.setContent(html, markupStyleCreator, tooltipModel, nearPoint.color, positionExpr); + tooltipContent.show(tooltipModel, nearPoint.color); + + this._updatePosition(tooltipModel, positionExpr, x, y, tooltipContent, params, el); + }; + + TooltipView.prototype._getNearestPoint = function (point, tooltipDataParams, trigger, borderColor) { + if (trigger === 'axis' || isArray(tooltipDataParams)) { + return { + color: borderColor || (this._renderMode === 'html' ? '#fff' : 'none') + }; + } + + if (!isArray(tooltipDataParams)) { + return { + color: borderColor || tooltipDataParams.color || tooltipDataParams.borderColor + }; + } + }; + + TooltipView.prototype._updatePosition = function (tooltipModel, positionExpr, x, y, content, params, el) { + var viewWidth = this._api.getWidth(); + + var viewHeight = this._api.getHeight(); + + positionExpr = positionExpr || tooltipModel.get('position'); + var contentSize = content.getSize(); + var align = tooltipModel.get('align'); + var vAlign = tooltipModel.get('verticalAlign'); + var rect = el && el.getBoundingRect().clone(); + el && rect.applyTransform(el.transform); + + if (isFunction(positionExpr)) { + positionExpr = positionExpr([x, y], params, content.el, rect, { + viewSize: [viewWidth, viewHeight], + contentSize: contentSize.slice() + }); + } + + if (isArray(positionExpr)) { + x = parsePercent$3(positionExpr[0], viewWidth); + y = parsePercent$3(positionExpr[1], viewHeight); + } else if (isObject(positionExpr)) { + var boxLayoutPosition = positionExpr; + boxLayoutPosition.width = contentSize[0]; + boxLayoutPosition.height = contentSize[1]; + var layoutRect = getLayoutRect(boxLayoutPosition, { + width: viewWidth, + height: viewHeight + }); + x = layoutRect.x; + y = layoutRect.y; + align = null; + vAlign = null; + } else if (isString(positionExpr) && el) { + var pos = calcTooltipPosition(positionExpr, rect, contentSize); + x = pos[0]; + y = pos[1]; + } else { + var pos = refixTooltipPosition(x, y, content, viewWidth, viewHeight, align ? null : 20, vAlign ? null : 20); + x = pos[0]; + y = pos[1]; + } + + align && (x -= isCenterAlign(align) ? contentSize[0] / 2 : align === 'right' ? contentSize[0] : 0); + vAlign && (y -= isCenterAlign(vAlign) ? contentSize[1] / 2 : vAlign === 'bottom' ? contentSize[1] : 0); + + if (shouldTooltipConfine(tooltipModel)) { + var pos = confineTooltipPosition(x, y, content, viewWidth, viewHeight); + x = pos[0]; + y = pos[1]; + } + + content.moveTo(x, y); + }; + + TooltipView.prototype._updateContentNotChangedOnAxis = function (dataByCoordSys) { + var lastCoordSys = this._lastDataByCoordSys; + var contentNotChanged = !!lastCoordSys && lastCoordSys.length === dataByCoordSys.length; + contentNotChanged && each$c(lastCoordSys, function (lastItemCoordSys, indexCoordSys) { + var lastDataByAxis = lastItemCoordSys.dataByAxis || []; + var thisItemCoordSys = dataByCoordSys[indexCoordSys] || {}; + var thisDataByAxis = thisItemCoordSys.dataByAxis || []; + contentNotChanged = contentNotChanged && lastDataByAxis.length === thisDataByAxis.length; + contentNotChanged && each$c(lastDataByAxis, function (lastItem, indexAxis) { + var thisItem = thisDataByAxis[indexAxis] || {}; + var lastIndices = lastItem.seriesDataIndices || []; + var newIndices = thisItem.seriesDataIndices || []; + contentNotChanged = contentNotChanged && lastItem.value === thisItem.value && lastItem.axisType === thisItem.axisType && lastItem.axisId === thisItem.axisId && lastIndices.length === newIndices.length; + contentNotChanged && each$c(lastIndices, function (lastIdxItem, j) { + var newIdxItem = newIndices[j]; + contentNotChanged = contentNotChanged && lastIdxItem.seriesIndex === newIdxItem.seriesIndex && lastIdxItem.dataIndex === newIdxItem.dataIndex; + }); + }); + }); + this._lastDataByCoordSys = dataByCoordSys; + return !!contentNotChanged; + }; + + TooltipView.prototype._hide = function (dispatchAction) { + this._lastDataByCoordSys = null; + dispatchAction({ + type: 'hideTip', + from: this.uid + }); + }; + + TooltipView.prototype.dispose = function (ecModel, api) { + if (env.node) { + return; + } + + this._tooltipContent.dispose(); + + unregister('itemTooltip', api); + }; + + TooltipView.type = 'tooltip'; + return TooltipView; + }(ComponentView); + + function buildTooltipModel(modelCascade) { + var resultModel = modelCascade.pop(); + + while (modelCascade.length) { + var tooltipOpt = modelCascade.pop(); + + if (tooltipOpt) { + if (tooltipOpt instanceof Model) { + tooltipOpt = tooltipOpt.get('tooltip', true); + } + + if (isString(tooltipOpt)) { + tooltipOpt = { + formatter: tooltipOpt + }; + } + + resultModel = new Model(tooltipOpt, resultModel, resultModel.ecModel); + } + } + + return resultModel; + } + + function makeDispatchAction$1(payload, api) { + return payload.dispatchAction || bind(api.dispatchAction, api); + } + + function refixTooltipPosition(x, y, content, viewWidth, viewHeight, gapH, gapV) { + var size = content.getOuterSize(); + var width = size.width; + var height = size.height; + + if (gapH != null) { + if (x + width + gapH + 2 > viewWidth) { + x -= width + gapH; + } else { + x += gapH; + } + } + + if (gapV != null) { + if (y + height + gapV > viewHeight) { + y -= height + gapV; + } else { + y += gapV; + } + } + + return [x, y]; + } + + function confineTooltipPosition(x, y, content, viewWidth, viewHeight) { + var size = content.getOuterSize(); + var width = size.width; + var height = size.height; + x = Math.min(x + width, viewWidth) - width; + y = Math.min(y + height, viewHeight) - height; + x = Math.max(x, 0); + y = Math.max(y, 0); + return [x, y]; + } + + function calcTooltipPosition(position, rect, contentSize) { + var domWidth = contentSize[0]; + var domHeight = contentSize[1]; + var gap = 10; + var offset = 5; + var x = 0; + var y = 0; + var rectWidth = rect.width; + var rectHeight = rect.height; + + switch (position) { + case 'inside': + x = rect.x + rectWidth / 2 - domWidth / 2; + y = rect.y + rectHeight / 2 - domHeight / 2; + break; + + case 'top': + x = rect.x + rectWidth / 2 - domWidth / 2; + y = rect.y - domHeight - gap; + break; + + case 'bottom': + x = rect.x + rectWidth / 2 - domWidth / 2; + y = rect.y + rectHeight + gap; + break; + + case 'left': + x = rect.x - domWidth - gap - offset; + y = rect.y + rectHeight / 2 - domHeight / 2; + break; + + case 'right': + x = rect.x + rectWidth + gap + offset; + y = rect.y + rectHeight / 2 - domHeight / 2; + } + + return [x, y]; + } + + function isCenterAlign(align) { + return align === 'center' || align === 'middle'; + } + + function install$A(registers) { + use(install$r); + registers.registerComponentModel(TooltipModel); + registers.registerComponentView(TooltipView); + registers.registerAction({ + type: 'showTip', + event: 'showTip', + update: 'tooltip:manuallyShowTip' + }, function () {}); + registers.registerAction({ + type: 'hideTip', + event: 'hideTip', + update: 'tooltip:manuallyHideTip' + }, function () {}); + } + + var DEFAULT_TOOLBOX_BTNS = ['rect', 'polygon', 'keep', 'clear']; + function brushPreprocessor(option, isNew) { + var brushComponents = normalizeToArray(option ? option.brush : []); + + if (!brushComponents.length) { + return; + } + + var brushComponentSpecifiedBtns = []; + each(brushComponents, function (brushOpt) { + var tbs = brushOpt.hasOwnProperty('toolbox') ? brushOpt.toolbox : []; + + if (tbs instanceof Array) { + brushComponentSpecifiedBtns = brushComponentSpecifiedBtns.concat(tbs); + } + }); + var toolbox = option && option.toolbox; + + if (isArray(toolbox)) { + toolbox = toolbox[0]; + } + + if (!toolbox) { + toolbox = { + feature: {} + }; + option.toolbox = [toolbox]; + } + + var toolboxFeature = toolbox.feature || (toolbox.feature = {}); + var toolboxBrush = toolboxFeature.brush || (toolboxFeature.brush = {}); + var brushTypes = toolboxBrush.type || (toolboxBrush.type = []); + brushTypes.push.apply(brushTypes, brushComponentSpecifiedBtns); + removeDuplicate(brushTypes); + + if (isNew && !brushTypes.length) { + brushTypes.push.apply(brushTypes, DEFAULT_TOOLBOX_BTNS); + } + } + + function removeDuplicate(arr) { + var map = {}; + each(arr, function (val) { + map[val] = 1; + }); + arr.length = 0; + each(map, function (flag, val) { + arr.push(val); + }); + } + + var each$d = each; + + function hasKeys(obj) { + if (obj) { + for (var name_1 in obj) { + if (obj.hasOwnProperty(name_1)) { + return true; + } + } + } + } + + function createVisualMappings(option, stateList, supplementVisualOption) { + var visualMappings = {}; + each$d(stateList, function (state) { + var mappings = visualMappings[state] = createMappings(); + each$d(option[state], function (visualData, visualType) { + if (!VisualMapping.isValidType(visualType)) { + return; + } + + var mappingOption = { + type: visualType, + visual: visualData + }; + supplementVisualOption && supplementVisualOption(mappingOption, state); + mappings[visualType] = new VisualMapping(mappingOption); + + if (visualType === 'opacity') { + mappingOption = clone(mappingOption); + mappingOption.type = 'colorAlpha'; + mappings.__hidden.__alphaForOpacity = new VisualMapping(mappingOption); + } + }); + }); + return visualMappings; + + function createMappings() { + var Creater = function () {}; + + Creater.prototype.__hidden = Creater.prototype; + var obj = new Creater(); + return obj; + } + } + function replaceVisualOption(thisOption, newOption, keys) { + var has; + each(keys, function (key) { + if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) { + has = true; + } + }); + has && each(keys, function (key) { + if (newOption.hasOwnProperty(key) && hasKeys(newOption[key])) { + thisOption[key] = clone(newOption[key]); + } else { + delete thisOption[key]; + } + }); + } + function applyVisual(stateList, visualMappings, data, getValueState, scope, dimension) { + var visualTypesMap = {}; + each(stateList, function (state) { + var visualTypes = VisualMapping.prepareVisualTypes(visualMappings[state]); + visualTypesMap[state] = visualTypes; + }); + var dataIndex; + + function getVisual(key) { + return getItemVisualFromData(data, dataIndex, key); + } + + function setVisual(key, value) { + setItemVisualFromData(data, dataIndex, key, value); + } + + if (dimension == null) { + data.each(eachItem); + } else { + data.each([dimension], eachItem); + } + + function eachItem(valueOrIndex, index) { + dataIndex = dimension == null ? valueOrIndex : index; + var rawDataItem = data.getRawDataItem(dataIndex); + + if (rawDataItem && rawDataItem.visualMap === false) { + return; + } + + var valueState = getValueState.call(scope, valueOrIndex); + var mappings = visualMappings[valueState]; + var visualTypes = visualTypesMap[valueState]; + + for (var i = 0, len = visualTypes.length; i < len; i++) { + var type = visualTypes[i]; + mappings[type] && mappings[type].applyVisual(valueOrIndex, getVisual, setVisual); + } + } + } + function incrementalApplyVisual(stateList, visualMappings, getValueState, dim) { + var visualTypesMap = {}; + each(stateList, function (state) { + var visualTypes = VisualMapping.prepareVisualTypes(visualMappings[state]); + visualTypesMap[state] = visualTypes; + }); + return { + progress: function progress(params, data) { + var dimName; + + if (dim != null) { + dimName = data.getDimension(dim); + } + + function getVisual(key) { + return getItemVisualFromData(data, dataIndex, key); + } + + function setVisual(key, value) { + setItemVisualFromData(data, dataIndex, key, value); + } + + var dataIndex; + + while ((dataIndex = params.next()) != null) { + var rawDataItem = data.getRawDataItem(dataIndex); + + if (rawDataItem && rawDataItem.visualMap === false) { + continue; + } + + var value = dim != null ? data.get(dimName, dataIndex) : dataIndex; + var valueState = getValueState(value); + var mappings = visualMappings[valueState]; + var visualTypes = visualTypesMap[valueState]; + + for (var i = 0, len = visualTypes.length; i < len; i++) { + var type = visualTypes[i]; + mappings[type] && mappings[type].applyVisual(value, getVisual, setVisual); + } + } + } + }; + } + + function makeBrushCommonSelectorForSeries(area) { + var brushType = area.brushType; + var selectors = { + point: function (itemLayout) { + return selector[brushType].point(itemLayout, selectors, area); + }, + rect: function (itemLayout) { + return selector[brushType].rect(itemLayout, selectors, area); + } + }; + return selectors; + } + var selector = { + lineX: getLineSelectors(0), + lineY: getLineSelectors(1), + rect: { + point: function (itemLayout, selectors, area) { + return itemLayout && area.boundingRect.contain(itemLayout[0], itemLayout[1]); + }, + rect: function (itemLayout, selectors, area) { + return itemLayout && area.boundingRect.intersect(itemLayout); + } + }, + polygon: { + point: function (itemLayout, selectors, area) { + return itemLayout && area.boundingRect.contain(itemLayout[0], itemLayout[1]) && contain$2(area.range, itemLayout[0], itemLayout[1]); + }, + rect: function (itemLayout, selectors, area) { + var points = area.range; + + if (!itemLayout || points.length <= 1) { + return false; + } + + var x = itemLayout.x; + var y = itemLayout.y; + var width = itemLayout.width; + var height = itemLayout.height; + var p = points[0]; + + if (contain$2(points, x, y) || contain$2(points, x + width, y) || contain$2(points, x, y + height) || contain$2(points, x + width, y + height) || BoundingRect.create(itemLayout).contain(p[0], p[1]) || linePolygonIntersect(x, y, x + width, y, points) || linePolygonIntersect(x, y, x, y + height, points) || linePolygonIntersect(x + width, y, x + width, y + height, points) || linePolygonIntersect(x, y + height, x + width, y + height, points)) { + return true; + } + } + } + }; + + function getLineSelectors(xyIndex) { + var xy = ['x', 'y']; + var wh = ['width', 'height']; + return { + point: function (itemLayout, selectors, area) { + if (itemLayout) { + var range = area.range; + var p = itemLayout[xyIndex]; + return inLineRange(p, range); + } + }, + rect: function (itemLayout, selectors, area) { + if (itemLayout) { + var range = area.range; + var layoutRange = [itemLayout[xy[xyIndex]], itemLayout[xy[xyIndex]] + itemLayout[wh[xyIndex]]]; + layoutRange[1] < layoutRange[0] && layoutRange.reverse(); + return inLineRange(layoutRange[0], range) || inLineRange(layoutRange[1], range) || inLineRange(range[0], layoutRange) || inLineRange(range[1], layoutRange); + } + } + }; + } + + function inLineRange(p, range) { + return range[0] <= p && p <= range[1]; + } + + var STATE_LIST = ['inBrush', 'outOfBrush']; + var DISPATCH_METHOD = '__ecBrushSelect'; + var DISPATCH_FLAG = '__ecInBrushSelectEvent'; + function layoutCovers(ecModel) { + ecModel.eachComponent({ + mainType: 'brush' + }, function (brushModel) { + var brushTargetManager = brushModel.brushTargetManager = new BrushTargetManager(brushModel.option, ecModel); + brushTargetManager.setInputRanges(brushModel.areas, ecModel); + }); + } + function brushVisual(ecModel, api, payload) { + var brushSelected = []; + var throttleType; + var throttleDelay; + ecModel.eachComponent({ + mainType: 'brush' + }, function (brushModel) { + payload && payload.type === 'takeGlobalCursor' && brushModel.setBrushOption(payload.key === 'brush' ? payload.brushOption : { + brushType: false + }); + }); + layoutCovers(ecModel); + ecModel.eachComponent({ + mainType: 'brush' + }, function (brushModel, brushIndex) { + var thisBrushSelected = { + brushId: brushModel.id, + brushIndex: brushIndex, + brushName: brushModel.name, + areas: clone(brushModel.areas), + selected: [] + }; + brushSelected.push(thisBrushSelected); + var brushOption = brushModel.option; + var brushLink = brushOption.brushLink; + var linkedSeriesMap = []; + var selectedDataIndexForLink = []; + var rangeInfoBySeries = []; + var hasBrushExists = false; + + if (!brushIndex) { + throttleType = brushOption.throttleType; + throttleDelay = brushOption.throttleDelay; + } + + var areas = map(brushModel.areas, function (area) { + var builder = boundingRectBuilders[area.brushType]; + var selectableArea = defaults({ + boundingRect: builder ? builder(area) : void 0 + }, area); + selectableArea.selectors = makeBrushCommonSelectorForSeries(selectableArea); + return selectableArea; + }); + var visualMappings = createVisualMappings(brushModel.option, STATE_LIST, function (mappingOption) { + mappingOption.mappingMethod = 'fixed'; + }); + isArray(brushLink) && each(brushLink, function (seriesIndex) { + linkedSeriesMap[seriesIndex] = 1; + }); + + function linkOthers(seriesIndex) { + return brushLink === 'all' || !!linkedSeriesMap[seriesIndex]; + } + + function brushed(rangeInfoList) { + return !!rangeInfoList.length; + } + + ecModel.eachSeries(function (seriesModel, seriesIndex) { + var rangeInfoList = rangeInfoBySeries[seriesIndex] = []; + seriesModel.subType === 'parallel' ? stepAParallel(seriesModel, seriesIndex) : stepAOthers(seriesModel, seriesIndex, rangeInfoList); + }); + + function stepAParallel(seriesModel, seriesIndex) { + var coordSys = seriesModel.coordinateSystem; + hasBrushExists = hasBrushExists || coordSys.hasAxisBrushed(); + linkOthers(seriesIndex) && coordSys.eachActiveState(seriesModel.getData(), function (activeState, dataIndex) { + activeState === 'active' && (selectedDataIndexForLink[dataIndex] = 1); + }); + } + + function stepAOthers(seriesModel, seriesIndex, rangeInfoList) { + if (!seriesModel.brushSelector || brushModelNotControll(brushModel, seriesIndex)) { + return; + } + + each(areas, function (area) { + if (brushModel.brushTargetManager.controlSeries(area, seriesModel, ecModel)) { + rangeInfoList.push(area); + } + + hasBrushExists = hasBrushExists || brushed(rangeInfoList); + }); + + if (linkOthers(seriesIndex) && brushed(rangeInfoList)) { + var data_1 = seriesModel.getData(); + data_1.each(function (dataIndex) { + if (checkInRange(seriesModel, rangeInfoList, data_1, dataIndex)) { + selectedDataIndexForLink[dataIndex] = 1; + } + }); + } + } + + ecModel.eachSeries(function (seriesModel, seriesIndex) { + var seriesBrushSelected = { + seriesId: seriesModel.id, + seriesIndex: seriesIndex, + seriesName: seriesModel.name, + dataIndex: [] + }; + thisBrushSelected.selected.push(seriesBrushSelected); + var rangeInfoList = rangeInfoBySeries[seriesIndex]; + var data = seriesModel.getData(); + var getValueState = linkOthers(seriesIndex) ? function (dataIndex) { + return selectedDataIndexForLink[dataIndex] ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush') : 'outOfBrush'; + } : function (dataIndex) { + return checkInRange(seriesModel, rangeInfoList, data, dataIndex) ? (seriesBrushSelected.dataIndex.push(data.getRawIndex(dataIndex)), 'inBrush') : 'outOfBrush'; + }; + (linkOthers(seriesIndex) ? hasBrushExists : brushed(rangeInfoList)) && applyVisual(STATE_LIST, visualMappings, data, getValueState); + }); + }); + dispatchAction(api, throttleType, throttleDelay, brushSelected, payload); + } + + function dispatchAction(api, throttleType, throttleDelay, brushSelected, payload) { + if (!payload) { + return; + } + + var zr = api.getZr(); + + if (zr[DISPATCH_FLAG]) { + return; + } + + if (!zr[DISPATCH_METHOD]) { + zr[DISPATCH_METHOD] = doDispatch; + } + + var fn = createOrUpdate(zr, DISPATCH_METHOD, throttleDelay, throttleType); + fn(api, brushSelected); + } + + function doDispatch(api, brushSelected) { + if (!api.isDisposed()) { + var zr = api.getZr(); + zr[DISPATCH_FLAG] = true; + api.dispatchAction({ + type: 'brushSelect', + batch: brushSelected + }); + zr[DISPATCH_FLAG] = false; + } + } + + function checkInRange(seriesModel, rangeInfoList, data, dataIndex) { + for (var i = 0, len = rangeInfoList.length; i < len; i++) { + var area = rangeInfoList[i]; + + if (seriesModel.brushSelector(dataIndex, data, area.selectors, area)) { + return true; + } + } + } + + function brushModelNotControll(brushModel, seriesIndex) { + var seriesIndices = brushModel.option.seriesIndex; + return seriesIndices != null && seriesIndices !== 'all' && (isArray(seriesIndices) ? indexOf(seriesIndices, seriesIndex) < 0 : seriesIndex !== seriesIndices); + } + + var boundingRectBuilders = { + rect: function (area) { + return getBoundingRectFromMinMax(area.range); + }, + polygon: function (area) { + var minMax; + var range = area.range; + + for (var i = 0, len = range.length; i < len; i++) { + minMax = minMax || [[Infinity, -Infinity], [Infinity, -Infinity]]; + var rg = range[i]; + rg[0] < minMax[0][0] && (minMax[0][0] = rg[0]); + rg[0] > minMax[0][1] && (minMax[0][1] = rg[0]); + rg[1] < minMax[1][0] && (minMax[1][0] = rg[1]); + rg[1] > minMax[1][1] && (minMax[1][1] = rg[1]); + } + + return minMax && getBoundingRectFromMinMax(minMax); + } + }; + + function getBoundingRectFromMinMax(minMax) { + return new BoundingRect(minMax[0][0], minMax[1][0], minMax[0][1] - minMax[0][0], minMax[1][1] - minMax[1][0]); + } + + var BrushView = function (_super) { + __extends(BrushView, _super); + + function BrushView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = BrushView.type; + return _this; + } + + BrushView.prototype.init = function (ecModel, api) { + this.ecModel = ecModel; + this.api = api; + this.model; + (this._brushController = new BrushController(api.getZr())).on('brush', bind(this._onBrush, this)).mount(); + }; + + BrushView.prototype.render = function (brushModel, ecModel, api, payload) { + this.model = brushModel; + + this._updateController(brushModel, ecModel, api, payload); + }; + + BrushView.prototype.updateTransform = function (brushModel, ecModel, api, payload) { + layoutCovers(ecModel); + + this._updateController(brushModel, ecModel, api, payload); + }; + + BrushView.prototype.updateVisual = function (brushModel, ecModel, api, payload) { + this.updateTransform(brushModel, ecModel, api, payload); + }; + + BrushView.prototype.updateView = function (brushModel, ecModel, api, payload) { + this._updateController(brushModel, ecModel, api, payload); + }; + + BrushView.prototype._updateController = function (brushModel, ecModel, api, payload) { + (!payload || payload.$from !== brushModel.id) && this._brushController.setPanels(brushModel.brushTargetManager.makePanelOpts(api)).enableBrush(brushModel.brushOption).updateCovers(brushModel.areas.slice()); + }; + + BrushView.prototype.dispose = function () { + this._brushController.dispose(); + }; + + BrushView.prototype._onBrush = function (eventParam) { + var modelId = this.model.id; + var areas = this.model.brushTargetManager.setOutputRanges(eventParam.areas, this.ecModel); + (!eventParam.isEnd || eventParam.removeOnClick) && this.api.dispatchAction({ + type: 'brush', + brushId: modelId, + areas: clone(areas), + $from: modelId + }); + eventParam.isEnd && this.api.dispatchAction({ + type: 'brushEnd', + brushId: modelId, + areas: clone(areas), + $from: modelId + }); + }; + + BrushView.type = 'brush'; + return BrushView; + }(ComponentView); + + var DEFAULT_OUT_OF_BRUSH_COLOR = '#ddd'; + + var BrushModel = function (_super) { + __extends(BrushModel, _super); + + function BrushModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = BrushModel.type; + _this.areas = []; + _this.brushOption = {}; + return _this; + } + + BrushModel.prototype.optionUpdated = function (newOption, isInit) { + var thisOption = this.option; + !isInit && replaceVisualOption(thisOption, newOption, ['inBrush', 'outOfBrush']); + var inBrush = thisOption.inBrush = thisOption.inBrush || {}; + thisOption.outOfBrush = thisOption.outOfBrush || { + color: DEFAULT_OUT_OF_BRUSH_COLOR + }; + + if (!inBrush.hasOwnProperty('liftZ')) { + inBrush.liftZ = 5; + } + }; + + BrushModel.prototype.setAreas = function (areas) { + if ("development" !== 'production') { + assert(isArray(areas)); + each(areas, function (area) { + assert(area.brushType, 'Illegal areas'); + }); + } + + if (!areas) { + return; + } + + this.areas = map(areas, function (area) { + return generateBrushOption(this.option, area); + }, this); + }; + + BrushModel.prototype.setBrushOption = function (brushOption) { + this.brushOption = generateBrushOption(this.option, brushOption); + this.brushType = this.brushOption.brushType; + }; + + BrushModel.type = 'brush'; + BrushModel.dependencies = ['geo', 'grid', 'xAxis', 'yAxis', 'parallel', 'series']; + BrushModel.defaultOption = { + seriesIndex: 'all', + brushType: 'rect', + brushMode: 'single', + transformable: true, + brushStyle: { + borderWidth: 1, + color: 'rgba(210,219,238,0.3)', + borderColor: '#D2DBEE' + }, + throttleType: 'fixRate', + throttleDelay: 0, + removeOnClick: true, + z: 10000 + }; + return BrushModel; + }(ComponentModel); + + function generateBrushOption(option, brushOption) { + return merge({ + brushType: option.brushType, + brushMode: option.brushMode, + transformable: option.transformable, + brushStyle: new Model(option.brushStyle).getItemStyle(), + removeOnClick: option.removeOnClick, + z: option.z + }, brushOption, true); + } + + var ICON_TYPES = ['rect', 'polygon', 'lineX', 'lineY', 'keep', 'clear']; + + var BrushFeature = function (_super) { + __extends(BrushFeature, _super); + + function BrushFeature() { + return _super !== null && _super.apply(this, arguments) || this; + } + + BrushFeature.prototype.render = function (featureModel, ecModel, api) { + var brushType; + var brushMode; + var isBrushed; + ecModel.eachComponent({ + mainType: 'brush' + }, function (brushModel) { + brushType = brushModel.brushType; + brushMode = brushModel.brushOption.brushMode || 'single'; + isBrushed = isBrushed || !!brushModel.areas.length; + }); + this._brushType = brushType; + this._brushMode = brushMode; + each(featureModel.get('type', true), function (type) { + featureModel.setIconStatus(type, (type === 'keep' ? brushMode === 'multiple' : type === 'clear' ? isBrushed : type === brushType) ? 'emphasis' : 'normal'); + }); + }; + + BrushFeature.prototype.updateView = function (featureModel, ecModel, api) { + this.render(featureModel, ecModel, api); + }; + + BrushFeature.prototype.getIcons = function () { + var model = this.model; + var availableIcons = model.get('icon', true); + var icons = {}; + each(model.get('type', true), function (type) { + if (availableIcons[type]) { + icons[type] = availableIcons[type]; + } + }); + return icons; + }; + + BrushFeature.prototype.onclick = function (ecModel, api, type) { + var brushType = this._brushType; + var brushMode = this._brushMode; + + if (type === 'clear') { + api.dispatchAction({ + type: 'axisAreaSelect', + intervals: [] + }); + api.dispatchAction({ + type: 'brush', + command: 'clear', + areas: [] + }); + } else { + api.dispatchAction({ + type: 'takeGlobalCursor', + key: 'brush', + brushOption: { + brushType: type === 'keep' ? brushType : brushType === type ? false : type, + brushMode: type === 'keep' ? brushMode === 'multiple' ? 'single' : 'multiple' : brushMode + } + }); + } + }; + + BrushFeature.getDefaultOption = function (ecModel) { + var defaultOption = { + show: true, + type: ICON_TYPES.slice(), + icon: { + rect: 'M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13', + polygon: 'M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2', + lineX: 'M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4', + lineY: 'M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4', + keep: 'M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z', + clear: 'M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2' + }, + title: ecModel.getLocale(['toolbox', 'brush', 'title']) + }; + return defaultOption; + }; + + return BrushFeature; + }(ToolboxFeature); + + function install$B(registers) { + registers.registerComponentView(BrushView); + registers.registerComponentModel(BrushModel); + registers.registerPreprocessor(brushPreprocessor); + registers.registerVisual(registers.PRIORITY.VISUAL.BRUSH, brushVisual); + registers.registerAction({ + type: 'brush', + event: 'brush', + update: 'updateVisual' + }, function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'brush', + query: payload + }, function (brushModel) { + brushModel.setAreas(payload.areas); + }); + }); + registers.registerAction({ + type: 'brushSelect', + event: 'brushSelected', + update: 'none' + }, function () {}); + registers.registerAction({ + type: 'brushEnd', + event: 'brushEnd', + update: 'none' + }, function () {}); + registerFeature('brush', BrushFeature); + } + + var TitleModel = function (_super) { + __extends(TitleModel, _super); + + function TitleModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TitleModel.type; + _this.layoutMode = { + type: 'box', + ignoreSize: true + }; + return _this; + } + + TitleModel.type = 'title'; + TitleModel.defaultOption = { + zlevel: 0, + z: 6, + show: true, + 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: 'bold', + color: '#464646' + }, + subtextStyle: { + fontSize: 12, + color: '#6E7079' + } + }; + return TitleModel; + }(ComponentModel); + + var TitleView = function (_super) { + __extends(TitleView, _super); + + function TitleView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TitleView.type; + return _this; + } + + TitleView.prototype.render = function (titleModel, ecModel, api) { + this.group.removeAll(); + + if (!titleModel.get('show')) { + return; + } + + var group = this.group; + var textStyleModel = titleModel.getModel('textStyle'); + var subtextStyleModel = titleModel.getModel('subtextStyle'); + var textAlign = titleModel.get('textAlign'); + var textVerticalAlign = retrieve2(titleModel.get('textBaseline'), titleModel.get('textVerticalAlign')); + var textEl = new ZRText({ + style: createTextStyle(textStyleModel, { + text: titleModel.get('text'), + fill: textStyleModel.getTextColor() + }, { + disableBox: true + }), + z2: 10 + }); + var textRect = textEl.getBoundingRect(); + var subText = titleModel.get('subtext'); + var subTextEl = new ZRText({ + style: createTextStyle(subtextStyleModel, { + text: subText, + fill: subtextStyleModel.getTextColor(), + y: textRect.height + titleModel.get('itemGap'), + verticalAlign: 'top' + }, { + disableBox: true + }), + z2: 10 + }); + var link = titleModel.get('link'); + var sublink = titleModel.get('sublink'); + var triggerEvent = titleModel.get('triggerEvent', true); + textEl.silent = !link && !triggerEvent; + subTextEl.silent = !sublink && !triggerEvent; + + if (link) { + textEl.on('click', function () { + windowOpen(link, '_' + titleModel.get('target')); + }); + } + + if (sublink) { + subTextEl.on('click', function () { + windowOpen(sublink, '_' + titleModel.get('subtarget')); + }); + } + + getECData(textEl).eventData = getECData(subTextEl).eventData = triggerEvent ? { + componentType: 'title', + componentIndex: titleModel.componentIndex + } : null; + group.add(textEl); + subText && group.add(subTextEl); + var groupRect = group.getBoundingRect(); + var layoutOption = titleModel.getBoxLayoutParams(); + layoutOption.width = groupRect.width; + layoutOption.height = groupRect.height; + var layoutRect = getLayoutRect(layoutOption, { + width: api.getWidth(), + height: api.getHeight() + }, titleModel.get('padding')); + + if (!textAlign) { + textAlign = titleModel.get('left') || titleModel.get('right'); + + if (textAlign === 'middle') { + textAlign = 'center'; + } + + if (textAlign === 'right') { + layoutRect.x += layoutRect.width; + } else if (textAlign === 'center') { + layoutRect.x += layoutRect.width / 2; + } + } + + if (!textVerticalAlign) { + textVerticalAlign = titleModel.get('top') || titleModel.get('bottom'); + + if (textVerticalAlign === 'center') { + textVerticalAlign = 'middle'; + } + + if (textVerticalAlign === 'bottom') { + layoutRect.y += layoutRect.height; + } else if (textVerticalAlign === 'middle') { + layoutRect.y += layoutRect.height / 2; + } + + textVerticalAlign = textVerticalAlign || 'top'; + } + + group.x = layoutRect.x; + group.y = layoutRect.y; + group.markRedraw(); + var alignStyle = { + align: textAlign, + verticalAlign: textVerticalAlign + }; + textEl.setStyle(alignStyle); + subTextEl.setStyle(alignStyle); + groupRect = group.getBoundingRect(); + var padding = layoutRect.margin; + var style = titleModel.getItemStyle(['color', 'opacity']); + style.fill = titleModel.get('backgroundColor'); + var rect = new Rect({ + shape: { + x: groupRect.x - padding[3], + y: groupRect.y - padding[0], + width: groupRect.width + padding[1] + padding[3], + height: groupRect.height + padding[0] + padding[2], + r: titleModel.get('borderRadius') + }, + style: style, + subPixelOptimize: true, + silent: true + }); + group.add(rect); + }; + + TitleView.type = 'title'; + return TitleView; + }(ComponentView); + + function install$C(registers) { + registers.registerComponentModel(TitleModel); + registers.registerComponentView(TitleView); + } + + var TimelineModel = function (_super) { + __extends(TimelineModel, _super); + + function TimelineModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TimelineModel.type; + _this.layoutMode = 'box'; + return _this; + } + + TimelineModel.prototype.init = function (option, parentModel, ecModel) { + this.mergeDefaultAndTheme(option, ecModel); + + this._initData(); + }; + + TimelineModel.prototype.mergeOption = function (option) { + _super.prototype.mergeOption.apply(this, arguments); + + this._initData(); + }; + + TimelineModel.prototype.setCurrentIndex = function (currentIndex) { + if (currentIndex == null) { + currentIndex = this.option.currentIndex; + } + + var count = this._data.count(); + + if (this.option.loop) { + currentIndex = (currentIndex % count + count) % count; + } else { + currentIndex >= count && (currentIndex = count - 1); + currentIndex < 0 && (currentIndex = 0); + } + + this.option.currentIndex = currentIndex; + }; + + TimelineModel.prototype.getCurrentIndex = function () { + return this.option.currentIndex; + }; + + TimelineModel.prototype.isIndexMax = function () { + return this.getCurrentIndex() >= this._data.count() - 1; + }; + + TimelineModel.prototype.setPlayState = function (state) { + this.option.autoPlay = !!state; + }; + + TimelineModel.prototype.getPlayState = function () { + return !!this.option.autoPlay; + }; + + TimelineModel.prototype._initData = function () { + var thisOption = this.option; + var dataArr = thisOption.data || []; + var axisType = thisOption.axisType; + var names = this._names = []; + var processedDataArr; + + if (axisType === 'category') { + processedDataArr = []; + each(dataArr, function (item, index) { + var value = convertOptionIdName(getDataItemValue(item), ''); + var newItem; + + if (isObject(item)) { + newItem = clone(item); + newItem.value = index; + } else { + newItem = index; + } + + processedDataArr.push(newItem); + names.push(value); + }); + } else { + processedDataArr = dataArr; + } + + var dimType = { + category: 'ordinal', + time: 'time', + value: 'number' + }[axisType] || 'number'; + var data = this._data = new List([{ + name: 'value', + type: dimType + }], this); + data.initData(processedDataArr, names); + }; + + TimelineModel.prototype.getData = function () { + return this._data; + }; + + TimelineModel.prototype.getCategories = function () { + if (this.get('axisType') === 'category') { + return this._names.slice(); + } + }; + + TimelineModel.type = 'timeline'; + TimelineModel.defaultOption = { + zlevel: 0, + z: 4, + show: true, + axisType: 'time', + realtime: true, + left: '20%', + top: null, + right: '20%', + bottom: 0, + width: null, + height: 40, + padding: 5, + controlPosition: 'left', + autoPlay: false, + rewind: false, + loop: true, + playInterval: 2000, + currentIndex: 0, + itemStyle: {}, + label: { + color: '#000' + }, + data: [] + }; + return TimelineModel; + }(ComponentModel); + + var SliderTimelineModel = function (_super) { + __extends(SliderTimelineModel, _super); + + function SliderTimelineModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SliderTimelineModel.type; + return _this; + } + + SliderTimelineModel.type = 'timeline.slider'; + SliderTimelineModel.defaultOption = inheritDefaultOption(TimelineModel.defaultOption, { + backgroundColor: 'rgba(0,0,0,0)', + borderColor: '#ccc', + borderWidth: 0, + orient: 'horizontal', + inverse: false, + tooltip: { + trigger: 'item' + }, + symbol: 'circle', + symbolSize: 12, + lineStyle: { + show: true, + width: 2, + color: '#DAE1F5' + }, + label: { + position: 'auto', + show: true, + interval: 'auto', + rotate: 0, + color: '#A4B1D7' + }, + itemStyle: { + color: '#A4B1D7', + borderWidth: 1 + }, + checkpointStyle: { + symbol: 'circle', + symbolSize: 15, + color: '#316bf3', + borderColor: '#fff', + borderWidth: 2, + shadowBlur: 2, + shadowOffsetX: 1, + shadowOffsetY: 1, + shadowColor: 'rgba(0, 0, 0, 0.3)', + animation: true, + animationDuration: 300, + animationEasing: 'quinticInOut' + }, + controlStyle: { + show: true, + showPlayBtn: true, + showPrevBtn: true, + showNextBtn: true, + itemSize: 24, + itemGap: 12, + position: 'left', + playIcon: 'path://M31.6,53C17.5,53,6,41.5,6,27.4S17.5,1.8,31.6,1.8C45.7,1.8,57.2,13.3,57.2,27.4S45.7,53,31.6,53z M31.6,3.3 C18.4,3.3,7.5,14.1,7.5,27.4c0,13.3,10.8,24.1,24.1,24.1C44.9,51.5,55.7,40.7,55.7,27.4C55.7,14.1,44.9,3.3,31.6,3.3z M24.9,21.3 c0-2.2,1.6-3.1,3.5-2l10.5,6.1c1.899,1.1,1.899,2.9,0,4l-10.5,6.1c-1.9,1.1-3.5,0.2-3.5-2V21.3z', + stopIcon: 'path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z', + nextIcon: 'M2,18.5A1.52,1.52,0,0,1,.92,18a1.49,1.49,0,0,1,0-2.12L7.81,9.36,1,3.11A1.5,1.5,0,1,1,3,.89l8,7.34a1.48,1.48,0,0,1,.49,1.09,1.51,1.51,0,0,1-.46,1.1L3,18.08A1.5,1.5,0,0,1,2,18.5Z', + prevIcon: 'M10,.5A1.52,1.52,0,0,1,11.08,1a1.49,1.49,0,0,1,0,2.12L4.19,9.64,11,15.89a1.5,1.5,0,1,1-2,2.22L1,10.77A1.48,1.48,0,0,1,.5,9.68,1.51,1.51,0,0,1,1,8.58L9,.92A1.5,1.5,0,0,1,10,.5Z', + prevBtnSize: 18, + nextBtnSize: 18, + color: '#A4B1D7', + borderColor: '#A4B1D7', + borderWidth: 1 + }, + emphasis: { + label: { + show: true, + color: '#6f778d' + }, + itemStyle: { + color: '#316BF3' + }, + controlStyle: { + color: '#316BF3', + borderColor: '#316BF3', + borderWidth: 2 + } + }, + progress: { + lineStyle: { + color: '#316BF3' + }, + itemStyle: { + color: '#316BF3' + }, + label: { + color: '#6f778d' + } + }, + data: [] + }); + return SliderTimelineModel; + }(TimelineModel); + + mixin(SliderTimelineModel, DataFormatMixin.prototype); + + var TimelineView = function (_super) { + __extends(TimelineView, _super); + + function TimelineView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = TimelineView.type; + return _this; + } + + TimelineView.type = 'timeline'; + return TimelineView; + }(ComponentView); + + var TimelineAxis = function (_super) { + __extends(TimelineAxis, _super); + + function TimelineAxis(dim, scale, coordExtent, axisType) { + var _this = _super.call(this, dim, scale, coordExtent) || this; + + _this.type = axisType || 'value'; + return _this; + } + + TimelineAxis.prototype.getLabelModel = function () { + return this.model.getModel('label'); + }; + + TimelineAxis.prototype.isHorizontal = function () { + return this.model.get('orient') === 'horizontal'; + }; + + return TimelineAxis; + }(Axis); + + var PI$8 = Math.PI; + var labelDataIndexStore = makeInner(); + + var SliderTimelineView = function (_super) { + __extends(SliderTimelineView, _super); + + function SliderTimelineView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SliderTimelineView.type; + return _this; + } + + SliderTimelineView.prototype.init = function (ecModel, api) { + this.api = api; + }; + + SliderTimelineView.prototype.render = function (timelineModel, ecModel, api) { + this.model = timelineModel; + this.api = api; + this.ecModel = ecModel; + this.group.removeAll(); + + if (timelineModel.get('show', true)) { + var layoutInfo_1 = this._layout(timelineModel, api); + + var mainGroup_1 = this._createGroup('_mainGroup'); + + var labelGroup = this._createGroup('_labelGroup'); + + var axis_1 = this._axis = this._createAxis(layoutInfo_1, timelineModel); + + timelineModel.formatTooltip = function (dataIndex) { + var name = axis_1.scale.getLabel({ + value: dataIndex + }); + return createTooltipMarkup('nameValue', { + noName: true, + value: name + }); + }; + + each(['AxisLine', 'AxisTick', 'Control', 'CurrentPointer'], function (name) { + this['_render' + name](layoutInfo_1, mainGroup_1, axis_1, timelineModel); + }, this); + + this._renderAxisLabel(layoutInfo_1, labelGroup, axis_1, timelineModel); + + this._position(layoutInfo_1, timelineModel); + } + + this._doPlayStop(); + + this._updateTicksStatus(); + }; + + SliderTimelineView.prototype.remove = function () { + this._clearTimer(); + + this.group.removeAll(); + }; + + SliderTimelineView.prototype.dispose = function () { + this._clearTimer(); + }; + + SliderTimelineView.prototype._layout = function (timelineModel, api) { + var labelPosOpt = timelineModel.get(['label', 'position']); + var orient = timelineModel.get('orient'); + var viewRect = getViewRect$5(timelineModel, api); + var parsedLabelPos; + + if (labelPosOpt == null || labelPosOpt === 'auto') { + parsedLabelPos = orient === 'horizontal' ? viewRect.y + viewRect.height / 2 < api.getHeight() / 2 ? '-' : '+' : viewRect.x + viewRect.width / 2 < api.getWidth() / 2 ? '+' : '-'; + } else if (isString(labelPosOpt)) { + parsedLabelPos = { + horizontal: { + top: '-', + bottom: '+' + }, + vertical: { + left: '-', + right: '+' + } + }[orient][labelPosOpt]; + } else { + parsedLabelPos = labelPosOpt; + } + + var labelAlignMap = { + horizontal: 'center', + vertical: parsedLabelPos >= 0 || parsedLabelPos === '+' ? 'left' : 'right' + }; + var labelBaselineMap = { + horizontal: parsedLabelPos >= 0 || parsedLabelPos === '+' ? 'top' : 'bottom', + vertical: 'middle' + }; + var rotationMap = { + horizontal: 0, + vertical: PI$8 / 2 + }; + var mainLength = orient === 'vertical' ? viewRect.height : viewRect.width; + var controlModel = timelineModel.getModel('controlStyle'); + var showControl = controlModel.get('show', true); + var controlSize = showControl ? controlModel.get('itemSize') : 0; + var controlGap = showControl ? controlModel.get('itemGap') : 0; + var sizePlusGap = controlSize + controlGap; + var labelRotation = timelineModel.get(['label', 'rotate']) || 0; + labelRotation = labelRotation * PI$8 / 180; + var playPosition; + var prevBtnPosition; + var nextBtnPosition; + var controlPosition = controlModel.get('position', true); + var showPlayBtn = showControl && controlModel.get('showPlayBtn', true); + var showPrevBtn = showControl && controlModel.get('showPrevBtn', true); + var showNextBtn = showControl && controlModel.get('showNextBtn', true); + var xLeft = 0; + var xRight = mainLength; + + if (controlPosition === 'left' || controlPosition === 'bottom') { + showPlayBtn && (playPosition = [0, 0], xLeft += sizePlusGap); + showPrevBtn && (prevBtnPosition = [xLeft, 0], xLeft += sizePlusGap); + showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap); + } else { + showPlayBtn && (playPosition = [xRight - controlSize, 0], xRight -= sizePlusGap); + showPrevBtn && (prevBtnPosition = [0, 0], xLeft += sizePlusGap); + showNextBtn && (nextBtnPosition = [xRight - controlSize, 0], xRight -= sizePlusGap); + } + + var axisExtent = [xLeft, xRight]; + + if (timelineModel.get('inverse')) { + axisExtent.reverse(); + } + + return { + viewRect: viewRect, + mainLength: mainLength, + orient: orient, + rotation: rotationMap[orient], + labelRotation: labelRotation, + labelPosOpt: parsedLabelPos, + labelAlign: timelineModel.get(['label', 'align']) || labelAlignMap[orient], + labelBaseline: timelineModel.get(['label', 'verticalAlign']) || timelineModel.get(['label', 'baseline']) || labelBaselineMap[orient], + playPosition: playPosition, + prevBtnPosition: prevBtnPosition, + nextBtnPosition: nextBtnPosition, + axisExtent: axisExtent, + controlSize: controlSize, + controlGap: controlGap + }; + }; + + SliderTimelineView.prototype._position = function (layoutInfo, timelineModel) { + var mainGroup = this._mainGroup; + var labelGroup = this._labelGroup; + var viewRect = layoutInfo.viewRect; + + if (layoutInfo.orient === 'vertical') { + var m = create$1(); + var rotateOriginX = viewRect.x; + var rotateOriginY = viewRect.y + viewRect.height; + translate(m, m, [-rotateOriginX, -rotateOriginY]); + rotate(m, m, -PI$8 / 2); + translate(m, m, [rotateOriginX, rotateOriginY]); + viewRect = viewRect.clone(); + viewRect.applyTransform(m); + } + + var viewBound = getBound(viewRect); + var mainBound = getBound(mainGroup.getBoundingRect()); + var labelBound = getBound(labelGroup.getBoundingRect()); + var mainPosition = [mainGroup.x, mainGroup.y]; + var labelsPosition = [labelGroup.x, labelGroup.y]; + labelsPosition[0] = mainPosition[0] = viewBound[0][0]; + var labelPosOpt = layoutInfo.labelPosOpt; + + if (labelPosOpt == null || isString(labelPosOpt)) { + var mainBoundIdx = labelPosOpt === '+' ? 0 : 1; + toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx); + toBound(labelsPosition, labelBound, viewBound, 1, 1 - mainBoundIdx); + } else { + var mainBoundIdx = labelPosOpt >= 0 ? 0 : 1; + toBound(mainPosition, mainBound, viewBound, 1, mainBoundIdx); + labelsPosition[1] = mainPosition[1] + labelPosOpt; + } + + mainGroup.setPosition(mainPosition); + labelGroup.setPosition(labelsPosition); + mainGroup.rotation = labelGroup.rotation = layoutInfo.rotation; + setOrigin(mainGroup); + setOrigin(labelGroup); + + function setOrigin(targetGroup) { + targetGroup.originX = viewBound[0][0] - targetGroup.x; + targetGroup.originY = viewBound[1][0] - targetGroup.y; + } + + function getBound(rect) { + return [[rect.x, rect.x + rect.width], [rect.y, rect.y + rect.height]]; + } + + function toBound(fromPos, from, to, dimIdx, boundIdx) { + fromPos[dimIdx] += to[dimIdx][boundIdx] - from[dimIdx][boundIdx]; + } + }; + + SliderTimelineView.prototype._createAxis = function (layoutInfo, timelineModel) { + var data = timelineModel.getData(); + var axisType = timelineModel.get('axisType'); + var scale = createScaleByModel$1(timelineModel, axisType); + + scale.getTicks = function () { + return data.mapArray(['value'], function (value) { + return { + value: value + }; + }); + }; + + var dataExtent = data.getDataExtent('value'); + scale.setExtent(dataExtent[0], dataExtent[1]); + scale.niceTicks(); + var axis = new TimelineAxis('value', scale, layoutInfo.axisExtent, axisType); + axis.model = timelineModel; + return axis; + }; + + SliderTimelineView.prototype._createGroup = function (key) { + var newGroup = this[key] = new Group(); + this.group.add(newGroup); + return newGroup; + }; + + SliderTimelineView.prototype._renderAxisLine = function (layoutInfo, group, axis, timelineModel) { + var axisExtent = axis.getExtent(); + + if (!timelineModel.get(['lineStyle', 'show'])) { + return; + } + + var line = new Line({ + shape: { + x1: axisExtent[0], + y1: 0, + x2: axisExtent[1], + y2: 0 + }, + style: extend({ + lineCap: 'round' + }, timelineModel.getModel('lineStyle').getLineStyle()), + silent: true, + z2: 1 + }); + group.add(line); + var progressLine = this._progressLine = new Line({ + shape: { + x1: axisExtent[0], + x2: this._currentPointer ? this._currentPointer.x : axisExtent[0], + y1: 0, + y2: 0 + }, + style: defaults({ + lineCap: 'round', + lineWidth: line.style.lineWidth + }, timelineModel.getModel(['progress', 'lineStyle']).getLineStyle()), + silent: true, + z2: 1 + }); + group.add(progressLine); + }; + + SliderTimelineView.prototype._renderAxisTick = function (layoutInfo, group, axis, timelineModel) { + var _this = this; + + var data = timelineModel.getData(); + var ticks = axis.scale.getTicks(); + this._tickSymbols = []; + each(ticks, function (tick) { + var tickCoord = axis.dataToCoord(tick.value); + var itemModel = data.getItemModel(tick.value); + var itemStyleModel = itemModel.getModel('itemStyle'); + var hoverStyleModel = itemModel.getModel(['emphasis', 'itemStyle']); + var progressStyleModel = itemModel.getModel(['progress', 'itemStyle']); + var symbolOpt = { + x: tickCoord, + y: 0, + onclick: bind(_this._changeTimeline, _this, tick.value) + }; + var el = giveSymbol(itemModel, itemStyleModel, group, symbolOpt); + el.ensureState('emphasis').style = hoverStyleModel.getItemStyle(); + el.ensureState('progress').style = progressStyleModel.getItemStyle(); + enableHoverEmphasis(el); + var ecData = getECData(el); + + if (itemModel.get('tooltip')) { + ecData.dataIndex = tick.value; + ecData.dataModel = timelineModel; + } else { + ecData.dataIndex = ecData.dataModel = null; + } + + _this._tickSymbols.push(el); + }); + }; + + SliderTimelineView.prototype._renderAxisLabel = function (layoutInfo, group, axis, timelineModel) { + var _this = this; + + var labelModel = axis.getLabelModel(); + + if (!labelModel.get('show')) { + return; + } + + var data = timelineModel.getData(); + var labels = axis.getViewLabels(); + this._tickLabels = []; + each(labels, function (labelItem) { + var dataIndex = labelItem.tickValue; + var itemModel = data.getItemModel(dataIndex); + var normalLabelModel = itemModel.getModel('label'); + var hoverLabelModel = itemModel.getModel(['emphasis', 'label']); + var progressLabelModel = itemModel.getModel(['progress', 'label']); + var tickCoord = axis.dataToCoord(labelItem.tickValue); + var textEl = new ZRText({ + x: tickCoord, + y: 0, + rotation: layoutInfo.labelRotation - layoutInfo.rotation, + onclick: bind(_this._changeTimeline, _this, dataIndex), + silent: false, + style: createTextStyle(normalLabelModel, { + text: labelItem.formattedLabel, + align: layoutInfo.labelAlign, + verticalAlign: layoutInfo.labelBaseline + }) + }); + textEl.ensureState('emphasis').style = createTextStyle(hoverLabelModel); + textEl.ensureState('progress').style = createTextStyle(progressLabelModel); + group.add(textEl); + enableHoverEmphasis(textEl); + labelDataIndexStore(textEl).dataIndex = dataIndex; + + _this._tickLabels.push(textEl); + }); + }; + + SliderTimelineView.prototype._renderControl = function (layoutInfo, group, axis, timelineModel) { + var controlSize = layoutInfo.controlSize; + var rotation = layoutInfo.rotation; + var itemStyle = timelineModel.getModel('controlStyle').getItemStyle(); + var hoverStyle = timelineModel.getModel(['emphasis', 'controlStyle']).getItemStyle(); + var playState = timelineModel.getPlayState(); + var inverse = timelineModel.get('inverse', true); + makeBtn(layoutInfo.nextBtnPosition, 'next', bind(this._changeTimeline, this, inverse ? '-' : '+')); + makeBtn(layoutInfo.prevBtnPosition, 'prev', bind(this._changeTimeline, this, inverse ? '+' : '-')); + makeBtn(layoutInfo.playPosition, playState ? 'stop' : 'play', bind(this._handlePlayClick, this, !playState), true); + + function makeBtn(position, iconName, onclick, willRotate) { + if (!position) { + return; + } + + var iconSize = parsePercent(retrieve2(timelineModel.get(['controlStyle', iconName + 'BtnSize']), controlSize), controlSize); + var rect = [0, -iconSize / 2, iconSize, iconSize]; + var opt = { + position: position, + origin: [controlSize / 2, 0], + rotation: willRotate ? -rotation : 0, + rectHover: true, + style: itemStyle, + onclick: onclick + }; + var btn = makeControlIcon(timelineModel, iconName + 'Icon', rect, opt); + btn.ensureState('emphasis').style = hoverStyle; + group.add(btn); + enableHoverEmphasis(btn); + } + }; + + SliderTimelineView.prototype._renderCurrentPointer = function (layoutInfo, group, axis, timelineModel) { + var data = timelineModel.getData(); + var currentIndex = timelineModel.getCurrentIndex(); + var pointerModel = data.getItemModel(currentIndex).getModel('checkpointStyle'); + var me = this; + var callback = { + onCreate: function (pointer) { + pointer.draggable = true; + pointer.drift = bind(me._handlePointerDrag, me); + pointer.ondragend = bind(me._handlePointerDragend, me); + pointerMoveTo(pointer, me._progressLine, currentIndex, axis, timelineModel, true); + }, + onUpdate: function (pointer) { + pointerMoveTo(pointer, me._progressLine, currentIndex, axis, timelineModel); + } + }; + this._currentPointer = giveSymbol(pointerModel, pointerModel, this._mainGroup, {}, this._currentPointer, callback); + }; + + SliderTimelineView.prototype._handlePlayClick = function (nextState) { + this._clearTimer(); + + this.api.dispatchAction({ + type: 'timelinePlayChange', + playState: nextState, + from: this.uid + }); + }; + + SliderTimelineView.prototype._handlePointerDrag = function (dx, dy, e) { + this._clearTimer(); + + this._pointerChangeTimeline([e.offsetX, e.offsetY]); + }; + + SliderTimelineView.prototype._handlePointerDragend = function (e) { + this._pointerChangeTimeline([e.offsetX, e.offsetY], true); + }; + + SliderTimelineView.prototype._pointerChangeTimeline = function (mousePos, trigger) { + var toCoord = this._toAxisCoord(mousePos)[0]; + + var axis = this._axis; + var axisExtent = asc(axis.getExtent().slice()); + toCoord > axisExtent[1] && (toCoord = axisExtent[1]); + toCoord < axisExtent[0] && (toCoord = axisExtent[0]); + this._currentPointer.x = toCoord; + + this._currentPointer.markRedraw(); + + this._progressLine.shape.x2 = toCoord; + + this._progressLine.dirty(); + + var targetDataIndex = this._findNearestTick(toCoord); + + var timelineModel = this.model; + + if (trigger || targetDataIndex !== timelineModel.getCurrentIndex() && timelineModel.get('realtime')) { + this._changeTimeline(targetDataIndex); + } + }; + + SliderTimelineView.prototype._doPlayStop = function () { + var _this = this; + + this._clearTimer(); + + if (this.model.getPlayState()) { + this._timer = setTimeout(function () { + var timelineModel = _this.model; + + _this._changeTimeline(timelineModel.getCurrentIndex() + (timelineModel.get('rewind', true) ? -1 : 1)); + }, this.model.get('playInterval')); + } + }; + + SliderTimelineView.prototype._toAxisCoord = function (vertex) { + var trans = this._mainGroup.getLocalTransform(); + + return applyTransform$1(vertex, trans, true); + }; + + SliderTimelineView.prototype._findNearestTick = function (axisCoord) { + var data = this.model.getData(); + var dist = Infinity; + var targetDataIndex; + var axis = this._axis; + data.each(['value'], function (value, dataIndex) { + var coord = axis.dataToCoord(value); + var d = Math.abs(coord - axisCoord); + + if (d < dist) { + dist = d; + targetDataIndex = dataIndex; + } + }); + return targetDataIndex; + }; + + SliderTimelineView.prototype._clearTimer = function () { + if (this._timer) { + clearTimeout(this._timer); + this._timer = null; + } + }; + + SliderTimelineView.prototype._changeTimeline = function (nextIndex) { + var currentIndex = this.model.getCurrentIndex(); + + if (nextIndex === '+') { + nextIndex = currentIndex + 1; + } else if (nextIndex === '-') { + nextIndex = currentIndex - 1; + } + + this.api.dispatchAction({ + type: 'timelineChange', + currentIndex: nextIndex, + from: this.uid + }); + }; + + SliderTimelineView.prototype._updateTicksStatus = function () { + var currentIndex = this.model.getCurrentIndex(); + var tickSymbols = this._tickSymbols; + var tickLabels = this._tickLabels; + + if (tickSymbols) { + for (var i = 0; i < tickSymbols.length; i++) { + tickSymbols && tickSymbols[i] && tickSymbols[i].toggleState('progress', i < currentIndex); + } + } + + if (tickLabels) { + for (var i = 0; i < tickLabels.length; i++) { + tickLabels && tickLabels[i] && tickLabels[i].toggleState('progress', labelDataIndexStore(tickLabels[i]).dataIndex <= currentIndex); + } + } + }; + + SliderTimelineView.type = 'timeline.slider'; + return SliderTimelineView; + }(TimelineView); + + function createScaleByModel$1(model, axisType) { + axisType = axisType || model.get('type'); + + if (axisType) { + switch (axisType) { + case 'category': + return new OrdinalScale({ + ordinalMeta: model.getCategories(), + extent: [Infinity, -Infinity] + }); + + case 'time': + return new TimeScale({ + locale: model.ecModel.getLocaleModel(), + useUTC: model.ecModel.get('useUTC') + }); + + default: + return new IntervalScale(); + } + } + } + + function getViewRect$5(model, api) { + return getLayoutRect(model.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }, model.get('padding')); + } + + function makeControlIcon(timelineModel, objPath, rect, opts) { + var style = opts.style; + var icon = createIcon(timelineModel.get(['controlStyle', objPath]), opts || {}, new BoundingRect(rect[0], rect[1], rect[2], rect[3])); + + if (style) { + icon.setStyle(style); + } + + return icon; + } + + function giveSymbol(hostModel, itemStyleModel, group, opt, symbol, callback) { + var color = itemStyleModel.get('color'); + + if (!symbol) { + var symbolType = hostModel.get('symbol'); + symbol = createSymbol(symbolType, -1, -1, 2, 2, color); + symbol.setStyle('strokeNoScale', true); + group.add(symbol); + callback && callback.onCreate(symbol); + } else { + symbol.setColor(color); + group.add(symbol); + callback && callback.onUpdate(symbol); + } + + var itemStyle = itemStyleModel.getItemStyle(['color']); + symbol.setStyle(itemStyle); + opt = merge({ + rectHover: true, + z2: 100 + }, opt, true); + var symbolSize = hostModel.get('symbolSize'); + symbolSize = symbolSize instanceof Array ? symbolSize.slice() : [+symbolSize, +symbolSize]; + opt.scaleX = symbolSize[0] / 2; + opt.scaleY = symbolSize[1] / 2; + var symbolOffset = hostModel.get('symbolOffset'); + + if (symbolOffset) { + opt.x = opt.x || 0; + opt.y = opt.y || 0; + opt.x += parsePercent$1(symbolOffset[0], symbolSize[0]); + opt.y += parsePercent$1(symbolOffset[1], symbolSize[1]); + } + + var symbolRotate = hostModel.get('symbolRotate'); + opt.rotation = (symbolRotate || 0) * Math.PI / 180 || 0; + symbol.attr(opt); + symbol.updateTransform(); + return symbol; + } + + function pointerMoveTo(pointer, progressLine, dataIndex, axis, timelineModel, noAnimation) { + if (pointer.dragging) { + return; + } + + var pointerModel = timelineModel.getModel('checkpointStyle'); + var toCoord = axis.dataToCoord(timelineModel.getData().get('value', dataIndex)); + + if (noAnimation || !pointerModel.get('animation', true)) { + pointer.attr({ + x: toCoord, + y: 0 + }); + progressLine && progressLine.attr({ + shape: { + x2: toCoord + } + }); + } else { + var animationCfg = { + duration: pointerModel.get('animationDuration', true), + easing: pointerModel.get('animationEasing', true) + }; + pointer.stopAnimation(null, true); + pointer.animateTo({ + x: toCoord, + y: 0 + }, animationCfg); + progressLine && progressLine.animateTo({ + shape: { + x2: toCoord + } + }, animationCfg); + } + } + + function installTimelineAction(registers) { + registers.registerAction({ + type: 'timelineChange', + event: 'timelineChanged', + update: 'prepareAndUpdate' + }, function (payload, ecModel) { + var timelineModel = ecModel.getComponent('timeline'); + + if (timelineModel && payload.currentIndex != null) { + timelineModel.setCurrentIndex(payload.currentIndex); + + if (!timelineModel.get('loop', true) && timelineModel.isIndexMax()) { + timelineModel.setPlayState(false); + } + } + + ecModel.resetOption('timeline', { + replaceMerge: timelineModel.get('replaceMerge', true) + }); + return defaults({ + currentIndex: timelineModel.option.currentIndex + }, payload); + }); + registers.registerAction({ + type: 'timelinePlayChange', + event: 'timelinePlayChanged', + update: 'update' + }, function (payload, ecModel) { + var timelineModel = ecModel.getComponent('timeline'); + + if (timelineModel && payload.playState != null) { + timelineModel.setPlayState(payload.playState); + } + }); + } + + function timelinePreprocessor(option) { + var timelineOpt = option && option.timeline; + + if (!isArray(timelineOpt)) { + timelineOpt = timelineOpt ? [timelineOpt] : []; + } + + each(timelineOpt, function (opt) { + if (!opt) { + return; + } + + compatibleEC2(opt); + }); + } + + function compatibleEC2(opt) { + var type = opt.type; + var ec2Types = { + 'number': 'value', + 'time': 'time' + }; + + if (ec2Types[type]) { + opt.axisType = ec2Types[type]; + delete opt.type; + } + + transferItem(opt); + + if (has(opt, 'controlPosition')) { + var controlStyle = opt.controlStyle || (opt.controlStyle = {}); + + if (!has(controlStyle, 'position')) { + controlStyle.position = opt.controlPosition; + } + + if (controlStyle.position === 'none' && !has(controlStyle, 'show')) { + controlStyle.show = false; + delete controlStyle.position; + } + + delete opt.controlPosition; + } + + each(opt.data || [], function (dataItem) { + if (isObject(dataItem) && !isArray(dataItem)) { + if (!has(dataItem, 'value') && has(dataItem, 'name')) { + dataItem.value = dataItem.name; + } + + transferItem(dataItem); + } + }); + } + + function transferItem(opt) { + var itemStyle = opt.itemStyle || (opt.itemStyle = {}); + var itemStyleEmphasis = itemStyle.emphasis || (itemStyle.emphasis = {}); + var label = opt.label || opt.label || {}; + var labelNormal = label.normal || (label.normal = {}); + var excludeLabelAttr = { + normal: 1, + emphasis: 1 + }; + each(label, function (value, name) { + if (!excludeLabelAttr[name] && !has(labelNormal, name)) { + labelNormal[name] = value; + } + }); + + if (itemStyleEmphasis.label && !has(label, 'emphasis')) { + label.emphasis = itemStyleEmphasis.label; + delete itemStyleEmphasis.label; + } + } + + function has(obj, attr) { + return obj.hasOwnProperty(attr); + } + + function install$D(registers) { + registers.registerComponentModel(SliderTimelineModel); + registers.registerComponentView(SliderTimelineView); + registers.registerSubTypeDefaulter('timeline', function () { + return 'slider'; + }); + installTimelineAction(registers); + registers.registerPreprocessor(timelinePreprocessor); + } + + function fillLabel(opt) { + defaultEmphasis(opt, 'label', ['show']); + } + + var inner$i = makeInner(); + + var MarkerModel = function (_super) { + __extends(MarkerModel, _super); + + function MarkerModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkerModel.type; + _this.createdBySelf = false; + return _this; + } + + MarkerModel.prototype.init = function (option, parentModel, ecModel) { + if ("development" !== 'production') { + if (this.type === 'marker') { + throw new Error('Marker component is abstract component. Use markLine, markPoint, markArea instead.'); + } + } + + this.mergeDefaultAndTheme(option, ecModel); + + this._mergeOption(option, ecModel, false, true); + }; + + MarkerModel.prototype.isAnimationEnabled = function () { + if (env.node) { + return false; + } + + var hostSeries = this.__hostSeries; + return this.getShallow('animation') && hostSeries && hostSeries.isAnimationEnabled(); + }; + + MarkerModel.prototype.mergeOption = function (newOpt, ecModel) { + this._mergeOption(newOpt, ecModel, false, false); + }; + + MarkerModel.prototype._mergeOption = function (newOpt, ecModel, createdBySelf, isInit) { + var componentType = this.mainType; + + if (!createdBySelf) { + ecModel.eachSeries(function (seriesModel) { + var markerOpt = seriesModel.get(this.mainType, true); + var markerModel = inner$i(seriesModel)[componentType]; + + if (!markerOpt || !markerOpt.data) { + inner$i(seriesModel)[componentType] = null; + return; + } + + if (!markerModel) { + if (isInit) { + fillLabel(markerOpt); + } + + each(markerOpt.data, function (item) { + if (item instanceof Array) { + fillLabel(item[0]); + fillLabel(item[1]); + } else { + fillLabel(item); + } + }); + markerModel = this.createMarkerModelFromSeries(markerOpt, this, ecModel); + extend(markerModel, { + mainType: this.mainType, + seriesIndex: seriesModel.seriesIndex, + name: seriesModel.name, + createdBySelf: true + }); + markerModel.__hostSeries = seriesModel; + } else { + markerModel._mergeOption(markerOpt, ecModel, true); + } + + inner$i(seriesModel)[componentType] = markerModel; + }, this); + } + }; + + MarkerModel.prototype.formatTooltip = function (dataIndex, multipleSeries, dataType) { + var data = this.getData(); + var value = this.getRawValue(dataIndex); + var itemName = data.getName(dataIndex); + return createTooltipMarkup('section', { + header: this.name, + blocks: [createTooltipMarkup('nameValue', { + name: itemName, + value: value, + noName: !itemName, + noValue: value == null + })] + }); + }; + + MarkerModel.prototype.getData = function () { + return this._data; + }; + + MarkerModel.prototype.setData = function (data) { + this._data = data; + }; + + MarkerModel.getMarkerModelFromSeries = function (seriesModel, componentType) { + return inner$i(seriesModel)[componentType]; + }; + + MarkerModel.type = 'marker'; + MarkerModel.dependencies = ['series', 'grid', 'polar', 'geo']; + return MarkerModel; + }(ComponentModel); + + mixin(MarkerModel, DataFormatMixin.prototype); + + var MarkPointModel = function (_super) { + __extends(MarkPointModel, _super); + + function MarkPointModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkPointModel.type; + return _this; + } + + MarkPointModel.prototype.createMarkerModelFromSeries = function (markerOpt, masterMarkerModel, ecModel) { + return new MarkPointModel(markerOpt, masterMarkerModel, ecModel); + }; + + MarkPointModel.type = 'markPoint'; + MarkPointModel.defaultOption = { + zlevel: 0, + z: 5, + symbol: 'pin', + symbolSize: 50, + tooltip: { + trigger: 'item' + }, + label: { + show: true, + position: 'inside' + }, + itemStyle: { + borderWidth: 2 + }, + emphasis: { + label: { + show: true + } + } + }; + return MarkPointModel; + }(MarkerModel); + + function hasXOrY(item) { + return !(isNaN(parseFloat(item.x)) && isNaN(parseFloat(item.y))); + } + + function hasXAndY(item) { + return !isNaN(parseFloat(item.x)) && !isNaN(parseFloat(item.y)); + } + + function markerTypeCalculatorWithExtent(markerType, data, otherDataDim, targetDataDim, otherCoordIndex, targetCoordIndex) { + var coordArr = []; + var stacked = isDimensionStacked(data, targetDataDim); + var calcDataDim = stacked ? data.getCalculationInfo('stackResultDimension') : targetDataDim; + var value = numCalculate(data, calcDataDim, markerType); + var dataIndex = data.indicesOfNearest(calcDataDim, value)[0]; + coordArr[otherCoordIndex] = data.get(otherDataDim, dataIndex); + coordArr[targetCoordIndex] = data.get(calcDataDim, dataIndex); + var coordArrValue = data.get(targetDataDim, dataIndex); + var precision = getPrecision(data.get(targetDataDim, dataIndex)); + precision = Math.min(precision, 20); + + if (precision >= 0) { + coordArr[targetCoordIndex] = +coordArr[targetCoordIndex].toFixed(precision); + } + + return [coordArr, coordArrValue]; + } + + var markerTypeCalculator = { + min: curry(markerTypeCalculatorWithExtent, 'min'), + max: curry(markerTypeCalculatorWithExtent, 'max'), + average: curry(markerTypeCalculatorWithExtent, 'average'), + median: curry(markerTypeCalculatorWithExtent, 'median') + }; + function dataTransform(seriesModel, item) { + var data = seriesModel.getData(); + var coordSys = seriesModel.coordinateSystem; + + if (item && !hasXAndY(item) && !isArray(item.coord) && coordSys) { + var dims = coordSys.dimensions; + var axisInfo = getAxisInfo$1(item, data, coordSys, seriesModel); + item = clone(item); + + if (item.type && markerTypeCalculator[item.type] && axisInfo.baseAxis && axisInfo.valueAxis) { + var otherCoordIndex = indexOf(dims, axisInfo.baseAxis.dim); + var targetCoordIndex = indexOf(dims, axisInfo.valueAxis.dim); + var coordInfo = markerTypeCalculator[item.type](data, axisInfo.baseDataDim, axisInfo.valueDataDim, otherCoordIndex, targetCoordIndex); + item.coord = coordInfo[0]; + item.value = coordInfo[1]; + } else { + var coord = [item.xAxis != null ? item.xAxis : item.radiusAxis, item.yAxis != null ? item.yAxis : item.angleAxis]; + + for (var i = 0; i < 2; i++) { + if (markerTypeCalculator[coord[i]]) { + coord[i] = numCalculate(data, data.mapDimension(dims[i]), coord[i]); + } + } + + item.coord = coord; + } + } + + return item; + } + function getAxisInfo$1(item, data, coordSys, seriesModel) { + var ret = {}; + + if (item.valueIndex != null || item.valueDim != null) { + ret.valueDataDim = item.valueIndex != null ? data.getDimension(item.valueIndex) : item.valueDim; + ret.valueAxis = coordSys.getAxis(dataDimToCoordDim(seriesModel, ret.valueDataDim)); + ret.baseAxis = coordSys.getOtherAxis(ret.valueAxis); + ret.baseDataDim = data.mapDimension(ret.baseAxis.dim); + } else { + ret.baseAxis = seriesModel.getBaseAxis(); + ret.valueAxis = coordSys.getOtherAxis(ret.baseAxis); + ret.baseDataDim = data.mapDimension(ret.baseAxis.dim); + ret.valueDataDim = data.mapDimension(ret.valueAxis.dim); + } + + return ret; + } + + function dataDimToCoordDim(seriesModel, dataDim) { + var data = seriesModel.getData(); + var dimensions = data.dimensions; + dataDim = data.getDimension(dataDim); + + for (var i = 0; i < dimensions.length; i++) { + var dimItem = data.getDimensionInfo(dimensions[i]); + + if (dimItem.name === dataDim) { + return dimItem.coordDim; + } + } + } + + function dataFilter$1(coordSys, item) { + return coordSys && coordSys.containData && item.coord && !hasXOrY(item) ? coordSys.containData(item.coord) : true; + } + function dimValueGetter(item, dimName, dataIndex, dimIndex) { + if (dimIndex < 2) { + return item.coord && item.coord[dimIndex]; + } + + return item.value; + } + function numCalculate(data, valueDataDim, type) { + if (type === 'average') { + var sum_1 = 0; + var count_1 = 0; + data.each(valueDataDim, function (val, idx) { + if (!isNaN(val)) { + sum_1 += val; + count_1++; + } + }); + return sum_1 / count_1; + } else if (type === 'median') { + return data.getMedian(valueDataDim); + } else { + return data.getDataExtent(valueDataDim)[type === 'max' ? 1 : 0]; + } + } + + var inner$j = makeInner(); + + var MarkerView = function (_super) { + __extends(MarkerView, _super); + + function MarkerView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkerView.type; + return _this; + } + + MarkerView.prototype.init = function () { + this.markerGroupMap = createHashMap(); + }; + + MarkerView.prototype.render = function (markerModel, ecModel, api) { + var _this = this; + + var markerGroupMap = this.markerGroupMap; + markerGroupMap.each(function (item) { + inner$j(item).keep = false; + }); + ecModel.eachSeries(function (seriesModel) { + var markerModel = MarkerModel.getMarkerModelFromSeries(seriesModel, _this.type); + markerModel && _this.renderSeries(seriesModel, markerModel, ecModel, api); + }); + markerGroupMap.each(function (item) { + !inner$j(item).keep && _this.group.remove(item.group); + }); + }; + + MarkerView.prototype.markKeep = function (drawGroup) { + inner$j(drawGroup).keep = true; + }; + + MarkerView.prototype.blurSeries = function (seriesModelList) { + var _this = this; + + each(seriesModelList, function (seriesModel) { + var markerModel = MarkerModel.getMarkerModelFromSeries(seriesModel, _this.type); + + if (markerModel) { + var data = markerModel.getData(); + data.eachItemGraphicEl(function (el) { + if (el) { + enterBlur(el); + } + }); + } + }); + }; + + MarkerView.type = 'marker'; + return MarkerView; + }(ComponentView); + + function updateMarkerLayout(mpData, seriesModel, api) { + var coordSys = seriesModel.coordinateSystem; + mpData.each(function (idx) { + var itemModel = mpData.getItemModel(idx); + var point; + var xPx = parsePercent$1(itemModel.get('x'), api.getWidth()); + var yPx = parsePercent$1(itemModel.get('y'), api.getHeight()); + + if (!isNaN(xPx) && !isNaN(yPx)) { + point = [xPx, yPx]; + } else if (seriesModel.getMarkerPosition) { + point = seriesModel.getMarkerPosition(mpData.getValues(mpData.dimensions, idx)); + } else if (coordSys) { + var x = mpData.get(coordSys.dimensions[0], idx); + var y = mpData.get(coordSys.dimensions[1], idx); + point = coordSys.dataToPoint([x, y]); + } + + if (!isNaN(xPx)) { + point[0] = xPx; + } + + if (!isNaN(yPx)) { + point[1] = yPx; + } + + mpData.setItemLayout(idx, point); + }); + } + + var MarkPointView = function (_super) { + __extends(MarkPointView, _super); + + function MarkPointView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkPointView.type; + return _this; + } + + MarkPointView.prototype.updateTransform = function (markPointModel, ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + var mpModel = MarkerModel.getMarkerModelFromSeries(seriesModel, 'markPoint'); + + if (mpModel) { + updateMarkerLayout(mpModel.getData(), seriesModel, api); + this.markerGroupMap.get(seriesModel.id).updateLayout(); + } + }, this); + }; + + MarkPointView.prototype.renderSeries = function (seriesModel, mpModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + var seriesId = seriesModel.id; + var seriesData = seriesModel.getData(); + var symbolDrawMap = this.markerGroupMap; + var symbolDraw = symbolDrawMap.get(seriesId) || symbolDrawMap.set(seriesId, new SymbolDraw()); + var mpData = createList$1(coordSys, seriesModel, mpModel); + mpModel.setData(mpData); + updateMarkerLayout(mpModel.getData(), seriesModel, api); + mpData.each(function (idx) { + var itemModel = mpData.getItemModel(idx); + var symbol = itemModel.getShallow('symbol'); + var symbolSize = itemModel.getShallow('symbolSize'); + var symbolRotate = itemModel.getShallow('symbolRotate'); + + if (isFunction(symbol) || isFunction(symbolSize) || isFunction(symbolRotate)) { + var rawIdx = mpModel.getRawValue(idx); + var dataParams = mpModel.getDataParams(idx); + + if (isFunction(symbol)) { + symbol = symbol(rawIdx, dataParams); + } + + if (isFunction(symbolSize)) { + symbolSize = symbolSize(rawIdx, dataParams); + } + + if (isFunction(symbolRotate)) { + symbolRotate = symbolRotate(rawIdx, dataParams); + } + } + + var style = itemModel.getModel('itemStyle').getItemStyle(); + var color = getVisualFromData(seriesData, 'color'); + + if (!style.fill) { + style.fill = color; + } + + mpData.setItemVisual(idx, { + symbol: symbol, + symbolSize: symbolSize, + symbolRotate: symbolRotate, + style: style + }); + }); + symbolDraw.updateData(mpData); + this.group.add(symbolDraw.group); + mpData.eachItemGraphicEl(function (el) { + el.traverse(function (child) { + getECData(child).dataModel = mpModel; + }); + }); + this.markKeep(symbolDraw); + symbolDraw.group.silent = mpModel.get('silent') || seriesModel.get('silent'); + }; + + MarkPointView.type = 'markPoint'; + return MarkPointView; + }(MarkerView); + + function createList$1(coordSys, seriesModel, mpModel) { + var coordDimsInfos; + + if (coordSys) { + coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) { + var info = seriesModel.getData().getDimensionInfo(seriesModel.getData().mapDimension(coordDim)) || {}; + return defaults({ + name: coordDim + }, info); + }); + } else { + coordDimsInfos = [{ + name: 'value', + type: 'float' + }]; + } + + var mpData = new List(coordDimsInfos, mpModel); + var dataOpt = map(mpModel.get('data'), curry(dataTransform, seriesModel)); + + if (coordSys) { + dataOpt = filter(dataOpt, curry(dataFilter$1, coordSys)); + } + + mpData.initData(dataOpt, null, coordSys ? dimValueGetter : function (item) { + return item.value; + }); + return mpData; + } + + function install$E(registers) { + registers.registerComponentModel(MarkPointModel); + registers.registerComponentView(MarkPointView); + registers.registerPreprocessor(function (opt) { + opt.markPoint = opt.markPoint || {}; + }); + } + + var MarkLineModel = function (_super) { + __extends(MarkLineModel, _super); + + function MarkLineModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkLineModel.type; + return _this; + } + + MarkLineModel.prototype.createMarkerModelFromSeries = function (markerOpt, masterMarkerModel, ecModel) { + return new MarkLineModel(markerOpt, masterMarkerModel, ecModel); + }; + + MarkLineModel.type = 'markLine'; + MarkLineModel.defaultOption = { + zlevel: 0, + z: 5, + symbol: ['circle', 'arrow'], + symbolSize: [8, 16], + precision: 2, + tooltip: { + trigger: 'item' + }, + label: { + show: true, + position: 'end', + distance: 5 + }, + lineStyle: { + type: 'dashed' + }, + emphasis: { + label: { + show: true + }, + lineStyle: { + width: 3 + } + }, + animationEasing: 'linear' + }; + return MarkLineModel; + }(MarkerModel); + + var inner$k = makeInner(); + + var markLineTransform = function (seriesModel, coordSys, mlModel, item) { + var data = seriesModel.getData(); + var itemArray; + + if (!isArray(item)) { + var mlType = item.type; + + if (mlType === 'min' || mlType === 'max' || mlType === 'average' || mlType === 'median' || item.xAxis != null || item.yAxis != null) { + var valueAxis = void 0; + var value = void 0; + + if (item.yAxis != null || item.xAxis != null) { + valueAxis = coordSys.getAxis(item.yAxis != null ? 'y' : 'x'); + value = retrieve(item.yAxis, item.xAxis); + } else { + var axisInfo = getAxisInfo$1(item, data, coordSys, seriesModel); + valueAxis = axisInfo.valueAxis; + var valueDataDim = getStackedDimension(data, axisInfo.valueDataDim); + value = numCalculate(data, valueDataDim, mlType); + } + + var valueIndex = valueAxis.dim === 'x' ? 0 : 1; + var baseIndex = 1 - valueIndex; + var mlFrom = clone(item); + var mlTo = { + coord: [] + }; + mlFrom.type = null; + mlFrom.coord = []; + mlFrom.coord[baseIndex] = -Infinity; + mlTo.coord[baseIndex] = Infinity; + var precision = mlModel.get('precision'); + + if (precision >= 0 && typeof value === 'number') { + value = +value.toFixed(Math.min(precision, 20)); + } + + mlFrom.coord[valueIndex] = mlTo.coord[valueIndex] = value; + itemArray = [mlFrom, mlTo, { + type: mlType, + valueIndex: item.valueIndex, + value: value + }]; + } else { + if ("development" !== 'production') { + logError('Invalid markLine data.'); + } + + itemArray = []; + } + } else { + itemArray = item; + } + + var normalizedItem = [dataTransform(seriesModel, itemArray[0]), dataTransform(seriesModel, itemArray[1]), extend({}, itemArray[2])]; + normalizedItem[2].type = normalizedItem[2].type || null; + merge(normalizedItem[2], normalizedItem[0]); + merge(normalizedItem[2], normalizedItem[1]); + return normalizedItem; + }; + + function isInifinity(val) { + return !isNaN(val) && !isFinite(val); + } + + function ifMarkLineHasOnlyDim(dimIndex, fromCoord, toCoord, coordSys) { + var otherDimIndex = 1 - dimIndex; + var dimName = coordSys.dimensions[dimIndex]; + return isInifinity(fromCoord[otherDimIndex]) && isInifinity(toCoord[otherDimIndex]) && fromCoord[dimIndex] === toCoord[dimIndex] && coordSys.getAxis(dimName).containData(fromCoord[dimIndex]); + } + + function markLineFilter(coordSys, item) { + if (coordSys.type === 'cartesian2d') { + var fromCoord = item[0].coord; + var toCoord = item[1].coord; + + if (fromCoord && toCoord && (ifMarkLineHasOnlyDim(1, fromCoord, toCoord, coordSys) || ifMarkLineHasOnlyDim(0, fromCoord, toCoord, coordSys))) { + return true; + } + } + + return dataFilter$1(coordSys, item[0]) && dataFilter$1(coordSys, item[1]); + } + + function updateSingleMarkerEndLayout(data, idx, isFrom, seriesModel, api) { + var coordSys = seriesModel.coordinateSystem; + var itemModel = data.getItemModel(idx); + var point; + var xPx = parsePercent$1(itemModel.get('x'), api.getWidth()); + var yPx = parsePercent$1(itemModel.get('y'), api.getHeight()); + + if (!isNaN(xPx) && !isNaN(yPx)) { + point = [xPx, yPx]; + } else { + if (seriesModel.getMarkerPosition) { + point = seriesModel.getMarkerPosition(data.getValues(data.dimensions, idx)); + } else { + var dims = coordSys.dimensions; + var x = data.get(dims[0], idx); + var y = data.get(dims[1], idx); + point = coordSys.dataToPoint([x, y]); + } + + if (isCoordinateSystemType(coordSys, 'cartesian2d')) { + var xAxis = coordSys.getAxis('x'); + var yAxis = coordSys.getAxis('y'); + var dims = coordSys.dimensions; + + if (isInifinity(data.get(dims[0], idx))) { + point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[isFrom ? 0 : 1]); + } else if (isInifinity(data.get(dims[1], idx))) { + point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[isFrom ? 0 : 1]); + } + } + + if (!isNaN(xPx)) { + point[0] = xPx; + } + + if (!isNaN(yPx)) { + point[1] = yPx; + } + } + + data.setItemLayout(idx, point); + } + + var MarkLineView = function (_super) { + __extends(MarkLineView, _super); + + function MarkLineView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkLineView.type; + return _this; + } + + MarkLineView.prototype.updateTransform = function (markLineModel, ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + var mlModel = MarkerModel.getMarkerModelFromSeries(seriesModel, 'markLine'); + + if (mlModel) { + var mlData_1 = mlModel.getData(); + var fromData_1 = inner$k(mlModel).from; + var toData_1 = inner$k(mlModel).to; + fromData_1.each(function (idx) { + updateSingleMarkerEndLayout(fromData_1, idx, true, seriesModel, api); + updateSingleMarkerEndLayout(toData_1, idx, false, seriesModel, api); + }); + mlData_1.each(function (idx) { + mlData_1.setItemLayout(idx, [fromData_1.getItemLayout(idx), toData_1.getItemLayout(idx)]); + }); + this.markerGroupMap.get(seriesModel.id).updateLayout(); + } + }, this); + }; + + MarkLineView.prototype.renderSeries = function (seriesModel, mlModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + var seriesId = seriesModel.id; + var seriesData = seriesModel.getData(); + var lineDrawMap = this.markerGroupMap; + var lineDraw = lineDrawMap.get(seriesId) || lineDrawMap.set(seriesId, new LineDraw()); + this.group.add(lineDraw.group); + var mlData = createList$2(coordSys, seriesModel, mlModel); + var fromData = mlData.from; + var toData = mlData.to; + var lineData = mlData.line; + inner$k(mlModel).from = fromData; + inner$k(mlModel).to = toData; + mlModel.setData(lineData); + var symbolType = mlModel.get('symbol'); + var symbolSize = mlModel.get('symbolSize'); + + if (!isArray(symbolType)) { + symbolType = [symbolType, symbolType]; + } + + if (!isArray(symbolSize)) { + symbolSize = [symbolSize, symbolSize]; + } + + mlData.from.each(function (idx) { + updateDataVisualAndLayout(fromData, idx, true); + updateDataVisualAndLayout(toData, idx, false); + }); + lineData.each(function (idx) { + var lineStyle = lineData.getItemModel(idx).getModel('lineStyle').getLineStyle(); + lineData.setItemLayout(idx, [fromData.getItemLayout(idx), toData.getItemLayout(idx)]); + + if (lineStyle.stroke == null) { + lineStyle.stroke = fromData.getItemVisual(idx, 'style').fill; + } + + lineData.setItemVisual(idx, { + fromSymbolRotate: fromData.getItemVisual(idx, 'symbolRotate'), + fromSymbolSize: fromData.getItemVisual(idx, 'symbolSize'), + fromSymbol: fromData.getItemVisual(idx, 'symbol'), + toSymbolRotate: toData.getItemVisual(idx, 'symbolRotate'), + toSymbolSize: toData.getItemVisual(idx, 'symbolSize'), + toSymbol: toData.getItemVisual(idx, 'symbol'), + style: lineStyle + }); + }); + lineDraw.updateData(lineData); + mlData.line.eachItemGraphicEl(function (el, idx) { + el.traverse(function (child) { + getECData(child).dataModel = mlModel; + }); + }); + + function updateDataVisualAndLayout(data, idx, isFrom) { + var itemModel = data.getItemModel(idx); + updateSingleMarkerEndLayout(data, idx, isFrom, seriesModel, api); + var style = itemModel.getModel('itemStyle').getItemStyle(); + + if (style.fill == null) { + style.fill = getVisualFromData(seriesData, 'color'); + } + + data.setItemVisual(idx, { + symbolRotate: itemModel.get('symbolRotate'), + symbolSize: itemModel.get('symbolSize') || symbolSize[isFrom ? 0 : 1], + symbol: itemModel.get('symbol', true) || symbolType[isFrom ? 0 : 1], + style: style + }); + } + + this.markKeep(lineDraw); + lineDraw.group.silent = mlModel.get('silent') || seriesModel.get('silent'); + }; + + MarkLineView.type = 'markLine'; + return MarkLineView; + }(MarkerView); + + function createList$2(coordSys, seriesModel, mlModel) { + var coordDimsInfos; + + if (coordSys) { + coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) { + var info = seriesModel.getData().getDimensionInfo(seriesModel.getData().mapDimension(coordDim)) || {}; + return defaults({ + name: coordDim + }, info); + }); + } else { + coordDimsInfos = [{ + name: 'value', + type: 'float' + }]; + } + + var fromData = new List(coordDimsInfos, mlModel); + var toData = new List(coordDimsInfos, mlModel); + var lineData = new List([], mlModel); + var optData = map(mlModel.get('data'), curry(markLineTransform, seriesModel, coordSys, mlModel)); + + if (coordSys) { + optData = filter(optData, curry(markLineFilter, coordSys)); + } + + var dimValueGetter$1 = coordSys ? dimValueGetter : function (item) { + return item.value; + }; + fromData.initData(map(optData, function (item) { + return item[0]; + }), null, dimValueGetter$1); + toData.initData(map(optData, function (item) { + return item[1]; + }), null, dimValueGetter$1); + lineData.initData(map(optData, function (item) { + return item[2]; + })); + lineData.hasItemOption = true; + return { + from: fromData, + to: toData, + line: lineData + }; + } + + function install$F(registers) { + registers.registerComponentModel(MarkLineModel); + registers.registerComponentView(MarkLineView); + registers.registerPreprocessor(function (opt) { + opt.markLine = opt.markLine || {}; + }); + } + + var MarkAreaModel = function (_super) { + __extends(MarkAreaModel, _super); + + function MarkAreaModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkAreaModel.type; + return _this; + } + + MarkAreaModel.prototype.createMarkerModelFromSeries = function (markerOpt, masterMarkerModel, ecModel) { + return new MarkAreaModel(markerOpt, masterMarkerModel, ecModel); + }; + + MarkAreaModel.type = 'markArea'; + MarkAreaModel.defaultOption = { + zlevel: 0, + z: 1, + tooltip: { + trigger: 'item' + }, + animation: false, + label: { + show: true, + position: 'top' + }, + itemStyle: { + borderWidth: 0 + }, + emphasis: { + label: { + show: true, + position: 'top' + } + } + }; + return MarkAreaModel; + }(MarkerModel); + + var inner$l = makeInner(); + + var markAreaTransform = function (seriesModel, coordSys, maModel, item) { + var lt = dataTransform(seriesModel, item[0]); + var rb = dataTransform(seriesModel, item[1]); + var ltCoord = lt.coord; + var rbCoord = rb.coord; + ltCoord[0] = retrieve(ltCoord[0], -Infinity); + ltCoord[1] = retrieve(ltCoord[1], -Infinity); + rbCoord[0] = retrieve(rbCoord[0], Infinity); + rbCoord[1] = retrieve(rbCoord[1], Infinity); + var result = mergeAll([{}, lt, rb]); + result.coord = [lt.coord, rb.coord]; + result.x0 = lt.x; + result.y0 = lt.y; + result.x1 = rb.x; + result.y1 = rb.y; + return result; + }; + + function isInifinity$1(val) { + return !isNaN(val) && !isFinite(val); + } + + function ifMarkAreaHasOnlyDim(dimIndex, fromCoord, toCoord, coordSys) { + var otherDimIndex = 1 - dimIndex; + return isInifinity$1(fromCoord[otherDimIndex]) && isInifinity$1(toCoord[otherDimIndex]); + } + + function markAreaFilter(coordSys, item) { + var fromCoord = item.coord[0]; + var toCoord = item.coord[1]; + + if (isCoordinateSystemType(coordSys, 'cartesian2d')) { + if (fromCoord && toCoord && (ifMarkAreaHasOnlyDim(1, fromCoord, toCoord) || ifMarkAreaHasOnlyDim(0, fromCoord, toCoord))) { + return true; + } + } + + return dataFilter$1(coordSys, { + coord: fromCoord, + x: item.x0, + y: item.y0 + }) || dataFilter$1(coordSys, { + coord: toCoord, + x: item.x1, + y: item.y1 + }); + } + + function getSingleMarkerEndPoint(data, idx, dims, seriesModel, api) { + var coordSys = seriesModel.coordinateSystem; + var itemModel = data.getItemModel(idx); + var point; + var xPx = parsePercent$1(itemModel.get(dims[0]), api.getWidth()); + var yPx = parsePercent$1(itemModel.get(dims[1]), api.getHeight()); + + if (!isNaN(xPx) && !isNaN(yPx)) { + point = [xPx, yPx]; + } else { + if (seriesModel.getMarkerPosition) { + point = seriesModel.getMarkerPosition(data.getValues(dims, idx)); + } else { + var x = data.get(dims[0], idx); + var y = data.get(dims[1], idx); + var pt = [x, y]; + coordSys.clampData && coordSys.clampData(pt, pt); + point = coordSys.dataToPoint(pt, true); + } + + if (isCoordinateSystemType(coordSys, 'cartesian2d')) { + var xAxis = coordSys.getAxis('x'); + var yAxis = coordSys.getAxis('y'); + var x = data.get(dims[0], idx); + var y = data.get(dims[1], idx); + + if (isInifinity$1(x)) { + point[0] = xAxis.toGlobalCoord(xAxis.getExtent()[dims[0] === 'x0' ? 0 : 1]); + } else if (isInifinity$1(y)) { + point[1] = yAxis.toGlobalCoord(yAxis.getExtent()[dims[1] === 'y0' ? 0 : 1]); + } + } + + if (!isNaN(xPx)) { + point[0] = xPx; + } + + if (!isNaN(yPx)) { + point[1] = yPx; + } + } + + return point; + } + + var dimPermutations = [['x0', 'y0'], ['x1', 'y0'], ['x1', 'y1'], ['x0', 'y1']]; + + var MarkAreaView = function (_super) { + __extends(MarkAreaView, _super); + + function MarkAreaView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = MarkAreaView.type; + return _this; + } + + MarkAreaView.prototype.updateTransform = function (markAreaModel, ecModel, api) { + ecModel.eachSeries(function (seriesModel) { + var maModel = MarkerModel.getMarkerModelFromSeries(seriesModel, 'markArea'); + + if (maModel) { + var areaData_1 = maModel.getData(); + areaData_1.each(function (idx) { + var points = map(dimPermutations, function (dim) { + return getSingleMarkerEndPoint(areaData_1, idx, dim, seriesModel, api); + }); + areaData_1.setItemLayout(idx, points); + var el = areaData_1.getItemGraphicEl(idx); + el.setShape('points', points); + }); + } + }, this); + }; + + MarkAreaView.prototype.renderSeries = function (seriesModel, maModel, ecModel, api) { + var coordSys = seriesModel.coordinateSystem; + var seriesId = seriesModel.id; + var seriesData = seriesModel.getData(); + var areaGroupMap = this.markerGroupMap; + var polygonGroup = areaGroupMap.get(seriesId) || areaGroupMap.set(seriesId, { + group: new Group() + }); + this.group.add(polygonGroup.group); + this.markKeep(polygonGroup); + var areaData = createList$3(coordSys, seriesModel, maModel); + maModel.setData(areaData); + areaData.each(function (idx) { + var points = map(dimPermutations, function (dim) { + return getSingleMarkerEndPoint(areaData, idx, dim, seriesModel, api); + }); + var allClipped = true; + each(dimPermutations, function (dim) { + if (!allClipped) { + return; + } + + var xValue = areaData.get(dim[0], idx); + var yValue = areaData.get(dim[1], idx); + + if ((isInifinity$1(xValue) || coordSys.getAxis('x').containData(xValue)) && (isInifinity$1(yValue) || coordSys.getAxis('y').containData(yValue))) { + allClipped = false; + } + }); + areaData.setItemLayout(idx, { + points: points, + allClipped: allClipped + }); + var style = areaData.getItemModel(idx).getModel('itemStyle').getItemStyle(); + var color$1 = getVisualFromData(seriesData, 'color'); + + if (!style.fill) { + style.fill = color$1; + + if (typeof style.fill === 'string') { + style.fill = modifyAlpha(style.fill, 0.4); + } + } + + if (!style.stroke) { + style.stroke = color$1; + } + + areaData.setItemVisual(idx, 'style', style); + }); + areaData.diff(inner$l(polygonGroup).data).add(function (idx) { + var layout = areaData.getItemLayout(idx); + + if (!layout.allClipped) { + var polygon = new Polygon({ + shape: { + points: layout.points + } + }); + areaData.setItemGraphicEl(idx, polygon); + polygonGroup.group.add(polygon); + } + }).update(function (newIdx, oldIdx) { + var polygon = inner$l(polygonGroup).data.getItemGraphicEl(oldIdx); + var layout = areaData.getItemLayout(newIdx); + + if (!layout.allClipped) { + if (polygon) { + updateProps(polygon, { + shape: { + points: layout.points + } + }, maModel, newIdx); + } else { + polygon = new Polygon({ + shape: { + points: layout.points + } + }); + } + + areaData.setItemGraphicEl(newIdx, polygon); + polygonGroup.group.add(polygon); + } else if (polygon) { + polygonGroup.group.remove(polygon); + } + }).remove(function (idx) { + var polygon = inner$l(polygonGroup).data.getItemGraphicEl(idx); + polygonGroup.group.remove(polygon); + }).execute(); + areaData.eachItemGraphicEl(function (polygon, idx) { + var itemModel = areaData.getItemModel(idx); + var style = areaData.getItemVisual(idx, 'style'); + polygon.useStyle(areaData.getItemVisual(idx, 'style')); + setLabelStyle(polygon, getLabelStatesModels(itemModel), { + labelFetcher: maModel, + labelDataIndex: idx, + defaultText: areaData.getName(idx) || '', + inheritColor: typeof style.fill === 'string' ? modifyAlpha(style.fill, 1) : '#000' + }); + setStatesStylesFromModel(polygon, itemModel); + enableHoverEmphasis(polygon); + getECData(polygon).dataModel = maModel; + }); + inner$l(polygonGroup).data = areaData; + polygonGroup.group.silent = maModel.get('silent') || seriesModel.get('silent'); + }; + + MarkAreaView.type = 'markArea'; + return MarkAreaView; + }(MarkerView); + + function createList$3(coordSys, seriesModel, maModel) { + var coordDimsInfos; + var areaData; + var dims = ['x0', 'y0', 'x1', 'y1']; + + if (coordSys) { + coordDimsInfos = map(coordSys && coordSys.dimensions, function (coordDim) { + var data = seriesModel.getData(); + var info = data.getDimensionInfo(data.mapDimension(coordDim)) || {}; + return defaults({ + name: coordDim + }, info); + }); + areaData = new List(map(dims, function (dim, idx) { + return { + name: dim, + type: coordDimsInfos[idx % 2].type + }; + }), maModel); + } else { + coordDimsInfos = [{ + name: 'value', + type: 'float' + }]; + areaData = new List(coordDimsInfos, maModel); + } + + var optData = map(maModel.get('data'), curry(markAreaTransform, seriesModel, coordSys, maModel)); + + if (coordSys) { + optData = filter(optData, curry(markAreaFilter, coordSys)); + } + + var dimValueGetter = coordSys ? function (item, dimName, dataIndex, dimIndex) { + return item.coord[Math.floor(dimIndex / 2)][dimIndex % 2]; + } : function (item) { + return item.value; + }; + areaData.initData(optData, null, dimValueGetter); + areaData.hasItemOption = true; + return areaData; + } + + function install$G(registers) { + registers.registerComponentModel(MarkAreaModel); + registers.registerComponentView(MarkAreaView); + registers.registerPreprocessor(function (opt) { + opt.markArea = opt.markArea || {}; + }); + } + + var getDefaultSelectorOptions = function (ecModel, type) { + if (type === 'all') { + return { + type: 'all', + title: ecModel.getLocale(['legend', 'selector', 'all']) + }; + } else if (type === 'inverse') { + return { + type: 'inverse', + title: ecModel.getLocale(['legend', 'selector', 'inverse']) + }; + } + }; + + var LegendModel = function (_super) { + __extends(LegendModel, _super); + + function LegendModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = LegendModel.type; + _this.layoutMode = { + type: 'box', + ignoreSize: true + }; + return _this; + } + + LegendModel.prototype.init = function (option, parentModel, ecModel) { + this.mergeDefaultAndTheme(option, ecModel); + option.selected = option.selected || {}; + + this._updateSelector(option); + }; + + LegendModel.prototype.mergeOption = function (option, ecModel) { + _super.prototype.mergeOption.call(this, option, ecModel); + + this._updateSelector(option); + }; + + LegendModel.prototype._updateSelector = function (option) { + var selector = option.selector; + var ecModel = this.ecModel; + + if (selector === true) { + selector = option.selector = ['all', 'inverse']; + } + + if (isArray(selector)) { + each(selector, function (item, index) { + isString(item) && (item = { + type: item + }); + selector[index] = merge(item, getDefaultSelectorOptions(ecModel, item.type)); + }); + } + }; + + LegendModel.prototype.optionUpdated = function () { + this._updateData(this.ecModel); + + var legendData = this._data; + + if (legendData[0] && this.get('selectedMode') === 'single') { + var hasSelected = false; + + for (var i = 0; i < legendData.length; i++) { + var name_1 = legendData[i].get('name'); + + if (this.isSelected(name_1)) { + this.select(name_1); + hasSelected = true; + break; + } + } + + !hasSelected && this.select(legendData[0].get('name')); + } + }; + + LegendModel.prototype._updateData = function (ecModel) { + var potentialData = []; + var availableNames = []; + ecModel.eachRawSeries(function (seriesModel) { + var seriesName = seriesModel.name; + availableNames.push(seriesName); + var isPotential; + + if (seriesModel.legendVisualProvider) { + var provider = seriesModel.legendVisualProvider; + var names = provider.getAllNames(); + + if (!ecModel.isSeriesFiltered(seriesModel)) { + availableNames = availableNames.concat(names); + } + + if (names.length) { + potentialData = potentialData.concat(names); + } else { + isPotential = true; + } + } else { + isPotential = true; + } + + if (isPotential && isNameSpecified(seriesModel)) { + potentialData.push(seriesModel.name); + } + }); + this._availableNames = availableNames; + var rawData = this.get('data') || potentialData; + var legendData = map(rawData, function (dataItem) { + if (typeof dataItem === 'string' || typeof dataItem === 'number') { + dataItem = { + name: dataItem + }; + } + + return new Model(dataItem, this, this.ecModel); + }, this); + this._data = legendData; + }; + + LegendModel.prototype.getData = function () { + return this._data; + }; + + LegendModel.prototype.select = function (name) { + var selected = this.option.selected; + var selectedMode = this.get('selectedMode'); + + if (selectedMode === 'single') { + var data = this._data; + each(data, function (dataItem) { + selected[dataItem.get('name')] = false; + }); + } + + selected[name] = true; + }; + + LegendModel.prototype.unSelect = function (name) { + if (this.get('selectedMode') !== 'single') { + this.option.selected[name] = false; + } + }; + + LegendModel.prototype.toggleSelected = function (name) { + var selected = this.option.selected; + + if (!selected.hasOwnProperty(name)) { + selected[name] = true; + } + + this[selected[name] ? 'unSelect' : 'select'](name); + }; + + LegendModel.prototype.allSelect = function () { + var data = this._data; + var selected = this.option.selected; + each(data, function (dataItem) { + selected[dataItem.get('name', true)] = true; + }); + }; + + LegendModel.prototype.inverseSelect = function () { + var data = this._data; + var selected = this.option.selected; + each(data, function (dataItem) { + var name = dataItem.get('name', true); + + if (!selected.hasOwnProperty(name)) { + selected[name] = true; + } + + selected[name] = !selected[name]; + }); + }; + + LegendModel.prototype.isSelected = function (name) { + var selected = this.option.selected; + return !(selected.hasOwnProperty(name) && !selected[name]) && indexOf(this._availableNames, name) >= 0; + }; + + LegendModel.prototype.getOrient = function () { + return this.get('orient') === 'vertical' ? { + index: 1, + name: 'vertical' + } : { + index: 0, + name: 'horizontal' + }; + }; + + LegendModel.type = 'legend.plain'; + LegendModel.dependencies = ['series']; + LegendModel.defaultOption = { + zlevel: 0, + z: 4, + show: true, + 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', + inactiveBorderColor: '#ccc', + itemStyle: { + borderWidth: 0 + }, + textStyle: { + color: '#333' + }, + selectedMode: true, + selector: false, + selectorLabel: { + show: true, + borderRadius: 10, + padding: [3, 5, 3, 5], + fontSize: 12, + fontFamily: ' sans-serif', + color: '#666', + borderWidth: 1, + borderColor: '#666' + }, + emphasis: { + selectorLabel: { + show: true, + color: '#eee', + backgroundColor: '#666' + } + }, + selectorPosition: 'auto', + selectorItemGap: 7, + selectorButtonGap: 10, + tooltip: { + show: false + } + }; + return LegendModel; + }(ComponentModel); + + var curry$1 = curry; + var each$e = each; + var Group$2 = Group; + + var LegendView = function (_super) { + __extends(LegendView, _super); + + function LegendView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = LegendView.type; + _this.newlineDisabled = false; + return _this; + } + + LegendView.prototype.init = function () { + this.group.add(this._contentGroup = new Group$2()); + this.group.add(this._selectorGroup = new Group$2()); + this._isFirstRender = true; + }; + + LegendView.prototype.getContentGroup = function () { + return this._contentGroup; + }; + + LegendView.prototype.getSelectorGroup = function () { + return this._selectorGroup; + }; + + LegendView.prototype.render = function (legendModel, ecModel, api) { + var isFirstRender = this._isFirstRender; + this._isFirstRender = false; + this.resetInner(); + + if (!legendModel.get('show', true)) { + return; + } + + var itemAlign = legendModel.get('align'); + var orient = legendModel.get('orient'); + + if (!itemAlign || itemAlign === 'auto') { + itemAlign = legendModel.get('left') === 'right' && orient === 'vertical' ? 'right' : 'left'; + } + + var selector = legendModel.get('selector', true); + var selectorPosition = legendModel.get('selectorPosition', true); + + if (selector && (!selectorPosition || selectorPosition === 'auto')) { + selectorPosition = orient === 'horizontal' ? 'end' : 'start'; + } + + this.renderInner(itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition); + var positionInfo = legendModel.getBoxLayoutParams(); + var viewportSize = { + width: api.getWidth(), + height: api.getHeight() + }; + var padding = legendModel.get('padding'); + var maxSize = getLayoutRect(positionInfo, viewportSize, padding); + var mainRect = this.layoutInner(legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition); + var layoutRect = getLayoutRect(defaults({ + width: mainRect.width, + height: mainRect.height + }, positionInfo), viewportSize, padding); + this.group.x = layoutRect.x - mainRect.x; + this.group.y = layoutRect.y - mainRect.y; + this.group.markRedraw(); + this.group.add(this._backgroundEl = makeBackground(mainRect, legendModel)); + }; + + LegendView.prototype.resetInner = function () { + this.getContentGroup().removeAll(); + this._backgroundEl && this.group.remove(this._backgroundEl); + this.getSelectorGroup().removeAll(); + }; + + LegendView.prototype.renderInner = function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) { + var contentGroup = this.getContentGroup(); + var legendDrawnMap = createHashMap(); + var selectMode = legendModel.get('selectedMode'); + var excludeSeriesId = []; + ecModel.eachRawSeries(function (seriesModel) { + !seriesModel.get('legendHoverLink') && excludeSeriesId.push(seriesModel.id); + }); + each$e(legendModel.getData(), function (itemModel, dataIndex) { + var name = itemModel.get('name'); + + if (!this.newlineDisabled && (name === '' || name === '\n')) { + var g = new Group$2(); + g.newline = true; + contentGroup.add(g); + return; + } + + var seriesModel = ecModel.getSeriesByName(name)[0]; + + if (legendDrawnMap.get(name)) { + return; + } + + if (seriesModel) { + var data = seriesModel.getData(); + var style = data.getVisual('style'); + var color = style[data.getVisual('drawType')] || style.fill; + var borderColor = style.stroke; + var decal = style.decal; + var legendSymbolType = data.getVisual('legendSymbol') || 'roundRect'; + var symbolType = data.getVisual('symbol'); + + var itemGroup = this._createItem(name, dataIndex, itemModel, legendModel, legendSymbolType, symbolType, itemAlign, color, borderColor, decal, selectMode); + + itemGroup.on('click', curry$1(dispatchSelectAction, name, null, api, excludeSeriesId)).on('mouseover', curry$1(dispatchHighlightAction, seriesModel.name, null, api, excludeSeriesId)).on('mouseout', curry$1(dispatchDownplayAction, seriesModel.name, null, api, excludeSeriesId)); + legendDrawnMap.set(name, true); + } else { + ecModel.eachRawSeries(function (seriesModel) { + if (legendDrawnMap.get(name)) { + return; + } + + if (seriesModel.legendVisualProvider) { + var provider = seriesModel.legendVisualProvider; + + if (!provider.containName(name)) { + return; + } + + var idx = provider.indexOfName(name); + var style = provider.getItemVisual(idx, 'style'); + var borderColor = style.stroke; + var decal = style.decal; + var color = style.fill; + var colorArr = parse(style.fill); + + if (colorArr && colorArr[3] === 0) { + colorArr[3] = 0.2; + color = stringify(colorArr, 'rgba'); + } + + var legendSymbolType = 'roundRect'; + + var itemGroup = this._createItem(name, dataIndex, itemModel, legendModel, legendSymbolType, null, itemAlign, color, borderColor, decal, selectMode); + + itemGroup.on('click', curry$1(dispatchSelectAction, null, name, api, excludeSeriesId)).on('mouseover', curry$1(dispatchHighlightAction, null, name, api, excludeSeriesId)).on('mouseout', curry$1(dispatchDownplayAction, null, name, api, excludeSeriesId)); + legendDrawnMap.set(name, true); + } + }, this); + } + + if ("development" !== 'production') { + if (!legendDrawnMap.get(name)) { + console.warn(name + ' series not exists. Legend data should be same with series name or data name.'); + } + } + }, this); + + if (selector) { + this._createSelector(selector, legendModel, api, orient, selectorPosition); + } + }; + + LegendView.prototype._createSelector = function (selector, legendModel, api, orient, selectorPosition) { + var selectorGroup = this.getSelectorGroup(); + each$e(selector, function createSelectorButton(selectorItem) { + var type = selectorItem.type; + var labelText = new ZRText({ + style: { + x: 0, + y: 0, + align: 'center', + verticalAlign: 'middle' + }, + onclick: function () { + api.dispatchAction({ + type: type === 'all' ? 'legendAllSelect' : 'legendInverseSelect' + }); + } + }); + selectorGroup.add(labelText); + var labelModel = legendModel.getModel('selectorLabel'); + var emphasisLabelModel = legendModel.getModel(['emphasis', 'selectorLabel']); + setLabelStyle(labelText, { + normal: labelModel, + emphasis: emphasisLabelModel + }, { + defaultText: selectorItem.title + }); + enableHoverEmphasis(labelText); + }); + }; + + LegendView.prototype._createItem = function (name, dataIndex, itemModel, legendModel, legendSymbolType, symbolType, itemAlign, color, borderColor, decal, selectMode) { + var itemWidth = legendModel.get('itemWidth'); + var itemHeight = legendModel.get('itemHeight'); + var inactiveColor = legendModel.get('inactiveColor'); + var inactiveBorderColor = legendModel.get('inactiveBorderColor'); + var symbolKeepAspect = legendModel.get('symbolKeepAspect'); + var legendModelItemStyle = legendModel.getModel('itemStyle'); + var isSelected = legendModel.isSelected(name); + var itemGroup = new Group$2(); + var textStyleModel = itemModel.getModel('textStyle'); + var itemIcon = itemModel.get('icon'); + var tooltipModel = itemModel.getModel('tooltip'); + var legendGlobalTooltipModel = tooltipModel.parentModel; + legendSymbolType = itemIcon || legendSymbolType; + var legendSymbol = createSymbol(legendSymbolType, 0, 0, itemWidth, itemHeight, isSelected ? color : inactiveColor, symbolKeepAspect == null ? true : symbolKeepAspect); + itemGroup.add(setSymbolStyle(legendSymbol, legendSymbolType, legendModelItemStyle, borderColor, inactiveBorderColor, decal, isSelected)); + + if (!itemIcon && symbolType && (symbolType !== legendSymbolType || symbolType === 'none')) { + var size = itemHeight * 0.8; + + if (symbolType === 'none') { + symbolType = 'circle'; + } + + var legendSymbolCenter = createSymbol(symbolType, (itemWidth - size) / 2, (itemHeight - size) / 2, size, size, isSelected ? color : inactiveColor, symbolKeepAspect == null ? true : symbolKeepAspect); + itemGroup.add(setSymbolStyle(legendSymbolCenter, symbolType, legendModelItemStyle, borderColor, inactiveBorderColor, decal, isSelected)); + } + + var textX = itemAlign === 'left' ? itemWidth + 5 : -5; + var textAlign = itemAlign; + var formatter = legendModel.get('formatter'); + var content = name; + + if (typeof formatter === 'string' && formatter) { + content = formatter.replace('{name}', name != null ? name : ''); + } else if (typeof formatter === 'function') { + content = formatter(name); + } + + itemGroup.add(new ZRText({ + style: createTextStyle(textStyleModel, { + text: content, + x: textX, + y: itemHeight / 2, + fill: isSelected ? textStyleModel.getTextColor() : inactiveColor, + align: textAlign, + verticalAlign: 'middle' + }) + })); + var hitRect = new Rect({ + shape: itemGroup.getBoundingRect(), + invisible: true + }); + + if (tooltipModel.get('show')) { + var formatterParams = { + componentType: 'legend', + legendIndex: legendModel.componentIndex, + name: name, + $vars: ['name'] + }; + hitRect.tooltip = extend({ + content: name, + formatter: legendGlobalTooltipModel.get('formatter', true) || function (params) { + return params.name; + }, + formatterParams: formatterParams + }, tooltipModel.option); + } + + itemGroup.add(hitRect); + itemGroup.eachChild(function (child) { + child.silent = true; + }); + hitRect.silent = !selectMode; + this.getContentGroup().add(itemGroup); + enableHoverEmphasis(itemGroup); + itemGroup.__legendDataIndex = dataIndex; + return itemGroup; + }; + + LegendView.prototype.layoutInner = function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) { + var contentGroup = this.getContentGroup(); + var selectorGroup = this.getSelectorGroup(); + box(legendModel.get('orient'), contentGroup, legendModel.get('itemGap'), maxSize.width, maxSize.height); + var contentRect = contentGroup.getBoundingRect(); + var contentPos = [-contentRect.x, -contentRect.y]; + selectorGroup.markRedraw(); + contentGroup.markRedraw(); + + if (selector) { + box('horizontal', selectorGroup, legendModel.get('selectorItemGap', true)); + var selectorRect = selectorGroup.getBoundingRect(); + var selectorPos = [-selectorRect.x, -selectorRect.y]; + var selectorButtonGap = legendModel.get('selectorButtonGap', true); + var orientIdx = legendModel.getOrient().index; + var wh = orientIdx === 0 ? 'width' : 'height'; + var hw = orientIdx === 0 ? 'height' : 'width'; + var yx = orientIdx === 0 ? 'y' : 'x'; + + if (selectorPosition === 'end') { + selectorPos[orientIdx] += contentRect[wh] + selectorButtonGap; + } else { + contentPos[orientIdx] += selectorRect[wh] + selectorButtonGap; + } + + selectorPos[1 - orientIdx] += contentRect[hw] / 2 - selectorRect[hw] / 2; + selectorGroup.x = selectorPos[0]; + selectorGroup.y = selectorPos[1]; + contentGroup.x = contentPos[0]; + contentGroup.y = contentPos[1]; + var mainRect = { + x: 0, + y: 0 + }; + mainRect[wh] = contentRect[wh] + selectorButtonGap + selectorRect[wh]; + mainRect[hw] = Math.max(contentRect[hw], selectorRect[hw]); + mainRect[yx] = Math.min(0, selectorRect[yx] + selectorPos[1 - orientIdx]); + return mainRect; + } else { + contentGroup.x = contentPos[0]; + contentGroup.y = contentPos[1]; + return this.group.getBoundingRect(); + } + }; + + LegendView.prototype.remove = function () { + this.getContentGroup().removeAll(); + this._isFirstRender = true; + }; + + LegendView.type = 'legend.plain'; + return LegendView; + }(ComponentView); + + function setSymbolStyle(symbol, symbolType, legendModelItemStyle, borderColor, inactiveBorderColor, decal, isSelected) { + var itemStyle; + + if (symbolType !== 'line' && symbolType.indexOf('empty') < 0) { + itemStyle = legendModelItemStyle.getItemStyle(); + symbol.style.stroke = borderColor; + symbol.style.decal = decal; + + if (!isSelected) { + itemStyle.stroke = inactiveBorderColor; + } + } else { + itemStyle = legendModelItemStyle.getItemStyle(['borderWidth', 'borderColor']); + } + + symbol.setStyle(itemStyle); + return symbol; + } + + function dispatchSelectAction(seriesName, dataName, api, excludeSeriesId) { + dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId); + api.dispatchAction({ + type: 'legendToggleSelect', + name: seriesName != null ? seriesName : dataName + }); + dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId); + } + + function isUseHoverLayer(api) { + var list = api.getZr().storage.getDisplayList(); + var emphasisState; + var i = 0; + var len = list.length; + + while (i < len && !(emphasisState = list[i].states.emphasis)) { + i++; + } + + return emphasisState && emphasisState.hoverLayer; + } + + function dispatchHighlightAction(seriesName, dataName, api, excludeSeriesId) { + if (!isUseHoverLayer(api)) { + api.dispatchAction({ + type: 'highlight', + seriesName: seriesName, + name: dataName, + excludeSeriesId: excludeSeriesId + }); + } + } + + function dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId) { + if (!isUseHoverLayer(api)) { + api.dispatchAction({ + type: 'downplay', + seriesName: seriesName, + name: dataName, + excludeSeriesId: excludeSeriesId + }); + } + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function legendFilter(ecModel) { + var legendModels = ecModel.findComponents({ + mainType: 'legend' + }); + + if (legendModels && legendModels.length) { + ecModel.filterSeries(function (series) { + for (var i = 0; i < legendModels.length; i++) { + if (!legendModels[i].isSelected(series.name)) { + return false; + } + } + + return true; + }); + } + } + + function legendSelectActionHandler(methodName, payload, ecModel) { + var selectedMap = {}; + var isToggleSelect = methodName === 'toggleSelected'; + var isSelected; + ecModel.eachComponent('legend', function (legendModel) { + if (isToggleSelect && isSelected != null) { + legendModel[isSelected ? 'select' : 'unSelect'](payload.name); + } else if (methodName === 'allSelect' || methodName === 'inverseSelect') { + legendModel[methodName](); + } else { + legendModel[methodName](payload.name); + isSelected = legendModel.isSelected(payload.name); + } + + var legendData = legendModel.getData(); + each(legendData, function (model) { + var name = model.get('name'); + + if (name === '\n' || name === '') { + return; + } + + var isItemSelected = legendModel.isSelected(name); + + if (selectedMap.hasOwnProperty(name)) { + selectedMap[name] = selectedMap[name] && isItemSelected; + } else { + selectedMap[name] = isItemSelected; + } + }); + }); + return methodName === 'allSelect' || methodName === 'inverseSelect' ? { + selected: selectedMap + } : { + name: payload.name, + selected: selectedMap + }; + } + + function installLegendAction(registers) { + registers.registerAction('legendToggleSelect', 'legendselectchanged', curry(legendSelectActionHandler, 'toggleSelected')); + registers.registerAction('legendAllSelect', 'legendselectall', curry(legendSelectActionHandler, 'allSelect')); + registers.registerAction('legendInverseSelect', 'legendinverseselect', curry(legendSelectActionHandler, 'inverseSelect')); + registers.registerAction('legendSelect', 'legendselected', curry(legendSelectActionHandler, 'select')); + registers.registerAction('legendUnSelect', 'legendunselected', curry(legendSelectActionHandler, 'unSelect')); + } + + function install$H(registers) { + registers.registerComponentModel(LegendModel); + registers.registerComponentView(LegendView); + registers.registerProcessor(registers.PRIORITY.PROCESSOR.SERIES_FILTER, legendFilter); + registers.registerSubTypeDefaulter('legend', function () { + return 'plain'; + }); + installLegendAction(registers); + } + + var ScrollableLegendModel = function (_super) { + __extends(ScrollableLegendModel, _super); + + function ScrollableLegendModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ScrollableLegendModel.type; + return _this; + } + + ScrollableLegendModel.prototype.setScrollDataIndex = function (scrollDataIndex) { + this.option.scrollDataIndex = scrollDataIndex; + }; + + ScrollableLegendModel.prototype.init = function (option, parentModel, ecModel) { + var inputPositionParams = getLayoutParams(option); + + _super.prototype.init.call(this, option, parentModel, ecModel); + + mergeAndNormalizeLayoutParams$1(this, option, inputPositionParams); + }; + + ScrollableLegendModel.prototype.mergeOption = function (option, ecModel) { + _super.prototype.mergeOption.call(this, option, ecModel); + + mergeAndNormalizeLayoutParams$1(this, this.option, option); + }; + + ScrollableLegendModel.type = 'legend.scroll'; + ScrollableLegendModel.defaultOption = inheritDefaultOption(LegendModel.defaultOption, { + scrollDataIndex: 0, + pageButtonItemGap: 5, + pageButtonGap: null, + pageButtonPosition: 'end', + pageFormatter: '{current}/{total}', + pageIcons: { + horizontal: ['M0,0L12,-10L12,10z', 'M0,0L-12,-10L-12,10z'], + vertical: ['M0,0L20,0L10,-20z', 'M0,0L20,0L10,20z'] + }, + pageIconColor: '#2f4554', + pageIconInactiveColor: '#aaa', + pageIconSize: 15, + pageTextStyle: { + color: '#333' + }, + animationDurationUpdate: 800 + }); + return ScrollableLegendModel; + }(LegendModel); + + function mergeAndNormalizeLayoutParams$1(legendModel, target, raw) { + var orient = legendModel.getOrient(); + var ignoreSize = [1, 1]; + ignoreSize[orient.index] = 0; + mergeLayoutParam(target, raw, { + type: 'box', + ignoreSize: !!ignoreSize + }); + } + + var Group$3 = Group; + var WH$1 = ['width', 'height']; + var XY$1 = ['x', 'y']; + + var ScrollableLegendView = function (_super) { + __extends(ScrollableLegendView, _super); + + function ScrollableLegendView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ScrollableLegendView.type; + _this.newlineDisabled = true; + _this._currentIndex = 0; + return _this; + } + + ScrollableLegendView.prototype.init = function () { + _super.prototype.init.call(this); + + this.group.add(this._containerGroup = new Group$3()); + + this._containerGroup.add(this.getContentGroup()); + + this.group.add(this._controllerGroup = new Group$3()); + }; + + ScrollableLegendView.prototype.resetInner = function () { + _super.prototype.resetInner.call(this); + + this._controllerGroup.removeAll(); + + this._containerGroup.removeClipPath(); + + this._containerGroup.__rectSize = null; + }; + + ScrollableLegendView.prototype.renderInner = function (itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition) { + var self = this; + + _super.prototype.renderInner.call(this, itemAlign, legendModel, ecModel, api, selector, orient, selectorPosition); + + var controllerGroup = this._controllerGroup; + var pageIconSize = legendModel.get('pageIconSize', true); + var pageIconSizeArr = isArray(pageIconSize) ? pageIconSize : [pageIconSize, pageIconSize]; + createPageButton('pagePrev', 0); + var pageTextStyleModel = legendModel.getModel('pageTextStyle'); + controllerGroup.add(new ZRText({ + name: 'pageText', + style: { + text: 'xx/xx', + fill: pageTextStyleModel.getTextColor(), + font: pageTextStyleModel.getFont(), + verticalAlign: 'middle', + align: 'center' + }, + silent: true + })); + createPageButton('pageNext', 1); + + function createPageButton(name, iconIdx) { + var pageDataIndexName = name + 'DataIndex'; + var icon = createIcon(legendModel.get('pageIcons', true)[legendModel.getOrient().name][iconIdx], { + onclick: bind(self._pageGo, self, pageDataIndexName, legendModel, api) + }, { + x: -pageIconSizeArr[0] / 2, + y: -pageIconSizeArr[1] / 2, + width: pageIconSizeArr[0], + height: pageIconSizeArr[1] + }); + icon.name = name; + controllerGroup.add(icon); + } + }; + + ScrollableLegendView.prototype.layoutInner = function (legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) { + var selectorGroup = this.getSelectorGroup(); + var orientIdx = legendModel.getOrient().index; + var wh = WH$1[orientIdx]; + var xy = XY$1[orientIdx]; + var hw = WH$1[1 - orientIdx]; + var yx = XY$1[1 - orientIdx]; + selector && box('horizontal', selectorGroup, legendModel.get('selectorItemGap', true)); + var selectorButtonGap = legendModel.get('selectorButtonGap', true); + var selectorRect = selectorGroup.getBoundingRect(); + var selectorPos = [-selectorRect.x, -selectorRect.y]; + var processMaxSize = clone(maxSize); + selector && (processMaxSize[wh] = maxSize[wh] - selectorRect[wh] - selectorButtonGap); + + var mainRect = this._layoutContentAndController(legendModel, isFirstRender, processMaxSize, orientIdx, wh, hw, yx, xy); + + if (selector) { + if (selectorPosition === 'end') { + selectorPos[orientIdx] += mainRect[wh] + selectorButtonGap; + } else { + var offset = selectorRect[wh] + selectorButtonGap; + selectorPos[orientIdx] -= offset; + mainRect[xy] -= offset; + } + + mainRect[wh] += selectorRect[wh] + selectorButtonGap; + selectorPos[1 - orientIdx] += mainRect[yx] + mainRect[hw] / 2 - selectorRect[hw] / 2; + mainRect[hw] = Math.max(mainRect[hw], selectorRect[hw]); + mainRect[yx] = Math.min(mainRect[yx], selectorRect[yx] + selectorPos[1 - orientIdx]); + selectorGroup.x = selectorPos[0]; + selectorGroup.y = selectorPos[1]; + selectorGroup.markRedraw(); + } + + return mainRect; + }; + + ScrollableLegendView.prototype._layoutContentAndController = function (legendModel, isFirstRender, maxSize, orientIdx, wh, hw, yx, xy) { + var contentGroup = this.getContentGroup(); + var containerGroup = this._containerGroup; + var controllerGroup = this._controllerGroup; + box(legendModel.get('orient'), contentGroup, legendModel.get('itemGap'), !orientIdx ? null : maxSize.width, orientIdx ? null : maxSize.height); + box('horizontal', controllerGroup, legendModel.get('pageButtonItemGap', true)); + var contentRect = contentGroup.getBoundingRect(); + var controllerRect = controllerGroup.getBoundingRect(); + var showController = this._showController = contentRect[wh] > maxSize[wh]; + var contentPos = [-contentRect.x, -contentRect.y]; + + if (!isFirstRender) { + contentPos[orientIdx] = contentGroup[xy]; + } + + var containerPos = [0, 0]; + var controllerPos = [-controllerRect.x, -controllerRect.y]; + var pageButtonGap = retrieve2(legendModel.get('pageButtonGap', true), legendModel.get('itemGap', true)); + + if (showController) { + var pageButtonPosition = legendModel.get('pageButtonPosition', true); + + if (pageButtonPosition === 'end') { + controllerPos[orientIdx] += maxSize[wh] - controllerRect[wh]; + } else { + containerPos[orientIdx] += controllerRect[wh] + pageButtonGap; + } + } + + controllerPos[1 - orientIdx] += contentRect[hw] / 2 - controllerRect[hw] / 2; + contentGroup.setPosition(contentPos); + containerGroup.setPosition(containerPos); + controllerGroup.setPosition(controllerPos); + var mainRect = { + x: 0, + y: 0 + }; + mainRect[wh] = showController ? maxSize[wh] : contentRect[wh]; + mainRect[hw] = Math.max(contentRect[hw], controllerRect[hw]); + mainRect[yx] = Math.min(0, controllerRect[yx] + controllerPos[1 - orientIdx]); + containerGroup.__rectSize = maxSize[wh]; + + if (showController) { + var clipShape = { + x: 0, + y: 0 + }; + clipShape[wh] = Math.max(maxSize[wh] - controllerRect[wh] - pageButtonGap, 0); + clipShape[hw] = mainRect[hw]; + containerGroup.setClipPath(new Rect({ + shape: clipShape + })); + containerGroup.__rectSize = clipShape[wh]; + } else { + controllerGroup.eachChild(function (child) { + child.attr({ + invisible: true, + silent: true + }); + }); + } + + var pageInfo = this._getPageInfo(legendModel); + + pageInfo.pageIndex != null && updateProps(contentGroup, { + x: pageInfo.contentPosition[0], + y: pageInfo.contentPosition[1] + }, showController ? legendModel : null); + + this._updatePageInfoView(legendModel, pageInfo); + + return mainRect; + }; + + ScrollableLegendView.prototype._pageGo = function (to, legendModel, api) { + var scrollDataIndex = this._getPageInfo(legendModel)[to]; + + scrollDataIndex != null && api.dispatchAction({ + type: 'legendScroll', + scrollDataIndex: scrollDataIndex, + legendId: legendModel.id + }); + }; + + ScrollableLegendView.prototype._updatePageInfoView = function (legendModel, pageInfo) { + var controllerGroup = this._controllerGroup; + each(['pagePrev', 'pageNext'], function (name) { + var key = name + 'DataIndex'; + var canJump = pageInfo[key] != null; + var icon = controllerGroup.childOfName(name); + + if (icon) { + icon.setStyle('fill', canJump ? legendModel.get('pageIconColor', true) : legendModel.get('pageIconInactiveColor', true)); + icon.cursor = canJump ? 'pointer' : 'default'; + } + }); + var pageText = controllerGroup.childOfName('pageText'); + var pageFormatter = legendModel.get('pageFormatter'); + var pageIndex = pageInfo.pageIndex; + var current = pageIndex != null ? pageIndex + 1 : 0; + var total = pageInfo.pageCount; + pageText && pageFormatter && pageText.setStyle('text', isString(pageFormatter) ? pageFormatter.replace('{current}', current == null ? '' : current + '').replace('{total}', total == null ? '' : total + '') : pageFormatter({ + current: current, + total: total + })); + }; + + ScrollableLegendView.prototype._getPageInfo = function (legendModel) { + var scrollDataIndex = legendModel.get('scrollDataIndex', true); + var contentGroup = this.getContentGroup(); + var containerRectSize = this._containerGroup.__rectSize; + var orientIdx = legendModel.getOrient().index; + var wh = WH$1[orientIdx]; + var xy = XY$1[orientIdx]; + + var targetItemIndex = this._findTargetItemIndex(scrollDataIndex); + + var children = contentGroup.children(); + var targetItem = children[targetItemIndex]; + var itemCount = children.length; + var pCount = !itemCount ? 0 : 1; + var result = { + contentPosition: [contentGroup.x, contentGroup.y], + pageCount: pCount, + pageIndex: pCount - 1, + pagePrevDataIndex: null, + pageNextDataIndex: null + }; + + if (!targetItem) { + return result; + } + + var targetItemInfo = getItemInfo(targetItem); + result.contentPosition[orientIdx] = -targetItemInfo.s; + + for (var i = targetItemIndex + 1, winStartItemInfo = targetItemInfo, winEndItemInfo = targetItemInfo, currItemInfo = null; i <= itemCount; ++i) { + currItemInfo = getItemInfo(children[i]); + + if (!currItemInfo && winEndItemInfo.e > winStartItemInfo.s + containerRectSize || currItemInfo && !intersect(currItemInfo, winStartItemInfo.s)) { + if (winEndItemInfo.i > winStartItemInfo.i) { + winStartItemInfo = winEndItemInfo; + } else { + winStartItemInfo = currItemInfo; + } + + if (winStartItemInfo) { + if (result.pageNextDataIndex == null) { + result.pageNextDataIndex = winStartItemInfo.i; + } + + ++result.pageCount; + } + } + + winEndItemInfo = currItemInfo; + } + + for (var i = targetItemIndex - 1, winStartItemInfo = targetItemInfo, winEndItemInfo = targetItemInfo, currItemInfo = null; i >= -1; --i) { + currItemInfo = getItemInfo(children[i]); + + if ((!currItemInfo || !intersect(winEndItemInfo, currItemInfo.s)) && winStartItemInfo.i < winEndItemInfo.i) { + winEndItemInfo = winStartItemInfo; + + if (result.pagePrevDataIndex == null) { + result.pagePrevDataIndex = winStartItemInfo.i; + } + + ++result.pageCount; + ++result.pageIndex; + } + + winStartItemInfo = currItemInfo; + } + + return result; + + function getItemInfo(el) { + if (el) { + var itemRect = el.getBoundingRect(); + var start = itemRect[xy] + el[xy]; + return { + s: start, + e: start + itemRect[wh], + i: el.__legendDataIndex + }; + } + } + + function intersect(itemInfo, winStart) { + return itemInfo.e >= winStart && itemInfo.s <= winStart + containerRectSize; + } + }; + + ScrollableLegendView.prototype._findTargetItemIndex = function (targetDataIndex) { + if (!this._showController) { + return 0; + } + + var index; + var contentGroup = this.getContentGroup(); + var defaultIndex; + contentGroup.eachChild(function (child, idx) { + var legendDataIdx = child.__legendDataIndex; + + if (defaultIndex == null && legendDataIdx != null) { + defaultIndex = idx; + } + + if (legendDataIdx === targetDataIndex) { + index = idx; + } + }); + return index != null ? index : defaultIndex; + }; + + ScrollableLegendView.type = 'legend.scroll'; + return ScrollableLegendView; + }(LegendView); + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + function installScrollableLegendAction(registers) { + registers.registerAction('legendScroll', 'legendscroll', function (payload, ecModel) { + var scrollDataIndex = payload.scrollDataIndex; + scrollDataIndex != null && ecModel.eachComponent({ + mainType: 'legend', + subType: 'scroll', + query: payload + }, function (legendModel) { + legendModel.setScrollDataIndex(scrollDataIndex); + }); + }); + } + + function install$I(registers) { + use(install$H); + registers.registerComponentModel(ScrollableLegendModel); + registers.registerComponentView(ScrollableLegendView); + installScrollableLegendAction(registers); + } + + function install$J(registers) { + use(install$H); + use(install$I); + } + + var InsideZoomModel = function (_super) { + __extends(InsideZoomModel, _super); + + function InsideZoomModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = InsideZoomModel.type; + return _this; + } + + InsideZoomModel.type = 'dataZoom.inside'; + InsideZoomModel.defaultOption = inheritDefaultOption(DataZoomModel.defaultOption, { + disabled: false, + zoomLock: false, + zoomOnMouseWheel: true, + moveOnMouseMove: true, + moveOnMouseWheel: false, + preventDefaultMouseMove: true + }); + return InsideZoomModel; + }(DataZoomModel); + + var inner$m = makeInner(); + function setViewInfoToCoordSysRecord(api, dataZoomModel, getRange) { + inner$m(api).coordSysRecordMap.each(function (coordSysRecord) { + var dzInfo = coordSysRecord.dataZoomInfoMap.get(dataZoomModel.uid); + + if (dzInfo) { + dzInfo.getRange = getRange; + } + }); + } + function disposeCoordSysRecordIfNeeded(api, dataZoomModel) { + var coordSysRecordMap = inner$m(api).coordSysRecordMap; + var coordSysKeyArr = coordSysRecordMap.keys(); + + for (var i = 0; i < coordSysKeyArr.length; i++) { + var coordSysKey = coordSysKeyArr[i]; + var coordSysRecord = coordSysRecordMap.get(coordSysKey); + var dataZoomInfoMap = coordSysRecord.dataZoomInfoMap; + + if (dataZoomInfoMap) { + var dzUid = dataZoomModel.uid; + var dzInfo = dataZoomInfoMap.get(dzUid); + + if (dzInfo) { + dataZoomInfoMap.removeKey(dzUid); + + if (!dataZoomInfoMap.keys().length) { + disposeCoordSysRecord(coordSysRecordMap, coordSysRecord); + } + } + } + } + } + + function disposeCoordSysRecord(coordSysRecordMap, coordSysRecord) { + if (coordSysRecord) { + coordSysRecordMap.removeKey(coordSysRecord.model.uid); + var controller = coordSysRecord.controller; + controller && controller.dispose(); + } + } + + function createCoordSysRecord(api, coordSysModel) { + var coordSysRecord = { + model: coordSysModel, + containsPoint: curry(containsPoint, coordSysModel), + dispatchAction: curry(dispatchAction$1, api), + dataZoomInfoMap: null, + controller: null + }; + var controller = coordSysRecord.controller = new RoamController(api.getZr()); + each(['pan', 'zoom', 'scrollMove'], function (eventName) { + controller.on(eventName, function (event) { + var batch = []; + coordSysRecord.dataZoomInfoMap.each(function (dzInfo) { + if (!event.isAvailableBehavior(dzInfo.model.option)) { + return; + } + + var method = (dzInfo.getRange || {})[eventName]; + var range = method && method(dzInfo.dzReferCoordSysInfo, coordSysRecord.model.mainType, coordSysRecord.controller, event); + !dzInfo.model.get('disabled', true) && range && batch.push({ + dataZoomId: dzInfo.model.id, + start: range[0], + end: range[1] + }); + }); + batch.length && coordSysRecord.dispatchAction(batch); + }); + }); + return coordSysRecord; + } + + function dispatchAction$1(api, batch) { + api.dispatchAction({ + type: 'dataZoom', + animation: { + easing: 'cubicOut', + duration: 100 + }, + batch: batch + }); + } + + function containsPoint(coordSysModel, e, x, y) { + return coordSysModel.coordinateSystem.containPoint([x, y]); + } + + function mergeControllerParams(dataZoomInfoMap) { + var controlType; + var prefix = 'type_'; + var typePriority = { + 'type_true': 2, + 'type_move': 1, + 'type_false': 0, + 'type_undefined': -1 + }; + var preventDefaultMouseMove = true; + dataZoomInfoMap.each(function (dataZoomInfo) { + var dataZoomModel = dataZoomInfo.model; + var oneType = dataZoomModel.get('disabled', true) ? false : dataZoomModel.get('zoomLock', true) ? 'move' : true; + + if (typePriority[prefix + oneType] > typePriority[prefix + controlType]) { + controlType = oneType; + } + + preventDefaultMouseMove = preventDefaultMouseMove && dataZoomModel.get('preventDefaultMouseMove', true); + }); + return { + controlType: controlType, + opt: { + zoomOnMouseWheel: true, + moveOnMouseMove: true, + moveOnMouseWheel: true, + preventDefaultMouseMove: !!preventDefaultMouseMove + } + }; + } + + function installDataZoomRoamProcessor(registers) { + registers.registerProcessor(registers.PRIORITY.PROCESSOR.FILTER, function (ecModel, api) { + var apiInner = inner$m(api); + var coordSysRecordMap = apiInner.coordSysRecordMap || (apiInner.coordSysRecordMap = createHashMap()); + coordSysRecordMap.each(function (coordSysRecord) { + coordSysRecord.dataZoomInfoMap = null; + }); + ecModel.eachComponent({ + mainType: 'dataZoom', + subType: 'inside' + }, function (dataZoomModel) { + var dzReferCoordSysWrap = collectReferCoordSysModelInfo(dataZoomModel); + each(dzReferCoordSysWrap.infoList, function (dzCoordSysInfo) { + var coordSysUid = dzCoordSysInfo.model.uid; + var coordSysRecord = coordSysRecordMap.get(coordSysUid) || coordSysRecordMap.set(coordSysUid, createCoordSysRecord(api, dzCoordSysInfo.model)); + var dataZoomInfoMap = coordSysRecord.dataZoomInfoMap || (coordSysRecord.dataZoomInfoMap = createHashMap()); + dataZoomInfoMap.set(dataZoomModel.uid, { + dzReferCoordSysInfo: dzCoordSysInfo, + model: dataZoomModel, + getRange: null + }); + }); + }); + coordSysRecordMap.each(function (coordSysRecord) { + var controller = coordSysRecord.controller; + var firstDzInfo; + var dataZoomInfoMap = coordSysRecord.dataZoomInfoMap; + + if (dataZoomInfoMap) { + var firstDzKey = dataZoomInfoMap.keys()[0]; + + if (firstDzKey != null) { + firstDzInfo = dataZoomInfoMap.get(firstDzKey); + } + } + + if (!firstDzInfo) { + disposeCoordSysRecord(coordSysRecordMap, coordSysRecord); + return; + } + + var controllerParams = mergeControllerParams(dataZoomInfoMap); + controller.enable(controllerParams.controlType, controllerParams.opt); + controller.setPointerChecker(coordSysRecord.containsPoint); + createOrUpdate(coordSysRecord, 'dispatchAction', firstDzInfo.model.get('throttle', true), 'fixRate'); + }); + }); + } + + var InsideZoomView = function (_super) { + __extends(InsideZoomView, _super); + + function InsideZoomView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = 'dataZoom.inside'; + return _this; + } + + InsideZoomView.prototype.render = function (dataZoomModel, ecModel, api) { + _super.prototype.render.apply(this, arguments); + + if (dataZoomModel.noTarget()) { + this._clear(); + + return; + } + + this.range = dataZoomModel.getPercentRange(); + setViewInfoToCoordSysRecord(api, dataZoomModel, { + pan: bind(getRangeHandlers.pan, this), + zoom: bind(getRangeHandlers.zoom, this), + scrollMove: bind(getRangeHandlers.scrollMove, this) + }); + }; + + InsideZoomView.prototype.dispose = function () { + this._clear(); + + _super.prototype.dispose.apply(this, arguments); + }; + + InsideZoomView.prototype._clear = function () { + disposeCoordSysRecordIfNeeded(this.api, this.dataZoomModel); + this.range = null; + }; + + InsideZoomView.type = 'dataZoom.inside'; + return InsideZoomView; + }(DataZoomView); + + var getRangeHandlers = { + zoom: function (coordSysInfo, coordSysMainType, controller, e) { + var lastRange = this.range; + var range = lastRange.slice(); + var axisModel = coordSysInfo.axisModels[0]; + + if (!axisModel) { + return; + } + + var directionInfo = getDirectionInfo[coordSysMainType](null, [e.originX, e.originY], axisModel, controller, coordSysInfo); + var percentPoint = (directionInfo.signal > 0 ? directionInfo.pixelStart + directionInfo.pixelLength - directionInfo.pixel : directionInfo.pixel - directionInfo.pixelStart) / directionInfo.pixelLength * (range[1] - range[0]) + range[0]; + var scale = Math.max(1 / e.scale, 0); + range[0] = (range[0] - percentPoint) * scale + percentPoint; + range[1] = (range[1] - percentPoint) * scale + percentPoint; + var minMaxSpan = this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan(); + sliderMove(0, range, [0, 100], 0, minMaxSpan.minSpan, minMaxSpan.maxSpan); + this.range = range; + + if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) { + return range; + } + }, + pan: makeMover(function (range, axisModel, coordSysInfo, coordSysMainType, controller, e) { + var directionInfo = getDirectionInfo[coordSysMainType]([e.oldX, e.oldY], [e.newX, e.newY], axisModel, controller, coordSysInfo); + return directionInfo.signal * (range[1] - range[0]) * directionInfo.pixel / directionInfo.pixelLength; + }), + scrollMove: makeMover(function (range, axisModel, coordSysInfo, coordSysMainType, controller, e) { + var directionInfo = getDirectionInfo[coordSysMainType]([0, 0], [e.scrollDelta, e.scrollDelta], axisModel, controller, coordSysInfo); + return directionInfo.signal * (range[1] - range[0]) * e.scrollDelta; + }) + }; + + function makeMover(getPercentDelta) { + return function (coordSysInfo, coordSysMainType, controller, e) { + var lastRange = this.range; + var range = lastRange.slice(); + var axisModel = coordSysInfo.axisModels[0]; + + if (!axisModel) { + return; + } + + var percentDelta = getPercentDelta(range, axisModel, coordSysInfo, coordSysMainType, controller, e); + sliderMove(percentDelta, range, [0, 100], 'all'); + this.range = range; + + if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) { + return range; + } + }; + } + + var getDirectionInfo = { + grid: function (oldPoint, newPoint, axisModel, controller, coordSysInfo) { + var axis = axisModel.axis; + var ret = {}; + var rect = coordSysInfo.model.coordinateSystem.getRect(); + oldPoint = oldPoint || [0, 0]; + + if (axis.dim === 'x') { + ret.pixel = newPoint[0] - oldPoint[0]; + ret.pixelLength = rect.width; + ret.pixelStart = rect.x; + ret.signal = axis.inverse ? 1 : -1; + } else { + ret.pixel = newPoint[1] - oldPoint[1]; + ret.pixelLength = rect.height; + ret.pixelStart = rect.y; + ret.signal = axis.inverse ? -1 : 1; + } + + return ret; + }, + polar: function (oldPoint, newPoint, axisModel, controller, coordSysInfo) { + var axis = axisModel.axis; + var ret = {}; + var polar = coordSysInfo.model.coordinateSystem; + var radiusExtent = polar.getRadiusAxis().getExtent(); + var angleExtent = polar.getAngleAxis().getExtent(); + oldPoint = oldPoint ? polar.pointToCoord(oldPoint) : [0, 0]; + newPoint = polar.pointToCoord(newPoint); + + if (axisModel.mainType === 'radiusAxis') { + ret.pixel = newPoint[0] - oldPoint[0]; + ret.pixelLength = radiusExtent[1] - radiusExtent[0]; + ret.pixelStart = radiusExtent[0]; + ret.signal = axis.inverse ? 1 : -1; + } else { + ret.pixel = newPoint[1] - oldPoint[1]; + ret.pixelLength = angleExtent[1] - angleExtent[0]; + ret.pixelStart = angleExtent[0]; + ret.signal = axis.inverse ? -1 : 1; + } + + return ret; + }, + singleAxis: function (oldPoint, newPoint, axisModel, controller, coordSysInfo) { + var axis = axisModel.axis; + var rect = coordSysInfo.model.coordinateSystem.getRect(); + var ret = {}; + oldPoint = oldPoint || [0, 0]; + + if (axis.orient === 'horizontal') { + ret.pixel = newPoint[0] - oldPoint[0]; + ret.pixelLength = rect.width; + ret.pixelStart = rect.x; + ret.signal = axis.inverse ? 1 : -1; + } else { + ret.pixel = newPoint[1] - oldPoint[1]; + ret.pixelLength = rect.height; + ret.pixelStart = rect.y; + ret.signal = axis.inverse ? -1 : 1; + } + + return ret; + } + }; + + function install$K(registers) { + installCommon(registers); + registers.registerComponentModel(InsideZoomModel); + registers.registerComponentView(InsideZoomView); + installDataZoomRoamProcessor(registers); + } + + var SliderZoomModel = function (_super) { + __extends(SliderZoomModel, _super); + + function SliderZoomModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SliderZoomModel.type; + return _this; + } + + SliderZoomModel.type = 'dataZoom.slider'; + SliderZoomModel.layoutMode = 'box'; + SliderZoomModel.defaultOption = inheritDefaultOption(DataZoomModel.defaultOption, { + show: true, + right: 'ph', + top: 'ph', + width: 'ph', + height: 'ph', + left: null, + bottom: null, + borderColor: '#d2dbee', + borderRadius: 3, + backgroundColor: 'rgba(47,69,84,0)', + dataBackground: { + lineStyle: { + color: '#d2dbee', + width: 0.5 + }, + areaStyle: { + color: '#d2dbee', + opacity: 0.2 + } + }, + selectedDataBackground: { + lineStyle: { + color: '#8fb0f7', + width: 0.5 + }, + areaStyle: { + color: '#8fb0f7', + opacity: 0.2 + } + }, + fillerColor: 'rgba(135,175,274,0.2)', + handleIcon: 'path://M-9.35,34.56V42m0-40V9.5m-2,0h4a2,2,0,0,1,2,2v21a2,2,0,0,1-2,2h-4a2,2,0,0,1-2-2v-21A2,2,0,0,1-11.35,9.5Z', + handleSize: '100%', + handleStyle: { + color: '#fff', + borderColor: '#ACB8D1' + }, + moveHandleSize: 7, + moveHandleIcon: 'path://M-320.9-50L-320.9-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-348-41-339-50-320.9-50z M-212.3-50L-212.3-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-239.4-41-230.4-50-212.3-50z M-103.7-50L-103.7-50c18.1,0,27.1,9,27.1,27.1V85.7c0,18.1-9,27.1-27.1,27.1l0,0c-18.1,0-27.1-9-27.1-27.1V-22.9C-130.9-41-121.8-50-103.7-50z', + moveHandleStyle: { + color: '#D2DBEE', + opacity: 0.7 + }, + showDetail: true, + showDataShadow: 'auto', + realtime: true, + zoomLock: false, + textStyle: { + color: '#6E7079' + }, + brushSelect: true, + brushStyle: { + color: 'rgba(135,175,274,0.15)' + }, + emphasis: { + handleStyle: { + borderColor: '#8FB0F7' + }, + moveHandleStyle: { + color: '#8FB0F7' + } + } + }); + return SliderZoomModel; + }(DataZoomModel); + + var Rect$2 = Rect; + var DEFAULT_LOCATION_EDGE_GAP = 7; + var DEFAULT_FRAME_BORDER_WIDTH = 1; + var DEFAULT_FILLER_SIZE = 30; + var DEFAULT_MOVE_HANDLE_SIZE = 7; + var HORIZONTAL = 'horizontal'; + var VERTICAL = 'vertical'; + var LABEL_GAP = 5; + var SHOW_DATA_SHADOW_SERIES_TYPE = ['line', 'bar', 'candlestick', 'scatter']; + var REALTIME_ANIMATION_CONFIG = { + easing: 'cubicOut', + duration: 100 + }; + + var SliderZoomView = function (_super) { + __extends(SliderZoomView, _super); + + function SliderZoomView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = SliderZoomView.type; + _this._displayables = {}; + return _this; + } + + SliderZoomView.prototype.init = function (ecModel, api) { + this.api = api; + this._onBrush = bind(this._onBrush, this); + this._onBrushEnd = bind(this._onBrushEnd, this); + }; + + SliderZoomView.prototype.render = function (dataZoomModel, ecModel, api, payload) { + _super.prototype.render.apply(this, arguments); + + createOrUpdate(this, '_dispatchZoomAction', dataZoomModel.get('throttle'), 'fixRate'); + this._orient = dataZoomModel.getOrient(); + + if (dataZoomModel.get('show') === false) { + this.group.removeAll(); + return; + } + + if (dataZoomModel.noTarget()) { + this._clear(); + + this.group.removeAll(); + return; + } + + if (!payload || payload.type !== 'dataZoom' || payload.from !== this.uid) { + this._buildView(); + } + + this._updateView(); + }; + + SliderZoomView.prototype.dispose = function () { + this._clear(); + + _super.prototype.dispose.apply(this, arguments); + }; + + SliderZoomView.prototype._clear = function () { + clear(this, '_dispatchZoomAction'); + var zr = this.api.getZr(); + zr.off('mousemove', this._onBrush); + zr.off('mouseup', this._onBrushEnd); + }; + + SliderZoomView.prototype._buildView = function () { + var thisGroup = this.group; + thisGroup.removeAll(); + this._brushing = false; + this._displayables.brushRect = null; + + this._resetLocation(); + + this._resetInterval(); + + var barGroup = this._displayables.sliderGroup = new Group(); + + this._renderBackground(); + + this._renderHandle(); + + this._renderDataShadow(); + + thisGroup.add(barGroup); + + this._positionGroup(); + }; + + SliderZoomView.prototype._resetLocation = function () { + var dataZoomModel = this.dataZoomModel; + var api = this.api; + var showMoveHandle = dataZoomModel.get('brushSelect'); + var moveHandleSize = showMoveHandle ? DEFAULT_MOVE_HANDLE_SIZE : 0; + + var coordRect = this._findCoordRect(); + + var ecSize = { + width: api.getWidth(), + height: api.getHeight() + }; + var positionInfo = this._orient === HORIZONTAL ? { + right: ecSize.width - coordRect.x - coordRect.width, + top: ecSize.height - DEFAULT_FILLER_SIZE - DEFAULT_LOCATION_EDGE_GAP - moveHandleSize, + width: coordRect.width, + height: DEFAULT_FILLER_SIZE + } : { + right: DEFAULT_LOCATION_EDGE_GAP, + top: coordRect.y, + width: DEFAULT_FILLER_SIZE, + height: coordRect.height + }; + var layoutParams = getLayoutParams(dataZoomModel.option); + each(['right', 'top', 'width', 'height'], function (name) { + if (layoutParams[name] === 'ph') { + layoutParams[name] = positionInfo[name]; + } + }); + var layoutRect = getLayoutRect(layoutParams, ecSize); + this._location = { + x: layoutRect.x, + y: layoutRect.y + }; + this._size = [layoutRect.width, layoutRect.height]; + this._orient === VERTICAL && this._size.reverse(); + }; + + SliderZoomView.prototype._positionGroup = function () { + var thisGroup = this.group; + var location = this._location; + var orient = this._orient; + var targetAxisModel = this.dataZoomModel.getFirstTargetAxisModel(); + var inverse = targetAxisModel && targetAxisModel.get('inverse'); + var sliderGroup = this._displayables.sliderGroup; + var otherAxisInverse = (this._dataShadowInfo || {}).otherAxisInverse; + sliderGroup.attr(orient === HORIZONTAL && !inverse ? { + scaleY: otherAxisInverse ? 1 : -1, + scaleX: 1 + } : orient === HORIZONTAL && inverse ? { + scaleY: otherAxisInverse ? 1 : -1, + scaleX: -1 + } : orient === VERTICAL && !inverse ? { + scaleY: otherAxisInverse ? -1 : 1, + scaleX: 1, + rotation: Math.PI / 2 + } : { + scaleY: otherAxisInverse ? -1 : 1, + scaleX: -1, + rotation: Math.PI / 2 + }); + var rect = thisGroup.getBoundingRect([sliderGroup]); + thisGroup.x = location.x - rect.x; + thisGroup.y = location.y - rect.y; + thisGroup.markRedraw(); + }; + + SliderZoomView.prototype._getViewExtent = function () { + return [0, this._size[0]]; + }; + + SliderZoomView.prototype._renderBackground = function () { + var dataZoomModel = this.dataZoomModel; + var size = this._size; + var barGroup = this._displayables.sliderGroup; + var brushSelect = dataZoomModel.get('brushSelect'); + barGroup.add(new Rect$2({ + silent: true, + shape: { + x: 0, + y: 0, + width: size[0], + height: size[1] + }, + style: { + fill: dataZoomModel.get('backgroundColor') + }, + z2: -40 + })); + var clickPanel = new Rect$2({ + shape: { + x: 0, + y: 0, + width: size[0], + height: size[1] + }, + style: { + fill: 'transparent' + }, + z2: 0, + onclick: bind(this._onClickPanel, this) + }); + var zr = this.api.getZr(); + + if (brushSelect) { + clickPanel.on('mousedown', this._onBrushStart, this); + clickPanel.cursor = 'crosshair'; + zr.on('mousemove', this._onBrush); + zr.on('mouseup', this._onBrushEnd); + } else { + zr.off('mousemove', this._onBrush); + zr.off('mouseup', this._onBrushEnd); + } + + barGroup.add(clickPanel); + }; + + SliderZoomView.prototype._renderDataShadow = function () { + var info = this._dataShadowInfo = this._prepareDataShadowInfo(); + + this._displayables.dataShadowSegs = []; + + if (!info) { + return; + } + + var size = this._size; + var seriesModel = info.series; + var data = seriesModel.getRawData(); + var otherDim = seriesModel.getShadowDim ? seriesModel.getShadowDim() : info.otherDim; + + if (otherDim == null) { + return; + } + + var otherDataExtent = data.getDataExtent(otherDim); + var otherOffset = (otherDataExtent[1] - otherDataExtent[0]) * 0.3; + otherDataExtent = [otherDataExtent[0] - otherOffset, otherDataExtent[1] + otherOffset]; + var otherShadowExtent = [0, size[1]]; + var thisShadowExtent = [0, size[0]]; + var areaPoints = [[size[0], 0], [0, 0]]; + var linePoints = []; + var step = thisShadowExtent[1] / (data.count() - 1); + var thisCoord = 0; + var stride = Math.round(data.count() / size[0]); + var lastIsEmpty; + data.each([otherDim], function (value, index) { + if (stride > 0 && index % stride) { + thisCoord += step; + return; + } + + var isEmpty = value == null || isNaN(value) || value === ''; + var otherCoord = isEmpty ? 0 : linearMap(value, otherDataExtent, otherShadowExtent, true); + + if (isEmpty && !lastIsEmpty && index) { + areaPoints.push([areaPoints[areaPoints.length - 1][0], 0]); + linePoints.push([linePoints[linePoints.length - 1][0], 0]); + } else if (!isEmpty && lastIsEmpty) { + areaPoints.push([thisCoord, 0]); + linePoints.push([thisCoord, 0]); + } + + areaPoints.push([thisCoord, otherCoord]); + linePoints.push([thisCoord, otherCoord]); + thisCoord += step; + lastIsEmpty = isEmpty; + }); + var dataZoomModel = this.dataZoomModel; + + function createDataShadowGroup(isSelectedArea) { + var model = dataZoomModel.getModel(isSelectedArea ? 'selectedDataBackground' : 'dataBackground'); + var group = new Group(); + var polygon = new Polygon({ + shape: { + points: areaPoints + }, + segmentIgnoreThreshold: 1, + style: model.getModel('areaStyle').getAreaStyle(), + silent: true, + z2: -20 + }); + var polyline = new Polyline({ + shape: { + points: linePoints + }, + segmentIgnoreThreshold: 1, + style: model.getModel('lineStyle').getLineStyle(), + silent: true, + z2: -19 + }); + group.add(polygon); + group.add(polyline); + return group; + } + + for (var i = 0; i < 3; i++) { + var group = createDataShadowGroup(i === 1); + + this._displayables.sliderGroup.add(group); + + this._displayables.dataShadowSegs.push(group); + } + }; + + SliderZoomView.prototype._prepareDataShadowInfo = function () { + var dataZoomModel = this.dataZoomModel; + var showDataShadow = dataZoomModel.get('showDataShadow'); + + if (showDataShadow === false) { + return; + } + + var result; + var ecModel = this.ecModel; + dataZoomModel.eachTargetAxis(function (axisDim, axisIndex) { + var seriesModels = dataZoomModel.getAxisProxy(axisDim, axisIndex).getTargetSeriesModels(); + each(seriesModels, function (seriesModel) { + if (result) { + return; + } + + if (showDataShadow !== true && indexOf(SHOW_DATA_SHADOW_SERIES_TYPE, seriesModel.get('type')) < 0) { + return; + } + + var thisAxis = ecModel.getComponent(getAxisMainType(axisDim), axisIndex).axis; + var otherDim = getOtherDim(axisDim); + var otherAxisInverse; + var coordSys = seriesModel.coordinateSystem; + + if (otherDim != null && coordSys.getOtherAxis) { + otherAxisInverse = coordSys.getOtherAxis(thisAxis).inverse; + } + + otherDim = seriesModel.getData().mapDimension(otherDim); + result = { + thisAxis: thisAxis, + series: seriesModel, + thisDim: axisDim, + otherDim: otherDim, + otherAxisInverse: otherAxisInverse + }; + }, this); + }, this); + return result; + }; + + SliderZoomView.prototype._renderHandle = function () { + var thisGroup = this.group; + var displayables = this._displayables; + var handles = displayables.handles = [null, null]; + var handleLabels = displayables.handleLabels = [null, null]; + var sliderGroup = this._displayables.sliderGroup; + var size = this._size; + var dataZoomModel = this.dataZoomModel; + var api = this.api; + var borderRadius = dataZoomModel.get('borderRadius') || 0; + var brushSelect = dataZoomModel.get('brushSelect'); + var filler = displayables.filler = new Rect$2({ + silent: brushSelect, + style: { + fill: dataZoomModel.get('fillerColor') + }, + textConfig: { + position: 'inside' + } + }); + sliderGroup.add(filler); + sliderGroup.add(new Rect$2({ + silent: true, + subPixelOptimize: true, + shape: { + x: 0, + y: 0, + width: size[0], + height: size[1], + r: borderRadius + }, + style: { + stroke: dataZoomModel.get('dataBackgroundColor') || dataZoomModel.get('borderColor'), + lineWidth: DEFAULT_FRAME_BORDER_WIDTH, + fill: 'rgba(0,0,0,0)' + } + })); + each([0, 1], function (handleIndex) { + var iconStr = dataZoomModel.get('handleIcon'); + + if (!symbolBuildProxies[iconStr] && iconStr.indexOf('path://') < 0) { + iconStr = 'path://' + iconStr; + + if ("development" !== 'production') { + deprecateLog('handleIcon now needs \'path://\' prefix when using a path string'); + } + } + + var path = createSymbol(iconStr, -1, 0, 2, 2, null, true); + path.attr({ + cursor: getCursor(this._orient), + draggable: true, + drift: bind(this._onDragMove, this, handleIndex), + ondragend: bind(this._onDragEnd, this), + onmouseover: bind(this._showDataInfo, this, true), + onmouseout: bind(this._showDataInfo, this, false), + z2: 5 + }); + var bRect = path.getBoundingRect(); + var handleSize = dataZoomModel.get('handleSize'); + this._handleHeight = parsePercent$1(handleSize, this._size[1]); + this._handleWidth = bRect.width / bRect.height * this._handleHeight; + path.setStyle(dataZoomModel.getModel('handleStyle').getItemStyle()); + path.style.strokeNoScale = true; + path.rectHover = true; + path.ensureState('emphasis').style = dataZoomModel.getModel(['emphasis', 'handleStyle']).getItemStyle(); + enableHoverEmphasis(path); + var handleColor = dataZoomModel.get('handleColor'); + + if (handleColor != null) { + path.style.fill = handleColor; + } + + sliderGroup.add(handles[handleIndex] = path); + var textStyleModel = dataZoomModel.getModel('textStyle'); + thisGroup.add(handleLabels[handleIndex] = new ZRText({ + silent: true, + invisible: true, + style: { + x: 0, + y: 0, + text: '', + verticalAlign: 'middle', + align: 'center', + fill: textStyleModel.getTextColor(), + font: textStyleModel.getFont() + }, + z2: 10 + })); + }, this); + var actualMoveZone = filler; + + if (brushSelect) { + var moveHandleHeight = parsePercent$1(dataZoomModel.get('moveHandleSize'), size[1]); + var moveHandle_1 = displayables.moveHandle = new Rect({ + style: dataZoomModel.getModel('moveHandleStyle').getItemStyle(), + silent: true, + shape: { + r: [0, 0, 2, 2], + y: size[1] - 0.5, + height: moveHandleHeight + } + }); + var iconSize = moveHandleHeight * 0.8; + var moveHandleIcon = displayables.moveHandleIcon = createSymbol(dataZoomModel.get('moveHandleIcon'), -iconSize / 2, -iconSize / 2, iconSize, iconSize, '#fff', true); + moveHandleIcon.silent = true; + moveHandleIcon.y = size[1] + moveHandleHeight / 2 - 0.5; + moveHandle_1.ensureState('emphasis').style = dataZoomModel.getModel(['emphasis', 'moveHandleStyle']).getItemStyle(); + var moveZoneExpandSize = Math.min(size[1] / 2, Math.max(moveHandleHeight, 10)); + actualMoveZone = displayables.moveZone = new Rect({ + invisible: true, + shape: { + y: size[1] - moveZoneExpandSize, + height: moveHandleHeight + moveZoneExpandSize + } + }); + actualMoveZone.on('mouseover', function () { + api.enterEmphasis(moveHandle_1); + }).on('mouseout', function () { + api.leaveEmphasis(moveHandle_1); + }); + sliderGroup.add(moveHandle_1); + sliderGroup.add(moveHandleIcon); + sliderGroup.add(actualMoveZone); + } + + actualMoveZone.attr({ + draggable: true, + cursor: getCursor(this._orient), + drift: bind(this._onDragMove, this, 'all'), + ondragstart: bind(this._showDataInfo, this, true), + ondragend: bind(this._onDragEnd, this), + onmouseover: bind(this._showDataInfo, this, true), + onmouseout: bind(this._showDataInfo, this, false) + }); + }; + + SliderZoomView.prototype._resetInterval = function () { + var range = this._range = this.dataZoomModel.getPercentRange(); + + var viewExtent = this._getViewExtent(); + + this._handleEnds = [linearMap(range[0], [0, 100], viewExtent, true), linearMap(range[1], [0, 100], viewExtent, true)]; + }; + + SliderZoomView.prototype._updateInterval = function (handleIndex, delta) { + var dataZoomModel = this.dataZoomModel; + var handleEnds = this._handleEnds; + + var viewExtend = this._getViewExtent(); + + var minMaxSpan = dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan(); + var percentExtent = [0, 100]; + sliderMove(delta, handleEnds, viewExtend, dataZoomModel.get('zoomLock') ? 'all' : handleIndex, minMaxSpan.minSpan != null ? linearMap(minMaxSpan.minSpan, percentExtent, viewExtend, true) : null, minMaxSpan.maxSpan != null ? linearMap(minMaxSpan.maxSpan, percentExtent, viewExtend, true) : null); + var lastRange = this._range; + var range = this._range = asc([linearMap(handleEnds[0], viewExtend, percentExtent, true), linearMap(handleEnds[1], viewExtend, percentExtent, true)]); + return !lastRange || lastRange[0] !== range[0] || lastRange[1] !== range[1]; + }; + + SliderZoomView.prototype._updateView = function (nonRealtime) { + var displaybles = this._displayables; + var handleEnds = this._handleEnds; + var handleInterval = asc(handleEnds.slice()); + var size = this._size; + each([0, 1], function (handleIndex) { + var handle = displaybles.handles[handleIndex]; + var handleHeight = this._handleHeight; + handle.attr({ + scaleX: handleHeight / 2, + scaleY: handleHeight / 2, + x: handleEnds[handleIndex] + (handleIndex ? -1 : 1), + y: size[1] / 2 - handleHeight / 2 + }); + }, this); + displaybles.filler.setShape({ + x: handleInterval[0], + y: 0, + width: handleInterval[1] - handleInterval[0], + height: size[1] + }); + var viewExtent = { + x: handleInterval[0], + width: handleInterval[1] - handleInterval[0] + }; + + if (displaybles.moveHandle) { + displaybles.moveHandle.setShape(viewExtent); + displaybles.moveZone.setShape(viewExtent); + displaybles.moveZone.getBoundingRect(); + displaybles.moveHandleIcon && displaybles.moveHandleIcon.attr('x', viewExtent.x + viewExtent.width / 2); + } + + var dataShadowSegs = displaybles.dataShadowSegs; + var segIntervals = [0, handleInterval[0], handleInterval[1], size[0]]; + + for (var i = 0; i < dataShadowSegs.length; i++) { + var segGroup = dataShadowSegs[i]; + var clipPath = segGroup.getClipPath(); + + if (!clipPath) { + clipPath = new Rect(); + segGroup.setClipPath(clipPath); + } + + clipPath.setShape({ + x: segIntervals[i], + y: 0, + width: segIntervals[i + 1] - segIntervals[i], + height: size[1] + }); + } + + this._updateDataInfo(nonRealtime); + }; + + SliderZoomView.prototype._updateDataInfo = function (nonRealtime) { + var dataZoomModel = this.dataZoomModel; + var displaybles = this._displayables; + var handleLabels = displaybles.handleLabels; + var orient = this._orient; + var labelTexts = ['', '']; + + if (dataZoomModel.get('showDetail')) { + var axisProxy = dataZoomModel.findRepresentativeAxisProxy(); + + if (axisProxy) { + var axis = axisProxy.getAxisModel().axis; + var range = this._range; + var dataInterval = nonRealtime ? axisProxy.calculateDataWindow({ + start: range[0], + end: range[1] + }).valueWindow : axisProxy.getDataValueWindow(); + labelTexts = [this._formatLabel(dataInterval[0], axis), this._formatLabel(dataInterval[1], axis)]; + } + } + + var orderedHandleEnds = asc(this._handleEnds.slice()); + setLabel.call(this, 0); + setLabel.call(this, 1); + + function setLabel(handleIndex) { + var barTransform = getTransform(displaybles.handles[handleIndex].parent, this.group); + var direction = transformDirection(handleIndex === 0 ? 'right' : 'left', barTransform); + var offset = this._handleWidth / 2 + LABEL_GAP; + var textPoint = applyTransform$1([orderedHandleEnds[handleIndex] + (handleIndex === 0 ? -offset : offset), this._size[1] / 2], barTransform); + handleLabels[handleIndex].setStyle({ + x: textPoint[0], + y: textPoint[1], + verticalAlign: orient === HORIZONTAL ? 'middle' : direction, + align: orient === HORIZONTAL ? direction : 'center', + text: labelTexts[handleIndex] + }); + } + }; + + SliderZoomView.prototype._formatLabel = function (value, axis) { + var dataZoomModel = this.dataZoomModel; + var labelFormatter = dataZoomModel.get('labelFormatter'); + var labelPrecision = dataZoomModel.get('labelPrecision'); + + if (labelPrecision == null || labelPrecision === 'auto') { + labelPrecision = axis.getPixelPrecision(); + } + + var valueStr = value == null || isNaN(value) ? '' : axis.type === 'category' || axis.type === 'time' ? axis.scale.getLabel({ + value: Math.round(value) + }) : value.toFixed(Math.min(labelPrecision, 20)); + return isFunction(labelFormatter) ? labelFormatter(value, valueStr) : isString(labelFormatter) ? labelFormatter.replace('{value}', valueStr) : valueStr; + }; + + SliderZoomView.prototype._showDataInfo = function (showOrHide) { + showOrHide = this._dragging || showOrHide; + var displayables = this._displayables; + var handleLabels = displayables.handleLabels; + handleLabels[0].attr('invisible', !showOrHide); + handleLabels[1].attr('invisible', !showOrHide); + displayables.moveHandle && this.api[showOrHide ? 'enterEmphasis' : 'leaveEmphasis'](displayables.moveHandle, 1); + }; + + SliderZoomView.prototype._onDragMove = function (handleIndex, dx, dy, event) { + this._dragging = true; + stop(event.event); + + var barTransform = this._displayables.sliderGroup.getLocalTransform(); + + var vertex = applyTransform$1([dx, dy], barTransform, true); + + var changed = this._updateInterval(handleIndex, vertex[0]); + + var realtime = this.dataZoomModel.get('realtime'); + + this._updateView(!realtime); + + changed && realtime && this._dispatchZoomAction(true); + }; + + SliderZoomView.prototype._onDragEnd = function () { + this._dragging = false; + + this._showDataInfo(false); + + var realtime = this.dataZoomModel.get('realtime'); + !realtime && this._dispatchZoomAction(false); + }; + + SliderZoomView.prototype._onClickPanel = function (e) { + var size = this._size; + + var localPoint = this._displayables.sliderGroup.transformCoordToLocal(e.offsetX, e.offsetY); + + if (localPoint[0] < 0 || localPoint[0] > size[0] || localPoint[1] < 0 || localPoint[1] > size[1]) { + return; + } + + var handleEnds = this._handleEnds; + var center = (handleEnds[0] + handleEnds[1]) / 2; + + var changed = this._updateInterval('all', localPoint[0] - center); + + this._updateView(); + + changed && this._dispatchZoomAction(false); + }; + + SliderZoomView.prototype._onBrushStart = function (e) { + var x = e.offsetX; + var y = e.offsetY; + this._brushStart = new Point(x, y); + this._brushing = true; + this._brushStartTime = +new Date(); + }; + + SliderZoomView.prototype._onBrushEnd = function (e) { + if (!this._brushing) { + return; + } + + var brushRect = this._displayables.brushRect; + this._brushing = false; + + if (!brushRect) { + return; + } + + brushRect.attr('ignore', true); + var brushShape = brushRect.shape; + var brushEndTime = +new Date(); + + if (brushEndTime - this._brushStartTime < 200 && Math.abs(brushShape.width) < 5) { + return; + } + + var viewExtend = this._getViewExtent(); + + var percentExtent = [0, 100]; + this._range = asc([linearMap(brushShape.x, viewExtend, percentExtent, true), linearMap(brushShape.x + brushShape.width, viewExtend, percentExtent, true)]); + this._handleEnds = [brushShape.x, brushShape.x + brushShape.width]; + + this._updateView(); + + this._dispatchZoomAction(false); + }; + + SliderZoomView.prototype._onBrush = function (e) { + if (this._brushing) { + stop(e.event); + + this._updateBrushRect(e.offsetX, e.offsetY); + } + }; + + SliderZoomView.prototype._updateBrushRect = function (mouseX, mouseY) { + var displayables = this._displayables; + var dataZoomModel = this.dataZoomModel; + var brushRect = displayables.brushRect; + + if (!brushRect) { + brushRect = displayables.brushRect = new Rect$2({ + silent: true, + style: dataZoomModel.getModel('brushStyle').getItemStyle() + }); + displayables.sliderGroup.add(brushRect); + } + + brushRect.attr('ignore', false); + var brushStart = this._brushStart; + var sliderGroup = this._displayables.sliderGroup; + var endPoint = sliderGroup.transformCoordToLocal(mouseX, mouseY); + var startPoint = sliderGroup.transformCoordToLocal(brushStart.x, brushStart.y); + var size = this._size; + endPoint[0] = Math.max(Math.min(size[0], endPoint[0]), 0); + brushRect.setShape({ + x: startPoint[0], + y: 0, + width: endPoint[0] - startPoint[0], + height: size[1] + }); + }; + + SliderZoomView.prototype._dispatchZoomAction = function (realtime) { + var range = this._range; + this.api.dispatchAction({ + type: 'dataZoom', + from: this.uid, + dataZoomId: this.dataZoomModel.id, + animation: realtime ? REALTIME_ANIMATION_CONFIG : null, + start: range[0], + end: range[1] + }); + }; + + SliderZoomView.prototype._findCoordRect = function () { + var rect; + var coordSysInfoList = collectReferCoordSysModelInfo(this.dataZoomModel).infoList; + + if (!rect && coordSysInfoList.length) { + var coordSys = coordSysInfoList[0].model.coordinateSystem; + rect = coordSys.getRect && coordSys.getRect(); + } + + if (!rect) { + var width = this.api.getWidth(); + var height = this.api.getHeight(); + rect = { + x: width * 0.2, + y: height * 0.2, + width: width * 0.6, + height: height * 0.6 + }; + } + + return rect; + }; + + SliderZoomView.type = 'dataZoom.slider'; + return SliderZoomView; + }(DataZoomView); + + function getOtherDim(thisDim) { + var map = { + x: 'y', + y: 'x', + radius: 'angle', + angle: 'radius' + }; + return map[thisDim]; + } + + function getCursor(orient) { + return orient === 'vertical' ? 'ns-resize' : 'ew-resize'; + } + + function install$L(registers) { + registers.registerComponentModel(SliderZoomModel); + registers.registerComponentView(SliderZoomView); + installCommon(registers); + } + + function install$M(registers) { + use(install$K); + use(install$L); + } + + var visualDefault = { + get: function (visualType, key, isCategory) { + var value = clone((defaultOption$1[visualType] || {})[key]); + return isCategory ? isArray(value) ? value[value.length - 1] : value : value; + } + }; + var defaultOption$1 = { + color: { + active: ['#006edd', '#e0ffff'], + inactive: ['rgba(0,0,0,0)'] + }, + colorHue: { + active: [0, 360], + inactive: [0, 0] + }, + colorSaturation: { + active: [0.3, 1], + inactive: [0, 0] + }, + colorLightness: { + active: [0.9, 0.5], + inactive: [0, 0] + }, + colorAlpha: { + active: [0.3, 1], + inactive: [0, 0] + }, + opacity: { + active: [0.3, 1], + inactive: [0, 0] + }, + symbol: { + active: ['circle', 'roundRect', 'diamond'], + inactive: ['none'] + }, + symbolSize: { + active: [10, 50], + inactive: [0, 0] + } + }; + + var mapVisual$1 = VisualMapping.mapVisual; + var eachVisual = VisualMapping.eachVisual; + var isArray$1 = isArray; + var each$f = each; + var asc$2 = asc; + var linearMap$1 = linearMap; + + var VisualMapModel = function (_super) { + __extends(VisualMapModel, _super); + + function VisualMapModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = VisualMapModel.type; + _this.stateList = ['inRange', 'outOfRange']; + _this.replacableOptionKeys = ['inRange', 'outOfRange', 'target', 'controller', 'color']; + _this.layoutMode = { + type: 'box', + ignoreSize: true + }; + _this.dataBound = [-Infinity, Infinity]; + _this.targetVisuals = {}; + _this.controllerVisuals = {}; + return _this; + } + + VisualMapModel.prototype.init = function (option, parentModel, ecModel) { + this.mergeDefaultAndTheme(option, ecModel); + }; + + VisualMapModel.prototype.optionUpdated = function (newOption, isInit) { + var thisOption = this.option; + + if (!env.canvasSupported) { + thisOption.realtime = false; + } + + !isInit && replaceVisualOption(thisOption, newOption, this.replacableOptionKeys); + this.textStyleModel = this.getModel('textStyle'); + this.resetItemSize(); + this.completeVisualOption(); + }; + + VisualMapModel.prototype.resetVisual = function (supplementVisualOption) { + var stateList = this.stateList; + supplementVisualOption = bind(supplementVisualOption, this); + this.controllerVisuals = createVisualMappings(this.option.controller, stateList, supplementVisualOption); + this.targetVisuals = createVisualMappings(this.option.target, stateList, supplementVisualOption); + }; + + VisualMapModel.prototype.getTargetSeriesIndices = function () { + var optionSeriesIndex = this.option.seriesIndex; + var seriesIndices = []; + + if (optionSeriesIndex == null || optionSeriesIndex === 'all') { + this.ecModel.eachSeries(function (seriesModel, index) { + seriesIndices.push(index); + }); + } else { + seriesIndices = normalizeToArray(optionSeriesIndex); + } + + return seriesIndices; + }; + + VisualMapModel.prototype.eachTargetSeries = function (callback, context) { + each(this.getTargetSeriesIndices(), function (seriesIndex) { + var seriesModel = this.ecModel.getSeriesByIndex(seriesIndex); + + if (seriesModel) { + callback.call(context, seriesModel); + } + }, this); + }; + + VisualMapModel.prototype.isTargetSeries = function (seriesModel) { + var is = false; + this.eachTargetSeries(function (model) { + model === seriesModel && (is = true); + }); + return is; + }; + + VisualMapModel.prototype.formatValueText = function (value, isCategory, edgeSymbols) { + var option = this.option; + var precision = option.precision; + var dataBound = this.dataBound; + var formatter = option.formatter; + var isMinMax; + edgeSymbols = edgeSymbols || ['<', '>']; + + if (isArray(value)) { + value = value.slice(); + isMinMax = true; + } + + var textValue = isCategory ? value : isMinMax ? [toFixed(value[0]), toFixed(value[1])] : toFixed(value); + + if (isString(formatter)) { + return formatter.replace('{value}', isMinMax ? textValue[0] : textValue).replace('{value2}', isMinMax ? textValue[1] : textValue); + } else if (isFunction(formatter)) { + return isMinMax ? formatter(value[0], value[1]) : formatter(value); + } + + if (isMinMax) { + if (value[0] === dataBound[0]) { + return edgeSymbols[0] + ' ' + textValue[1]; + } else if (value[1] === dataBound[1]) { + return edgeSymbols[1] + ' ' + textValue[0]; + } else { + return textValue[0] + ' - ' + textValue[1]; + } + } else { + return textValue; + } + + function toFixed(val) { + return val === dataBound[0] ? 'min' : val === dataBound[1] ? 'max' : (+val).toFixed(Math.min(precision, 20)); + } + }; + + VisualMapModel.prototype.resetExtent = function () { + var thisOption = this.option; + var extent = asc$2([thisOption.min, thisOption.max]); + this._dataExtent = extent; + }; + + VisualMapModel.prototype.getDataDimension = function (list) { + var optDim = this.option.dimension; + var listDimensions = list.dimensions; + + if (optDim == null && !listDimensions.length) { + return; + } + + if (optDim != null) { + return list.getDimension(optDim); + } + + var dimNames = list.dimensions; + + for (var i = dimNames.length - 1; i >= 0; i--) { + var dimName = dimNames[i]; + var dimInfo = list.getDimensionInfo(dimName); + + if (!dimInfo.isCalculationCoord) { + return dimName; + } + } + }; + + VisualMapModel.prototype.getExtent = function () { + return this._dataExtent.slice(); + }; + + VisualMapModel.prototype.completeVisualOption = function () { + var ecModel = this.ecModel; + var thisOption = this.option; + var base = { + inRange: thisOption.inRange, + outOfRange: thisOption.outOfRange + }; + var target = thisOption.target || (thisOption.target = {}); + var controller = thisOption.controller || (thisOption.controller = {}); + merge(target, base); + merge(controller, base); + var isCategory = this.isCategory(); + completeSingle.call(this, target); + completeSingle.call(this, controller); + completeInactive.call(this, target, 'inRange', 'outOfRange'); + completeController.call(this, controller); + + function completeSingle(base) { + if (isArray$1(thisOption.color) && !base.inRange) { + base.inRange = { + color: thisOption.color.slice().reverse() + }; + } + + base.inRange = base.inRange || { + color: ecModel.get('gradientColor') + }; + } + + function completeInactive(base, stateExist, stateAbsent) { + var optExist = base[stateExist]; + var optAbsent = base[stateAbsent]; + + if (optExist && !optAbsent) { + optAbsent = base[stateAbsent] = {}; + each$f(optExist, function (visualData, visualType) { + if (!VisualMapping.isValidType(visualType)) { + return; + } + + var defa = visualDefault.get(visualType, 'inactive', isCategory); + + if (defa != null) { + optAbsent[visualType] = defa; + + if (visualType === 'color' && !optAbsent.hasOwnProperty('opacity') && !optAbsent.hasOwnProperty('colorAlpha')) { + optAbsent.opacity = [0, 0]; + } + } + }); + } + } + + function completeController(controller) { + var symbolExists = (controller.inRange || {}).symbol || (controller.outOfRange || {}).symbol; + var symbolSizeExists = (controller.inRange || {}).symbolSize || (controller.outOfRange || {}).symbolSize; + var inactiveColor = this.get('inactiveColor'); + each$f(this.stateList, function (state) { + var itemSize = this.itemSize; + var visuals = controller[state]; + + if (!visuals) { + visuals = controller[state] = { + color: isCategory ? inactiveColor : [inactiveColor] + }; + } + + if (visuals.symbol == null) { + visuals.symbol = symbolExists && clone(symbolExists) || (isCategory ? 'roundRect' : ['roundRect']); + } + + if (visuals.symbolSize == null) { + visuals.symbolSize = symbolSizeExists && clone(symbolSizeExists) || (isCategory ? itemSize[0] : [itemSize[0], itemSize[0]]); + } + + visuals.symbol = mapVisual$1(visuals.symbol, function (symbol) { + return symbol === 'none' || symbol === 'square' ? 'roundRect' : symbol; + }); + var symbolSize = visuals.symbolSize; + + if (symbolSize != null) { + var max_1 = -Infinity; + eachVisual(symbolSize, function (value) { + value > max_1 && (max_1 = value); + }); + visuals.symbolSize = mapVisual$1(symbolSize, function (value) { + return linearMap$1(value, [0, max_1], [0, itemSize[0]], true); + }); + } + }, this); + } + }; + + VisualMapModel.prototype.resetItemSize = function () { + this.itemSize = [parseFloat(this.get('itemWidth')), parseFloat(this.get('itemHeight'))]; + }; + + VisualMapModel.prototype.isCategory = function () { + return !!this.option.categories; + }; + + VisualMapModel.prototype.setSelected = function (selected) {}; + + VisualMapModel.prototype.getSelected = function () { + return null; + }; + + VisualMapModel.prototype.getValueState = function (value) { + return null; + }; + + VisualMapModel.prototype.getVisualMeta = function (getColorVisual) { + return null; + }; + + VisualMapModel.type = 'visualMap'; + VisualMapModel.dependencies = ['series']; + VisualMapModel.defaultOption = { + show: true, + zlevel: 0, + z: 4, + seriesIndex: 'all', + min: 0, + max: 200, + left: 0, + right: null, + top: null, + bottom: 0, + itemWidth: null, + itemHeight: null, + inverse: false, + orient: 'vertical', + backgroundColor: 'rgba(0,0,0,0)', + borderColor: '#ccc', + contentColor: '#5793f3', + inactiveColor: '#aaa', + borderWidth: 0, + padding: 5, + textGap: 10, + precision: 0, + textStyle: { + color: '#333' + } + }; + return VisualMapModel; + }(ComponentModel); + + var DEFAULT_BAR_BOUND = [20, 140]; + + var ContinuousModel = function (_super) { + __extends(ContinuousModel, _super); + + function ContinuousModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ContinuousModel.type; + return _this; + } + + ContinuousModel.prototype.optionUpdated = function (newOption, isInit) { + _super.prototype.optionUpdated.apply(this, arguments); + + this.resetExtent(); + this.resetVisual(function (mappingOption) { + mappingOption.mappingMethod = 'linear'; + mappingOption.dataExtent = this.getExtent(); + }); + + this._resetRange(); + }; + + ContinuousModel.prototype.resetItemSize = function () { + _super.prototype.resetItemSize.apply(this, arguments); + + var itemSize = this.itemSize; + (itemSize[0] == null || isNaN(itemSize[0])) && (itemSize[0] = DEFAULT_BAR_BOUND[0]); + (itemSize[1] == null || isNaN(itemSize[1])) && (itemSize[1] = DEFAULT_BAR_BOUND[1]); + }; + + ContinuousModel.prototype._resetRange = function () { + var dataExtent = this.getExtent(); + var range = this.option.range; + + if (!range || range.auto) { + dataExtent.auto = 1; + this.option.range = dataExtent; + } else if (isArray(range)) { + if (range[0] > range[1]) { + range.reverse(); + } + + range[0] = Math.max(range[0], dataExtent[0]); + range[1] = Math.min(range[1], dataExtent[1]); + } + }; + + ContinuousModel.prototype.completeVisualOption = function () { + _super.prototype.completeVisualOption.apply(this, arguments); + + each(this.stateList, function (state) { + var symbolSize = this.option.controller[state].symbolSize; + + if (symbolSize && symbolSize[0] !== symbolSize[1]) { + symbolSize[0] = symbolSize[1] / 3; + } + }, this); + }; + + ContinuousModel.prototype.setSelected = function (selected) { + this.option.range = selected.slice(); + + this._resetRange(); + }; + + ContinuousModel.prototype.getSelected = function () { + var dataExtent = this.getExtent(); + var dataInterval = asc((this.get('range') || []).slice()); + dataInterval[0] > dataExtent[1] && (dataInterval[0] = dataExtent[1]); + dataInterval[1] > dataExtent[1] && (dataInterval[1] = dataExtent[1]); + dataInterval[0] < dataExtent[0] && (dataInterval[0] = dataExtent[0]); + dataInterval[1] < dataExtent[0] && (dataInterval[1] = dataExtent[0]); + return dataInterval; + }; + + ContinuousModel.prototype.getValueState = function (value) { + var range = this.option.range; + var dataExtent = this.getExtent(); + return (range[0] <= dataExtent[0] || range[0] <= value) && (range[1] >= dataExtent[1] || value <= range[1]) ? 'inRange' : 'outOfRange'; + }; + + ContinuousModel.prototype.findTargetDataIndices = function (range) { + var result = []; + this.eachTargetSeries(function (seriesModel) { + var dataIndices = []; + var data = seriesModel.getData(); + data.each(this.getDataDimension(data), function (value, dataIndex) { + range[0] <= value && value <= range[1] && dataIndices.push(dataIndex); + }, this); + result.push({ + seriesId: seriesModel.id, + dataIndex: dataIndices + }); + }, this); + return result; + }; + + ContinuousModel.prototype.getVisualMeta = function (getColorVisual) { + var oVals = getColorStopValues(this, 'outOfRange', this.getExtent()); + var iVals = getColorStopValues(this, 'inRange', this.option.range.slice()); + var stops = []; + + function setStop(value, valueState) { + stops.push({ + value: value, + color: getColorVisual(value, valueState) + }); + } + + var iIdx = 0; + var oIdx = 0; + var iLen = iVals.length; + var oLen = oVals.length; + + for (; oIdx < oLen && (!iVals.length || oVals[oIdx] <= iVals[0]); oIdx++) { + if (oVals[oIdx] < iVals[iIdx]) { + setStop(oVals[oIdx], 'outOfRange'); + } + } + + for (var first = 1; iIdx < iLen; iIdx++, first = 0) { + first && stops.length && setStop(iVals[iIdx], 'outOfRange'); + setStop(iVals[iIdx], 'inRange'); + } + + for (var first = 1; oIdx < oLen; oIdx++) { + if (!iVals.length || iVals[iVals.length - 1] < oVals[oIdx]) { + if (first) { + stops.length && setStop(stops[stops.length - 1].value, 'outOfRange'); + first = 0; + } + + setStop(oVals[oIdx], 'outOfRange'); + } + } + + var stopsLen = stops.length; + return { + stops: stops, + outerColors: [stopsLen ? stops[0].color : 'transparent', stopsLen ? stops[stopsLen - 1].color : 'transparent'] + }; + }; + + ContinuousModel.type = 'visualMap.continuous'; + ContinuousModel.defaultOption = inheritDefaultOption(VisualMapModel.defaultOption, { + align: 'auto', + calculable: false, + hoverLink: true, + realtime: true, + handleIcon: 'path://M-11.39,9.77h0a3.5,3.5,0,0,1-3.5,3.5h-22a3.5,3.5,0,0,1-3.5-3.5h0a3.5,3.5,0,0,1,3.5-3.5h22A3.5,3.5,0,0,1-11.39,9.77Z', + handleSize: '120%', + handleStyle: { + borderColor: '#fff', + borderWidth: 1 + }, + indicatorIcon: 'circle', + indicatorSize: '50%', + indicatorStyle: { + borderColor: '#fff', + borderWidth: 2, + shadowBlur: 2, + shadowOffsetX: 1, + shadowOffsetY: 1, + shadowColor: 'rgba(0,0,0,0.2)' + } + }); + return ContinuousModel; + }(VisualMapModel); + + function getColorStopValues(visualMapModel, valueState, dataExtent) { + if (dataExtent[0] === dataExtent[1]) { + return dataExtent.slice(); + } + + var count = 200; + var step = (dataExtent[1] - dataExtent[0]) / count; + var value = dataExtent[0]; + var stopValues = []; + + for (var i = 0; i <= count && value < dataExtent[1]; i++) { + stopValues.push(value); + value += step; + } + + stopValues.push(dataExtent[1]); + return stopValues; + } + + var VisualMapView = function (_super) { + __extends(VisualMapView, _super); + + function VisualMapView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = VisualMapView.type; + _this.autoPositionValues = { + left: 1, + right: 1, + top: 1, + bottom: 1 + }; + return _this; + } + + VisualMapView.prototype.init = function (ecModel, api) { + this.ecModel = ecModel; + this.api = api; + }; + + VisualMapView.prototype.render = function (visualMapModel, ecModel, api, payload) { + this.visualMapModel = visualMapModel; + + if (visualMapModel.get('show') === false) { + this.group.removeAll(); + return; + } + + this.doRender(visualMapModel, ecModel, api, payload); + }; + + VisualMapView.prototype.renderBackground = function (group) { + var visualMapModel = this.visualMapModel; + var padding = normalizeCssArray$1(visualMapModel.get('padding') || 0); + var rect = group.getBoundingRect(); + group.add(new Rect({ + z2: -1, + silent: true, + shape: { + x: rect.x - padding[3], + y: rect.y - padding[0], + width: rect.width + padding[3] + padding[1], + height: rect.height + padding[0] + padding[2] + }, + style: { + fill: visualMapModel.get('backgroundColor'), + stroke: visualMapModel.get('borderColor'), + lineWidth: visualMapModel.get('borderWidth') + } + })); + }; + + VisualMapView.prototype.getControllerVisual = function (targetValue, visualCluster, opts) { + opts = opts || {}; + var forceState = opts.forceState; + var visualMapModel = this.visualMapModel; + var visualObj = {}; + + if (visualCluster === 'symbol') { + visualObj.symbol = visualMapModel.get('itemSymbol'); + } + + if (visualCluster === 'color') { + var defaultColor = visualMapModel.get('contentColor'); + visualObj.color = defaultColor; + } + + function getter(key) { + return visualObj[key]; + } + + function setter(key, value) { + visualObj[key] = value; + } + + var mappings = visualMapModel.controllerVisuals[forceState || visualMapModel.getValueState(targetValue)]; + var visualTypes = VisualMapping.prepareVisualTypes(mappings); + each(visualTypes, function (type) { + var visualMapping = mappings[type]; + + if (opts.convertOpacityToAlpha && type === 'opacity') { + type = 'colorAlpha'; + visualMapping = mappings.__alphaForOpacity; + } + + if (VisualMapping.dependsOn(type, visualCluster)) { + visualMapping && visualMapping.applyVisual(targetValue, getter, setter); + } + }); + return visualObj[visualCluster]; + }; + + VisualMapView.prototype.positionGroup = function (group) { + var model = this.visualMapModel; + var api = this.api; + positionElement(group, model.getBoxLayoutParams(), { + width: api.getWidth(), + height: api.getHeight() + }); + }; + + VisualMapView.prototype.doRender = function (visualMapModel, ecModel, api, payload) {}; + + VisualMapView.type = 'visualMap'; + return VisualMapView; + }(ComponentView); + + var paramsSet = [['left', 'right', 'width'], ['top', 'bottom', 'height']]; + function getItemAlign(visualMapModel, api, itemSize) { + var modelOption = visualMapModel.option; + var itemAlign = modelOption.align; + + if (itemAlign != null && itemAlign !== 'auto') { + return itemAlign; + } + + var ecSize = { + width: api.getWidth(), + height: api.getHeight() + }; + var realIndex = modelOption.orient === 'horizontal' ? 1 : 0; + var reals = paramsSet[realIndex]; + var fakeValue = [0, null, 10]; + var layoutInput = {}; + + for (var i = 0; i < 3; i++) { + layoutInput[paramsSet[1 - realIndex][i]] = fakeValue[i]; + layoutInput[reals[i]] = i === 2 ? itemSize[0] : modelOption[reals[i]]; + } + + var rParam = [['x', 'width', 3], ['y', 'height', 0]][realIndex]; + var rect = getLayoutRect(layoutInput, ecSize, modelOption.padding); + return reals[(rect.margin[rParam[2]] || 0) + rect[rParam[0]] + rect[rParam[1]] * 0.5 < ecSize[rParam[1]] * 0.5 ? 0 : 1]; + } + function makeHighDownBatch(batch, visualMapModel) { + each(batch || [], function (batchItem) { + if (batchItem.dataIndex != null) { + batchItem.dataIndexInside = batchItem.dataIndex; + batchItem.dataIndex = null; + } + + batchItem.highlightKey = 'visualMap' + (visualMapModel ? visualMapModel.componentIndex : ''); + }); + return batch; + } + + var linearMap$2 = linearMap; + var each$g = each; + var mathMin$a = Math.min; + var mathMax$a = Math.max; + var HOVER_LINK_SIZE = 12; + var HOVER_LINK_OUT = 6; + + var ContinuousView = function (_super) { + __extends(ContinuousView, _super); + + function ContinuousView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = ContinuousView.type; + _this._shapes = {}; + _this._dataInterval = []; + _this._handleEnds = []; + _this._hoverLinkDataIndices = []; + return _this; + } + + ContinuousView.prototype.doRender = function (visualMapModel, ecModel, api, payload) { + this._api = api; + + if (!payload || payload.type !== 'selectDataRange' || payload.from !== this.uid) { + this._buildView(); + } + }; + + ContinuousView.prototype._buildView = function () { + this.group.removeAll(); + var visualMapModel = this.visualMapModel; + var thisGroup = this.group; + this._orient = visualMapModel.get('orient'); + this._useHandle = visualMapModel.get('calculable'); + + this._resetInterval(); + + this._renderBar(thisGroup); + + var dataRangeText = visualMapModel.get('text'); + + this._renderEndsText(thisGroup, dataRangeText, 0); + + this._renderEndsText(thisGroup, dataRangeText, 1); + + this._updateView(true); + + this.renderBackground(thisGroup); + + this._updateView(); + + this._enableHoverLinkToSeries(); + + this._enableHoverLinkFromSeries(); + + this.positionGroup(thisGroup); + }; + + ContinuousView.prototype._renderEndsText = function (group, dataRangeText, endsIndex) { + if (!dataRangeText) { + return; + } + + var text = dataRangeText[1 - endsIndex]; + text = text != null ? text + '' : ''; + var visualMapModel = this.visualMapModel; + var textGap = visualMapModel.get('textGap'); + var itemSize = visualMapModel.itemSize; + var barGroup = this._shapes.mainGroup; + + var position = this._applyTransform([itemSize[0] / 2, endsIndex === 0 ? -textGap : itemSize[1] + textGap], barGroup); + + var align = this._applyTransform(endsIndex === 0 ? 'bottom' : 'top', barGroup); + + var orient = this._orient; + var textStyleModel = this.visualMapModel.textStyleModel; + this.group.add(new ZRText({ + style: { + x: position[0], + y: position[1], + verticalAlign: orient === 'horizontal' ? 'middle' : align, + align: orient === 'horizontal' ? align : 'center', + text: text, + font: textStyleModel.getFont(), + fill: textStyleModel.getTextColor() + } + })); + }; + + ContinuousView.prototype._renderBar = function (targetGroup) { + var visualMapModel = this.visualMapModel; + var shapes = this._shapes; + var itemSize = visualMapModel.itemSize; + var orient = this._orient; + var useHandle = this._useHandle; + var itemAlign = getItemAlign(visualMapModel, this.api, itemSize); + + var mainGroup = shapes.mainGroup = this._createBarGroup(itemAlign); + + var gradientBarGroup = new Group(); + mainGroup.add(gradientBarGroup); + gradientBarGroup.add(shapes.outOfRange = createPolygon()); + gradientBarGroup.add(shapes.inRange = createPolygon(null, useHandle ? getCursor$1(this._orient) : null, bind(this._dragHandle, this, 'all', false), bind(this._dragHandle, this, 'all', true))); + gradientBarGroup.setClipPath(new Rect({ + shape: { + x: 0, + y: 0, + width: itemSize[0], + height: itemSize[1], + r: 3 + } + })); + var textRect = visualMapModel.textStyleModel.getTextRect('国'); + var textSize = mathMax$a(textRect.width, textRect.height); + + if (useHandle) { + shapes.handleThumbs = []; + shapes.handleLabels = []; + shapes.handleLabelPoints = []; + + this._createHandle(visualMapModel, mainGroup, 0, itemSize, textSize, orient); + + this._createHandle(visualMapModel, mainGroup, 1, itemSize, textSize, orient); + } + + this._createIndicator(visualMapModel, mainGroup, itemSize, textSize, orient); + + targetGroup.add(mainGroup); + }; + + ContinuousView.prototype._createHandle = function (visualMapModel, mainGroup, handleIndex, itemSize, textSize, orient) { + var onDrift = bind(this._dragHandle, this, handleIndex, false); + var onDragEnd = bind(this._dragHandle, this, handleIndex, true); + var handleSize = parsePercent(visualMapModel.get('handleSize'), itemSize[0]); + var handleThumb = createSymbol(visualMapModel.get('handleIcon'), -handleSize / 2, -handleSize / 2, handleSize, handleSize, null, true); + var cursor = getCursor$1(this._orient); + handleThumb.attr({ + cursor: cursor, + draggable: true, + drift: onDrift, + ondragend: onDragEnd, + onmousemove: function (e) { + stop(e.event); + } + }); + handleThumb.x = itemSize[0] / 2; + handleThumb.useStyle(visualMapModel.getModel('handleStyle').getItemStyle()); + handleThumb.setStyle({ + strokeNoScale: true, + strokeFirst: true + }); + handleThumb.style.lineWidth *= 2; + handleThumb.ensureState('emphasis').style = visualMapModel.getModel(['emphasis', 'handleStyle']).getItemStyle(); + setAsHighDownDispatcher(handleThumb, true); + mainGroup.add(handleThumb); + var textStyleModel = this.visualMapModel.textStyleModel; + var handleLabel = new ZRText({ + cursor: cursor, + draggable: true, + drift: onDrift, + onmousemove: function (e) { + stop(e.event); + }, + ondragend: onDragEnd, + style: { + x: 0, + y: 0, + text: '', + font: textStyleModel.getFont(), + fill: textStyleModel.getTextColor() + } + }); + handleLabel.ensureState('blur').style = { + opacity: 0.1 + }; + handleLabel.stateTransition = { + duration: 200 + }; + this.group.add(handleLabel); + var handleLabelPoint = [handleSize, 0]; + var shapes = this._shapes; + shapes.handleThumbs[handleIndex] = handleThumb; + shapes.handleLabelPoints[handleIndex] = handleLabelPoint; + shapes.handleLabels[handleIndex] = handleLabel; + }; + + ContinuousView.prototype._createIndicator = function (visualMapModel, mainGroup, itemSize, textSize, orient) { + var scale = parsePercent(visualMapModel.get('indicatorSize'), itemSize[0]); + var indicator = createSymbol(visualMapModel.get('indicatorIcon'), -scale / 2, -scale / 2, scale, scale, null, true); + indicator.attr({ + cursor: 'move', + invisible: true, + silent: true, + x: itemSize[0] / 2 + }); + var indicatorStyle = visualMapModel.getModel('indicatorStyle').getItemStyle(); + + if (indicator instanceof ZRImage) { + var pathStyle = indicator.style; + indicator.useStyle(extend({ + image: pathStyle.image, + x: pathStyle.x, + y: pathStyle.y, + width: pathStyle.width, + height: pathStyle.height + }, indicatorStyle)); + } else { + indicator.useStyle(indicatorStyle); + } + + mainGroup.add(indicator); + var textStyleModel = this.visualMapModel.textStyleModel; + var indicatorLabel = new ZRText({ + silent: true, + invisible: true, + style: { + x: 0, + y: 0, + text: '', + font: textStyleModel.getFont(), + fill: textStyleModel.getTextColor() + } + }); + this.group.add(indicatorLabel); + var indicatorLabelPoint = [(orient === 'horizontal' ? textSize / 2 : HOVER_LINK_OUT) + itemSize[0] / 2, 0]; + var shapes = this._shapes; + shapes.indicator = indicator; + shapes.indicatorLabel = indicatorLabel; + shapes.indicatorLabelPoint = indicatorLabelPoint; + this._firstShowIndicator = true; + }; + + ContinuousView.prototype._dragHandle = function (handleIndex, isEnd, dx, dy) { + if (!this._useHandle) { + return; + } + + this._dragging = !isEnd; + + if (!isEnd) { + var vertex = this._applyTransform([dx, dy], this._shapes.mainGroup, true); + + this._updateInterval(handleIndex, vertex[1]); + + this._hideIndicator(); + + this._updateView(); + } + + if (isEnd === !this.visualMapModel.get('realtime')) { + this.api.dispatchAction({ + type: 'selectDataRange', + from: this.uid, + visualMapId: this.visualMapModel.id, + selected: this._dataInterval.slice() + }); + } + + if (isEnd) { + !this._hovering && this._clearHoverLinkToSeries(); + } else if (useHoverLinkOnHandle(this.visualMapModel)) { + this._doHoverLinkToSeries(this._handleEnds[handleIndex], false); + } + }; + + ContinuousView.prototype._resetInterval = function () { + var visualMapModel = this.visualMapModel; + var dataInterval = this._dataInterval = visualMapModel.getSelected(); + var dataExtent = visualMapModel.getExtent(); + var sizeExtent = [0, visualMapModel.itemSize[1]]; + this._handleEnds = [linearMap$2(dataInterval[0], dataExtent, sizeExtent, true), linearMap$2(dataInterval[1], dataExtent, sizeExtent, true)]; + }; + + ContinuousView.prototype._updateInterval = function (handleIndex, delta) { + delta = delta || 0; + var visualMapModel = this.visualMapModel; + var handleEnds = this._handleEnds; + var sizeExtent = [0, visualMapModel.itemSize[1]]; + sliderMove(delta, handleEnds, sizeExtent, handleIndex, 0); + var dataExtent = visualMapModel.getExtent(); + this._dataInterval = [linearMap$2(handleEnds[0], sizeExtent, dataExtent, true), linearMap$2(handleEnds[1], sizeExtent, dataExtent, true)]; + }; + + ContinuousView.prototype._updateView = function (forSketch) { + var visualMapModel = this.visualMapModel; + var dataExtent = visualMapModel.getExtent(); + var shapes = this._shapes; + var outOfRangeHandleEnds = [0, visualMapModel.itemSize[1]]; + var inRangeHandleEnds = forSketch ? outOfRangeHandleEnds : this._handleEnds; + + var visualInRange = this._createBarVisual(this._dataInterval, dataExtent, inRangeHandleEnds, 'inRange'); + + var visualOutOfRange = this._createBarVisual(dataExtent, dataExtent, outOfRangeHandleEnds, 'outOfRange'); + + shapes.inRange.setStyle({ + fill: visualInRange.barColor + }).setShape('points', visualInRange.barPoints); + shapes.outOfRange.setStyle({ + fill: visualOutOfRange.barColor + }).setShape('points', visualOutOfRange.barPoints); + + this._updateHandle(inRangeHandleEnds, visualInRange); + }; + + ContinuousView.prototype._createBarVisual = function (dataInterval, dataExtent, handleEnds, forceState) { + var opts = { + forceState: forceState, + convertOpacityToAlpha: true + }; + + var colorStops = this._makeColorGradient(dataInterval, opts); + + var symbolSizes = [this.getControllerVisual(dataInterval[0], 'symbolSize', opts), this.getControllerVisual(dataInterval[1], 'symbolSize', opts)]; + + var barPoints = this._createBarPoints(handleEnds, symbolSizes); + + return { + barColor: new LinearGradient(0, 0, 0, 1, colorStops), + barPoints: barPoints, + handlesColor: [colorStops[0].color, colorStops[colorStops.length - 1].color] + }; + }; + + ContinuousView.prototype._makeColorGradient = function (dataInterval, opts) { + var sampleNumber = 100; + var colorStops = []; + var step = (dataInterval[1] - dataInterval[0]) / sampleNumber; + colorStops.push({ + color: this.getControllerVisual(dataInterval[0], 'color', opts), + offset: 0 + }); + + for (var i = 1; i < sampleNumber; i++) { + var currValue = dataInterval[0] + step * i; + + if (currValue > dataInterval[1]) { + break; + } + + colorStops.push({ + color: this.getControllerVisual(currValue, 'color', opts), + offset: i / sampleNumber + }); + } + + colorStops.push({ + color: this.getControllerVisual(dataInterval[1], 'color', opts), + offset: 1 + }); + return colorStops; + }; + + ContinuousView.prototype._createBarPoints = function (handleEnds, symbolSizes) { + var itemSize = this.visualMapModel.itemSize; + return [[itemSize[0] - symbolSizes[0], handleEnds[0]], [itemSize[0], handleEnds[0]], [itemSize[0], handleEnds[1]], [itemSize[0] - symbolSizes[1], handleEnds[1]]]; + }; + + ContinuousView.prototype._createBarGroup = function (itemAlign) { + var orient = this._orient; + var inverse = this.visualMapModel.get('inverse'); + return new Group(orient === 'horizontal' && !inverse ? { + scaleX: itemAlign === 'bottom' ? 1 : -1, + rotation: Math.PI / 2 + } : orient === 'horizontal' && inverse ? { + scaleX: itemAlign === 'bottom' ? -1 : 1, + rotation: -Math.PI / 2 + } : orient === 'vertical' && !inverse ? { + scaleX: itemAlign === 'left' ? 1 : -1, + scaleY: -1 + } : { + scaleX: itemAlign === 'left' ? 1 : -1 + }); + }; + + ContinuousView.prototype._updateHandle = function (handleEnds, visualInRange) { + if (!this._useHandle) { + return; + } + + var shapes = this._shapes; + var visualMapModel = this.visualMapModel; + var handleThumbs = shapes.handleThumbs; + var handleLabels = shapes.handleLabels; + var itemSize = visualMapModel.itemSize; + var dataExtent = visualMapModel.getExtent(); + each$g([0, 1], function (handleIndex) { + var handleThumb = handleThumbs[handleIndex]; + handleThumb.setStyle('fill', visualInRange.handlesColor[handleIndex]); + handleThumb.y = handleEnds[handleIndex]; + var val = linearMap$2(handleEnds[handleIndex], [0, itemSize[1]], dataExtent, true); + var symbolSize = this.getControllerVisual(val, 'symbolSize'); + handleThumb.scaleX = handleThumb.scaleY = symbolSize / itemSize[0]; + handleThumb.x = itemSize[0] - symbolSize / 2; + var textPoint = applyTransform$1(shapes.handleLabelPoints[handleIndex], getTransform(handleThumb, this.group)); + handleLabels[handleIndex].setStyle({ + x: textPoint[0], + y: textPoint[1], + text: visualMapModel.formatValueText(this._dataInterval[handleIndex]), + verticalAlign: 'middle', + align: this._orient === 'vertical' ? this._applyTransform('left', shapes.mainGroup) : 'center' + }); + }, this); + }; + + ContinuousView.prototype._showIndicator = function (cursorValue, textValue, rangeSymbol, halfHoverLinkSize) { + var visualMapModel = this.visualMapModel; + var dataExtent = visualMapModel.getExtent(); + var itemSize = visualMapModel.itemSize; + var sizeExtent = [0, itemSize[1]]; + var shapes = this._shapes; + var indicator = shapes.indicator; + + if (!indicator) { + return; + } + + indicator.attr('invisible', false); + var opts = { + convertOpacityToAlpha: true + }; + var color = this.getControllerVisual(cursorValue, 'color', opts); + var symbolSize = this.getControllerVisual(cursorValue, 'symbolSize'); + var y = linearMap$2(cursorValue, dataExtent, sizeExtent, true); + var x = itemSize[0] - symbolSize / 2; + var oldIndicatorPos = { + x: indicator.x, + y: indicator.y + }; + indicator.y = y; + indicator.x = x; + var textPoint = applyTransform$1(shapes.indicatorLabelPoint, getTransform(indicator, this.group)); + var indicatorLabel = shapes.indicatorLabel; + indicatorLabel.attr('invisible', false); + + var align = this._applyTransform('left', shapes.mainGroup); + + var orient = this._orient; + var isHorizontal = orient === 'horizontal'; + indicatorLabel.setStyle({ + text: (rangeSymbol ? rangeSymbol : '') + visualMapModel.formatValueText(textValue), + verticalAlign: isHorizontal ? align : 'middle', + align: isHorizontal ? 'center' : align + }); + var indicatorNewProps = { + x: x, + y: y, + style: { + fill: color + } + }; + var labelNewProps = { + style: { + x: textPoint[0], + y: textPoint[1] + } + }; + + if (visualMapModel.ecModel.isAnimationEnabled() && !this._firstShowIndicator) { + var animationCfg = { + duration: 100, + easing: 'cubicInOut', + additive: true + }; + indicator.x = oldIndicatorPos.x; + indicator.y = oldIndicatorPos.y; + indicator.animateTo(indicatorNewProps, animationCfg); + indicatorLabel.animateTo(labelNewProps, animationCfg); + } else { + indicator.attr(indicatorNewProps); + indicatorLabel.attr(labelNewProps); + } + + this._firstShowIndicator = false; + var handleLabels = this._shapes.handleLabels; + + if (handleLabels) { + for (var i = 0; i < handleLabels.length; i++) { + this._api.enterBlur(handleLabels[i]); + } + } + }; + + ContinuousView.prototype._enableHoverLinkToSeries = function () { + var self = this; + + this._shapes.mainGroup.on('mousemove', function (e) { + self._hovering = true; + + if (!self._dragging) { + var itemSize = self.visualMapModel.itemSize; + + var pos = self._applyTransform([e.offsetX, e.offsetY], self._shapes.mainGroup, true, true); + + pos[1] = mathMin$a(mathMax$a(0, pos[1]), itemSize[1]); + + self._doHoverLinkToSeries(pos[1], 0 <= pos[0] && pos[0] <= itemSize[0]); + } + }).on('mouseout', function () { + self._hovering = false; + !self._dragging && self._clearHoverLinkToSeries(); + }); + }; + + ContinuousView.prototype._enableHoverLinkFromSeries = function () { + var zr = this.api.getZr(); + + if (this.visualMapModel.option.hoverLink) { + zr.on('mouseover', this._hoverLinkFromSeriesMouseOver, this); + zr.on('mouseout', this._hideIndicator, this); + } else { + this._clearHoverLinkFromSeries(); + } + }; + + ContinuousView.prototype._doHoverLinkToSeries = function (cursorPos, hoverOnBar) { + var visualMapModel = this.visualMapModel; + var itemSize = visualMapModel.itemSize; + + if (!visualMapModel.option.hoverLink) { + return; + } + + var sizeExtent = [0, itemSize[1]]; + var dataExtent = visualMapModel.getExtent(); + cursorPos = mathMin$a(mathMax$a(sizeExtent[0], cursorPos), sizeExtent[1]); + var halfHoverLinkSize = getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent); + var hoverRange = [cursorPos - halfHoverLinkSize, cursorPos + halfHoverLinkSize]; + var cursorValue = linearMap$2(cursorPos, sizeExtent, dataExtent, true); + var valueRange = [linearMap$2(hoverRange[0], sizeExtent, dataExtent, true), linearMap$2(hoverRange[1], sizeExtent, dataExtent, true)]; + hoverRange[0] < sizeExtent[0] && (valueRange[0] = -Infinity); + hoverRange[1] > sizeExtent[1] && (valueRange[1] = Infinity); + + if (hoverOnBar) { + if (valueRange[0] === -Infinity) { + this._showIndicator(cursorValue, valueRange[1], '< ', halfHoverLinkSize); + } else if (valueRange[1] === Infinity) { + this._showIndicator(cursorValue, valueRange[0], '> ', halfHoverLinkSize); + } else { + this._showIndicator(cursorValue, cursorValue, '≈ ', halfHoverLinkSize); + } + } + + var oldBatch = this._hoverLinkDataIndices; + var newBatch = []; + + if (hoverOnBar || useHoverLinkOnHandle(visualMapModel)) { + newBatch = this._hoverLinkDataIndices = visualMapModel.findTargetDataIndices(valueRange); + } + + var resultBatches = compressBatches(oldBatch, newBatch); + + this._dispatchHighDown('downplay', makeHighDownBatch(resultBatches[0], visualMapModel)); + + this._dispatchHighDown('highlight', makeHighDownBatch(resultBatches[1], visualMapModel)); + }; + + ContinuousView.prototype._hoverLinkFromSeriesMouseOver = function (e) { + var el = e.target; + var visualMapModel = this.visualMapModel; + + if (!el || getECData(el).dataIndex == null) { + return; + } + + var ecData = getECData(el); + var dataModel = this.ecModel.getSeriesByIndex(ecData.seriesIndex); + + if (!visualMapModel.isTargetSeries(dataModel)) { + return; + } + + var data = dataModel.getData(ecData.dataType); + var value = data.get(visualMapModel.getDataDimension(data), ecData.dataIndex); + + if (!isNaN(value)) { + this._showIndicator(value, value); + } + }; + + ContinuousView.prototype._hideIndicator = function () { + var shapes = this._shapes; + shapes.indicator && shapes.indicator.attr('invisible', true); + shapes.indicatorLabel && shapes.indicatorLabel.attr('invisible', true); + var handleLabels = this._shapes.handleLabels; + + if (handleLabels) { + for (var i = 0; i < handleLabels.length; i++) { + this._api.leaveBlur(handleLabels[i]); + } + } + }; + + ContinuousView.prototype._clearHoverLinkToSeries = function () { + this._hideIndicator(); + + var indices = this._hoverLinkDataIndices; + + this._dispatchHighDown('downplay', makeHighDownBatch(indices, this.visualMapModel)); + + indices.length = 0; + }; + + ContinuousView.prototype._clearHoverLinkFromSeries = function () { + this._hideIndicator(); + + var zr = this.api.getZr(); + zr.off('mouseover', this._hoverLinkFromSeriesMouseOver); + zr.off('mouseout', this._hideIndicator); + }; + + ContinuousView.prototype._applyTransform = function (vertex, element, inverse, global) { + var transform = getTransform(element, global ? null : this.group); + return isArray(vertex) ? applyTransform$1(vertex, transform, inverse) : transformDirection(vertex, transform, inverse); + }; + + ContinuousView.prototype._dispatchHighDown = function (type, batch) { + batch && batch.length && this.api.dispatchAction({ + type: type, + batch: batch + }); + }; + + ContinuousView.prototype.dispose = function () { + this._clearHoverLinkFromSeries(); + + this._clearHoverLinkToSeries(); + }; + + ContinuousView.prototype.remove = function () { + this._clearHoverLinkFromSeries(); + + this._clearHoverLinkToSeries(); + }; + + ContinuousView.type = 'visualMap.continuous'; + return ContinuousView; + }(VisualMapView); + + function createPolygon(points, cursor, onDrift, onDragEnd) { + return new Polygon({ + shape: { + points: points + }, + draggable: !!onDrift, + cursor: cursor, + drift: onDrift, + onmousemove: function (e) { + stop(e.event); + }, + ondragend: onDragEnd + }); + } + + function getHalfHoverLinkSize(visualMapModel, dataExtent, sizeExtent) { + var halfHoverLinkSize = HOVER_LINK_SIZE / 2; + var hoverLinkDataSize = visualMapModel.get('hoverLinkDataSize'); + + if (hoverLinkDataSize) { + halfHoverLinkSize = linearMap$2(hoverLinkDataSize, dataExtent, sizeExtent, true) / 2; + } + + return halfHoverLinkSize; + } + + function useHoverLinkOnHandle(visualMapModel) { + var hoverLinkOnHandle = visualMapModel.get('hoverLinkOnHandle'); + return !!(hoverLinkOnHandle == null ? visualMapModel.get('realtime') : hoverLinkOnHandle); + } + + function getCursor$1(orient) { + return orient === 'vertical' ? 'ns-resize' : 'ew-resize'; + } + + /* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + + /** + * AUTO-GENERATED FILE. DO NOT MODIFY. + */ + + var visualMapActionInfo = { + type: 'selectDataRange', + event: 'dataRangeSelected', + update: 'update' + }; + var visualMapActionHander = function (payload, ecModel) { + ecModel.eachComponent({ + mainType: 'visualMap', + query: payload + }, function (model) { + model.setSelected(payload.selected); + }); + }; + + var visualMapEncodingHandlers = [{ + createOnAllSeries: true, + reset: function (seriesModel, ecModel) { + var resetDefines = []; + ecModel.eachComponent('visualMap', function (visualMapModel) { + var pipelineContext = seriesModel.pipelineContext; + + if (!visualMapModel.isTargetSeries(seriesModel) || pipelineContext && pipelineContext.large) { + return; + } + + resetDefines.push(incrementalApplyVisual(visualMapModel.stateList, visualMapModel.targetVisuals, bind(visualMapModel.getValueState, visualMapModel), visualMapModel.getDataDimension(seriesModel.getData()))); + }); + return resetDefines; + } + }, { + createOnAllSeries: true, + reset: function (seriesModel, ecModel) { + var data = seriesModel.getData(); + var visualMetaList = []; + ecModel.eachComponent('visualMap', function (visualMapModel) { + if (visualMapModel.isTargetSeries(seriesModel)) { + var visualMeta = visualMapModel.getVisualMeta(bind(getColorVisual, null, seriesModel, visualMapModel)) || { + stops: [], + outerColors: [] + }; + var concreteDim = visualMapModel.getDataDimension(data); + var dimInfo = data.getDimensionInfo(concreteDim); + + if (dimInfo != null) { + visualMeta.dimension = dimInfo.index; + visualMetaList.push(visualMeta); + } + } + }); + seriesModel.getData().setVisual('visualMeta', visualMetaList); + } + }]; + + function getColorVisual(seriesModel, visualMapModel, value, valueState) { + var mappings = visualMapModel.targetVisuals[valueState]; + var visualTypes = VisualMapping.prepareVisualTypes(mappings); + var resultVisual = { + color: getVisualFromData(seriesModel.getData(), 'color') + }; + + for (var i = 0, len = visualTypes.length; i < len; i++) { + var type = visualTypes[i]; + var mapping = mappings[type === 'opacity' ? '__alphaForOpacity' : type]; + mapping && mapping.applyVisual(value, getVisual, setVisual); + } + + return resultVisual.color; + + function getVisual(key) { + return resultVisual[key]; + } + + function setVisual(key, value) { + resultVisual[key] = value; + } + } + + var each$h = each; + function visualMapPreprocessor(option) { + var visualMap = option && option.visualMap; + + if (!isArray(visualMap)) { + visualMap = visualMap ? [visualMap] : []; + } + + each$h(visualMap, function (opt) { + if (!opt) { + return; + } + + if (has$1(opt, 'splitList') && !has$1(opt, 'pieces')) { + opt.pieces = opt.splitList; + delete opt.splitList; + } + + var pieces = opt.pieces; + + if (pieces && isArray(pieces)) { + each$h(pieces, function (piece) { + if (isObject(piece)) { + if (has$1(piece, 'start') && !has$1(piece, 'min')) { + piece.min = piece.start; + } + + if (has$1(piece, 'end') && !has$1(piece, 'max')) { + piece.max = piece.end; + } + } + }); + } + }); + } + + function has$1(obj, name) { + return obj && obj.hasOwnProperty && obj.hasOwnProperty(name); + } + + var installed$1 = false; + function installCommon$1(registers) { + if (installed$1) { + return; + } + + installed$1 = true; + registers.registerSubTypeDefaulter('visualMap', function (option) { + return !option.categories && (!(option.pieces ? option.pieces.length > 0 : option.splitNumber > 0) || option.calculable) ? 'continuous' : 'piecewise'; + }); + registers.registerAction(visualMapActionInfo, visualMapActionHander); + each(visualMapEncodingHandlers, function (handler) { + registers.registerVisual(registers.PRIORITY.VISUAL.COMPONENT, handler); + }); + registers.registerPreprocessor(visualMapPreprocessor); + } + + function install$N(registers) { + registers.registerComponentModel(ContinuousModel); + registers.registerComponentView(ContinuousView); + installCommon$1(registers); + } + + var PiecewiseModel = function (_super) { + __extends(PiecewiseModel, _super); + + function PiecewiseModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = PiecewiseModel.type; + _this._pieceList = []; + return _this; + } + + PiecewiseModel.prototype.optionUpdated = function (newOption, isInit) { + _super.prototype.optionUpdated.apply(this, arguments); + + this.resetExtent(); + + var mode = this._mode = this._determineMode(); + + this._pieceList = []; + + resetMethods[this._mode].call(this, this._pieceList); + + this._resetSelected(newOption, isInit); + + var categories = this.option.categories; + this.resetVisual(function (mappingOption, state) { + if (mode === 'categories') { + mappingOption.mappingMethod = 'category'; + mappingOption.categories = clone(categories); + } else { + mappingOption.dataExtent = this.getExtent(); + mappingOption.mappingMethod = 'piecewise'; + mappingOption.pieceList = map(this._pieceList, function (piece) { + piece = clone(piece); + + if (state !== 'inRange') { + piece.visual = null; + } + + return piece; + }); + } + }); + }; + + PiecewiseModel.prototype.completeVisualOption = function () { + var option = this.option; + var visualTypesInPieces = {}; + var visualTypes = VisualMapping.listVisualTypes(); + var isCategory = this.isCategory(); + each(option.pieces, function (piece) { + each(visualTypes, function (visualType) { + if (piece.hasOwnProperty(visualType)) { + visualTypesInPieces[visualType] = 1; + } + }); + }); + each(visualTypesInPieces, function (v, visualType) { + var exists = false; + each(this.stateList, function (state) { + exists = exists || has(option, state, visualType) || has(option.target, state, visualType); + }, this); + !exists && each(this.stateList, function (state) { + (option[state] || (option[state] = {}))[visualType] = visualDefault.get(visualType, state === 'inRange' ? 'active' : 'inactive', isCategory); + }); + }, this); + + function has(obj, state, visualType) { + return obj && obj[state] && obj[state].hasOwnProperty(visualType); + } + + _super.prototype.completeVisualOption.apply(this, arguments); + }; + + PiecewiseModel.prototype._resetSelected = function (newOption, isInit) { + var thisOption = this.option; + var pieceList = this._pieceList; + var selected = (isInit ? thisOption : newOption).selected || {}; + thisOption.selected = selected; + each(pieceList, function (piece, index) { + var key = this.getSelectedMapKey(piece); + + if (!selected.hasOwnProperty(key)) { + selected[key] = true; + } + }, this); + + if (thisOption.selectedMode === 'single') { + var hasSel_1 = false; + each(pieceList, function (piece, index) { + var key = this.getSelectedMapKey(piece); + + if (selected[key]) { + hasSel_1 ? selected[key] = false : hasSel_1 = true; + } + }, this); + } + }; + + PiecewiseModel.prototype.getSelectedMapKey = function (piece) { + return this._mode === 'categories' ? piece.value + '' : piece.index + ''; + }; + + PiecewiseModel.prototype.getPieceList = function () { + return this._pieceList; + }; + + PiecewiseModel.prototype._determineMode = function () { + var option = this.option; + return option.pieces && option.pieces.length > 0 ? 'pieces' : this.option.categories ? 'categories' : 'splitNumber'; + }; + + PiecewiseModel.prototype.setSelected = function (selected) { + this.option.selected = clone(selected); + }; + + PiecewiseModel.prototype.getValueState = function (value) { + var index = VisualMapping.findPieceIndex(value, this._pieceList); + return index != null ? this.option.selected[this.getSelectedMapKey(this._pieceList[index])] ? 'inRange' : 'outOfRange' : 'outOfRange'; + }; + + PiecewiseModel.prototype.findTargetDataIndices = function (pieceIndex) { + var result = []; + var pieceList = this._pieceList; + this.eachTargetSeries(function (seriesModel) { + var dataIndices = []; + var data = seriesModel.getData(); + data.each(this.getDataDimension(data), function (value, dataIndex) { + var pIdx = VisualMapping.findPieceIndex(value, pieceList); + pIdx === pieceIndex && dataIndices.push(dataIndex); + }, this); + result.push({ + seriesId: seriesModel.id, + dataIndex: dataIndices + }); + }, this); + return result; + }; + + PiecewiseModel.prototype.getRepresentValue = function (piece) { + var representValue; + + if (this.isCategory()) { + representValue = piece.value; + } else { + if (piece.value != null) { + representValue = piece.value; + } else { + var pieceInterval = piece.interval || []; + representValue = pieceInterval[0] === -Infinity && pieceInterval[1] === Infinity ? 0 : (pieceInterval[0] + pieceInterval[1]) / 2; + } + } + + return representValue; + }; + + PiecewiseModel.prototype.getVisualMeta = function (getColorVisual) { + if (this.isCategory()) { + return; + } + + var stops = []; + var outerColors = ['', '']; + var visualMapModel = this; + + function setStop(interval, valueState) { + var representValue = visualMapModel.getRepresentValue({ + interval: interval + }); + + if (!valueState) { + valueState = visualMapModel.getValueState(representValue); + } + + var color = getColorVisual(representValue, valueState); + + if (interval[0] === -Infinity) { + outerColors[0] = color; + } else if (interval[1] === Infinity) { + outerColors[1] = color; + } else { + stops.push({ + value: interval[0], + color: color + }, { + value: interval[1], + color: color + }); + } + } + + var pieceList = this._pieceList.slice(); + + if (!pieceList.length) { + pieceList.push({ + interval: [-Infinity, Infinity] + }); + } else { + var edge = pieceList[0].interval[0]; + edge !== -Infinity && pieceList.unshift({ + interval: [-Infinity, edge] + }); + edge = pieceList[pieceList.length - 1].interval[1]; + edge !== Infinity && pieceList.push({ + interval: [edge, Infinity] + }); + } + + var curr = -Infinity; + each(pieceList, function (piece) { + var interval = piece.interval; + + if (interval) { + interval[0] > curr && setStop([curr, interval[0]], 'outOfRange'); + setStop(interval.slice()); + curr = interval[1]; + } + }, this); + return { + stops: stops, + outerColors: outerColors + }; + }; + + PiecewiseModel.type = 'visualMap.piecewise'; + PiecewiseModel.defaultOption = inheritDefaultOption(VisualMapModel.defaultOption, { + selected: null, + minOpen: false, + maxOpen: false, + align: 'auto', + itemWidth: 20, + itemHeight: 14, + itemSymbol: 'roundRect', + pieces: null, + categories: null, + splitNumber: 5, + selectedMode: 'multiple', + itemGap: 10, + hoverLink: true + }); + return PiecewiseModel; + }(VisualMapModel); + var resetMethods = { + splitNumber: function (outPieceList) { + var thisOption = this.option; + var precision = Math.min(thisOption.precision, 20); + var dataExtent = this.getExtent(); + var splitNumber = thisOption.splitNumber; + splitNumber = Math.max(parseInt(splitNumber, 10), 1); + thisOption.splitNumber = splitNumber; + var splitStep = (dataExtent[1] - dataExtent[0]) / splitNumber; + + while (+splitStep.toFixed(precision) !== splitStep && precision < 5) { + precision++; + } + + thisOption.precision = precision; + splitStep = +splitStep.toFixed(precision); + + if (thisOption.minOpen) { + outPieceList.push({ + interval: [-Infinity, dataExtent[0]], + close: [0, 0] + }); + } + + for (var index = 0, curr = dataExtent[0]; index < splitNumber; curr += splitStep, index++) { + var max = index === splitNumber - 1 ? dataExtent[1] : curr + splitStep; + outPieceList.push({ + interval: [curr, max], + close: [1, 1] + }); + } + + if (thisOption.maxOpen) { + outPieceList.push({ + interval: [dataExtent[1], Infinity], + close: [0, 0] + }); + } + + reformIntervals(outPieceList); + each(outPieceList, function (piece, index) { + piece.index = index; + piece.text = this.formatValueText(piece.interval); + }, this); + }, + categories: function (outPieceList) { + var thisOption = this.option; + each(thisOption.categories, function (cate) { + outPieceList.push({ + text: this.formatValueText(cate, true), + value: cate + }); + }, this); + normalizeReverse(thisOption, outPieceList); + }, + pieces: function (outPieceList) { + var thisOption = this.option; + each(thisOption.pieces, function (pieceListItem, index) { + if (!isObject(pieceListItem)) { + pieceListItem = { + value: pieceListItem + }; + } + + var item = { + text: '', + index: index + }; + + if (pieceListItem.label != null) { + item.text = pieceListItem.label; + } + + if (pieceListItem.hasOwnProperty('value')) { + var value = item.value = pieceListItem.value; + item.interval = [value, value]; + item.close = [1, 1]; + } else { + var interval = item.interval = []; + var close_1 = item.close = [0, 0]; + var closeList = [1, 0, 1]; + var infinityList = [-Infinity, Infinity]; + var useMinMax = []; + + for (var lg = 0; lg < 2; lg++) { + var names = [['gte', 'gt', 'min'], ['lte', 'lt', 'max']][lg]; + + for (var i = 0; i < 3 && interval[lg] == null; i++) { + interval[lg] = pieceListItem[names[i]]; + close_1[lg] = closeList[i]; + useMinMax[lg] = i === 2; + } + + interval[lg] == null && (interval[lg] = infinityList[lg]); + } + + useMinMax[0] && interval[1] === Infinity && (close_1[0] = 0); + useMinMax[1] && interval[0] === -Infinity && (close_1[1] = 0); + + if ("development" !== 'production') { + if (interval[0] > interval[1]) { + console.warn('Piece ' + index + 'is illegal: ' + interval + ' lower bound should not greater then uppper bound.'); + } + } + + if (interval[0] === interval[1] && close_1[0] && close_1[1]) { + item.value = interval[0]; + } + } + + item.visual = VisualMapping.retrieveVisuals(pieceListItem); + outPieceList.push(item); + }, this); + normalizeReverse(thisOption, outPieceList); + reformIntervals(outPieceList); + each(outPieceList, function (piece) { + var close = piece.close; + var edgeSymbols = [['<', '≤'][close[1]], ['>', '≥'][close[0]]]; + piece.text = piece.text || this.formatValueText(piece.value != null ? piece.value : piece.interval, false, edgeSymbols); + }, this); + } + }; + + function normalizeReverse(thisOption, pieceList) { + var inverse = thisOption.inverse; + + if (thisOption.orient === 'vertical' ? !inverse : inverse) { + pieceList.reverse(); + } + } + + var PiecewiseVisualMapView = function (_super) { + __extends(PiecewiseVisualMapView, _super); + + function PiecewiseVisualMapView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = PiecewiseVisualMapView.type; + return _this; + } + + PiecewiseVisualMapView.prototype.doRender = function () { + var thisGroup = this.group; + thisGroup.removeAll(); + var visualMapModel = this.visualMapModel; + var textGap = visualMapModel.get('textGap'); + var textStyleModel = visualMapModel.textStyleModel; + var textFont = textStyleModel.getFont(); + var textFill = textStyleModel.getTextColor(); + + var itemAlign = this._getItemAlign(); + + var itemSize = visualMapModel.itemSize; + + var viewData = this._getViewData(); + + var endsText = viewData.endsText; + var showLabel = retrieve(visualMapModel.get('showLabel', true), !endsText); + endsText && this._renderEndsText(thisGroup, endsText[0], itemSize, showLabel, itemAlign); + each(viewData.viewPieceList, function (item) { + var piece = item.piece; + var itemGroup = new Group(); + itemGroup.onclick = bind(this._onItemClick, this, piece); + + this._enableHoverLink(itemGroup, item.indexInModelPieceList); + + var representValue = visualMapModel.getRepresentValue(piece); + + this._createItemSymbol(itemGroup, representValue, [0, 0, itemSize[0], itemSize[1]]); + + if (showLabel) { + var visualState = this.visualMapModel.getValueState(representValue); + itemGroup.add(new ZRText({ + style: { + x: itemAlign === 'right' ? -textGap : itemSize[0] + textGap, + y: itemSize[1] / 2, + text: piece.text, + verticalAlign: 'middle', + align: itemAlign, + font: textFont, + fill: textFill, + opacity: visualState === 'outOfRange' ? 0.5 : 1 + } + })); + } + + thisGroup.add(itemGroup); + }, this); + endsText && this._renderEndsText(thisGroup, endsText[1], itemSize, showLabel, itemAlign); + box(visualMapModel.get('orient'), thisGroup, visualMapModel.get('itemGap')); + this.renderBackground(thisGroup); + this.positionGroup(thisGroup); + }; + + PiecewiseVisualMapView.prototype._enableHoverLink = function (itemGroup, pieceIndex) { + var _this = this; + + itemGroup.on('mouseover', function () { + return onHoverLink('highlight'); + }).on('mouseout', function () { + return onHoverLink('downplay'); + }); + + var onHoverLink = function (method) { + var visualMapModel = _this.visualMapModel; + visualMapModel.option.hoverLink && _this.api.dispatchAction({ + type: method, + batch: makeHighDownBatch(visualMapModel.findTargetDataIndices(pieceIndex), visualMapModel) + }); + }; + }; + + PiecewiseVisualMapView.prototype._getItemAlign = function () { + var visualMapModel = this.visualMapModel; + var modelOption = visualMapModel.option; + + if (modelOption.orient === 'vertical') { + return getItemAlign(visualMapModel, this.api, visualMapModel.itemSize); + } else { + var align = modelOption.align; + + if (!align || align === 'auto') { + align = 'left'; + } + + return align; + } + }; + + PiecewiseVisualMapView.prototype._renderEndsText = function (group, text, itemSize, showLabel, itemAlign) { + if (!text) { + return; + } + + var itemGroup = new Group(); + var textStyleModel = this.visualMapModel.textStyleModel; + itemGroup.add(new ZRText({ + style: { + x: showLabel ? itemAlign === 'right' ? itemSize[0] : 0 : itemSize[0] / 2, + y: itemSize[1] / 2, + verticalAlign: 'middle', + align: showLabel ? itemAlign : 'center', + text: text, + font: textStyleModel.getFont(), + fill: textStyleModel.getTextColor() + } + })); + group.add(itemGroup); + }; + + PiecewiseVisualMapView.prototype._getViewData = function () { + var visualMapModel = this.visualMapModel; + var viewPieceList = map(visualMapModel.getPieceList(), function (piece, index) { + return { + piece: piece, + indexInModelPieceList: index + }; + }); + var endsText = visualMapModel.get('text'); + var orient = visualMapModel.get('orient'); + var inverse = visualMapModel.get('inverse'); + + if (orient === 'horizontal' ? inverse : !inverse) { + viewPieceList.reverse(); + } else if (endsText) { + endsText = endsText.slice().reverse(); + } + + return { + viewPieceList: viewPieceList, + endsText: endsText + }; + }; + + PiecewiseVisualMapView.prototype._createItemSymbol = function (group, representValue, shapeParam) { + group.add(createSymbol(this.getControllerVisual(representValue, 'symbol'), shapeParam[0], shapeParam[1], shapeParam[2], shapeParam[3], this.getControllerVisual(representValue, 'color'))); + }; + + PiecewiseVisualMapView.prototype._onItemClick = function (piece) { + var visualMapModel = this.visualMapModel; + var option = visualMapModel.option; + var selected = clone(option.selected); + var newKey = visualMapModel.getSelectedMapKey(piece); + + if (option.selectedMode === 'single') { + selected[newKey] = true; + each(selected, function (o, key) { + selected[key] = key === newKey; + }); + } else { + selected[newKey] = !selected[newKey]; + } + + this.api.dispatchAction({ + type: 'selectDataRange', + from: this.uid, + visualMapId: this.visualMapModel.id, + selected: selected + }); + }; + + PiecewiseVisualMapView.type = 'visualMap.piecewise'; + return PiecewiseVisualMapView; + }(VisualMapView); + + function install$O(registers) { + registers.registerComponentModel(PiecewiseModel); + registers.registerComponentView(PiecewiseVisualMapView); + installCommon$1(registers); + } + + function install$P(registers) { + use(install$N); + use(install$O); + } + + var DEFAULT_OPTION = { + label: { + enabled: true + }, + decal: { + show: false + } + }; + var inner$n = makeInner(); + var decalPaletteScope = {}; + function ariaVisual(ecModel, api) { + var ariaModel = ecModel.getModel('aria'); + + if (!ariaModel.get('enabled')) { + return; + } + + var defaultOption = clone(DEFAULT_OPTION); + merge(defaultOption.label, ecModel.getLocaleModel().get('aria'), false); + merge(ariaModel.option, defaultOption, false); + setDecal(); + setLabel(); + + function setDecal() { + var decalModel = ariaModel.getModel('decal'); + var useDecal = decalModel.get('show'); + + if (useDecal) { + var paletteScopeGroupByType_1 = createHashMap(); + ecModel.eachSeries(function (seriesModel) { + if (!seriesModel.useColorPaletteOnData) { + return; + } + + var decalScope = paletteScopeGroupByType_1.get(seriesModel.type); + + if (!decalScope) { + decalScope = {}; + paletteScopeGroupByType_1.set(seriesModel.type, decalScope); + } + + inner$n(seriesModel).scope = decalScope; + }); + ecModel.eachRawSeries(function (seriesModel) { + if (ecModel.isSeriesFiltered(seriesModel)) { + return; + } + + if (typeof seriesModel.enableAriaDecal === 'function') { + seriesModel.enableAriaDecal(); + return; + } + + var data = seriesModel.getData(); + + if (seriesModel.useColorPaletteOnData) { + var dataAll_1 = seriesModel.getRawData(); + var idxMap_1 = {}; + var decalScope_1 = inner$n(seriesModel).scope; + data.each(function (idx) { + var rawIdx = data.getRawIndex(idx); + idxMap_1[rawIdx] = idx; + }); + var dataCount_1 = dataAll_1.count(); + dataAll_1.each(function (rawIdx) { + var idx = idxMap_1[rawIdx]; + var name = dataAll_1.getName(rawIdx) || rawIdx + ''; + var paletteDecal = getDecalFromPalette(seriesModel.ecModel, name, decalScope_1, dataCount_1); + var specifiedDecal = data.getItemVisual(idx, 'decal'); + data.setItemVisual(idx, 'decal', mergeDecal(specifiedDecal, paletteDecal)); + }); + } else { + var paletteDecal = getDecalFromPalette(seriesModel.ecModel, seriesModel.name, decalPaletteScope, ecModel.getSeriesCount()); + var specifiedDecal = data.getVisual('decal'); + data.setVisual('decal', mergeDecal(specifiedDecal, paletteDecal)); + } + + function mergeDecal(specifiedDecal, paletteDecal) { + var resultDecal = specifiedDecal ? extend(extend({}, paletteDecal), specifiedDecal) : paletteDecal; + resultDecal.dirty = true; + return resultDecal; + } + }); + } + } + + function setLabel() { + var labelLocale = ecModel.getLocaleModel().get('aria'); + var labelModel = ariaModel.getModel('label'); + labelModel.option = defaults(labelModel.option, labelLocale); + + if (!labelModel.get('enabled')) { + return; + } + + var dom = api.getZr().dom; + + if (labelModel.get('description')) { + dom.setAttribute('aria-label', labelModel.get('description')); + return; + } + + var seriesCnt = ecModel.getSeriesCount(); + var maxDataCnt = labelModel.get(['data', 'maxCount']) || 10; + var maxSeriesCnt = labelModel.get(['series', 'maxCount']) || 10; + var displaySeriesCnt = Math.min(seriesCnt, maxSeriesCnt); + var ariaLabel; + + if (seriesCnt < 1) { + return; + } else { + var title = getTitle(); + + if (title) { + var withTitle = labelModel.get(['general', 'withTitle']); + ariaLabel = replace(withTitle, { + title: title + }); + } else { + ariaLabel = labelModel.get(['general', 'withoutTitle']); + } + + var seriesLabels_1 = []; + var prefix = seriesCnt > 1 ? labelModel.get(['series', 'multiple', 'prefix']) : labelModel.get(['series', 'single', 'prefix']); + ariaLabel += replace(prefix, { + seriesCount: seriesCnt + }); + ecModel.eachSeries(function (seriesModel, idx) { + if (idx < displaySeriesCnt) { + var seriesLabel = void 0; + var seriesName = seriesModel.get('name'); + var withName = seriesName ? 'withName' : 'withoutName'; + seriesLabel = seriesCnt > 1 ? labelModel.get(['series', 'multiple', withName]) : labelModel.get(['series', 'single', withName]); + seriesLabel = replace(seriesLabel, { + seriesId: seriesModel.seriesIndex, + seriesName: seriesModel.get('name'), + seriesType: getSeriesTypeName(seriesModel.subType) + }); + var data = seriesModel.getData(); + + if (data.count() > maxDataCnt) { + var partialLabel = labelModel.get(['data', 'partialData']); + seriesLabel += replace(partialLabel, { + displayCnt: maxDataCnt + }); + } else { + seriesLabel += labelModel.get(['data', 'allData']); + } + + var dataLabels = []; + + for (var i = 0; i < data.count(); i++) { + if (i < maxDataCnt) { + var name_1 = data.getName(i); + var value = retrieveRawValue(data, i); + var dataLabel = labelModel.get(['data', name_1 ? 'withName' : 'withoutName']); + dataLabels.push(replace(dataLabel, { + name: name_1, + value: value + })); + } + } + + var middleSeparator_1 = labelModel.get(['data', 'separator', 'middle']); + var endSeparator_1 = labelModel.get(['data', 'separator', 'end']); + seriesLabel += dataLabels.join(middleSeparator_1) + endSeparator_1; + seriesLabels_1.push(seriesLabel); + } + }); + var separatorModel = labelModel.getModel(['series', 'multiple', 'separator']); + var middleSeparator = separatorModel.get('middle'); + var endSeparator = separatorModel.get('end'); + ariaLabel += seriesLabels_1.join(middleSeparator) + endSeparator; + dom.setAttribute('aria-label', ariaLabel); + } + } + + function replace(str, keyValues) { + if (typeof str !== 'string') { + return str; + } + + var result = str; + each(keyValues, function (value, key) { + result = result.replace(new RegExp('\\{\\s*' + key + '\\s*\\}', 'g'), value); + }); + return result; + } + + function getTitle() { + var title = ecModel.get('title'); + + if (title && title.length) { + title = title[0]; + } + + return title && title.text; + } + + function getSeriesTypeName(type) { + return ecModel.getLocaleModel().get(['series', 'typeNames'])[type] || '自定义图'; + } + } + + function ariaPreprocessor(option) { + if (!option || !option.aria) { + return; + } + + var aria = option.aria; + + if (aria.show != null) { + aria.enabled = aria.show; + } + + aria.label = aria.label || {}; + each(['description', 'general', 'series', 'data'], function (name) { + if (aria[name] != null) { + aria.label[name] = aria[name]; + } + }); + } + + function install$Q(registers) { + registers.registerPreprocessor(ariaPreprocessor); + registers.registerVisual(registers.PRIORITY.VISUAL.ARIA, ariaVisual); + } + + var RELATIONAL_EXPRESSION_OP_ALIAS_MAP = { + value: 'eq', + '<': 'lt', + '<=': 'lte', + '>': 'gt', + '>=': 'gte', + '=': 'eq', + '!=': 'ne', + '<>': 'ne' + }; + + var RegExpEvaluator = function () { + function RegExpEvaluator(rVal) { + var condValue = this._condVal = isString(rVal) ? new RegExp(rVal) : isRegExp(rVal) ? rVal : null; + + if (condValue == null) { + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = makePrintable('Illegal regexp', rVal, 'in'); + } + + throwError(errMsg); + } + } + + RegExpEvaluator.prototype.evaluate = function (lVal) { + var type = typeof lVal; + return type === 'string' ? this._condVal.test(lVal) : type === 'number' ? this._condVal.test(lVal + '') : false; + }; + + return RegExpEvaluator; + }(); + + var ConstConditionInternal = function () { + function ConstConditionInternal() {} + + ConstConditionInternal.prototype.evaluate = function () { + return this.value; + }; + + return ConstConditionInternal; + }(); + + var AndConditionInternal = function () { + function AndConditionInternal() {} + + AndConditionInternal.prototype.evaluate = function () { + var children = this.children; + + for (var i = 0; i < children.length; i++) { + if (!children[i].evaluate()) { + return false; + } + } + + return true; + }; + + return AndConditionInternal; + }(); + + var OrConditionInternal = function () { + function OrConditionInternal() {} + + OrConditionInternal.prototype.evaluate = function () { + var children = this.children; + + for (var i = 0; i < children.length; i++) { + if (children[i].evaluate()) { + return true; + } + } + + return false; + }; + + return OrConditionInternal; + }(); + + var NotConditionInternal = function () { + function NotConditionInternal() {} + + NotConditionInternal.prototype.evaluate = function () { + return !this.child.evaluate(); + }; + + return NotConditionInternal; + }(); + + var RelationalConditionInternal = function () { + function RelationalConditionInternal() {} + + RelationalConditionInternal.prototype.evaluate = function () { + var needParse = !!this.valueParser; + var getValue = this.getValue; + var tarValRaw = getValue(this.valueGetterParam); + var tarValParsed = needParse ? this.valueParser(tarValRaw) : null; + + for (var i = 0; i < this.subCondList.length; i++) { + if (!this.subCondList[i].evaluate(needParse ? tarValParsed : tarValRaw)) { + return false; + } + } + + return true; + }; + + return RelationalConditionInternal; + }(); + + function parseOption(exprOption, getters) { + if (exprOption === true || exprOption === false) { + var cond = new ConstConditionInternal(); + cond.value = exprOption; + return cond; + } + + var errMsg = ''; + + if (!isObjectNotArray(exprOption)) { + if ("development" !== 'production') { + errMsg = makePrintable('Illegal config. Expect a plain object but actually', exprOption); + } + + throwError(errMsg); + } + + if (exprOption.and) { + return parseAndOrOption('and', exprOption, getters); + } else if (exprOption.or) { + return parseAndOrOption('or', exprOption, getters); + } else if (exprOption.not) { + return parseNotOption(exprOption, getters); + } + + return parseRelationalOption(exprOption, getters); + } + + function parseAndOrOption(op, exprOption, getters) { + var subOptionArr = exprOption[op]; + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = makePrintable('"and"/"or" condition should only be `' + op + ': [...]` and must not be empty array.', 'Illegal condition:', exprOption); + } + + if (!isArray(subOptionArr)) { + throwError(errMsg); + } + + if (!subOptionArr.length) { + throwError(errMsg); + } + + var cond = op === 'and' ? new AndConditionInternal() : new OrConditionInternal(); + cond.children = map(subOptionArr, function (subOption) { + return parseOption(subOption, getters); + }); + + if (!cond.children.length) { + throwError(errMsg); + } + + return cond; + } + + function parseNotOption(exprOption, getters) { + var subOption = exprOption.not; + var errMsg = ''; + + if ("development" !== 'production') { + errMsg = makePrintable('"not" condition should only be `not: {}`.', 'Illegal condition:', exprOption); + } + + if (!isObjectNotArray(subOption)) { + throwError(errMsg); + } + + var cond = new NotConditionInternal(); + cond.child = parseOption(subOption, getters); + + if (!cond.child) { + throwError(errMsg); + } + + return cond; + } + + function parseRelationalOption(exprOption, getters) { + var errMsg = ''; + var valueGetterParam = getters.prepareGetValue(exprOption); + var subCondList = []; + var exprKeys = keys(exprOption); + var parserName = exprOption.parser; + var valueParser = parserName ? getRawValueParser(parserName) : null; + + for (var i = 0; i < exprKeys.length; i++) { + var keyRaw = exprKeys[i]; + + if (keyRaw === 'parser' || getters.valueGetterAttrMap.get(keyRaw)) { + continue; + } + + var op = hasOwn(RELATIONAL_EXPRESSION_OP_ALIAS_MAP, keyRaw) ? RELATIONAL_EXPRESSION_OP_ALIAS_MAP[keyRaw] : keyRaw; + var condValueRaw = exprOption[keyRaw]; + var condValueParsed = valueParser ? valueParser(condValueRaw) : condValueRaw; + var evaluator = createFilterComparator(op, condValueParsed) || op === 'reg' && new RegExpEvaluator(condValueParsed); + + if (!evaluator) { + if ("development" !== 'production') { + errMsg = makePrintable('Illegal relational operation: "' + keyRaw + '" in condition:', exprOption); + } + + throwError(errMsg); + } + + subCondList.push(evaluator); + } + + if (!subCondList.length) { + if ("development" !== 'production') { + errMsg = makePrintable('Relational condition must have at least one operator.', 'Illegal condition:', exprOption); + } + + throwError(errMsg); + } + + var cond = new RelationalConditionInternal(); + cond.valueGetterParam = valueGetterParam; + cond.valueParser = valueParser; + cond.getValue = getters.getValue; + cond.subCondList = subCondList; + return cond; + } + + function isObjectNotArray(val) { + return isObject(val) && !isArrayLike(val); + } + + var ConditionalExpressionParsed = function () { + function ConditionalExpressionParsed(exprOption, getters) { + this._cond = parseOption(exprOption, getters); + } + + ConditionalExpressionParsed.prototype.evaluate = function () { + return this._cond.evaluate(); + }; + + return ConditionalExpressionParsed; + }(); + function parseConditionalExpression(exprOption, getters) { + return new ConditionalExpressionParsed(exprOption, getters); + } + + var filterTransform = { + type: 'echarts:filter', + transform: function (params) { + var upstream = params.upstream; + var rawItem; + var condition = parseConditionalExpression(params.config, { + valueGetterAttrMap: createHashMap({ + dimension: true + }), + prepareGetValue: function (exprOption) { + var errMsg = ''; + var dimLoose = exprOption.dimension; + + if (!hasOwn(exprOption, 'dimension')) { + if ("development" !== 'production') { + errMsg = makePrintable('Relation condition must has prop "dimension" specified.', 'Illegal condition:', exprOption); + } + + throwError(errMsg); + } + + var dimInfo = upstream.getDimensionInfo(dimLoose); + + if (!dimInfo) { + if ("development" !== 'production') { + errMsg = makePrintable('Can not find dimension info via: ' + dimLoose + '.\n', 'Existing dimensions: ', upstream.cloneAllDimensionInfo(), '.\n', 'Illegal condition:', exprOption, '.\n'); + } + + throwError(errMsg); + } + + return { + dimIdx: dimInfo.index + }; + }, + getValue: function (param) { + return upstream.retrieveValueFromItem(rawItem, param.dimIdx); + } + }); + var resultData = []; + + for (var i = 0, len = upstream.count(); i < len; i++) { + rawItem = upstream.getRawDataItem(i); + + if (condition.evaluate()) { + resultData.push(rawItem); + } + } + + return { + data: resultData + }; + } + }; + + var sampleLog = ''; + + if ("development" !== 'production') { + sampleLog = ['Valid config is like:', '{ dimension: "age", order: "asc" }', 'or [{ dimension: "age", order: "asc"], { dimension: "date", order: "desc" }]'].join(' '); + } + + var sortTransform = { + type: 'echarts:sort', + transform: function (params) { + var upstream = params.upstream; + var config = params.config; + var errMsg = ''; + var orderExprList = normalizeToArray(config); + + if (!orderExprList.length) { + if ("development" !== 'production') { + errMsg = 'Empty `config` in sort transform.'; + } + + throwError(errMsg); + } + + var orderDefList = []; + each(orderExprList, function (orderExpr) { + var dimLoose = orderExpr.dimension; + var order = orderExpr.order; + var parserName = orderExpr.parser; + var incomparable = orderExpr.incomparable; + + if (dimLoose == null) { + if ("development" !== 'production') { + errMsg = 'Sort transform config must has "dimension" specified.' + sampleLog; + } + + throwError(errMsg); + } + + if (order !== 'asc' && order !== 'desc') { + if ("development" !== 'production') { + errMsg = 'Sort transform config must has "order" specified.' + sampleLog; + } + + throwError(errMsg); + } + + if (incomparable && incomparable !== 'min' && incomparable !== 'max') { + var errMsg_1 = ''; + + if ("development" !== 'production') { + errMsg_1 = 'incomparable must be "min" or "max" rather than "' + incomparable + '".'; + } + + throwError(errMsg_1); + } + + if (order !== 'asc' && order !== 'desc') { + var errMsg_2 = ''; + + if ("development" !== 'production') { + errMsg_2 = 'order must be "asc" or "desc" rather than "' + order + '".'; + } + + throwError(errMsg_2); + } + + var dimInfo = upstream.getDimensionInfo(dimLoose); + + if (!dimInfo) { + if ("development" !== 'production') { + errMsg = makePrintable('Can not find dimension info via: ' + dimLoose + '.\n', 'Existing dimensions: ', upstream.cloneAllDimensionInfo(), '.\n', 'Illegal config:', orderExpr, '.\n'); + } + + throwError(errMsg); + } + + var parser = parserName ? getRawValueParser(parserName) : null; + + if (parserName && !parser) { + if ("development" !== 'production') { + errMsg = makePrintable('Invalid parser name ' + parserName + '.\n', 'Illegal config:', orderExpr, '.\n'); + } + + throwError(errMsg); + } + + orderDefList.push({ + dimIdx: dimInfo.index, + parser: parser, + comparator: new SortOrderComparator(order, incomparable) + }); + }); + var sourceFormat = upstream.sourceFormat; + + if (sourceFormat !== SOURCE_FORMAT_ARRAY_ROWS && sourceFormat !== SOURCE_FORMAT_OBJECT_ROWS) { + if ("development" !== 'production') { + errMsg = 'sourceFormat "' + sourceFormat + '" is not supported yet'; + } + + throwError(errMsg); + } + + var resultData = []; + + for (var i = 0, len = upstream.count(); i < len; i++) { + resultData.push(upstream.getRawDataItem(i)); + } + + resultData.sort(function (item0, item1) { + for (var i = 0; i < orderDefList.length; i++) { + var orderDef = orderDefList[i]; + var val0 = upstream.retrieveValueFromItem(item0, orderDef.dimIdx); + var val1 = upstream.retrieveValueFromItem(item1, orderDef.dimIdx); + + if (orderDef.parser) { + val0 = orderDef.parser(val0); + val1 = orderDef.parser(val1); + } + + var result = orderDef.comparator.evaluate(val0, val1); + + if (result !== 0) { + return result; + } + } + + return 0; + }); + return { + data: resultData + }; + } + }; + + function install$R(registers) { + registers.registerTransform(filterTransform); + registers.registerTransform(sortTransform); + } + + var DatasetModel = function (_super) { + __extends(DatasetModel, _super); + + function DatasetModel() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = 'dataset'; + return _this; + } + + DatasetModel.prototype.init = function (option, parentModel, ecModel) { + _super.prototype.init.call(this, option, parentModel, ecModel); + + this._sourceManager = new SourceManager(this); + disableTransformOptionMerge(this); + }; + + DatasetModel.prototype.mergeOption = function (newOption, ecModel) { + _super.prototype.mergeOption.call(this, newOption, ecModel); + + disableTransformOptionMerge(this); + }; + + DatasetModel.prototype.optionUpdated = function () { + this._sourceManager.dirty(); + }; + + DatasetModel.prototype.getSourceManager = function () { + return this._sourceManager; + }; + + DatasetModel.type = 'dataset'; + DatasetModel.defaultOption = { + seriesLayoutBy: SERIES_LAYOUT_BY_COLUMN + }; + return DatasetModel; + }(ComponentModel); + + var DatasetView = function (_super) { + __extends(DatasetView, _super); + + function DatasetView() { + var _this = _super !== null && _super.apply(this, arguments) || this; + + _this.type = 'dataset'; + return _this; + } + + DatasetView.type = 'dataset'; + return DatasetView; + }(ComponentView); + + function install$S(registers) { + registers.registerComponentModel(DatasetModel); + registers.registerComponentView(DatasetView); + } + + use([install$1]); + use([install]); + use([install$2, install$3, install$4, install$6, install$8, install$9, install$a, install$b, install$c, install$d, install$e, install$g, install$h, install$i, install$j, install$k, install$l, install$m, install$n, install$o, install$p, install$q]); + use(install$s); + use(install$t); + use(install$u); + use(install$v); + use(install$f); + use(install$w); + use(install$x); + use(install$z); + use(install$A); + use(install$r); + use(install$B); + use(install$C); + use(install$D); + use(install$E); + use(install$F); + use(install$G); + use(install$J); + use(install$M); + use(install$K); + use(install$L); + use(install$P); + use(install$N); + use(install$O); + use(install$Q); + use(install$R); + use(install$S); + + exports.Axis = Axis; + exports.ChartView = ChartView; + exports.ComponentModel = ComponentModel; + exports.ComponentView = ComponentView; + exports.List = List; + exports.Model = Model; + exports.PRIORITY = PRIORITY; + exports.SeriesModel = SeriesModel; + exports.color = color; + exports.connect = connect; + exports.dataTool = dataTool; + exports.dependencies = dependencies; + exports.disConnect = disConnect; + exports.disconnect = disconnect; + exports.dispose = dispose$1; + exports.env = env; + exports.extendChartView = extendChartView; + exports.extendComponentModel = extendComponentModel; + exports.extendComponentView = extendComponentView; + exports.extendSeriesModel = extendSeriesModel; + exports.format = format$1; + exports.getCoordinateSystemDimensions = getCoordinateSystemDimensions; + exports.getInstanceByDom = getInstanceByDom; + exports.getInstanceById = getInstanceById; + exports.getMap = getMap; + exports.graphic = graphic$1; + exports.helper = helper; + exports.init = init$1; + exports.innerDrawElementOnCanvas = brushSingle; + exports.matrix = matrix; + exports.number = number; + exports.parseGeoJSON = parseGeoJSON; + exports.parseGeoJson = parseGeoJSON; + exports.registerAction = registerAction; + exports.registerCoordinateSystem = registerCoordinateSystem; + exports.registerLayout = registerLayout; + exports.registerLoading = registerLoading; + exports.registerLocale = registerLocale; + exports.registerMap = registerMap; + exports.registerPostInit = registerPostInit; + exports.registerPostUpdate = registerPostUpdate; + exports.registerPreprocessor = registerPreprocessor; + exports.registerProcessor = registerProcessor; + exports.registerTheme = registerTheme; + exports.registerTransform = registerTransform; + exports.registerVisual = registerVisual; + exports.setCanvasCreator = setCanvasCreator; + exports.throttle = throttle; + exports.time = time; + exports.use = use; + exports.util = util$1; + exports.vector = vector; + exports.version = version$1; + exports.zrUtil = util; + exports.zrender = zrender; + Object.defineProperty(exports, '__esModule', { value: true }); + return exports; +}))); + +//# sourceMappingURL=echarts.js.map diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/WaterFlow.css b/WaterCloud.Web/wwwroot/js/lay-module/flow/WaterFlow.css new file mode 100644 index 0000000..73e229b --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/flow/WaterFlow.css @@ -0,0 +1,206 @@ +v\:group,v\:rect,v\:imagedata,v\:oval,v\:line,v\:polyline,v\:stroke,v\:textbox { display:inline-block;background:transparent } +::-ms-clear,::-ms-reveal{display:none;} +/*总体样式*/ +.WaterFlow { + background: #1e9fff0f; + border: #ddd 1px solid; + position: relative; + -moz-user-select: none; + -webkit-user-select: none; + border-radius: 4px; + color: #333 +} +.WaterFlow,.WaterFlow *{ + -webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box; font-size:16px;line-height:1.42857143; + font-family: "Microsoft Yahei", "Helvetica Neue", Helvetica, Hiragino Sans GB, WenQuanYi Micro Hei, Arial, sans-serif; +} +.WaterFlow:before,.WaterFlow:after,.WaterFlow *:before,.WaterFlow *:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} +.WaterFlow i{ + display:block;width:18px;height:18px;overflow:hidden;font-size:18px;color:black;text-align:center;margin:0 auto; + filter:Alpha(Opacity=70);-moz-opacity:0.7;opacity: 0.7;text-shadow:0.5px 0 #fff,0 0.5px #fff;line-height:1; +} +.WaterFlow a.a_disabled,.WaterFlow a.a_disabled:hover {border:0 !important;padding:4px 6px;background: transparent !important; cursor: not-allowed !important;} +.WaterFlow a.a_disabled i:before{color:#ccc !important;} +/*绘图区的样式*/ +.WaterFlow_work{position:absolute;top:3px;right:3px;bottom:3px;left:3px;overflow:auto;background-color:#fff;} +.WaterFlow_work .WaterFlow_work_inner{ + /*background: -webkit-linear-gradient(top, transparent 11px, #e3e3e3 12px),-webkit-linear-gradient(left, transparent 11px, #e3e3e3 12px);*/ + /*background: -moz-linear-gradient(top, transparent 11px, #e3e3e3 12px),-moz-linear-gradient(left, transparent 11px, #e3e3e3 12px);*/ + /*background: -o-linear-gradient(top, transparent 11px, #e3e3e3 12px),-o-linear-gradient(left, transparent 11px, #e3e3e3 12px);*/ + /*background: -ms-linear-gradient(top, transparent 11px, #e3e3e3 12px),-ms-linear-gradient(left, transparent 11px, #e3e3e3 12px);*/ + /*background: linear-gradient(top, transparent 11px, #e3e3e3 12px),linear-gradient(left, transparent 11px, #e3e3e3 12px);*/ + /*-webkit-background-size: 12px 12px; -moz-background-size: 12px 12px; background-size: 12px 12px;*/ + position:relative;overflow:hidden; background-image:url(data:image/gif;base64,R0lGODlhDAAMAJEAAOrq6v////Hx8QAAACH5BAAHAP8ALAAAAAAMAAwAAAIWjI8hycvonomSPtvkwYlDPQniSApAAQA7); +} +/*与矢量线有关的样式*/ +.WaterFlow_work text{color:#fff;font-size:16px;line-height:1.42857143; + font-family: "Microsoft Yahei", "Helvetica Neue", Helvetica, Hiragino Sans GB, WenQuanYi Micro Hei, Arial, sans-serif;} + +/*顶部栏的样式*/ +.WaterFlow_head{clear:both;height:28px;border-bottom:#00B4E1 2px solid;margin-left:-1px} +.WaterFlow_head label{ + font-weight:bold;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:27px;padding:3px;width:176px; + background:#00B4E1;float:left;color:#fff;border-radius:3px 0 0 0;overflow:hidden;margin:-1px 4px 0 0;text-align:center; +} +.WaterFlow_head_btn{display:block;border:0;height:26px;width:30px;cursor:default;padding:4px 6px;margin:0 2px;float:left;outline:none;blr:expression(this.onFocus=this.blur());text-decoration:none;cursor:pointer} +.WaterFlow_head_btn i{display:inline-block;overflow:hidden;width:18px;height:18px;border:0;font-size:16px;line-height:18px;} +.WaterFlow_head_btn:hover{background:#fff;padding:4px 5px;border-left:#ddd 1px solid;border-right:#ddd 1px solid} + +/*左侧绘图工具栏的样式*/ +.WaterFlow_tool{float:left;clear:left;border-right:#ddd 1px solid;margin-left:-1px;} +.WaterFlow_tool_div{width:34px;padding:4px 0;overflow:hidden;margin-right:-1px;} +.WaterFlow_tool span{height:0;overflow:hidden;border-top:#ddd 1px solid;border-bottom:#fff 1px solid;margin:0 2px;clear:both;display:block;} +.WaterFlow_tool_btn{display:block;border:0;height:34px;width:34px;cursor:default;padding:8px;outline:none;blr:expression(this.onFocus=this.blur());color:#777;text-decoration:none;cursor:pointer} +.WaterFlow_tool_btn i{display:block;overflow:hidden;width:18px;height:18px;border:0} +.WaterFlow_tool_btn:hover{border:#ddd 1px solid;background:#fff;padding:7px} +.WaterFlow_tool_btndown{ + cursor:default;outline:none;blr:expression(this.onFocus=this.blur());height:34px;width:36px;margin:0 -1px; + padding:8px 9px;background:#00B4E1;/*#FFBF00*/display:block;text-decoration:none;filter:Alpha(Opacity=70);-moz-opacity:0.7;opacity: 0.7; +} +.WaterFlow_tool_btndown i{display:block;overflow:hidden;width:18px;height:18px;color:#000;filter:Alpha(Opacity=37);-moz-opacity:0.37;opacity: 0.37;position:relative} + +/*工作区扩展边栏样式*/ +.WaterFlow_extend_right{position:absolute;z-index:10002;top:0;right:0;height:100%;width:14px;cursor:e-resize;filter:Alpha(Opacity=20);-moz-opacity:0.2;opacity: 0.2} +.WaterFlow_extend_bottom{position:absolute;z-index:10002;bottom:0;left:0;width:100%;height:14px;cursor:s-resize;filter:Alpha(Opacity=20);-moz-opacity:0.2;opacity: 0.2} +.WaterFlow_extend_right:hover{background-color:#999;border:#fff 1px solid} +.WaterFlow_extend_bottom:hover{background-color:#999;border:#fff 1px solid} + +/*区域分组(泳道)的样式*/ +.WaterFlow_work_group{cursor:default;position:absolute;overflow:hidden;top:0;left:0} +.WaterFlow_area{cursor:default;position:absolute;overflow:hidden;} +.WaterFlow_area .lock{cursor:default;} +.WaterFlow_area .bg{cursor:move;filter:Alpha(Opacity=30);-moz-opacity:0.3;opacity: 0.3;} +.WaterFlow_area.lock .bg{cursor:default;} +.WaterFlow_area label{cursor:text;top:0;left:23px;position:absolute;display:block;} +.WaterFlow_area.lock label{cursor:default;} +.WaterFlow_area i{top:2px;left:2px;width:18px;height:20px;position:absolute;cursor:pointer;} +.WaterFlow_area i:before{content:"\e6bd"} +.WaterFlow_area.area_red .bg{border:1px solid red;background-color:#FF7865} +.WaterFlow_area.area_red label,.WaterFlow_area.area_red i{color:red;} +.WaterFlow_area.area_yellow .bg{border:1px solid #CD925A;background-color:#FFD564} +.WaterFlow_area.area_yellow label,.WaterFlow_area.area_yellow i{color:#FFBA1D;} +.WaterFlow_area.area_blue .bg{border:1px solid #347BB1;background-color:#549CDE} +.WaterFlow_area.area_blue label,.WaterFlow_area.area_blue i{color:#347BB1;} +.WaterFlow_area.area_green .bg{border:1px solid green;background-color:#84CA04} +.WaterFlow_area.area_green label,.WaterFlow_area.area_green i{color:green;} + +/*画连线区域所需要的样式*/ +.WaterFlow_work svg{display:block;position:absolute;top:0;left:0} +.WaterFlow_work v\:group{position:relative;display:block} +.WaterFlow_work v\:group v\:line{overflow:visible} +.WaterFlow_work v\:group v\:polyline{overflow:visible} +.WaterFlow_work v\:group div{cursor:text;position:absolute;overflow:visible;display:inline;float:left;white-space: nowrap} +.WaterFlow_work .draw{color:#ff8800} + +/*各种节点样式*/ +.WaterFlow_item{ + position:absolute;background:#A1DCEB;padding:1px; + border-radius:1px;background-color:#C1DCFC;box-shadow:1px 1px 2px rgba(99,99,99,2); +} +.WaterFlow table{padding:1px 2px;border-radius:2px} +.WaterFlow td,.WaterFlow td div{ vertical-align:middle;text-align:center;padding:0;cursor:default;word-wrap:break-word;word-break:break-all} +.WaterFlow .ico { + width: 18px; + cursor: move; + text-align: center; + vertical-align: middle; + padding-left: 5px; +} +.WaterFlow .ico i{filter:Alpha(Opacity=30);-moz-opacity:0.3;opacity:0.3;color:#000;margin:0 auto;} + +.WaterFlow .item_round{border-radius:10px; overflow:visible} +.WaterFlow .item_round table{border:0;padding:3px;width:26px;height:26px} +.WaterFlow .item_round .span{ + display:block;text-align:center; position:absolute;top:100%;left:-100%;width:300%;overflow:visible; + padding:0;cursor:default;word-wrap: break-word;word-break:break-all +} +.WaterFlow .item_mix{background:#B6F700;color:#fff} +.WaterFlow .item_focus{border:#3892D3 1px solid !important;padding:0;z-index:5} +.WaterFlow .item_focus table{margin:0 !important;} +.WaterFlow .item_focus.item_round .span{ + display:block;text-align:center; position:absolute;margin-top:1px;overflow:visible; + padding:0;cursor:default;word-wrap: break-word;word-break:break-all; +} +.WaterFlow .item_mark{border:#ff8800 2px solid;padding:0} +.WaterFlow .item_mark table{margin:-1px} +.WaterFlow .item_mark td{cursor:crosshair} +.WaterFlow .item_mark.item_round .span{padding-top:2px} + +/*编辑时一些工具的页面特效*/ +.WaterFlow textarea{position:absolute;border:#3892D3 1px solid;display:none;overflow-y:visible;width:100px;z-index:10001} +.WaterFlow div .rs_right{overflow:hidden;position:absolute;right:-1px;top:-1px;height:100%;width:6px;cursor:w-resize} +.WaterFlow div .rs_bottom{overflow:hidden;position:absolute;left:-1px;bottom:-1px;width:100%;height:6px;cursor:n-resize} +.WaterFlow div .rs_rb{ + position:absolute;right:-1px;bottom:0;width:10px;height:9px;filter:Alpha(Opacity=70);-moz-opacity:0.7;opacity:0.7; + font-family:"iconflow" !important;font-size:12px;color:#475669;line-height:1;overflow:hidden;cursor:pointer;cursor:nw-resize; +} +.WaterFlow div .rs_rb:before{content:"\e6b7";} +.WaterFlow div .rs_close{ + position:absolute;right:-1px;top:1px;width:10px;height:9px;filter:Alpha(Opacity=70);-moz-opacity:0.7;opacity:0.7; + font-family:"iconflow" !important;font-size:12px;color:#475669;line-height:1;overflow:hidden;cursor:pointer; +} +.WaterFlow div .rs_close:before{content:"\e674";} +.WaterFlow .rs_ghost{ + position:absolute;display:none;overflow:hidden;border:#8492A6 1px dashed; background:#E5E9F2; + filter:Alpha(Opacity=50);-moz-opacity:0.5;opacity: 0.5;z-index:10 +} +.WaterFlow .WaterFlow_line_oper{ + width:82px;height:20px;background:#E5E9F2;border:#8492A6 1px solid;position:absolute; + filter:Alpha(Opacity=50);-moz-opacity:0.5;opacity: 0.5;z-index:10000; +} +.WaterFlow .WaterFlow_line_mp{ + width:9px;height:9px;filter:Alpha(Opacity=40);-moz-opacity:0.4;opacity:0.4;overflow:hidden; + position:absolute;z-index:9999;background:#333;cursor:crosshair +} +.WaterFlow_linemove{background-color:transparent;filter:Alpha(Opacity=50);-moz-opacity:0.5;opacity:0.5;overflow:hidden;position:absolute;z-index:9999;} +.WaterFlow_line_oper i{display:inline-block;margin-left:2px;cursor:pointer;position:relative;} +.WaterFlow .b_l1:before{content:"\e60d";color:#1F2D3D} +.WaterFlow .b_l2:before{content:"\e60e";color:#1F2D3D} +.WaterFlow .b_l3:before{content:"\e601";color:#1F2D3D} +.WaterFlow .b_x:before{content:"\e61a";color:red} + + +/*以下为图标样式(固定大小18px*18px,矢量字体大小16px),用户可自定义扩展自己的新矢量图标字体,写法参照以下的内容*/ +@font-face {font-family: "iconflow"; + src: url('fonts/iconflow.eot?t=1494321407539'); /* IE9*/ + src: url('fonts/iconflow.eot?t=1494321407539#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('fonts/iconflow.woff?t=1494321407539') format('woff'), /* chrome, firefox */ + url('fonts/iconflow.ttf?t=1494321407539') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ + url('fonts/iconflow.svg?t=1494321407539#iconflow') format('svg'); /* iOS 4.1- */ +} +.WaterFlow_area i,.WaterFlow .WaterFlow_line_oper i,.WaterFlow_tool i,.WaterFlow_head i,.WaterFlow_item .ico i{ + font-family:"iconflow" !important; + font-size:18px;line-height:20px; + font-style:normal; + -webkit-font-smoothing: antialiased; + -webkit-text-stroke-width: 0.2px; + -moz-osx-font-smoothing: grayscale; +} +/*自带的一些节点矢量图标样式*/ +.WaterFlow .ico_cursor:before{ content:"\e602"; } +.WaterFlow .ico_start:before{ content:"\e700"; } +.WaterFlow .ico_end:before{ content:"\e609"; } +.WaterFlow .ico_fork:before{ content:"\e60c"; } +.WaterFlow .ico_join:before{ content:"\e606"; } +.WaterFlow .ico_direct:before{ content:"\e605"; } +.WaterFlow .ico_dashed:before{ content:"\e675"; } +.WaterFlow .ico_group:before{ content:"\e663"; } +.WaterFlow .ico_complex:before{ content:"\e872"; } +/*.WaterFlow .ico_complex{background:url(assets/img/waterflow_icon.png) no-repeat -116px -20px;opacity:1 !important;filter:Alpha(Opacity=70) !important;}*/ +.WaterFlow .ico_node:before{ content:"\e678"; } +.WaterFlow .ico_task:before{ content:"\e6af"; } +/*.WaterFlow .ico_task{background:url(assets/img/waterflow_icon.png) no-repeat 2px -45px;opacity:1 !important;filter:Alpha(Opacity=70) !important;}*/ +.WaterFlow .ico_chat:before{ content:"\e61b"; } +.WaterFlow .ico_state:before{ content:"\e633"; } +.WaterFlow .ico_plug:before{ content:"\e66c"; } +.WaterFlow .ico_menu:before{ content:"\e649"; } +.WaterFlow .ico_sound:before{ content:"\e62b"; } + +/*以下是内部用头部工具栏按钮专用的样式*/ +.WaterFlow .ico_open:before{ content:"\e7a0";color:#FFD300 } +.WaterFlow .ico_new:before{ content:"\e659"; } +.WaterFlow .ico_reload:before{ content:"\e607";color:#669900 } +.WaterFlow .ico_save:before{ content:"\e63d";color:#0099cc } +.WaterFlow .ico_undo:before{ content:"\e673";color:#ff8800 } +.WaterFlow .ico_redo:before{ content:"\e672";color:#ff8800 } +.WaterFlow .ico_print:before{ content:"\e671"; } diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/flowlayout.js b/WaterCloud.Web/wwwroot/js/lay-module/flow/flowlayout.js new file mode 100644 index 0000000..558d622 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/flow/flowlayout.js @@ -0,0 +1,395 @@ +layui.define(["jquery", "layer"], + function (exports) { + var $ = layui.jquery; + var layer = layui.layer; + //初始化设计流程器 + $.fn.flowdesign = function (options) { + var $frmpreview = $(this); + if (!$frmpreview.attr('id')) { + return false; + } + $frmpreview.html(""); + + var defaultcnf = { + width: 500, + height: 400, + haveHead: false, + haveTool: true, + headLabel: true, + toolBtns: ["start round mix", "end round", "node", "fork", "join"], + haveGroup: true, + useOperStack: true, + needNoTag: true, + useName: "处理人", + tagName: { "1": "通过", "2": "不通过", "3": "驳回/撤回" }, + tagClass: { "1": "#5cb85c", "2": "#d9534f", "3": "#f0ad4e" }, + resultName: "结果", + timeName: "处理时间", + remarkName: "备注", + }; + if (options != undefined) { + $.extend(defaultcnf, options); + } + + var flowPanel = $.createWaterFlow($(this), defaultcnf); + flowPanel.setNodeRemarks({ + cursor: "选择指针", + direct: "转换连线", + dashed: "关联虚线", + start: "开始节点", + end: "结束节点", + task: "任务节点", + node: "任务节点", + chat: "决策节点", + state: "状态节点", + plug: "附加插件", + fork: "会签开始节点", + join: "会签结束节点", + complex: "复合节点", + group: "组织划分框编辑开" + }); + if (options != undefined + && options.flowcontent != undefined + && options.flowcontent != null) { //加载内容 + flowPanel.loadData(options.flowcontent); + } + + //导出数据扩展方法 + //所有节点必须有进出线段 + //必须有开始结束节点(且只能为一个) + //分流合流节点必须成对出现 + //分流合流节点必须一一对应且中间必须有且只能有一个普通节点 + //分流节点与合流节点之前的审核节点必须有且只能有一条出去和进来节点 + flowPanel.exportDataEx = function () { + var data = flowPanel.exportData(); + var fromlines = {}, + tolines = {}, + nodes = {}, + fnodes = [], //会签分流节点 + hnodes = [], //会签合流节点 + startroundFlag = 0, //开始节点标识 + endroundFlag = 0; //结束节点标识 + for (var i in data.lines) { + if (fromlines[data.lines[i].from] == undefined) { + fromlines[data.lines[i].from] = []; + } + fromlines[data.lines[i].from].push(data.lines[i].to); + + if (tolines[data.lines[i].to] == undefined) { + tolines[data.lines[i].to] = []; + } + tolines[data.lines[i].to].push(data.lines[i].from); + } + for (var j in data.nodes) { + var _node = data.nodes[j]; + var _flag = false; + switch (_node.type) { + case "start round mix": + startroundFlag++; + if (fromlines[_node.id] == undefined) { + layer.msg("开始节点无法流转到下一个节点"); + return -1; + } + break; + case "end round": + endroundFlag++; + if (tolines[_node.id] == undefined) { + layer.msg("无法流转到结束节点"); + return -1; + } + break; + case "node": + if (_node.setInfo == null) { + layer.msg("请设置任务节点【"+_node.name+"】操作人员"); + return -1; + } + _flag = true; + break; + case "fork": + _flag = true; + fnodes.push(_node.id); + break; + case "join": + hnodes.push(_node.id); + _flag = true; + break; + default: + layer.msg("节点数据异常!"); + return -1; + break; + } + nodes[_node.id] = _node; + } + if (startroundFlag == 0) { + layer.msg("必须有开始节点"); + return -1; + } + + if (endroundFlag == 0) { + layer.msg("必须有结束节点"); + return -1; + } + + if (fnodes.length != hnodes.length) { + layer.msg("会签开始的节点数量必须等于会签结束的节点数量"); + return -1; + } + return data; + } + + flowPanel.SetNodeEx = function (id, data) { + flowPanel.setName(id, data.NodeName, "node", data); + } + flowPanel.SetLineEx = function (id, data) { + flowPanel.setName(id, data.LineName, "line", data); + } + flowPanel.SetAreaEx = function (id, data) { + flowPanel.setName(id, data.AreaName, "area", data); + flowPanel.setAreaColor(id, data.AreaColor); + } + flowPanel.onItemDbClick = function (id, type) { + var obj = flowPanel.getItemInfo(id, type); + switch (type) { + case "node": + if ('OpenNode' in options) { + options.OpenNode(obj); + } + break; + case "line": + if ('OpenLine' in options) { + options.OpenLine(obj); + } + break; + case "area": + if ('OpenArea' in options) { + options.OpenArea(obj); + } + break; + } + return false; + } + flowPanel.onItemRightClick = function (id, type) { + var obj = flowPanel.getItemInfo(id, type); + switch (type) { + case "node": + if ('OpenNode' in options) { + options.OpenNode(obj); + } + break; + case "line": + if ('OpenLine' in options) { + options.OpenLine(obj); + } + break; + case "area": + if ('OpenArea' in options) { + options.OpenArea(obj); + } + break; + } + return false; + } + if (defaultcnf.isprocessing) //如果是显示进程状态 + { + var tipHtml = + '
                '; + if (defaultcnf.needNoTag==true) { + tipHtml += + '
                正在处理
                '; + } + if (!!defaultcnf.tagClass && Object.keys(defaultcnf.tagClass).length > 0) { + for (var p in defaultcnf.tagClass) {//遍历json对象的每个key/value对,p为key + tipHtml += + '
                ' + defaultcnf.tagName[p] + '
                '; + } + } + if (defaultcnf.needNoTag == true) { + tipHtml += + '
                未处理
                '; + } + $('.WaterFlow_work .WaterFlow_work_inner').css('background-image', 'none'); + $('td').css('color', '#fff'); + $frmpreview.css('background', '#fff'); + $('.ico').remove(); + $('.WaterFlow_item').css('border', '0px'); + $frmpreview.append(tipHtml); + $.each(options.nodeData, + function (i, item) { + $("#" + item.id).css("background", "#999"); + if (item.type == "start round mix") { + $("#" + item.id).css("background", "#5cb85c"); + } else { + if (item.id == options.activityId) { + $("#" + item.id).css("background", "#5bc0de"); + } + if (item.setInfo != undefined && item.setInfo.Taged != undefined) { + if (!!defaultcnf.tagName[item.setInfo.Taged]) { + $("#" + item.id).css("background", defaultcnf.tagClass[item.setInfo.Taged]); + } else { + $("#" + item.id).css("background", "#999"); + } + } + } + if (item.setInfo != undefined && item.setInfo.Taged != undefined) { + var tips = '
                '; + tips += "

                " + defaultcnf.useName+":" + item.setInfo.UserName + "

                "; + tips += "

                " + defaultcnf.resultName + ":" + defaultcnf.tagName[item.setInfo.Taged] + "

                "; + tips += "

                " + defaultcnf.timeName +":" + item.setInfo.TagedTime + "

                "; + tips += "
                " + defaultcnf.remarkName +":" + item.setInfo.Description + "
                "; + + $('#' + item.id).hover(function () { + layer.tips(tips, '#' + item.id); + }); + } else { + $('#' + item.id).hover(function () { + layer.tips('暂无处理信息', '#' + item.id); + }); + } + }); + } + if (options.preview == 1) { + preview(); + } + + //预览 + function preview() { + var _frmitems = {}; + for (var i in options.frmData) { + var _frmitem = options.frmData[i]; + _frmitems[_frmitem.control_field] = _frmitem.control_label; + } + var DataBaseLinkData = {}; + + + var _NodeRejectType = { "0": "前一步", "1": "第一步", "2": "某一步", "3": "用户指定", "4": "不处理" }; + var _NodeIsOver = { "0": "不允许", "1": "允许" }; + var _NodeDesignate = { + "NodeDesignateType1": "所有成员", + "NodeDesignateType2": "指定成员", + "NodeDesignateType3": "发起者领导", + "NodeDesignateType4": "前一步骤领导", + "NodeDesignateType5": "发起者部门领导", + "NodeDesignateType6": "发起者公司领导" + }; + var _NodeConfluenceType = { "all": "所有步骤通过", "one": "一个步骤通过即可", "2": "按百分比计算" }; + if (options.flowcontent == undefined) return; + $.each(options.flowcontent.nodes, + function (i, item) { + if (item.setInfo != undefined) { + var _popoverhtml = ""; + _popoverhtml += + '
                  基本信息
                '; + _popoverhtml += '
                  '; + _popoverhtml += '
                • 节点标识:' + item.setInfo.NodeCode + '
                • '; + _popoverhtml += '
                • 驳回类型:' + _NodeRejectType[item.setInfo.NodeRejectType] + '
                • '; + _popoverhtml += '
                • 终止流程:' + _NodeIsOver[item.setInfo.NodeIsOver] + '
                • '; + if (item.setInfo.Description != "") { + _popoverhtml += '
                • 备注:' + item.setInfo.Description + '
                • '; + } + if (item.setInfo.NodeConfluenceType != "") { + _popoverhtml += '
                • 会签策略:' + + _NodeConfluenceType[item.setInfo.NodeConfluenceType] + + '
                • '; + if (item.setInfo.NodeConfluenceType == 2) { + _popoverhtml += '
                • 会签比例:' + item.setInfo.NodeConfluenceRate + '
                • '; + } + } + if (item.setInfo.NodeDataBase != "") { + _popoverhtml += '
                • 绑定数据库:' + DataBaseLinkData[item.setInfo.NodeDataBase] + '
                • '; + } + if (item.setInfo.NodeTable != "") { + _popoverhtml += '
                • 绑定表名:' + item.setInfo.NodeTable + '
                • '; + } + if (item.setInfo.NodePram != "") { + _popoverhtml += '
                • 绑定字段:' + item.setInfo.NodePram + '
                • '; + } + _popoverhtml += '
                '; + + _popoverhtml += + '
                  审核者
                '; + _popoverhtml += '
                  '; + _popoverhtml += '
                • 类型:' + _NodeDesignate[item.setInfo.NodeDesignate] + '
                • '; + if (item.setInfo.NodeDesignateData != undefined) { + var _rowstr = ""; + for (var i in item.setInfo.NodeDesignateData.roles) { + var _postitem = item.setInfo.NodeDesignateData.roles[i]; + var _one = top.clientroleData[_postitem]; + _rowstr += ' ' + + (_one == undefined ? _postitem : _one.FullName) + + ''; + if (i == item.setInfo.NodeDesignateData.roles.length - 1) { + _popoverhtml += '
                • 角色:' + _rowstr + '
                • '; + } + } + + _rowstr = ""; + for (var i in item.setInfo.NodeDesignateData.users) { + var _postitem = item.setInfo.NodeDesignateData.users[i]; + var _one = clientuserData[_postitem]; + _rowstr += ' ' + + (_one == undefined ? _postitem : _one.RealName) + + ''; + if (i == item.setInfo.NodeDesignateData.users.length - 1) { + _popoverhtml += '
                • 用户:' + _rowstr + '
                • '; + } + } + } + _popoverhtml += '
                '; + + var _row = ""; + for (var i in item.setInfo.frmPermissionInfo) { + var _item = item.setInfo.frmPermissionInfo[i]; + var _downtext = ""; + if (_item.down) { + _downtext = ' | 可下载'; + } else if (_item.down != undefined) { + _downtext = ' | 不可下载'; + } + _row += '
              • ' + + _frmitems[_item.fieldid] + + ': ' + + (_item.look ? '可查看' : '不可查看') + + _downtext + + '
              • '; + if (i == item.setInfo.frmPermissionInfo.length - 1) { + _popoverhtml += + '
                  权限分配
                '; + _popoverhtml += '
                  '; + _popoverhtml += _row; + _popoverhtml += '
                '; + } + } + + if (item.setInfo.NodeDataBaseToSQL != "" || item.setInfo.NodeSQL != "") { + _popoverhtml += + '
                  执行SQL
                '; + _popoverhtml += '
                  '; + _popoverhtml += '
                • 数据库:' + DataBaseLinkData[item.setInfo.NodeDataBaseToSQL] + '
                • '; + _popoverhtml += '
                • SQL语句:' + item.setInfo.NodeSQL + '
                • '; + _popoverhtml += '
                '; + } + + $('#' + item.id).attr('title', item.name); + $('#' + item.id).attr('data-toggle', 'popover'); + $('#' + item.id).attr('data-placement', 'bottom'); + $('#' + item.id).attr('data-content', _popoverhtml); + } else { + $('#' + item.id).attr('title', item.name); + $('#' + item.id).attr('data-toggle', 'popover'); + $('#' + item.id).attr('data-placement', 'bottom'); + $('#' + item.id).attr('data-content', "该节点未被设置"); + } + }); + //$('.WaterFlow_item').popover({ html: true }); + } + + return flowPanel; + } + + exports('flowlayout'); + }); + + + + + diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/demo.css b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/demo.css new file mode 100644 index 0000000..3d9cbe7 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/demo.css @@ -0,0 +1,370 @@ +*{margin: 0;padding: 0;list-style: none;} +/* +KISSY CSS Reset +理念:1. reset 的目的不是清除浏览器的默认样式,这仅是部分工作。清除和重置是紧密不可分的。 +2. reset 的目的不是让默认样式在所有浏览器下一致,而是减少默认样式有可能带来的问题。 +3. reset 期望提供一套普适通用的基础样式。但没有银弹,推荐根据具体需求,裁剪和修改后再使用。 +特色:1. 适应中文;2. 基于最新主流浏览器。 +维护:玉伯, 正淳 + */ + +/** 清除内外边距 **/ +body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* structural elements 结构元素 */ +dl, dt, dd, ul, ol, li, /* list elements 列表元素 */ +pre, /* text formatting elements 文本格式元素 */ +form, fieldset, legend, button, input, textarea, /* form elements 表单元素 */ +th, td /* table elements 表格元素 */ { + margin: 0; + padding: 0; +} + +/** 设置默认字体 **/ +body, +button, input, select, textarea /* for ie */ { + font: 12px/1.5 tahoma, arial, \5b8b\4f53, sans-serif; +} +h1, h2, h3, h4, h5, h6 { font-size: 100%; } +address, cite, dfn, em, var { font-style: normal; } /* 将斜体扶正 */ +code, kbd, pre, samp { font-family: courier new, courier, monospace; } /* 统一等宽字体 */ +small { font-size: 12px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */ + +/** 重置列表元素 **/ +ul, ol { list-style: none; } + +/** 重置文本格式元素 **/ +a { text-decoration: none; } +a:hover { text-decoration: underline; } + + +/** 重置表单元素 **/ +legend { color: #000; } /* for ie6 */ +fieldset, img { border: 0; } /* img 搭车:让链接里的 img 无边框 */ +button, input, select, textarea { font-size: 100%; } /* 使得表单元素在 ie 下能继承字体大小 */ +/* 注:optgroup 无法扶正 */ + +/** 重置表格元素 **/ +table { border-collapse: collapse; border-spacing: 0; } + +/* 清除浮动 */ +.ks-clear:after, .clear:after { + content: '\20'; + display: block; + height: 0; + clear: both; +} +.ks-clear, .clear { + *zoom: 1; +} + +.main { + padding: 30px 100px; +width: 960px; +margin: 0 auto; +} +.main h1{font-size:36px; color:#333; text-align:left;margin-bottom:30px; border-bottom: 1px solid #eee;} + +.helps{margin-top:40px;} +.helps pre{ + padding:20px; + margin:10px 0; + border:solid 1px #e7e1cd; + background-color: #fffdef; + overflow: auto; +} + +.icon_lists{ + width: 100% !important; + +} + +.icon_lists li{ + float:left; + width: 100px; + height:180px; + text-align: center; + list-style: none !important; +} +.icon_lists .icon{ + font-size: 42px; + line-height: 100px; + margin: 10px 0; + color:#333; + -webkit-transition: font-size 0.25s ease-out 0s; + -moz-transition: font-size 0.25s ease-out 0s; + transition: font-size 0.25s ease-out 0s; + +} +.icon_lists .icon:hover{ + font-size: 100px; +} + + + +.markdown { + color: #666; + font-size: 14px; + line-height: 1.8; +} + +.highlight { + line-height: 1.5; +} + +.markdown img { + vertical-align: middle; + max-width: 100%; +} + +.markdown h1 { + color: #404040; + font-weight: 500; + line-height: 40px; + margin-bottom: 24px; +} + +.markdown h2, +.markdown h3, +.markdown h4, +.markdown h5, +.markdown h6 { + color: #404040; + margin: 1.6em 0 0.6em 0; + font-weight: 500; + clear: both; +} + +.markdown h1 { + font-size: 28px; +} + +.markdown h2 { + font-size: 22px; +} + +.markdown h3 { + font-size: 16px; +} + +.markdown h4 { + font-size: 14px; +} + +.markdown h5 { + font-size: 12px; +} + +.markdown h6 { + font-size: 12px; +} + +.markdown hr { + height: 1px; + border: 0; + background: #e9e9e9; + margin: 16px 0; + clear: both; +} + +.markdown p, +.markdown pre { + margin: 1em 0; +} + +.markdown > p, +.markdown > blockquote, +.markdown > .highlight, +.markdown > ol, +.markdown > ul { + width: 80%; +} + +.markdown ul > li { + list-style: circle; +} + +.markdown > ul li, +.markdown blockquote ul > li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown > ul li p, +.markdown > ol li p { + margin: 0.6em 0; +} + +.markdown ol > li { + list-style: decimal; +} + +.markdown > ol li, +.markdown blockquote ol > li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown code { + margin: 0 3px; + padding: 0 5px; + background: #eee; + border-radius: 3px; +} + +.markdown pre { + border-radius: 6px; + background: #f7f7f7; + padding: 20px; +} + +.markdown pre code { + border: none; + background: #f7f7f7; + margin: 0; +} + +.markdown strong, +.markdown b { + font-weight: 600; +} + +.markdown > table { + border-collapse: collapse; + border-spacing: 0px; + empty-cells: show; + border: 1px solid #e9e9e9; + width: 95%; + margin-bottom: 24px; +} + +.markdown > table th { + white-space: nowrap; + color: #333; + font-weight: 600; + +} + +.markdown > table th, +.markdown > table td { + border: 1px solid #e9e9e9; + padding: 8px 16px; + text-align: left; +} + +.markdown > table th { + background: #F7F7F7; +} + +.markdown blockquote { + font-size: 90%; + color: #999; + border-left: 4px solid #e9e9e9; + padding-left: 0.8em; + margin: 1em 0; + font-style: italic; +} + +.markdown blockquote p { + margin: 0; +} + +.markdown .anchor { + opacity: 0; + transition: opacity 0.3s ease; + margin-left: 8px; +} + +.markdown .waiting { + color: #ccc; +} + +.markdown h1:hover .anchor, +.markdown h2:hover .anchor, +.markdown h3:hover .anchor, +.markdown h4:hover .anchor, +.markdown h5:hover .anchor, +.markdown h6:hover .anchor { + opacity: 1; + display: inline-block; +} + +.markdown > br, +.markdown > p > br { + clear: both; +} + + +.hljs { + display: block; + background: white; + padding: 0.5em; + color: #333333; + overflow-x: auto; +} + +.hljs-comment, +.hljs-meta { + color: #969896; +} + +.hljs-string, +.hljs-variable, +.hljs-template-variable, +.hljs-strong, +.hljs-emphasis, +.hljs-quote { + color: #df5000; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-type { + color: #a71d5d; +} + +.hljs-literal, +.hljs-symbol, +.hljs-bullet, +.hljs-attribute { + color: #0086b3; +} + +.hljs-section, +.hljs-name { + color: #63a35c; +} + +.hljs-tag { + color: #333333; +} + +.hljs-title, +.hljs-attr, +.hljs-selector-id, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #795da3; +} + +.hljs-addition { + color: #55a532; + background-color: #eaffea; +} + +.hljs-deletion { + color: #bd2c00; + background-color: #ffecec; +} + +.hljs-link { + text-decoration: underline; +} + +pre{ + background: #fff; +} + + + + + diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/demo_fontclass.html b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/demo_fontclass.html new file mode 100644 index 0000000..3e8304d --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/demo_fontclass.html @@ -0,0 +1,256 @@ + + + + + + IconFont + + + + +
                +

                IconFont 图标

                +
                  + +
                • + +
                  指针
                  +
                  .i-zhizhen1
                  +
                • + +
                • + +
                  关闭
                  +
                  .i-msnui-close-fat
                  +
                • + +
                • + +
                  close
                  +
                  .i-close
                  +
                • + +
                • + +
                  文件添加
                  +
                  .i-wenjiantianjia
                  +
                • + +
                • + +
                  tag
                  +
                  .i-tag
                  +
                • + +
                • + +
                  conow-redo
                  +
                  .i-conowredo
                  +
                • + +
                • + +
                  conow-revoke
                  +
                  .i-conowrevoke
                  +
                • + +
                • + +
                  保存
                  +
                  .i-baocun
                  +
                • + +
                • + +
                  Refresh
                  +
                  .i-refresh
                  +
                • + +
                • + +
                  右下-实心
                  +
                  .i-youxiashixin
                  +
                • + +
                • + +
                  拍照按钮
                  +
                  .i-paizhaoanniu
                  +
                • + +
                • + +
                  徽章
                  +
                  .i-huizhang
                  +
                • + +
                • + +
                  hr工作台
                  +
                  .i-hrgongzuotai
                  +
                • + +
                • + +
                  停止
                  +
                  .i-tingzhi-copy
                  +
                • + +
                • + +
                  文件夹
                  +
                  .i-wenjianjia
                  +
                • + +
                • + +
                  声音
                  +
                  .i-webtubiaoku08
                  +
                • + +
                • + +
                  数据库
                  +
                  .i-database
                  +
                • + +
                • + +
                  插件 (1)
                  +
                  .i-chajian1
                  +
                • + +
                • + +
                  菜单
                  +
                  .i-caidan
                  +
                • + +
                • + +
                  网络
                  +
                  .i-wangluo
                  +
                • + +
                • + +
                  打印
                  +
                  .i-dayin
                  +
                • + +
                • + +
                  用户
                  +
                  .i-user
                  +
                • + +
                • + +
                  开始
                  +
                  .i-kaishi
                  +
                • + +
                • + +
                  合并
                  +
                  .i-hebing
                  +
                • + +
                • + +
                  聊天
                  +
                  .i-liaotian
                  +
                • + +
                • + +
                  定时
                  +
                  .i-dingshi
                  +
                • + +
                • + +
                  斜箭头
                  +
                  .i-xiejiantou
                  +
                • + +
                • + +
                  配置
                  +
                  .i-peizhi
                  +
                • + +
                • + +
                  项目组合
                  +
                  .i-xiangmuzuhe
                  +
                • + +
                • + +
                  系统参数配置
                  +
                  .i-xitongcanshupeizhi
                  +
                • + +
                • + +
                  区块
                  +
                  .i-qukuai
                  +
                • + +
                • + +
                  分支
                  +
                  .i-fenzhi
                  +
                • + +
                • + +
                  01
                  +
                  .i-icon-test
                  +
                • + +
                • + +
                  02
                  +
                  .i-icon-test1
                  +
                • + +
                • + +
                  小虚线
                  +
                  .i-xiaoxuxian
                  +
                • + +
                • + +
                  检查工具 直线
                  +
                  .i-jianchagongjuzhixian
                  +
                • + +
                + +

                font-class引用

                +
                + +

                font-class是unicode使用方式的一种变种,主要是解决unicode书写不直观,语意不明确的问题。

                +

                与unicode使用方式相比,具有如下特点:

                +
                  +
                • 兼容性良好,支持ie8+,及所有现代浏览器。
                • +
                • 相比于unicode语意明确,书写更直观。可以很容易分辨这个icon是什么。
                • +
                • 因为使用class来定义图标,所以当要替换图标时,只需要修改class里面的unicode引用。
                • +
                • 不过因为本质上还是使用的字体,所以多色图标还是不支持的。
                • +
                +

                使用步骤如下:

                +

                第一步:引入项目下面生成的fontclass代码:

                + + +
                <link rel="stylesheet" type="text/css" href="./iconfont.css">
                +

                第二步:挑选相应图标并获取类名,应用于页面:

                +
                <i class="iconflow i-xxx"></i>
                +
                +

                "iconflow"是你项目下的font-family。可以通过编辑项目查看,默认是"iconfont"。

                +
                +
                + + diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/demo_symbol.html b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/demo_symbol.html new file mode 100644 index 0000000..3ed6607 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/demo_symbol.html @@ -0,0 +1,351 @@ + + + + + + IconFont + + + + + + +
                +

                IconFont 图标

                +
                  + +
                • + +
                  指针
                  +
                  #i-zhizhen1
                  +
                • + +
                • + +
                  关闭
                  +
                  #i-msnui-close-fat
                  +
                • + +
                • + +
                  close
                  +
                  #i-close
                  +
                • + +
                • + +
                  文件添加
                  +
                  #i-wenjiantianjia
                  +
                • + +
                • + +
                  tag
                  +
                  #i-tag
                  +
                • + +
                • + +
                  conow-redo
                  +
                  #i-conowredo
                  +
                • + +
                • + +
                  conow-revoke
                  +
                  #i-conowrevoke
                  +
                • + +
                • + +
                  保存
                  +
                  #i-baocun
                  +
                • + +
                • + +
                  Refresh
                  +
                  #i-refresh
                  +
                • + +
                • + +
                  右下-实心
                  +
                  #i-youxiashixin
                  +
                • + +
                • + +
                  拍照按钮
                  +
                  #i-paizhaoanniu
                  +
                • + +
                • + +
                  徽章
                  +
                  #i-huizhang
                  +
                • + +
                • + +
                  hr工作台
                  +
                  #i-hrgongzuotai
                  +
                • + +
                • + +
                  停止
                  +
                  #i-tingzhi-copy
                  +
                • + +
                • + +
                  文件夹
                  +
                  #i-wenjianjia
                  +
                • + +
                • + +
                  声音
                  +
                  #i-webtubiaoku08
                  +
                • + +
                • + +
                  数据库
                  +
                  #i-database
                  +
                • + +
                • + +
                  插件 (1)
                  +
                  #i-chajian1
                  +
                • + +
                • + +
                  菜单
                  +
                  #i-caidan
                  +
                • + +
                • + +
                  网络
                  +
                  #i-wangluo
                  +
                • + +
                • + +
                  打印
                  +
                  #i-dayin
                  +
                • + +
                • + +
                  用户
                  +
                  #i-user
                  +
                • + +
                • + +
                  开始
                  +
                  #i-kaishi
                  +
                • + +
                • + +
                  合并
                  +
                  #i-hebing
                  +
                • + +
                • + +
                  聊天
                  +
                  #i-liaotian
                  +
                • + +
                • + +
                  定时
                  +
                  #i-dingshi
                  +
                • + +
                • + +
                  斜箭头
                  +
                  #i-xiejiantou
                  +
                • + +
                • + +
                  配置
                  +
                  #i-peizhi
                  +
                • + +
                • + +
                  项目组合
                  +
                  #i-xiangmuzuhe
                  +
                • + +
                • + +
                  系统参数配置
                  +
                  #i-xitongcanshupeizhi
                  +
                • + +
                • + +
                  区块
                  +
                  #i-qukuai
                  +
                • + +
                • + +
                  分支
                  +
                  #i-fenzhi
                  +
                • + +
                • + +
                  01
                  +
                  #i-icon-test
                  +
                • + +
                • + +
                  02
                  +
                  #i-icon-test1
                  +
                • + +
                • + +
                  小虚线
                  +
                  #i-xiaoxuxian
                  +
                • + +
                • + +
                  检查工具 直线
                  +
                  #i-jianchagongjuzhixian
                  +
                • + +
                + + +

                symbol引用

                +
                + +

                这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章 + 这种用法其实是做了一个svg的集合,与另外两种相比具有如下特点:

                +
                  +
                • 支持多色图标了,不再受单色限制。
                • +
                • 通过一些技巧,支持像字体那样,通过font-size,color来调整样式。
                • +
                • 兼容性较差,支持 ie9+,及现代浏览器。
                • +
                • 浏览器渲染svg的性能一般,还不如png。
                • +
                +

                使用步骤如下:

                +

                第一步:引入项目下面生成的symbol代码:

                +
                <script src="./iconfont.js"></script>
                +

                第二步:加入通用css代码(引入一次就行):

                +
                <style type="text/css">
                +.icon {
                +   width: 1em; height: 1em;
                +   vertical-align: -0.15em;
                +   fill: currentColor;
                +   overflow: hidden;
                +}
                +</style>
                +

                第三步:挑选相应图标并获取类名,应用于页面:

                +
                <svg class="icon" aria-hidden="true">
                +  <use xlink:href="#i-xxx"></use>
                +</svg>
                +        
                +
                + + diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/demo_unicode.html b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/demo_unicode.html new file mode 100644 index 0000000..5defb75 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/demo_unicode.html @@ -0,0 +1,294 @@ + + + + + + IconFont + + + + + +
                +

                IconFont 图标

                +
                  + +
                • + +
                  指针
                  +
                  &#xe602;
                  +
                • + +
                • + +
                  关闭
                  +
                  &#xe674;
                  +
                • + +
                • + +
                  close
                  +
                  &#xe61a;
                  +
                • + +
                • + +
                  文件添加
                  +
                  &#xe659;
                  +
                • + +
                • + +
                  tag
                  +
                  &#xe6f9;
                  +
                • + +
                • + +
                  conow-redo
                  +
                  &#xe672;
                  +
                • + +
                • + +
                  conow-revoke
                  +
                  &#xe673;
                  +
                • + +
                • + +
                  保存
                  +
                  &#xe63d;
                  +
                • + +
                • + +
                  Refresh
                  +
                  &#xe607;
                  +
                • + +
                • + +
                  右下-实心
                  +
                  &#xe6b7;
                  +
                • + +
                • + +
                  拍照按钮
                  +
                  &#xe6bd;
                  +
                • + +
                • + +
                  徽章
                  +
                  &#xe611;
                  +
                • + +
                • + +
                  hr工作台
                  +
                  &#xe600;
                  +
                • + +
                • + +
                  停止
                  +
                  &#xe609;
                  +
                • + +
                • + +
                  文件夹
                  +
                  &#xe7a0;
                  +
                • + +
                • + +
                  声音
                  +
                  &#xe643;
                  +
                • + +
                • + +
                  数据库
                  +
                  &#xe742;
                  +
                • + +
                • + +
                  插件 (1)
                  +
                  &#xe66c;
                  +
                • + +
                • + +
                  菜单
                  +
                  &#xe649;
                  +
                • + +
                • + +
                  网络
                  +
                  &#xe62b;
                  +
                • + +
                • + +
                  打印
                  +
                  &#xe671;
                  +
                • + +
                • + +
                  用户
                  +
                  &#xe6af;
                  +
                • + +
                • + +
                  开始
                  +
                  &#xe700;
                  +
                • + +
                • + +
                  合并
                  +
                  &#xe606;
                  +
                • + +
                • + +
                  聊天
                  +
                  &#xe61b;
                  +
                • + +
                • + +
                  定时
                  +
                  &#xe633;
                  +
                • + +
                • + +
                  斜箭头
                  +
                  &#xe605;
                  +
                • + +
                • + +
                  配置
                  +
                  &#xe678;
                  +
                • + +
                • + +
                  项目组合
                  +
                  &#xe872;
                  +
                • + +
                • + +
                  系统参数配置
                  +
                  &#xe68f;
                  +
                • + +
                • + +
                  区块
                  +
                  &#xe663;
                  +
                • + +
                • + +
                  分支
                  +
                  &#xe60c;
                  +
                • + +
                • + +
                  01
                  +
                  &#xe60d;
                  +
                • + +
                • + +
                  02
                  +
                  &#xe60e;
                  +
                • + +
                • + +
                  小虚线
                  +
                  &#xe675;
                  +
                • + +
                • + +
                  检查工具 直线
                  +
                  &#xe624;
                  +
                • + +
                +

                unicode引用

                +
                + +

                unicode是字体在网页端最原始的应用方式,特点是:

                +
                  +
                • 兼容性最好,支持ie6+,及所有现代浏览器。
                • +
                • 支持按字体的方式去动态调整图标大小,颜色等等。
                • +
                • 但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。
                • +
                +
                +

                注意:新版iconfont支持多色图标,这些多色图标在unicode模式下将不能使用,如果有需求建议使用symbol的引用方式

                +
                +

                unicode使用步骤如下:

                +

                第一步:拷贝项目下面生成的font-face

                +
                @font-face {
                +  font-family: 'iconfont';
                +  src: url('iconfont.eot');
                +  src: url('iconfont.eot?#iefix') format('embedded-opentype'),
                +  url('iconfont.woff') format('woff'),
                +  url('iconfont.ttf') format('truetype'),
                +  url('iconfont.svg#iconfont') format('svg');
                +}
                +
                +

                第二步:定义使用iconfont的样式

                +
                .iconfont{
                +  font-family:"iconfont" !important;
                +  font-size:16px;font-style:normal;
                +  -webkit-font-smoothing: antialiased;
                +  -webkit-text-stroke-width: 0.2px;
                +  -moz-osx-font-smoothing: grayscale;
                +}
                +
                +

                第三步:挑选相应图标并获取字体编码,应用于页面

                +
                <i class="iconfont">&#x33;</i>
                + +
                +

                "iconfont"是你项目下的font-family。可以通过编辑项目查看,默认是"iconfont"。

                +
                +
                + + + + diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconflow.eot b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconflow.eot new file mode 100644 index 0000000..2b15303 Binary files /dev/null and b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconflow.eot differ diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconflow.svg b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconflow.svg new file mode 100644 index 0000000..7291cb4 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconflow.svg @@ -0,0 +1,141 @@ + + + + + +Created by iconfont + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconflow.ttf b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconflow.ttf new file mode 100644 index 0000000..79d3600 Binary files /dev/null and b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconflow.ttf differ diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconflow.woff b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconflow.woff new file mode 100644 index 0000000..5514164 Binary files /dev/null and b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconflow.woff differ diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconfont.css b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconfont.css new file mode 100644 index 0000000..4c491d4 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconfont.css @@ -0,0 +1,89 @@ + +@font-face {font-family: "iconflow"; + src: url('iconflow.eot?t=1501167404138'); /* IE9*/ + src: url('iconflow.eot?t=1501167404138#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('iconflow.woff?t=1501167404138') format('woff'), /* chrome, firefox */ + url('iconflow.ttf?t=1501167404138') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ + url('iconflow.svg?t=1501167404138#iconflow') format('svg'); /* iOS 4.1- */ +} + +.iconflow { + font-family:"iconflow" !important; + font-size:16px; + font-style:normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.i-zhizhen1:before { content: "\e602"; } + +.i-msnui-close-fat:before { content: "\e674"; } + +.i-close:before { content: "\e61a"; } + +.i-wenjiantianjia:before { content: "\e659"; } + +.i-tag:before { content: "\e6f9"; } + +.i-conowredo:before { content: "\e672"; } + +.i-conowrevoke:before { content: "\e673"; } + +.i-baocun:before { content: "\e63d"; } + +.i-refresh:before { content: "\e607"; } + +.i-youxiashixin:before { content: "\e6b7"; } + +.i-paizhaoanniu:before { content: "\e6bd"; } + +.i-huizhang:before { content: "\e611"; } + +.i-hrgongzuotai:before { content: "\e600"; } + +.i-tingzhi-copy:before { content: "\e609"; } + +.i-wenjianjia:before { content: "\e7a0"; } + +.i-webtubiaoku08:before { content: "\e643"; } + +.i-database:before { content: "\e742"; } + +.i-chajian1:before { content: "\e66c"; } + +.i-caidan:before { content: "\e649"; } + +.i-wangluo:before { content: "\e62b"; } + +.i-dayin:before { content: "\e671"; } + +.i-user:before { content: "\e6af"; } + +.i-kaishi:before { content: "\e700"; } + +.i-hebing:before { content: "\e606"; } + +.i-liaotian:before { content: "\e61b"; } + +.i-dingshi:before { content: "\e633"; } + +.i-xiejiantou:before { content: "\e605"; } + +.i-peizhi:before { content: "\e678"; } + +.i-xiangmuzuhe:before { content: "\e872"; } + +.i-xitongcanshupeizhi:before { content: "\e68f"; } + +.i-qukuai:before { content: "\e663"; } + +.i-fenzhi:before { content: "\e60c"; } + +.i-icon-test:before { content: "\e60d"; } + +.i-icon-test1:before { content: "\e60e"; } + +.i-xiaoxuxian:before { content: "\e675"; } + +.i-jianchagongjuzhixian:before { content: "\e624"; } + diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconfont.js b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconfont.js new file mode 100644 index 0000000..51ffabf --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/flow/fonts/iconfont.js @@ -0,0 +1 @@ +(function(window){var svgSprite=""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+''+""+''+""+''+""+''+""+""+""+''+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+''+""+''+""+''+""+''+""+''+""+''+""+''+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+''+""+''+""+""+""+"";var script=function(){var scripts=document.getElementsByTagName("script");return scripts[scripts.length-1]}();var shouldInjectCss=script.getAttribute("data-injectcss");var ready=function(fn){if(document.addEventListener){if(~["complete","loaded","interactive"].indexOf(document.readyState)){setTimeout(fn,0)}else{var loadFn=function(){document.removeEventListener("DOMContentLoaded",loadFn,false);fn()};document.addEventListener("DOMContentLoaded",loadFn,false)}}else if(document.attachEvent){IEContentLoaded(window,fn)}function IEContentLoaded(w,fn){var d=w.document,done=false,init=function(){if(!done){done=true;fn()}};var polling=function(){try{d.documentElement.doScroll("left")}catch(e){setTimeout(polling,50);return}init()};polling();d.onreadystatechange=function(){if(d.readyState=="complete"){d.onreadystatechange=null;init()}}}};var before=function(el,target){target.parentNode.insertBefore(el,target)};var prepend=function(el,target){if(target.firstChild){before(el,target.firstChild)}else{target.appendChild(el)}};function appendSvg(){var div,svg;div=document.createElement("div");div.innerHTML=svgSprite;svgSprite=null;svg=div.getElementsByTagName("svg")[0];if(svg){svg.setAttribute("aria-hidden","true");svg.style.position="absolute";svg.style.width=0;svg.style.height=0;svg.style.overflow="hidden";prepend(svg,document.body)}}if(shouldInjectCss&&!window.__iconfont__svg__cssinject__){window.__iconfont__svg__cssinject__=true;try{document.write("")}catch(e){console&&console.log(e)}}ready(appendSvg)})(window) \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/img/wallbg.png b/WaterCloud.Web/wwwroot/js/lay-module/flow/img/wallbg.png new file mode 100644 index 0000000..ff63bc8 Binary files /dev/null and b/WaterCloud.Web/wwwroot/js/lay-module/flow/img/wallbg.png differ diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/img/waterflow_icon.png b/WaterCloud.Web/wwwroot/js/lay-module/flow/img/waterflow_icon.png new file mode 100644 index 0000000..3c9742d Binary files /dev/null and b/WaterCloud.Web/wwwroot/js/lay-module/flow/img/waterflow_icon.png differ diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/waterflow.export.js b/WaterCloud.Web/wwwroot/js/lay-module/flow/waterflow.export.js new file mode 100644 index 0000000..4f0bcca --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/flow/waterflow.export.js @@ -0,0 +1,427 @@ +/* + * 导出流程图文件并下载的扩展包方法 + */ +;(function ( global, factory ) { + 'use strict'; + if ( typeof define !== 'undefined' && define.amd ) { // export as AMD... + define( ['jquery','WaterFlow'], factory ); + } + else if ( typeof module !== 'undefined' && module.exports ) { // ...or as browserify + factory( require('jquery'), require('WaterFlow') ); + }else + factory( global.$, global.WaterFlow ); + +}( typeof window !== 'undefined' ? window : this, function ( $,WaterFlow ) { + if(WaterFlow.prototype.exportDiagram && typeof WaterFlow.prototype.exportDiagram==='function'){ + return;//防止多次载入 + } + var Cmder = { + //构建背景 + initBg : function(width,height,bgColor){ + var canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + var ctx = canvas.getContext('2d'); + if(bgColor) ctx.fillStyle = bgColor; + ctx.fillRect(0,0,canvas.width,canvas.height); + ctx.save(); + return canvas; + }, + _toNum: function(str){ + return str!==null&&str!==''? parseInt(str.split('px')[0],10):undefined; + }, + _analyseLabel: function(labelDom){ + var tagName = labelDom[0].tagName; + var offsetLeft = labelDom[0].offsetLeft; + var offsetTop = labelDom[0].offsetTop; + if(tagName==='TD'){ + offsetLeft += labelDom.children("div")[0].offsetLeft; + offsetTop += labelDom.children("div")[0].offsetTop; + } + + var lineHeight = this._toNum(labelDom.css("line-height")); + var fontSize = labelDom.css('font-size'); + return { + font: fontSize+' '+labelDom.css('font-family'), + fontSize: this._toNum(fontSize.split("px")[0]), + text: labelDom.text(),//文字内容 + color: labelDom.css('color'),//文字颜色 + width: labelDom[0].offsetWidth,//文字容器宽度 + height: labelDom[0].offsetHeight,//文字容器高度 + lineHeight:lineHeight, + offsetLeft:offsetLeft, + offsetTop:offsetTop, + lineNum: Math.ceil(labelDom[0].offsetHeight/lineHeight)//文字要分几行? + }; + }, + _analyseIcon: function(iconDom){ + var bgImg = iconDom.css("background-image"); + var property={ + // top: this._toNum(iconDom[0].style.top),// + // left: this._toNum(iconDom[0].style.left),// + offsetLeft:iconDom[0].offsetLeft, + offsetTop:iconDom[0].offsetTop, + width: iconDom.width(), + height: iconDom.height() + }; + + if(bgImg && bgImg!=='none'){//CSS SPITE背景图式 + bgImg = bgImg.replace(/"/g,"").split("url(")[1]; + property.backgroundImage=bgImg.substr(0,bgImg.length-1);//图标背景图 + bgImg = iconDom.css("background-position").split(" "); + property.pX = parseFloat(bgImg[0].split("px")[0])*-1;//图标背景定位X + property.pY = parseFloat(bgImg[1].split("px")[0])*-1;//图标背景定位Y + }else{//矢量图标字体式 + $.extend(property,{ + font: iconDom.css('font-size')+' '+iconDom.css('font-family').split(' ')[0],//图标矢量字体库 + lineHeight : this._toNum(iconDom.css('line-height')),//图标矢量字体行高 + color: iconDom.css('color'),//图标矢量字体颜色 + opacity: parseFloat(iconDom.css("opacity")),//图标矢量透明度 + content:window.getComputedStyle(iconDom[0],'::before').getPropertyValue('content') + }); + } + + return property; + }, + _analyseArea : function(areaDom){ + var bg=areaDom.children(".bg"); + return { + top: this._toNum(areaDom[0].style.top), + left: this._toNum(areaDom[0].style.left), + width: areaDom.outerWidth(), + height: areaDom.outerHeight(), + borderColor: bg.css('border-top-color'),//区域边框颜色 + bgColor: bg.css('background-color'),//区域块背景色 + opacity: parseFloat(bg.css("opacity")),//区域块透明度 + icon: this._analyseIcon(areaDom.children('i')), + label: this._analyseLabel(areaDom.children("label")) + }; + }, + _analyseNode : function(nodeDom){ + var property={ + top: this._toNum(nodeDom[0].style.top),// + left: this._toNum(nodeDom[0].style.left),// + width: nodeDom.outerWidth(),// + height: nodeDom.outerHeight(),// + borderColor: nodeDom.css('border-top-color'),//节点边框颜色 + borderWidth: this._toNum(nodeDom.css('border-top-width')),//节点边框宽度 + bgColor: nodeDom.css('background-color'),//节点背景色 + borderRadius: this._toNum(nodeDom.css("border-top-left-radius")),//节点圆角半径 + boxShadow: nodeDom.css("box-shadow"),//节点阴影 + icon: this._analyseIcon(nodeDom.find('i')) + }; + if(nodeDom.hasClass("item_round")){ + property.label = this._analyseLabel(nodeDom.children(".span")); + }else{ + property.label = this._analyseLabel(nodeDom.children("table").find("td:eq(1)")); + } + return property; + }, + _fillIcon:function(canvas, bgLeft,bgTop,icon, bgImage){ + var ctx = canvas.getContext('2d'); + if(icon.backgroundImage===undefined){//矢量字体图标 + if(icon.content.indexOf('"')===0){ + icon.content = icon.content.split('"')[1]; + } + icon.color = icon.color.replace('rgb', 'rgba').replace(')', ', ' + icon.opacity + ')'); + ctx.fillStyle = icon.color; + ctx.font = icon.font; + ctx.textAlign='center'; + ctx.textBaseline='middle'; + // 绘制内容 + ctx.fillText(icon.content, bgLeft+icon.offsetLeft+4+icon.width/2, bgTop+icon.offsetTop+4+icon.height/2); + return null; + }else{//css spite背景定位图标 + var tmpX=0,tmpY=0; + if(icon.pX<0){ + tmpX-=icon.pX; icon.pX=0; + } + if(icon.pY<0){ + tmpY-=icon.pY; icon.pY=0; + } + //console.log(icon.pX+','+icon.pY); + ctx.drawImage(bgImage, icon.pX, icon.pY, icon.width, icon.height, + bgLeft+icon.offsetLeft+4+tmpX, bgTop+icon.offsetTop+4+tmpY, icon.width, icon.height ); + } + }, + _fillLabel: function(canvas, bgLeft, bgTop, label) { + var ctx = canvas.getContext('2d'); + ctx.fillStyle = label.color; + ctx.textAlign='center'; + ctx.font = label.font; + ctx.textBaseline='top'; + + var str=label.text; + var lineWidth = 0;//某一行字的实际宽度 + var lastSubStrIndex= 0; //每次开始截取的字符串的索引 + var hack = (window.ActiveXObject || "ActiveXObject" in window)? 1:0; + var x = bgLeft+label.offsetLeft+label.width/2+hack/2;//文字(可能有多行)的x坐标 + var y = bgTop+label.offsetTop+hack;//某一行文字(可能有多行)的y坐标 + if(navigator.userAgent.indexOf('Firefox')>=0){ + y += (label.lineHeight-label.fontSize); + } + for(var i=0;i= label.width ){ + ctx.fillText(str.substring(lastSubStrIndex,i),x,y);//绘制截取部分 + y+=label.lineHeight; + lineWidth=0; + lastSubStrIndex=i; + } + }else{//绘制剩余部分 + ctx.fillText(str.substring(lastSubStrIndex,i+1),x,y); + } + } + }, + //根据区域组信息在背景上画一堆区域组泳道(传参areas为要绘制的区域组详细json信息) + renderAreas:function(canvas,areas, iconBgImage){ + var ctx = canvas.getContext('2d'); + for(var key in areas) { + var area = areas[key]; + //填充半透明矩形 + area.bgColor = area.bgColor.replace('rgb', 'rgba').replace(')', ', ' + area.opacity + ')'); + area.borderColor = area.borderColor.replace('rgb', 'rgba').replace(')', ', ' + area.opacity + ')'); + ctx.fillStyle = area.bgColor; + ctx.strokeStyle = area.borderColor; + ctx.rect(area.left, area.top, area.width, area.height); + ctx.fill(); + ctx.stroke(); + this._fillIcon(canvas, area.left-3, area.top-3, area.icon, iconBgImage); + this._fillLabel(canvas, area.left, area.top, area.label); + } + }, + + //根据节点信息在背景上画一组节点(传参nodes为要绘制的节点详细json信息) + renderNodes:function(canvas,nodes,iconBgImage){ + var ctx = canvas.getContext('2d'); + var imgLoadFuncs=[]; + for(var key in nodes){ + var node = nodes[key]; + //渲染阴影 + var sd = node.boxShadow.split(") "); + if(sd.length===1){ + var tmp = node.boxShadow.split("rgba"); + sd[0]='rgba'+tmp[1]; + sd[1]=tmp[0]; + } + ctx.shadowColor = sd[0]; + sd=sd[1].split(" "); + ctx.shadowOffsetX=this._toNum(sd[0])+(node.borderWidth>1? 1:0); + ctx.shadowOffsetY=this._toNum(sd[1])+(node.borderWidth>1? 1:0); + ctx.shadowBlur=this._toNum(sd[2]); + //填充圆角矩形 + ctx.fillStyle=node.bgColor; + ctx.roundRect( node.left+node.borderWidth/2, node.top+node.borderWidth/2, + node.width-node.borderWidth, node.height-node.borderWidth, node.borderRadius).fill(); + //加边框 + ctx.shadowBlur=0; + ctx.shadowColor=''; + ctx.shadowOffsetX=0; + ctx.shadowOffsetY=0; + ctx.strokeStyle = node.borderColor; + ctx.lineWidth = (node.borderWidth===0? 0.01:node.borderWidth); + ctx.stroke(); + this._fillIcon(canvas, node.left, node.top+(node.borderRadius>6? 1:0), node.icon, iconBgImage); + this._fillLabel(canvas, node.left, node.top, node.label); + } + return imgLoadFuncs; + }, + + _analyseLine:function(lineDom){ //only for IE + var fontFamily = $(".WaterFlow").css("font-family"); + //基本样式 + var path = lineDom.childNodes[1]; + var property={ + color: path.getAttribute("stroke"),//箭头则用fill + lineWidth: path.getAttribute("stroke-width"),//线条宽度箭头的strokeWidth为0 + lineCap: 'round' + }; + var style = path.style.strokeDasharray; + property.lineDash=(style && style!=null); + //文字 + var text=lineDom.childNodes[2]; + var fontColor = text.getAttribute("fill"); + if(!fontColor||fontColor===null||fontColor===''){ + fontColor='#777'; + } + property.label={ + text: text.textContent, + font: text.style.fontSize+' '+fontFamily, + color: fontColor, + left:text.getAttribute("x"), + top:text.getAttribute("y") + }; + + //获取连线从首至尾各个点的坐标值 + var d = path.getAttribute("d"); + var tmp = d.substring(2,d.length).split("L"); + var points=[];//连线中各点集合 + for(var i=0;i-1){//当为IE11及以下版本浏览器时,使用Canvg第三方工具 + var lineEl={}; + for(var key in Goo.$lineDom){ + lineEl[key]=Cmder._analyseLine(Goo.$lineDom[key]); + } + //console.log(lineEl); + Cmder.renderLines(canvas,lineEl); + try{ + var blob = canvas.msToBlob(); + navigator.msSaveBlob(blob, fileName+".png"); + } + catch(e){ + //生成一个下载链接并点击 + var base64 = canvas.toDataURL('image/png'); //将画布内的信息导出为png图片数据 + $('body').append(''); + var oPop=window.open("",'_blank'); + for (; oPop.document.readyState !== "complete";) { + if (oPop.document.readyState === "complete") break; + } + oPop.document.write(''+fileName+'.png'); + } + }else{ + var strSvg = '' + +'' + $("#draw_"+Goo.$id).html() +''; //COPY连线内容 + var image = new Image(); + image.src='data:image/svg+xml,'+ encodeURIComponent(strSvg); + image.onload=function(){ + ctx.drawImage(image, 0, 0); + var a = document.createElementNS("http://www.w3.org/1999/xhtml", "a"); + a.href = canvas.toDataURL('image/png'); //将画布内的信息导出为png图片数据 + a.download = fileName+".png"; //设定下载名称 + document.body.appendChild(a); + a.click(); //点击触发下载 + document.body.removeChild(a); + }; + } + }; + // 如果图片已经存在于浏览器缓存,直接调用回调函数 + if(!iconImage || iconImage.complete|| (!!window.ActiveXObject||"ActiveXObject" in window) ) { + tempFunc(); + return;// 直接返回,不用再处理onload事件 + } + iconImage.onload=function(){ + tempFunc(); + }; + + } +})); \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/waterflow.js b/WaterCloud.Web/wwwroot/js/lay-module/flow/waterflow.js new file mode 100644 index 0000000..38dcf29 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/flow/waterflow.js @@ -0,0 +1,2538 @@ +/** + * WaterFlow流程图设计器 + */ + +layui.define("jquery", + function(exports) { + + var jQuery = layui.jquery; + var $ = layui.jquery; + + //预先定义几个公用方法 + //获取一个DIV的绝对坐标的功能函数,即使是非绝对定位,一样能获取到 + function _elCsys(dom) { + var t = dom.offsetTop; + var l = dom.offsetLeft; + dom=dom.offsetParent; + while (dom) { + t += dom.offsetTop; + l += dom.offsetLeft; + dom=dom.offsetParent; + } + return { top: t, left: l }; + } + //兼容各种浏览器的,获取鼠标真实位置 + function _mouseP(ev){ + if(!ev) ev=window.event; + if(ev.pageX || ev.pageY){ + return {x:ev.pageX, y:ev.pageY}; + } + return { + x:ev.clientX + document.documentElement.scrollLeft - document.body.clientLeft, + y:ev.clientY + document.documentElement.scrollTop - document.body.clientTop + }; + } + //计算两个节点间要连折线的话,连线的所有坐标 + function calcPolyPoints(n1,n2,type,M,scale){ + if(!scale) scale=1.0; + var N1={left:n1.left*scale, top:n1.top*scale, width:n1.width*scale, height:n1.height*scale}; + var N2={left:n2.left*scale, top:n2.top*scale, width:n2.width*scale, height:n2.height*scale}; + M=M*scale; + //开始/结束两个节点的中心 + var SP={x:N1.left+N1.width/2,y:N1.top+N1.height/2}; + var EP={x:N2.left+N2.width/2,y:N2.top+N2.height/2}; + var m1=[],m2=[],sp,ep; + //如果是允许中段可左右移动的折线,则参数M为可移动中段线的X坐标 + //粗略计算起始点 + sp=[SP.x,SP.y]; + ep=[EP.x,EP.y]; + if(type==="lr"){ + //粗略计算2个中点 + m1=[M,SP.y]; + m2=[M,EP.y]; + //再具体分析修改开始点和中点1 + if(m1[0]>N1.left&&m1[0]EP.y? N1.top:N1.top+N1.height); + sp[0]=m1[0];sp[1]=m1[1]; + } + else{ + sp[0]=(m1[0]N2.left&&m2[0]EP.y? N2.top+N2.height:N2.top); + ep[0]=m2[0];ep[1]=m2[1]; + } + else{ + ep[0]=(m2[0]N1.top&&m1[1]EP.x? N1.left:N1.left+N1.width); + sp[0]=m1[0];sp[1]=m1[1]; + } + else{ + sp[1]=(m1[1]N2.top&&m2[1]EP.x? N2.left+N2.width:N2.left); + ep[0]=m2[0];ep[1]=m2[1]; + } + else{ + ep[1]=(m2[1]=x22){ + X_1=x11;X_2=x22; + } + //节点2在节点1右边 + else if(x12<=x21){ + X_1=x12;X_2=x21; + } + //节点2在节点1水平部分重合 + else if(x11<=x21&&x12>=x21&&x12<=x22){ + X_1=(x12+x21)/2;X_2=X_1; + } + else if(x11>=x21&&x12<=x22){ + X_1=(x11+x12)/2;X_2=X_1; + } + else if(x21>=x11&&x22<=x12){ + X_1=(x21+x22)/2;X_2=X_1; + } + else if(x11<=x22&&x12>=x22){ + X_1=(x11+x22)/2;X_2=X_1; + } + + //Y判断: + var y11=n1.top*scale ,y12=n1.top*scale +n1.height*scale ,y21=n2.top*scale ,y22=n2.top*scale +n2.height*scale ; + //节点2在节点1上边 + if(y11>=y22){ + Y_1=y11;Y_2=y22; + } + //节点2在节点1下边 + else if(y12<=y21){ + Y_1=y12;Y_2=y21; + } + //节点2在节点1垂直部分重合 + else if(y11<=y21&&y12>=y21&&y12<=y22){ + Y_1=(y12+y21)/2;Y_2=Y_1; + } + else if(y11>=y21&&y12<=y22){ + Y_1=(y11+y12)/2;Y_2=Y_1; + } + else if(y21>=y11&&y22<=y12){ + Y_1=(y21+y22)/2;Y_2=Y_1; + } + else if(y11<=y22&&y12>=y22){ + Y_1=(y11+y22)/2;Y_2=Y_1; + } + return {"start":[X_1,Y_1],"end":[X_2,Y_2]}; + } + //初始化折线中段的X/Y坐标,mType='rb'时为X坐标,mType='tb'时为Y坐标 + function getMValue(n1,n2,mType,scale){ + if(!scale) scale=1.0; + if(mType==="lr"){ + return (n1.left*scale + n1.width*scale/2 + n2.left*scale + n2.width*scale/2 )/2; + } + else if(mType==="tb"){ + return (n1.top*scale + n1.height*scale/2 + n2.top*scale + n2.height*scale/2 )/2; + } + } +//构造类: +var WaterFlow = function(selector,property){ + console.log('Your browser\'s navigator.userAgent is:',navigator.userAgent); + if (navigator.userAgent.indexOf("MSIE 8.0")>0||navigator.userAgent.indexOf("MSIE 7.0")>0||navigator.userAgent.indexOf("MSIE 6.0")>0) + WaterFlow.prototype.useSVG=""; + else WaterFlow.prototype.useSVG="1"; +//初始化区域图的对象 + this.$bgDiv=$(selector);//最父框架的DIV + this.$bgDiv.addClass("WaterFlow"); + this.$id=this.$bgDiv.attr("id")||'WaterFlow_'+new Date().getTime(); + if(property.colors && typeof property.colors ==='object'){ + $.extend(WaterFlow.color, property.colors); + } + this.$bgDiv.css("color",WaterFlow.color.font); + if(WaterFlow.color.main){ + this.$bgDiv.append(''); + } + var width=(property.width||this.$bgDiv.width()); + var height=(property.height||this.$bgDiv.height()); + this.$bgDiv.css({width:width+"px",height:height+"px"}); + this.$tool=null;//左侧工具栏对象 + this.$head=null;//顶部标签及工具栏按钮 + this.$title="newFlow_1";//流程图的名称 + this.$nowType="cursor";//当前要绘制的对象类型 + this.$lineData={}; + this.$lineCount=0; + this.$nodeData={}; + this.$nodeCount=0; + this.$areaData={}; + this.$areaCount=0; + this.$lineDom={}; + this.$nodeDom={}; + this.$areaDom={}; + this.$max=property.initNum||1;//计算默认ID值的起始SEQUENCE + this.$focus="";//当前被选定的节点/转换线ID,如果没选中或者工作区被清空,则为"" + //this.$cursor="default";//鼠标指针在工作区内的样式 + this.$editable=false;//工作区是否可编辑 + this.$deletedItem={};//在流程图的编辑操作中被删除掉的元素ID集合,元素ID为KEY,元素类型(node,line.area)为VALUE + this.$workExtendStep=200;//在自动/手动扩展可编辑区时,一次扩展后宽/高增加多少像素 + this.$scale=1.00;//工作区内容的缩放比例,从0.1至无穷大,初始默认为1 + var headHeight=0; + var tmp="",titleText; + if(property.haveHead){ + tmp="
                "; + if(property.headLabel){ + tmp+=""; + } + if(property.headBtns) + for(var x=0;x" + } + tmp+="
                "; + this.$head=$(tmp); + this.$bgDiv.append(this.$head); + if(property.headBtns){ + this.$head.find(".ico_undo").parent().addClass("a_disabled"); + this.$head.find(".ico_redo").parent().addClass("a_disabled"); + //以下是当工具栏按钮被点击时触发的事件自定义(虚函数),格式为function(),因为可直接用THIS操作对象本身,不用传参;用户可自行重定义: + this.onBtnNewClick=null;//新建流程图按钮被点中 + this.onBtnOpenClick=null;//打开流程图按钮定义 + this.onBtnSaveClick=null;//保存流程图按钮定义 + this.onFreshClick=null;//重载流程图按钮定义 + this.onPrintClick=null;//打印流程图按钮定义 + this.$headBtnEvents=property.headBtnEvents;//用户对头部栏另行自定义类型按钮的事件绑定json集合,key为按钮类型名,value为方法定义 + this.$head.on("click",{inthis:this},function(e){ + if(!e)e=window.event; + var tar=e.target; + if(tar.tagName==="DIV"||tar.tagName==="SPAN") return; + else if(tar.tagName==="A") tar=tar.childNodes[0]; + var This=e.data.inthis, Class=$(tar).attr("class"); + //定义顶部操作栏按钮的事件 + switch(Class){ + case "ico_new": if(This.onBtnNewClick!==null) This.onBtnNewClick();break; + case "ico_open": if(This.onBtnOpenClick!==null) This.onBtnOpenClick();break; + case "ico_save": if(This.onBtnSaveClick!==null) This.onBtnSaveClick();break; + case "ico_undo": This.undo();break; + case "ico_redo": This.redo();break; + case "ico_reload": if(This.onFreshClick!==null) This.onFreshClick();break; + case "ico_print": if(This.onPrintClick!==null) This.onPrintClick();break; + default: + if(typeof This.$headBtnEvents!=='undefined' && typeof This.$headBtnEvents[Class]==='function'){ + This.$headBtnEvents[Class](); + } + } + }); + } + headHeight=28; + } + var toolWidth=0; + if(property.haveTool){ + this.$bgDiv.append("
                "); + this.$tool=this.$bgDiv.find(".WaterFlow_tool div"); + //未加代码:加入绘图工具按钮 + var titleCursor=WaterFlow.remarks.toolBtns["cursor"]? " title='"+WaterFlow.remarks.toolBtns["cursor"]+"'":""; + var titleDirect=WaterFlow.remarks.toolBtns["direct"]? " title='"+WaterFlow.remarks.toolBtns["direct"]+"'":""; + var titleDashed=WaterFlow.remarks.toolBtns["dashed"]? " title='"+WaterFlow.remarks.toolBtns["dashed"]+"'":""; + this.$tool.append("
                " + +"" + +"" + +(property.haveDashed? "":"") + ); + if(property.toolBtns&&property.toolBtns.length>0){ + tmp=""; + for(var i=0;i";//加入自定义按钮 + } + this.$tool.append(tmp); + } + //加入区域划分框工具开关按钮 + if(property.haveGroup){ + var titleGroup=WaterFlow.remarks.toolBtns["group"]? " title='"+WaterFlow.remarks.toolBtns["group"]+"'":""; + this.$tool.append(""); + } + toolWidth=31; + this.$nowType="cursor"; + //绑定各个按钮的点击事件 + this.$tool.on("click",{inthis:this},function(e){ + if(!e)e=window.event; + var tar; + switch(e.target.tagName){ + case "SPAN":return false; + case "DIV":return false; + case "I": tar=e.target.parentNode;break; + case "A": tar=e.target; + } + var type=$(tar).attr("type"); + e.data.inthis.switchToolBtn(type); + return false; + }); + this.$editable=true;//只有具有工具栏时可编辑 + } + + //确定工作区在设计器中的位置、宽高 + width=width-toolWidth-9; + height=height-headHeight-(property.haveHead? 5:8); + this.$bgDiv.append("
                "); + this.$workArea=$("
                ") + .attr({"unselectable":"on","onselectstart":'return false',"onselect":'document.selection.empty()'}); + this.$bgDiv.children(".WaterFlow_work").append(this.$workArea); + //计算工作区相对WaterFlow父框架的绝对定位运算值,并保存 + this.t={top:property.haveHead? 28:3,left:property.haveTool?34:3}; + + //绑定工作区事件 + this.$workArea.on("click",{inthis:this},function(e){ + if(!e)e=window.event; + var This=e.data.inthis; + var type=This.$nowType; + if(type==="cursor"){ + var tar=$(e.target); + var n=tar.prop("tagName"); + if(n==="svg"||(n==="DIV"&&tar.prop("class").indexOf("WaterFlow_work")>-1)||n==="LABEL"){ + console.log(n); + if(This.$lineOper && This.$lineOper.data("tid")){ + This.focusItem(This.$lineOper.data("tid"),false); + } + else{This.blurItem();} + } + return; + } + else if(type==="direct"||type==="dashed"||type==="group")return; + if(!This.$editable)return; + var X,Y; + var ev=_mouseP(e),t=_elCsys(this); + X=ev.x-t.left+this.parentNode.scrollLeft; + Y=ev.y-t.top+this.parentNode.scrollTop; + if (This.$nowType.indexOf("start")>-1) { + This.addNode(new Date().getTime().toString(), { name: "开始_" + This.$max, left: X, top: Y, type: This.$nowType }); + } + else if (This.$nowType.indexOf("end") > -1) { + This.addNode(new Date().getTime().toString(), { name: "结束_" + This.$max, left: X, top: Y, type: This.$nowType }); + } + else if (This.$nowType.indexOf("fork") > -1) { + This.addNode(new Date().getTime().toString(), { name: "会签开始_" + This.$max, left: X, top: Y, type: This.$nowType }); + } + else if (This.$nowType.indexOf("join") > -1) { + This.addNode(new Date().getTime().toString(), { name: "会签结束_" + This.$max, left: X, top: Y, type: This.$nowType }); + } + else { + This.addNode(new Date().getTime().toString(), { name: "任务节点_" + This.$max, left: X, top: Y, type: This.$nowType }); + } + This.$max++; + }); + + this.$draw=null;//画矢量线条的容器 + this._initDraw("draw_"+this.$id,width,height); + this.$group=null;//画区域块(泳道)的容器 + if(property.haveGroup) + this._initGroup(width,height); + //为了节点而增加的一些集体绑定 + this._initWorkForNode(); + + //一些基本的元素事件,这些事件可直接通过this访问对象本身 + //当操作某个单元(节点/线)被由不选中变成选中时,触发的方法,返回FALSE可阻止选中事件的发生 + //格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line"两种取值,"area"不支持被选中 + this.onItemFocus=null; + //当操作某个单元(节点/线)被由选中变成不选中时,触发的方法,返回FALSE可阻止取消选中事件的发生 + //格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line"两种取值,"area"不支持被取消选中 + this.onItemBlur=null; + //当用重色标注某个节点/转换线时触发的方法,返回FALSE可阻止重定大小/造型事件的发生 + //格式function(id,type,mark):id是单元的唯一标识ID,type是单元类型("node"节点,"line"转换线),mark为布尔值,表示是要标注TRUE还是取消标注FALSE + this.onItemMark=null; + //当操作某个单元(节点/线/区域块)被双击时,触发的方法,返回FALSE可阻止取消原来双击事件(双击后直接编辑)的发生 + //格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值 + this.onItemDbClick=null; + //当操作某个单元(节点/线/区域块)被右键点击时,触发的方法,返回FALSE可阻止取消原来右击事件(一般是浏览器默认的右键菜单)的发生 + //格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值 + this.onItemRightClick=null; + + if(this.$editable){ + //绑定当节点/线/分组块的一些操作事件,这些事件可直接通过this访问对象本身 + //当操作某个单元(节点/线/分组块)被添加时,触发的方法,返回FALSE可阻止添加事件的发生 + //格式function(id,type,json):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值,json即addNode,addLine或addArea方法的第二个传参json. + this.onItemAdd=null; + //当操作某个单元(节点/线/分组块)被删除时,触发的方法,返回FALSE可阻止删除事件的发生 + //格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值 + this.onItemDel=null; + //当操作某个单元(节点/分组块)被移动时,触发的方法,返回FALSE可阻止移动事件的发生 + //格式function(id,type,left,top):id是单元的唯一标识ID,type是单元的种类,有"node","area"两种取值,线line不支持移动,left是新的左边距坐标,top是新的顶边距坐标 + this.onItemMove=null; + //当操作某个单元(节点/线/分组块)被重命名时,触发的方法,返回FALSE可阻止重命名事件的发生 + //格式function(id,name,type):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值,name是新的名称 + this.onItemRename=null; + //当操作某个单元(节点/分组块)被重定义大小或造型时,触发的方法,返回FALSE可阻止重定大小/造型事件的发生 + //格式function(id,type,width,height):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值;width是新的宽度,height是新的高度 + this.onItemResize=null; + //当移动某条折线中段的位置,触发的方法,返回FALSE可阻止重定大小/造型事件的发生 + //格式function(id,M):id是单元的唯一标识ID,M是中段的新X(或Y)的坐标 + this.onLineMove=null; + //当变换某条连接线的类型,触发的方法,返回FALSE可阻止重定大小/造型事件的发生 + //格式function(id,type):id是单元的唯一标识ID,type是连接线的新类型,"sl":直线,"lr":中段可左右移动的折线,"tb":中段可上下移动的折线 + this.onLineSetType=null; + //当变换某条连接线的端点变更连接的节点时,触发的方法,返回FALSE可阻止重定大小/造型事件的发生 + //格式function(id,newStart,newEnd):id是连线单元的唯一标识ID,newStart,newEnd分别是起始节点的ID和到达节点的ID + this.onLinePointMove=null; + this._initExpendFunc();//初始化手动扩展工作区宽高的功能 + //对节点、区域块进行移动或者RESIZE时用来显示的遮罩层 + this.$ghost=$("
                ").attr({"unselectable":"on","onselectstart":'return false',"onselect":'document.selection.empty()'}); + this.$bgDiv.append(this.$ghost); + this._initEditFunc(property.useOperStack); + } +}; + +WaterFlow.prototype={ + useSVG:"", //浏览器是否能用SVG? + _getSvgMarker:function(id,color){ + var m=document.createElementNS("http://www.w3.org/2000/svg","marker"); + m.setAttribute("id",id); + m.setAttribute("viewBox","0 0 6 6"); + m.setAttribute("refX",'5'); + m.setAttribute("refY",'3'); + m.setAttribute("markerUnits","strokeWidth"); + m.setAttribute("markerWidth",'6'); + m.setAttribute("markerHeight",'6'); + m.setAttribute("orient","auto"); + var path=document.createElementNS("http://www.w3.org/2000/svg","path"); + path.setAttribute("d","M 0 0 L 6 3 L 0 6 z"); + path.setAttribute("fill",color); + path.setAttribute("stroke-width",'0'); + m.appendChild(path); + return m; + }, + //初始化连线层 + _initDraw:function(id,width,height){ + if(WaterFlow.prototype.useSVG!==""){ + this.$draw=document.createElementNS("http://www.w3.org/2000/svg","svg");//可创建带有指定命名空间的元素节点 + this.$workArea.prepend(this.$draw); + var defs=document.createElementNS("http://www.w3.org/2000/svg","defs"); + this.$draw.appendChild(defs); + defs.appendChild(WaterFlow.prototype._getSvgMarker("arrow1",WaterFlow.color.line)); + defs.appendChild(WaterFlow.prototype._getSvgMarker("arrow2",WaterFlow.color.mark)); + defs.appendChild(WaterFlow.prototype._getSvgMarker("arrow3",WaterFlow.color.mark)); + } + else{ + this.$draw = document.createElement("v:group"); + this.$draw.coordsize = width+","+height; + this.$workArea.prepend("
                "); + this.$workArea.children("div")[0].insertBefore(this.$draw,null); + } + this.$draw.id = id; + this.$draw.style.width = width + "px"; + this.$draw.style.height = height + "px"; + + //绑定连线的点击选中以及双击编辑事件 + var tmpClk=null; + if(WaterFlow.prototype.useSVG!=="") tmpClk="g"; + else tmpClk="PolyLine"; + //绑定选中事件 + $(this.$draw).on("click",tmpClk,{inthis:this},function(e){ + e.data.inthis.focusItem(this.id,true); + }); + if(!this.$editable) return; + + //绑定右键事件 + $(this.$draw).on("contextmenu",tmpClk,{inthis:this},function(e){ + var This=e.data.inthis; + if(typeof This.onItemRightClick==='function' && This.onItemRightClick(this.id,"line")===false){ + window.event? window.event.returnValue=false : e.preventDefault(); + return false; + } + }); + $(this.$draw).on("dblclick",tmpClk,{inthis:this},function(e){ + var This=e.data.inthis; + if(typeof This.onItemDbClick==='function' && This.onItemDbClick(this.id,"line")===false) return; + var oldTxt,x,y,from,to; + if(WaterFlow.prototype.useSVG!==""){ + oldTxt=this.childNodes[2].textContent; + from=this.getAttribute("from").split(","); + to=this.getAttribute("to").split(","); + }else{ + oldTxt=this.childNodes[1].innerHTML; + var n=this.getAttribute("fromTo").split(","); + from=[n[0],n[1]]; + to=[n[2],n[3]]; + } + if(This.$lineData[this.id].type==="lr"){ + from[0]=This.$lineData[this.id].M*This.$scale; + to[0]=from[0]; + } + else if(This.$lineData[this.id].type==="tb"){ + from[1]=This.$lineData[this.id].M*This.$scale; + to[1]=from[1]; + } + x=(parseInt(from[0],10)+parseInt(to[0],10))/2-64; + y=(parseInt(from[1],10)+parseInt(to[1],10))/2-18; + var t=This.t;//t=_elCsys(This.$workArea[0]); + This.$textArea.val(oldTxt).css({display:"block",width:130,height:26, + left:t.left+x-This.$workArea[0].parentNode.scrollLeft, + top:t.top+y-This.$workArea[0].parentNode.scrollTop}).data("id",This.$focus).focus(); + This.$workArea.parent().one("mousedown",function(e){ + if(e.button===2)return false; + This.setName(This.$textArea.data("id"),This.$textArea.val(),"line"); + This.$textArea.val("").removeData("id").hide(); + }); + }); + }, + //初始化区域块(泳道)层 + _initGroup:function(width,height){ + this.$group=$("
                ");//存放背景区域的容器 + this.$workArea.prepend(this.$group); + if(!this.$editable) return; + + //绑定右键事件 + this.$group.on("contextmenu",".WaterFlow_area",{inthis:this},function(e){ + var This=e.data.inthis; + if(typeof This.onItemRightClick==='function' && This.onItemRightClick(this.id,"area")===false){ + window.event? window.event.returnValue=false : e.preventDefault(); + return false; + } + }); + //区域划分框操作区的事件绑定 + this.$group.on("mousedown",{inthis:this},function(e){//绑定RESIZE功能以及移动功能 + if(e.button===2)return false; + var This=e.data.inthis; + if(This.$nowType!=="group") return; + if(!e)e=window.event; + var cursor=$(e.target).css("cursor"); + var id=e.target.parentNode; + switch(cursor){ + case "nw-resize":id=id.parentNode;break; + case "w-resize":id=id.parentNode;break; + case "n-resize":id=id.parentNode;break; + case "move":break; + default:return; + } + id=id.id; + + var ev=_mouseP(e),t=This.t;//t=_elCsys(This.$workArea[0]); + + var X,Y,vX,vY; + X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft; + Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop; + if (cursor !== "move") { + This.$ghost.css({ + display: "block", + width: This.$areaData[id].width * This.$scale + "px", + height: This.$areaData[id].height * This.$scale + "px", + top: This.$areaData[id].top * This.$scale + t.top - This.$workArea[0].parentNode.scrollTop + "px", + left: This.$areaData[id].left * This.$scale + t.left - This.$workArea[0].parentNode.scrollLeft + "px", + cursor: cursor + }); + vX = (This.$areaData[id].left * This.$scale + This.$areaData[id].width * This.$scale) - X; + vY = (This.$areaData[id].top * This.$scale + This.$areaData[id].height * This.$scale) - Y; + } + else { + vX = X - This.$areaData[id].left * This.$scale; + vY = Y - This.$areaData[id].top * This.$scale; + } + var isMove=false; + This.$ghost.css("cursor",cursor); + document.onmousemove=function(e){ + if(!e)e=window.event; + var ev=_mouseP(e); + if(cursor!=="move"){ + X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft-This.$areaData[id].left*This.$scale+vX; + Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop-This.$areaData[id].top*This.$scale+vY; + if(X<200*This.$scale) X=200*This.$scale; + if(Y<100*This.$scale) Y=100*This.$scale; + switch(cursor){ + case "nw-resize":This.$ghost.css({width:X+"px",height:Y+"px"});break; + case "w-resize":This.$ghost.css({width:X+"px"});break; + case "n-resize":This.$ghost.css({height:Y+"px"});break; + } + } + else{ + if(This.$ghost.css("display")==="none"){ + This.$ghost.css({display:"block", + width:This.$areaData[id].width*This.$scale+"px", height:This.$areaData[id].height*This.$scale+"px", + top:This.$areaData[id].top*This.$scale+t.top-This.$workArea[0].parentNode.scrollTop+"px", + left:This.$areaData[id].left*This.$scale+t.left-This.$workArea[0].parentNode.scrollLeft+"px",cursor:cursor}); + } + X=ev.x-vX;Y=ev.y-vY; + if(Xt.left+This.$workArea.width()) + X=t.left+This.$workArea.width()-This.$workArea[0].parentNode.scrollLeft-This.$areaData[id].width*This.$scale; + if(Yt.top+This.$workArea.height()) + Y=t.top+This.$workArea.height()-This.$workArea[0].parentNode.scrollTop-This.$areaData[id].height*This.$scale; + This.$ghost.css({left:X+"px",top:Y+"px"}); + } + isMove=true; + }; + document.onmouseup=function(){ + This.$ghost.empty().hide(); + document.onmousemove=null; + document.onmouseup=null; + if(!isMove)return; + if(cursor!=="move") + This.resizeArea(id,This.$ghost.outerWidth()/This.$scale,This.$ghost.outerHeight()/This.$scale); + else + This.moveArea(id,(X+This.$workArea[0].parentNode.scrollLeft-t.left)/This.$scale, (Y+This.$workArea[0].parentNode.scrollTop-t.top)/This.$scale); + return false; + } + }); + //绑定修改文字说明功能 + this.$group.on("dblclick",{inthis:this},function(e){ + var This=e.data.inthis; + if(This.$nowType!=="group") return; + if(!e)e=window.event; + if(e.target.tagName!=="LABEL") return false; + var p=e.target.parentNode; + if(typeof This.onItemDbClick==='function' && This.onItemDbClick(p.id,"area")===false) return; + + var oldTxt=e.target.innerHTML; + var x=parseInt(p.style.left,10)+18,y=parseInt(p.style.top,10)+1; + var t=This.t;//t=_elCsys(This.$workArea[0]); + This.$textArea.val(oldTxt).css({display:"block",width:130,height:26, + left:t.left+x-This.$workArea[0].parentNode.scrollLeft, + top:t.top+y-This.$workArea[0].parentNode.scrollTop}).data("id",p.id).focus(); + This.$workArea.parent().one("mouseup",function(e){ + if(e.button===2)return false; + if(This.$textArea.css("display")==="block"){ + This.setName(This.$textArea.data("id"),This.$textArea.val(),"area"); + This.$textArea.val("").removeData("id").hide(); + } + return false; + }); + return false; + }); + //绑定点击事件 + this.$group.mouseup({inthis:this},function(e){ + var This=e.data.inthis; + if(This.$textArea.css("display")==="block"){ + This.setName(This.$textArea.data("id"),This.$textArea.val(),"area"); + This.$textArea.val("").removeData("id").hide(); + return false; + } + + if(This.$nowType!=="group") return; + if(!e)e=window.event; + switch($(e.target).attr("class")){ + case "rs_close": This.delArea(e.target.parentNode.parentNode.id);return false;//删除该分组区域 + case "bg": return; + } + switch(e.target.tagName){ + case "LABEL": return false; + case "I"://绑定变色功能 + var id=e.target.parentNode.id; + switch(This.$areaData[id].color){ + case "red": This.setAreaColor(id,"yellow");break; + case "yellow": This.setAreaColor(id,"blue");break; + case "blue": This.setAreaColor(id,"green");break; + case "green": This.setAreaColor(id,"red");break; + } + return false; + } + if(e.data.inthis.$ghost.css("display")==="none"){ + var X,Y; + var ev=_mouseP(e),t=_elCsys(this); + X=ev.x-t.left+this.parentNode.parentNode.scrollLeft; + Y=ev.y-t.top+this.parentNode.parentNode.scrollTop; + var color=["red","yellow","blue","green"]; + e.data.inthis.addArea(new Date().getTime(), + { name:"区域_"+e.data.inthis.$max,left:X/This.$scale,top:Y/This.$scale,color:color[e.data.inthis.$max%4],width:200,height:100} + ); + e.data.inthis.$max++; + return false; + } + }); + }, + //初始化节点绘制层 + _initWorkForNode:function(){ + //绑定点击事件 + this.$workArea.on("click",".WaterFlow_item",{inthis:this},function(e){ + e.data.inthis.focusItem(this.id,true); + $(this).removeClass("item_mark"); + }); + //绑定右键事件 + this.$workArea.on("contextmenu",".WaterFlow_item",{inthis:this},function(e){ + var This=e.data.inthis; + if(typeof This.onItemRightClick==='function' && This.onItemRightClick(this.id,"node")===false){ + window.event? window.event.returnValue=false : e.preventDefault(); + return false; + } + }); + + //绑定双击功能 + var tmpDbClickFunc=function(This){ + This.$workArea.parent().one("mousedown",function(e){ + if(e.button===2)return false; + This.setName(This.$textArea.data("id"),This.$textArea.val(),"node"); + This.$textArea.val("").removeData("id").hide(); + }); + }; + this.$workArea.on("dblclick",".ico",{inthis:this},function(e){ + var id=$(this).parents(".WaterFlow_item").attr("id"); + var This=e.data.inthis; + if(typeof This.onItemDbClick==='function' && This.onItemDbClick(id,"node")===false) return false; + }); + //绑定双击(包括双击编辑)事件 + this.$workArea.on("dblclick",".WaterFlow_item > .span",{inthis:this},function(e){ + var id=this.parentNode.id; + var This=e.data.inthis; + if(typeof This.onItemDbClick==='function' && This.onItemDbClick(id,"node")===false) return false; + if(!This.$editable) return; + var oldTxt=this.innerHTML; + var t=This.t;//t=_elCsys(This.$workArea[0]); + This.$textArea.val(oldTxt).css({display:"block",height:$(this).height()+6,width:100, + left:t.left+This.$nodeData[id].left*This.$scale-This.$workArea[0].parentNode.scrollLeft-26, + top:t.top+This.$nodeData[id].top*This.$scale-This.$workArea[0].parentNode.scrollTop+26}) + .data("id",This.$focus).focus(); + tmpDbClickFunc(This); + }); + this.$workArea.on("dblclick",".ico + td",{inthis:this},function(e){ + var id=$(this).parents(".WaterFlow_item").attr("id"); + var This=e.data.inthis; + if(typeof This.onItemDbClick==='function' && This.onItemDbClick(id,"node")===false) return false; + if(!This.$editable) return; + var oldTxt=this.childNodes[0].innerHTML; + var t=This.t;//t=_elCsys(This.$workArea[0]); + This.$textArea.val(oldTxt).css({display:"block",width:$(this).width()+26,height:$(this).height()+6, + left:t.left+26+This.$nodeData[id].left*This.$scale-This.$workArea[0].parentNode.scrollLeft, + top:t.top+2+This.$nodeData[id].top*This.$scale-This.$workArea[0].parentNode.scrollTop}) + .data("id",This.$focus).focus(); + tmpDbClickFunc(This); + }); + if(!this.$editable) return; + + //以下是工作区为编辑模式时才绑定的事件 + //绑定用鼠标移动事件 + this.$workArea.on("mousedown",".ico",{inthis:this},function(e){ + if(!e)e=window.event; + if(e.button===2)return false; + var This=e.data.inthis; + if(This.$nowType==="direct"||This.$nowType==="dashed") return; + var Dom=$(this).parents(".WaterFlow_item"); + var id=Dom.attr("id"); + This.focusItem(id,true); + + var ev=_mouseP(e),t=This.t;//t=_elCsys(This.$workArea[0]); + + Dom.children("table").clone().prependTo(This.$ghost); + var X,Y; + X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft; + Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop; + var vX=X-This.$nodeData[id].left*This.$scale,vY=Y-This.$nodeData[id].top*This.$scale; + var isMove=false; + document.onmousemove=function(e){ + if(!e)e=window.event; + var ev=_mouseP(e); + if(X===ev.x-vX&&Y===ev.y-vY) return false; + X=ev.x-vX;Y=ev.y-vY; + + if(isMove&&This.$ghost.css("display")==="none"){ + This.$ghost.css({display:"block", + width:This.$nodeData[id].width*This.$scale+"px", height:This.$nodeData[id].height*This.$scale+"px", + top:This.$nodeData[id].top*This.$scale+t.top-This.$workArea[0].parentNode.scrollTop+"px", + left:This.$nodeData[id].left*This.$scale+t.left-This.$workArea[0].parentNode.scrollLeft+"px", + cursor:"move" + }); + } + + if(Xt.left+This.$workArea.width()) + X=t.left+This.$workArea.width()-This.$workArea[0].parentNode.scrollLeft-This.$nodeData[id].width*This.$scale; + if(Yt.top+This.$workArea.height()) + Y=t.top+This.$workArea.height()-This.$workArea[0].parentNode.scrollTop-This.$nodeData[id].height*This.$scale; + This.$ghost.css({left:X+"px",top:Y+"px"}); + isMove=true; + }; + document.onmouseup=function(){ + if(isMove)This.moveNode(id,(X+This.$workArea[0].parentNode.scrollLeft-t.left)/This.$scale,(Y+This.$workArea[0].parentNode.scrollTop-t.top)/This.$scale); + This.$ghost.empty().hide(); + document.onmousemove=null; + document.onmouseup=null; + } + }); + //绑定鼠标覆盖/移出事件 + this.$workArea.on("mouseenter",".WaterFlow_item",{inthis:this},function(e){ + if((e.data.inthis.$nowType!=="direct"&&e.data.inthis.$nowType!=="dashed")&&!document.getElementById("WaterFlow_tmp_line")) return; + $(this).addClass("item_mark").addClass("crosshair").css("border-color",WaterFlow.color.mark); + }); + this.$workArea.on("mouseleave",".WaterFlow_item",{inthis:this},function(e){ + if((e.data.inthis.$nowType!=="direct"&&e.data.inthis.$nowType!=="dashed")&&!document.getElementById("WaterFlow_tmp_line")) return; + $(this).removeClass("item_mark").removeClass("crosshair"); + if(this.id===e.data.inthis.$focus){ + $(this).css("border-color",WaterFlow.color.line); + }else{ + $(this).css("border-color",WaterFlow.color.node); + } + }); + //绑定连线时确定初始点 + this.$workArea.on("mousedown",".WaterFlow_item",{inthis:this},function(e){ + if(e.button===2)return false; + var This=e.data.inthis; + if(This.$nowType!=="direct"&&This.$nowType!=="dashed") return; + var ev=_mouseP(e),t=_elCsys(This.$workArea[0]); + var X,Y; + X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft; + Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop; + This.$workArea.data("lineStart",{"x":X,"y":Y,"id":this.id}).css("cursor","crosshair"); + var line=WaterFlow.prototype.drawLine("WaterFlow_tmp_line",[X,Y],[X,Y],true,true,1); + This.$draw.appendChild(line); + }); + //绑定连线时确定结束点 + this.$workArea.on("mouseup",".WaterFlow_item",{inthis:this},function(e){ + var This=e.data.inthis; + if((This.$nowType!=="direct"&&This.$nowType!=="dashed")&&!This.$mpTo.data("p")) return; + var lineStart=This.$workArea.data("lineStart"); + var lineEnd=This.$workArea.data("lineEnd"); + if(lineStart&&!This.$mpTo.data("p")){ + var tmp={from:lineStart.id,to:this.id,name:""}; + if(This.$nowType==="dashed"){ + tmp.dash=true; + } + This.addLine(new Date().getTime().toString(),tmp); + This.$max++; + } + else{ + if(lineStart){ + This.moveLinePoints(This.$focus,lineStart.id,this.id); + }else if(lineEnd){ + This.moveLinePoints(This.$focus,this.id,lineEnd.id); + } + if(!This.$nodeData[this.id].marked){ + $(this).removeClass("item_mark"); + if(this.id!==This.$focus){ + $(this).css("border-color",WaterFlow.color.node); + } + else{ + $(this).css("border-color",WaterFlow.color.line); + } + } + } + }); + + //绑定节点的删除功能 + this.$workArea.on("click",".rs_close",{inthis:this},function(e){ + if(!e)e=window.event; + e.data.inthis.delNode(e.data.inthis.$focus); + return false; + }); + //绑定节点的RESIZE功能 + this.$workArea.on("mousedown",".WaterFlow_item > div > div[class!=rs_close]",{inthis:this},function(e){ + if(!e)e=window.event; + if(e.button===2)return false; + var cursor=$(this).css("cursor"); + if(cursor==="pointer"){return;} + var This=e.data.inthis; + var id=This.$focus; + This.switchToolBtn("cursor"); + e.cancelBubble = true; + e.stopPropagation(); + + var ev=_mouseP(e),t=This.t;//t=_elCsys(This.$workArea[0]); + This.$ghost.css({display:"block", + width:This.$nodeData[id].width*This.$scale+"px", height:This.$nodeData[id].height*This.$scale+"px", + top:This.$nodeData[id].top*This.$scale+t.top-This.$workArea[0].parentNode.scrollTop+"px", + left:This.$nodeData[id].left*This.$scale+t.left-This.$workArea[0].parentNode.scrollLeft+"px", + cursor:cursor + }); + var X,Y; + X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft; + Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop; + var vX=(This.$nodeData[id].left*This.$scale+This.$nodeData[id].width*This.$scale)-X; + var vY=(This.$nodeData[id].top*This.$scale+This.$nodeData[id].height*This.$scale)-Y; + var isMove=false; + This.$ghost.css("cursor",cursor); + document.onmousemove=function(e){ + if(!e)e=window.event; + var ev=_mouseP(e); + X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft-This.$nodeData[id].left*This.$scale+vX; + Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop-This.$nodeData[id].top*This.$scale+vY; + if(X<104*This.$scale) X=104*This.$scale; + if(Y<28*This.$scale) Y=28*This.$scale; + isMove=true; + switch(cursor){ + case "nw-resize":This.$ghost.css({width:X+"px",height:Y+"px"});break; + case "w-resize":This.$ghost.css({width:X+"px"});break; + case "n-resize":This.$ghost.css({height:Y+"px"});break; + } + }; + document.onmouseup=function(){ + document.onmousemove=null; + document.onmouseup=null; + This.$ghost.hide(); + if(!isMove)return; + //if(!e)e=window.event; + This.resizeNode(id,This.$ghost.outerWidth()/This.$scale,This.$ghost.outerHeight()/This.$scale); + }; + }); + }, + //加入手动扩展编辑区功能,一次扩展200px + _initExpendFunc:function(){ + var titleExendRight=WaterFlow.remarks.extendRight? ' title="'+WaterFlow.remarks.extendRight+'"':''; + var titleExendBottom=WaterFlow.remarks.extendBottom? ' title="'+WaterFlow.remarks.extendBottom+'"':''; + this.$workArea.append('
                '); + this.$workArea.children(".WaterFlow_extend_right").on("click",{inthis:this},function(e){ + var This=e.data.inthis; + var w = This.$workArea.width()+This.$workExtendStep; + var h = This.$workArea.height(); + This.$workArea.css({width:w+"px"}); + if(WaterFlow.prototype.useSVG===""){ + This.$draw.coordsize = w+","+h; + } + This.$draw.style.width = w + "px"; + if(This.$group!=null){ + This.$group.css({width:w+"px"}); + } + var parentDiv = This.$workArea.parent()[0]; + parentDiv.scrollLeft = parentDiv.scrollWidth; + This.$workArea.parent().css("overflow","scroll"); + return false; + }); + this.$workArea.children(".WaterFlow_extend_bottom").on("click",{inthis:this},function(e){ + var This=e.data.inthis; + var w = This.$workArea.width(); + var h = This.$workArea.height()+This.$workExtendStep; + This.$workArea.css({height:h+"px"}); + if(WaterFlow.prototype.useSVG===""){ + This.$draw.coordsize = w+","+h; + } + This.$draw.style.height = h + "px"; + if(This.$group!=null){ + This.$group.css({height:h+"px"}); + } + var parentDiv = This.$workArea.parent()[0]; + parentDiv.scrollTop = parentDiv.scrollHeight; + This.$workArea.parent().css("overflow","scroll"); + return false; + }); + }, + //初始化用来改变连线的连接端点的两个小方块的操作事件 + _initLinePointsChg:function(){ + this.$mpFrom.on("mousedown",{inthis:this},function(e){ + var This=e.data.inthis; + This.switchToolBtn("cursor"); + var ps=This.$mpFrom.data("p").split(","); + var pe=This.$mpTo.data("p").split(","); + $(this).hide(); + This.$workArea.data("lineEnd",{"x":pe[0],"y":pe[1],"id":This.$lineData[This.$lineOper.data("tid")].to}).css("cursor","crosshair"); + var line=WaterFlow.prototype.drawLine("WaterFlow_tmp_line",[ps[0],ps[1]],[pe[0],pe[1]],true,true,1); + This.$draw.appendChild(line); + return false; + }); + this.$mpTo.on("mousedown",{inthis:this},function(e){ + var This=e.data.inthis; + This.switchToolBtn("cursor"); + var ps=This.$mpFrom.data("p").split(","); + var pe=This.$mpTo.data("p").split(","); + $(this).hide(); + This.$workArea.data("lineStart",{"x":ps[0],"y":ps[1],"id":This.$lineData[This.$lineOper.data("tid")].from}).css("cursor","crosshair"); + var line=WaterFlow.prototype.drawLine("WaterFlow_tmp_line",[ps[0],ps[1]],[pe[0],pe[1]],true,true,1); + This.$draw.appendChild(line); + return false; + }); + }, + //初始化设计器的编辑功能 + _initEditFunc:function(useOperStack){ + //划线或改线时用的绑定 + this.$workArea.mousemove({inthis:this},function(e){ + var This=e.data.inthis; + if((This.$nowType!=="direct"&&This.$nowType!=="dashed")&&!This.$mpTo.data("p")) return; + var lineStart=$(this).data("lineStart"); + var lineEnd=$(this).data("lineEnd"); + if(!lineStart&&!lineEnd)return; + + var ev=_mouseP(e),t=_elCsys(this); + var X,Y; + X=ev.x-t.left+this.parentNode.scrollLeft; + Y=ev.y-t.top+this.parentNode.scrollTop; + var line=document.getElementById("WaterFlow_tmp_line"); + if(lineStart){ + if(WaterFlow.prototype.useSVG!==""){ + line.childNodes[0].setAttribute("d","M "+lineStart.x+" "+lineStart.y+" L "+X+" "+Y); + line.childNodes[1].setAttribute("d","M "+lineStart.x+" "+lineStart.y+" L "+X+" "+Y); + if(line.childNodes[1].getAttribute("marker-end")==='url("#arrow2")') + line.childNodes[1].setAttribute("marker-end","url(#arrow3)"); + else line.childNodes[1].setAttribute("marker-end","url(#arrow2)"); + } + else line.points.value=lineStart.x+","+lineStart.y+" "+X+","+Y; + }else if(lineEnd){ + if(WaterFlow.prototype.useSVG!==""){ + line.childNodes[0].setAttribute("d","M "+X+" "+Y+" L "+lineEnd.x+" "+lineEnd.y); + line.childNodes[1].setAttribute("d","M "+X+" "+Y+" L "+lineEnd.x+" "+lineEnd.y); + if(line.childNodes[1].getAttribute("marker-end")==='url("#arrow2")') + line.childNodes[1].setAttribute("marker-end","url(#arrow3)"); + else line.childNodes[1].setAttribute("marker-end","url(#arrow2)"); + } + else line.points.value=X+","+Y+" "+lineEnd.x+","+lineEnd.y; + } + }); + this.$workArea.mouseup({inthis:this},function(e){ + var This=e.data.inthis; + if((This.$nowType!=="direct"&&This.$nowType!=="dashed")&&!This.$mpTo.data("p")) return; + var tmp=document.getElementById("WaterFlow_tmp_line"); + if(tmp){ + $(this).css("cursor","auto").removeData("lineStart").removeData("lineEnd"); + This.$mpTo.hide().removeData("p"); + This.$mpFrom.hide().removeData("p"); + This.$draw.removeChild(tmp); + This.focusItem(This.$focus,false); + }else{ + This.$lineOper.removeData("tid"); + } + }); + + this.$textArea=$(""); + this.$bgDiv.append(this.$textArea); + this.$lineMove=$('');//操作折线时的移动框 + this.$workArea.append(this.$lineMove); + this.$lineMove.on("mousedown",{inthis:this},function(e){ + if(e.button===2)return false; + var lm=$(this); + lm.css({"background-color":"#333"}); + var This=e.data.inthis; + var ev=_mouseP(e),t=_elCsys(This.$workArea[0]); + var X,Y; + X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft; + Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop; + var p=This.$lineMove.position(); + var vX=X-p.left,vY=Y-p.top; + var isMove=false; + document.onmousemove=function(e){ + if(!e)e=window.event; + var ev=_mouseP(e); + //var ps=This.$lineMove.position(); + X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft; + Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop; + if(This.$lineMove.data("type")==="lr"){ + X=X-vX; + if(X<0) X=0; + else if(X>This.$workArea.width()) + X=This.$workArea.width(); + This.$lineMove.css({left:X+"px"}); + } + else if(This.$lineMove.data("type")==="tb"){ + Y=Y-vY; + if(Y<0) Y=0; + else if(Y>This.$workArea.height()) + Y=This.$workArea.height(); + This.$lineMove.css({top:Y+"px"}); + } + isMove=true; + }; + document.onmouseup=function(){ + if(isMove){ + var p=This.$lineMove.position(); + if(This.$lineMove.data("type")==="lr") + This.setLineM(This.$lineMove.data("tid"),(p.left+3)/This.$scale); + else if(This.$lineMove.data("type")==="tb") + This.setLineM(This.$lineMove.data("tid"),(p.top+3)/This.$scale); + } + This.$lineMove.css({"background-color":"transparent"}); + if(This.$focus===This.$lineMove.data("tid")){ + This.focusItem(This.$lineMove.data("tid")); + } + document.onmousemove=null; + document.onmouseup=null; + }; + }); + + //选定一条转换线后出现的浮动操作栏,有改变线的样式和删除线等按钮。 + this.$lineOper=$("");//选定线时显示的操作框 + this.$workArea.parent().append(this.$lineOper); + this.$lineOper.on("click",{inthis:this},function(e){ + if(!e)e=window.event; + if(e.target.tagName!=="I") return; + var This=e.data.inthis; + var id=$(this).data("tid"); + switch($(e.target).attr("class")){ + case "b_x": + This.delLine(id); + this.style.display="none";break; + case "b_l1": + This.setLineType(id,"lr");break; + case "b_l2": + This.setLineType(id,"tb");break; + case "b_l3": + This.setLineType(id,"sl");break; + } + }); + //新增移动线两个端点至新的节点功能移动功能,这里要提供移动用的DOM + this.$mpFrom=$(""); + this.$mpTo=$(""); + this.$workArea.append(this.$mpFrom).append(this.$mpTo); + this._initLinePointsChg(); + + if(useOperStack){//如果要使用堆栈记录操作并提供“撤销/重做”的功能,只在编辑状态下有效 + this.$undoStack=[]; + this.$redoStack=[]; + this.$isUndo=0; + ///////////////以下是构造撤销操作/重做操作的方法 + //检查撤销栈与重做栈处理好头部按钮的显示 + this._checkStack=function(type){ + if(this.$head===null) return; + if(!type || type==='undo'){ + if(this.$undoStack.length===0){ + this.$head.find(".ico_undo").parent().addClass("a_disabled"); + }else{ + this.$head.find(".ico_undo").parent().removeClass("a_disabled"); + } + } + if(!type || type==='redo'){ + if(this.$redoStack.length===0){ + this.$head.find(".ico_redo").parent().addClass("a_disabled"); + }else{ + this.$head.find(".ico_redo").parent().removeClass("a_disabled"); + } + } + }; + //为了节省浏览器内存空间,undo/redo中的操作缓存栈,最多只可放50步操作;超过50步时,将自动删掉最旧的一个缓存 + this.pushOper=function(funcName,paras){ + if(this.$isUndo===1){ + this.$redoStack.push([funcName,paras]); + this.$isUndo=0; + if(this.$redoStack.length>50) this.$redoStack.shift(); + this._checkStack('redo'); + }else{ + this.$undoStack.push([funcName,paras]); + if(this.$undoStack.length>50) this.$undoStack.shift(); + if(this.$isUndo===0){ + this.$redoStack.splice(0,this.$redoStack.length); + } + this.$isUndo=0; + this._checkStack(); + } + }; + //将外部的方法加入到WaterFlow对象的事务操作堆栈中,在过后的undo/redo操作中可以进行控制,一般用于对流程图以外的附加信息进行编辑的事务撤销/重做控制; + //传参func为要执行方法对象,jsonPara为外部方法仅有的一个面向字面的JSON传参,由JSON对象带入所有要传的信息; + //提示:为了让外部方法能够被UNDO/REDO,需要在编写这些外部方法实现时,加入对该方法执行后效果回退的另一个执行方法的pushExternalOper + this.pushExternalOper=function(func,jsonPara){ + this.pushOper("externalFunc",[func,jsonPara]); + }; + //撤销上一步操作 + this.undo=function(){ + if(this.$undoStack.length===0) return; + this.blurItem(); + var tmp=this.$undoStack.pop(); + this.$isUndo=1; + if(tmp[0]==="externalFunc"){ + tmp[1][0](tmp[1][1]); + } + else{ + //传参的数量,最小0个最多12个. + this[tmp[0]](tmp[1][0],tmp[1][1],tmp[1][2],tmp[1][3],tmp[1][4],tmp[1][5], + tmp[1][6],tmp[1][7],tmp[1][8],tmp[1][9],tmp[1][10],tmp[1][11]); + } + this._checkStack(); + }; + //重做最近一次被撤销的操作 + this.redo=function(){ + if(this.$redoStack.length===0) return; + this.blurItem(); + var tmp=this.$redoStack.pop(); + this.$isUndo=2; + if(tmp[0]==="externalFunc"){ + tmp[1][0](tmp[1][1]); + } + else{ + //传参的数量,最小0个最多12个. + this[tmp[0]](tmp[1][0],tmp[1][1],tmp[1][2],tmp[1][3],tmp[1][4],tmp[1][5], + tmp[1][6],tmp[1][7],tmp[1][8],tmp[1][9],tmp[1][10],tmp[1][11]); + } + this._checkStack(); + }; + } + $(document).keydown({inthis:this},function(e){ + //绑定键盘操作 + var This=e.data.inthis; + if(This.$focus==="")return; + switch(e.keyCode){ + case 46://删除 + This.delNode(This.$focus,true); + This.delLine(This.$focus); + break; + } + }); + }, + + //对头部栏自定义按钮的事件绑定,用户可用来对另行加入的头部按钮自定义功能 + //传参为json结构,key为按钮的类型名(需另行写好'ico_'+按钮类型名的样式类定义),value为相关事件的方法实现定义 + bindHeadBtnEvent:function(funcs){ + if(this.$head!=null) + this.$headBtnEvents=funcs; + }, + //每一种类型节点及其按钮的说明文字 + setNodeRemarks:function(remark){ + if(this.$tool==null) return; + this.$tool.children("a").each(function(){ + try{ + this.title=remark[$(this).attr("id").split("btn_")[1]]; + }catch(e){} + }); + }, + //(当有顶部工具栏按钮组时)设定顶部工具栏按钮的说明文字 + setHeadToolsRemarks:function(remark){ + if(this.$head==null) return; + this.$head.children("a").each(function(){ + try{ + this.title=remark[$(this).children("i").attr("class").split('ico_')[1]]; + }catch(e){} + }); + }, + //设定扩展工作区宽高的长条按钮的说明文字 + setExtWorkRemarks:function(remark){ + this.$workArea.children(".WaterFlow_extend_right").attr("title",remark.extendRight); + this.$workArea.children(".WaterFlow_extend_bottom").attr("title",remark.extendBottom); + }, + + //切换左边工具栏按钮,传参TYPE表示切换成哪种类型的按钮 + switchToolBtn:function(type){ + if(this.$tool!=null){ + this.$tool.children("#"+this.$id+"_btn_"+this.$nowType.split(" ")[0]).attr("class","WaterFlow_tool_btn"); + } + if(this.$nowType==="group"){ + this.$workArea.prepend(this.$group); + for(var k in this.$areaDom) this.$areaDom[k].addClass("lock").children("div:eq(1)").css("display","none"); + } + this.$nowType=type; + if(this.$tool!=null){ + this.$tool.children("#"+this.$id+"_btn_"+type.split(" ")[0]).attr("class","WaterFlow_tool_btndown"); + } + if(this.$nowType==="group"){ + this.blurItem(); + this.$workArea.append(this.$group); + for(var key in this.$areaDom) this.$areaDom[key].removeClass("lock").children("div:eq(1)").css("display",""); + }else if(this.$nowType==="direct"||this.$nowType==="dashed"){ + this.blurItem(); + } + if(this.$textArea&&this.$textArea.css("display")==="none") this.$textArea.removeData("id").val("").hide(); + }, + + //获取节点/连线/分组区域的详细信息 + getItemInfo:function(id,type){ + switch(type){ + case "node": return this.$nodeData[id]||null; + case "line": return this.$lineData[id]||null; + case "area": return this.$areaData[id]||null; + } + }, + //取消所有节点/连线被选定的状态 + blurItem:function(){ + if(this.$focus!==""){ + var jq=$("#"+this.$focus); + if(jq.prop("tagName")==="DIV"){ + if(typeof this.onItemBlur==='function' && this.onItemBlur(this.$focus,"node")===false) return false; + jq.removeClass("item_focus").children("div:eq(0)").css("display","none"); + if(this.$nodeData[this.$focus].marked){ + jq.addClass("item_mark").css("border-color",WaterFlow.color.mark); + } + } + else{ + if(typeof this.onItemBlur==='function' && this.onItemBlur(this.$focus,"line")===false) return false; + if(WaterFlow.prototype.useSVG!==""){ + if(!this.$lineData[this.$focus].marked){ + jq[0].childNodes[1].setAttribute("stroke",WaterFlow.color.line); + jq[0].childNodes[1].setAttribute("marker-end","url(#arrow1)"); + } + } + else{ + if(!this.$lineData[this.$focus].marked){ + jq[0].strokeColor=WaterFlow.color.line; + } + } + if(this.$editable){ + this.$lineMove.hide().removeData("type").removeData("tid"); + this.$lineOper.hide().removeData("tid"); + this.$mpFrom.hide().removeData("p"); + this.$mpTo.hide().removeData("p"); + } + } + } + this.$focus=""; + return true; + }, + //选定某个节点/转换线 bool:TRUE决定了要触发选中事件,FALSE则不触发选中事件,多用在程序内部调用。 + focusItem: function (id, bool) { + if (!id) { + return false; + } + var jq=$("#"+id); + if(jq.length===0) return; + if(!this.blurItem()) return;//先执行"取消选中",如果返回FLASE,则也会阻止选定事件继续进行. + if(bool&& typeof this.onItemFocus==='function' && this.onItemFocus(id,"node")===false) return; + this.$focus=id; + if(jq.prop("tagName")==="DIV"){ + jq.addClass("item_focus"); + if(WaterFlow.color.line){ + jq.css("border-color",WaterFlow.color.line); + } + if(this.$editable)jq.children("div:eq(0)").css("display","block"); + //this.$workArea.append(jq); + }else{//如果是连接线 + if(WaterFlow.prototype.useSVG!==""){ + jq[0].childNodes[1].setAttribute("stroke",WaterFlow.color.mark); + jq[0].childNodes[1].setAttribute("marker-end","url(#arrow2)"); + } + else{ + jq[0].strokeColor=WaterFlow.color.mark; + } + if(!this.$editable) return; + var x,y,from,to,n; + if(WaterFlow.prototype.useSVG!==""){ + from=jq.attr("from").split(","); + to=jq.attr("to").split(","); + n=[from[0],from[1],to[0],to[1]]; + }else{ + n=jq[0].getAttribute("fromTo").split(","); + from=[n[0],n[1]]; + to=[n[2],n[3]]; + } + from[0]=parseInt(from[0],10); + from[1]=parseInt(from[1],10); + to[0]=parseInt(to[0],10); + to[1]=parseInt(to[1],10); + //var t=_elCsys(this.$workArea[0]); + if(this.$lineData[id].type==="lr"){ + from[0]=this.$lineData[id].M*this.$scale; + to[0]=from[0]; + + this.$lineMove.css({ + width:"5px",height:(to[1]-from[1])*(to[1]>from[1]? 1:-1)+"px", + left:from[0]-3+"px", + top:(to[1]>from[1]? from[1]:to[1])+1+"px", + cursor:"e-resize",display:"block" + }).data({"type":"lr","tid":id}); + } + else if(this.$lineData[id].type==="tb"){ + from[1]=this.$lineData[id].M*this.$scale; + to[1]=from[1]; + this.$lineMove.css({ + width:(to[0]-from[0])*(to[0]>from[0]? 1:-1)+"px",height:"5px", + left:(to[0]>from[0]? from[0]:to[0])+1+"px", + top:from[1]-3+"px", + cursor:"s-resize",display:"block" + }).data({"type":"tb","tid":id}); + } + x=(from[0]+to[0])/2-40; + y=(from[1]+to[1])/2+4; + this.$lineOper.css({display:"block",left:x+"px",top:y+"px"}).data("tid",id); + if(this.$editable){ + this.$mpFrom.css({display:"block",left:n[0]-4+"px",top:n[1]-4+"px"}).data("p",n[0]+","+n[1]); + this.$mpTo.css({display:"block",left:n[2]-4+"px",top:n[3]-4+"px"}).data("p",n[2]+","+n[3]); + } + this.$draw.appendChild(jq[0]); + } + + this.switchToolBtn("cursor"); + }, + //传入一个节点的ID,判断在图中的哪个区域组(泳道)的范围内 + _node2Area:function(nodeId){ + if(this.$group===null) return; + var node=this.$nodeData[nodeId]; + var lane=false; + for(var key in this.$areaData){ + var area = this.$areaData[key]; + if( node.left>=area.left&&node.left=area.top&&node.top
                " + json.name + "
                "); + } + else { + if (!json.height || json.height < 30) json.height = 30; + this.$nodeDom[id] = $("
                " + json.name + "
                "); + } + if(WaterFlow.color.node){ + if(json.type.indexOf(" mix")>-1){ + this.$nodeDom[id].css({"background-color":WaterFlow.color.mix,"border-color":WaterFlow.color.mix}); + if(WaterFlow.color.mixFont){ + this.$nodeDom[id].find("td:eq(1)").css("color",WaterFlow.color.mixFont); + this.$nodeDom[id].find(".span").css("color",WaterFlow.color.mixFont); + } + }else{ + this.$nodeDom[id].css({"background-color":WaterFlow.color.node,"border-color":WaterFlow.color.node}); + } + if(mark&&WaterFlow.color.mark){ + this.$nodeDom[id].css({"border-color":WaterFlow.color.mark}); + } + } + if(json.type.indexOf(" mix")>-1){ + this.$nodeDom[id].addClass("item_mix"); + } + + var ua=navigator.userAgent.toLowerCase(); + if(ua.indexOf('msie')!==-1 && ua.indexOf('8.0')!==-1) + this.$nodeDom[id].css("filter","progid:DXImageTransform.Microsoft.Shadow(color=#94AAC2,direction=135,strength=2)"); + this.$workArea.append(this.$nodeDom[id]); + this.$nodeData[id]=json; + ++this.$nodeCount; + if(this.$editable){ + this.$nodeData[id].alt=true; + this._node2Area(id); + if(this.$deletedItem[id]) delete this.$deletedItem[id];//在回退删除操作时,去掉该元素的删除记录 + } + }, + //移动节点到一个新的位置 + moveNode:function(id,left,top){ + if(!this.$nodeData[id]) return; + if(typeof this.onItemMove==='function' && this.onItemMove(id,"node",left,top)===false) return; + if(this.$undoStack){ + var paras=[id,this.$nodeData[id].left,this.$nodeData[id].top]; + this.pushOper("moveNode",paras); + } + if(left<0) left=0; + if(top<0) top=0; + $("#"+id).css({left:left*this.$scale+"px",top:top*this.$scale+"px"}); + this.$nodeData[id].left=left; + this.$nodeData[id].top=top; + //重画转换线 + this.resetLines(id,this.$nodeData[id]); + if(this.$editable){ + this.$nodeData[id].alt=true; + this._node2Area(id); + } + }, + //设置节点/连线/分组区域的文字信息 + setName:function(id,name,type, setInfo){ + var oldName; + if (type === "node") {//如果是节点 + this.$nodeData[id].setInfo = setInfo; + if(!this.$nodeData[id]) return; + if(this.$nodeData[id].name===name) return; + if(typeof this.onItemRename==='function' && this.onItemRename(id,name,"node")===false) return; + oldName=this.$nodeData[id].name; + this.$nodeData[id].name=name; + if(this.$nodeData[id].type.indexOf("round")>1){ + this.$nodeDom[id].children(".span").text(name); + } + else{ + this.$nodeDom[id].find("td:eq(1)").children("div").text(name); + + var width=this.$nodeDom[id].outerWidth(); + var height=this.$nodeDom[id].outerHeight(); + if(this.$nodeData[id].width!==width || this.$nodeData[id].height!==height){ + this.$nodeDom[id].children("table").css({width:width-2+"px",height:height-2+"px"}); + if(this.$undoStack){ + var para=[id,this.$nodeData[id].width,this.$nodeData[id].height]; + this.pushOper("resizeNode",para); + } + this.$nodeData[id].width=width; + this.$nodeData[id].height=height; + } + } + if(this.$editable){ + this.$nodeData[id].alt=true; + } + //重画转换线 + this.resetLines(id,this.$nodeData[id]); + } + else if (type === "line") {//如果是线 + this.$lineData[id].Compares = setInfo.Compares; + delete this.$lineData[id].setInfo; + if(!this.$lineData[id]) return; + if(this.$lineData[id].name===name) return; + if(typeof this.onItemRename==='function' && this.onItemRename(id,name,"node")===false) return; + oldName=this.$lineData[id].name; + this.$lineData[id].name=name; + if(WaterFlow.prototype.useSVG!==""){ + this.$lineDom[id].childNodes[2].textContent=name; + } + else{ + this.$lineDom[id].childNodes[1].innerHTML=name; + var n=this.$lineDom[id].getAttribute("fromTo").split(","); + var x; + if(this.$lineData[id].type!=="lr"){ + x=(n[2]-n[0])/2; + } + else{ + var Min=n[2]>n[0]? n[0]:n[2]; + if(Min>this.$lineData[id].M) Min=this.$lineData[id].M; + x=this.$lineData[id].M-Min; + } + if(x<0) x=x*-1; + this.$lineDom[id].childNodes[1].style.left=x-this.$lineDom[id].childNodes[1].offsetWidth/2+4+"px"; + } + if(this.$editable){ + this.$lineData[id].alt=true; + } + } + else if(type==="area"){//如果是分组区域 + if(!this.$areaData[id]) return; + if(this.$areaData[id].name===name) return; + if(typeof this.onItemRename==='function' && this.onItemRename(id,name,"node")===false) return; + oldName=this.$areaData[id].name; + this.$areaData[id].name=name; + this.$areaDom[id].children("label").text(name); + if(this.$editable){ + this.$areaData[id].alt=true; + } + } + if(this.$undoStack){ + var paras=[id,oldName,type]; + this.pushOper("setName",paras); + } + }, + //设置节点的尺寸,仅支持非开始/结束节点 + resizeNode:function(id,width,height){ + if(!this.$nodeData[id]) return; + if(typeof this.onItemResize==='function' && this.onItemResize(id,"node",width,height)===false) return; + if(this.$nodeData[id].type==="start"||this.$nodeData[id].type==="end")return; + if(this.$undoStack){ + var paras=[id,this.$nodeData[id].width,this.$nodeData[id].height]; + this.pushOper("resizeNode",paras); + } + + this.$nodeDom[id].children("table").css({width:(width-2)*this.$scale+"px",height:(height-2)*this.$scale+"px"}); + //确保因内部文字太多而撑大时,宽高尺寸仍然是精确的 + width=this.$nodeDom[id].outerWidth(); + height=this.$nodeDom[id].outerHeight(); + this.$nodeDom[id].children("table").css({width:width-2+"px",height:height-2+"px"}); + //确保因内部文字太多而撑大时,宽高尺寸仍然是精确的 END + this.$nodeData[id].width=width; + this.$nodeData[id].height=height; + if(this.$editable){ + this.$nodeData[id].alt=true; + } + //重画转换线 + this.resetLines(id,this.$nodeData[id]); + this._node2Area(id); + }, + //删除节点 + delNode:function(id,trigger){ + if(!this.$nodeData[id]) return; + if(false!==trigger && typeof this.onItemDel==='function' && this.onItemDel(id,"node")===false) return; + //先删除可能的连线 + for(var k in this.$lineData){ + if(this.$lineData[k].from===id||this.$lineData[k].to===id){ + //this.$draw.removeChild(this.$lineDom[k]); + //delete this.$lineData[k]; + //delete this.$lineDom[k]; + this.delLine(k,false); + } + } + //再删除节点本身 + if(this.$undoStack){ + var paras=[id,this.$nodeData[id]]; + this.pushOper("addNode",paras); + } + delete this.$nodeData[id]; + this.$nodeDom[id].remove(); + delete this.$nodeDom[id]; + --this.$nodeCount; + if(this.$focus===id) this.$focus=""; + + if(this.$editable){ + //在回退新增操作时,如果节点ID以this.$id+"_node_"开头,则表示为本次编辑时新加入的节点,这些节点的删除不用加入到$deletedItem中 + //if(id.indexOf(this.$id+"_node_")<0) + this.$deletedItem[id]="node"; + } + }, + //设置流程图的名称 + setTitle:function(text){ + this.$title=text; + if(this.$head) this.$head.children("label").attr("title",text).text(text); + }, + //仅供内部使用:计算流程图的实际宽高(单位像素) + _suitSize:function(){ + var maxW=0,maxH=0; + for(var k1 in this.$nodeData){ + var node = this.$nodeData[k1]; + if(maxW < node.width+node.left){ + maxW = node.width+node.left; + } + if(maxH < node.height+node.top){ + maxH = node.height+node.top; + } + } + for(var k2 in this.$areaData){ + var area = this.$areaData[k2]; + if(maxW < area.width+area.left){ + maxW = area.width+area.left; + } + if(maxH < area.height+area.top){ + maxH = area.height+area.top; + } + } + for(var k3 in this.$lineData){ + var line = this.$lineData[k3]; + if(line.M && line.type==="lt" && maxW < line.M ){ + maxW = M+4; + } + if(line.M && line.type==="tb" && maxH < line.M ){ + maxH = M+4; + } + } + return {width:maxW,height:maxH} + + }, + //载入一组数据 + loadData: function (data) { + this.clearData(); //载入之前先清空数据 yubaolee + var t=this.$editable; + this.$editable=false; + if(data.title) this.setTitle(data.title); + if (data.initNum) this.$max = data.initNum; + + if (data != "") { + var length,k; + for (k = 0, length = data.nodes.length; k < length; k++) { + this.addNode(data.nodes[k].id, data.nodes[k]); + } + for (k = 0, length = data.lines.length; k < length; k++) { + this.addLine(data.lines[k].id, data.lines[k]); + } + for (k = 0,length = data.areas.length; k < length; k++) { + this.addArea(data.areas[k].id, data.areas[k]); + } + } + + + this.$editable=t; + this.$deletedItem={}; + //自行重构工作区,使之大小自适应 + var width=this.$workArea.width(); + var height=this.$workArea.height(); + var max=this._suitSize(); + while(max.width>width){ + width+=this.$workExtendStep; + } + while(max.height>height){ + height+=this.$workExtendStep; + } + this.$workArea.css({height:height+"px",width:width+"px"}); + if(WaterFlow.prototype.useSVG===""){ + this.$draw.coordsize = width+","+height; + } + this.$draw.style.width = width + "px"; + this.$draw.style.height = height + "px"; + if(this.$group!=null){ + this.$group.css({height:height+"px",width:width+"px"}); + } + }, + //用AJAX方式,远程读取一组数据 + //参数para为JSON结构,与JQUERY中$.ajax()方法的传参一样 + loadDataAjax:function(para){ + var This=this; + $.ajax({ + type:para.type, + url:para.url, + dataType:"json", + data:para.data, + success: function(msg){ + if(para['dataFilter']) para['dataFilter'](msg,"json"); + This.loadData(msg); + if(para.success) para.success(msg); + }, + error: function(XMLHttpRequest, textStatus, errorThrown){ + if(para.error) para.error(textStatus,errorThrown); + } + }) + }, + //把画好的整个流程图导出到一个变量中(其实也可以直接访问WaterFlow对象的$nodeData,$lineData,$areaData这三个JSON属性) + exportData:function(){ + var ret={}; + ret.title=this.$title; + ret.nodes=[]; + ret.lines=[]; + ret.areas=[]; + ret.initNum=this.$max; + for(var k1 in this.$nodeData){ + if(!this.$nodeData[k1].marked){ + delete this.$nodeData[k1]["marked"]; + } + ret.nodes.push(JSON.parse(JSON.stringify(this.$nodeData[k1]))); + //ret.nodes[k1]=JSON.parse(JSON.stringify(this.$nodeData[k1])); + } + for(var k2 in this.$lineData){ + if(!this.$lineData[k2].marked){ + delete this.$lineData[k2]["marked"]; + } + ret.lines.push(JSON.parse(JSON.stringify(this.$lineData[k2]))); + // ret.lines[k2]=JSON.parse(JSON.stringify(this.$lineData[k2])); + } + for(var k3 in this.$areaData){ + if(!this.$areaData[k3].marked){ + delete this.$areaData[k3]["marked"]; + } + + ret.areas.push(JSON.parse(JSON.stringify(this.$areaData[k3]))); + // ret.areas[k3]=JSON.parse(JSON.stringify(this.$areaData[k3])); + } + return ret; + }, + //只把本次编辑流程图中作了变更(包括增删改)的元素导出到一个变量中,以方便用户每次编辑载入的流程图后只获取变更过的数据 + exportAlter:function(){ + var ret={nodes:{},lines:{},areas:{}}; + for(var k1 in this.$nodeData){ + if(this.$nodeData[k1].alt){ + ret.nodes[k1]=this.$nodeData[k1]; + } + } + for(var k2 in this.$lineData){ + if(this.$lineData[k2].alt){ + ret.lines[k2]=this.$lineData[k2]; + } + } + for(var k3 in this.$areaData){ + if(this.$areaData[k3].alt){ + ret.areas[k3]=this.$areaData[k3]; + } + } + ret.deletedItem=this.$deletedItem; + return ret; + }, + //变更元素的ID,一般用于快速保存后,将后台返回新元素的ID更新到页面中;type为元素类型(节点,连线,区块) + transNewId:function(oldId,newId,type){ + var tmp; + switch(type){ + case "node": + if(this.$nodeData[oldId]){ + tmp=this.$nodeData[oldId]; + delete this.$nodeData[oldId]; + this.$nodeData[newId]=tmp; + tmp=this.$nodeDom[oldId].attr("id",newId); + delete this.$nodeDom[oldId]; + this.$nodeDom[newId]=tmp; + } + break; + case "line": + if(this.$lineData[oldId]){ + tmp=this.$lineData[oldId]; + delete this.$lineData[oldId]; + this.$lineData[newId]=tmp; + tmp=this.$lineDom[oldId].attr("id",newId); + delete this.$lineDom[oldId]; + this.$lineDom[newId]=tmp; + } + break; + case "area": + if(this.$areaData[oldId]){ + tmp=this.$areaData[oldId]; + delete this.$areaData[oldId]; + this.$areaData[newId]=tmp; + tmp=this.$areaDom[oldId].attr("id",newId); + delete this.$areaDom[oldId]; + this.$areaDom[newId]=tmp; + } + break; + } + }, + //清空工作区及已载入的数据 + clearData:function(){ + for(var k1 in this.$nodeData){ + this.delNode(k1); + } + for(var k2 in this.$lineData){ + this.delLine(k2); + } + for(var k3 in this.$areaData){ + this.delArea(k3); + } + this.$deletedItem={}; + }, + //销毁自己 + destrory:function(){ + this.$bgDiv.empty(); + this.$lineData=null; + this.$nodeData=null; + this.$lineDom=null; + this.$nodeDom=null; + this.$areaDom=null; + this.$areaData=null; + this.$nodeCount=0; + this.$areaCount=0; + this.$areaCount=0; + this.$deletedItem={}; + }, +///////////以下为有关画线的方法 + //绘制一条箭头线,并返回线的DOM + drawLine:function(id,sp,ep,mark,dash,$scale){ + var line,text; + var x=(ep[0]+sp[0])/2, y=(ep[1]+sp[1])/2; + if(WaterFlow.prototype.useSVG!==""){ + line=document.createElementNS("http://www.w3.org/2000/svg","g"); + var hi=document.createElementNS("http://www.w3.org/2000/svg","path"); + var path=document.createElementNS("http://www.w3.org/2000/svg","path"); + + if(id!=="") line.setAttribute("id",id); + line.setAttribute("from",sp[0]+","+sp[1]); + line.setAttribute("to",ep[0]+","+ep[1]); + hi.setAttribute("visibility","hidden"); + hi.setAttribute("stroke-width",'9'); + hi.setAttribute("fill","none"); + hi.setAttribute("stroke","white"); + hi.setAttribute("d","M "+sp[0]+" "+sp[1]+" L "+ep[0]+" "+ep[1]); + hi.setAttribute("pointer-events","stroke"); + path.setAttribute("d","M "+sp[0]+" "+sp[1]+" L "+ep[0]+" "+ep[1]); + path.setAttribute("stroke-width",mark? '2.4':'1.4'); + path.setAttribute("stroke-linecap","round"); + path.setAttribute("fill","none"); + if(dash) path.setAttribute("style", "stroke-dasharray:6,5"); + if(mark){ + path.setAttribute("stroke",WaterFlow.color.mark); + path.setAttribute("marker-end","url(#arrow2)"); + } + else{ + path.setAttribute("stroke",WaterFlow.color.line); + path.setAttribute("marker-end","url(#arrow1)"); + } + line.appendChild(hi); + line.appendChild(path); + line.style.cursor="crosshair"; + if(id!==""&&id!=="WaterFlow_tmp_line"){ + text=document.createElementNS("http://www.w3.org/2000/svg","text"); + text.setAttribute("fill",WaterFlow.color.lineFont); + line.appendChild(text); + + text.setAttribute("text-anchor","middle"); + text.setAttribute("x",x+''); + text.setAttribute("y",y+''); + text.style.cursor="text"; + text.style.fontSize=16*$scale+"px"; + line.style.cursor="pointer"; + } + }else{ + line=document.createElement("v:polyline"); + if(id!=="") line.id=id; + //line.style.position="absolute"; + line.points.value=sp[0]+","+sp[1]+" "+ep[0]+","+ep[1]; + line.setAttribute("fromTo",sp[0]+","+sp[1]+","+ep[0]+","+ep[1]); + line.strokeWeight="1.2"; + line.stroke.EndArrow="Block"; + line.style.cursor="crosshair"; + if(id!==""&&id!=="WaterFlow_tmp_line"){ + text=document.createElement("div"); + //text.innerHTML=id; + line.appendChild(text); + if(x<0) x=x*-1; + if(y<0) y=y*-1; + text.style.left=x+"px"; + text.style.top=y-6+"px"; + text.style.color=WaterFlow.color.lineFont; + text.style.fontSize=16*$scale+"px"; + line.style.cursor="pointer"; + } + if(dash) line.stroke.dashStyle="Dash"; + if(mark) line.strokeColor=WaterFlow.color.mark; + else line.strokeColor=WaterFlow.color.line; + line.fillColor=WaterFlow.color.line; + } + return line; + }, + //画一条只有两个中点的折线 + drawPoly:function(id,sp,m1,m2,ep,mark,dash,$scale){ + var poly,strPath, text; + var x=(m2[0]+m1[0])/2, y=(m2[1]+m1[1])/2; + if(WaterFlow.prototype.useSVG!==""){ + poly=document.createElementNS("http://www.w3.org/2000/svg","g"); + var hi=document.createElementNS("http://www.w3.org/2000/svg","path"); + var path=document.createElementNS("http://www.w3.org/2000/svg","path"); + if(id!=="") poly.setAttribute("id",id); + poly.setAttribute("from",sp[0]+","+sp[1]); + poly.setAttribute("to",ep[0]+","+ep[1]); + hi.setAttribute("visibility","hidden"); + hi.setAttribute("stroke-width",'9'); + hi.setAttribute("fill","none"); + hi.setAttribute("stroke","white"); + strPath="M "+sp[0]+" "+sp[1]; + if(m1[0]!==sp[0]||m1[1]!==sp[1]) + strPath+=" L "+m1[0]+" "+m1[1]; + if(m2[0]!==ep[0]||m2[1]!==ep[1]) + strPath+=" L "+m2[0]+" "+m2[1]; + strPath+=" L "+ep[0]+" "+ep[1]; + hi.setAttribute("d",strPath); + hi.setAttribute("pointer-events","stroke"); + path.setAttribute("d",strPath); + path.setAttribute("stroke-width",mark? '2.4':'1.4'); + path.setAttribute("stroke-linecap","round"); + path.setAttribute("fill","none"); + if(dash) path.setAttribute("style", "stroke-dasharray:6,5"); + if(mark){ + path.setAttribute("stroke",WaterFlow.color.mark); + path.setAttribute("marker-end","url(#arrow2)"); + } + else{ + path.setAttribute("stroke",WaterFlow.color.line); + path.setAttribute("marker-end","url(#arrow1)"); + } + poly.appendChild(hi); + poly.appendChild(path); + text=document.createElementNS("http://www.w3.org/2000/svg","text"); + text.setAttribute("fill",WaterFlow.color.lineFont); + poly.appendChild(text); + text.setAttribute("text-anchor","middle"); + text.setAttribute("x",x+''); + text.setAttribute("y",y+''); + text.style.cursor="text"; + } + else{ + poly=document.createElement("v:Polyline"); + if(id!=="") poly.id=id; + poly.filled="false"; + strPath=sp[0]+","+sp[1]; + if(m1[0]!==sp[0]||m1[1]!==sp[1]) + strPath+=" "+m1[0]+","+m1[1]; + if(m2[0]!==ep[0]||m2[1]!==ep[1]) + strPath+=" "+m2[0]+","+m2[1]; + strPath+=" "+ep[0]+","+ep[1]; + poly.points.value=strPath; + poly.setAttribute("fromTo",sp[0]+","+sp[1]+","+ep[0]+","+ep[1]); + poly.strokeWeight=mark? "2.4":"1.2"; + poly.stroke.EndArrow="Block"; + text=document.createElement("div"); + //text.innerHTML=id; + poly.appendChild(text); + if(x<0) x=x*-1; + if(y<0) y=y*-1; + text.style.left=x+"px"; + text.style.top=y-4+"px"; + text.style.color=WaterFlow.color.lineFont; + if(dash) poly.stroke.dashStyle="Dash"; + if(mark) poly.strokeColor=WaterFlow.color.mark; + else poly.strokeColor=WaterFlow.color.line; + } + poly.style.cursor="pointer"; + text.style.fontSize=16*$scale+"px"; + return poly; + }, + //原lineData已经设定好的情况下,只在绘图工作区画一条线的页面元素 + addLineDom:function(id,lineData){ + var n1=this.$nodeData[lineData.from],n2=this.$nodeData[lineData.to];//获取开始/结束节点的数据 + if(!n1||!n2) return; + //开始计算线端点坐标 + var res; + if(lineData.type&&lineData.type!=="sl") + res=calcPolyPoints(n1,n2,lineData.type,lineData.M, this.$scale); + else + res=calcStartEnd(n1,n2, this.$scale); + if(!res) return; + + if(lineData.type==="sl") + this.$lineDom[id]=WaterFlow.prototype.drawLine(id,res.start,res.end,lineData.marked,lineData.dash, this.$scale); + else + this.$lineDom[id]=WaterFlow.prototype.drawPoly(id,res.start,res.m1,res.m2,res.end,lineData.marked,lineData.dash, this.$scale); + this.$draw.appendChild(this.$lineDom[id]); + if(WaterFlow.prototype.useSVG===""){ + this.$lineDom[id].childNodes[1].innerHTML=lineData.name; + if(lineData.type!=="sl"){ + var Min=(res.start[0]>res.end[0]? res.end[0]:res.start[0]); + if(Min>res.m2[0]) Min=res.m2[0]; + if(Min>res.m1[0]) Min=res.m1[0]; + this.$lineDom[id].childNodes[1].style.left = (res.m2[0]+res.m1[0])/2-Min-this.$lineDom[id].childNodes[1].offsetWidth/2+4; + Min=(res.start[1]>res.end[1]? res.end[1]:res.start[1]); + if(Min>res.m2[1]) Min=res.m2[1]; + if(Min>res.m1[1]) Min=res.m1[1]; + this.$lineDom[id].childNodes[1].style.top = (res.m2[1]+res.m1[1])/2-Min-this.$lineDom[id].childNodes[1].offsetHeight/2; + }else + this.$lineDom[id].childNodes[1].style.left= + ((res.end[0]-res.start[0])*(res.end[0]>res.start[0]? 1:-1)-this.$lineDom[id].childNodes[1].offsetWidth)/2+4; + } + else{ + this.$lineDom[id].childNodes[2].textContent=lineData.name; + } + }, + //增加一条线 + addLine: function (id, json) { + if (json.id == undefined) { + $.extend(json, { id: id }); + } + if(typeof this.onItemAdd==='function' && this.onItemAdd(id,"line",json)===false)return; + if(this.$undoStack&&this.$editable){ + this.pushOper("delLine",[id]); + } + if(json.from===json.to) return; + var n1=this.$nodeData[json.from],n2=this.$nodeData[json.to];//获取开始/结束节点的数据 + if(!n1||!n2) return; + //避免两个节点间不能有一条以上同向接连线 + for(var k in this.$lineData){ + if((json.from===this.$lineData[k].from&&json.to===this.$lineData[k].to&&json.dash===this.$lineData[k].dash)) + return; + } + //设置$lineData[id] + this.$lineData[id]={}; + if(json.type){ + this.$lineData[id].type=json.type; + this.$lineData[id].M=json.M; + } + else this.$lineData[id].type="sl";//默认为直线 + this.$lineData[id].from=json.from; + this.$lineData[id].to = json.to; + this.$lineData[id].id = json.id; //赋值ID + this.$lineData[id].setInfo = json.setInfo; + this.$lineData[id].Compares = json.Compares; + this.$lineData[id].name=json.name; + if(json.marked) this.$lineData[id].marked=json.marked; + else this.$lineData[id].marked=false; + if(json.dash) this.$lineData[id].dash=json.dash; + else this.$lineData[id].dash=false; + //设置$lineData[id]完毕 + + this.addLineDom(id,this.$lineData[id]); + + ++this.$lineCount; + if(this.$editable){ + this.$lineData[id].alt=true; + if(this.$deletedItem[id]) delete this.$deletedItem[id];//在回退删除操作时,去掉该元素的删除记录 + } + }, + //重构所有连向某个节点的线的显示,传参结构为$nodeData数组的一个单元结构 + resetLines:function(id,node){ + for(var i in this.$lineData){ + var other=null;//获取结束/开始节点的数据 + var res; + if(this.$lineData[i].from===id){//找结束点 + other=this.$nodeData[this.$lineData[i].to]||null; + if(other==null) continue; + if(this.$lineData[i].type==="sl") + res=calcStartEnd(node,other, this.$scale); + else + res=calcPolyPoints(node,other,this.$lineData[i].type,this.$lineData[i].M, this.$scale); + if(!res) break; + } + else if(this.$lineData[i].to===id){//找开始点 + other=this.$nodeData[this.$lineData[i].from]||null; + if(other==null) continue; + if(this.$lineData[i].type==="sl") + res=calcStartEnd(other,node, this.$scale); + else + res=calcPolyPoints(other,node,this.$lineData[i].type,this.$lineData[i].M, this.$scale); + if(!res) break; + } + if(other==null) continue; + this.$draw.removeChild(this.$lineDom[i]); + if(this.$lineData[i].type==="sl"){ + this.$lineDom[i]=WaterFlow.prototype.drawLine(i,res.start,res.end,this.$lineData[i].marked,this.$lineData[i].dash, this.$scale); + } + else{ + this.$lineDom[i]=WaterFlow.prototype.drawPoly(i,res.start,res.m1,res.m2,res.end,this.$lineData[i].marked,this.$lineData[i].dash, this.$scale); + } + this.$draw.appendChild(this.$lineDom[i]); + if(WaterFlow.prototype.useSVG===""){ + this.$lineDom[i].childNodes[1].innerHTML=this.$lineData[i].name; + if(this.$lineData[i].type!=="sl"){ + var Min=(res.start[0]>res.end[0]? res.end[0]:res.start[0]); + if(Min>res.m2[0]) Min=res.m2[0]; + if(Min>res.m1[0]) Min=res.m1[0]; + this.$lineDom[i].childNodes[1].style.left = (res.m2[0]+res.m1[0])/2-Min-this.$lineDom[i].childNodes[1].offsetWidth/2+4; + Min=(res.start[1]>res.end[1]? res.end[1]:res.start[1]); + if(Min>res.m2[1]) Min=res.m2[1]; + if(Min>res.m1[1]) Min=res.m1[1]; + this.$lineDom[i].childNodes[1].style.top = (res.m2[1]+res.m1[1])/2-Min-this.$lineDom[i].childNodes[1].offsetHeight/2-4; + }else + this.$lineDom[i].childNodes[1].style.left= + ((res.end[0]-res.start[0])*(res.end[0]>res.start[0]? 1:-1)-this.$lineDom[i].childNodes[1].offsetWidth)/2+4; + } + else this.$lineDom[i].childNodes[2].textContent=this.$lineData[i].name; + } + }, + //重新设置连线的样式 newType= "sl":直线, "lr":中段可左右移动型折线, "tb":中段可上下移动型折线 + setLineType:function(id,newType,M){ + if(!newType||newType==null||newType===""||newType===this.$lineData[id].type) return false; + if(typeof this.onLineSetType==='function' && this.onLineSetType(id,newType)===false) return; + if(this.$undoStack){ + var paras=[id,this.$lineData[id].type,this.$lineData[id].M]; + this.pushOper("setLineType",paras); + } + var from=this.$lineData[id].from; + var to=this.$lineData[id].to; + this.$lineData[id].type=newType; + var res; + //如果是变成折线 + if(newType!=="sl"){ + //res=calcPolyPoints(this.$nodeData[from],this.$nodeData[to],this.$lineData[id].type,this.$lineData[id].M, this.$scale); + if(M){ + this.setLineM(id,M,true); + }else{ + this.setLineM(id,getMValue(this.$nodeData[from],this.$nodeData[to],newType),true); + } + } + //如果是变回直线 + else{ + delete this.$lineData[id].M; + this.$lineMove.hide().removeData("type").removeData("tid"); + res=calcStartEnd(this.$nodeData[from],this.$nodeData[to], this.$scale); + if(!res) return; + this.$draw.removeChild(this.$lineDom[id]); + this.$lineDom[id]=WaterFlow.prototype.drawLine(id,res.start,res.end,this.$lineData[id].marked,this.$lineData[id].dash, this.$scale); + this.$draw.appendChild(this.$lineDom[id]); + if(WaterFlow.prototype.useSVG===""){ + this.$lineDom[id].childNodes[1].innerHTML=this.$lineData[id].name; + this.$lineDom[id].childNodes[1].style.left= + ((res.end[0]-res.start[0])*(res.end[0]>res.start[0]? 1:-1)-this.$lineDom[id].childNodes[1].offsetWidth)/2+4; + } + else + this.$lineDom[id].childNodes[2].textContent=this.$lineData[id].name; + } + if(this.$focus===id){ + this.focusItem(id); + } + if(this.$editable){ + this.$lineData[id].alt=true; + } + }, + //设置折线中段的X坐标值(可左右移动时)或Y坐标值(可上下移动时) + setLineM:function(id,M,noStack){ + if(!this.$lineData[id]||M<0||!this.$lineData[id].type||this.$lineData[id].type==="sl") return false; + if(typeof this.onLineMove==='function' && this.onLineMove(id,M)===false) return false; + if(this.$undoStack&&!noStack){ + var paras=[id,this.$lineData[id].M]; + this.pushOper("setLineM",paras); + } + var from=this.$lineData[id].from; + var to=this.$lineData[id].to; + this.$lineData[id].M=M; + var ps=calcPolyPoints(this.$nodeData[from],this.$nodeData[to],this.$lineData[id].type,this.$lineData[id].M, this.$scale); + this.$draw.removeChild(this.$lineDom[id]); + this.$lineDom[id]=WaterFlow.prototype.drawPoly(id,ps.start,ps.m1,ps.m2,ps.end,this.$lineData[id].marked,this.$lineData[id].dash, this.$scale); + this.$draw.appendChild(this.$lineDom[id]); + if(WaterFlow.prototype.useSVG===""){ + this.$lineDom[id].childNodes[1].innerHTML=this.$lineData[id].name; + var Min=(ps.start[0]>ps.end[0]? ps.end[0]:ps.start[0]); + if(Min>ps.m2[0]) Min=ps.m2[0]; + if(Min>ps.m1[0]) Min=ps.m1[0]; + this.$lineDom[id].childNodes[1].style.left = (ps.m2[0]+ps.m1[0])/2-Min-this.$lineDom[id].childNodes[1].offsetWidth/2+4; + Min=(ps.start[1]>ps.end[1]? ps.end[1]:ps.start[1]); + if(Min>ps.m2[1]) Min=ps.m2[1]; + if(Min>ps.m1[1]) Min=ps.m1[1]; + this.$lineDom[id].childNodes[1].style.top = (ps.m2[1]+ps.m1[1])/2-Min-this.$lineDom[id].childNodes[1].offsetHeight/2-4; + } + else this.$lineDom[id].childNodes[2].textContent=this.$lineData[id].name; + if(this.$editable){ + this.$lineData[id].alt=true; + } + }, + //删除转换线 + delLine:function(id,trigger){ + if(!this.$lineData[id]) return; + if(false!==trigger && typeof this.onItemDel==='function' && this.onItemDel(id,"node")===false) return; + if(this.$undoStack){ + var paras=[id,this.$lineData[id]]; + this.pushOper("addLine",paras); + } + this.$draw.removeChild(this.$lineDom[id]); + delete this.$lineData[id]; + delete this.$lineDom[id]; + if(this.$focus===id) this.$focus=""; + --this.$lineCount; + if(this.$editable){ + //在回退新增操作时,如果节点ID以this.$id+"_line_"开头,则表示为本次编辑时新加入的节点,这些节点的删除不用加入到$deletedItem中 + // if(id.indexOf(this.$id+"_line_")<0) + this.$deletedItem[id]="line"; + this.$mpFrom.hide().removeData("p"); + this.$mpTo.hide().removeData("p"); + } + if(this.$lineOper){ + this.$lineOper.hide().removeData("tid"); + } + }, + //变更连线两个端点所连的节点 + //参数:要变更端点的连线ID,新的开始节点ID、新的结束节点ID;如果开始/结束节点ID是传入null或者"",则表示原端点不变 + moveLinePoints:function(lineId, newStart, newEnd, noStack){ + if(newStart===newEnd) return; + if(!lineId||!this.$lineData[lineId]) return; + if(newStart==null||newStart==="") + newStart=this.$lineData[lineId].from; + if(newEnd==null||newEnd==="") + newEnd=this.$lineData[lineId].to; + + //避免两个节点间不能有一条以上同向接连线 + for(var k in this.$lineData){ + if((newStart===this.$lineData[k].from&&newEnd===this.$lineData[k].to)) + return; + } + if(typeof this.onLinePointMove==='function' && this.onLinePointMove(lineId,newStart,newEnd)===false) return; + if(this.$undoStack&&!noStack){ + var paras=[lineId,this.$lineData[lineId].from,this.$lineData[lineId].to]; + this.pushOper("moveLinePoints",paras); + } + if(newStart!=null&&newStart!==""){ + this.$lineData[lineId].from=newStart; + } + if(newEnd!=null&&newEnd!==""){ + this.$lineData[lineId].to=newEnd; + } + //重建转换线 + this.$draw.removeChild(this.$lineDom[lineId]); + this.addLineDom(lineId,this.$lineData[lineId]); + if(this.$editable){ + this.$lineData[lineId].alt=true; + } + }, + + //用颜色标注/取消标注一个节点或转换线,常用于显示重点或流程的进度。 + //这是一个在编辑模式中无用,但是在纯浏览模式中非常有用的方法,实际运用中可用于跟踪流程的进度。 + markItem:function(id,type,mark){ + if(type==="node"){ + if(!this.$nodeData[id]) return; + if(typeof this.onItemMark==='function' && this.onItemMark(id,"node",mark)===false) return; + this.$nodeData[id].marked=mark||false; + if(mark){ + this.$nodeDom[id].addClass("item_mark").css("border-color",WaterFlow.color.mark); + } + else{ + this.$nodeDom[id].removeClass("item_mark"); + if(id!==this.$focus) this.$nodeDom[id].css("border-color","transparent"); + } + + }else if(type==="line"){ + if(!this.$lineData[id]) return; + if(this.onItemMark!=null&&!this.onItemMark(id,"line",mark)) return; + this.$lineData[id].marked=mark||false; + if(WaterFlow.prototype.useSVG!==""){ + if(mark){ + this.$lineDom[id].childNodes[1].setAttribute("stroke",WaterFlow.color.mark); + this.$lineDom[id].childNodes[1].setAttribute("marker-end","url(#arrow2)"); + this.$lineDom[id].childNodes[1].setAttribute("stroke-width",2.4); + }else{ + this.$lineDom[id].childNodes[1].setAttribute("stroke",WaterFlow.color.line); + this.$lineDom[id].childNodes[1].setAttribute("marker-end","url(#arrow1)"); + this.$lineDom[id].childNodes[1].setAttribute("stroke-width",1.4); + } + }else{ + if(mark){ + this.$lineDom[id].strokeColor=WaterFlow.color.mark; + this.$lineDom[id].strokeWeight="2.4"; + } + else{ + this.$lineDom[id].strokeColor=WaterFlow.color.line; + this.$lineDom[id].strokeWeight="1.2"; + } + } + } + if(this.$undoStack){ + var paras=[id,type,!mark]; + this.pushOper("markItem",paras); + } + }, + ////////////////////////以下为区域分组块操作 + //传入一个区域组(泳道)的ID,判断图中所有节点在此区域组(泳道)的范围内 + _areaFixNodes:function(areaId){ + var area=this.$areaData[areaId]; + for(var key in this.$nodeData){ + var node = this.$nodeData[key]; + if( node.left>=area.left&&node.left=area.top&&node.top
                " + +"
                "); + this.$areaData[id]=json; + this.$group.append(this.$areaDom[id]); + if(this.$nowType!=="group") this.$areaDom[id].children("div:eq(1)").css("display","none"); + ++this.$areaCount; + if(this.$editable){ + this.$areaData[id].alt=true; + this._areaFixNodes(id); + if(this.$deletedItem[id]) delete this.$deletedItem[id];//在回退删除操作时,去掉该元素的删除记录 + } + }, + //重构整个流程图设计器的宽高 + reinitSize:function(width,height){ + var w=(width||this.$bgDiv.width()); + var h=(height||this.$bgDiv.height()); + this.$bgDiv.css({height:h+"px",width:w+"px"}); + var headHeight=0,hack=8; + if(this.$head!=null){ + headHeight=26; + hack=5; + } + if(this.$tool!=null){ + this.$tool.css({height:h-headHeight-hack+"px"}); + w-=31; + } + w-=9; + h=h-headHeight-(this.$head!=null? 5:8); + //this.$workArea.parent().css({height:h+"px",width:w+"px"}); + + if(this.$workArea.width()>w){ + w=this.$workArea.width(); + } + if(this.$workArea.height()>h){ + h=this.$workArea.height(); + } + + this.$workArea.css({height:h+"px",width:w+"px"}); + if(WaterFlow.prototype.useSVG===""){ + this.$draw.coordsize = w+","+h; + } + this.$draw.style.width = w + "px"; + this.$draw.style.height = h + "px"; + if(this.$group!=null){ + this.$group.css({height:h+"px",width:w+"px"}); + } + }, + //重设整个工作区内容的显示缩放比例,从0.5至4倍 + resetScale:function(scale){ + if(!scale) scale=1.0; + else if(scale<0.5) scale=0.5; + else if(scale>4) scale=4; + //以上是固定死取值范围:不让用户缩放过大或过小,已免无意中影响的显示效果 + if(this.$scale===scale) return; + var oldS=this.$scale; + this.$scale=scale; + var factor = oldS/scale;//因数(旧缩放比例除以新缩放比例),元素的现有值除以该因子,就能得到新的缩放后的值 + var W=0,H=0,P={};//宽、高、左及上的临时变量 + //开始正式的缩放(节点、连线、泳道块有宽高和定位,其它编辑工具元素则只有定位)(全部以左上角为原点) + this.blurItem(); + //先缩放工作区 + W=this.$workArea.width()/factor; + H=this.$workArea.height()/factor; + this.$workArea.css({"height":H+"px","width":W+"px"}); + if(WaterFlow.prototype.useSVG!==""){ + + }else{ + this.$draw.coordsize = W+","+H; + } + this.$draw.style.width = W + "px"; + this.$draw.style.height = H + "px"; + if(this.$group!=null){ + this.$group.css({height:H+"px",width:W+"px"}); + } + //缩放节点 + var isWebkit = navigator.userAgent.toLowerCase().indexOf('webkit') > -1; + this.$workArea.children(".WaterFlow_item").each(function(){ + var This=$(this); + P=This.position(); + This.css({ "left":P.left/factor+"px", "top":P.top/factor+"px" }); + This=This.children("table"); + W=This.outerWidth()/factor; + H=This.outerHeight()/factor; + This.css({ "width":W+"px", "height":H+"px" }); + var tmp=18*scale; + This.find("td[class='ico']").css({width:tmp+"px"}); + var newSize= {}; + if(tmp<12&&isWebkit){ + newSize["width"]="18px";newSize["height"]="18px"; + newSize["font-size"]="18px"; + newSize["transform"]="scale("+(tmp/18)+")"; + newSize["margin"]=-((18-tmp)/2)+"px"; + }else{ + newSize["width"]=tmp+"px"; newSize["height"]=tmp+"px"; + newSize["font-size"]=tmp+"px"; + newSize["transform"]="none"; + newSize["margin"]="0px auto"; + } + This.find("td[class='ico']").children("i").css(newSize); + + tmp=16*scale; + if(This.parent().find(".span").length===1){ + This.parent().css("border-radius",W/2+"px"); + This=This.parent().find(".span"); + This.css({"font-size":tmp+"px"}); + }else{ + This=This.find("td:eq(1) div"); + newSize={}; + if(tmp<12&&isWebkit){ + newSize["font-size"]="16px"; + newSize["transform"]="scale("+(tmp/16)+")"; + var mW=(W/scale-18-(W-18*scale))/2; + var mH=(H/scale-H)/2; + newSize["margin"]=-mH+"px "+(-mW)+"px"; + }else{ + newSize["transform"]="none"; + newSize["font-size"]=tmp+"px"; + newSize["margin"]="0px"; + } + This.css(newSize); + } + }); + //缩放区域图 + var ifs=16*scale+2; + this.$group.children(".WaterFlow_area").each(function(){ + var This=$(this); + P=This.position(); + This.css({ "left":P.left/factor+"px", "top":P.top/factor+"px" }); + This=This.children("div:eq(0)"); + W=This.outerWidth()/factor; + H=This.outerHeight()/factor; + This.css({ "width":W+"px", "height":H+"px" }); + This.next("label").css({ + "font-size": 16*scale+"px", + "left": ifs+3+"px" + }).next("i").css({ + "font-size": ifs-2+"px", + width:ifs+"px", + height:ifs+"px", + "line-height":ifs+"px" + }); + }); + //缩放连线 + for(var id in this.$lineDom){ + this.$draw.removeChild(this.$lineDom[id]); + delete this.$lineDom[id]; + } + for (var key in this.$lineData) { + this.addLineDom(key, this.$lineData[key]); + } + } +}; +//默认的颜色样式 +WaterFlow.color={ + //main:"#20A0FF", + font:"#15428B", + node:"#A1DCEB", + line:"#1D8CE0", + lineFont:"#777", + mark:"#ff8800", + mix:"#B6F700", + mixFont:"#777" +}; + //默认的文字说明注释内容 +WaterFlow.remarks={ + headBtns:{}, + toolBtns:{}, + extendRight:undefined, + extendBottom:undefined +}; +//当不想使用jquery插件式初始化方法时,另一种通过直接调用WaterFlow内部构造方法进行的初始化 +WaterFlow.init=function(selector,property){ + return new WaterFlow(selector,property); +}; +//在初始化出一个对象前的公用方法:覆盖设定WaterFlow默认的颜色定义 +WaterFlow.setColors=function(colors){ + $.extend(WaterFlow.color,colors); +}; +//扩展WaterFlow方法的扩展用接口,一般用在CMD,AMD +WaterFlow.extend=function(json){ + for(var funcName in json){ + WaterFlow.prototype[funcName]=json[funcName]; + } +}; +//将此类的构造函数加入至JQUERY对象中 +$.extend({ + createWaterFlow:function(selector,property){ + return new WaterFlow(selector,property); + } +}); + + exports('waterflow'); + }); diff --git a/WaterCloud.Web/wwwroot/js/lay-module/flow/waterflow.print.js b/WaterCloud.Web/wwwroot/js/lay-module/flow/waterflow.print.js new file mode 100644 index 0000000..a13c99c --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/flow/waterflow.print.js @@ -0,0 +1,207 @@ +/* + * 打印预览或另存为PDF功能,需要依赖: + * ../plugin/printThis.js + */ +;(function ( global, factory ) { + 'use strict'; + if ( typeof define !== 'undefined' && define.amd ) { // export as AMD... + define( ['jquery','WaterFlow'], factory ); + } + else if ( typeof module !== 'undefined' && module.exports ) { // ...or as browserify + factory( require('jquery'), require('WaterFlow') ); + }else + factory( global.$, global.WaterFlow ); + +}( typeof window !== 'undefined' ? window : this, function ( $,WaterFlow ) { + if(WaterFlow.prototype.print && typeof WaterFlow.prototype.print==='function'){ + return;//防止多次载入 + } +/* + * printThis v1.12.2 + * @desc Printing plug-in for jQuery + * @author Jason Day + * 精简版 only for WaterFlow + */ + (function($) { + + function appendContent($el, content) { + if (!content) return; + + // Simple test for a jQuery element + $el.append(content.jquery ? content.clone() : content); + } + + function appendBody($body, $element, opt) { + // Clone for safety and convenience + // Calls clone(withDataAndEvents = true) to copy form values. + var $content = $element.clone(); + + if (opt.printContainer) { + // grab $.selector as container + $content.appendTo($body); + } else { + // otherwise just print interior elements of container + $content.each(function() { + $(this).children().appendTo($body) + }); + } + } + + var opt; + $.fn.printThis = function(options) { + opt = $.extend({}, $.fn.printThis.defaults, options); + var $element = this instanceof jQuery ? this : $(this); + + var strFrameName = "printThis-" + (new Date()).getTime(); + + if (window.location.hostname !== document.domain && navigator.userAgent.match(/msie/i)) { + // Ugly IE hacks due to IE not inheriting document.domain from parent + // checks if document.domain is set by comparing the host name against document.domain + var iframeSrc = 'javascript:document.write("")'; + var printI = document.createElement('iframe'); + printI.name = "printIframe"; + printI.id = strFrameName; + printI.className = "MSIE"; + document.body.appendChild(printI); + printI.src = iframeSrc; + + } else { + // other browsers inherit document.domain, and IE works if document.domain is not explicitly set + var $frame = $("'); + }, + + /** + * 初始化缓存地址 + * @param clearUrl + */ + renderClear: function (clearUrl) { + $('.layuimini-clear').attr('data-href', clearUrl); + }, + + /** + * 初始化iframe窗口动画 + * @param anim + */ + renderAnim: function (anim) { + if (anim) { + $('#layuimini-bg-color').after(''); + } + }, + /** + * 进入全屏 + */ + fullScreen: function () { + var el = document.documentElement; + var rfs = el.requestFullScreen || el.webkitRequestFullScreen; + if (typeof rfs != "undefined" && rfs) { + rfs.call(el); + } else if (typeof window.ActiveXObject != "undefined") { + var wscript = new ActiveXObject("WScript.Shell"); + if (wscript != null) { + wscript.SendKeys("{F11}"); + } + } else if (el.msRequestFullscreen) { + el.msRequestFullscreen(); + } else if (el.oRequestFullscreen) { + el.oRequestFullscreen(); + } else if (el.webkitRequestFullscreen) { + el.webkitRequestFullscreen(); + } else if (el.mozRequestFullScreen) { + el.mozRequestFullScreen(); + } else { + miniAdmin.error('浏览器不支持全屏调用!'); + } + }, + + /** + * 退出全屏 + */ + exitFullScreen: function () { + var el = document; + var cfs = el.cancelFullScreen || el.webkitCancelFullScreen || el.exitFullScreen; + if (typeof cfs != "undefined" && cfs) { + cfs.call(el); + } else if (typeof window.ActiveXObject != "undefined") { + var wscript = new ActiveXObject("WScript.Shell"); + if (wscript != null) { + wscript.SendKeys("{F11}"); + } + } else if (el.msExitFullscreen) { + el.msExitFullscreen(); + } else if (el.oRequestFullscreen) { + el.oCancelFullScreen(); + } else if (el.mozCancelFullScreen) { + el.mozCancelFullScreen(); + } else if (el.webkitCancelFullScreen) { + el.webkitCancelFullScreen(); + } else { + miniAdmin.error('浏览器不支持全屏调用!'); + } + }, + + /** + * 初始化设备端 + */ + renderDevice: function () { + if (miniAdmin.checkMobile()) { + $('.layuimini-tool i').attr('data-side-fold', 1); + $('.layuimini-tool i').attr('class', 'fa fa-outdent'); + $('.layui-layout-body').removeClass('layuimini-mini'); + $('.layui-layout-body').addClass('layuimini-all'); + } + }, + + + /** + * 初始化加载时间 + * @param loadingTime + */ + deleteLoader: function (loadingTime) { + setTimeout(function () { + $('.layuimini-loader').fadeOut(); + }, loadingTime * 1000) + }, + + /** + * 成功 + * @param title + * @returns {*} + */ + success: function (title) { + return layer.msg(title, { icon: 1, shade: this.shade, scrollbar: false, time: 2000, shadeClose: true }); + }, + + /** + * 失败 + * @param title + * @returns {*} + */ + error: function (title) { + return layer.msg(title, { icon: 2, shade: this.shade, scrollbar: false, time: 3000, shadeClose: true }); + }, + + /** + * 判断是否为手机 + * @returns {boolean} + */ + checkMobile: function () { + var ua = navigator.userAgent.toLocaleLowerCase(); + var pf = navigator.platform.toLocaleLowerCase(); + var isAndroid = (/android/i).test(ua) || ((/iPhone|iPod|iPad/i).test(ua) && (/linux/i).test(pf)) + || (/ucweb.*linux/i.test(ua)); + var isIOS = (/iPhone|iPod|iPad/i).test(ua) && !isAndroid; + var isWinPhone = (/Windows Phone|ZuneWP7/i).test(ua); + var clientWidth = document.documentElement.clientWidth; + if (!isAndroid && !isIOS && !isWinPhone && clientWidth > 1024) { + return false; + } else { + return true; + } + }, + + /** + * 监听 + */ + listen: function () { + + /** + * 清理 + */ + $('body').on('click', '[data-clear]', function () { + var loading = layer.load(0, { shade: false, time: 2 * 1000 }); + sessionStorage.clear(); + + // 判断是否清理服务端 + var clearUrl = $(this).attr('data-href'); + if (clearUrl != undefined && clearUrl != '' && clearUrl != null) { + $.getJSON(clearUrl, function (data, status) { + layer.close(loading); + if (data.code != 1) { + return miniAdmin.error(data.msg); + } else { + miniAdmin.success(data.msg); + var setTime1 = setTimeout(function () { + clearTimeout(setTime1); + window.location.href = document.location.origin + '/Login/Index'; + }, 300); + + return false; + } + }).fail(function () { + layer.close(loading); + return miniAdmin.error('清理缓存接口有误'); + }); + } else { + layer.close(loading); + return miniAdmin.success(data.msg); + } + }); + /** + * 主页 + */ + $('body').on('click', '[data-tohome]', function () { + miniTab.openNewTabByIframe({ + title: "主页", + href: sessionStorage.getItem('layuiminiHomeHref') + }); + }); + /** + * 消息 + */ + $('body').on('click', '[data-notice]', function () { + var loading = layer.load(0, { shade: false, time: 2 * 1000 }); + var clientHeight = (document.documentElement.clientHeight) - 60; + layer.open({ + type: 2, + title: false, + closeBtn: 0, + shade: 0.2, + anim: 2, + shadeClose: true, + id: 'layuiMessage', + area: ['250px', clientHeight + 'px'],//带私信宽度340px + offset: 'rb', + content: '/Home/Message', + success: function (index, layero) { + $(layero).addClass("scroll-wrapper");//苹果 iframe 滚动条失效解决方式 + }, + end: function () { + $('.layui-icon-notice').empty(); + } + }); + layer.close(loading); + }); + /** + * 刷新 + */ + $('body').on('click', '[data-refresh]', function () { + $(".layui-tab-item.layui-show").find("iframe")[0].contentWindow.location.reload(); + miniAdmin.success('刷新成功'); + }); + + /** + * 监听提示信息 + */ + $("body").on("mouseenter", ".layui-nav-tree .menu-li", function () { + if (miniAdmin.checkMobile()) { + return false; + } + var classInfo = $(this).attr('class'), + tips = $(this).prop("innerHTML"), + isShow = $('.layuimini-tool i').attr('data-side-fold'); + if (isShow == 0 && tips) { + tips = "
                • " + tips + "
                "; + window.openTips = layer.tips(tips, $(this), { + tips: [2, '#2f4056'], + time: 300000, + skin: "popup-tips", + success: function (el) { + var left = $(el).position().left - 10; + $(el).css({ left: left }); + element.render(); + } + }); + } + }); + + $("body").on("mouseleave", ".popup-tips", function () { + if (miniAdmin.checkMobile()) { + return false; + } + var isShow = $('.layuimini-tool i').attr('data-side-fold'); + if (isShow == 0) { + try { + layer.close(window.openTips); + } catch (e) { + console.log(e.message); + } + } + }); + + + /** + * 全屏 + */ + $('body').on('click', '[data-check-screen]', function () { + var check = $(this).attr('data-check-screen'); + if (check == 'full') { + miniAdmin.fullScreen(); + $(this).attr('data-check-screen', 'exit'); + $(this).html(''); + } else { + miniAdmin.exitFullScreen(); + $(this).attr('data-check-screen', 'full'); + $(this).html(''); + } + }); + + /** + * 点击遮罩层 + */ + $('body').on('click', '.layuimini-make', function () { + miniAdmin.renderDevice(); + }); + + } + }; + + + exports("miniAdmin", miniAdmin); +}); \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/layuimini/miniMenu.js b/WaterCloud.Web/wwwroot/js/lay-module/layuimini/miniMenu.js new file mode 100644 index 0000000..9359195 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/layuimini/miniMenu.js @@ -0,0 +1,263 @@ +/** + * date:2020/02/27 + * author:Mr.Chung + * version:2.0 + * description:layuimini 菜单框架扩展 + */ +layui.define(["element", "laytpl", "jquery"], function (exports) { + var element = layui.element, + $ = layui.$, + laytpl = layui.laytpl, + layer = layui.layer; + + var miniMenu = { + + /** + * 菜单初始化 + * @param options.menuList 菜单数据信息 + * @param options.multiModule 是否开启多模块 + * @param options.menuChildOpen 是否展开子菜单 + * @param options.menuOpen 是否缩放 + */ + render: function (options) { + options.menuList = options.menuList || []; + options.multiModule = options.multiModule || false; + options.menuChildOpen = options.menuChildOpen || false; + options.menuOpen = options.menuOpen || false; + if (options.multiModule) { + miniMenu.renderMultiModule(options.menuList, options.menuChildOpen); + } else { + miniMenu.renderSingleModule(options.menuList, options.menuChildOpen); + } + miniMenu.listen(); + if (options.menuOpen) { + $('.layuimini-tool [data-side-fold]').attr('data-side-fold', 0); + $('.layuimini-tool [data-side-fold]').attr('class', 'fa fa-indent'); + $('.layuimini-tool [data-side-fold]').attr('title', '展开'); + $('.layui-layout-body').removeClass('layuimini-all'); + $('.layui-layout-body').addClass('layuimini-mini'); + } + }, + + /** + * 单模块 + * @param menuList 菜单数据 + * @param menuChildOpen 是否默认展开 + */ + renderSingleModule: function (menuList, menuChildOpen) { + menuList = menuList || []; + var leftMenuHtml = '', + childOpenClass = '', + leftMenuCheckDefault = 'layui-this'; + var me = this; + if (menuChildOpen) childOpenClass = ' layui-nav-itemed'; + leftMenuHtml = this.renderLeftMenu(menuList, { childOpenClass: childOpenClass }); + $('.layui-layout-body').addClass('layuimini-single-module'); //单模块标识 + $('.layuimini-header-menu').remove(); + $('.layuimini-menu-left').html(leftMenuHtml); + + element.init(); + }, + + /** + * 渲染一级菜单 + */ + compileMenu: function (menu, isSub) { + var menuHtml = ''; + if (isSub) { + menuHtml = '' + } + return laytpl(menuHtml).render(menu); + }, + compileMenuContainer: function (menu, isSub) { + var wrapperHtml = '
                  {{- d.children}}
                '; + if (isSub) { + wrapperHtml = '
                {{- d.children}}
                '; + } + if (!menu.children) { + return ""; + } + return laytpl(wrapperHtml).render(menu); + }, + + each: function (list, callback) { + var _list = []; + for (var i = 0, length = list.length; i < length; i++) { + _list[i] = callback(i, list[i]); + } + return _list; + }, + renderChildrenMenu: function (menuList, options) { + var me = this; + menuList = menuList || []; + var html = this.each(menuList, function (idx, menu) { + if (menu.child && menu.child.length) { + menu.children = me.renderChildrenMenu(menu.child, { childOpenClass: options.childOpenClass || '' }); + } + menu.className = ""; + menu.childOpenClass = options.childOpenClass || '' + return me.compileMenu(menu, true) + }).join(""); + return me.compileMenuContainer({ children: html }, true) + }, + renderLeftMenu: function (leftMenus, options) { + options = options || {}; + var me = this; + var leftMenusHtml = me.each(leftMenus || [], function (idx, leftMenu) { // 左侧菜单遍历 + var children = me.renderChildrenMenu(leftMenu.child, { childOpenClass: options.childOpenClass }); + var leftMenuHtml = me.compileMenu({ + href: leftMenu.href, + target: leftMenu.target, + childOpenClass: options.childOpenClass, + icon: leftMenu.icon, + title: leftMenu.title, + children: children, + className: '', + }); + return leftMenuHtml; + }).join(""); + + leftMenusHtml = me.compileMenuContainer({ id: options.parentMenuId, className: options.leftMenuCheckDefault, children: leftMenusHtml }); + return leftMenusHtml; + }, + /** + * 多模块 + * @param menuList 菜单数据 + * @param menuChildOpen 是否默认展开 + */ + renderMultiModule: function (menuList, menuChildOpen) { + menuList = menuList || []; + var me = this; + var headerMenuHtml = '', + headerMobileMenuHtml = '', + leftMenuHtml = '', + leftMenuCheckDefault = 'layui-this', + childOpenClass = '', + headerMenuCheckDefault = 'layui-this'; + + if (menuChildOpen) childOpenClass = ' layui-nav-itemed'; + var headerMenuHtml = this.each(menuList, function (index, val) { //顶部菜单渲染 + var menu = 'multi_module_' + index; + var id = menu + "HeaderId"; + var topMenuItemHtml = ""; + topMenuItemHtml = me.compileMenu({ + className: headerMenuCheckDefault, + menu: menu, + id: id, + title: val.title, + href: "", + target: "", + children: "" + }); + leftMenuHtml += me.renderLeftMenu(val.child, { + parentMenuId: menu, + childOpenClass: childOpenClass, + leftMenuCheckDefault: leftMenuCheckDefault + }); + headerMobileMenuHtml += me.compileMenu({ id: id, menu: menu, id: id, icon: val.icon, title: val.title, }, true); + headerMenuCheckDefault = ""; + leftMenuCheckDefault = "layui-hide"; + return topMenuItemHtml; + }).join(""); + $('.layui-layout-body').addClass('layuimini-multi-module'); //多模块标识 + $('.layuimini-menu-header-pc').html(headerMenuHtml); //电脑 + $('.layuimini-menu-left').html(leftMenuHtml); + $('.layuimini-menu-header-mobile').html(headerMobileMenuHtml); //手机 + element.init(); + }, + + /** + * 监听 + */ + listen: function () { + + /** + * 菜单模块切换 + */ + $('body').on('click', '[data-menu]', function () { + var loading = layer.load(0, { shade: false, time: 2 * 1000 }); + var menuId = $(this).attr('data-menu'); + // header + $(".layuimini-header-menu .layui-nav-item.layui-this").removeClass('layui-this'); + $(this).addClass('layui-this'); + // left + $(".layuimini-menu-left .layui-nav.layui-nav-tree.layui-this").addClass('layui-hide'); + $(".layuimini-menu-left .layui-nav.layui-nav-tree.layui-this.layui-hide").removeClass('layui-this'); + $("#" + menuId).removeClass('layui-hide'); + $("#" + menuId).addClass('layui-this'); + layer.close(loading); + }); + + /** + * 菜单缩放 + */ + $('body').on('click', '.layuimini-site-mobile', function () { + var loading = layer.load(0, { shade: false, time: 2 * 1000 }); + var isShow = $('.layuimini-tool [data-side-fold]').attr('data-side-fold'); + if (isShow == 1) { // 缩放 + $('.layuimini-tool [data-side-fold]').attr('data-side-fold', 0); + $('.layuimini-tool [data-side-fold]').attr('class', 'fa fa-indent'); + $('.layuimini-tool [data-side-fold]').attr('title', '展开'); + $('.layui-layout-body').removeClass('layuimini-all'); + $('.layui-layout-body').addClass('layuimini-mini'); + } else { // 正常 + $('.layuimini-tool [data-side-fold]').attr('data-side-fold', 1); + $('.layuimini-tool [data-side-fold]').attr('class', 'fa fa-outdent'); + $('.layuimini-tool [data-side-fold]').attr('title', '缩放'); + $('.layui-layout-body').removeClass('layuimini-mini'); + $('.layui-layout-body').addClass('layuimini-all'); + layer.close(window.openTips); + } + element.init(); + layer.close(loading); + }); + /** + * 菜单缩放 + */ + $('body').on('click', '[data-side-fold]', function () { + var loading = layer.load(0, { shade: false, time: 2 * 1000 }); + var isShow = $('.layuimini-tool [data-side-fold]').attr('data-side-fold'); + if (isShow == 1) { // 缩放 + $('.layuimini-tool [data-side-fold]').attr('data-side-fold', 0); + $('.layuimini-tool [data-side-fold]').attr('class', 'fa fa-indent'); + $('.layuimini-tool [data-side-fold]').attr('title', '展开'); + $('.layui-layout-body').removeClass('layuimini-all'); + $('.layui-layout-body').addClass('layuimini-mini'); + // $(".menu-li").each(function (idx,el) { + // $(el).addClass("hidden-sub-menu"); + // }); + + } else { // 正常 + $('.layuimini-tool [data-side-fold]').attr('data-side-fold', 1); + $('.layuimini-tool [data-side-fold]').attr('class', 'fa fa-outdent'); + $('.layuimini-tool [data-side-fold]').attr('title', '缩放'); + $('.layui-layout-body').removeClass('layuimini-mini'); + $('.layui-layout-body').addClass('layuimini-all'); + // $(".menu-li").each(function (idx,el) { + // $(el).removeClass("hidden-sub-menu"); + // }); + layer.close(window.openTips); + } + element.init(); + layer.close(loading); + }); + + /** + * 手机端点开模块 + */ + $('body').on('click', '.layuimini-header-menu.layuimini-mobile-show dd', function () { + var loading = layer.load(0, { shade: false, time: 2 * 1000 }); + var check = $('.layuimini-tool [data-side-fold]').attr('data-side-fold'); + if (check === "1") { + $('.layuimini-site-mobile').trigger("click"); + element.init(); + } + layer.close(loading); + }); + }, + + }; + + + exports("miniMenu", miniMenu); +}); \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/layuimini/miniTab.js b/WaterCloud.Web/wwwroot/js/lay-module/layuimini/miniTab.js new file mode 100644 index 0000000..7106c2f --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/layuimini/miniTab.js @@ -0,0 +1,647 @@ +/** + * date:2020/02/27 + * author:Mr.Chung + * version:2.0 + * description:layuimini tab框架扩展 + */ +layui.define(["element", "layer", "jquery"], function (exports) { + var element = layui.element, + layer = layui.layer, + $ = layui.$; + + + var miniTab = { + + /** + * 初始化tab + * @param options + */ + render: function (options) { + options.filter = options.filter || null; + options.multiModule = options.multiModule || false; + options.urlHashLocation = options.urlHashLocation || false; + options.maxTabNum = options.maxTabNum || 20; + options.menuList = options.menuList || []; // todo 后期菜单想改为不操作dom, 而是直接操作初始化传过来的数据 + options.homeInfo = options.homeInfo || {}; + options.listenSwichCallback = options.listenSwichCallback || function () { + }; + miniTab.listen(options); + miniTab.listenRoll(); + miniTab.listenSwitch(options); + miniTab.listenHash(options); + }, + + /** + * 新建tab窗口 + * @param options.tabId + * @param options.href + * @param options.title + * @param options.isIframe + * @param options.maxTabNum + */ + create: function (options) { + options.tabId = options.tabId || null; + options.href = options.href || null; + options.title = options.title || null; + options.isIframe = options.isIframe || false; + options.maxTabNum = options.maxTabNum || 20; + if (top.$(".layuimini-tab .layui-tab-title li").length >= options.maxTabNum) { + layer.msg('Tab窗口已达到限定数量,请先关闭部分Tab'); + return false; + } + if (top.$(".layuimini-tab").length == 0) { + window.open(options.href, "_blank"); + } + else { + var ele = element; + if (options.isIframe) ele = parent.layui.element; + ele.tabAdd('layuiminiTab', { + title: '' + options.title + '' //用于演示 + , content: '' + , id: options.tabId + }); + $('.layuimini-menu-left').attr('layuimini-tab-tag', 'add'); + } + var name = 'layuiminimenu_list'+"="; + var datajson = {}; + var ca = document.cookie.split(';'); + for (var i = 0; i < ca.length; i++) { + var c = ca[i].trim(); + if (c.indexOf(name) == 0) datajson =JSON.parse(unescape(c.substring(name.length, c.length))); + } + if (!datajson[options.tabId]) { + datajson[options.tabId] = options.title.trim(); + var d = new Date(); + d.setTime(d.getTime() + (1 * 24 * 60 * 60 * 1000)); + var expires = "expires=" + d.toGMTString(); + document.cookie = 'layuiminimenu_list' + "=" + escape(JSON.stringify(datajson)) + ";" + "path=/;" + expires; + } + }, + + + /** + * 切换选项卡 + * @param tabId + */ + change: function (tabId) { + element.tabChange('layuiminiTab', tabId); + }, + + /** + * 删除tab窗口 + * @param tabId + * @param isParent + */ + delete: function (tabId, isParent) { + // todo 未知BUG,不知道是不是layui问题,必须先删除元素 + $(".layuimini-tab .layui-tab-title .layui-unselect.layui-tab-bar").remove(); + + if (isParent === true) { + parent.layui.element.tabDelete('layuiminiTab', tabId); + } else { + element.tabDelete('layuiminiTab', tabId); + } + }, + + /** + * 在iframe层打开新tab方法 + */ + openNewTabByIframe: function (options) { + options.href = options.href || null; + options.title = options.title || null; + var loading = parent.layer.load(0, { shade: false, time: 2 * 1000 }); + if (options.href === null || options.href === undefined) options.href = new Date().getTime(); + var checkTab = miniTab.check(options.href.split("?")[0], true); + if (!checkTab) { + miniTab.create({ + tabId: options.href.split("?")[0], + href: options.href, + title: options.title, + isIframe: true, + }); + } + parent.layui.element.tabChange('layuiminiTab', options.href.split("?")[0]); + parent.layer.close(loading); + }, + + /** + * 在iframe层关闭当前tab方法 + */ + deleteCurrentByIframe: function () { + var ele = $(".layuimini-tab .layui-tab-title li.layui-this", parent.document); + if (ele.length > 0) { + var layId = $(ele[0]).attr('lay-id'); + miniTab.delete(layId, true); + } + }, + + /** + * 判断tab窗口 + */ + check: function (tabId, isIframe) { + // 判断选项卡上是否有 + var checkTab = false; + if (isIframe === undefined || isIframe === false) { + $(".layui-tab-title li").each(function () { + var checkTabId = $(this).attr('lay-id'); + if (checkTabId != null && checkTabId === tabId) { + checkTab = true; + } + }); + } else { + parent.layui.$(".layui-tab-title li").each(function () { + var checkTabId = $(this).attr('lay-id'); + if (checkTabId != null && checkTabId === tabId) { + checkTab = true; + } + }); + } + return checkTab; + }, + + /** + * 开启tab右键菜单 + * @param tabId + * @param left + */ + openTabRignMenu: function (tabId, left) { + miniTab.closeTabRignMenu(); + var menuHtml = '
                \n' + + '
                \n' + + '
                刷新当前
                \n' + + '
                关闭当前
                \n' + + '
                关闭其他
                \n' + + '
                关闭全部
                \n' + + '
                \n' + + '
                '; + var makeHtml = '
                '; + $('.layuimini-tab .layui-tab-title').after(menuHtml); + $('.layuimini-tab .layui-tab-content').after(makeHtml); + }, + + /** + * 关闭tab右键菜单 + */ + closeTabRignMenu: function () { + $('.layuimini-tab-mousedown').remove(); + $('.layuimini-tab-make').remove(); + }, + + /** + * 查询菜单信息 + * @param href + * @param menuList + */ + searchMenu: function (href, menuList) { + var menu; + for (key in menuList) { + var item = menuList[key]; + if (item.href === href) { + menu = item; + break; + } + if (item.child) { + newMenu = miniTab.searchMenu(href, item.child); + if (newMenu) { + menu = newMenu; + break; + } + } + } + return menu; + }, + + /** + * 监听 + * @param options + */ + listen: function (options) { + options = options || {}; + options.maxTabNum = options.maxTabNum || 20; + + /** + * 打开新窗口 + */ + $('body').on('click', '[layuimini-href]', function () { + var loading = layer.load(0, { shade: false, time: 2 * 1000 }); + var tabId = $(this).attr('layuimini-href'), + href = $(this).attr('layuimini-href'), + title = $(this).text(), + target = $(this).attr('target'); + + var el = $("[layuimini-href='" + href + "']", ".layuimini-menu-left"); + layer.close(window.openTips); + if (el.length) { + $(el).closest(".layui-nav-tree").find(".layui-this").removeClass("layui-this"); + $(el).parent().addClass("layui-this"); + } + + if (target === '_blank') { + layer.close(loading); + window.open(href, "_blank"); + return false; + } + if (target === '_open') { + layer.close(loading); + layer.open({ + type: 2, + title: title, + isOutAnim: true,//关闭动画 + maxmin: true, //开启最大化最小化按钮 + fix: false, + area: ['500px', '500px'], + content: href, + success: function (layero) { + $(layero).addClass("scroll-wrapper");//苹果 iframe 滚动条失效解决方式 + } + }); + return false; + } + if (tabId === null || tabId === undefined) tabId = new Date().getTime(); + var checkTab = miniTab.check(tabId); + if (!checkTab) { + miniTab.create({ + tabId: tabId, + href: href, + title: title, + isIframe: false, + maxTabNum: options.maxTabNum, + }); + } + element.tabChange('layuiminiTab', tabId); + layer.close(loading); + }); + + /** + * 在iframe子菜单上打开新窗口 + */ + $('body').on('click', '[layuimini-content-href]', function () { + var loading = parent.layer.load(0, { shade: false, time: 2 * 1000 }); + var tabId = $(this).attr('layuimini-content-href'), + href = $(this).attr('layuimini-content-href'), + title = $(this).attr('data-title'), + target = $(this).attr('target'); + if (target === '_blank') { + parent.layer.close(loading); + window.open(href, "_blank"); + return false; + } + if (tabId === null || tabId === undefined) tabId = new Date().getTime(); + var checkTab = miniTab.check(tabId, true); + if (!checkTab) { + miniTab.create({ + tabId: tabId, + href: href, + title: title, + isIframe: true, + maxTabNum: options.maxTabNum, + }); + } + parent.layui.element.tabChange('layuiminiTab', tabId); + parent.layer.close(loading); + }); + + /** + * 关闭选项卡 + **/ + $('body').on('click', '.layuimini-tab .layui-tab-title .layui-tab-close', function () { + var loading = layer.load(0, { shade: false, time: 2 * 1000 }); + var $parent = $(this).parent(); + var tabId = $parent.attr('lay-id'); + if (tabId !== undefined || tabId !== null) { + miniTab.delete(tabId); + } + layer.close(loading); + }); + + /** + * 选项卡操作 + */ + $('body').on('click', '[layuimini-tab-close]', function () { + var loading = layer.load(0, { shade: false, time: 2 * 1000 }); + var closeType = $(this).attr('layuimini-tab-close'); + top.$(".layuimini-tab .layui-tab-title li").each(function () { + var tabId = $(this).attr('lay-id'); + var id = $(this).attr('id'); + var isCurrent = $(this).hasClass('layui-this'); + if (id !== 'layuiminiHomeTabId') { + if (closeType === 'all') { + miniTab.delete(tabId); + } else { + if (closeType === 'current' && isCurrent) { + miniTab.delete(tabId); + } else if (closeType === 'other' && !isCurrent) { + miniTab.delete(tabId); + } + } + } + }); + layer.close(loading); + }); + + /** + * 禁用网页右键 + */ + $(".layuimini-tab .layui-tab-title").unbind("mousedown").bind("contextmenu", function (e) { + e.preventDefault(); + return false; + }); + + /** + * 注册鼠标右键 + */ + $('body').on('mousedown', '.layuimini-tab .layui-tab-title li', function (e) { + var left = $(this).offset().left - $('.layuimini-tab ').offset().left + ($(this).width() / 2), + tabId = $(this).attr('lay-id'); + if (e.which === 3) { + miniTab.openTabRignMenu(tabId, left); + } + }); + + /** + * 关闭tab右键菜单 + */ + $('body').on('click', '.layui-body,.layui-header,.layuimini-menu-left,.layuimini-tab-make', function () { + miniTab.closeTabRignMenu(); + }); + + /** + * tab右键选项卡操作 + */ + $('body').on('click', '[layuimini-tab-menu-close]', function () { + var loading = layer.load(0, { shade: false, time: 2 * 1000 }); + var closeType = $(this).attr('layuimini-tab-menu-close'), + currentTabId = $('.layuimini-tab-mousedown').attr('data-tab-id'); + $(".layuimini-tab .layui-tab-title li").each(function () { + var tabId = $(this).attr('lay-id'); + var id = $(this).attr('id'); + if (id !== 'layuiminiHomeTabId') { + if (closeType === 'all') { + miniTab.delete(tabId); + } else { + if (closeType === 'current' && currentTabId === tabId) { + miniTab.delete(tabId); + } else if (closeType === 'other' && currentTabId !== tabId) { + miniTab.delete(tabId); + } + } + } + }); + miniTab.closeTabRignMenu(); + layer.close(loading); + }); + }, + + /** + * 监听tab切换 + * @param options + */ + listenSwitch: function (options) { + options.filter = options.filter || null; + options.multiModule = options.multiModule || false; + options.urlHashLocation = options.urlHashLocation || false; + options.listenSwichCallback = options.listenSwichCallback || function () { + + }; + element.on('tab(' + options.filter + ')', function (data) { + var tabId = $(this).attr('lay-id'); + if (options.urlHashLocation) { + location.hash = '/' + tabId; + } + if (tabId != options.homeInfo.href) { + var d = new Date(); + d.setTime(d.getTime() + (1 * 24 * 60 * 60 * 1000)); + var expires = "expires=" + d.toGMTString(); + document.cookie = 'wc_returnurl' + "=" + tabId + ";" + "path=/;" + expires; + } + if (typeof options.listenSwichCallback === 'function') { + options.listenSwichCallback(); + } + // 判断是否为新增窗口 + if ($('.layuimini-menu-left').attr('layuimini-tab-tag') === 'add') { + $('.layuimini-menu-left').attr('layuimini-tab-tag', 'no') + } else { + $("[layuimini-href]").parent().removeClass('layui-this'); + if (options.multiModule) { + miniTab.listenSwitchMultiModule(tabId); + } else { + miniTab.listenSwitchSingleModule(tabId); + } + //切换tab刷新table表单的样式 + // 获取到对应的iframe中table对象集合 + var frames = window.frames[data.index]; + if (frames) { + var tableDoms = frames.document.getElementsByTagName('table'); + for (var i = 0; i < tableDoms.length; i++) { + var tableDom = tableDoms[i]; + // 判断是否存在对应对象以及是否存在table的id属性 + if (tableDom !== undefined && tableDom.id !== undefined && tableDom.id !== '') { + // 存在则获取iframe元素的Window对象 + var iframe = $('iframe[src^="' + tabId + '"]')[0].contentWindow; + // 调用resize + iframe.layui.table.resize(tableDom.id); + } + } + } + } + miniTab.rollPosition(); + }); + }, + + /** + * 监听hash变化 + * @param options + * @returns {boolean} + */ + listenHash: function (options) { + options.urlHashLocation = options.urlHashLocation || false; + options.maxTabNum = options.maxTabNum || 20; + options.homeInfo = options.homeInfo || {}; + options.menuList = options.menuList || []; + if (!options.urlHashLocation) return false; + var tabId = location.hash.replace(/^#\//, ''); + if (tabId === null || tabId === undefined || tabId === '') return false; + + // 判断是否为首页 + if (tabId === options.homeInfo.href) return false; + + // 判断是否为右侧菜单 + var menu = miniTab.searchMenu(tabId, options.menuList); + if (menu !== undefined) { + miniTab.create({ + tabId: tabId, + href: tabId, + title: menu.title, + isIframe: false, + maxTabNum: options.maxTabNum, + }); + $('.layuimini-menu-left').attr('layuimini-tab-tag', 'no'); + element.tabChange('layuiminiTab', tabId); + return false; + } + + // 判断是否为快捷菜单 + var isSearchMenu = false; + $("[layuimini-content-href]").each(function () { + if ($(this).attr("layuimini-content-href") === tabId) { + var title = $(this).attr("data-title"); + miniTab.create({ + tabId: tabId, + href: tabId, + title: title, + isIframe: false, + maxTabNum: options.maxTabNum, + }); + $('.layuimini-menu-left').attr('layuimini-tab-tag', 'no'); + element.tabChange('layuiminiTab', tabId); + isSearchMenu = true; + return false; + } + }); + if (isSearchMenu) return false; + + // 既不是右侧菜单、快捷菜单,就直接打开 + var name = 'layuiminimenu_list'+ "="; + var title = tabId; + var datajson = {}; + var ca = document.cookie.split(';'); + for (var i = 0; i < ca.length; i++) { + var c = ca[i].trim(); + if (c.indexOf(name) == 0) datajson =JSON.parse(unescape(c.substring(name.length, c.length))); + } + if (!!datajson[tabId]) { + var title = datajson[tabId]; + } + miniTab.create({ + tabId: tabId, + href: tabId, + title: title, + isIframe: false, + maxTabNum: options.maxTabNum, + }); + element.tabChange('layuiminiTab', tabId); + return false; + }, + + /** + * 监听滚动 + */ + listenRoll: function () { + $(".layuimini-tab-roll-left").click(function () { + miniTab.rollClick("left"); + }); + $(".layuimini-tab-roll-right").click(function () { + miniTab.rollClick("right"); + }); + }, + + /** + * 单模块切换 + * @param tabId + */ + listenSwitchSingleModule: function (tabId) { + $("[layuimini-href]").each(function () { + if ($(this).attr("layuimini-href") === tabId) { + // 自动展开菜单栏 + var addMenuClass = function ($element, type) { + if (type === 1) { + $element.addClass('layui-this'); + if ($element.hasClass('layui-nav-item') && $element.hasClass('layui-this')) { + $(".layuimini-header-menu li").attr('class', 'layui-nav-item'); + } else { + addMenuClass($element.parent().parent(), 2); + } + } else { + $element.addClass('layui-nav-itemed'); + if ($element.hasClass('layui-nav-item') && $element.hasClass('layui-nav-itemed')) { + $(".layuimini-header-menu li").attr('class', 'layui-nav-item'); + } else { + addMenuClass($element.parent().parent(), 2); + } + } + }; + addMenuClass($(this).parent(), 1); + return false; + } + }); + }, + + /** + * 多模块切换 + * @param tabId + */ + listenSwitchMultiModule: function (tabId) { + $("[layuimini-href]").each(function () { + if ($(this).attr("layuimini-href") === tabId) { + + // 自动展开菜单栏 + var addMenuClass = function ($element, type) { + if (type === 1) { + $element.addClass('layui-this'); + if ($element.hasClass('layui-nav-item') && $element.hasClass('layui-this')) { + var moduleId = $element.parent().attr('id'); + $(".layuimini-header-menu li").attr('class', 'layui-nav-item'); + $("#" + moduleId + "HeaderId").addClass("layui-this"); + $(".layuimini-menu-left .layui-nav.layui-nav-tree").attr('class', 'layui-nav layui-nav-tree layui-hide'); + $("#" + moduleId).attr('class', 'layui-nav layui-nav-tree layui-this'); + } else { + addMenuClass($element.parent().parent(), 2); + } + } else { + $element.addClass('layui-nav-itemed'); + if ($element.hasClass('layui-nav-item') && $element.hasClass('layui-nav-itemed')) { + var moduleId = $element.parent().attr('id'); + $(".layuimini-header-menu li").attr('class', 'layui-nav-item'); + $("#" + moduleId + "HeaderId").addClass("layui-this"); + $(".layuimini-menu-left .layui-nav.layui-nav-tree").attr('class', 'layui-nav layui-nav-tree layui-hide'); + $("#" + moduleId).attr('class', 'layui-nav layui-nav-tree layui-this'); + } else { + addMenuClass($element.parent().parent(), 2); + } + } + }; + addMenuClass($(this).parent(), 1); + return false; + } + }); + }, + + /** + * 自动定位 + */ + rollPosition: function () { + var $tabTitle = $('.layuimini-tab .layui-tab-title'); + var autoLeft = 0; + $tabTitle.children("li").each(function () { + if ($(this).hasClass('layui-this')) { + return false; + } else { + autoLeft += $(this).outerWidth(); + } + }); + $tabTitle.animate({ + scrollLeft: autoLeft - $tabTitle.width() / 3 + }, 200); + }, + + /** + * 点击滚动 + * @param direction + */ + rollClick: function (direction) { + var $tabTitle = $('.layuimini-tab .layui-tab-title'); + var left = $tabTitle.scrollLeft(); + if ('left' === direction) { + $tabTitle.animate({ + scrollLeft: left - 450 + }, 200); + } else { + $tabTitle.animate({ + scrollLeft: left + 450 + }, 200); + } + } + + }; + exports("miniTab", miniTab); +}); diff --git a/WaterCloud.Web/wwwroot/js/lay-module/layuimini/miniTheme.js b/WaterCloud.Web/wwwroot/js/lay-module/layuimini/miniTheme.js new file mode 100644 index 0000000..9d9fd3a --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/layuimini/miniTheme.js @@ -0,0 +1,474 @@ +/** + * date:2020/02/28 + * author:Mr.Chung + * version:2.0 + * description:layuimini tab框架扩展 + */ +layui.define(["jquery", "layer"], function (exports) { + var $ = layui.$, + layer = layui.layer; + + var miniTheme = { + + /** + * 主题配置项 + * @param bgcolorId + * @returns {{headerLogo, menuLeftHover, headerRight, menuLeft, headerRightThis, menuLeftThis}|*|*[]} + */ + config: function (bgcolorId) { + var bgColorConfig = [ + { + headerRightBg: '#2D8CF0', //头部右侧背景色 + headerRightBgThis: '#0069b7', //头部右侧选中背景色, + headerRightColor: '#fafafa', //头部右侧字体颜色, + headerRightChildColor: '#676767', //头部右侧下拉字体颜色, + headerRightColorThis: '#ffffff', //头部右侧鼠标选中, + headerRightNavMore: '#fafafa', //头部右侧更多下拉颜色, + headerRightNavMoreBg: '#0069b7', //头部右侧更多下拉列表选中背景色, + headerRightNavMoreColor: '#ffffff', //头部右侧更多下拉列表字体色, + headerRightToolColor: '#bbe3df', //头部缩放按钮样式, + headerLogoBg: '#0069b7', //logo背景颜色, + headerLogoColor: '#ffffff', //logo字体颜色, + leftMenuNavMore: '#ffffff', //左侧菜单更多下拉样式, + leftMenuBg: '#28333E', //左侧菜单背景, + leftMenuBgThis: '#2D8CF0', //左侧菜单选中背景, + leftMenuChildBg: 'rgba(0,0,0,.3)', //左侧菜单子菜单背景, + leftMenuColor: '#ffffff', //左侧菜单字体颜色, + leftMenuColorThis: '#ffffff', //左侧菜单选中字体颜色, + tabActiveColor: '#2d8cf0', //tab选项卡选中颜色, + }, + { + headerRightBg: '#ffffff', //头部右侧背景色 + headerRightBgThis: '#e4e4e4', //头部右侧选中背景色, + headerRightColor: 'rgba(107, 107, 107, 0.7)', //头部右侧字体颜色, + headerRightChildColor: 'rgba(107, 107, 107, 0.7)', //头部右侧下拉字体颜色, + headerRightColorThis: '#565656', //头部右侧鼠标选中, + headerRightNavMore: 'rgba(160, 160, 160, 0.7)', //头部右侧更多下拉颜色, + headerRightNavMoreBg: '#1E9FFF', //头部右侧更多下拉列表选中背景色, + headerRightNavMoreColor: '#ffffff', //头部右侧更多下拉列表字体色, + headerRightToolColor: '#565656', //头部缩放按钮样式, + headerLogoBg: '#192027', //logo背景颜色, + headerLogoColor: '#ffffff', //logo字体颜色, + leftMenuNavMore: '#ffffff', //左侧菜单更多下拉样式, + leftMenuBg: '#28333E', //左侧菜单背景, + leftMenuBgThis: '#1E9FFF', //左侧菜单选中背景, + leftMenuChildBg: '#0c0f13', //左侧菜单子菜单背景, + leftMenuColor: '#ffffff', //左侧菜单字体颜色, + leftMenuColorThis: '#ffffff', //左侧菜单选中字体颜色, + tabActiveColor: '#1e9fff', //tab选项卡选中颜色, + }, + { + headerRightBg: '#23262e', //头部右侧背景色 + headerRightBgThis: '#0c0c0c', //头部右侧选中背景色, + headerRightColor: '#fafafa', //头部右侧字体颜色, + headerRightChildColor: '#676767', //头部右侧下拉字体颜色, + headerRightColorThis: '#ffffff', //头部右侧鼠标选中, + headerRightNavMore: '#fafafa', //头部右侧更多下拉颜色, + headerRightNavMoreBg: '#1aa094', //头部右侧更多下拉列表选中背景色, + headerRightNavMoreColor: '#ffffff', //头部右侧更多下拉列表字体色, + headerRightToolColor: '#bbe3df', //头部缩放按钮样式, + headerLogoBg: '#0c0c0c', //logo背景颜色, + headerLogoColor: '#ffffff', //logo字体颜色, + leftMenuNavMore: '#ffffff', //左侧菜单更多下拉样式, + leftMenuBg: '#23262e', //左侧菜单背景, + leftMenuBgThis: '#737373', //左侧菜单选中背景, + leftMenuChildBg: 'rgba(0,0,0,.3)', //左侧菜单子菜单背景, + leftMenuColor: '#ffffff', //左侧菜单字体颜色, + leftMenuColorThis: '#ffffff', //左侧菜单选中字体颜色, + tabActiveColor: '#23262e', //tab选项卡选中颜色, + }, + { + headerRightBg: '#ffa4d1', //头部右侧背景色 + headerRightBgThis: '#bf7b9d', //头部右侧选中背景色, + headerRightColor: '#fafafa', //头部右侧字体颜色, + headerRightChildColor: '#676767', //头部右侧下拉字体颜色, + headerRightColorThis: '#ffffff', //头部右侧鼠标选中, + headerRightNavMore: '#fafafa', //头部右侧更多下拉颜色, + headerRightNavMoreBg: '#ffa4d1', //头部右侧更多下拉列表选中背景色, + headerRightNavMoreColor: '#ffffff', //头部右侧更多下拉列表字体色, + headerRightToolColor: '#bbe3df', //头部缩放按钮样式, + headerLogoBg: '#e694bd', //logo背景颜色, + headerLogoColor: '#ffffff', //logo字体颜色, + leftMenuNavMore: '#ffffff', //左侧菜单更多下拉样式, + leftMenuBg: '#1f1f1f', //左侧菜单背景, + leftMenuBgThis: '#737373', //左侧菜单选中背景, + leftMenuChildBg: 'rgba(0,0,0,.3)', //左侧菜单子菜单背景, + leftMenuColor: '#ffffff', //左侧菜单字体颜色, + leftMenuColorThis: '#ffffff', //左侧菜单选中字体颜色, + tabActiveColor: '#ffa4d1', //tab选项卡选中颜色, + }, + { + headerRightBg: '#1aa094', //头部右侧背景色 + headerRightBgThis: '#197971', //头部右侧选中背景色, + headerRightColor: '#fafafa', //头部右侧字体颜色, + headerRightChildColor: '#676767', //头部右侧下拉字体颜色, + headerRightColorThis: '#ffffff', //头部右侧鼠标选中, + headerRightNavMore: '#fafafa', //头部右侧更多下拉颜色, + headerRightNavMoreBg: '#1aa094', //头部右侧更多下拉列表选中背景色, + headerRightNavMoreColor: '#ffffff', //头部右侧更多下拉列表字体色, + headerRightToolColor: '#bbe3df', //头部缩放按钮样式, + headerLogoBg: '#0c0c0c', //logo背景颜色, + headerLogoColor: '#ffffff', //logo字体颜色, + leftMenuNavMore: '#ffffff', //左侧菜单更多下拉样式, + leftMenuBg: '#23262e', //左侧菜单背景, + leftMenuBgThis: '#1aa094', //左侧菜单选中背景, + leftMenuChildBg: 'rgba(0,0,0,.3)', //左侧菜单子菜单背景, + leftMenuColor: '#ffffff', //左侧菜单字体颜色, + leftMenuColorThis: '#ffffff', //左侧菜单选中字体颜色, + tabActiveColor: '#1aa094', //tab选项卡选中颜色, + }, + { + headerRightBg: '#1e9fff', //头部右侧背景色 + headerRightBgThis: '#0069b7', //头部右侧选中背景色, + headerRightColor: '#fafafa', //头部右侧字体颜色, + headerRightChildColor: '#676767', //头部右侧下拉字体颜色, + headerRightColorThis: '#ffffff', //头部右侧鼠标选中, + headerRightNavMore: '#fafafa', //头部右侧更多下拉颜色, + headerRightNavMoreBg: '#1e9fff', //头部右侧更多下拉列表选中背景色, + headerRightNavMoreColor: '#ffffff', //头部右侧更多下拉列表字体色, + headerRightToolColor: '#bbe3df', //头部缩放按钮样式, + headerLogoBg: '#0c0c0c', //logo背景颜色, + headerLogoColor: '#ffffff', //logo字体颜色, + leftMenuNavMore: '#ffffff', //左侧菜单更多下拉样式, + leftMenuBg: '#1f1f1f', //左侧菜单背景, + leftMenuBgThis: '#1e9fff', //左侧菜单选中背景, + leftMenuChildBg: 'rgba(0,0,0,.3)', //左侧菜单子菜单背景, + leftMenuColor: '#ffffff', //左侧菜单字体颜色, + leftMenuColorThis: '#ffffff', //左侧菜单选中字体颜色, + tabActiveColor: '#1e9fff', //tab选项卡选中颜色, + }, + { + headerRightBg: '#ffb800', //头部右侧背景色 + headerRightBgThis: '#d09600', //头部右侧选中背景色, + headerRightColor: '#fafafa', //头部右侧字体颜色, + headerRightChildColor: '#676767', //头部右侧下拉字体颜色, + headerRightColorThis: '#ffffff', //头部右侧鼠标选中, + headerRightNavMore: '#fafafa', //头部右侧更多下拉颜色, + headerRightNavMoreBg: '#d09600', //头部右侧更多下拉列表选中背景色, + headerRightNavMoreColor: '#ffffff', //头部右侧更多下拉列表字体色, + headerRightToolColor: '#bbe3df', //头部缩放按钮样式, + headerLogoBg: '#243346', //logo背景颜色, + headerLogoColor: '#ffffff', //logo字体颜色, + leftMenuNavMore: '#ffffff', //左侧菜单更多下拉样式, + leftMenuBg: '#2f4056', //左侧菜单背景, + leftMenuBgThis: '#8593a7', //左侧菜单选中背景, + leftMenuChildBg: 'rgba(0,0,0,.3)', //左侧菜单子菜单背景, + leftMenuColor: '#ffffff', //左侧菜单字体颜色, + leftMenuColorThis: '#ffffff', //左侧菜单选中字体颜色, + tabActiveColor: '#ffb800', //tab选项卡选中颜色, + }, + { + headerRightBg: '#e82121', //头部右侧背景色 + headerRightBgThis: '#ae1919', //头部右侧选中背景色, + headerRightColor: '#fafafa', //头部右侧字体颜色, + headerRightChildColor: '#676767', //头部右侧下拉字体颜色, + headerRightColorThis: '#ffffff', //头部右侧鼠标选中, + headerRightNavMore: '#fafafa', //头部右侧更多下拉颜色, + headerRightNavMoreBg: '#ae1919', //头部右侧更多下拉列表选中背景色, + headerRightNavMoreColor: '#ffffff', //头部右侧更多下拉列表字体色, + headerRightToolColor: '#bbe3df', //头部缩放按钮样式, + headerLogoBg: '#0c0c0c', //logo背景颜色, + headerLogoColor: '#ffffff', //logo字体颜色, + leftMenuNavMore: '#ffffff', //左侧菜单更多下拉样式, + leftMenuBg: '#1f1f1f', //左侧菜单背景, + leftMenuBgThis: '#3b3f4b', //左侧菜单选中背景, + leftMenuChildBg: 'rgba(0,0,0,.3)', //左侧菜单子菜单背景, + leftMenuColor: '#ffffff', //左侧菜单字体颜色, + leftMenuColorThis: '#ffffff', //左侧菜单选中字体颜色, + tabActiveColor: '#e82121', //tab选项卡选中颜色, + }, + { + headerRightBg: '#963885', //头部右侧背景色 + headerRightBgThis: '#772c6a', //头部右侧选中背景色, + headerRightColor: '#fafafa', //头部右侧字体颜色, + headerRightChildColor: '#676767', //头部右侧下拉字体颜色, + headerRightColorThis: '#ffffff', //头部右侧鼠标选中, + headerRightNavMore: '#fafafa', //头部右侧更多下拉颜色, + headerRightNavMoreBg: '#772c6a', //头部右侧更多下拉列表选中背景色, + headerRightNavMoreColor: '#ffffff', //头部右侧更多下拉列表字体色, + headerRightToolColor: '#bbe3df', //头部缩放按钮样式, + headerLogoBg: '#243346', //logo背景颜色, + headerLogoColor: '#ffffff', //logo字体颜色, + leftMenuNavMore: '#ffffff', //左侧菜单更多下拉样式, + leftMenuBg: '#2f4056', //左侧菜单背景, + leftMenuBgThis: '#586473', //左侧菜单选中背景, + leftMenuChildBg: 'rgba(0,0,0,.3)', //左侧菜单子菜单背景, + leftMenuColor: '#ffffff', //左侧菜单字体颜色, + leftMenuColorThis: '#ffffff', //左侧菜单选中字体颜色, + tabActiveColor: '#963885', //tab选项卡选中颜色, + }, + { + headerRightBg: '#ffb800', //头部右侧背景色 + headerRightBgThis: '#d09600', //头部右侧选中背景色, + headerRightColor: '#fafafa', //头部右侧字体颜色, + headerRightChildColor: '#676767', //头部右侧下拉字体颜色, + headerRightColorThis: '#ffffff', //头部右侧鼠标选中, + headerRightNavMore: '#fafafa', //头部右侧更多下拉颜色, + headerRightNavMoreBg: '#d09600', //头部右侧更多下拉列表选中背景色, + headerRightNavMoreColor: '#ffffff', //头部右侧更多下拉列表字体色, + headerRightToolColor: '#bbe3df', //头部缩放按钮样式, + headerLogoBg: '#d09600', //logo背景颜色, + headerLogoColor: '#ffffff', //logo字体颜色, + leftMenuNavMore: '#ffffff', //左侧菜单更多下拉样式, + leftMenuBg: '#2f4056', //左侧菜单背景, + leftMenuBgThis: '#3b3f4b', //左侧菜单选中背景, + leftMenuChildBg: 'rgba(0,0,0,.3)', //左侧菜单子菜单背景, + leftMenuColor: '#ffffff', //左侧菜单字体颜色, + leftMenuColorThis: '#ffffff', //左侧菜单选中字体颜色, + tabActiveColor: '#ffb800', //tab选项卡选中颜色, + }, + { + headerRightBg: '#e82121', //头部右侧背景色 + headerRightBgThis: '#ae1919', //头部右侧选中背景色, + headerRightColor: '#fafafa', //头部右侧字体颜色, + headerRightChildColor: '#676767', //头部右侧下拉字体颜色, + headerRightColorThis: '#ffffff', //头部右侧鼠标选中, + headerRightNavMore: '#fafafa', //头部右侧更多下拉颜色, + headerRightNavMoreBg: '#ae1919', //头部右侧更多下拉列表选中背景色, + headerRightNavMoreColor: '#ffffff', //头部右侧更多下拉列表字体色, + headerRightToolColor: '#bbe3df', //头部缩放按钮样式, + headerLogoBg: '#d91f1f', //logo背景颜色, + headerLogoColor: '#ffffff', //logo字体颜色, + leftMenuNavMore: '#ffffff', //左侧菜单更多下拉样式, + leftMenuBg: '#1f1f1f', //左侧菜单背景, + leftMenuBgThis: '#3b3f4b', //左侧菜单选中背景, + leftMenuChildBg: 'rgba(0,0,0,.3)', //左侧菜单子菜单背景, + leftMenuColor: '#ffffff', //左侧菜单字体颜色, + leftMenuColorThis: '#ffffff', //左侧菜单选中字体颜色, + tabActiveColor: '#e82121', //tab选项卡选中颜色, + }, + { + headerRightBg: '#963885', //头部右侧背景色 + headerRightBgThis: '#772c6a', //头部右侧选中背景色, + headerRightColor: '#fafafa', //头部右侧字体颜色, + headerRightChildColor: '#676767', //头部右侧下拉字体颜色, + headerRightColorThis: '#ffffff', //头部右侧鼠标选中, + headerRightNavMore: '#fafafa', //头部右侧更多下拉颜色, + headerRightNavMoreBg: '#772c6a', //头部右侧更多下拉列表选中背景色, + headerRightNavMoreColor: '#ffffff', //头部右侧更多下拉列表字体色, + headerRightToolColor: '#bbe3df', //头部缩放按钮样式, + headerLogoBg: '#772c6a', //logo背景颜色, + headerLogoColor: '#ffffff', //logo字体颜色, + leftMenuNavMore: '#ffffff', //左侧菜单更多下拉样式, + leftMenuBg: '#2f4056', //左侧菜单背景, + leftMenuBgThis: '#626f7f', //左侧菜单选中背景, + leftMenuChildBg: 'rgba(0,0,0,.3)', //左侧菜单子菜单背景, + leftMenuColor: '#ffffff', //左侧菜单字体颜色, + leftMenuColorThis: '#ffffff', //左侧菜单选中字体颜色, + tabActiveColor: '#963885', //tab选项卡选中颜色, + } + ]; + if (bgcolorId === undefined) { + return bgColorConfig; + } else { + return bgColorConfig[bgcolorId]; + } + }, + + /** + * 初始化 + * @param options + */ + render: function (options) { + options.bgColorDefault = options.bgColorDefault || false; + options.listen = options.listen || false; + var bgcolorId = sessionStorage.getItem('layuiminiBgcolorId'); + if (bgcolorId === null || bgcolorId === undefined || bgcolorId === '') { + bgcolorId = options.bgColorDefault; + } + miniTheme.buildThemeCss(bgcolorId); + if (options.listen) miniTheme.listen(options); + }, + + /** + * 构建主题样式 + * @param bgcolorId + * @returns {boolean} + */ + buildThemeCss: function (bgcolorId) { + if (!bgcolorId) { + return false; + } + var bgcolorData = miniTheme.config(bgcolorId); + var styleHtml = '/*头部右侧背景色 headerRightBg */\n' + + '.layui-layout-admin .layui-header {\n' + + ' background-color: ' + bgcolorData.headerRightBg + ' !important;\n' + + '}\n' + + '\n' + + '/*头部右侧选中背景色 headerRightBgThis */\n' + + '.layui-layout-admin .layui-header .layuimini-header-content > ul > .layui-nav-item.layui-this, .layuimini-tool i:hover {\n' + + ' background-color: ' + bgcolorData.headerRightBgThis + ' !important;\n' + + '}\n' + + '\n' + + '/*头部右侧字体颜色 headerRightColor */\n' + + '.layui-layout-admin .layui-header .layui-nav .layui-nav-item a {\n' + + ' color: ' + bgcolorData.headerRightColor + ';\n' + + '}\n' + + '/**头部右侧下拉字体颜色 headerRightChildColor */\n' + + '.layui-layout-admin .layui-header .layui-nav .layui-nav-item .layui-nav-child a {\n' + + ' color: ' + bgcolorData.headerRightChildColor + '!important;\n' + + '}\n' + + '\n' + + '/*头部右侧鼠标选中 headerRightColorThis */\n' + + '.layui-header .layuimini-menu-header-pc.layui-nav .layui-nav-item a:hover, .layui-header .layuimini-header-menu.layuimini-pc-show.layui-nav .layui-this a {\n' + + ' color: ' + bgcolorData.headerRightColorThis + ' !important;\n' + + '}\n' + + '\n' + + '/*头部右侧更多下拉颜色 headerRightNavMore */\n' + + '.layui-header .layui-nav .layui-nav-more {\n' + + ' border-top-color: ' + bgcolorData.headerRightNavMore + ' !important;\n' + + '}\n' + + '\n' + + '/*头部右侧更多下拉颜色 headerRightNavMore */\n' + + '.layui-header .layui-nav .layui-nav-mored, .layui-header .layui-nav-itemed > a .layui-nav-more {\n' + + ' border-color: transparent transparent ' + bgcolorData.headerRightNavMore + ' !important;\n' + + '}\n' + + '\n' + + '/**头部右侧更多下拉配置色 headerRightNavMoreBg headerRightNavMoreColor */\n' + + '.layui-header .layui-nav .layui-nav-child dd.layui-this a, .layui-header .layui-nav-child dd.layui-this, .layui-layout-admin .layui-header .layui-nav .layui-nav-item .layui-nav-child .layui-this a {\n' + + ' background-color: ' + bgcolorData.headerRightNavMoreBg + ' !important;\n' + + ' color:' + bgcolorData.headerRightNavMoreColor + ' !important;\n' + + '}\n' + + '\n' + + '/*头部缩放按钮样式 headerRightToolColor */\n' + + '.layui-layout-admin .layui-header .layuimini-tool i {\n' + + ' color: ' + bgcolorData.headerRightToolColor + ';\n' + + '}\n' + + '\n' + + '/*logo背景颜色 headerLogoBg */\n' + + '.layui-layout-admin .layuimini-logo {\n' + + ' background-color: ' + bgcolorData.headerLogoBg + ' !important;\n' + + '}\n' + + '\n' + + '/*logo字体颜色 headerLogoColor */\n' + + '.layui-layout-admin .layuimini-logo h1 {\n' + + ' color: ' + bgcolorData.headerLogoColor + ';\n' + + '}\n' + + '\n' + + '/*左侧菜单更多下拉样式 leftMenuNavMore */\n' + + '.layuimini-menu-left .layui-nav .layui-nav-more,.layuimini-menu-left-zoom.layui-nav .layui-nav-more {\n' + + ' border-top-color: ' + bgcolorData.leftMenuNavMore + ';\n' + + '}\n' + + '\n' + + '/*左侧菜单更多下拉样式 leftMenuNavMore */\n' + + '.layuimini-menu-left .layui-nav .layui-nav-mored, .layuimini-menu-left .layui-nav-itemed > a .layui-nav-more, .layuimini-menu-left-zoom.layui-nav .layui-nav-mored, .layuimini-menu-left-zoom.layui-nav-itemed > a .layui-nav-more {\n' + + ' border-color: transparent transparent ' + bgcolorData.leftMenuNavMore + ' !important;\n' + + '}\n' + + '\n' + + '/*左侧菜单背景 leftMenuBg */\n' + + '.layui-side.layui-bg-black, .layui-side.layui-bg-black > .layuimini-menu-left > ul, .layuimini-menu-left-zoom > ul {\n' + + ' background-color: ' + bgcolorData.leftMenuBg + ' !important;\n' + + '}\n' + + '\n' + + '/*左侧菜单选中背景 leftMenuBgThis */\n' + + '.layuimini-menu-left .layui-nav-tree .layui-this, .layuimini-menu-left .layui-nav-tree .layui-this > a, .layuimini-menu-left .layui-nav-tree .layui-nav-child dd.layui-this, .layuimini-menu-left .layui-nav-tree .layui-nav-child dd.layui-this a, .layuimini-menu-left-zoom.layui-nav-tree .layui-this, .layuimini-menu-left-zoom.layui-nav-tree .layui-this > a, .layuimini-menu-left-zoom.layui-nav-tree .layui-nav-child dd.layui-this, .layuimini-menu-left-zoom.layui-nav-tree .layui-nav-child dd.layui-this a {\n' + + ' background-color: ' + bgcolorData.leftMenuBgThis + ' !important\n' + + '}\n' + + '\n' + + '/*左侧菜单子菜单背景 leftMenuChildBg */\n' + + '.layuimini-menu-left .layui-nav-itemed > .layui-nav-child{\n' + + ' background-color: ' + bgcolorData.leftMenuChildBg + ' !important;\n' + + '}\n' + + '\n' + + '/*左侧菜单字体颜色 leftMenuColor */\n' + + '.layuimini-menu-left .layui-nav .layui-nav-item a, .layuimini-menu-left-zoom.layui-nav .layui-nav-item a {\n' + + ' color: ' + bgcolorData.leftMenuColor + ' !important;\n' + + '}\n' + + '\n' + + '/*左侧菜单选中字体颜色 leftMenuColorThis */\n' + + '.layuimini-menu-left .layui-nav .layui-nav-item a:hover, .layuimini-menu-left .layui-nav .layui-this a, .layuimini-menu-left-zoom.layui-nav .layui-nav-item a:hover, .layuimini-menu-left-zoom.layui-nav .layui-this a {\n' + + ' color:' + bgcolorData.leftMenuColorThis + ' !important;\n' + + '}\n' + + '\n' + + '/**tab选项卡选中颜色 tabActiveColor */\n' + + '.layuimini-tab .layui-tab-title .layui-this .layuimini-tab-active {\n' + + ' background-color: ' + bgcolorData.tabActiveColor + ';\n' + + '}\n'; + $('#layuimini-bg-color').html(styleHtml); + }, + + /** + * 构建主题选择html + * @param options + * @returns {string} + */ + buildBgColorHtml: function (options) { + options.bgColorDefault = options.bgColorDefault || 0; + var bgcolorId = parseInt(sessionStorage.getItem('layuiminiBgcolorId')); + if (isNaN(bgcolorId)) bgcolorId = options.bgColorDefault; + var bgColorConfig = miniTheme.config(); + var html = ''; + $.each(bgColorConfig, function (key, val) { + if (key === bgcolorId) { + html += '
              • \n'; + } else { + html += '
              • \n'; + } + html += '\n' + + '
                \n' + + '
                \n' + + '
                \n' + + '
              • '; + }); + return html; + }, + + /** + * 监听 + * @param options + */ + listen: function (options) { + $('body').on('click', '[data-bgcolor]', function () { + var loading = layer.load(0, { shade: false, time: 2 * 1000 }); + var clientHeight = (document.documentElement.clientHeight) - 60; + var bgColorHtml = miniTheme.buildBgColorHtml(options); + var html = '
                \n' + + '
                \n' + + '配色方案\n' + + '
                \n' + + '
                \n' + + '
                  \n' + bgColorHtml + '
                \n' + + '
                \n' + + '
                \n' + + ' 开发文档\n' + + ' 开源地址\n' + + ' 演示地址\n' + + '
                ' + + '
                '; + layer.open({ + type: 1, + title: false, + closeBtn: 0, + shade: 0.2, + anim: 2, + shadeClose: true, + id: 'layuiminiBgColor', + area: ['340px', clientHeight + 'px'], + offset: 'rb', + content: html, + success: function (index, layero) { + }, + end: function () { + $('.layuimini-select-bgcolor').removeClass('layui-this'); + } + }); + layer.close(loading); + }); + + $('body').on('click', '[data-select-bgcolor]', function () { + var bgcolorId = $(this).attr('data-select-bgcolor'); + $('.layuimini-color .color-content ul .layui-this').attr('class', ''); + $(this).attr('class', 'layui-this'); + localStorage.setItem('watercloudBgcolorId', bgcolorId); + miniTheme.render({ + bgColorDefault: bgcolorId, + listen: false, + }); + }); + } + }; + + exports("miniTheme", miniTheme); + +}) + ; \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/layuimini/miniTongji.js b/WaterCloud.Web/wwwroot/js/lay-module/layuimini/miniTongji.js new file mode 100644 index 0000000..f0ca101 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/layuimini/miniTongji.js @@ -0,0 +1,40 @@ +/** + * date:2020/03/01 + * author:Mr.Chung + * version:2.0 + * description:layuimini 统计框架扩展 + */ +layui.define(["jquery"], function (exports) { + var $ = layui.$; + + var miniTongji = { + + /** + * 初始化 + * @param options + */ + render: function (options) { + options.specific = options.specific || false; + options.domains = options.domains || []; + var domain = window.location.hostname; + if (options.specific === false || (options.specific === true && options.domains.indexOf(domain) >=0)) { + miniTongji.listen(); + } + }, + + /** + * 监听统计代码 + */ + listen: function () { + var _hmt = _hmt || []; + (function () { + var hm = document.createElement("script"); + hm.src = "https://hm.baidu.com/hm.js?d97abf6d61c21d773f97835defbdef4e"; + var s = document.getElementsByTagName("script")[0]; + s.parentNode.insertBefore(hm, s); + })(); + } + }; + + exports("miniTongji", miniTongji); +}); \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/loading/wcLoading.css b/WaterCloud.Web/wwwroot/js/lay-module/loading/wcLoading.css new file mode 100644 index 0000000..5de94dc --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/loading/wcLoading.css @@ -0,0 +1,102 @@ +.wc-loading { + position:absolute; + display:block; + width:100%; + height:100%; + top:0; + left:0; + right:0; + bottom:0; + z-index:19891017; + background-color:#fff +} +.wc-loading.close { + animation: close 1s; + -webkit-animation: close 1s; + animation-fill-mode: forwards; +} +.ball-loader{ + position:absolute; + left:50%; + top:50%; + transform:translate(-50%, -50%); + -ms-transform:translate(-50%, -50%); + -webkit-transform:translate(-50%, -50%) +} +.ball-loader>span, .signal-loader>span { + background-color: #4aca85; + display:inline-block +} +.wc-loading.orange_theme .ball-loader>span, .signal-loader>span{ + background-color: #FF4806; +} +.wc-loading.blue_theme .ball-loader>span, .signal-loader>span{ + background-color: #2D8CF0; +} +.ball-loader>span:nth-child(1), .ball-loader.sm>span:nth-child(1), .signal-loader>span:nth-child(1), .signal-loader.sm>span:nth-child(1) { + -webkit-animation-delay:0s; + animation-delay:0s +} +.ball-loader>span:nth-child(2), .ball-loader.sm>span:nth-child(2), .signal-loader>span:nth-child(2), .signal-loader.sm>span:nth-child(2) { + -webkit-animation-delay:.1s; + animation-delay:.1s +} +.ball-loader>span:nth-child(3), .ball-loader.sm>span:nth-child(3), .signal-loader>span:nth-child(3), .signal-loader.sm>span:nth-child(3) { + -webkit-animation-delay:.15s; + animation-delay:.15s +} +.ball-loader>span:nth-child(4), .ball-loader.sm>span:nth-child(4), .signal-loader>span:nth-child(4), .signal-loader.sm>span:nth-child(4) { + -webkit-animation-delay:.2s; + animation-delay:.2s +} +.ball-loader>span { + width:20px; + height:20px; + margin:0 3px; + border-radius:50%; + transform:scale(0); + -ms-transform:scale(0); + -webkit-transform:scale(0); + animation:ball-load 1s ease-in-out infinite; + -webkit-animation:1s ball-load ease-in-out infinite +} +@-webkit-keyframes ball-load { + 0% { + transform:scale(0); + -webkit-transform:scale(0) + } + 50% { + transform:scale(1); + -webkit-transform:scale(1) + } + 100% { + transform:scale(0); + -webkit-transform:scale(0) + } +} +@keyframes ball-load { + 0% { + transform:scale(0); + -webkit-transform:scale(0) + } + 50% { + transform:scale(1); + -webkit-transform:scale(1) + } + 100% { + transform:scale(0); + -webkit-transform:scale(0) + } +} +@-webkit-keyframes close { + 0% { + opacity: 1; + /*display: block;*/ + } + 100% { + opacity: 0; + /*display: none;*/ + } +} + + diff --git a/WaterCloud.Web/wwwroot/js/lay-module/loading/wcLoading.js b/WaterCloud.Web/wwwroot/js/lay-module/loading/wcLoading.js new file mode 100644 index 0000000..b1e9369 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/loading/wcLoading.js @@ -0,0 +1,64 @@ +var wc_load_options = { + time: 0,//初始时间设0 + content: "waterlcloud..." +}; + +!function (content, options) { + var load_config = parseInt(sessionStorage.getItem('layuiminiBgcolorId')) || 0; + + + function templateFun(options) { + //默认蓝色 + if (!load_config || load_config == 0 || load_config == 1 || load_config == 5) { + return "
                " + + "
                " + + "" + + "
                " + + "
                "; + } + //绿色 + else if (load_config == 2 || load_config == 3 || load_config == 4) { + return "
                " + + "
                " + + "" + + "
                " + + "
                "; + } + //橙色 + else { + return "
                " + + "
                " + + "" + + "
                " + + "
                "; + } + + } + + function headerInit(content, options) { + options = options || {}; + if (typeof content == "string") { + options["content"] = content || wc_load_options.content; + } else if (typeof content == "object") { + options = content; + } + options.time = options.time || wc_load_options.time; + options.content = options.content || wc_load_options.content; + return options; + } + + wc_load_options = headerInit(content, options); + var template = templateFun(wc_load_options); + document.writeln(template); +}(); + +var wcLoading = { + close: function (time, dom) { + time = time || wc_load_options.time; + dom = dom || document.getElementsByClassName("wc-loading")[0]; + dom.classList.add("close"); + dom.parentNode.removeChild(dom);/**删除当前节点*/ + } +}; + + diff --git a/WaterCloud.Web/wwwroot/js/lay-module/notice/notice.css b/WaterCloud.Web/wwwroot/js/lay-module/notice/notice.css new file mode 100644 index 0000000..65c9fea --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/notice/notice.css @@ -0,0 +1,228 @@ +.toast-title { + font-weight: bold; +} +.toast-message { + -ms-word-wrap: break-word; + word-wrap: break-word; +} +.toast-message a, +.toast-message label { + color: #FFFFFF; +} +.toast-message a:hover { + color: #CCCCCC; + text-decoration: none; +} +.toast-close-button { + position: relative; + right: -0.3em; + top: -0.3em; + float: right; + font-size: 20px; + font-weight: bold; + color: #FFFFFF; + -webkit-text-shadow: 0 1px 0 #ffffff; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.8; + -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); + filter: alpha(opacity=80); + line-height: 1; +} +.toast-close-button:hover, +.toast-close-button:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.4; + -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); + filter: alpha(opacity=40); +} +.rtl .toast-close-button { + left: -0.3em; + float: left; + right: 0.3em; +} +/*Additional properties for button version + iOS requires the button element instead of an anchor tag. + If you want the anchor version, it requires `href="#"`.*/ +button.toast-close-button { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.toast-top-center { + top: 0; + right: 0; + width: 100%; +} +.toast-bottom-center { + bottom: 0; + right: 0; + width: 100%; +} +.toast-top-full-width { + top: 0; + right: 0; + width: 100%; +} +.toast-bottom-full-width { + bottom: 0; + right: 0; + width: 100%; +} +.toast-top-left { + top: 12px; + left: 12px; +} +.toast-top-right { + top: 12px; + right: 12px; +} +.toast-bottom-right { + right: 12px; + bottom: 12px; +} +.toast-bottom-left { + bottom: 12px; + left: 12px; +} +#toast-container { + position: fixed; + z-index: 999999; + pointer-events: none; + /*overrides*/ +} +#toast-container * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +#toast-container > div { + position: relative; + pointer-events: auto; + overflow: hidden; + margin: 0 0 6px; + padding: 15px 15px 15px 50px; + width: 300px; + -moz-border-radius: 3px 3px 3px 3px; + -webkit-border-radius: 3px 3px 3px 3px; + border-radius: 3px 3px 3px 3px; + background-position: 15px center; + background-repeat: no-repeat; + -moz-box-shadow: 0 0 12px #999999; + -webkit-box-shadow: 0 0 12px #999999; + box-shadow: 0 0 12px #999999; + color: #FFFFFF; + opacity: 0.8; + -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); + filter: alpha(opacity=80); +} +#toast-container > div.rtl { + direction: rtl; + padding: 15px 50px 15px 15px; + background-position: right 15px center; +} +#toast-container > div:hover { + -moz-box-shadow: 0 0 12px #000000; + -webkit-box-shadow: 0 0 12px #000000; + box-shadow: 0 0 12px #000000; + opacity: 1; + -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); + filter: alpha(opacity=100); + cursor: pointer; +} +#toast-container > .toast-info { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important; +} +#toast-container > .toast-error { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important; +} +#toast-container > .toast-success { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important; +} +#toast-container > .toast-warning { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important; +} +#toast-container.toast-top-center > div, +#toast-container.toast-bottom-center > div { + width: 300px; + margin-left: auto; + margin-right: auto; +} +#toast-container.toast-top-full-width > div, +#toast-container.toast-bottom-full-width > div { + width: 96%; + margin-left: auto; + margin-right: auto; +} +.toast { + background-color: #030303; +} +.toast-success { + background-color: #51A351; +} +.toast-error { + background-color: #BD362F; +} +.toast-info { + background-color: #2F96B4; +} +.toast-warning { + background-color: #F89406; +} +.toast-progress { + position: absolute; + left: 0; + bottom: 0; + height: 4px; + background-color: #000000; + opacity: 0.4; + -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); + filter: alpha(opacity=40); +} +/*Responsive Design*/ +@media all and (max-width: 240px) { + #toast-container > div { + padding: 8px 8px 8px 50px; + width: 11em; + } + #toast-container > div.rtl { + padding: 8px 50px 8px 8px; + } + #toast-container .toast-close-button { + right: -0.2em; + top: -0.2em; + } + #toast-container .rtl .toast-close-button { + left: -0.2em; + right: 0.2em; + } +} +@media all and (min-width: 241px) and (max-width: 480px) { + #toast-container > div { + padding: 8px 8px 8px 50px; + width: 18em; + } + #toast-container > div.rtl { + padding: 8px 50px 8px 8px; + } + #toast-container .toast-close-button { + right: -0.2em; + top: -0.2em; + } + #toast-container .rtl .toast-close-button { + left: -0.2em; + right: 0.2em; + } +} +@media all and (min-width: 481px) and (max-width: 768px) { + #toast-container > div { + padding: 15px 15px 15px 50px; + width: 25em; + } + #toast-container > div.rtl { + padding: 15px 50px 15px 15px; + } +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/notice/notice.js b/WaterCloud.Web/wwwroot/js/lay-module/notice/notice.js new file mode 100644 index 0000000..475070a --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/notice/notice.js @@ -0,0 +1,486 @@ +/* + * Toastr + * Copyright 2012-2015 + * Authors: John Papa, Hans Fjällemark, and Tim Ferrell. + * All Rights Reserved. + * Use, reproduction, distribution, and modification of this code is subject to the terms and + * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php + * + * ARIA Support: Greta Krafsig + * + * Project: https://github.com/CodeSeven/toastr + */ +/* global define */ +(function (define) { + define(['jquery'], function ($) { + return (function () { + var $container; + var listener; + var toastId = 0; + var toastType = { + error: 'error', + info: 'info', + success: 'success', + warning: 'warning' + }; + + var cssStyle = $(''); + $("body").append(cssStyle); + + var toastr = { + clear: clear, + remove: remove, + error: error, + getContainer: getContainer, + info: info, + options: {}, + subscribe: subscribe, + success: success, + version: '2.1.4', + warning: warning + }; + + var previousToast; + + return toastr; + + //////////////// + + function error(message, title, optionsOverride) { + return notify({ + type: toastType.error, + iconClass: getOptions().iconClasses.error, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function getContainer(options, create) { + if (!options) { options = getOptions(); } + $container = $('#' + options.containerId); + if ($container.length) { + return $container; + } + if (create) { + $container = createContainer(options); + } + return $container; + } + + function info(message, title, optionsOverride) { + return notify({ + type: toastType.info, + iconClass: getOptions().iconClasses.info, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function subscribe(callback) { + listener = callback; + } + + function success(message, title, optionsOverride) { + return notify({ + type: toastType.success, + iconClass: getOptions().iconClasses.success, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function warning(message, title, optionsOverride) { + return notify({ + type: toastType.warning, + iconClass: getOptions().iconClasses.warning, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function clear($toastElement, clearOptions) { + var options = getOptions(); + if (!$container) { getContainer(options); } + if (!clearToast($toastElement, options, clearOptions)) { + clearContainer(options); + } + } + + function remove($toastElement) { + var options = getOptions(); + if (!$container) { getContainer(options); } + if ($toastElement && $(':focus', $toastElement).length === 0) { + removeToast($toastElement); + return; + } + if ($container.children().length) { + $container.remove(); + } + } + + // internal functions + + function clearContainer (options) { + var toastsToClear = $container.children(); + for (var i = toastsToClear.length - 1; i >= 0; i--) { + clearToast($(toastsToClear[i]), options); + } + } + + function clearToast ($toastElement, options, clearOptions) { + var force = clearOptions && clearOptions.force ? clearOptions.force : false; + if ($toastElement && (force || $(':focus', $toastElement).length === 0)) { + $toastElement[options.hideMethod]({ + duration: options.hideDuration, + easing: options.hideEasing, + complete: function () { removeToast($toastElement); } + }); + return true; + } + return false; + } + + function createContainer(options) { + $container = $('
                ') + .attr('id', options.containerId) + .addClass(options.positionClass); + + $container.appendTo($(options.target)); + return $container; + } + + function getDefaults() { + return { + tapToDismiss: true, + toastClass: 'toast', + containerId: 'toast-container', + debug: false, + + showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery + showDuration: 300, + showEasing: 'swing', //swing and linear are built into jQuery + onShown: undefined, + hideMethod: 'fadeOut', + hideDuration: 1000, + hideEasing: 'swing', + onHidden: undefined, + closeMethod: false, + closeDuration: false, + closeEasing: false, + closeOnHover: true, + + extendedTimeOut: 1000, + iconClasses: { + error: 'toast-error', + info: 'toast-info', + success: 'toast-success', + warning: 'toast-warning' + }, + iconClass: 'toast-info', + positionClass: 'toast-top-right', + timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky + titleClass: 'toast-title', + messageClass: 'toast-message', + escapeHtml: false, + target: 'body', + closeHtml: '', + closeClass: 'toast-close-button', + newestOnTop: true, + preventDuplicates: false, + progressBar: false, + progressClass: 'toast-progress', + rtl: false + }; + } + + function publish(args) { + if (!listener) { return; } + listener(args); + } + + function notify(map) { + var options = getOptions(); + var iconClass = map.iconClass || options.iconClass; + + if (typeof (map.optionsOverride) !== 'undefined') { + options = $.extend(options, map.optionsOverride); + iconClass = map.optionsOverride.iconClass || iconClass; + } + + if (shouldExit(options, map)) { return; } + + toastId++; + + $container = getContainer(options, true); + + var intervalId = null; + var $toastElement = $('
                '); + var $titleElement = $('
                '); + var $messageElement = $('
                '); + var $progressElement = $('
                '); + var $closeElement = $(options.closeHtml); + var progressBar = { + intervalId: null, + hideEta: null, + maxHideTime: null + }; + var response = { + toastId: toastId, + state: 'visible', + startTime: new Date(), + options: options, + map: map + }; + + personalizeToast(); + + displayToast(); + + handleEvents(); + + publish(response); + + if (options.debug && console) { + console.log(response); + } + + return $toastElement; + + function escapeHtml(source) { + if (source == null) { + source = ''; + } + + return source + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>'); + } + + function personalizeToast() { + setIcon(); + setTitle(); + setMessage(); + setCloseButton(); + setProgressBar(); + setRTL(); + setSequence(); + setAria(); + } + + function setAria() { + var ariaValue = ''; + switch (map.iconClass) { + case 'toast-success': + case 'toast-info': + ariaValue = 'polite'; + break; + default: + ariaValue = 'assertive'; + } + $toastElement.attr('aria-live', ariaValue); + } + + function handleEvents() { + if (options.closeOnHover) { + $toastElement.hover(stickAround, delayedHideToast); + } + + if (!options.onclick && options.tapToDismiss) { + $toastElement.click(hideToast); + } + + if (options.closeButton && $closeElement) { + $closeElement.click(function (event) { + if (event.stopPropagation) { + event.stopPropagation(); + } else if (event.cancelBubble !== undefined && event.cancelBubble !== true) { + event.cancelBubble = true; + } + + if (options.onCloseClick) { + options.onCloseClick(event); + } + + hideToast(true); + }); + } + + if (options.onclick) { + $toastElement.click(function (event) { + options.onclick(event); + hideToast(); + }); + } + } + + function displayToast() { + $toastElement.hide(); + + $toastElement[options.showMethod]( + {duration: options.showDuration, easing: options.showEasing, complete: options.onShown} + ); + + if (options.timeOut > 0) { + intervalId = setTimeout(hideToast, options.timeOut); + progressBar.maxHideTime = parseFloat(options.timeOut); + progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; + if (options.progressBar) { + progressBar.intervalId = setInterval(updateProgress, 10); + } + } + } + + function setIcon() { + if (map.iconClass) { + $toastElement.addClass(options.toastClass).addClass(iconClass); + } + } + + function setSequence() { + if (options.newestOnTop) { + $container.prepend($toastElement); + } else { + $container.append($toastElement); + } + } + + function setTitle() { + if (map.title) { + var suffix = map.title; + if (options.escapeHtml) { + suffix = escapeHtml(map.title); + } + $titleElement.append(suffix).addClass(options.titleClass); + $toastElement.append($titleElement); + } + } + + function setMessage() { + if (map.message) { + var suffix = map.message; + if (options.escapeHtml) { + suffix = escapeHtml(map.message); + } + $messageElement.append(suffix).addClass(options.messageClass); + $toastElement.append($messageElement); + } + } + + function setCloseButton() { + if (options.closeButton) { + $closeElement.addClass(options.closeClass).attr('role', 'button'); + $toastElement.prepend($closeElement); + } + } + + function setProgressBar() { + if (options.progressBar) { + $progressElement.addClass(options.progressClass); + $toastElement.prepend($progressElement); + } + } + + function setRTL() { + if (options.rtl) { + $toastElement.addClass('rtl'); + } + } + + function shouldExit(options, map) { + if (options.preventDuplicates) { + if (map.message === previousToast) { + return true; + } else { + previousToast = map.message; + } + } + return false; + } + + function hideToast(override) { + var method = override && options.closeMethod !== false ? options.closeMethod : options.hideMethod; + var duration = override && options.closeDuration !== false ? + options.closeDuration : options.hideDuration; + var easing = override && options.closeEasing !== false ? options.closeEasing : options.hideEasing; + if ($(':focus', $toastElement).length && !override) { + return; + } + clearTimeout(progressBar.intervalId); + return $toastElement[method]({ + duration: duration, + easing: easing, + complete: function () { + removeToast($toastElement); + clearTimeout(intervalId); + if (options.onHidden && response.state !== 'hidden') { + options.onHidden(); + } + response.state = 'hidden'; + response.endTime = new Date(); + publish(response); + } + }); + } + + function delayedHideToast() { + if (options.timeOut > 0 || options.extendedTimeOut > 0) { + intervalId = setTimeout(hideToast, options.extendedTimeOut); + progressBar.maxHideTime = parseFloat(options.extendedTimeOut); + progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime; + } + } + + function stickAround() { + clearTimeout(intervalId); + progressBar.hideEta = 0; + $toastElement.stop(true, true)[options.showMethod]( + {duration: options.showDuration, easing: options.showEasing} + ); + } + + function updateProgress() { + var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100; + $progressElement.width(percentage + '%'); + } + } + + function getOptions() { + return $.extend({}, getDefaults(), toastr.options); + } + + function removeToast($toastElement) { + if (!$container) { $container = getContainer(); } + if ($toastElement.is(':visible')) { + return; + } + $toastElement.remove(); + $toastElement = null; + if ($container.children().length === 0) { + $container.remove(); + previousToast = undefined; + } + } + + })(); + }); +}(typeof define === 'function' && define.amd ? define : function (deps, factory) { + if (typeof module !== 'undefined' && module.exports) { //Node + module.exports = factory(require('jquery')); + } + else if (window.layui && layui.define){ + layui.define('jquery', function (exports) { //layui加载 + exports('toastr', factory(layui.jquery)); + exports('notice', factory(layui.jquery)); + }); + } + else { + window.toastr = factory(window.jQuery); + } +})); \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/numberInput/numberInput.js b/WaterCloud.Web/wwwroot/js/lay-module/numberInput/numberInput.js new file mode 100644 index 0000000..406953c --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/numberInput/numberInput.js @@ -0,0 +1,204 @@ +layui.define(['jquery','util','layer'],function (exports) { + var $ = layui.$, + util = layui.util, + layer = layui.layer, + input_elem = 'input[number-input]', + baseClassName = 'layui-input-number', + numberInputBtn = [ + '
                ', + '', + '', + '
                ', + ].join(''), + style = [ + '' + ].join(''); + $('head link:last')[0] && $('head link:last').after(style) || $('head').append(style); + + var numberInput = { + options:{ + elem:input_elem + }, + render:function (option) { + var _this = this; + _this.options = $.extend(_this.options, option); + $(_this.options.elem).not('[lay-ignore]').addClass(baseClassName).wrap('
                '); + $(_this.options.elem).not('[lay-ignore]').after(numberInputBtn); + _this.listen(); + }, + listen:function () { + var _this = this; + $(_this.options.elem).bind('input propertychange',function () { + var value = $(this).val(); + $(this).val(value.replace(/[^\-?\d.]/g,'')); + }); + + $(_this.options.elem).keydown(function (event) { + var e = event||window.event; + var k = e.keyCode || e.which; + switch (k) { + case 38: + // 按下向上箭头 + $(this).siblings('.layui-number-input-btn').children('[lay-click="numberUp"]').trigger('click').css('background','#eee'); + break; + case 40: + // 按下向上箭头 + $(this).siblings('.layui-number-input-btn').children('[lay-click="numberDown"]').trigger('click').css('background','#eee'); + break; + default: + break; + } + return false; + }); + $(_this.options.elem).keyup(function () { + var e = event||window.event; + var k = e.keyCode || e.which; + switch (k) { + case 38: + // 按下向上箭头 + $(this).siblings('.layui-number-input-btn').children('[lay-click="numberUp"]').css('background',''); + break; + case 40: + // 按下向上箭头 + $(this).siblings('.layui-number-input-btn').children('[lay-click="numberDown"]').css('background',''); + break; + default: + break; + } + return false; + }); + var timeOut; + //长按 + $('[lay-click="numberUp"],[lay-click="numberDown"]').mousedown(function () { + var $this = $(this); + timeOut = setInterval(function () { + $this.trigger('click'); + },200) + }); + $('[lay-click="numberUp"],[lay-click="numberDown"]').mouseup(function () { + clearInterval(timeOut); + }); + $('[lay-click="numberUp"],[lay-click="numberDown"]').mouseout(function () { + clearInterval(timeOut); + }); + util.event('lay-click',{ + numberUp:function (othis) { + var thisInput = othis.parent().parent().children('.'+baseClassName); + var thisInputValue = Number(thisInput.val()||0); + var step = thisInput.attr('step')||1; + var maxValue = Number(thisInput.attr('max')); + if (maxValue!=undefined){ + if (thisInputValue>=maxValue){ + layer.tips('最大值'+maxValue,thisInput,{tips:1}); + return false; + } + } + thisInputValue=_this.add(thisInputValue,parseFloat(step)); + thisInput.val('').focus().val(thisInputValue); + }, + numberDown:function(othis){ + var thisInput = othis.parent().parent().children('.'+baseClassName); + var thisInputValue = thisInput.val()||0; + var step = thisInput.attr('step')||1; + var minValue = thisInput.attr('min'); + if (minValue!=undefined){ + if (thisInputValue<=minValue){ + layer.tips('最小值'+minValue,thisInput,{tips:1}); + return false; + } + } + thisInputValue = _this.subtraction(thisInputValue,step); + thisInput.val('').focus().val(thisInputValue); + } + }); + }, + /** + * 加法 + * @param arg1 + * @param arg2 + * @returns {number} + */ + add:function (arg1, arg2) { + var r1,r2,m; + try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0} + try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0} + m=Math.pow(10,Math.max(r1,r2)) + return (this.multiplication(arg1,m)+this.multiplication(arg2,m))/m + }, + /** + * 减法 + * @param arg1 被减数 + * @param arg2 减数 + * @returns {string} + */ + subtraction:function (arg1, arg2) { + var r1, r2, m, n; + try { + r1 = arg1.toString().split(".")[1].length; + } + catch (e) { + r1 = 0; + } + try { + r2 = arg2.toString().split(".")[1].length; + } + catch (e) { + r2 = 0; + } + m = Math.pow(10, Math.max(r1, r2)); + //last modify by deeka + //动态控制精度长度 + n = (r1 >= r2) ? r1 : r2; + return ((arg1 * m - arg2 * m) / m).toFixed(n); + }, + /** + * 乘法 + * @param arg1 + * @param arg2 + * @returns {number} + */ + multiplication:function (arg1,arg2) { + var m=0,s1=arg1.toString(),s2=arg2.toString(); + try{m+=s1.split(".")[1].length}catch(e){} + try{m+=s2.split(".")[1].length}catch(e){} + return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m) + }, + /** + * 除法 + * @param arg1 + * @param arg2 + * @returns {*|number} + */ + division:function (arg1,arg2) { + var t1 = 0, t2 = 0, r1, r2; + try { + t1 = arg1.toString().split(".")[1].length + } catch (e) { + } + try { + t2 = arg2.toString().split(".")[1].length + } catch (e) { + } + with (Math) { + r1 = Number(arg1.toString().replace(".", "")) + r2 = Number(arg2.toString().replace(".", "")) + return this.multiplication((r1 / r2), pow(10, t2 - t1)); + } + } + }; + //外部接口 + var exportApi = { + render:function(option){ + numberInput.render(option) + }, + }; + exports('numberInput',exportApi); +}); \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/optimizeSelectOption/optimizeSelectOption.css b/WaterCloud.Web/wwwroot/js/lay-module/optimizeSelectOption/optimizeSelectOption.css new file mode 100644 index 0000000..dc7a957 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/optimizeSelectOption/optimizeSelectOption.css @@ -0,0 +1,10 @@ +.layui-layer-content div.layui-form-select>div.layui-select-title+ dl, +.select_option_to_layer div.layui-form-select>div.layui-select-title+ dl +{ + visibility: hidden; +} + +.layui-layer.layui-option-layer { + mso-border-shadow: no; + box-shadow: none; +} diff --git a/WaterCloud.Web/wwwroot/js/lay-module/optimizeSelectOption/optimizeSelectOption.js b/WaterCloud.Web/wwwroot/js/lay-module/optimizeSelectOption/optimizeSelectOption.js new file mode 100644 index 0000000..9385bda --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/optimizeSelectOption/optimizeSelectOption.js @@ -0,0 +1,248 @@ +/*! + + @Title: optimizeSelectOption + @Description:优化select在layer和表格中显示的问题 + @Site: + @Author: 岁月小偷 + @License:MIT + + */ +;!function (factory) { + 'use strict'; + var modelName = 'optimizeSelectOption'; + if (!window.top.layui) { + // 顶层引入layui是使用该组件的最低要求 + console.warn('使用插件:' + modelName + '页面顶层窗口必须引入layui'); + layui.define(['form'], function (exports) { + exports(modelName, {msg: '使用插件:' + modelName + '页面顶层窗口必须引入layui'}); + }); + } else { + // 利用的是顶层的top去弹出,所以用top的layui去use layer确保顶层 + window.top.layui.use('layer', function () { + layui.define(['form'], function (exports) { //layui加载 + exports(modelName, factory(modelName)); + }); + }); + } +}(function (modelName) { + var version = '0.2.0'; + var $ = layui.$; + var form = layui.form; + var layer = layui.layer; + + var filePath = layui.cache.modules.optimizeSelectOption + .substr(0, layui.cache.modules.optimizeSelectOption.lastIndexOf('/')); + // 引入tablePlug.css + layui.link(filePath + '/optimizeSelectOption.css?v' + version); + + var selectors = [ + '.layui-table-view', // layui的表格中 + '.layui-layer-content', // 用type:1 弹出的layer中 + '.select_option_to_layer' // 任意其他的位置 + ]; + // 记录弹窗的index的变量 + window.top.layer._indexTemp = window.top.layer._indexTemp || {}; + + if (!form.render.plugFlag) { + // 只要未改造过的才需要改造一下 + // 保留一下原始的form.render + var formRender = form.render; + form.render = function (type, filter, jqObj) { + var that = this; + var retObj; + // if (jqObj && jqObj.length) { + if (jqObj) { + layui.each(jqObj, function (index, elem) { + elem = $(elem); + var elemP = elem.parent(); + var formFlag = elemP.hasClass('layui-form'); + var filterTemp = elemP.attr('lay-filter'); + // mark一下当前的 + formFlag ? '' : elemP.addClass('layui-form'); + filterTemp ? '' : elemP.attr('lay-filter', 'tablePlug_form_filter_temp_' + new Date().getTime() + '_' + Math.floor(Math.random() * 100000)); + // 将焦点集中到要渲染的这个的容器上 + retObj = formRender.call(that, type, elemP.attr('lay-filter')); + // 恢复现场 + formFlag ? '' : elemP.removeClass('layui-form'); + filterTemp ? '' : elemP.attr('lay-filter', null); + }); + } else { + retObj = formRender.call(that, type, filter); + } + return retObj; + }; + form.render.plugFlag = true; + } + + // 关闭弹出的选项 + var close = function () { + if (!!window.top&&'layer' in window.top) { + window.top.layer.close(window.top.layer._indexTemp[modelName]); + } + }; + + // 获得某个节点的位置 offsetTop: 是否获得相对top window的位移 + function getPosition(elem, _window, offsetTop) { + _window = _window || window; + elem = elem.length ? elem.get(0) : elem; + var offsetTemp = {}; + if (offsetTop && _window.top !== _window.self) { + var frameElem = _window.frames.frameElement; + offsetTemp = getPosition(frameElem, _window.parent, offsetTop); + } + var offset = elem.getBoundingClientRect(); + + return { + top: offset.top + (offsetTemp.top||0), + left: offset.left + (offsetTemp.left||0) + }; + } + + var config = {}; + + // 针对某个组件的效果优化注册方法 + var render = function (name, options) { + var that = this; + if (config.name) { + console.warn('针对', name, '的显示优化已经存在,请不要重复渲染!'); + return that; + } + + // 优化select的选项在某些场景下的显示问题 + $(document).on('click' + , selectors.map(function (value) { + // return value + ' .layui-select-title,' + value + ' .xm-select-title'; + return value + ' ' + options.triggerElem; + }).join(',') + , function (event) { + layui.stope(event); + close(); + var triggerElem = $(this); + var titleElem = triggerElem; + var dlElem = typeof options.dlElem === 'function' ? options.dlElem(triggerElem) : titleElem.next(); + // var selectElem = titleElem.parent().prev(); + var selectElem = titleElem.parent().prev(); + var selectupFlag = titleElem.parent().hasClass('layui-form-selectup'); + + function getDlPosition() { + var titleElemPosition = getPosition(titleElem, window, true); + var topTemp = titleElemPosition.top; + var leftTemp = titleElemPosition.left; + if (selectupFlag) { + topTemp = topTemp - dlElem.outerHeight() + titleElem.outerHeight() - parseFloat(dlElem.css('bottom')); + } else { + topTemp += parseFloat(dlElem.css('top')); + } + if (topTemp + dlElem.outerHeight() > window.top.innerHeight && !selectupFlag) { + // 出现原始的form表单判断向下弹出,但是最终弹出超出窗口下边界的情形的处理 + selectupFlag = true; + topTemp -= (dlElem.outerHeight() + (2 * parseFloat(dlElem.css('top')) - titleElem.outerHeight())); + } + return { + top: topTemp, + left: leftTemp + }; + } + + var dlPosition = getDlPosition(); + + titleElem.css({backgroundColor: 'transparent'}); + window.top.layer._indexTemp[modelName] = window.top.layer.open({ + type: 1, + title: false, + closeBtn: 0, + shade: 0, + anim: -1, + fixed: titleElem.closest('.layui-layer-content').length || window.top !== window.self, + isOutAnim: false, + // offset: [topTemp + 'px', leftTemp + 'px'], + offset: [dlPosition.top + 'px', dlPosition.left + 'px'], + // area: [dlElem.outerWidth() + 'px', dlElem.outerHeight() + 'px'], + area: dlElem.outerWidth() + 'px', + content: '
                ', + skin: 'layui-option-layer', + success: function (layero, index) { + dlElem.css({ + top: 0, + position: 'relative' + }).appendTo(layero.find('.layui-layer-content').css({overflow: 'hidden'}).find('.layui-form-selected')); + layero.width(titleElem.width()); + // 原本的做法在ie下获得的是auto其他的浏览器却是确定的值,目前简单处理,先自行计算出来,后面再调优 + var bottom_computed = window.top.innerHeight - layero.outerHeight() - parseFloat(layero.css('top')); + selectupFlag && (layero.css({top: 'auto', bottom: bottom_computed + 'px'})); + // 调用各自的success回调 + typeof options.success === 'function' && options.success.call(this, index, layero); + // 通用的事件处理 + layero.on('mousedown', function (event) { + layui.stope(event); + }); + setTimeout(function () { + // 延迟500毫秒添加事件处理,应对ie浏览器下某一些特定场景下点击select出来option的时候回有一个容器滚动导致直接关闭选项的问题 + // 不包含selectors的选择器的节点 + titleElem.parentsUntil(selectors.join(',')).one('scroll', function (event) { + // 用window.top.layer去弹出的选项在其title所在的容器滚动的时候都关闭 + close(); + }); + // 单独给选择器的节点加上 + titleElem.parents(selectors.join(',')).one('scroll', function (event) { + // 用window.top.layer去弹出的选项在其title所在的容器滚动的时候都关闭 + close(); + }); + + var windowTemp = window; + do { + var $Temp = windowTemp.$ || windowTemp.layui.$; + if ($Temp) { + // 点击document的时候触发 + $Temp(windowTemp.document).one('click', function (event) { + close(); + }); + + $Temp(windowTemp.document).one('mousedown', function (event) { + close(); + }); + + // 窗口resize的时候关掉表格中的下拉 + $Temp(windowTemp).one('resize', function (event) { + close(); + }); + + // 监听滚动在必要的时候关掉select的选项弹出(主要是在多级的父子页面的时候) + $Temp(windowTemp.document).one('scroll', function () { + if (top !== self &&!!parent&& 'parent' in parent&& parent.parent) { + // 多级嵌套的窗口就直接关掉了 + close(); + } + }); + } + } while (windowTemp.self !== windowTemp.top ? windowTemp = windowTemp.parent : false); + }, 500); + }, + end: function () { + typeof options.end === 'function' && options.end.call(this, selectElem); + } + }); + }); + }; + + // 内置初始化layui的select的效果,目前还不够晚上不提供给外部注册一些其他有类似问题的组件的处理 + render('layuiSelect', { + triggerElem: 'div:not(.layui-select-disabled)>.layui-select-title', // 触发的选择器 + success: function (index, layero) { + // layui 的select是单选点击一个的时候就关闭layer + layero.find('dl dd').click(function () { + close(); + }); + }, + end: function (selectElem) { + form.render('select', null, selectElem); + } + }); + + return { + version: version, + getPosition: getPosition, + close: close + // render: render // 不完善,暂不对外提供 + }; +}); diff --git a/WaterCloud.Web/wwwroot/js/lay-module/optimizeSelectOption/optimizeSelectOption.min.js b/WaterCloud.Web/wwwroot/js/lay-module/optimizeSelectOption/optimizeSelectOption.min.js new file mode 100644 index 0000000..344c922 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/optimizeSelectOption/optimizeSelectOption.min.js @@ -0,0 +1,2 @@ +/** layui-v2.5.4 MIT License By https://www.layui.com */ + ;!function(e){"use strict";var t="optimizeSelectOption";window.top.layui?window.top.layui.use("layer",function(){layui.define(["form"],function(n){n(t,e(t))})}):(console.warn("使用插件:"+t+"页面顶层窗口必须引入layui"),layui.define(["form"],function(e){e(t,{msg:"使用插件:"+t+"页面顶层窗口必须引入layui"})}))}(function(e){function t(e,n,o){n=n||window,e=e.length?e.get(0):e;var i={};if(o&&n.top!==n.self){var l=n.frames.frameElement;i=t(l,n.parent,o)}var a=e.getBoundingClientRect();return{top:a.top+(i.top||0),left:a.left+(i.left||0)}}var n="0.2.0",o=layui.$,i=layui.form,l=(layui.layer,layui.cache.modules.optimizeSelectOption.substr(0,layui.cache.modules.optimizeSelectOption.lastIndexOf("/")));layui.link(l+"/optimizeSelectOption.css?v"+n);var a=[".layui-table-view",".layui-layer-content",".select_option_to_layer"];if(window.top.layer._indexTemp=window.top.layer._indexTemp||{},!i.render.plugFlag){var r=i.render;i.render=function(e,t,n){var i,l=this;return n?layui.each(n,function(t,n){n=o(n);var a=n.parent(),s=a.hasClass("layui-form"),u=a.attr("lay-filter");s?"":a.addClass("layui-form"),u?"":a.attr("lay-filter","tablePlug_form_filter_temp_"+(new Date).getTime()+"_"+Math.floor(1e5*Math.random())),i=r.call(l,e,a.attr("lay-filter")),s?"":a.removeClass("layui-form"),u?"":a.attr("lay-filter",null)}):i=r.call(l,e,t),i},i.render.plugFlag=!0}var s=function(){window.top.layer.close(window.top.layer._indexTemp[e])},u={},c=function(n,i){var l=this;return u.name?(console.warn("针对",n,"的显示优化已经存在,请不要重复渲染!"),l):void o(document).on("click",a.map(function(e){return e+" "+i.triggerElem}).join(","),function(n){function l(){var e=t(u,window,!0),n=e.top,o=e.left;return p?n=n-c.outerHeight()+u.outerHeight()-parseFloat(c.css("bottom")):n+=parseFloat(c.css("top")),n+c.outerHeight()>window.top.innerHeight&&!p&&(p=!0,n-=c.outerHeight()+(2*parseFloat(c.css("top"))-u.outerHeight())),{top:n,left:o}}layui.stope(n),s();var r=o(this),u=r,c="function"==typeof i.dlElem?i.dlElem(r):u.next(),f=u.parent().prev(),p=u.parent().hasClass("layui-form-selectup"),d=l();u.css({backgroundColor:"transparent"}),window.top.layer._indexTemp[e]=window.top.layer.open({type:1,title:!1,closeBtn:0,shade:0,anim:-1,fixed:u.closest(".layui-layer-content").length||window.top!==window.self,isOutAnim:!1,offset:[d.top+"px",d.left+"px"],area:c.outerWidth()+"px",content:'
                ',skin:"layui-option-layer",success:function(e,t){c.css({top:0,position:"relative"}).appendTo(e.find(".layui-layer-content").css({overflow:"hidden"}).find(".layui-form-selected")),e.width(u.width());var n=window.top.innerHeight-e.outerHeight()-parseFloat(e.css("top"));p&&e.css({top:"auto",bottom:n+"px"}),"function"==typeof i.success&&i.success.call(this,t,e),e.on("mousedown",function(e){layui.stope(e)}),setTimeout(function(){u.parentsUntil(a.join(",")).one("scroll",function(e){s()}),u.parents(a.join(",")).one("scroll",function(e){s()});var e=window;do{var t=e.$||e.layui.$;t&&(t(e.document).one("click",function(e){s()}),t(e.document).one("mousedown",function(e){s()}),t(e).one("resize",function(e){s()}),t(e.document).one("scroll",function(){top!==self&&parent.parent&&s()}))}while(e.self!==e.top&&(e=e.parent))},500)},end:function(){"function"==typeof i.end&&i.end.call(this,f)}})})};return c("layuiSelect",{triggerElem:"div:not(.layui-select-disabled)>.layui-select-title",success:function(e,t){t.find("dl dd").click(function(){s()})},end:function(e){i.render("select",null,e)}}),{version:n,getPosition:t,close:s}}); \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/soulTable/excel.js b/WaterCloud.Web/wwwroot/js/lay-module/soulTable/excel.js new file mode 100644 index 0000000..7ce78bc --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/soulTable/excel.js @@ -0,0 +1,32630 @@ +/* +* @Author: Jeffrey Wang +* @Desc: 整理强大的 SheetJS 功能,依赖 XLSX.js 和 FileSaver +* @Version: v1.4 +* @Date: 2018-03-24 09:54:17 +* @Last Modified by: Jeffrey Wang +* @Last Modified time: 2019-01-15 11:49:09 +*/ +if (typeof layui === 'undefined' && typeof jQuery === 'undefined') { + console.error('非layui调用请先加载jQuery') +} +if (typeof jQuery !== 'undefined') { + $ = jQuery +} +LAY_EXCEL = { + /** + * 兼容老版本的导出函数 + * @param {[type]} data [description] + * @param {[type]} filename [description] + * @param {[type]} type [description] + * @return {[type]} [description] + */ + downloadExl: function(data, filename, type) { + type = type ? type : 'xlsx'; + this.exportExcel({sheet1: data}, filename+'.'+type, type, null); + }, + /** + * 导出Excel并弹出下载框,具体使用方法和范围请参考文档 + * @param data object + * @param {[type]} filename [description] + * @param {[type]} type [description] + * @param {[type]} opt [description] + * @return {[type]} [description] + */ + exportExcel : function(data, filename, type, opt) { + type = type ? type : 'xlsx'; + filename = filename ? filename : '导出数据.'+type; + + // 创建一个 XLSX 对象 + var wb = XLSX.utils.book_new(); + // 1. 定义excel对的基本属性 + var Props = { + Title: filename, + Subject: 'Export From web browser', + Author: "excel.wj2015.com", + Manager: '', + Company: '', + Category: '', + Keywords: '', + Comments: '', + LastAuthor: '', + CreatedData: new Date(), + }; + opt && opt.Props && (Props = $.extend(Props, opt.Props)); + // 默认进行压缩 + wb.compression = opt ? opt.compression : true + if(wb.compression !== false) { + wb.compression = true + } + wb.Props = Props; + // 特殊属性实现,比如合并单元格 + var wbExtend = { + '!merges': null + ,'!margins': null + ,'!cols': null + ,'!rows': null + ,'!protect': null + ,'!autofilter': null + }; + opt && opt.extend && (wbExtend = $.extend(wbExtend, opt.extend)); + // 清理空配置 + for (var key in wbExtend) { + if (!wbExtend.hasOwnProperty(key)) { + continue; + } + if (!wbExtend[key]) { + delete wbExtend[key]; + } + } + + // 判断 data 如果是 sheet 级别数据,自动加 sheet1 + if ($.isArray(data)) { + data = {sheet1: data}; + } + + for(var sheet_name in data) { + if (!data.hasOwnProperty(sheet_name)) { + continue; + } + var content = data[sheet_name]; + // 2. 设置sheet名称 + wb.SheetNames.push(sheet_name); + // 3. 分配工作表对象到 sheet + var is_aoa = false; + if (content.length && content[0] && $.isArray(content[0])) { + is_aoa = true; + } + if (is_aoa) { + ws = XLSX.utils.aoa_to_sheet(content); + } else { + var option = {}; + if (content.length) { + option.headers = content.unshift(); + option.skipHeader = true; + // 分离并重组样式 + var splitRes = this.splitContent(content); + } + var ws = XLSX.utils.json_to_sheet(content, option); + // 特殊属性,支持单独设置某个sheet的属性 + if (wbExtend[sheet_name]) { + $.extend(ws, wbExtend[sheet_name]); + } else { + $.extend(ws, wbExtend); + } + // 合并样式 + if (typeof splitRes !== 'undefined') { + this.mergeCellOpt(ws, splitRes.style); + } + } + wb.Sheets[sheet_name] = ws; + }; + + // 4. 输出工作表 + var wbout = XLSX.write(wb, {bookType: type, type: 'binary', cellStyles: true, compression: wb.compression}); + + // 5. 跨浏览器支持,采用 FileSaver 三方库 + saveAs(new Blob([this.s2ab(wbout)], {type: "application/octet-stream"}), filename); + }, + /** + * 分离内容和样式 + * @param {[type]} content [description] + * @return {[type]} [description] + */ + splitContent: function(content) { + var styleContent = {}; + // 扫描每个单元格,如果是对象则等表格转换完毕后分离出来重新赋值 + for (var line = 0; line < content.length; line++) { + var lineData = content[line]; + var rowIndex = 0; + for (var row in lineData) { + if (!lineData.hasOwnProperty(row)) { + continue; + } + var rowData = lineData[row]; + if (typeof rowData === 'object') { + // typeof null == object + if (rowData !== null) { + styleContent[this.numToTitle(rowIndex+1)+(parseInt(line)+1)] = rowData; + } else { + lineData[row] = ''; + } + } else { + // JeffreyWang 2019-03-10针对 0 的hack处理 + if (rowData === 0) { + rowData = { + v: '0', + s: { + alignment: { + horizontal: 'right' + } + } + } + } + styleContent[this.numToTitle(rowIndex+1)+(parseInt(line)+1)] = rowData; + } + rowIndex++; + } + } + return { + content: content, + style: styleContent + }; + }, + /** + * 合并内容和样式 + * @param {[type]} ws [description] + * @param {[type]} style [description] + * @return {[type]} [description] + */ + mergeCellOpt: function(ws, style) { + for (var row in style) { + if (!style.hasOwnProperty(row)) { + continue; + } + var rowOpt = style[row]; + if (ws[row]) { + // 其他属性做一个初始化 + var otherOpt = ['t', 'w', 'f', 'r', 'h', 'c', 'z', 'l', 's']; + for (var i = 0; i < otherOpt.length; i++) { + ws[row][otherOpt[i]] = ws[row][otherOpt[i]]; + } + $.extend(ws[row], rowOpt); + } + } + }, + /** + * 将table转换为JSON数据 + * @param dom + */ + tableToJson: function(dom) { + dom = $(dom) + + var head = [] + dom.find('thead > tr').each(function () { + var line = [] + $(this).find('td,th').each(function () { + line.push($(this).text()) + }) + head.push(line) + }) + + var body = []; + dom.find('tbody > tr').each(function () { + var line = [] + $(this).find('td').each(function () { + line.push($(this).text()) + }) + body.push(line) + }) + + return { + head: head, + body: body + } + }, + // 测试代码: + // for(i=1;i<100;i++){var change = layui.excel.numToTitle(i);console.log(i, change, layui.excel.titleToNum(change));} + // numsToTitle备忘录提效 + numsTitleCache: {}, + // titleToTitle 备忘录提效 + titleNumsCache: {}, + /** + * 将数字(从一开始)转换为 A、B、C...AA、AB + * @param {[int]} num [description] + * @return {[type]} [description] + */ + numToTitle: function(num) { + if (this.numsTitleCache[num]) { + return this.numsTitleCache[num]; + } + var ans = ''; + if (num > 26) { + // 要注意小心 26 的倍数导致的无限递归问题 + var dec = num % 26; + ans = this.numToTitle((num - dec)/26) + this.numToTitle(dec?dec:26); + this.numsTitleCache[num] = ans; + this.titleNumsCache[ans] = num; + return ans; + } else { + // A 的 ascii 为 0,顺位相加 + ans = String.fromCharCode(64 + num); + this.numsTitleCache[num] = ans; + this.titleNumsCache[ans] = num; + return ans; + } + }, + /** + * 将A、B、AA、ABC转换为 1、2、3形式的数字 + * @param {[type]} title [description] + * @return {number} [description] + */ + titleToNum: function(title) { + if (this.titleNumsCache[title]) { + return this.titleNumsCache[title]; + } + var len = title.length; + var total = 0; + for (var index in title) { + if (!title.hasOwnProperty(index)) { + continue; + } + var char = title[index]; + var code = char.charCodeAt() - 64; + total += code * Math.pow(26, len - index - 1); + } + this.numsTitleCache[total] = title; + this.titleNumsCache[title] = total; + return total; + }, + /** + * 批量设置单元格属性 + * @param {array} data [sheet级别的数据] + * @param {string} range [范围字符串,比如 A1:C12,开始位置默认 A1,结束位置默认整个表格右下角] + * @param {object} config [批量设置的单元格属性] + * @param {function} filter [回调函数,传递函数生效,返回值作为新的值(可用于过滤、规则替换样式等骚操作)] + * @return {array} [重新渲染后的 sheet 数据] + */ + setExportCellStyle: function(data, range, config, filter) { + if (typeof data !== 'object' || !data.length || !data[0] || !Object.keys(data[0]).length) { + return []; + } + + // 以 rowIndex 为键,field 为值 + var fieldKeys = Object.keys(data[0]); + var maxCol = data.length -1; + var maxRow = fieldKeys.length - 1; + // 默认 A1 ~ 右下角 + var startPos = {c: 0, r: 0}; + var endPos = {c: maxCol, r: maxRow}; + + if (range && typeof range === 'string') { + var rangeArr = range.split(':'); + if (rangeArr[0].length) { + startPos = this.splitPosition(rangeArr[0]); + } + if (typeof rangeArr[1] !== 'undefined' && rangeArr[1] !== '') { + endPos = this.splitPosition(rangeArr[1]); + } + } else { + // pass + } + // position范围限制 - 考虑到特殊情况取消此限制 + // startPos.c = startPos.c < maxCol ? startPos.c : maxCol; + // endPos.c = endPos.c < maxCol ? endPos.c : maxCol; + // startPos.r = startPos.r < maxRow ? startPos.r : maxRow; + // endPos.r = endPos.r < maxRow ? endPos.r : maxRow; + + if (startPos.c > endPos.c) { + console.error('开始列不得大于结束列'); + } + if (startPos.r > endPos.r) { + console.error('开始行不得大于结束行'); + } + + // 遍历范围内的数据,进行样式设置,按从上到下从左到右按行遍历 + for (var currentRow = startPos.r; currentRow <= endPos.r; currentRow++) { + for (var currentCol = startPos.c; currentCol <= endPos.c; currentCol++) { + // 如果有回调则执行回调判断,否则全部更新,如果遇到超出数据范围的,自动置空 + var row = data[currentRow]; + if (!row) { + row = {}; + for (var key = 0; key < fieldKeys.length; key++) { + row[fieldKeys[key]] = ''; + } + data[currentRow] = row; + } + var cell = row[fieldKeys[currentCol]]; + var newCell = null; + if (cell === null || cell === undefined) { + cell = ''; + } + + // 手工合并(相同的则以当前函数config为准) + if (typeof cell === 'object') { + newCell = $.extend(true, {}, cell, config); + } else { + newCell = $.extend(true, {}, {v: cell}, config); + } + + if ( + typeof filter === 'function' + ) { + newCell = filter(cell, newCell, row, config, currentRow, currentCol, fieldKeys[currentCol]); + } else { + } + // 回写 + data[currentRow][fieldKeys[currentCol]] = newCell; + } + } + return data; + }, + /** + * 合并单元格快速生成配置的函数 传入 [ ['开始坐标 A1', '结束坐标 D2'], ['开始坐标 B2', '结束坐标 E3'] ] + * @param {[type]} origin [description] + * @return {[type]} [description] + */ + makeMergeConfig: function(origin) { + var merge = []; + for (var index = 0; index < origin.length; index++) { + merge.push({ + s: this.splitPosition(origin[index][0]), + e: this.splitPosition(origin[index][1]), + }); + } + return merge; + }, + /** + * 自动生成列宽配置 + * @param {$ObjMap} data [A、B、C的宽度映射] + * @param {number} defaultNum [description] + * @return {$ObjMap} [description] + */ + makeColConfig: function(data, defaultNum) { + defaultNum = defaultNum > 0 ? defaultNum : 50; + // 将列的 ABC 转换为 index + var change = []; + var startIndex = 0; + for (var index in data) { + if (!data.hasOwnProperty(index)) { + continue; + } + var item = data[index]; + if (index.match && index.match(/[A-Z]*/)) { + var currentIndex = this.titleToNum(index) - 1; + // 填充未配置的单元格 + while (startIndex < currentIndex) { + change.push({wpx: defaultNum}); + startIndex++; + } + startIndex = currentIndex+1; + change.push({wpx: item > 0 ? item : defaultNum}); + } + }; + return change; + }, + /** + * 自动生成列高配置 + * @param {[type]} data [description] + * @param {[type]} defaultNum [description] + * @return {[type]} [description] + */ + makeRowConfig: function(data, defaultNum) { + defaultNum = defaultNum > 0 ? defaultNum : 10; + // 将列的 ABC 转换为 index + var change = []; + var startIndex = 0; + for (var index in data) { + if (!data.hasOwnProperty(index)) { + continue; + } + var item = data[index]; + if (index.match && index.match(/[0-9]*/)) { + var currentIndex = parseInt(index) - 1; + // 填充未配置的行 + while (startIndex < currentIndex) { + change.push({hpx: defaultNum}); + startIndex++; + } + startIndex = currentIndex+1; + change.push({hpx: item > 0 ? item : defaultNum}); + } + }; + return change; + }, + /** + * 将A1分离成 {c: 0, r: 0} 格式的数据 + * @param {string} pos [description] + * @return {{r: number, c: number}} [description] + */ + splitPosition: function(pos) { + var res = pos.match('^([A-Z]+)([0-9]+)$'); + if (!res) { + return {c: 0, r: 0}; + } + // 转换结果相比需要的结果需要减一转换 + return { + c: this.titleToNum(res[1]) - 1, + r: parseInt(res[2]) - 1 + } + }, + /** + * 将二进制数据转为8位字节 + * @param {[type]} s [description] + * @return {[type]} [description] + */ + s2ab: function(s) { + var buf = new ArrayBuffer(s.length); + var view = new Uint8Array(buf); + for (var i = 0; i < s.length; i++) { + view[i] = s.charCodeAt(i) & 0xFF; + } + return buf; + }, + /** + * 将导出的数据格式,转换为可以aoa导出的格式 + * @return {[type]} [description] + */ + filterDataToAoaData: function(filterData){ + var aoaData = []; + $.each(filterData, function(index, item) { + var itemData = []; + for (var i in item) { + if (!item.hasOwnProperty(i)) { + continue; + } + itemData.push(item[i]); + } + aoaData.push(itemData); + }); + return aoaData; + }, + /** + * 梳理导出的数据,包括字段排序和多余数据过滤,具体功能请参见文档 + * @param {[type]} data [需要梳理的数据] + * @param {[type]} fields [支持数组和对象,用于映射关系和字段排序] + * @return {[type]} [description] + */ + filterExportData: function(data, fields) { + // PS:之所以不直接引用 data 节省内存,是因为担心如果 fields 可能存在如下情况: { "id": 'test_id', 'test_id': 'new_id' },会导致处理异常 + var exportData = []; + var true_fields = []; + // filed 支持两种模式,数组则单纯排序,对象则转换映射关系,为了统一处理,将数组转换为符合要求的映射关系对象 + if (Array.isArray(fields)) { + for (var i = 0; i< fields.length; i++) { + true_fields[fields[i]] = fields[i]; + } + } else { + true_fields = fields; + } + for (var i = 0; i < data.length; i++) { + var item = data[i]; + exportData[i] = {}; + for (var key in true_fields) { + if (!true_fields.hasOwnProperty(key)) { + continue; + } + var new_field_name = key; + var old_field_name = true_fields[key]; + // 如果传入的是回调,则回调的值则为新值 + if (typeof old_field_name === 'function' && old_field_name.apply) { + exportData[i][new_field_name] = old_field_name.apply(window, [new_field_name, item, data, i]); + } else { + if (typeof item[old_field_name] !== 'undefined') { + exportData[i][new_field_name] = item[old_field_name]; + } else { + exportData[i][new_field_name] = ''; + } + } + } + } + return exportData; + }, + /** + * 梳理导入的数据,参数意义可参考 filterExportData + * @param {[type]} data [description] + * @param {[type]} fields [description] + * @return {[type]} [description] + */ + filterImportData: function(data, fields) { + var that = this; + $.each(data, function(fileindex, xlsx) { + $.each(xlsx, function(sheetname, content) { + xlsx[sheetname] = that.filterExportData(content, fields); + }); + }); + return data; + }, + /** + * 读取Excel,支持多文件多表格读取 + * @param {[type]} files [description] + * @param {[type]} opt [description] + * @param {Function} callback [description] + * @return {[type]} [description] + */ + importExcel: function(files, opt, callback) { + var option = { + header: 'A', + range: null, + fields: null, + }; + $.extend(option, opt); + var that = this; + + if (files.length < 1) { + throw {code: 999, 'message': '传入文件为空'}; + } + var supportReadMime = [ + 'application/vnd.ms-excel', + 'application/msexcel', + 'application/x-msexcel', + 'application/x-ms-excel', + 'application/x-excel', + 'application/x-dos_ms_excel', + 'application/xls', + 'application/x-xls', + 'application/vnd-xls', + 'application/csv', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + '' + ]; + $.each(files, function(index, item) { + if (supportReadMime.indexOf(item.type) === -1) { + throw {code: 999, message: item.name+'('+item.type+')为不支持的文件类型'}; + } + }); + + // 按照二进制读取 + var data = {}; + var book = {}; + $.each(files, function(index, item) { + var reader = new FileReader(); + if (!reader) { + throw {code: 999, message: '不支持FileReader,请更换更新的浏览器'}; + } + // 读取excel表格对象 + reader.onload = function(ev) { + var wb = XLSX.read(ev.target.result, { + type: 'binary' + }); + var excelData = {}; + $.each(wb.Sheets, function(sheet, sheetObj) { + // 全为空的去掉 + if (wb.Sheets.hasOwnProperty(sheet)) { + var opt = { + header: option.header, + defval: '' + }; + if (option.range) { + opt.range = option.range; + } + excelData[sheet] = XLSX.utils.sheet_to_json(sheetObj, opt); + // 支持梳理数据 + if (option.fields) { + excelData[sheet] = that.filterExportData(excelData[sheet], option.fields); + } + } + }); + data[index] = excelData; + book[index] = wb; + // 全部读取完毕才执行 + if (index === files.length - 1) { + callback && callback.apply && callback.apply(window, [data, book]); + } + }; + reader.readAsBinaryString(item); + }); + } +} + +if (typeof layui !== 'undefined') { + layui.define(['jquery'], function(exports){ + $ = layui.jquery; + exports('excel', LAY_EXCEL); + }); +} +/*---------split--------*//* Blob.js + * A Blob, File, FileReader & URL implementation. + * 2018-08-09 + * + * By Eli Grey, http://eligrey.com + * By Jimmy Wärting, https://github.com/jimmywarting + * License: MIT + * See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md + */ + +;(function(){ + + var global = typeof window === 'object' + ? window : typeof self === 'object' + ? self : this + + var BlobBuilder = global.BlobBuilder + || global.WebKitBlobBuilder + || global.MSBlobBuilder + || global.MozBlobBuilder; + + global.URL = global.URL || global.webkitURL || function(href, a) { + a = document.createElement('a') + a.href = href + return a + } + + var origBlob = global.Blob + var createObjectURL = URL.createObjectURL + var revokeObjectURL = URL.revokeObjectURL + var strTag = global.Symbol && global.Symbol.toStringTag + var blobSupported = false + var blobSupportsArrayBufferView = false + var arrayBufferSupported = !!global.ArrayBuffer + var blobBuilderSupported = BlobBuilder + && BlobBuilder.prototype.append + && BlobBuilder.prototype.getBlob; + + try { + // Check if Blob constructor is supported + blobSupported = new Blob(['ä']).size === 2 + + // Check if Blob constructor supports ArrayBufferViews + // Fails in Safari 6, so we need to map to ArrayBuffers there. + blobSupportsArrayBufferView = new Blob([new Uint8Array([1,2])]).size === 2 + } catch(e) {} + + /** + * Helper function that maps ArrayBufferViews to ArrayBuffers + * Used by BlobBuilder constructor and old browsers that didn't + * support it in the Blob constructor. + */ + function mapArrayBufferViews(ary) { + return ary.map(function(chunk) { + if (chunk.buffer instanceof ArrayBuffer) { + var buf = chunk.buffer; + + // if this is a subarray, make a copy so we only + // include the subarray region from the underlying buffer + if (chunk.byteLength !== buf.byteLength) { + var copy = new Uint8Array(chunk.byteLength); + copy.set(new Uint8Array(buf, chunk.byteOffset, chunk.byteLength)); + buf = copy.buffer; + } + + return buf; + } + + return chunk; + }); + } + + function BlobBuilderConstructor(ary, options) { + options = options || {}; + + var bb = new BlobBuilder(); + mapArrayBufferViews(ary).forEach(function(part) { + bb.append(part); + }); + + return options.type ? bb.getBlob(options.type) : bb.getBlob(); + }; + + function BlobConstructor(ary, options) { + return new origBlob(mapArrayBufferViews(ary), options || {}); + }; + + if (global.Blob) { + BlobBuilderConstructor.prototype = Blob.prototype; + BlobConstructor.prototype = Blob.prototype; + } + + function FakeBlobBuilder() { + function toUTF8Array(str) { + var utf8 = []; + for (var i=0; i < str.length; i++) { + var charcode = str.charCodeAt(i); + if (charcode < 0x80) utf8.push(charcode); + else if (charcode < 0x800) { + utf8.push(0xc0 | (charcode >> 6), + 0x80 | (charcode & 0x3f)); + } + else if (charcode < 0xd800 || charcode >= 0xe000) { + utf8.push(0xe0 | (charcode >> 12), + 0x80 | ((charcode>>6) & 0x3f), + 0x80 | (charcode & 0x3f)); + } + // surrogate pair + else { + i++; + // UTF-16 encodes 0x10000-0x10FFFF by + // subtracting 0x10000 and splitting the + // 20 bits of 0x0-0xFFFFF into two halves + charcode = 0x10000 + (((charcode & 0x3ff)<<10) + | (str.charCodeAt(i) & 0x3ff)); + utf8.push(0xf0 | (charcode >>18), + 0x80 | ((charcode>>12) & 0x3f), + 0x80 | ((charcode>>6) & 0x3f), + 0x80 | (charcode & 0x3f)); + } + } + return utf8; + } + function fromUtf8Array(array) { + var out, i, len, c; + var char2, char3; + + out = ""; + len = array.length; + i = 0; + while (i < len) { + c = array[i++]; + switch (c >> 4) + { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: + // 0xxxxxxx + out += String.fromCharCode(c); + break; + case 12: case 13: + // 110x xxxx 10xx xxxx + char2 = array[i++]; + out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); + break; + case 14: + // 1110 xxxx 10xx xxxx 10xx xxxx + char2 = array[i++]; + char3 = array[i++]; + out += String.fromCharCode(((c & 0x0F) << 12) | + ((char2 & 0x3F) << 6) | + ((char3 & 0x3F) << 0)); + break; + } + } + return out; + } + function isDataView(obj) { + return obj && DataView.prototype.isPrototypeOf(obj) + } + function bufferClone(buf) { + var view = new Array(buf.byteLength) + var array = new Uint8Array(buf) + var i = view.length + while(i--) { + view[i] = array[i] + } + return view + } + function encodeByteArray(input) { + var byteToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' + + var output = []; + + for (var i = 0; i < input.length; i += 3) { + var byte1 = input[i]; + var haveByte2 = i + 1 < input.length; + var byte2 = haveByte2 ? input[i + 1] : 0; + var haveByte3 = i + 2 < input.length; + var byte3 = haveByte3 ? input[i + 2] : 0; + + var outByte1 = byte1 >> 2; + var outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4); + var outByte3 = ((byte2 & 0x0F) << 2) | (byte3 >> 6); + var outByte4 = byte3 & 0x3F; + + if (!haveByte3) { + outByte4 = 64; + + if (!haveByte2) { + outByte3 = 64; + } + } + + output.push( + byteToCharMap[outByte1], byteToCharMap[outByte2], + byteToCharMap[outByte3], byteToCharMap[outByte4]) + } + + return output.join('') + } + + var create = Object.create || function (a) { + function c() {} + c.prototype = a; + return new c + } + + if (arrayBufferSupported) { + var viewClasses = [ + '[object Int8Array]', + '[object Uint8Array]', + '[object Uint8ClampedArray]', + '[object Int16Array]', + '[object Uint16Array]', + '[object Int32Array]', + '[object Uint32Array]', + '[object Float32Array]', + '[object Float64Array]' + ] + + var isArrayBufferView = ArrayBuffer.isView || function(obj) { + return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1 + } + } + + + + /********************************************************/ + /* Blob constructor */ + /********************************************************/ + function Blob(chunks, opts) { + chunks = chunks || [] + for (var i = 0, len = chunks.length; i < len; i++) { + var chunk = chunks[i] + if (chunk instanceof Blob) { + chunks[i] = chunk._buffer + } else if (typeof chunk === 'string') { + chunks[i] = toUTF8Array(chunk) + } else if (arrayBufferSupported && (ArrayBuffer.prototype.isPrototypeOf(chunk) || isArrayBufferView(chunk))) { + chunks[i] = bufferClone(chunk) + } else if (arrayBufferSupported && isDataView(chunk)) { + chunks[i] = bufferClone(chunk.buffer) + } else { + chunks[i] = toUTF8Array(String(chunk)) + } + } + + this._buffer = [].concat.apply([], chunks) + this.size = this._buffer.length + this.type = opts ? opts.type || '' : '' + } + + Blob.prototype.slice = function(start, end, type) { + var slice = this._buffer.slice(start || 0, end || this._buffer.length) + return new Blob([slice], {type: type}) + } + + Blob.prototype.toString = function() { + return '[object Blob]' + } + + + + /********************************************************/ + /* File constructor */ + /********************************************************/ + function File(chunks, name, opts) { + opts = opts || {} + var a = Blob.call(this, chunks, opts) || this + a.name = name + a.lastModifiedDate = opts.lastModified ? new Date(opts.lastModified) : new Date + a.lastModified = +a.lastModifiedDate + + return a + } + + File.prototype = create(Blob.prototype); + File.prototype.constructor = File; + + if (Object.setPrototypeOf) + Object.setPrototypeOf(File, Blob); + else { + try {File.__proto__ = Blob} catch (e) {} + } + + File.prototype.toString = function() { + return '[object File]' + } + + + /********************************************************/ + /* FileReader constructor */ + /********************************************************/ + function FileReader() { + if (!(this instanceof FileReader)) + throw new TypeError("Failed to construct 'FileReader': Please use the 'new' operator, this DOM object constructor cannot be called as a function.") + + var delegate = document.createDocumentFragment() + this.addEventListener = delegate.addEventListener + this.dispatchEvent = function(evt) { + var local = this['on' + evt.type] + if (typeof local === 'function') local(evt) + delegate.dispatchEvent(evt) + } + this.removeEventListener = delegate.removeEventListener + } + + function _read(fr, blob, kind) { + if (!(blob instanceof Blob)) + throw new TypeError("Failed to execute '" + kind + "' on 'FileReader': parameter 1 is not of type 'Blob'.") + + fr.result = '' + + setTimeout(function(){ + this.readyState = FileReader.LOADING + fr.dispatchEvent(new Event('load')) + fr.dispatchEvent(new Event('loadend')) + }) + } + + FileReader.EMPTY = 0 + FileReader.LOADING = 1 + FileReader.DONE = 2 + FileReader.prototype.error = null + FileReader.prototype.onabort = null + FileReader.prototype.onerror = null + FileReader.prototype.onload = null + FileReader.prototype.onloadend = null + FileReader.prototype.onloadstart = null + FileReader.prototype.onprogress = null + + FileReader.prototype.readAsDataURL = function(blob) { + _read(this, blob, 'readAsDataURL') + this.result = 'data:' + blob.type + ';base64,' + encodeByteArray(blob._buffer) + } + + FileReader.prototype.readAsText = function(blob) { + _read(this, blob, 'readAsText') + this.result = fromUtf8Array(blob._buffer) + } + + FileReader.prototype.readAsArrayBuffer = function(blob) { + _read(this, blob, 'readAsText') + this.result = blob._buffer.slice() + } + + FileReader.prototype.abort = function() {} + + + /********************************************************/ + /* URL */ + /********************************************************/ + URL.createObjectURL = function(blob) { + return blob instanceof Blob + ? 'data:' + blob.type + ';base64,' + encodeByteArray(blob._buffer) + : createObjectURL.call(URL, blob) + } + + URL.revokeObjectURL = function(url) { + revokeObjectURL && revokeObjectURL.call(URL, url) + } + + /********************************************************/ + /* XHR */ + /********************************************************/ + var _send = global.XMLHttpRequest && global.XMLHttpRequest.prototype.send + if (_send) { + XMLHttpRequest.prototype.send = function(data) { + if (data instanceof Blob) { + this.setRequestHeader('Content-Type', data.type) + _send.call(this, fromUtf8Array(data._buffer)) + } else { + _send.call(this, data) + } + } + } + + global.FileReader = FileReader + global.File = File + global.Blob = Blob + } + + if (strTag) { + File.prototype[strTag] = 'File' + Blob.prototype[strTag] = 'Blob' + FileReader.prototype[strTag] = 'FileReader' + } + + function fixFileAndXHR() { + var isIE = !!global.ActiveXObject || ( + '-ms-scroll-limit' in document.documentElement.style && + '-ms-ime-align' in document.documentElement.style + ) + + // Monkey patched + // IE don't set Content-Type header on XHR whose body is a typed Blob + // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/6047383 + var _send = global.XMLHttpRequest && global.XMLHttpRequest.prototype.send + if (isIE && _send) { + XMLHttpRequest.prototype.send = function(data) { + if (data instanceof Blob) { + this.setRequestHeader('Content-Type', data.type) + _send.call(this, data) + } else { + _send.call(this, data) + } + } + } + + try { + new File([], '') + } catch(e) { + try { + var klass = new Function('class File extends Blob {' + + 'constructor(chunks, name, opts) {' + + 'opts = opts || {};' + + 'super(chunks, opts || {});' + + 'this.name = name;' + + 'this.lastModifiedDate = opts.lastModified ? new Date(opts.lastModified) : new Date;' + + 'this.lastModified = +this.lastModifiedDate;' + + '}};' + + 'return new File([], ""), File' + )() + global.File = klass + } catch(e) { + var klass = function(b, d, c) { + var blob = new Blob(b, c) + var t = c && void 0 !== c.lastModified ? new Date(c.lastModified) : new Date + + blob.name = d + blob.lastModifiedDate = t + blob.lastModified = +t + blob.toString = function() { + return '[object File]' + } + + if (strTag) + blob[strTag] = 'File' + + return blob + } + global.File = klass + } + } + } + + if (blobSupported) { + fixFileAndXHR() + global.Blob = blobSupportsArrayBufferView ? global.Blob : BlobConstructor + } else if (blobBuilderSupported) { + fixFileAndXHR() + global.Blob = BlobBuilderConstructor; + } else { + FakeBlobBuilder() + } + +})(); +/*---------split--------*/(function(a,b){if("function"==typeof define&&define.amd)define([],b);else if("undefined"!=typeof exports)b();else{b(),a.FileSaver={exports:{}}.exports}})(this,function(){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Depricated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(b,c,d){var e=new XMLHttpRequest;e.open("GET",b),e.responseType="blob",e.onload=function(){a(e.response,c,d)},e.onerror=function(){console.error("could not download file")},e.send()}function d(a){var b=new XMLHttpRequest;return b.open("HEAD",a,!1),b.send(),200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:void 0,a=f.saveAs||"object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(f,g,h){if(g=g||f.name||"download","string"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement("a");i.href=f,i.target="_blank",setTimeout(function(){e(i)})}}:function(a,b,d,e){if(e=e||open("","_blank"),e&&(e.document.title=e.document.body.innerText="downloading..."),"string"==typeof a)return c(a,b,d);var g="application/octet-stream"===a.type,h=/constructor/i.test(f.HTMLElement)||f.safari,i=/CriOS\/[\d]+/.test(navigator.userAgent);if((i||g&&h)&&"object"==typeof FileReader){var j=new FileReader;j.onloadend=function(){var a=j.result;a=i?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),e?e.location.href=a:location=a,e=null},j.readAsDataURL(a)}else{var k=f.URL||f.webkitURL,l=k.createObjectURL(a);e?e.location=l:location.href=l,e=null,setTimeout(function(){k.revokeObjectURL(l)},4E4)}};f.saveAs=a.saveAs=a,"undefined"!=typeof module&&(module.exports=a)}); + +/*---------split--------*//* + +JSZip - A Javascript class for generating and reading zip files + + +(c) 2009-2014 Stuart Knightley +Dual licenced under the MIT license or GPLv3. See https://raw.github.com/Stuk/jszip/master/LICENSE.markdown. + +JSZip uses the library pako released under the MIT license : +https://github.com/nodeca/pako/blob/master/LICENSE + +Note: since JSZip 3 removed critical functionality, this version assigns to the +`JSZipSync` variable. Another JSZip version can be loaded in parallel. +*/ +(function(e){ + if("object"==typeof exports&&"undefined"!=typeof module&&"undefined"==typeof DO_NOT_EXPORT_JSZIP)module.exports=e(); + else if("function"==typeof define&&define.amd&&"undefined"==typeof DO_NOT_EXPORT_JSZIP){JSZipSync=e();define([],e);} + else{ + var f; + "undefined"!=typeof window?f=window: + "undefined"!=typeof global?f=global: + "undefined"!=typeof $ && $.global?f=$.global: + "undefined"!=typeof self&&(f=self),f.JSZipSync=e() + } +}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2)) { + enc3 = enc4 = 64; + } + else if (isNaN(chr3)) { + enc4 = 64; + } + + output = output + _keyStr.charAt(enc1) + _keyStr.charAt(enc2) + _keyStr.charAt(enc3) + _keyStr.charAt(enc4); + + } + + return output; + }; + +// public method for decoding + exports.decode = function(input, utf8) { + var output = ""; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + while (i < input.length) { + + enc1 = _keyStr.indexOf(input.charAt(i++)); + enc2 = _keyStr.indexOf(input.charAt(i++)); + enc3 = _keyStr.indexOf(input.charAt(i++)); + enc4 = _keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output = output + String.fromCharCode(chr1); + + if (enc3 != 64) { + output = output + String.fromCharCode(chr2); + } + if (enc4 != 64) { + output = output + String.fromCharCode(chr3); + } + + } + + return output; + + }; + + },{}],2:[function(_dereq_,module,exports){ + 'use strict'; + function CompressedObject() { + this.compressedSize = 0; + this.uncompressedSize = 0; + this.crc32 = 0; + this.compressionMethod = null; + this.compressedContent = null; + } + + CompressedObject.prototype = { + /** + * Return the decompressed content in an unspecified format. + * The format will depend on the decompressor. + * @return {Object} the decompressed content. + */ + getContent: function() { + return null; // see implementation + }, + /** + * Return the compressed content in an unspecified format. + * The format will depend on the compressed conten source. + * @return {Object} the compressed content. + */ + getCompressedContent: function() { + return null; // see implementation + } + }; + module.exports = CompressedObject; + + },{}],3:[function(_dereq_,module,exports){ + 'use strict'; + exports.STORE = { + magic: "\x00\x00", + compress: function(content) { + return content; // no compression + }, + uncompress: function(content) { + return content; // no compression + }, + compressInputType: null, + uncompressInputType: null + }; + exports.DEFLATE = _dereq_('./flate'); + + },{"./flate":8}],4:[function(_dereq_,module,exports){ + 'use strict'; + + var utils = _dereq_('./utils'); + + var table = [ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + ]; + + /** + * + * Javascript crc32 + * http://www.webtoolkit.info/ + * + */ + module.exports = function crc32(input, crc) { + if (typeof input === "undefined" || !input.length) { + return 0; + } + + var isArray = utils.getTypeOf(input) !== "string"; + + if (typeof(crc) == "undefined") { + crc = 0; + } + var x = 0; + var y = 0; + var b = 0; + + crc = crc ^ (-1); + for (var i = 0, iTop = input.length; i < iTop; i++) { + b = isArray ? input[i] : input.charCodeAt(i); + y = (crc ^ b) & 0xFF; + x = table[y]; + crc = (crc >>> 8) ^ x; + } + + return crc ^ (-1); + }; +// vim: set shiftwidth=4 softtabstop=4: + + },{"./utils":21}],5:[function(_dereq_,module,exports){ + 'use strict'; + var utils = _dereq_('./utils'); + + function DataReader(data) { + this.data = null; // type : see implementation + this.length = 0; + this.index = 0; + } + DataReader.prototype = { + /** + * Check that the offset will not go too far. + * @param {string} offset the additional offset to check. + * @throws {Error} an Error if the offset is out of bounds. + */ + checkOffset: function(offset) { + this.checkIndex(this.index + offset); + }, + /** + * Check that the specifed index will not be too far. + * @param {string} newIndex the index to check. + * @throws {Error} an Error if the index is out of bounds. + */ + checkIndex: function(newIndex) { + if (this.length < newIndex || newIndex < 0) { + throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?"); + } + }, + /** + * Change the index. + * @param {number} newIndex The new index. + * @throws {Error} if the new index is out of the data. + */ + setIndex: function(newIndex) { + this.checkIndex(newIndex); + this.index = newIndex; + }, + /** + * Skip the next n bytes. + * @param {number} n the number of bytes to skip. + * @throws {Error} if the new index is out of the data. + */ + skip: function(n) { + this.setIndex(this.index + n); + }, + /** + * Get the byte at the specified index. + * @param {number} i the index to use. + * @return {number} a byte. + */ + byteAt: function(i) { + // see implementations + }, + /** + * Get the next number with a given byte size. + * @param {number} size the number of bytes to read. + * @return {number} the corresponding number. + */ + readInt: function(size) { + var result = 0, + i; + this.checkOffset(size); + for (i = this.index + size - 1; i >= this.index; i--) { + result = (result << 8) + this.byteAt(i); + } + this.index += size; + return result; + }, + /** + * Get the next string with a given byte size. + * @param {number} size the number of bytes to read. + * @return {string} the corresponding string. + */ + readString: function(size) { + return utils.transformTo("string", this.readData(size)); + }, + /** + * Get raw data without conversion, bytes. + * @param {number} size the number of bytes to read. + * @return {Object} the raw data, implementation specific. + */ + readData: function(size) { + // see implementations + }, + /** + * Find the last occurence of a zip signature (4 bytes). + * @param {string} sig the signature to find. + * @return {number} the index of the last occurence, -1 if not found. + */ + lastIndexOfSignature: function(sig) { + // see implementations + }, + /** + * Get the next date. + * @return {Date} the date. + */ + readDate: function() { + var dostime = this.readInt(4); + return new Date( + ((dostime >> 25) & 0x7f) + 1980, // year + ((dostime >> 21) & 0x0f) - 1, // month + (dostime >> 16) & 0x1f, // day + (dostime >> 11) & 0x1f, // hour + (dostime >> 5) & 0x3f, // minute + (dostime & 0x1f) << 1); // second + } + }; + module.exports = DataReader; + + },{"./utils":21}],6:[function(_dereq_,module,exports){ + 'use strict'; + exports.base64 = false; + exports.binary = false; + exports.dir = false; + exports.createFolders = false; + exports.date = null; + exports.compression = null; + exports.comment = null; + + },{}],7:[function(_dereq_,module,exports){ + 'use strict'; + var utils = _dereq_('./utils'); + + /** + * @deprecated + * This function will be removed in a future version without replacement. + */ + exports.string2binary = function(str) { + return utils.string2binary(str); + }; + + /** + * @deprecated + * This function will be removed in a future version without replacement. + */ + exports.string2Uint8Array = function(str) { + return utils.transformTo("uint8array", str); + }; + + /** + * @deprecated + * This function will be removed in a future version without replacement. + */ + exports.uint8Array2String = function(array) { + return utils.transformTo("string", array); + }; + + /** + * @deprecated + * This function will be removed in a future version without replacement. + */ + exports.string2Blob = function(str) { + var buffer = utils.transformTo("arraybuffer", str); + return utils.arrayBuffer2Blob(buffer); + }; + + /** + * @deprecated + * This function will be removed in a future version without replacement. + */ + exports.arrayBuffer2Blob = function(buffer) { + return utils.arrayBuffer2Blob(buffer); + }; + + /** + * @deprecated + * This function will be removed in a future version without replacement. + */ + exports.transformTo = function(outputType, input) { + return utils.transformTo(outputType, input); + }; + + /** + * @deprecated + * This function will be removed in a future version without replacement. + */ + exports.getTypeOf = function(input) { + return utils.getTypeOf(input); + }; + + /** + * @deprecated + * This function will be removed in a future version without replacement. + */ + exports.checkSupport = function(type) { + return utils.checkSupport(type); + }; + + /** + * @deprecated + * This value will be removed in a future version without replacement. + */ + exports.MAX_VALUE_16BITS = utils.MAX_VALUE_16BITS; + + /** + * @deprecated + * This value will be removed in a future version without replacement. + */ + exports.MAX_VALUE_32BITS = utils.MAX_VALUE_32BITS; + + + /** + * @deprecated + * This function will be removed in a future version without replacement. + */ + exports.pretty = function(str) { + return utils.pretty(str); + }; + + /** + * @deprecated + * This function will be removed in a future version without replacement. + */ + exports.findCompression = function(compressionMethod) { + return utils.findCompression(compressionMethod); + }; + + /** + * @deprecated + * This function will be removed in a future version without replacement. + */ + exports.isRegExp = function (object) { + return utils.isRegExp(object); + }; + + + },{"./utils":21}],8:[function(_dereq_,module,exports){ + 'use strict'; + var USE_TYPEDARRAY = (typeof Uint8Array !== 'undefined') && (typeof Uint16Array !== 'undefined') && (typeof Uint32Array !== 'undefined'); + + var pako = _dereq_("pako"); + exports.uncompressInputType = USE_TYPEDARRAY ? "uint8array" : "array"; + exports.compressInputType = USE_TYPEDARRAY ? "uint8array" : "array"; + + exports.magic = "\x08\x00"; + exports.compress = function(input) { + return pako.deflateRaw(input); + }; + exports.uncompress = function(input) { + return pako.inflateRaw(input); + }; + + },{"pako":24}],9:[function(_dereq_,module,exports){ + 'use strict'; + + var base64 = _dereq_('./base64'); + + /** + Usage: + zip = new JSZip(); + zip.file("hello.txt", "Hello, World!").file("tempfile", "nothing"); + zip.folder("images").file("smile.gif", base64Data, {base64: true}); + zip.file("Xmas.txt", "Ho ho ho !", {date : new Date("December 25, 2007 00:00:01")}); + zip.remove("tempfile"); + + base64zip = zip.generate(); + + **/ + + /** + * Representation a of zip file in js + * @constructor + * @param {String=|ArrayBuffer=|Uint8Array=} data the data to load, if any (optional). + * @param {Object=} options the options for creating this objects (optional). + */ + function JSZipSync(data, options) { + // if this constructor is used without `new`, it adds `new` before itself: + if(!(this instanceof JSZipSync)) return new JSZipSync(data, options); + + // object containing the files : + // { + // "folder/" : {...}, + // "folder/data.txt" : {...} + // } + this.files = {}; + + this.comment = null; + + // Where we are in the hierarchy + this.root = ""; + if (data) { + this.load(data, options); + } + this.clone = function() { + var newObj = new JSZipSync(); + for (var i in this) { + if (typeof this[i] !== "function") { + newObj[i] = this[i]; + } + } + return newObj; + }; + } + JSZipSync.prototype = _dereq_('./object'); + JSZipSync.prototype.load = _dereq_('./load'); + JSZipSync.support = _dereq_('./support'); + JSZipSync.defaults = _dereq_('./defaults'); + + /** + * @deprecated + * This namespace will be removed in a future version without replacement. + */ + JSZipSync.utils = _dereq_('./deprecatedPublicUtils'); + + JSZipSync.base64 = { + /** + * @deprecated + * This method will be removed in a future version without replacement. + */ + encode : function(input) { + return base64.encode(input); + }, + /** + * @deprecated + * This method will be removed in a future version without replacement. + */ + decode : function(input) { + return base64.decode(input); + } + }; + JSZipSync.compressions = _dereq_('./compressions'); + module.exports = JSZipSync; + + },{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(_dereq_,module,exports){ + 'use strict'; + var base64 = _dereq_('./base64'); + var ZipEntries = _dereq_('./zipEntries'); + module.exports = function(data, options) { + var files, zipEntries, i, input; + options = options || {}; + if (options.base64) { + data = base64.decode(data); + } + + zipEntries = new ZipEntries(data, options); + files = zipEntries.files; + for (i = 0; i < files.length; i++) { + input = files[i]; + this.file(input.fileName, input.decompressed, { + binary: true, + optimizedBinaryString: true, + date: input.date, + dir: input.dir, + comment : input.fileComment.length ? input.fileComment : null, + createFolders: options.createFolders + }); + } + if (zipEntries.zipComment.length) { + this.comment = zipEntries.zipComment; + } + + return this; + }; + + },{"./base64":1,"./zipEntries":22}],11:[function(_dereq_,module,exports){ + (function (Buffer){ + 'use strict'; + var Buffer_from = /*::(*/function(){}/*:: :any)*/; + if(typeof Buffer !== 'undefined') { + var nbfs = !Buffer.from; + if(!nbfs) try { Buffer.from("foo", "utf8"); } catch(e) { nbfs = true; } + Buffer_from = nbfs ? function(buf, enc) { return (enc) ? new Buffer(buf, enc) : new Buffer(buf); } : Buffer.from.bind(Buffer); + // $FlowIgnore + if(!Buffer.alloc) Buffer.alloc = function(n) { return new Buffer(n); }; + } + module.exports = function(data, encoding){ + return typeof data == 'number' ? Buffer.alloc(data) : Buffer_from(data, encoding); + }; + module.exports.test = function(b){ + return Buffer.isBuffer(b); + }; + }).call(this,(typeof Buffer !== "undefined" ? Buffer : undefined)) + },{}],12:[function(_dereq_,module,exports){ + 'use strict'; + var Uint8ArrayReader = _dereq_('./uint8ArrayReader'); + + function NodeBufferReader(data) { + this.data = data; + this.length = this.data.length; + this.index = 0; + } + NodeBufferReader.prototype = new Uint8ArrayReader(); + + /** + * @see DataReader.readData + */ + NodeBufferReader.prototype.readData = function(size) { + this.checkOffset(size); + var result = this.data.slice(this.index, this.index + size); + this.index += size; + return result; + }; + module.exports = NodeBufferReader; + + },{"./uint8ArrayReader":18}],13:[function(_dereq_,module,exports){ + 'use strict'; + var support = _dereq_('./support'); + var utils = _dereq_('./utils'); + var crc32 = _dereq_('./crc32'); + var signature = _dereq_('./signature'); + var defaults = _dereq_('./defaults'); + var base64 = _dereq_('./base64'); + var compressions = _dereq_('./compressions'); + var CompressedObject = _dereq_('./compressedObject'); + var nodeBuffer = _dereq_('./nodeBuffer'); + var utf8 = _dereq_('./utf8'); + var StringWriter = _dereq_('./stringWriter'); + var Uint8ArrayWriter = _dereq_('./uint8ArrayWriter'); + + /** + * Returns the raw data of a ZipObject, decompress the content if necessary. + * @param {ZipObject} file the file to use. + * @return {String|ArrayBuffer|Uint8Array|Buffer} the data. + */ + var getRawData = function(file) { + if (file._data instanceof CompressedObject) { + file._data = file._data.getContent(); + file.options.binary = true; + file.options.base64 = false; + + if (utils.getTypeOf(file._data) === "uint8array") { + var copy = file._data; + // when reading an arraybuffer, the CompressedObject mechanism will keep it and subarray() a Uint8Array. + // if we request a file in the same format, we might get the same Uint8Array or its ArrayBuffer (the original zip file). + file._data = new Uint8Array(copy.length); + // with an empty Uint8Array, Opera fails with a "Offset larger than array size" + if (copy.length !== 0) { + file._data.set(copy, 0); + } + } + } + return file._data; + }; + + /** + * Returns the data of a ZipObject in a binary form. If the content is an unicode string, encode it. + * @param {ZipObject} file the file to use. + * @return {String|ArrayBuffer|Uint8Array|Buffer} the data. + */ + var getBinaryData = function(file) { + var result = getRawData(file), + type = utils.getTypeOf(result); + if (type === "string") { + if (!file.options.binary) { + // unicode text ! + // unicode string => binary string is a painful process, check if we can avoid it. + if (support.nodebuffer) { + return nodeBuffer(result, "utf-8"); + } + } + return file.asBinary(); + } + return result; + }; + + /** + * Transform this._data into a string. + * @param {function} filter a function String -> String, applied if not null on the result. + * @return {String} the string representing this._data. + */ + var dataToString = function(asUTF8) { + var result = getRawData(this); + if (result === null || typeof result === "undefined") { + return ""; + } + // if the data is a base64 string, we decode it before checking the encoding ! + if (this.options.base64) { + result = base64.decode(result); + } + if (asUTF8 && this.options.binary) { + // JSZip.prototype.utf8decode supports arrays as input + // skip to array => string step, utf8decode will do it. + result = out.utf8decode(result); + } + else { + // no utf8 transformation, do the array => string step. + result = utils.transformTo("string", result); + } + + if (!asUTF8 && !this.options.binary) { + result = utils.transformTo("string", out.utf8encode(result)); + } + return result; + }; + /** + * A simple object representing a file in the zip file. + * @constructor + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data + * @param {Object} options the options of the file + */ + var ZipObject = function(name, data, options) { + this.name = name; + this.dir = options.dir; + this.date = options.date; + this.comment = options.comment; + + this._data = data; + this.options = options; + + /* + * This object contains initial values for dir and date. + * With them, we can check if the user changed the deprecated metadata in + * `ZipObject#options` or not. + */ + this._initialMetadata = { + dir : options.dir, + date : options.date + }; + }; + + ZipObject.prototype = { + /** + * Return the content as UTF8 string. + * @return {string} the UTF8 string. + */ + asText: function() { + return dataToString.call(this, true); + }, + /** + * Returns the binary content. + * @return {string} the content as binary. + */ + asBinary: function() { + return dataToString.call(this, false); + }, + /** + * Returns the content as a nodejs Buffer. + * @return {Buffer} the content as a Buffer. + */ + asNodeBuffer: function() { + var result = getBinaryData(this); + return utils.transformTo("nodebuffer", result); + }, + /** + * Returns the content as an Uint8Array. + * @return {Uint8Array} the content as an Uint8Array. + */ + asUint8Array: function() { + var result = getBinaryData(this); + return utils.transformTo("uint8array", result); + }, + /** + * Returns the content as an ArrayBuffer. + * @return {ArrayBuffer} the content as an ArrayBufer. + */ + asArrayBuffer: function() { + return this.asUint8Array().buffer; + } + }; + + /** + * Transform an integer into a string in hexadecimal. + * @private + * @param {number} dec the number to convert. + * @param {number} bytes the number of bytes to generate. + * @returns {string} the result. + */ + var decToHex = function(dec, bytes) { + var hex = "", + i; + for (i = 0; i < bytes; i++) { + hex += String.fromCharCode(dec & 0xff); + dec = dec >>> 8; + } + return hex; + }; + + /** + * Merge the objects passed as parameters into a new one. + * @private + * @param {...Object} var_args All objects to merge. + * @return {Object} a new object with the data of the others. + */ + var extend = function() { + var result = {}, i, attr; + for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers + for (attr in arguments[i]) { + if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") { + result[attr] = arguments[i][attr]; + } + } + } + return result; + }; + + /** + * Transforms the (incomplete) options from the user into the complete + * set of options to create a file. + * @private + * @param {Object} o the options from the user. + * @return {Object} the complete set of options. + */ + var prepareFileAttrs = function(o) { + o = o || {}; + if (o.base64 === true && (o.binary === null || o.binary === undefined)) { + o.binary = true; + } + o = extend(o, defaults); + o.date = o.date || new Date(); + if (o.compression !== null) o.compression = o.compression.toUpperCase(); + + return o; + }; + + /** + * Add a file in the current folder. + * @private + * @param {string} name the name of the file + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the data of the file + * @param {Object} o the options of the file + * @return {Object} the new file. + */ + var fileAdd = function(name, data, o) { + // be sure sub folders exist + var dataType = utils.getTypeOf(data), + parent; + + o = prepareFileAttrs(o); + + if (o.createFolders && (parent = parentFolder(name))) { + folderAdd.call(this, parent, true); + } + + if (o.dir || data === null || typeof data === "undefined") { + o.base64 = false; + o.binary = false; + data = null; + } + else if (dataType === "string") { + if (o.binary && !o.base64) { + // optimizedBinaryString == true means that the file has already been filtered with a 0xFF mask + if (o.optimizedBinaryString !== true) { + // this is a string, not in a base64 format. + // Be sure that this is a correct "binary string" + data = utils.string2binary(data); + } + } + } + else { // arraybuffer, uint8array, ... + o.base64 = false; + o.binary = true; + + if (!dataType && !(data instanceof CompressedObject)) { + throw new Error("The data of '" + name + "' is in an unsupported format !"); + } + + // special case : it's way easier to work with Uint8Array than with ArrayBuffer + if (dataType === "arraybuffer") { + data = utils.transformTo("uint8array", data); + } + } + + var object = new ZipObject(name, data, o); + this.files[name] = object; + return object; + }; + + /** + * Find the parent folder of the path. + * @private + * @param {string} path the path to use + * @return {string} the parent folder, or "" + */ + var parentFolder = function (path) { + if (path.slice(-1) == '/') { + path = path.substring(0, path.length - 1); + } + var lastSlash = path.lastIndexOf('/'); + return (lastSlash > 0) ? path.substring(0, lastSlash) : ""; + }; + + /** + * Add a (sub) folder in the current folder. + * @private + * @param {string} name the folder's name + * @param {boolean=} [createFolders] If true, automatically create sub + * folders. Defaults to false. + * @return {Object} the new folder. + */ + var folderAdd = function(name, createFolders) { + // Check the name ends with a / + if (name.slice(-1) != "/") { + name += "/"; // IE doesn't like substr(-1) + } + + createFolders = (typeof createFolders !== 'undefined') ? createFolders : false; + + // Does this folder already exist? + if (!this.files[name]) { + fileAdd.call(this, name, null, { + dir: true, + createFolders: createFolders + }); + } + return this.files[name]; + }; + + /** + * Generate a JSZip.CompressedObject for a given zipOject. + * @param {ZipObject} file the object to read. + * @param {JSZip.compression} compression the compression to use. + * @return {JSZip.CompressedObject} the compressed result. + */ + var generateCompressedObjectFrom = function(file, compression) { + var result = new CompressedObject(), + content; + + // the data has not been decompressed, we might reuse things ! + if (file._data instanceof CompressedObject) { + result.uncompressedSize = file._data.uncompressedSize; + result.crc32 = file._data.crc32; + + if (result.uncompressedSize === 0 || file.dir) { + compression = compressions['STORE']; + result.compressedContent = ""; + result.crc32 = 0; + } + else if (file._data.compressionMethod === compression.magic) { + result.compressedContent = file._data.getCompressedContent(); + } + else { + content = file._data.getContent(); + // need to decompress / recompress + result.compressedContent = compression.compress(utils.transformTo(compression.compressInputType, content)); + } + } + else { + // have uncompressed data + content = getBinaryData(file); + if (!content || content.length === 0 || file.dir) { + compression = compressions['STORE']; + content = ""; + } + result.uncompressedSize = content.length; + result.crc32 = crc32(content); + result.compressedContent = compression.compress(utils.transformTo(compression.compressInputType, content)); + } + + result.compressedSize = result.compressedContent.length; + result.compressionMethod = compression.magic; + + return result; + }; + + /** + * Generate the various parts used in the construction of the final zip file. + * @param {string} name the file name. + * @param {ZipObject} file the file content. + * @param {JSZip.CompressedObject} compressedObject the compressed object. + * @param {number} offset the current offset from the start of the zip file. + * @return {object} the zip parts. + */ + var generateZipParts = function(name, file, compressedObject, offset) { + var data = compressedObject.compressedContent, + utfEncodedFileName = utils.transformTo("string", utf8.utf8encode(file.name)), + comment = file.comment || "", + utfEncodedComment = utils.transformTo("string", utf8.utf8encode(comment)), + useUTF8ForFileName = utfEncodedFileName.length !== file.name.length, + useUTF8ForComment = utfEncodedComment.length !== comment.length, + o = file.options, + dosTime, + dosDate, + extraFields = "", + unicodePathExtraField = "", + unicodeCommentExtraField = "", + dir, date; + + + // handle the deprecated options.dir + if (file._initialMetadata.dir !== file.dir) { + dir = file.dir; + } else { + dir = o.dir; + } + + // handle the deprecated options.date + if(file._initialMetadata.date !== file.date) { + date = file.date; + } else { + date = o.date; + } + + + dosTime = date.getHours(); + dosTime = dosTime << 6; + dosTime = dosTime | date.getMinutes(); + dosTime = dosTime << 5; + dosTime = dosTime | date.getSeconds() / 2; + + dosDate = date.getFullYear() - 1980; + dosDate = dosDate << 4; + dosDate = dosDate | (date.getMonth() + 1); + dosDate = dosDate << 5; + dosDate = dosDate | date.getDate(); + + if (useUTF8ForFileName) { + // set the unicode path extra field. unzip needs at least one extra + // field to correctly handle unicode path, so using the path is as good + // as any other information. This could improve the situation with + // other archive managers too. + // This field is usually used without the utf8 flag, with a non + // unicode path in the header (winrar, winzip). This helps (a bit) + // with the messy Windows' default compressed folders feature but + // breaks on p7zip which doesn't seek the unicode path extra field. + // So for now, UTF-8 everywhere ! + unicodePathExtraField = + // Version + decToHex(1, 1) + + // NameCRC32 + decToHex(crc32(utfEncodedFileName), 4) + + // UnicodeName + utfEncodedFileName; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x70" + + // size + decToHex(unicodePathExtraField.length, 2) + + // content + unicodePathExtraField; + } + + if(useUTF8ForComment) { + + unicodeCommentExtraField = + // Version + decToHex(1, 1) + + // CommentCRC32 + decToHex(this.crc32(utfEncodedComment), 4) + + // UnicodeName + utfEncodedComment; + + extraFields += + // Info-ZIP Unicode Path Extra Field + "\x75\x63" + + // size + decToHex(unicodeCommentExtraField.length, 2) + + // content + unicodeCommentExtraField; + } + + var header = ""; + + // version needed to extract + header += "\x0A\x00"; + // general purpose bit flag + // set bit 11 if utf8 + header += (useUTF8ForFileName || useUTF8ForComment) ? "\x00\x08" : "\x00\x00"; + // compression method + header += compressedObject.compressionMethod; + // last mod file time + header += decToHex(dosTime, 2); + // last mod file date + header += decToHex(dosDate, 2); + // crc-32 + header += decToHex(compressedObject.crc32, 4); + // compressed size + header += decToHex(compressedObject.compressedSize, 4); + // uncompressed size + header += decToHex(compressedObject.uncompressedSize, 4); + // file name length + header += decToHex(utfEncodedFileName.length, 2); + // extra field length + header += decToHex(extraFields.length, 2); + + + var fileRecord = signature.LOCAL_FILE_HEADER + header + utfEncodedFileName + extraFields; + + var dirRecord = signature.CENTRAL_FILE_HEADER + + // version made by (00: DOS) + "\x14\x00" + + // file header (common to file and central directory) + header + + // file comment length + decToHex(utfEncodedComment.length, 2) + + // disk number start + "\x00\x00" + + // internal file attributes TODO + "\x00\x00" + + // external file attributes + (dir === true ? "\x10\x00\x00\x00" : "\x00\x00\x00\x00") + + // relative offset of local header + decToHex(offset, 4) + + // file name + utfEncodedFileName + + // extra field + extraFields + + // file comment + utfEncodedComment; + + return { + fileRecord: fileRecord, + dirRecord: dirRecord, + compressedObject: compressedObject + }; + }; + + +// return the actual prototype of JSZip + var out = { + /** + * Read an existing zip and merge the data in the current JSZip object. + * The implementation is in jszip-load.js, don't forget to include it. + * @param {String|ArrayBuffer|Uint8Array|Buffer} stream The stream to load + * @param {Object} options Options for loading the stream. + * options.base64 : is the stream in base64 ? default : false + * @return {JSZip} the current JSZip object + */ + load: function(stream, options) { + throw new Error("Load method is not defined. Is the file jszip-load.js included ?"); + }, + + /** + * Filter nested files/folders with the specified function. + * @param {Function} search the predicate to use : + * function (relativePath, file) {...} + * It takes 2 arguments : the relative path and the file. + * @return {Array} An array of matching elements. + */ + filter: function(search) { + var result = [], + filename, relativePath, file, fileClone; + for (filename in this.files) { + if (!this.files.hasOwnProperty(filename)) { + continue; + } + file = this.files[filename]; + // return a new object, don't let the user mess with our internal objects :) + fileClone = new ZipObject(file.name, file._data, extend(file.options)); + relativePath = filename.slice(this.root.length, filename.length); + if (filename.slice(0, this.root.length) === this.root && // the file is in the current root + search(relativePath, fileClone)) { // and the file matches the function + result.push(fileClone); + } + } + return result; + }, + + /** + * Add a file to the zip file, or search a file. + * @param {string|RegExp} name The name of the file to add (if data is defined), + * the name of the file to find (if no data) or a regex to match files. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data The file data, either raw or base64 encoded + * @param {Object} o File options + * @return {JSZip|Object|Array} this JSZip object (when adding a file), + * a file (when searching by string) or an array of files (when searching by regex). + */ + file: function(name, data, o) { + if (arguments.length === 1) { + if (utils.isRegExp(name)) { + var regexp = name; + return this.filter(function(relativePath, file) { + return !file.dir && regexp.test(relativePath); + }); + } + else { // text + return this.filter(function(relativePath, file) { + return !file.dir && relativePath === name; + })[0] || null; + } + } + else { // more than one argument : we have data ! + name = this.root + name; + fileAdd.call(this, name, data, o); + } + return this; + }, + + /** + * Add a directory to the zip file, or search. + * @param {String|RegExp} arg The name of the directory to add, or a regex to search folders. + * @return {JSZip} an object with the new directory as the root, or an array containing matching folders. + */ + folder: function(arg) { + if (!arg) { + return this; + } + + if (utils.isRegExp(arg)) { + return this.filter(function(relativePath, file) { + return file.dir && arg.test(relativePath); + }); + } + + // else, name is a new folder + var name = this.root + arg; + var newFolder = folderAdd.call(this, name); + + // Allow chaining by returning a new object with this folder as the root + var ret = this.clone(); + ret.root = newFolder.name; + return ret; + }, + + /** + * Delete a file, or a directory and all sub-files, from the zip + * @param {string} name the name of the file to delete + * @return {JSZip} this JSZip object + */ + remove: function(name) { + name = this.root + name; + var file = this.files[name]; + if (!file) { + // Look for any folders + if (name.slice(-1) != "/") { + name += "/"; + } + file = this.files[name]; + } + + if (file && !file.dir) { + // file + delete this.files[name]; + } else { + // maybe a folder, delete recursively + var kids = this.filter(function(relativePath, file) { + return file.name.slice(0, name.length) === name; + }); + for (var i = 0; i < kids.length; i++) { + delete this.files[kids[i].name]; + } + } + + return this; + }, + + /** + * Generate the complete zip file + * @param {Object} options the options to generate the zip file : + * - base64, (deprecated, use type instead) true to generate base64. + * - compression, "STORE" by default. + * - type, "base64" by default. Values are : string, base64, uint8array, arraybuffer, blob. + * @return {String|Uint8Array|ArrayBuffer|Buffer|Blob} the zip file + */ + generate: function(options) { + options = extend(options || {}, { + base64: true, + compression: "STORE", + type: "base64", + comment: null + }); + + utils.checkSupport(options.type); + + var zipData = [], + localDirLength = 0, + centralDirLength = 0, + writer, i, + utfEncodedComment = utils.transformTo("string", this.utf8encode(options.comment || this.comment || "")); + + // first, generate all the zip parts. + for (var name in this.files) { + if (!this.files.hasOwnProperty(name)) { + continue; + } + var file = this.files[name]; + + var compressionName = file.options.compression || options.compression.toUpperCase(); + var compression = compressions[compressionName]; + if (!compression) { + throw new Error(compressionName + " is not a valid compression method !"); + } + + var compressedObject = generateCompressedObjectFrom.call(this, file, compression); + + var zipPart = generateZipParts.call(this, name, file, compressedObject, localDirLength); + localDirLength += zipPart.fileRecord.length + compressedObject.compressedSize; + centralDirLength += zipPart.dirRecord.length; + zipData.push(zipPart); + } + + var dirEnd = ""; + + // end of central dir signature + dirEnd = signature.CENTRAL_DIRECTORY_END + + // number of this disk + "\x00\x00" + + // number of the disk with the start of the central directory + "\x00\x00" + + // total number of entries in the central directory on this disk + decToHex(zipData.length, 2) + + // total number of entries in the central directory + decToHex(zipData.length, 2) + + // size of the central directory 4 bytes + decToHex(centralDirLength, 4) + + // offset of start of central directory with respect to the starting disk number + decToHex(localDirLength, 4) + + // .ZIP file comment length + decToHex(utfEncodedComment.length, 2) + + // .ZIP file comment + utfEncodedComment; + + + // we have all the parts (and the total length) + // time to create a writer ! + var typeName = options.type.toLowerCase(); + if(typeName==="uint8array"||typeName==="arraybuffer"||typeName==="blob"||typeName==="nodebuffer") { + writer = new Uint8ArrayWriter(localDirLength + centralDirLength + dirEnd.length); + }else{ + writer = new StringWriter(localDirLength + centralDirLength + dirEnd.length); + } + + for (i = 0; i < zipData.length; i++) { + writer.append(zipData[i].fileRecord); + writer.append(zipData[i].compressedObject.compressedContent); + } + for (i = 0; i < zipData.length; i++) { + writer.append(zipData[i].dirRecord); + } + + writer.append(dirEnd); + + var zip = writer.finalize(); + + + + switch(options.type.toLowerCase()) { + // case "zip is an Uint8Array" + case "uint8array" : + case "arraybuffer" : + case "nodebuffer" : + return utils.transformTo(options.type.toLowerCase(), zip); + case "blob" : + return utils.arrayBuffer2Blob(utils.transformTo("arraybuffer", zip)); + // case "zip is a string" + case "base64" : + return (options.base64) ? base64.encode(zip) : zip; + default : // case "string" : + return zip; + } + + }, + + /** + * @deprecated + * This method will be removed in a future version without replacement. + */ + crc32: function (input, crc) { + return crc32(input, crc); + }, + + /** + * @deprecated + * This method will be removed in a future version without replacement. + */ + utf8encode: function (string) { + return utils.transformTo("string", utf8.utf8encode(string)); + }, + + /** + * @deprecated + * This method will be removed in a future version without replacement. + */ + utf8decode: function (input) { + return utf8.utf8decode(input); + } + }; + module.exports = out; + + },{"./base64":1,"./compressedObject":2,"./compressions":3,"./crc32":4,"./defaults":6,"./nodeBuffer":11,"./signature":14,"./stringWriter":16,"./support":17,"./uint8ArrayWriter":19,"./utf8":20,"./utils":21}],14:[function(_dereq_,module,exports){ + 'use strict'; + exports.LOCAL_FILE_HEADER = "PK\x03\x04"; + exports.CENTRAL_FILE_HEADER = "PK\x01\x02"; + exports.CENTRAL_DIRECTORY_END = "PK\x05\x06"; + exports.ZIP64_CENTRAL_DIRECTORY_LOCATOR = "PK\x06\x07"; + exports.ZIP64_CENTRAL_DIRECTORY_END = "PK\x06\x06"; + exports.DATA_DESCRIPTOR = "PK\x07\x08"; + + },{}],15:[function(_dereq_,module,exports){ + 'use strict'; + var DataReader = _dereq_('./dataReader'); + var utils = _dereq_('./utils'); + + function StringReader(data, optimizedBinaryString) { + this.data = data; + if (!optimizedBinaryString) { + this.data = utils.string2binary(this.data); + } + this.length = this.data.length; + this.index = 0; + } + StringReader.prototype = new DataReader(); + /** + * @see DataReader.byteAt + */ + StringReader.prototype.byteAt = function(i) { + return this.data.charCodeAt(i); + }; + /** + * @see DataReader.lastIndexOfSignature + */ + StringReader.prototype.lastIndexOfSignature = function(sig) { + return this.data.lastIndexOf(sig); + }; + /** + * @see DataReader.readData + */ + StringReader.prototype.readData = function(size) { + this.checkOffset(size); + // this will work because the constructor applied the "& 0xff" mask. + var result = this.data.slice(this.index, this.index + size); + this.index += size; + return result; + }; + module.exports = StringReader; + + },{"./dataReader":5,"./utils":21}],16:[function(_dereq_,module,exports){ + 'use strict'; + + var utils = _dereq_('./utils'); + + /** + * An object to write any content to a string. + * @constructor + */ + var StringWriter = function() { + this.data = []; + }; + StringWriter.prototype = { + /** + * Append any content to the current string. + * @param {Object} input the content to add. + */ + append: function(input) { + input = utils.transformTo("string", input); + this.data.push(input); + }, + /** + * Finalize the construction an return the result. + * @return {string} the generated string. + */ + finalize: function() { + return this.data.join(""); + } + }; + + module.exports = StringWriter; + + },{"./utils":21}],17:[function(_dereq_,module,exports){ + (function (Buffer){ + 'use strict'; + exports.base64 = true; + exports.array = true; + exports.string = true; + exports.arraybuffer = typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined"; +// contains true if JSZip can read/generate nodejs Buffer, false otherwise. +// Browserify will provide a Buffer implementation for browsers, which is +// an augmented Uint8Array (i.e., can be used as either Buffer or U8). + exports.nodebuffer = typeof Buffer !== "undefined"; +// contains true if JSZip can read/generate Uint8Array, false otherwise. + exports.uint8array = typeof Uint8Array !== "undefined"; + + if (typeof ArrayBuffer === "undefined") { + exports.blob = false; + } + else { + var buffer = new ArrayBuffer(0); + try { + exports.blob = new Blob([buffer], { + type: "application/zip" + }).size === 0; + } + catch (e) { + try { + var Builder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; + var builder = new Builder(); + builder.append(buffer); + exports.blob = builder.getBlob('application/zip').size === 0; + } + catch (e) { + exports.blob = false; + } + } + } + + }).call(this,(typeof Buffer !== "undefined" ? Buffer : undefined)) + },{}],18:[function(_dereq_,module,exports){ + 'use strict'; + var DataReader = _dereq_('./dataReader'); + + function Uint8ArrayReader(data) { + if (data) { + this.data = data; + this.length = this.data.length; + this.index = 0; + } + } + Uint8ArrayReader.prototype = new DataReader(); + /** + * @see DataReader.byteAt + */ + Uint8ArrayReader.prototype.byteAt = function(i) { + return this.data[i]; + }; + /** + * @see DataReader.lastIndexOfSignature + */ + Uint8ArrayReader.prototype.lastIndexOfSignature = function(sig) { + var sig0 = sig.charCodeAt(0), + sig1 = sig.charCodeAt(1), + sig2 = sig.charCodeAt(2), + sig3 = sig.charCodeAt(3); + for (var i = this.length - 4; i >= 0; --i) { + if (this.data[i] === sig0 && this.data[i + 1] === sig1 && this.data[i + 2] === sig2 && this.data[i + 3] === sig3) { + return i; + } + } + + return -1; + }; + /** + * @see DataReader.readData + */ + Uint8ArrayReader.prototype.readData = function(size) { + this.checkOffset(size); + if(size === 0) { + // in IE10, when using subarray(idx, idx), we get the array [0x00] instead of []. + return new Uint8Array(0); + } + var result = this.data.subarray(this.index, this.index + size); + this.index += size; + return result; + }; + module.exports = Uint8ArrayReader; + + },{"./dataReader":5}],19:[function(_dereq_,module,exports){ + 'use strict'; + + var utils = _dereq_('./utils'); + + /** + * An object to write any content to an Uint8Array. + * @constructor + * @param {number} length The length of the array. + */ + var Uint8ArrayWriter = function(length) { + this.data = new Uint8Array(length); + this.index = 0; + }; + Uint8ArrayWriter.prototype = { + /** + * Append any content to the current array. + * @param {Object} input the content to add. + */ + append: function(input) { + if (input.length !== 0) { + // with an empty Uint8Array, Opera fails with a "Offset larger than array size" + input = utils.transformTo("uint8array", input); + this.data.set(input, this.index); + this.index += input.length; + } + }, + /** + * Finalize the construction an return the result. + * @return {Uint8Array} the generated array. + */ + finalize: function() { + return this.data; + } + }; + + module.exports = Uint8ArrayWriter; + + },{"./utils":21}],20:[function(_dereq_,module,exports){ + 'use strict'; + + var utils = _dereq_('./utils'); + var support = _dereq_('./support'); + var nodeBuffer = _dereq_('./nodeBuffer'); + + /** + * The following functions come from pako, from pako/lib/utils/strings + * released under the MIT license, see pako https://github.com/nodeca/pako/ + */ + +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff + var _utf8len = new Array(256); + for (var i=0; i<256; i++) { + _utf8len[i] = (i >= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); + } + _utf8len[254]=_utf8len[254]=1; // Invalid sequence start + +// convert string to array (typed, when possible) + var string2buf = function (str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if (((c & 0xfc00) === 0xd800) && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += (c < 0x80) ? 1 : ((c < 0x800) ? 2 : ((c < 0x10000) ? 3 : 4)); + } + + // allocate buffer + if (support.uint8array) { + buf = new Uint8Array(buf_len); + } else { + buf = new Array(buf_len); + } + + // convert + for (i=0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | ((c >>> 6) & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | ((c >>> 12) & 0x3f); + buf[i++] = 0x80 | ((c >>> 6) & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; + }; + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); + var utf8border = function(buf, max) { + var pos; + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + pos = max-1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Fuckup - very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means vuffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; + }; + +// convert array to string + var buf2string = function (buf) { + var str, i, out, c, c_len; + var len = buf.length; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + var utf16buf = new Array(len*2); + + for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; + } + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); + } + } + + // shrinkBuf(utf16buf, out) + if (utf16buf.length !== out) { + if(utf16buf.subarray) { + utf16buf = utf16buf.subarray(0, out); + } else { + utf16buf.length = out; + } + } + + // return String.fromCharCode.apply(null, utf16buf); + return utils.applyFromCharCode(utf16buf); + }; + + +// That's all for the pako functions. + + + /** + * Transform a javascript string into an array (typed if possible) of bytes, + * UTF-8 encoded. + * @param {String} str the string to encode + * @return {Array|Uint8Array|Buffer} the UTF-8 encoded string. + */ + exports.utf8encode = function utf8encode(str) { + if (support.nodebuffer) { + return nodeBuffer(str, "utf-8"); + } + + return string2buf(str); + }; + + + /** + * Transform a bytes array (or a representation) representing an UTF-8 encoded + * string into a javascript string. + * @param {Array|Uint8Array|Buffer} buf the data de decode + * @return {String} the decoded string. + */ + exports.utf8decode = function utf8decode(buf) { + if (support.nodebuffer) { + return utils.transformTo("nodebuffer", buf).toString("utf-8"); + } + + buf = utils.transformTo(support.uint8array ? "uint8array" : "array", buf); + + // return buf2string(buf); + // Chrome prefers to work with "small" chunks of data + // for the method buf2string. + // Firefox and Chrome has their own shortcut, IE doesn't seem to really care. + var result = [], k = 0, len = buf.length, chunk = 65536; + while (k < len) { + var nextBoundary = utf8border(buf, Math.min(k + chunk, len)); + if (support.uint8array) { + result.push(buf2string(buf.subarray(k, nextBoundary))); + } else { + result.push(buf2string(buf.slice(k, nextBoundary))); + } + k = nextBoundary; + } + return result.join(""); + + }; +// vim: set shiftwidth=4 softtabstop=4: + + },{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(_dereq_,module,exports){ + 'use strict'; + var support = _dereq_('./support'); + var compressions = _dereq_('./compressions'); + var nodeBuffer = _dereq_('./nodeBuffer'); + /** + * Convert a string to a "binary string" : a string containing only char codes between 0 and 255. + * @param {string} str the string to transform. + * @return {String} the binary string. + */ + exports.string2binary = function(str) { + var result = ""; + for (var i = 0; i < str.length; i++) { + result += String.fromCharCode(str.charCodeAt(i) & 0xff); + } + return result; + }; + exports.arrayBuffer2Blob = function(buffer) { + exports.checkSupport("blob"); + + try { + // Blob constructor + return new Blob([buffer], { + type: "application/zip" + }); + } + catch (e) { + + try { + // deprecated, browser only, old way + var Builder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder; + var builder = new Builder(); + builder.append(buffer); + return builder.getBlob('application/zip'); + } + catch (e) { + + // well, fuck ?! + throw new Error("Bug : can't construct the Blob."); + } + } + + + }; + /** + * The identity function. + * @param {Object} input the input. + * @return {Object} the same input. + */ + function identity(input) { + return input; + } + + /** + * Fill in an array with a string. + * @param {String} str the string to use. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated). + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array. + */ + function stringToArrayLike(str, array) { + for (var i = 0; i < str.length; ++i) { + array[i] = str.charCodeAt(i) & 0xFF; + } + return array; + } + + /** + * Transform an array-like object to a string. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. + * @return {String} the result. + */ + function arrayLikeToString(array) { + // Performances notes : + // -------------------- + // String.fromCharCode.apply(null, array) is the fastest, see + // see http://jsperf.com/converting-a-uint8array-to-a-string/2 + // but the stack is limited (and we can get huge arrays !). + // + // result += String.fromCharCode(array[i]); generate too many strings ! + // + // This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2 + var chunk = 65536; + var result = [], + len = array.length, + type = exports.getTypeOf(array), + k = 0, + canUseApply = true; + try { + switch(type) { + case "uint8array": + String.fromCharCode.apply(null, new Uint8Array(0)); + break; + case "nodebuffer": + String.fromCharCode.apply(null, nodeBuffer(0)); + break; + } + } catch(e) { + canUseApply = false; + } + + // no apply : slow and painful algorithm + // default browser on android 4.* + if (!canUseApply) { + var resultStr = ""; + for(var i = 0; i < array.length;i++) { + resultStr += String.fromCharCode(array[i]); + } + return resultStr; + } + while (k < len && chunk > 1) { + try { + if (type === "array" || type === "nodebuffer") { + result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len)))); + } + else { + result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len)))); + } + k += chunk; + } + catch (e) { + chunk = Math.floor(chunk / 2); + } + } + return result.join(""); + } + + exports.applyFromCharCode = arrayLikeToString; + + + /** + * Copy the data from an array-like to an other array-like. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array. + * @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated. + * @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array. + */ + function arrayLikeToArrayLike(arrayFrom, arrayTo) { + for (var i = 0; i < arrayFrom.length; i++) { + arrayTo[i] = arrayFrom[i]; + } + return arrayTo; + } + +// a matrix containing functions to transform everything into everything. + var transform = {}; + +// string to ? + transform["string"] = { + "string": identity, + "array": function(input) { + return stringToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["string"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return stringToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": function(input) { + return stringToArrayLike(input, nodeBuffer(input.length)); + } + }; + +// array to ? + transform["array"] = { + "string": arrayLikeToString, + "array": identity, + "arraybuffer": function(input) { + return (new Uint8Array(input)).buffer; + }, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodeBuffer(input); + } + }; + +// arraybuffer to ? + transform["arraybuffer"] = { + "string": function(input) { + return arrayLikeToString(new Uint8Array(input)); + }, + "array": function(input) { + return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength)); + }, + "arraybuffer": identity, + "uint8array": function(input) { + return new Uint8Array(input); + }, + "nodebuffer": function(input) { + return nodeBuffer(new Uint8Array(input)); + } + }; + +// uint8array to ? + transform["uint8array"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return input.buffer; + }, + "uint8array": identity, + "nodebuffer": function(input) { + return nodeBuffer(input); + } + }; + +// nodebuffer to ? + transform["nodebuffer"] = { + "string": arrayLikeToString, + "array": function(input) { + return arrayLikeToArrayLike(input, new Array(input.length)); + }, + "arraybuffer": function(input) { + return transform["nodebuffer"]["uint8array"](input).buffer; + }, + "uint8array": function(input) { + return arrayLikeToArrayLike(input, new Uint8Array(input.length)); + }, + "nodebuffer": identity + }; + + /** + * Transform an input into any type. + * The supported output type are : string, array, uint8array, arraybuffer, nodebuffer. + * If no output type is specified, the unmodified input will be returned. + * @param {String} outputType the output type. + * @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert. + * @throws {Error} an Error if the browser doesn't support the requested output type. + */ + exports.transformTo = function(outputType, input) { + if (!input) { + // undefined, null, etc + // an empty string won't harm. + input = ""; + } + if (!outputType) { + return input; + } + exports.checkSupport(outputType); + var inputType = exports.getTypeOf(input); + var result = transform[inputType][outputType](input); + return result; + }; + + /** + * Return the type of the input. + * The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer. + * @param {Object} input the input to identify. + * @return {String} the (lowercase) type of the input. + */ + exports.getTypeOf = function(input) { + if (typeof input === "string") { + return "string"; + } + if (Object.prototype.toString.call(input) === "[object Array]") { + return "array"; + } + if (support.nodebuffer && nodeBuffer.test(input)) { + return "nodebuffer"; + } + if (support.uint8array && input instanceof Uint8Array) { + return "uint8array"; + } + if (support.arraybuffer && input instanceof ArrayBuffer) { + return "arraybuffer"; + } + }; + + /** + * Throw an exception if the type is not supported. + * @param {String} type the type to check. + * @throws {Error} an Error if the browser doesn't support the requested type. + */ + exports.checkSupport = function(type) { + var supported = support[type.toLowerCase()]; + if (!supported) { + throw new Error(type + " is not supported by this browser"); + } + }; + exports.MAX_VALUE_16BITS = 65535; + exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1 + + /** + * Prettify a string read as binary. + * @param {string} str the string to prettify. + * @return {string} a pretty string. + */ + exports.pretty = function(str) { + var res = '', + code, i; + for (i = 0; i < (str || "").length; i++) { + code = str.charCodeAt(i); + res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase(); + } + return res; + }; + + /** + * Find a compression registered in JSZip. + * @param {string} compressionMethod the method magic to find. + * @return {Object|null} the JSZip compression object, null if none found. + */ + exports.findCompression = function(compressionMethod) { + for (var method in compressions) { + if (!compressions.hasOwnProperty(method)) { + continue; + } + if (compressions[method].magic === compressionMethod) { + return compressions[method]; + } + } + return null; + }; + /** + * Cross-window, cross-Node-context regular expression detection + * @param {Object} object Anything + * @return {Boolean} true if the object is a regular expression, + * false otherwise + */ + exports.isRegExp = function (object) { + return Object.prototype.toString.call(object) === "[object RegExp]"; + }; + + + },{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(_dereq_,module,exports){ + 'use strict'; + var StringReader = _dereq_('./stringReader'); + var NodeBufferReader = _dereq_('./nodeBufferReader'); + var Uint8ArrayReader = _dereq_('./uint8ArrayReader'); + var utils = _dereq_('./utils'); + var sig = _dereq_('./signature'); + var ZipEntry = _dereq_('./zipEntry'); + var support = _dereq_('./support'); + var jszipProto = _dereq_('./object'); +// class ZipEntries {{{ + /** + * All the entries in the zip file. + * @constructor + * @param {String|ArrayBuffer|Uint8Array} data the binary stream to load. + * @param {Object} loadOptions Options for loading the stream. + */ + function ZipEntries(data, loadOptions) { + this.files = []; + this.loadOptions = loadOptions; + if (data) { + this.load(data); + } + } + ZipEntries.prototype = { + /** + * Check that the reader is on the speficied signature. + * @param {string} expectedSignature the expected signature. + * @throws {Error} if it is an other signature. + */ + checkSignature: function(expectedSignature) { + var signature = this.reader.readString(4); + if (signature !== expectedSignature) { + throw new Error("Corrupted zip or bug : unexpected signature " + "(" + utils.pretty(signature) + ", expected " + utils.pretty(expectedSignature) + ")"); + } + }, + /** + * Read the end of the central directory. + */ + readBlockEndOfCentral: function() { + this.diskNumber = this.reader.readInt(2); + this.diskWithCentralDirStart = this.reader.readInt(2); + this.centralDirRecordsOnThisDisk = this.reader.readInt(2); + this.centralDirRecords = this.reader.readInt(2); + this.centralDirSize = this.reader.readInt(4); + this.centralDirOffset = this.reader.readInt(4); + + this.zipCommentLength = this.reader.readInt(2); + // warning : the encoding depends of the system locale + // On a linux machine with LANG=en_US.utf8, this field is utf8 encoded. + // On a windows machine, this field is encoded with the localized windows code page. + this.zipComment = this.reader.readString(this.zipCommentLength); + // To get consistent behavior with the generation part, we will assume that + // this is utf8 encoded. + this.zipComment = jszipProto.utf8decode(this.zipComment); + }, + /** + * Read the end of the Zip 64 central directory. + * Not merged with the method readEndOfCentral : + * The end of central can coexist with its Zip64 brother, + * I don't want to read the wrong number of bytes ! + */ + readBlockZip64EndOfCentral: function() { + this.zip64EndOfCentralSize = this.reader.readInt(8); + this.versionMadeBy = this.reader.readString(2); + this.versionNeeded = this.reader.readInt(2); + this.diskNumber = this.reader.readInt(4); + this.diskWithCentralDirStart = this.reader.readInt(4); + this.centralDirRecordsOnThisDisk = this.reader.readInt(8); + this.centralDirRecords = this.reader.readInt(8); + this.centralDirSize = this.reader.readInt(8); + this.centralDirOffset = this.reader.readInt(8); + + this.zip64ExtensibleData = {}; + var extraDataSize = this.zip64EndOfCentralSize - 44, + index = 0, + extraFieldId, + extraFieldLength, + extraFieldValue; + while (index < extraDataSize) { + extraFieldId = this.reader.readInt(2); + extraFieldLength = this.reader.readInt(4); + extraFieldValue = this.reader.readString(extraFieldLength); + this.zip64ExtensibleData[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Read the end of the Zip 64 central directory locator. + */ + readBlockZip64EndOfCentralLocator: function() { + this.diskWithZip64CentralDirStart = this.reader.readInt(4); + this.relativeOffsetEndOfZip64CentralDir = this.reader.readInt(8); + this.disksCount = this.reader.readInt(4); + if (this.disksCount > 1) { + throw new Error("Multi-volumes zip are not supported"); + } + }, + /** + * Read the local files, based on the offset read in the central part. + */ + readLocalFiles: function() { + var i, file; + for (i = 0; i < this.files.length; i++) { + file = this.files[i]; + this.reader.setIndex(file.localHeaderOffset); + this.checkSignature(sig.LOCAL_FILE_HEADER); + file.readLocalPart(this.reader); + file.handleUTF8(); + } + }, + /** + * Read the central directory. + */ + readCentralDir: function() { + var file; + + this.reader.setIndex(this.centralDirOffset); + while (this.reader.readString(4) === sig.CENTRAL_FILE_HEADER) { + file = new ZipEntry({ + zip64: this.zip64 + }, this.loadOptions); + file.readCentralPart(this.reader); + this.files.push(file); + } + }, + /** + * Read the end of central directory. + */ + readEndOfCentral: function() { + var offset = this.reader.lastIndexOfSignature(sig.CENTRAL_DIRECTORY_END); + if (offset === -1) { + throw new Error("Corrupted zip : can't find end of central directory"); + } + this.reader.setIndex(offset); + this.checkSignature(sig.CENTRAL_DIRECTORY_END); + this.readBlockEndOfCentral(); + + + /* extract from the zip spec : + 4) If one of the fields in the end of central directory + record is too small to hold required data, the field + should be set to -1 (0xFFFF or 0xFFFFFFFF) and the + ZIP64 format record should be created. + 5) The end of central directory record and the + Zip64 end of central directory locator record must + reside on the same disk when splitting or spanning + an archive. + */ + if (this.diskNumber === utils.MAX_VALUE_16BITS || this.diskWithCentralDirStart === utils.MAX_VALUE_16BITS || this.centralDirRecordsOnThisDisk === utils.MAX_VALUE_16BITS || this.centralDirRecords === utils.MAX_VALUE_16BITS || this.centralDirSize === utils.MAX_VALUE_32BITS || this.centralDirOffset === utils.MAX_VALUE_32BITS) { + this.zip64 = true; + + /* + Warning : the zip64 extension is supported, but ONLY if the 64bits integer read from + the zip file can fit into a 32bits integer. This cannot be solved : Javascript represents + all numbers as 64-bit double precision IEEE 754 floating point numbers. + So, we have 53bits for integers and bitwise operations treat everything as 32bits. + see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Bitwise_Operators + and http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf section 8.5 + */ + + // should look for a zip64 EOCD locator + offset = this.reader.lastIndexOfSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + if (offset === -1) { + throw new Error("Corrupted zip : can't find the ZIP64 end of central directory locator"); + } + this.reader.setIndex(offset); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_LOCATOR); + this.readBlockZip64EndOfCentralLocator(); + + // now the zip64 EOCD record + this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir); + this.checkSignature(sig.ZIP64_CENTRAL_DIRECTORY_END); + this.readBlockZip64EndOfCentral(); + } + }, + prepareReader: function(data) { + var type = utils.getTypeOf(data); + if (type === "string" && !support.uint8array) { + this.reader = new StringReader(data, this.loadOptions.optimizedBinaryString); + } + else if (type === "nodebuffer") { + this.reader = new NodeBufferReader(data); + } + else { + this.reader = new Uint8ArrayReader(utils.transformTo("uint8array", data)); + } + }, + /** + * Read a zip file and create ZipEntries. + * @param {String|ArrayBuffer|Uint8Array|Buffer} data the binary string representing a zip file. + */ + load: function(data) { + this.prepareReader(data); + this.readEndOfCentral(); + this.readCentralDir(); + this.readLocalFiles(); + } + }; +// }}} end of ZipEntries + module.exports = ZipEntries; + + },{"./nodeBufferReader":12,"./object":13,"./signature":14,"./stringReader":15,"./support":17,"./uint8ArrayReader":18,"./utils":21,"./zipEntry":23}],23:[function(_dereq_,module,exports){ + 'use strict'; + var StringReader = _dereq_('./stringReader'); + var utils = _dereq_('./utils'); + var CompressedObject = _dereq_('./compressedObject'); + var jszipProto = _dereq_('./object'); +// class ZipEntry {{{ + /** + * An entry in the zip file. + * @constructor + * @param {Object} options Options of the current file. + * @param {Object} loadOptions Options for loading the stream. + */ + function ZipEntry(options, loadOptions) { + this.options = options; + this.loadOptions = loadOptions; + } + ZipEntry.prototype = { + /** + * say if the file is encrypted. + * @return {boolean} true if the file is encrypted, false otherwise. + */ + isEncrypted: function() { + // bit 1 is set + return (this.bitFlag & 0x0001) === 0x0001; + }, + /** + * say if the file has utf-8 filename/comment. + * @return {boolean} true if the filename/comment is in utf-8, false otherwise. + */ + useUTF8: function() { + // bit 11 is set + return (this.bitFlag & 0x0800) === 0x0800; + }, + /** + * Prepare the function used to generate the compressed content from this ZipFile. + * @param {DataReader} reader the reader to use. + * @param {number} from the offset from where we should read the data. + * @param {number} length the length of the data to read. + * @return {Function} the callback to get the compressed content (the type depends of the DataReader class). + */ + prepareCompressedContent: function(reader, from, length) { + return function() { + var previousIndex = reader.index; + reader.setIndex(from); + var compressedFileData = reader.readData(length); + reader.setIndex(previousIndex); + + return compressedFileData; + }; + }, + /** + * Prepare the function used to generate the uncompressed content from this ZipFile. + * @param {DataReader} reader the reader to use. + * @param {number} from the offset from where we should read the data. + * @param {number} length the length of the data to read. + * @param {JSZip.compression} compression the compression used on this file. + * @param {number} uncompressedSize the uncompressed size to expect. + * @return {Function} the callback to get the uncompressed content (the type depends of the DataReader class). + */ + prepareContent: function(reader, from, length, compression, uncompressedSize) { + return function() { + + var compressedFileData = utils.transformTo(compression.uncompressInputType, this.getCompressedContent()); + var uncompressedFileData = compression.uncompress(compressedFileData); + + if (uncompressedFileData.length !== uncompressedSize) { + throw new Error("Bug : uncompressed data size mismatch"); + } + + return uncompressedFileData; + }; + }, + /** + * Read the local part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readLocalPart: function(reader) { + var compression, localExtraFieldsLength; + + // we already know everything from the central dir ! + // If the central dir data are false, we are doomed. + // On the bright side, the local part is scary : zip64, data descriptors, both, etc. + // The less data we get here, the more reliable this should be. + // Let's skip the whole header and dash to the data ! + reader.skip(22); + // in some zip created on windows, the filename stored in the central dir contains \ instead of /. + // Strangely, the filename here is OK. + // I would love to treat these zip files as corrupted (see http://www.info-zip.org/FAQ.html#backslashes + // or APPNOTE#4.4.17.1, "All slashes MUST be forward slashes '/'") but there are a lot of bad zip generators... + // Search "unzip mismatching "local" filename continuing with "central" filename version" on + // the internet. + // + // I think I see the logic here : the central directory is used to display + // content and the local directory is used to extract the files. Mixing / and \ + // may be used to display \ to windows users and use / when extracting the files. + // Unfortunately, this lead also to some issues : http://seclists.org/fulldisclosure/2009/Sep/394 + this.fileNameLength = reader.readInt(2); + localExtraFieldsLength = reader.readInt(2); // can't be sure this will be the same as the central dir + this.fileName = reader.readString(this.fileNameLength); + reader.skip(localExtraFieldsLength); + + if (this.compressedSize == -1 || this.uncompressedSize == -1) { + throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory " + "(compressedSize == -1 || uncompressedSize == -1)"); + } + + compression = utils.findCompression(this.compressionMethod); + if (compression === null) { // no compression found + throw new Error("Corrupted zip : compression " + utils.pretty(this.compressionMethod) + " unknown (inner file : " + this.fileName + ")"); + } + this.decompressed = new CompressedObject(); + this.decompressed.compressedSize = this.compressedSize; + this.decompressed.uncompressedSize = this.uncompressedSize; + this.decompressed.crc32 = this.crc32; + this.decompressed.compressionMethod = this.compressionMethod; + this.decompressed.getCompressedContent = this.prepareCompressedContent(reader, reader.index, this.compressedSize, compression); + this.decompressed.getContent = this.prepareContent(reader, reader.index, this.compressedSize, compression, this.uncompressedSize); + + // we need to compute the crc32... + if (this.loadOptions.checkCRC32) { + this.decompressed = utils.transformTo("string", this.decompressed.getContent()); + if (jszipProto.crc32(this.decompressed) !== this.crc32) { + throw new Error("Corrupted zip : CRC32 mismatch"); + } + } + }, + + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readCentralPart: function(reader) { + this.versionMadeBy = reader.readString(2); + this.versionNeeded = reader.readInt(2); + this.bitFlag = reader.readInt(2); + this.compressionMethod = reader.readString(2); + this.date = reader.readDate(); + this.crc32 = reader.readInt(4); + this.compressedSize = reader.readInt(4); + this.uncompressedSize = reader.readInt(4); + this.fileNameLength = reader.readInt(2); + this.extraFieldsLength = reader.readInt(2); + this.fileCommentLength = reader.readInt(2); + this.diskNumberStart = reader.readInt(2); + this.internalFileAttributes = reader.readInt(2); + this.externalFileAttributes = reader.readInt(4); + this.localHeaderOffset = reader.readInt(4); + + if (this.isEncrypted()) { + throw new Error("Encrypted zip are not supported"); + } + + this.fileName = reader.readString(this.fileNameLength); + this.readExtraFields(reader); + this.parseZIP64ExtraField(reader); + this.fileComment = reader.readString(this.fileCommentLength); + + // warning, this is true only for zip with madeBy == DOS (plateform dependent feature) + this.dir = this.externalFileAttributes & 0x00000010 ? true : false; + }, + /** + * Parse the ZIP64 extra field and merge the info in the current ZipEntry. + * @param {DataReader} reader the reader to use. + */ + parseZIP64ExtraField: function(reader) { + + if (!this.extraFields[0x0001]) { + return; + } + + // should be something, preparing the extra reader + var extraReader = new StringReader(this.extraFields[0x0001].value); + + // I really hope that these 64bits integer can fit in 32 bits integer, because js + // won't let us have more. + if (this.uncompressedSize === utils.MAX_VALUE_32BITS) { + this.uncompressedSize = extraReader.readInt(8); + } + if (this.compressedSize === utils.MAX_VALUE_32BITS) { + this.compressedSize = extraReader.readInt(8); + } + if (this.localHeaderOffset === utils.MAX_VALUE_32BITS) { + this.localHeaderOffset = extraReader.readInt(8); + } + if (this.diskNumberStart === utils.MAX_VALUE_32BITS) { + this.diskNumberStart = extraReader.readInt(4); + } + }, + /** + * Read the central part of a zip file and add the info in this object. + * @param {DataReader} reader the reader to use. + */ + readExtraFields: function(reader) { + var start = reader.index, + extraFieldId, + extraFieldLength, + extraFieldValue; + + this.extraFields = this.extraFields || {}; + + while (reader.index < start + this.extraFieldsLength) { + extraFieldId = reader.readInt(2); + extraFieldLength = reader.readInt(2); + extraFieldValue = reader.readString(extraFieldLength); + + this.extraFields[extraFieldId] = { + id: extraFieldId, + length: extraFieldLength, + value: extraFieldValue + }; + } + }, + /** + * Apply an UTF8 transformation if needed. + */ + handleUTF8: function() { + if (this.useUTF8()) { + this.fileName = jszipProto.utf8decode(this.fileName); + this.fileComment = jszipProto.utf8decode(this.fileComment); + } else { + var upath = this.findExtraFieldUnicodePath(); + if (upath !== null) { + this.fileName = upath; + } + var ucomment = this.findExtraFieldUnicodeComment(); + if (ucomment !== null) { + this.fileComment = ucomment; + } + } + }, + + /** + * Find the unicode path declared in the extra field, if any. + * @return {String} the unicode path, null otherwise. + */ + findExtraFieldUnicodePath: function() { + var upathField = this.extraFields[0x7075]; + if (upathField) { + var extraReader = new StringReader(upathField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the filename changed, this field is out of date. + if (jszipProto.crc32(this.fileName) !== extraReader.readInt(4)) { + return null; + } + + return jszipProto.utf8decode(extraReader.readString(upathField.length - 5)); + } + return null; + }, + + /** + * Find the unicode comment declared in the extra field, if any. + * @return {String} the unicode comment, null otherwise. + */ + findExtraFieldUnicodeComment: function() { + var ucommentField = this.extraFields[0x6375]; + if (ucommentField) { + var extraReader = new StringReader(ucommentField.value); + + // wrong version + if (extraReader.readInt(1) !== 1) { + return null; + } + + // the crc of the comment changed, this field is out of date. + if (jszipProto.crc32(this.fileComment) !== extraReader.readInt(4)) { + return null; + } + + return jszipProto.utf8decode(extraReader.readString(ucommentField.length - 5)); + } + return null; + } + }; + module.exports = ZipEntry; + + },{"./compressedObject":2,"./object":13,"./stringReader":15,"./utils":21}],24:[function(_dereq_,module,exports){ +// Top level file is just a mixin of submodules & constants + 'use strict'; + + var assign = _dereq_('./lib/utils/common').assign; + + var deflate = _dereq_('./lib/deflate'); + var inflate = _dereq_('./lib/inflate'); + var constants = _dereq_('./lib/zlib/constants'); + + var pako = {}; + + assign(pako, deflate, inflate, constants); + + module.exports = pako; + },{"./lib/deflate":25,"./lib/inflate":26,"./lib/utils/common":27,"./lib/zlib/constants":30}],25:[function(_dereq_,module,exports){ + 'use strict'; + + + var zlib_deflate = _dereq_('./zlib/deflate.js'); + var utils = _dereq_('./utils/common'); + var strings = _dereq_('./utils/strings'); + var msg = _dereq_('./zlib/messages'); + var zstream = _dereq_('./zlib/zstream'); + + + /* Public constants ==========================================================*/ + /* ===========================================================================*/ + + var Z_NO_FLUSH = 0; + var Z_FINISH = 4; + + var Z_OK = 0; + var Z_STREAM_END = 1; + + var Z_DEFAULT_COMPRESSION = -1; + + var Z_DEFAULT_STRATEGY = 0; + + var Z_DEFLATED = 8; + + /* ===========================================================================*/ + + + /** + * class Deflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[deflate]], + * [[deflateRaw]] and [[gzip]]. + **/ + + /* internal + * Deflate.chunks -> Array + * + * Chunks of output data, if [[Deflate#onData]] not overriden. + **/ + + /** + * Deflate.result -> Uint8Array|Array + * + * Compressed result, generated by default [[Deflate#onData]] + * and [[Deflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Deflate#push]] with `Z_FINISH` / `true` param). + **/ + + /** + * Deflate.err -> Number + * + * Error code after deflate finished. 0 (Z_OK) on success. + * You will not need it in real life, because deflate errors + * are possible only on wrong options or bad `onData` / `onEnd` + * custom handlers. + **/ + + /** + * Deflate.msg -> String + * + * Error message, if [[Deflate.err]] != 0 + **/ + + + /** + * new Deflate(options) + * - options (Object): zlib deflate options. + * + * Creates new deflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `level` + * - `windowBits` + * - `memLevel` + * - `strategy` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw deflate + * - `gzip` (Boolean) - create gzip wrapper + * - `to` (String) - if equal to 'string', then result will be "binary string" + * (each char code [0..255]) + * - `header` (Object) - custom header for gzip + * - `text` (Boolean) - true if compressed data believed to be text + * - `time` (Number) - modification time, unix timestamp + * - `os` (Number) - operation system code + * - `extra` (Array) - array of bytes with extra data (max 65536) + * - `name` (String) - file name (binary string) + * - `comment` (String) - comment (binary string) + * - `hcrc` (Boolean) - true if header crc should be added + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var deflate = new pako.Deflate({ level: 3}); + * + * deflate.push(chunk1, false); + * deflate.push(chunk2, true); // true -> last chunk + * + * if (deflate.err) { throw new Error(deflate.err); } + * + * console.log(deflate.result); + * ``` + **/ + var Deflate = function(options) { + + this.options = utils.assign({ + level: Z_DEFAULT_COMPRESSION, + method: Z_DEFLATED, + chunkSize: 16384, + windowBits: 15, + memLevel: 8, + strategy: Z_DEFAULT_STRATEGY, + to: '' + }, options || {}); + + var opt = this.options; + + if (opt.raw && (opt.windowBits > 0)) { + opt.windowBits = -opt.windowBits; + } + + else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { + opt.windowBits += 16; + } + + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data + + this.strm = new zstream(); + this.strm.avail_out = 0; + + var status = zlib_deflate.deflateInit2( + this.strm, + opt.level, + opt.method, + opt.windowBits, + opt.memLevel, + opt.strategy + ); + + if (status !== Z_OK) { + throw new Error(msg[status]); + } + + if (opt.header) { + zlib_deflate.deflateSetHeader(this.strm, opt.header); + } + }; + + /** + * Deflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|String): input data. Strings will be converted to + * utf8 byte sequence. + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH. + * + * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with + * new compressed chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That flush internal pending buffers and call + * [[Deflate#onEnd]]. + * + * On fail call [[Deflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * array format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ + Deflate.prototype.push = function(data, mode) { + var strm = this.strm; + var chunkSize = this.options.chunkSize; + var status, _mode; + + if (this.ended) { return false; } + + _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); + + // Convert data if needed + if (typeof data === 'string') { + // If we need to compress text, change encoding to utf8. + strm.input = strings.string2buf(data); + } else { + strm.input = data; + } + + strm.next_in = 0; + strm.avail_in = strm.input.length; + + do { + if (strm.avail_out === 0) { + strm.output = new utils.Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + status = zlib_deflate.deflate(strm, _mode); /* no bad return value */ + + if (status !== Z_STREAM_END && status !== Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + if (strm.avail_out === 0 || (strm.avail_in === 0 && _mode === Z_FINISH)) { + if (this.options.to === 'string') { + this.onData(strings.buf2binstring(utils.shrinkBuf(strm.output, strm.next_out))); + } else { + this.onData(utils.shrinkBuf(strm.output, strm.next_out)); + } + } + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); + + // Finalize on the last chunk. + if (_mode === Z_FINISH) { + status = zlib_deflate.deflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === Z_OK; + } + + return true; + }; + + + /** + * Deflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): ouput data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ + Deflate.prototype.onData = function(chunk) { + this.chunks.push(chunk); + }; + + + /** + * Deflate#onEnd(status) -> Void + * - status (Number): deflate status. 0 (Z_OK) on success, + * other if not. + * + * Called once after you tell deflate that input stream complete + * or error happenned. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ + Deflate.prototype.onEnd = function(status) { + // On success - join + if (status === Z_OK) { + if (this.options.to === 'string') { + this.result = this.chunks.join(''); + } else { + this.result = utils.flattenChunks(this.chunks); + } + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; + }; + + + /** + * deflate(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to compress. + * - options (Object): zlib deflate options. + * + * Compress `data` with deflate alrorythm and `options`. + * + * Supported options are: + * + * - level + * - windowBits + * - memLevel + * - strategy + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Sugar (options): + * + * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify + * negative windowBits implicitly. + * - `to` (String) - if equal to 'string', then result will be "binary string" + * (each char code [0..255]) + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , data = Uint8Array([1,2,3,4,5,6,7,8,9]); + * + * console.log(pako.deflate(data)); + * ``` + **/ + function deflate(input, options) { + var deflator = new Deflate(options); + + deflator.push(input, true); + + // That will never happens, if you don't cheat with options :) + if (deflator.err) { throw deflator.msg; } + + return deflator.result; + } + + + /** + * deflateRaw(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to compress. + * - options (Object): zlib deflate options. + * + * The same as [[deflate]], but creates raw data, without wrapper + * (header and adler32 crc). + **/ + function deflateRaw(input, options) { + options = options || {}; + options.raw = true; + return deflate(input, options); + } + + + /** + * gzip(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to compress. + * - options (Object): zlib deflate options. + * + * The same as [[deflate]], but create gzip wrapper instead of + * deflate one. + **/ + function gzip(input, options) { + options = options || {}; + options.gzip = true; + return deflate(input, options); + } + + + exports.Deflate = Deflate; + exports.deflate = deflate; + exports.deflateRaw = deflateRaw; + exports.gzip = gzip; + },{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(_dereq_,module,exports){ + 'use strict'; + + + var zlib_inflate = _dereq_('./zlib/inflate.js'); + var utils = _dereq_('./utils/common'); + var strings = _dereq_('./utils/strings'); + var c = _dereq_('./zlib/constants'); + var msg = _dereq_('./zlib/messages'); + var zstream = _dereq_('./zlib/zstream'); + var gzheader = _dereq_('./zlib/gzheader'); + + + /** + * class Inflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[inflate]] + * and [[inflateRaw]]. + **/ + + /* internal + * inflate.chunks -> Array + * + * Chunks of output data, if [[Inflate#onData]] not overriden. + **/ + + /** + * Inflate.result -> Uint8Array|Array|String + * + * Uncompressed result, generated by default [[Inflate#onData]] + * and [[Inflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Inflate#push]] with `Z_FINISH` / `true` param). + **/ + + /** + * Inflate.err -> Number + * + * Error code after inflate finished. 0 (Z_OK) on success. + * Should be checked if broken data possible. + **/ + + /** + * Inflate.msg -> String + * + * Error message, if [[Inflate.err]] != 0 + **/ + + + /** + * new Inflate(options) + * - options (Object): zlib inflate options. + * + * Creates new inflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `windowBits` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw inflate + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * By default, when no options set, autodetect deflate/gzip data format via + * wrapper header. + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var inflate = new pako.Inflate({ level: 3}); + * + * inflate.push(chunk1, false); + * inflate.push(chunk2, true); // true -> last chunk + * + * if (inflate.err) { throw new Error(inflate.err); } + * + * console.log(inflate.result); + * ``` + **/ + var Inflate = function(options) { + + this.options = utils.assign({ + chunkSize: 16384, + windowBits: 0, + to: '' + }, options || {}); + + var opt = this.options; + + // Force window size for `raw` data, if not set directly, + // because we have no header for autodetect. + if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { + opt.windowBits = -opt.windowBits; + if (opt.windowBits === 0) { opt.windowBits = -15; } + } + + // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate + if ((opt.windowBits >= 0) && (opt.windowBits < 16) && + !(options && options.windowBits)) { + opt.windowBits += 32; + } + + // Gzip header has no info about windows size, we can do autodetect only + // for deflate. So, if window size not set, force it to max when gzip possible + if ((opt.windowBits > 15) && (opt.windowBits < 48)) { + // bit 3 (16) -> gzipped data + // bit 4 (32) -> autodetect gzip/deflate + if ((opt.windowBits & 15) === 0) { + opt.windowBits |= 15; + } + } + + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data + + this.strm = new zstream(); + this.strm.avail_out = 0; + + var status = zlib_inflate.inflateInit2( + this.strm, + opt.windowBits + ); + + if (status !== c.Z_OK) { + throw new Error(msg[status]); + } + + this.header = new gzheader(); + + zlib_inflate.inflateGetHeader(this.strm, this.header); + }; + + /** + * Inflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|String): input data + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH. + * + * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with + * new output chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That flush internal pending buffers and call + * [[Inflate#onEnd]]. + * + * On fail call [[Inflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ + Inflate.prototype.push = function(data, mode) { + var strm = this.strm; + var chunkSize = this.options.chunkSize; + var status, _mode; + var next_out_utf8, tail, utf8str; + + if (this.ended) { return false; } + _mode = (mode === ~~mode) ? mode : ((mode === true) ? c.Z_FINISH : c.Z_NO_FLUSH); + + // Convert data if needed + if (typeof data === 'string') { + // Only binary strings can be decompressed on practice + strm.input = strings.binstring2buf(data); + } else { + strm.input = data; + } + + strm.next_in = 0; + strm.avail_in = strm.input.length; + + do { + if (strm.avail_out === 0) { + strm.output = new utils.Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } + + status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH); /* no bad return value */ + + if (status !== c.Z_STREAM_END && status !== c.Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + + if (strm.next_out) { + if (strm.avail_out === 0 || status === c.Z_STREAM_END || (strm.avail_in === 0 && _mode === c.Z_FINISH)) { + + if (this.options.to === 'string') { + + next_out_utf8 = strings.utf8border(strm.output, strm.next_out); + + tail = strm.next_out - next_out_utf8; + utf8str = strings.buf2string(strm.output, next_out_utf8); + + // move tail + strm.next_out = tail; + strm.avail_out = chunkSize - tail; + if (tail) { utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); } + + this.onData(utf8str); + + } else { + this.onData(utils.shrinkBuf(strm.output, strm.next_out)); + } + } + } + } while ((strm.avail_in > 0) && status !== c.Z_STREAM_END); + + if (status === c.Z_STREAM_END) { + _mode = c.Z_FINISH; + } + // Finalize on the last chunk. + if (_mode === c.Z_FINISH) { + status = zlib_inflate.inflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === c.Z_OK; + } + + return true; + }; + + + /** + * Inflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): ouput data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ + Inflate.prototype.onData = function(chunk) { + this.chunks.push(chunk); + }; + + + /** + * Inflate#onEnd(status) -> Void + * - status (Number): inflate status. 0 (Z_OK) on success, + * other if not. + * + * Called once after you tell inflate that input stream complete + * or error happenned. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ + Inflate.prototype.onEnd = function(status) { + // On success - join + if (status === c.Z_OK) { + if (this.options.to === 'string') { + // Glue & convert here, until we teach pako to send + // utf8 alligned strings to onData + this.result = this.chunks.join(''); + } else { + this.result = utils.flattenChunks(this.chunks); + } + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; + }; + + + /** + * inflate(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to decompress. + * - options (Object): zlib inflate options. + * + * Decompress `data` with inflate/ungzip and `options`. Autodetect + * format via wrapper header by default. That's why we don't provide + * separate `ungzip` method. + * + * Supported options are: + * + * - windowBits + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information. + * + * Sugar (options): + * + * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify + * negative windowBits implicitly. + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , input = pako.deflate([1,2,3,4,5,6,7,8,9]) + * , output; + * + * try { + * output = pako.inflate(input); + * } catch (err) + * console.log(err); + * } + * ``` + **/ + function inflate(input, options) { + var inflator = new Inflate(options); + + inflator.push(input, true); + + // That will never happens, if you don't cheat with options :) + if (inflator.err) { throw inflator.msg; } + + return inflator.result; + } + + + /** + * inflateRaw(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to decompress. + * - options (Object): zlib inflate options. + * + * The same as [[inflate]], but creates raw data, without wrapper + * (header and adler32 crc). + **/ + function inflateRaw(input, options) { + options = options || {}; + options.raw = true; + return inflate(input, options); + } + + + /** + * ungzip(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to decompress. + * - options (Object): zlib inflate options. + * + * Just shortcut to [[inflate]], because it autodetects format + * by header.content. Done for convenience. + **/ + + + exports.Inflate = Inflate; + exports.inflate = inflate; + exports.inflateRaw = inflateRaw; + exports.ungzip = inflate; + + },{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(_dereq_,module,exports){ + 'use strict'; + + + var TYPED_OK = (typeof Uint8Array !== 'undefined') && + (typeof Uint16Array !== 'undefined') && + (typeof Int32Array !== 'undefined'); + + + exports.assign = function (obj /*from1, from2, from3, ...*/) { + var sources = Array.prototype.slice.call(arguments, 1); + while (sources.length) { + var source = sources.shift(); + if (!source) { continue; } + + if (typeof(source) !== 'object') { + throw new TypeError(source + 'must be non-object'); + } + + for (var p in source) { + if (source.hasOwnProperty(p)) { + obj[p] = source[p]; + } + } + } + + return obj; + }; + + +// reduce buffer size, avoiding mem copy + exports.shrinkBuf = function (buf, size) { + if (buf.length === size) { return buf; } + if (buf.subarray) { return buf.subarray(0, size); } + buf.length = size; + return buf; + }; + + + var fnTyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + if (src.subarray && dest.subarray) { + dest.set(src.subarray(src_offs, src_offs+len), dest_offs); + return; + } + // Fallback to ordinary array + for(var i=0; i= 252 ? 6 : i >= 248 ? 5 : i >= 240 ? 4 : i >= 224 ? 3 : i >= 192 ? 2 : 1); + } + _utf8len[254]=_utf8len[254]=1; // Invalid sequence start + + +// convert string to array (typed, when possible) + exports.string2buf = function (str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + buf = new utils.Buf8(buf_len); + + // convert + for (i=0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos+1 < str_len)) { + c2 = str.charCodeAt(m_pos+1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; + }; + +// Helper (used in 2 places) + function buf2binstring(buf, len) { + // use fallback for big arrays to avoid stack overflow + if (len < 65537) { + if ((buf.subarray && STR_APPLY_UIA_OK) || (!buf.subarray && STR_APPLY_OK)) { + return String.fromCharCode.apply(null, utils.shrinkBuf(buf, len)); + } + } + + var result = ''; + for(var i=0; i < len; i++) { + result += String.fromCharCode(buf[i]); + } + return result; + } + + +// Convert byte array to binary string + exports.buf2binstring = function(buf) { + return buf2binstring(buf, buf.length); + }; + + +// Convert binary string (typed, when possible) + exports.binstring2buf = function(str) { + var buf = new utils.Buf8(str.length); + for(var i=0, len=buf.length; i < len; i++) { + buf[i] = str.charCodeAt(i); + } + return buf; + }; + + +// convert array to string + exports.buf2string = function (buf, max) { + var i, out, c, c_len; + var len = max || buf.length; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + var utf16buf = new Array(len*2); + + for (out=0, i=0; i 4) { utf16buf[out++] = 0xfffd; i += c_len-1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; + } + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); + } + } + + return buf2binstring(utf16buf, out); + }; + + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); + exports.utf8border = function(buf, max) { + var pos; + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + pos = max-1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Fuckup - very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means vuffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; + }; + + },{"./common":27}],29:[function(_dereq_,module,exports){ + 'use strict'; + +// Note: adler32 takes 12% for level 0 and 2% for level 6. +// It doesn't worth to make additional optimizationa as in original. +// Small size is preferable. + + function adler32(adler, buf, len, pos) { + var s1 = (adler & 0xffff) |0 + , s2 = ((adler >>> 16) & 0xffff) |0 + , n = 0; + + while (len !== 0) { + // Set limit ~ twice less than 5552, to keep + // s2 in 31-bits, because we force signed ints. + // in other case %= will fail. + n = len > 2000 ? 2000 : len; + len -= n; + + do { + s1 = (s1 + buf[pos++]) |0; + s2 = (s2 + s1) |0; + } while (--n); + + s1 %= 65521; + s2 %= 65521; + } + + return (s1 | (s2 << 16)) |0; + } + + + module.exports = adler32; + },{}],30:[function(_dereq_,module,exports){ + module.exports = { + + /* Allowed flush values; see deflate() and inflate() below for details */ + Z_NO_FLUSH: 0, + Z_PARTIAL_FLUSH: 1, + Z_SYNC_FLUSH: 2, + Z_FULL_FLUSH: 3, + Z_FINISH: 4, + Z_BLOCK: 5, + Z_TREES: 6, + + /* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + Z_OK: 0, + Z_STREAM_END: 1, + Z_NEED_DICT: 2, + Z_ERRNO: -1, + Z_STREAM_ERROR: -2, + Z_DATA_ERROR: -3, + //Z_MEM_ERROR: -4, + Z_BUF_ERROR: -5, + //Z_VERSION_ERROR: -6, + + /* compression levels */ + Z_NO_COMPRESSION: 0, + Z_BEST_SPEED: 1, + Z_BEST_COMPRESSION: 9, + Z_DEFAULT_COMPRESSION: -1, + + + Z_FILTERED: 1, + Z_HUFFMAN_ONLY: 2, + Z_RLE: 3, + Z_FIXED: 4, + Z_DEFAULT_STRATEGY: 0, + + /* Possible values of the data_type field (though see inflate()) */ + Z_BINARY: 0, + Z_TEXT: 1, + //Z_ASCII: 1, // = Z_TEXT (deprecated) + Z_UNKNOWN: 2, + + /* The deflate compression method */ + Z_DEFLATED: 8 + //Z_NULL: null // Use -1 or null inline, depending on var type + }; + },{}],31:[function(_dereq_,module,exports){ + 'use strict'; + +// Note: we can't get significant speed boost here. +// So write code to minimize size - no pregenerated tables +// and array tools dependencies. + + +// Use ordinary array, since untyped makes no boost here + function makeTable() { + var c, table = []; + + for(var n =0; n < 256; n++){ + c = n; + for(var k =0; k < 8; k++){ + c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; + } + +// Create table on load. Just 255 signed longs. Not a problem. + var crcTable = makeTable(); + + + function crc32(crc, buf, len, pos) { + var t = crcTable + , end = pos + len; + + crc = crc ^ (-1); + + for (var i = pos; i < end; i++ ) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; + } + + + module.exports = crc32; + },{}],32:[function(_dereq_,module,exports){ + 'use strict'; + + var utils = _dereq_('../utils/common'); + var trees = _dereq_('./trees'); + var adler32 = _dereq_('./adler32'); + var crc32 = _dereq_('./crc32'); + var msg = _dereq_('./messages'); + + /* Public constants ==========================================================*/ + /* ===========================================================================*/ + + + /* Allowed flush values; see deflate() and inflate() below for details */ + var Z_NO_FLUSH = 0; + var Z_PARTIAL_FLUSH = 1; +//var Z_SYNC_FLUSH = 2; + var Z_FULL_FLUSH = 3; + var Z_FINISH = 4; + var Z_BLOCK = 5; +//var Z_TREES = 6; + + + /* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + var Z_OK = 0; + var Z_STREAM_END = 1; +//var Z_NEED_DICT = 2; +//var Z_ERRNO = -1; + var Z_STREAM_ERROR = -2; + var Z_DATA_ERROR = -3; +//var Z_MEM_ERROR = -4; + var Z_BUF_ERROR = -5; +//var Z_VERSION_ERROR = -6; + + + /* compression levels */ +//var Z_NO_COMPRESSION = 0; +//var Z_BEST_SPEED = 1; +//var Z_BEST_COMPRESSION = 9; + var Z_DEFAULT_COMPRESSION = -1; + + + var Z_FILTERED = 1; + var Z_HUFFMAN_ONLY = 2; + var Z_RLE = 3; + var Z_FIXED = 4; + var Z_DEFAULT_STRATEGY = 0; + + /* Possible values of the data_type field (though see inflate()) */ +//var Z_BINARY = 0; +//var Z_TEXT = 1; +//var Z_ASCII = 1; // = Z_TEXT + var Z_UNKNOWN = 2; + + + /* The deflate compression method */ + var Z_DEFLATED = 8; + + /*============================================================================*/ + + + var MAX_MEM_LEVEL = 9; + /* Maximum value for memLevel in deflateInit2 */ + var MAX_WBITS = 15; + /* 32K LZ77 window */ + var DEF_MEM_LEVEL = 8; + + + var LENGTH_CODES = 29; + /* number of length codes, not counting the special END_BLOCK code */ + var LITERALS = 256; + /* number of literal bytes 0..255 */ + var L_CODES = LITERALS + 1 + LENGTH_CODES; + /* number of Literal or Length codes, including the END_BLOCK code */ + var D_CODES = 30; + /* number of distance codes */ + var BL_CODES = 19; + /* number of codes used to transfer the bit lengths */ + var HEAP_SIZE = 2*L_CODES + 1; + /* maximum heap size */ + var MAX_BITS = 15; + /* All codes must not exceed MAX_BITS bits */ + + var MIN_MATCH = 3; + var MAX_MATCH = 258; + var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1); + + var PRESET_DICT = 0x20; + + var INIT_STATE = 42; + var EXTRA_STATE = 69; + var NAME_STATE = 73; + var COMMENT_STATE = 91; + var HCRC_STATE = 103; + var BUSY_STATE = 113; + var FINISH_STATE = 666; + + var BS_NEED_MORE = 1; /* block not completed, need more input or more output */ + var BS_BLOCK_DONE = 2; /* block flush performed */ + var BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ + var BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ + + var OS_CODE = 0x03; // Unix :) . Don't detect, use this default. + + function err(strm, errorCode) { + strm.msg = msg[errorCode]; + return errorCode; + } + + function rank(f) { + return ((f) << 1) - ((f) > 4 ? 9 : 0); + } + + function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } } + + + /* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->output buffer and copying into it. + * (See also read_buf()). + */ + function flush_pending(strm) { + var s = strm.state; + + //_tr_flush_bits(s); + var len = s.pending; + if (len > strm.avail_out) { + len = strm.avail_out; + } + if (len === 0) { return; } + + utils.arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); + strm.next_out += len; + s.pending_out += len; + strm.total_out += len; + strm.avail_out -= len; + s.pending -= len; + if (s.pending === 0) { + s.pending_out = 0; + } + } + + + function flush_block_only (s, last) { + trees._tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); + s.block_start = s.strstart; + flush_pending(s.strm); + } + + + function put_byte(s, b) { + s.pending_buf[s.pending++] = b; + } + + + /* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ + function putShortMSB(s, b) { +// put_byte(s, (Byte)(b >> 8)); +// put_byte(s, (Byte)(b & 0xff)); + s.pending_buf[s.pending++] = (b >>> 8) & 0xff; + s.pending_buf[s.pending++] = b & 0xff; + } + + + /* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->input buffer and copying from it. + * (See also flush_pending()). + */ + function read_buf(strm, buf, start, size) { + var len = strm.avail_in; + + if (len > size) { len = size; } + if (len === 0) { return 0; } + + strm.avail_in -= len; + + utils.arraySet(buf, strm.input, strm.next_in, len, start); + if (strm.state.wrap === 1) { + strm.adler = adler32(strm.adler, buf, len, start); + } + + else if (strm.state.wrap === 2) { + strm.adler = crc32(strm.adler, buf, len, start); + } + + strm.next_in += len; + strm.total_in += len; + + return len; + } + + + /* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ + function longest_match(s, cur_match) { + var chain_length = s.max_chain_length; /* max hash chain length */ + var scan = s.strstart; /* current string */ + var match; /* matched string */ + var len; /* length of current match */ + var best_len = s.prev_length; /* best match length so far */ + var nice_match = s.nice_match; /* stop if match long enough */ + var limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? + s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; + + var _win = s.window; // shortcut + + var wmask = s.w_mask; + var prev = s.prev; + + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + + var strend = s.strstart + MAX_MATCH; + var scan_end1 = _win[scan + best_len - 1]; + var scan_end = _win[scan + best_len]; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s.prev_length >= s.good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if (nice_match > s.lookahead) { nice_match = s.lookahead; } + + // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + // Assert(cur_match < s->strstart, "no future"); + match = cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ + + if (_win[match + best_len] !== scan_end || + _win[match + best_len - 1] !== scan_end1 || + _win[match] !== _win[scan] || + _win[++match] !== _win[scan + 1]) { + continue; + } + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2; + match++; + // Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + /*jshint noempty:false*/ + } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + scan < strend); + + // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (strend - scan); + scan = strend - MAX_MATCH; + + if (len > best_len) { + s.match_start = cur_match; + best_len = len; + if (len >= nice_match) { + break; + } + scan_end1 = _win[scan + best_len - 1]; + scan_end = _win[scan + best_len]; + } + } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); + + if (best_len <= s.lookahead) { + return best_len; + } + return s.lookahead; + } + + + /* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ + function fill_window(s) { + var _w_size = s.w_size; + var p, n, m, more, str; + + //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = s.window_size - s.lookahead - s.strstart; + + // JS ints have 32 bit, block below not needed + /* Deal with !@#$% 64K limit: */ + //if (sizeof(int) <= 2) { + // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + // more = wsize; + // + // } else if (more == (unsigned)(-1)) { + // /* Very unlikely, but possible on 16 bit machine if + // * strstart == 0 && lookahead == 1 (input done a byte at time) + // */ + // more--; + // } + //} + + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { + + utils.arraySet(s.window, s.window, _w_size, _w_size, 0); + s.match_start -= _w_size; + s.strstart -= _w_size; + /* we now have strstart >= MAX_DIST */ + s.block_start -= _w_size; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + + n = s.hash_size; + p = n; + do { + m = s.head[--p]; + s.head[p] = (m >= _w_size ? m - _w_size : 0); + } while (--n); + + n = _w_size; + p = n; + do { + m = s.prev[--p]; + s.prev[p] = (m >= _w_size ? m - _w_size : 0); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); + + more += _w_size; + } + if (s.strm.avail_in === 0) { + break; + } + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + //Assert(more >= 2, "more < 2"); + n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); + s.lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s.lookahead + s.insert >= MIN_MATCH) { + str = s.strstart - s.insert; + s.ins_h = s.window[str]; + + /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; +//#if MIN_MATCH != 3 +// Call update_hash() MIN_MATCH-3 more times +//#endif + while (s.insert) { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH-1]) & s.hash_mask; + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = str; + str++; + s.insert--; + if (s.lookahead + s.insert < MIN_MATCH) { + break; + } + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ +// if (s.high_water < s.window_size) { +// var curr = s.strstart + s.lookahead; +// var init = 0; +// +// if (s.high_water < curr) { +// /* Previous high water mark below current data -- zero WIN_INIT +// * bytes or up to end of window, whichever is less. +// */ +// init = s.window_size - curr; +// if (init > WIN_INIT) +// init = WIN_INIT; +// zmemzero(s->window + curr, (unsigned)init); +// s->high_water = curr + init; +// } +// else if (s->high_water < (ulg)curr + WIN_INIT) { +// /* High water mark at or above current data, but below current data +// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up +// * to end of window, whichever is less. +// */ +// init = (ulg)curr + WIN_INIT - s->high_water; +// if (init > s->window_size - s->high_water) +// init = s->window_size - s->high_water; +// zmemzero(s->window + s->high_water, (unsigned)init); +// s->high_water += init; +// } +// } +// +// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, +// "not enough room for search"); + } + + /* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ + function deflate_stored(s, flush) { + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + var max_block_size = 0xffff; + + if (max_block_size > s.pending_buf_size - 5) { + max_block_size = s.pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s.lookahead <= 1) { + + //Assert(s->strstart < s->w_size+MAX_DIST(s) || + // s->block_start >= (long)s->w_size, "slide too late"); +// if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || +// s.block_start >= s.w_size)) { +// throw new Error("slide too late"); +// } + + fill_window(s); + if (s.lookahead === 0 && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + + if (s.lookahead === 0) { + break; + } + /* flush the current block */ + } + //Assert(s->block_start >= 0L, "block gone"); +// if (s.block_start < 0) throw new Error("block gone"); + + s.strstart += s.lookahead; + s.lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + var max_start = s.block_start + max_block_size; + + if (s.strstart === 0 || s.strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s.lookahead = s.strstart - max_start; + s.strstart = max_start; + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + + + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + + s.insert = 0; + + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + + if (s.strstart > s.block_start) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + return BS_NEED_MORE; + } + + /* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ + function deflate_fast(s, flush) { + var hash_head; /* head of the hash chain */ + var bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { + break; /* flush the current block */ + } + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + } + if (s.match_length >= MIN_MATCH) { + // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only + + /*** _tr_tally_dist(s, s.strstart - s.match_start, + s.match_length - MIN_MATCH, bflush); ***/ + bflush = trees._tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH); + + s.lookahead -= s.match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) { + s.match_length--; /* string at strstart already in table */ + do { + s.strstart++; + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s.match_length !== 0); + s.strstart++; + } else + { + s.strstart += s.match_length; + s.match_length = 0; + s.ins_h = s.window[s.strstart]; + /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; + +//#if MIN_MATCH != 3 +// Call UPDATE_HASH() MIN_MATCH-3 more times +//#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s.window[s.strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = ((s.strstart < (MIN_MATCH-1)) ? s.strstart : MIN_MATCH-1); + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; + } + + /* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ + function deflate_slow(s, flush) { + var hash_head; /* head of hash chain */ + var bflush; /* set if current block must be flushed */ + + var max_insert; + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + + /* Find the longest match, discarding those <= prev_length. + */ + s.prev_length = s.match_length; + s.prev_match = s.match_start; + s.match_length = MIN_MATCH-1; + + if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && + s.strstart - hash_head <= (s.w_size-MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + + if (s.match_length <= 5 && + (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s.match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) { + max_insert = s.strstart + s.lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + //check_match(s, s.strstart-1, s.prev_match, s.prev_length); + + /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, + s.prev_length - MIN_MATCH, bflush);***/ + bflush = trees._tr_tally(s, s.strstart - 1- s.prev_match, s.prev_length - MIN_MATCH); + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s.lookahead -= s.prev_length-1; + s.prev_length -= 2; + do { + if (++s.strstart <= max_insert) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + } while (--s.prev_length !== 0); + s.match_available = 0; + s.match_length = MIN_MATCH-1; + s.strstart++; + + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + } else if (s.match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart-1]); + + if (bflush) { + /*** FLUSH_BLOCK_ONLY(s, 0) ***/ + flush_block_only(s, false); + /***/ + } + s.strstart++; + s.lookahead--; + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s.match_available = 1; + s.strstart++; + s.lookahead--; + } + } + //Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s.match_available) { + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart-1]); + + s.match_available = 0; + } + s.insert = s.strstart < MIN_MATCH-1 ? s.strstart : MIN_MATCH-1; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + return BS_BLOCK_DONE; + } + + + /* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ + function deflate_rle(s, flush) { + var bflush; /* set if current block must be flushed */ + var prev; /* byte at distance one to match */ + var scan, strend; /* scan goes up to strend for length of run */ + + var _win = s.window; + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. + */ + if (s.lookahead <= MAX_MATCH) { + fill_window(s); + if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s.match_length = 0; + if (s.lookahead >= MIN_MATCH && s.strstart > 0) { + scan = s.strstart - 1; + prev = _win[scan]; + if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { + strend = s.strstart + MAX_MATCH; + do { + /*jshint noempty:false*/ + } while (prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + scan < strend); + s.match_length = MAX_MATCH - (strend - scan); + if (s.match_length > s.lookahead) { + s.match_length = s.lookahead; + } + } + //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s.match_length >= MIN_MATCH) { + //check_match(s, s.strstart, s.strstart - 1, s.match_length); + + /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ + bflush = trees._tr_tally(s, 1, s.match_length - MIN_MATCH); + + s.lookahead -= s.match_length; + s.strstart += s.match_length; + s.match_length = 0; + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; + } + + /* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ + function deflate_huff(s, flush) { + var bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s.lookahead === 0) { + fill_window(s); + if (s.lookahead === 0) { + if (flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s.match_length = 0; + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); + s.lookahead--; + s.strstart++; + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; + } + + /* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ + var Config = function (good_length, max_lazy, nice_length, max_chain, func) { + this.good_length = good_length; + this.max_lazy = max_lazy; + this.nice_length = nice_length; + this.max_chain = max_chain; + this.func = func; + }; + + var configuration_table; + + configuration_table = [ + /* good lazy nice chain */ + new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ + new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ + new Config(4, 5, 16, 8, deflate_fast), /* 2 */ + new Config(4, 6, 32, 32, deflate_fast), /* 3 */ + + new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ + new Config(8, 16, 32, 32, deflate_slow), /* 5 */ + new Config(8, 16, 128, 128, deflate_slow), /* 6 */ + new Config(8, 32, 128, 256, deflate_slow), /* 7 */ + new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ + new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ + ]; + + + /* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ + function lm_init(s) { + s.window_size = 2 * s.w_size; + + /*** CLEAR_HASH(s); ***/ + zero(s.head); // Fill with NIL (= 0); + + /* Set the default configuration parameters: + */ + s.max_lazy_match = configuration_table[s.level].max_lazy; + s.good_match = configuration_table[s.level].good_length; + s.nice_match = configuration_table[s.level].nice_length; + s.max_chain_length = configuration_table[s.level].max_chain; + + s.strstart = 0; + s.block_start = 0; + s.lookahead = 0; + s.insert = 0; + s.match_length = s.prev_length = MIN_MATCH - 1; + s.match_available = 0; + s.ins_h = 0; + } + + + function DeflateState() { + this.strm = null; /* pointer back to this zlib stream */ + this.status = 0; /* as the name implies */ + this.pending_buf = null; /* output still pending */ + this.pending_buf_size = 0; /* size of pending_buf */ + this.pending_out = 0; /* next pending byte to output to the stream */ + this.pending = 0; /* nb of bytes in the pending buffer */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.gzhead = null; /* gzip header information to write */ + this.gzindex = 0; /* where in extra, name, or comment */ + this.method = Z_DEFLATED; /* can only be DEFLATED */ + this.last_flush = -1; /* value of flush param for previous deflate call */ + + this.w_size = 0; /* LZ77 window size (32K by default) */ + this.w_bits = 0; /* log2(w_size) (8..16) */ + this.w_mask = 0; /* w_size - 1 */ + + this.window = null; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. + */ + + this.window_size = 0; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + this.prev = null; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + this.head = null; /* Heads of the hash chains or NIL. */ + + this.ins_h = 0; /* hash index of string to be inserted */ + this.hash_size = 0; /* number of elements in hash table */ + this.hash_bits = 0; /* log2(hash_size) */ + this.hash_mask = 0; /* hash_size-1 */ + + this.hash_shift = 0; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + this.block_start = 0; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + this.match_length = 0; /* length of best match */ + this.prev_match = 0; /* previous match */ + this.match_available = 0; /* set if previous match exists */ + this.strstart = 0; /* start of string to insert */ + this.match_start = 0; /* start of matching string */ + this.lookahead = 0; /* number of valid bytes ahead in window */ + + this.prev_length = 0; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + this.max_chain_length = 0; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + this.max_lazy_match = 0; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ + // That's alias to max_lazy_match, don't use directly + //this.max_insert_length = 0; + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + this.level = 0; /* compression level (1..9) */ + this.strategy = 0; /* favor or force Huffman coding*/ + + this.good_match = 0; + /* Use a faster search when the previous match is longer than this */ + + this.nice_match = 0; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + + /* Didn't use ct_data typedef below to suppress compiler warning */ + + // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + // Use flat array of DOUBLE size, with interleaved fata, + // because JS does not support effective + this.dyn_ltree = new utils.Buf16(HEAP_SIZE * 2); + this.dyn_dtree = new utils.Buf16((2*D_CODES+1) * 2); + this.bl_tree = new utils.Buf16((2*BL_CODES+1) * 2); + zero(this.dyn_ltree); + zero(this.dyn_dtree); + zero(this.bl_tree); + + this.l_desc = null; /* desc. for literal tree */ + this.d_desc = null; /* desc. for distance tree */ + this.bl_desc = null; /* desc. for bit length tree */ + + //ush bl_count[MAX_BITS+1]; + this.bl_count = new utils.Buf16(MAX_BITS+1); + /* number of codes at each bit length for an optimal tree */ + + //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + this.heap = new utils.Buf16(2*L_CODES+1); /* heap used to build the Huffman trees */ + zero(this.heap); + + this.heap_len = 0; /* number of elements in the heap */ + this.heap_max = 0; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + this.depth = new utils.Buf16(2*L_CODES+1); //uch depth[2*L_CODES+1]; + zero(this.depth); + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + this.l_buf = 0; /* buffer index for literals or lengths */ + + this.lit_bufsize = 0; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + this.last_lit = 0; /* running index in l_buf */ + + this.d_buf = 0; + /* Buffer index for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + this.opt_len = 0; /* bit length of current block with optimal trees */ + this.static_len = 0; /* bit length of current block with static trees */ + this.matches = 0; /* number of string matches in current block */ + this.insert = 0; /* bytes at end of window left to insert */ + + + this.bi_buf = 0; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + this.bi_valid = 0; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + // Used for window memory init. We safely ignore it for JS. That makes + // sense only for pointers and memory check tools. + //this.high_water = 0; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + } + + + function deflateResetKeep(strm) { + var s; + + if (!strm || !strm.state) { + return err(strm, Z_STREAM_ERROR); + } + + strm.total_in = strm.total_out = 0; + strm.data_type = Z_UNKNOWN; + + s = strm.state; + s.pending = 0; + s.pending_out = 0; + + if (s.wrap < 0) { + s.wrap = -s.wrap; + /* was made negative by deflate(..., Z_FINISH); */ + } + s.status = (s.wrap ? INIT_STATE : BUSY_STATE); + strm.adler = (s.wrap === 2) ? + 0 // crc32(0, Z_NULL, 0) + : + 1; // adler32(0, Z_NULL, 0) + s.last_flush = Z_NO_FLUSH; + trees._tr_init(s); + return Z_OK; + } + + + function deflateReset(strm) { + var ret = deflateResetKeep(strm); + if (ret === Z_OK) { + lm_init(strm.state); + } + return ret; + } + + + function deflateSetHeader(strm, head) { + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } + strm.state.gzhead = head; + return Z_OK; + } + + + function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { + if (!strm) { // === Z_NULL + return Z_STREAM_ERROR; + } + var wrap = 1; + + if (level === Z_DEFAULT_COMPRESSION) { + level = 6; + } + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } + + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } + + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return err(strm, Z_STREAM_ERROR); + } + + + if (windowBits === 8) { + windowBits = 9; + } + /* until 256-byte window bug fixed */ + + var s = new DeflateState(); + + strm.state = s; + s.strm = strm; + + s.wrap = wrap; + s.gzhead = null; + s.w_bits = windowBits; + s.w_size = 1 << s.w_bits; + s.w_mask = s.w_size - 1; + + s.hash_bits = memLevel + 7; + s.hash_size = 1 << s.hash_bits; + s.hash_mask = s.hash_size - 1; + s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH); + + s.window = new utils.Buf8(s.w_size * 2); + s.head = new utils.Buf16(s.hash_size); + s.prev = new utils.Buf16(s.w_size); + + // Don't need mem init magic for JS. + //s.high_water = 0; /* nothing written to s->window yet */ + + s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + s.pending_buf_size = s.lit_bufsize * 4; + s.pending_buf = new utils.Buf8(s.pending_buf_size); + + s.d_buf = s.lit_bufsize >> 1; + s.l_buf = (1 + 2) * s.lit_bufsize; + + s.level = level; + s.strategy = strategy; + s.method = method; + + return deflateReset(strm); + } + + function deflateInit(strm, level) { + return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); + } + + + function deflate(strm, flush) { + var old_flush, s; + var beg, val; // for gzip header write only + + if (!strm || !strm.state || + flush > Z_BLOCK || flush < 0) { + return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; + } + + s = strm.state; + + if (!strm.output || + (!strm.input && strm.avail_in !== 0) || + (s.status === FINISH_STATE && flush !== Z_FINISH)) { + return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); + } + + s.strm = strm; /* just in case */ + old_flush = s.last_flush; + s.last_flush = flush; + + /* Write the header */ + if (s.status === INIT_STATE) { + + if (s.wrap === 2) { // GZIP header + strm.adler = 0; //crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (!s.gzhead) { // s->gzhead == Z_NULL + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s.status = BUSY_STATE; + } + else { + put_byte(s, (s.gzhead.text ? 1 : 0) + + (s.gzhead.hcrc ? 2 : 0) + + (!s.gzhead.extra ? 0 : 4) + + (!s.gzhead.name ? 0 : 8) + + (!s.gzhead.comment ? 0 : 16) + ); + put_byte(s, s.gzhead.time & 0xff); + put_byte(s, (s.gzhead.time >> 8) & 0xff); + put_byte(s, (s.gzhead.time >> 16) & 0xff); + put_byte(s, (s.gzhead.time >> 24) & 0xff); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, s.gzhead.os & 0xff); + if (s.gzhead.extra && s.gzhead.extra.length) { + put_byte(s, s.gzhead.extra.length & 0xff); + put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); + } + if (s.gzhead.hcrc) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); + } + s.gzindex = 0; + s.status = EXTRA_STATE; + } + } + else // DEFLATE header + { + var header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; + var level_flags = -1; + + if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { + level_flags = 0; + } else if (s.level < 6) { + level_flags = 1; + } else if (s.level === 6) { + level_flags = 2; + } else { + level_flags = 3; + } + header |= (level_flags << 6); + if (s.strstart !== 0) { header |= PRESET_DICT; } + header += 31 - (header % 31); + + s.status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s.strstart !== 0) { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + strm.adler = 1; // adler32(0L, Z_NULL, 0); + } + } + +//#ifdef GZIP + if (s.status === EXTRA_STATE) { + if (s.gzhead.extra/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + + while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + break; + } + } + put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); + s.gzindex++; + } + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (s.gzindex === s.gzhead.extra.length) { + s.gzindex = 0; + s.status = NAME_STATE; + } + } + else { + s.status = NAME_STATE; + } + } + if (s.status === NAME_STATE) { + if (s.gzhead.name/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; + + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.name.length) { + val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + + if (s.gzhead.hcrc && s.pending > beg){ + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.gzindex = 0; + s.status = COMMENT_STATE; + } + } + else { + s.status = COMMENT_STATE; + } + } + if (s.status === COMMENT_STATE) { + if (s.gzhead.comment/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; + + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.comment.length) { + val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.status = HCRC_STATE; + } + } + else { + s.status = HCRC_STATE; + } + } + if (s.status === HCRC_STATE) { + if (s.gzhead.hcrc) { + if (s.pending + 2 > s.pending_buf_size) { + flush_pending(strm); + } + if (s.pending + 2 <= s.pending_buf_size) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + strm.adler = 0; //crc32(0L, Z_NULL, 0); + s.status = BUSY_STATE; + } + } + else { + s.status = BUSY_STATE; + } + } +//#endif + + /* Flush as much pending output as possible */ + if (s.pending !== 0) { + flush_pending(strm); + if (strm.avail_out === 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s.last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && + flush !== Z_FINISH) { + return err(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s.status === FINISH_STATE && strm.avail_in !== 0) { + return err(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm.avail_in !== 0 || s.lookahead !== 0 || + (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { + var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : + (s.strategy === Z_RLE ? deflate_rle(s, flush) : + configuration_table[s.level].func(s, flush)); + + if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { + s.status = FINISH_STATE; + } + if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { + if (strm.avail_out === 0) { + s.last_flush = -1; + /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate === BS_BLOCK_DONE) { + if (flush === Z_PARTIAL_FLUSH) { + trees._tr_align(s); + } + else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + + trees._tr_stored_block(s, 0, 0, false); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush === Z_FULL_FLUSH) { + /*** CLEAR_HASH(s); ***/ /* forget history */ + zero(s.head); // Fill with NIL (= 0); + + if (s.lookahead === 0) { + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + } + } + flush_pending(strm); + if (strm.avail_out === 0) { + s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + //Assert(strm->avail_out > 0, "bug2"); + //if (strm.avail_out <= 0) { throw new Error("bug2");} + + if (flush !== Z_FINISH) { return Z_OK; } + if (s.wrap <= 0) { return Z_STREAM_END; } + + /* Write the trailer */ + if (s.wrap === 2) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + put_byte(s, (strm.adler >> 16) & 0xff); + put_byte(s, (strm.adler >> 24) & 0xff); + put_byte(s, strm.total_in & 0xff); + put_byte(s, (strm.total_in >> 8) & 0xff); + put_byte(s, (strm.total_in >> 16) & 0xff); + put_byte(s, (strm.total_in >> 24) & 0xff); + } + else + { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s.wrap > 0) { s.wrap = -s.wrap; } + /* write the trailer only once! */ + return s.pending !== 0 ? Z_OK : Z_STREAM_END; + } + + function deflateEnd(strm) { + var status; + + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; + } + + status = strm.state.status; + if (status !== INIT_STATE && + status !== EXTRA_STATE && + status !== NAME_STATE && + status !== COMMENT_STATE && + status !== HCRC_STATE && + status !== BUSY_STATE && + status !== FINISH_STATE + ) { + return err(strm, Z_STREAM_ERROR); + } + + strm.state = null; + + return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; + } + + /* ========================================================================= + * Copy the source state to the destination state + */ +//function deflateCopy(dest, source) { +// +//} + + exports.deflateInit = deflateInit; + exports.deflateInit2 = deflateInit2; + exports.deflateReset = deflateReset; + exports.deflateResetKeep = deflateResetKeep; + exports.deflateSetHeader = deflateSetHeader; + exports.deflate = deflate; + exports.deflateEnd = deflateEnd; + exports.deflateInfo = 'pako deflate (from Nodeca project)'; + + /* Not implemented +exports.deflateBound = deflateBound; +exports.deflateCopy = deflateCopy; +exports.deflateSetDictionary = deflateSetDictionary; +exports.deflateParams = deflateParams; +exports.deflatePending = deflatePending; +exports.deflatePrime = deflatePrime; +exports.deflateTune = deflateTune; +*/ + },{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(_dereq_,module,exports){ + 'use strict'; + + + function GZheader() { + /* true if compressed data believed to be text */ + this.text = 0; + /* modification time */ + this.time = 0; + /* extra flags (not used when writing a gzip file) */ + this.xflags = 0; + /* operating system */ + this.os = 0; + /* pointer to extra field or Z_NULL if none */ + this.extra = null; + /* extra field length (valid if extra != Z_NULL) */ + this.extra_len = 0; // Actually, we don't need it in JS, + // but leave for few code modifications + + // + // Setup limits is not necessary because in js we should not preallocate memory + // for inflate use constant limit in 65536 bytes + // + + /* space at extra (only when reading header) */ + // this.extra_max = 0; + /* pointer to zero-terminated file name or Z_NULL */ + this.name = ''; + /* space at name (only when reading header) */ + // this.name_max = 0; + /* pointer to zero-terminated comment or Z_NULL */ + this.comment = ''; + /* space at comment (only when reading header) */ + // this.comm_max = 0; + /* true if there was or will be a header crc */ + this.hcrc = 0; + /* true when done reading gzip header (not used when writing a gzip file) */ + this.done = false; + } + + module.exports = GZheader; + },{}],34:[function(_dereq_,module,exports){ + 'use strict'; + +// See state defs from inflate.js + var BAD = 30; /* got a data error -- remain here until reset */ + var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ + + /* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state.mode === LEN + strm.avail_in >= 6 + strm.avail_out >= 258 + start >= strm.avail_out + state.bits < 8 + + On return, state.mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm.avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm.avail_out >= 258 for each loop to avoid checking for + output space. + */ + module.exports = function inflate_fast(strm, start) { + var state; + var _in; /* local strm.input */ + var last; /* have enough input while in < last */ + var _out; /* local strm.output */ + var beg; /* inflate()'s initial strm.output */ + var end; /* while out < end, enough space available */ +//#ifdef INFLATE_STRICT + var dmax; /* maximum distance from zlib header */ +//#endif + var wsize; /* window size or zero if not using window */ + var whave; /* valid bytes in the window */ + var wnext; /* window write index */ + var window; /* allocated sliding window, if wsize != 0 */ + var hold; /* local strm.hold */ + var bits; /* local strm.bits */ + var lcode; /* local strm.lencode */ + var dcode; /* local strm.distcode */ + var lmask; /* mask for first level of length codes */ + var dmask; /* mask for first level of distance codes */ + var here; /* retrieved table entry */ + var op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + var len; /* match length, unused bytes */ + var dist; /* match distance */ + var from; /* where to copy match from */ + var from_source; + + + var input, output; // JS specific, because we have no pointers + + /* copy state to local variables */ + state = strm.state; + //here = state.here; + _in = strm.next_in; + input = strm.input; + last = _in + (strm.avail_in - 5); + _out = strm.next_out; + output = strm.output; + beg = _out - (start - strm.avail_out); + end = _out + (strm.avail_out - 257); +//#ifdef INFLATE_STRICT + dmax = state.dmax; +//#endif + wsize = state.wsize; + whave = state.whave; + wnext = state.wnext; + window = state.window; + hold = state.hold; + bits = state.bits; + lcode = state.lencode; + dcode = state.distcode; + lmask = (1 << state.lenbits) - 1; + dmask = (1 << state.distbits) - 1; + + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + top: + do { + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + + here = lcode[hold & lmask]; + + dolen: + for (;;) { // Goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = (here >>> 16) & 0xff/*here.op*/; + if (op === 0) { /* literal */ + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + output[_out++] = here & 0xffff/*here.val*/; + } + else if (op & 16) { /* length base */ + len = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + len += hold & ((1 << op) - 1); + hold >>>= op; + bits -= op; + } + //Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + here = dcode[hold & dmask]; + + dodist: + for (;;) { // goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = (here >>> 16) & 0xff/*here.op*/; + + if (op & 16) { /* distance base */ + dist = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + } + dist += hold & ((1 << op) - 1); +//#ifdef INFLATE_STRICT + if (dist > dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break top; + } +//#endif + hold >>>= op; + bits -= op; + //Tracevv((stderr, "inflate: distance %u\n", dist)); + op = _out - beg; /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break top; + } + +// (!) This block is disabled in zlib defailts, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// if (len <= op - whave) { +// do { +// output[_out++] = 0; +// } while (--len); +// continue top; +// } +// len -= op - whave; +// do { +// output[_out++] = 0; +// } while (--op > whave); +// if (op === 0) { +// from = _out - dist; +// do { +// output[_out++] = output[from++]; +// } while (--len); +// continue top; +// } +//#endif + } + from = 0; // window index + from_source = window; + if (wnext === 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + output[_out++] = window[from++]; + } while (--op); + from = 0; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + output[_out++] = window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + while (len > 2) { + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + len -= 3; + } + if (len) { + output[_out++] = from_source[from++]; + if (len > 1) { + output[_out++] = from_source[from++]; + } + } + } + else { + from = _out - dist; /* copy direct from output */ + do { /* minimum length is three */ + output[_out++] = output[from++]; + output[_out++] = output[from++]; + output[_out++] = output[from++]; + len -= 3; + } while (len > 2); + if (len) { + output[_out++] = output[from++]; + if (len > 1) { + output[_out++] = output[from++]; + } + } + } + } + else if ((op & 64) === 0) { /* 2nd level distance code */ + here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; + continue dodist; + } + else { + strm.msg = 'invalid distance code'; + state.mode = BAD; + break top; + } + + break; // need to emulate goto via "continue" + } + } + else if ((op & 64) === 0) { /* 2nd level length code */ + here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; + continue dolen; + } + else if (op & 32) { /* end-of-block */ + //Tracevv((stderr, "inflate: end of block\n")); + state.mode = TYPE; + break top; + } + else { + strm.msg = 'invalid literal/length code'; + state.mode = BAD; + break top; + } + + break; // need to emulate goto via "continue" + } + } while (_in < last && _out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + _in -= len; + bits -= len << 3; + hold &= (1 << bits) - 1; + + /* update state and return */ + strm.next_in = _in; + strm.next_out = _out; + strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); + strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); + state.hold = hold; + state.bits = bits; + return; + }; + + },{}],35:[function(_dereq_,module,exports){ + 'use strict'; + + + var utils = _dereq_('../utils/common'); + var adler32 = _dereq_('./adler32'); + var crc32 = _dereq_('./crc32'); + var inflate_fast = _dereq_('./inffast'); + var inflate_table = _dereq_('./inftrees'); + + var CODES = 0; + var LENS = 1; + var DISTS = 2; + + /* Public constants ==========================================================*/ + /* ===========================================================================*/ + + + /* Allowed flush values; see deflate() and inflate() below for details */ +//var Z_NO_FLUSH = 0; +//var Z_PARTIAL_FLUSH = 1; +//var Z_SYNC_FLUSH = 2; +//var Z_FULL_FLUSH = 3; + var Z_FINISH = 4; + var Z_BLOCK = 5; + var Z_TREES = 6; + + + /* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + var Z_OK = 0; + var Z_STREAM_END = 1; + var Z_NEED_DICT = 2; +//var Z_ERRNO = -1; + var Z_STREAM_ERROR = -2; + var Z_DATA_ERROR = -3; + var Z_MEM_ERROR = -4; + var Z_BUF_ERROR = -5; +//var Z_VERSION_ERROR = -6; + + /* The deflate compression method */ + var Z_DEFLATED = 8; + + + /* STATES ====================================================================*/ + /* ===========================================================================*/ + + + var HEAD = 1; /* i: waiting for magic header */ + var FLAGS = 2; /* i: waiting for method and flags (gzip) */ + var TIME = 3; /* i: waiting for modification time (gzip) */ + var OS = 4; /* i: waiting for extra flags and operating system (gzip) */ + var EXLEN = 5; /* i: waiting for extra length (gzip) */ + var EXTRA = 6; /* i: waiting for extra bytes (gzip) */ + var NAME = 7; /* i: waiting for end of file name (gzip) */ + var COMMENT = 8; /* i: waiting for end of comment (gzip) */ + var HCRC = 9; /* i: waiting for header crc (gzip) */ + var DICTID = 10; /* i: waiting for dictionary check value */ + var DICT = 11; /* waiting for inflateSetDictionary() call */ + var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ + var TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ + var STORED = 14; /* i: waiting for stored size (length and complement) */ + var COPY_ = 15; /* i/o: same as COPY below, but only first time in */ + var COPY = 16; /* i/o: waiting for input or output to copy stored block */ + var TABLE = 17; /* i: waiting for dynamic block table lengths */ + var LENLENS = 18; /* i: waiting for code length code lengths */ + var CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ + var LEN_ = 20; /* i: same as LEN below, but only first time in */ + var LEN = 21; /* i: waiting for length/lit/eob code */ + var LENEXT = 22; /* i: waiting for length extra bits */ + var DIST = 23; /* i: waiting for distance code */ + var DISTEXT = 24; /* i: waiting for distance extra bits */ + var MATCH = 25; /* o: waiting for output space to copy string */ + var LIT = 26; /* o: waiting for output space to write literal */ + var CHECK = 27; /* i: waiting for 32-bit check value */ + var LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ + var DONE = 29; /* finished check, done -- remain here until reset */ + var BAD = 30; /* got a data error -- remain here until reset */ + var MEM = 31; /* got an inflate() memory error -- remain here until reset */ + var SYNC = 32; /* looking for synchronization bytes to restart inflate() */ + + /* ===========================================================================*/ + + + + var ENOUGH_LENS = 852; + var ENOUGH_DISTS = 592; +//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + + var MAX_WBITS = 15; + /* 32K LZ77 window */ + var DEF_WBITS = MAX_WBITS; + + + function ZSWAP32(q) { + return (((q >>> 24) & 0xff) + + ((q >>> 8) & 0xff00) + + ((q & 0xff00) << 8) + + ((q & 0xff) << 24)); + } + + + function InflateState() { + this.mode = 0; /* current inflate mode */ + this.last = false; /* true if processing last block */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.havedict = false; /* true if dictionary provided */ + this.flags = 0; /* gzip header method and flags (0 if zlib) */ + this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ + this.check = 0; /* protected copy of check value */ + this.total = 0; /* protected copy of output count */ + // TODO: may be {} + this.head = null; /* where to save gzip header information */ + + /* sliding window */ + this.wbits = 0; /* log base 2 of requested window size */ + this.wsize = 0; /* window size or zero if not using window */ + this.whave = 0; /* valid bytes in the window */ + this.wnext = 0; /* window write index */ + this.window = null; /* allocated sliding window, if needed */ + + /* bit accumulator */ + this.hold = 0; /* input bit accumulator */ + this.bits = 0; /* number of bits in "in" */ + + /* for string and stored block copying */ + this.length = 0; /* literal or length of data to copy */ + this.offset = 0; /* distance back to copy string from */ + + /* for table and code decoding */ + this.extra = 0; /* extra bits needed */ + + /* fixed and dynamic code tables */ + this.lencode = null; /* starting table for length/literal codes */ + this.distcode = null; /* starting table for distance codes */ + this.lenbits = 0; /* index bits for lencode */ + this.distbits = 0; /* index bits for distcode */ + + /* dynamic table building */ + this.ncode = 0; /* number of code length code lengths */ + this.nlen = 0; /* number of length code lengths */ + this.ndist = 0; /* number of distance code lengths */ + this.have = 0; /* number of code lengths in lens[] */ + this.next = null; /* next available space in codes[] */ + + this.lens = new utils.Buf16(320); /* temporary storage for code lengths */ + this.work = new utils.Buf16(288); /* work area for code table building */ + + /* + because we don't have pointers in js, we use lencode and distcode directly + as buffers so we don't need codes + */ + //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ + this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ + this.distdyn = null; /* dynamic table for distance codes (JS specific) */ + this.sane = 0; /* if false, allow invalid distance too far */ + this.back = 0; /* bits back of last unprocessed length/lit */ + this.was = 0; /* initial length of match */ + } + + function inflateResetKeep(strm) { + var state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + strm.total_in = strm.total_out = state.total = 0; + strm.msg = ''; /*Z_NULL*/ + if (state.wrap) { /* to support ill-conceived Java test suite */ + strm.adler = state.wrap & 1; + } + state.mode = HEAD; + state.last = 0; + state.havedict = 0; + state.dmax = 32768; + state.head = null/*Z_NULL*/; + state.hold = 0; + state.bits = 0; + //state.lencode = state.distcode = state.next = state.codes; + state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS); + state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS); + + state.sane = 1; + state.back = -1; + //Tracev((stderr, "inflate: reset\n")); + return Z_OK; + } + + function inflateReset(strm) { + var state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + state.wsize = 0; + state.whave = 0; + state.wnext = 0; + return inflateResetKeep(strm); + + } + + function inflateReset2(strm, windowBits) { + var wrap; + var state; + + /* get the state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; + if (windowBits < 48) { + windowBits &= 15; + } + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) { + return Z_STREAM_ERROR; + } + if (state.window !== null && state.wbits !== windowBits) { + state.window = null; + } + + /* update state and reset the rest of it */ + state.wrap = wrap; + state.wbits = windowBits; + return inflateReset(strm); + } + + function inflateInit2(strm, windowBits) { + var ret; + var state; + + if (!strm) { return Z_STREAM_ERROR; } + //strm.msg = Z_NULL; /* in case we return an error */ + + state = new InflateState(); + + //if (state === Z_NULL) return Z_MEM_ERROR; + //Tracev((stderr, "inflate: allocated\n")); + strm.state = state; + state.window = null/*Z_NULL*/; + ret = inflateReset2(strm, windowBits); + if (ret !== Z_OK) { + strm.state = null/*Z_NULL*/; + } + return ret; + } + + function inflateInit(strm) { + return inflateInit2(strm, DEF_WBITS); + } + + + /* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ + var virgin = true; + + var lenfix, distfix; // We have no pointers in JS, so keep tables separate + + function fixedtables(state) { + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + var sym; + + lenfix = new utils.Buf32(512); + distfix = new utils.Buf32(32); + + /* literal/length table */ + sym = 0; + while (sym < 144) { state.lens[sym++] = 8; } + while (sym < 256) { state.lens[sym++] = 9; } + while (sym < 280) { state.lens[sym++] = 7; } + while (sym < 288) { state.lens[sym++] = 8; } + + inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, {bits: 9}); + + /* distance table */ + sym = 0; + while (sym < 32) { state.lens[sym++] = 5; } + + inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, {bits: 5}); + + /* do this just once */ + virgin = false; + } + + state.lencode = lenfix; + state.lenbits = 9; + state.distcode = distfix; + state.distbits = 5; + } + + + /* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ + function updatewindow(strm, src, end, copy) { + var dist; + var state = strm.state; + + /* if it hasn't been done already, allocate space for the window */ + if (state.window === null) { + state.wsize = 1 << state.wbits; + state.wnext = 0; + state.whave = 0; + + state.window = new utils.Buf8(state.wsize); + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state.wsize) { + utils.arraySet(state.window,src, end - state.wsize, state.wsize, 0); + state.wnext = 0; + state.whave = state.wsize; + } + else { + dist = state.wsize - state.wnext; + if (dist > copy) { + dist = copy; + } + //zmemcpy(state->window + state->wnext, end - copy, dist); + utils.arraySet(state.window,src, end - copy, dist, state.wnext); + copy -= dist; + if (copy) { + //zmemcpy(state->window, end - copy, copy); + utils.arraySet(state.window,src, end - copy, copy, 0); + state.wnext = copy; + state.whave = state.wsize; + } + else { + state.wnext += dist; + if (state.wnext === state.wsize) { state.wnext = 0; } + if (state.whave < state.wsize) { state.whave += dist; } + } + } + return 0; + } + + function inflate(strm, flush) { + var state; + var input, output; // input/output buffers + var next; /* next input INDEX */ + var put; /* next output INDEX */ + var have, left; /* available input and output */ + var hold; /* bit buffer */ + var bits; /* bits in bit buffer */ + var _in, _out; /* save starting available input and output */ + var copy; /* number of stored or match bytes to copy */ + var from; /* where to copy match bytes from */ + var from_source; + var here = 0; /* current decoding table entry */ + var here_bits, here_op, here_val; // paked "here" denormalized (JS specific) + //var last; /* parent table entry */ + var last_bits, last_op, last_val; // paked "last" denormalized (JS specific) + var len; /* length to copy for repeats, bits to drop */ + var ret; /* return code */ + var hbuf = new utils.Buf8(4); /* buffer for gzip header crc calculation */ + var opts; + + var n; // temporary var for NEED_BITS + + var order = /* permutation of code lengths */ + [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]; + + + if (!strm || !strm.state || !strm.output || + (!strm.input && strm.avail_in !== 0)) { + return Z_STREAM_ERROR; + } + + state = strm.state; + if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */ + + + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + _in = have; + _out = left; + ret = Z_OK; + + inf_leave: // goto emulation + for (;;) { + switch (state.mode) { + case HEAD: + if (state.wrap === 0) { + state.mode = TYPEDO; + break; + } + //=== NEEDBITS(16); + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ + state.check = 0/*crc32(0L, Z_NULL, 0)*/; + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = FLAGS; + break; + } + state.flags = 0; /* expect zlib header */ + if (state.head) { + state.head.done = false; + } + if (!(state.wrap & 1) || /* check if zlib header allowed */ + (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { + strm.msg = 'incorrect header check'; + state.mode = BAD; + break; + } + if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD; + break; + } + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// + len = (hold & 0x0f)/*BITS(4)*/ + 8; + if (state.wbits === 0) { + state.wbits = len; + } + else if (len > state.wbits) { + strm.msg = 'invalid window size'; + state.mode = BAD; + break; + } + state.dmax = 1 << len; + //Tracev((stderr, "inflate: zlib header ok\n")); + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = hold & 0x200 ? DICTID : TYPE; + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + break; + case FLAGS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.flags = hold; + if ((state.flags & 0xff) !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD; + break; + } + if (state.flags & 0xe000) { + strm.msg = 'unknown header flags set'; + state.mode = BAD; + break; + } + if (state.head) { + state.head.text = ((hold >> 8) & 1); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = TIME; + /* falls through */ + case TIME: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.time = hold; + } + if (state.flags & 0x0200) { + //=== CRC4(state.check, hold) + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + hbuf[2] = (hold >>> 16) & 0xff; + hbuf[3] = (hold >>> 24) & 0xff; + state.check = crc32(state.check, hbuf, 4, 0); + //=== + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = OS; + /* falls through */ + case OS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.xflags = (hold & 0xff); + state.head.os = (hold >> 8); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = EXLEN; + /* falls through */ + case EXLEN: + if (state.flags & 0x0400) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length = hold; + if (state.head) { + state.head.extra_len = hold; + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + else if (state.head) { + state.head.extra = null/*Z_NULL*/; + } + state.mode = EXTRA; + /* falls through */ + case EXTRA: + if (state.flags & 0x0400) { + copy = state.length; + if (copy > have) { copy = have; } + if (copy) { + if (state.head) { + len = state.head.extra_len - state.length; + if (!state.head.extra) { + // Use untyped array for more conveniend processing later + state.head.extra = new Array(state.head.extra_len); + } + utils.arraySet( + state.head.extra, + input, + next, + // extra field is limited to 65536 bytes + // - no need for additional size check + copy, + /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ + len + ); + //zmemcpy(state.head.extra + len, next, + // len + copy > state.head.extra_max ? + // state.head.extra_max - len : copy); + } + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + state.length -= copy; + } + if (state.length) { break inf_leave; } + } + state.length = 0; + state.mode = NAME; + /* falls through */ + case NAME: + if (state.flags & 0x0800) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + // TODO: 2 or 1 bytes? + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.name_max*/)) { + state.head.name += String.fromCharCode(len); + } + } while (len && copy < have); + + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.name = null; + } + state.length = 0; + state.mode = COMMENT; + /* falls through */ + case COMMENT: + if (state.flags & 0x1000) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.comm_max*/)) { + state.head.comment += String.fromCharCode(len); + } + } while (len && copy < have); + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.comment = null; + } + state.mode = HCRC; + /* falls through */ + case HCRC: + if (state.flags & 0x0200) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.check & 0xffff)) { + strm.msg = 'header crc mismatch'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + if (state.head) { + state.head.hcrc = ((state.flags >> 9) & 1); + state.head.done = true; + } + strm.adler = state.check = 0 /*crc32(0L, Z_NULL, 0)*/; + state.mode = TYPE; + break; + case DICTID: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + strm.adler = state.check = ZSWAP32(hold); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = DICT; + /* falls through */ + case DICT: + if (state.havedict === 0) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + return Z_NEED_DICT; + } + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = TYPE; + /* falls through */ + case TYPE: + if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } + /* falls through */ + case TYPEDO: + if (state.last) { + //--- BYTEBITS() ---// + hold >>>= bits & 7; + bits -= bits & 7; + //---// + state.mode = CHECK; + break; + } + //=== NEEDBITS(3); */ + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.last = (hold & 0x01)/*BITS(1)*/; + //--- DROPBITS(1) ---// + hold >>>= 1; + bits -= 1; + //---// + + switch ((hold & 0x03)/*BITS(2)*/) { + case 0: /* stored block */ + //Tracev((stderr, "inflate: stored block%s\n", + // state.last ? " (last)" : "")); + state.mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + //Tracev((stderr, "inflate: fixed codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = LEN_; /* decode codes */ + if (flush === Z_TREES) { + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break inf_leave; + } + break; + case 2: /* dynamic block */ + //Tracev((stderr, "inflate: dynamic codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = TABLE; + break; + case 3: + strm.msg = 'invalid block type'; + state.mode = BAD; + } + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break; + case STORED: + //--- BYTEBITS() ---// /* go to byte boundary */ + hold >>>= bits & 7; + bits -= bits & 7; + //---// + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { + strm.msg = 'invalid stored block lengths'; + state.mode = BAD; + break; + } + state.length = hold & 0xffff; + //Tracev((stderr, "inflate: stored length %u\n", + // state.length)); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = COPY_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case COPY_: + state.mode = COPY; + /* falls through */ + case COPY: + copy = state.length; + if (copy) { + if (copy > have) { copy = have; } + if (copy > left) { copy = left; } + if (copy === 0) { break inf_leave; } + //--- zmemcpy(put, next, copy); --- + utils.arraySet(output, input, next, copy, put); + //---// + have -= copy; + next += copy; + left -= copy; + put += copy; + state.length -= copy; + break; + } + //Tracev((stderr, "inflate: stored end\n")); + state.mode = TYPE; + break; + case TABLE: + //=== NEEDBITS(14); */ + while (bits < 14) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// +//#ifndef PKZIP_BUG_WORKAROUND + if (state.nlen > 286 || state.ndist > 30) { + strm.msg = 'too many length or distance symbols'; + state.mode = BAD; + break; + } +//#endif + //Tracev((stderr, "inflate: table sizes ok\n")); + state.have = 0; + state.mode = LENLENS; + /* falls through */ + case LENLENS: + while (state.have < state.ncode) { + //=== NEEDBITS(3); + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + while (state.have < 19) { + state.lens[order[state.have++]] = 0; + } + // We have separate tables & no pointers. 2 commented lines below not needed. + //state.next = state.codes; + //state.lencode = state.next; + // Switch to use dynamic table + state.lencode = state.lendyn; + state.lenbits = 7; + + opts = {bits: state.lenbits}; + ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); + state.lenbits = opts.bits; + + if (ret) { + strm.msg = 'invalid code lengths set'; + state.mode = BAD; + break; + } + //Tracev((stderr, "inflate: code lengths ok\n")); + state.have = 0; + state.mode = CODELENS; + /* falls through */ + case CODELENS: + while (state.have < state.nlen + state.ndist) { + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_val < 16) { + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.lens[state.have++] = here_val; + } + else { + if (here_val === 16) { + //=== NEEDBITS(here.bits + 2); + n = here_bits + 2; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + if (state.have === 0) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD; + break; + } + len = state.lens[state.have - 1]; + copy = 3 + (hold & 0x03);//BITS(2); + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + } + else if (here_val === 17) { + //=== NEEDBITS(here.bits + 3); + n = here_bits + 3; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 3 + (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + else { + //=== NEEDBITS(here.bits + 7); + n = here_bits + 7; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 11 + (hold & 0x7f);//BITS(7); + //--- DROPBITS(7) ---// + hold >>>= 7; + bits -= 7; + //---// + } + if (state.have + copy > state.nlen + state.ndist) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD; + break; + } + while (copy--) { + state.lens[state.have++] = len; + } + } + } + + /* handle error breaks in while */ + if (state.mode === BAD) { break; } + + /* check for end-of-block code (better have one) */ + if (state.lens[256] === 0) { + strm.msg = 'invalid code -- missing end-of-block'; + state.mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state.lenbits = 9; + + opts = {bits: state.lenbits}; + ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.lenbits = opts.bits; + // state.lencode = state.next; + + if (ret) { + strm.msg = 'invalid literal/lengths set'; + state.mode = BAD; + break; + } + + state.distbits = 6; + //state.distcode.copy(state.codes); + // Switch to use dynamic table + state.distcode = state.distdyn; + opts = {bits: state.distbits}; + ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.distbits = opts.bits; + // state.distcode = state.next; + + if (ret) { + strm.msg = 'invalid distances set'; + state.mode = BAD; + break; + } + //Tracev((stderr, 'inflate: codes ok\n')); + state.mode = LEN_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case LEN_: + state.mode = LEN; + /* falls through */ + case LEN: + if (have >= 6 && left >= 258) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + inflate_fast(strm, _out); + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + if (state.mode === TYPE) { + state.back = -1; + } + break; + } + state.back = 0; + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) -1)]; /*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if (here_bits <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_op && (here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.lencode[last_val + + ((hold & ((1 << (last_bits + last_op)) -1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + state.length = here_val; + if (here_op === 0) { + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + state.mode = LIT; + break; + } + if (here_op & 32) { + //Tracevv((stderr, "inflate: end of block\n")); + state.back = -1; + state.mode = TYPE; + break; + } + if (here_op & 64) { + strm.msg = 'invalid literal/length code'; + state.mode = BAD; + break; + } + state.extra = here_op & 15; + state.mode = LENEXT; + /* falls through */ + case LENEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length += hold & ((1 << state.extra) -1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } + //Tracevv((stderr, "inflate: length %u\n", state.length)); + state.was = state.length; + state.mode = DIST; + /* falls through */ + case DIST: + for (;;) { + here = state.distcode[hold & ((1 << state.distbits) -1)];/*BITS(state.distbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if ((here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.distcode[last_val + + ((hold & ((1 << (last_bits + last_op)) -1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + if (here_op & 64) { + strm.msg = 'invalid distance code'; + state.mode = BAD; + break; + } + state.offset = here_val; + state.extra = (here_op) & 15; + state.mode = DISTEXT; + /* falls through */ + case DISTEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.offset += hold & ((1 << state.extra) -1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } +//#ifdef INFLATE_STRICT + if (state.offset > state.dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break; + } +//#endif + //Tracevv((stderr, "inflate: distance %u\n", state.offset)); + state.mode = MATCH; + /* falls through */ + case MATCH: + if (left === 0) { break inf_leave; } + copy = _out - left; + if (state.offset > copy) { /* copy from window */ + copy = state.offset - copy; + if (copy > state.whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break; + } +// (!) This block is disabled in zlib defailts, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// Trace((stderr, "inflate.c too far\n")); +// copy -= state.whave; +// if (copy > state.length) { copy = state.length; } +// if (copy > left) { copy = left; } +// left -= copy; +// state.length -= copy; +// do { +// output[put++] = 0; +// } while (--copy); +// if (state.length === 0) { state.mode = LEN; } +// break; +//#endif + } + if (copy > state.wnext) { + copy -= state.wnext; + from = state.wsize - copy; + } + else { + from = state.wnext - copy; + } + if (copy > state.length) { copy = state.length; } + from_source = state.window; + } + else { /* copy from output */ + from_source = output; + from = put - state.offset; + copy = state.length; + } + if (copy > left) { copy = left; } + left -= copy; + state.length -= copy; + do { + output[put++] = from_source[from++]; + } while (--copy); + if (state.length === 0) { state.mode = LEN; } + break; + case LIT: + if (left === 0) { break inf_leave; } + output[put++] = state.length; + left--; + state.mode = LEN; + break; + case CHECK: + if (state.wrap) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + // Use '|' insdead of '+' to make sure that result is signed + hold |= input[next++] << bits; + bits += 8; + } + //===// + _out -= left; + strm.total_out += _out; + state.total += _out; + if (_out) { + strm.adler = state.check = + /*UPDATE(state.check, put - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); + + } + _out = left; + // NB: crc32 stored as signed 32-bit int, ZSWAP32 returns signed too + if ((state.flags ? hold : ZSWAP32(hold)) !== state.check) { + strm.msg = 'incorrect data check'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: check matches trailer\n")); + } + state.mode = LENGTH; + /* falls through */ + case LENGTH: + if (state.wrap && state.flags) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.total & 0xffffffff)) { + strm.msg = 'incorrect length check'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: length matches trailer\n")); + } + state.mode = DONE; + /* falls through */ + case DONE: + ret = Z_STREAM_END; + break inf_leave; + case BAD: + ret = Z_DATA_ERROR; + break inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + /* falls through */ + default: + return Z_STREAM_ERROR; + } + } + + // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + + if (state.wsize || (_out !== strm.avail_out && state.mode < BAD && + (state.mode < CHECK || flush !== Z_FINISH))) { + if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) { + state.mode = MEM; + return Z_MEM_ERROR; + } + } + _in -= strm.avail_in; + _out -= strm.avail_out; + strm.total_in += _in; + strm.total_out += _out; + state.total += _out; + if (state.wrap && _out) { + strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); + } + strm.data_type = state.bits + (state.last ? 64 : 0) + + (state.mode === TYPE ? 128 : 0) + + (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); + if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { + ret = Z_BUF_ERROR; + } + return ret; + } + + function inflateEnd(strm) { + + if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { + return Z_STREAM_ERROR; + } + + var state = strm.state; + if (state.window) { + state.window = null; + } + strm.state = null; + return Z_OK; + } + + function inflateGetHeader(strm, head) { + var state; + + /* check state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } + + /* save header structure */ + state.head = head; + head.done = false; + return Z_OK; + } + + + exports.inflateReset = inflateReset; + exports.inflateReset2 = inflateReset2; + exports.inflateResetKeep = inflateResetKeep; + exports.inflateInit = inflateInit; + exports.inflateInit2 = inflateInit2; + exports.inflate = inflate; + exports.inflateEnd = inflateEnd; + exports.inflateGetHeader = inflateGetHeader; + exports.inflateInfo = 'pako inflate (from Nodeca project)'; + + /* Not implemented +exports.inflateCopy = inflateCopy; +exports.inflateGetDictionary = inflateGetDictionary; +exports.inflateMark = inflateMark; +exports.inflatePrime = inflatePrime; +exports.inflateSetDictionary = inflateSetDictionary; +exports.inflateSync = inflateSync; +exports.inflateSyncPoint = inflateSyncPoint; +exports.inflateUndermine = inflateUndermine; +*/ + },{"../utils/common":27,"./adler32":29,"./crc32":31,"./inffast":34,"./inftrees":36}],36:[function(_dereq_,module,exports){ + 'use strict'; + + + var utils = _dereq_('../utils/common'); + + var MAXBITS = 15; + var ENOUGH_LENS = 852; + var ENOUGH_DISTS = 592; +//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + + var CODES = 0; + var LENS = 1; + var DISTS = 2; + + var lbase = [ /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 + ]; + + var lext = [ /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 + ]; + + var dbase = [ /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0 + ]; + + var dext = [ /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64 + ]; + + module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) + { + var bits = opts.bits; + //here = opts.here; /* table entry for duplication */ + + var len = 0; /* a code's length in bits */ + var sym = 0; /* index of code symbols */ + var min = 0, max = 0; /* minimum and maximum code lengths */ + var root = 0; /* number of index bits for root table */ + var curr = 0; /* number of index bits for current table */ + var drop = 0; /* code bits to drop for sub-table */ + var left = 0; /* number of prefix codes available */ + var used = 0; /* code entries in table used */ + var huff = 0; /* Huffman code */ + var incr; /* for incrementing code, index */ + var fill; /* index for replicating entries */ + var low; /* low bits for current root entry */ + var mask; /* mask for low root bits */ + var next; /* next available space in table */ + var base = null; /* base value table to use */ + var base_index = 0; +// var shoextra; /* extra bits table to use */ + var end; /* use base and extra for symbol > end */ + var count = new utils.Buf16(MAXBITS+1); //[MAXBITS+1]; /* number of codes of each length */ + var offs = new utils.Buf16(MAXBITS+1); //[MAXBITS+1]; /* offsets in table for each length */ + var extra = null; + var extra_index = 0; + + var here_bits, here_op, here_val; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) { + count[len] = 0; + } + for (sym = 0; sym < codes; sym++) { + count[lens[lens_index + sym]]++; + } + + /* bound code lengths, force root to be within code lengths */ + root = bits; + for (max = MAXBITS; max >= 1; max--) { + if (count[max] !== 0) { break; } + } + if (root > max) { + root = max; + } + if (max === 0) { /* no symbols to code at all */ + //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ + //table.bits[opts.table_index] = 1; //here.bits = (var char)1; + //table.val[opts.table_index++] = 0; //here.val = (var short)0; + table[table_index++] = (1 << 24) | (64 << 16) | 0; + + + //table.op[opts.table_index] = 64; + //table.bits[opts.table_index] = 1; + //table.val[opts.table_index++] = 0; + table[table_index++] = (1 << 24) | (64 << 16) | 0; + + opts.bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) { + if (count[min] !== 0) { break; } + } + if (root < min) { + root = min; + } + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) { + return -1; + } /* over-subscribed */ + } + if (left > 0 && (type === CODES || max !== 1)) { + return -1; /* incomplete set */ + } + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) { + offs[len + 1] = offs[len] + count[len]; + } + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) { + if (lens[lens_index + sym] !== 0) { + work[offs[lens[lens_index + sym]]++] = sym; + } + } + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + // poor man optimization - use if-else instead of switch, + // to avoid deopts in old v8 + if (type === CODES) { + base = extra = work; /* dummy value--not used */ + end = 19; + } else if (type === LENS) { + base = lbase; + base_index -= 257; + extra = lext; + extra_index -= 257; + end = 256; + } else { /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize opts for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = table_index; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = -1; /* trigger new sub-table when len > root */ + used = 1 << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type === LENS && used > ENOUGH_LENS) || + (type === DISTS && used > ENOUGH_DISTS)) { + return 1; + } + + var i=0; + /* process all codes and make table entries */ + for (;;) { + i++; + /* create table entry */ + here_bits = len - drop; + if (work[sym] < end) { + here_op = 0; + here_val = work[sym]; + } + else if (work[sym] > end) { + here_op = extra[extra_index + work[sym]]; + here_val = base[base_index + work[sym]]; + } + else { + here_op = 32 + 64; /* end of block */ + here_val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1 << (len - drop); + fill = 1 << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0; + } while (fill !== 0); + + /* backwards increment the len-bit code huff */ + incr = 1 << (len - 1); + while (huff & incr) { + incr >>= 1; + } + if (incr !== 0) { + huff &= incr - 1; + huff += incr; + } else { + huff = 0; + } + + /* go to next symbol, update count, len */ + sym++; + if (--count[len] === 0) { + if (len === max) { break; } + len = lens[lens_index + work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) !== low) { + /* if first time, transition to sub-tables */ + if (drop === 0) { + drop = root; + } + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = 1 << curr; + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) { break; } + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1 << curr; + if ((type === LENS && used > ENOUGH_LENS) || + (type === DISTS && used > ENOUGH_DISTS)) { + return 1; + } + + /* point entry in root table to sub-table */ + low = huff & mask; + /*table.op[low] = curr; + table.bits[low] = root; + table.val[low] = next - opts.table_index;*/ + table[low] = (root << 24) | (curr << 16) | (next - table_index) |0; + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff !== 0) { + //table.op[next + huff] = 64; /* invalid code marker */ + //table.bits[next + huff] = len - drop; + //table.val[next + huff] = 0; + table[next + huff] = ((len - drop) << 24) | (64 << 16) |0; + } + + /* set return parameters */ + //opts.table_index += used; + opts.bits = root; + return 0; + }; + + },{"../utils/common":27}],37:[function(_dereq_,module,exports){ + 'use strict'; + + module.exports = { + '2': 'need dictionary', /* Z_NEED_DICT 2 */ + '1': 'stream end', /* Z_STREAM_END 1 */ + '0': '', /* Z_OK 0 */ + '-1': 'file error', /* Z_ERRNO (-1) */ + '-2': 'stream error', /* Z_STREAM_ERROR (-2) */ + '-3': 'data error', /* Z_DATA_ERROR (-3) */ + '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */ + '-5': 'buffer error', /* Z_BUF_ERROR (-5) */ + '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ + }; + },{}],38:[function(_dereq_,module,exports){ + 'use strict'; + + + var utils = _dereq_('../utils/common'); + + /* Public constants ==========================================================*/ + /* ===========================================================================*/ + + +//var Z_FILTERED = 1; +//var Z_HUFFMAN_ONLY = 2; +//var Z_RLE = 3; + var Z_FIXED = 4; +//var Z_DEFAULT_STRATEGY = 0; + + /* Possible values of the data_type field (though see inflate()) */ + var Z_BINARY = 0; + var Z_TEXT = 1; +//var Z_ASCII = 1; // = Z_TEXT + var Z_UNKNOWN = 2; + + /*============================================================================*/ + + + function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } } + +// From zutil.h + + var STORED_BLOCK = 0; + var STATIC_TREES = 1; + var DYN_TREES = 2; + /* The three kinds of block type */ + + var MIN_MATCH = 3; + var MAX_MATCH = 258; + /* The minimum and maximum match lengths */ + +// From deflate.h + /* =========================================================================== + * Internal compression state. + */ + + var LENGTH_CODES = 29; + /* number of length codes, not counting the special END_BLOCK code */ + + var LITERALS = 256; + /* number of literal bytes 0..255 */ + + var L_CODES = LITERALS + 1 + LENGTH_CODES; + /* number of Literal or Length codes, including the END_BLOCK code */ + + var D_CODES = 30; + /* number of distance codes */ + + var BL_CODES = 19; + /* number of codes used to transfer the bit lengths */ + + var HEAP_SIZE = 2*L_CODES + 1; + /* maximum heap size */ + + var MAX_BITS = 15; + /* All codes must not exceed MAX_BITS bits */ + + var Buf_size = 16; + /* size of bit buffer in bi_buf */ + + + /* =========================================================================== + * Constants + */ + + var MAX_BL_BITS = 7; + /* Bit length codes must not exceed MAX_BL_BITS bits */ + + var END_BLOCK = 256; + /* end of block literal code */ + + var REP_3_6 = 16; + /* repeat previous bit length 3-6 times (2 bits of repeat count) */ + + var REPZ_3_10 = 17; + /* repeat a zero length 3-10 times (3 bits of repeat count) */ + + var REPZ_11_138 = 18; + /* repeat a zero length 11-138 times (7 bits of repeat count) */ + + var extra_lbits = /* extra bits for each length code */ + [0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0]; + + var extra_dbits = /* extra bits for each distance code */ + [0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13]; + + var extra_blbits = /* extra bits for each bit length code */ + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7]; + + var bl_order = + [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]; + /* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + + /* =========================================================================== + * Local data. These are initialized only once. + */ + +// We pre-fill arrays with 0 to avoid uninitialized gaps + + var DIST_CODE_LEN = 512; /* see definition of array dist_code below */ + +// !!!! Use flat array insdead of structure, Freq = i*2, Len = i*2+1 + var static_ltree = new Array((L_CODES+2) * 2); + zero(static_ltree); + /* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + + var static_dtree = new Array(D_CODES * 2); + zero(static_dtree); + /* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + + var _dist_code = new Array(DIST_CODE_LEN); + zero(_dist_code); + /* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + + var _length_code = new Array(MAX_MATCH-MIN_MATCH+1); + zero(_length_code); + /* length code for each normalized match length (0 == MIN_MATCH) */ + + var base_length = new Array(LENGTH_CODES); + zero(base_length); + /* First normalized length for each code (0 = MIN_MATCH) */ + + var base_dist = new Array(D_CODES); + zero(base_dist); + /* First normalized distance for each code (0 = distance of 1) */ + + + var StaticTreeDesc = function (static_tree, extra_bits, extra_base, elems, max_length) { + + this.static_tree = static_tree; /* static tree or NULL */ + this.extra_bits = extra_bits; /* extra bits for each code or NULL */ + this.extra_base = extra_base; /* base index for extra_bits */ + this.elems = elems; /* max number of elements in the tree */ + this.max_length = max_length; /* max bit length for the codes */ + + // show if `static_tree` has data or dummy - needed for monomorphic objects + this.has_stree = static_tree && static_tree.length; + }; + + + var static_l_desc; + var static_d_desc; + var static_bl_desc; + + + var TreeDesc = function(dyn_tree, stat_desc) { + this.dyn_tree = dyn_tree; /* the dynamic tree */ + this.max_code = 0; /* largest code with non zero frequency */ + this.stat_desc = stat_desc; /* the corresponding static tree */ + }; + + + + function d_code(dist) { + return dist < 256 ? _dist_code[dist] : _dist_code[256 + (dist >>> 7)]; + } + + + /* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ + function put_short (s, w) { +// put_byte(s, (uch)((w) & 0xff)); +// put_byte(s, (uch)((ush)(w) >> 8)); + s.pending_buf[s.pending++] = (w) & 0xff; + s.pending_buf[s.pending++] = (w >>> 8) & 0xff; + } + + + /* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ + function send_bits(s, value, length) { + if (s.bi_valid > (Buf_size - length)) { + s.bi_buf |= (value << s.bi_valid) & 0xffff; + put_short(s, s.bi_buf); + s.bi_buf = value >> (Buf_size - s.bi_valid); + s.bi_valid += length - Buf_size; + } else { + s.bi_buf |= (value << s.bi_valid) & 0xffff; + s.bi_valid += length; + } + } + + + function send_code(s, c, tree) { + send_bits(s, tree[c*2]/*.Code*/, tree[c*2 + 1]/*.Len*/); + } + + + /* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ + function bi_reverse(code, len) { + var res = 0; + do { + res |= code & 1; + code >>>= 1; + res <<= 1; + } while (--len > 0); + return res >>> 1; + } + + + /* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ + function bi_flush(s) { + if (s.bi_valid === 16) { + put_short(s, s.bi_buf); + s.bi_buf = 0; + s.bi_valid = 0; + + } else if (s.bi_valid >= 8) { + s.pending_buf[s.pending++] = s.bi_buf & 0xff; + s.bi_buf >>= 8; + s.bi_valid -= 8; + } + } + + + /* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ + function gen_bitlen(s, desc) +// deflate_state *s; +// tree_desc *desc; /* the tree descriptor */ + { + var tree = desc.dyn_tree; + var max_code = desc.max_code; + var stree = desc.stat_desc.static_tree; + var has_stree = desc.stat_desc.has_stree; + var extra = desc.stat_desc.extra_bits; + var base = desc.stat_desc.extra_base; + var max_length = desc.stat_desc.max_length; + var h; /* heap index */ + var n, m; /* iterate over the tree elements */ + var bits; /* bit length */ + var xbits; /* extra bits */ + var f; /* frequency */ + var overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) { + s.bl_count[bits] = 0; + } + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s.heap[s.heap_max]*2 + 1]/*.Len*/ = 0; /* root of the heap */ + + for (h = s.heap_max+1; h < HEAP_SIZE; h++) { + n = s.heap[h]; + bits = tree[tree[n*2 +1]/*.Dad*/ * 2 + 1]/*.Len*/ + 1; + if (bits > max_length) { + bits = max_length; + overflow++; + } + tree[n*2 + 1]/*.Len*/ = bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) { continue; } /* not a leaf node */ + + s.bl_count[bits]++; + xbits = 0; + if (n >= base) { + xbits = extra[n-base]; + } + f = tree[n * 2]/*.Freq*/; + s.opt_len += f * (bits + xbits); + if (has_stree) { + s.static_len += f * (stree[n*2 + 1]/*.Len*/ + xbits); + } + } + if (overflow === 0) { return; } + + // Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s.bl_count[bits] === 0) { bits--; } + s.bl_count[bits]--; /* move one leaf down the tree */ + s.bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s.bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits !== 0; bits--) { + n = s.bl_count[bits]; + while (n !== 0) { + m = s.heap[--h]; + if (m > max_code) { continue; } + if (tree[m*2 + 1]/*.Len*/ !== bits) { + // Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s.opt_len += (bits - tree[m*2 + 1]/*.Len*/)*tree[m*2]/*.Freq*/; + tree[m*2 + 1]/*.Len*/ = bits; + } + n--; + } + } + } + + + /* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ + function gen_codes(tree, max_code, bl_count) +// ct_data *tree; /* the tree to decorate */ +// int max_code; /* largest code with non zero frequency */ +// ushf *bl_count; /* number of codes at each bit length */ + { + var next_code = new Array(MAX_BITS+1); /* next code value for each bit length */ + var code = 0; /* running code value */ + var bits; /* bit index */ + var n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + //Assert (code + bl_count[MAX_BITS]-1 == (1< length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = code; + } + } + //Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) { + bl_count[bits] = 0; + } + + n = 0; + while (n <= 143) { + static_ltree[n*2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + while (n <= 255) { + static_ltree[n*2 + 1]/*.Len*/ = 9; + n++; + bl_count[9]++; + } + while (n <= 279) { + static_ltree[n*2 + 1]/*.Len*/ = 7; + n++; + bl_count[7]++; + } + while (n <= 287) { + static_ltree[n*2 + 1]/*.Len*/ = 8; + n++; + bl_count[8]++; + } + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes(static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n*2 + 1]/*.Len*/ = 5; + static_dtree[n*2]/*.Code*/ = bi_reverse(n, 5); + } + + // Now data ready and we can init static trees + static_l_desc = new StaticTreeDesc(static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS); + static_d_desc = new StaticTreeDesc(static_dtree, extra_dbits, 0, D_CODES, MAX_BITS); + static_bl_desc =new StaticTreeDesc(new Array(0), extra_blbits, 0, BL_CODES, MAX_BL_BITS); + + //static_init_done = true; + } + + + /* =========================================================================== + * Initialize a new block. + */ + function init_block(s) { + var n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) { s.dyn_ltree[n*2]/*.Freq*/ = 0; } + for (n = 0; n < D_CODES; n++) { s.dyn_dtree[n*2]/*.Freq*/ = 0; } + for (n = 0; n < BL_CODES; n++) { s.bl_tree[n*2]/*.Freq*/ = 0; } + + s.dyn_ltree[END_BLOCK*2]/*.Freq*/ = 1; + s.opt_len = s.static_len = 0; + s.last_lit = s.matches = 0; + } + + + /* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ + function bi_windup(s) + { + if (s.bi_valid > 8) { + put_short(s, s.bi_buf); + } else if (s.bi_valid > 0) { + //put_byte(s, (Byte)s->bi_buf); + s.pending_buf[s.pending++] = s.bi_buf; + } + s.bi_buf = 0; + s.bi_valid = 0; + } + + /* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ + function copy_block(s, buf, len, header) +//DeflateState *s; +//charf *buf; /* the input data */ +//unsigned len; /* its length */ +//int header; /* true if block header must be written */ + { + bi_windup(s); /* align on byte boundary */ + + if (header) { + put_short(s, len); + put_short(s, ~len); + } +// while (len--) { +// put_byte(s, *buf++); +// } + utils.arraySet(s.pending_buf, s.window, buf, len, s.pending); + s.pending += len; + } + + /* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ + function smaller(tree, n, m, depth) { + var _n2 = n*2; + var _m2 = m*2; + return (tree[_n2]/*.Freq*/ < tree[_m2]/*.Freq*/ || + (tree[_n2]/*.Freq*/ === tree[_m2]/*.Freq*/ && depth[n] <= depth[m])); + } + + /* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ + function pqdownheap(s, tree, k) +// deflate_state *s; +// ct_data *tree; /* the tree to restore */ +// int k; /* node to move down */ + { + var v = s.heap[k]; + var j = k << 1; /* left son of k */ + while (j <= s.heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s.heap_len && + smaller(tree, s.heap[j+1], s.heap[j], s.depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s.heap[j], s.depth)) { break; } + + /* Exchange v with the smallest son */ + s.heap[k] = s.heap[j]; + k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s.heap[k] = v; + } + + +// inlined manually +// var SMALLEST = 1; + + /* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ + function compress_block(s, ltree, dtree) +// deflate_state *s; +// const ct_data *ltree; /* literal tree */ +// const ct_data *dtree; /* distance tree */ + { + var dist; /* distance of matched string */ + var lc; /* match length or unmatched char (if dist == 0) */ + var lx = 0; /* running index in l_buf */ + var code; /* the code to send */ + var extra; /* number of extra bits to send */ + + if (s.last_lit !== 0) { + do { + dist = (s.pending_buf[s.d_buf + lx*2] << 8) | (s.pending_buf[s.d_buf + lx*2 + 1]); + lc = s.pending_buf[s.l_buf + lx]; + lx++; + + if (dist === 0) { + send_code(s, lc, ltree); /* send a literal byte */ + //Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra !== 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + //Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra !== 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + //Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + // "pendingBuf overflow"); + + } while (lx < s.last_lit); + } + + send_code(s, END_BLOCK, ltree); + } + + + /* =========================================================================== + * Construct one Huffman tree and assigns the code bit strings and lengths. + * Update the total bit length for the current block. + * IN assertion: the field freq is set for all tree elements. + * OUT assertions: the fields len and code are set to the optimal bit length + * and corresponding code. The length opt_len is updated; static_len is + * also updated if stree is not null. The field max_code is set. + */ + function build_tree(s, desc) +// deflate_state *s; +// tree_desc *desc; /* the tree descriptor */ + { + var tree = desc.dyn_tree; + var stree = desc.stat_desc.static_tree; + var has_stree = desc.stat_desc.has_stree; + var elems = desc.stat_desc.elems; + var n, m; /* iterate over heap elements */ + var max_code = -1; /* largest code with non zero frequency */ + var node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s.heap_len = 0; + s.heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n * 2]/*.Freq*/ !== 0) { + s.heap[++s.heap_len] = max_code = n; + s.depth[n] = 0; + + } else { + tree[n*2 + 1]/*.Len*/ = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s.heap_len < 2) { + node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0); + tree[node * 2]/*.Freq*/ = 1; + s.depth[node] = 0; + s.opt_len--; + + if (has_stree) { + s.static_len -= stree[node*2 + 1]/*.Len*/; + } + /* node is 0 or 1 so it does not have extra bits */ + } + desc.max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = (s.heap_len >> 1/*int /2*/); n >= 1; n--) { pqdownheap(s, tree, n); } + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + //pqremove(s, tree, n); /* n = node of least frequency */ + /*** pqremove ***/ + n = s.heap[1/*SMALLEST*/]; + s.heap[1/*SMALLEST*/] = s.heap[s.heap_len--]; + pqdownheap(s, tree, 1/*SMALLEST*/); + /***/ + + m = s.heap[1/*SMALLEST*/]; /* m = node of next least frequency */ + + s.heap[--s.heap_max] = n; /* keep the nodes sorted by frequency */ + s.heap[--s.heap_max] = m; + + /* Create a new node father of n and m */ + tree[node * 2]/*.Freq*/ = tree[n * 2]/*.Freq*/ + tree[m * 2]/*.Freq*/; + s.depth[node] = (s.depth[n] >= s.depth[m] ? s.depth[n] : s.depth[m]) + 1; + tree[n*2 + 1]/*.Dad*/ = tree[m*2 + 1]/*.Dad*/ = node; + + /* and insert the new node in the heap */ + s.heap[1/*SMALLEST*/] = node++; + pqdownheap(s, tree, 1/*SMALLEST*/); + + } while (s.heap_len >= 2); + + s.heap[--s.heap_max] = s.heap[1/*SMALLEST*/]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes(tree, max_code, s.bl_count); + } + + + /* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ + function scan_tree(s, tree, max_code) +// deflate_state *s; +// ct_data *tree; /* the tree to be scanned */ +// int max_code; /* and its largest code of non zero frequency */ + { + var n; /* iterates over all tree elements */ + var prevlen = -1; /* last emitted length */ + var curlen; /* length of current code */ + + var nextlen = tree[0*2 + 1]/*.Len*/; /* length of next code */ + + var count = 0; /* repeat count of the current code */ + var max_count = 7; /* max repeat count */ + var min_count = 4; /* min repeat count */ + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + tree[(max_code+1)*2 + 1]/*.Len*/ = 0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n+1)*2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + s.bl_tree[curlen * 2]/*.Freq*/ += count; + + } else if (curlen !== 0) { + + if (curlen !== prevlen) { s.bl_tree[curlen * 2]/*.Freq*/++; } + s.bl_tree[REP_3_6*2]/*.Freq*/++; + + } else if (count <= 10) { + s.bl_tree[REPZ_3_10*2]/*.Freq*/++; + + } else { + s.bl_tree[REPZ_11_138*2]/*.Freq*/++; + } + + count = 0; + prevlen = curlen; + + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } + } + + + /* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ + function send_tree(s, tree, max_code) +// deflate_state *s; +// ct_data *tree; /* the tree to be scanned */ +// int max_code; /* and its largest code of non zero frequency */ + { + var n; /* iterates over all tree elements */ + var prevlen = -1; /* last emitted length */ + var curlen; /* length of current code */ + + var nextlen = tree[0*2 + 1]/*.Len*/; /* length of next code */ + + var count = 0; /* repeat count of the current code */ + var max_count = 7; /* max repeat count */ + var min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen === 0) { + max_count = 138; + min_count = 3; + } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; + nextlen = tree[(n+1)*2 + 1]/*.Len*/; + + if (++count < max_count && curlen === nextlen) { + continue; + + } else if (count < min_count) { + do { send_code(s, curlen, s.bl_tree); } while (--count !== 0); + + } else if (curlen !== 0) { + if (curlen !== prevlen) { + send_code(s, curlen, s.bl_tree); + count--; + } + //Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s.bl_tree); + send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s.bl_tree); + send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s.bl_tree); + send_bits(s, count-11, 7); + } + + count = 0; + prevlen = curlen; + if (nextlen === 0) { + max_count = 138; + min_count = 3; + + } else if (curlen === nextlen) { + max_count = 6; + min_count = 3; + + } else { + max_count = 7; + min_count = 4; + } + } + } + + + /* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ + function build_bl_tree(s) { + var max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, s.dyn_ltree, s.l_desc.max_code); + scan_tree(s, s.dyn_dtree, s.d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, s.bl_desc); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s.bl_tree[bl_order[max_blindex]*2 + 1]/*.Len*/ !== 0) { + break; + } + } + /* Update opt_len to include the bit length tree and counts */ + s.opt_len += 3*(max_blindex+1) + 5+5+4; + //Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + // s->opt_len, s->static_len)); + + return max_blindex; + } + + + /* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ + function send_all_trees(s, lcodes, dcodes, blcodes) +// deflate_state *s; +// int lcodes, dcodes, blcodes; /* number of codes for each tree */ + { + var rank; /* index in bl_order */ + + //Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + //Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + // "too many codes"); + //Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + //Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s.bl_tree[bl_order[rank]*2 + 1]/*.Len*/, 3); + } + //Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_ltree, lcodes-1); /* literal tree */ + //Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, s.dyn_dtree, dcodes-1); /* distance tree */ + //Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); + } + + + /* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ + function detect_data_type(s) { + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + var black_mask = 0xf3ffc07f; + var n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>>= 1) { + if ((black_mask & 1) && (s.dyn_ltree[n*2]/*.Freq*/ !== 0)) { + return Z_BINARY; + } + } + + /* Check for textual ("white-listed") bytes. */ + if (s.dyn_ltree[9 * 2]/*.Freq*/ !== 0 || s.dyn_ltree[10 * 2]/*.Freq*/ !== 0 || + s.dyn_ltree[13 * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + for (n = 32; n < LITERALS; n++) { + if (s.dyn_ltree[n * 2]/*.Freq*/ !== 0) { + return Z_TEXT; + } + } + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; + } + + + var static_init_done = false; + + /* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ + function _tr_init(s) + { + + if (!static_init_done) { + tr_static_init(); + static_init_done = true; + } + + s.l_desc = new TreeDesc(s.dyn_ltree, static_l_desc); + s.d_desc = new TreeDesc(s.dyn_dtree, static_d_desc); + s.bl_desc = new TreeDesc(s.bl_tree, static_bl_desc); + + s.bi_buf = 0; + s.bi_valid = 0; + + /* Initialize the first block of the first file: */ + init_block(s); + } + + + /* =========================================================================== + * Send a stored block + */ + function _tr_stored_block(s, buf, stored_len, last) +//DeflateState *s; +//charf *buf; /* input block */ +//ulg stored_len; /* length of input block */ +//int last; /* one if this is the last block for a file */ + { + send_bits(s, (STORED_BLOCK<<1)+(last ? 1 : 0), 3); /* send block type */ + copy_block(s, buf, stored_len, true); /* with header */ + } + + + /* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + */ + function _tr_align(s) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); + bi_flush(s); + } + + + /* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ + function _tr_flush_block(s, buf, stored_len, last) +//DeflateState *s; +//charf *buf; /* input block, or NULL if too old */ +//ulg stored_len; /* length of input block */ +//int last; /* one if this is the last block for a file */ + { + var opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + var max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s.level > 0) { + + /* Check if the file is binary or text */ + if (s.strm.data_type === Z_UNKNOWN) { + s.strm.data_type = detect_data_type(s); + } + + /* Construct the literal and distance trees */ + build_tree(s, s.l_desc); + // Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + + build_tree(s, s.d_desc); + // Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + // s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s.opt_len+3+7) >>> 3; + static_lenb = (s.static_len+3+7) >>> 3; + + // Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + // opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + // s->last_lit)); + + if (static_lenb <= opt_lenb) { opt_lenb = static_lenb; } + + } else { + // Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + + if ((stored_len+4 <= opt_lenb) && (buf !== -1)) { + /* 4: two words for the lengths */ + + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + + } else if (s.strategy === Z_FIXED || static_lenb === opt_lenb) { + + send_bits(s, (STATIC_TREES<<1) + (last ? 1 : 0), 3); + compress_block(s, static_ltree, static_dtree); + + } else { + send_bits(s, (DYN_TREES<<1) + (last ? 1 : 0), 3); + send_all_trees(s, s.l_desc.max_code+1, s.d_desc.max_code+1, max_blindex+1); + compress_block(s, s.dyn_ltree, s.dyn_dtree); + } + // Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); + } + // Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + // s->compressed_len-7*last)); + } + + /* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ + function _tr_tally(s, dist, lc) +// deflate_state *s; +// unsigned dist; /* distance of matched string */ +// unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ + { + //var out_length, in_length, dcode; + + s.pending_buf[s.d_buf + s.last_lit * 2] = (dist >>> 8) & 0xff; + s.pending_buf[s.d_buf + s.last_lit * 2 + 1] = dist & 0xff; + + s.pending_buf[s.l_buf + s.last_lit] = lc & 0xff; + s.last_lit++; + + if (dist === 0) { + /* lc is the unmatched char */ + s.dyn_ltree[lc*2]/*.Freq*/++; + } else { + s.matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + //Assert((ush)dist < (ush)MAX_DIST(s) && + // (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + // (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s.dyn_ltree[(_length_code[lc]+LITERALS+1) * 2]/*.Freq*/++; + s.dyn_dtree[d_code(dist) * 2]/*.Freq*/++; + } + +// (!) This block is disabled in zlib defailts, +// don't enable it for binary compatibility + +//#ifdef TRUNCATE_BLOCK +// /* Try to guess if it is profitable to stop the current block here */ +// if ((s.last_lit & 0x1fff) === 0 && s.level > 2) { +// /* Compute an upper bound for the compressed length */ +// out_length = s.last_lit*8; +// in_length = s.strstart - s.block_start; +// +// for (dcode = 0; dcode < D_CODES; dcode++) { +// out_length += s.dyn_dtree[dcode*2]/*.Freq*/ * (5 + extra_dbits[dcode]); +// } +// out_length >>>= 3; +// //Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", +// // s->last_lit, in_length, out_length, +// // 100L - out_length*100L/in_length)); +// if (s.matches < (s.last_lit>>1)/*int /2*/ && out_length < (in_length>>1)/*int /2*/) { +// return true; +// } +// } +//#endif + + return (s.last_lit === s.lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ + } + + exports._tr_init = _tr_init; + exports._tr_stored_block = _tr_stored_block; + exports._tr_flush_block = _tr_flush_block; + exports._tr_tally = _tr_tally; + exports._tr_align = _tr_align; + },{"../utils/common":27}],39:[function(_dereq_,module,exports){ + 'use strict'; + + + function ZStream() { + /* next input byte */ + this.input = null; // JS specific, because we have no pointers + this.next_in = 0; + /* number of bytes available at input */ + this.avail_in = 0; + /* total number of input bytes read so far */ + this.total_in = 0; + /* next output byte should be put there */ + this.output = null; // JS specific, because we have no pointers + this.next_out = 0; + /* remaining free space at output */ + this.avail_out = 0; + /* total number of bytes output so far */ + this.total_out = 0; + /* last error message, NULL if no error */ + this.msg = ''/*Z_NULL*/; + /* not visible by applications */ + this.state = null; + /* best guess about the data type: binary or text */ + this.data_type = 2/*Z_UNKNOWN*/; + /* adler32 value of the uncompressed data */ + this.adler = 0; + } + + module.exports = ZStream; + },{}]},{},[9]) +(9) +}));/*---------split--------*//*! xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ +/* vim: set ts=2: */ +/*exported XLSX */ +/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */ +var XLSX = {}; +function make_xlsx_lib(XLSX){ + XLSX.version = '0.14.3'; + var current_codepage = 1200, current_ansi = 1252; + /*global cptable:true, window */ + if(typeof module !== "undefined" && typeof require !== 'undefined') { + if(typeof cptable === 'undefined') { + if(typeof global !== 'undefined') global.cptable = undefined; + else if(typeof window !== 'undefined') window.cptable = undefined; + } + } + + var VALID_ANSI = [ 874, 932, 936, 949, 950 ]; + for(var i = 0; i <= 8; ++i) VALID_ANSI.push(1250 + i); + /* ECMA-376 Part I 18.4.1 charset to codepage mapping */ + var CS2CP = ({ + 0: 1252, /* ANSI */ + 1: 65001, /* DEFAULT */ + 2: 65001, /* SYMBOL */ + 77: 10000, /* MAC */ + 128: 932, /* SHIFTJIS */ + 129: 949, /* HANGUL */ + 130: 1361, /* JOHAB */ + 134: 936, /* GB2312 */ + 136: 950, /* CHINESEBIG5 */ + 161: 1253, /* GREEK */ + 162: 1254, /* TURKISH */ + 163: 1258, /* VIETNAMESE */ + 177: 1255, /* HEBREW */ + 178: 1256, /* ARABIC */ + 186: 1257, /* BALTIC */ + 204: 1251, /* RUSSIAN */ + 222: 874, /* THAI */ + 238: 1250, /* EASTEUROPE */ + 255: 1252, /* OEM */ + 69: 6969 /* MISC */ + }); + + var set_ansi = function(cp) { if(VALID_ANSI.indexOf(cp) == -1) return; current_ansi = CS2CP[0] = cp; }; + function reset_ansi() { set_ansi(1252); } + + var set_cp = function(cp) { current_codepage = cp; set_ansi(cp); }; + function reset_cp() { set_cp(1200); reset_ansi(); } + + function char_codes(data) { var o = []; for(var i = 0, len = data.length; i < len; ++i) o[i] = data.charCodeAt(i); return o; } + + function utf16leread(data) { + var o = []; + for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i) + (data.charCodeAt(2*i+1)<<8)); + return o.join(""); + } + function utf16beread(data) { + var o = []; + for(var i = 0; i < (data.length>>1); ++i) o[i] = String.fromCharCode(data.charCodeAt(2*i+1) + (data.charCodeAt(2*i)<<8)); + return o.join(""); + } + + var debom = function(data) { + var c1 = data.charCodeAt(0), c2 = data.charCodeAt(1); + if(c1 == 0xFF && c2 == 0xFE) return utf16leread(data.slice(2)); + if(c1 == 0xFE && c2 == 0xFF) return utf16beread(data.slice(2)); + if(c1 == 0xFEFF) return data.slice(1); + return data; + }; + + var _getchar = function _gc1(x) { return String.fromCharCode(x); }; + if(typeof cptable !== 'undefined') { + set_cp = function(cp) { current_codepage = cp; }; + debom = function(data) { + if(data.charCodeAt(0) === 0xFF && data.charCodeAt(1) === 0xFE) { return cptable.utils.decode(1200, char_codes(data.slice(2))); } + return data; + }; + _getchar = function _gc2(x) { + if(current_codepage === 1200) return String.fromCharCode(x); + return cptable.utils.decode(current_codepage, [x&255,x>>8])[0]; + }; + } + var DENSE = null; + var DIF_XL = true; + var Base64 = (function make_b64(){ + var map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + return { + encode: function(input) { + var o = ""; + var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0; + for(var i = 0; i < input.length; ) { + c1 = input.charCodeAt(i++); + e1 = (c1 >> 2); + + c2 = input.charCodeAt(i++); + e2 = ((c1 & 3) << 4) | (c2 >> 4); + + c3 = input.charCodeAt(i++); + e3 = ((c2 & 15) << 2) | (c3 >> 6); + e4 = (c3 & 63); + if (isNaN(c2)) { e3 = e4 = 64; } + else if (isNaN(c3)) { e4 = 64; } + o += map.charAt(e1) + map.charAt(e2) + map.charAt(e3) + map.charAt(e4); + } + return o; + }, + decode: function b64_decode(input) { + var o = ""; + var c1=0, c2=0, c3=0, e1=0, e2=0, e3=0, e4=0; + input = input.replace(/[^\w\+\/\=]/g, ""); + for(var i = 0; i < input.length;) { + e1 = map.indexOf(input.charAt(i++)); + e2 = map.indexOf(input.charAt(i++)); + c1 = (e1 << 2) | (e2 >> 4); + o += String.fromCharCode(c1); + + e3 = map.indexOf(input.charAt(i++)); + c2 = ((e2 & 15) << 4) | (e3 >> 2); + if (e3 !== 64) { o += String.fromCharCode(c2); } + + e4 = map.indexOf(input.charAt(i++)); + c3 = ((e3 & 3) << 6) | e4; + if (e4 !== 64) { o += String.fromCharCode(c3); } + } + return o; + } + }; + })(); + var has_buf = (typeof Buffer !== 'undefined' && typeof process !== 'undefined' && typeof process.versions !== 'undefined' && !!process.versions.node); + + var Buffer_from = function(){}; + + if(typeof Buffer !== 'undefined') { + var nbfs = !Buffer.from; + if(!nbfs) try { Buffer.from("foo", "utf8"); } catch(e) { nbfs = true; } + Buffer_from = nbfs ? function(buf, enc) { return (enc) ? new Buffer(buf, enc) : new Buffer(buf); } : Buffer.from.bind(Buffer); + // $FlowIgnore + if(!Buffer.alloc) Buffer.alloc = function(n) { return new Buffer(n); }; + // $FlowIgnore + if(!Buffer.allocUnsafe) Buffer.allocUnsafe = function(n) { return new Buffer(n); }; + } + + function new_raw_buf(len) { + /* jshint -W056 */ + return has_buf ? Buffer.alloc(len) : new Array(len); + /* jshint +W056 */ + } + + function new_unsafe_buf(len) { + /* jshint -W056 */ + return has_buf ? Buffer.allocUnsafe(len) : new Array(len); + /* jshint +W056 */ + } + + var s2a = function s2a(s) { + // $FlowIgnore + if(has_buf) return Buffer_from(s, "binary"); + return s.split("").map(function(x){ return x.charCodeAt(0) & 0xff; }); + }; + + function s2ab(s) { + if(typeof ArrayBuffer === 'undefined') return s2a(s); + var buf = new ArrayBuffer(s.length), view = new Uint8Array(buf); + for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF; + return buf; + } + + function a2s(data) { + if(Array.isArray(data)) return data.map(_chr).join(""); + var o = []; for(var i = 0; i < data.length; ++i) o[i] = _chr(data[i]); return o.join(""); + } + + function a2u(data) { + if(typeof Uint8Array === 'undefined') throw new Error("Unsupported"); + return new Uint8Array(data); + } + + function ab2a(data) { + if(typeof ArrayBuffer == 'undefined') throw new Error("Unsupported"); + if(data instanceof ArrayBuffer) return ab2a(new Uint8Array(data)); + var o = new Array(data.length); + for(var i = 0; i < data.length; ++i) o[i] = data[i]; + return o; + } + + var bconcat = function(bufs) { return [].concat.apply([], bufs); }; + + var chr0 = /\u0000/g, chr1 = /[\u0001-\u0006]/g; + /* ssf.js (C) 2013-present SheetJS -- http://sheetjs.com */ + /*jshint -W041 */ + var SSF = ({}); + var make_ssf = function make_ssf(SSF){ + SSF.version = '0.10.2'; + function _strrev(x) { var o = "", i = x.length-1; while(i>=0) o += x.charAt(i--); return o; } + function fill(c,l) { var o = ""; while(o.length < l) o+=c; return o; } + function pad0(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;} + function pad_(v,d){var t=""+v;return t.length>=d?t:fill(' ',d-t.length)+t;} + function rpad_(v,d){var t=""+v; return t.length>=d?t:t+fill(' ',d-t.length);} + function pad0r1(v,d){var t=""+Math.round(v); return t.length>=d?t:fill('0',d-t.length)+t;} + function pad0r2(v,d){var t=""+v; return t.length>=d?t:fill('0',d-t.length)+t;} + var p2_32 = Math.pow(2,32); + function pad0r(v,d){if(v>p2_32||v<-p2_32) return pad0r1(v,d); var i = Math.round(v); return pad0r2(i,d); } + function isgeneral(s, i) { i = i || 0; return s.length >= 7 + i && (s.charCodeAt(i)|32) === 103 && (s.charCodeAt(i+1)|32) === 101 && (s.charCodeAt(i+2)|32) === 110 && (s.charCodeAt(i+3)|32) === 101 && (s.charCodeAt(i+4)|32) === 114 && (s.charCodeAt(i+5)|32) === 97 && (s.charCodeAt(i+6)|32) === 108; } + var days = [ + ['Sun', 'Sunday'], + ['Mon', 'Monday'], + ['Tue', 'Tuesday'], + ['Wed', 'Wednesday'], + ['Thu', 'Thursday'], + ['Fri', 'Friday'], + ['Sat', 'Saturday'] + ]; + var months = [ + ['J', 'Jan', 'January'], + ['F', 'Feb', 'February'], + ['M', 'Mar', 'March'], + ['A', 'Apr', 'April'], + ['M', 'May', 'May'], + ['J', 'Jun', 'June'], + ['J', 'Jul', 'July'], + ['A', 'Aug', 'August'], + ['S', 'Sep', 'September'], + ['O', 'Oct', 'October'], + ['N', 'Nov', 'November'], + ['D', 'Dec', 'December'] + ]; + function init_table(t) { + t[0]= 'General'; + t[1]= '0'; + t[2]= '0.00'; + t[3]= '#,##0'; + t[4]= '#,##0.00'; + t[9]= '0%'; + t[10]= '0.00%'; + t[11]= '0.00E+00'; + t[12]= '# ?/?'; + t[13]= '# ??/??'; + t[14]= 'm/d/yy'; + t[15]= 'd-mmm-yy'; + t[16]= 'd-mmm'; + t[17]= 'mmm-yy'; + t[18]= 'h:mm AM/PM'; + t[19]= 'h:mm:ss AM/PM'; + t[20]= 'h:mm'; + t[21]= 'h:mm:ss'; + t[22]= 'm/d/yy h:mm'; + t[37]= '#,##0 ;(#,##0)'; + t[38]= '#,##0 ;[Red](#,##0)'; + t[39]= '#,##0.00;(#,##0.00)'; + t[40]= '#,##0.00;[Red](#,##0.00)'; + t[45]= 'mm:ss'; + t[46]= '[h]:mm:ss'; + t[47]= 'mmss.0'; + t[48]= '##0.0E+0'; + t[49]= '@'; + t[56]= '"上午/下午 "hh"時"mm"分"ss"秒 "'; + t[65535]= 'General'; + } + + var table_fmt = {}; + init_table(table_fmt); + function frac(x, D, mixed) { + var sgn = x < 0 ? -1 : 1; + var B = x * sgn; + var P_2 = 0, P_1 = 1, P = 0; + var Q_2 = 1, Q_1 = 0, Q = 0; + var A = Math.floor(B); + while(Q_1 < D) { + A = Math.floor(B); + P = A * P_1 + P_2; + Q = A * Q_1 + Q_2; + if((B - A) < 0.00000005) break; + B = 1 / (B - A); + P_2 = P_1; P_1 = P; + Q_2 = Q_1; Q_1 = Q; + } + if(Q > D) { if(Q_1 > D) { Q = Q_2; P = P_2; } else { Q = Q_1; P = P_1; } } + if(!mixed) return [0, sgn * P, Q]; + var q = Math.floor(sgn * P/Q); + return [q, sgn*P - q*Q, Q]; + } + function parse_date_code(v,opts,b2) { + if(v > 2958465 || v < 0) return null; + var date = (v|0), time = Math.floor(86400 * (v - date)), dow=0; + var dout=[]; + var out={D:date, T:time, u:86400*(v-date)-time,y:0,m:0,d:0,H:0,M:0,S:0,q:0}; + if(Math.abs(out.u) < 1e-6) out.u = 0; + if(opts && opts.date1904) date += 1462; + if(out.u > 0.9999) { + out.u = 0; + if(++time == 86400) { out.T = time = 0; ++date; ++out.D; } + } + if(date === 60) {dout = b2 ? [1317,10,29] : [1900,2,29]; dow=3;} + else if(date === 0) {dout = b2 ? [1317,8,29] : [1900,1,0]; dow=6;} + else { + if(date > 60) --date; + /* 1 = Jan 1 1900 in Gregorian */ + var d = new Date(1900, 0, 1); + d.setDate(d.getDate() + date - 1); + dout = [d.getFullYear(), d.getMonth()+1,d.getDate()]; + dow = d.getDay(); + if(date < 60) dow = (dow + 6) % 7; + if(b2) dow = fix_hijri(d, dout); + } + out.y = dout[0]; out.m = dout[1]; out.d = dout[2]; + out.S = time % 60; time = Math.floor(time / 60); + out.M = time % 60; time = Math.floor(time / 60); + out.H = time; + out.q = dow; + return out; + } + SSF.parse_date_code = parse_date_code; + var basedate = new Date(1899, 11, 31, 0, 0, 0); + var dnthresh = basedate.getTime(); + var base1904 = new Date(1900, 2, 1, 0, 0, 0); + function datenum_local(v, date1904) { + var epoch = v.getTime(); + if(date1904) epoch -= 1461*24*60*60*1000; + else if(v >= base1904) epoch += 24*60*60*1000; + return (epoch - (dnthresh + (v.getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000); + } + function general_fmt_int(v) { return v.toString(10); } + SSF._general_int = general_fmt_int; + var general_fmt_num = (function make_general_fmt_num() { + var gnr1 = /\.(\d*[1-9])0+$/, gnr2 = /\.0*$/, gnr4 = /\.(\d*[1-9])0+/, gnr5 = /\.0*[Ee]/, gnr6 = /(E[+-])(\d)$/; + function gfn2(v) { + var w = (v<0?12:11); + var o = gfn5(v.toFixed(12)); if(o.length <= w) return o; + o = v.toPrecision(10); if(o.length <= w) return o; + return v.toExponential(5); + } + function gfn3(v) { + var o = v.toFixed(11).replace(gnr1,".$1"); + if(o.length > (v<0?12:11)) o = v.toPrecision(6); + return o; + } + function gfn4(o) { + for(var i = 0; i != o.length; ++i) if((o.charCodeAt(i) | 0x20) === 101) return o.replace(gnr4,".$1").replace(gnr5,"E").replace("e","E").replace(gnr6,"$10$2"); + return o; + } + function gfn5(o) { + return o.indexOf(".") > -1 ? o.replace(gnr2,"").replace(gnr1,".$1") : o; + } + return function general_fmt_num(v) { + var V = Math.floor(Math.log(Math.abs(v))*Math.LOG10E), o; + if(V >= -4 && V <= -1) o = v.toPrecision(10+V); + else if(Math.abs(V) <= 9) o = gfn2(v); + else if(V === 10) o = v.toFixed(10).substr(0,12); + else o = gfn3(v); + return gfn5(gfn4(o)); + };})(); + SSF._general_num = general_fmt_num; + function general_fmt(v, opts) { + switch(typeof v) { + case 'string': return v; + case 'boolean': return v ? "TRUE" : "FALSE"; + case 'number': return (v|0) === v ? general_fmt_int(v) : general_fmt_num(v); + case 'undefined': return ""; + case 'object': + if(v == null) return ""; + if(v instanceof Date) return format(14, datenum_local(v, opts && opts.date1904), opts); + } + throw new Error("unsupported value in General format: " + v); + } + SSF._general = general_fmt; + function fix_hijri() { return 0; } + /*jshint -W086 */ + function write_date(type, fmt, val, ss0) { + var o="", ss=0, tt=0, y = val.y, out, outl = 0; + switch(type) { + case 98: /* 'b' buddhist year */ + y = val.y + 543; + /* falls through */ + case 121: /* 'y' year */ + switch(fmt.length) { + case 1: case 2: out = y % 100; outl = 2; break; + default: out = y % 10000; outl = 4; break; + } break; + case 109: /* 'm' month */ + switch(fmt.length) { + case 1: case 2: out = val.m; outl = fmt.length; break; + case 3: return months[val.m-1][1]; + case 5: return months[val.m-1][0]; + default: return months[val.m-1][2]; + } break; + case 100: /* 'd' day */ + switch(fmt.length) { + case 1: case 2: out = val.d; outl = fmt.length; break; + case 3: return days[val.q][0]; + default: return days[val.q][1]; + } break; + case 104: /* 'h' 12-hour */ + switch(fmt.length) { + case 1: case 2: out = 1+(val.H+11)%12; outl = fmt.length; break; + default: throw 'bad hour format: ' + fmt; + } break; + case 72: /* 'H' 24-hour */ + switch(fmt.length) { + case 1: case 2: out = val.H; outl = fmt.length; break; + default: throw 'bad hour format: ' + fmt; + } break; + case 77: /* 'M' minutes */ + switch(fmt.length) { + case 1: case 2: out = val.M; outl = fmt.length; break; + default: throw 'bad minute format: ' + fmt; + } break; + case 115: /* 's' seconds */ + if(fmt != 's' && fmt != 'ss' && fmt != '.0' && fmt != '.00' && fmt != '.000') throw 'bad second format: ' + fmt; + if(val.u === 0 && (fmt == "s" || fmt == "ss")) return pad0(val.S, fmt.length); + if(ss0 >= 2) tt = ss0 === 3 ? 1000 : 100; + else tt = ss0 === 1 ? 10 : 1; + ss = Math.round((tt)*(val.S + val.u)); + if(ss >= 60*tt) ss = 0; + if(fmt === 's') return ss === 0 ? "0" : ""+ss/tt; + o = pad0(ss,2 + ss0); + if(fmt === 'ss') return o.substr(0,2); + return "." + o.substr(2,fmt.length-1); + case 90: /* 'Z' absolute time */ + switch(fmt) { + case '[h]': case '[hh]': out = val.D*24+val.H; break; + case '[m]': case '[mm]': out = (val.D*24+val.H)*60+val.M; break; + case '[s]': case '[ss]': out = ((val.D*24+val.H)*60+val.M)*60+Math.round(val.S+val.u); break; + default: throw 'bad abstime format: ' + fmt; + } outl = fmt.length === 3 ? 1 : 2; break; + case 101: /* 'e' era */ + out = y; outl = 1; + } + if(outl > 0) return pad0(out, outl); else return ""; + } + /*jshint +W086 */ + function commaify(s) { + var w = 3; + if(s.length <= w) return s; + var j = (s.length % w), o = s.substr(0,j); + for(; j!=s.length; j+=w) o+=(o.length > 0 ? "," : "") + s.substr(j,w); + return o; + } + var write_num = (function make_write_num(){ + var pct1 = /%/g; + function write_num_pct(type, fmt, val){ + var sfmt = fmt.replace(pct1,""), mul = fmt.length - sfmt.length; + return write_num(type, sfmt, val * Math.pow(10,2*mul)) + fill("%",mul); + } + function write_num_cm(type, fmt, val){ + var idx = fmt.length - 1; + while(fmt.charCodeAt(idx-1) === 44) --idx; + return write_num(type, fmt.substr(0,idx), val / Math.pow(10,3*(fmt.length-idx))); + } + function write_num_exp(fmt, val){ + var o; + var idx = fmt.indexOf("E") - fmt.indexOf(".") - 1; + if(fmt.match(/^#+0.0E\+0$/)) { + if(val == 0) return "0.0E+0"; + else if(val < 0) return "-" + write_num_exp(fmt, -val); + var period = fmt.indexOf("."); if(period === -1) period=fmt.indexOf('E'); + var ee = Math.floor(Math.log(val)*Math.LOG10E)%period; + if(ee < 0) ee += period; + o = (val/Math.pow(10,ee)).toPrecision(idx+1+(period+ee)%period); + if(o.indexOf("e") === -1) { + var fakee = Math.floor(Math.log(val)*Math.LOG10E); + if(o.indexOf(".") === -1) o = o.charAt(0) + "." + o.substr(1) + "E+" + (fakee - o.length+ee); + else o += "E+" + (fakee - ee); + while(o.substr(0,2) === "0.") { + o = o.charAt(0) + o.substr(2,period) + "." + o.substr(2+period); + o = o.replace(/^0+([1-9])/,"$1").replace(/^0+\./,"0."); + } + o = o.replace(/\+-/,"-"); + } + o = o.replace(/^([+-]?)(\d*)\.(\d*)[Ee]/,function($$,$1,$2,$3) { return $1 + $2 + $3.substr(0,(period+ee)%period) + "." + $3.substr(ee) + "E"; }); + } else o = val.toExponential(idx); + if(fmt.match(/E\+00$/) && o.match(/e[+-]\d$/)) o = o.substr(0,o.length-1) + "0" + o.charAt(o.length-1); + if(fmt.match(/E\-/) && o.match(/e\+/)) o = o.replace(/e\+/,"e"); + return o.replace("e","E"); + } + var frac1 = /# (\?+)( ?)\/( ?)(\d+)/; + function write_num_f1(r, aval, sign) { + var den = parseInt(r[4],10), rr = Math.round(aval * den), base = Math.floor(rr/den); + var myn = (rr - base*den), myd = den; + return sign + (base === 0 ? "" : ""+base) + " " + (myn === 0 ? fill(" ", r[1].length + 1 + r[4].length) : pad_(myn,r[1].length) + r[2] + "/" + r[3] + pad0(myd,r[4].length)); + } + function write_num_f2(r, aval, sign) { + return sign + (aval === 0 ? "" : ""+aval) + fill(" ", r[1].length + 2 + r[4].length); + } + var dec1 = /^#*0*\.([0#]+)/; + var closeparen = /\).*[0#]/; + var phone = /\(###\) ###\\?-####/; + function hashq(str) { + var o = "", cc; + for(var i = 0; i != str.length; ++i) switch((cc=str.charCodeAt(i))) { + case 35: break; + case 63: o+= " "; break; + case 48: o+= "0"; break; + default: o+= String.fromCharCode(cc); + } + return o; + } + function rnd(val, d) { var dd = Math.pow(10,d); return ""+(Math.round(val * dd)/dd); } + function dec(val, d) { + if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) { + return 0; + } + return Math.round((val-Math.floor(val))*Math.pow(10,d)); + } + function carry(val, d) { + if (d < ('' + Math.round((val-Math.floor(val))*Math.pow(10,d))).length) { + return 1; + } + return 0; + } + function flr(val) { if(val < 2147483647 && val > -2147483648) return ""+(val >= 0 ? (val|0) : (val-1|0)); return ""+Math.floor(val); } + function write_num_flt(type, fmt, val) { + if(type.charCodeAt(0) === 40 && !fmt.match(closeparen)) { + var ffmt = fmt.replace(/\( */,"").replace(/ \)/,"").replace(/\)/,""); + if(val >= 0) return write_num_flt('n', ffmt, val); + return '(' + write_num_flt('n', ffmt, -val) + ')'; + } + if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm(type, fmt, val); + if(fmt.indexOf('%') !== -1) return write_num_pct(type, fmt, val); + if(fmt.indexOf('E') !== -1) return write_num_exp(fmt, val); + if(fmt.charCodeAt(0) === 36) return "$"+write_num_flt(type,fmt.substr(fmt.charAt(1)==' '?2:1),val); + var o; + var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : ""; + if(fmt.match(/^00+$/)) return sign + pad0r(aval,fmt.length); + if(fmt.match(/^[#?]+$/)) { + o = pad0r(val,0); if(o === "0") o = ""; + return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o; + } + if((r = fmt.match(frac1))) return write_num_f1(r, aval, sign); + if(fmt.match(/^#+0+$/)) return sign + pad0r(aval,fmt.length - fmt.indexOf("0")); + if((r = fmt.match(dec1))) { + o = rnd(val, r[1].length).replace(/^([^\.]+)$/,"$1."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1])).replace(/\.(\d*)$/,function($$, $1) { return "." + $1 + fill("0", hashq(r[1]).length-$1.length); }); + return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,"."); + } + fmt = fmt.replace(/^#+([0.])/, "$1"); + if((r = fmt.match(/^(0*)\.(#*)$/))) { + return sign + rnd(aval, r[2].length).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":"."); + } + if((r = fmt.match(/^#{1,3},##0(\.?)$/))) return sign + commaify(pad0r(aval,0)); + if((r = fmt.match(/^#,##0\.([#0]*0)$/))) { + return val < 0 ? "-" + write_num_flt(type, fmt, -val) : commaify(""+(Math.floor(val) + carry(val, r[1].length))) + "." + pad0(dec(val, r[1].length),r[1].length); + } + if((r = fmt.match(/^#,#*,#0/))) return write_num_flt(type,fmt.replace(/^#,#*,/,""),val); + if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) { + o = _strrev(write_num_flt(type, fmt.replace(/[\\-]/g,""), val)); + ri = 0; + return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri= 0) return write_num_int('n', ffmt, val); + return '(' + write_num_int('n', ffmt, -val) + ')'; + } + if(fmt.charCodeAt(fmt.length - 1) === 44) return write_num_cm2(type, fmt, val); + if(fmt.indexOf('%') !== -1) return write_num_pct2(type, fmt, val); + if(fmt.indexOf('E') !== -1) return write_num_exp2(fmt, val); + if(fmt.charCodeAt(0) === 36) return "$"+write_num_int(type,fmt.substr(fmt.charAt(1)==' '?2:1),val); + var o; + var r, ri, ff, aval = Math.abs(val), sign = val < 0 ? "-" : ""; + if(fmt.match(/^00+$/)) return sign + pad0(aval,fmt.length); + if(fmt.match(/^[#?]+$/)) { + o = (""+val); if(val === 0) o = ""; + return o.length > fmt.length ? o : hashq(fmt.substr(0,fmt.length-o.length)) + o; + } + if((r = fmt.match(frac1))) return write_num_f2(r, aval, sign); + if(fmt.match(/^#+0+$/)) return sign + pad0(aval,fmt.length - fmt.indexOf("0")); + if((r = fmt.match(dec1))) { + o = (""+val).replace(/^([^\.]+)$/,"$1."+hashq(r[1])).replace(/\.$/,"."+hashq(r[1])); + o = o.replace(/\.(\d*)$/,function($$, $1) { + return "." + $1 + fill("0", hashq(r[1]).length-$1.length); }); + return fmt.indexOf("0.") !== -1 ? o : o.replace(/^0\./,"."); + } + fmt = fmt.replace(/^#+([0.])/, "$1"); + if((r = fmt.match(/^(0*)\.(#*)$/))) { + return sign + (""+aval).replace(/\.(\d*[1-9])0*$/,".$1").replace(/^(-?\d*)$/,"$1.").replace(/^0\./,r[1].length?"0.":"."); + } + if((r = fmt.match(/^#{1,3},##0(\.?)$/))) return sign + commaify((""+aval)); + if((r = fmt.match(/^#,##0\.([#0]*0)$/))) { + return val < 0 ? "-" + write_num_int(type, fmt, -val) : commaify((""+val)) + "." + fill('0',r[1].length); + } + if((r = fmt.match(/^#,#*,#0/))) return write_num_int(type,fmt.replace(/^#,#*,/,""),val); + if((r = fmt.match(/^([0#]+)(\\?-([0#]+))+$/))) { + o = _strrev(write_num_int(type, fmt.replace(/[\\-]/g,""), val)); + ri = 0; + return _strrev(_strrev(fmt.replace(/\\/g,"")).replace(/[0#]/g,function(x){return ri -1 || (c=='\\' && fmt.charAt(i+1) == "-" && "0#".indexOf(fmt.charAt(i+2))>-1))){/* empty */} + break; + case '?': while(fmt.charAt(++i) === c){/* empty */} break; + case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break; + case '(': case ')': ++i; break; + case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1){/* empty */} break; + case ' ': ++i; break; + default: ++i; break; + } + } + return false; + } + SSF.is_date = fmt_is_date; + function eval_fmt(fmt, v, opts, flen) { + var out = [], o = "", i = 0, c = "", lst='t', dt, j, cc; + var hr='H'; + /* Tokenize */ + while(i < fmt.length) { + switch((c = fmt.charAt(i))) { + case 'G': /* General */ + if(!isgeneral(fmt, i)) throw new Error('unrecognized character ' + c + ' in ' +fmt); + out[out.length] = {t:'G', v:'General'}; i+=7; break; + case '"': /* Literal text */ + for(o="";(cc=fmt.charCodeAt(++i)) !== 34 && i < fmt.length;) o += String.fromCharCode(cc); + out[out.length] = {t:'t', v:o}; ++i; break; + case '\\': var w = fmt.charAt(++i), t = (w === "(" || w === ")") ? w : 't'; + out[out.length] = {t:t, v:w}; ++i; break; + case '_': out[out.length] = {t:'t', v:" "}; i+=2; break; + case '@': /* Text Placeholder */ + out[out.length] = {t:'T', v:v}; ++i; break; + case 'B': case 'b': + if(fmt.charAt(i+1) === "1" || fmt.charAt(i+1) === "2") { + if(dt==null) { dt=parse_date_code(v, opts, fmt.charAt(i+1) === "2"); if(dt==null) return ""; } + out[out.length] = {t:'X', v:fmt.substr(i,2)}; lst = c; i+=2; break; + } + /* falls through */ + case 'M': case 'D': case 'Y': case 'H': case 'S': case 'E': + c = c.toLowerCase(); + /* falls through */ + case 'm': case 'd': case 'y': case 'h': case 's': case 'e': case 'g': + if(v < 0) return ""; + if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; } + o = c; while(++i < fmt.length && fmt.charAt(i).toLowerCase() === c) o+=c; + if(c === 'm' && lst.toLowerCase() === 'h') c = 'M'; + if(c === 'h') c = hr; + out[out.length] = {t:c, v:o}; lst = c; break; + case 'A': case 'a': + var q={t:c, v:c}; + if(dt==null) dt=parse_date_code(v, opts); + if(fmt.substr(i, 3).toUpperCase() === "A/P") { if(dt!=null) q.v = dt.H >= 12 ? "P" : "A"; q.t = 'T'; hr='h';i+=3;} + else if(fmt.substr(i,5).toUpperCase() === "AM/PM") { if(dt!=null) q.v = dt.H >= 12 ? "PM" : "AM"; q.t = 'T'; i+=5; hr='h'; } + else { q.t = "t"; ++i; } + if(dt==null && q.t === 'T') return ""; + out[out.length] = q; lst = c; break; + case '[': + o = c; + while(fmt.charAt(i++) !== ']' && i < fmt.length) o += fmt.charAt(i); + if(o.slice(-1) !== ']') throw 'unterminated "[" block: |' + o + '|'; + if(o.match(abstime)) { + if(dt==null) { dt=parse_date_code(v, opts); if(dt==null) return ""; } + out[out.length] = {t:'Z', v:o.toLowerCase()}; + lst = o.charAt(1); + } else if(o.indexOf("$") > -1) { + o = (o.match(/\$([^-\[\]]*)/)||[])[1]||"$"; + if(!fmt_is_date(fmt)) out[out.length] = {t:'t',v:o}; + } + break; + /* Numbers */ + case '.': + if(dt != null) { + o = c; while(++i < fmt.length && (c=fmt.charAt(i)) === "0") o += c; + out[out.length] = {t:'s', v:o}; break; + } + /* falls through */ + case '0': case '#': + o = c; while((++i < fmt.length && "0#?.,E+-%".indexOf(c=fmt.charAt(i)) > -1) || (c=='\\' && fmt.charAt(i+1) == "-" && i < fmt.length - 2 && "0#".indexOf(fmt.charAt(i+2))>-1)) o += c; + out[out.length] = {t:'n', v:o}; break; + case '?': + o = c; while(fmt.charAt(++i) === c) o+=c; + out[out.length] = {t:c, v:o}; lst = c; break; + case '*': ++i; if(fmt.charAt(i) == ' ' || fmt.charAt(i) == '*') ++i; break; // ** + case '(': case ')': out[out.length] = {t:(flen===1?'t':c), v:c}; ++i; break; + case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + o = c; while(i < fmt.length && "0123456789".indexOf(fmt.charAt(++i)) > -1) o+=fmt.charAt(i); + out[out.length] = {t:'D', v:o}; break; + case ' ': out[out.length] = {t:c, v:c}; ++i; break; + default: + if(",$-+/():!^&'~{}<>=€acfijklopqrtuvwxzP".indexOf(c) === -1) throw new Error('unrecognized character ' + c + ' in ' + fmt); + out[out.length] = {t:'t', v:c}; ++i; break; + } + } + var bt = 0, ss0 = 0, ssm; + for(i=out.length-1, lst='t'; i >= 0; --i) { + switch(out[i].t) { + case 'h': case 'H': out[i].t = hr; lst='h'; if(bt < 1) bt = 1; break; + case 's': + if((ssm=out[i].v.match(/\.0+$/))) ss0=Math.max(ss0,ssm[0].length-1); + if(bt < 3) bt = 3; + /* falls through */ + case 'd': case 'y': case 'M': case 'e': lst=out[i].t; break; + case 'm': if(lst === 's') { out[i].t = 'M'; if(bt < 2) bt = 2; } break; + case 'X': /*if(out[i].v === "B2");*/ + break; + case 'Z': + if(bt < 1 && out[i].v.match(/[Hh]/)) bt = 1; + if(bt < 2 && out[i].v.match(/[Mm]/)) bt = 2; + if(bt < 3 && out[i].v.match(/[Ss]/)) bt = 3; + } + } + switch(bt) { + case 0: break; + case 1: + if(dt.u >= 0.5) { dt.u = 0; ++dt.S; } + if(dt.S >= 60) { dt.S = 0; ++dt.M; } + if(dt.M >= 60) { dt.M = 0; ++dt.H; } + break; + case 2: + if(dt.u >= 0.5) { dt.u = 0; ++dt.S; } + if(dt.S >= 60) { dt.S = 0; ++dt.M; } + break; + } + /* replace fields */ + var nstr = "", jj; + for(i=0; i < out.length; ++i) { + switch(out[i].t) { + case 't': case 'T': case ' ': case 'D': break; + case 'X': out[i].v = ""; out[i].t = ";"; break; + case 'd': case 'm': case 'y': case 'h': case 'H': case 'M': case 's': case 'e': case 'b': case 'Z': + out[i].v = write_date(out[i].t.charCodeAt(0), out[i].v, dt, ss0); + out[i].t = 't'; break; + case 'n': case '(': case '?': + jj = i+1; + while(out[jj] != null && ( + (c=out[jj].t) === "?" || c === "D" || + ((c === " " || c === "t") && out[jj+1] != null && (out[jj+1].t === '?' || out[jj+1].t === "t" && out[jj+1].v === '/')) || + (out[i].t === '(' && (c === ' ' || c === 'n' || c === ')')) || + (c === 't' && (out[jj].v === '/' || out[jj].v === ' ' && out[jj+1] != null && out[jj+1].t == '?')) + )) { + out[i].v += out[jj].v; + out[jj] = {v:"", t:";"}; ++jj; + } + nstr += out[i].v; + i = jj-1; break; + case 'G': out[i].t = 't'; out[i].v = general_fmt(v,opts); break; + } + } + var vv = "", myv, ostr; + if(nstr.length > 0) { + if(nstr.charCodeAt(0) == 40) /* '(' */ { + myv = (v<0&&nstr.charCodeAt(0) === 45 ? -v : v); + ostr = write_num('(', nstr, myv); + } else { + myv = (v<0 && flen > 1 ? -v : v); + ostr = write_num('n', nstr, myv); + if(myv < 0 && out[0] && out[0].t == 't') { + ostr = ostr.substr(1); + out[0].v = "-" + out[0].v; + } + } + jj=ostr.length-1; + var decpt = out.length; + for(i=0; i < out.length; ++i) if(out[i] != null && out[i].t != 't' && out[i].v.indexOf(".") > -1) { decpt = i; break; } + var lasti=out.length; + if(decpt === out.length && ostr.indexOf("E") === -1) { + for(i=out.length-1; i>= 0;--i) { + if(out[i] == null || 'n?('.indexOf(out[i].t) === -1) continue; + if(jj>=out[i].v.length-1) { jj -= out[i].v.length; out[i].v = ostr.substr(jj+1, out[i].v.length); } + else if(jj < 0) out[i].v = ""; + else { out[i].v = ostr.substr(0, jj+1); jj = -1; } + out[i].t = 't'; + lasti = i; + } + if(jj>=0 && lasti= 0; --i) { + if(out[i] == null || 'n?('.indexOf(out[i].t) === -1) continue; + j=out[i].v.indexOf(".")>-1&&i===decpt?out[i].v.indexOf(".")-1:out[i].v.length-1; + vv = out[i].v.substr(j+1); + for(; j>=0; --j) { + if(jj>=0 && (out[i].v.charAt(j) === "0" || out[i].v.charAt(j) === "#")) vv = ostr.charAt(jj--) + vv; + } + out[i].v = vv; + out[i].t = 't'; + lasti = i; + } + if(jj>=0 && lasti-1&&i===decpt?out[i].v.indexOf(".")+1:0; + vv = out[i].v.substr(0,j); + for(; j-1) { + myv = (flen >1 && v < 0 && i>0 && out[i-1].v === "-" ? -v:v); + out[i].v = write_num(out[i].t, out[i].v, myv); + out[i].t = 't'; + } + var retval = ""; + for(i=0; i !== out.length; ++i) if(out[i] != null) retval += out[i].v; + return retval; + } + SSF._eval = eval_fmt; + var cfregex = /\[[=<>]/; + var cfregex2 = /\[(=|>[=]?|<[>=]?)(-?\d+(?:\.\d*)?)\]/; + function chkcond(v, rr) { + if(rr == null) return false; + var thresh = parseFloat(rr[2]); + switch(rr[1]) { + case "=": if(v == thresh) return true; break; + case ">": if(v > thresh) return true; break; + case "<": if(v < thresh) return true; break; + case "<>": if(v != thresh) return true; break; + case ">=": if(v >= thresh) return true; break; + case "<=": if(v <= thresh) return true; break; + } + return false; + } + function choose_fmt(f, v) { + var fmt = split_fmt(f); + var l = fmt.length, lat = fmt[l-1].indexOf("@"); + if(l<4 && lat>-1) --l; + if(fmt.length > 4) throw new Error("cannot find right format for |" + fmt.join("|") + "|"); + if(typeof v !== "number") return [4, fmt.length === 4 || lat>-1?fmt[fmt.length-1]:"@"]; + switch(fmt.length) { + case 1: fmt = lat>-1 ? ["General", "General", "General", fmt[0]] : [fmt[0], fmt[0], fmt[0], "@"]; break; + case 2: fmt = lat>-1 ? [fmt[0], fmt[0], fmt[0], fmt[1]] : [fmt[0], fmt[1], fmt[0], "@"]; break; + case 3: fmt = lat>-1 ? [fmt[0], fmt[1], fmt[0], fmt[2]] : [fmt[0], fmt[1], fmt[2], "@"]; break; + case 4: break; + } + var ff = v > 0 ? fmt[0] : v < 0 ? fmt[1] : fmt[2]; + if(fmt[0].indexOf("[") === -1 && fmt[1].indexOf("[") === -1) return [l, ff]; + if(fmt[0].match(cfregex) != null || fmt[1].match(cfregex) != null) { + var m1 = fmt[0].match(cfregex2); + var m2 = fmt[1].match(cfregex2); + return chkcond(v, m1) ? [l, fmt[0]] : chkcond(v, m2) ? [l, fmt[1]] : [l, fmt[m1 != null && m2 != null ? 2 : 1]]; + } + return [l, ff]; + } + function format(fmt,v,o) { + if(o == null) o = {}; + var sfmt = ""; + switch(typeof fmt) { + case "string": + if(fmt == "m/d/yy" && o.dateNF) sfmt = o.dateNF; + else sfmt = fmt; + break; + case "number": + if(fmt == 14 && o.dateNF) sfmt = o.dateNF; + else sfmt = (o.table != null ? (o.table) : table_fmt)[fmt]; + break; + } + if(isgeneral(sfmt,0)) return general_fmt(v, o); + if(v instanceof Date) v = datenum_local(v, o.date1904); + var f = choose_fmt(sfmt, v); + if(isgeneral(f[1])) return general_fmt(v, o); + if(v === true) v = "TRUE"; else if(v === false) v = "FALSE"; + else if(v === "" || v == null) return ""; + return eval_fmt(f[1], v, o, f[0]); + } + function load_entry(fmt, idx) { + if(typeof idx != 'number') { + idx = +idx || -1; + for(var i = 0; i < 0x0188; ++i) { + if(table_fmt[i] == undefined) { if(idx < 0) idx = i; continue; } + if(table_fmt[i] == fmt) { idx = i; break; } + } + if(idx < 0) idx = 0x187; + } + table_fmt[idx] = fmt; + return idx; + } + SSF.load = load_entry; + SSF._table = table_fmt; + SSF.get_table = function get_table() { return table_fmt; }; + SSF.load_table = function load_table(tbl) { + for(var i=0; i!=0x0188; ++i) + if(tbl[i] !== undefined) load_entry(tbl[i], i); + }; + SSF.init_table = init_table; + SSF.format = format; + }; + make_ssf(SSF); + /* map from xlml named formats to SSF TODO: localize */ + var XLMLFormatMap/*{[string]:string}*/ = ({ + "General Number": "General", + "General Date": SSF._table[22], + "Long Date": "dddd, mmmm dd, yyyy", + "Medium Date": SSF._table[15], + "Short Date": SSF._table[14], + "Long Time": SSF._table[19], + "Medium Time": SSF._table[18], + "Short Time": SSF._table[20], + "Currency": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)', + "Fixed": SSF._table[2], + "Standard": SSF._table[4], + "Percent": SSF._table[10], + "Scientific": SSF._table[11], + "Yes/No": '"Yes";"Yes";"No";@', + "True/False": '"True";"True";"False";@', + "On/Off": '"Yes";"Yes";"No";@' + }); + + var SSFImplicit/*{[number]:string}*/ = ({ + "5": '"$"#,##0_);\\("$"#,##0\\)', + "6": '"$"#,##0_);[Red]\\("$"#,##0\\)', + "7": '"$"#,##0.00_);\\("$"#,##0.00\\)', + "8": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)', + "23": 'General', "24": 'General', "25": 'General', "26": 'General', + "27": 'm/d/yy', "28": 'm/d/yy', "29": 'm/d/yy', "30": 'm/d/yy', "31": 'm/d/yy', + "32": 'h:mm:ss', "33": 'h:mm:ss', "34": 'h:mm:ss', "35": 'h:mm:ss', + "36": 'm/d/yy', + "41": '_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)', + "42": '_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_)', + "43": '_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)', + "44": '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)', + "50": 'm/d/yy', "51": 'm/d/yy', "52": 'm/d/yy', "53": 'm/d/yy', "54": 'm/d/yy', + "55": 'm/d/yy', "56": 'm/d/yy', "57": 'm/d/yy', "58": 'm/d/yy', + "59": '0', + "60": '0.00', + "61": '#,##0', + "62": '#,##0.00', + "63": '"$"#,##0_);\\("$"#,##0\\)', + "64": '"$"#,##0_);[Red]\\("$"#,##0\\)', + "65": '"$"#,##0.00_);\\("$"#,##0.00\\)', + "66": '"$"#,##0.00_);[Red]\\("$"#,##0.00\\)', + "67": '0%', + "68": '0.00%', + "69": '# ?/?', + "70": '# ??/??', + "71": 'm/d/yy', + "72": 'm/d/yy', + "73": 'd-mmm-yy', + "74": 'd-mmm', + "75": 'mmm-yy', + "76": 'h:mm', + "77": 'h:mm:ss', + "78": 'm/d/yy h:mm', + "79": 'mm:ss', + "80": '[h]:mm:ss', + "81": 'mmss.0' + }); + + /* dateNF parse TODO: move to SSF */ + var dateNFregex = /[dD]+|[mM]+|[yYeE]+|[Hh]+|[Ss]+/g; + function dateNF_regex(dateNF) { + var fmt = typeof dateNF == "number" ? SSF._table[dateNF] : dateNF; + fmt = fmt.replace(dateNFregex, "(\\d+)"); + return new RegExp("^" + fmt + "$"); + } + function dateNF_fix(str, dateNF, match) { + var Y = -1, m = -1, d = -1, H = -1, M = -1, S = -1; + (dateNF.match(dateNFregex)||[]).forEach(function(n, i) { + var v = parseInt(match[i+1], 10); + switch(n.toLowerCase().charAt(0)) { + case 'y': Y = v; break; case 'd': d = v; break; + case 'h': H = v; break; case 's': S = v; break; + case 'm': if(H >= 0) M = v; else m = v; break; + } + }); + if(S >= 0 && M == -1 && m >= 0) { M = m; m = -1; } + var datestr = (("" + (Y>=0?Y: new Date().getFullYear())).slice(-4) + "-" + ("00" + (m>=1?m:1)).slice(-2) + "-" + ("00" + (d>=1?d:1)).slice(-2)); + if(datestr.length == 7) datestr = "0" + datestr; + if(datestr.length == 8) datestr = "20" + datestr; + var timestr = (("00" + (H>=0?H:0)).slice(-2) + ":" + ("00" + (M>=0?M:0)).slice(-2) + ":" + ("00" + (S>=0?S:0)).slice(-2)); + if(H == -1 && M == -1 && S == -1) return datestr; + if(Y == -1 && m == -1 && d == -1) return timestr; + return datestr + "T" + timestr; + } + + var DO_NOT_EXPORT_CFB = true; + /* cfb.js (C) 2013-present SheetJS -- http://sheetjs.com */ + /* vim: set ts=2: */ + /*jshint eqnull:true */ + /*exported CFB */ + /*global module, require:false, process:false, Buffer:false, Uint8Array:false, Uint16Array:false */ + + /* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */ + /* vim: set ts=2: */ + /*exported CRC32 */ + var CRC32; + (function (factory) { + /*jshint ignore:start */ + /*eslint-disable */ + factory(CRC32 = {}); + /*eslint-enable */ + /*jshint ignore:end */ + }(function(CRC32) { + CRC32.version = '1.2.0'; + /* see perf/crc32table.js */ + /*global Int32Array */ + function signed_crc_table() { + var c = 0, table = new Array(256); + + for(var n =0; n != 256; ++n){ + c = n; + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + c = ((c&1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1)); + table[n] = c; + } + + return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table; + } + + var T = signed_crc_table(); + function crc32_bstr(bstr, seed) { + var C = seed ^ -1, L = bstr.length - 1; + for(var i = 0; i < L;) { + C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF]; + C = (C>>>8) ^ T[(C^bstr.charCodeAt(i++))&0xFF]; + } + if(i === L) C = (C>>>8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF]; + return C ^ -1; + } + + function crc32_buf(buf, seed) { + if(buf.length > 10000) return crc32_buf_8(buf, seed); + var C = seed ^ -1, L = buf.length - 3; + for(var i = 0; i < L;) { + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + } + while(i < L+3) C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + return C ^ -1; + } + + function crc32_buf_8(buf, seed) { + var C = seed ^ -1, L = buf.length - 7; + for(var i = 0; i < L;) { + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + } + while(i < L+7) C = (C>>>8) ^ T[(C^buf[i++])&0xFF]; + return C ^ -1; + } + + function crc32_str(str, seed) { + var C = seed ^ -1; + for(var i = 0, L=str.length, c, d; i < L;) { + c = str.charCodeAt(i++); + if(c < 0x80) { + C = (C>>>8) ^ T[(C ^ c)&0xFF]; + } else if(c < 0x800) { + C = (C>>>8) ^ T[(C ^ (192|((c>>6)&31)))&0xFF]; + C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF]; + } else if(c >= 0xD800 && c < 0xE000) { + c = (c&1023)+64; d = str.charCodeAt(i++)&1023; + C = (C>>>8) ^ T[(C ^ (240|((c>>8)&7)))&0xFF]; + C = (C>>>8) ^ T[(C ^ (128|((c>>2)&63)))&0xFF]; + C = (C>>>8) ^ T[(C ^ (128|((d>>6)&15)|((c&3)<<4)))&0xFF]; + C = (C>>>8) ^ T[(C ^ (128|(d&63)))&0xFF]; + } else { + C = (C>>>8) ^ T[(C ^ (224|((c>>12)&15)))&0xFF]; + C = (C>>>8) ^ T[(C ^ (128|((c>>6)&63)))&0xFF]; + C = (C>>>8) ^ T[(C ^ (128|(c&63)))&0xFF]; + } + } + return C ^ -1; + } + CRC32.table = T; + CRC32.bstr = crc32_bstr; + CRC32.buf = crc32_buf; + CRC32.str = crc32_str; + })); + /* [MS-CFB] v20171201 */ + var CFB = (function _CFB(){ + var exports = {}; + exports.version = '1.1.0'; + /* [MS-CFB] 2.6.4 */ + function namecmp(l, r) { + var L = l.split("/"), R = r.split("/"); + for(var i = 0, c = 0, Z = Math.min(L.length, R.length); i < Z; ++i) { + if((c = L[i].length - R[i].length)) return c; + if(L[i] != R[i]) return L[i] < R[i] ? -1 : 1; + } + return L.length - R.length; + } + function dirname(p) { + if(p.charAt(p.length - 1) == "/") return (p.slice(0,-1).indexOf("/") === -1) ? p : dirname(p.slice(0, -1)); + var c = p.lastIndexOf("/"); + return (c === -1) ? p : p.slice(0, c+1); + } + + function filename(p) { + if(p.charAt(p.length - 1) == "/") return filename(p.slice(0, -1)); + var c = p.lastIndexOf("/"); + return (c === -1) ? p : p.slice(c+1); + } + /* -------------------------------------------------------------------------- */ + /* DOS Date format: + high|YYYYYYYm.mmmddddd.HHHHHMMM.MMMSSSSS|low + add 1980 to stored year + stored second should be doubled +*/ + + /* write JS date to buf as a DOS date */ + function write_dos_date(buf, date) { + if(typeof date === "string") date = new Date(date); + var hms = date.getHours(); + hms = hms << 6 | date.getMinutes(); + hms = hms << 5 | (date.getSeconds()>>>1); + buf.write_shift(2, hms); + var ymd = (date.getFullYear() - 1980); + ymd = ymd << 4 | (date.getMonth()+1); + ymd = ymd << 5 | date.getDate(); + buf.write_shift(2, ymd); + } + + /* read four bytes from buf and interpret as a DOS date */ + function parse_dos_date(buf) { + var hms = buf.read_shift(2) & 0xFFFF; + var ymd = buf.read_shift(2) & 0xFFFF; + var val = new Date(); + var d = ymd & 0x1F; ymd >>>= 5; + var m = ymd & 0x0F; ymd >>>= 4; + val.setMilliseconds(0); + val.setFullYear(ymd + 1980); + val.setMonth(m-1); + val.setDate(d); + var S = hms & 0x1F; hms >>>= 5; + var M = hms & 0x3F; hms >>>= 6; + val.setHours(hms); + val.setMinutes(M); + val.setSeconds(S<<1); + return val; + } + function parse_extra_field(blob) { + prep_blob(blob, 0); + var o = {}; + var flags = 0; + while(blob.l <= blob.length - 4) { + var type = blob.read_shift(2); + var sz = blob.read_shift(2), tgt = blob.l + sz; + var p = {}; + switch(type) { + /* UNIX-style Timestamps */ + case 0x5455: { + flags = blob.read_shift(1); + if(flags & 1) p.mtime = blob.read_shift(4); + /* for some reason, CD flag corresponds to LFH */ + if(sz > 5) { + if(flags & 2) p.atime = blob.read_shift(4); + if(flags & 4) p.ctime = blob.read_shift(4); + } + if(p.mtime) p.mt = new Date(p.mtime*1000); + } + break; + } + blob.l = tgt; + o[type] = p; + } + return o; + } + var fs; + function get_fs() { return fs || (fs = require('fs')); } + function parse(file, options) { + if(file[0] == 0x50 && file[1] == 0x4b) return parse_zip(file, options); + if(file.length < 512) throw new Error("CFB file size " + file.length + " < 512"); + var mver = 3; + var ssz = 512; + var nmfs = 0; // number of mini FAT sectors + var difat_sec_cnt = 0; + var dir_start = 0; + var minifat_start = 0; + var difat_start = 0; + + var fat_addrs = []; // locations of FAT sectors + + /* [MS-CFB] 2.2 Compound File Header */ + var blob = file.slice(0,512); + prep_blob(blob, 0); + + /* major version */ + var mv = check_get_mver(blob); + mver = mv[0]; + switch(mver) { + case 3: ssz = 512; break; case 4: ssz = 4096; break; + case 0: if(mv[1] == 0) return parse_zip(file, options); + /* falls through */ + default: throw new Error("Major Version: Expected 3 or 4 saw " + mver); + } + + /* reprocess header */ + if(ssz !== 512) { blob = file.slice(0,ssz); prep_blob(blob, 28 /* blob.l */); } + /* Save header for final object */ + var header = file.slice(0,ssz); + + check_shifts(blob, mver); + +// Number of Directory Sectors + var dir_cnt = blob.read_shift(4, 'i'); + if(mver === 3 && dir_cnt !== 0) throw new Error('# Directory Sectors: Expected 0 saw ' + dir_cnt); + +// Number of FAT Sectors + blob.l += 4; + +// First Directory Sector Location + dir_start = blob.read_shift(4, 'i'); + +// Transaction Signature + blob.l += 4; + +// Mini Stream Cutoff Size + blob.chk('00100000', 'Mini Stream Cutoff Size: '); + +// First Mini FAT Sector Location + minifat_start = blob.read_shift(4, 'i'); + +// Number of Mini FAT Sectors + nmfs = blob.read_shift(4, 'i'); + +// First DIFAT sector location + difat_start = blob.read_shift(4, 'i'); + +// Number of DIFAT Sectors + difat_sec_cnt = blob.read_shift(4, 'i'); + +// Grab FAT Sector Locations + for(var q = -1, j = 0; j < 109; ++j) { /* 109 = (512 - blob.l)>>>2; */ + q = blob.read_shift(4, 'i'); + if(q<0) break; + fat_addrs[j] = q; + } + + /** Break the file up into sectors */ + var sectors = sectorify(file, ssz); + + sleuth_fat(difat_start, difat_sec_cnt, sectors, ssz, fat_addrs); + + /** Chains */ + var sector_list = make_sector_list(sectors, dir_start, fat_addrs, ssz); + + sector_list[dir_start].name = "!Directory"; + if(nmfs > 0 && minifat_start !== ENDOFCHAIN) sector_list[minifat_start].name = "!MiniFAT"; + sector_list[fat_addrs[0]].name = "!FAT"; + sector_list.fat_addrs = fat_addrs; + sector_list.ssz = ssz; + + /* [MS-CFB] 2.6.1 Compound File Directory Entry */ + var files = {}, Paths = [], FileIndex = [], FullPaths = []; + read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex, minifat_start); + + build_full_paths(FileIndex, FullPaths, Paths); + Paths.shift(); + + var o = { + FileIndex: FileIndex, + FullPaths: FullPaths + }; + +// $FlowIgnore + if(options && options.raw) o.raw = {header: header, sectors: sectors}; + return o; + } // parse + + /* [MS-CFB] 2.2 Compound File Header -- read up to major version */ + function check_get_mver(blob) { + if(blob[blob.l] == 0x50 && blob[blob.l + 1] == 0x4b) return [0, 0]; + // header signature 8 + blob.chk(HEADER_SIGNATURE, 'Header Signature: '); + + // clsid 16 + blob.chk(HEADER_CLSID, 'CLSID: '); + + // minor version 2 + var mver = blob.read_shift(2, 'u'); + + return [blob.read_shift(2,'u'), mver]; + } + function check_shifts(blob, mver) { + var shift = 0x09; + + // Byte Order + //blob.chk('feff', 'Byte Order: '); // note: some writers put 0xffff + blob.l += 2; + + // Sector Shift + switch((shift = blob.read_shift(2))) { + case 0x09: if(mver != 3) throw new Error('Sector Shift: Expected 9 saw ' + shift); break; + case 0x0c: if(mver != 4) throw new Error('Sector Shift: Expected 12 saw ' + shift); break; + default: throw new Error('Sector Shift: Expected 9 or 12 saw ' + shift); + } + + // Mini Sector Shift + blob.chk('0600', 'Mini Sector Shift: '); + + // Reserved + blob.chk('000000000000', 'Reserved: '); + } + + /** Break the file up into sectors */ + function sectorify(file, ssz) { + var nsectors = Math.ceil(file.length/ssz)-1; + var sectors = []; + for(var i=1; i < nsectors; ++i) sectors[i-1] = file.slice(i*ssz,(i+1)*ssz); + sectors[nsectors-1] = file.slice(nsectors*ssz); + return sectors; + } + + /* [MS-CFB] 2.6.4 Red-Black Tree */ + function build_full_paths(FI, FP, Paths) { + var i = 0, L = 0, R = 0, C = 0, j = 0, pl = Paths.length; + var dad = [], q = []; + + for(; i < pl; ++i) { dad[i]=q[i]=i; FP[i]=Paths[i]; } + + for(; j < q.length; ++j) { + i = q[j]; + L = FI[i].L; R = FI[i].R; C = FI[i].C; + if(dad[i] === i) { + if(L !== -1 /*NOSTREAM*/ && dad[L] !== L) dad[i] = dad[L]; + if(R !== -1 && dad[R] !== R) dad[i] = dad[R]; + } + if(C !== -1 /*NOSTREAM*/) dad[C] = i; + if(L !== -1) { dad[L] = dad[i]; if(q.lastIndexOf(L) < j) q.push(L); } + if(R !== -1) { dad[R] = dad[i]; if(q.lastIndexOf(R) < j) q.push(R); } + } + for(i=1; i < pl; ++i) if(dad[i] === i) { + if(R !== -1 /*NOSTREAM*/ && dad[R] !== R) dad[i] = dad[R]; + else if(L !== -1 && dad[L] !== L) dad[i] = dad[L]; + } + + for(i=1; i < pl; ++i) { + if(FI[i].type === 0 /* unknown */) continue; + j = dad[i]; + if(j === 0) FP[i] = FP[0] + "/" + FP[i]; + else while(j !== 0 && j !== dad[j]) { + FP[i] = FP[j] + "/" + FP[i]; + j = dad[j]; + } + dad[i] = 0; + } + + FP[0] += "/"; + for(i=1; i < pl; ++i) { + if(FI[i].type !== 2 /* stream */) FP[i] += "/"; + } + } + + function get_mfat_entry(entry, payload, mini) { + var start = entry.start, size = entry.size; + //return (payload.slice(start*MSSZ, start*MSSZ + size)); + var o = []; + var idx = start; + while(mini && size > 0 && idx >= 0) { + o.push(payload.slice(idx * MSSZ, idx * MSSZ + MSSZ)); + size -= MSSZ; + idx = __readInt32LE(mini, idx * 4); + } + if(o.length === 0) return (new_buf(0)); + return (bconcat(o).slice(0, entry.size)); + } + + /** Chase down the rest of the DIFAT chain to build a comprehensive list + DIFAT chains by storing the next sector number as the last 32 bits */ + function sleuth_fat(idx, cnt, sectors, ssz, fat_addrs) { + var q = ENDOFCHAIN; + if(idx === ENDOFCHAIN) { + if(cnt !== 0) throw new Error("DIFAT chain shorter than expected"); + } else if(idx !== -1 /*FREESECT*/) { + var sector = sectors[idx], m = (ssz>>>2)-1; + if(!sector) return; + for(var i = 0; i < m; ++i) { + if((q = __readInt32LE(sector,i*4)) === ENDOFCHAIN) break; + fat_addrs.push(q); + } + sleuth_fat(__readInt32LE(sector,ssz-4),cnt - 1, sectors, ssz, fat_addrs); + } + } + + /** Follow the linked list of sectors for a given starting point */ + function get_sector_list(sectors, start, fat_addrs, ssz, chkd) { + var buf = [], buf_chain = []; + if(!chkd) chkd = []; + var modulus = ssz - 1, j = 0, jj = 0; + for(j=start; j>=0;) { + chkd[j] = true; + buf[buf.length] = j; + buf_chain.push(sectors[j]); + var addr = fat_addrs[Math.floor(j*4/ssz)]; + jj = ((j*4) & modulus); + if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz); + if(!sectors[addr]) break; + j = __readInt32LE(sectors[addr], jj); + } + return {nodes: buf, data:__toBuffer([buf_chain])}; + } + + /** Chase down the sector linked lists */ + function make_sector_list(sectors, dir_start, fat_addrs, ssz) { + var sl = sectors.length, sector_list = ([]); + var chkd = [], buf = [], buf_chain = []; + var modulus = ssz - 1, i=0, j=0, k=0, jj=0; + for(i=0; i < sl; ++i) { + buf = ([]); + k = (i + dir_start); if(k >= sl) k-=sl; + if(chkd[k]) continue; + buf_chain = []; + for(j=k; j>=0;) { + chkd[j] = true; + buf[buf.length] = j; + buf_chain.push(sectors[j]); + var addr = fat_addrs[Math.floor(j*4/ssz)]; + jj = ((j*4) & modulus); + if(ssz < 4 + jj) throw new Error("FAT boundary crossed: " + j + " 4 "+ssz); + if(!sectors[addr]) break; + j = __readInt32LE(sectors[addr], jj); + } + sector_list[k] = ({nodes: buf, data:__toBuffer([buf_chain])}); + } + return sector_list; + } + + /* [MS-CFB] 2.6.1 Compound File Directory Entry */ + function read_directory(dir_start, sector_list, sectors, Paths, nmfs, files, FileIndex, mini) { + var minifat_store = 0, pl = (Paths.length?2:0); + var sector = sector_list[dir_start].data; + var i = 0, namelen = 0, name; + for(; i < sector.length; i+= 128) { + var blob = sector.slice(i, i+128); + prep_blob(blob, 64); + namelen = blob.read_shift(2); + name = __utf16le(blob,0,namelen-pl); + Paths.push(name); + var o = ({ + name: name, + type: blob.read_shift(1), + color: blob.read_shift(1), + L: blob.read_shift(4, 'i'), + R: blob.read_shift(4, 'i'), + C: blob.read_shift(4, 'i'), + clsid: blob.read_shift(16), + state: blob.read_shift(4, 'i'), + start: 0, + size: 0 + }); + var ctime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(ctime !== 0) o.ct = read_date(blob, blob.l-8); + var mtime = blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2) + blob.read_shift(2); + if(mtime !== 0) o.mt = read_date(blob, blob.l-8); + o.start = blob.read_shift(4, 'i'); + o.size = blob.read_shift(4, 'i'); + if(o.size < 0 && o.start < 0) { o.size = o.type = 0; o.start = ENDOFCHAIN; o.name = ""; } + if(o.type === 5) { /* root */ + minifat_store = o.start; + if(nmfs > 0 && minifat_store !== ENDOFCHAIN) sector_list[minifat_store].name = "!StreamData"; + /*minifat_size = o.size;*/ + } else if(o.size >= 4096 /* MSCSZ */) { + o.storage = 'fat'; + if(sector_list[o.start] === undefined) sector_list[o.start] = get_sector_list(sectors, o.start, sector_list.fat_addrs, sector_list.ssz); + sector_list[o.start].name = o.name; + o.content = (sector_list[o.start].data.slice(0,o.size)); + } else { + o.storage = 'minifat'; + if(o.size < 0) o.size = 0; + else if(minifat_store !== ENDOFCHAIN && o.start !== ENDOFCHAIN && sector_list[minifat_store]) { + o.content = get_mfat_entry(o, sector_list[minifat_store].data, (sector_list[mini]||{}).data); + } + } + if(o.content) prep_blob(o.content, 0); + files[name] = o; + FileIndex.push(o); + } + } + + function read_date(blob, offset) { + return new Date(( ( (__readUInt32LE(blob,offset+4)/1e7)*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7 ) - 11644473600)*1000); + } + + function read_file(filename, options) { + get_fs(); + return parse(fs.readFileSync(filename), options); + } + + function read(blob, options) { + switch(options && options.type || "base64") { + case "file": return read_file(blob, options); + case "base64": return parse(s2a(Base64.decode(blob)), options); + case "binary": return parse(s2a(blob), options); + } + return parse(blob, options); + } + + function init_cfb(cfb, opts) { + var o = opts || {}, root = o.root || "Root Entry"; + if(!cfb.FullPaths) cfb.FullPaths = []; + if(!cfb.FileIndex) cfb.FileIndex = []; + if(cfb.FullPaths.length !== cfb.FileIndex.length) throw new Error("inconsistent CFB structure"); + if(cfb.FullPaths.length === 0) { + cfb.FullPaths[0] = root + "/"; + cfb.FileIndex[0] = ({ name: root, type: 5 }); + } + if(o.CLSID) cfb.FileIndex[0].clsid = o.CLSID; + seed_cfb(cfb); + } + function seed_cfb(cfb) { + var nm = "\u0001Sh33tJ5"; + if(CFB.find(cfb, "/" + nm)) return; + var p = new_buf(4); p[0] = 55; p[1] = p[3] = 50; p[2] = 54; + cfb.FileIndex.push(({ name: nm, type: 2, content:p, size:4, L:69, R:69, C:69 })); + cfb.FullPaths.push(cfb.FullPaths[0] + nm); + rebuild_cfb(cfb); + } + function rebuild_cfb(cfb, f) { + init_cfb(cfb); + var gc = false, s = false; + for(var i = cfb.FullPaths.length - 1; i >= 0; --i) { + var _file = cfb.FileIndex[i]; + switch(_file.type) { + case 0: + if(s) gc = true; + else { cfb.FileIndex.pop(); cfb.FullPaths.pop(); } + break; + case 1: case 2: case 5: + s = true; + if(isNaN(_file.R * _file.L * _file.C)) gc = true; + if(_file.R > -1 && _file.L > -1 && _file.R == _file.L) gc = true; + break; + default: gc = true; break; + } + } + if(!gc && !f) return; + + var now = new Date(1987, 1, 19), j = 0; + var data = []; + for(i = 0; i < cfb.FullPaths.length; ++i) { + if(cfb.FileIndex[i].type === 0) continue; + data.push([cfb.FullPaths[i], cfb.FileIndex[i]]); + } + for(i = 0; i < data.length; ++i) { + var dad = dirname(data[i][0]); + s = false; + for(j = 0; j < data.length; ++j) if(data[j][0] === dad) s = true; + if(!s) data.push([dad, ({ + name: filename(dad).replace("/",""), + type: 1, + clsid: HEADER_CLSID, + ct: now, mt: now, + content: null + })]); + } + + data.sort(function(x,y) { return namecmp(x[0], y[0]); }); + cfb.FullPaths = []; cfb.FileIndex = []; + for(i = 0; i < data.length; ++i) { cfb.FullPaths[i] = data[i][0]; cfb.FileIndex[i] = data[i][1]; } + for(i = 0; i < data.length; ++i) { + var elt = cfb.FileIndex[i]; + var nm = cfb.FullPaths[i]; + + elt.name = filename(nm).replace("/",""); + elt.L = elt.R = elt.C = -(elt.color = 1); + elt.size = elt.content ? elt.content.length : 0; + elt.start = 0; + elt.clsid = (elt.clsid || HEADER_CLSID); + if(i === 0) { + elt.C = data.length > 1 ? 1 : -1; + elt.size = 0; + elt.type = 5; + } else if(nm.slice(-1) == "/") { + for(j=i+1;j < data.length; ++j) if(dirname(cfb.FullPaths[j])==nm) break; + elt.C = j >= data.length ? -1 : j; + for(j=i+1;j < data.length; ++j) if(dirname(cfb.FullPaths[j])==dirname(nm)) break; + elt.R = j >= data.length ? -1 : j; + elt.type = 1; + } else { + if(dirname(cfb.FullPaths[i+1]||"") == dirname(nm)) elt.R = i + 1; + elt.type = 2; + } + } + + } + + function _write(cfb, options) { + var _opts = options || {}; + rebuild_cfb(cfb); + if(_opts.fileType == 'zip') return write_zip(cfb, _opts); + var L = (function(cfb){ + var mini_size = 0, fat_size = 0; + for(var i = 0; i < cfb.FileIndex.length; ++i) { + var file = cfb.FileIndex[i]; + if(!file.content) continue; + var flen = file.content.length; + if(flen > 0){ + if(flen < 0x1000) mini_size += (flen + 0x3F) >> 6; + else fat_size += (flen + 0x01FF) >> 9; + } + } + var dir_cnt = (cfb.FullPaths.length +3) >> 2; + var mini_cnt = (mini_size + 7) >> 3; + var mfat_cnt = (mini_size + 0x7F) >> 7; + var fat_base = mini_cnt + fat_size + dir_cnt + mfat_cnt; + var fat_cnt = (fat_base + 0x7F) >> 7; + var difat_cnt = fat_cnt <= 109 ? 0 : Math.ceil((fat_cnt-109)/0x7F); + while(((fat_base + fat_cnt + difat_cnt + 0x7F) >> 7) > fat_cnt) difat_cnt = ++fat_cnt <= 109 ? 0 : Math.ceil((fat_cnt-109)/0x7F); + var L = [1, difat_cnt, fat_cnt, mfat_cnt, dir_cnt, fat_size, mini_size, 0]; + cfb.FileIndex[0].size = mini_size << 6; + L[7] = (cfb.FileIndex[0].start=L[0]+L[1]+L[2]+L[3]+L[4]+L[5])+((L[6]+7) >> 3); + return L; + })(cfb); + var o = new_buf(L[7] << 9); + var i = 0, T = 0; + { + for(i = 0; i < 8; ++i) o.write_shift(1, HEADER_SIG[i]); + for(i = 0; i < 8; ++i) o.write_shift(2, 0); + o.write_shift(2, 0x003E); + o.write_shift(2, 0x0003); + o.write_shift(2, 0xFFFE); + o.write_shift(2, 0x0009); + o.write_shift(2, 0x0006); + for(i = 0; i < 3; ++i) o.write_shift(2, 0); + o.write_shift(4, 0); + o.write_shift(4, L[2]); + o.write_shift(4, L[0] + L[1] + L[2] + L[3] - 1); + o.write_shift(4, 0); + o.write_shift(4, 1<<12); + o.write_shift(4, L[3] ? L[0] + L[1] + L[2] - 1: ENDOFCHAIN); + o.write_shift(4, L[3]); + o.write_shift(-4, L[1] ? L[0] - 1: ENDOFCHAIN); + o.write_shift(4, L[1]); + for(i = 0; i < 109; ++i) o.write_shift(-4, i < L[2] ? L[1] + i : -1); + } + if(L[1]) { + for(T = 0; T < L[1]; ++T) { + for(; i < 236 + T * 127; ++i) o.write_shift(-4, i < L[2] ? L[1] + i : -1); + o.write_shift(-4, T === L[1] - 1 ? ENDOFCHAIN : T + 1); + } + } + var chainit = function(w) { + for(T += w; i> 9); + } + chainit((L[6] + 7) >> 3); + while(o.l & 0x1FF) o.write_shift(-4, consts.ENDOFCHAIN); + T = i = 0; + for(j = 0; j < cfb.FileIndex.length; ++j) { + file = cfb.FileIndex[j]; + if(!file.content) continue; + flen = file.content.length; + if(!flen || flen >= 0x1000) continue; + file.start = T; + chainit((flen + 0x3F) >> 6); + } + while(o.l & 0x1FF) o.write_shift(-4, consts.ENDOFCHAIN); + for(i = 0; i < L[4]<<2; ++i) { + var nm = cfb.FullPaths[i]; + if(!nm || nm.length === 0) { + for(j = 0; j < 17; ++j) o.write_shift(4, 0); + for(j = 0; j < 3; ++j) o.write_shift(4, -1); + for(j = 0; j < 12; ++j) o.write_shift(4, 0); + continue; + } + file = cfb.FileIndex[i]; + if(i === 0) file.start = file.size ? file.start - 1 : ENDOFCHAIN; + var _nm = (i === 0 && _opts.root) || file.name; + flen = 2*(_nm.length+1); + o.write_shift(64, _nm, "utf16le"); + o.write_shift(2, flen); + o.write_shift(1, file.type); + o.write_shift(1, file.color); + o.write_shift(-4, file.L); + o.write_shift(-4, file.R); + o.write_shift(-4, file.C); + if(!file.clsid) for(j = 0; j < 4; ++j) o.write_shift(4, 0); + else o.write_shift(16, file.clsid, "hex"); + o.write_shift(4, file.state || 0); + o.write_shift(4, 0); o.write_shift(4, 0); + o.write_shift(4, 0); o.write_shift(4, 0); + o.write_shift(4, file.start); + o.write_shift(4, file.size); o.write_shift(4, 0); + } + for(i = 1; i < cfb.FileIndex.length; ++i) { + file = cfb.FileIndex[i]; + if(file.size >= 0x1000) { + o.l = (file.start+1) << 9; + for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]); + for(; j & 0x1FF; ++j) o.write_shift(1, 0); + } + } + for(i = 1; i < cfb.FileIndex.length; ++i) { + file = cfb.FileIndex[i]; + if(file.size > 0 && file.size < 0x1000) { + for(j = 0; j < file.size; ++j) o.write_shift(1, file.content[j]); + for(; j & 0x3F; ++j) o.write_shift(1, 0); + } + } + while(o.l < o.length) o.write_shift(1, 0); + return o; + } + /* [MS-CFB] 2.6.4 (Unicode 3.0.1 case conversion) */ + function find(cfb, path) { + var UCFullPaths = cfb.FullPaths.map(function(x) { return x.toUpperCase(); }); + var UCPaths = UCFullPaths.map(function(x) { var y = x.split("/"); return y[y.length - (x.slice(-1) == "/" ? 2 : 1)]; }); + var k = false; + if(path.charCodeAt(0) === 47 /* "/" */) { k = true; path = UCFullPaths[0].slice(0, -1) + path; } + else k = path.indexOf("/") !== -1; + var UCPath = path.toUpperCase(); + var w = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath); + if(w !== -1) return cfb.FileIndex[w]; + + var m = !UCPath.match(chr1); + UCPath = UCPath.replace(chr0,''); + if(m) UCPath = UCPath.replace(chr1,'!'); + for(w = 0; w < UCFullPaths.length; ++w) { + if((m ? UCFullPaths[w].replace(chr1,'!') : UCFullPaths[w]).replace(chr0,'') == UCPath) return cfb.FileIndex[w]; + if((m ? UCPaths[w].replace(chr1,'!') : UCPaths[w]).replace(chr0,'') == UCPath) return cfb.FileIndex[w]; + } + return null; + } + /** CFB Constants */ + var MSSZ = 64; /* Mini Sector Size = 1<<6 */ +//var MSCSZ = 4096; /* Mini Stream Cutoff Size */ + /* 2.1 Compound File Sector Numbers and Types */ + var ENDOFCHAIN = -2; + /* 2.2 Compound File Header */ + var HEADER_SIGNATURE = 'd0cf11e0a1b11ae1'; + var HEADER_SIG = [0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]; + var HEADER_CLSID = '00000000000000000000000000000000'; + var consts = { + /* 2.1 Compund File Sector Numbers and Types */ + MAXREGSECT: -6, + DIFSECT: -4, + FATSECT: -3, + ENDOFCHAIN: ENDOFCHAIN, + FREESECT: -1, + /* 2.2 Compound File Header */ + HEADER_SIGNATURE: HEADER_SIGNATURE, + HEADER_MINOR_VERSION: '3e00', + MAXREGSID: -6, + NOSTREAM: -1, + HEADER_CLSID: HEADER_CLSID, + /* 2.6.1 Compound File Directory Entry */ + EntryTypes: ['unknown','storage','stream','lockbytes','property','root'] + }; + + function write_file(cfb, filename, options) { + get_fs(); + var o = _write(cfb, options); + fs.writeFileSync(filename, o); + } + + function a2s(o) { + var out = new Array(o.length); + for(var i = 0; i < o.length; ++i) out[i] = String.fromCharCode(o[i]); + return out.join(""); + } + + function write(cfb, options) { + var o = _write(cfb, options); + switch(options && options.type) { + case "file": get_fs(); fs.writeFileSync(options.filename, (o)); return o; + case "binary": return a2s(o); + case "base64": return Base64.encode(a2s(o)); + } + return o; + } + /* node < 8.1 zlib does not expose bytesRead, so default to pure JS */ + var _zlib; + function use_zlib(zlib) { try { + var InflateRaw = zlib.InflateRaw; + var InflRaw = new InflateRaw(); + InflRaw._processChunk(new Uint8Array([3, 0]), InflRaw._finishFlushFlag); + if(InflRaw.bytesRead) _zlib = zlib; + else throw new Error("zlib does not expose bytesRead"); + } catch(e) {console.error("cannot use native zlib: " + (e.message || e)); } } + + function _inflateRawSync(payload, usz) { + if(!_zlib) return _inflate(payload, usz); + var InflateRaw = _zlib.InflateRaw; + var InflRaw = new InflateRaw(); + var out = InflRaw._processChunk(payload.slice(payload.l), InflRaw._finishFlushFlag); + payload.l += InflRaw.bytesRead; + return out; + } + + function _deflateRawSync(payload) { + return _zlib ? _zlib.deflateRawSync(payload) : _deflate(payload); + } + var CLEN_ORDER = [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; + + /* LEN_ID = [ 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285 ]; */ + var LEN_LN = [ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13 , 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 ]; + + /* DST_ID = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 ]; */ + var DST_LN = [ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 ]; + + function bit_swap_8(n) { var t = (((((n<<1)|(n<<11)) & 0x22110) | (((n<<5)|(n<<15)) & 0x88440))); return ((t>>16) | (t>>8) |t)&0xFF; } + + var use_typed_arrays = typeof Uint8Array !== 'undefined'; + + var bitswap8 = use_typed_arrays ? new Uint8Array(1<<8) : []; + for(var q = 0; q < (1<<8); ++q) bitswap8[q] = bit_swap_8(q); + + function bit_swap_n(n, b) { + var rev = bitswap8[n & 0xFF]; + if(b <= 8) return rev >>> (8-b); + rev = (rev << 8) | bitswap8[(n>>8)&0xFF]; + if(b <= 16) return rev >>> (16-b); + rev = (rev << 8) | bitswap8[(n>>16)&0xFF]; + return rev >>> (24-b); + } + + /* helpers for unaligned bit reads */ + function read_bits_2(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 6 ? 0 : buf[h+1]<<8))>>>w)& 0x03; } + function read_bits_3(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 5 ? 0 : buf[h+1]<<8))>>>w)& 0x07; } + function read_bits_4(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 4 ? 0 : buf[h+1]<<8))>>>w)& 0x0F; } + function read_bits_5(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 3 ? 0 : buf[h+1]<<8))>>>w)& 0x1F; } + function read_bits_7(buf, bl) { var w = (bl&7), h = (bl>>>3); return ((buf[h]|(w <= 1 ? 0 : buf[h+1]<<8))>>>w)& 0x7F; } + + /* works up to n = 3 * 8 + 1 = 25 */ + function read_bits_n(buf, bl, n) { + var w = (bl&7), h = (bl>>>3), f = ((1<>> w; + if(n < 8 - w) return v & f; + v |= buf[h+1]<<(8-w); + if(n < 16 - w) return v & f; + v |= buf[h+2]<<(16-w); + if(n < 24 - w) return v & f; + v |= buf[h+3]<<(24-w); + return v & f; + } + + /* until ArrayBuffer#realloc is a thing, fake a realloc */ + function realloc(b, sz) { + var L = b.length, M = 2*L > sz ? 2*L : sz + 5, i = 0; + if(L >= sz) return b; + if(has_buf) { + var o = new_unsafe_buf(M); + // $FlowIgnore + if(b.copy) b.copy(o); + else for(; i < b.length; ++i) o[i] = b[i]; + return o; + } else if(use_typed_arrays) { + var a = new Uint8Array(M); + if(a.set) a.set(b); + else for(; i < b.length; ++i) a[i] = b[i]; + return a; + } + b.length = M; + return b; + } + + /* zero-filled arrays for older browsers */ + function zero_fill_array(n) { + var o = new Array(n); + for(var i = 0; i < n; ++i) o[i] = 0; + return o; + }var _deflate = (function() { + var _deflateRaw = (function() { + return function deflateRaw(data, out) { + var boff = 0; + while(boff < data.length) { + var L = Math.min(0xFFFF, data.length - boff); + var h = boff + L == data.length; + /* TODO: this is only type 0 stored */ + out.write_shift(1, +h); + out.write_shift(2, L); + out.write_shift(2, (~L) & 0xFFFF); + while(L-- > 0) out[out.l++] = data[boff++]; + } + return out.l; + }; + })(); + + return function(data) { + var buf = new_buf(50+Math.floor(data.length*1.1)); + var off = _deflateRaw(data, buf); + return buf.slice(0, off); + }; + })(); + /* modified inflate function also moves original read head */ + + /* build tree (used for literals and lengths) */ + function build_tree(clens, cmap, MAX) { + var maxlen = 1, w = 0, i = 0, j = 0, ccode = 0, L = clens.length; + + var bl_count = use_typed_arrays ? new Uint16Array(32) : zero_fill_array(32); + for(i = 0; i < 32; ++i) bl_count[i] = 0; + + for(i = L; i < MAX; ++i) clens[i] = 0; + L = clens.length; + + var ctree = use_typed_arrays ? new Uint16Array(L) : zero_fill_array(L); // [] + + /* build code tree */ + for(i = 0; i < L; ++i) { + bl_count[(w = clens[i])]++; + if(maxlen < w) maxlen = w; + ctree[i] = 0; + } + bl_count[0] = 0; + for(i = 1; i <= maxlen; ++i) bl_count[i+16] = (ccode = (ccode + bl_count[i-1])<<1); + for(i = 0; i < L; ++i) { + ccode = clens[i]; + if(ccode != 0) ctree[i] = bl_count[ccode+16]++; + } + + /* cmap[maxlen + 4 bits] = (off&15) + (lit<<4) reverse mapping */ + var cleni = 0; + for(i = 0; i < L; ++i) { + cleni = clens[i]; + if(cleni != 0) { + ccode = bit_swap_n(ctree[i], maxlen)>>(maxlen-cleni); + for(j = (1<<(maxlen + 4 - cleni)) - 1; j>=0; --j) + cmap[ccode|(j<>(8-cleni); + for(var j = (1<<(7-cleni))-1; j>=0; --j) dyn_cmap[ccode|(j<>>= 3)) { + case 16: + w = 3 + read_bits_2(data, boff); boff += 2; + ccode = hcodes[hcodes.length - 1]; + while(w-- > 0) hcodes.push(ccode); + break; + case 17: + w = 3 + read_bits_3(data, boff); boff += 3; + while(w-- > 0) hcodes.push(0); + break; + case 18: + w = 11 + read_bits_7(data, boff); boff += 7; + while(w -- > 0) hcodes.push(0); + break; + default: + hcodes.push(ccode); + if(maxlen < ccode) maxlen = ccode; + break; + } + } + + /* build literal / length trees */ + var h1 = hcodes.slice(0, _HLIT), h2 = hcodes.slice(_HLIT); + for(i = _HLIT; i < 286; ++i) h1[i] = 0; + for(i = _HDIST; i < 30; ++i) h2[i] = 0; + dyn_len_1 = build_tree(h1, dyn_lmap, 286); + dyn_len_2 = build_tree(h2, dyn_dmap, 30); + return boff; + } + + /* return [ data, bytesRead ] */ + function inflate(data, usz) { + /* shortcircuit for empty buffer [0x03, 0x00] */ + if(data[0] == 3 && !(data[1] & 0x3)) { return [new_raw_buf(usz), 2]; } + + /* bit offset */ + var boff = 0; + + /* header includes final bit and type bits */ + var header = 0; + + var outbuf = new_unsafe_buf(usz ? usz : (1<<18)); + var woff = 0; + var OL = outbuf.length>>>0; + var max_len_1 = 0, max_len_2 = 0; + + while((header&1) == 0) { + header = read_bits_3(data, boff); boff += 3; + if((header >>> 1) == 0) { + /* Stored block */ + if(boff & 7) boff += 8 - (boff&7); + /* 2 bytes sz, 2 bytes bit inverse */ + var sz = data[boff>>>3] | data[(boff>>>3)+1]<<8; + boff += 32; + /* push sz bytes */ + if(!usz && OL < woff + sz) { outbuf = realloc(outbuf, woff + sz); OL = outbuf.length; } + if(typeof data.copy === 'function') { + // $FlowIgnore + data.copy(outbuf, woff, boff>>>3, (boff>>>3)+sz); + woff += sz; boff += 8*sz; + } else while(sz-- > 0) { outbuf[woff++] = data[boff>>>3]; boff += 8; } + continue; + } else if((header >>> 1) == 1) { + /* Fixed Huffman */ + max_len_1 = 9; max_len_2 = 5; + } else { + /* Dynamic Huffman */ + boff = dyn(data, boff); + max_len_1 = dyn_len_1; max_len_2 = dyn_len_2; + } + if(!usz && (OL < woff + 32767)) { outbuf = realloc(outbuf, woff + 32767); OL = outbuf.length; } + for(;;) { // while(true) is apparently out of vogue in modern JS circles + /* ingest code and move read head */ + var bits = read_bits_n(data, boff, max_len_1); + var code = (header>>>1) == 1 ? fix_lmap[bits] : dyn_lmap[bits]; + boff += code & 15; code >>>= 4; + /* 0-255 are literals, 256 is end of block token, 257+ are copy tokens */ + if(((code>>>8)&0xFF) === 0) outbuf[woff++] = code; + else if(code == 256) break; + else { + code -= 257; + var len_eb = (code < 8) ? 0 : ((code-4)>>2); if(len_eb > 5) len_eb = 0; + var tgt = woff + LEN_LN[code]; + /* length extra bits */ + if(len_eb > 0) { + tgt += read_bits_n(data, boff, len_eb); + boff += len_eb; + } + + /* dist code */ + bits = read_bits_n(data, boff, max_len_2); + code = (header>>>1) == 1 ? fix_dmap[bits] : dyn_dmap[bits]; + boff += code & 15; code >>>= 4; + var dst_eb = (code < 4 ? 0 : (code-2)>>1); + var dst = DST_LN[code]; + /* dist extra bits */ + if(dst_eb > 0) { + dst += read_bits_n(data, boff, dst_eb); + boff += dst_eb; + } + + /* in the common case, manual byte copy is faster than TA set / Buffer copy */ + if(!usz && OL < tgt) { outbuf = realloc(outbuf, tgt); OL = outbuf.length; } + while(woff < tgt) { outbuf[woff] = outbuf[woff - dst]; ++woff; } + } + } + } + return [usz ? outbuf : outbuf.slice(0, woff), (boff+7)>>>3]; + } + + function _inflate(payload, usz) { + var data = payload.slice(payload.l||0); + var out = inflate(data, usz); + payload.l += out[1]; + return out[0]; + } + + function warn_or_throw(wrn, msg) { + if(wrn) { if(typeof console !== 'undefined') console.error(msg); } + else throw new Error(msg); + } + + function parse_zip(file, options) { + var blob = file; + prep_blob(blob, 0); + + var FileIndex = [], FullPaths = []; + var o = { + FileIndex: FileIndex, + FullPaths: FullPaths + }; + init_cfb(o, { root: options.root }); + + /* find end of central directory, start just after signature */ + var i = blob.length - 4; + while((blob[i] != 0x50 || blob[i+1] != 0x4b || blob[i+2] != 0x05 || blob[i+3] != 0x06) && i >= 0) --i; + blob.l = i + 4; + + /* parse end of central directory */ + blob.l += 4; + var fcnt = blob.read_shift(2); + blob.l += 6; + var start_cd = blob.read_shift(4); + + /* parse central directory */ + blob.l = start_cd; + + for(i = 0; i < fcnt; ++i) { + /* trust local file header instead of CD entry */ + blob.l += 20; + var csz = blob.read_shift(4); + var usz = blob.read_shift(4); + var namelen = blob.read_shift(2); + var efsz = blob.read_shift(2); + var fcsz = blob.read_shift(2); + blob.l += 8; + var offset = blob.read_shift(4); + var EF = parse_extra_field(blob.slice(blob.l+namelen, blob.l+namelen+efsz)); + blob.l += namelen + efsz + fcsz; + + var L = blob.l; + blob.l = offset + 4; + parse_local_file(blob, csz, usz, o, EF); + blob.l = L; + } + + return o; + } + + + /* head starts just after local file header signature */ + function parse_local_file(blob, csz, usz, o, EF) { + /* [local file header] */ + blob.l += 2; + var flags = blob.read_shift(2); + var meth = blob.read_shift(2); + var date = parse_dos_date(blob); + + if(flags & 0x2041) throw new Error("Unsupported ZIP encryption"); + var crc32 = blob.read_shift(4); + var _csz = blob.read_shift(4); + var _usz = blob.read_shift(4); + + var namelen = blob.read_shift(2); + var efsz = blob.read_shift(2); + + // TODO: flags & (1<<11) // UTF8 + var name = ""; for(var i = 0; i < namelen; ++i) name += String.fromCharCode(blob[blob.l++]); + if(efsz) { + var ef = parse_extra_field(blob.slice(blob.l, blob.l + efsz)); + if((ef[0x5455]||{}).mt) date = ef[0x5455].mt; + if(((EF||{})[0x5455]||{}).mt) date = EF[0x5455].mt; + } + blob.l += efsz; + + /* [encryption header] */ + + /* [file data] */ + var data = blob.slice(blob.l, blob.l + _csz); + switch(meth) { + case 8: data = _inflateRawSync(blob, _usz); break; + case 0: break; + default: throw new Error("Unsupported ZIP Compression method " + meth); + } + + /* [data descriptor] */ + var wrn = false; + if(flags & 8) { + crc32 = blob.read_shift(4); + if(crc32 == 0x08074b50) { crc32 = blob.read_shift(4); wrn = true; } + _csz = blob.read_shift(4); + _usz = blob.read_shift(4); + } + + if(_csz != csz) warn_or_throw(wrn, "Bad compressed size: " + csz + " != " + _csz); + if(_usz != usz) warn_or_throw(wrn, "Bad uncompressed size: " + usz + " != " + _usz); + var _crc32 = CRC32.buf(data, 0); + if(crc32 != _crc32) warn_or_throw(wrn, "Bad CRC32 checksum: " + crc32 + " != " + _crc32); + cfb_add(o, name, data, {unsafe: true, mt: date}); + } + function write_zip(cfb, options) { + var _opts = options || {}; + var out = [], cdirs = []; + var o = new_buf(1); + var method = (_opts.compression ? 8 : 0), flags = 0; + var desc = false; + if(desc) flags |= 8; + var i = 0, j = 0; + + var start_cd = 0, fcnt = 0; + var root = cfb.FullPaths[0], fp = root, fi = cfb.FileIndex[0]; + var crcs = []; + var sz_cd = 0; + + for(i = 1; i < cfb.FullPaths.length; ++i) { + fp = cfb.FullPaths[i].slice(root.length); fi = cfb.FileIndex[i]; + if(!fi.size || !fi.content || fp == "\u0001Sh33tJ5") continue; + var start = start_cd; + + /* TODO: CP437 filename */ + var namebuf = new_buf(fp.length); + for(j = 0; j < fp.length; ++j) namebuf.write_shift(1, fp.charCodeAt(j) & 0x7F); + namebuf = namebuf.slice(0, namebuf.l); + crcs[fcnt] = CRC32.buf(fi.content, 0); + + var outbuf = fi.content; + if(method == 8) outbuf = _deflateRawSync(outbuf); + + /* local file header */ + o = new_buf(30); + o.write_shift(4, 0x04034b50); + o.write_shift(2, 20); + o.write_shift(2, flags); + o.write_shift(2, method); + /* TODO: last mod file time/date */ + if(fi.mt) write_dos_date(o, fi.mt); + else o.write_shift(4, 0); + o.write_shift(-4, (flags & 8) ? 0 : crcs[fcnt]); + o.write_shift(4, (flags & 8) ? 0 : outbuf.length); + o.write_shift(4, (flags & 8) ? 0 : fi.content.length); + o.write_shift(2, namebuf.length); + o.write_shift(2, 0); + + start_cd += o.length; + out.push(o); + start_cd += namebuf.length; + out.push(namebuf); + + /* TODO: encryption header ? */ + start_cd += outbuf.length; + out.push(outbuf); + + /* data descriptor */ + if(flags & 8) { + o = new_buf(12); + o.write_shift(-4, crcs[fcnt]); + o.write_shift(4, outbuf.length); + o.write_shift(4, fi.content.length); + start_cd += o.l; + out.push(o); + } + + /* central directory */ + o = new_buf(46); + o.write_shift(4, 0x02014b50); + o.write_shift(2, 0); + o.write_shift(2, 20); + o.write_shift(2, flags); + o.write_shift(2, method); + o.write_shift(4, 0); /* TODO: last mod file time/date */ + o.write_shift(-4, crcs[fcnt]); + + o.write_shift(4, outbuf.length); + o.write_shift(4, fi.content.length); + o.write_shift(2, namebuf.length); + o.write_shift(2, 0); + o.write_shift(2, 0); + o.write_shift(2, 0); + o.write_shift(2, 0); + o.write_shift(4, 0); + o.write_shift(4, start); + + sz_cd += o.l; + cdirs.push(o); + sz_cd += namebuf.length; + cdirs.push(namebuf); + ++fcnt; + } + + /* end of central directory */ + o = new_buf(22); + o.write_shift(4, 0x06054b50); + o.write_shift(2, 0); + o.write_shift(2, 0); + o.write_shift(2, fcnt); + o.write_shift(2, fcnt); + o.write_shift(4, sz_cd); + o.write_shift(4, start_cd); + o.write_shift(2, 0); + + return bconcat(([bconcat((out)), bconcat(cdirs), o])); + } + function cfb_new(opts) { + var o = ({}); + init_cfb(o, opts); + return o; + } + + function cfb_add(cfb, name, content, opts) { + var unsafe = opts && opts.unsafe; + if(!unsafe) init_cfb(cfb); + var file = !unsafe && CFB.find(cfb, name); + if(!file) { + var fpath = cfb.FullPaths[0]; + if(name.slice(0, fpath.length) == fpath) fpath = name; + else { + if(fpath.slice(-1) != "/") fpath += "/"; + fpath = (fpath + name).replace("//","/"); + } + file = ({name: filename(name), type: 2}); + cfb.FileIndex.push(file); + cfb.FullPaths.push(fpath); + if(!unsafe) CFB.utils.cfb_gc(cfb); + } + file.content = (content); + file.size = content ? content.length : 0; + if(opts) { + if(opts.CLSID) file.clsid = opts.CLSID; + if(opts.mt) file.mt = opts.mt; + if(opts.ct) file.ct = opts.ct; + } + return file; + } + + function cfb_del(cfb, name) { + init_cfb(cfb); + var file = CFB.find(cfb, name); + if(file) for(var j = 0; j < cfb.FileIndex.length; ++j) if(cfb.FileIndex[j] == file) { + cfb.FileIndex.splice(j, 1); + cfb.FullPaths.splice(j, 1); + return true; + } + return false; + } + + function cfb_mov(cfb, old_name, new_name) { + init_cfb(cfb); + var file = CFB.find(cfb, old_name); + if(file) for(var j = 0; j < cfb.FileIndex.length; ++j) if(cfb.FileIndex[j] == file) { + cfb.FileIndex[j].name = filename(new_name); + cfb.FullPaths[j] = new_name; + return true; + } + return false; + } + + function cfb_gc(cfb) { rebuild_cfb(cfb, true); } + + exports.find = find; + exports.read = read; + exports.parse = parse; + exports.write = write; + exports.writeFile = write_file; + exports.utils = { + cfb_new: cfb_new, + cfb_add: cfb_add, + cfb_del: cfb_del, + cfb_mov: cfb_mov, + cfb_gc: cfb_gc, + ReadShift: ReadShift, + CheckField: CheckField, + prep_blob: prep_blob, + bconcat: bconcat, + use_zlib: use_zlib, + _deflateRaw: _deflate, + _inflateRaw: _inflate, + consts: consts + }; + + return exports; + })(); + + if(typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO_NOT_EXPORT_CFB === 'undefined') { module.exports = CFB; } + var _fs; + if(typeof require !== 'undefined') try { _fs = require('fs'); } catch(e) {} + + /* normalize data for blob ctor */ + function blobify(data) { + if(typeof data === "string") return s2ab(data); + if(Array.isArray(data)) return a2u(data); + return data; + } + /* write or download file */ + function write_dl(fname, payload, enc) { + /*global IE_SaveFile, Blob, navigator, saveAs, URL, document, File, chrome */ + if(typeof _fs !== 'undefined' && _fs.writeFileSync) return enc ? _fs.writeFileSync(fname, payload, enc) : _fs.writeFileSync(fname, payload); + var data = (enc == "utf8") ? utf8write(payload) : payload; + if(typeof IE_SaveFile !== 'undefined') return IE_SaveFile(data, fname); + if(typeof Blob !== 'undefined') { + var blob = new Blob([blobify(data)], {type:"application/octet-stream"}); + if(typeof navigator !== 'undefined' && navigator.msSaveBlob) return navigator.msSaveBlob(blob, fname); + if(typeof saveAs !== 'undefined') return saveAs(blob, fname); + if(typeof URL !== 'undefined' && typeof document !== 'undefined' && document.createElement && URL.createObjectURL) { + var url = URL.createObjectURL(blob); + if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") { + if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000); + return chrome.downloads.download({ url: url, filename: fname, saveAs: true}); + } + var a = document.createElement("a"); + if(a.download != null) { + a.download = fname; a.href = url; document.body.appendChild(a); a.click(); + document.body.removeChild(a); + if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000); + return url; + } + } + } + // $FlowIgnore + if(typeof $ !== 'undefined' && typeof File !== 'undefined' && typeof Folder !== 'undefined') try { // extendscript + // $FlowIgnore + var out = File(fname); out.open("w"); out.encoding = "binary"; + if(Array.isArray(payload)) payload = a2s(payload); + out.write(payload); out.close(); return payload; + } catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; } + throw new Error("cannot save file " + fname); + } + + /* read binary data from file */ + function read_binary(path) { + if(typeof _fs !== 'undefined') return _fs.readFileSync(path); + // $FlowIgnore + if(typeof $ !== 'undefined' && typeof File !== 'undefined' && typeof Folder !== 'undefined') try { // extendscript + // $FlowIgnore + var infile = File(path); infile.open("r"); infile.encoding = "binary"; + var data = infile.read(); infile.close(); + return data; + } catch(e) { if(!e.message || !e.message.match(/onstruct/)) throw e; } + throw new Error("Cannot access file " + path); + } + function keys(o) { + var ks = Object.keys(o), o2 = []; + for(var i = 0; i < ks.length; ++i) if(o.hasOwnProperty(ks[i])) o2.push(ks[i]); + return o2; + } + + function evert_key(obj, key) { + var o = ([]), K = keys(obj); + for(var i = 0; i !== K.length; ++i) if(o[obj[K[i]][key]] == null) o[obj[K[i]][key]] = K[i]; + return o; + } + + function evert(obj) { + var o = ([]), K = keys(obj); + for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = K[i]; + return o; + } + + function evert_num(obj) { + var o = ([]), K = keys(obj); + for(var i = 0; i !== K.length; ++i) o[obj[K[i]]] = parseInt(K[i],10); + return o; + } + + function evert_arr(obj) { + var o = ([]), K = keys(obj); + for(var i = 0; i !== K.length; ++i) { + if(o[obj[K[i]]] == null) o[obj[K[i]]] = []; + o[obj[K[i]]].push(K[i]); + } + return o; + } + + var basedate = new Date(1899, 11, 30, 0, 0, 0); // 2209161600000 + var dnthresh = basedate.getTime() + (new Date().getTimezoneOffset() - basedate.getTimezoneOffset()) * 60000; + function datenum(v, date1904) { + var epoch = v.getTime(); + if(date1904) epoch -= 1462*24*60*60*1000; + return (epoch - dnthresh) / (24 * 60 * 60 * 1000); + } + function numdate(v) { + var out = new Date(); + out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh); + return out; + } + + /* ISO 8601 Duration */ + function parse_isodur(s) { + var sec = 0, mt = 0, time = false; + var m = s.match(/P([0-9\.]+Y)?([0-9\.]+M)?([0-9\.]+D)?T([0-9\.]+H)?([0-9\.]+M)?([0-9\.]+S)?/); + if(!m) throw new Error("|" + s + "| is not an ISO8601 Duration"); + for(var i = 1; i != m.length; ++i) { + if(!m[i]) continue; + mt = 1; + if(i > 3) time = true; + switch(m[i].slice(m[i].length-1)) { + case 'Y': + throw new Error("Unsupported ISO Duration Field: " + m[i].slice(m[i].length-1)); + case 'D': mt *= 24; + /* falls through */ + case 'H': mt *= 60; + /* falls through */ + case 'M': + if(!time) throw new Error("Unsupported ISO Duration Field: M"); + else mt *= 60; + /* falls through */ + case 'S': break; + } + sec += mt * parseInt(m[i], 10); + } + return sec; + } + + var good_pd_date = new Date('2017-02-19T19:06:09.000Z'); + if(isNaN(good_pd_date.getFullYear())) good_pd_date = new Date('2/19/17'); + var good_pd = good_pd_date.getFullYear() == 2017; + /* parses a date as a local date */ + function parseDate(str, fixdate) { + var d = new Date(str); + if(good_pd) { + if(fixdate > 0) d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000); + else if(fixdate < 0) d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000); + return d; + } + if(str instanceof Date) return str; + if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) { + var s = d.getFullYear(); + if(str.indexOf("" + s) > -1) return d; + d.setFullYear(d.getFullYear() + 100); return d; + } + var n = str.match(/\d+/g)||["2017","2","19","0","0","0"]; + var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0)); + if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000); + return out; + } + + function cc2str(arr) { + var o = ""; + for(var i = 0; i != arr.length; ++i) o += String.fromCharCode(arr[i]); + return o; + } + + function dup(o) { + if(typeof JSON != 'undefined' && !Array.isArray(o)) return JSON.parse(JSON.stringify(o)); + if(typeof o != 'object' || o == null) return o; + if(o instanceof Date) return new Date(o.getTime()); + var out = {}; + for(var k in o) if(o.hasOwnProperty(k)) out[k] = dup(o[k]); + return out; + } + + function fill(c,l) { var o = ""; while(o.length < l) o+=c; return o; } + + /* TODO: stress test */ + function fuzzynum(s) { + var v = Number(s); + if(!isNaN(v)) return v; + var wt = 1; + var ss = s.replace(/([\d]),([\d])/g,"$1$2").replace(/[$]/g,"").replace(/[%]/g, function() { wt *= 100; return "";}); + if(!isNaN(v = Number(ss))) return v / wt; + ss = ss.replace(/[(](.*)[)]/,function($$, $1) { wt = -wt; return $1;}); + if(!isNaN(v = Number(ss))) return v / wt; + return v; + } + function fuzzydate(s) { + var o = new Date(s), n = new Date(NaN); + var y = o.getYear(), m = o.getMonth(), d = o.getDate(); + if(isNaN(d)) return n; + if(y < 0 || y > 8099) return n; + if((m > 0 || d > 1) && y != 101) return o; + if(s.toLowerCase().match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) return o; + if(s.match(/[^-0-9:,\/\\]/)) return n; + return o; + } + + var safe_split_regex = "abacaba".split(/(:?b)/i).length == 5; + function split_regex(str, re, def) { + if(safe_split_regex || typeof re == "string") return str.split(re); + var p = str.split(re), o = [p[0]]; + for(var i = 1; i < p.length; ++i) { o.push(def); o.push(p[i]); } + return o; + } + function getdatastr(data) { + if(!data) return null; + if(data.data) return debom(data.data); + if(data.asNodeBuffer && has_buf) return debom(data.asNodeBuffer().toString('binary')); + if(data.asBinary) return debom(data.asBinary()); + if(data._data && data._data.getContent) return debom(cc2str(Array.prototype.slice.call(data._data.getContent(),0))); + return null; + } + + function getdatabin(data) { + if(!data) return null; + if(data.data) return char_codes(data.data); + if(data.asNodeBuffer && has_buf) return data.asNodeBuffer(); + if(data._data && data._data.getContent) { + var o = data._data.getContent(); + if(typeof o == "string") return char_codes(o); + return Array.prototype.slice.call(o); + } + return null; + } + + function getdata(data) { return (data && data.name.slice(-4) === ".bin") ? getdatabin(data) : getdatastr(data); } + + /* Part 2 Section 10.1.2 "Mapping Content Types" Names are case-insensitive */ + /* OASIS does not comment on filename case sensitivity */ + function safegetzipfile(zip, file) { + var k = keys(zip.files); + var f = file.toLowerCase(), g = f.replace(/\//g,'\\'); + for(var i=0; i\/]+)\s*=\s*((?:")([^"]*)(?:")|(?:')([^']*)(?:')|([^'">\s]+))/g; + var tagregex=/<[\/\?]?[a-zA-Z0-9:]+(?:\s+[^"\s?>\/]+\s*=\s*(?:"[^"]*"|'[^']*'|[^'">\s=]+))*\s?[\/\?]?>/g; + if(!(XML_HEADER.match(tagregex))) tagregex = /<[^>]*>/g; + var nsregex=/<\w*:/, nsregex2 = /<(\/?)\w+:/; + function parsexmltag(tag, skip_root) { + var z = ({}); + var eq = 0, c = 0; + for(; eq !== tag.length; ++eq) if((c = tag.charCodeAt(eq)) === 32 || c === 10 || c === 13) break; + if(!skip_root) z[0] = tag.slice(0, eq); + if(eq === tag.length) return z; + var m = tag.match(attregexg), j=0, v="", i=0, q="", cc="", quot = 1; + if(m) for(i = 0; i != m.length; ++i) { + cc = m[i]; + for(c=0; c != cc.length; ++c) if(cc.charCodeAt(c) === 61) break; + q = cc.slice(0,c).trim(); + while(cc.charCodeAt(c+1) == 32) ++c; + quot = ((eq=cc.charCodeAt(c+1)) == 34 || eq == 39) ? 1 : 0; + v = cc.slice(c+1+quot, cc.length-quot); + for(j=0;j!=q.length;++j) if(q.charCodeAt(j) === 58) break; + if(j===q.length) { + if(q.indexOf("_") > 0) q = q.slice(0, q.indexOf("_")); // from ods + z[q] = v; + z[q.toLowerCase()] = v; + } + else { + var k = (j===5 && q.slice(0,5)==="xmlns"?"xmlns":"")+q.slice(j+1); + if(z[k] && q.slice(j-3,j) == "ext") continue; // from ods + z[k] = v; + z[k.toLowerCase()] = v; + } + } + return z; + } + function strip_ns(x) { return x.replace(nsregex2, "<$1"); } + + var encodings = { + '"': '"', + ''': "'", + '>': '>', + '<': '<', + '&': '&' + }; + var rencoding = evert(encodings); +//var rencstr = "&<>'\"".split(""); + +// TODO: CP remap (need to read file version to determine OS) + var unescapexml = (function() { + /* 22.4.2.4 bstr (Basic String) */ + var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/g, coderegex = /_x([\da-fA-F]{4})_/g; + return function unescapexml(text) { + var s = text + '', i = s.indexOf("-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));}); + var j = s.indexOf("]]>"); + return unescapexml(s.slice(0, i)) + s.slice(i+9,j) + unescapexml(s.slice(j+3)); + }; + })(); + + var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g; + function escapexml(text){ + var s = text + ''; + return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";}); + } + function escapexmltag(text){ return escapexml(text).replace(/ /g,"_x0020_"); } + + var htmlcharegex = /[\u0000-\u001f]/g; + function escapehtml(text){ + var s = text + ''; + return s.replace(decregex, function(y) { return rencoding[y]; }).replace(/\n/g, "
                ").replace(htmlcharegex,function(s) { return "&#x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + ";"; }); + } + + function escapexlml(text){ + var s = text + ''; + return s.replace(decregex, function(y) { return rencoding[y]; }).replace(htmlcharegex,function(s) { return "&#x" + (s.charCodeAt(0).toString(16)).toUpperCase() + ";"; }); + } + + /* TODO: handle codepages */ + var xlml_fixstr = (function() { + var entregex = /&#(\d+);/g; + function entrepl($$,$1) { return String.fromCharCode(parseInt($1,10)); } + return function xlml_fixstr(str) { return str.replace(entregex,entrepl); }; + })(); + var xlml_unfixstr = (function() { + return function xlml_unfixstr(str) { return str.replace(/(\r\n|[\r\n])/g,"\ "); }; + })(); + + function parsexmlbool(value) { + switch(value) { + case 1: case true: case '1': case 'true': case 'TRUE': return true; + /* case '0': case 'false': case 'FALSE':*/ + default: return false; + } + } + + var utf8read = function utf8reada(orig) { + var out = "", i = 0, c = 0, d = 0, e = 0, f = 0, w = 0; + while (i < orig.length) { + c = orig.charCodeAt(i++); + if (c < 128) { out += String.fromCharCode(c); continue; } + d = orig.charCodeAt(i++); + if (c>191 && c<224) { f = ((c & 31) << 6); f |= (d & 63); out += String.fromCharCode(f); continue; } + e = orig.charCodeAt(i++); + if (c < 240) { out += String.fromCharCode(((c & 15) << 12) | ((d & 63) << 6) | (e & 63)); continue; } + f = orig.charCodeAt(i++); + w = (((c & 7) << 18) | ((d & 63) << 12) | ((e & 63) << 6) | (f & 63))-65536; + out += String.fromCharCode(0xD800 + ((w>>>10)&1023)); + out += String.fromCharCode(0xDC00 + (w&1023)); + } + return out; + }; + + var utf8write = function(orig) { + var out = [], i = 0, c = 0, d = 0; + while(i < orig.length) { + c = orig.charCodeAt(i++); + switch(true) { + case c < 128: out.push(String.fromCharCode(c)); break; + case c < 2048: + out.push(String.fromCharCode(192 + (c >> 6))); + out.push(String.fromCharCode(128 + (c & 63))); + break; + case c >= 55296 && c < 57344: + c -= 55296; d = orig.charCodeAt(i++) - 56320 + (c<<10); + out.push(String.fromCharCode(240 + ((d >>18) & 7))); + out.push(String.fromCharCode(144 + ((d >>12) & 63))); + out.push(String.fromCharCode(128 + ((d >> 6) & 63))); + out.push(String.fromCharCode(128 + (d & 63))); + break; + default: + out.push(String.fromCharCode(224 + (c >> 12))); + out.push(String.fromCharCode(128 + ((c >> 6) & 63))); + out.push(String.fromCharCode(128 + (c & 63))); + } + } + return out.join(""); + }; + + if(has_buf) { + var utf8readb = function utf8readb(data) { + var out = Buffer.alloc(2*data.length), w, i, j = 1, k = 0, ww=0, c; + for(i = 0; i < data.length; i+=j) { + j = 1; + if((c=data.charCodeAt(i)) < 128) w = c; + else if(c < 224) { w = (c&31)*64+(data.charCodeAt(i+1)&63); j=2; } + else if(c < 240) { w=(c&15)*4096+(data.charCodeAt(i+1)&63)*64+(data.charCodeAt(i+2)&63); j=3; } + else { j = 4; + w = (c & 7)*262144+(data.charCodeAt(i+1)&63)*4096+(data.charCodeAt(i+2)&63)*64+(data.charCodeAt(i+3)&63); + w -= 65536; ww = 0xD800 + ((w>>>10)&1023); w = 0xDC00 + (w&1023); + } + if(ww !== 0) { out[k++] = ww&255; out[k++] = ww>>>8; ww = 0; } + out[k++] = w%256; out[k++] = w>>>8; + } + return out.slice(0,k).toString('ucs2'); + }; + var corpus = "foo bar baz\u00e2\u0098\u0083\u00f0\u009f\u008d\u00a3"; + if(utf8read(corpus) == utf8readb(corpus)) utf8read = utf8readb; + // $FlowIgnore + var utf8readc = function utf8readc(data) { return Buffer_from(data, 'binary').toString('utf8'); }; + if(utf8read(corpus) == utf8readc(corpus)) utf8read = utf8readc; + + // $FlowIgnore + utf8write = function(data) { return Buffer_from(data, 'utf8').toString("binary"); }; + } + +// matches ... extracts content + var matchtag = (function() { + var mtcache = ({}); + return function matchtag(f,g) { + var t = f+"|"+(g||""); + if(mtcache[t]) return mtcache[t]; + return (mtcache[t] = new RegExp('<(?:\\w+:)?'+f+'(?: xml:space="preserve")?(?:[^>]*)>([\\s\\S]*?)',((g||"")))); + }; + })(); + + var htmldecode = (function() { + var entities = [ + ['nbsp', ' '], ['middot', '·'], + ['quot', '"'], ['apos', "'"], ['gt', '>'], ['lt', '<'], ['amp', '&'] + ].map(function(x) { return [new RegExp('&' + x[0] + ';', "g"), x[1]]; }); + return function htmldecode(str) { + var o = str.replace(/^[\t\n\r ]+/, "").replace(/[\t\n\r ]+$/,"").replace(/[\t\n\r ]+/g, " ").replace(/<\s*[bB][rR]\s*\/?>/g,"\n").replace(/<[^>]*>/g,""); + for(var i = 0; i < entities.length; ++i) o = o.replace(entities[i][0], entities[i][1]); + return o; + }; + })(); + + var vtregex = (function(){ var vt_cache = {}; + return function vt_regex(bt) { + if(vt_cache[bt] !== undefined) return vt_cache[bt]; + return (vt_cache[bt] = new RegExp("<(?:vt:)?" + bt + ">([\\s\\S]*?)", 'g') ); + };})(); + var vtvregex = /<\/?(?:vt:)?variant>/g, vtmregex = /<(?:vt:)([^>]*)>([\s\S]*)' + g + ''; } + + function wxt_helper(h) { return keys(h).map(function(k) { return " " + k + '="' + h[k] + '"';}).join(""); } + function writextag(f,g,h) { return '<' + f + ((h != null) ? wxt_helper(h) : "") + ((g != null) ? (g.match(wtregex)?' xml:space="preserve"' : "") + '>' + g + '';} + + function write_w3cdtf(d, t) { try { return d.toISOString().replace(/\.\d*/,""); } catch(e) { if(t) throw e; } return ""; } + + function write_vt(s) { + switch(typeof s) { + case 'string': return writextag('vt:lpwstr', s); + case 'number': return writextag((s|0)==s?'vt:i4':'vt:r8', String(s)); + case 'boolean': return writextag('vt:bool',s?'true':'false'); + } + if(s instanceof Date) return writextag('vt:filetime', write_w3cdtf(s)); + throw new Error("Unable to serialize " + s); + } + + var XMLNS = ({ + 'dc': 'http://purl.org/dc/elements/1.1/', + 'dcterms': 'http://purl.org/dc/terms/', + 'dcmitype': 'http://purl.org/dc/dcmitype/', + 'mx': 'http://schemas.microsoft.com/office/mac/excel/2008/main', + 'r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships', + 'sjs': 'http://schemas.openxmlformats.org/package/2006/sheetjs/core-properties', + 'vt': 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes', + 'xsi': 'http://www.w3.org/2001/XMLSchema-instance', + 'xsd': 'http://www.w3.org/2001/XMLSchema' + }); + + XMLNS.main = [ + 'http://schemas.openxmlformats.org/spreadsheetml/2006/main', + 'http://purl.oclc.org/ooxml/spreadsheetml/main', + 'http://schemas.microsoft.com/office/excel/2006/main', + 'http://schemas.microsoft.com/office/excel/2006/2' + ]; + + var XLMLNS = ({ + 'o': 'urn:schemas-microsoft-com:office:office', + 'x': 'urn:schemas-microsoft-com:office:excel', + 'ss': 'urn:schemas-microsoft-com:office:spreadsheet', + 'dt': 'uuid:C2F41010-65B3-11d1-A29F-00AA00C14882', + 'mv': 'http://macVmlSchemaUri', + 'v': 'urn:schemas-microsoft-com:vml', + 'html': 'http://www.w3.org/TR/REC-html40' + }); + function read_double_le(b, idx) { + var s = 1 - 2 * (b[idx + 7] >>> 7); + var e = ((b[idx + 7] & 0x7f) << 4) + ((b[idx + 6] >>> 4) & 0x0f); + var m = (b[idx+6]&0x0f); + for(var i = 5; i >= 0; --i) m = m * 256 + b[idx + i]; + if(e == 0x7ff) return m == 0 ? (s * Infinity) : NaN; + if(e == 0) e = -1022; + else { e -= 1023; m += Math.pow(2,52); } + return s * Math.pow(2, e - 52) * m; + } + + function write_double_le(b, v, idx) { + var bs = ((((v < 0) || (1/v == -Infinity)) ? 1 : 0) << 7), e = 0, m = 0; + var av = bs ? (-v) : v; + if(!isFinite(av)) { e = 0x7ff; m = isNaN(v) ? 0x6969 : 0; } + else if(av == 0) e = m = 0; + else { + e = Math.floor(Math.log(av) / Math.LN2); + m = av * Math.pow(2, 52 - e); + if((e <= -1023) && (!isFinite(m) || (m < Math.pow(2,52)))) { e = -1022; } + else { m -= Math.pow(2,52); e+=1023; } + } + for(var i = 0; i <= 5; ++i, m/=256) b[idx + i] = m & 0xff; + b[idx + 6] = ((e & 0x0f) << 4) | (m & 0xf); + b[idx + 7] = (e >> 4) | bs; + } + + var __toBuffer = function(bufs) { var x=[],w=10240; for(var i=0;i 0 ? __utf8(b, i+4,i+4+len-1) : "";}; + var ___lpstr = __lpstr; + var __cpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";}; + var ___cpstr = __cpstr; + var __lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len-1) : "";}; + var ___lpwstr = __lpwstr; + var __lpp4, ___lpp4; + __lpp4 = ___lpp4 = function lpp4_(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf16le(b, i+4,i+4+len) : "";}; + var __8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? __utf8(b, i+4,i+4+len) : "";}; + var ___8lpp4 = __8lpp4; + var __double, ___double; + __double = ___double = function(b, idx) { return read_double_le(b, idx);}; + var is_buf = function is_buf_a(a) { return Array.isArray(a); }; + + if(has_buf) { + __utf16le = function(b,s,e) { if(!Buffer.isBuffer(b)) return ___utf16le(b,s,e); return b.toString('utf16le',s,e).replace(chr0,'')/*.replace(chr1,'!')*/; }; + __hexlify = function(b,s,l) { return Buffer.isBuffer(b) ? b.toString('hex',s,s+l) : ___hexlify(b,s,l); }; + __lpstr = function lpstr_b(b, i) { if(!Buffer.isBuffer(b)) return ___lpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";}; + __cpstr = function cpstr_b(b, i) { if(!Buffer.isBuffer(b)) return ___cpstr(b, i); var len = b.readUInt32LE(i); return len > 0 ? b.toString('utf8',i+4,i+4+len-1) : "";}; + __lpwstr = function lpwstr_b(b, i) { if(!Buffer.isBuffer(b)) return ___lpwstr(b, i); var len = 2*b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len-1);}; + __lpp4 = function lpp4_b(b, i) { if(!Buffer.isBuffer(b)) return ___lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf16le',i+4,i+4+len);}; + __8lpp4 = function lpp4_8b(b, i) { if(!Buffer.isBuffer(b)) return ___8lpp4(b, i); var len = b.readUInt32LE(i); return b.toString('utf8',i+4,i+4+len);}; + __utf8 = function utf8_b(b, s, e) { return (Buffer.isBuffer(b)) ? b.toString('utf8',s,e) : ___utf8(b,s,e); }; + __toBuffer = function(bufs) { return (bufs[0].length > 0 && Buffer.isBuffer(bufs[0][0])) ? Buffer.concat(bufs[0]) : ___toBuffer(bufs);}; + bconcat = function(bufs) { return Buffer.isBuffer(bufs[0]) ? Buffer.concat(bufs) : [].concat.apply([], bufs); }; + __double = function double_(b, i) { if(Buffer.isBuffer(b)) return b.readDoubleLE(i); return ___double(b,i); }; + is_buf = function is_buf_b(a) { return Buffer.isBuffer(a) || Array.isArray(a); }; + } + + /* from js-xls */ + if(typeof cptable !== 'undefined') { + __utf16le = function(b,s,e) { return cptable.utils.decode(1200, b.slice(s,e)).replace(chr0, ''); }; + __utf8 = function(b,s,e) { return cptable.utils.decode(65001, b.slice(s,e)); }; + __lpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_ansi, b.slice(i+4, i+4+len-1)) : "";}; + __cpstr = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(current_codepage, b.slice(i+4, i+4+len-1)) : "";}; + __lpwstr = function(b,i) { var len = 2*__readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len-1)) : "";}; + __lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(1200, b.slice(i+4,i+4+len)) : "";}; + __8lpp4 = function(b,i) { var len = __readUInt32LE(b,i); return len > 0 ? cptable.utils.decode(65001, b.slice(i+4,i+4+len)) : "";}; + } + + var __readUInt8 = function(b, idx) { return b[idx]; }; + var __readUInt16LE = function(b, idx) { return (b[idx+1]*(1<<8))+b[idx]; }; + var __readInt16LE = function(b, idx) { var u = (b[idx+1]*(1<<8))+b[idx]; return (u < 0x8000) ? u : ((0xffff - u + 1) * -1); }; + var __readUInt32LE = function(b, idx) { return b[idx+3]*(1<<24)+(b[idx+2]<<16)+(b[idx+1]<<8)+b[idx]; }; + var __readInt32LE = function(b, idx) { return (b[idx+3]<<24)|(b[idx+2]<<16)|(b[idx+1]<<8)|b[idx]; }; + var __readInt32BE = function(b, idx) { return (b[idx]<<24)|(b[idx+1]<<16)|(b[idx+2]<<8)|b[idx+3]; }; + + function ReadShift(size, t) { + var o="", oI, oR, oo=[], w, vv, i, loc; + switch(t) { + case 'dbcs': + loc = this.l; + if(has_buf && Buffer.isBuffer(this)) o = this.slice(this.l, this.l+2*size).toString("utf16le"); + else for(i = 0; i < size; ++i) { o+=String.fromCharCode(__readUInt16LE(this, loc)); loc+=2; } + size *= 2; + break; + + case 'utf8': o = __utf8(this, this.l, this.l + size); break; + case 'utf16le': size *= 2; o = __utf16le(this, this.l, this.l + size); break; + + case 'wstr': + if(typeof cptable !== 'undefined') o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l+2*size)); + else return ReadShift.call(this, size, 'dbcs'); + size = 2 * size; break; + + /* [MS-OLEDS] 2.1.4 LengthPrefixedAnsiString */ + case 'lpstr-ansi': o = __lpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break; + case 'lpstr-cp': o = __cpstr(this, this.l); size = 4 + __readUInt32LE(this, this.l); break; + /* [MS-OLEDS] 2.1.5 LengthPrefixedUnicodeString */ + case 'lpwstr': o = __lpwstr(this, this.l); size = 4 + 2 * __readUInt32LE(this, this.l); break; + /* [MS-OFFCRYPTO] 2.1.2 Length-Prefixed Padded Unicode String (UNICODE-LP-P4) */ + case 'lpp4': size = 4 + __readUInt32LE(this, this.l); o = __lpp4(this, this.l); if(size & 0x02) size += 2; break; + /* [MS-OFFCRYPTO] 2.1.3 Length-Prefixed UTF-8 String (UTF-8-LP-P4) */ + case '8lpp4': size = 4 + __readUInt32LE(this, this.l); o = __8lpp4(this, this.l); if(size & 0x03) size += 4 - (size & 0x03); break; + + case 'cstr': size = 0; o = ""; + while((w=__readUInt8(this, this.l + size++))!==0) oo.push(_getchar(w)); + o = oo.join(""); break; + case '_wstr': size = 0; o = ""; + while((w=__readUInt16LE(this,this.l +size))!==0){oo.push(_getchar(w));size+=2;} + size+=2; o = oo.join(""); break; + + /* sbcs and dbcs support continue records in the SST way TODO codepages */ + case 'dbcs-cont': o = ""; loc = this.l; + for(i = 0; i < size; ++i) { + if(this.lens && this.lens.indexOf(loc) !== -1) { + w = __readUInt8(this, loc); + this.l = loc + 1; + vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont'); + return oo.join("") + vv; + } + oo.push(_getchar(__readUInt16LE(this, loc))); + loc+=2; + } o = oo.join(""); size *= 2; break; + + case 'cpstr': + if(typeof cptable !== 'undefined') { + o = cptable.utils.decode(current_codepage, this.slice(this.l, this.l + size)); + break; + } + /* falls through */ + case 'sbcs-cont': o = ""; loc = this.l; + for(i = 0; i != size; ++i) { + if(this.lens && this.lens.indexOf(loc) !== -1) { + w = __readUInt8(this, loc); + this.l = loc + 1; + vv = ReadShift.call(this, size-i, w ? 'dbcs-cont' : 'sbcs-cont'); + return oo.join("") + vv; + } + oo.push(_getchar(__readUInt8(this, loc))); + loc+=1; + } o = oo.join(""); break; + + default: + switch(size) { + case 1: oI = __readUInt8(this, this.l); this.l++; return oI; + case 2: oI = (t === 'i' ? __readInt16LE : __readUInt16LE)(this, this.l); this.l += 2; return oI; + case 4: case -4: + if(t === 'i' || ((this[this.l+3] & 0x80)===0)) { oI = ((size > 0) ? __readInt32LE : __readInt32BE)(this, this.l); this.l += 4; return oI; } + else { oR = __readUInt32LE(this, this.l); this.l += 4; } return oR; + case 8: case -8: + if(t === 'f') { + if(size == 8) oR = __double(this, this.l); + else oR = __double([this[this.l+7],this[this.l+6],this[this.l+5],this[this.l+4],this[this.l+3],this[this.l+2],this[this.l+1],this[this.l+0]], 0); + this.l += 8; return oR; + } else size = 8; + /* falls through */ + case 16: o = __hexlify(this, this.l, size); break; + }} + this.l+=size; return o; + } + + var __writeUInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); b[idx+2] = ((val >>> 16) & 0xFF); b[idx+3] = ((val >>> 24) & 0xFF); }; + var __writeInt32LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >> 8) & 0xFF); b[idx+2] = ((val >> 16) & 0xFF); b[idx+3] = ((val >> 24) & 0xFF); }; + var __writeUInt16LE = function(b, val, idx) { b[idx] = (val & 0xFF); b[idx+1] = ((val >>> 8) & 0xFF); }; + + function WriteShift(t, val, f) { + var size = 0, i = 0; + if(f === 'dbcs') { + for(i = 0; i != val.length; ++i) __writeUInt16LE(this, val.charCodeAt(i), this.l + 2 * i); + size = 2 * val.length; + } else if(f === 'sbcs') { + /* TODO: codepage */ + val = val.replace(/[^\x00-\x7F]/g, "_"); + for(i = 0; i != val.length; ++i) this[this.l + i] = (val.charCodeAt(i) & 0xFF); + size = val.length; + } else if(f === 'hex') { + for(; i < t; ++i) { + this[this.l++] = (parseInt(val.slice(2*i, 2*i+2), 16)||0); + } return this; + } else if(f === 'utf16le') { + var end = Math.min(this.l + t, this.length); + for(i = 0; i < Math.min(val.length, t); ++i) { + var cc = val.charCodeAt(i); + this[this.l++] = (cc & 0xff); + this[this.l++] = (cc >> 8); + } + while(this.l < end) this[this.l++] = 0; + return this; + } else switch(t) { + case 1: size = 1; this[this.l] = val&0xFF; break; + case 2: size = 2; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; break; + case 3: size = 3; this[this.l] = val&0xFF; val >>>= 8; this[this.l+1] = val&0xFF; val >>>= 8; this[this.l+2] = val&0xFF; break; + case 4: size = 4; __writeUInt32LE(this, val, this.l); break; + case 8: size = 8; if(f === 'f') { write_double_le(this, val, this.l); break; } + /* falls through */ + case 16: break; + case -4: size = 4; __writeInt32LE(this, val, this.l); break; + } + this.l += size; return this; + } + + function CheckField(hexstr, fld) { + var m = __hexlify(this,this.l,hexstr.length>>1); + if(m !== hexstr) throw new Error(fld + 'Expected ' + hexstr + ' saw ' + m); + this.l += hexstr.length>>1; + } + + function prep_blob(blob, pos) { + blob.l = pos; + blob.read_shift = ReadShift; + blob.chk = CheckField; + blob.write_shift = WriteShift; + } + + function parsenoop(blob, length) { blob.l += length; } + + function new_buf(sz) { + var o = new_raw_buf(sz); + prep_blob(o, 0); + return o; + } + + /* [MS-XLSB] 2.1.4 Record */ + function recordhopper(data, cb, opts) { + if(!data) return; + var tmpbyte, cntbyte, length; + prep_blob(data, data.l || 0); + var L = data.length, RT = 0, tgt = 0; + while(data.l < L) { + RT = data.read_shift(1); + if(RT & 0x80) RT = (RT & 0x7F) + ((data.read_shift(1) & 0x7F)<<7); + var R = XLSBRecordEnum[RT] || XLSBRecordEnum[0xFFFF]; + tmpbyte = data.read_shift(1); + length = tmpbyte & 0x7F; + for(cntbyte = 1; cntbyte <4 && (tmpbyte & 0x80); ++cntbyte) length += ((tmpbyte = data.read_shift(1)) & 0x7F)<<(7*cntbyte); + tgt = data.l + length; + var d = (R.f||parsenoop)(data, length, opts); + data.l = tgt; + if(cb(d, R.n, RT)) return; + } + } + + /* control buffer usage for fixed-length buffers */ + function buf_array() { + var bufs = [], blksz = has_buf ? 256 : 2048; + var newblk = function ba_newblk(sz) { + var o = (new_buf(sz)); + prep_blob(o, 0); + return o; + }; + + var curbuf = newblk(blksz); + + var endbuf = function ba_endbuf() { + if(!curbuf) return; + if(curbuf.length > curbuf.l) { curbuf = curbuf.slice(0, curbuf.l); curbuf.l = curbuf.length; } + if(curbuf.length > 0) bufs.push(curbuf); + curbuf = null; + }; + + var next = function ba_next(sz) { + if(curbuf && (sz < (curbuf.length - curbuf.l))) return curbuf; + endbuf(); + return (curbuf = newblk(Math.max(sz+1, blksz))); + }; + + var end = function ba_end() { + endbuf(); + return __toBuffer([bufs]); + }; + + var push = function ba_push(buf) { endbuf(); curbuf = buf; if(curbuf.l == null) curbuf.l = curbuf.length; next(blksz); }; + + return ({ next:next, push:push, end:end, _bufs:bufs }); + } + + function write_record(ba, type, payload, length) { + var t = +XLSBRE[type], l; + if(isNaN(t)) return; // TODO: throw something here? + if(!length) length = XLSBRecordEnum[t].p || (payload||[]).length || 0; + l = 1 + (t >= 0x80 ? 1 : 0) + 1/* + length*/; + if(length >= 0x80) ++l; if(length >= 0x4000) ++l; if(length >= 0x200000) ++l; + var o = ba.next(l); + if(t <= 0x7F) o.write_shift(1, t); + else { + o.write_shift(1, (t & 0x7F) + 0x80); + o.write_shift(1, (t >> 7)); + } + for(var i = 0; i != 4; ++i) { + if(length >= 0x80) { o.write_shift(1, (length & 0x7F)+0x80); length >>= 7; } + else { o.write_shift(1, length); break; } + } + if(length > 0 && is_buf(payload)) ba.push(payload); + } + /* XLS ranges enforced */ + function shift_cell_xls(cell, tgt, opts) { + var out = dup(cell); + if(tgt.s) { + if(out.cRel) out.c += tgt.s.c; + if(out.rRel) out.r += tgt.s.r; + } else { + if(out.cRel) out.c += tgt.c; + if(out.rRel) out.r += tgt.r; + } + if(!opts || opts.biff < 12) { + while(out.c >= 0x100) out.c -= 0x100; + while(out.r >= 0x10000) out.r -= 0x10000; + } + return out; + } + + function shift_range_xls(cell, range, opts) { + var out = dup(cell); + out.s = shift_cell_xls(out.s, range.s, opts); + out.e = shift_cell_xls(out.e, range.s, opts); + return out; + } + + function encode_cell_xls(c, biff) { + if(c.cRel && c.c < 0) { c = dup(c); c.c += (biff > 8) ? 0x4000 : 0x100; } + if(c.rRel && c.r < 0) { c = dup(c); c.r += (biff > 8) ? 0x100000 : ((biff > 5) ? 0x10000 : 0x4000); } + var s = encode_cell(c); + if(c.cRel === 0) s = fix_col(s); + if(c.rRel === 0) s = fix_row(s); + return s; + } + + function encode_range_xls(r, opts) { + if(r.s.r == 0 && !r.s.rRel) { + if(r.e.r == (opts.biff >= 12 ? 0xFFFFF : (opts.biff >= 8 ? 0x10000 : 0x4000)) && !r.e.rRel) { + return (r.s.cRel ? "" : "$") + encode_col(r.s.c) + ":" + (r.e.cRel ? "" : "$") + encode_col(r.e.c); + } + } + if(r.s.c == 0 && !r.s.cRel) { + if(r.e.c == (opts.biff >= 12 ? 0xFFFF : 0xFF) && !r.e.cRel) { + return (r.s.rRel ? "" : "$") + encode_row(r.s.r) + ":" + (r.e.rRel ? "" : "$") + encode_row(r.e.r); + } + } + return encode_cell_xls(r.s, opts.biff) + ":" + encode_cell_xls(r.e, opts.biff); + } + var OFFCRYPTO = {}; + + var make_offcrypto = function(O, _crypto) { + var crypto; + if(typeof _crypto !== 'undefined') crypto = _crypto; + else if(typeof require !== 'undefined') { + try { crypto = undefined; } + catch(e) { crypto = null; } + } + + O.rc4 = function(key, data) { + var S = new Array(256); + var c = 0, i = 0, j = 0, t = 0; + for(i = 0; i != 256; ++i) S[i] = i; + for(i = 0; i != 256; ++i) { + j = (j + S[i] + (key[i%key.length]).charCodeAt(0))&255; + t = S[i]; S[i] = S[j]; S[j] = t; + } + // $FlowIgnore + i = j = 0; var out = Buffer(data.length); + for(c = 0; c != data.length; ++c) { + i = (i + 1)&255; + j = (j + S[i])%256; + t = S[i]; S[i] = S[j]; S[j] = t; + out[c] = (data[c] ^ S[(S[i]+S[j])&255]); + } + return out; + }; + + O.md5 = function(hex) { + if(!crypto) throw new Error("Unsupported crypto"); + return crypto.createHash('md5').update(hex).digest('hex'); + }; + }; + /*global crypto:true */ + make_offcrypto(OFFCRYPTO, typeof crypto !== "undefined" ? crypto : undefined); + + function decode_row(rowstr) { return parseInt(unfix_row(rowstr),10) - 1; } + function encode_row(row) { return "" + (row + 1); } + function fix_row(cstr) { return cstr.replace(/([A-Z]|^)(\d+)$/,"$1$$$2"); } + function unfix_row(cstr) { return cstr.replace(/\$(\d+)$/,"$1"); } + + function decode_col(colstr) { var c = unfix_col(colstr), d = 0, i = 0; for(; i !== c.length; ++i) d = 26*d + c.charCodeAt(i) - 64; return d - 1; } + function encode_col(col) { var s=""; for(++col; col; col=Math.floor((col-1)/26)) s = String.fromCharCode(((col-1)%26) + 65) + s; return s; } + function fix_col(cstr) { return cstr.replace(/^([A-Z])/,"$$$1"); } + function unfix_col(cstr) { return cstr.replace(/^\$([A-Z])/,"$1"); } + + function split_cell(cstr) { return cstr.replace(/(\$?[A-Z]*)(\$?\d*)/,"$1,$2").split(","); } + function decode_cell(cstr) { var splt = split_cell(cstr); return { c:decode_col(splt[0]), r:decode_row(splt[1]) }; } + function encode_cell(cell) { return encode_col(cell.c) + encode_row(cell.r); } + function decode_range(range) { var x =range.split(":").map(decode_cell); return {s:x[0],e:x[x.length-1]}; } + function encode_range(cs,ce) { + if(typeof ce === 'undefined' || typeof ce === 'number') { + return encode_range(cs.s, cs.e); + } + if(typeof cs !== 'string') cs = encode_cell((cs)); + if(typeof ce !== 'string') ce = encode_cell((ce)); + return cs == ce ? cs : cs + ":" + ce; + } + + function safe_decode_range(range) { + var o = {s:{c:0,r:0},e:{c:0,r:0}}; + var idx = 0, i = 0, cc = 0; + var len = range.length; + for(idx = 0; i < len; ++i) { + if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break; + idx = 26*idx + cc; + } + o.s.c = --idx; + + for(idx = 0; i < len; ++i) { + if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break; + idx = 10*idx + cc; + } + o.s.r = --idx; + + if(i === len || range.charCodeAt(++i) === 58) { o.e.c=o.s.c; o.e.r=o.s.r; return o; } + + for(idx = 0; i != len; ++i) { + if((cc=range.charCodeAt(i)-64) < 1 || cc > 26) break; + idx = 26*idx + cc; + } + o.e.c = --idx; + + for(idx = 0; i != len; ++i) { + if((cc=range.charCodeAt(i)-48) < 0 || cc > 9) break; + idx = 10*idx + cc; + } + o.e.r = --idx; + return o; + } + + function safe_format_cell(cell, v) { + var q = (cell.t == 'd' && v instanceof Date); + if(cell.z != null) try { return (cell.w = SSF.format(cell.z, q ? datenum(v) : v)); } catch(e) { } + try { return (cell.w = SSF.format((cell.XF||{}).numFmtId||(q ? 14 : 0), q ? datenum(v) : v)); } catch(e) { return ''+v; } + } + + function format_cell(cell, v, o) { + if(cell == null || cell.t == null || cell.t == 'z') return ""; + if(cell.w !== undefined) return cell.w; + if(cell.t == 'd' && !cell.z && o && o.dateNF) cell.z = o.dateNF; + if(v == undefined) return safe_format_cell(cell, cell.v); + return safe_format_cell(cell, v); + } + + function sheet_to_workbook(sheet, opts) { + var n = opts && opts.sheet ? opts.sheet : "Sheet1"; + var sheets = {}; sheets[n] = sheet; + return { SheetNames: [n], Sheets: sheets }; + } + + function sheet_add_aoa(_ws, data, opts) { + var o = opts || {}; + var dense = _ws ? Array.isArray(_ws) : o.dense; + if(DENSE != null && dense == null) dense = DENSE; + var ws = _ws || (dense ? ([]) : ({})); + var _R = 0, _C = 0; + if(ws && o.origin != null) { + if(typeof o.origin == 'number') _R = o.origin; + else { + var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin; + _R = _origin.r; _C = _origin.c; + } + } + var range = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}); + if(ws['!ref']) { + var _range = safe_decode_range(ws['!ref']); + range.s.c = _range.s.c; + range.s.r = _range.s.r; + range.e.c = Math.max(range.e.c, _range.e.c); + range.e.r = Math.max(range.e.r, _range.e.r); + if(_R == -1) range.e.r = _R = _range.e.r + 1; + } + for(var R = 0; R != data.length; ++R) { + if(!data[R]) continue; + if(!Array.isArray(data[R])) throw new Error("aoa_to_sheet expects an array of arrays"); + for(var C = 0; C != data[R].length; ++C) { + if(typeof data[R][C] === 'undefined') continue; + var cell = ({v: data[R][C] }); + var __R = _R + R, __C = _C + C; + if(range.s.r > __R) range.s.r = __R; + if(range.s.c > __C) range.s.c = __C; + if(range.e.r < __R) range.e.r = __R; + if(range.e.c < __C) range.e.c = __C; + if(data[R][C] && typeof data[R][C] === 'object' && !Array.isArray(data[R][C]) && !(data[R][C] instanceof Date)) cell = data[R][C]; + else { + if(Array.isArray(cell.v)) { cell.f = data[R][C][1]; cell.v = cell.v[0]; } + if(cell.v === null) { if(cell.f) cell.t = 'n'; else if(!o.sheetStubs) continue; else cell.t = 'z'; } + else if(typeof cell.v === 'number') cell.t = 'n'; + else if(typeof cell.v === 'boolean') cell.t = 'b'; + else if(cell.v instanceof Date) { + cell.z = o.dateNF || SSF._table[14]; + if(o.cellDates) { cell.t = 'd'; cell.w = SSF.format(cell.z, datenum(cell.v)); } + else { cell.t = 'n'; cell.v = datenum(cell.v); cell.w = SSF.format(cell.z, cell.v); } + } + else cell.t = 's'; + } + if(dense) { + if(!ws[__R]) ws[__R] = []; + ws[__R][__C] = cell; + } else { + var cell_ref = encode_cell(({c:__C,r:__R})); + ws[cell_ref] = cell; + } + } + } + if(range.s.c < 10000000) ws['!ref'] = encode_range(range); + return ws; + } + function aoa_to_sheet(data, opts) { return sheet_add_aoa(null, data, opts); } + + function write_UInt32LE(x, o) { + if(!o) o = new_buf(4); + o.write_shift(4, x); + return o; + } + + /* [MS-XLSB] 2.5.168 */ + function parse_XLWideString(data) { + var cchCharacters = data.read_shift(4); + return cchCharacters === 0 ? "" : data.read_shift(cchCharacters, 'dbcs'); + } + function write_XLWideString(data, o) { + var _null = false; if(o == null) { _null = true; o = new_buf(4+2*data.length); } + o.write_shift(4, data.length); + if(data.length > 0) o.write_shift(0, data, 'dbcs'); + return _null ? o.slice(0, o.l) : o; + } + + /* [MS-XLSB] 2.5.143 */ + function parse_StrRun(data) { + return { ich: data.read_shift(2), ifnt: data.read_shift(2) }; + } + function write_StrRun(run, o) { + if(!o) o = new_buf(4); + o.write_shift(2, run.ich || 0); + o.write_shift(2, run.ifnt || 0); + return o; + } + + /* [MS-XLSB] 2.5.121 */ + function parse_RichStr(data, length) { + var start = data.l; + var flags = data.read_shift(1); + var str = parse_XLWideString(data); + var rgsStrRun = []; + var z = ({ t: str, h: str }); + if((flags & 1) !== 0) { /* fRichStr */ + /* TODO: formatted string */ + var dwSizeStrRun = data.read_shift(4); + for(var i = 0; i != dwSizeStrRun; ++i) rgsStrRun.push(parse_StrRun(data)); + z.r = rgsStrRun; + } + else z.r = [{ich:0, ifnt:0}]; + //if((flags & 2) !== 0) { /* fExtStr */ + // /* TODO: phonetic string */ + //} + data.l = start + length; + return z; + } + function write_RichStr(str, o) { + /* TODO: formatted string */ + var _null = false; if(o == null) { _null = true; o = new_buf(15+4*str.t.length); } + o.write_shift(1,0); + write_XLWideString(str.t, o); + return _null ? o.slice(0, o.l) : o; + } + /* [MS-XLSB] 2.4.328 BrtCommentText (RichStr w/1 run) */ + var parse_BrtCommentText = parse_RichStr; + function write_BrtCommentText(str, o) { + /* TODO: formatted string */ + var _null = false; if(o == null) { _null = true; o = new_buf(23+4*str.t.length); } + o.write_shift(1,1); + write_XLWideString(str.t, o); + o.write_shift(4,1); + write_StrRun({ich:0,ifnt:0}, o); + return _null ? o.slice(0, o.l) : o; + } + + /* [MS-XLSB] 2.5.9 */ + function parse_XLSBCell(data) { + var col = data.read_shift(4); + var iStyleRef = data.read_shift(2); + iStyleRef += data.read_shift(1) <<16; + data.l++; //var fPhShow = data.read_shift(1); + return { c:col, iStyleRef: iStyleRef }; + } + function write_XLSBCell(cell, o) { + if(o == null) o = new_buf(8); + o.write_shift(-4, cell.c); + o.write_shift(3, cell.iStyleRef || cell.s); + o.write_shift(1, 0); /* fPhShow */ + return o; + } + + + /* [MS-XLSB] 2.5.21 */ + var parse_XLSBCodeName = parse_XLWideString; + var write_XLSBCodeName = write_XLWideString; + + /* [MS-XLSB] 2.5.166 */ + function parse_XLNullableWideString(data) { + var cchCharacters = data.read_shift(4); + return cchCharacters === 0 || cchCharacters === 0xFFFFFFFF ? "" : data.read_shift(cchCharacters, 'dbcs'); + } + function write_XLNullableWideString(data, o) { + var _null = false; if(o == null) { _null = true; o = new_buf(127); } + o.write_shift(4, data.length > 0 ? data.length : 0xFFFFFFFF); + if(data.length > 0) o.write_shift(0, data, 'dbcs'); + return _null ? o.slice(0, o.l) : o; + } + + /* [MS-XLSB] 2.5.165 */ + var parse_XLNameWideString = parse_XLWideString; +//var write_XLNameWideString = write_XLWideString; + + /* [MS-XLSB] 2.5.114 */ + var parse_RelID = parse_XLNullableWideString; + var write_RelID = write_XLNullableWideString; + + + /* [MS-XLS] 2.5.217 ; [MS-XLSB] 2.5.122 */ + function parse_RkNumber(data) { + var b = data.slice(data.l, data.l+4); + var fX100 = (b[0] & 1), fInt = (b[0] & 2); + data.l+=4; + b[0] &= 0xFC; // b[0] &= ~3; + var RK = fInt === 0 ? __double([0,0,0,0,b[0],b[1],b[2],b[3]],0) : __readInt32LE(b,0)>>2; + return fX100 ? (RK/100) : RK; + } + function write_RkNumber(data, o) { + if(o == null) o = new_buf(4); + var fX100 = 0, fInt = 0, d100 = data * 100; + if((data == (data | 0)) && (data >= -(1<<29)) && (data < (1 << 29))) { fInt = 1; } + else if((d100 == (d100 | 0)) && (d100 >= -(1<<29)) && (d100 < (1 << 29))) { fInt = 1; fX100 = 1; } + if(fInt) o.write_shift(-4, ((fX100 ? d100 : data) << 2) + (fX100 + 2)); + else throw new Error("unsupported RkNumber " + data); // TODO + } + + + /* [MS-XLSB] 2.5.117 RfX */ + function parse_RfX(data ) { + var cell = ({s: {}, e: {}}); + cell.s.r = data.read_shift(4); + cell.e.r = data.read_shift(4); + cell.s.c = data.read_shift(4); + cell.e.c = data.read_shift(4); + return cell; + } + function write_RfX(r, o) { + if(!o) o = new_buf(16); + o.write_shift(4, r.s.r); + o.write_shift(4, r.e.r); + o.write_shift(4, r.s.c); + o.write_shift(4, r.e.c); + return o; + } + + /* [MS-XLSB] 2.5.153 UncheckedRfX */ + var parse_UncheckedRfX = parse_RfX; + var write_UncheckedRfX = write_RfX; + + /* [MS-XLS] 2.5.342 ; [MS-XLSB] 2.5.171 */ + /* TODO: error checking, NaN and Infinity values are not valid Xnum */ + function parse_Xnum(data) { return data.read_shift(8, 'f'); } + function write_Xnum(data, o) { return (o || new_buf(8)).write_shift(8, data, 'f'); } + + /* [MS-XLSB] 2.5.97.2 */ + var BErr = { + 0x00: "#NULL!", + 0x07: "#DIV/0!", + 0x0F: "#VALUE!", + 0x17: "#REF!", + 0x1D: "#NAME?", + 0x24: "#NUM!", + 0x2A: "#N/A", + 0x2B: "#GETTING_DATA", + 0xFF: "#WTF?" + }; + var RBErr = evert_num(BErr); + + /* [MS-XLSB] 2.4.324 BrtColor */ + function parse_BrtColor(data) { + var out = {}; + var d = data.read_shift(1); + + //var fValidRGB = d & 1; + var xColorType = d >>> 1; + + var index = data.read_shift(1); + var nTS = data.read_shift(2, 'i'); + var bR = data.read_shift(1); + var bG = data.read_shift(1); + var bB = data.read_shift(1); + data.l++; //var bAlpha = data.read_shift(1); + + switch(xColorType) { + case 0: out.auto = 1; break; + case 1: + out.index = index; + var icv = XLSIcv[index]; + /* automatic pseudo index 81 */ + if(icv) out.rgb = rgb2Hex(icv); + break; + case 2: + /* if(!fValidRGB) throw new Error("invalid"); */ + out.rgb = rgb2Hex([bR, bG, bB]); + break; + case 3: out.theme = index; break; + } + if(nTS != 0) out.tint = nTS > 0 ? nTS / 32767 : nTS / 32768; + + return out; + } + function write_BrtColor(color, o) { + if(!o) o = new_buf(8); + if(!color||color.auto) { o.write_shift(4, 0); o.write_shift(4, 0); return o; } + if(color.index) { + o.write_shift(1, 0x02); + o.write_shift(1, color.index); + } else if(color.theme) { + o.write_shift(1, 0x06); + o.write_shift(1, color.theme); + } else { + o.write_shift(1, 0x05); + o.write_shift(1, 0); + } + var nTS = color.tint || 0; + if(nTS > 0) nTS *= 32767; + else if(nTS < 0) nTS *= 32768; + o.write_shift(2, nTS); + if(!color.rgb) { + o.write_shift(2, 0); + o.write_shift(1, 0); + o.write_shift(1, 0); + } else { + var rgb = (color.rgb || 'FFFFFF'); + o.write_shift(1, parseInt(rgb.slice(0,2),16)); + o.write_shift(1, parseInt(rgb.slice(2,4),16)); + o.write_shift(1, parseInt(rgb.slice(4,6),16)); + o.write_shift(1, 0xFF); + } + return o; + } + + /* [MS-XLSB] 2.5.52 */ + function parse_FontFlags(data) { + var d = data.read_shift(1); + data.l++; + var out = { + /* fBold: d & 0x01 */ + fItalic: d & 0x02, + /* fUnderline: d & 0x04 */ + fStrikeout: d & 0x08, + fOutline: d & 0x10, + fShadow: d & 0x20, + fCondense: d & 0x40, + fExtend: d & 0x80 + }; + return out; + } + function write_FontFlags(font, o) { + if(!o) o = new_buf(2); + var grbit = + (font.italic ? 0x02 : 0) | + (font.strike ? 0x08 : 0) | + (font.outline ? 0x10 : 0) | + (font.shadow ? 0x20 : 0) | + (font.condense ? 0x40 : 0) | + (font.extend ? 0x80 : 0); + o.write_shift(1, grbit); + o.write_shift(1, 0); + return o; + } + + /* [MS-OLEDS] 2.3.1 and 2.3.2 */ + function parse_ClipboardFormatOrString(o, w) { + // $FlowIgnore + var ClipFmt = {2:"BITMAP",3:"METAFILEPICT",8:"DIB",14:"ENHMETAFILE"}; + var m = o.read_shift(4); + switch(m) { + case 0x00000000: return ""; + case 0xffffffff: case 0xfffffffe: return ClipFmt[o.read_shift(4)]||""; + } + if(m > 0x190) throw new Error("Unsupported Clipboard: " + m.toString(16)); + o.l -= 4; + return o.read_shift(0, w == 1 ? "lpstr" : "lpwstr"); + } + function parse_ClipboardFormatOrAnsiString(o) { return parse_ClipboardFormatOrString(o, 1); } + function parse_ClipboardFormatOrUnicodeString(o) { return parse_ClipboardFormatOrString(o, 2); } + + /* [MS-OLEPS] 2.2 PropertyType */ +//var VT_EMPTY = 0x0000; +//var VT_NULL = 0x0001; + var VT_I2 = 0x0002; + var VT_I4 = 0x0003; +//var VT_R4 = 0x0004; +//var VT_R8 = 0x0005; +//var VT_CY = 0x0006; +//var VT_DATE = 0x0007; +//var VT_BSTR = 0x0008; +//var VT_ERROR = 0x000A; + var VT_BOOL = 0x000B; + var VT_VARIANT = 0x000C; +//var VT_DECIMAL = 0x000E; +//var VT_I1 = 0x0010; +//var VT_UI1 = 0x0011; +//var VT_UI2 = 0x0012; + var VT_UI4 = 0x0013; +//var VT_I8 = 0x0014; +//var VT_UI8 = 0x0015; +//var VT_INT = 0x0016; +//var VT_UINT = 0x0017; + var VT_LPSTR = 0x001E; +//var VT_LPWSTR = 0x001F; + var VT_FILETIME = 0x0040; + var VT_BLOB = 0x0041; +//var VT_STREAM = 0x0042; +//var VT_STORAGE = 0x0043; +//var VT_STREAMED_Object = 0x0044; +//var VT_STORED_Object = 0x0045; +//var VT_BLOB_Object = 0x0046; + var VT_CF = 0x0047; +//var VT_CLSID = 0x0048; +//var VT_VERSIONED_STREAM = 0x0049; + var VT_VECTOR = 0x1000; +//var VT_ARRAY = 0x2000; + + var VT_STRING = 0x0050; // 2.3.3.1.11 VtString + var VT_USTR = 0x0051; // 2.3.3.1.12 VtUnalignedString + var VT_CUSTOM = [VT_STRING, VT_USTR]; + + /* [MS-OSHARED] 2.3.3.2.2.1 Document Summary Information PIDDSI */ + var DocSummaryPIDDSI = { + 0x01: { n: 'CodePage', t: VT_I2 }, + 0x02: { n: 'Category', t: VT_STRING }, + 0x03: { n: 'PresentationFormat', t: VT_STRING }, + 0x04: { n: 'ByteCount', t: VT_I4 }, + 0x05: { n: 'LineCount', t: VT_I4 }, + 0x06: { n: 'ParagraphCount', t: VT_I4 }, + 0x07: { n: 'SlideCount', t: VT_I4 }, + 0x08: { n: 'NoteCount', t: VT_I4 }, + 0x09: { n: 'HiddenCount', t: VT_I4 }, + 0x0a: { n: 'MultimediaClipCount', t: VT_I4 }, + 0x0b: { n: 'ScaleCrop', t: VT_BOOL }, + 0x0c: { n: 'HeadingPairs', t: VT_VECTOR | VT_VARIANT }, + 0x0d: { n: 'TitlesOfParts', t: VT_VECTOR | VT_LPSTR }, + 0x0e: { n: 'Manager', t: VT_STRING }, + 0x0f: { n: 'Company', t: VT_STRING }, + 0x10: { n: 'LinksUpToDate', t: VT_BOOL }, + 0x11: { n: 'CharacterCount', t: VT_I4 }, + 0x13: { n: 'SharedDoc', t: VT_BOOL }, + 0x16: { n: 'HyperlinksChanged', t: VT_BOOL }, + 0x17: { n: 'AppVersion', t: VT_I4, p: 'version' }, + 0x18: { n: 'DigSig', t: VT_BLOB }, + 0x1A: { n: 'ContentType', t: VT_STRING }, + 0x1B: { n: 'ContentStatus', t: VT_STRING }, + 0x1C: { n: 'Language', t: VT_STRING }, + 0x1D: { n: 'Version', t: VT_STRING }, + 0xFF: {} + }; + + /* [MS-OSHARED] 2.3.3.2.1.1 Summary Information Property Set PIDSI */ + var SummaryPIDSI = { + 0x01: { n: 'CodePage', t: VT_I2 }, + 0x02: { n: 'Title', t: VT_STRING }, + 0x03: { n: 'Subject', t: VT_STRING }, + 0x04: { n: 'Author', t: VT_STRING }, + 0x05: { n: 'Keywords', t: VT_STRING }, + 0x06: { n: 'Comments', t: VT_STRING }, + 0x07: { n: 'Template', t: VT_STRING }, + 0x08: { n: 'LastAuthor', t: VT_STRING }, + 0x09: { n: 'RevNumber', t: VT_STRING }, + 0x0A: { n: 'EditTime', t: VT_FILETIME }, + 0x0B: { n: 'LastPrinted', t: VT_FILETIME }, + 0x0C: { n: 'CreatedDate', t: VT_FILETIME }, + 0x0D: { n: 'ModifiedDate', t: VT_FILETIME }, + 0x0E: { n: 'PageCount', t: VT_I4 }, + 0x0F: { n: 'WordCount', t: VT_I4 }, + 0x10: { n: 'CharCount', t: VT_I4 }, + 0x11: { n: 'Thumbnail', t: VT_CF }, + 0x12: { n: 'Application', t: VT_STRING }, + 0x13: { n: 'DocSecurity', t: VT_I4 }, + 0xFF: {} + }; + + /* [MS-OLEPS] 2.18 */ + var SpecialProperties = { + 0x80000000: { n: 'Locale', t: VT_UI4 }, + 0x80000003: { n: 'Behavior', t: VT_UI4 }, + 0x72627262: {} + }; + + (function() { + for(var y in SpecialProperties) if(SpecialProperties.hasOwnProperty(y)) + DocSummaryPIDDSI[y] = SummaryPIDSI[y] = SpecialProperties[y]; + })(); + + var DocSummaryRE = evert_key(DocSummaryPIDDSI, "n"); + var SummaryRE = evert_key(SummaryPIDSI, "n"); + + /* [MS-XLS] 2.4.63 Country/Region codes */ + var CountryEnum = { + 0x0001: "US", // United States + 0x0002: "CA", // Canada + 0x0003: "", // Latin America (except Brazil) + 0x0007: "RU", // Russia + 0x0014: "EG", // Egypt + 0x001E: "GR", // Greece + 0x001F: "NL", // Netherlands + 0x0020: "BE", // Belgium + 0x0021: "FR", // France + 0x0022: "ES", // Spain + 0x0024: "HU", // Hungary + 0x0027: "IT", // Italy + 0x0029: "CH", // Switzerland + 0x002B: "AT", // Austria + 0x002C: "GB", // United Kingdom + 0x002D: "DK", // Denmark + 0x002E: "SE", // Sweden + 0x002F: "NO", // Norway + 0x0030: "PL", // Poland + 0x0031: "DE", // Germany + 0x0034: "MX", // Mexico + 0x0037: "BR", // Brazil + 0x003d: "AU", // Australia + 0x0040: "NZ", // New Zealand + 0x0042: "TH", // Thailand + 0x0051: "JP", // Japan + 0x0052: "KR", // Korea + 0x0054: "VN", // Viet Nam + 0x0056: "CN", // China + 0x005A: "TR", // Turkey + 0x0069: "JS", // Ramastan + 0x00D5: "DZ", // Algeria + 0x00D8: "MA", // Morocco + 0x00DA: "LY", // Libya + 0x015F: "PT", // Portugal + 0x0162: "IS", // Iceland + 0x0166: "FI", // Finland + 0x01A4: "CZ", // Czech Republic + 0x0376: "TW", // Taiwan + 0x03C1: "LB", // Lebanon + 0x03C2: "JO", // Jordan + 0x03C3: "SY", // Syria + 0x03C4: "IQ", // Iraq + 0x03C5: "KW", // Kuwait + 0x03C6: "SA", // Saudi Arabia + 0x03CB: "AE", // United Arab Emirates + 0x03CC: "IL", // Israel + 0x03CE: "QA", // Qatar + 0x03D5: "IR", // Iran + 0xFFFF: "US" // United States + }; + + /* [MS-XLS] 2.5.127 */ + var XLSFillPattern = [ + null, + 'solid', + 'mediumGray', + 'darkGray', + 'lightGray', + 'darkHorizontal', + 'darkVertical', + 'darkDown', + 'darkUp', + 'darkGrid', + 'darkTrellis', + 'lightHorizontal', + 'lightVertical', + 'lightDown', + 'lightUp', + 'lightGrid', + 'lightTrellis', + 'gray125', + 'gray0625' + ]; + + function rgbify(arr) { return arr.map(function(x) { return [(x>>16)&255,(x>>8)&255,x&255]; }); } + + /* [MS-XLS] 2.5.161 */ + /* [MS-XLSB] 2.5.75 Icv */ + var XLSIcv = rgbify([ + /* Color Constants */ + 0x000000, + 0xFFFFFF, + 0xFF0000, + 0x00FF00, + 0x0000FF, + 0xFFFF00, + 0xFF00FF, + 0x00FFFF, + + /* Overridable Defaults */ + 0x000000, + 0xFFFFFF, + 0xFF0000, + 0x00FF00, + 0x0000FF, + 0xFFFF00, + 0xFF00FF, + 0x00FFFF, + + 0x800000, + 0x008000, + 0x000080, + 0x808000, + 0x800080, + 0x008080, + 0xC0C0C0, + 0x808080, + 0x9999FF, + 0x993366, + 0xFFFFCC, + 0xCCFFFF, + 0x660066, + 0xFF8080, + 0x0066CC, + 0xCCCCFF, + + 0x000080, + 0xFF00FF, + 0xFFFF00, + 0x00FFFF, + 0x800080, + 0x800000, + 0x008080, + 0x0000FF, + 0x00CCFF, + 0xCCFFFF, + 0xCCFFCC, + 0xFFFF99, + 0x99CCFF, + 0xFF99CC, + 0xCC99FF, + 0xFFCC99, + + 0x3366FF, + 0x33CCCC, + 0x99CC00, + 0xFFCC00, + 0xFF9900, + 0xFF6600, + 0x666699, + 0x969696, + 0x003366, + 0x339966, + 0x003300, + 0x333300, + 0x993300, + 0x993366, + 0x333399, + 0x333333, + + /* Other entries to appease BIFF8/12 */ + 0xFFFFFF, /* 0x40 icvForeground ?? */ + 0x000000, /* 0x41 icvBackground ?? */ + 0x000000, /* 0x42 icvFrame ?? */ + 0x000000, /* 0x43 icv3D ?? */ + 0x000000, /* 0x44 icv3DText ?? */ + 0x000000, /* 0x45 icv3DHilite ?? */ + 0x000000, /* 0x46 icv3DShadow ?? */ + 0x000000, /* 0x47 icvHilite ?? */ + 0x000000, /* 0x48 icvCtlText ?? */ + 0x000000, /* 0x49 icvCtlScrl ?? */ + 0x000000, /* 0x4A icvCtlInv ?? */ + 0x000000, /* 0x4B icvCtlBody ?? */ + 0x000000, /* 0x4C icvCtlFrame ?? */ + 0x000000, /* 0x4D icvCtlFore ?? */ + 0x000000, /* 0x4E icvCtlBack ?? */ + 0x000000, /* 0x4F icvCtlNeutral */ + 0x000000, /* 0x50 icvInfoBk ?? */ + 0x000000 /* 0x51 icvInfoText ?? */ + ]); + + /* Parts enumerated in OPC spec, MS-XLSB and MS-XLSX */ + /* 12.3 Part Summary */ + /* 14.2 Part Summary */ + /* [MS-XLSX] 2.1 Part Enumerations ; [MS-XLSB] 2.1.7 Part Enumeration */ + var ct2type/*{[string]:string}*/ = ({ + /* Workbook */ + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml": "workbooks", + + /* Worksheet */ + "application/vnd.ms-excel.binIndexWs": "TODO", /* Binary Index */ + + /* Macrosheet */ + "application/vnd.ms-excel.intlmacrosheet": "TODO", + "application/vnd.ms-excel.binIndexMs": "TODO", /* Binary Index */ + + /* File Properties */ + "application/vnd.openxmlformats-package.core-properties+xml": "coreprops", + "application/vnd.openxmlformats-officedocument.custom-properties+xml": "custprops", + "application/vnd.openxmlformats-officedocument.extended-properties+xml": "extprops", + + /* Custom Data Properties */ + "application/vnd.openxmlformats-officedocument.customXmlProperties+xml": "TODO", + "application/vnd.openxmlformats-officedocument.spreadsheetml.customProperty": "TODO", + + /* PivotTable */ + "application/vnd.ms-excel.pivotTable": "TODO", + "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml": "TODO", + + /* Chart Colors */ + "application/vnd.ms-office.chartcolorstyle+xml": "TODO", + + /* Chart Style */ + "application/vnd.ms-office.chartstyle+xml": "TODO", + + /* Calculation Chain */ + "application/vnd.ms-excel.calcChain": "calcchains", + "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml": "calcchains", + + /* Printer Settings */ + "application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings": "TODO", + + /* ActiveX */ + "application/vnd.ms-office.activeX": "TODO", + "application/vnd.ms-office.activeX+xml": "TODO", + + /* Custom Toolbars */ + "application/vnd.ms-excel.attachedToolbars": "TODO", + + /* External Data Connections */ + "application/vnd.ms-excel.connections": "TODO", + "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml": "TODO", + + /* External Links */ + "application/vnd.ms-excel.externalLink": "links", + "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml": "links", + + /* Metadata */ + "application/vnd.ms-excel.sheetMetadata": "TODO", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheetMetadata+xml": "TODO", + + /* PivotCache */ + "application/vnd.ms-excel.pivotCacheDefinition": "TODO", + "application/vnd.ms-excel.pivotCacheRecords": "TODO", + "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml": "TODO", + "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml": "TODO", + + /* Query Table */ + "application/vnd.ms-excel.queryTable": "TODO", + "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml": "TODO", + + /* Shared Workbook */ + "application/vnd.ms-excel.userNames": "TODO", + "application/vnd.ms-excel.revisionHeaders": "TODO", + "application/vnd.ms-excel.revisionLog": "TODO", + "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml": "TODO", + "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml": "TODO", + "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml": "TODO", + + /* Single Cell Table */ + "application/vnd.ms-excel.tableSingleCells": "TODO", + "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml": "TODO", + + /* Slicer */ + "application/vnd.ms-excel.slicer": "TODO", + "application/vnd.ms-excel.slicerCache": "TODO", + "application/vnd.ms-excel.slicer+xml": "TODO", + "application/vnd.ms-excel.slicerCache+xml": "TODO", + + /* Sort Map */ + "application/vnd.ms-excel.wsSortMap": "TODO", + + /* Table */ + "application/vnd.ms-excel.table": "TODO", + "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml": "TODO", + + /* Themes */ + "application/vnd.openxmlformats-officedocument.theme+xml": "themes", + + /* Theme Override */ + "application/vnd.openxmlformats-officedocument.themeOverride+xml": "TODO", + + /* Timeline */ + "application/vnd.ms-excel.Timeline+xml": "TODO", /* verify */ + "application/vnd.ms-excel.TimelineCache+xml": "TODO", /* verify */ + + /* VBA */ + "application/vnd.ms-office.vbaProject": "vba", + "application/vnd.ms-office.vbaProjectSignature": "vba", + + /* Volatile Dependencies */ + "application/vnd.ms-office.volatileDependencies": "TODO", + "application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml": "TODO", + + /* Control Properties */ + "application/vnd.ms-excel.controlproperties+xml": "TODO", + + /* Data Model */ + "application/vnd.openxmlformats-officedocument.model+data": "TODO", + + /* Survey */ + "application/vnd.ms-excel.Survey+xml": "TODO", + + /* Drawing */ + "application/vnd.openxmlformats-officedocument.drawing+xml": "drawings", + "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": "TODO", + "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml": "TODO", + "application/vnd.openxmlformats-officedocument.drawingml.diagramColors+xml": "TODO", + "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml": "TODO", + "application/vnd.openxmlformats-officedocument.drawingml.diagramLayout+xml": "TODO", + "application/vnd.openxmlformats-officedocument.drawingml.diagramStyle+xml": "TODO", + + /* VML */ + "application/vnd.openxmlformats-officedocument.vmlDrawing": "TODO", + + "application/vnd.openxmlformats-package.relationships+xml": "rels", + "application/vnd.openxmlformats-officedocument.oleObject": "TODO", + + /* Image */ + "image/png": "TODO", + + "sheet": "js" + }); + + var CT_LIST = (function(){ + var o = { + workbooks: { + xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", + xlsm: "application/vnd.ms-excel.sheet.macroEnabled.main+xml", + xlsb: "application/vnd.ms-excel.sheet.binary.macroEnabled.main", + xlam: "application/vnd.ms-excel.addin.macroEnabled.main+xml", + xltx: "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml" + }, + strs: { /* Shared Strings */ + xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml", + xlsb: "application/vnd.ms-excel.sharedStrings" + }, + comments: { /* Comments */ + xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml", + xlsb: "application/vnd.ms-excel.comments" + }, + sheets: { /* Worksheet */ + xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml", + xlsb: "application/vnd.ms-excel.worksheet" + }, + charts: { /* Chartsheet */ + xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml", + xlsb: "application/vnd.ms-excel.chartsheet" + }, + dialogs: { /* Dialogsheet */ + xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml", + xlsb: "application/vnd.ms-excel.dialogsheet" + }, + macros: { /* Macrosheet (Excel 4.0 Macros) */ + xlsx: "application/vnd.ms-excel.macrosheet+xml", + xlsb: "application/vnd.ms-excel.macrosheet" + }, + styles: { /* Styles */ + xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml", + xlsb: "application/vnd.ms-excel.styles" + } + }; + keys(o).forEach(function(k) { ["xlsm", "xlam"].forEach(function(v) { if(!o[k][v]) o[k][v] = o[k].xlsx; }); }); + keys(o).forEach(function(k){ keys(o[k]).forEach(function(v) { ct2type[o[k][v]] = k; }); }); + return o; + })(); + + var type2ct/*{[string]:Array}*/ = evert_arr(ct2type); + + XMLNS.CT = 'http://schemas.openxmlformats.org/package/2006/content-types'; + + function new_ct() { + return ({ + workbooks:[], sheets:[], charts:[], dialogs:[], macros:[], + rels:[], strs:[], comments:[], links:[], + coreprops:[], extprops:[], custprops:[], themes:[], styles:[], + calcchains:[], vba: [], drawings: [], + TODO:[], xmlns: "" }); + } + + function parse_ct(data) { + var ct = new_ct(); + if(!data || !data.match) return ct; + var ctext = {}; + (data.match(tagregex)||[]).forEach(function(x) { + var y = parsexmltag(x); + switch(y[0].replace(nsregex,"<")) { + case ' 0 ? ct.calcchains[0] : ""; + ct.sst = ct.strs.length > 0 ? ct.strs[0] : ""; + ct.style = ct.styles.length > 0 ? ct.styles[0] : ""; + ct.defaults = ctext; + delete ct.calcchains; + return ct; + } + + var CTYPE_XML_ROOT = writextag('Types', null, { + 'xmlns': XMLNS.CT, + 'xmlns:xsd': XMLNS.xsd, + 'xmlns:xsi': XMLNS.xsi + }); + + var CTYPE_DEFAULTS = [ + ['xml', 'application/xml'], + ['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'], + ['vml', 'application/vnd.openxmlformats-officedocument.vmlDrawing'], + /* from test files */ + ['bmp', 'image/bmp'], + ['png', 'image/png'], + ['gif', 'image/gif'], + ['emf', 'image/x-emf'], + ['wmf', 'image/x-wmf'], + ['jpg', 'image/jpeg'], ['jpeg', 'image/jpeg'], + ['tif', 'image/tiff'], ['tiff', 'image/tiff'], + ['pdf', 'application/pdf'], + ['rels', type2ct.rels[0]] + ].map(function(x) { + return writextag('Default', null, {'Extension':x[0], 'ContentType': x[1]}); + }); + + function write_ct(ct, opts) { + var o = [], v; + o[o.length] = (XML_HEADER); + o[o.length] = (CTYPE_XML_ROOT); + o = o.concat(CTYPE_DEFAULTS); + var f1 = function(w) { + if(ct[w] && ct[w].length > 0) { + v = ct[w][0]; + o[o.length] = (writextag('Override', null, { + 'PartName': (v[0] == '/' ? "":"/") + v, + 'ContentType': CT_LIST[w][opts.bookType || 'xlsx'] + })); + } + }; + var f2 = function(w) { + (ct[w]||[]).forEach(function(v) { + o[o.length] = (writextag('Override', null, { + 'PartName': (v[0] == '/' ? "":"/") + v, + 'ContentType': CT_LIST[w][opts.bookType || 'xlsx'] + })); + }); + }; + var f3 = function(t) { + (ct[t]||[]).forEach(function(v) { + o[o.length] = (writextag('Override', null, { + 'PartName': (v[0] == '/' ? "":"/") + v, + 'ContentType': type2ct[t][0] + })); + }); + }; + f1('workbooks'); + f2('sheets'); + f2('charts'); + f3('themes'); + ['strs', 'styles'].forEach(f1); + ['coreprops', 'extprops', 'custprops'].forEach(f3); + f3('vba'); + f3('comments'); + f3('drawings'); + if(o.length>2){ o[o.length] = (''); o[1]=o[1].replace("/>",">"); } + return o.join(""); + } + /* 9.3 Relationships */ + var RELS = ({ + WB: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", + SHEET: "http://sheetjs.openxmlformats.org/officeDocument/2006/relationships/officeDocument", + HLINK: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", + VML: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing", + VBA: "http://schemas.microsoft.com/office/2006/relationships/vbaProject" + }); + + /* 9.3.3 Representing Relationships */ + function get_rels_path(file) { + var n = file.lastIndexOf("/"); + return file.slice(0,n+1) + '_rels/' + file.slice(n+1) + ".rels"; + } + + function parse_rels(data, currentFilePath) { + if (!data) return data; + if (currentFilePath.charAt(0) !== '/') { + currentFilePath = '/'+currentFilePath; + } + var rels = {}; + var hash = {}; + + (data.match(tagregex)||[]).forEach(function(x) { + var y = parsexmltag(x); + /* 9.3.2.2 OPC_Relationships */ + if (y[0] === '2){ o[o.length] = (''); o[1]=o[1].replace("/>",">"); } + return o.join(""); + } + + function add_rels(rels, rId, f, type, relobj) { + if(!relobj) relobj = {}; + if(!rels['!id']) rels['!id'] = {}; + if(rId < 0) for(rId = 1; rels['!id']['rId' + rId]; ++rId){/* empty */} + relobj.Id = 'rId' + rId; + relobj.Type = type; + relobj.Target = f; + if(relobj.Type == RELS.HLINK) relobj.TargetMode = "External"; + if(rels['!id'][relobj.Id]) throw new Error("Cannot rewrite rId " + rId); + rels['!id'][relobj.Id] = relobj; + rels[('/' + relobj.Target).replace("//","/")] = relobj; + return rId; + } + /* Open Document Format for Office Applications (OpenDocument) Version 1.2 */ + /* Part 3 Section 4 Manifest File */ + var CT_ODS = "application/vnd.oasis.opendocument.spreadsheet"; + function parse_manifest(d, opts) { + var str = xlml_normalize(d); + var Rn; + var FEtag; + while((Rn = xlmlregex.exec(str))) switch(Rn[3]) { + case 'manifest': break; // 4.2 + case 'file-entry': // 4.3 + FEtag = parsexmltag(Rn[0], false); + if(FEtag.path == '/' && FEtag.type !== CT_ODS) throw new Error("This OpenDocument is not a spreadsheet"); + break; + case 'encryption-data': // 4.4 + case 'algorithm': // 4.5 + case 'start-key-generation': // 4.6 + case 'key-derivation': // 4.7 + throw new Error("Unsupported ODS Encryption"); + default: if(opts && opts.WTF) throw Rn; + } + } + + function write_manifest(manifest) { + var o = [XML_HEADER]; + o.push('\n'); + o.push(' \n'); + for(var i = 0; i < manifest.length; ++i) o.push(' \n'); + o.push(''); + return o.join(""); + } + + /* Part 3 Section 6 Metadata Manifest File */ + function write_rdf_type(file, res, tag) { + return [ + ' \n', + ' \n', + ' \n' + ].join(""); + } + function write_rdf_has(base, file) { + return [ + ' \n', + ' \n', + ' \n' + ].join(""); + } + function write_rdf(rdf) { + var o = [XML_HEADER]; + o.push('\n'); + for(var i = 0; i != rdf.length; ++i) { + o.push(write_rdf_type(rdf[i][0], rdf[i][1])); + o.push(write_rdf_has("",rdf[i][0])); + } + o.push(write_rdf_type("","Document", "pkg")); + o.push(''); + return o.join(""); + } + /* TODO: pull properties */ + var write_meta_ods = (function() { + var payload = 'Sheet' + 'JS ' + XLSX.version + ''; + return function wmo() { + return payload; + }; + })(); + + /* ECMA-376 Part II 11.1 Core Properties Part */ + /* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */ + var CORE_PROPS = [ + ["cp:category", "Category"], + ["cp:contentStatus", "ContentStatus"], + ["cp:keywords", "Keywords"], + ["cp:lastModifiedBy", "LastAuthor"], + ["cp:lastPrinted", "LastPrinted"], + ["cp:revision", "RevNumber"], + ["cp:version", "Version"], + ["dc:creator", "Author"], + ["dc:description", "Comments"], + ["dc:identifier", "Identifier"], + ["dc:language", "Language"], + ["dc:subject", "Subject"], + ["dc:title", "Title"], + ["dcterms:created", "CreatedDate", 'date'], + ["dcterms:modified", "ModifiedDate", 'date'] + ]; + + XMLNS.CORE_PROPS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"; + RELS.CORE_PROPS = 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties'; + + var CORE_PROPS_REGEX = (function() { + var r = new Array(CORE_PROPS.length); + for(var i = 0; i < CORE_PROPS.length; ++i) { + var f = CORE_PROPS[i]; + var g = "(?:"+ f[0].slice(0,f[0].indexOf(":")) +":)"+ f[0].slice(f[0].indexOf(":")+1); + r[i] = new RegExp("<" + g + "[^>]*>([\\s\\S]*?)<\/" + g + ">"); + } + return r; + })(); + + function parse_core_props(data) { + var p = {}; + data = utf8read(data); + + for(var i = 0; i < CORE_PROPS.length; ++i) { + var f = CORE_PROPS[i], cur = data.match(CORE_PROPS_REGEX[i]); + if(cur != null && cur.length > 0) p[f[1]] = cur[1]; + if(f[2] === 'date' && p[f[1]]) p[f[1]] = parseDate(p[f[1]]); + } + + return p; + } + + var CORE_PROPS_XML_ROOT = writextag('cp:coreProperties', null, { + //'xmlns': XMLNS.CORE_PROPS, + 'xmlns:cp': XMLNS.CORE_PROPS, + 'xmlns:dc': XMLNS.dc, + 'xmlns:dcterms': XMLNS.dcterms, + 'xmlns:dcmitype': XMLNS.dcmitype, + 'xmlns:xsi': XMLNS.xsi + }); + + function cp_doit(f, g, h, o, p) { + if(p[f] != null || g == null || g === "") return; + p[f] = g; + o[o.length] = (h ? writextag(f,g,h) : writetag(f,g)); + } + + function write_core_props(cp, _opts) { + var opts = _opts || {}; + var o = [XML_HEADER, CORE_PROPS_XML_ROOT], p = {}; + if(!cp && !opts.Props) return o.join(""); + + if(cp) { + if(cp.CreatedDate != null) cp_doit("dcterms:created", typeof cp.CreatedDate === "string" ? cp.CreatedDate : write_w3cdtf(cp.CreatedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p); + if(cp.ModifiedDate != null) cp_doit("dcterms:modified", typeof cp.ModifiedDate === "string" ? cp.ModifiedDate : write_w3cdtf(cp.ModifiedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p); + } + + for(var i = 0; i != CORE_PROPS.length; ++i) { + var f = CORE_PROPS[i]; + var v = opts.Props && opts.Props[f[1]] != null ? opts.Props[f[1]] : cp ? cp[f[1]] : null; + if(v === true) v = "1"; + else if(v === false) v = "0"; + else if(typeof v == "number") v = String(v); + if(v != null) cp_doit(f[0], v, null, o, p); + } + if(o.length>2){ o[o.length] = (''); o[1]=o[1].replace("/>",">"); } + return o.join(""); + } + /* 15.2.12.3 Extended File Properties Part */ + /* [MS-OSHARED] 2.3.3.2.[1-2].1 (PIDSI/PIDDSI) */ + var EXT_PROPS = [ + ["Application", "Application", "string"], + ["AppVersion", "AppVersion", "string"], + ["Company", "Company", "string"], + ["DocSecurity", "DocSecurity", "string"], + ["Manager", "Manager", "string"], + ["HyperlinksChanged", "HyperlinksChanged", "bool"], + ["SharedDoc", "SharedDoc", "bool"], + ["LinksUpToDate", "LinksUpToDate", "bool"], + ["ScaleCrop", "ScaleCrop", "bool"], + ["HeadingPairs", "HeadingPairs", "raw"], + ["TitlesOfParts", "TitlesOfParts", "raw"] + ]; + + XMLNS.EXT_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"; + RELS.EXT_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties'; + + var PseudoPropsPairs = [ + "Worksheets", "SheetNames", + "NamedRanges", "DefinedNames", + "Chartsheets", "ChartNames" + ]; + function load_props_pairs(HP, TOP, props, opts) { + var v = []; + if(typeof HP == "string") v = parseVector(HP, opts); + else for(var j = 0; j < HP.length; ++j) v = v.concat(HP[j].map(function(hp) { return {v:hp}; })); + var parts = (typeof TOP == "string") ? parseVector(TOP, opts).map(function (x) { return x.v; }) : TOP; + var idx = 0, len = 0; + if(parts.length > 0) for(var i = 0; i !== v.length; i += 2) { + len = +(v[i+1].v); + switch(v[i].v) { + case "Worksheets": + case "工作表": + case "Листы": + case "أوراق العمل": + case "ワークシート": + case "גליונות עבודה": + case "Arbeitsblätter": + case "Çalışma Sayfaları": + case "Feuilles de calcul": + case "Fogli di lavoro": + case "Folhas de cálculo": + case "Planilhas": + case "Regneark": + case "Werkbladen": + props.Worksheets = len; + props.SheetNames = parts.slice(idx, idx + len); + break; + + case "Named Ranges": + case "名前付き一覧": + case "Benannte Bereiche": + case "Navngivne områder": + props.NamedRanges = len; + props.DefinedNames = parts.slice(idx, idx + len); + break; + + case "Charts": + case "Diagramme": + props.Chartsheets = len; + props.ChartNames = parts.slice(idx, idx + len); + break; + } + idx += len; + } + } + + function parse_ext_props(data, p, opts) { + var q = {}; if(!p) p = {}; + data = utf8read(data); + + EXT_PROPS.forEach(function(f) { + switch(f[2]) { + case "string": p[f[1]] = (data.match(matchtag(f[0]))||[])[1]; break; + case "bool": p[f[1]] = (data.match(matchtag(f[0]))||[])[1] === "true"; break; + case "raw": + var cur = data.match(new RegExp("<" + f[0] + "[^>]*>([\\s\\S]*?)<\/" + f[0] + ">")); + if(cur && cur.length > 0) q[f[1]] = cur[1]; + break; + } + }); + + if(q.HeadingPairs && q.TitlesOfParts) load_props_pairs(q.HeadingPairs, q.TitlesOfParts, p, opts); + + return p; + } + + var EXT_PROPS_XML_ROOT = writextag('Properties', null, { + 'xmlns': XMLNS.EXT_PROPS, + 'xmlns:vt': XMLNS.vt + }); + + function write_ext_props(cp) { + var o = [], W = writextag; + if(!cp) cp = {}; + cp.Application = "SheetJS"; + o[o.length] = (XML_HEADER); + o[o.length] = (EXT_PROPS_XML_ROOT); + + EXT_PROPS.forEach(function(f) { + if(cp[f[1]] === undefined) return; + var v; + switch(f[2]) { + case 'string': v = String(cp[f[1]]); break; + case 'bool': v = cp[f[1]] ? 'true' : 'false'; break; + } + if(v !== undefined) o[o.length] = (W(f[0], v)); + }); + + /* TODO: HeadingPairs, TitlesOfParts */ + o[o.length] = (W('HeadingPairs', W('vt:vector', W('vt:variant', 'Worksheets')+W('vt:variant', W('vt:i4', String(cp.Worksheets))), {size:2, baseType:"variant"}))); + o[o.length] = (W('TitlesOfParts', W('vt:vector', cp.SheetNames.map(function(s) { return "" + escapexml(s) + ""; }).join(""), {size: cp.Worksheets, baseType:"lpstr"}))); + if(o.length>2){ o[o.length] = (''); o[1]=o[1].replace("/>",">"); } + return o.join(""); + } + /* 15.2.12.2 Custom File Properties Part */ + XMLNS.CUST_PROPS = "http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"; + RELS.CUST_PROPS = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties'; + + var custregex = /<[^>]+>[^<]*/g; + function parse_cust_props(data, opts) { + var p = {}, name = ""; + var m = data.match(custregex); + if(m) for(var i = 0; i != m.length; ++i) { + var x = m[i], y = parsexmltag(x); + switch(y[0]) { + case '': name = null; break; + default: if (x.indexOf(''); + var type = toks[0].slice(4), text = toks[1]; + /* 22.4.2.32 (CT_Variant). Omit the binary types from 22.4 (Variant Types) */ + switch(type) { + case 'lpstr': case 'bstr': case 'lpwstr': + p[name] = unescapexml(text); + break; + case 'bool': + p[name] = parsexmlbool(text); + break; + case 'i1': case 'i2': case 'i4': case 'i8': case 'int': case 'uint': + p[name] = parseInt(text, 10); + break; + case 'r4': case 'r8': case 'decimal': + p[name] = parseFloat(text); + break; + case 'filetime': case 'date': + p[name] = parseDate(text); + break; + case 'cy': case 'error': + p[name] = unescapexml(text); + break; + default: + if(type.slice(-1) == '/') break; + if(opts.WTF && typeof console !== 'undefined') console.warn('Unexpected', x, type, toks); + } + } else if(x.slice(0,2) === "2){ o[o.length] = ''; o[1]=o[1].replace("/>",">"); } + return o.join(""); + } + /* Common Name -> XLML Name */ + var XLMLDocPropsMap = { + Title: 'Title', + Subject: 'Subject', + Author: 'Author', + Keywords: 'Keywords', + Comments: 'Description', + LastAuthor: 'LastAuthor', + RevNumber: 'Revision', + Application: 'AppName', + /* TotalTime: 'TotalTime', */ + LastPrinted: 'LastPrinted', + CreatedDate: 'Created', + ModifiedDate: 'LastSaved', + /* Pages */ + /* Words */ + /* Characters */ + Category: 'Category', + /* PresentationFormat */ + Manager: 'Manager', + Company: 'Company', + /* Guid */ + /* HyperlinkBase */ + /* Bytes */ + /* Lines */ + /* Paragraphs */ + /* CharactersWithSpaces */ + AppVersion: 'Version', + + ContentStatus: 'ContentStatus', /* NOTE: missing from schema */ + Identifier: 'Identifier', /* NOTE: missing from schema */ + Language: 'Language' /* NOTE: missing from schema */ + }; + var evert_XLMLDPM = evert(XLMLDocPropsMap); + + function xlml_set_prop(Props, tag, val) { + tag = evert_XLMLDPM[tag] || tag; + Props[tag] = val; + } + + function xlml_write_docprops(Props, opts) { + var o = []; + keys(XLMLDocPropsMap).map(function(m) { + for(var i = 0; i < CORE_PROPS.length; ++i) if(CORE_PROPS[i][1] == m) return CORE_PROPS[i]; + for(i = 0; i < EXT_PROPS.length; ++i) if(EXT_PROPS[i][1] == m) return EXT_PROPS[i]; + throw m; + }).forEach(function(p) { + if(Props[p[1]] == null) return; + var m = opts && opts.Props && opts.Props[p[1]] != null ? opts.Props[p[1]] : Props[p[1]]; + switch(p[2]) { + case 'date': m = new Date(m).toISOString().replace(/\.\d*Z/,"Z"); break; + } + if(typeof m == 'number') m = String(m); + else if(m === true || m === false) { m = m ? "1" : "0"; } + else if(m instanceof Date) m = new Date(m).toISOString().replace(/\.\d*Z/,""); + o.push(writetag(XLMLDocPropsMap[p[1]] || p[1], m)); + }); + return writextag('DocumentProperties', o.join(""), {xmlns:XLMLNS.o }); + } + function xlml_write_custprops(Props, Custprops) { + var BLACKLIST = ["Worksheets","SheetNames"]; + var T = 'CustomDocumentProperties'; + var o = []; + if(Props) keys(Props).forEach(function(k) { + if(!Props.hasOwnProperty(k)) return; + for(var i = 0; i < CORE_PROPS.length; ++i) if(k == CORE_PROPS[i][1]) return; + for(i = 0; i < EXT_PROPS.length; ++i) if(k == EXT_PROPS[i][1]) return; + for(i = 0; i < BLACKLIST.length; ++i) if(k == BLACKLIST[i]) return; + + var m = Props[k]; + var t = "string"; + if(typeof m == 'number') { t = "float"; m = String(m); } + else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; } + else m = String(m); + o.push(writextag(escapexmltag(k), m, {"dt:dt":t})); + }); + if(Custprops) keys(Custprops).forEach(function(k) { + if(!Custprops.hasOwnProperty(k)) return; + if(Props && Props.hasOwnProperty(k)) return; + var m = Custprops[k]; + var t = "string"; + if(typeof m == 'number') { t = "float"; m = String(m); } + else if(m === true || m === false) { t = "boolean"; m = m ? "1" : "0"; } + else if(m instanceof Date) { t = "dateTime.tz"; m = m.toISOString(); } + else m = String(m); + o.push(writextag(escapexmltag(k), m, {"dt:dt":t})); + }); + return '<' + T + ' xmlns="' + XLMLNS.o + '">' + o.join("") + ''; + } + /* [MS-DTYP] 2.3.3 FILETIME */ + /* [MS-OLEDS] 2.1.3 FILETIME (Packet Version) */ + /* [MS-OLEPS] 2.8 FILETIME (Packet Version) */ + function parse_FILETIME(blob) { + var dwLowDateTime = blob.read_shift(4), dwHighDateTime = blob.read_shift(4); + return new Date(((dwHighDateTime/1e7*Math.pow(2,32) + dwLowDateTime/1e7) - 11644473600)*1000).toISOString().replace(/\.000/,""); + } + function write_FILETIME(time) { + var date = (typeof time == "string") ? new Date(Date.parse(time)) : time; + var t = date.getTime() / 1000 + 11644473600; + var l = t % Math.pow(2,32), h = (t - l) / Math.pow(2,32); + l *= 1e7; h *= 1e7; + var w = (l / Math.pow(2,32)) | 0; + if(w > 0) { l = l % Math.pow(2,32); h += w; } + var o = new_buf(8); o.write_shift(4, l); o.write_shift(4, h); return o; + } + + /* [MS-OSHARED] 2.3.3.1.4 Lpstr */ + function parse_lpstr(blob, type, pad) { + var start = blob.l; + var str = blob.read_shift(0, 'lpstr-cp'); + if(pad) while((blob.l - start) & 3) ++blob.l; + return str; + } + + /* [MS-OSHARED] 2.3.3.1.6 Lpwstr */ + function parse_lpwstr(blob, type, pad) { + var str = blob.read_shift(0, 'lpwstr'); + if(pad) blob.l += (4 - ((str.length+1) & 3)) & 3; + return str; + } + + + /* [MS-OSHARED] 2.3.3.1.11 VtString */ + /* [MS-OSHARED] 2.3.3.1.12 VtUnalignedString */ + function parse_VtStringBase(blob, stringType, pad) { + if(stringType === 0x1F /*VT_LPWSTR*/) return parse_lpwstr(blob); + return parse_lpstr(blob, stringType, pad); + } + + function parse_VtString(blob, t, pad) { return parse_VtStringBase(blob, t, pad === false ? 0: 4); } + function parse_VtUnalignedString(blob, t) { if(!t) throw new Error("VtUnalignedString must have positive length"); return parse_VtStringBase(blob, t, 0); } + + /* [MS-OSHARED] 2.3.3.1.9 VtVecUnalignedLpstrValue */ + function parse_VtVecUnalignedLpstrValue(blob) { + var length = blob.read_shift(4); + var ret = []; + for(var i = 0; i != length; ++i) ret[i] = blob.read_shift(0, 'lpstr-cp').replace(chr0,''); + return ret; + } + + /* [MS-OSHARED] 2.3.3.1.10 VtVecUnalignedLpstr */ + function parse_VtVecUnalignedLpstr(blob) { + return parse_VtVecUnalignedLpstrValue(blob); + } + + /* [MS-OSHARED] 2.3.3.1.13 VtHeadingPair */ + function parse_VtHeadingPair(blob) { + var headingString = parse_TypedPropertyValue(blob, VT_USTR); + var headerParts = parse_TypedPropertyValue(blob, VT_I4); + return [headingString, headerParts]; + } + + /* [MS-OSHARED] 2.3.3.1.14 VtVecHeadingPairValue */ + function parse_VtVecHeadingPairValue(blob) { + var cElements = blob.read_shift(4); + var out = []; + for(var i = 0; i != cElements / 2; ++i) out.push(parse_VtHeadingPair(blob)); + return out; + } + + /* [MS-OSHARED] 2.3.3.1.15 VtVecHeadingPair */ + function parse_VtVecHeadingPair(blob) { + // NOTE: When invoked, wType & padding were already consumed + return parse_VtVecHeadingPairValue(blob); + } + + /* [MS-OLEPS] 2.18.1 Dictionary (uses 2.17, 2.16) */ + function parse_dictionary(blob,CodePage) { + var cnt = blob.read_shift(4); + var dict = ({}); + for(var j = 0; j != cnt; ++j) { + var pid = blob.read_shift(4); + var len = blob.read_shift(4); + dict[pid] = blob.read_shift(len, (CodePage === 0x4B0 ?'utf16le':'utf8')).replace(chr0,'').replace(chr1,'!'); + if(CodePage === 0x4B0 && (len % 2)) blob.l += 2; + } + if(blob.l & 3) blob.l = (blob.l>>2+1)<<2; + return dict; + } + + /* [MS-OLEPS] 2.9 BLOB */ + function parse_BLOB(blob) { + var size = blob.read_shift(4); + var bytes = blob.slice(blob.l,blob.l+size); + blob.l += size; + if((size & 3) > 0) blob.l += (4 - (size & 3)) & 3; + return bytes; + } + + /* [MS-OLEPS] 2.11 ClipboardData */ + function parse_ClipboardData(blob) { + // TODO + var o = {}; + o.Size = blob.read_shift(4); + //o.Format = blob.read_shift(4); + blob.l += o.Size + 3 - (o.Size - 1) % 4; + return o; + } + + /* [MS-OLEPS] 2.15 TypedPropertyValue */ + function parse_TypedPropertyValue(blob, type, _opts) { + var t = blob.read_shift(2), ret, opts = _opts||{}; + blob.l += 2; + if(type !== VT_VARIANT) + if(t !== type && VT_CUSTOM.indexOf(type)===-1) throw new Error('Expected type ' + type + ' saw ' + t); + switch(type === VT_VARIANT ? t : type) { + case 0x02 /*VT_I2*/: ret = blob.read_shift(2, 'i'); if(!opts.raw) blob.l += 2; return ret; + case 0x03 /*VT_I4*/: ret = blob.read_shift(4, 'i'); return ret; + case 0x0B /*VT_BOOL*/: return blob.read_shift(4) !== 0x0; + case 0x13 /*VT_UI4*/: ret = blob.read_shift(4); return ret; + case 0x1E /*VT_LPSTR*/: return parse_lpstr(blob, t, 4).replace(chr0,''); + case 0x1F /*VT_LPWSTR*/: return parse_lpwstr(blob); + case 0x40 /*VT_FILETIME*/: return parse_FILETIME(blob); + case 0x41 /*VT_BLOB*/: return parse_BLOB(blob); + case 0x47 /*VT_CF*/: return parse_ClipboardData(blob); + case 0x50 /*VT_STRING*/: return parse_VtString(blob, t, !opts.raw).replace(chr0,''); + case 0x51 /*VT_USTR*/: return parse_VtUnalignedString(blob, t/*, 4*/).replace(chr0,''); + case 0x100C /*VT_VECTOR|VT_VARIANT*/: return parse_VtVecHeadingPair(blob); + case 0x101E /*VT_LPSTR*/: return parse_VtVecUnalignedLpstr(blob); + default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + t); + } + } + function write_TypedPropertyValue(type, value) { + var o = new_buf(4), p = new_buf(4); + o.write_shift(4, type == 0x50 ? 0x1F : type); + switch(type) { + case 0x03 /*VT_I4*/: p.write_shift(-4, value); break; + case 0x05 /*VT_I4*/: p = new_buf(8); p.write_shift(8, value, 'f'); break; + case 0x0B /*VT_BOOL*/: p.write_shift(4, value ? 0x01 : 0x00); break; + case 0x40 /*VT_FILETIME*/: p = write_FILETIME(value); break; + case 0x1F /*VT_LPWSTR*/: + case 0x50 /*VT_STRING*/: + p = new_buf(4 + 2 * (value.length + 1) + (value.length % 2 ? 0 : 2)); + p.write_shift(4, value.length + 1); + p.write_shift(0, value, "dbcs"); + while(p.l != p.length) p.write_shift(1, 0); + break; + default: throw new Error("TypedPropertyValue unrecognized type " + type + " " + value); + } + return bconcat([o, p]); + } + + /* [MS-OLEPS] 2.20 PropertySet */ + function parse_PropertySet(blob, PIDSI) { + var start_addr = blob.l; + var size = blob.read_shift(4); + var NumProps = blob.read_shift(4); + var Props = [], i = 0; + var CodePage = 0; + var Dictionary = -1, DictObj = ({}); + for(i = 0; i != NumProps; ++i) { + var PropID = blob.read_shift(4); + var Offset = blob.read_shift(4); + Props[i] = [PropID, Offset + start_addr]; + } + Props.sort(function(x,y) { return x[1] - y[1]; }); + var PropH = {}; + for(i = 0; i != NumProps; ++i) { + if(blob.l !== Props[i][1]) { + var fail = true; + if(i>0 && PIDSI) switch(PIDSI[Props[i-1][0]].t) { + case 0x02 /*VT_I2*/: if(blob.l+2 === Props[i][1]) { blob.l+=2; fail = false; } break; + case 0x50 /*VT_STRING*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break; + case 0x100C /*VT_VECTOR|VT_VARIANT*/: if(blob.l <= Props[i][1]) { blob.l=Props[i][1]; fail = false; } break; + } + if((!PIDSI||i==0) && blob.l <= Props[i][1]) { fail=false; blob.l = Props[i][1]; } + if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i); + } + if(PIDSI) { + var piddsi = PIDSI[Props[i][0]]; + PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true}); + if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + ("0000" + String(PropH[piddsi.n] & 0xFFFF)).slice(-4); + if(piddsi.n == "CodePage") switch(PropH[piddsi.n]) { + case 0: PropH[piddsi.n] = 1252; + /* falls through */ + case 874: + case 932: + case 936: + case 949: + case 950: + case 1250: + case 1251: + case 1253: + case 1254: + case 1255: + case 1256: + case 1257: + case 1258: + case 10000: + case 1200: + case 1201: + case 1252: + case 65000: case -536: + case 65001: case -535: + set_cp(CodePage = (PropH[piddsi.n]>>>0) & 0xFFFF); break; + default: throw new Error("Unsupported CodePage: " + PropH[piddsi.n]); + } + } else { + if(Props[i][0] === 0x1) { + CodePage = PropH.CodePage = (parse_TypedPropertyValue(blob, VT_I2)); + set_cp(CodePage); + if(Dictionary !== -1) { + var oldpos = blob.l; + blob.l = Props[Dictionary][1]; + DictObj = parse_dictionary(blob,CodePage); + blob.l = oldpos; + } + } else if(Props[i][0] === 0) { + if(CodePage === 0) { Dictionary = i; blob.l = Props[i+1][1]; continue; } + DictObj = parse_dictionary(blob,CodePage); + } else { + var name = DictObj[Props[i][0]]; + var val; + /* [MS-OSHARED] 2.3.3.2.3.1.2 + PROPVARIANT */ + switch(blob[blob.l]) { + case 0x41 /*VT_BLOB*/: blob.l += 4; val = parse_BLOB(blob); break; + case 0x1E /*VT_LPSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break; + case 0x1F /*VT_LPWSTR*/: blob.l += 4; val = parse_VtString(blob, blob[blob.l-4]).replace(/\u0000+$/,""); break; + case 0x03 /*VT_I4*/: blob.l += 4; val = blob.read_shift(4, 'i'); break; + case 0x13 /*VT_UI4*/: blob.l += 4; val = blob.read_shift(4); break; + case 0x05 /*VT_R8*/: blob.l += 4; val = blob.read_shift(8, 'f'); break; + case 0x0B /*VT_BOOL*/: blob.l += 4; val = parsebool(blob, 4); break; + case 0x40 /*VT_FILETIME*/: blob.l += 4; val = parseDate(parse_FILETIME(blob)); break; + default: throw new Error("unparsed value: " + blob[blob.l]); + } + PropH[name] = val; + } + } + } + blob.l = start_addr + size; /* step ahead to skip padding */ + return PropH; + } + var XLSPSSkip = [ "CodePage", "Thumbnail", "_PID_LINKBASE", "_PID_HLINKS", "SystemIdentifier", "FMTID" ].concat(PseudoPropsPairs); + function guess_property_type(val) { + switch(typeof val) { + case "boolean": return 0x0B; + case "number": return ((val|0)==val) ? 0x03 : 0x05; + case "string": return 0x1F; + case "object": if(val instanceof Date) return 0x40; break; + } + return -1; + } + function write_PropertySet(entries, RE, PIDSI) { + var hdr = new_buf(8), piao = [], prop = []; + var sz = 8, i = 0; + + var pr = new_buf(8), pio = new_buf(8); + pr.write_shift(4, 0x0002); + pr.write_shift(4, 0x04B0); + pio.write_shift(4, 0x0001); + prop.push(pr); piao.push(pio); + sz += 8 + pr.length; + + if(!RE) { + pio = new_buf(8); + pio.write_shift(4, 0); + piao.unshift(pio); + + var bufs = [new_buf(4)]; + bufs[0].write_shift(4, entries.length); + for(i = 0; i < entries.length; ++i) { + var value = entries[i][0]; + pr = new_buf(4 + 4 + 2 * (value.length + 1) + (value.length % 2 ? 0 : 2)); + pr.write_shift(4, i+2); + pr.write_shift(4, value.length + 1); + pr.write_shift(0, value, "dbcs"); + while(pr.l != pr.length) pr.write_shift(1, 0); + bufs.push(pr); + } + pr = bconcat(bufs); + prop.unshift(pr); + sz += 8 + pr.length; + } + + for(i = 0; i < entries.length; ++i) { + if(RE && !RE[entries[i][0]]) continue; + if(XLSPSSkip.indexOf(entries[i][0]) > -1) continue; + if(entries[i][1] == null) continue; + + var val = entries[i][1], idx = 0; + if(RE) { + idx = +RE[entries[i][0]]; + var pinfo = (PIDSI)[idx]; + if(pinfo.p == "version" && typeof val == "string") { + var arr = val.split("."); + val = ((+arr[0])<<16) + ((+arr[1])||0); + } + pr = write_TypedPropertyValue(pinfo.t, val); + } else { + var T = guess_property_type(val); + if(T == -1) { T = 0x1F; val = String(val); } + pr = write_TypedPropertyValue(T, val); + } + prop.push(pr); + + pio = new_buf(8); + pio.write_shift(4, !RE ? 2+i : idx); + piao.push(pio); + + sz += 8 + pr.length; + } + + var w = 8 * (prop.length + 1); + for(i = 0; i < prop.length; ++i) { piao[i].write_shift(4, w); w += prop[i].length; } + hdr.write_shift(4, sz); + hdr.write_shift(4, prop.length); + return bconcat([hdr].concat(piao).concat(prop)); + } + + /* [MS-OLEPS] 2.21 PropertySetStream */ + function parse_PropertySetStream(file, PIDSI, clsid) { + var blob = file.content; + if(!blob) return ({}); + prep_blob(blob, 0); + + var NumSets, FMTID0, FMTID1, Offset0, Offset1 = 0; + blob.chk('feff', 'Byte Order: '); + + /*var vers = */blob.read_shift(2); // TODO: check version + var SystemIdentifier = blob.read_shift(4); + var CLSID = blob.read_shift(16); + if(CLSID !== CFB.utils.consts.HEADER_CLSID && CLSID !== clsid) throw new Error("Bad PropertySet CLSID " + CLSID); + NumSets = blob.read_shift(4); + if(NumSets !== 1 && NumSets !== 2) throw new Error("Unrecognized #Sets: " + NumSets); + FMTID0 = blob.read_shift(16); Offset0 = blob.read_shift(4); + + if(NumSets === 1 && Offset0 !== blob.l) throw new Error("Length mismatch: " + Offset0 + " !== " + blob.l); + else if(NumSets === 2) { FMTID1 = blob.read_shift(16); Offset1 = blob.read_shift(4); } + var PSet0 = parse_PropertySet(blob, PIDSI); + + var rval = ({ SystemIdentifier: SystemIdentifier }); + for(var y in PSet0) rval[y] = PSet0[y]; + //rval.blob = blob; + rval.FMTID = FMTID0; + //rval.PSet0 = PSet0; + if(NumSets === 1) return rval; + if(Offset1 - blob.l == 2) blob.l += 2; + if(blob.l !== Offset1) throw new Error("Length mismatch 2: " + blob.l + " !== " + Offset1); + var PSet1; + try { PSet1 = parse_PropertySet(blob, null); } catch(e) {/* empty */} + for(y in PSet1) rval[y] = PSet1[y]; + rval.FMTID = [FMTID0, FMTID1]; // TODO: verify FMTID0/1 + return rval; + } + function write_PropertySetStream(entries, clsid, RE, PIDSI, entries2, clsid2) { + var hdr = new_buf(entries2 ? 68 : 48); + var bufs = [hdr]; + hdr.write_shift(2, 0xFFFE); + hdr.write_shift(2, 0x0000); /* TODO: type 1 props */ + hdr.write_shift(4, 0x32363237); + hdr.write_shift(16, CFB.utils.consts.HEADER_CLSID, "hex"); + hdr.write_shift(4, (entries2 ? 2 : 1)); + hdr.write_shift(16, clsid, "hex"); + hdr.write_shift(4, (entries2 ? 68 : 48)); + var ps0 = write_PropertySet(entries, RE, PIDSI); + bufs.push(ps0); + + if(entries2) { + var ps1 = write_PropertySet(entries2, null, null); + hdr.write_shift(16, clsid2, "hex"); + hdr.write_shift(4, 68 + ps0.length); + bufs.push(ps1); + } + return bconcat(bufs); + } + + function parsenoop2(blob, length) { blob.read_shift(length); return null; } + function writezeroes(n, o) { if(!o) o=new_buf(n); for(var j=0; j= 12 ? 2 : 1); + var encoding = 'sbcs-cont'; + var cp = current_codepage; + if(opts && opts.biff >= 8) current_codepage = 1200; + if(!opts || opts.biff == 8 ) { + var fHighByte = blob.read_shift(1); + if(fHighByte) { encoding = 'dbcs-cont'; } + } else if(opts.biff == 12) { + encoding = 'wstr'; + } + if(opts.biff >= 2 && opts.biff <= 5) encoding = 'cpstr'; + var o = cch ? blob.read_shift(cch, encoding) : ""; + current_codepage = cp; + return o; + } + + /* 2.5.293 XLUnicodeRichExtendedString */ + function parse_XLUnicodeRichExtendedString(blob) { + var cp = current_codepage; + current_codepage = 1200; + var cch = blob.read_shift(2), flags = blob.read_shift(1); + var /*fHighByte = flags & 0x1,*/ fExtSt = flags & 0x4, fRichSt = flags & 0x8; + var width = 1 + (flags & 0x1); // 0x0 -> utf8, 0x1 -> dbcs + var cRun = 0, cbExtRst; + var z = {}; + if(fRichSt) cRun = blob.read_shift(2); + if(fExtSt) cbExtRst = blob.read_shift(4); + var encoding = width == 2 ? 'dbcs-cont' : 'sbcs-cont'; + var msg = cch === 0 ? "" : blob.read_shift(cch, encoding); + if(fRichSt) blob.l += 4 * cRun; //TODO: parse this + if(fExtSt) blob.l += cbExtRst; //TODO: parse this + z.t = msg; + if(!fRichSt) { z.raw = "" + z.t + ""; z.r = z.t; } + current_codepage = cp; + return z; + } + + /* 2.5.296 XLUnicodeStringNoCch */ + function parse_XLUnicodeStringNoCch(blob, cch, opts) { + var retval; + if(opts) { + if(opts.biff >= 2 && opts.biff <= 5) return blob.read_shift(cch, 'cpstr'); + if(opts.biff >= 12) return blob.read_shift(cch, 'dbcs-cont'); + } + var fHighByte = blob.read_shift(1); + if(fHighByte===0) { retval = blob.read_shift(cch, 'sbcs-cont'); } + else { retval = blob.read_shift(cch, 'dbcs-cont'); } + return retval; + } + + /* 2.5.294 XLUnicodeString */ + function parse_XLUnicodeString(blob, length, opts) { + var cch = blob.read_shift(opts && opts.biff == 2 ? 1 : 2); + if(cch === 0) { blob.l++; return ""; } + return parse_XLUnicodeStringNoCch(blob, cch, opts); + } + /* BIFF5 override */ + function parse_XLUnicodeString2(blob, length, opts) { + if(opts.biff > 5) return parse_XLUnicodeString(blob, length, opts); + var cch = blob.read_shift(1); + if(cch === 0) { blob.l++; return ""; } + return blob.read_shift(cch, (opts.biff <= 4 || !blob.lens ) ? 'cpstr' : 'sbcs-cont'); + } + /* TODO: BIFF5 and lower, codepage awareness */ + function write_XLUnicodeString(str, opts, o) { + if(!o) o = new_buf(3 + 2 * str.length); + o.write_shift(2, str.length); + o.write_shift(1, 1); + o.write_shift(31, str, 'utf16le'); + return o; + } + + /* [MS-XLS] 2.5.61 ControlInfo */ + function parse_ControlInfo(blob) { + var flags = blob.read_shift(1); + blob.l++; + var accel = blob.read_shift(2); + blob.l += 2; + return [flags, accel]; + } + + /* [MS-OSHARED] 2.3.7.6 URLMoniker TODO: flags */ + function parse_URLMoniker(blob) { + var len = blob.read_shift(4), start = blob.l; + var extra = false; + if(len > 24) { + /* look ahead */ + blob.l += len - 24; + if(blob.read_shift(16) === "795881f43b1d7f48af2c825dc4852763") extra = true; + blob.l = start; + } + var url = blob.read_shift((extra?len-24:len)>>1, 'utf16le').replace(chr0,""); + if(extra) blob.l += 24; + return url; + } + + /* [MS-OSHARED] 2.3.7.8 FileMoniker TODO: all fields */ + function parse_FileMoniker(blob) { + blob.l += 2; //var cAnti = blob.read_shift(2); + var ansiPath = blob.read_shift(0, 'lpstr-ansi'); + blob.l += 2; //var endServer = blob.read_shift(2); + if(blob.read_shift(2) != 0xDEAD) throw new Error("Bad FileMoniker"); + var sz = blob.read_shift(4); + if(sz === 0) return ansiPath.replace(/\\/g,"/"); + var bytes = blob.read_shift(4); + if(blob.read_shift(2) != 3) throw new Error("Bad FileMoniker"); + var unicodePath = blob.read_shift(bytes>>1, 'utf16le').replace(chr0,""); + return unicodePath; + } + + /* [MS-OSHARED] 2.3.7.2 HyperlinkMoniker TODO: all the monikers */ + function parse_HyperlinkMoniker(blob, length) { + var clsid = blob.read_shift(16); length -= 16; + switch(clsid) { + case "e0c9ea79f9bace118c8200aa004ba90b": return parse_URLMoniker(blob, length); + case "0303000000000000c000000000000046": return parse_FileMoniker(blob, length); + default: throw new Error("Unsupported Moniker " + clsid); + } + } + + /* [MS-OSHARED] 2.3.7.9 HyperlinkString */ + function parse_HyperlinkString(blob) { + var len = blob.read_shift(4); + var o = len > 0 ? blob.read_shift(len, 'utf16le').replace(chr0, "") : ""; + return o; + } + + /* [MS-OSHARED] 2.3.7.1 Hyperlink Object */ + function parse_Hyperlink(blob, length) { + var end = blob.l + length; + var sVer = blob.read_shift(4); + if(sVer !== 2) throw new Error("Unrecognized streamVersion: " + sVer); + var flags = blob.read_shift(2); + blob.l += 2; + var displayName, targetFrameName, moniker, oleMoniker, Loc="", guid, fileTime; + if(flags & 0x0010) displayName = parse_HyperlinkString(blob, end - blob.l); + if(flags & 0x0080) targetFrameName = parse_HyperlinkString(blob, end - blob.l); + if((flags & 0x0101) === 0x0101) moniker = parse_HyperlinkString(blob, end - blob.l); + if((flags & 0x0101) === 0x0001) oleMoniker = parse_HyperlinkMoniker(blob, end - blob.l); + if(flags & 0x0008) Loc = parse_HyperlinkString(blob, end - blob.l); + if(flags & 0x0020) guid = blob.read_shift(16); + if(flags & 0x0040) fileTime = parse_FILETIME(blob/*, 8*/); + blob.l = end; + var target = targetFrameName||moniker||oleMoniker||""; + if(target && Loc) target+="#"+Loc; + if(!target) target = "#" + Loc; + var out = ({Target:target}); + if(guid) out.guid = guid; + if(fileTime) out.time = fileTime; + if(displayName) out.Tooltip = displayName; + return out; + } + function write_Hyperlink(hl) { + var out = new_buf(512), i = 0; + var Target = hl.Target; + var F = Target.indexOf("#") > -1 ? 0x1f : 0x17; + switch(Target.charAt(0)) { case "#": F=0x1c; break; case ".": F&=~2; break; } + out.write_shift(4,2); out.write_shift(4, F); + var data = [8,6815827,6619237,4849780,83]; for(i = 0; i < data.length; ++i) out.write_shift(4, data[i]); + if(F == 0x1C) { + Target = Target.slice(1); + out.write_shift(4, Target.length + 1); + for(i = 0; i < Target.length; ++i) out.write_shift(2, Target.charCodeAt(i)); + out.write_shift(2, 0); + } else if(F & 0x02) { + data = "e0 c9 ea 79 f9 ba ce 11 8c 82 00 aa 00 4b a9 0b".split(" "); + for(i = 0; i < data.length; ++i) out.write_shift(1, parseInt(data[i], 16)); + out.write_shift(4, 2*(Target.length + 1)); + for(i = 0; i < Target.length; ++i) out.write_shift(2, Target.charCodeAt(i)); + out.write_shift(2, 0); + } else { + data = "03 03 00 00 00 00 00 00 c0 00 00 00 00 00 00 46".split(" "); + for(i = 0; i < data.length; ++i) out.write_shift(1, parseInt(data[i], 16)); + var P = 0; + while(Target.slice(P*3,P*3+3)=="../"||Target.slice(P*3,P*3+3)=="..\\") ++P; + out.write_shift(2, P); + out.write_shift(4, Target.length + 1); + for(i = 0; i < Target.length; ++i) out.write_shift(1, Target.charCodeAt(i) & 0xFF); + out.write_shift(1, 0); + out.write_shift(2, 0xFFFF); + out.write_shift(2, 0xDEAD); + for(i = 0; i < 6; ++i) out.write_shift(4, 0); + } + return out.slice(0, out.l); + } + + /* 2.5.178 LongRGBA */ + function parse_LongRGBA(blob) { var r = blob.read_shift(1), g = blob.read_shift(1), b = blob.read_shift(1), a = blob.read_shift(1); return [r,g,b,a]; } + + /* 2.5.177 LongRGB */ + function parse_LongRGB(blob, length) { var x = parse_LongRGBA(blob, length); x[3] = 0; return x; } + + + /* [MS-XLS] 2.5.19 */ + function parse_XLSCell(blob) { + var rw = blob.read_shift(2); // 0-indexed + var col = blob.read_shift(2); + var ixfe = blob.read_shift(2); + return ({r:rw, c:col, ixfe:ixfe}); + } + function write_XLSCell(R, C, ixfe, o) { + if(!o) o = new_buf(6); + o.write_shift(2, R); + o.write_shift(2, C); + o.write_shift(2, ixfe||0); + return o; + } + + /* [MS-XLS] 2.5.134 */ + function parse_frtHeader(blob) { + var rt = blob.read_shift(2); + var flags = blob.read_shift(2); // TODO: parse these flags + blob.l += 8; + return {type: rt, flags: flags}; + } + + + + function parse_OptXLUnicodeString(blob, length, opts) { return length === 0 ? "" : parse_XLUnicodeString2(blob, length, opts); } + + /* [MS-XLS] 2.5.344 */ + function parse_XTI(blob, length, opts) { + var w = opts.biff > 8 ? 4 : 2; + var iSupBook = blob.read_shift(w), itabFirst = blob.read_shift(w,'i'), itabLast = blob.read_shift(w,'i'); + return [iSupBook, itabFirst, itabLast]; + } + + /* [MS-XLS] 2.5.218 */ + function parse_RkRec(blob) { + var ixfe = blob.read_shift(2); + var RK = parse_RkNumber(blob); + return [ixfe, RK]; + } + + /* [MS-XLS] 2.5.1 */ + function parse_AddinUdf(blob, length, opts) { + blob.l += 4; length -= 4; + var l = blob.l + length; + var udfName = parse_ShortXLUnicodeString(blob, length, opts); + var cb = blob.read_shift(2); + l -= blob.l; + if(cb !== l) throw new Error("Malformed AddinUdf: padding = " + l + " != " + cb); + blob.l += cb; + return udfName; + } + + /* [MS-XLS] 2.5.209 TODO: Check sizes */ + function parse_Ref8U(blob) { + var rwFirst = blob.read_shift(2); + var rwLast = blob.read_shift(2); + var colFirst = blob.read_shift(2); + var colLast = blob.read_shift(2); + return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}}; + } + function write_Ref8U(r, o) { + if(!o) o = new_buf(8); + o.write_shift(2, r.s.r); + o.write_shift(2, r.e.r); + o.write_shift(2, r.s.c); + o.write_shift(2, r.e.c); + return o; + } + + /* [MS-XLS] 2.5.211 */ + function parse_RefU(blob) { + var rwFirst = blob.read_shift(2); + var rwLast = blob.read_shift(2); + var colFirst = blob.read_shift(1); + var colLast = blob.read_shift(1); + return {s:{c:colFirst, r:rwFirst}, e:{c:colLast,r:rwLast}}; + } + + /* [MS-XLS] 2.5.207 */ + var parse_Ref = parse_RefU; + + /* [MS-XLS] 2.5.143 */ + function parse_FtCmo(blob) { + blob.l += 4; + var ot = blob.read_shift(2); + var id = blob.read_shift(2); + var flags = blob.read_shift(2); + blob.l+=12; + return [id, ot, flags]; + } + + /* [MS-XLS] 2.5.149 */ + function parse_FtNts(blob) { + var out = {}; + blob.l += 4; + blob.l += 16; // GUID TODO + out.fSharedNote = blob.read_shift(2); + blob.l += 4; + return out; + } + + /* [MS-XLS] 2.5.142 */ + function parse_FtCf(blob) { + var out = {}; + blob.l += 4; + blob.cf = blob.read_shift(2); + return out; + } + + /* [MS-XLS] 2.5.140 - 2.5.154 and friends */ + function parse_FtSkip(blob) { blob.l += 2; blob.l += blob.read_shift(2); } + var FtTab = { + 0x00: parse_FtSkip, /* FtEnd */ + 0x04: parse_FtSkip, /* FtMacro */ + 0x05: parse_FtSkip, /* FtButton */ + 0x06: parse_FtSkip, /* FtGmo */ + 0x07: parse_FtCf, /* FtCf */ + 0x08: parse_FtSkip, /* FtPioGrbit */ + 0x09: parse_FtSkip, /* FtPictFmla */ + 0x0A: parse_FtSkip, /* FtCbls */ + 0x0B: parse_FtSkip, /* FtRbo */ + 0x0C: parse_FtSkip, /* FtSbs */ + 0x0D: parse_FtNts, /* FtNts */ + 0x0E: parse_FtSkip, /* FtSbsFmla */ + 0x0F: parse_FtSkip, /* FtGboData */ + 0x10: parse_FtSkip, /* FtEdoData */ + 0x11: parse_FtSkip, /* FtRboData */ + 0x12: parse_FtSkip, /* FtCblsData */ + 0x13: parse_FtSkip, /* FtLbsData */ + 0x14: parse_FtSkip, /* FtCblsFmla */ + 0x15: parse_FtCmo + }; + function parse_FtArray(blob, length) { + var tgt = blob.l + length; + var fts = []; + while(blob.l < tgt) { + var ft = blob.read_shift(2); + blob.l-=2; + try { + fts.push(FtTab[ft](blob, tgt - blob.l)); + } catch(e) { blob.l = tgt; return fts; } + } + if(blob.l != tgt) blob.l = tgt; //throw new Error("bad Object Ft-sequence"); + return fts; + } + + /* --- 2.4 Records --- */ + + /* [MS-XLS] 2.4.21 */ + function parse_BOF(blob, length) { + var o = {BIFFVer:0, dt:0}; + o.BIFFVer = blob.read_shift(2); length -= 2; + if(length >= 2) { o.dt = blob.read_shift(2); blob.l -= 2; } + switch(o.BIFFVer) { + case 0x0600: /* BIFF8 */ + case 0x0500: /* BIFF5 */ + case 0x0400: /* BIFF4 */ + case 0x0300: /* BIFF3 */ + case 0x0200: /* BIFF2 */ + case 0x0002: case 0x0007: /* BIFF2 */ + break; + default: if(length > 6) throw new Error("Unexpected BIFF Ver " + o.BIFFVer); + } + + blob.read_shift(length); + return o; + } + function write_BOF(wb, t, o) { + var h = 0x0600, w = 16; + switch(o.bookType) { + case 'biff8': break; + case 'biff5': h = 0x0500; w = 8; break; + case 'biff4': h = 0x0004; w = 6; break; + case 'biff3': h = 0x0003; w = 6; break; + case 'biff2': h = 0x0002; w = 4; break; + case 'xla': break; + default: throw new Error("unsupported BIFF version"); + } + var out = new_buf(w); + out.write_shift(2, h); + out.write_shift(2, t); + if(w > 4) out.write_shift(2, 0x7262); + if(w > 6) out.write_shift(2, 0x07CD); + if(w > 8) { + out.write_shift(2, 0xC009); + out.write_shift(2, 0x0001); + out.write_shift(2, 0x0706); + out.write_shift(2, 0x0000); + } + return out; + } + + + /* [MS-XLS] 2.4.146 */ + function parse_InterfaceHdr(blob, length) { + if(length === 0) return 0x04b0; + if((blob.read_shift(2))!==0x04b0){/* empty */} + return 0x04b0; + } + + + /* [MS-XLS] 2.4.349 */ + function parse_WriteAccess(blob, length, opts) { + if(opts.enc) { blob.l += length; return ""; } + var l = blob.l; + // TODO: make sure XLUnicodeString doesnt overrun + var UserName = parse_XLUnicodeString2(blob, 0, opts); + blob.read_shift(length + l - blob.l); + return UserName; + } + function write_WriteAccess(s, opts) { + var b8 = !opts || opts.biff == 8; + var o = new_buf(b8 ? 112 : 54); + o.write_shift(opts.biff == 8 ? 2 : 1, 7); + if(b8) o.write_shift(1, 0); + o.write_shift(4, 0x33336853); + o.write_shift(4, (0x00534A74 | (b8 ? 0 : 0x20000000))); + while(o.l < o.length) o.write_shift(1, (b8 ? 0 : 32)); + return o; + } + + /* [MS-XLS] 2.4.351 */ + function parse_WsBool(blob, length, opts) { + var flags = opts && opts.biff == 8 || length == 2 ? blob.read_shift(2) : (blob.l += length, 0); + return { fDialog: flags & 0x10 }; + } + + /* [MS-XLS] 2.4.28 */ + function parse_BoundSheet8(blob, length, opts) { + var pos = blob.read_shift(4); + var hidden = blob.read_shift(1) & 0x03; + var dt = blob.read_shift(1); + switch(dt) { + case 0: dt = 'Worksheet'; break; + case 1: dt = 'Macrosheet'; break; + case 2: dt = 'Chartsheet'; break; + case 6: dt = 'VBAModule'; break; + } + var name = parse_ShortXLUnicodeString(blob, 0, opts); + if(name.length === 0) name = "Sheet1"; + return { pos:pos, hs:hidden, dt:dt, name:name }; + } + function write_BoundSheet8(data, opts) { + var w = (!opts || opts.biff >= 8 ? 2 : 1); + var o = new_buf(8 + w * data.name.length); + o.write_shift(4, data.pos); + o.write_shift(1, data.hs || 0); + o.write_shift(1, data.dt); + o.write_shift(1, data.name.length); + if(opts.biff >= 8) o.write_shift(1, 1); + o.write_shift(w * data.name.length, data.name, opts.biff < 8 ? 'sbcs' : 'utf16le'); + var out = o.slice(0, o.l); + out.l = o.l; return out; + } + + /* [MS-XLS] 2.4.265 TODO */ + function parse_SST(blob, length) { + var end = blob.l + length; + var cnt = blob.read_shift(4); + var ucnt = blob.read_shift(4); + var strs = ([]); + for(var i = 0; i != ucnt && blob.l < end; ++i) { + strs.push(parse_XLUnicodeRichExtendedString(blob)); + } + strs.Count = cnt; strs.Unique = ucnt; + return strs; + } + + /* [MS-XLS] 2.4.107 */ + function parse_ExtSST(blob, length) { + var extsst = {}; + extsst.dsst = blob.read_shift(2); + blob.l += length-2; + return extsst; + } + + + /* [MS-XLS] 2.4.221 TODO: check BIFF2-4 */ + function parse_Row(blob) { + var z = ({}); + z.r = blob.read_shift(2); + z.c = blob.read_shift(2); + z.cnt = blob.read_shift(2) - z.c; + var miyRw = blob.read_shift(2); + blob.l += 4; // reserved(2), unused(2) + var flags = blob.read_shift(1); // various flags + blob.l += 3; // reserved(8), ixfe(12), flags(4) + if(flags & 0x07) z.level = flags & 0x07; + // collapsed: flags & 0x10 + if(flags & 0x20) z.hidden = true; + if(flags & 0x40) z.hpt = miyRw / 20; + return z; + } + + + /* [MS-XLS] 2.4.125 */ + function parse_ForceFullCalculation(blob) { + var header = parse_frtHeader(blob); + if(header.type != 0x08A3) throw new Error("Invalid Future Record " + header.type); + var fullcalc = blob.read_shift(4); + return fullcalc !== 0x0; + } + + + + + + /* [MS-XLS] 2.4.215 rt */ + function parse_RecalcId(blob) { + blob.read_shift(2); + return blob.read_shift(4); + } + + /* [MS-XLS] 2.4.87 */ + function parse_DefaultRowHeight(blob, length, opts) { + var f = 0; + if(!(opts && opts.biff == 2)) { + f = blob.read_shift(2); + } + var miyRw = blob.read_shift(2); + if((opts && opts.biff == 2)) { + f = 1 - (miyRw >> 15); miyRw &= 0x7fff; + } + var fl = {Unsynced:f&1,DyZero:(f&2)>>1,ExAsc:(f&4)>>2,ExDsc:(f&8)>>3}; + return [fl, miyRw]; + } + + /* [MS-XLS] 2.4.345 TODO */ + function parse_Window1(blob) { + var xWn = blob.read_shift(2), yWn = blob.read_shift(2), dxWn = blob.read_shift(2), dyWn = blob.read_shift(2); + var flags = blob.read_shift(2), iTabCur = blob.read_shift(2), iTabFirst = blob.read_shift(2); + var ctabSel = blob.read_shift(2), wTabRatio = blob.read_shift(2); + return { Pos: [xWn, yWn], Dim: [dxWn, dyWn], Flags: flags, CurTab: iTabCur, + FirstTab: iTabFirst, Selected: ctabSel, TabRatio: wTabRatio }; + } + function write_Window1() { + var o = new_buf(18); + o.write_shift(2, 0); + o.write_shift(2, 0); + o.write_shift(2, 0x7260); + o.write_shift(2, 0x44c0); + o.write_shift(2, 0x38); + o.write_shift(2, 0); + o.write_shift(2, 0); + o.write_shift(2, 1); + o.write_shift(2, 0x01f4); + return o; + } + /* [MS-XLS] 2.4.346 TODO */ + function parse_Window2(blob, length, opts) { + if(opts && opts.biff >= 2 && opts.biff < 8) return {}; + var f = blob.read_shift(2); + return { RTL: f & 0x40 }; + } + function write_Window2(view) { + var o = new_buf(18), f = 0x6b6; + if(view && view.RTL) f |= 0x40; + o.write_shift(2, f); + o.write_shift(4, 0); + o.write_shift(4, 64); + o.write_shift(4, 0); + o.write_shift(4, 0); + return o; + } + + /* [MS-XLS] 2.4.122 TODO */ + function parse_Font(blob, length, opts) { + var o = { + dyHeight: blob.read_shift(2), + fl: blob.read_shift(2) + }; + switch((opts && opts.biff) || 8) { + case 2: break; + case 3: case 4: blob.l += 2; break; + default: blob.l += 10; break; + } + o.name = parse_ShortXLUnicodeString(blob, 0, opts); + return o; + } + function write_Font(data, opts) { + var name = data.name || "Arial"; + var b5 = (opts && (opts.biff == 5)), w = (b5 ? (15 + name.length) : (16 + 2 * name.length)); + var o = new_buf(w); + o.write_shift(2, (data.sz || 12) * 20); + o.write_shift(4, 0); + o.write_shift(2, 400); + o.write_shift(4, 0); + o.write_shift(2, 0); + o.write_shift(1, name.length); + if(!b5) o.write_shift(1, 1); + o.write_shift((b5 ? 1 : 2) * name.length, name, (b5 ? "sbcs" : "utf16le")); + return o; + } + + /* [MS-XLS] 2.4.149 */ + function parse_LabelSst(blob) { + var cell = parse_XLSCell(blob); + cell.isst = blob.read_shift(4); + return cell; + } + + /* [MS-XLS] 2.4.148 */ + function parse_Label(blob, length, opts) { + var target = blob.l + length; + var cell = parse_XLSCell(blob, 6); + if(opts.biff == 2) blob.l++; + var str = parse_XLUnicodeString(blob, target - blob.l, opts); + cell.val = str; + return cell; + } + function write_Label(R, C, v, os, opts) { + var b8 = !opts || opts.biff == 8; + var o = new_buf(6 + 2 + (+b8) + (1 + b8) * v.length); + write_XLSCell(R, C, os, o); + o.write_shift(2, v.length); + if(b8) o.write_shift(1, 1); + o.write_shift((1 + b8) * v.length, v, b8 ? 'utf16le' : 'sbcs'); + return o; + } + + + /* [MS-XLS] 2.4.126 Number Formats */ + function parse_Format(blob, length, opts) { + var numFmtId = blob.read_shift(2); + var fmtstr = parse_XLUnicodeString2(blob, 0, opts); + return [numFmtId, fmtstr]; + } + function write_Format(i, f, opts, o) { + var b5 = (opts && (opts.biff == 5)); + if(!o) o = new_buf(b5 ? (3 + f.length) : (5 + 2 * f.length)); + o.write_shift(2, i); + o.write_shift((b5 ? 1 : 2), f.length); + if(!b5) o.write_shift(1, 1); + o.write_shift((b5 ? 1 : 2) * f.length, f, (b5 ? 'sbcs' : 'utf16le')); + var out = (o.length > o.l) ? o.slice(0, o.l) : o; + if(out.l == null) out.l = out.length; + return out; + } + var parse_BIFF2Format = parse_XLUnicodeString2; + + /* [MS-XLS] 2.4.90 */ + function parse_Dimensions(blob, length, opts) { + var end = blob.l + length; + var w = opts.biff == 8 || !opts.biff ? 4 : 2; + var r = blob.read_shift(w), R = blob.read_shift(w); + var c = blob.read_shift(2), C = blob.read_shift(2); + blob.l = end; + return {s: {r:r, c:c}, e: {r:R, c:C}}; + } + function write_Dimensions(range, opts) { + var w = opts.biff == 8 || !opts.biff ? 4 : 2; + var o = new_buf(2*w + 6); + o.write_shift(w, range.s.r); + o.write_shift(w, range.e.r + 1); + o.write_shift(2, range.s.c); + o.write_shift(2, range.e.c + 1); + o.write_shift(2, 0); + return o; + } + + /* [MS-XLS] 2.4.220 */ + function parse_RK(blob) { + var rw = blob.read_shift(2), col = blob.read_shift(2); + var rkrec = parse_RkRec(blob); + return {r:rw, c:col, ixfe:rkrec[0], rknum:rkrec[1]}; + } + + /* [MS-XLS] 2.4.175 */ + function parse_MulRk(blob, length) { + var target = blob.l + length - 2; + var rw = blob.read_shift(2), col = blob.read_shift(2); + var rkrecs = []; + while(blob.l < target) rkrecs.push(parse_RkRec(blob)); + if(blob.l !== target) throw new Error("MulRK read error"); + var lastcol = blob.read_shift(2); + if(rkrecs.length != lastcol - col + 1) throw new Error("MulRK length mismatch"); + return {r:rw, c:col, C:lastcol, rkrec:rkrecs}; + } + /* [MS-XLS] 2.4.174 */ + function parse_MulBlank(blob, length) { + var target = blob.l + length - 2; + var rw = blob.read_shift(2), col = blob.read_shift(2); + var ixfes = []; + while(blob.l < target) ixfes.push(blob.read_shift(2)); + if(blob.l !== target) throw new Error("MulBlank read error"); + var lastcol = blob.read_shift(2); + if(ixfes.length != lastcol - col + 1) throw new Error("MulBlank length mismatch"); + return {r:rw, c:col, C:lastcol, ixfe:ixfes}; + } + + /* [MS-XLS] 2.5.20 2.5.249 TODO: interpret values here */ + function parse_CellStyleXF(blob, length, style, opts) { + var o = {}; + var a = blob.read_shift(4), b = blob.read_shift(4); + var c = blob.read_shift(4), d = blob.read_shift(2); + o.patternType = XLSFillPattern[c >> 26]; + + if(!opts.cellStyles) return o; + o.alc = a & 0x07; + o.fWrap = (a >> 3) & 0x01; + o.alcV = (a >> 4) & 0x07; + o.fJustLast = (a >> 7) & 0x01; + o.trot = (a >> 8) & 0xFF; + o.cIndent = (a >> 16) & 0x0F; + o.fShrinkToFit = (a >> 20) & 0x01; + o.iReadOrder = (a >> 22) & 0x02; + o.fAtrNum = (a >> 26) & 0x01; + o.fAtrFnt = (a >> 27) & 0x01; + o.fAtrAlc = (a >> 28) & 0x01; + o.fAtrBdr = (a >> 29) & 0x01; + o.fAtrPat = (a >> 30) & 0x01; + o.fAtrProt = (a >> 31) & 0x01; + + o.dgLeft = b & 0x0F; + o.dgRight = (b >> 4) & 0x0F; + o.dgTop = (b >> 8) & 0x0F; + o.dgBottom = (b >> 12) & 0x0F; + o.icvLeft = (b >> 16) & 0x7F; + o.icvRight = (b >> 23) & 0x7F; + o.grbitDiag = (b >> 30) & 0x03; + + o.icvTop = c & 0x7F; + o.icvBottom = (c >> 7) & 0x7F; + o.icvDiag = (c >> 14) & 0x7F; + o.dgDiag = (c >> 21) & 0x0F; + + o.icvFore = d & 0x7F; + o.icvBack = (d >> 7) & 0x7F; + o.fsxButton = (d >> 14) & 0x01; + return o; + } +//function parse_CellXF(blob, length, opts) {return parse_CellStyleXF(blob,length,0, opts);} +//function parse_StyleXF(blob, length, opts) {return parse_CellStyleXF(blob,length,1, opts);} + + /* [MS-XLS] 2.4.353 TODO: actually do this right */ + function parse_XF(blob, length, opts) { + var o = {}; + o.ifnt = blob.read_shift(2); o.numFmtId = blob.read_shift(2); o.flags = blob.read_shift(2); + o.fStyle = (o.flags >> 2) & 0x01; + length -= 6; + o.data = parse_CellStyleXF(blob, length, o.fStyle, opts); + return o; + } + function write_XF(data, ixfeP, opts, o) { + var b5 = (opts && (opts.biff == 5)); + if(!o) o = new_buf(b5 ? 16 : 20); + o.write_shift(2, 0); + if(data.style) { + o.write_shift(2, (data.numFmtId||0)); + o.write_shift(2, 0xFFF4); + } else { + o.write_shift(2, (data.numFmtId||0)); + o.write_shift(2, (ixfeP<<4)); + } + o.write_shift(4, 0); + o.write_shift(4, 0); + if(!b5) o.write_shift(4, 0); + o.write_shift(2, 0); + return o; + } + + /* [MS-XLS] 2.4.134 */ + function parse_Guts(blob) { + blob.l += 4; + var out = [blob.read_shift(2), blob.read_shift(2)]; + if(out[0] !== 0) out[0]--; + if(out[1] !== 0) out[1]--; + if(out[0] > 7 || out[1] > 7) throw new Error("Bad Gutters: " + out.join("|")); + return out; + } + function write_Guts(guts) { + var o = new_buf(8); + o.write_shift(4, 0); + o.write_shift(2, guts[0] ? guts[0] + 1 : 0); + o.write_shift(2, guts[1] ? guts[1] + 1 : 0); + return o; + } + + /* [MS-XLS] 2.4.24 */ + function parse_BoolErr(blob, length, opts) { + var cell = parse_XLSCell(blob, 6); + if(opts.biff == 2) ++blob.l; + var val = parse_Bes(blob, 2); + cell.val = val; + cell.t = (val === true || val === false) ? 'b' : 'e'; + return cell; + } + function write_BoolErr(R, C, v, os, opts, t) { + var o = new_buf(8); + write_XLSCell(R, C, os, o); + write_Bes(v, t, o); + return o; + } + + /* [MS-XLS] 2.4.180 Number */ + function parse_Number(blob) { + var cell = parse_XLSCell(blob, 6); + var xnum = parse_Xnum(blob, 8); + cell.val = xnum; + return cell; + } + function write_Number(R, C, v, os) { + var o = new_buf(14); + write_XLSCell(R, C, os, o); + write_Xnum(v, o); + return o; + } + + var parse_XLHeaderFooter = parse_OptXLUnicodeString; // TODO: parse 2.4.136 + + /* [MS-XLS] 2.4.271 */ + function parse_SupBook(blob, length, opts) { + var end = blob.l + length; + var ctab = blob.read_shift(2); + var cch = blob.read_shift(2); + opts.sbcch = cch; + if(cch == 0x0401 || cch == 0x3A01) return [cch, ctab]; + if(cch < 0x01 || cch >0xff) throw new Error("Unexpected SupBook type: "+cch); + var virtPath = parse_XLUnicodeStringNoCch(blob, cch); + /* TODO: 2.5.277 Virtual Path */ + var rgst = []; + while(end > blob.l) rgst.push(parse_XLUnicodeString(blob)); + return [cch, ctab, virtPath, rgst]; + } + + /* [MS-XLS] 2.4.105 TODO */ + function parse_ExternName(blob, length, opts) { + var flags = blob.read_shift(2); + var body; + var o = ({ + fBuiltIn: flags & 0x01, + fWantAdvise: (flags >>> 1) & 0x01, + fWantPict: (flags >>> 2) & 0x01, + fOle: (flags >>> 3) & 0x01, + fOleLink: (flags >>> 4) & 0x01, + cf: (flags >>> 5) & 0x3FF, + fIcon: flags >>> 15 & 0x01 + }); + if(opts.sbcch === 0x3A01) body = parse_AddinUdf(blob, length-2, opts); + //else throw new Error("unsupported SupBook cch: " + opts.sbcch); + o.body = body || blob.read_shift(length-2); + if(typeof body === "string") o.Name = body; + return o; + } + + /* [MS-XLS] 2.4.150 TODO */ + var XLSLblBuiltIn = [ + "_xlnm.Consolidate_Area", + "_xlnm.Auto_Open", + "_xlnm.Auto_Close", + "_xlnm.Extract", + "_xlnm.Database", + "_xlnm.Criteria", + "_xlnm.Print_Area", + "_xlnm.Print_Titles", + "_xlnm.Recorder", + "_xlnm.Data_Form", + "_xlnm.Auto_Activate", + "_xlnm.Auto_Deactivate", + "_xlnm.Sheet_Title", + "_xlnm._FilterDatabase" + ]; + function parse_Lbl(blob, length, opts) { + var target = blob.l + length; + var flags = blob.read_shift(2); + var chKey = blob.read_shift(1); + var cch = blob.read_shift(1); + var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2); + var itab = 0; + if(!opts || opts.biff >= 5) { + if(opts.biff != 5) blob.l += 2; + itab = blob.read_shift(2); + if(opts.biff == 5) blob.l += 2; + blob.l += 4; + } + var name = parse_XLUnicodeStringNoCch(blob, cch, opts); + if(flags & 0x20) name = XLSLblBuiltIn[name.charCodeAt(0)]; + var npflen = target - blob.l; if(opts && opts.biff == 2) --npflen; + var rgce = target == blob.l || cce === 0 ? [] : parse_NameParsedFormula(blob, npflen, opts, cce); + return { + chKey: chKey, + Name: name, + itab: itab, + rgce: rgce + }; + } + + /* [MS-XLS] 2.4.106 TODO: verify filename encoding */ + function parse_ExternSheet(blob, length, opts) { + if(opts.biff < 8) return parse_BIFF5ExternSheet(blob, length, opts); + var o = [], target = blob.l + length, len = blob.read_shift(opts.biff > 8 ? 4 : 2); + while(len-- !== 0) o.push(parse_XTI(blob, opts.biff > 8 ? 12 : 6, opts)); + // [iSupBook, itabFirst, itabLast]; + if(blob.l != target) throw new Error("Bad ExternSheet: " + blob.l + " != " + target); + return o; + } + function parse_BIFF5ExternSheet(blob, length, opts) { + if(blob[blob.l + 1] == 0x03) blob[blob.l]++; + var o = parse_ShortXLUnicodeString(blob, length, opts); + return o.charCodeAt(0) == 0x03 ? o.slice(1) : o; + } + + /* [MS-XLS] 2.4.176 TODO: check older biff */ + function parse_NameCmt(blob, length, opts) { + if(opts.biff < 8) { blob.l += length; return; } + var cchName = blob.read_shift(2); + var cchComment = blob.read_shift(2); + var name = parse_XLUnicodeStringNoCch(blob, cchName, opts); + var comment = parse_XLUnicodeStringNoCch(blob, cchComment, opts); + return [name, comment]; + } + + /* [MS-XLS] 2.4.260 */ + function parse_ShrFmla(blob, length, opts) { + var ref = parse_RefU(blob, 6); + blob.l++; + var cUse = blob.read_shift(1); + length -= 8; + return [parse_SharedParsedFormula(blob, length, opts), cUse, ref]; + } + + /* [MS-XLS] 2.4.4 TODO */ + function parse_Array(blob, length, opts) { + var ref = parse_Ref(blob, 6); + /* TODO: fAlwaysCalc */ + switch(opts.biff) { + case 2: blob.l ++; length -= 7; break; + case 3: case 4: blob.l += 2; length -= 8; break; + default: blob.l += 6; length -= 12; + } + return [ref, parse_ArrayParsedFormula(blob, length, opts, ref)]; + } + + /* [MS-XLS] 2.4.173 */ + function parse_MTRSettings(blob) { + var fMTREnabled = blob.read_shift(4) !== 0x00; + var fUserSetThreadCount = blob.read_shift(4) !== 0x00; + var cUserThreadCount = blob.read_shift(4); + return [fMTREnabled, fUserSetThreadCount, cUserThreadCount]; + } + + /* [MS-XLS] 2.5.186 TODO: BIFF5 */ + function parse_NoteSh(blob, length, opts) { + if(opts.biff < 8) return; + var row = blob.read_shift(2), col = blob.read_shift(2); + var flags = blob.read_shift(2), idObj = blob.read_shift(2); + var stAuthor = parse_XLUnicodeString2(blob, 0, opts); + if(opts.biff < 8) blob.read_shift(1); + return [{r:row,c:col}, stAuthor, idObj, flags]; + } + + /* [MS-XLS] 2.4.179 */ + function parse_Note(blob, length, opts) { + /* TODO: Support revisions */ + return parse_NoteSh(blob, length, opts); + } + + /* [MS-XLS] 2.4.168 */ + function parse_MergeCells(blob, length) { + var merges = []; + var cmcs = blob.read_shift(2); + while (cmcs--) merges.push(parse_Ref8U(blob,length)); + return merges; + } + function write_MergeCells(merges) { + var o = new_buf(2 + merges.length * 8); + o.write_shift(2, merges.length); + for(var i = 0; i < merges.length; ++i) write_Ref8U(merges[i], o); + return o; + } + + /* [MS-XLS] 2.4.181 TODO: parse all the things! */ + function parse_Obj(blob, length, opts) { + if(opts && opts.biff < 8) return parse_BIFF5Obj(blob, length, opts); + var cmo = parse_FtCmo(blob, 22); // id, ot, flags + var fts = parse_FtArray(blob, length-22, cmo[1]); + return { cmo: cmo, ft:fts }; + } + /* from older spec */ + var parse_BIFF5OT = []; + parse_BIFF5OT[0x08] = function(blob, length) { + var tgt = blob.l + length; + blob.l += 10; // todo + var cf = blob.read_shift(2); + blob.l += 4; + blob.l += 2; //var cbPictFmla = blob.read_shift(2); + blob.l += 2; + blob.l += 2; //var grbit = blob.read_shift(2); + blob.l += 4; + var cchName = blob.read_shift(1); + blob.l += cchName; // TODO: stName + blob.l = tgt; // TODO: fmla + return { fmt:cf }; + }; + + function parse_BIFF5Obj(blob, length, opts) { + blob.l += 4; //var cnt = blob.read_shift(4); + var ot = blob.read_shift(2); + var id = blob.read_shift(2); + var grbit = blob.read_shift(2); + blob.l += 2; //var colL = blob.read_shift(2); + blob.l += 2; //var dxL = blob.read_shift(2); + blob.l += 2; //var rwT = blob.read_shift(2); + blob.l += 2; //var dyT = blob.read_shift(2); + blob.l += 2; //var colR = blob.read_shift(2); + blob.l += 2; //var dxR = blob.read_shift(2); + blob.l += 2; //var rwB = blob.read_shift(2); + blob.l += 2; //var dyB = blob.read_shift(2); + blob.l += 2; //var cbMacro = blob.read_shift(2); + blob.l += 6; + length -= 36; + var fts = []; + fts.push((parse_BIFF5OT[ot]||parsenoop)(blob, length, opts)); + return { cmo: [id, ot, grbit], ft:fts }; + } + + /* [MS-XLS] 2.4.329 TODO: parse properly */ + function parse_TxO(blob, length, opts) { + var s = blob.l; + var texts = ""; + try { + blob.l += 4; + var ot = (opts.lastobj||{cmo:[0,0]}).cmo[1]; + var controlInfo; // eslint-disable-line no-unused-vars + if([0,5,7,11,12,14].indexOf(ot) == -1) blob.l += 6; + else controlInfo = parse_ControlInfo(blob, 6, opts); + var cchText = blob.read_shift(2); + /*var cbRuns = */blob.read_shift(2); + /*var ifntEmpty = */parseuint16(blob, 2); + var len = blob.read_shift(2); + blob.l += len; + //var fmla = parse_ObjFmla(blob, s + length - blob.l); + + for(var i = 1; i < blob.lens.length-1; ++i) { + if(blob.l-s != blob.lens[i]) throw new Error("TxO: bad continue record"); + var hdr = blob[blob.l]; + var t = parse_XLUnicodeStringNoCch(blob, blob.lens[i+1]-blob.lens[i]-1); + texts += t; + if(texts.length >= (hdr ? cchText : 2*cchText)) break; + } + if(texts.length !== cchText && texts.length !== cchText*2) { + throw new Error("cchText: " + cchText + " != " + texts.length); + } + + blob.l = s + length; + /* [MS-XLS] 2.5.272 TxORuns */ +// var rgTxoRuns = []; +// for(var j = 0; j != cbRuns/8-1; ++j) blob.l += 8; +// var cchText2 = blob.read_shift(2); +// if(cchText2 !== cchText) throw new Error("TxOLastRun mismatch: " + cchText2 + " " + cchText); +// blob.l += 6; +// if(s + length != blob.l) throw new Error("TxO " + (s + length) + ", at " + blob.l); + return { t: texts }; + } catch(e) { blob.l = s + length; return { t: texts }; } + } + + /* [MS-XLS] 2.4.140 */ + function parse_HLink(blob, length) { + var ref = parse_Ref8U(blob, 8); + blob.l += 16; /* CLSID */ + var hlink = parse_Hyperlink(blob, length-24); + return [ref, hlink]; + } + function write_HLink(hl) { + var O = new_buf(24); + var ref = decode_cell(hl[0]); + O.write_shift(2, ref.r); O.write_shift(2, ref.r); + O.write_shift(2, ref.c); O.write_shift(2, ref.c); + var clsid = "d0 c9 ea 79 f9 ba ce 11 8c 82 00 aa 00 4b a9 0b".split(" "); + for(var i = 0; i < 16; ++i) O.write_shift(1, parseInt(clsid[i], 16)); + return bconcat([O, write_Hyperlink(hl[1])]); + } + + + /* [MS-XLS] 2.4.141 */ + function parse_HLinkTooltip(blob, length) { + blob.read_shift(2); + var ref = parse_Ref8U(blob, 8); + var wzTooltip = blob.read_shift((length-10)/2, 'dbcs-cont'); + wzTooltip = wzTooltip.replace(chr0,""); + return [ref, wzTooltip]; + } + function write_HLinkTooltip(hl) { + var TT = hl[1].Tooltip; + var O = new_buf(10 + 2 * (TT.length + 1)); + O.write_shift(2, 0x0800); + var ref = decode_cell(hl[0]); + O.write_shift(2, ref.r); O.write_shift(2, ref.r); + O.write_shift(2, ref.c); O.write_shift(2, ref.c); + for(var i = 0; i < TT.length; ++i) O.write_shift(2, TT.charCodeAt(i)); + O.write_shift(2, 0); + return O; + } + + /* [MS-XLS] 2.4.63 */ + function parse_Country(blob) { + var o = [0,0], d; + d = blob.read_shift(2); o[0] = CountryEnum[d] || d; + d = blob.read_shift(2); o[1] = CountryEnum[d] || d; + return o; + } + function write_Country(o) { + if(!o) o = new_buf(4); + o.write_shift(2, 0x01); + o.write_shift(2, 0x01); + return o; + } + + /* [MS-XLS] 2.4.50 ClrtClient */ + function parse_ClrtClient(blob) { + var ccv = blob.read_shift(2); + var o = []; + while(ccv-->0) o.push(parse_LongRGB(blob, 8)); + return o; + } + + /* [MS-XLS] 2.4.188 */ + function parse_Palette(blob) { + var ccv = blob.read_shift(2); + var o = []; + while(ccv-->0) o.push(parse_LongRGB(blob, 8)); + return o; + } + + /* [MS-XLS] 2.4.354 */ + function parse_XFCRC(blob) { + blob.l += 2; + var o = {cxfs:0, crc:0}; + o.cxfs = blob.read_shift(2); + o.crc = blob.read_shift(4); + return o; + } + + /* [MS-XLS] 2.4.53 TODO: parse flags */ + /* [MS-XLSB] 2.4.323 TODO: parse flags */ + function parse_ColInfo(blob, length, opts) { + if(!opts.cellStyles) return parsenoop(blob, length); + var w = opts && opts.biff >= 12 ? 4 : 2; + var colFirst = blob.read_shift(w); + var colLast = blob.read_shift(w); + var coldx = blob.read_shift(w); + var ixfe = blob.read_shift(w); + var flags = blob.read_shift(2); + if(w == 2) blob.l += 2; + return {s:colFirst, e:colLast, w:coldx, ixfe:ixfe, flags:flags}; + } + + /* [MS-XLS] 2.4.257 */ + function parse_Setup(blob, length) { + var o = {}; + if(length < 32) return o; + blob.l += 16; + o.header = parse_Xnum(blob, 8); + o.footer = parse_Xnum(blob, 8); + blob.l += 2; + return o; + } + + /* [MS-XLS] 2.4.261 */ + function parse_ShtProps(blob, length, opts) { + var def = {area:false}; + if(opts.biff != 5) { blob.l += length; return def; } + var d = blob.read_shift(1); blob.l += 3; + if((d & 0x10)) def.area = true; + return def; + } + + /* [MS-XLS] 2.4.241 */ + function write_RRTabId(n) { + var out = new_buf(2 * n); + for(var i = 0; i < n; ++i) out.write_shift(2, i+1); + return out; + } + + var parse_Blank = parse_XLSCell; /* [MS-XLS] 2.4.20 Just the cell */ + var parse_Scl = parseuint16a; /* [MS-XLS] 2.4.247 num, den */ + var parse_String = parse_XLUnicodeString; /* [MS-XLS] 2.4.268 */ + + /* --- Specific to versions before BIFF8 --- */ + function parse_ImData(blob) { + var cf = blob.read_shift(2); + var env = blob.read_shift(2); + var lcb = blob.read_shift(4); + var o = {fmt:cf, env:env, len:lcb, data:blob.slice(blob.l,blob.l+lcb)}; + blob.l += lcb; + return o; + } + + /* BIFF2_??? where ??? is the name from [XLS] */ + function parse_BIFF2STR(blob, length, opts) { + var cell = parse_XLSCell(blob, 6); + ++blob.l; + var str = parse_XLUnicodeString2(blob, length-7, opts); + cell.t = 'str'; + cell.val = str; + return cell; + } + + function parse_BIFF2NUM(blob) { + var cell = parse_XLSCell(blob, 6); + ++blob.l; + var num = parse_Xnum(blob, 8); + cell.t = 'n'; + cell.val = num; + return cell; + } + function write_BIFF2NUM(r, c, val) { + var out = new_buf(15); + write_BIFF2Cell(out, r, c); + out.write_shift(8, val, 'f'); + return out; + } + + function parse_BIFF2INT(blob) { + var cell = parse_XLSCell(blob, 6); + ++blob.l; + var num = blob.read_shift(2); + cell.t = 'n'; + cell.val = num; + return cell; + } + function write_BIFF2INT(r, c, val) { + var out = new_buf(9); + write_BIFF2Cell(out, r, c); + out.write_shift(2, val); + return out; + } + + function parse_BIFF2STRING(blob) { + var cch = blob.read_shift(1); + if(cch === 0) { blob.l++; return ""; } + return blob.read_shift(cch, 'sbcs-cont'); + } + + /* TODO: convert to BIFF8 font struct */ + function parse_BIFF2FONTXTRA(blob, length) { + blob.l += 6; // unknown + blob.l += 2; // font weight "bls" + blob.l += 1; // charset + blob.l += 3; // unknown + blob.l += 1; // font family + blob.l += length - 13; + } + + /* TODO: parse rich text runs */ + function parse_RString(blob, length, opts) { + var end = blob.l + length; + var cell = parse_XLSCell(blob, 6); + var cch = blob.read_shift(2); + var str = parse_XLUnicodeStringNoCch(blob, cch, opts); + blob.l = end; + cell.t = 'str'; + cell.val = str; + return cell; + } + /* from js-harb (C) 2014-present SheetJS */ + var DBF = (function() { + var dbf_codepage_map = { + /* Code Pages Supported by Visual FoxPro */ + 0x01: 437, 0x02: 850, + 0x03: 1252, 0x04: 10000, + 0x64: 852, 0x65: 866, + 0x66: 865, 0x67: 861, + 0x68: 895, 0x69: 620, + 0x6A: 737, 0x6B: 857, + 0x78: 950, 0x79: 949, + 0x7A: 936, 0x7B: 932, + 0x7C: 874, 0x7D: 1255, + 0x7E: 1256, 0x96: 10007, + 0x97: 10029, 0x98: 10006, + 0xC8: 1250, 0xC9: 1251, + 0xCA: 1254, 0xCB: 1253, + + /* shapefile DBF extension */ + 0x00: 20127, 0x08: 865, + 0x09: 437, 0x0A: 850, + 0x0B: 437, 0x0D: 437, + 0x0E: 850, 0x0F: 437, + 0x10: 850, 0x11: 437, + 0x12: 850, 0x13: 932, + 0x14: 850, 0x15: 437, + 0x16: 850, 0x17: 865, + 0x18: 437, 0x19: 437, + 0x1A: 850, 0x1B: 437, + 0x1C: 863, 0x1D: 850, + 0x1F: 852, 0x22: 852, + 0x23: 852, 0x24: 860, + 0x25: 850, 0x26: 866, + 0x37: 850, 0x40: 852, + 0x4D: 936, 0x4E: 949, + 0x4F: 950, 0x50: 874, + 0x57: 1252, 0x58: 1252, + 0x59: 1252, + + 0xFF: 16969 + }; + + /* TODO: find an actual specification */ + function dbf_to_aoa(buf, opts) { + var out = []; + /* TODO: browser based */ + var d = (new_raw_buf(1)); + switch(opts.type) { + case 'base64': d = s2a(Base64.decode(buf)); break; + case 'binary': d = s2a(buf); break; + case 'buffer': + case 'array': d = buf; break; + } + prep_blob(d, 0); + /* header */ + var ft = d.read_shift(1); + var memo = false; + var vfp = false, l7 = false; + switch(ft) { + case 0x02: case 0x03: break; + case 0x30: vfp = true; memo = true; break; + case 0x31: vfp = true; break; + case 0x83: memo = true; break; + case 0x8B: memo = true; break; + case 0x8C: memo = true; l7 = true; break; + case 0xF5: memo = true; break; + default: throw new Error("DBF Unsupported Version: " + ft.toString(16)); + } + var /*filedate = new Date(),*/ nrow = 0, fpos = 0; + if(ft == 0x02) nrow = d.read_shift(2); + /*filedate = new Date(d.read_shift(1) + 1900, d.read_shift(1) - 1, d.read_shift(1));*/d.l += 3; + if(ft != 0x02) nrow = d.read_shift(4); + if(ft != 0x02) fpos = d.read_shift(2); + var rlen = d.read_shift(2); + + var /*flags = 0,*/ current_cp = 1252; + if(ft != 0x02) { + d.l+=16; + /*flags = */d.read_shift(1); + //if(memo && ((flags & 0x02) === 0)) throw new Error("DBF Flags " + flags.toString(16) + " ft " + ft.toString(16)); + + /* codepage present in FoxPro */ + if(d[d.l] !== 0) current_cp = dbf_codepage_map[d[d.l]]; + d.l+=1; + + d.l+=2; + } + if(l7) d.l += 36; + var fields = [], field = ({}); + var hend = fpos - 10 - (vfp ? 264 : 0), ww = l7 ? 32 : 11; + while(ft == 0x02 ? d.l < d.length && d[d.l] != 0x0d: d.l < hend) { + field = ({}); + field.name = cptable.utils.decode(current_cp, d.slice(d.l, d.l+ww)).replace(/[\u0000\r\n].*$/g,""); + d.l += ww; + field.type = String.fromCharCode(d.read_shift(1)); + if(ft != 0x02 && !l7) field.offset = d.read_shift(4); + field.len = d.read_shift(1); + if(ft == 0x02) field.offset = d.read_shift(2); + field.dec = d.read_shift(1); + if(field.name.length) fields.push(field); + if(ft != 0x02) d.l += l7 ? 13 : 14; + switch(field.type) { + case 'B': // VFP Double + if((!vfp || field.len != 8) && opts.WTF) console.log('Skipping ' + field.name + ':' + field.type); + break; + case 'G': // General + case 'P': // Picture + if(opts.WTF) console.log('Skipping ' + field.name + ':' + field.type); + break; + case 'C': // character + case 'D': // date + case 'F': // floating point + case 'I': // long + case 'L': // boolean + case 'M': // memo + case 'N': // number + case 'O': // double + case 'T': // datetime + case 'Y': // currency + case '0': // VFP _NullFlags + case '@': // timestamp + case '+': // autoincrement + break; + default: throw new Error('Unknown Field Type: ' + field.type); + } + } + if(d[d.l] !== 0x0D) d.l = fpos-1; + else if(ft == 0x02) d.l = 0x209; + if(ft != 0x02) { + if(d.read_shift(1) !== 0x0D) throw new Error("DBF Terminator not found " + d.l + " " + d[d.l]); + d.l = fpos; + } + /* data */ + var R = 0, C = 0; + out[0] = []; + for(C = 0; C != fields.length; ++C) out[0][C] = fields[C].name; + while(nrow-- > 0) { + if(d[d.l] === 0x2A) { d.l+=rlen; continue; } + ++d.l; + out[++R] = []; C = 0; + for(C = 0; C != fields.length; ++C) { + var dd = d.slice(d.l, d.l+fields[C].len); d.l+=fields[C].len; + prep_blob(dd, 0); + var s = cptable.utils.decode(current_cp, dd); + switch(fields[C].type) { + case 'C': + out[R][C] = cptable.utils.decode(current_cp, dd); + out[R][C] = out[R][C].trim(); + break; + case 'D': + if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8)); + else out[R][C] = s; + break; + case 'F': out[R][C] = parseFloat(s.trim()); break; + case '+': case 'I': out[R][C] = l7 ? dd.read_shift(-4, 'i') ^ 0x80000000 : dd.read_shift(4, 'i'); break; + case 'L': switch(s.toUpperCase()) { + case 'Y': case 'T': out[R][C] = true; break; + case 'N': case 'F': out[R][C] = false; break; + case ' ': case '?': out[R][C] = false; break; /* NOTE: technically uninitialized */ + default: throw new Error("DBF Unrecognized L:|" + s + "|"); + } break; + case 'M': /* TODO: handle memo files */ + if(!memo) throw new Error("DBF Unexpected MEMO for type " + ft.toString(16)); + out[R][C] = "##MEMO##" + (l7 ? parseInt(s.trim(), 10): dd.read_shift(4)); + break; + case 'N': out[R][C] = +s.replace(/\u0000/g,"").trim(); break; + case '@': out[R][C] = new Date(dd.read_shift(-8, 'f') - 0x388317533400); break; + case 'T': out[R][C] = new Date((dd.read_shift(4) - 0x253D8C) * 0x5265C00 + dd.read_shift(4)); break; + case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4; break; + case 'O': out[R][C] = -dd.read_shift(-8, 'f'); break; + case 'B': if(vfp && fields[C].len == 8) { out[R][C] = dd.read_shift(8,'f'); break; } + /* falls through */ + case 'G': case 'P': dd.l += fields[C].len; break; + case '0': + if(fields[C].name === '_NullFlags') break; + /* falls through */ + default: throw new Error("DBF Unsupported data type " + fields[C].type); + } + } + } + if(ft != 0x02) if(d.l < d.length && d[d.l++] != 0x1A) throw new Error("DBF EOF Marker missing " + (d.l-1) + " of " + d.length + " " + d[d.l-1].toString(16)); + if(opts && opts.sheetRows) out = out.slice(0, opts.sheetRows); + return out; + } + + function dbf_to_sheet(buf, opts) { + var o = opts || {}; + if(!o.dateNF) o.dateNF = "yyyymmdd"; + return aoa_to_sheet(dbf_to_aoa(buf, o), o); + } + + function dbf_to_workbook(buf, opts) { + try { return sheet_to_workbook(dbf_to_sheet(buf, opts), opts); } + catch(e) { if(opts && opts.WTF) throw e; } + return ({SheetNames:[],Sheets:{}}); + } + + var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 }; + function sheet_to_dbf(ws, opts) { + var o = opts || {}; + if(o.type == "string") throw new Error("Cannot write DBF to JS string"); + var ba = buf_array(); + var aoa = sheet_to_json(ws, {header:1, cellDates:true}); + var headers = aoa[0], data = aoa.slice(1); + var i = 0, j = 0, hcnt = 0, rlen = 1; + for(i = 0; i < headers.length; ++i) { + if(i == null) continue; + ++hcnt; + if(typeof headers[i] === 'number') headers[i] = headers[i].toString(10); + if(typeof headers[i] !== 'string') throw new Error("DBF Invalid column name " + headers[i] + " |" + (typeof headers[i]) + "|"); + if(headers.indexOf(headers[i]) !== i) for(j=0; j<1024;++j) + if(headers.indexOf(headers[i] + "_" + j) == -1) { headers[i] += "_" + j; break; } + } + var range = safe_decode_range(ws['!ref']); + var coltypes = []; + for(i = 0; i <= range.e.c - range.s.c; ++i) { + var col = []; + for(j=0; j < data.length; ++j) { + if(data[j][i] != null) col.push(data[j][i]); + } + if(col.length == 0 || headers[i] == null) { coltypes[i] = '?'; continue; } + var guess = '', _guess = ''; + for(j = 0; j < col.length; ++j) { + switch(typeof col[j]) { + /* TODO: check if L2 compat is desired */ + case 'number': _guess = 'B'; break; + case 'string': _guess = 'C'; break; + case 'boolean': _guess = 'L'; break; + case 'object': _guess = col[j] instanceof Date ? 'D' : 'C'; break; + default: _guess = 'C'; + } + guess = guess && guess != _guess ? 'C' : _guess; + if(guess == 'C') break; + } + rlen += _RLEN[guess] || 0; + coltypes[i] = guess; + } + + var h = ba.next(32); + h.write_shift(4, 0x13021130); + h.write_shift(4, data.length); + h.write_shift(2, 296 + 32 * hcnt); + h.write_shift(2, rlen); + for(i=0; i < 4; ++i) h.write_shift(4, 0); + h.write_shift(4, 0x00000300); // TODO: CP + + for(i = 0, j = 0; i < headers.length; ++i) { + if(headers[i] == null) continue; + var hf = ba.next(32); + var _f = (headers[i].slice(-10) + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00").slice(0, 11); + hf.write_shift(1, _f, "sbcs"); + hf.write_shift(1, coltypes[i] == '?' ? 'C' : coltypes[i], "sbcs"); + hf.write_shift(4, j); + hf.write_shift(1, _RLEN[coltypes[i]] || 0); + hf.write_shift(1, 0); + hf.write_shift(1, 0x02); + hf.write_shift(4, 0); + hf.write_shift(1, 0); + hf.write_shift(4, 0); + hf.write_shift(4, 0); + j += _RLEN[coltypes[i]] || 0; + } + + var hb = ba.next(264); + hb.write_shift(4, 0x0000000D); + for(i=0; i < 65;++i) hb.write_shift(4, 0x00000000); + for(i=0; i < data.length; ++i) { + var rout = ba.next(rlen); + rout.write_shift(1, 0); + for(j=0; j 0) switch(RT) { + case 'ID': break; /* header */ + case 'E': break; /* EOF */ + case 'B': break; /* dimensions */ + case 'O': break; /* options? */ + case 'P': + if(record[1].charAt(0) == 'P') + formats.push(rstr.slice(3).replace(/;;/g, ";")); + break; + case 'C': + var C_seen_K = false, C_seen_X = false; + for(rj=1; rj 0) { rowinfo[R].hpt = Mval; rowinfo[R].hpx = pt2px(Mval); } + else if(Mval === 0) rowinfo[R].hidden = true; + break; + default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr); + } + if(F_seen < 1) next_cell_format = null; break; + default: if(opts && opts.WTF) throw new Error("SYLK bad record " + rstr); + } + } + if(rowinfo.length > 0) sht['!rows'] = rowinfo; + if(colinfo.length > 0) sht['!cols'] = colinfo; + if(opts && opts.sheetRows) arr = arr.slice(0, opts.sheetRows); + return [arr, sht]; + } + + function sylk_to_sheet(d, opts) { + var aoasht = sylk_to_aoa(d, opts); + var aoa = aoasht[0], ws = aoasht[1]; + var o = aoa_to_sheet(aoa, opts); + keys(ws).forEach(function(k) { o[k] = ws[k]; }); + return o; + } + + function sylk_to_workbook(d, opts) { return sheet_to_workbook(sylk_to_sheet(d, opts), opts); } + + function write_ws_cell_sylk(cell, ws, R, C) { + var o = "C;Y" + (R+1) + ";X" + (C+1) + ";K"; + switch(cell.t) { + case 'n': + o += (cell.v||0); + if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break; + case 'b': o += cell.v ? "TRUE" : "FALSE"; break; + case 'e': o += cell.w || cell.v; break; + case 'd': o += '"' + (cell.w || cell.v) + '"'; break; + case 's': o += '"' + cell.v.replace(/"/g,"") + '"'; break; + } + return o; + } + + function write_ws_cols_sylk(out, cols) { + cols.forEach(function(col, i) { + var rec = "F;W" + (i+1) + " " + (i+1) + " "; + if(col.hidden) rec += "0"; + else { + if(typeof col.width == 'number') col.wpx = width2px(col.width); + if(typeof col.wpx == 'number') col.wch = px2char(col.wpx); + if(typeof col.wch == 'number') rec += Math.round(col.wch); + } + if(rec.charAt(rec.length - 1) != " ") out.push(rec); + }); + } + + function write_ws_rows_sylk(out, rows) { + rows.forEach(function(row, i) { + var rec = "F;"; + if(row.hidden) rec += "M0;"; + else if(row.hpt) rec += "M" + 20 * row.hpt + ";"; + else if(row.hpx) rec += "M" + 20 * px2pt(row.hpx) + ";"; + if(rec.length > 2) out.push(rec + "R" + (i+1)); + }); + } + + function sheet_to_sylk(ws, opts) { + var preamble = ["ID;PWXL;N;E"], o = []; + var r = safe_decode_range(ws['!ref']), cell; + var dense = Array.isArray(ws); + var RS = "\r\n"; + + preamble.push("P;PGeneral"); + preamble.push("F;P0;DG0G8;M255"); + if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']); + if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']); + + preamble.push("B;Y" + (r.e.r - r.s.r + 1) + ";X" + (r.e.c - r.s.c + 1) + ";D" + [r.s.c,r.s.r,r.e.c,r.e.r].join(" ")); + for(var R = r.s.r; R <= r.e.r; ++R) { + for(var C = r.s.c; C <= r.e.c; ++C) { + var coord = encode_cell({r:R,c:C}); + cell = dense ? (ws[R]||[])[C]: ws[coord]; + if(!cell || (cell.v == null && (!cell.f || cell.F))) continue; + o.push(write_ws_cell_sylk(cell, ws, R, C, opts)); + } + } + return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS; + } + + return { + to_workbook: sylk_to_workbook, + to_sheet: sylk_to_sheet, + from_sheet: sheet_to_sylk + }; + })(); + + var DIF = (function() { + function dif_to_aoa(d, opts) { + switch(opts.type) { + case 'base64': return dif_to_aoa_str(Base64.decode(d), opts); + case 'binary': return dif_to_aoa_str(d, opts); + case 'buffer': return dif_to_aoa_str(d.toString('binary'), opts); + case 'array': return dif_to_aoa_str(cc2str(d), opts); + } + throw new Error("Unrecognized type " + opts.type); + } + function dif_to_aoa_str(str, opts) { + var records = str.split('\n'), R = -1, C = -1, ri = 0, arr = []; + for (; ri !== records.length; ++ri) { + if (records[ri].trim() === 'BOT') { arr[++R] = []; C = 0; continue; } + if (R < 0) continue; + var metadata = records[ri].trim().split(","); + var type = metadata[0], value = metadata[1]; + ++ri; + var data = records[ri].trim(); + switch (+type) { + case -1: + if (data === 'BOT') { arr[++R] = []; C = 0; continue; } + else if (data !== 'EOD') throw new Error("Unrecognized DIF special command " + data); + break; + case 0: + if(data === 'TRUE') arr[R][C] = true; + else if(data === 'FALSE') arr[R][C] = false; + else if(!isNaN(fuzzynum(value))) arr[R][C] = fuzzynum(value); + else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value); + else arr[R][C] = value; + ++C; break; + case 1: + data = data.slice(1,data.length-1); + arr[R][C++] = data !== '' ? data : null; + break; + } + if (data === 'EOD') break; + } + if(opts && opts.sheetRows) arr = arr.slice(0, opts.sheetRows); + return arr; + } + + function dif_to_sheet(str, opts) { return aoa_to_sheet(dif_to_aoa(str, opts), opts); } + function dif_to_workbook(str, opts) { return sheet_to_workbook(dif_to_sheet(str, opts), opts); } + + var sheet_to_dif = (function() { + var push_field = function pf(o, topic, v, n, s) { + o.push(topic); + o.push(v + "," + n); + o.push('"' + s.replace(/"/g,'""') + '"'); + }; + var push_value = function po(o, type, v, s) { + o.push(type + "," + v); + o.push(type == 1 ? '"' + s.replace(/"/g,'""') + '"' : s); + }; + return function sheet_to_dif(ws) { + var o = []; + var r = safe_decode_range(ws['!ref']), cell; + var dense = Array.isArray(ws); + push_field(o, "TABLE", 0, 1, "sheetjs"); + push_field(o, "VECTORS", 0, r.e.r - r.s.r + 1,""); + push_field(o, "TUPLES", 0, r.e.c - r.s.c + 1,""); + push_field(o, "DATA", 0, 0,""); + for(var R = r.s.r; R <= r.e.r; ++R) { + push_value(o, -1, 0, "BOT"); + for(var C = r.s.c; C <= r.e.c; ++C) { + var coord = encode_cell({r:R,c:C}); + cell = dense ? (ws[R]||[])[C] : ws[coord]; + if(!cell) { push_value(o, 1, 0, ""); continue;} + switch(cell.t) { + case 'n': + var val = DIF_XL ? cell.w : cell.v; + if(!val && cell.v != null) val = cell.v; + if(val == null) { + if(DIF_XL && cell.f && !cell.F) push_value(o, 1, 0, "=" + cell.f); + else push_value(o, 1, 0, ""); + } + else push_value(o, 0, val, "V"); + break; + case 'b': + push_value(o, 0, cell.v ? 1 : 0, cell.v ? "TRUE" : "FALSE"); + break; + case 's': + push_value(o, 1, 0, (!DIF_XL || isNaN(cell.v)) ? cell.v : '="' + cell.v + '"'); + break; + case 'd': + if(!cell.w) cell.w = SSF.format(cell.z || SSF._table[14], datenum(parseDate(cell.v))); + if(DIF_XL) push_value(o, 0, cell.w, "V"); + else push_value(o, 1, 0, cell.w); + break; + default: push_value(o, 1, 0, ""); + } + } + } + push_value(o, -1, 0, "EOD"); + var RS = "\r\n"; + var oo = o.join(RS); + //while((oo.length & 0x7F) != 0) oo += "\0"; + return oo; + }; + })(); + return { + to_workbook: dif_to_workbook, + to_sheet: dif_to_sheet, + from_sheet: sheet_to_dif + }; + })(); + + var ETH = (function() { + function decode(s) { return s.replace(/\\b/g,"\\").replace(/\\c/g,":").replace(/\\n/g,"\n"); } + function encode(s) { return s.replace(/\\/g, "\\b").replace(/:/g, "\\c").replace(/\n/g,"\\n"); } + + function eth_to_aoa(str, opts) { + var records = str.split('\n'), R = -1, C = -1, ri = 0, arr = []; + for (; ri !== records.length; ++ri) { + var record = records[ri].trim().split(":"); + if(record[0] !== 'cell') continue; + var addr = decode_cell(record[1]); + if(arr.length <= addr.r) for(R = arr.length; R <= addr.r; ++R) if(!arr[R]) arr[R] = []; + R = addr.r; C = addr.c; + switch(record[2]) { + case 't': arr[R][C] = decode(record[3]); break; + case 'v': arr[R][C] = +record[3]; break; + case 'vtf': var _f = record[record.length - 1]; + /* falls through */ + case 'vtc': + switch(record[3]) { + case 'nl': arr[R][C] = +record[4] ? true : false; break; + default: arr[R][C] = +record[4]; break; + } + if(record[2] == 'vtf') arr[R][C] = [arr[R][C], _f]; + } + } + if(opts && opts.sheetRows) arr = arr.slice(0, opts.sheetRows); + return arr; + } + + function eth_to_sheet(d, opts) { return aoa_to_sheet(eth_to_aoa(d, opts), opts); } + function eth_to_workbook(d, opts) { return sheet_to_workbook(eth_to_sheet(d, opts), opts); } + + var header = [ + "socialcalc:version:1.5", + "MIME-Version: 1.0", + "Content-Type: multipart/mixed; boundary=SocialCalcSpreadsheetControlSave" + ].join("\n"); + + var sep = [ + "--SocialCalcSpreadsheetControlSave", + "Content-type: text/plain; charset=UTF-8" + ].join("\n") + "\n"; + + /* TODO: the other parts */ + var meta = [ + "# SocialCalc Spreadsheet Control Save", + "part:sheet" + ].join("\n"); + + var end = "--SocialCalcSpreadsheetControlSave--"; + + function sheet_to_eth_data(ws) { + if(!ws || !ws['!ref']) return ""; + var o = [], oo = [], cell, coord = ""; + var r = decode_range(ws['!ref']); + var dense = Array.isArray(ws); + for(var R = r.s.r; R <= r.e.r; ++R) { + for(var C = r.s.c; C <= r.e.c; ++C) { + coord = encode_cell({r:R,c:C}); + cell = dense ? (ws[R]||[])[C] : ws[coord]; + if(!cell || cell.v == null || cell.t === 'z') continue; + oo = ["cell", coord, 't']; + switch(cell.t) { + case 's': case 'str': oo.push(encode(cell.v)); break; + case 'n': + if(!cell.f) { oo[2]='v'; oo[3]=cell.v; } + else { oo[2]='vtf'; oo[3]='n'; oo[4]=cell.v; oo[5]=encode(cell.f); } + break; + case 'b': + oo[2] = 'vt'+(cell.f?'f':'c'); oo[3]='nl'; oo[4]=cell.v?"1":"0"; + oo[5] = encode(cell.f||(cell.v?'TRUE':'FALSE')); + break; + case 'd': + var t = datenum(parseDate(cell.v)); + oo[2] = 'vtc'; oo[3] = 'nd'; oo[4] = ""+t; + oo[5] = cell.w || SSF.format(cell.z || SSF._table[14], t); + break; + case 'e': continue; + } + o.push(oo.join(":")); + } + } + o.push("sheet:c:" + (r.e.c-r.s.c+1) + ":r:" + (r.e.r-r.s.r+1) + ":tvf:1"); + o.push("valueformat:1:text-wiki"); + //o.push("copiedfrom:" + ws['!ref']); // clipboard only + return o.join("\n"); + } + + function sheet_to_eth(ws) { + return [header, sep, meta, sep, sheet_to_eth_data(ws), end].join("\n"); + // return ["version:1.5", sheet_to_eth_data(ws)].join("\n"); // clipboard form + } + + return { + to_workbook: eth_to_workbook, + to_sheet: eth_to_sheet, + from_sheet: sheet_to_eth + }; + })(); + + var PRN = (function() { + function set_text_arr(data, arr, R, C, o) { + if(o.raw) arr[R][C] = data; + else if(data === 'TRUE') arr[R][C] = true; + else if(data === 'FALSE') arr[R][C] = false; + else if(data === ""){/* empty */} + else if(!isNaN(fuzzynum(data))) arr[R][C] = fuzzynum(data); + else if(!isNaN(fuzzydate(data).getDate())) arr[R][C] = parseDate(data); + else arr[R][C] = data; + } + + function prn_to_aoa_str(f, opts) { + var o = opts || {}; + var arr = ([]); + if(!f || f.length === 0) return arr; + var lines = f.split(/[\r\n]/); + var L = lines.length - 1; + while(L >= 0 && lines[L].length === 0) --L; + var start = 10, idx = 0; + var R = 0; + for(; R <= L; ++R) { + idx = lines[R].indexOf(" "); + if(idx == -1) idx = lines[R].length; else idx++; + start = Math.max(start, idx); + } + for(R = 0; R <= L; ++R) { + arr[R] = []; + /* TODO: confirm that widths are always 10 */ + var C = 0; + set_text_arr(lines[R].slice(0, start).trim(), arr, R, C, o); + for(C = 1; C <= (lines[R].length - start)/10 + 1; ++C) + set_text_arr(lines[R].slice(start+(C-1)*10,start+C*10).trim(),arr,R,C,o); + } + if(o.sheetRows) arr = arr.slice(0, o.sheetRows); + return arr; + } + + // List of accepted CSV separators + var guess_seps = { + 0x2C: ',', + 0x09: "\t", + 0x3B: ';' + }; + + // CSV separator weights to be used in case of equal numbers + var guess_sep_weights = { + 0x2C: 3, + 0x09: 2, + 0x3B: 1 + }; + + function guess_sep(str) { + var cnt = {}, instr = false, end = 0, cc = 0; + for(;end < str.length;++end) { + if((cc=str.charCodeAt(end)) == 0x22) instr = !instr; + else if(!instr && cc in guess_seps) cnt[cc] = (cnt[cc]||0)+1; + } + + cc = []; + for(end in cnt) if ( cnt.hasOwnProperty(end) ) { + cc.push([ cnt[end], end ]); + } + + if ( !cc.length ) { + cnt = guess_sep_weights; + for(end in cnt) if ( cnt.hasOwnProperty(end) ) { + cc.push([ cnt[end], end ]); + } + } + + cc.sort(function(a, b) { return a[0] - b[0] || guess_sep_weights[a[1]] - guess_sep_weights[b[1]]; }); + + return guess_seps[cc.pop()[1]]; + } + + function dsv_to_sheet_str(str, opts) { + var o = opts || {}; + var sep = ""; + if(DENSE != null && o.dense == null) o.dense = DENSE; + var ws = o.dense ? ([]) : ({}); + var range = ({s: {c:0, r:0}, e: {c:0, r:0}}); + + if(str.slice(0,4) == "sep=" && str.charCodeAt(5) == 10) { sep = str.charAt(4); str = str.slice(6); } + else sep = guess_sep(str.slice(0,1024)); + var R = 0, C = 0, v = 0; + var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0; + str = str.replace(/\r\n/mg, "\n"); + var _re = o.dateNF != null ? dateNF_regex(o.dateNF) : null; + function finish_cell() { + var s = str.slice(start, end); + var cell = ({}); + if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"'); + if(s.length === 0) cell.t = 'z'; + else if(o.raw) { cell.t = 's'; cell.v = s; } + else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; } + else if(s.charCodeAt(0) == 0x3D) { + if(s.charCodeAt(1) == 0x22 && s.charCodeAt(s.length - 1) == 0x22) { cell.t = 's'; cell.v = s.slice(2,-1).replace(/""/g,'"'); } + else if(fuzzyfmla(s)) { cell.t = 'n'; cell.f = s.slice(1); } + else { cell.t = 's'; cell.v = s; } } + else if(s == "TRUE") { cell.t = 'b'; cell.v = true; } + else if(s == "FALSE") { cell.t = 'b'; cell.v = false; } + else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; if(o.cellText !== false) cell.w = s; cell.v = v; } + else if(!isNaN(fuzzydate(s).getDate()) || _re && s.match(_re)) { + cell.z = o.dateNF || SSF._table[14]; + var k = 0; + if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; } + if(o.cellDates) { cell.t = 'd'; cell.v = parseDate(s, k); } + else { cell.t = 'n'; cell.v = datenum(parseDate(s, k)); } + if(o.cellText !== false) cell.w = SSF.format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v); + if(!o.cellNF) delete cell.z; + } else { + cell.t = 's'; + cell.v = s; + } + if(cell.t == 'z'){} + else if(o.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = cell; } + else ws[encode_cell({c:C,r:R})] = cell; + start = end+1; + if(range.e.c < C) range.e.c = C; + if(range.e.r < R) range.e.r = R; + if(cc == sepcc) ++C; else { C = 0; ++R; if(o.sheetRows && o.sheetRows <= R) return true; } + } + outer: for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) { + case 0x22: instr = !instr; break; + case sepcc: case 0x0a: case 0x0d: if(!instr && finish_cell()) break outer; break; + default: break; + } + if(end - start > 0) finish_cell(); + + ws['!ref'] = encode_range(range); + return ws; + } + + function prn_to_sheet_str(str, opts) { + if(str.slice(0,4) == "sep=") return dsv_to_sheet_str(str, opts); + if(str.indexOf("\t") >= 0 || str.indexOf(",") >= 0 || str.indexOf(";") >= 0) return dsv_to_sheet_str(str, opts); + return aoa_to_sheet(prn_to_aoa_str(str, opts), opts); + } + + function prn_to_sheet(d, opts) { + var str = "", bytes = opts.type == 'string' ? [0,0,0,0] : firstbyte(d, opts); + switch(opts.type) { + case 'base64': str = Base64.decode(d); break; + case 'binary': str = d; break; + case 'buffer': + if(opts.codepage == 65001) str = d.toString('utf8'); + else if(opts.codepage && typeof cptable !== 'undefined') str = cptable.utils.decode(opts.codepage, d); + else str = d.toString('binary'); + break; + case 'array': str = cc2str(d); break; + case 'string': str = d; break; + default: throw new Error("Unrecognized type " + opts.type); + } + if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str.slice(3)); + else if((opts.type == 'binary') && typeof cptable !== 'undefined' && opts.codepage) str = cptable.utils.decode(opts.codepage, cptable.utils.encode(1252,str)); + if(str.slice(0,19) == "socialcalc:version:") return ETH.to_sheet(opts.type == 'string' ? str : utf8read(str), opts); + return prn_to_sheet_str(str, opts); + } + + function prn_to_workbook(d, opts) { return sheet_to_workbook(prn_to_sheet(d, opts), opts); } + + function sheet_to_prn(ws) { + var o = []; + var r = safe_decode_range(ws['!ref']), cell; + var dense = Array.isArray(ws); + for(var R = r.s.r; R <= r.e.r; ++R) { + var oo = []; + for(var C = r.s.c; C <= r.e.c; ++C) { + var coord = encode_cell({r:R,c:C}); + cell = dense ? (ws[R]||[])[C] : ws[coord]; + if(!cell || cell.v == null) { oo.push(" "); continue; } + var w = (cell.w || (format_cell(cell), cell.w) || "").slice(0,10); + while(w.length < 10) w += " "; + oo.push(w + (C === 0 ? " " : "")); + } + o.push(oo.join("")); + } + return o.join("\n"); + } + + return { + to_workbook: prn_to_workbook, + to_sheet: prn_to_sheet, + from_sheet: sheet_to_prn + }; + })(); + + /* Excel defaults to SYLK but warns if data is not valid */ + function read_wb_ID(d, opts) { + var o = opts || {}, OLD_WTF = !!o.WTF; o.WTF = true; + try { + var out = SYLK.to_workbook(d, o); + o.WTF = OLD_WTF; + return out; + } catch(e) { + o.WTF = OLD_WTF; + if(!e.message.match(/SYLK bad record ID/) && OLD_WTF) throw e; + return PRN.to_workbook(d, opts); + } + } + var WK_ = (function() { + function lotushopper(data, cb, opts) { + if(!data) return; + prep_blob(data, data.l || 0); + var Enum = opts.Enum || WK1Enum; + while(data.l < data.length) { + var RT = data.read_shift(2); + var R = Enum[RT] || Enum[0xFF]; + var length = data.read_shift(2); + var tgt = data.l + length; + var d = (R.f||parsenoop)(data, length, opts); + data.l = tgt; + if(cb(d, R.n, RT)) return; + } + } + + function lotus_to_workbook(d, opts) { + switch(opts.type) { + case 'base64': return lotus_to_workbook_buf(s2a(Base64.decode(d)), opts); + case 'binary': return lotus_to_workbook_buf(s2a(d), opts); + case 'buffer': + case 'array': return lotus_to_workbook_buf(d, opts); + } + throw "Unsupported type " + opts.type; + } + + function lotus_to_workbook_buf(d, opts) { + if(!d) return d; + var o = opts || {}; + if(DENSE != null && o.dense == null) o.dense = DENSE; + var s = ((o.dense ? [] : {})), n = "Sheet1", sidx = 0; + var sheets = {}, snames = [n]; + + var refguess = {s: {r:0, c:0}, e: {r:0, c:0} }; + var sheetRows = o.sheetRows || 0; + + if(d[2] == 0x02) o.Enum = WK1Enum; + else if(d[2] == 0x1a) o.Enum = WK3Enum; + else if(d[2] == 0x0e) { o.Enum = WK3Enum; o.qpro = true; d.l = 0; } + else throw new Error("Unrecognized LOTUS BOF " + d[2]); + lotushopper(d, function(val, Rn, RT) { + if(d[2] == 0x02) switch(RT) { + case 0x00: + o.vers = val; + if(val >= 0x1000) o.qpro = true; + break; + case 0x06: refguess = val; break; /* RANGE */ + case 0x0F: /* LABEL */ + if(!o.qpro) val[1].v = val[1].v.slice(1); + /* falls through */ + case 0x0D: /* INTEGER */ + case 0x0E: /* NUMBER */ + case 0x10: /* FORMULA */ + case 0x33: /* STRING */ + /* TODO: actual translation of the format code */ + if(RT == 0x0E && (val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) { + val[1].z = o.dateNF || SSF._table[14]; + if(o.cellDates) { val[1].t = 'd'; val[1].v = numdate(val[1].v); } + } + if(o.dense) { + if(!s[val[0].r]) s[val[0].r] = []; + s[val[0].r][val[0].c] = val[1]; + } else s[encode_cell(val[0])] = val[1]; + break; + } else switch(RT) { + case 0x16: /* LABEL16 */ + val[1].v = val[1].v.slice(1); + /* falls through */ + case 0x17: /* NUMBER17 */ + case 0x18: /* NUMBER18 */ + case 0x19: /* FORMULA19 */ + case 0x25: /* NUMBER25 */ + case 0x27: /* NUMBER27 */ + case 0x28: /* FORMULA28 */ + if(val[3] > sidx) { + s["!ref"] = encode_range(refguess); + sheets[n] = s; + s = (o.dense ? [] : {}); + refguess = {s: {r:0, c:0}, e: {r:0, c:0} }; + sidx = val[3]; n = "Sheet" + (sidx + 1); + snames.push(n); + } + if(sheetRows > 0 && val[0].r >= sheetRows) break; + if(o.dense) { + if(!s[val[0].r]) s[val[0].r] = []; + s[val[0].r][val[0].c] = val[1]; + } else s[encode_cell(val[0])] = val[1]; + if(refguess.e.c < val[0].c) refguess.e.c = val[0].c; + if(refguess.e.r < val[0].r) refguess.e.r = val[0].r; + break; + default: break; + } + }, o); + + s["!ref"] = encode_range(refguess); + sheets[n] = s; + return { SheetNames: snames, Sheets:sheets }; + } + + function parse_RANGE(blob) { + var o = {s:{c:0,r:0},e:{c:0,r:0}}; + o.s.c = blob.read_shift(2); + o.s.r = blob.read_shift(2); + o.e.c = blob.read_shift(2); + o.e.r = blob.read_shift(2); + if(o.s.c == 0xFFFF) o.s.c = o.e.c = o.s.r = o.e.r = 0; + return o; + } + + function parse_cell(blob, length, opts) { + var o = [{c:0,r:0}, {t:'n',v:0}, 0]; + if(opts.qpro && opts.vers != 0x5120) { + o[0].c = blob.read_shift(1); + blob.l++; + o[0].r = blob.read_shift(2); + blob.l+=2; + } else { + o[2] = blob.read_shift(1); + o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2); + } + return o; + } + + function parse_LABEL(blob, length, opts) { + var tgt = blob.l + length; + var o = parse_cell(blob, length, opts); + o[1].t = 's'; + if(opts.vers == 0x5120) { + blob.l++; + var len = blob.read_shift(1); + o[1].v = blob.read_shift(len, 'utf8'); + return o; + } + if(opts.qpro) blob.l++; + o[1].v = blob.read_shift(tgt - blob.l, 'cstr'); + return o; + } + + function parse_INTEGER(blob, length, opts) { + var o = parse_cell(blob, length, opts); + o[1].v = blob.read_shift(2, 'i'); + return o; + } + + function parse_NUMBER(blob, length, opts) { + var o = parse_cell(blob, length, opts); + o[1].v = blob.read_shift(8, 'f'); + return o; + } + + function parse_FORMULA(blob, length, opts) { + var tgt = blob.l + length; + var o = parse_cell(blob, length, opts); + /* TODO: formula */ + o[1].v = blob.read_shift(8, 'f'); + if(opts.qpro) blob.l = tgt; + else { + var flen = blob.read_shift(2); + blob.l += flen; + } + return o; + } + + function parse_cell_3(blob) { + var o = [{c:0,r:0}, {t:'n',v:0}, 0]; + o[0].r = blob.read_shift(2); o[3] = blob[blob.l++]; o[0].c = blob[blob.l++]; + return o; + } + + function parse_LABEL_16(blob, length) { + var o = parse_cell_3(blob, length); + o[1].t = 's'; + o[1].v = blob.read_shift(length - 4, 'cstr'); + return o; + } + + function parse_NUMBER_18(blob, length) { + var o = parse_cell_3(blob, length); + o[1].v = blob.read_shift(2); + var v = o[1].v >> 1; + /* TODO: figure out all of the corner cases */ + if(o[1].v & 0x1) { + switch(v & 0x07) { + case 1: v = (v >> 3) * 500; break; + case 2: v = (v >> 3) / 20; break; + case 4: v = (v >> 3) / 2000; break; + case 6: v = (v >> 3) / 16; break; + case 7: v = (v >> 3) / 64; break; + default: throw "unknown NUMBER_18 encoding " + (v & 0x07); + } + } + o[1].v = v; + return o; + } + + function parse_NUMBER_17(blob, length) { + var o = parse_cell_3(blob, length); + var v1 = blob.read_shift(4); + var v2 = blob.read_shift(4); + var e = blob.read_shift(2); + if(e == 0xFFFF) { o[1].v = 0; return o; } + var s = e & 0x8000; e = (e&0x7FFF) - 16446; + o[1].v = (s*2 - 1) * ((e > 0 ? (v2 << e) : (v2 >>> -e)) + (e > -32 ? (v1 << (e + 32)) : (v1 >>> -(e + 32)))); + return o; + } + + function parse_FORMULA_19(blob, length) { + var o = parse_NUMBER_17(blob, 14); + blob.l += length - 14; /* TODO: formula */ + return o; + } + + function parse_NUMBER_25(blob, length) { + var o = parse_cell_3(blob, length); + var v1 = blob.read_shift(4); + o[1].v = v1 >> 6; + return o; + } + + function parse_NUMBER_27(blob, length) { + var o = parse_cell_3(blob, length); + var v1 = blob.read_shift(8,'f'); + o[1].v = v1; + return o; + } + + function parse_FORMULA_28(blob, length) { + var o = parse_NUMBER_27(blob, 14); + blob.l += length - 10; /* TODO: formula */ + return o; + } + + var WK1Enum = { + 0x0000: { n:"BOF", f:parseuint16 }, + 0x0001: { n:"EOF" }, + 0x0002: { n:"CALCMODE" }, + 0x0003: { n:"CALCORDER" }, + 0x0004: { n:"SPLIT" }, + 0x0005: { n:"SYNC" }, + 0x0006: { n:"RANGE", f:parse_RANGE }, + 0x0007: { n:"WINDOW1" }, + 0x0008: { n:"COLW1" }, + 0x0009: { n:"WINTWO" }, + 0x000A: { n:"COLW2" }, + 0x000B: { n:"NAME" }, + 0x000C: { n:"BLANK" }, + 0x000D: { n:"INTEGER", f:parse_INTEGER }, + 0x000E: { n:"NUMBER", f:parse_NUMBER }, + 0x000F: { n:"LABEL", f:parse_LABEL }, + 0x0010: { n:"FORMULA", f:parse_FORMULA }, + 0x0018: { n:"TABLE" }, + 0x0019: { n:"ORANGE" }, + 0x001A: { n:"PRANGE" }, + 0x001B: { n:"SRANGE" }, + 0x001C: { n:"FRANGE" }, + 0x001D: { n:"KRANGE1" }, + 0x0020: { n:"HRANGE" }, + 0x0023: { n:"KRANGE2" }, + 0x0024: { n:"PROTEC" }, + 0x0025: { n:"FOOTER" }, + 0x0026: { n:"HEADER" }, + 0x0027: { n:"SETUP" }, + 0x0028: { n:"MARGINS" }, + 0x0029: { n:"LABELFMT" }, + 0x002A: { n:"TITLES" }, + 0x002B: { n:"SHEETJS" }, + 0x002D: { n:"GRAPH" }, + 0x002E: { n:"NGRAPH" }, + 0x002F: { n:"CALCCOUNT" }, + 0x0030: { n:"UNFORMATTED" }, + 0x0031: { n:"CURSORW12" }, + 0x0032: { n:"WINDOW" }, + 0x0033: { n:"STRING", f:parse_LABEL }, + 0x0037: { n:"PASSWORD" }, + 0x0038: { n:"LOCKED" }, + 0x003C: { n:"QUERY" }, + 0x003D: { n:"QUERYNAME" }, + 0x003E: { n:"PRINT" }, + 0x003F: { n:"PRINTNAME" }, + 0x0040: { n:"GRAPH2" }, + 0x0041: { n:"GRAPHNAME" }, + 0x0042: { n:"ZOOM" }, + 0x0043: { n:"SYMSPLIT" }, + 0x0044: { n:"NSROWS" }, + 0x0045: { n:"NSCOLS" }, + 0x0046: { n:"RULER" }, + 0x0047: { n:"NNAME" }, + 0x0048: { n:"ACOMM" }, + 0x0049: { n:"AMACRO" }, + 0x004A: { n:"PARSE" }, + 0x00FF: { n:"", f:parsenoop } + }; + + var WK3Enum = { + 0x0000: { n:"BOF" }, + 0x0001: { n:"EOF" }, + 0x0003: { n:"??" }, + 0x0004: { n:"??" }, + 0x0005: { n:"??" }, + 0x0006: { n:"??" }, + 0x0007: { n:"??" }, + 0x0009: { n:"??" }, + 0x000a: { n:"??" }, + 0x000b: { n:"??" }, + 0x000c: { n:"??" }, + 0x000e: { n:"??" }, + 0x000f: { n:"??" }, + 0x0010: { n:"??" }, + 0x0011: { n:"??" }, + 0x0012: { n:"??" }, + 0x0013: { n:"??" }, + 0x0015: { n:"??" }, + 0x0016: { n:"LABEL16", f:parse_LABEL_16}, + 0x0017: { n:"NUMBER17", f:parse_NUMBER_17 }, + 0x0018: { n:"NUMBER18", f:parse_NUMBER_18 }, + 0x0019: { n:"FORMULA19", f:parse_FORMULA_19}, + 0x001a: { n:"??" }, + 0x001b: { n:"??" }, + 0x001c: { n:"??" }, + 0x001d: { n:"??" }, + 0x001e: { n:"??" }, + 0x001f: { n:"??" }, + 0x0021: { n:"??" }, + 0x0025: { n:"NUMBER25", f:parse_NUMBER_25 }, + 0x0027: { n:"NUMBER27", f:parse_NUMBER_27 }, + 0x0028: { n:"FORMULA28", f:parse_FORMULA_28 }, + 0x00FF: { n:"", f:parsenoop } + }; + return { + to_workbook: lotus_to_workbook + }; + })(); + /* Parse a list of tags */ + var parse_rs = (function parse_rs_factory() { + var tregex = matchtag("t"), rpregex = matchtag("rPr"), rregex = /<(?:\w+:)?r>/g, rend = /<\/(?:\w+:)?r>/, nlregex = /\r\n/g; + /* 18.4.7 rPr CT_RPrElt */ + var parse_rpr = function parse_rpr(rpr, intro, outro) { + var font = {}, cp = 65001, align = ""; + var pass = false; + var m = rpr.match(tagregex), i = 0; + if(m) for(;i!=m.length; ++i) { + var y = parsexmltag(m[i]); + switch(y[0].replace(/\w*:/g,"")) { + /* 18.8.12 condense CT_BooleanProperty */ + /* ** not required . */ + case '': + case '': font.shadow = 1; break; + case '': break; + + /* 18.4.1 charset CT_IntProperty TODO */ + case '': + case '': font.outline = 1; break; + case '': break; + + /* 18.4.5 rFont CT_FontName */ + case '': + case '': font.strike = 1; break; + case '': break; + + /* 18.4.13 u CT_UnderlineProperty */ + case '': + case '': font.u = 1; break; + case '': break; + + /* 18.8.2 b */ + case '': + case '': font.b = 1; break; + case '': break; + + /* 18.8.26 i */ + case '': + case '': font.i = 1; break; + case '': break; + + /* 18.3.1.15 color CT_Color TODO: tint, theme, auto, indexed */ + case '': case '': break; + case '': pass = false; break; + default: + if(y[0].charCodeAt(1) !== 47 && !pass) throw new Error('Unrecognized rich format ' + y[0]); + } + } + var style = []; + + if(font.u) style.push("text-decoration: underline;"); + if(font.uval) style.push("text-underline-style:" + font.uval + ";"); + if(font.sz) style.push("font-size:" + font.sz + "pt;"); + if(font.outline) style.push("text-effect: outline;"); + if(font.shadow) style.push("text-shadow: auto;"); + intro.push(''); + + if(font.b) { intro.push(""); outro.push(""); } + if(font.i) { intro.push(""); outro.push(""); } + if(font.strike) { intro.push(""); outro.push(""); } + + if(align == "superscript") align = "sup"; + else if(align == "subscript") align = "sub"; + if(align != "") { intro.push("<" + align + ">"); outro.push(""); } + + outro.push(""); + return cp; + }; + + /* 18.4.4 r CT_RElt */ + function parse_r(r) { + var terms = [[],"",[]]; + /* 18.4.12 t ST_Xstring */ + var t = r.match(tregex)/*, cp = 65001*/; + if(!t) return ""; + terms[1] = t[1]; + + var rpr = r.match(rpregex); + if(rpr) /*cp = */parse_rpr(rpr[1], terms[0], terms[2]); + + return terms[0].join("") + terms[1].replace(nlregex,'
                ') + terms[2].join(""); + } + return function parse_rs(rs) { + return rs.replace(rregex,"").split(rend).map(parse_r).join(""); + }; + })(); + + /* 18.4.8 si CT_Rst */ + var sitregex = /<(?:\w+:)?t[^>]*>([^<]*)<\/(?:\w+:)?t>/g, sirregex = /<(?:\w+:)?r>/; + var sirphregex = /<(?:\w+:)?rPh.*?>([\s\S]*?)<\/(?:\w+:)?rPh>/g; + function parse_si(x, opts) { + var html = opts ? opts.cellHTML : true; + var z = {}; + if(!x) return null; + //var y; + /* 18.4.12 t ST_Xstring (Plaintext String) */ + // TODO: is whitespace actually valid here? + if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) { + z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||"")); + z.r = utf8read(x); + if(html) z.h = escapehtml(z.t); + } + /* 18.4.4 r CT_RElt (Rich Text Run) */ + else if((/*y = */x.match(sirregex))) { + z.r = utf8read(x); + z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,""))); + if(html) z.h = parse_rs(z.r); + } + /* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */ + /* 18.4.6 rPh CT_PhoneticRun (TODO: needed for Asian support) */ + return z; + } + + /* 18.4 Shared String Table */ + var sstr0 = /<(?:\w+:)?sst([^>]*)>([\s\S]*)<\/(?:\w+:)?sst>/; + var sstr1 = /<(?:\w+:)?(?:si|sstItem)>/g; + var sstr2 = /<\/(?:\w+:)?(?:si|sstItem)>/; + function parse_sst_xml(data, opts) { + var s = ([]), ss = ""; + if(!data) return s; + /* 18.4.9 sst CT_Sst */ + var sst = data.match(sstr0); + if(sst) { + ss = sst[2].replace(sstr1,"").split(sstr2); + for(var i = 0; i != ss.length; ++i) { + var o = parse_si(ss[i].trim(), opts); + if(o != null) s[s.length] = o; + } + sst = parsexmltag(sst[1]); s.Count = sst.count; s.Unique = sst.uniqueCount; + } + return s; + } + + RELS.SST = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"; + var straywsregex = /^\s|\s$|[\t\n\r]/; + function write_sst_xml(sst, opts) { + if(!opts.bookSST) return ""; + var o = [XML_HEADER]; + o[o.length] = (writextag('sst', null, { + xmlns: XMLNS.main[0], + count: sst.Count, + uniqueCount: sst.Unique + })); + for(var i = 0; i != sst.length; ++i) { if(sst[i] == null) continue; + var s = sst[i]; + var sitag = ""; + if(s.r) sitag += s.r; + else { + sitag += ""; + } + sitag += ""; + o[o.length] = (sitag); + } + if(o.length>2){ o[o.length] = (''); o[1]=o[1].replace("/>",">"); } + return o.join(""); + } + /* [MS-XLSB] 2.4.221 BrtBeginSst */ + function parse_BrtBeginSst(data) { + return [data.read_shift(4), data.read_shift(4)]; + } + + /* [MS-XLSB] 2.1.7.45 Shared Strings */ + function parse_sst_bin(data, opts) { + var s = ([]); + var pass = false; + recordhopper(data, function hopper_sst(val, R_n, RT) { + switch(RT) { + case 0x009F: /* 'BrtBeginSst' */ + s.Count = val[0]; s.Unique = val[1]; break; + case 0x0013: /* 'BrtSSTItem' */ + s.push(val); break; + case 0x00A0: /* 'BrtEndSst' */ + return true; + + case 0x0023: /* 'BrtFRTBegin' */ + pass = true; break; + case 0x0024: /* 'BrtFRTEnd' */ + pass = false; break; + + default: + if(R_n.indexOf("Begin") > 0){/* empty */} + else if(R_n.indexOf("End") > 0){/* empty */} + if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n); + } + }); + return s; + } + + function write_BrtBeginSst(sst, o) { + if(!o) o = new_buf(8); + o.write_shift(4, sst.Count); + o.write_shift(4, sst.Unique); + return o; + } + + var write_BrtSSTItem = write_RichStr; + + function write_sst_bin(sst) { + var ba = buf_array(); + write_record(ba, "BrtBeginSst", write_BrtBeginSst(sst)); + for(var i = 0; i < sst.length; ++i) write_record(ba, "BrtSSTItem", write_BrtSSTItem(sst[i])); + /* FRTSST */ + write_record(ba, "BrtEndSst"); + return ba.end(); + } + function _JS2ANSI(str) { + if(typeof cptable !== 'undefined') return cptable.utils.encode(current_ansi, str); + var o = [], oo = str.split(""); + for(var i = 0; i < oo.length; ++i) o[i] = oo[i].charCodeAt(0); + return o; + } + + /* [MS-OFFCRYPTO] 2.1.4 Version */ + function parse_CRYPTOVersion(blob, length) { + var o = {}; + o.Major = blob.read_shift(2); + o.Minor = blob.read_shift(2); + if(length >= 4) blob.l += length - 4; + return o; + } + + /* [MS-OFFCRYPTO] 2.1.5 DataSpaceVersionInfo */ + function parse_DataSpaceVersionInfo(blob) { + var o = {}; + o.id = blob.read_shift(0, 'lpp4'); + o.R = parse_CRYPTOVersion(blob, 4); + o.U = parse_CRYPTOVersion(blob, 4); + o.W = parse_CRYPTOVersion(blob, 4); + return o; + } + + /* [MS-OFFCRYPTO] 2.1.6.1 DataSpaceMapEntry Structure */ + function parse_DataSpaceMapEntry(blob) { + var len = blob.read_shift(4); + var end = blob.l + len - 4; + var o = {}; + var cnt = blob.read_shift(4); + var comps = []; + /* [MS-OFFCRYPTO] 2.1.6.2 DataSpaceReferenceComponent Structure */ + while(cnt-- > 0) comps.push({ t: blob.read_shift(4), v: blob.read_shift(0, 'lpp4') }); + o.name = blob.read_shift(0, 'lpp4'); + o.comps = comps; + if(blob.l != end) throw new Error("Bad DataSpaceMapEntry: " + blob.l + " != " + end); + return o; + } + + /* [MS-OFFCRYPTO] 2.1.6 DataSpaceMap */ + function parse_DataSpaceMap(blob) { + var o = []; + blob.l += 4; // must be 0x8 + var cnt = blob.read_shift(4); + while(cnt-- > 0) o.push(parse_DataSpaceMapEntry(blob)); + return o; + } + + /* [MS-OFFCRYPTO] 2.1.7 DataSpaceDefinition */ + function parse_DataSpaceDefinition(blob) { + var o = []; + blob.l += 4; // must be 0x8 + var cnt = blob.read_shift(4); + while(cnt-- > 0) o.push(blob.read_shift(0, 'lpp4')); + return o; + } + + /* [MS-OFFCRYPTO] 2.1.8 DataSpaceDefinition */ + function parse_TransformInfoHeader(blob) { + var o = {}; + /*var len = */blob.read_shift(4); + blob.l += 4; // must be 0x1 + o.id = blob.read_shift(0, 'lpp4'); + o.name = blob.read_shift(0, 'lpp4'); + o.R = parse_CRYPTOVersion(blob, 4); + o.U = parse_CRYPTOVersion(blob, 4); + o.W = parse_CRYPTOVersion(blob, 4); + return o; + } + + function parse_Primary(blob) { + /* [MS-OFFCRYPTO] 2.2.6 IRMDSTransformInfo */ + var hdr = parse_TransformInfoHeader(blob); + /* [MS-OFFCRYPTO] 2.1.9 EncryptionTransformInfo */ + hdr.ename = blob.read_shift(0, '8lpp4'); + hdr.blksz = blob.read_shift(4); + hdr.cmode = blob.read_shift(4); + if(blob.read_shift(4) != 0x04) throw new Error("Bad !Primary record"); + return hdr; + } + + /* [MS-OFFCRYPTO] 2.3.2 Encryption Header */ + function parse_EncryptionHeader(blob, length) { + var tgt = blob.l + length; + var o = {}; + o.Flags = (blob.read_shift(4) & 0x3F); + blob.l += 4; + o.AlgID = blob.read_shift(4); + var valid = false; + switch(o.AlgID) { + case 0x660E: case 0x660F: case 0x6610: valid = (o.Flags == 0x24); break; + case 0x6801: valid = (o.Flags == 0x04); break; + case 0: valid = (o.Flags == 0x10 || o.Flags == 0x04 || o.Flags == 0x24); break; + default: throw 'Unrecognized encryption algorithm: ' + o.AlgID; + } + if(!valid) throw new Error("Encryption Flags/AlgID mismatch"); + o.AlgIDHash = blob.read_shift(4); + o.KeySize = blob.read_shift(4); + o.ProviderType = blob.read_shift(4); + blob.l += 8; + o.CSPName = blob.read_shift((tgt-blob.l)>>1, 'utf16le'); + blob.l = tgt; + return o; + } + + /* [MS-OFFCRYPTO] 2.3.3 Encryption Verifier */ + function parse_EncryptionVerifier(blob, length) { + var o = {}, tgt = blob.l + length; + blob.l += 4; // SaltSize must be 0x10 + o.Salt = blob.slice(blob.l, blob.l+16); blob.l += 16; + o.Verifier = blob.slice(blob.l, blob.l+16); blob.l += 16; + /*var sz = */blob.read_shift(4); + o.VerifierHash = blob.slice(blob.l, tgt); blob.l = tgt; + return o; + } + + /* [MS-OFFCRYPTO] 2.3.4.* EncryptionInfo Stream */ + function parse_EncryptionInfo(blob) { + var vers = parse_CRYPTOVersion(blob); + switch(vers.Minor) { + case 0x02: return [vers.Minor, parse_EncInfoStd(blob, vers)]; + case 0x03: return [vers.Minor, parse_EncInfoExt(blob, vers)]; + case 0x04: return [vers.Minor, parse_EncInfoAgl(blob, vers)]; + } + throw new Error("ECMA-376 Encrypted file unrecognized Version: " + vers.Minor); + } + + /* [MS-OFFCRYPTO] 2.3.4.5 EncryptionInfo Stream (Standard Encryption) */ + function parse_EncInfoStd(blob) { + var flags = blob.read_shift(4); + if((flags & 0x3F) != 0x24) throw new Error("EncryptionInfo mismatch"); + var sz = blob.read_shift(4); + //var tgt = blob.l + sz; + var hdr = parse_EncryptionHeader(blob, sz); + var verifier = parse_EncryptionVerifier(blob, blob.length - blob.l); + return { t:"Std", h:hdr, v:verifier }; + } + /* [MS-OFFCRYPTO] 2.3.4.6 EncryptionInfo Stream (Extensible Encryption) */ + function parse_EncInfoExt() { throw new Error("File is password-protected: ECMA-376 Extensible"); } + /* [MS-OFFCRYPTO] 2.3.4.10 EncryptionInfo Stream (Agile Encryption) */ + function parse_EncInfoAgl(blob) { + var KeyData = ["saltSize","blockSize","keyBits","hashSize","cipherAlgorithm","cipherChaining","hashAlgorithm","saltValue"]; + blob.l+=4; + var xml = blob.read_shift(blob.length - blob.l, 'utf8'); + var o = {}; + xml.replace(tagregex, function xml_agile(x) { + var y = parsexmltag(x); + switch(strip_ns(y[0])) { + case '': break; + case '': case '': break; + + case '': break; + case ' 4 || vers.Major < 2) throw new Error('unrecognized major version code: ' + vers.Major); + o.Flags = blob.read_shift(4); length -= 4; + var sz = blob.read_shift(4); length -= 4; + o.EncryptionHeader = parse_EncryptionHeader(blob, sz); length -= sz; + o.EncryptionVerifier = parse_EncryptionVerifier(blob, length); + return o; + } + /* [MS-OFFCRYPTO] 2.3.6.1 RC4 Encryption Header */ + function parse_RC4Header(blob) { + var o = {}; + var vers = o.EncryptionVersionInfo = parse_CRYPTOVersion(blob, 4); + if(vers.Major != 1 || vers.Minor != 1) throw 'unrecognized version code ' + vers.Major + ' : ' + vers.Minor; + o.Salt = blob.read_shift(16); + o.EncryptedVerifier = blob.read_shift(16); + o.EncryptedVerifierHash = blob.read_shift(16); + return o; + } + + /* [MS-OFFCRYPTO] 2.3.7.1 Binary Document Password Verifier Derivation */ + function crypto_CreatePasswordVerifier_Method1(Password) { + var Verifier = 0x0000, PasswordArray; + var PasswordDecoded = _JS2ANSI(Password); + var len = PasswordDecoded.length + 1, i, PasswordByte; + var Intermediate1, Intermediate2, Intermediate3; + PasswordArray = new_raw_buf(len); + PasswordArray[0] = PasswordDecoded.length; + for(i = 1; i != len; ++i) PasswordArray[i] = PasswordDecoded[i-1]; + for(i = len-1; i >= 0; --i) { + PasswordByte = PasswordArray[i]; + Intermediate1 = ((Verifier & 0x4000) === 0x0000) ? 0 : 1; + Intermediate2 = (Verifier << 1) & 0x7FFF; + Intermediate3 = Intermediate1 | Intermediate2; + Verifier = Intermediate3 ^ PasswordByte; + } + return Verifier ^ 0xCE4B; + } + + /* [MS-OFFCRYPTO] 2.3.7.2 Binary Document XOR Array Initialization */ + var crypto_CreateXorArray_Method1 = (function() { + var PadArray = [0xBB, 0xFF, 0xFF, 0xBA, 0xFF, 0xFF, 0xB9, 0x80, 0x00, 0xBE, 0x0F, 0x00, 0xBF, 0x0F, 0x00]; + var InitialCode = [0xE1F0, 0x1D0F, 0xCC9C, 0x84C0, 0x110C, 0x0E10, 0xF1CE, 0x313E, 0x1872, 0xE139, 0xD40F, 0x84F9, 0x280C, 0xA96A, 0x4EC3]; + var XorMatrix = [0xAEFC, 0x4DD9, 0x9BB2, 0x2745, 0x4E8A, 0x9D14, 0x2A09, 0x7B61, 0xF6C2, 0xFDA5, 0xEB6B, 0xC6F7, 0x9DCF, 0x2BBF, 0x4563, 0x8AC6, 0x05AD, 0x0B5A, 0x16B4, 0x2D68, 0x5AD0, 0x0375, 0x06EA, 0x0DD4, 0x1BA8, 0x3750, 0x6EA0, 0xDD40, 0xD849, 0xA0B3, 0x5147, 0xA28E, 0x553D, 0xAA7A, 0x44D5, 0x6F45, 0xDE8A, 0xAD35, 0x4A4B, 0x9496, 0x390D, 0x721A, 0xEB23, 0xC667, 0x9CEF, 0x29FF, 0x53FE, 0xA7FC, 0x5FD9, 0x47D3, 0x8FA6, 0x0F6D, 0x1EDA, 0x3DB4, 0x7B68, 0xF6D0, 0xB861, 0x60E3, 0xC1C6, 0x93AD, 0x377B, 0x6EF6, 0xDDEC, 0x45A0, 0x8B40, 0x06A1, 0x0D42, 0x1A84, 0x3508, 0x6A10, 0xAA51, 0x4483, 0x8906, 0x022D, 0x045A, 0x08B4, 0x1168, 0x76B4, 0xED68, 0xCAF1, 0x85C3, 0x1BA7, 0x374E, 0x6E9C, 0x3730, 0x6E60, 0xDCC0, 0xA9A1, 0x4363, 0x86C6, 0x1DAD, 0x3331, 0x6662, 0xCCC4, 0x89A9, 0x0373, 0x06E6, 0x0DCC, 0x1021, 0x2042, 0x4084, 0x8108, 0x1231, 0x2462, 0x48C4]; + var Ror = function(Byte) { return ((Byte/2) | (Byte*128)) & 0xFF; }; + var XorRor = function(byte1, byte2) { return Ror(byte1 ^ byte2); }; + var CreateXorKey_Method1 = function(Password) { + var XorKey = InitialCode[Password.length - 1]; + var CurrentElement = 0x68; + for(var i = Password.length-1; i >= 0; --i) { + var Char = Password[i]; + for(var j = 0; j != 7; ++j) { + if(Char & 0x40) XorKey ^= XorMatrix[CurrentElement]; + Char *= 2; --CurrentElement; + } + } + return XorKey; + }; + return function(password) { + var Password = _JS2ANSI(password); + var XorKey = CreateXorKey_Method1(Password); + var Index = Password.length; + var ObfuscationArray = new_raw_buf(16); + for(var i = 0; i != 16; ++i) ObfuscationArray[i] = 0x00; + var Temp, PasswordLastChar, PadIndex; + if((Index & 1) === 1) { + Temp = XorKey >> 8; + ObfuscationArray[Index] = XorRor(PadArray[0], Temp); + --Index; + Temp = XorKey & 0xFF; + PasswordLastChar = Password[Password.length - 1]; + ObfuscationArray[Index] = XorRor(PasswordLastChar, Temp); + } + while(Index > 0) { + --Index; + Temp = XorKey >> 8; + ObfuscationArray[Index] = XorRor(Password[Index], Temp); + --Index; + Temp = XorKey & 0xFF; + ObfuscationArray[Index] = XorRor(Password[Index], Temp); + } + Index = 15; + PadIndex = 15 - Password.length; + while(PadIndex > 0) { + Temp = XorKey >> 8; + ObfuscationArray[Index] = XorRor(PadArray[PadIndex], Temp); + --Index; + --PadIndex; + Temp = XorKey & 0xFF; + ObfuscationArray[Index] = XorRor(Password[Index], Temp); + --Index; + --PadIndex; + } + return ObfuscationArray; + }; + })(); + + /* [MS-OFFCRYPTO] 2.3.7.3 Binary Document XOR Data Transformation Method 1 */ + var crypto_DecryptData_Method1 = function(password, Data, XorArrayIndex, XorArray, O) { + /* If XorArray is set, use it; if O is not set, make changes in-place */ + if(!O) O = Data; + if(!XorArray) XorArray = crypto_CreateXorArray_Method1(password); + var Index, Value; + for(Index = 0; Index != Data.length; ++Index) { + Value = Data[Index]; + Value ^= XorArray[XorArrayIndex]; + Value = ((Value>>5) | (Value<<3)) & 0xFF; + O[Index] = Value; + ++XorArrayIndex; + } + return [O, XorArrayIndex, XorArray]; + }; + + var crypto_MakeXorDecryptor = function(password) { + var XorArrayIndex = 0, XorArray = crypto_CreateXorArray_Method1(password); + return function(Data) { + var O = crypto_DecryptData_Method1("", Data, XorArrayIndex, XorArray); + XorArrayIndex = O[1]; + return O[0]; + }; + }; + + /* 2.5.343 */ + function parse_XORObfuscation(blob, length, opts, out) { + var o = ({ key: parseuint16(blob), verificationBytes: parseuint16(blob) }); + if(opts.password) o.verifier = crypto_CreatePasswordVerifier_Method1(opts.password); + out.valid = o.verificationBytes === o.verifier; + if(out.valid) out.insitu = crypto_MakeXorDecryptor(opts.password); + return o; + } + + /* 2.4.117 */ + function parse_FilePassHeader(blob, length, oo) { + var o = oo || {}; o.Info = blob.read_shift(2); blob.l -= 2; + if(o.Info === 1) o.Data = parse_RC4Header(blob, length); + else o.Data = parse_RC4CryptoHeader(blob, length); + return o; + } + function parse_FilePass(blob, length, opts) { + var o = ({ Type: opts.biff >= 8 ? blob.read_shift(2) : 0 }); /* wEncryptionType */ + if(o.Type) parse_FilePassHeader(blob, length-2, o); + else parse_XORObfuscation(blob, opts.biff >= 8 ? length : length - 2, opts, o); + return o; + } + + + var RTF = (function() { + function rtf_to_sheet(d, opts) { + switch(opts.type) { + case 'base64': return rtf_to_sheet_str(Base64.decode(d), opts); + case 'binary': return rtf_to_sheet_str(d, opts); + case 'buffer': return rtf_to_sheet_str(d.toString('binary'), opts); + case 'array': return rtf_to_sheet_str(cc2str(d), opts); + } + throw new Error("Unrecognized type " + opts.type); + } + + function rtf_to_sheet_str(str, opts) { + var o = opts || {}; + var ws = o.dense ? ([]) : ({}); + var range = ({s: {c:0, r:0}, e: {c:0, r:0}}); + + // TODO: parse + if(!str.match(/\\trowd/)) throw new Error("RTF missing table"); + + ws['!ref'] = encode_range(range); + return ws; + } + + function rtf_to_workbook(d, opts) { return sheet_to_workbook(rtf_to_sheet(d, opts), opts); } + + /* TODO: this is a stub */ + function sheet_to_rtf(ws) { + var o = ["{\\rtf1\\ansi"]; + var r = safe_decode_range(ws['!ref']), cell; + var dense = Array.isArray(ws); + for(var R = r.s.r; R <= r.e.r; ++R) { + o.push("\\trowd\\trautofit1"); + for(var C = r.s.c; C <= r.e.c; ++C) o.push("\\cellx" + (C+1)); + o.push("\\pard\\intbl"); + for(C = r.s.c; C <= r.e.c; ++C) { + var coord = encode_cell({r:R,c:C}); + cell = dense ? (ws[R]||[])[C]: ws[coord]; + if(!cell || cell.v == null && (!cell.f || cell.F)) continue; + o.push(" " + (cell.w || (format_cell(cell), cell.w))); + o.push("\\cell"); + } + o.push("\\pard\\intbl\\row"); + } + return o.join("") + "}"; + } + + return { + to_workbook: rtf_to_workbook, + to_sheet: rtf_to_sheet, + from_sheet: sheet_to_rtf + }; + })(); + function hex2RGB(h) { + var o = h.slice(h[0]==="#"?1:0).slice(0,6); + return [parseInt(o.slice(0,2),16),parseInt(o.slice(2,4),16),parseInt(o.slice(4,6),16)]; + } + function rgb2Hex(rgb) { + for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]); + return o.toString(16).toUpperCase().slice(1); + } + + function rgb2HSL(rgb) { + var R = rgb[0]/255, G = rgb[1]/255, B=rgb[2]/255; + var M = Math.max(R, G, B), m = Math.min(R, G, B), C = M - m; + if(C === 0) return [0, 0, R]; + + var H6 = 0, S = 0, L2 = (M + m); + S = C / (L2 > 1 ? 2 - L2 : L2); + switch(M){ + case R: H6 = ((G - B) / C + 6)%6; break; + case G: H6 = ((B - R) / C + 2); break; + case B: H6 = ((R - G) / C + 4); break; + } + return [H6 / 6, S, L2 / 2]; + } + + function hsl2RGB(hsl){ + var H = hsl[0], S = hsl[1], L = hsl[2]; + var C = S * 2 * (L < 0.5 ? L : 1 - L), m = L - C/2; + var rgb = [m,m,m], h6 = 6*H; + + var X; + if(S !== 0) switch(h6|0) { + case 0: case 6: X = C * h6; rgb[0] += C; rgb[1] += X; break; + case 1: X = C * (2 - h6); rgb[0] += X; rgb[1] += C; break; + case 2: X = C * (h6 - 2); rgb[1] += C; rgb[2] += X; break; + case 3: X = C * (4 - h6); rgb[1] += X; rgb[2] += C; break; + case 4: X = C * (h6 - 4); rgb[2] += C; rgb[0] += X; break; + case 5: X = C * (6 - h6); rgb[2] += X; rgb[0] += C; break; + } + for(var i = 0; i != 3; ++i) rgb[i] = Math.round(rgb[i]*255); + return rgb; + } + + /* 18.8.3 bgColor tint algorithm */ + function rgb_tint(hex, tint) { + if(tint === 0) return hex; + var hsl = rgb2HSL(hex2RGB(hex)); + if (tint < 0) hsl[2] = hsl[2] * (1 + tint); + else hsl[2] = 1 - (1 - hsl[2]) * (1 - tint); + return rgb2Hex(hsl2RGB(hsl)); + } + + /* 18.3.1.13 width calculations */ + /* [MS-OI29500] 2.1.595 Column Width & Formatting */ + var DEF_MDW = 6, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW; + function width2px(width) { return Math.floor(( width + (Math.round(128/MDW))/256 )* MDW ); } + function px2char(px) { return (Math.floor((px - 5)/MDW * 100 + 0.5))/100; } + function char2width(chr) { return (Math.round((chr * MDW + 5)/MDW*256))/256; } +//function px2char_(px) { return (((px - 5)/MDW * 100 + 0.5))/100; } +//function char2width_(chr) { return (((chr * MDW + 5)/MDW*256))/256; } + function cycle_width(collw) { return char2width(px2char(width2px(collw))); } + /* XLSX/XLSB/XLS specify width in units of MDW */ + function find_mdw_colw(collw) { + var delta = Math.abs(collw - cycle_width(collw)), _MDW = MDW; + if(delta > 0.005) for(MDW=MIN_MDW; MDW 0.5) guess--; + if(Math.abs(guess) < delta) { delta = Math.abs(guess); _MDW = MDW; } + } + MDW = _MDW; +}*/ + + function process_col(coll) { + if(coll.width) { + coll.wpx = width2px(coll.width); + coll.wch = px2char(coll.wpx); + coll.MDW = MDW; + } else if(coll.wpx) { + coll.wch = px2char(coll.wpx); + coll.width = char2width(coll.wch); + coll.MDW = MDW; + } else if(typeof coll.wch == 'number') { + coll.width = char2width(coll.wch); + coll.wpx = width2px(coll.width); + coll.MDW = MDW; + } + if(coll.customWidth) delete coll.customWidth; + } + + var DEF_PPI = 96, PPI = DEF_PPI; + function px2pt(px) { return px * 96 / PPI; } + function pt2px(pt) { return pt * PPI / 96; } + + /* [MS-EXSPXML3] 2.4.54 ST_enmPattern */ + var XLMLPatternTypeMap = { + "None": "none", + "Solid": "solid", + "Gray50": "mediumGray", + "Gray75": "darkGray", + "Gray25": "lightGray", + "HorzStripe": "darkHorizontal", + "VertStripe": "darkVertical", + "ReverseDiagStripe": "darkDown", + "DiagStripe": "darkUp", + "DiagCross": "darkGrid", + "ThickDiagCross": "darkTrellis", + "ThinHorzStripe": "lightHorizontal", + "ThinVertStripe": "lightVertical", + "ThinReverseDiagStripe": "lightDown", + "ThinHorzCross": "lightGrid" + }; + + /* 18.8.5 borders CT_Borders */ + function parse_borders(t, styles, themes, opts) { + styles.Borders = []; + var border = {}/*, sub_border = {}*/; + var pass = false; + t[0].match(tagregex).forEach(function(x) { + var y = parsexmltag(x); + switch(strip_ns(y[0])) { + case '': case '': break; + + /* 18.8.4 border CT_Border */ + case '': case '': + border = {}; + if (y.diagonalUp) { border.diagonalUp = y.diagonalUp; } + if (y.diagonalDown) { border.diagonalDown = y.diagonalDown; } + styles.Borders.push(border); + break; + case '': break; + + /* note: not in spec, appears to be CT_BorderPr */ + case '': break; + case '': break; + case '': break; + + /* note: not in spec, appears to be CT_BorderPr */ + case '': break; + case '': break; + case '': break; + + /* 18.8.43 top CT_BorderPr */ + case '': break; + case '': break; + case '': break; + + /* 18.8.6 bottom CT_BorderPr */ + case '': break; + case '': break; + case '': break; + + /* 18.8.13 diagonal CT_BorderPr */ + case '': case '': break; + case '': break; + + /* 18.8.25 horizontal CT_BorderPr */ + case '': case '': break; + case '': break; + + /* 18.8.44 vertical CT_BorderPr */ + case '': case '': break; + case '': break; + + /* 18.8.37 start CT_BorderPr */ + case '': case '': break; + case '': break; + + /* 18.8.16 end CT_BorderPr */ + case '': case '': break; + case '': break; + + /* 18.8.? color CT_Color */ + case '': break; + case '': case '': break; + + /* 18.2.10 extLst CT_ExtensionList ? */ + case '': case '': break; + case '': pass = false; break; + default: if(opts && opts.WTF) { + if(!pass) throw new Error('unrecognized ' + y[0] + ' in borders'); + } + } + }); + } + + /* 18.8.21 fills CT_Fills */ + function parse_fills(t, styles, themes, opts) { + styles.Fills = []; + var fill = {}; + var pass = false; + t[0].match(tagregex).forEach(function(x) { + var y = parsexmltag(x); + switch(strip_ns(y[0])) { + case '': case '': break; + + /* 18.8.20 fill CT_Fill */ + case '': case '': + fill = {}; styles.Fills.push(fill); break; + case '': break; + + /* 18.8.24 gradientFill CT_GradientFill */ + case '': break; + case '': styles.Fills.push(fill); fill = {}; break; + + /* 18.8.32 patternFill CT_PatternFill */ + case '': + if(y.patternType) fill.patternType = y.patternType; + break; + case '': case '': break; + + /* 18.8.3 bgColor CT_Color */ + case '': case '': break; + + /* 18.8.19 fgColor CT_Color */ + case '': case '': break; + + /* 18.8.38 stop CT_GradientStop */ + case '': break; + case '': break; + + /* 18.8.? color CT_Color */ + case '': break; + case '': break; + + /* 18.2.10 extLst CT_ExtensionList ? */ + case '': case '': break; + case '': pass = false; break; + default: if(opts && opts.WTF) { + if(!pass) throw new Error('unrecognized ' + y[0] + ' in fills'); + } + } + }); + } + + /* 18.8.23 fonts CT_Fonts */ + function parse_fonts(t, styles, themes, opts) { + styles.Fonts = []; + var font = {}; + var pass = false; + t[0].match(tagregex).forEach(function(x) { + var y = parsexmltag(x); + switch(strip_ns(y[0])) { + case '': case '': break; + + /* 18.8.22 font CT_Font */ + case '': break; + case '': case '': + styles.Fonts.push(font); + font = {}; + break; + + /* 18.8.29 name CT_FontName */ + case '': case '': break; + + /* 18.8.2 b CT_BooleanProperty */ + case '': font.bold = 1; break; + + /* 18.8.26 i CT_BooleanProperty */ + case '': font.italic = 1; break; + + /* 18.4.13 u CT_UnderlineProperty */ + case '': font.underline = 1; break; + + /* 18.4.10 strike CT_BooleanProperty */ + case '': font.strike = 1; break; + + /* 18.4.2 outline CT_BooleanProperty */ + case '': font.outline = 1; break; + + /* 18.8.36 shadow CT_BooleanProperty */ + case '': font.shadow = 1; break; + + /* 18.8.12 condense CT_BooleanProperty */ + case '': font.condense = 1; break; + + /* 18.8.17 extend CT_BooleanProperty */ + case '': font.extend = 1; break; + + /* 18.4.11 sz CT_FontSize */ + case '': case '': break; + + /* 18.4.14 vertAlign CT_VerticalAlignFontProperty */ + case '': case '': break; + + /* 18.8.18 family CT_FontFamily */ + case '': case '': break; + + /* 18.8.35 scheme CT_FontScheme */ + case '': case '': break; + + /* 18.4.1 charset CT_IntProperty */ + case '': case '': break; + + /* 18.2.10 extLst CT_ExtensionList ? */ + case '': case '': break; + case '': pass = false; break; + default: if(opts && opts.WTF) { + if(!pass) throw new Error('unrecognized ' + y[0] + ' in fonts'); + } + } + }); + } + + /* 18.8.31 numFmts CT_NumFmts */ + function parse_numFmts(t, styles, opts) { + styles.NumberFmt = []; + var k/*Array*/ = (keys(SSF._table)); + for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]]; + var m = t[0].match(tagregex); + if(!m) return; + for(i=0; i < m.length; ++i) { + var y = parsexmltag(m[i]); + switch(strip_ns(y[0])) { + case '': case '': case '': break; + case '0) { + if(j > 0x188) { + for(j = 0x188; j > 0x3c; --j) if(styles.NumberFmt[j] == null) break; + styles.NumberFmt[j] = f; + } + SSF.load(f,j); + } + } break; + case '': break; + default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in numFmts'); + } + } + } + + function write_numFmts(NF) { + var o = [""]; + [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) { + for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) o[o.length] = (writextag('numFmt',null,{numFmtId:i,formatCode:escapexml(NF[i])})); + }); + if(o.length === 1) return ""; + o[o.length] = (""); + o[0] = writextag('numFmts', null, { count:o.length-2 }).replace("/>", ">"); + return o.join(""); + } + + /* 18.8.10 cellXfs CT_CellXfs */ + var cellXF_uint = [ "numFmtId", "fillId", "fontId", "borderId", "xfId" ]; + var cellXF_bool = [ "applyAlignment", "applyBorder", "applyFill", "applyFont", "applyNumberFormat", "applyProtection", "pivotButton", "quotePrefix" ]; + function parse_cellXfs(t, styles, opts) { + styles.CellXf = []; + var xf; + var pass = false; + t[0].match(tagregex).forEach(function(x) { + var y = parsexmltag(x), i = 0; + switch(strip_ns(y[0])) { + case '': case '': case '': break; + + /* 18.8.45 xf CT_Xf */ + case '': + xf = y; + delete xf[0]; + for(i = 0; i < cellXF_uint.length; ++i) if(xf[cellXF_uint[i]]) + xf[cellXF_uint[i]] = parseInt(xf[cellXF_uint[i]], 10); + for(i = 0; i < cellXF_bool.length; ++i) if(xf[cellXF_bool[i]]) + xf[cellXF_bool[i]] = parsexmlbool(xf[cellXF_bool[i]]); + if(xf.numFmtId > 0x188) { + for(i = 0x188; i > 0x3c; --i) if(styles.NumberFmt[xf.numFmtId] == styles.NumberFmt[i]) { xf.numFmtId = i; break; } + } + styles.CellXf.push(xf); break; + case '': break; + + /* 18.8.1 alignment CT_CellAlignment */ + case '': + var alignment = {}; + if(y.vertical) alignment.vertical = y.vertical; + if(y.horizontal) alignment.horizontal = y.horizontal; + if(y.textRotation != null) alignment.textRotation = y.textRotation; + if(y.indent) alignment.indent = y.indent; + if(y.wrapText) alignment.wrapText = y.wrapText; + xf.alignment = alignment; + break; + case '': break; + + /* 18.8.33 protection CT_CellProtection */ + case '': case '': break; + + /* 18.2.10 extLst CT_ExtensionList ? */ + case '': case '': break; + case '': pass = false; break; + default: if(opts && opts.WTF) { + if(!pass) throw new Error('unrecognized ' + y[0] + ' in cellXfs'); + } + } + }); + } + + function write_cellXfs(cellXfs) { + var o = []; + o[o.length] = (writextag('cellXfs',null)); + cellXfs.forEach(function(c) { o[o.length] = (writextag('xf', null, c)); }); + o[o.length] = (""); + if(o.length === 2) return ""; + o[0] = writextag('cellXfs',null, {count:o.length-2}).replace("/>",">"); + return o.join(""); + } + + /* 18.8 Styles CT_Stylesheet*/ + var parse_sty_xml= (function make_pstyx() { + var numFmtRegex = /<(?:\w+:)?numFmts([^>]*)>[\S\s]*?<\/(?:\w+:)?numFmts>/; + var cellXfRegex = /<(?:\w+:)?cellXfs([^>]*)>[\S\s]*?<\/(?:\w+:)?cellXfs>/; + var fillsRegex = /<(?:\w+:)?fills([^>]*)>[\S\s]*?<\/(?:\w+:)?fills>/; + var fontsRegex = /<(?:\w+:)?fonts([^>]*)>[\S\s]*?<\/(?:\w+:)?fonts>/; + var bordersRegex = /<(?:\w+:)?borders([^>]*)>[\S\s]*?<\/(?:\w+:)?borders>/; + + return function parse_sty_xml(data, themes, opts) { + var styles = {}; + if(!data) return styles; + data = data.replace(//mg,"").replace(//gm,""); + /* 18.8.39 styleSheet CT_Stylesheet */ + var t; + + /* 18.8.31 numFmts CT_NumFmts ? */ + if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts); + + /* 18.8.23 fonts CT_Fonts ? */ + if((t=data.match(fontsRegex))) parse_fonts(t, styles, themes, opts); + + /* 18.8.21 fills CT_Fills ? */ + if((t=data.match(fillsRegex))) parse_fills(t, styles, themes, opts); + + /* 18.8.5 borders CT_Borders ? */ + if((t=data.match(bordersRegex))) parse_borders(t, styles, themes, opts); + + /* 18.8.9 cellStyleXfs CT_CellStyleXfs ? */ + + /* 18.8.10 cellXfs CT_CellXfs ? */ + if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts); + + /* 18.8.8 cellStyles CT_CellStyles ? */ + /* 18.8.15 dxfs CT_Dxfs ? */ + /* 18.8.42 tableStyles CT_TableStyles ? */ + /* 18.8.11 colors CT_Colors ? */ + /* 18.2.10 extLst CT_ExtensionList ? */ + + return styles; + }; + })(); + + var STYLES_XML_ROOT = writextag('styleSheet', null, { + 'xmlns': XMLNS.main[0], + 'xmlns:vt': XMLNS.vt + }); + + RELS.STY = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"; + + function write_sty_xml(wb, opts) { + if (typeof style_builder != 'undefined' && typeof 'require' != 'undefined') { + return style_builder.toXml(); + } + var o = [XML_HEADER, STYLES_XML_ROOT], w; + if(wb.SSF && (w = write_numFmts(wb.SSF)) != null) o[o.length] = w; + o[o.length] = (''); + o[o.length] = (''); + o[o.length] = (''); + o[o.length] = (''); + if((w = write_cellXfs(opts.cellXfs))) o[o.length] = (w); + o[o.length] = (''); + o[o.length] = (''); + o[o.length] = (''); + + if(o.length>2){ o[o.length] = (''); o[1]=o[1].replace("/>",">"); } + return o.join(""); + } + /* [MS-XLSB] 2.4.657 BrtFmt */ + function parse_BrtFmt(data, length) { + var numFmtId = data.read_shift(2); + var stFmtCode = parse_XLWideString(data,length-2); + return [numFmtId, stFmtCode]; + } + function write_BrtFmt(i, f, o) { + if(!o) o = new_buf(6 + 4 * f.length); + o.write_shift(2, i); + write_XLWideString(f, o); + var out = (o.length > o.l) ? o.slice(0, o.l) : o; + if(o.l == null) o.l = o.length; + return out; + } + + /* [MS-XLSB] 2.4.659 BrtFont TODO */ + function parse_BrtFont(data, length, opts) { + var out = ({}); + + out.sz = data.read_shift(2) / 20; + + var grbit = parse_FontFlags(data, 2, opts); + if(grbit.fCondense) out.condense = 1; + if(grbit.fExtend) out.extend = 1; + if(grbit.fShadow) out.shadow = 1; + if(grbit.fOutline) out.outline = 1; + if(grbit.fStrikeout) out.strike = 1; + if(grbit.fItalic) out.italic = 1; + + var bls = data.read_shift(2); + if(bls === 0x02BC) out.bold = 1; + + switch(data.read_shift(2)) { + /* case 0: out.vertAlign = "baseline"; break; */ + case 1: out.vertAlign = "superscript"; break; + case 2: out.vertAlign = "subscript"; break; + } + + var underline = data.read_shift(1); + if(underline != 0) out.underline = underline; + + var family = data.read_shift(1); + if(family > 0) out.family = family; + + var bCharSet = data.read_shift(1); + if(bCharSet > 0) out.charset = bCharSet; + + data.l++; + out.color = parse_BrtColor(data, 8); + + switch(data.read_shift(1)) { + /* case 0: out.scheme = "none": break; */ + case 1: out.scheme = "major"; break; + case 2: out.scheme = "minor"; break; + } + + out.name = parse_XLWideString(data, length - 21); + + return out; + } + function write_BrtFont(font, o) { + if(!o) o = new_buf(25+4*32); + o.write_shift(2, font.sz * 20); + write_FontFlags(font, o); + o.write_shift(2, font.bold ? 0x02BC : 0x0190); + var sss = 0; + if(font.vertAlign == "superscript") sss = 1; + else if(font.vertAlign == "subscript") sss = 2; + o.write_shift(2, sss); + o.write_shift(1, font.underline || 0); + o.write_shift(1, font.family || 0); + o.write_shift(1, font.charset || 0); + o.write_shift(1, 0); + write_BrtColor(font.color, o); + var scheme = 0; + if(font.scheme == "major") scheme = 1; + if(font.scheme == "minor") scheme = 2; + o.write_shift(1, scheme); + write_XLWideString(font.name, o); + return o.length > o.l ? o.slice(0, o.l) : o; + } + + /* [MS-XLSB] 2.4.650 BrtFill */ + var XLSBFillPTNames = [ + "none", + "solid", + "mediumGray", + "darkGray", + "lightGray", + "darkHorizontal", + "darkVertical", + "darkDown", + "darkUp", + "darkGrid", + "darkTrellis", + "lightHorizontal", + "lightVertical", + "lightDown", + "lightUp", + "lightGrid", + "lightTrellis", + "gray125", + "gray0625" + ]; + var rev_XLSBFillPTNames = (evert(XLSBFillPTNames)); + /* TODO: gradient fill representation */ + var parse_BrtFill = parsenoop; + function write_BrtFill(fill, o) { + if(!o) o = new_buf(4*3 + 8*7 + 16*1); + var fls = rev_XLSBFillPTNames[fill.patternType]; + if(fls == null) fls = 0x28; + o.write_shift(4, fls); + var j = 0; + if(fls != 0x28) { + /* TODO: custom FG Color */ + write_BrtColor({auto:1}, o); + /* TODO: custom BG Color */ + write_BrtColor({auto:1}, o); + + for(; j < 12; ++j) o.write_shift(4, 0); + } else { + for(; j < 4; ++j) o.write_shift(4, 0); + + for(; j < 12; ++j) o.write_shift(4, 0); /* TODO */ + /* iGradientType */ + /* xnumDegree */ + /* xnumFillToLeft */ + /* xnumFillToRight */ + /* xnumFillToTop */ + /* xnumFillToBottom */ + /* cNumStop */ + /* xfillGradientStop */ + } + return o.length > o.l ? o.slice(0, o.l) : o; + } + + /* [MS-XLSB] 2.4.824 BrtXF */ + function parse_BrtXF(data, length) { + var tgt = data.l + length; + var ixfeParent = data.read_shift(2); + var ifmt = data.read_shift(2); + data.l = tgt; + return {ixfe:ixfeParent, numFmtId:ifmt }; + } + function write_BrtXF(data, ixfeP, o) { + if(!o) o = new_buf(16); + o.write_shift(2, ixfeP||0); + o.write_shift(2, data.numFmtId||0); + o.write_shift(2, 0); /* iFont */ + o.write_shift(2, 0); /* iFill */ + o.write_shift(2, 0); /* ixBorder */ + o.write_shift(1, 0); /* trot */ + o.write_shift(1, 0); /* indent */ + o.write_shift(1, 0); /* flags */ + o.write_shift(1, 0); /* flags */ + o.write_shift(1, 0); /* xfGrbitAtr */ + o.write_shift(1, 0); + return o; + } + + /* [MS-XLSB] 2.5.4 Blxf TODO */ + function write_Blxf(data, o) { + if(!o) o = new_buf(10); + o.write_shift(1, 0); /* dg */ + o.write_shift(1, 0); + o.write_shift(4, 0); /* color */ + o.write_shift(4, 0); /* color */ + return o; + } + /* [MS-XLSB] 2.4.302 BrtBorder TODO */ + var parse_BrtBorder = parsenoop; + function write_BrtBorder(border, o) { + if(!o) o = new_buf(51); + o.write_shift(1, 0); /* diagonal */ + write_Blxf(null, o); /* top */ + write_Blxf(null, o); /* bottom */ + write_Blxf(null, o); /* left */ + write_Blxf(null, o); /* right */ + write_Blxf(null, o); /* diag */ + return o.length > o.l ? o.slice(0, o.l) : o; + } + + /* [MS-XLSB] 2.4.763 BrtStyle TODO */ + function write_BrtStyle(style, o) { + if(!o) o = new_buf(12+4*10); + o.write_shift(4, style.xfId); + o.write_shift(2, 1); + o.write_shift(1, +style.builtinId); + o.write_shift(1, 0); /* iLevel */ + write_XLNullableWideString(style.name || "", o); + return o.length > o.l ? o.slice(0, o.l) : o; + } + + /* [MS-XLSB] 2.4.272 BrtBeginTableStyles */ + function write_BrtBeginTableStyles(cnt, defTableStyle, defPivotStyle) { + var o = new_buf(4+256*2*4); + o.write_shift(4, cnt); + write_XLNullableWideString(defTableStyle, o); + write_XLNullableWideString(defPivotStyle, o); + return o.length > o.l ? o.slice(0, o.l) : o; + } + + /* [MS-XLSB] 2.1.7.50 Styles */ + function parse_sty_bin(data, themes, opts) { + var styles = {}; + styles.NumberFmt = ([]); + for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y]; + + styles.CellXf = []; + styles.Fonts = []; + var state = []; + var pass = false; + recordhopper(data, function hopper_sty(val, R_n, RT) { + switch(RT) { + case 0x002C: /* 'BrtFmt' */ + styles.NumberFmt[val[0]] = val[1]; SSF.load(val[1], val[0]); + break; + case 0x002B: /* 'BrtFont' */ + styles.Fonts.push(val); + if(val.color.theme != null && themes && themes.themeElements && themes.themeElements.clrScheme) { + val.color.rgb = rgb_tint(themes.themeElements.clrScheme[val.color.theme].rgb, val.color.tint || 0); + } + break; + case 0x0401: /* 'BrtKnownFonts' */ break; + case 0x002D: /* 'BrtFill' */ break; + case 0x002E: /* 'BrtBorder' */ break; + case 0x002F: /* 'BrtXF' */ + if(state[state.length - 1] == "BrtBeginCellXFs") { + styles.CellXf.push(val); + } + break; + case 0x0030: /* 'BrtStyle' */ + case 0x01FB: /* 'BrtDXF' */ + case 0x023C: /* 'BrtMRUColor' */ + case 0x01DB: /* 'BrtIndexedColor': */ + break; + + case 0x0493: /* 'BrtDXF14' */ + case 0x0836: /* 'BrtDXF15' */ + case 0x046A: /* 'BrtSlicerStyleElement' */ + case 0x0200: /* 'BrtTableStyleElement' */ + case 0x082F: /* 'BrtTimelineStyleElement' */ + case 0x0C00: /* 'BrtUid' */ + break; + + case 0x0023: /* 'BrtFRTBegin' */ + pass = true; break; + case 0x0024: /* 'BrtFRTEnd' */ + pass = false; break; + case 0x0025: /* 'BrtACBegin' */ + state.push(R_n); break; + case 0x0026: /* 'BrtACEnd' */ + state.pop(); break; + + default: + if((R_n||"").indexOf("Begin") > 0) state.push(R_n); + else if((R_n||"").indexOf("End") > 0) state.pop(); + else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n); + } + }); + return styles; + } + + function write_FMTS_bin(ba, NF) { + if(!NF) return; + var cnt = 0; + [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) { + for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) ++cnt; + }); + + if(cnt == 0) return; + write_record(ba, "BrtBeginFmts", write_UInt32LE(cnt)); + [[5,8],[23,26],[41,44],[/*63*/50,/*66],[164,*/392]].forEach(function(r) { + for(var i = r[0]; i <= r[1]; ++i) if(NF[i] != null) write_record(ba, "BrtFmt", write_BrtFmt(i, NF[i])); + }); + write_record(ba, "BrtEndFmts"); + } + + function write_FONTS_bin(ba) { + var cnt = 1; + + if(cnt == 0) return; + write_record(ba, "BrtBeginFonts", write_UInt32LE(cnt)); + write_record(ba, "BrtFont", write_BrtFont({ + sz:12, + color: {theme:1}, + name: "Calibri", + family: 2, + scheme: "minor" + })); + /* 1*65491BrtFont [ACFONTS] */ + write_record(ba, "BrtEndFonts"); + } + + function write_FILLS_bin(ba) { + var cnt = 2; + + if(cnt == 0) return; + write_record(ba, "BrtBeginFills", write_UInt32LE(cnt)); + write_record(ba, "BrtFill", write_BrtFill({patternType:"none"})); + write_record(ba, "BrtFill", write_BrtFill({patternType:"gray125"})); + /* 1*65431BrtFill */ + write_record(ba, "BrtEndFills"); + } + + function write_BORDERS_bin(ba) { + var cnt = 1; + + if(cnt == 0) return; + write_record(ba, "BrtBeginBorders", write_UInt32LE(cnt)); + write_record(ba, "BrtBorder", write_BrtBorder({})); + /* 1*65430BrtBorder */ + write_record(ba, "BrtEndBorders"); + } + + function write_CELLSTYLEXFS_bin(ba) { + var cnt = 1; + write_record(ba, "BrtBeginCellStyleXFs", write_UInt32LE(cnt)); + write_record(ba, "BrtXF", write_BrtXF({ + numFmtId:0, + fontId:0, + fillId:0, + borderId:0 + }, 0xFFFF)); + /* 1*65430(BrtXF *FRT) */ + write_record(ba, "BrtEndCellStyleXFs"); + } + + function write_CELLXFS_bin(ba, data) { + write_record(ba, "BrtBeginCellXFs", write_UInt32LE(data.length)); + data.forEach(function(c) { write_record(ba, "BrtXF", write_BrtXF(c,0)); }); + /* 1*65430(BrtXF *FRT) */ + write_record(ba, "BrtEndCellXFs"); + } + + function write_STYLES_bin(ba) { + var cnt = 1; + + write_record(ba, "BrtBeginStyles", write_UInt32LE(cnt)); + write_record(ba, "BrtStyle", write_BrtStyle({ + xfId:0, + builtinId:0, + name:"Normal" + })); + /* 1*65430(BrtStyle *FRT) */ + write_record(ba, "BrtEndStyles"); + } + + function write_DXFS_bin(ba) { + var cnt = 0; + + write_record(ba, "BrtBeginDXFs", write_UInt32LE(cnt)); + /* *2147483647(BrtDXF *FRT) */ + write_record(ba, "BrtEndDXFs"); + } + + function write_TABLESTYLES_bin(ba) { + var cnt = 0; + + write_record(ba, "BrtBeginTableStyles", write_BrtBeginTableStyles(cnt, "TableStyleMedium9", "PivotStyleMedium4")); + /* *TABLESTYLE */ + write_record(ba, "BrtEndTableStyles"); + } + + function write_COLORPALETTE_bin() { + return; + /* BrtBeginColorPalette [INDEXEDCOLORS] [MRUCOLORS] BrtEndColorPalette */ + } + + /* [MS-XLSB] 2.1.7.50 Styles */ + function write_sty_bin(wb, opts) { + var ba = buf_array(); + write_record(ba, "BrtBeginStyleSheet"); + write_FMTS_bin(ba, wb.SSF); + write_FONTS_bin(ba, wb); + write_FILLS_bin(ba, wb); + write_BORDERS_bin(ba, wb); + write_CELLSTYLEXFS_bin(ba, wb); + write_CELLXFS_bin(ba, opts.cellXfs); + write_STYLES_bin(ba, wb); + write_DXFS_bin(ba, wb); + write_TABLESTYLES_bin(ba, wb); + write_COLORPALETTE_bin(ba, wb); + /* FRTSTYLESHEET*/ + write_record(ba, "BrtEndStyleSheet"); + return ba.end(); + } + RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"; + + /* 20.1.6.2 clrScheme CT_ColorScheme */ + function parse_clrScheme(t, themes, opts) { + themes.themeElements.clrScheme = []; + var color = {}; + (t[0].match(tagregex)||[]).forEach(function(x) { + var y = parsexmltag(x); + switch(y[0]) { + /* 20.1.6.2 clrScheme (Color Scheme) CT_ColorScheme */ + case '': break; + + /* 20.1.2.3.32 srgbClr CT_SRgbColor */ + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + case '': case '': + if (y[0].charAt(1) === '/') { + themes.themeElements.clrScheme.push(color); + color = {}; + } else { + color.name = y[0].slice(3, y[0].length - 1); + } + break; + + default: if(opts && opts.WTF) throw new Error('Unrecognized ' + y[0] + ' in clrScheme'); + } + }); + } + + /* 20.1.4.1.18 fontScheme CT_FontScheme */ + function parse_fontScheme() { } + + /* 20.1.4.1.15 fmtScheme CT_StyleMatrix */ + function parse_fmtScheme() { } + + var clrsregex = /]*)>[\s\S]*<\/a:clrScheme>/; + var fntsregex = /]*)>[\s\S]*<\/a:fontScheme>/; + var fmtsregex = /]*)>[\s\S]*<\/a:fmtScheme>/; + + /* 20.1.6.10 themeElements CT_BaseStyles */ + function parse_themeElements(data, themes, opts) { + themes.themeElements = {}; + + var t; + + [ + /* clrScheme CT_ColorScheme */ + ['clrScheme', clrsregex, parse_clrScheme], + /* fontScheme CT_FontScheme */ + ['fontScheme', fntsregex, parse_fontScheme], + /* fmtScheme CT_StyleMatrix */ + ['fmtScheme', fmtsregex, parse_fmtScheme] + ].forEach(function(m) { + if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements'); + m[2](t, themes, opts); + }); + } + + var themeltregex = /]*)>[\s\S]*<\/a:themeElements>/; + + /* 14.2.7 Theme Part */ + function parse_theme_xml(data, opts) { + /* 20.1.6.9 theme CT_OfficeStyleSheet */ + if(!data || data.length === 0) return parse_theme_xml(write_theme()); + + var t; + var themes = {}; + + /* themeElements CT_BaseStyles */ + if(!(t=data.match(themeltregex))) throw new Error('themeElements not found in theme'); + parse_themeElements(t[0], themes, opts); + + return themes; + } + + function write_theme(Themes, opts) { + if(opts && opts.themeXLSX) return opts.themeXLSX; + var o = [XML_HEADER]; + o[o.length] = ''; + o[o.length] = ''; + + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + o[o.length] = ''; + return o.join(""); + } + /* [MS-XLS] 2.4.326 TODO: payload is a zip file */ + function parse_Theme(blob, length, opts) { + var end = blob.l + length; + var dwThemeVersion = blob.read_shift(4); + if(dwThemeVersion === 124226) return; + if(!opts.cellStyles || !jszip) { blob.l = end; return; } + var data = blob.slice(blob.l); + blob.l = end; + var zip; try { zip = new jszip(data); } catch(e) { return; } + var themeXML = getzipstr(zip, "theme/theme/theme1.xml", true); + if(!themeXML) return; + return parse_theme_xml(themeXML, opts); + } + + /* 2.5.49 */ + function parse_ColorTheme(blob) { return blob.read_shift(4); } + + /* 2.5.155 */ + function parse_FullColorExt(blob) { + var o = {}; + o.xclrType = blob.read_shift(2); + o.nTintShade = blob.read_shift(2); + switch(o.xclrType) { + case 0: blob.l += 4; break; + case 1: o.xclrValue = parse_IcvXF(blob, 4); break; + case 2: o.xclrValue = parse_LongRGBA(blob, 4); break; + case 3: o.xclrValue = parse_ColorTheme(blob, 4); break; + case 4: blob.l += 4; break; + } + blob.l += 8; + return o; + } + + /* 2.5.164 TODO: read 7 bits*/ + function parse_IcvXF(blob, length) { + return parsenoop(blob, length); + } + + /* 2.5.280 */ + function parse_XFExtGradient(blob, length) { + return parsenoop(blob, length); + } + + /* [MS-XLS] 2.5.108 */ + function parse_ExtProp(blob) { + var extType = blob.read_shift(2); + var cb = blob.read_shift(2) - 4; + var o = [extType]; + switch(extType) { + case 0x04: case 0x05: case 0x07: case 0x08: + case 0x09: case 0x0A: case 0x0B: case 0x0D: + o[1] = parse_FullColorExt(blob, cb); break; + case 0x06: o[1] = parse_XFExtGradient(blob, cb); break; + case 0x0E: case 0x0F: o[1] = blob.read_shift(cb === 1 ? 1 : 2); break; + default: throw new Error("Unrecognized ExtProp type: " + extType + " " + cb); + } + return o; + } + + /* 2.4.355 */ + function parse_XFExt(blob, length) { + var end = blob.l + length; + blob.l += 2; + var ixfe = blob.read_shift(2); + blob.l += 2; + var cexts = blob.read_shift(2); + var ext = []; + while(cexts-- > 0) ext.push(parse_ExtProp(blob, end-blob.l)); + return {ixfe:ixfe, ext:ext}; + } + + /* xf is an XF, see parse_XFExt for xfext */ + function update_xfext(xf, xfext) { + xfext.forEach(function(xfe) { + switch(xfe[0]) { /* 2.5.108 extPropData */ + case 0x04: break; /* foreground color */ + case 0x05: break; /* background color */ + case 0x06: break; /* gradient fill */ + case 0x07: break; /* top cell border color */ + case 0x08: break; /* bottom cell border color */ + case 0x09: break; /* left cell border color */ + case 0x0a: break; /* right cell border color */ + case 0x0b: break; /* diagonal cell border color */ + case 0x0d: break; /* text color */ + case 0x0e: break; /* font scheme */ + case 0x0f: break; /* indentation level */ + } + }); + } + + /* 18.6 Calculation Chain */ + function parse_cc_xml(data) { + var d = []; + if(!data) return d; + var i = 1; + (data.match(tagregex)||[]).forEach(function(x) { + var y = parsexmltag(x); + switch(y[0]) { + case '': case '': break; + /* 18.6.1 c CT_CalcCell 1 */ + case ' 0){/* empty */} + else if((R_n||"").indexOf("End") > 0){/* empty */} + else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n); + } + }); + return out; + } + +//function write_cc_bin(data, opts) { } + /* 18.14 Supplementary Workbook Data */ + function parse_xlink_xml() { + //var opts = _opts || {}; + //if(opts.WTF) throw "XLSX External Link"; + } + + /* [MS-XLSB] 2.1.7.25 External Link */ + function parse_xlink_bin(data, name, _opts) { + if(!data) return data; + var opts = _opts || {}; + + var pass = false, end = false; + + recordhopper(data, function xlink_parse(val, R_n, RT) { + if(end) return; + switch(RT) { + case 0x0167: /* 'BrtSupTabs' */ + case 0x016B: /* 'BrtExternTableStart' */ + case 0x016C: /* 'BrtExternTableEnd' */ + case 0x016E: /* 'BrtExternRowHdr' */ + case 0x016F: /* 'BrtExternCellBlank' */ + case 0x0170: /* 'BrtExternCellReal' */ + case 0x0171: /* 'BrtExternCellBool' */ + case 0x0172: /* 'BrtExternCellError' */ + case 0x0173: /* 'BrtExternCellString' */ + case 0x01D8: /* 'BrtExternValueMeta' */ + case 0x0241: /* 'BrtSupNameStart' */ + case 0x0242: /* 'BrtSupNameValueStart' */ + case 0x0243: /* 'BrtSupNameValueEnd' */ + case 0x0244: /* 'BrtSupNameNum' */ + case 0x0245: /* 'BrtSupNameErr' */ + case 0x0246: /* 'BrtSupNameSt' */ + case 0x0247: /* 'BrtSupNameNil' */ + case 0x0248: /* 'BrtSupNameBool' */ + case 0x0249: /* 'BrtSupNameFmla' */ + case 0x024A: /* 'BrtSupNameBits' */ + case 0x024B: /* 'BrtSupNameEnd' */ + break; + + case 0x0023: /* 'BrtFRTBegin' */ + pass = true; break; + case 0x0024: /* 'BrtFRTEnd' */ + pass = false; break; + + default: + if((R_n||"").indexOf("Begin") > 0){/* empty */} + else if((R_n||"").indexOf("End") > 0){/* empty */} + else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT.toString(16) + " " + R_n); + } + }, opts); + } + RELS.IMG = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"; + RELS.DRAW = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing"; + /* 20.5 DrawingML - SpreadsheetML Drawing */ + function parse_drawing(data, rels) { + if(!data) return "??"; + /* + Chartsheet Drawing: + - 20.5.2.35 wsDr CT_Drawing + - 20.5.2.1 absoluteAnchor CT_AbsoluteAnchor + - 20.5.2.16 graphicFrame CT_GraphicalObjectFrame + - 20.1.2.2.16 graphic CT_GraphicalObject + - 20.1.2.2.17 graphicData CT_GraphicalObjectData + - chart reference + the actual type is based on the URI of the graphicData + TODO: handle embedded charts and other types of graphics + */ + var id = (data.match(/]*r:id="([^"]*)"/)||["",""])[1]; + + return rels['!id'][id].Target; + } + + /* L.5.5.2 SpreadsheetML Comments + VML Schema */ + var _shapeid = 1024; + function write_comments_vml(rId, comments) { + var csize = [21600, 21600]; + /* L.5.2.1.2 Path Attribute */ + var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(","); + var o = [ + writextag("xml", null, { 'xmlns:v': XLMLNS.v, 'xmlns:o': XLMLNS.o, 'xmlns:x': XLMLNS.x, 'xmlns:mv': XLMLNS.mv }).replace(/\/>/,">"), + writextag("o:shapelayout", writextag("o:idmap", null, {'v:ext':"edit", 'data':rId}), {'v:ext':"edit"}), + writextag("v:shapetype", [ + writextag("v:stroke", null, {joinstyle:"miter"}), + writextag("v:path", null, {gradientshapeok:"t", 'o:connecttype':"rect"}) + ].join(""), {id:"_x0000_t202", 'o:spt':202, coordsize:csize.join(","),path:bbox}) + ]; + while(_shapeid < rId * 1000) _shapeid += 1000; + + comments.forEach(function(x) { var c = decode_cell(x[0]); + o = o.concat([ + '', + writextag('v:fill', writextag("o:fill", null, {type:"gradientUnscaled", 'v:ext':"view"}), {'color2':"#BEFF82", 'angle':"-180", 'type':"gradient"}), + writextag("v:shadow", null, {on:"t", 'obscured':"t"}), + writextag("v:path", null, {'o:connecttype':"none"}), + '
                ', + '', + '', + '', + /* Part 4 19.4.2.3 Anchor (Anchor) */ + writetag('x:Anchor', [c.c, 0, c.r, 0, c.c+3, 100, c.r+5, 100].join(",")), + writetag('x:AutoFill', "False"), + writetag('x:Row', String(c.r)), + writetag('x:Column', String(c.c)), + x[1].hidden ? '' : '', + '', + '' + ]); }); + o.push(''); + return o.join(""); + } + + RELS.CMNT = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"; + + function parse_comments(zip, dirComments, sheets, sheetRels, opts) { + for(var i = 0; i != dirComments.length; ++i) { + var canonicalpath=dirComments[i]; + var comments=parse_cmnt(getzipdata(zip, canonicalpath.replace(/^\//,''), true), canonicalpath, opts); + if(!comments || !comments.length) continue; + // find the sheets targeted by these comments + var sheetNames = keys(sheets); + for(var j = 0; j != sheetNames.length; ++j) { + var sheetName = sheetNames[j]; + var rels = sheetRels[sheetName]; + if(rels) { + var rel = rels[canonicalpath]; + if(rel) insertCommentsIntoSheet(sheetName, sheets[sheetName], comments); + } + } + } + } + + function insertCommentsIntoSheet(sheetName, sheet, comments) { + var dense = Array.isArray(sheet); + var cell; + comments.forEach(function(comment) { + var r = decode_cell(comment.ref); + if(dense) { + if(!sheet[r.r]) sheet[r.r] = []; + cell = sheet[r.r][r.c]; + } else cell = sheet[comment.ref]; + if (!cell) { + cell = {}; + if(dense) sheet[r.r][r.c] = cell; + else sheet[comment.ref] = cell; + var range = safe_decode_range(sheet["!ref"]||"BDWGO1000001:A1"); + if(range.s.r > r.r) range.s.r = r.r; + if(range.e.r < r.r) range.e.r = r.r; + if(range.s.c > r.c) range.s.c = r.c; + if(range.e.c < r.c) range.e.c = r.c; + var encoded = encode_range(range); + if (encoded !== sheet["!ref"]) sheet["!ref"] = encoded; + } + + if (!cell.c) cell.c = []; + var o = ({a: comment.author, t: comment.t, r: comment.r}); + if(comment.h) o.h = comment.h; + cell.c.push(o); + }); + } + + /* 18.7 Comments */ + function parse_comments_xml(data, opts) { + /* 18.7.6 CT_Comments */ + if(data.match(/<(?:\w+:)?comments *\/>/)) return []; + var authors = []; + var commentList = []; + var authtag = data.match(/<(?:\w+:)?authors>([\s\S]*)<\/(?:\w+:)?authors>/); + if(authtag && authtag[1]) authtag[1].split(/<\/\w*:?author>/).forEach(function(x) { + if(x === "" || x.trim() === "") return; + var a = x.match(/<(?:\w+:)?author[^>]*>(.*)/); + if(a) authors.push(a[1]); + }); + var cmnttag = data.match(/<(?:\w+:)?commentList>([\s\S]*)<\/(?:\w+:)?commentList>/); + if(cmnttag && cmnttag[1]) cmnttag[1].split(/<\/\w*:?comment>/).forEach(function(x) { + if(x === "" || x.trim() === "") return; + var cm = x.match(/<(?:\w+:)?comment[^>]*>/); + if(!cm) return; + var y = parsexmltag(cm[0]); + var comment = ({ author: y.authorId && authors[y.authorId] || "sheetjsghost", ref: y.ref, guid: y.guid }); + var cell = decode_cell(y.ref); + if(opts.sheetRows && opts.sheetRows <= cell.r) return; + var textMatch = x.match(/<(?:\w+:)?text>([\s\S]*)<\/(?:\w+:)?text>/); + var rt = !!textMatch && !!textMatch[1] && parse_si(textMatch[1]) || {r:"",t:"",h:""}; + comment.r = rt.r; + if(rt.r == "") rt.t = rt.h = ""; + comment.t = rt.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n"); + if(opts.cellHTML) comment.h = rt.h; + commentList.push(comment); + }); + return commentList; + } + + var CMNT_XML_ROOT = writextag('comments', null, { 'xmlns': XMLNS.main[0] }); + function write_comments_xml(data) { + var o = [XML_HEADER, CMNT_XML_ROOT]; + + var iauthor = []; + o.push(""); + data.forEach(function(x) { x[1].forEach(function(w) { var a = escapexml(w.a); + if(iauthor.indexOf(a) > -1) return; + iauthor.push(a); + o.push("" + a + ""); + }); }); + o.push(""); + o.push(""); + data.forEach(function(d) { + d[1].forEach(function(c) { + /* 18.7.3 CT_Comment */ + o.push(''); + o.push(writetag("t", c.t == null ? "" : escapexml(c.t))); + o.push(''); + }); + }); + o.push(""); + if(o.length>2) { o[o.length] = (''); o[1]=o[1].replace("/>",">"); } + return o.join(""); + } + /* [MS-XLSB] 2.4.28 BrtBeginComment */ + function parse_BrtBeginComment(data) { + var out = {}; + out.iauthor = data.read_shift(4); + var rfx = parse_UncheckedRfX(data, 16); + out.rfx = rfx.s; + out.ref = encode_cell(rfx.s); + data.l += 16; /*var guid = parse_GUID(data); */ + return out; + } + function write_BrtBeginComment(data, o) { + if(o == null) o = new_buf(36); + o.write_shift(4, data[1].iauthor); + write_UncheckedRfX((data[0]), o); + o.write_shift(4, 0); + o.write_shift(4, 0); + o.write_shift(4, 0); + o.write_shift(4, 0); + return o; + } + + /* [MS-XLSB] 2.4.327 BrtCommentAuthor */ + var parse_BrtCommentAuthor = parse_XLWideString; + function write_BrtCommentAuthor(data) { return write_XLWideString(data.slice(0, 54)); } + + /* [MS-XLSB] 2.1.7.8 Comments */ + function parse_comments_bin(data, opts) { + var out = []; + var authors = []; + var c = {}; + var pass = false; + recordhopper(data, function hopper_cmnt(val, R_n, RT) { + switch(RT) { + case 0x0278: /* 'BrtCommentAuthor' */ + authors.push(val); break; + case 0x027B: /* 'BrtBeginComment' */ + c = val; break; + case 0x027D: /* 'BrtCommentText' */ + c.t = val.t; c.h = val.h; c.r = val.r; break; + case 0x027C: /* 'BrtEndComment' */ + c.author = authors[c.iauthor]; + delete c.iauthor; + if(opts.sheetRows && opts.sheetRows <= c.rfx.r) break; + if(!c.t) c.t = ""; + delete c.rfx; out.push(c); break; + + case 0x0C00: /* 'BrtUid' */ + break; + + case 0x0023: /* 'BrtFRTBegin' */ + pass = true; break; + case 0x0024: /* 'BrtFRTEnd' */ + pass = false; break; + case 0x0025: /* 'BrtACBegin' */ break; + case 0x0026: /* 'BrtACEnd' */ break; + + + default: + if((R_n||"").indexOf("Begin") > 0){/* empty */} + else if((R_n||"").indexOf("End") > 0){/* empty */} + else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n); + } + }); + return out; + } + + function write_comments_bin(data) { + var ba = buf_array(); + var iauthor = []; + write_record(ba, "BrtBeginComments"); + + write_record(ba, "BrtBeginCommentAuthors"); + data.forEach(function(comment) { + comment[1].forEach(function(c) { + if(iauthor.indexOf(c.a) > -1) return; + iauthor.push(c.a.slice(0,54)); + write_record(ba, "BrtCommentAuthor", write_BrtCommentAuthor(c.a)); + }); + }); + write_record(ba, "BrtEndCommentAuthors"); + + write_record(ba, "BrtBeginCommentList"); + data.forEach(function(comment) { + comment[1].forEach(function(c) { + c.iauthor = iauthor.indexOf(c.a); + var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])}; + write_record(ba, "BrtBeginComment", write_BrtBeginComment([range, c])); + if(c.t && c.t.length > 0) write_record(ba, "BrtCommentText", write_BrtCommentText(c)); + write_record(ba, "BrtEndComment"); + delete c.iauthor; + }); + }); + write_record(ba, "BrtEndCommentList"); + + write_record(ba, "BrtEndComments"); + return ba.end(); + } + var CT_VBA = "application/vnd.ms-office.vbaProject"; + function make_vba_xls(cfb) { + var newcfb = CFB.utils.cfb_new({root:"R"}); + cfb.FullPaths.forEach(function(p, i) { + if(p.slice(-1) === "/" || !p.match(/_VBA_PROJECT_CUR/)) return; + var newpath = p.replace(/^[^\/]*/,"R").replace(/\/_VBA_PROJECT_CUR\u0000*/, ""); + CFB.utils.cfb_add(newcfb, newpath, cfb.FileIndex[i].content); + }); + return CFB.write(newcfb); + } + + function fill_vba_xls(cfb, vba) { + vba.FullPaths.forEach(function(p, i) { + if(i == 0) return; + var newpath = p.replace(/[^\/]*[\/]/, "/_VBA_PROJECT_CUR/"); + if(newpath.slice(-1) !== "/") CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content); + }); + } + + var VBAFMTS = [ "xlsb", "xlsm", "xlam", "biff8", "xla" ]; + + RELS.DS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet"; + RELS.MS = "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet"; + + /* macro and dialog sheet stubs */ + function parse_ds_bin() { return {'!type':'dialog'}; } + function parse_ds_xml() { return {'!type':'dialog'}; } + function parse_ms_bin() { return {'!type':'macro'}; } + function parse_ms_xml() { return {'!type':'macro'}; } + /* TODO: it will be useful to parse the function str */ + var rc_to_a1 = (function(){ + var rcregex = /(^|[^A-Za-z])R(\[?)(-?\d+|)\]?C(\[?)(-?\d+|)\]?/g; + var rcbase = ({r:0,c:0}); + function rcfunc($$,$1,$2,$3,$4,$5) { + var R = $3.length>0?parseInt($3,10)|0:0, C = $5.length>0?parseInt($5,10)|0:0; + if(C<0 && $4.length === 0) C=0; + var cRel = false, rRel = false; + if($4.length > 0 || $5.length == 0) cRel = true; if(cRel) C += rcbase.c; else --C; + if($2.length > 0 || $3.length == 0) rRel = true; if(rRel) R += rcbase.r; else --R; + return $1 + (cRel ? "" : "$") + encode_col(C) + (rRel ? "" : "$") + encode_row(R); + } + return function rc_to_a1(fstr, base) { + rcbase = base; + return fstr.replace(rcregex, rcfunc); + }; + })(); + + var crefregex = /(^|[^._A-Z0-9])([$]?)([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])([$]?)([1-9]\d{0,5}|10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6])(?![_.\(A-Za-z0-9])/g; + var a1_to_rc =(function(){ + return function a1_to_rc(fstr, base) { + return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) { + var c = decode_col($3) - ($2 ? 0 : base.c); + var r = decode_row($5) - ($4 ? 0 : base.r); + var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1)); + var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1)); + return $1 + "R" + R + "C" + C; + }); + }; + })(); + + /* no defined name can collide with a valid cell address A1:XFD1048576 ... except LOG10! */ + function shift_formula_str(f, delta) { + return f.replace(crefregex, function($0, $1, $2, $3, $4, $5) { + return $1+($2=="$" ? $2+$3 : encode_col(decode_col($3)+delta.c))+($4=="$" ? $4+$5 : encode_row(decode_row($5) + delta.r)); + }); + } + + function shift_formula_xlsx(f, range, cell) { + var r = decode_range(range), s = r.s, c = decode_cell(cell); + var delta = {r:c.r - s.r, c:c.c - s.c}; + return shift_formula_str(f, delta); + } + + /* TODO: parse formula */ + function fuzzyfmla(f) { + if(f.length == 1) return false; + return true; + } + + function _xlfn(f) { + return f.replace(/_xlfn\./g,""); + } + function parseread1(blob) { blob.l+=1; return; } + + /* [MS-XLS] 2.5.51 */ + function parse_ColRelU(blob, length) { + var c = blob.read_shift(length == 1 ? 1 : 2); + return [c & 0x3FFF, (c >> 14) & 1, (c >> 15) & 1]; + } + + /* [MS-XLS] 2.5.198.105 ; [MS-XLSB] 2.5.97.89 */ + function parse_RgceArea(blob, length, opts) { + var w = 2; + if(opts) { + if(opts.biff >= 2 && opts.biff <= 5) return parse_RgceArea_BIFF2(blob, length, opts); + else if(opts.biff == 12) w = 4; + } + var r=blob.read_shift(w), R=blob.read_shift(w); + var c=parse_ColRelU(blob, 2); + var C=parse_ColRelU(blob, 2); + return { s:{r:r, c:c[0], cRel:c[1], rRel:c[2]}, e:{r:R, c:C[0], cRel:C[1], rRel:C[2]} }; + } + /* BIFF 2-5 encodes flags in the row field */ + function parse_RgceArea_BIFF2(blob) { + var r=parse_ColRelU(blob, 2), R=parse_ColRelU(blob, 2); + var c=blob.read_shift(1); + var C=blob.read_shift(1); + return { s:{r:r[0], c:c, cRel:r[1], rRel:r[2]}, e:{r:R[0], c:C, cRel:R[1], rRel:R[2]} }; + } + + /* [MS-XLS] 2.5.198.105 ; [MS-XLSB] 2.5.97.90 */ + function parse_RgceAreaRel(blob, length, opts) { + if(opts.biff < 8) return parse_RgceArea_BIFF2(blob, length, opts); + var r=blob.read_shift(opts.biff == 12 ? 4 : 2), R=blob.read_shift(opts.biff == 12 ? 4 : 2); + var c=parse_ColRelU(blob, 2); + var C=parse_ColRelU(blob, 2); + return { s:{r:r, c:c[0], cRel:c[1], rRel:c[2]}, e:{r:R, c:C[0], cRel:C[1], rRel:C[2]} }; + } + + /* [MS-XLS] 2.5.198.109 ; [MS-XLSB] 2.5.97.91 */ + function parse_RgceLoc(blob, length, opts) { + if(opts && opts.biff >= 2 && opts.biff <= 5) return parse_RgceLoc_BIFF2(blob, length, opts); + var r = blob.read_shift(opts && opts.biff == 12 ? 4 : 2); + var c = parse_ColRelU(blob, 2); + return {r:r, c:c[0], cRel:c[1], rRel:c[2]}; + } + function parse_RgceLoc_BIFF2(blob) { + var r = parse_ColRelU(blob, 2); + var c = blob.read_shift(1); + return {r:r[0], c:c, cRel:r[1], rRel:r[2]}; + } + + /* [MS-XLS] 2.5.198.107, 2.5.47 */ + function parse_RgceElfLoc(blob) { + var r = blob.read_shift(2); + var c = blob.read_shift(2); + return {r:r, c:c & 0xFF, fQuoted:!!(c & 0x4000), cRel:c>>15, rRel:c>>15 }; + } + + /* [MS-XLS] 2.5.198.111 ; [MS-XLSB] 2.5.97.92 TODO */ + function parse_RgceLocRel(blob, length, opts) { + var biff = opts && opts.biff ? opts.biff : 8; + if(biff >= 2 && biff <= 5) return parse_RgceLocRel_BIFF2(blob, length, opts); + var r = blob.read_shift(biff >= 12 ? 4 : 2); + var cl = blob.read_shift(2); + var cRel = (cl & 0x4000) >> 14, rRel = (cl & 0x8000) >> 15; + cl &= 0x3FFF; + if(rRel == 1) while(r > 0x7FFFF) r -= 0x100000; + if(cRel == 1) while(cl > 0x1FFF) cl = cl - 0x4000; + return {r:r,c:cl,cRel:cRel,rRel:rRel}; + } + function parse_RgceLocRel_BIFF2(blob) { + var rl = blob.read_shift(2); + var c = blob.read_shift(1); + var rRel = (rl & 0x8000) >> 15, cRel = (rl & 0x4000) >> 14; + rl &= 0x3FFF; + if(rRel == 1 && rl >= 0x2000) rl = rl - 0x4000; + if(cRel == 1 && c >= 0x80) c = c - 0x100; + return {r:rl,c:c,cRel:cRel,rRel:rRel}; + } + + /* [MS-XLS] 2.5.198.27 ; [MS-XLSB] 2.5.97.18 */ + function parse_PtgArea(blob, length, opts) { + var type = (blob[blob.l++] & 0x60) >> 5; + var area = parse_RgceArea(blob, opts.biff >= 2 && opts.biff <= 5 ? 6 : 8, opts); + return [type, area]; + } + + /* [MS-XLS] 2.5.198.28 ; [MS-XLSB] 2.5.97.19 */ + function parse_PtgArea3d(blob, length, opts) { + var type = (blob[blob.l++] & 0x60) >> 5; + var ixti = blob.read_shift(2, 'i'); + var w = 8; + if(opts) switch(opts.biff) { + case 5: blob.l += 12; w = 6; break; + case 12: w = 12; break; + } + var area = parse_RgceArea(blob, w, opts); + return [type, ixti, area]; + } + + /* [MS-XLS] 2.5.198.29 ; [MS-XLSB] 2.5.97.20 */ + function parse_PtgAreaErr(blob, length, opts) { + var type = (blob[blob.l++] & 0x60) >> 5; + blob.l += opts && (opts.biff > 8) ? 12 : (opts.biff < 8 ? 6 : 8); + return [type]; + } + /* [MS-XLS] 2.5.198.30 ; [MS-XLSB] 2.5.97.21 */ + function parse_PtgAreaErr3d(blob, length, opts) { + var type = (blob[blob.l++] & 0x60) >> 5; + var ixti = blob.read_shift(2); + var w = 8; + if(opts) switch(opts.biff) { + case 5: blob.l += 12; w = 6; break; + case 12: w = 12; break; + } + blob.l += w; + return [type, ixti]; + } + + /* [MS-XLS] 2.5.198.31 ; [MS-XLSB] 2.5.97.22 */ + function parse_PtgAreaN(blob, length, opts) { + var type = (blob[blob.l++] & 0x60) >> 5; + var area = parse_RgceAreaRel(blob, length - 1, opts); + return [type, area]; + } + + /* [MS-XLS] 2.5.198.32 ; [MS-XLSB] 2.5.97.23 */ + function parse_PtgArray(blob, length, opts) { + var type = (blob[blob.l++] & 0x60) >> 5; + blob.l += opts.biff == 2 ? 6 : opts.biff == 12 ? 14 : 7; + return [type]; + } + + /* [MS-XLS] 2.5.198.33 ; [MS-XLSB] 2.5.97.24 */ + function parse_PtgAttrBaxcel(blob) { + var bitSemi = blob[blob.l+1] & 0x01; /* 1 = volatile */ + var bitBaxcel = 1; + blob.l += 4; + return [bitSemi, bitBaxcel]; + } + + /* [MS-XLS] 2.5.198.34 ; [MS-XLSB] 2.5.97.25 */ + function parse_PtgAttrChoose(blob, length, opts) { + blob.l +=2; + var offset = blob.read_shift(opts && opts.biff == 2 ? 1 : 2); + var o = []; + /* offset is 1 less than the number of elements */ + for(var i = 0; i <= offset; ++i) o.push(blob.read_shift(opts && opts.biff == 2 ? 1 : 2)); + return o; + } + + /* [MS-XLS] 2.5.198.35 ; [MS-XLSB] 2.5.97.26 */ + function parse_PtgAttrGoto(blob, length, opts) { + var bitGoto = (blob[blob.l+1] & 0xFF) ? 1 : 0; + blob.l += 2; + return [bitGoto, blob.read_shift(opts && opts.biff == 2 ? 1 : 2)]; + } + + /* [MS-XLS] 2.5.198.36 ; [MS-XLSB] 2.5.97.27 */ + function parse_PtgAttrIf(blob, length, opts) { + var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0; + blob.l += 2; + return [bitIf, blob.read_shift(opts && opts.biff == 2 ? 1 : 2)]; + } + + /* [MS-XLSB] 2.5.97.28 */ + function parse_PtgAttrIfError(blob) { + var bitIf = (blob[blob.l+1] & 0xFF) ? 1 : 0; + blob.l += 2; + return [bitIf, blob.read_shift(2)]; + } + + /* [MS-XLS] 2.5.198.37 ; [MS-XLSB] 2.5.97.29 */ + function parse_PtgAttrSemi(blob, length, opts) { + var bitSemi = (blob[blob.l+1] & 0xFF) ? 1 : 0; + blob.l += opts && opts.biff == 2 ? 3 : 4; + return [bitSemi]; + } + + /* [MS-XLS] 2.5.198.40 ; [MS-XLSB] 2.5.97.32 */ + function parse_PtgAttrSpaceType(blob) { + var type = blob.read_shift(1), cch = blob.read_shift(1); + return [type, cch]; + } + + /* [MS-XLS] 2.5.198.38 ; [MS-XLSB] 2.5.97.30 */ + function parse_PtgAttrSpace(blob) { + blob.read_shift(2); + return parse_PtgAttrSpaceType(blob, 2); + } + + /* [MS-XLS] 2.5.198.39 ; [MS-XLSB] 2.5.97.31 */ + function parse_PtgAttrSpaceSemi(blob) { + blob.read_shift(2); + return parse_PtgAttrSpaceType(blob, 2); + } + + /* [MS-XLS] 2.5.198.84 ; [MS-XLSB] 2.5.97.68 TODO */ + function parse_PtgRef(blob, length, opts) { + //var ptg = blob[blob.l] & 0x1F; + var type = (blob[blob.l] & 0x60)>>5; + blob.l += 1; + var loc = parse_RgceLoc(blob, 0, opts); + return [type, loc]; + } + + /* [MS-XLS] 2.5.198.88 ; [MS-XLSB] 2.5.97.72 TODO */ + function parse_PtgRefN(blob, length, opts) { + var type = (blob[blob.l] & 0x60)>>5; + blob.l += 1; + var loc = parse_RgceLocRel(blob, 0, opts); + return [type, loc]; + } + + /* [MS-XLS] 2.5.198.85 ; [MS-XLSB] 2.5.97.69 TODO */ + function parse_PtgRef3d(blob, length, opts) { + var type = (blob[blob.l] & 0x60)>>5; + blob.l += 1; + var ixti = blob.read_shift(2); // XtiIndex + if(opts && opts.biff == 5) blob.l += 12; + var loc = parse_RgceLoc(blob, 0, opts); // TODO: or RgceLocRel + return [type, ixti, loc]; + } + + + /* [MS-XLS] 2.5.198.62 ; [MS-XLSB] 2.5.97.45 TODO */ + function parse_PtgFunc(blob, length, opts) { + //var ptg = blob[blob.l] & 0x1F; + var type = (blob[blob.l] & 0x60)>>5; + blob.l += 1; + var iftab = blob.read_shift(opts && opts.biff <= 3 ? 1 : 2); + return [FtabArgc[iftab], Ftab[iftab], type]; + } + /* [MS-XLS] 2.5.198.63 ; [MS-XLSB] 2.5.97.46 TODO */ + function parse_PtgFuncVar(blob, length, opts) { + var type = blob[blob.l++]; + var cparams = blob.read_shift(1), tab = opts && opts.biff <= 3 ? [(type == 0x58 ? -1 : 0), blob.read_shift(1)]: parsetab(blob); + return [cparams, (tab[0] === 0 ? Ftab : Cetab)[tab[1]]]; + } + + function parsetab(blob) { + return [blob[blob.l+1]>>7, blob.read_shift(2) & 0x7FFF]; + } + + /* [MS-XLS] 2.5.198.41 ; [MS-XLSB] 2.5.97.33 */ + function parse_PtgAttrSum(blob, length, opts) { + blob.l += opts && opts.biff == 2 ? 3 : 4; return; + } + + /* [MS-XLS] 2.5.198.58 ; [MS-XLSB] 2.5.97.40 */ + function parse_PtgExp(blob, length, opts) { + blob.l++; + if(opts && opts.biff == 12) return [blob.read_shift(4, 'i'), 0]; + var row = blob.read_shift(2); + var col = blob.read_shift(opts && opts.biff == 2 ? 1 : 2); + return [row, col]; + } + + /* [MS-XLS] 2.5.198.57 ; [MS-XLSB] 2.5.97.39 */ + function parse_PtgErr(blob) { blob.l++; return BErr[blob.read_shift(1)]; } + + /* [MS-XLS] 2.5.198.66 ; [MS-XLSB] 2.5.97.49 */ + function parse_PtgInt(blob) { blob.l++; return blob.read_shift(2); } + + /* [MS-XLS] 2.5.198.42 ; [MS-XLSB] 2.5.97.34 */ + function parse_PtgBool(blob) { blob.l++; return blob.read_shift(1)!==0;} + + /* [MS-XLS] 2.5.198.79 ; [MS-XLSB] 2.5.97.63 */ + function parse_PtgNum(blob) { blob.l++; return parse_Xnum(blob, 8); } + + /* [MS-XLS] 2.5.198.89 ; [MS-XLSB] 2.5.97.74 */ + function parse_PtgStr(blob, length, opts) { blob.l++; return parse_ShortXLUnicodeString(blob, length-1, opts); } + + /* [MS-XLS] 2.5.192.112 + 2.5.192.11{3,4,5,6,7} */ + /* [MS-XLSB] 2.5.97.93 + 2.5.97.9{4,5,6,7} */ + function parse_SerAr(blob, biff) { + var val = [blob.read_shift(1)]; + if(biff == 12) switch(val[0]) { + case 0x02: val[0] = 0x04; break; /* SerBool */ + case 0x04: val[0] = 0x10; break; /* SerErr */ + case 0x00: val[0] = 0x01; break; /* SerNum */ + case 0x01: val[0] = 0x02; break; /* SerStr */ + } + switch(val[0]) { + case 0x04: /* SerBool -- boolean */ + val[1] = parsebool(blob, 1) ? 'TRUE' : 'FALSE'; + if(biff != 12) blob.l += 7; break; + case 0x25: /* appears to be an alias */ + case 0x10: /* SerErr -- error */ + val[1] = BErr[blob[blob.l]]; + blob.l += ((biff == 12) ? 4 : 8); break; + case 0x00: /* SerNil -- honestly, I'm not sure how to reproduce this */ + blob.l += 8; break; + case 0x01: /* SerNum -- Xnum */ + val[1] = parse_Xnum(blob, 8); break; + case 0x02: /* SerStr -- XLUnicodeString (<256 chars) */ + val[1] = parse_XLUnicodeString2(blob, 0, {biff:biff > 0 && biff < 8 ? 2 : biff}); break; + default: throw new Error("Bad SerAr: " + val[0]); /* Unreachable */ + } + return val; + } + + /* [MS-XLS] 2.5.198.61 ; [MS-XLSB] 2.5.97.44 */ + function parse_PtgExtraMem(blob, cce, opts) { + var count = blob.read_shift((opts.biff == 12) ? 4 : 2); + var out = []; + for(var i = 0; i != count; ++i) out.push(((opts.biff == 12) ? parse_UncheckedRfX : parse_Ref8U)(blob, 8)); + return out; + } + + /* [MS-XLS] 2.5.198.59 ; [MS-XLSB] 2.5.97.41 */ + function parse_PtgExtraArray(blob, length, opts) { + var rows = 0, cols = 0; + if(opts.biff == 12) { + rows = blob.read_shift(4); // DRw + cols = blob.read_shift(4); // DCol + } else { + cols = 1 + blob.read_shift(1); //DColByteU + rows = 1 + blob.read_shift(2); //DRw + } + if(opts.biff >= 2 && opts.biff < 8) { --rows; if(--cols == 0) cols = 0x100; } + // $FlowIgnore + for(var i = 0, o = []; i != rows && (o[i] = []); ++i) + for(var j = 0; j != cols; ++j) o[i][j] = parse_SerAr(blob, opts.biff); + return o; + } + + /* [MS-XLS] 2.5.198.76 ; [MS-XLSB] 2.5.97.60 */ + function parse_PtgName(blob, length, opts) { + var type = (blob.read_shift(1) >>> 5) & 0x03; + var w = (!opts || (opts.biff >= 8)) ? 4 : 2; + var nameindex = blob.read_shift(w); + switch(opts.biff) { + case 2: blob.l += 5; break; + case 3: case 4: blob.l += 8; break; + case 5: blob.l += 12; break; + } + return [type, 0, nameindex]; + } + + /* [MS-XLS] 2.5.198.77 ; [MS-XLSB] 2.5.97.61 */ + function parse_PtgNameX(blob, length, opts) { + if(opts.biff == 5) return parse_PtgNameX_BIFF5(blob, length, opts); + var type = (blob.read_shift(1) >>> 5) & 0x03; + var ixti = blob.read_shift(2); // XtiIndex + var nameindex = blob.read_shift(4); + return [type, ixti, nameindex]; + } + function parse_PtgNameX_BIFF5(blob) { + var type = (blob.read_shift(1) >>> 5) & 0x03; + var ixti = blob.read_shift(2, 'i'); // XtiIndex + blob.l += 8; + var nameindex = blob.read_shift(2); + blob.l += 12; + return [type, ixti, nameindex]; + } + + /* [MS-XLS] 2.5.198.70 ; [MS-XLSB] 2.5.97.54 */ + function parse_PtgMemArea(blob, length, opts) { + var type = (blob.read_shift(1) >>> 5) & 0x03; + blob.l += (opts && opts.biff == 2 ? 3 : 4); + var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2); + return [type, cce]; + } + + /* [MS-XLS] 2.5.198.72 ; [MS-XLSB] 2.5.97.56 */ + function parse_PtgMemFunc(blob, length, opts) { + var type = (blob.read_shift(1) >>> 5) & 0x03; + var cce = blob.read_shift(opts && opts.biff == 2 ? 1 : 2); + return [type, cce]; + } + + + /* [MS-XLS] 2.5.198.86 ; [MS-XLSB] 2.5.97.69 */ + function parse_PtgRefErr(blob, length, opts) { + var type = (blob.read_shift(1) >>> 5) & 0x03; + blob.l += 4; + if(opts.biff < 8) blob.l--; + if(opts.biff == 12) blob.l += 2; + return [type]; + } + + /* [MS-XLS] 2.5.198.87 ; [MS-XLSB] 2.5.97.71 */ + function parse_PtgRefErr3d(blob, length, opts) { + var type = (blob[blob.l++] & 0x60) >> 5; + var ixti = blob.read_shift(2); + var w = 4; + if(opts) switch(opts.biff) { + case 5: w = 15; break; + case 12: w = 6; break; + } + blob.l += w; + return [type, ixti]; + } + + /* [MS-XLS] 2.5.198.71 ; [MS-XLSB] 2.5.97.55 */ + var parse_PtgMemErr = parsenoop; + /* [MS-XLS] 2.5.198.73 ; [MS-XLSB] 2.5.97.57 */ + var parse_PtgMemNoMem = parsenoop; + /* [MS-XLS] 2.5.198.92 */ + var parse_PtgTbl = parsenoop; + + function parse_PtgElfLoc(blob, length, opts) { + blob.l += 2; + return [parse_RgceElfLoc(blob, 4, opts)]; + } + function parse_PtgElfNoop(blob) { + blob.l += 6; + return []; + } + /* [MS-XLS] 2.5.198.46 */ + var parse_PtgElfCol = parse_PtgElfLoc; + /* [MS-XLS] 2.5.198.47 */ + var parse_PtgElfColS = parse_PtgElfNoop; + /* [MS-XLS] 2.5.198.48 */ + var parse_PtgElfColSV = parse_PtgElfNoop; + /* [MS-XLS] 2.5.198.49 */ + var parse_PtgElfColV = parse_PtgElfLoc; + /* [MS-XLS] 2.5.198.50 */ + function parse_PtgElfLel(blob) { + blob.l += 2; + return [parseuint16(blob), blob.read_shift(2) & 0x01]; + } + /* [MS-XLS] 2.5.198.51 */ + var parse_PtgElfRadical = parse_PtgElfLoc; + /* [MS-XLS] 2.5.198.52 */ + var parse_PtgElfRadicalLel = parse_PtgElfLel; + /* [MS-XLS] 2.5.198.53 */ + var parse_PtgElfRadicalS = parse_PtgElfNoop; + /* [MS-XLS] 2.5.198.54 */ + var parse_PtgElfRw = parse_PtgElfLoc; + /* [MS-XLS] 2.5.198.55 */ + var parse_PtgElfRwV = parse_PtgElfLoc; + + /* [MS-XLSB] 2.5.97.52 TODO */ + var PtgListRT = [ + "Data", + "All", + "Headers", + "??", + "?Data2", + "??", + "?DataHeaders", + "??", + "Totals", + "??", + "??", + "??", + "?DataTotals", + "??", + "??", + "??", + "?Current" + ]; + function parse_PtgList(blob) { + blob.l += 2; + var ixti = blob.read_shift(2); + var flags = blob.read_shift(2); + var idx = blob.read_shift(4); + var c = blob.read_shift(2); + var C = blob.read_shift(2); + var rt = PtgListRT[(flags >> 2) & 0x1F]; + return {ixti: ixti, coltype:(flags&0x3), rt:rt, idx:idx, c:c, C:C}; + } + /* [MS-XLS] 2.5.198.91 ; [MS-XLSB] 2.5.97.76 */ + function parse_PtgSxName(blob) { + blob.l += 2; + return [blob.read_shift(4)]; + } + + /* [XLS] old spec */ + function parse_PtgSheet(blob, length, opts) { + blob.l += 5; + blob.l += 2; + blob.l += (opts.biff == 2 ? 1 : 4); + return ["PTGSHEET"]; + } + function parse_PtgEndSheet(blob, length, opts) { + blob.l += (opts.biff == 2 ? 4 : 5); + return ["PTGENDSHEET"]; + } + function parse_PtgMemAreaN(blob) { + var type = (blob.read_shift(1) >>> 5) & 0x03; + var cce = blob.read_shift(2); + return [type, cce]; + } + function parse_PtgMemNoMemN(blob) { + var type = (blob.read_shift(1) >>> 5) & 0x03; + var cce = blob.read_shift(2); + return [type, cce]; + } + function parse_PtgAttrNoop(blob) { + blob.l += 4; + return [0, 0]; + } + + /* [MS-XLS] 2.5.198.25 ; [MS-XLSB] 2.5.97.16 */ + var PtgTypes = { + 0x01: { n:'PtgExp', f:parse_PtgExp }, + 0x02: { n:'PtgTbl', f:parse_PtgTbl }, + 0x03: { n:'PtgAdd', f:parseread1 }, + 0x04: { n:'PtgSub', f:parseread1 }, + 0x05: { n:'PtgMul', f:parseread1 }, + 0x06: { n:'PtgDiv', f:parseread1 }, + 0x07: { n:'PtgPower', f:parseread1 }, + 0x08: { n:'PtgConcat', f:parseread1 }, + 0x09: { n:'PtgLt', f:parseread1 }, + 0x0A: { n:'PtgLe', f:parseread1 }, + 0x0B: { n:'PtgEq', f:parseread1 }, + 0x0C: { n:'PtgGe', f:parseread1 }, + 0x0D: { n:'PtgGt', f:parseread1 }, + 0x0E: { n:'PtgNe', f:parseread1 }, + 0x0F: { n:'PtgIsect', f:parseread1 }, + 0x10: { n:'PtgUnion', f:parseread1 }, + 0x11: { n:'PtgRange', f:parseread1 }, + 0x12: { n:'PtgUplus', f:parseread1 }, + 0x13: { n:'PtgUminus', f:parseread1 }, + 0x14: { n:'PtgPercent', f:parseread1 }, + 0x15: { n:'PtgParen', f:parseread1 }, + 0x16: { n:'PtgMissArg', f:parseread1 }, + 0x17: { n:'PtgStr', f:parse_PtgStr }, + 0x1A: { n:'PtgSheet', f:parse_PtgSheet }, + 0x1B: { n:'PtgEndSheet', f:parse_PtgEndSheet }, + 0x1C: { n:'PtgErr', f:parse_PtgErr }, + 0x1D: { n:'PtgBool', f:parse_PtgBool }, + 0x1E: { n:'PtgInt', f:parse_PtgInt }, + 0x1F: { n:'PtgNum', f:parse_PtgNum }, + 0x20: { n:'PtgArray', f:parse_PtgArray }, + 0x21: { n:'PtgFunc', f:parse_PtgFunc }, + 0x22: { n:'PtgFuncVar', f:parse_PtgFuncVar }, + 0x23: { n:'PtgName', f:parse_PtgName }, + 0x24: { n:'PtgRef', f:parse_PtgRef }, + 0x25: { n:'PtgArea', f:parse_PtgArea }, + 0x26: { n:'PtgMemArea', f:parse_PtgMemArea }, + 0x27: { n:'PtgMemErr', f:parse_PtgMemErr }, + 0x28: { n:'PtgMemNoMem', f:parse_PtgMemNoMem }, + 0x29: { n:'PtgMemFunc', f:parse_PtgMemFunc }, + 0x2A: { n:'PtgRefErr', f:parse_PtgRefErr }, + 0x2B: { n:'PtgAreaErr', f:parse_PtgAreaErr }, + 0x2C: { n:'PtgRefN', f:parse_PtgRefN }, + 0x2D: { n:'PtgAreaN', f:parse_PtgAreaN }, + 0x2E: { n:'PtgMemAreaN', f:parse_PtgMemAreaN }, + 0x2F: { n:'PtgMemNoMemN', f:parse_PtgMemNoMemN }, + 0x39: { n:'PtgNameX', f:parse_PtgNameX }, + 0x3A: { n:'PtgRef3d', f:parse_PtgRef3d }, + 0x3B: { n:'PtgArea3d', f:parse_PtgArea3d }, + 0x3C: { n:'PtgRefErr3d', f:parse_PtgRefErr3d }, + 0x3D: { n:'PtgAreaErr3d', f:parse_PtgAreaErr3d }, + 0xFF: {} + }; + /* These are duplicated in the PtgTypes table */ + var PtgDupes = { + 0x40: 0x20, 0x60: 0x20, + 0x41: 0x21, 0x61: 0x21, + 0x42: 0x22, 0x62: 0x22, + 0x43: 0x23, 0x63: 0x23, + 0x44: 0x24, 0x64: 0x24, + 0x45: 0x25, 0x65: 0x25, + 0x46: 0x26, 0x66: 0x26, + 0x47: 0x27, 0x67: 0x27, + 0x48: 0x28, 0x68: 0x28, + 0x49: 0x29, 0x69: 0x29, + 0x4A: 0x2A, 0x6A: 0x2A, + 0x4B: 0x2B, 0x6B: 0x2B, + 0x4C: 0x2C, 0x6C: 0x2C, + 0x4D: 0x2D, 0x6D: 0x2D, + 0x4E: 0x2E, 0x6E: 0x2E, + 0x4F: 0x2F, 0x6F: 0x2F, + 0x58: 0x22, 0x78: 0x22, + 0x59: 0x39, 0x79: 0x39, + 0x5A: 0x3A, 0x7A: 0x3A, + 0x5B: 0x3B, 0x7B: 0x3B, + 0x5C: 0x3C, 0x7C: 0x3C, + 0x5D: 0x3D, 0x7D: 0x3D + }; + (function(){for(var y in PtgDupes) PtgTypes[y] = PtgTypes[PtgDupes[y]];})(); + + var Ptg18 = { + 0x01: { n:'PtgElfLel', f:parse_PtgElfLel }, + 0x02: { n:'PtgElfRw', f:parse_PtgElfRw }, + 0x03: { n:'PtgElfCol', f:parse_PtgElfCol }, + 0x06: { n:'PtgElfRwV', f:parse_PtgElfRwV }, + 0x07: { n:'PtgElfColV', f:parse_PtgElfColV }, + 0x0A: { n:'PtgElfRadical', f:parse_PtgElfRadical }, + 0x0B: { n:'PtgElfRadicalS', f:parse_PtgElfRadicalS }, + 0x0D: { n:'PtgElfColS', f:parse_PtgElfColS }, + 0x0F: { n:'PtgElfColSV', f:parse_PtgElfColSV }, + 0x10: { n:'PtgElfRadicalLel', f:parse_PtgElfRadicalLel }, + 0x19: { n:'PtgList', f:parse_PtgList }, + 0x1D: { n:'PtgSxName', f:parse_PtgSxName }, + 0xFF: {} + }; + var Ptg19 = { + 0x00: { n:'PtgAttrNoop', f:parse_PtgAttrNoop }, + 0x01: { n:'PtgAttrSemi', f:parse_PtgAttrSemi }, + 0x02: { n:'PtgAttrIf', f:parse_PtgAttrIf }, + 0x04: { n:'PtgAttrChoose', f:parse_PtgAttrChoose }, + 0x08: { n:'PtgAttrGoto', f:parse_PtgAttrGoto }, + 0x10: { n:'PtgAttrSum', f:parse_PtgAttrSum }, + 0x20: { n:'PtgAttrBaxcel', f:parse_PtgAttrBaxcel }, + 0x40: { n:'PtgAttrSpace', f:parse_PtgAttrSpace }, + 0x41: { n:'PtgAttrSpaceSemi', f:parse_PtgAttrSpaceSemi }, + 0x80: { n:'PtgAttrIfError', f:parse_PtgAttrIfError }, + 0xFF: {} + }; + Ptg19[0x21] = Ptg19[0x20]; + + /* [MS-XLS] 2.5.198.103 ; [MS-XLSB] 2.5.97.87 */ + function parse_RgbExtra(blob, length, rgce, opts) { + if(opts.biff < 8) return parsenoop(blob, length); + var target = blob.l + length; + var o = []; + for(var i = 0; i !== rgce.length; ++i) { + switch(rgce[i][0]) { + case 'PtgArray': /* PtgArray -> PtgExtraArray */ + rgce[i][1] = parse_PtgExtraArray(blob, 0, opts); + o.push(rgce[i][1]); + break; + case 'PtgMemArea': /* PtgMemArea -> PtgExtraMem */ + rgce[i][2] = parse_PtgExtraMem(blob, rgce[i][1], opts); + o.push(rgce[i][2]); + break; + case 'PtgExp': /* PtgExp -> PtgExtraCol */ + if(opts && opts.biff == 12) { + rgce[i][1][1] = blob.read_shift(4); + o.push(rgce[i][1]); + } break; + case 'PtgList': /* TODO: PtgList -> PtgExtraList */ + case 'PtgElfRadicalS': /* TODO: PtgElfRadicalS -> PtgExtraElf */ + case 'PtgElfColS': /* TODO: PtgElfColS -> PtgExtraElf */ + case 'PtgElfColSV': /* TODO: PtgElfColSV -> PtgExtraElf */ + throw "Unsupported " + rgce[i][0]; + default: break; + } + } + length = target - blob.l; + /* note: this is technically an error but Excel disregards */ + //if(target !== blob.l && blob.l !== target - length) throw new Error(target + " != " + blob.l); + if(length !== 0) o.push(parsenoop(blob, length)); + return o; + } + + /* [MS-XLS] 2.5.198.104 ; [MS-XLSB] 2.5.97.88 */ + function parse_Rgce(blob, length, opts) { + var target = blob.l + length; + var R, id, ptgs = []; + while(target != blob.l) { + length = target - blob.l; + id = blob[blob.l]; + R = PtgTypes[id]; + if(id === 0x18 || id === 0x19) R = (id === 0x18 ? Ptg18 : Ptg19)[blob[blob.l + 1]]; + if(!R || !R.f) { /*ptgs.push*/(parsenoop(blob, length)); } + else { ptgs.push([R.n, R.f(blob, length, opts)]); } + } + return ptgs; + } + + function stringify_array(f) { + var o = []; + for(var i = 0; i < f.length; ++i) { + var x = f[i], r = []; + for(var j = 0; j < x.length; ++j) { + var y = x[j]; + if(y) switch(y[0]) { + // TODO: handle embedded quotes + case 0x02: + r.push('"' + y[1].replace(/"/g,'""') + '"'); break; + default: r.push(y[1]); + } else r.push(""); + } + o.push(r.join(",")); + } + return o.join(";"); + } + + /* [MS-XLS] 2.2.2 ; [MS-XLSB] 2.2.2 TODO */ + var PtgBinOp = { + PtgAdd: "+", + PtgConcat: "&", + PtgDiv: "/", + PtgEq: "=", + PtgGe: ">=", + PtgGt: ">", + PtgLe: "<=", + PtgLt: "<", + PtgMul: "*", + PtgNe: "<>", + PtgPower: "^", + PtgSub: "-" + }; + function formula_quote_sheet_name(sname, opts) { + if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name"); + if(sname.indexOf(" ") > -1) return "'" + sname + "'"; + return sname; + } + function get_ixti_raw(supbooks, ixti, opts) { + if(!supbooks) return "SH33TJSERR0"; + if(opts.biff > 8 && (!supbooks.XTI || !supbooks.XTI[ixti])) return supbooks.SheetNames[ixti]; + if(!supbooks.XTI) return "SH33TJSERR6"; + var XTI = supbooks.XTI[ixti]; + if(opts.biff < 8) { + if(ixti > 10000) ixti-= 65536; + if(ixti < 0) ixti = -ixti; + return ixti == 0 ? "" : supbooks.XTI[ixti - 1]; + } + if(!XTI) return "SH33TJSERR1"; + var o = ""; + if(opts.biff > 8) switch(supbooks[XTI[0]][0]) { + case 0x0165: /* 'BrtSupSelf' */ + o = XTI[1] == -1 ? "#REF" : supbooks.SheetNames[XTI[1]]; + return XTI[1] == XTI[2] ? o : o + ":" + supbooks.SheetNames[XTI[2]]; + case 0x0166: /* 'BrtSupSame' */ + if(opts.SID != null) return supbooks.SheetNames[opts.SID]; + return "SH33TJSSAME" + supbooks[XTI[0]][0]; + case 0x0163: /* 'BrtSupBookSrc' */ + /* falls through */ + default: return "SH33TJSSRC" + supbooks[XTI[0]][0]; + } + switch(supbooks[XTI[0]][0][0]) { + case 0x0401: + o = XTI[1] == -1 ? "#REF" : (supbooks.SheetNames[XTI[1]] || "SH33TJSERR3"); + return XTI[1] == XTI[2] ? o : o + ":" + supbooks.SheetNames[XTI[2]]; + case 0x3A01: return "SH33TJSERR8"; + default: + if(!supbooks[XTI[0]][0][3]) return "SH33TJSERR2"; + o = XTI[1] == -1 ? "#REF" : (supbooks[XTI[0]][0][3][XTI[1]] || "SH33TJSERR4"); + return XTI[1] == XTI[2] ? o : o + ":" + supbooks[XTI[0]][0][3][XTI[2]]; + } + } + function get_ixti(supbooks, ixti, opts) { + return formula_quote_sheet_name(get_ixti_raw(supbooks, ixti, opts), opts); + } + function stringify_formula(formula/*Array*/, range, cell, supbooks, opts) { + var biff = (opts && opts.biff) || 8; + var _range = /*range != null ? range :*/ {s:{c:0, r:0},e:{c:0, r:0}}; + var stack = [], e1, e2, c, ixti=0, nameidx=0, r, sname=""; + if(!formula[0] || !formula[0][0]) return ""; + var last_sp = -1, sp = ""; + for(var ff = 0, fflen = formula[0].length; ff < fflen; ++ff) { + var f = formula[0][ff]; + switch(f[0]) { + case 'PtgUminus': /* [MS-XLS] 2.5.198.93 */ + stack.push("-" + stack.pop()); break; + case 'PtgUplus': /* [MS-XLS] 2.5.198.95 */ + stack.push("+" + stack.pop()); break; + case 'PtgPercent': /* [MS-XLS] 2.5.198.81 */ + stack.push(stack.pop() + "%"); break; + + case 'PtgAdd': /* [MS-XLS] 2.5.198.26 */ + case 'PtgConcat': /* [MS-XLS] 2.5.198.43 */ + case 'PtgDiv': /* [MS-XLS] 2.5.198.45 */ + case 'PtgEq': /* [MS-XLS] 2.5.198.56 */ + case 'PtgGe': /* [MS-XLS] 2.5.198.64 */ + case 'PtgGt': /* [MS-XLS] 2.5.198.65 */ + case 'PtgLe': /* [MS-XLS] 2.5.198.68 */ + case 'PtgLt': /* [MS-XLS] 2.5.198.69 */ + case 'PtgMul': /* [MS-XLS] 2.5.198.75 */ + case 'PtgNe': /* [MS-XLS] 2.5.198.78 */ + case 'PtgPower': /* [MS-XLS] 2.5.198.82 */ + case 'PtgSub': /* [MS-XLS] 2.5.198.90 */ + e1 = stack.pop(); e2 = stack.pop(); + if(last_sp >= 0) { + switch(formula[0][last_sp][1][0]) { + case 0: + // $FlowIgnore + sp = fill(" ", formula[0][last_sp][1][1]); break; + case 1: + // $FlowIgnore + sp = fill("\r", formula[0][last_sp][1][1]); break; + default: + sp = ""; + // $FlowIgnore + if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + formula[0][last_sp][1][0]); + } + e2 = e2 + sp; + last_sp = -1; + } + stack.push(e2+PtgBinOp[f[0]]+e1); + break; + + case 'PtgIsect': /* [MS-XLS] 2.5.198.67 */ + e1 = stack.pop(); e2 = stack.pop(); + stack.push(e2+" "+e1); + break; + case 'PtgUnion': /* [MS-XLS] 2.5.198.94 */ + e1 = stack.pop(); e2 = stack.pop(); + stack.push(e2+","+e1); + break; + case 'PtgRange': /* [MS-XLS] 2.5.198.83 */ + e1 = stack.pop(); e2 = stack.pop(); + stack.push(e2+":"+e1); + break; + + case 'PtgAttrChoose': /* [MS-XLS] 2.5.198.34 */ + break; + case 'PtgAttrGoto': /* [MS-XLS] 2.5.198.35 */ + break; + case 'PtgAttrIf': /* [MS-XLS] 2.5.198.36 */ + break; + case 'PtgAttrIfError': /* [MS-XLSB] 2.5.97.28 */ + break; + + + case 'PtgRef': /* [MS-XLS] 2.5.198.84 */ + c = shift_cell_xls((f[1][1]), _range, opts); + stack.push(encode_cell_xls(c, biff)); + break; + case 'PtgRefN': /* [MS-XLS] 2.5.198.88 */ + c = cell ? shift_cell_xls((f[1][1]), cell, opts) : (f[1][1]); + stack.push(encode_cell_xls(c, biff)); + break; + case 'PtgRef3d': /* [MS-XLS] 2.5.198.85 */ + ixti = f[1][1]; c = shift_cell_xls((f[1][2]), _range, opts); + sname = get_ixti(supbooks, ixti, opts); + var w = sname; /* IE9 fails on defined names */ // eslint-disable-line no-unused-vars + stack.push(sname + "!" + encode_cell_xls(c, biff)); + break; + + case 'PtgFunc': /* [MS-XLS] 2.5.198.62 */ + case 'PtgFuncVar': /* [MS-XLS] 2.5.198.63 */ + /* f[1] = [argc, func, type] */ + var argc = (f[1][0]), func = (f[1][1]); + if(!argc) argc = 0; + argc &= 0x7F; + var args = argc == 0 ? [] : stack.slice(-argc); + stack.length -= argc; + if(func === 'User') func = args.shift(); + stack.push(func + "(" + args.join(",") + ")"); + break; + + case 'PtgBool': /* [MS-XLS] 2.5.198.42 */ + stack.push(f[1] ? "TRUE" : "FALSE"); break; + case 'PtgInt': /* [MS-XLS] 2.5.198.66 */ + stack.push(f[1]); break; + case 'PtgNum': /* [MS-XLS] 2.5.198.79 TODO: precision? */ + stack.push(String(f[1])); break; + case 'PtgStr': /* [MS-XLS] 2.5.198.89 */ + // $FlowIgnore + stack.push('"' + f[1] + '"'); break; + case 'PtgErr': /* [MS-XLS] 2.5.198.57 */ + stack.push(f[1]); break; + case 'PtgAreaN': /* [MS-XLS] 2.5.198.31 TODO */ + r = shift_range_xls(f[1][1], cell ? {s:cell} : _range, opts); + stack.push(encode_range_xls((r), opts)); + break; + case 'PtgArea': /* [MS-XLS] 2.5.198.27 TODO: fixed points */ + r = shift_range_xls(f[1][1], _range, opts); + stack.push(encode_range_xls((r), opts)); + break; + case 'PtgArea3d': /* [MS-XLS] 2.5.198.28 TODO */ + ixti = f[1][1]; r = f[1][2]; + sname = get_ixti(supbooks, ixti, opts); + stack.push(sname + "!" + encode_range_xls((r), opts)); + break; + case 'PtgAttrSum': /* [MS-XLS] 2.5.198.41 */ + stack.push("SUM(" + stack.pop() + ")"); + break; + + case 'PtgAttrBaxcel': /* [MS-XLS] 2.5.198.33 */ + case 'PtgAttrSemi': /* [MS-XLS] 2.5.198.37 */ + break; + + case 'PtgName': /* [MS-XLS] 2.5.198.76 ; [MS-XLSB] 2.5.97.60 TODO: revisions */ + /* f[1] = type, 0, nameindex */ + nameidx = (f[1][2]); + var lbl = (supbooks.names||[])[nameidx-1] || (supbooks[0]||[])[nameidx]; + var name = lbl ? lbl.Name : "SH33TJSNAME" + String(nameidx); + if(name in XLSXFutureFunctions) name = XLSXFutureFunctions[name]; + stack.push(name); + break; + + case 'PtgNameX': /* [MS-XLS] 2.5.198.77 ; [MS-XLSB] 2.5.97.61 TODO: revisions */ + /* f[1] = type, ixti, nameindex */ + var bookidx = (f[1][1]); nameidx = (f[1][2]); var externbook; + /* TODO: Properly handle missing values */ + if(opts.biff <= 5) { + if(bookidx < 0) bookidx = -bookidx; + if(supbooks[bookidx]) externbook = supbooks[bookidx][nameidx]; + } else { + var o = ""; + if(((supbooks[bookidx]||[])[0]||[])[0] == 0x3A01){/* empty */} + else if(((supbooks[bookidx]||[])[0]||[])[0] == 0x0401){ + if(supbooks[bookidx][nameidx] && supbooks[bookidx][nameidx].itab > 0) { + o = supbooks.SheetNames[supbooks[bookidx][nameidx].itab-1] + "!"; + } + } + else o = supbooks.SheetNames[nameidx-1]+ "!"; + if(supbooks[bookidx] && supbooks[bookidx][nameidx]) o += supbooks[bookidx][nameidx].Name; + else if(supbooks[0] && supbooks[0][nameidx]) o += supbooks[0][nameidx].Name; + else o += "SH33TJSERRX"; + stack.push(o); + break; + } + if(!externbook) externbook = {Name: "SH33TJSERRY"}; + stack.push(externbook.Name); + break; + + case 'PtgParen': /* [MS-XLS] 2.5.198.80 */ + var lp = '(', rp = ')'; + if(last_sp >= 0) { + sp = ""; + switch(formula[0][last_sp][1][0]) { + // $FlowIgnore + case 2: lp = fill(" ", formula[0][last_sp][1][1]) + lp; break; + // $FlowIgnore + case 3: lp = fill("\r", formula[0][last_sp][1][1]) + lp; break; + // $FlowIgnore + case 4: rp = fill(" ", formula[0][last_sp][1][1]) + rp; break; + // $FlowIgnore + case 5: rp = fill("\r", formula[0][last_sp][1][1]) + rp; break; + default: + // $FlowIgnore + if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + formula[0][last_sp][1][0]); + } + last_sp = -1; + } + stack.push(lp + stack.pop() + rp); break; + + case 'PtgRefErr': /* [MS-XLS] 2.5.198.86 */ + stack.push('#REF!'); break; + + case 'PtgRefErr3d': /* [MS-XLS] 2.5.198.87 */ + stack.push('#REF!'); break; + + case 'PtgExp': /* [MS-XLS] 2.5.198.58 TODO */ + c = {c:(f[1][1]),r:(f[1][0])}; + var q = ({c: cell.c, r:cell.r}); + if(supbooks.sharedf[encode_cell(c)]) { + var parsedf = (supbooks.sharedf[encode_cell(c)]); + stack.push(stringify_formula(parsedf, _range, q, supbooks, opts)); + } + else { + var fnd = false; + for(e1=0;e1!=supbooks.arrayf.length; ++e1) { + /* TODO: should be something like range_has */ + e2 = supbooks.arrayf[e1]; + if(c.c < e2[0].s.c || c.c > e2[0].e.c) continue; + if(c.r < e2[0].s.r || c.r > e2[0].e.r) continue; + stack.push(stringify_formula(e2[1], _range, q, supbooks, opts)); + fnd = true; + break; + } + if(!fnd) stack.push(f[1]); + } + break; + + case 'PtgArray': /* [MS-XLS] 2.5.198.32 TODO */ + stack.push("{" + stringify_array(f[1]) + "}"); + break; + + case 'PtgMemArea': /* [MS-XLS] 2.5.198.70 TODO: confirm this is a non-display */ + //stack.push("(" + f[2].map(encode_range).join(",") + ")"); + break; + + case 'PtgAttrSpace': /* [MS-XLS] 2.5.198.38 */ + case 'PtgAttrSpaceSemi': /* [MS-XLS] 2.5.198.39 */ + last_sp = ff; + break; + + case 'PtgTbl': /* [MS-XLS] 2.5.198.92 TODO */ + break; + + case 'PtgMemErr': /* [MS-XLS] 2.5.198.71 */ + break; + + case 'PtgMissArg': /* [MS-XLS] 2.5.198.74 */ + stack.push(""); + break; + + case 'PtgAreaErr': /* [MS-XLS] 2.5.198.29 */ + stack.push("#REF!"); break; + + case 'PtgAreaErr3d': /* [MS-XLS] 2.5.198.30 */ + stack.push("#REF!"); break; + + case 'PtgList': /* [MS-XLSB] 2.5.97.52 */ + // $FlowIgnore + stack.push("Table" + f[1].idx + "[#" + f[1].rt + "]"); + break; + + case 'PtgMemAreaN': + case 'PtgMemNoMemN': + case 'PtgAttrNoop': + case 'PtgSheet': + case 'PtgEndSheet': + break; + + case 'PtgMemFunc': /* [MS-XLS] 2.5.198.72 TODO */ + break; + case 'PtgMemNoMem': /* [MS-XLS] 2.5.198.73 TODO */ + break; + + case 'PtgElfCol': /* [MS-XLS] 2.5.198.46 */ + case 'PtgElfColS': /* [MS-XLS] 2.5.198.47 */ + case 'PtgElfColSV': /* [MS-XLS] 2.5.198.48 */ + case 'PtgElfColV': /* [MS-XLS] 2.5.198.49 */ + case 'PtgElfLel': /* [MS-XLS] 2.5.198.50 */ + case 'PtgElfRadical': /* [MS-XLS] 2.5.198.51 */ + case 'PtgElfRadicalLel': /* [MS-XLS] 2.5.198.52 */ + case 'PtgElfRadicalS': /* [MS-XLS] 2.5.198.53 */ + case 'PtgElfRw': /* [MS-XLS] 2.5.198.54 */ + case 'PtgElfRwV': /* [MS-XLS] 2.5.198.55 */ + throw new Error("Unsupported ELFs"); + + case 'PtgSxName': /* [MS-XLS] 2.5.198.91 TODO -- find a test case */ + throw new Error('Unrecognized Formula Token: ' + String(f)); + default: throw new Error('Unrecognized Formula Token: ' + String(f)); + } + var PtgNonDisp = ['PtgAttrSpace', 'PtgAttrSpaceSemi', 'PtgAttrGoto']; + if(opts.biff != 3) if(last_sp >= 0 && PtgNonDisp.indexOf(formula[0][ff][0]) == -1) { + f = formula[0][last_sp]; + var _left = true; + switch(f[1][0]) { + /* note: some bad XLSB files omit the PtgParen */ + case 4: _left = false; + /* falls through */ + case 0: + // $FlowIgnore + sp = fill(" ", f[1][1]); break; + case 5: _left = false; + /* falls through */ + case 1: + // $FlowIgnore + sp = fill("\r", f[1][1]); break; + default: + sp = ""; + // $FlowIgnore + if(opts.WTF) throw new Error("Unexpected PtgAttrSpaceType " + f[1][0]); + } + stack.push((_left ? sp : "") + stack.pop() + (_left ? "" : sp)); + last_sp = -1; + } + } + if(stack.length > 1 && opts.WTF) throw new Error("bad formula stack"); + return stack[0]; + } + + /* [MS-XLS] 2.5.198.1 TODO */ + function parse_ArrayParsedFormula(blob, length, opts) { + var target = blob.l + length, len = opts.biff == 2 ? 1 : 2; + var rgcb, cce = blob.read_shift(len); // length of rgce + if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)]; + var rgce = parse_Rgce(blob, cce, opts); + if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts); + blob.l = target; + return [rgce, rgcb]; + } + + /* [MS-XLS] 2.5.198.3 TODO */ + function parse_XLSCellParsedFormula(blob, length, opts) { + var target = blob.l + length, len = opts.biff == 2 ? 1 : 2; + var rgcb, cce = blob.read_shift(len); // length of rgce + if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)]; + var rgce = parse_Rgce(blob, cce, opts); + if(length !== cce + len) rgcb = parse_RgbExtra(blob, length - cce - len, rgce, opts); + blob.l = target; + return [rgce, rgcb]; + } + + /* [MS-XLS] 2.5.198.21 */ + function parse_NameParsedFormula(blob, length, opts, cce) { + var target = blob.l + length; + var rgce = parse_Rgce(blob, cce, opts); + var rgcb; + if(target !== blob.l) rgcb = parse_RgbExtra(blob, target - blob.l, rgce, opts); + return [rgce, rgcb]; + } + + /* [MS-XLS] 2.5.198.118 TODO */ + function parse_SharedParsedFormula(blob, length, opts) { + var target = blob.l + length; + var rgcb, cce = blob.read_shift(2); // length of rgce + var rgce = parse_Rgce(blob, cce, opts); + if(cce == 0xFFFF) return [[],parsenoop(blob, length-2)]; + if(length !== cce + 2) rgcb = parse_RgbExtra(blob, target - cce - 2, rgce, opts); + return [rgce, rgcb]; + } + + /* [MS-XLS] 2.5.133 TODO: how to emit empty strings? */ + function parse_FormulaValue(blob) { + var b; + if(__readUInt16LE(blob,blob.l + 6) !== 0xFFFF) return [parse_Xnum(blob),'n']; + switch(blob[blob.l]) { + case 0x00: blob.l += 8; return ["String", 's']; + case 0x01: b = blob[blob.l+2] === 0x1; blob.l += 8; return [b,'b']; + case 0x02: b = blob[blob.l+2]; blob.l += 8; return [b,'e']; + case 0x03: blob.l += 8; return ["",'s']; + } + return []; + } + + /* [MS-XLS] 2.4.127 TODO */ + function parse_Formula(blob, length, opts) { + var end = blob.l + length; + var cell = parse_XLSCell(blob, 6); + if(opts.biff == 2) ++blob.l; + var val = parse_FormulaValue(blob,8); + var flags = blob.read_shift(1); + if(opts.biff != 2) { + blob.read_shift(1); + if(opts.biff >= 5) { + /*var chn = */blob.read_shift(4); + } + } + var cbf = parse_XLSCellParsedFormula(blob, end - blob.l, opts); + return {cell:cell, val:val[0], formula:cbf, shared: (flags >> 3) & 1, tt:val[1]}; + } + + /* XLSB Parsed Formula records have the same shape */ + function parse_XLSBParsedFormula(data, length, opts) { + var cce = data.read_shift(4); + var rgce = parse_Rgce(data, cce, opts); + var cb = data.read_shift(4); + var rgcb = cb > 0 ? parse_RgbExtra(data, cb, rgce, opts) : null; + return [rgce, rgcb]; + } + + /* [MS-XLSB] 2.5.97.1 ArrayParsedFormula */ + var parse_XLSBArrayParsedFormula = parse_XLSBParsedFormula; + /* [MS-XLSB] 2.5.97.4 CellParsedFormula */ + var parse_XLSBCellParsedFormula = parse_XLSBParsedFormula; + /* [MS-XLSB] 2.5.97.12 NameParsedFormula */ + var parse_XLSBNameParsedFormula = parse_XLSBParsedFormula; + /* [MS-XLSB] 2.5.97.98 SharedParsedFormula */ + var parse_XLSBSharedParsedFormula = parse_XLSBParsedFormula; + /* [MS-XLS] 2.5.198.4 */ + var Cetab = { + 0x0000: 'BEEP', + 0x0001: 'OPEN', + 0x0002: 'OPEN.LINKS', + 0x0003: 'CLOSE.ALL', + 0x0004: 'SAVE', + 0x0005: 'SAVE.AS', + 0x0006: 'FILE.DELETE', + 0x0007: 'PAGE.SETUP', + 0x0008: 'PRINT', + 0x0009: 'PRINTER.SETUP', + 0x000A: 'QUIT', + 0x000B: 'NEW.WINDOW', + 0x000C: 'ARRANGE.ALL', + 0x000D: 'WINDOW.SIZE', + 0x000E: 'WINDOW.MOVE', + 0x000F: 'FULL', + 0x0010: 'CLOSE', + 0x0011: 'RUN', + 0x0016: 'SET.PRINT.AREA', + 0x0017: 'SET.PRINT.TITLES', + 0x0018: 'SET.PAGE.BREAK', + 0x0019: 'REMOVE.PAGE.BREAK', + 0x001A: 'FONT', + 0x001B: 'DISPLAY', + 0x001C: 'PROTECT.DOCUMENT', + 0x001D: 'PRECISION', + 0x001E: 'A1.R1C1', + 0x001F: 'CALCULATE.NOW', + 0x0020: 'CALCULATION', + 0x0022: 'DATA.FIND', + 0x0023: 'EXTRACT', + 0x0024: 'DATA.DELETE', + 0x0025: 'SET.DATABASE', + 0x0026: 'SET.CRITERIA', + 0x0027: 'SORT', + 0x0028: 'DATA.SERIES', + 0x0029: 'TABLE', + 0x002A: 'FORMAT.NUMBER', + 0x002B: 'ALIGNMENT', + 0x002C: 'STYLE', + 0x002D: 'BORDER', + 0x002E: 'CELL.PROTECTION', + 0x002F: 'COLUMN.WIDTH', + 0x0030: 'UNDO', + 0x0031: 'CUT', + 0x0032: 'COPY', + 0x0033: 'PASTE', + 0x0034: 'CLEAR', + 0x0035: 'PASTE.SPECIAL', + 0x0036: 'EDIT.DELETE', + 0x0037: 'INSERT', + 0x0038: 'FILL.RIGHT', + 0x0039: 'FILL.DOWN', + 0x003D: 'DEFINE.NAME', + 0x003E: 'CREATE.NAMES', + 0x003F: 'FORMULA.GOTO', + 0x0040: 'FORMULA.FIND', + 0x0041: 'SELECT.LAST.CELL', + 0x0042: 'SHOW.ACTIVE.CELL', + 0x0043: 'GALLERY.AREA', + 0x0044: 'GALLERY.BAR', + 0x0045: 'GALLERY.COLUMN', + 0x0046: 'GALLERY.LINE', + 0x0047: 'GALLERY.PIE', + 0x0048: 'GALLERY.SCATTER', + 0x0049: 'COMBINATION', + 0x004A: 'PREFERRED', + 0x004B: 'ADD.OVERLAY', + 0x004C: 'GRIDLINES', + 0x004D: 'SET.PREFERRED', + 0x004E: 'AXES', + 0x004F: 'LEGEND', + 0x0050: 'ATTACH.TEXT', + 0x0051: 'ADD.ARROW', + 0x0052: 'SELECT.CHART', + 0x0053: 'SELECT.PLOT.AREA', + 0x0054: 'PATTERNS', + 0x0055: 'MAIN.CHART', + 0x0056: 'OVERLAY', + 0x0057: 'SCALE', + 0x0058: 'FORMAT.LEGEND', + 0x0059: 'FORMAT.TEXT', + 0x005A: 'EDIT.REPEAT', + 0x005B: 'PARSE', + 0x005C: 'JUSTIFY', + 0x005D: 'HIDE', + 0x005E: 'UNHIDE', + 0x005F: 'WORKSPACE', + 0x0060: 'FORMULA', + 0x0061: 'FORMULA.FILL', + 0x0062: 'FORMULA.ARRAY', + 0x0063: 'DATA.FIND.NEXT', + 0x0064: 'DATA.FIND.PREV', + 0x0065: 'FORMULA.FIND.NEXT', + 0x0066: 'FORMULA.FIND.PREV', + 0x0067: 'ACTIVATE', + 0x0068: 'ACTIVATE.NEXT', + 0x0069: 'ACTIVATE.PREV', + 0x006A: 'UNLOCKED.NEXT', + 0x006B: 'UNLOCKED.PREV', + 0x006C: 'COPY.PICTURE', + 0x006D: 'SELECT', + 0x006E: 'DELETE.NAME', + 0x006F: 'DELETE.FORMAT', + 0x0070: 'VLINE', + 0x0071: 'HLINE', + 0x0072: 'VPAGE', + 0x0073: 'HPAGE', + 0x0074: 'VSCROLL', + 0x0075: 'HSCROLL', + 0x0076: 'ALERT', + 0x0077: 'NEW', + 0x0078: 'CANCEL.COPY', + 0x0079: 'SHOW.CLIPBOARD', + 0x007A: 'MESSAGE', + 0x007C: 'PASTE.LINK', + 0x007D: 'APP.ACTIVATE', + 0x007E: 'DELETE.ARROW', + 0x007F: 'ROW.HEIGHT', + 0x0080: 'FORMAT.MOVE', + 0x0081: 'FORMAT.SIZE', + 0x0082: 'FORMULA.REPLACE', + 0x0083: 'SEND.KEYS', + 0x0084: 'SELECT.SPECIAL', + 0x0085: 'APPLY.NAMES', + 0x0086: 'REPLACE.FONT', + 0x0087: 'FREEZE.PANES', + 0x0088: 'SHOW.INFO', + 0x0089: 'SPLIT', + 0x008A: 'ON.WINDOW', + 0x008B: 'ON.DATA', + 0x008C: 'DISABLE.INPUT', + 0x008E: 'OUTLINE', + 0x008F: 'LIST.NAMES', + 0x0090: 'FILE.CLOSE', + 0x0091: 'SAVE.WORKBOOK', + 0x0092: 'DATA.FORM', + 0x0093: 'COPY.CHART', + 0x0094: 'ON.TIME', + 0x0095: 'WAIT', + 0x0096: 'FORMAT.FONT', + 0x0097: 'FILL.UP', + 0x0098: 'FILL.LEFT', + 0x0099: 'DELETE.OVERLAY', + 0x009B: 'SHORT.MENUS', + 0x009F: 'SET.UPDATE.STATUS', + 0x00A1: 'COLOR.PALETTE', + 0x00A2: 'DELETE.STYLE', + 0x00A3: 'WINDOW.RESTORE', + 0x00A4: 'WINDOW.MAXIMIZE', + 0x00A6: 'CHANGE.LINK', + 0x00A7: 'CALCULATE.DOCUMENT', + 0x00A8: 'ON.KEY', + 0x00A9: 'APP.RESTORE', + 0x00AA: 'APP.MOVE', + 0x00AB: 'APP.SIZE', + 0x00AC: 'APP.MINIMIZE', + 0x00AD: 'APP.MAXIMIZE', + 0x00AE: 'BRING.TO.FRONT', + 0x00AF: 'SEND.TO.BACK', + 0x00B9: 'MAIN.CHART.TYPE', + 0x00BA: 'OVERLAY.CHART.TYPE', + 0x00BB: 'SELECT.END', + 0x00BC: 'OPEN.MAIL', + 0x00BD: 'SEND.MAIL', + 0x00BE: 'STANDARD.FONT', + 0x00BF: 'CONSOLIDATE', + 0x00C0: 'SORT.SPECIAL', + 0x00C1: 'GALLERY.3D.AREA', + 0x00C2: 'GALLERY.3D.COLUMN', + 0x00C3: 'GALLERY.3D.LINE', + 0x00C4: 'GALLERY.3D.PIE', + 0x00C5: 'VIEW.3D', + 0x00C6: 'GOAL.SEEK', + 0x00C7: 'WORKGROUP', + 0x00C8: 'FILL.GROUP', + 0x00C9: 'UPDATE.LINK', + 0x00CA: 'PROMOTE', + 0x00CB: 'DEMOTE', + 0x00CC: 'SHOW.DETAIL', + 0x00CE: 'UNGROUP', + 0x00CF: 'OBJECT.PROPERTIES', + 0x00D0: 'SAVE.NEW.OBJECT', + 0x00D1: 'SHARE', + 0x00D2: 'SHARE.NAME', + 0x00D3: 'DUPLICATE', + 0x00D4: 'APPLY.STYLE', + 0x00D5: 'ASSIGN.TO.OBJECT', + 0x00D6: 'OBJECT.PROTECTION', + 0x00D7: 'HIDE.OBJECT', + 0x00D8: 'SET.EXTRACT', + 0x00D9: 'CREATE.PUBLISHER', + 0x00DA: 'SUBSCRIBE.TO', + 0x00DB: 'ATTRIBUTES', + 0x00DC: 'SHOW.TOOLBAR', + 0x00DE: 'PRINT.PREVIEW', + 0x00DF: 'EDIT.COLOR', + 0x00E0: 'SHOW.LEVELS', + 0x00E1: 'FORMAT.MAIN', + 0x00E2: 'FORMAT.OVERLAY', + 0x00E3: 'ON.RECALC', + 0x00E4: 'EDIT.SERIES', + 0x00E5: 'DEFINE.STYLE', + 0x00F0: 'LINE.PRINT', + 0x00F3: 'ENTER.DATA', + 0x00F9: 'GALLERY.RADAR', + 0x00FA: 'MERGE.STYLES', + 0x00FB: 'EDITION.OPTIONS', + 0x00FC: 'PASTE.PICTURE', + 0x00FD: 'PASTE.PICTURE.LINK', + 0x00FE: 'SPELLING', + 0x0100: 'ZOOM', + 0x0103: 'INSERT.OBJECT', + 0x0104: 'WINDOW.MINIMIZE', + 0x0109: 'SOUND.NOTE', + 0x010A: 'SOUND.PLAY', + 0x010B: 'FORMAT.SHAPE', + 0x010C: 'EXTEND.POLYGON', + 0x010D: 'FORMAT.AUTO', + 0x0110: 'GALLERY.3D.BAR', + 0x0111: 'GALLERY.3D.SURFACE', + 0x0112: 'FILL.AUTO', + 0x0114: 'CUSTOMIZE.TOOLBAR', + 0x0115: 'ADD.TOOL', + 0x0116: 'EDIT.OBJECT', + 0x0117: 'ON.DOUBLECLICK', + 0x0118: 'ON.ENTRY', + 0x0119: 'WORKBOOK.ADD', + 0x011A: 'WORKBOOK.MOVE', + 0x011B: 'WORKBOOK.COPY', + 0x011C: 'WORKBOOK.OPTIONS', + 0x011D: 'SAVE.WORKSPACE', + 0x0120: 'CHART.WIZARD', + 0x0121: 'DELETE.TOOL', + 0x0122: 'MOVE.TOOL', + 0x0123: 'WORKBOOK.SELECT', + 0x0124: 'WORKBOOK.ACTIVATE', + 0x0125: 'ASSIGN.TO.TOOL', + 0x0127: 'COPY.TOOL', + 0x0128: 'RESET.TOOL', + 0x0129: 'CONSTRAIN.NUMERIC', + 0x012A: 'PASTE.TOOL', + 0x012E: 'WORKBOOK.NEW', + 0x0131: 'SCENARIO.CELLS', + 0x0132: 'SCENARIO.DELETE', + 0x0133: 'SCENARIO.ADD', + 0x0134: 'SCENARIO.EDIT', + 0x0135: 'SCENARIO.SHOW', + 0x0136: 'SCENARIO.SHOW.NEXT', + 0x0137: 'SCENARIO.SUMMARY', + 0x0138: 'PIVOT.TABLE.WIZARD', + 0x0139: 'PIVOT.FIELD.PROPERTIES', + 0x013A: 'PIVOT.FIELD', + 0x013B: 'PIVOT.ITEM', + 0x013C: 'PIVOT.ADD.FIELDS', + 0x013E: 'OPTIONS.CALCULATION', + 0x013F: 'OPTIONS.EDIT', + 0x0140: 'OPTIONS.VIEW', + 0x0141: 'ADDIN.MANAGER', + 0x0142: 'MENU.EDITOR', + 0x0143: 'ATTACH.TOOLBARS', + 0x0144: 'VBAActivate', + 0x0145: 'OPTIONS.CHART', + 0x0148: 'VBA.INSERT.FILE', + 0x014A: 'VBA.PROCEDURE.DEFINITION', + 0x0150: 'ROUTING.SLIP', + 0x0152: 'ROUTE.DOCUMENT', + 0x0153: 'MAIL.LOGON', + 0x0156: 'INSERT.PICTURE', + 0x0157: 'EDIT.TOOL', + 0x0158: 'GALLERY.DOUGHNUT', + 0x015E: 'CHART.TREND', + 0x0160: 'PIVOT.ITEM.PROPERTIES', + 0x0162: 'WORKBOOK.INSERT', + 0x0163: 'OPTIONS.TRANSITION', + 0x0164: 'OPTIONS.GENERAL', + 0x0172: 'FILTER.ADVANCED', + 0x0175: 'MAIL.ADD.MAILER', + 0x0176: 'MAIL.DELETE.MAILER', + 0x0177: 'MAIL.REPLY', + 0x0178: 'MAIL.REPLY.ALL', + 0x0179: 'MAIL.FORWARD', + 0x017A: 'MAIL.NEXT.LETTER', + 0x017B: 'DATA.LABEL', + 0x017C: 'INSERT.TITLE', + 0x017D: 'FONT.PROPERTIES', + 0x017E: 'MACRO.OPTIONS', + 0x017F: 'WORKBOOK.HIDE', + 0x0180: 'WORKBOOK.UNHIDE', + 0x0181: 'WORKBOOK.DELETE', + 0x0182: 'WORKBOOK.NAME', + 0x0184: 'GALLERY.CUSTOM', + 0x0186: 'ADD.CHART.AUTOFORMAT', + 0x0187: 'DELETE.CHART.AUTOFORMAT', + 0x0188: 'CHART.ADD.DATA', + 0x0189: 'AUTO.OUTLINE', + 0x018A: 'TAB.ORDER', + 0x018B: 'SHOW.DIALOG', + 0x018C: 'SELECT.ALL', + 0x018D: 'UNGROUP.SHEETS', + 0x018E: 'SUBTOTAL.CREATE', + 0x018F: 'SUBTOTAL.REMOVE', + 0x0190: 'RENAME.OBJECT', + 0x019C: 'WORKBOOK.SCROLL', + 0x019D: 'WORKBOOK.NEXT', + 0x019E: 'WORKBOOK.PREV', + 0x019F: 'WORKBOOK.TAB.SPLIT', + 0x01A0: 'FULL.SCREEN', + 0x01A1: 'WORKBOOK.PROTECT', + 0x01A4: 'SCROLLBAR.PROPERTIES', + 0x01A5: 'PIVOT.SHOW.PAGES', + 0x01A6: 'TEXT.TO.COLUMNS', + 0x01A7: 'FORMAT.CHARTTYPE', + 0x01A8: 'LINK.FORMAT', + 0x01A9: 'TRACER.DISPLAY', + 0x01AE: 'TRACER.NAVIGATE', + 0x01AF: 'TRACER.CLEAR', + 0x01B0: 'TRACER.ERROR', + 0x01B1: 'PIVOT.FIELD.GROUP', + 0x01B2: 'PIVOT.FIELD.UNGROUP', + 0x01B3: 'CHECKBOX.PROPERTIES', + 0x01B4: 'LABEL.PROPERTIES', + 0x01B5: 'LISTBOX.PROPERTIES', + 0x01B6: 'EDITBOX.PROPERTIES', + 0x01B7: 'PIVOT.REFRESH', + 0x01B8: 'LINK.COMBO', + 0x01B9: 'OPEN.TEXT', + 0x01BA: 'HIDE.DIALOG', + 0x01BB: 'SET.DIALOG.FOCUS', + 0x01BC: 'ENABLE.OBJECT', + 0x01BD: 'PUSHBUTTON.PROPERTIES', + 0x01BE: 'SET.DIALOG.DEFAULT', + 0x01BF: 'FILTER', + 0x01C0: 'FILTER.SHOW.ALL', + 0x01C1: 'CLEAR.OUTLINE', + 0x01C2: 'FUNCTION.WIZARD', + 0x01C3: 'ADD.LIST.ITEM', + 0x01C4: 'SET.LIST.ITEM', + 0x01C5: 'REMOVE.LIST.ITEM', + 0x01C6: 'SELECT.LIST.ITEM', + 0x01C7: 'SET.CONTROL.VALUE', + 0x01C8: 'SAVE.COPY.AS', + 0x01CA: 'OPTIONS.LISTS.ADD', + 0x01CB: 'OPTIONS.LISTS.DELETE', + 0x01CC: 'SERIES.AXES', + 0x01CD: 'SERIES.X', + 0x01CE: 'SERIES.Y', + 0x01CF: 'ERRORBAR.X', + 0x01D0: 'ERRORBAR.Y', + 0x01D1: 'FORMAT.CHART', + 0x01D2: 'SERIES.ORDER', + 0x01D3: 'MAIL.LOGOFF', + 0x01D4: 'CLEAR.ROUTING.SLIP', + 0x01D5: 'APP.ACTIVATE.MICROSOFT', + 0x01D6: 'MAIL.EDIT.MAILER', + 0x01D7: 'ON.SHEET', + 0x01D8: 'STANDARD.WIDTH', + 0x01D9: 'SCENARIO.MERGE', + 0x01DA: 'SUMMARY.INFO', + 0x01DB: 'FIND.FILE', + 0x01DC: 'ACTIVE.CELL.FONT', + 0x01DD: 'ENABLE.TIPWIZARD', + 0x01DE: 'VBA.MAKE.ADDIN', + 0x01E0: 'INSERTDATATABLE', + 0x01E1: 'WORKGROUP.OPTIONS', + 0x01E2: 'MAIL.SEND.MAILER', + 0x01E5: 'AUTOCORRECT', + 0x01E9: 'POST.DOCUMENT', + 0x01EB: 'PICKLIST', + 0x01ED: 'VIEW.SHOW', + 0x01EE: 'VIEW.DEFINE', + 0x01EF: 'VIEW.DELETE', + 0x01FD: 'SHEET.BACKGROUND', + 0x01FE: 'INSERT.MAP.OBJECT', + 0x01FF: 'OPTIONS.MENONO', + 0x0205: 'MSOCHECKS', + 0x0206: 'NORMAL', + 0x0207: 'LAYOUT', + 0x0208: 'RM.PRINT.AREA', + 0x0209: 'CLEAR.PRINT.AREA', + 0x020A: 'ADD.PRINT.AREA', + 0x020B: 'MOVE.BRK', + 0x0221: 'HIDECURR.NOTE', + 0x0222: 'HIDEALL.NOTES', + 0x0223: 'DELETE.NOTE', + 0x0224: 'TRAVERSE.NOTES', + 0x0225: 'ACTIVATE.NOTES', + 0x026C: 'PROTECT.REVISIONS', + 0x026D: 'UNPROTECT.REVISIONS', + 0x0287: 'OPTIONS.ME', + 0x028D: 'WEB.PUBLISH', + 0x029B: 'NEWWEBQUERY', + 0x02A1: 'PIVOT.TABLE.CHART', + 0x02F1: 'OPTIONS.SAVE', + 0x02F3: 'OPTIONS.SPELL', + 0x0328: 'HIDEALL.INKANNOTS' + }; + + /* [MS-XLS] 2.5.198.17 */ + /* [MS-XLSB] 2.5.97.10 */ + var Ftab = { + 0x0000: 'COUNT', + 0x0001: 'IF', + 0x0002: 'ISNA', + 0x0003: 'ISERROR', + 0x0004: 'SUM', + 0x0005: 'AVERAGE', + 0x0006: 'MIN', + 0x0007: 'MAX', + 0x0008: 'ROW', + 0x0009: 'COLUMN', + 0x000A: 'NA', + 0x000B: 'NPV', + 0x000C: 'STDEV', + 0x000D: 'DOLLAR', + 0x000E: 'FIXED', + 0x000F: 'SIN', + 0x0010: 'COS', + 0x0011: 'TAN', + 0x0012: 'ATAN', + 0x0013: 'PI', + 0x0014: 'SQRT', + 0x0015: 'EXP', + 0x0016: 'LN', + 0x0017: 'LOG10', + 0x0018: 'ABS', + 0x0019: 'INT', + 0x001A: 'SIGN', + 0x001B: 'ROUND', + 0x001C: 'LOOKUP', + 0x001D: 'INDEX', + 0x001E: 'REPT', + 0x001F: 'MID', + 0x0020: 'LEN', + 0x0021: 'VALUE', + 0x0022: 'TRUE', + 0x0023: 'FALSE', + 0x0024: 'AND', + 0x0025: 'OR', + 0x0026: 'NOT', + 0x0027: 'MOD', + 0x0028: 'DCOUNT', + 0x0029: 'DSUM', + 0x002A: 'DAVERAGE', + 0x002B: 'DMIN', + 0x002C: 'DMAX', + 0x002D: 'DSTDEV', + 0x002E: 'VAR', + 0x002F: 'DVAR', + 0x0030: 'TEXT', + 0x0031: 'LINEST', + 0x0032: 'TREND', + 0x0033: 'LOGEST', + 0x0034: 'GROWTH', + 0x0035: 'GOTO', + 0x0036: 'HALT', + 0x0037: 'RETURN', + 0x0038: 'PV', + 0x0039: 'FV', + 0x003A: 'NPER', + 0x003B: 'PMT', + 0x003C: 'RATE', + 0x003D: 'MIRR', + 0x003E: 'IRR', + 0x003F: 'RAND', + 0x0040: 'MATCH', + 0x0041: 'DATE', + 0x0042: 'TIME', + 0x0043: 'DAY', + 0x0044: 'MONTH', + 0x0045: 'YEAR', + 0x0046: 'WEEKDAY', + 0x0047: 'HOUR', + 0x0048: 'MINUTE', + 0x0049: 'SECOND', + 0x004A: 'NOW', + 0x004B: 'AREAS', + 0x004C: 'ROWS', + 0x004D: 'COLUMNS', + 0x004E: 'OFFSET', + 0x004F: 'ABSREF', + 0x0050: 'RELREF', + 0x0051: 'ARGUMENT', + 0x0052: 'SEARCH', + 0x0053: 'TRANSPOSE', + 0x0054: 'ERROR', + 0x0055: 'STEP', + 0x0056: 'TYPE', + 0x0057: 'ECHO', + 0x0058: 'SET.NAME', + 0x0059: 'CALLER', + 0x005A: 'DEREF', + 0x005B: 'WINDOWS', + 0x005C: 'SERIES', + 0x005D: 'DOCUMENTS', + 0x005E: 'ACTIVE.CELL', + 0x005F: 'SELECTION', + 0x0060: 'RESULT', + 0x0061: 'ATAN2', + 0x0062: 'ASIN', + 0x0063: 'ACOS', + 0x0064: 'CHOOSE', + 0x0065: 'HLOOKUP', + 0x0066: 'VLOOKUP', + 0x0067: 'LINKS', + 0x0068: 'INPUT', + 0x0069: 'ISREF', + 0x006A: 'GET.FORMULA', + 0x006B: 'GET.NAME', + 0x006C: 'SET.VALUE', + 0x006D: 'LOG', + 0x006E: 'EXEC', + 0x006F: 'CHAR', + 0x0070: 'LOWER', + 0x0071: 'UPPER', + 0x0072: 'PROPER', + 0x0073: 'LEFT', + 0x0074: 'RIGHT', + 0x0075: 'EXACT', + 0x0076: 'TRIM', + 0x0077: 'REPLACE', + 0x0078: 'SUBSTITUTE', + 0x0079: 'CODE', + 0x007A: 'NAMES', + 0x007B: 'DIRECTORY', + 0x007C: 'FIND', + 0x007D: 'CELL', + 0x007E: 'ISERR', + 0x007F: 'ISTEXT', + 0x0080: 'ISNUMBER', + 0x0081: 'ISBLANK', + 0x0082: 'T', + 0x0083: 'N', + 0x0084: 'FOPEN', + 0x0085: 'FCLOSE', + 0x0086: 'FSIZE', + 0x0087: 'FREADLN', + 0x0088: 'FREAD', + 0x0089: 'FWRITELN', + 0x008A: 'FWRITE', + 0x008B: 'FPOS', + 0x008C: 'DATEVALUE', + 0x008D: 'TIMEVALUE', + 0x008E: 'SLN', + 0x008F: 'SYD', + 0x0090: 'DDB', + 0x0091: 'GET.DEF', + 0x0092: 'REFTEXT', + 0x0093: 'TEXTREF', + 0x0094: 'INDIRECT', + 0x0095: 'REGISTER', + 0x0096: 'CALL', + 0x0097: 'ADD.BAR', + 0x0098: 'ADD.MENU', + 0x0099: 'ADD.COMMAND', + 0x009A: 'ENABLE.COMMAND', + 0x009B: 'CHECK.COMMAND', + 0x009C: 'RENAME.COMMAND', + 0x009D: 'SHOW.BAR', + 0x009E: 'DELETE.MENU', + 0x009F: 'DELETE.COMMAND', + 0x00A0: 'GET.CHART.ITEM', + 0x00A1: 'DIALOG.BOX', + 0x00A2: 'CLEAN', + 0x00A3: 'MDETERM', + 0x00A4: 'MINVERSE', + 0x00A5: 'MMULT', + 0x00A6: 'FILES', + 0x00A7: 'IPMT', + 0x00A8: 'PPMT', + 0x00A9: 'COUNTA', + 0x00AA: 'CANCEL.KEY', + 0x00AB: 'FOR', + 0x00AC: 'WHILE', + 0x00AD: 'BREAK', + 0x00AE: 'NEXT', + 0x00AF: 'INITIATE', + 0x00B0: 'REQUEST', + 0x00B1: 'POKE', + 0x00B2: 'EXECUTE', + 0x00B3: 'TERMINATE', + 0x00B4: 'RESTART', + 0x00B5: 'HELP', + 0x00B6: 'GET.BAR', + 0x00B7: 'PRODUCT', + 0x00B8: 'FACT', + 0x00B9: 'GET.CELL', + 0x00BA: 'GET.WORKSPACE', + 0x00BB: 'GET.WINDOW', + 0x00BC: 'GET.DOCUMENT', + 0x00BD: 'DPRODUCT', + 0x00BE: 'ISNONTEXT', + 0x00BF: 'GET.NOTE', + 0x00C0: 'NOTE', + 0x00C1: 'STDEVP', + 0x00C2: 'VARP', + 0x00C3: 'DSTDEVP', + 0x00C4: 'DVARP', + 0x00C5: 'TRUNC', + 0x00C6: 'ISLOGICAL', + 0x00C7: 'DCOUNTA', + 0x00C8: 'DELETE.BAR', + 0x00C9: 'UNREGISTER', + 0x00CC: 'USDOLLAR', + 0x00CD: 'FINDB', + 0x00CE: 'SEARCHB', + 0x00CF: 'REPLACEB', + 0x00D0: 'LEFTB', + 0x00D1: 'RIGHTB', + 0x00D2: 'MIDB', + 0x00D3: 'LENB', + 0x00D4: 'ROUNDUP', + 0x00D5: 'ROUNDDOWN', + 0x00D6: 'ASC', + 0x00D7: 'DBCS', + 0x00D8: 'RANK', + 0x00DB: 'ADDRESS', + 0x00DC: 'DAYS360', + 0x00DD: 'TODAY', + 0x00DE: 'VDB', + 0x00DF: 'ELSE', + 0x00E0: 'ELSE.IF', + 0x00E1: 'END.IF', + 0x00E2: 'FOR.CELL', + 0x00E3: 'MEDIAN', + 0x00E4: 'SUMPRODUCT', + 0x00E5: 'SINH', + 0x00E6: 'COSH', + 0x00E7: 'TANH', + 0x00E8: 'ASINH', + 0x00E9: 'ACOSH', + 0x00EA: 'ATANH', + 0x00EB: 'DGET', + 0x00EC: 'CREATE.OBJECT', + 0x00ED: 'VOLATILE', + 0x00EE: 'LAST.ERROR', + 0x00EF: 'CUSTOM.UNDO', + 0x00F0: 'CUSTOM.REPEAT', + 0x00F1: 'FORMULA.CONVERT', + 0x00F2: 'GET.LINK.INFO', + 0x00F3: 'TEXT.BOX', + 0x00F4: 'INFO', + 0x00F5: 'GROUP', + 0x00F6: 'GET.OBJECT', + 0x00F7: 'DB', + 0x00F8: 'PAUSE', + 0x00FB: 'RESUME', + 0x00FC: 'FREQUENCY', + 0x00FD: 'ADD.TOOLBAR', + 0x00FE: 'DELETE.TOOLBAR', + 0x00FF: 'User', + 0x0100: 'RESET.TOOLBAR', + 0x0101: 'EVALUATE', + 0x0102: 'GET.TOOLBAR', + 0x0103: 'GET.TOOL', + 0x0104: 'SPELLING.CHECK', + 0x0105: 'ERROR.TYPE', + 0x0106: 'APP.TITLE', + 0x0107: 'WINDOW.TITLE', + 0x0108: 'SAVE.TOOLBAR', + 0x0109: 'ENABLE.TOOL', + 0x010A: 'PRESS.TOOL', + 0x010B: 'REGISTER.ID', + 0x010C: 'GET.WORKBOOK', + 0x010D: 'AVEDEV', + 0x010E: 'BETADIST', + 0x010F: 'GAMMALN', + 0x0110: 'BETAINV', + 0x0111: 'BINOMDIST', + 0x0112: 'CHIDIST', + 0x0113: 'CHIINV', + 0x0114: 'COMBIN', + 0x0115: 'CONFIDENCE', + 0x0116: 'CRITBINOM', + 0x0117: 'EVEN', + 0x0118: 'EXPONDIST', + 0x0119: 'FDIST', + 0x011A: 'FINV', + 0x011B: 'FISHER', + 0x011C: 'FISHERINV', + 0x011D: 'FLOOR', + 0x011E: 'GAMMADIST', + 0x011F: 'GAMMAINV', + 0x0120: 'CEILING', + 0x0121: 'HYPGEOMDIST', + 0x0122: 'LOGNORMDIST', + 0x0123: 'LOGINV', + 0x0124: 'NEGBINOMDIST', + 0x0125: 'NORMDIST', + 0x0126: 'NORMSDIST', + 0x0127: 'NORMINV', + 0x0128: 'NORMSINV', + 0x0129: 'STANDARDIZE', + 0x012A: 'ODD', + 0x012B: 'PERMUT', + 0x012C: 'POISSON', + 0x012D: 'TDIST', + 0x012E: 'WEIBULL', + 0x012F: 'SUMXMY2', + 0x0130: 'SUMX2MY2', + 0x0131: 'SUMX2PY2', + 0x0132: 'CHITEST', + 0x0133: 'CORREL', + 0x0134: 'COVAR', + 0x0135: 'FORECAST', + 0x0136: 'FTEST', + 0x0137: 'INTERCEPT', + 0x0138: 'PEARSON', + 0x0139: 'RSQ', + 0x013A: 'STEYX', + 0x013B: 'SLOPE', + 0x013C: 'TTEST', + 0x013D: 'PROB', + 0x013E: 'DEVSQ', + 0x013F: 'GEOMEAN', + 0x0140: 'HARMEAN', + 0x0141: 'SUMSQ', + 0x0142: 'KURT', + 0x0143: 'SKEW', + 0x0144: 'ZTEST', + 0x0145: 'LARGE', + 0x0146: 'SMALL', + 0x0147: 'QUARTILE', + 0x0148: 'PERCENTILE', + 0x0149: 'PERCENTRANK', + 0x014A: 'MODE', + 0x014B: 'TRIMMEAN', + 0x014C: 'TINV', + 0x014E: 'MOVIE.COMMAND', + 0x014F: 'GET.MOVIE', + 0x0150: 'CONCATENATE', + 0x0151: 'POWER', + 0x0152: 'PIVOT.ADD.DATA', + 0x0153: 'GET.PIVOT.TABLE', + 0x0154: 'GET.PIVOT.FIELD', + 0x0155: 'GET.PIVOT.ITEM', + 0x0156: 'RADIANS', + 0x0157: 'DEGREES', + 0x0158: 'SUBTOTAL', + 0x0159: 'SUMIF', + 0x015A: 'COUNTIF', + 0x015B: 'COUNTBLANK', + 0x015C: 'SCENARIO.GET', + 0x015D: 'OPTIONS.LISTS.GET', + 0x015E: 'ISPMT', + 0x015F: 'DATEDIF', + 0x0160: 'DATESTRING', + 0x0161: 'NUMBERSTRING', + 0x0162: 'ROMAN', + 0x0163: 'OPEN.DIALOG', + 0x0164: 'SAVE.DIALOG', + 0x0165: 'VIEW.GET', + 0x0166: 'GETPIVOTDATA', + 0x0167: 'HYPERLINK', + 0x0168: 'PHONETIC', + 0x0169: 'AVERAGEA', + 0x016A: 'MAXA', + 0x016B: 'MINA', + 0x016C: 'STDEVPA', + 0x016D: 'VARPA', + 0x016E: 'STDEVA', + 0x016F: 'VARA', + 0x0170: 'BAHTTEXT', + 0x0171: 'THAIDAYOFWEEK', + 0x0172: 'THAIDIGIT', + 0x0173: 'THAIMONTHOFYEAR', + 0x0174: 'THAINUMSOUND', + 0x0175: 'THAINUMSTRING', + 0x0176: 'THAISTRINGLENGTH', + 0x0177: 'ISTHAIDIGIT', + 0x0178: 'ROUNDBAHTDOWN', + 0x0179: 'ROUNDBAHTUP', + 0x017A: 'THAIYEAR', + 0x017B: 'RTD', + + 0x017C: 'CUBEVALUE', + 0x017D: 'CUBEMEMBER', + 0x017E: 'CUBEMEMBERPROPERTY', + 0x017F: 'CUBERANKEDMEMBER', + 0x0180: 'HEX2BIN', + 0x0181: 'HEX2DEC', + 0x0182: 'HEX2OCT', + 0x0183: 'DEC2BIN', + 0x0184: 'DEC2HEX', + 0x0185: 'DEC2OCT', + 0x0186: 'OCT2BIN', + 0x0187: 'OCT2HEX', + 0x0188: 'OCT2DEC', + 0x0189: 'BIN2DEC', + 0x018A: 'BIN2OCT', + 0x018B: 'BIN2HEX', + 0x018C: 'IMSUB', + 0x018D: 'IMDIV', + 0x018E: 'IMPOWER', + 0x018F: 'IMABS', + 0x0190: 'IMSQRT', + 0x0191: 'IMLN', + 0x0192: 'IMLOG2', + 0x0193: 'IMLOG10', + 0x0194: 'IMSIN', + 0x0195: 'IMCOS', + 0x0196: 'IMEXP', + 0x0197: 'IMARGUMENT', + 0x0198: 'IMCONJUGATE', + 0x0199: 'IMAGINARY', + 0x019A: 'IMREAL', + 0x019B: 'COMPLEX', + 0x019C: 'IMSUM', + 0x019D: 'IMPRODUCT', + 0x019E: 'SERIESSUM', + 0x019F: 'FACTDOUBLE', + 0x01A0: 'SQRTPI', + 0x01A1: 'QUOTIENT', + 0x01A2: 'DELTA', + 0x01A3: 'GESTEP', + 0x01A4: 'ISEVEN', + 0x01A5: 'ISODD', + 0x01A6: 'MROUND', + 0x01A7: 'ERF', + 0x01A8: 'ERFC', + 0x01A9: 'BESSELJ', + 0x01AA: 'BESSELK', + 0x01AB: 'BESSELY', + 0x01AC: 'BESSELI', + 0x01AD: 'XIRR', + 0x01AE: 'XNPV', + 0x01AF: 'PRICEMAT', + 0x01B0: 'YIELDMAT', + 0x01B1: 'INTRATE', + 0x01B2: 'RECEIVED', + 0x01B3: 'DISC', + 0x01B4: 'PRICEDISC', + 0x01B5: 'YIELDDISC', + 0x01B6: 'TBILLEQ', + 0x01B7: 'TBILLPRICE', + 0x01B8: 'TBILLYIELD', + 0x01B9: 'PRICE', + 0x01BA: 'YIELD', + 0x01BB: 'DOLLARDE', + 0x01BC: 'DOLLARFR', + 0x01BD: 'NOMINAL', + 0x01BE: 'EFFECT', + 0x01BF: 'CUMPRINC', + 0x01C0: 'CUMIPMT', + 0x01C1: 'EDATE', + 0x01C2: 'EOMONTH', + 0x01C3: 'YEARFRAC', + 0x01C4: 'COUPDAYBS', + 0x01C5: 'COUPDAYS', + 0x01C6: 'COUPDAYSNC', + 0x01C7: 'COUPNCD', + 0x01C8: 'COUPNUM', + 0x01C9: 'COUPPCD', + 0x01CA: 'DURATION', + 0x01CB: 'MDURATION', + 0x01CC: 'ODDLPRICE', + 0x01CD: 'ODDLYIELD', + 0x01CE: 'ODDFPRICE', + 0x01CF: 'ODDFYIELD', + 0x01D0: 'RANDBETWEEN', + 0x01D1: 'WEEKNUM', + 0x01D2: 'AMORDEGRC', + 0x01D3: 'AMORLINC', + 0x01D4: 'CONVERT', + 0x02D4: 'SHEETJS', + 0x01D5: 'ACCRINT', + 0x01D6: 'ACCRINTM', + 0x01D7: 'WORKDAY', + 0x01D8: 'NETWORKDAYS', + 0x01D9: 'GCD', + 0x01DA: 'MULTINOMIAL', + 0x01DB: 'LCM', + 0x01DC: 'FVSCHEDULE', + 0x01DD: 'CUBEKPIMEMBER', + 0x01DE: 'CUBESET', + 0x01DF: 'CUBESETCOUNT', + 0x01E0: 'IFERROR', + 0x01E1: 'COUNTIFS', + 0x01E2: 'SUMIFS', + 0x01E3: 'AVERAGEIF', + 0x01E4: 'AVERAGEIFS' + }; + var FtabArgc = { + 0x0002: 1, /* ISNA */ + 0x0003: 1, /* ISERROR */ + 0x000A: 0, /* NA */ + 0x000F: 1, /* SIN */ + 0x0010: 1, /* COS */ + 0x0011: 1, /* TAN */ + 0x0012: 1, /* ATAN */ + 0x0013: 0, /* PI */ + 0x0014: 1, /* SQRT */ + 0x0015: 1, /* EXP */ + 0x0016: 1, /* LN */ + 0x0017: 1, /* LOG10 */ + 0x0018: 1, /* ABS */ + 0x0019: 1, /* INT */ + 0x001A: 1, /* SIGN */ + 0x001B: 2, /* ROUND */ + 0x001E: 2, /* REPT */ + 0x001F: 3, /* MID */ + 0x0020: 1, /* LEN */ + 0x0021: 1, /* VALUE */ + 0x0022: 0, /* TRUE */ + 0x0023: 0, /* FALSE */ + 0x0026: 1, /* NOT */ + 0x0027: 2, /* MOD */ + 0x0028: 3, /* DCOUNT */ + 0x0029: 3, /* DSUM */ + 0x002A: 3, /* DAVERAGE */ + 0x002B: 3, /* DMIN */ + 0x002C: 3, /* DMAX */ + 0x002D: 3, /* DSTDEV */ + 0x002F: 3, /* DVAR */ + 0x0030: 2, /* TEXT */ + 0x0035: 1, /* GOTO */ + 0x003D: 3, /* MIRR */ + 0x003F: 0, /* RAND */ + 0x0041: 3, /* DATE */ + 0x0042: 3, /* TIME */ + 0x0043: 1, /* DAY */ + 0x0044: 1, /* MONTH */ + 0x0045: 1, /* YEAR */ + 0x0046: 1, /* WEEKDAY */ + 0x0047: 1, /* HOUR */ + 0x0048: 1, /* MINUTE */ + 0x0049: 1, /* SECOND */ + 0x004A: 0, /* NOW */ + 0x004B: 1, /* AREAS */ + 0x004C: 1, /* ROWS */ + 0x004D: 1, /* COLUMNS */ + 0x004F: 2, /* ABSREF */ + 0x0050: 2, /* RELREF */ + 0x0053: 1, /* TRANSPOSE */ + 0x0055: 0, /* STEP */ + 0x0056: 1, /* TYPE */ + 0x0059: 0, /* CALLER */ + 0x005A: 1, /* DEREF */ + 0x005E: 0, /* ACTIVE.CELL */ + 0x005F: 0, /* SELECTION */ + 0x0061: 2, /* ATAN2 */ + 0x0062: 1, /* ASIN */ + 0x0063: 1, /* ACOS */ + 0x0065: 3, /* HLOOKUP */ + 0x0066: 3, /* VLOOKUP */ + 0x0069: 1, /* ISREF */ + 0x006A: 1, /* GET.FORMULA */ + 0x006C: 2, /* SET.VALUE */ + 0x006F: 1, /* CHAR */ + 0x0070: 1, /* LOWER */ + 0x0071: 1, /* UPPER */ + 0x0072: 1, /* PROPER */ + 0x0075: 2, /* EXACT */ + 0x0076: 1, /* TRIM */ + 0x0077: 4, /* REPLACE */ + 0x0079: 1, /* CODE */ + 0x007E: 1, /* ISERR */ + 0x007F: 1, /* ISTEXT */ + 0x0080: 1, /* ISNUMBER */ + 0x0081: 1, /* ISBLANK */ + 0x0082: 1, /* T */ + 0x0083: 1, /* N */ + 0x0085: 1, /* FCLOSE */ + 0x0086: 1, /* FSIZE */ + 0x0087: 1, /* FREADLN */ + 0x0088: 2, /* FREAD */ + 0x0089: 2, /* FWRITELN */ + 0x008A: 2, /* FWRITE */ + 0x008C: 1, /* DATEVALUE */ + 0x008D: 1, /* TIMEVALUE */ + 0x008E: 3, /* SLN */ + 0x008F: 4, /* SYD */ + 0x0090: 4, /* DDB */ + 0x00A1: 1, /* DIALOG.BOX */ + 0x00A2: 1, /* CLEAN */ + 0x00A3: 1, /* MDETERM */ + 0x00A4: 1, /* MINVERSE */ + 0x00A5: 2, /* MMULT */ + 0x00AC: 1, /* WHILE */ + 0x00AF: 2, /* INITIATE */ + 0x00B0: 2, /* REQUEST */ + 0x00B1: 3, /* POKE */ + 0x00B2: 2, /* EXECUTE */ + 0x00B3: 1, /* TERMINATE */ + 0x00B8: 1, /* FACT */ + 0x00BA: 1, /* GET.WORKSPACE */ + 0x00BD: 3, /* DPRODUCT */ + 0x00BE: 1, /* ISNONTEXT */ + 0x00C3: 3, /* DSTDEVP */ + 0x00C4: 3, /* DVARP */ + 0x00C5: 1, /* TRUNC */ + 0x00C6: 1, /* ISLOGICAL */ + 0x00C7: 3, /* DCOUNTA */ + 0x00C9: 1, /* UNREGISTER */ + 0x00CF: 4, /* REPLACEB */ + 0x00D2: 3, /* MIDB */ + 0x00D3: 1, /* LENB */ + 0x00D4: 2, /* ROUNDUP */ + 0x00D5: 2, /* ROUNDDOWN */ + 0x00D6: 1, /* ASC */ + 0x00D7: 1, /* DBCS */ + 0x00E1: 0, /* END.IF */ + 0x00E5: 1, /* SINH */ + 0x00E6: 1, /* COSH */ + 0x00E7: 1, /* TANH */ + 0x00E8: 1, /* ASINH */ + 0x00E9: 1, /* ACOSH */ + 0x00EA: 1, /* ATANH */ + 0x00EB: 3, /* DGET */ + 0x00F4: 1, /* INFO */ + 0x00F7: 4, /* DB */ + 0x00FC: 2, /* FREQUENCY */ + 0x0101: 1, /* EVALUATE */ + 0x0105: 1, /* ERROR.TYPE */ + 0x010F: 1, /* GAMMALN */ + 0x0111: 4, /* BINOMDIST */ + 0x0112: 2, /* CHIDIST */ + 0x0113: 2, /* CHIINV */ + 0x0114: 2, /* COMBIN */ + 0x0115: 3, /* CONFIDENCE */ + 0x0116: 3, /* CRITBINOM */ + 0x0117: 1, /* EVEN */ + 0x0118: 3, /* EXPONDIST */ + 0x0119: 3, /* FDIST */ + 0x011A: 3, /* FINV */ + 0x011B: 1, /* FISHER */ + 0x011C: 1, /* FISHERINV */ + 0x011D: 2, /* FLOOR */ + 0x011E: 4, /* GAMMADIST */ + 0x011F: 3, /* GAMMAINV */ + 0x0120: 2, /* CEILING */ + 0x0121: 4, /* HYPGEOMDIST */ + 0x0122: 3, /* LOGNORMDIST */ + 0x0123: 3, /* LOGINV */ + 0x0124: 3, /* NEGBINOMDIST */ + 0x0125: 4, /* NORMDIST */ + 0x0126: 1, /* NORMSDIST */ + 0x0127: 3, /* NORMINV */ + 0x0128: 1, /* NORMSINV */ + 0x0129: 3, /* STANDARDIZE */ + 0x012A: 1, /* ODD */ + 0x012B: 2, /* PERMUT */ + 0x012C: 3, /* POISSON */ + 0x012D: 3, /* TDIST */ + 0x012E: 4, /* WEIBULL */ + 0x012F: 2, /* SUMXMY2 */ + 0x0130: 2, /* SUMX2MY2 */ + 0x0131: 2, /* SUMX2PY2 */ + 0x0132: 2, /* CHITEST */ + 0x0133: 2, /* CORREL */ + 0x0134: 2, /* COVAR */ + 0x0135: 3, /* FORECAST */ + 0x0136: 2, /* FTEST */ + 0x0137: 2, /* INTERCEPT */ + 0x0138: 2, /* PEARSON */ + 0x0139: 2, /* RSQ */ + 0x013A: 2, /* STEYX */ + 0x013B: 2, /* SLOPE */ + 0x013C: 4, /* TTEST */ + 0x0145: 2, /* LARGE */ + 0x0146: 2, /* SMALL */ + 0x0147: 2, /* QUARTILE */ + 0x0148: 2, /* PERCENTILE */ + 0x014B: 2, /* TRIMMEAN */ + 0x014C: 2, /* TINV */ + 0x0151: 2, /* POWER */ + 0x0156: 1, /* RADIANS */ + 0x0157: 1, /* DEGREES */ + 0x015A: 2, /* COUNTIF */ + 0x015B: 1, /* COUNTBLANK */ + 0x015E: 4, /* ISPMT */ + 0x015F: 3, /* DATEDIF */ + 0x0160: 1, /* DATESTRING */ + 0x0161: 2, /* NUMBERSTRING */ + 0x0168: 1, /* PHONETIC */ + 0x0170: 1, /* BAHTTEXT */ + 0x0171: 1, /* THAIDAYOFWEEK */ + 0x0172: 1, /* THAIDIGIT */ + 0x0173: 1, /* THAIMONTHOFYEAR */ + 0x0174: 1, /* THAINUMSOUND */ + 0x0175: 1, /* THAINUMSTRING */ + 0x0176: 1, /* THAISTRINGLENGTH */ + 0x0177: 1, /* ISTHAIDIGIT */ + 0x0178: 1, /* ROUNDBAHTDOWN */ + 0x0179: 1, /* ROUNDBAHTUP */ + 0x017A: 1, /* THAIYEAR */ + 0x017E: 3, /* CUBEMEMBERPROPERTY */ + 0x0181: 1, /* HEX2DEC */ + 0x0188: 1, /* OCT2DEC */ + 0x0189: 1, /* BIN2DEC */ + 0x018C: 2, /* IMSUB */ + 0x018D: 2, /* IMDIV */ + 0x018E: 2, /* IMPOWER */ + 0x018F: 1, /* IMABS */ + 0x0190: 1, /* IMSQRT */ + 0x0191: 1, /* IMLN */ + 0x0192: 1, /* IMLOG2 */ + 0x0193: 1, /* IMLOG10 */ + 0x0194: 1, /* IMSIN */ + 0x0195: 1, /* IMCOS */ + 0x0196: 1, /* IMEXP */ + 0x0197: 1, /* IMARGUMENT */ + 0x0198: 1, /* IMCONJUGATE */ + 0x0199: 1, /* IMAGINARY */ + 0x019A: 1, /* IMREAL */ + 0x019E: 4, /* SERIESSUM */ + 0x019F: 1, /* FACTDOUBLE */ + 0x01A0: 1, /* SQRTPI */ + 0x01A1: 2, /* QUOTIENT */ + 0x01A4: 1, /* ISEVEN */ + 0x01A5: 1, /* ISODD */ + 0x01A6: 2, /* MROUND */ + 0x01A8: 1, /* ERFC */ + 0x01A9: 2, /* BESSELJ */ + 0x01AA: 2, /* BESSELK */ + 0x01AB: 2, /* BESSELY */ + 0x01AC: 2, /* BESSELI */ + 0x01AE: 3, /* XNPV */ + 0x01B6: 3, /* TBILLEQ */ + 0x01B7: 3, /* TBILLPRICE */ + 0x01B8: 3, /* TBILLYIELD */ + 0x01BB: 2, /* DOLLARDE */ + 0x01BC: 2, /* DOLLARFR */ + 0x01BD: 2, /* NOMINAL */ + 0x01BE: 2, /* EFFECT */ + 0x01BF: 6, /* CUMPRINC */ + 0x01C0: 6, /* CUMIPMT */ + 0x01C1: 2, /* EDATE */ + 0x01C2: 2, /* EOMONTH */ + 0x01D0: 2, /* RANDBETWEEN */ + 0x01D4: 3, /* CONVERT */ + 0x01DC: 2, /* FVSCHEDULE */ + 0x01DF: 1, /* CUBESETCOUNT */ + 0x01E0: 2, /* IFERROR */ + 0xFFFF: 0 + }; + /* [MS-XLSX] 2.2.3 Functions */ + /* [MS-XLSB] 2.5.97.10 Ftab */ + var XLSXFutureFunctions = { + "_xlfn.ACOT": "ACOT", + "_xlfn.ACOTH": "ACOTH", + "_xlfn.AGGREGATE": "AGGREGATE", + "_xlfn.ARABIC": "ARABIC", + "_xlfn.AVERAGEIF": "AVERAGEIF", + "_xlfn.AVERAGEIFS": "AVERAGEIFS", + "_xlfn.BASE": "BASE", + "_xlfn.BETA.DIST": "BETA.DIST", + "_xlfn.BETA.INV": "BETA.INV", + "_xlfn.BINOM.DIST": "BINOM.DIST", + "_xlfn.BINOM.DIST.RANGE": "BINOM.DIST.RANGE", + "_xlfn.BINOM.INV": "BINOM.INV", + "_xlfn.BITAND": "BITAND", + "_xlfn.BITLSHIFT": "BITLSHIFT", + "_xlfn.BITOR": "BITOR", + "_xlfn.BITRSHIFT": "BITRSHIFT", + "_xlfn.BITXOR": "BITXOR", + "_xlfn.CEILING.MATH": "CEILING.MATH", + "_xlfn.CEILING.PRECISE": "CEILING.PRECISE", + "_xlfn.CHISQ.DIST": "CHISQ.DIST", + "_xlfn.CHISQ.DIST.RT": "CHISQ.DIST.RT", + "_xlfn.CHISQ.INV": "CHISQ.INV", + "_xlfn.CHISQ.INV.RT": "CHISQ.INV.RT", + "_xlfn.CHISQ.TEST": "CHISQ.TEST", + "_xlfn.COMBINA": "COMBINA", + "_xlfn.CONCAT": "CONCAT", + "_xlfn.CONFIDENCE.NORM": "CONFIDENCE.NORM", + "_xlfn.CONFIDENCE.T": "CONFIDENCE.T", + "_xlfn.COT": "COT", + "_xlfn.COTH": "COTH", + "_xlfn.COUNTIFS": "COUNTIFS", + "_xlfn.COVARIANCE.P": "COVARIANCE.P", + "_xlfn.COVARIANCE.S": "COVARIANCE.S", + "_xlfn.CSC": "CSC", + "_xlfn.CSCH": "CSCH", + "_xlfn.DAYS": "DAYS", + "_xlfn.DECIMAL": "DECIMAL", + "_xlfn.ECMA.CEILING": "ECMA.CEILING", + "_xlfn.ERF.PRECISE": "ERF.PRECISE", + "_xlfn.ERFC.PRECISE": "ERFC.PRECISE", + "_xlfn.EXPON.DIST": "EXPON.DIST", + "_xlfn.F.DIST": "F.DIST", + "_xlfn.F.DIST.RT": "F.DIST.RT", + "_xlfn.F.INV": "F.INV", + "_xlfn.F.INV.RT": "F.INV.RT", + "_xlfn.F.TEST": "F.TEST", + "_xlfn.FILTERXML": "FILTERXML", + "_xlfn.FLOOR.MATH": "FLOOR.MATH", + "_xlfn.FLOOR.PRECISE": "FLOOR.PRECISE", + "_xlfn.FORECAST.ETS": "FORECAST.ETS", + "_xlfn.FORECAST.ETS.CONFINT": "FORECAST.ETS.CONFINT", + "_xlfn.FORECAST.ETS.SEASONALITY": "FORECAST.ETS.SEASONALITY", + "_xlfn.FORECAST.ETS.STAT": "FORECAST.ETS.STAT", + "_xlfn.FORECAST.LINEAR": "FORECAST.LINEAR", + "_xlfn.FORMULATEXT": "FORMULATEXT", + "_xlfn.GAMMA": "GAMMA", + "_xlfn.GAMMA.DIST": "GAMMA.DIST", + "_xlfn.GAMMA.INV": "GAMMA.INV", + "_xlfn.GAMMALN.PRECISE": "GAMMALN.PRECISE", + "_xlfn.GAUSS": "GAUSS", + "_xlfn.HYPGEOM.DIST": "HYPGEOM.DIST", + "_xlfn.IFERROR": "IFERROR", + "_xlfn.IFNA": "IFNA", + "_xlfn.IFS": "IFS", + "_xlfn.IMCOSH": "IMCOSH", + "_xlfn.IMCOT": "IMCOT", + "_xlfn.IMCSC": "IMCSC", + "_xlfn.IMCSCH": "IMCSCH", + "_xlfn.IMSEC": "IMSEC", + "_xlfn.IMSECH": "IMSECH", + "_xlfn.IMSINH": "IMSINH", + "_xlfn.IMTAN": "IMTAN", + "_xlfn.ISFORMULA": "ISFORMULA", + "_xlfn.ISO.CEILING": "ISO.CEILING", + "_xlfn.ISOWEEKNUM": "ISOWEEKNUM", + "_xlfn.LOGNORM.DIST": "LOGNORM.DIST", + "_xlfn.LOGNORM.INV": "LOGNORM.INV", + "_xlfn.MAXIFS": "MAXIFS", + "_xlfn.MINIFS": "MINIFS", + "_xlfn.MODE.MULT": "MODE.MULT", + "_xlfn.MODE.SNGL": "MODE.SNGL", + "_xlfn.MUNIT": "MUNIT", + "_xlfn.NEGBINOM.DIST": "NEGBINOM.DIST", + "_xlfn.NETWORKDAYS.INTL": "NETWORKDAYS.INTL", + "_xlfn.NIGBINOM": "NIGBINOM", + "_xlfn.NORM.DIST": "NORM.DIST", + "_xlfn.NORM.INV": "NORM.INV", + "_xlfn.NORM.S.DIST": "NORM.S.DIST", + "_xlfn.NORM.S.INV": "NORM.S.INV", + "_xlfn.NUMBERVALUE": "NUMBERVALUE", + "_xlfn.PDURATION": "PDURATION", + "_xlfn.PERCENTILE.EXC": "PERCENTILE.EXC", + "_xlfn.PERCENTILE.INC": "PERCENTILE.INC", + "_xlfn.PERCENTRANK.EXC": "PERCENTRANK.EXC", + "_xlfn.PERCENTRANK.INC": "PERCENTRANK.INC", + "_xlfn.PERMUTATIONA": "PERMUTATIONA", + "_xlfn.PHI": "PHI", + "_xlfn.POISSON.DIST": "POISSON.DIST", + "_xlfn.QUARTILE.EXC": "QUARTILE.EXC", + "_xlfn.QUARTILE.INC": "QUARTILE.INC", + "_xlfn.QUERYSTRING": "QUERYSTRING", + "_xlfn.RANK.AVG": "RANK.AVG", + "_xlfn.RANK.EQ": "RANK.EQ", + "_xlfn.RRI": "RRI", + "_xlfn.SEC": "SEC", + "_xlfn.SECH": "SECH", + "_xlfn.SHEET": "SHEET", + "_xlfn.SHEETS": "SHEETS", + "_xlfn.SKEW.P": "SKEW.P", + "_xlfn.STDEV.P": "STDEV.P", + "_xlfn.STDEV.S": "STDEV.S", + "_xlfn.SUMIFS": "SUMIFS", + "_xlfn.SWITCH": "SWITCH", + "_xlfn.T.DIST": "T.DIST", + "_xlfn.T.DIST.2T": "T.DIST.2T", + "_xlfn.T.DIST.RT": "T.DIST.RT", + "_xlfn.T.INV": "T.INV", + "_xlfn.T.INV.2T": "T.INV.2T", + "_xlfn.T.TEST": "T.TEST", + "_xlfn.TEXTJOIN": "TEXTJOIN", + "_xlfn.UNICHAR": "UNICHAR", + "_xlfn.UNICODE": "UNICODE", + "_xlfn.VAR.P": "VAR.P", + "_xlfn.VAR.S": "VAR.S", + "_xlfn.WEBSERVICE": "WEBSERVICE", + "_xlfn.WEIBULL.DIST": "WEIBULL.DIST", + "_xlfn.WORKDAY.INTL": "WORKDAY.INTL", + "_xlfn.XOR": "XOR", + "_xlfn.Z.TEST": "Z.TEST" + }; + + /* Part 3 TODO: actually parse formulae */ + function ods_to_csf_formula(f) { + if(f.slice(0,3) == "of:") f = f.slice(3); + /* 5.2 Basic Expressions */ + if(f.charCodeAt(0) == 61) { + f = f.slice(1); + if(f.charCodeAt(0) == 61) f = f.slice(1); + } + f = f.replace(/COM\.MICROSOFT\./g, ""); + /* Part 3 Section 5.8 References */ + f = f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, function($$, $1) { return $1.replace(/\./g,""); }); + /* TODO: something other than this */ + f = f.replace(/\[.(#[A-Z]*[?!])\]/g, "$1"); + return f.replace(/[;~]/g,",").replace(/\|/g,";"); + } + + function csf_to_ods_formula(f) { + var o = "of:=" + f.replace(crefregex, "$1[.$2$3$4$5]").replace(/\]:\[/g,":"); + /* TODO: something other than this */ + return o.replace(/;/g, "|").replace(/,/g,";"); + } + + function ods_to_csf_3D(r) { + var a = r.split(":"); + var s = a[0].split(".")[0]; + return [s, a[0].split(".")[1] + (a.length > 1 ? (":" + (a[1].split(".")[1] || a[1].split(".")[0])) : "")]; + } + + function csf_to_ods_3D(r) { + return r.replace(/\./,"!"); + } + + var strs = {}; // shared strings + var _ssfopts = {}; // spreadsheet formatting options + + RELS.WS = [ + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet", + "http://purl.oclc.org/ooxml/officeDocument/relationships/worksheet" + ]; + + /*global Map */ + var browser_has_Map = typeof Map !== 'undefined'; + + function get_sst_id(sst, str, rev) { + var i = 0, len = sst.length; + if(rev) { + if(browser_has_Map ? rev.has(str) : rev.hasOwnProperty(str)) { + var revarr = browser_has_Map ? rev.get(str) : rev[str]; + for(; i < revarr.length; ++i) { + if(sst[revarr[i]].t === str) { sst.Count ++; return revarr[i]; } + } + } + } else for(; i < len; ++i) { + if(sst[i].t === str) { sst.Count ++; return i; } + } + sst[len] = ({t:str}); sst.Count ++; sst.Unique ++; + if(rev) { + if(browser_has_Map) { + if(!rev.has(str)) rev.set(str, []); + rev.get(str).push(len); + } else { + if(!rev.hasOwnProperty(str)) rev[str] = []; + rev[str].push(len); + } + } + return len; + } + + function col_obj_w(C, col) { + var p = ({min:C+1,max:C+1}); + /* wch (chars), wpx (pixels) */ + var wch = -1; + if(col.MDW) MDW = col.MDW; + if(col.width != null) p.customWidth = 1; + else if(col.wpx != null) wch = px2char(col.wpx); + else if(col.wch != null) wch = col.wch; + if(wch > -1) { p.width = char2width(wch); p.customWidth = 1; } + else if(col.width != null) p.width = col.width; + if(col.hidden) p.hidden = true; + return p; + } + + function default_margins(margins, mode) { + if(!margins) return; + var defs = [0.7, 0.7, 0.75, 0.75, 0.3, 0.3]; + if(mode == 'xlml') defs = [1, 1, 1, 1, 0.5, 0.5]; + if(margins.left == null) margins.left = defs[0]; + if(margins.right == null) margins.right = defs[1]; + if(margins.top == null) margins.top = defs[2]; + if(margins.bottom == null) margins.bottom = defs[3]; + if(margins.header == null) margins.header = defs[4]; + if(margins.footer == null) margins.footer = defs[5]; + } + + function get_cell_style(styles, cell, opts) { + if (typeof style_builder != 'undefined') { + if (/^\d+$/.exec(cell.s)) { return cell.s} // if its already an integer index, let it be + if (cell.s && (cell.s == +cell.s)) { return cell.s} // if its already an integer index, let it be + var s = cell.s || {}; + if (cell.z) s.numFmt = cell.z; + return style_builder.addStyle(s); + } + else { + var z = opts.revssf[cell.z != null ? cell.z : "General"]; + var i = 0x3c, len = styles.length; + if (z == null && opts.ssf) { + for (; i < 0x188; ++i) if (opts.ssf[i] == null) { + SSF.load(cell.z, i); + // $FlowIgnore + opts.ssf[i] = cell.z; + opts.revssf[cell.z] = z = i; + break; + } + } + for (i = 0; i != len; ++i) if (styles[i].numFmtId === z) return i; + styles[len] = { + numFmtId: z, + fontId: 0, + fillId: 0, + borderId: 0, + xfId: 0, + applyNumberFormat: 1 + }; + return len; + } + } + + function safe_format(p, fmtid, fillid, opts, themes, styles) { + if(p.t === 'z') return; + if(p.t === 'd' && typeof p.v === 'string') p.v = parseDate(p.v); + try { + if(opts.cellNF) p.z = SSF._table[fmtid]; + } catch(e) { if(opts.WTF) throw e; } + if(!opts || opts.cellText !== false) try { + if(SSF._table[fmtid] == null) SSF.load(SSFImplicit[fmtid] || "General", fmtid); + if(p.t === 'e') p.w = p.w || BErr[p.v]; + else if(fmtid === 0) { + if(p.t === 'n') { + if((p.v|0) === p.v) p.w = SSF._general_int(p.v); + else p.w = SSF._general_num(p.v); + } + else if(p.t === 'd') { + var dd = datenum(p.v); + if((dd|0) === dd) p.w = SSF._general_int(dd); + else p.w = SSF._general_num(dd); + } + else if(p.v === undefined) return ""; + else p.w = SSF._general(p.v,_ssfopts); + } + else if(p.t === 'd') p.w = SSF.format(fmtid,datenum(p.v),_ssfopts); + else p.w = SSF.format(fmtid,p.v,_ssfopts); + } catch(e) { if(opts.WTF) throw e; } + if(!opts.cellStyles) return; + if(fillid != null) try { + p.s = styles.Fills[fillid]; + if (p.s.fgColor && p.s.fgColor.theme && !p.s.fgColor.rgb) { + p.s.fgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.fgColor.theme].rgb, p.s.fgColor.tint || 0); + if(opts.WTF) p.s.fgColor.raw_rgb = themes.themeElements.clrScheme[p.s.fgColor.theme].rgb; + } + if (p.s.bgColor && p.s.bgColor.theme) { + p.s.bgColor.rgb = rgb_tint(themes.themeElements.clrScheme[p.s.bgColor.theme].rgb, p.s.bgColor.tint || 0); + if(opts.WTF) p.s.bgColor.raw_rgb = themes.themeElements.clrScheme[p.s.bgColor.theme].rgb; + } + } catch(e) { if(opts.WTF && styles.Fills) throw e; } + } + + function check_ws(ws, sname, i) { + if(ws && ws['!ref']) { + var range = safe_decode_range(ws['!ref']); + if(range.e.c < range.s.c || range.e.r < range.s.r) throw new Error("Bad range (" + i + "): " + ws['!ref']); + } + } + function parse_ws_xml_dim(ws, s) { + var d = safe_decode_range(s); + if(d.s.r<=d.e.r && d.s.c<=d.e.c && d.s.r>=0 && d.s.c>=0) ws["!ref"] = encode_range(d); + } + var mergecregex = /<(?:\w:)?mergeCell ref="[A-Z0-9:]+"\s*[\/]?>/g; + var sheetdataregex = /<(?:\w+:)?sheetData>([\s\S]*)<\/(?:\w+:)?sheetData>/; + var hlinkregex = /<(?:\w:)?hyperlink [^>]*>/mg; + var dimregex = /"(\w*:\w*)"/; + var colregex = /<(?:\w:)?col\b[^>]*[\/]?>/g; + var afregex = /<(?:\w:)?autoFilter[^>]*([\/]|>([\s\S]*)<\/(?:\w:)?autoFilter)>/g; + var marginregex= /<(?:\w:)?pageMargins[^>]*\/>/g; + var sheetprregex = /<(?:\w:)?sheetPr\b(?:[^>a-z][^>]*)?\/>/; + var svsregex = /<(?:\w:)?sheetViews[^>]*(?:[\/]|>([\s\S]*)<\/(?:\w:)?sheetViews)>/; + /* 18.3 Worksheets */ + function parse_ws_xml(data, opts, idx, rels, wb, themes, styles) { + if(!data) return data; + if(DENSE != null && opts.dense == null) opts.dense = DENSE; + + /* 18.3.1.99 worksheet CT_Worksheet */ + var s = opts.dense ? ([]) : ({}); + var refguess = ({s: {r:2000000, c:2000000}, e: {r:0, c:0} }); + + var data1 = "", data2 = ""; + var mtch = data.match(sheetdataregex); + if(mtch) { + data1 = data.slice(0, mtch.index); + data2 = data.slice(mtch.index + mtch[0].length); + } else data1 = data2 = data; + + /* 18.3.1.82 sheetPr CT_SheetPr */ + var sheetPr = data1.match(sheetprregex); + if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx); + + /* 18.3.1.35 dimension CT_SheetDimension */ + // $FlowIgnore + var ridx = (data1.match(/<(?:\w*:)?dimension/)||{index:-1}).index; + if(ridx > 0) { + var ref = data1.slice(ridx,ridx+50).match(dimregex); + if(ref) parse_ws_xml_dim(s, ref[1]); + } + + /* 18.3.1.88 sheetViews CT_SheetViews */ + var svs = data1.match(svsregex); + if(svs && svs[1]) parse_ws_xml_sheetviews(svs[1], wb); + + /* 18.3.1.17 cols CT_Cols */ + var columns = []; + if(opts.cellStyles) { + /* 18.3.1.13 col CT_Col */ + var cols = data1.match(colregex); + if(cols) parse_ws_xml_cols(columns, cols); + } + + /* 18.3.1.80 sheetData CT_SheetData ? */ + if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles); + + /* 18.3.1.2 autoFilter CT_AutoFilter */ + var afilter = data2.match(afregex); + if(afilter) s['!autofilter'] = parse_ws_xml_autofilter(afilter[0]); + + /* 18.3.1.55 mergeCells CT_MergeCells */ + var merges = []; + var _merge = data2.match(mergecregex); + if(_merge) for(ridx = 0; ridx != _merge.length; ++ridx) + merges[ridx] = safe_decode_range(_merge[ridx].slice(_merge[ridx].indexOf("\"")+1)); + + /* 18.3.1.48 hyperlinks CT_Hyperlinks */ + var hlink = data2.match(hlinkregex); + if(hlink) parse_ws_xml_hlinks(s, hlink, rels); + + /* 18.3.1.62 pageMargins CT_PageMargins */ + var margins = data2.match(marginregex); + if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0])); + + if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess); + if(opts.sheetRows > 0 && s["!ref"]) { + var tmpref = safe_decode_range(s["!ref"]); + if(opts.sheetRows <= +tmpref.e.r) { + tmpref.e.r = opts.sheetRows - 1; + if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r; + if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r; + if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c; + if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c; + s["!fullref"] = s["!ref"]; + s["!ref"] = encode_range(tmpref); + } + } + if(columns.length > 0) s["!cols"] = columns; + if(merges.length > 0) s["!merges"] = merges; + return s; + } + + function write_ws_xml_merges(merges) { + if(merges.length === 0) return ""; + var o = ''; + for(var i = 0; i != merges.length; ++i) o += ''; + return o + ''; + } + + /* 18.3.1.82-3 sheetPr CT_ChartsheetPr / CT_SheetPr */ + function parse_ws_xml_sheetpr(sheetPr, s, wb, idx) { + var data = parsexmltag(sheetPr); + if(!wb.Sheets[idx]) wb.Sheets[idx] = {}; + if(data.codeName) wb.Sheets[idx].CodeName = data.codeName; + } + + /* 18.3.1.85 sheetProtection CT_SheetProtection */ + function write_ws_xml_protection(sp) { + // algorithmName, hashValue, saltValue, spinCountpassword + var o = ({sheet:1}); + var deffalse = ["objects", "scenarios", "selectLockedCells", "selectUnlockedCells"]; + var deftrue = [ + "formatColumns", "formatRows", "formatCells", + "insertColumns", "insertRows", "insertHyperlinks", + "deleteColumns", "deleteRows", + "sort", "autoFilter", "pivotTables" + ]; + deffalse.forEach(function(n) { if(sp[n] != null && sp[n]) o[n] = "1"; }); + deftrue.forEach(function(n) { if(sp[n] != null && !sp[n]) o[n] = "0"; }); + /* TODO: algorithm */ + if(sp.password) o.password = crypto_CreatePasswordVerifier_Method1(sp.password).toString(16).toUpperCase(); + return writextag('sheetProtection', null, o); + } + + function parse_ws_xml_hlinks(s, data, rels) { + var dense = Array.isArray(s); + for(var i = 0; i != data.length; ++i) { + var val = parsexmltag(utf8read(data[i]), true); + if(!val.ref) return; + var rel = ((rels || {})['!id']||[])[val.id]; + if(rel) { + val.Target = rel.Target; + if(val.location) val.Target += "#"+val.location; + } else { + val.Target = "#" + val.location; + rel = {Target: val.Target, TargetMode: 'Internal'}; + } + val.Rel = rel; + if(val.tooltip) { val.Tooltip = val.tooltip; delete val.tooltip; } + var rng = safe_decode_range(val.ref); + for(var R=rng.s.r;R<=rng.e.r;++R) for(var C=rng.s.c;C<=rng.e.c;++C) { + var addr = encode_cell({c:C,r:R}); + if(dense) { + if(!s[R]) s[R] = []; + if(!s[R][C]) s[R][C] = {t:"z",v:undefined}; + s[R][C].l = val; + } else { + if(!s[addr]) s[addr] = {t:"z",v:undefined}; + s[addr].l = val; + } + } + } + } + + function parse_ws_xml_margins(margin) { + var o = {}; + ["left", "right", "top", "bottom", "header", "footer"].forEach(function(k) { + if(margin[k]) o[k] = parseFloat(margin[k]); + }); + return o; + } + function write_ws_xml_margins(margin) { + default_margins(margin); + return writextag('pageMargins', null, margin); + } + + function parse_ws_xml_cols(columns, cols) { + var seencol = false; + for(var coli = 0; coli != cols.length; ++coli) { + var coll = parsexmltag(cols[coli], true); + if(coll.hidden) coll.hidden = parsexmlbool(coll.hidden); + var colm=parseInt(coll.min, 10)-1, colM=parseInt(coll.max,10)-1; + delete coll.min; delete coll.max; coll.width = +coll.width; + if(!seencol && coll.width) { seencol = true; find_mdw_colw(coll.width); } + process_col(coll); + while(colm <= colM) columns[colm++] = dup(coll); + } + } + + function write_ws_xml_cols(ws, cols) { + var o = [""], col; + for(var i = 0; i != cols.length; ++i) { + if(!(col = cols[i])) continue; + o[o.length] = (writextag('col', null, col_obj_w(i, col))); + } + o[o.length] = ""; + return o.join(""); + } + + function parse_ws_xml_autofilter(data) { + var o = { ref: (data.match(/ref="([^"]*)"/)||[])[1]}; + return o; + } + function write_ws_xml_autofilter(data, ws, wb, idx) { + var ref = typeof data.ref == "string" ? data.ref : encode_range(data.ref); + if(!wb.Workbook) wb.Workbook = {}; + if(!wb.Workbook.Names) wb.Workbook.Names = []; + var names = wb.Workbook.Names; + var range = decode_range(ref); + if(range.s.r == range.e.r) { range.e.r = decode_range(ws["!ref"]).e.r; ref = encode_range(range); } + for(var i = 0; i < names.length; ++i) { + var name = names[i]; + if(name.Name != '_xlnm._FilterDatabase') continue; + if(name.Sheet != idx) continue; + name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break; + } + if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref }); + return writextag("autoFilter", null, {ref:ref}); + } + + /* 18.3.1.88 sheetViews CT_SheetViews */ + /* 18.3.1.87 sheetView CT_SheetView */ + var sviewregex = /<(?:\w:)?sheetView(?:[^>a-z][^>]*)?\/>/; + function parse_ws_xml_sheetviews(data, wb) { + (data.match(sviewregex)||[]).forEach(function(r) { + var tag = parsexmltag(r); + if(parsexmlbool(tag.rightToLeft)) { + if(!wb.Views) wb.Views = [{}]; + if(!wb.Views[0]) wb.Views[0] = {}; + wb.Views[0].RTL = true; + } + }); + } + function write_ws_xml_sheetviews(ws, opts, idx, wb) { + var sview = {workbookViewId:"0"}; + // $FlowIgnore + if( (((wb||{}).Workbook||{}).Views||[])[0] ) sview.rightToLeft = wb.Workbook.Views[0].RTL ? "1" : "0"; + return writextag("sheetViews", writextag("sheetView", null, sview), {}); + } + + function write_ws_xml_cell(cell, ref, ws, opts) { + if(cell.v === undefined && cell.f === undefined || cell.t === 'z') return ""; + var vv = ""; + var oldt = cell.t, oldv = cell.v; + switch(cell.t) { + case 'b': vv = cell.v ? "1" : "0"; break; + case 'n': vv = ''+cell.v; break; + case 'e': vv = BErr[cell.v]; break; + case 'd': + if(opts.cellDates) vv = parseDate(cell.v, -1).toISOString(); + else { + cell = dup(cell); + cell.t = 'n'; + vv = ''+(cell.v = datenum(parseDate(cell.v))); + } + if(typeof cell.z === 'undefined') cell.z = SSF._table[14]; + break; + default: vv = cell.v; break; + } + var v = writetag('v', escapexml(vv)), o = ({r:ref}); + /* TODO: cell style */ + var os = get_cell_style(opts.cellXfs, cell, opts); + if(os !== 0) o.s = os; + switch(cell.t) { + case 'n': break; + case 'd': o.t = "d"; break; + case 'b': o.t = "b"; break; + case 'e': o.t = "e"; break; + default: if(cell.v == null) { delete cell.t; break; } + if(opts.bookSST) { + v = writetag('v', ''+get_sst_id(opts.Strings, cell.v, opts.revStrings)); + o.t = "s"; break; + } + o.t = "str"; break; + } + if(cell.t != oldt) { cell.t = oldt; cell.v = oldv; } + if(cell.f) { + var ff = cell.F && cell.F.slice(0, ref.length) == ref ? {t:"array", ref:cell.F} : null; + v = writextag('f', escapexml(cell.f), ff) + (cell.v != null ? v : ""); + } + if(cell.l) ws['!links'].push([ref, cell.l]); + if(cell.c) ws['!comments'].push([ref, cell.c]); + return writextag('c', v, o); + } + + var parse_ws_xml_data = (function() { + var cellregex = /<(?:\w+:)?c[ >]/, rowregex = /<\/(?:\w+:)?row>/; + var rregex = /r=["']([^"']*)["']/, isregex = /<(?:\w+:)?is>([\S\s]*?)<\/(?:\w+:)?is>/; + var refregex = /ref=["']([^"']*)["']/; + var match_v = matchtag("v"), match_f = matchtag("f"); + + return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { + var ri = 0, x = "", cells = [], cref = [], idx=0, i=0, cc=0, d="", p; + var tag, tagr = 0, tagc = 0; + var sstr, ftag; + var fmtid = 0, fillid = 0; + var do_format = Array.isArray(styles.CellXf), cf; + var arrayf = []; + var sharedf = []; + var dense = Array.isArray(s); + var rows = [], rowobj = {}, rowrite = false; + for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) { + x = marr[mt].trim(); + var xlen = x.length; + if(xlen === 0) continue; + + /* 18.3.1.73 row CT_Row */ + for(ri = 0; ri < xlen; ++ri) if(x.charCodeAt(ri) === 62) break; ++ri; + tag = parsexmltag(x.slice(0,ri), true); + tagr = tag.r != null ? parseInt(tag.r, 10) : tagr+1; tagc = -1; + if(opts.sheetRows && opts.sheetRows < tagr) continue; + if(guess.s.r > tagr - 1) guess.s.r = tagr - 1; + if(guess.e.r < tagr - 1) guess.e.r = tagr - 1; + + if(opts && opts.cellStyles) { + rowobj = {}; rowrite = false; + if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); } + if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; } + if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; } + if(rowrite) rows[tagr-1] = rowobj; + } + + /* 18.3.1.4 c CT_Cell */ + cells = x.slice(ri).split(cellregex); + for(ri = 0; ri != cells.length; ++ri) { + x = cells[ri].trim(); + if(x.length === 0) continue; + cref = x.match(rregex); idx = ri; i=0; cc=0; + x = "":"") + x; + if(cref != null && cref.length === 2) { + idx = 0; d=cref[1]; + for(i=0; i != d.length; ++i) { + if((cc=d.charCodeAt(i)-64) < 1 || cc > 26) break; + idx = 26*idx + cc; + } + --idx; + tagc = idx; + } else ++tagc; + for(i = 0; i != x.length; ++i) if(x.charCodeAt(i) === 62) break; ++i; + tag = parsexmltag(x.slice(0,i), true); + if(!tag.r) tag.r = encode_cell({r:tagr-1, c:tagc}); + d = x.slice(i); + p = ({t:""}); + + if((cref=d.match(match_v))!= null && cref[1] !== '') p.v=unescapexml(cref[1]); + if(opts.cellFormula) { + if((cref=d.match(match_f))!= null && cref[1] !== '') { + /* TODO: match against XLSXFutureFunctions */ + p.f=_xlfn(unescapexml(utf8read(cref[1]))); + if(cref[0].indexOf('t="array"') > -1) { + p.F = (d.match(refregex)||[])[1]; + if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]); + } else if(cref[0].indexOf('t="shared"') > -1) { + // TODO: parse formula + ftag = parsexmltag(cref[0]); + sharedf[parseInt(ftag.si, 10)] = [ftag, _xlfn(unescapexml(utf8read(cref[1]))), tag.r]; + } + } else if((cref=d.match(/]*\/>/))) { + ftag = parsexmltag(cref[0]); + if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r); + } + /* TODO: factor out contains logic */ + var _tag = decode_cell(tag.r); + for(i = 0; i < arrayf.length; ++i) + if(_tag.r >= arrayf[i][0].s.r && _tag.r <= arrayf[i][0].e.r) + if(_tag.c >= arrayf[i][0].s.c && _tag.c <= arrayf[i][0].e.c) + p.F = arrayf[i][1]; + } + + if(tag.t == null && p.v === undefined) { + if(p.f || p.F) { + p.v = 0; p.t = "n"; + } else if(!opts.sheetStubs) continue; + else p.t = "z"; + } + else p.t = tag.t || "n"; + if(guess.s.c > tagc) guess.s.c = tagc; + if(guess.e.c < tagc) guess.e.c = tagc; + /* 18.18.11 t ST_CellType */ + switch(p.t) { + case 'n': + if(p.v == "" || p.v == null) { + if(!opts.sheetStubs) continue; + p.t = 'z'; + } else p.v = parseFloat(p.v); + break; + case 's': + if(typeof p.v == 'undefined') { + if(!opts.sheetStubs) continue; + p.t = 'z'; + } else { + sstr = strs[parseInt(p.v, 10)]; + p.v = sstr.t; + p.r = sstr.r; + if(opts.cellHTML) p.h = sstr.h; + } + break; + case 'str': + p.t = "s"; + p.v = (p.v!=null) ? utf8read(p.v) : ''; + if(opts.cellHTML) p.h = escapehtml(p.v); + break; + case 'inlineStr': + cref = d.match(isregex); + p.t = 's'; + if(cref != null && (sstr = parse_si(cref[1]))) p.v = sstr.t; else p.v = ""; + break; + case 'b': p.v = parsexmlbool(p.v); break; + case 'd': + if(opts.cellDates) p.v = parseDate(p.v, 1); + else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; } + break; + /* error string in .w, number in .v */ + case 'e': + if(!opts || opts.cellText !== false) p.w = p.v; + p.v = RBErr[p.v]; break; + } + /* formatting */ + fmtid = fillid = 0; + if(do_format && tag.s !== undefined) { + cf = styles.CellXf[tag.s]; + if(cf != null) { + if(cf.numFmtId != null) fmtid = cf.numFmtId; + if(opts.cellStyles) { + if(cf.fillId != null) fillid = cf.fillId; + } + } + } + safe_format(p, fmtid, fillid, opts, themes, styles); + if(opts.cellDates && do_format && p.t == 'n' && SSF.is_date(SSF._table[fmtid])) { p.t = 'd'; p.v = numdate(p.v); } + if(dense) { + var _r = decode_cell(tag.r); + if(!s[_r.r]) s[_r.r] = []; + s[_r.r][_r.c] = p; + } else s[tag.r] = p; + } + } + if(rows.length > 0) s['!rows'] = rows; + }; })(); + + function write_ws_xml_data(ws, opts, idx, wb) { + var o = [], r = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols = [], R=0, C=0, rows = ws['!rows']; + var dense = Array.isArray(ws); + var params = ({r:rr}), row, height = -1; + for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C); + for(R = range.s.r; R <= range.e.r; ++R) { + r = []; + rr = encode_row(R); + for(C = range.s.c; C <= range.e.c; ++C) { + ref = cols[C] + rr; + var _cell = dense ? (ws[R]||[])[C]: ws[ref]; + if(_cell === undefined) continue; + if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb)) != null) r.push(cell); + } + if(r.length > 0 || (rows && rows[R])) { + params = ({r:rr}); + if(rows && rows[R]) { + row = rows[R]; + if(row.hidden) params.hidden = 1; + height = -1; + if(row.hpx) height = px2pt(row.hpx); + else if(row.hpt) height = row.hpt; + if(height > -1) { params.ht = height; params.customHeight = 1; } + if(row.level) { params.outlineLevel = row.level; } + } + o[o.length] = (writextag('row', r.join(""), params)); + } + } + if(rows) for(; R < rows.length; ++R) { + if(rows && rows[R]) { + params = ({r:R+1}); + row = rows[R]; + if(row.hidden) params.hidden = 1; + height = -1; + if (row.hpx) height = px2pt(row.hpx); + else if (row.hpt) height = row.hpt; + if (height > -1) { params.ht = height; params.customHeight = 1; } + if (row.level) { params.outlineLevel = row.level; } + o[o.length] = (writextag('row', "", params)); + } + } + return o.join(""); + } + + var WS_XML_ROOT = writextag('worksheet', null, { + 'xmlns': XMLNS.main[0], + 'xmlns:r': XMLNS.r + }); + + function write_ws_xml(idx, opts, wb, rels) { + var o = [XML_HEADER, WS_XML_ROOT]; + var s = wb.SheetNames[idx], sidx = 0, rdata = ""; + var ws = wb.Sheets[s]; + if(ws == null) ws = {}; + var ref = ws['!ref'] || 'A1'; + var range = safe_decode_range(ref); + if(range.e.c > 0x3FFF || range.e.r > 0xFFFFF) { + if(opts.WTF) throw new Error("Range " + ref + " exceeds format limit A1:XFD1048576"); + range.e.c = Math.min(range.e.c, 0x3FFF); + range.e.r = Math.min(range.e.c, 0xFFFFF); + ref = encode_range(range); + } + if(!rels) rels = {}; + ws['!comments'] = []; + ws['!drawing'] = []; + + if(opts.bookType !== 'xlsx' && wb.vbaraw) { + var cname = wb.SheetNames[idx]; + try { if(wb.Workbook) cname = wb.Workbook.Sheets[idx].CodeName || cname; } catch(e) {} + o[o.length] = (writextag('sheetPr', null, {'codeName': escapexml(cname)})); + } + + o[o.length] = (writextag('dimension', null, {'ref': ref})); + + o[o.length] = write_ws_xml_sheetviews(ws, opts, idx, wb); + + /* TODO: store in WB, process styles */ + if(opts.sheetFormat) o[o.length] = (writextag('sheetFormatPr', null, { + defaultRowHeight:opts.sheetFormat.defaultRowHeight||'16', + baseColWidth:opts.sheetFormat.baseColWidth||'10', + outlineLevelRow:opts.sheetFormat.outlineLevelRow||'7' + })); + + if(ws['!cols'] != null && ws['!cols'].length > 0) o[o.length] = (write_ws_xml_cols(ws, ws['!cols'])); + + o[sidx = o.length] = ''; + ws['!links'] = []; + if(ws['!ref'] != null) { + rdata = write_ws_xml_data(ws, opts, idx, wb, rels); + if(rdata.length > 0) o[o.length] = (rdata); + } + if(o.length>sidx+1) { o[o.length] = (''); o[sidx]=o[sidx].replace("/>",">"); } + + /* sheetCalcPr */ + + if(ws['!protect'] != null) o[o.length] = write_ws_xml_protection(ws['!protect']); + + /* protectedRanges */ + /* scenarios */ + + if(ws['!autofilter'] != null) o[o.length] = write_ws_xml_autofilter(ws['!autofilter'], ws, wb, idx); + + /* sortState */ + /* dataConsolidate */ + /* customSheetViews */ + + if(ws['!merges'] != null && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges'])); + + /* phoneticPr */ + /* conditionalFormatting */ + /* dataValidations */ + + var relc = -1, rel, rId = -1; + if(ws['!links'].length > 0) { + o[o.length] = ""; + ws['!links'].forEach(function(l) { + if(!l[1].Target) return; + rel = ({"ref":l[0]}); + if(l[1].Target.charAt(0) != "#") { + rId = add_rels(rels, -1, escapexml(l[1].Target).replace(/#.*$/, ""), RELS.HLINK); + rel["r:id"] = "rId"+rId; + } + if((relc = l[1].Target.indexOf("#")) > -1) rel.location = escapexml(l[1].Target.slice(relc+1)); + if(l[1].Tooltip) rel.tooltip = escapexml(l[1].Tooltip); + o[o.length] = writextag("hyperlink",null,rel); + }); + o[o.length] = ""; + } + delete ws['!links']; + + /* printOptions */ + if (ws['!margins'] != null) o[o.length] = write_ws_xml_margins(ws['!margins']); + /* pageSetup */ + + //var hfidx = o.length; + o[o.length] = ""; + + /* rowBreaks */ + /* colBreaks */ + /* customProperties */ + /* cellWatches */ + + if(!opts || opts.ignoreEC || (opts.ignoreEC == (void 0))) o[o.length] = writetag("ignoredErrors", writextag("ignoredError", null, {numberStoredAsText:1, sqref:ref})); + + /* smartTags */ + + if(ws['!drawing'].length > 0) { + rId = add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW); + o[o.length] = writextag("drawing", null, {"r:id":"rId" + rId}); + } + else delete ws['!drawing']; + + if(ws['!comments'].length > 0) { + rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML); + o[o.length] = writextag("legacyDrawing", null, {"r:id":"rId" + rId}); + ws['!legacy'] = rId; + } + + /* drawingHF */ + /* picture */ + /* oleObjects */ + /* controls */ + /* webPublishItems */ + /* tableParts */ + /* extList */ + + if(o.length>2) { o[o.length] = (''); o[1]=o[1].replace("/>",">"); } + return o.join(""); + } + + /* [MS-XLSB] 2.4.726 BrtRowHdr */ + function parse_BrtRowHdr(data, length) { + var z = ({}); + var tgt = data.l + length; + z.r = data.read_shift(4); + data.l += 4; // TODO: ixfe + var miyRw = data.read_shift(2); + data.l += 1; // TODO: top/bot padding + var flags = data.read_shift(1); + data.l = tgt; + if(flags & 0x07) z.level = flags & 0x07; + if(flags & 0x10) z.hidden = true; + if(flags & 0x20) z.hpt = miyRw / 20; + return z; + } + function write_BrtRowHdr(R, range, ws) { + var o = new_buf(17+8*16); + var row = (ws['!rows']||[])[R]||{}; + o.write_shift(4, R); + + o.write_shift(4, 0); /* TODO: ixfe */ + + var miyRw = 0x0140; + if(row.hpx) miyRw = px2pt(row.hpx) * 20; + else if(row.hpt) miyRw = row.hpt * 20; + o.write_shift(2, miyRw); + + o.write_shift(1, 0); /* top/bot padding */ + + var flags = 0x0; + if(row.level) flags |= row.level; + if(row.hidden) flags |= 0x10; + if(row.hpx || row.hpt) flags |= 0x20; + o.write_shift(1, flags); + + o.write_shift(1, 0); /* phonetic guide */ + + /* [MS-XLSB] 2.5.8 BrtColSpan explains the mechanism */ + var ncolspan = 0, lcs = o.l; + o.l += 4; + + var caddr = {r:R, c:0}; + for(var i = 0; i < 16; ++i) { + if((range.s.c > ((i+1) << 10)) || (range.e.c < (i << 10))) continue; + var first = -1, last = -1; + for(var j = (i<<10); j < ((i+1)<<10); ++j) { + caddr.c = j; + var cell = Array.isArray(ws) ? (ws[caddr.r]||[])[caddr.c] : ws[encode_cell(caddr)]; + if(cell) { if(first < 0) first = j; last = j; } + } + if(first < 0) continue; + ++ncolspan; + o.write_shift(4, first); + o.write_shift(4, last); + } + + var l = o.l; + o.l = lcs; + o.write_shift(4, ncolspan); + o.l = l; + + return o.length > o.l ? o.slice(0, o.l) : o; + } + function write_row_header(ba, ws, range, R) { + var o = write_BrtRowHdr(R, range, ws); + if((o.length > 17) || (ws['!rows']||[])[R]) write_record(ba, 'BrtRowHdr', o); + } + + /* [MS-XLSB] 2.4.820 BrtWsDim */ + var parse_BrtWsDim = parse_UncheckedRfX; + var write_BrtWsDim = write_UncheckedRfX; + + /* [MS-XLSB] 2.4.821 BrtWsFmtInfo */ + function parse_BrtWsFmtInfo() { + } +//function write_BrtWsFmtInfo(ws, o) { } + + /* [MS-XLSB] 2.4.823 BrtWsProp */ + function parse_BrtWsProp(data, length) { + var z = {}; + /* TODO: pull flags */ + data.l += 19; + z.name = parse_XLSBCodeName(data, length - 19); + return z; + } + function write_BrtWsProp(str, o) { + if(o == null) o = new_buf(84+4*str.length); + for(var i = 0; i < 3; ++i) o.write_shift(1,0); + write_BrtColor({auto:1}, o); + o.write_shift(-4,-1); + o.write_shift(-4,-1); + write_XLSBCodeName(str, o); + return o.slice(0, o.l); + } + + /* [MS-XLSB] 2.4.306 BrtCellBlank */ + function parse_BrtCellBlank(data) { + var cell = parse_XLSBCell(data); + return [cell]; + } + function write_BrtCellBlank(cell, ncell, o) { + if(o == null) o = new_buf(8); + return write_XLSBCell(ncell, o); + } + + + /* [MS-XLSB] 2.4.307 BrtCellBool */ + function parse_BrtCellBool(data) { + var cell = parse_XLSBCell(data); + var fBool = data.read_shift(1); + return [cell, fBool, 'b']; + } + function write_BrtCellBool(cell, ncell, o) { + if(o == null) o = new_buf(9); + write_XLSBCell(ncell, o); + o.write_shift(1, cell.v ? 1 : 0); + return o; + } + + /* [MS-XLSB] 2.4.308 BrtCellError */ + function parse_BrtCellError(data) { + var cell = parse_XLSBCell(data); + var bError = data.read_shift(1); + return [cell, bError, 'e']; + } + + /* [MS-XLSB] 2.4.311 BrtCellIsst */ + function parse_BrtCellIsst(data) { + var cell = parse_XLSBCell(data); + var isst = data.read_shift(4); + return [cell, isst, 's']; + } + function write_BrtCellIsst(cell, ncell, o) { + if(o == null) o = new_buf(12); + write_XLSBCell(ncell, o); + o.write_shift(4, ncell.v); + return o; + } + + /* [MS-XLSB] 2.4.313 BrtCellReal */ + function parse_BrtCellReal(data) { + var cell = parse_XLSBCell(data); + var value = parse_Xnum(data); + return [cell, value, 'n']; + } + function write_BrtCellReal(cell, ncell, o) { + if(o == null) o = new_buf(16); + write_XLSBCell(ncell, o); + write_Xnum(cell.v, o); + return o; + } + + /* [MS-XLSB] 2.4.314 BrtCellRk */ + function parse_BrtCellRk(data) { + var cell = parse_XLSBCell(data); + var value = parse_RkNumber(data); + return [cell, value, 'n']; + } + function write_BrtCellRk(cell, ncell, o) { + if(o == null) o = new_buf(12); + write_XLSBCell(ncell, o); + write_RkNumber(cell.v, o); + return o; + } + + + /* [MS-XLSB] 2.4.317 BrtCellSt */ + function parse_BrtCellSt(data) { + var cell = parse_XLSBCell(data); + var value = parse_XLWideString(data); + return [cell, value, 'str']; + } + function write_BrtCellSt(cell, ncell, o) { + if(o == null) o = new_buf(12 + 4 * cell.v.length); + write_XLSBCell(ncell, o); + write_XLWideString(cell.v, o); + return o.length > o.l ? o.slice(0, o.l) : o; + } + + /* [MS-XLSB] 2.4.653 BrtFmlaBool */ + function parse_BrtFmlaBool(data, length, opts) { + var end = data.l + length; + var cell = parse_XLSBCell(data); + cell.r = opts['!row']; + var value = data.read_shift(1); + var o = [cell, value, 'b']; + if(opts.cellFormula) { + data.l += 2; + var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts); + o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */ + } + else data.l = end; + return o; + } + + /* [MS-XLSB] 2.4.654 BrtFmlaError */ + function parse_BrtFmlaError(data, length, opts) { + var end = data.l + length; + var cell = parse_XLSBCell(data); + cell.r = opts['!row']; + var value = data.read_shift(1); + var o = [cell, value, 'e']; + if(opts.cellFormula) { + data.l += 2; + var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts); + o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */ + } + else data.l = end; + return o; + } + + /* [MS-XLSB] 2.4.655 BrtFmlaNum */ + function parse_BrtFmlaNum(data, length, opts) { + var end = data.l + length; + var cell = parse_XLSBCell(data); + cell.r = opts['!row']; + var value = parse_Xnum(data); + var o = [cell, value, 'n']; + if(opts.cellFormula) { + data.l += 2; + var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts); + o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */ + } + else data.l = end; + return o; + } + + /* [MS-XLSB] 2.4.656 BrtFmlaString */ + function parse_BrtFmlaString(data, length, opts) { + var end = data.l + length; + var cell = parse_XLSBCell(data); + cell.r = opts['!row']; + var value = parse_XLWideString(data); + var o = [cell, value, 'str']; + if(opts.cellFormula) { + data.l += 2; + var formula = parse_XLSBCellParsedFormula(data, end - data.l, opts); + o[3] = stringify_formula(formula, null/*range*/, cell, opts.supbooks, opts);/* TODO */ + } + else data.l = end; + return o; + } + + /* [MS-XLSB] 2.4.682 BrtMergeCell */ + var parse_BrtMergeCell = parse_UncheckedRfX; + var write_BrtMergeCell = write_UncheckedRfX; + /* [MS-XLSB] 2.4.107 BrtBeginMergeCells */ + function write_BrtBeginMergeCells(cnt, o) { + if(o == null) o = new_buf(4); + o.write_shift(4, cnt); + return o; + } + + /* [MS-XLSB] 2.4.662 BrtHLink */ + function parse_BrtHLink(data, length) { + var end = data.l + length; + var rfx = parse_UncheckedRfX(data, 16); + var relId = parse_XLNullableWideString(data); + var loc = parse_XLWideString(data); + var tooltip = parse_XLWideString(data); + var display = parse_XLWideString(data); + data.l = end; + var o = ({rfx:rfx, relId:relId, loc:loc, display:display}); + if(tooltip) o.Tooltip = tooltip; + return o; + } + function write_BrtHLink(l, rId) { + var o = new_buf(50+4*(l[1].Target.length + (l[1].Tooltip || "").length)); + write_UncheckedRfX({s:decode_cell(l[0]), e:decode_cell(l[0])}, o); + write_RelID("rId" + rId, o); + var locidx = l[1].Target.indexOf("#"); + var loc = locidx == -1 ? "" : l[1].Target.slice(locidx+1); + write_XLWideString(loc || "", o); + write_XLWideString(l[1].Tooltip || "", o); + write_XLWideString("", o); + return o.slice(0, o.l); + } + + /* [MS-XLSB] 2.4.6 BrtArrFmla */ + function parse_BrtArrFmla(data, length, opts) { + var end = data.l + length; + var rfx = parse_RfX(data, 16); + var fAlwaysCalc = data.read_shift(1); + var o = [rfx]; o[2] = fAlwaysCalc; + if(opts.cellFormula) { + var formula = parse_XLSBArrayParsedFormula(data, end - data.l, opts); + o[1] = formula; + } else data.l = end; + return o; + } + + /* [MS-XLSB] 2.4.750 BrtShrFmla */ + function parse_BrtShrFmla(data, length, opts) { + var end = data.l + length; + var rfx = parse_UncheckedRfX(data, 16); + var o = [rfx]; + if(opts.cellFormula) { + var formula = parse_XLSBSharedParsedFormula(data, end - data.l, opts); + o[1] = formula; + data.l = end; + } else data.l = end; + return o; + } + + /* [MS-XLSB] 2.4.323 BrtColInfo */ + /* TODO: once XLS ColInfo is set, combine the functions */ + function write_BrtColInfo(C, col, o) { + if(o == null) o = new_buf(18); + var p = col_obj_w(C, col); + o.write_shift(-4, C); + o.write_shift(-4, C); + o.write_shift(4, (p.width || 10) * 256); + o.write_shift(4, 0/*ixfe*/); // style + var flags = 0; + if(col.hidden) flags |= 0x01; + if(typeof p.width == 'number') flags |= 0x02; + o.write_shift(1, flags); // bit flag + o.write_shift(1, 0); // bit flag + return o; + } + + /* [MS-XLSB] 2.4.678 BrtMargins */ + var BrtMarginKeys = ["left","right","top","bottom","header","footer"]; + function parse_BrtMargins(data) { + var margins = ({}); + BrtMarginKeys.forEach(function(k) { margins[k] = parse_Xnum(data, 8); }); + return margins; + } + function write_BrtMargins(margins, o) { + if(o == null) o = new_buf(6*8); + default_margins(margins); + BrtMarginKeys.forEach(function(k) { write_Xnum((margins)[k], o); }); + return o; + } + + /* [MS-XLSB] 2.4.299 BrtBeginWsView */ + function parse_BrtBeginWsView(data) { + var f = data.read_shift(2); + data.l += 28; + return { RTL: f & 0x20 }; + } + function write_BrtBeginWsView(ws, Workbook, o) { + if(o == null) o = new_buf(30); + var f = 0x39c; + if((((Workbook||{}).Views||[])[0]||{}).RTL) f |= 0x20; + o.write_shift(2, f); // bit flag + o.write_shift(4, 0); + o.write_shift(4, 0); // view first row + o.write_shift(4, 0); // view first col + o.write_shift(1, 0); // gridline color ICV + o.write_shift(1, 0); + o.write_shift(2, 0); + o.write_shift(2, 100); // zoom scale + o.write_shift(2, 0); + o.write_shift(2, 0); + o.write_shift(2, 0); + o.write_shift(4, 0); // workbook view id + return o; + } + + /* [MS-XLSB] 2.4.309 BrtCellIgnoreEC */ + function write_BrtCellIgnoreEC(ref) { + var o = new_buf(24); + o.write_shift(4, 4); + o.write_shift(4, 1); + write_UncheckedRfX(ref, o); + return o; + } + + /* [MS-XLSB] 2.4.748 BrtSheetProtection */ + function write_BrtSheetProtection(sp, o) { + if(o == null) o = new_buf(16*4+2); + o.write_shift(2, sp.password ? crypto_CreatePasswordVerifier_Method1(sp.password) : 0); + o.write_shift(4, 1); // this record should not be written if no protection + [ + ["objects", false], // fObjects + ["scenarios", false], // fScenarios + ["formatCells", true], // fFormatCells + ["formatColumns", true], // fFormatColumns + ["formatRows", true], // fFormatRows + ["insertColumns", true], // fInsertColumns + ["insertRows", true], // fInsertRows + ["insertHyperlinks", true], // fInsertHyperlinks + ["deleteColumns", true], // fDeleteColumns + ["deleteRows", true], // fDeleteRows + ["selectLockedCells", false], // fSelLockedCells + ["sort", true], // fSort + ["autoFilter", true], // fAutoFilter + ["pivotTables", true], // fPivotTables + ["selectUnlockedCells", false] // fSelUnlockedCells + ].forEach(function(n) { + if(n[1]) o.write_shift(4, sp[n[0]] != null && !sp[n[0]] ? 1 : 0); + else o.write_shift(4, sp[n[0]] != null && sp[n[0]] ? 0 : 1); + }); + return o; + } + + /* [MS-XLSB] 2.1.7.61 Worksheet */ + function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles) { + if(!data) return data; + var opts = _opts || {}; + if(!rels) rels = {'!id':{}}; + if(DENSE != null && opts.dense == null) opts.dense = DENSE; + var s = (opts.dense ? [] : {}); + + var ref; + var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; + + var pass = false, end = false; + var row, p, cf, R, C, addr, sstr, rr, cell; + var merges = []; + opts.biff = 12; + opts['!row'] = 0; + + var ai = 0, af = false; + + var arrayf = []; + var sharedf = {}; + var supbooks = opts.supbooks || wb.supbooks || ([[]]); + supbooks.sharedf = sharedf; + supbooks.arrayf = arrayf; + supbooks.SheetNames = wb.SheetNames || wb.Sheets.map(function(x) { return x.name; }); + if(!opts.supbooks) { + opts.supbooks = supbooks; + if(wb.Names) for(var i = 0; i < wb.Names.length; ++i) supbooks[0][i+1] = wb.Names[i]; + } + + var colinfo = [], rowinfo = []; + var seencol = false; + + recordhopper(data, function ws_parse(val, R_n, RT) { + if(end) return; + switch(RT) { + case 0x0094: /* 'BrtWsDim' */ + ref = val; break; + case 0x0000: /* 'BrtRowHdr' */ + row = val; + if(opts.sheetRows && opts.sheetRows <= row.r) end=true; + rr = encode_row(R = row.r); + opts['!row'] = row.r; + if(val.hidden || val.hpt || val.level != null) { + if(val.hpt) val.hpx = pt2px(val.hpt); + rowinfo[val.r] = val; + } + break; + + case 0x0002: /* 'BrtCellRk' */ + case 0x0003: /* 'BrtCellError' */ + case 0x0004: /* 'BrtCellBool' */ + case 0x0005: /* 'BrtCellReal' */ + case 0x0006: /* 'BrtCellSt' */ + case 0x0007: /* 'BrtCellIsst' */ + case 0x0008: /* 'BrtFmlaString' */ + case 0x0009: /* 'BrtFmlaNum' */ + case 0x000A: /* 'BrtFmlaBool' */ + case 0x000B: /* 'BrtFmlaError' */ + p = ({t:val[2]}); + switch(val[2]) { + case 'n': p.v = val[1]; break; + case 's': sstr = strs[val[1]]; p.v = sstr.t; p.r = sstr.r; break; + case 'b': p.v = val[1] ? true : false; break; + case 'e': p.v = val[1]; if(opts.cellText !== false) p.w = BErr[p.v]; break; + case 'str': p.t = 's'; p.v = val[1]; break; + } + if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles); + C = val[0].c; + if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; } + else s[encode_col(C) + rr] = p; + if(opts.cellFormula) { + af = false; + for(ai = 0; ai < arrayf.length; ++ai) { + var aii = arrayf[ai]; + if(row.r >= aii[0].s.r && row.r <= aii[0].e.r) + if(C >= aii[0].s.c && C <= aii[0].e.c) { + p.F = encode_range(aii[0]); af = true; + } + } + if(!af && val.length > 3) p.f = val[3]; + } + if(refguess.s.r > row.r) refguess.s.r = row.r; + if(refguess.s.c > C) refguess.s.c = C; + if(refguess.e.r < row.r) refguess.e.r = row.r; + if(refguess.e.c < C) refguess.e.c = C; + if(opts.cellDates && cf && p.t == 'n' && SSF.is_date(SSF._table[cf.numFmtId])) { + var _d = SSF.parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); } + } + break; + + case 0x0001: /* 'BrtCellBlank' */ + if(!opts.sheetStubs || pass) break; + p = ({t:'z',v:undefined}); + C = val[0].c; + if(opts.dense) { if(!s[R]) s[R] = []; s[R][C] = p; } + else s[encode_col(C) + rr] = p; + if(refguess.s.r > row.r) refguess.s.r = row.r; + if(refguess.s.c > C) refguess.s.c = C; + if(refguess.e.r < row.r) refguess.e.r = row.r; + if(refguess.e.c < C) refguess.e.c = C; + break; + + case 0x00B0: /* 'BrtMergeCell' */ + merges.push(val); break; + + case 0x01EE: /* 'BrtHLink' */ + var rel = rels['!id'][val.relId]; + if(rel) { + val.Target = rel.Target; + if(val.loc) val.Target += "#"+val.loc; + val.Rel = rel; + } else if(val.relId == '') { + val.Target = "#" + val.loc; + } + for(R=val.rfx.s.r;R<=val.rfx.e.r;++R) for(C=val.rfx.s.c;C<=val.rfx.e.c;++C) { + if(opts.dense) { + if(!s[R]) s[R] = []; + if(!s[R][C]) s[R][C] = {t:'z',v:undefined}; + s[R][C].l = val; + } else { + addr = encode_cell({c:C,r:R}); + if(!s[addr]) s[addr] = {t:'z',v:undefined}; + s[addr].l = val; + } + } + break; + + case 0x01AA: /* 'BrtArrFmla' */ + if(!opts.cellFormula) break; + arrayf.push(val); + cell = ((opts.dense ? s[R][C] : s[encode_col(C) + rr])); + cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts); + cell.F = encode_range(val[0]); + break; + case 0x01AB: /* 'BrtShrFmla' */ + if(!opts.cellFormula) break; + sharedf[encode_cell(val[0].s)] = val[1]; + cell = (opts.dense ? s[R][C] : s[encode_col(C) + rr]); + cell.f = stringify_formula(val[1], refguess, {r:row.r, c:C}, supbooks, opts); + break; + + /* identical to 'ColInfo' in XLS */ + case 0x003C: /* 'BrtColInfo' */ + if(!opts.cellStyles) break; + while(val.e >= val.s) { + colinfo[val.e--] = { width: val.w/256, hidden: !!(val.flags & 0x01) }; + if(!seencol) { seencol = true; find_mdw_colw(val.w/256); } + process_col(colinfo[val.e+1]); + } + break; + + case 0x00A1: /* 'BrtBeginAFilter' */ + s['!autofilter'] = { ref:encode_range(val) }; + break; + + case 0x01DC: /* 'BrtMargins' */ + s['!margins'] = val; + break; + + case 0x0093: /* 'BrtWsProp' */ + if(!wb.Sheets[idx]) wb.Sheets[idx] = {}; + if(val.name) wb.Sheets[idx].CodeName = val.name; + break; + + case 0x0089: /* 'BrtBeginWsView' */ + if(!wb.Views) wb.Views = [{}]; + if(!wb.Views[0]) wb.Views[0] = {}; + if(val.RTL) wb.Views[0].RTL = true; + break; + + case 0x01E5: /* 'BrtWsFmtInfo' */ + break; + case 0x00AF: /* 'BrtAFilterDateGroupItem' */ + case 0x0284: /* 'BrtActiveX' */ + case 0x0271: /* 'BrtBigName' */ + case 0x0232: /* 'BrtBkHim' */ + case 0x018C: /* 'BrtBrk' */ + case 0x0458: /* 'BrtCFIcon' */ + case 0x047A: /* 'BrtCFRuleExt' */ + case 0x01D7: /* 'BrtCFVO' */ + case 0x041A: /* 'BrtCFVO14' */ + case 0x0289: /* 'BrtCellIgnoreEC' */ + case 0x0451: /* 'BrtCellIgnoreEC14' */ + case 0x0031: /* 'BrtCellMeta' */ + case 0x024D: /* 'BrtCellSmartTagProperty' */ + case 0x025F: /* 'BrtCellWatch' */ + case 0x0234: /* 'BrtColor' */ + case 0x041F: /* 'BrtColor14' */ + case 0x00A8: /* 'BrtColorFilter' */ + case 0x00AE: /* 'BrtCustomFilter' */ + case 0x049C: /* 'BrtCustomFilter14' */ + case 0x01F3: /* 'BrtDRef' */ + case 0x0040: /* 'BrtDVal' */ + case 0x041D: /* 'BrtDVal14' */ + case 0x0226: /* 'BrtDrawing' */ + case 0x00AB: /* 'BrtDynamicFilter' */ + case 0x00A7: /* 'BrtFilter' */ + case 0x0499: /* 'BrtFilter14' */ + case 0x00A9: /* 'BrtIconFilter' */ + case 0x049D: /* 'BrtIconFilter14' */ + case 0x0227: /* 'BrtLegacyDrawing' */ + case 0x0228: /* 'BrtLegacyDrawingHF' */ + case 0x0295: /* 'BrtListPart' */ + case 0x027F: /* 'BrtOleObject' */ + case 0x01DE: /* 'BrtPageSetup' */ + case 0x0097: /* 'BrtPane' */ + case 0x0219: /* 'BrtPhoneticInfo' */ + case 0x01DD: /* 'BrtPrintOptions' */ + case 0x0218: /* 'BrtRangeProtection' */ + case 0x044F: /* 'BrtRangeProtection14' */ + case 0x02A8: /* 'BrtRangeProtectionIso' */ + case 0x0450: /* 'BrtRangeProtectionIso14' */ + case 0x0400: /* 'BrtRwDescent' */ + case 0x0098: /* 'BrtSel' */ + case 0x0297: /* 'BrtSheetCalcProp' */ + case 0x0217: /* 'BrtSheetProtection' */ + case 0x02A6: /* 'BrtSheetProtectionIso' */ + case 0x01F8: /* 'BrtSlc' */ + case 0x0413: /* 'BrtSparkline' */ + case 0x01AC: /* 'BrtTable' */ + case 0x00AA: /* 'BrtTop10Filter' */ + case 0x0C00: /* 'BrtUid' */ + case 0x0032: /* 'BrtValueMeta' */ + case 0x0816: /* 'BrtWebExtension' */ + case 0x0415: /* 'BrtWsFmtInfoEx14' */ + break; + + case 0x0023: /* 'BrtFRTBegin' */ + pass = true; break; + case 0x0024: /* 'BrtFRTEnd' */ + pass = false; break; + case 0x0025: /* 'BrtACBegin' */ break; + case 0x0026: /* 'BrtACEnd' */ break; + + default: + if((R_n||"").indexOf("Begin") > 0){/* empty */} + else if((R_n||"").indexOf("End") > 0){/* empty */} + else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n); + } + }, opts); + + delete opts.supbooks; + delete opts['!row']; + + if(!s["!ref"] && (refguess.s.r < 2000000 || ref && (ref.e.r > 0 || ref.e.c > 0 || ref.s.r > 0 || ref.s.c > 0))) s["!ref"] = encode_range(ref || refguess); + if(opts.sheetRows && s["!ref"]) { + var tmpref = safe_decode_range(s["!ref"]); + if(opts.sheetRows <= +tmpref.e.r) { + tmpref.e.r = opts.sheetRows - 1; + if(tmpref.e.r > refguess.e.r) tmpref.e.r = refguess.e.r; + if(tmpref.e.r < tmpref.s.r) tmpref.s.r = tmpref.e.r; + if(tmpref.e.c > refguess.e.c) tmpref.e.c = refguess.e.c; + if(tmpref.e.c < tmpref.s.c) tmpref.s.c = tmpref.e.c; + s["!fullref"] = s["!ref"]; + s["!ref"] = encode_range(tmpref); + } + } + if(merges.length > 0) s["!merges"] = merges; + if(colinfo.length > 0) s["!cols"] = colinfo; + if(rowinfo.length > 0) s["!rows"] = rowinfo; + return s; + } + + /* TODO: something useful -- this is a stub */ + function write_ws_bin_cell(ba, cell, R, C, opts, ws) { + if(cell.v === undefined) return ""; + var vv = ""; + switch(cell.t) { + case 'b': vv = cell.v ? "1" : "0"; break; + case 'd': // no BrtCellDate :( + cell = dup(cell); + cell.z = cell.z || SSF._table[14]; + cell.v = datenum(parseDate(cell.v)); cell.t = 'n'; + break; + /* falls through */ + case 'n': case 'e': vv = ''+cell.v; break; + default: vv = cell.v; break; + } + var o = ({r:R, c:C}); + /* TODO: cell style */ + o.s = get_cell_style(opts.cellXfs, cell, opts); + if(cell.l) ws['!links'].push([encode_cell(o), cell.l]); + if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]); + switch(cell.t) { + case 's': case 'str': + if(opts.bookSST) { + vv = get_sst_id(opts.Strings, (cell.v), opts.revStrings); + o.t = "s"; o.v = vv; + write_record(ba, "BrtCellIsst", write_BrtCellIsst(cell, o)); + } else { + o.t = "str"; + write_record(ba, "BrtCellSt", write_BrtCellSt(cell, o)); + } + return; + case 'n': + /* TODO: determine threshold for Real vs RK */ + if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) write_record(ba, "BrtCellRk", write_BrtCellRk(cell, o)); + else write_record(ba, "BrtCellReal", write_BrtCellReal(cell, o)); + return; + case 'b': + o.t = "b"; + write_record(ba, "BrtCellBool", write_BrtCellBool(cell, o)); + return; + case 'e': /* TODO: error */ o.t = "e"; break; + } + write_record(ba, "BrtCellBlank", write_BrtCellBlank(cell, o)); + } + + function write_CELLTABLE(ba, ws, idx, opts) { + var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = []; + write_record(ba, 'BrtBeginSheetData'); + var dense = Array.isArray(ws); + var cap = range.e.r; + if(ws['!rows']) cap = Math.max(range.e.r, ws['!rows'].length - 1); + for(var R = range.s.r; R <= cap; ++R) { + rr = encode_row(R); + /* [ACCELLTABLE] */ + /* BrtRowHdr */ + write_row_header(ba, ws, range, R); + if(R <= range.e.r) for(var C = range.s.c; C <= range.e.c; ++C) { + /* *16384CELL */ + if(R === range.s.r) cols[C] = encode_col(C); + ref = cols[C] + rr; + var cell = dense ? (ws[R]||[])[C] : ws[ref]; + if(!cell) continue; + /* write cell */ + write_ws_bin_cell(ba, cell, R, C, opts, ws); + } + } + write_record(ba, 'BrtEndSheetData'); + } + + function write_MERGECELLS(ba, ws) { + if(!ws || !ws['!merges']) return; + write_record(ba, 'BrtBeginMergeCells', write_BrtBeginMergeCells(ws['!merges'].length)); + ws['!merges'].forEach(function(m) { write_record(ba, 'BrtMergeCell', write_BrtMergeCell(m)); }); + write_record(ba, 'BrtEndMergeCells'); + } + + function write_COLINFOS(ba, ws) { + if(!ws || !ws['!cols']) return; + write_record(ba, 'BrtBeginColInfos'); + ws['!cols'].forEach(function(m, i) { if(m) write_record(ba, 'BrtColInfo', write_BrtColInfo(i, m)); }); + write_record(ba, 'BrtEndColInfos'); + } + + function write_IGNOREECS(ba, ws) { + if(!ws || !ws['!ref']) return; + write_record(ba, 'BrtBeginCellIgnoreECs'); + write_record(ba, 'BrtCellIgnoreEC', write_BrtCellIgnoreEC(safe_decode_range(ws['!ref']))); + write_record(ba, 'BrtEndCellIgnoreECs'); + } + + function write_HLINKS(ba, ws, rels) { + /* *BrtHLink */ + ws['!links'].forEach(function(l) { + if(!l[1].Target) return; + var rId = add_rels(rels, -1, l[1].Target.replace(/#.*$/, ""), RELS.HLINK); + write_record(ba, "BrtHLink", write_BrtHLink(l, rId)); + }); + delete ws['!links']; + } + function write_LEGACYDRAWING(ba, ws, idx, rels) { + /* [BrtLegacyDrawing] */ + if(ws['!comments'].length > 0) { + var rId = add_rels(rels, -1, "../drawings/vmlDrawing" + (idx+1) + ".vml", RELS.VML); + write_record(ba, "BrtLegacyDrawing", write_RelID("rId" + rId)); + ws['!legacy'] = rId; + } + } + + function write_AUTOFILTER(ba, ws) { + if(!ws['!autofilter']) return; + write_record(ba, "BrtBeginAFilter", write_UncheckedRfX(safe_decode_range(ws['!autofilter'].ref))); + /* *FILTERCOLUMN */ + /* [SORTSTATE] */ + /* BrtEndAFilter */ + write_record(ba, "BrtEndAFilter"); + } + + function write_WSVIEWS2(ba, ws, Workbook) { + write_record(ba, "BrtBeginWsViews"); + { /* 1*WSVIEW2 */ + /* [ACUID] */ + write_record(ba, "BrtBeginWsView", write_BrtBeginWsView(ws, Workbook)); + /* [BrtPane] */ + /* *4BrtSel */ + /* *4SXSELECT */ + /* *FRT */ + write_record(ba, "BrtEndWsView"); + } + /* *FRT */ + write_record(ba, "BrtEndWsViews"); + } + + function write_WSFMTINFO() { + /* [ACWSFMTINFO] */ + //write_record(ba, "BrtWsFmtInfo", write_BrtWsFmtInfo(ws)); + } + + function write_SHEETPROTECT(ba, ws) { + if(!ws['!protect']) return; + /* [BrtSheetProtectionIso] */ + write_record(ba, "BrtSheetProtection", write_BrtSheetProtection(ws['!protect'])); + } + + function write_ws_bin(idx, opts, wb, rels) { + var ba = buf_array(); + var s = wb.SheetNames[idx], ws = wb.Sheets[s] || {}; + var c = s; try { if(wb && wb.Workbook) c = wb.Workbook.Sheets[idx].CodeName || c; } catch(e) {} + var r = safe_decode_range(ws['!ref'] || "A1"); + if(r.e.c > 0x3FFF || r.e.r > 0xFFFFF) { + if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:XFD1048576"); + r.e.c = Math.min(r.e.c, 0x3FFF); + r.e.r = Math.min(r.e.c, 0xFFFFF); + } + ws['!links'] = []; + /* passed back to write_zip and removed there */ + ws['!comments'] = []; + write_record(ba, "BrtBeginSheet"); + if(wb.vbaraw) write_record(ba, "BrtWsProp", write_BrtWsProp(c)); + write_record(ba, "BrtWsDim", write_BrtWsDim(r)); + write_WSVIEWS2(ba, ws, wb.Workbook); + write_WSFMTINFO(ba, ws); + write_COLINFOS(ba, ws, idx, opts, wb); + write_CELLTABLE(ba, ws, idx, opts, wb); + /* [BrtSheetCalcProp] */ + write_SHEETPROTECT(ba, ws); + /* *([BrtRangeProtectionIso] BrtRangeProtection) */ + /* [SCENMAN] */ + write_AUTOFILTER(ba, ws); + /* [SORTSTATE] */ + /* [DCON] */ + /* [USERSHVIEWS] */ + write_MERGECELLS(ba, ws); + /* [BrtPhoneticInfo] */ + /* *CONDITIONALFORMATTING */ + /* [DVALS] */ + write_HLINKS(ba, ws, rels); + /* [BrtPrintOptions] */ + if(ws['!margins']) write_record(ba, "BrtMargins", write_BrtMargins(ws['!margins'])); + /* [BrtPageSetup] */ + /* [HEADERFOOTER] */ + /* [RWBRK] */ + /* [COLBRK] */ + /* *BrtBigName */ + /* [CELLWATCHES] */ + if(!opts || opts.ignoreEC || (opts.ignoreEC == (void 0))) write_IGNOREECS(ba, ws); + /* [SMARTTAGS] */ + /* [BrtDrawing] */ + write_LEGACYDRAWING(ba, ws, idx, rels); + /* [BrtLegacyDrawingHF] */ + /* [BrtBkHim] */ + /* [OLEOBJECTS] */ + /* [ACTIVEXCONTROLS] */ + /* [WEBPUBITEMS] */ + /* [LISTPARTS] */ + /* FRTWORKSHEET */ + write_record(ba, "BrtEndSheet"); + return ba.end(); + } + function parse_numCache(data) { + var col = []; + + /* 21.2.2.150 pt CT_NumVal */ + (data.match(/(.*?)<\/c:pt>/mg)||[]).forEach(function(pt) { + var q = pt.match(/(.*)<\/c:v><\/c:pt>/); + if(!q) return; + col[+q[1]] = +q[2]; + }); + + /* 21.2.2.71 formatCode CT_Xstring */ + var nf = unescapexml((data.match(/([\s\S]*?)<\/c:formatCode>/) || ["","General"])[1]); + + return [col, nf]; + } + + /* 21.2 DrawingML - Charts */ + function parse_chart(data, name, opts, rels, wb, csheet) { + var cs = ((csheet || {"!type":"chart"})); + if(!data) return csheet; + /* 21.2.2.27 chart CT_Chart */ + + var C = 0, R = 0, col = "A"; + var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; + + /* 21.2.2.120 numCache CT_NumData */ + (data.match(/[\s\S]*?<\/c:numCache>/gm)||[]).forEach(function(nc) { + var cache = parse_numCache(nc); + refguess.s.r = refguess.s.c = 0; + refguess.e.c = C; + col = encode_col(C); + cache[0].forEach(function(n,i) { + cs[col + encode_row(i)] = {t:'n', v:n, z:cache[1] }; + R = i; + }); + if(refguess.e.r < R) refguess.e.r = R; + ++C; + }); + if(C > 0) cs["!ref"] = encode_range(refguess); + return cs; + } + RELS.CS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartsheet"; + + var CS_XML_ROOT = writextag('chartsheet', null, { + 'xmlns': XMLNS.main[0], + 'xmlns:r': XMLNS.r + }); + + /* 18.3 Worksheets also covers Chartsheets */ + function parse_cs_xml(data, opts, idx, rels, wb) { + if(!data) return data; + /* 18.3.1.12 chartsheet CT_ChartSheet */ + if(!rels) rels = {'!id':{}}; + var s = {'!type':"chart", '!chart':null, '!rel':""}; + var m; + + /* 18.3.1.83 sheetPr CT_ChartsheetPr */ + var sheetPr = data.match(sheetprregex); + if(sheetPr) parse_ws_xml_sheetpr(sheetPr[0], s, wb, idx); + + /* 18.3.1.36 drawing CT_Drawing */ + if((m = data.match(/drawing r:id="(.*?)"/))) s['!rel'] = m[1]; + + if(rels['!id'][s['!rel']]) s['!chart'] = rels['!id'][s['!rel']]; + return s; + } + function write_cs_xml(idx, opts, wb, rels) { + var o = [XML_HEADER, CS_XML_ROOT]; + o[o.length] = writextag("drawing", null, {"r:id": "rId1"}); + add_rels(rels, -1, "../drawings/drawing" + (idx+1) + ".xml", RELS.DRAW); + if(o.length>2) { o[o.length] = (''); o[1]=o[1].replace("/>",">"); } + return o.join(""); + } + + /* [MS-XLSB] 2.4.331 BrtCsProp */ + function parse_BrtCsProp(data, length) { + data.l += 10; + var name = parse_XLWideString(data, length - 10); + return { name: name }; + } + + /* [MS-XLSB] 2.1.7.7 Chart Sheet */ + function parse_cs_bin(data, opts, idx, rels, wb) { + if(!data) return data; + if(!rels) rels = {'!id':{}}; + var s = {'!type':"chart", '!chart':null, '!rel':""}; + var state = []; + var pass = false; + recordhopper(data, function cs_parse(val, R_n, RT) { + switch(RT) { + + case 0x0226: /* 'BrtDrawing' */ + s['!rel'] = val; break; + + case 0x028B: /* 'BrtCsProp' */ + if(!wb.Sheets[idx]) wb.Sheets[idx] = {}; + if(val.name) wb.Sheets[idx].CodeName = val.name; + break; + + case 0x0232: /* 'BrtBkHim' */ + case 0x028C: /* 'BrtCsPageSetup' */ + case 0x029D: /* 'BrtCsProtection' */ + case 0x02A7: /* 'BrtCsProtectionIso' */ + case 0x0227: /* 'BrtLegacyDrawing' */ + case 0x0228: /* 'BrtLegacyDrawingHF' */ + case 0x01DC: /* 'BrtMargins' */ + case 0x0C00: /* 'BrtUid' */ + break; + + case 0x0023: /* 'BrtFRTBegin' */ + pass = true; break; + case 0x0024: /* 'BrtFRTEnd' */ + pass = false; break; + case 0x0025: /* 'BrtACBegin' */ + state.push(R_n); break; + case 0x0026: /* 'BrtACEnd' */ + state.pop(); break; + + default: + if((R_n||"").indexOf("Begin") > 0) state.push(R_n); + else if((R_n||"").indexOf("End") > 0) state.pop(); + else if(!pass || opts.WTF) throw new Error("Unexpected record " + RT + " " + R_n); + } + }, opts); + + if(rels['!id'][s['!rel']]) s['!chart'] = rels['!id'][s['!rel']]; + return s; + } + function write_cs_bin() { + var ba = buf_array(); + write_record(ba, "BrtBeginSheet"); + /* [BrtCsProp] */ + /* CSVIEWS */ + /* [[BrtCsProtectionIso] BrtCsProtection] */ + /* [USERCSVIEWS] */ + /* [BrtMargins] */ + /* [BrtCsPageSetup] */ + /* [HEADERFOOTER] */ + /* BrtDrawing */ + /* [BrtLegacyDrawing] */ + /* [BrtLegacyDrawingHF] */ + /* [BrtBkHim] */ + /* [WEBPUBITEMS] */ + /* FRTCHARTSHEET */ + write_record(ba, "BrtEndSheet"); + return ba.end(); + } + /* 18.2.28 (CT_WorkbookProtection) Defaults */ + var WBPropsDef = [ + ['allowRefreshQuery', false, "bool"], + ['autoCompressPictures', true, "bool"], + ['backupFile', false, "bool"], + ['checkCompatibility', false, "bool"], + ['CodeName', ''], + ['date1904', false, "bool"], + ['defaultThemeVersion', 0, "int"], + ['filterPrivacy', false, "bool"], + ['hidePivotFieldList', false, "bool"], + ['promptedSolutions', false, "bool"], + ['publishItems', false, "bool"], + ['refreshAllConnections', false, "bool"], + ['saveExternalLinkValues', true, "bool"], + ['showBorderUnselectedTables', true, "bool"], + ['showInkAnnotation', true, "bool"], + ['showObjects', 'all'], + ['showPivotChartFilter', false, "bool"], + ['updateLinks', 'userSet'] + ]; + + /* 18.2.30 (CT_BookView) Defaults */ + var WBViewDef = [ + ['activeTab', 0, "int"], + ['autoFilterDateGrouping', true, "bool"], + ['firstSheet', 0, "int"], + ['minimized', false, "bool"], + ['showHorizontalScroll', true, "bool"], + ['showSheetTabs', true, "bool"], + ['showVerticalScroll', true, "bool"], + ['tabRatio', 600, "int"], + ['visibility', 'visible'] + //window{Height,Width}, {x,y}Window + ]; + + /* 18.2.19 (CT_Sheet) Defaults */ + var SheetDef = [ + //['state', 'visible'] + ]; + + /* 18.2.2 (CT_CalcPr) Defaults */ + var CalcPrDef = [ + ['calcCompleted', 'true'], + ['calcMode', 'auto'], + ['calcOnSave', 'true'], + ['concurrentCalc', 'true'], + ['fullCalcOnLoad', 'false'], + ['fullPrecision', 'true'], + ['iterate', 'false'], + ['iterateCount', '100'], + ['iterateDelta', '0.001'], + ['refMode', 'A1'] + ]; + + /* 18.2.3 (CT_CustomWorkbookView) Defaults */ + /*var CustomWBViewDef = [ + ['autoUpdate', 'false'], + ['changesSavedWin', 'false'], + ['includeHiddenRowCol', 'true'], + ['includePrintSettings', 'true'], + ['maximized', 'false'], + ['minimized', 'false'], + ['onlySync', 'false'], + ['personalView', 'false'], + ['showComments', 'commIndicator'], + ['showFormulaBar', 'true'], + ['showHorizontalScroll', 'true'], + ['showObjects', 'all'], + ['showSheetTabs', 'true'], + ['showStatusbar', 'true'], + ['showVerticalScroll', 'true'], + ['tabRatio', '600'], + ['xWindow', '0'], + ['yWindow', '0'] +];*/ + + function push_defaults_array(target, defaults) { + for(var j = 0; j != target.length; ++j) { var w = target[j]; + for(var i=0; i != defaults.length; ++i) { var z = defaults[i]; + if(w[z[0]] == null) w[z[0]] = z[1]; + else switch(z[2]) { + case "bool": if(typeof w[z[0]] == "string") w[z[0]] = parsexmlbool(w[z[0]]); break; + case "int": if(typeof w[z[0]] == "string") w[z[0]] = parseInt(w[z[0]], 10); break; + } + } + } + } + function push_defaults(target, defaults) { + for(var i = 0; i != defaults.length; ++i) { var z = defaults[i]; + if(target[z[0]] == null) target[z[0]] = z[1]; + else switch(z[2]) { + case "bool": if(typeof target[z[0]] == "string") target[z[0]] = parsexmlbool(target[z[0]]); break; + case "int": if(typeof target[z[0]] == "string") target[z[0]] = parseInt(target[z[0]], 10); break; + } + } + } + + function parse_wb_defaults(wb) { + push_defaults(wb.WBProps, WBPropsDef); + push_defaults(wb.CalcPr, CalcPrDef); + + push_defaults_array(wb.WBView, WBViewDef); + push_defaults_array(wb.Sheets, SheetDef); + + _ssfopts.date1904 = parsexmlbool(wb.WBProps.date1904); + } + + function safe1904(wb) { + /* TODO: store date1904 somewhere else */ + if(!wb.Workbook) return "false"; + if(!wb.Workbook.WBProps) return "false"; + return parsexmlbool(wb.Workbook.WBProps.date1904) ? "true" : "false"; + } + + var badchars = "][*?\/\\".split(""); + function check_ws_name(n, safe) { + if(n.length > 31) { if(safe) return false; throw new Error("Sheet names cannot exceed 31 chars"); } + var _good = true; + badchars.forEach(function(c) { + if(n.indexOf(c) == -1) return; + if(!safe) throw new Error("Sheet name cannot contain : \\ / ? * [ ]"); + _good = false; + }); + return _good; + } + function check_wb_names(N, S, codes) { + N.forEach(function(n,i) { + check_ws_name(n); + for(var j = 0; j < i; ++j) if(n == N[j]) throw new Error("Duplicate Sheet Name: " + n); + if(codes) { + var cn = (S && S[i] && S[i].CodeName) || n; + if(cn.charCodeAt(0) == 95 && cn.length > 22) throw new Error("Bad Code Name: Worksheet" + cn); + } + }); + } + function check_wb(wb) { + if(!wb || !wb.SheetNames || !wb.Sheets) throw new Error("Invalid Workbook"); + if(!wb.SheetNames.length) throw new Error("Workbook is empty"); + var Sheets = (wb.Workbook && wb.Workbook.Sheets) || []; + check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw); + for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i); + /* TODO: validate workbook */ + } + /* 18.2 Workbook */ + var wbnsregex = /<\w+:workbook/; + function parse_wb_xml(data, opts) { + if(!data) throw new Error("Could not find file"); + var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, Names:[], xmlns: "" }; + var pass = false, xmlns = "xmlns"; + var dname = {}, dnstart = 0; + data.replace(tagregex, function xml_wb(x, idx) { + var y = parsexmltag(x); + switch(strip_ns(y[0])) { + case '': break; + + /* 18.2.13 fileVersion CT_FileVersion ? */ + case '': case '': break; + + /* 18.2.12 fileSharing CT_FileSharing ? */ + case '': break; + + /* 18.2.28 workbookPr CT_WorkbookPr ? */ + case '': + WBPropsDef.forEach(function(w) { + if(y[w[0]] == null) return; + switch(w[2]) { + case "bool": wb.WBProps[w[0]] = parsexmlbool(y[w[0]]); break; + case "int": wb.WBProps[w[0]] = parseInt(y[w[0]], 10); break; + default: wb.WBProps[w[0]] = y[w[0]]; + } + }); + if(y.codeName) wb.WBProps.CodeName = y.codeName; + break; + case '': break; + + /* 18.2.29 workbookProtection CT_WorkbookProtection ? */ + case '': break; + + /* 18.2.1 bookViews CT_BookViews ? */ + case '': case '': break; + /* 18.2.30 workbookView CT_BookView + */ + case '': delete y[0]; wb.WBView.push(y); break; + case '': break; + + /* 18.2.20 sheets CT_Sheets 1 */ + case '': case '': break; // aggregate sheet + /* 18.2.19 sheet CT_Sheet + */ + case '': break; + + /* 18.2.15 functionGroups CT_FunctionGroups ? */ + case '': break; + /* 18.2.14 functionGroup CT_FunctionGroup + */ + case '': case '': break; + /* 18.2.8 externalReference CT_ExternalReference + */ + case '': break; + case '': case '': pass=false; break; + /* 18.2.5 definedName CT_DefinedName + */ + case '': { + dname.Ref = unescapexml(utf8read(data.slice(dnstart, idx))); + wb.Names.push(dname); + } break; + case '': break; + + /* 18.2.2 calcPr CT_CalcPr ? */ + case '': delete y[0]; wb.CalcPr = y; break; + case '': break; + + /* 18.2.16 oleSize CT_OleSize ? (ref required) */ + case '': case '': case '': break; + + /* 18.2.18 pivotCaches CT_PivotCaches ? */ + case '': case '': case '': break; + + /* 18.2.23 smartTagTypes CT_SmartTagTypes ? */ + case '': case '': break; + /* 18.2.22 smartTagType CT_SmartTagType ? */ + case '': break; + + /* 18.2.11 fileRecoveryPr CT_FileRecoveryPr ? */ + case '': break; + + /* 18.2.26 webPublishObjects CT_WebPublishObjects ? */ + case '': case '': break; + /* 18.2.25 webPublishObject CT_WebPublishObject ? */ + case '': case '': case '': break; + /* 18.2.7 ext CT_Extension + */ + case '': pass=false; break; + + /* Others */ + case '': pass=true; break; + case '': pass=false; break; + + /* TODO */ + case ' 0); + + /* fileVersion */ + /* fileSharing */ + + var workbookPr = ({codeName:"ThisWorkbook"}); + if(wb.Workbook && wb.Workbook.WBProps) { + WBPropsDef.forEach(function(x) { + if((wb.Workbook.WBProps[x[0]]) == null) return; + if((wb.Workbook.WBProps[x[0]]) == x[1]) return; + workbookPr[x[0]] = (wb.Workbook.WBProps[x[0]]); + }); + if(wb.Workbook.WBProps.CodeName) { workbookPr.codeName = wb.Workbook.WBProps.CodeName; delete workbookPr.CodeName; } + } + o[o.length] = (writextag('workbookPr', null, workbookPr)); + + /* workbookProtection */ + + var sheets = wb.Workbook && wb.Workbook.Sheets || []; + var i = 0; + + /* bookViews */ + + o[o.length] = ""; + for(i = 0; i != wb.SheetNames.length; ++i) { + var sht = ({name:escapexml(wb.SheetNames[i].slice(0,31))}); + sht.sheetId = ""+(i+1); + sht["r:id"] = "rId"+(i+1); + if(sheets[i]) switch(sheets[i].Hidden) { + case 1: sht.state = "hidden"; break; + case 2: sht.state = "veryHidden"; break; + } + o[o.length] = (writextag('sheet',null,sht)); + } + o[o.length] = ""; + + /* functionGroups */ + /* externalReferences */ + + if(write_names) { + o[o.length] = ""; + if(wb.Workbook && wb.Workbook.Names) wb.Workbook.Names.forEach(function(n) { + var d = {name:n.Name}; + if(n.Comment) d.comment = n.Comment; + if(n.Sheet != null) d.localSheetId = ""+n.Sheet; + if(n.Hidden) d.hidden = "1"; + if(!n.Ref) return; + o[o.length] = writextag('definedName', String(n.Ref).replace(//g, ">"), d); + }); + o[o.length] = ""; + } + + /* calcPr */ + /* oleSize */ + /* customWorkbookViews */ + /* pivotCaches */ + /* smartTagPr */ + /* smartTagTypes */ + /* webPublishing */ + /* fileRecoveryPr */ + /* webPublishObjects */ + /* extLst */ + + if(o.length>2){ o[o.length] = ''; o[1]=o[1].replace("/>",">"); } + return o.join(""); + } + /* [MS-XLSB] 2.4.304 BrtBundleSh */ + function parse_BrtBundleSh(data, length) { + var z = {}; + z.Hidden = data.read_shift(4); //hsState ST_SheetState + z.iTabID = data.read_shift(4); + z.strRelID = parse_RelID(data,length-8); + z.name = parse_XLWideString(data); + return z; + } + function write_BrtBundleSh(data, o) { + if(!o) o = new_buf(127); + o.write_shift(4, data.Hidden); + o.write_shift(4, data.iTabID); + write_RelID(data.strRelID, o); + write_XLWideString(data.name.slice(0,31), o); + return o.length > o.l ? o.slice(0, o.l) : o; + } + + /* [MS-XLSB] 2.4.815 BrtWbProp */ + function parse_BrtWbProp(data, length) { + var o = ({}); + var flags = data.read_shift(4); + o.defaultThemeVersion = data.read_shift(4); + var strName = (length > 8) ? parse_XLWideString(data) : ""; + if(strName.length > 0) o.CodeName = strName; + o.autoCompressPictures = !!(flags & 0x10000); + o.backupFile = !!(flags & 0x40); + o.checkCompatibility = !!(flags & 0x1000); + o.date1904 = !!(flags & 0x01); + o.filterPrivacy = !!(flags & 0x08); + o.hidePivotFieldList = !!(flags & 0x400); + o.promptedSolutions = !!(flags & 0x10); + o.publishItems = !!(flags & 0x800); + o.refreshAllConnections = !!(flags & 0x40000); + o.saveExternalLinkValues = !!(flags & 0x80); + o.showBorderUnselectedTables = !!(flags & 0x04); + o.showInkAnnotation = !!(flags & 0x20); + o.showObjects = ["all", "placeholders", "none"][(flags >> 13) & 0x03]; + o.showPivotChartFilter = !!(flags & 0x8000); + o.updateLinks = ["userSet", "never", "always"][(flags >> 8) & 0x03]; + return o; + } + function write_BrtWbProp(data, o) { + if(!o) o = new_buf(72); + var flags = 0; + if(data) { + /* TODO: mirror parse_BrtWbProp fields */ + if(data.filterPrivacy) flags |= 0x08; + } + o.write_shift(4, flags); + o.write_shift(4, 0); + write_XLSBCodeName(data && data.CodeName || "ThisWorkbook", o); + return o.slice(0, o.l); + } + + function parse_BrtFRTArchID$(data, length) { + var o = {}; + data.read_shift(4); + o.ArchID = data.read_shift(4); + data.l += length - 8; + return o; + } + + /* [MS-XLSB] 2.4.687 BrtName */ + function parse_BrtName(data, length, opts) { + var end = data.l + length; + data.l += 4; //var flags = data.read_shift(4); + data.l += 1; //var chKey = data.read_shift(1); + var itab = data.read_shift(4); + var name = parse_XLNameWideString(data); + var formula = parse_XLSBNameParsedFormula(data, 0, opts); + var comment = parse_XLNullableWideString(data); + //if(0 /* fProc */) { + // unusedstring1: XLNullableWideString + // description: XLNullableWideString + // helpTopic: XLNullableWideString + // unusedstring2: XLNullableWideString + //} + data.l = end; + var out = ({Name:name, Ptg:formula}); + if(itab < 0xFFFFFFF) out.Sheet = itab; + if(comment) out.Comment = comment; + return out; + } + + /* [MS-XLSB] 2.1.7.61 Workbook */ + function parse_wb_bin(data, opts) { + var wb = { AppVersion:{}, WBProps:{}, WBView:[], Sheets:[], CalcPr:{}, xmlns: "" }; + var state = []; + var pass = false; + + if(!opts) opts = {}; + opts.biff = 12; + + var Names = []; + var supbooks = ([[]]); + supbooks.SheetNames = []; + supbooks.XTI = []; + + recordhopper(data, function hopper_wb(val, R_n, RT) { + switch(RT) { + case 0x009C: /* 'BrtBundleSh' */ + supbooks.SheetNames.push(val.name); + wb.Sheets.push(val); break; + + case 0x0099: /* 'BrtWbProp' */ + wb.WBProps = val; break; + + case 0x0027: /* 'BrtName' */ + if(val.Sheet != null) opts.SID = val.Sheet; + val.Ref = stringify_formula(val.Ptg, null, null, supbooks, opts); + delete opts.SID; + delete val.Ptg; + Names.push(val); + break; + case 0x040C: /* 'BrtNameExt' */ break; + + case 0x0165: /* 'BrtSupSelf' */ + case 0x0166: /* 'BrtSupSame' */ + case 0x0163: /* 'BrtSupBookSrc' */ + case 0x029B: /* 'BrtSupAddin' */ + if(!supbooks[0].length) supbooks[0] = [RT, val]; + else supbooks.push([RT, val]); + supbooks[supbooks.length - 1].XTI = []; + break; + case 0x016A: /* 'BrtExternSheet' */ + if(supbooks.length === 0) { supbooks[0] = []; supbooks[0].XTI = []; } + supbooks[supbooks.length - 1].XTI = supbooks[supbooks.length - 1].XTI.concat(val); + supbooks.XTI = supbooks.XTI.concat(val); + break; + case 0x0169: /* 'BrtPlaceholderName' */ + break; + + /* case 'BrtModelTimeGroupingCalcCol' */ + case 0x0C00: /* 'BrtUid' */ + case 0x0C01: /* 'BrtRevisionPtr' */ + case 0x0817: /* 'BrtAbsPath15' */ + case 0x0216: /* 'BrtBookProtection' */ + case 0x02A5: /* 'BrtBookProtectionIso' */ + case 0x009E: /* 'BrtBookView' */ + case 0x009D: /* 'BrtCalcProp' */ + case 0x0262: /* 'BrtCrashRecErr' */ + case 0x0802: /* 'BrtDecoupledPivotCacheID' */ + case 0x009B: /* 'BrtFileRecover' */ + case 0x0224: /* 'BrtFileSharing' */ + case 0x02A4: /* 'BrtFileSharingIso' */ + case 0x0080: /* 'BrtFileVersion' */ + case 0x0299: /* 'BrtFnGroup' */ + case 0x0850: /* 'BrtModelRelationship' */ + case 0x084D: /* 'BrtModelTable' */ + case 0x0225: /* 'BrtOleSize' */ + case 0x0805: /* 'BrtPivotTableRef' */ + case 0x0254: /* 'BrtSmartTagType' */ + case 0x081C: /* 'BrtTableSlicerCacheID' */ + case 0x081B: /* 'BrtTableSlicerCacheIDs' */ + case 0x0822: /* 'BrtTimelineCachePivotCacheID' */ + case 0x018D: /* 'BrtUserBookView' */ + case 0x009A: /* 'BrtWbFactoid' */ + case 0x045D: /* 'BrtWbProp14' */ + case 0x0229: /* 'BrtWebOpt' */ + case 0x082B: /* 'BrtWorkBookPr15' */ + break; + + case 0x0023: /* 'BrtFRTBegin' */ + state.push(R_n); pass = true; break; + case 0x0024: /* 'BrtFRTEnd' */ + state.pop(); pass = false; break; + case 0x0025: /* 'BrtACBegin' */ + state.push(R_n); pass = true; break; + case 0x0026: /* 'BrtACEnd' */ + state.pop(); pass = false; break; + + case 0x0010: /* 'BrtFRTArchID$' */ break; + + default: + if((R_n||"").indexOf("Begin") > 0){/* empty */} + else if((R_n||"").indexOf("End") > 0){/* empty */} + else if(!pass || (opts.WTF && state[state.length-1] != "BrtACBegin" && state[state.length-1] != "BrtFRTBegin")) throw new Error("Unexpected record " + RT + " " + R_n); + } + }, opts); + + parse_wb_defaults(wb); + + // $FlowIgnore + wb.Names = Names; + + (wb).supbooks = supbooks; + return wb; + } + + function write_BUNDLESHS(ba, wb) { + write_record(ba, "BrtBeginBundleShs"); + for(var idx = 0; idx != wb.SheetNames.length; ++idx) { + var viz = wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx] && wb.Workbook.Sheets[idx].Hidden || 0; + var d = { Hidden: viz, iTabID: idx+1, strRelID: 'rId' + (idx+1), name: wb.SheetNames[idx] }; + write_record(ba, "BrtBundleSh", write_BrtBundleSh(d)); + } + write_record(ba, "BrtEndBundleShs"); + } + + /* [MS-XLSB] 2.4.649 BrtFileVersion */ + function write_BrtFileVersion(data, o) { + if(!o) o = new_buf(127); + for(var i = 0; i != 4; ++i) o.write_shift(4, 0); + write_XLWideString("SheetJS", o); + write_XLWideString(XLSX.version, o); + write_XLWideString(XLSX.version, o); + write_XLWideString("7262", o); + o.length = o.l; + return o.length > o.l ? o.slice(0, o.l) : o; + } + + /* [MS-XLSB] 2.4.301 BrtBookView */ + function write_BrtBookView(idx, o) { + if(!o) o = new_buf(29); + o.write_shift(-4, 0); + o.write_shift(-4, 460); + o.write_shift(4, 28800); + o.write_shift(4, 17600); + o.write_shift(4, 500); + o.write_shift(4, idx); + o.write_shift(4, idx); + var flags = 0x78; + o.write_shift(1, flags); + return o.length > o.l ? o.slice(0, o.l) : o; + } + + function write_BOOKVIEWS(ba, wb) { + /* required if hidden tab appears before visible tab */ + if(!wb.Workbook || !wb.Workbook.Sheets) return; + var sheets = wb.Workbook.Sheets; + var i = 0, vistab = -1, hidden = -1; + for(; i < sheets.length; ++i) { + if(!sheets[i] || !sheets[i].Hidden && vistab == -1) vistab = i; + else if(sheets[i].Hidden == 1 && hidden == -1) hidden = i; + } + if(hidden > vistab) return; + write_record(ba, "BrtBeginBookViews"); + write_record(ba, "BrtBookView", write_BrtBookView(vistab)); + /* 1*(BrtBookView *FRT) */ + write_record(ba, "BrtEndBookViews"); + } + + /* [MS-XLSB] 2.4.305 BrtCalcProp */ + /*function write_BrtCalcProp(data, o) { + if(!o) o = new_buf(26); + o.write_shift(4,0); // force recalc + o.write_shift(4,1); + o.write_shift(4,0); + write_Xnum(0, o); + o.write_shift(-4, 1023); + o.write_shift(1, 0x33); + o.write_shift(1, 0x00); + return o; +}*/ + + /* [MS-XLSB] 2.4.646 BrtFileRecover */ + /*function write_BrtFileRecover(data, o) { + if(!o) o = new_buf(1); + o.write_shift(1,0); + return o; +}*/ + + /* [MS-XLSB] 2.1.7.61 Workbook */ + function write_wb_bin(wb, opts) { + var ba = buf_array(); + write_record(ba, "BrtBeginBook"); + write_record(ba, "BrtFileVersion", write_BrtFileVersion()); + /* [[BrtFileSharingIso] BrtFileSharing] */ + write_record(ba, "BrtWbProp", write_BrtWbProp(wb.Workbook && wb.Workbook.WBProps || null)); + /* [ACABSPATH] */ + /* [[BrtBookProtectionIso] BrtBookProtection] */ + write_BOOKVIEWS(ba, wb, opts); + write_BUNDLESHS(ba, wb, opts); + /* [FNGROUP] */ + /* [EXTERNALS] */ + /* *BrtName */ + /* write_record(ba, "BrtCalcProp", write_BrtCalcProp()); */ + /* [BrtOleSize] */ + /* *(BrtUserBookView *FRT) */ + /* [PIVOTCACHEIDS] */ + /* [BrtWbFactoid] */ + /* [SMARTTAGTYPES] */ + /* [BrtWebOpt] */ + /* write_record(ba, "BrtFileRecover", write_BrtFileRecover()); */ + /* [WEBPUBITEMS] */ + /* [CRERRS] */ + /* FRTWORKBOOK */ + write_record(ba, "BrtEndBook"); + + return ba.end(); + } + function parse_wb(data, name, opts) { + if(name.slice(-4)===".bin") return parse_wb_bin((data), opts); + return parse_wb_xml((data), opts); + } + + function parse_ws(data, name, idx, opts, rels, wb, themes, styles) { + if(name.slice(-4)===".bin") return parse_ws_bin((data), opts, idx, rels, wb, themes, styles); + return parse_ws_xml((data), opts, idx, rels, wb, themes, styles); + } + + function parse_cs(data, name, idx, opts, rels, wb, themes, styles) { + if(name.slice(-4)===".bin") return parse_cs_bin((data), opts, idx, rels, wb, themes, styles); + return parse_cs_xml((data), opts, idx, rels, wb, themes, styles); + } + + function parse_ms(data, name, idx, opts, rels, wb, themes, styles) { + if(name.slice(-4)===".bin") return parse_ms_bin((data), opts, idx, rels, wb, themes, styles); + return parse_ms_xml((data), opts, idx, rels, wb, themes, styles); + } + + function parse_ds(data, name, idx, opts, rels, wb, themes, styles) { + if(name.slice(-4)===".bin") return parse_ds_bin((data), opts, idx, rels, wb, themes, styles); + return parse_ds_xml((data), opts, idx, rels, wb, themes, styles); + } + + function parse_sty(data, name, themes, opts) { + if(name.slice(-4)===".bin") return parse_sty_bin((data), themes, opts); + return parse_sty_xml((data), themes, opts); + } + + function parse_theme(data, name, opts) { + return parse_theme_xml(data, opts); + } + + function parse_sst(data, name, opts) { + if(name.slice(-4)===".bin") return parse_sst_bin((data), opts); + return parse_sst_xml((data), opts); + } + + function parse_cmnt(data, name, opts) { + if(name.slice(-4)===".bin") return parse_comments_bin((data), opts); + return parse_comments_xml((data), opts); + } + + function parse_cc(data, name, opts) { + if(name.slice(-4)===".bin") return parse_cc_bin((data), name, opts); + return parse_cc_xml((data), name, opts); + } + + function parse_xlink(data, name, opts) { + if(name.slice(-4)===".bin") return parse_xlink_bin((data), name, opts); + return parse_xlink_xml((data), name, opts); + } + + function write_wb(wb, name, opts) { + return (name.slice(-4)===".bin" ? write_wb_bin : write_wb_xml)(wb, opts); + } + + function write_ws(data, name, opts, wb, rels) { + return (name.slice(-4)===".bin" ? write_ws_bin : write_ws_xml)(data, opts, wb, rels); + } + +// eslint-disable-next-line no-unused-vars + function write_cs(data, name, opts, wb, rels) { + return (name.slice(-4)===".bin" ? write_cs_bin : write_cs_xml)(data, opts, wb, rels); + } + + function write_sty(data, name, opts) { + return (name.slice(-4)===".bin" ? write_sty_bin : write_sty_xml)(data, opts); + } + + function write_sst(data, name, opts) { + return (name.slice(-4)===".bin" ? write_sst_bin : write_sst_xml)(data, opts); + } + + function write_cmnt(data, name, opts) { + return (name.slice(-4)===".bin" ? write_comments_bin : write_comments_xml)(data, opts); + } + /* +function write_cc(data, name:string, opts) { + return (name.slice(-4)===".bin" ? write_cc_bin : write_cc_xml)(data, opts); +} +*/ + var attregexg2=/([\w:]+)=((?:")([^"]*)(?:")|(?:')([^']*)(?:'))/g; + var attregex2=/([\w:]+)=((?:")(?:[^"]*)(?:")|(?:')(?:[^']*)(?:'))/; + var _chr = function(c) { return String.fromCharCode(c); }; + function xlml_parsexmltag(tag, skip_root) { + var words = tag.split(/\s+/); + var z = ([]); if(!skip_root) z[0] = words[0]; + if(words.length === 1) return z; + var m = tag.match(attregexg2), y, j, w, i; + if(m) for(i = 0; i != m.length; ++i) { + y = m[i].match(attregex2); + if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].slice(1,y[2].length-1); + else { + if(y[1].slice(0,6) === "xmlns:") w = "xmlns"+y[1].slice(6); + else w = y[1].slice(j+1); + z[w] = y[2].slice(1,y[2].length-1); + } + } + return z; + } + function xlml_parsexmltagobj(tag) { + var words = tag.split(/\s+/); + var z = {}; + if(words.length === 1) return z; + var m = tag.match(attregexg2), y, j, w, i; + if(m) for(i = 0; i != m.length; ++i) { + y = m[i].match(attregex2); + if((j=y[1].indexOf(":")) === -1) z[y[1]] = y[2].slice(1,y[2].length-1); + else { + if(y[1].slice(0,6) === "xmlns:") w = "xmlns"+y[1].slice(6); + else w = y[1].slice(j+1); + z[w] = y[2].slice(1,y[2].length-1); + } + } + return z; + } + +// ---- + + function xlml_format(format, value) { + var fmt = XLMLFormatMap[format] || unescapexml(format); + if(fmt === "General") return SSF._general(value); + return SSF.format(fmt, value); + } + + function xlml_set_custprop(Custprops, key, cp, val) { + var oval = val; + switch((cp[0].match(/dt:dt="([\w.]+)"/)||["",""])[1]) { + case "boolean": oval = parsexmlbool(val); break; + case "i2": case "int": oval = parseInt(val, 10); break; + case "r4": case "float": oval = parseFloat(val); break; + case "date": case "dateTime.tz": oval = parseDate(val); break; + case "i8": case "string": case "fixed": case "uuid": case "bin.base64": break; + default: throw new Error("bad custprop:" + cp[0]); + } + Custprops[unescapexml(key)] = oval; + } + + function safe_format_xlml(cell, nf, o) { + if(cell.t === 'z') return; + if(!o || o.cellText !== false) try { + if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; } + else if(nf === "General") { + if(cell.t === 'n') { + if((cell.v|0) === cell.v) cell.w = SSF._general_int(cell.v); + else cell.w = SSF._general_num(cell.v); + } + else cell.w = SSF._general(cell.v); + } + else cell.w = xlml_format(nf||"General", cell.v); + } catch(e) { if(o.WTF) throw e; } + try { + var z = XLMLFormatMap[nf]||nf||"General"; + if(o.cellNF) cell.z = z; + if(o.cellDates && cell.t == 'n' && SSF.is_date(z)) { + var _d = SSF.parse_date_code(cell.v); if(_d) { cell.t = 'd'; cell.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); } + } + } catch(e) { if(o.WTF) throw e; } + } + + function process_style_xlml(styles, stag, opts) { + if(opts.cellStyles) { + if(stag.Interior) { + var I = stag.Interior; + if(I.Pattern) I.patternType = XLMLPatternTypeMap[I.Pattern] || I.Pattern; + } + } + styles[stag.ID] = stag; + } + + /* TODO: there must exist some form of OSP-blessed spec */ + function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, arrayf, o) { + var nf = "General", sid = cell.StyleID, S = {}; o = o || {}; + var interiors = []; + var i = 0; + if(sid === undefined && row) sid = row.StyleID; + if(sid === undefined && csty) sid = csty.StyleID; + while(styles[sid] !== undefined) { + if(styles[sid].nf) nf = styles[sid].nf; + if(styles[sid].Interior) interiors.push(styles[sid].Interior); + if(!styles[sid].Parent) break; + sid = styles[sid].Parent; + } + switch(data.Type) { + case 'Boolean': + cell.t = 'b'; + cell.v = parsexmlbool(xml); + break; + case 'String': + cell.t = 's'; cell.r = xlml_fixstr(unescapexml(xml)); + cell.v = xml.indexOf("<") > -1 ? unescapexml(ss) : cell.r; + break; + case 'DateTime': + if(xml.slice(-1) != "Z") xml += "Z"; + cell.v = (parseDate(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000); + if(cell.v !== cell.v) cell.v = unescapexml(xml); + else if(cell.v<60) cell.v = cell.v -1; + if(!nf || nf == "General") nf = "yyyy-mm-dd"; + /* falls through */ + case 'Number': + if(cell.v === undefined) cell.v=+xml; + if(!cell.t) cell.t = 'n'; + break; + case 'Error': cell.t = 'e'; cell.v = RBErr[xml]; if(o.cellText !== false) cell.w = xml; break; + default: cell.t = 's'; cell.v = xlml_fixstr(ss||xml); break; + } + safe_format_xlml(cell, nf, o); + if(o.cellFormula !== false) { + if(cell.Formula) { + var fstr = unescapexml(cell.Formula); + /* strictly speaking, the leading = is required but some writers omit */ + if(fstr.charCodeAt(0) == 61 /* = */) fstr = fstr.slice(1); + cell.f = rc_to_a1(fstr, base); + delete cell.Formula; + if(cell.ArrayRange == "RC") cell.F = rc_to_a1("RC:RC", base); + else if(cell.ArrayRange) { + cell.F = rc_to_a1(cell.ArrayRange, base); + arrayf.push([safe_decode_range(cell.F), cell.F]); + } + } else { + for(i = 0; i < arrayf.length; ++i) + if(base.r >= arrayf[i][0].s.r && base.r <= arrayf[i][0].e.r) + if(base.c >= arrayf[i][0].s.c && base.c <= arrayf[i][0].e.c) + cell.F = arrayf[i][1]; + } + } + if(o.cellStyles) { + interiors.forEach(function(x) { + if(!S.patternType && x.patternType) S.patternType = x.patternType; + }); + cell.s = S; + } + if(cell.StyleID !== undefined) cell.ixfe = cell.StyleID; + } + + function xlml_clean_comment(comment) { + comment.t = comment.v || ""; + comment.t = comment.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n"); + comment.v = comment.w = comment.ixfe = undefined; + } + + function xlml_normalize(d) { + if(has_buf && Buffer.isBuffer(d)) return d.toString('utf8'); + if(typeof d === 'string') return d; + /* duktape */ + if(typeof Uint8Array !== 'undefined' && d instanceof Uint8Array) return utf8read(a2s(ab2a(d))); + throw new Error("Bad input format: expected Buffer or string"); + } + + /* TODO: Everything */ + /* UOS uses CJK in tags */ + var xlmlregex = /<(\/?)([^\s?>!\/:]*:|)([^\s?>:\/]+)[^>]*>/mg; +//var xlmlregex = /<(\/?)([a-z0-9]*:|)(\w+)[^>]*>/mg; + function parse_xlml_xml(d, _opts) { + var opts = _opts || {}; + make_ssf(SSF); + var str = debom(xlml_normalize(d)); + if(opts.type == 'binary' || opts.type == 'array' || opts.type == 'base64') { + if(typeof cptable !== 'undefined') str = cptable.utils.decode(65001, char_codes(str)); + else str = utf8read(str); + } + var opening = str.slice(0, 1024).toLowerCase(), ishtml = false; + if(opening.indexOf("= 0) ishtml = true; }); + if(ishtml) return HTML_.to_workbook(str, opts); + var Rn; + var state = [], tmp; + if(DENSE != null && opts.dense == null) opts.dense = DENSE; + var sheets = {}, sheetnames = [], cursheet = (opts.dense ? [] : {}), sheetname = ""; + var table = {}, cell = ({}), row = {};// eslint-disable-line no-unused-vars + var dtag = xlml_parsexmltag(''), didx = 0; + var c = 0, r = 0; + var refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; + var styles = {}, stag = {}; + var ss = "", fidx = 0; + var merges = []; + var Props = {}, Custprops = {}, pidx = 0, cp = []; + var comments = [], comment = ({}); + var cstys = [], csty, seencol = false; + var arrayf = []; + var rowinfo = [], rowobj = {}, cc = 0, rr = 0; + var Workbook = ({ Sheets:[], WBProps:{date1904:false} }), wsprops = {}; + xlmlregex.lastIndex = 0; + str = str.replace(//mg,""); + while((Rn = xlmlregex.exec(str))) switch(Rn[3]) { + case 'Data': + if(state[state.length-1][1]) break; + if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]=="Comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts); + else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; } + break; + case 'Cell': + if(Rn[1]==='/'){ + if(comments.length > 0) cell.c = comments; + if((!opts.sheetRows || opts.sheetRows > r) && cell.v !== undefined) { + if(opts.dense) { + if(!cursheet[r]) cursheet[r] = []; + cursheet[r][c] = cell; + } else cursheet[encode_col(c) + encode_row(r)] = cell; + } + if(cell.HRef) { + cell.l = ({Target:cell.HRef}); + if(cell.HRefScreenTip) cell.l.Tooltip = cell.HRefScreenTip; + delete cell.HRef; delete cell.HRefScreenTip; + } + if(cell.MergeAcross || cell.MergeDown) { + cc = c + (parseInt(cell.MergeAcross,10)|0); + rr = r + (parseInt(cell.MergeDown,10)|0); + merges.push({s:{c:c,r:r},e:{c:cc,r:rr}}); + } + if(!opts.sheetStubs) { if(cell.MergeAcross) c = cc + 1; else ++c; } + else if(cell.MergeAcross || cell.MergeDown) { + for(var cma = c; cma <= cc; ++cma) { + for(var cmd = r; cmd <= rr; ++cmd) { + if(cma > c || cmd > r) { + if(opts.dense) { + if(!cursheet[cmd]) cursheet[cmd] = []; + cursheet[cmd][cma] = {t:'z'}; + } else cursheet[encode_col(cma) + encode_row(cmd)] = {t:'z'}; + } + } + } + c = cc + 1; + } + else ++c; + } else { + cell = xlml_parsexmltagobj(Rn[0]); + if(cell.Index) c = +cell.Index - 1; + if(c < refguess.s.c) refguess.s.c = c; + if(c > refguess.e.c) refguess.e.c = c; + if(Rn[0].slice(-2) === "/>") ++c; + comments = []; + } + break; + case 'Row': + if(Rn[1]==='/' || Rn[0].slice(-2) === "/>") { + if(r < refguess.s.r) refguess.s.r = r; + if(r > refguess.e.r) refguess.e.r = r; + if(Rn[0].slice(-2) === "/>") { + row = xlml_parsexmltag(Rn[0]); + if(row.Index) r = +row.Index - 1; + } + c = 0; ++r; + } else { + row = xlml_parsexmltag(Rn[0]); + if(row.Index) r = +row.Index - 1; + rowobj = {}; + if(row.AutoFitHeight == "0" || row.Height) { + rowobj.hpx = parseInt(row.Height, 10); rowobj.hpt = px2pt(rowobj.hpx); + rowinfo[r] = rowobj; + } + if(row.Hidden == "1") { rowobj.hidden = true; rowinfo[r] = rowobj; } + } + break; + case 'Worksheet': /* TODO: read range from FullRows/FullColumns */ + if(Rn[1]==='/'){ + if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|")); + sheetnames.push(sheetname); + if(refguess.s.r <= refguess.e.r && refguess.s.c <= refguess.e.c) { + cursheet["!ref"] = encode_range(refguess); + if(opts.sheetRows && opts.sheetRows <= refguess.e.r) { + cursheet["!fullref"] = cursheet["!ref"]; + refguess.e.r = opts.sheetRows - 1; + cursheet["!ref"] = encode_range(refguess); + } + } + if(merges.length) cursheet["!merges"] = merges; + if(cstys.length > 0) cursheet["!cols"] = cstys; + if(rowinfo.length > 0) cursheet["!rows"] = rowinfo; + sheets[sheetname] = cursheet; + } else { + refguess = {s: {r:2000000, c:2000000}, e: {r:0, c:0} }; + r = c = 0; + state.push([Rn[3], false]); + tmp = xlml_parsexmltag(Rn[0]); + sheetname = unescapexml(tmp.Name); + cursheet = (opts.dense ? [] : {}); + merges = []; + arrayf = []; + rowinfo = []; + wsprops = {name:sheetname, Hidden:0}; + Workbook.Sheets.push(wsprops); + } + break; + case 'Table': + if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));} + else if(Rn[0].slice(-2) == "/>") break; + else { + table = xlml_parsexmltag(Rn[0]); + state.push([Rn[3], false]); + cstys = []; seencol = false; + } + break; + + case 'Style': + if(Rn[1]==='/') process_style_xlml(styles, stag, opts); + else stag = xlml_parsexmltag(Rn[0]); + break; + + case 'NumberFormat': + stag.nf = unescapexml(xlml_parsexmltag(Rn[0]).Format || "General"); + if(XLMLFormatMap[stag.nf]) stag.nf = XLMLFormatMap[stag.nf]; + for(var ssfidx = 0; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == stag.nf) break; + if(ssfidx == 0x188) for(ssfidx = 0x39; ssfidx != 0x188; ++ssfidx) if(SSF._table[ssfidx] == null) { SSF.load(stag.nf, ssfidx); break; } + break; + + case 'Column': + if(state[state.length-1][0] !== 'Table') break; + csty = xlml_parsexmltag(Rn[0]); + if(csty.Hidden) { csty.hidden = true; delete csty.Hidden; } + if(csty.Width) csty.wpx = parseInt(csty.Width, 10); + if(!seencol && csty.wpx > 10) { + seencol = true; MDW = DEF_MDW; //find_mdw_wpx(csty.wpx); + for(var _col = 0; _col < cstys.length; ++_col) if(cstys[_col]) process_col(cstys[_col]); + } + if(seencol) process_col(csty); + cstys[(csty.Index-1||cstys.length)] = csty; + for(var i = 0; i < +csty.Span; ++i) cstys[cstys.length] = dup(csty); + break; + + case 'NamedRange': + if(!Workbook.Names) Workbook.Names = []; + var _NamedRange = parsexmltag(Rn[0]); + var _DefinedName = ({ + Name: _NamedRange.Name, + Ref: rc_to_a1(_NamedRange.RefersTo.slice(1), {r:0, c:0}) + }); + if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1; + Workbook.Names.push(_DefinedName); + break; + + case 'NamedCell': break; + case 'B': break; + case 'I': break; + case 'U': break; + case 'S': break; + case 'Sub': break; + case 'Sup': break; + case 'Span': break; + case 'Border': break; + case 'Alignment': break; + case 'Borders': break; + case 'Font': + if(Rn[0].slice(-2) === "/>") break; + else if(Rn[1]==="/") ss += str.slice(fidx, Rn.index); + else fidx = Rn.index + Rn[0].length; + break; + case 'Interior': + if(!opts.cellStyles) break; + stag.Interior = xlml_parsexmltag(Rn[0]); + break; + case 'Protection': break; + + case 'Author': + case 'Title': + case 'Description': + case 'Created': + case 'Keywords': + case 'Subject': + case 'Category': + case 'Company': + case 'LastAuthor': + case 'LastSaved': + case 'LastPrinted': + case 'Version': + case 'Revision': + case 'TotalTime': + case 'HyperlinkBase': + case 'Manager': + case 'ContentStatus': + case 'Identifier': + case 'Language': + case 'AppName': + if(Rn[0].slice(-2) === "/>") break; + else if(Rn[1]==="/") xlml_set_prop(Props, Rn[3], str.slice(pidx, Rn.index)); + else pidx = Rn.index + Rn[0].length; + break; + case 'Paragraphs': break; + + case 'Styles': + case 'Workbook': + if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));} + else state.push([Rn[3], false]); + break; + + case 'Comment': + if(Rn[1]==='/'){ + if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|")); + xlml_clean_comment(comment); + comments.push(comment); + } else { + state.push([Rn[3], false]); + tmp = xlml_parsexmltag(Rn[0]); + comment = ({a:tmp.Author}); + } + break; + + case 'AutoFilter': + if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));} + else if(Rn[0].charAt(Rn[0].length-2) !== '/') { + var AutoFilter = xlml_parsexmltag(Rn[0]); + cursheet['!autofilter'] = { ref:rc_to_a1(AutoFilter.Range).replace(/\$/g,"") }; + state.push([Rn[3], true]); + } + break; + + case 'Name': break; + + case 'ComponentOptions': + case 'DocumentProperties': + case 'CustomDocumentProperties': + case 'OfficeDocumentSettings': + case 'PivotTable': + case 'PivotCache': + case 'Names': + case 'MapInfo': + case 'PageBreaks': + case 'QueryTable': + case 'DataValidation': + case 'Sorting': + case 'Schema': + case 'data': + case 'ConditionalFormatting': + case 'SmartTagType': + case 'SmartTags': + case 'ExcelWorkbook': + case 'WorkbookOptions': + case 'WorksheetOptions': + if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw new Error("Bad state: "+tmp.join("|"));} + else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]); + break; + + default: + /* FODS file root is */ + if(state.length == 0 && Rn[3] == "document") return parse_fods(str, opts); + /* UOS file root is */ + if(state.length == 0 && Rn[3] == "UOF") return parse_fods(str, opts); + + var seen = true; + switch(state[state.length-1][0]) { + /* OfficeDocumentSettings */ + case 'OfficeDocumentSettings': switch(Rn[3]) { + case 'AllowPNG': break; + case 'RemovePersonalInformation': break; + case 'DownloadComponents': break; + case 'LocationOfComponents': break; + case 'Colors': break; + case 'Color': break; + case 'Index': break; + case 'RGB': break; + case 'PixelsPerInch': break; // TODO: set PPI + case 'TargetScreenSize': break; + case 'ReadOnlyRecommended': break; + default: seen = false; + } break; + + /* ComponentOptions */ + case 'ComponentOptions': switch(Rn[3]) { + case 'Toolbar': break; + case 'HideOfficeLogo': break; + case 'SpreadsheetAutoFit': break; + case 'Label': break; + case 'Caption': break; + case 'MaxHeight': break; + case 'MaxWidth': break; + case 'NextSheetNumber': break; + default: seen = false; + } break; + + /* ExcelWorkbook */ + case 'ExcelWorkbook': switch(Rn[3]) { + case 'Date1904': + Workbook.WBProps.date1904 = true; + break; + case 'WindowHeight': break; + case 'WindowWidth': break; + case 'WindowTopX': break; + case 'WindowTopY': break; + case 'TabRatio': break; + case 'ProtectStructure': break; + case 'ProtectWindows': break; + case 'ActiveSheet': break; + case 'DisplayInkNotes': break; + case 'FirstVisibleSheet': break; + case 'SupBook': break; + case 'SheetName': break; + case 'SheetIndex': break; + case 'SheetIndexFirst': break; + case 'SheetIndexLast': break; + case 'Dll': break; + case 'AcceptLabelsInFormulas': break; + case 'DoNotSaveLinkValues': break; + case 'Iteration': break; + case 'MaxIterations': break; + case 'MaxChange': break; + case 'Path': break; + case 'Xct': break; + case 'Count': break; + case 'SelectedSheets': break; + case 'Calculation': break; + case 'Uncalced': break; + case 'StartupPrompt': break; + case 'Crn': break; + case 'ExternName': break; + case 'Formula': break; + case 'ColFirst': break; + case 'ColLast': break; + case 'WantAdvise': break; + case 'Boolean': break; + case 'Error': break; + case 'Text': break; + case 'OLE': break; + case 'NoAutoRecover': break; + case 'PublishObjects': break; + case 'DoNotCalculateBeforeSave': break; + case 'Number': break; + case 'RefModeR1C1': break; + case 'EmbedSaveSmartTags': break; + default: seen = false; + } break; + + /* WorkbookOptions */ + case 'WorkbookOptions': switch(Rn[3]) { + case 'OWCVersion': break; + case 'Height': break; + case 'Width': break; + default: seen = false; + } break; + + /* WorksheetOptions */ + case 'WorksheetOptions': switch(Rn[3]) { + case 'Visible': + if(Rn[0].slice(-2) === "/>"){/* empty */} + else if(Rn[1]==="/") switch(str.slice(pidx, Rn.index)) { + case "SheetHidden": wsprops.Hidden = 1; break; + case "SheetVeryHidden": wsprops.Hidden = 2; break; + } + else pidx = Rn.index + Rn[0].length; + break; + case 'Header': + if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml'); + cursheet['!margins'].header = parsexmltag(Rn[0]).Margin; + break; + case 'Footer': + if(!cursheet['!margins']) default_margins(cursheet['!margins']={}, 'xlml'); + cursheet['!margins'].footer = parsexmltag(Rn[0]).Margin; + break; + case 'PageMargins': + var pagemargins = parsexmltag(Rn[0]); + if(!cursheet['!margins']) default_margins(cursheet['!margins']={},'xlml'); + if(pagemargins.Top) cursheet['!margins'].top = pagemargins.Top; + if(pagemargins.Left) cursheet['!margins'].left = pagemargins.Left; + if(pagemargins.Right) cursheet['!margins'].right = pagemargins.Right; + if(pagemargins.Bottom) cursheet['!margins'].bottom = pagemargins.Bottom; + break; + case 'DisplayRightToLeft': + if(!Workbook.Views) Workbook.Views = []; + if(!Workbook.Views[0]) Workbook.Views[0] = {}; + Workbook.Views[0].RTL = true; + break; + + case 'Unsynced': break; + case 'Print': break; + case 'Panes': break; + case 'Scale': break; + case 'Pane': break; + case 'Number': break; + case 'Layout': break; + case 'PageSetup': break; + case 'Selected': break; + case 'ProtectObjects': break; + case 'EnableSelection': break; + case 'ProtectScenarios': break; + case 'ValidPrinterInfo': break; + case 'HorizontalResolution': break; + case 'VerticalResolution': break; + case 'NumberofCopies': break; + case 'ActiveRow': break; + case 'ActiveCol': break; + case 'ActivePane': break; + case 'TopRowVisible': break; + case 'TopRowBottomPane': break; + case 'LeftColumnVisible': break; + case 'LeftColumnRightPane': break; + case 'FitToPage': break; + case 'RangeSelection': break; + case 'PaperSizeIndex': break; + case 'PageLayoutZoom': break; + case 'PageBreakZoom': break; + case 'FilterOn': break; + case 'DoNotDisplayGridlines': break; + case 'SplitHorizontal': break; + case 'SplitVertical': break; + case 'FreezePanes': break; + case 'FrozenNoSplit': break; + case 'FitWidth': break; + case 'FitHeight': break; + case 'CommentsLayout': break; + case 'Zoom': break; + case 'LeftToRight': break; + case 'Gridlines': break; + case 'AllowSort': break; + case 'AllowFilter': break; + case 'AllowInsertRows': break; + case 'AllowDeleteRows': break; + case 'AllowInsertCols': break; + case 'AllowDeleteCols': break; + case 'AllowInsertHyperlinks': break; + case 'AllowFormatCells': break; + case 'AllowSizeCols': break; + case 'AllowSizeRows': break; + case 'NoSummaryRowsBelowDetail': break; + case 'TabColorIndex': break; + case 'DoNotDisplayHeadings': break; + case 'ShowPageLayoutZoom': break; + case 'NoSummaryColumnsRightDetail': break; + case 'BlackAndWhite': break; + case 'DoNotDisplayZeros': break; + case 'DisplayPageBreak': break; + case 'RowColHeadings': break; + case 'DoNotDisplayOutline': break; + case 'NoOrientation': break; + case 'AllowUsePivotTables': break; + case 'ZeroHeight': break; + case 'ViewableRange': break; + case 'Selection': break; + case 'ProtectContents': break; + default: seen = false; + } break; + + /* PivotTable */ + case 'PivotTable': case 'PivotCache': switch(Rn[3]) { + case 'ImmediateItemsOnDrop': break; + case 'ShowPageMultipleItemLabel': break; + case 'CompactRowIndent': break; + case 'Location': break; + case 'PivotField': break; + case 'Orientation': break; + case 'LayoutForm': break; + case 'LayoutSubtotalLocation': break; + case 'LayoutCompactRow': break; + case 'Position': break; + case 'PivotItem': break; + case 'DataType': break; + case 'DataField': break; + case 'SourceName': break; + case 'ParentField': break; + case 'PTLineItems': break; + case 'PTLineItem': break; + case 'CountOfSameItems': break; + case 'Item': break; + case 'ItemType': break; + case 'PTSource': break; + case 'CacheIndex': break; + case 'ConsolidationReference': break; + case 'FileName': break; + case 'Reference': break; + case 'NoColumnGrand': break; + case 'NoRowGrand': break; + case 'BlankLineAfterItems': break; + case 'Hidden': break; + case 'Subtotal': break; + case 'BaseField': break; + case 'MapChildItems': break; + case 'Function': break; + case 'RefreshOnFileOpen': break; + case 'PrintSetTitles': break; + case 'MergeLabels': break; + case 'DefaultVersion': break; + case 'RefreshName': break; + case 'RefreshDate': break; + case 'RefreshDateCopy': break; + case 'VersionLastRefresh': break; + case 'VersionLastUpdate': break; + case 'VersionUpdateableMin': break; + case 'VersionRefreshableMin': break; + case 'Calculation': break; + default: seen = false; + } break; + + /* PageBreaks */ + case 'PageBreaks': switch(Rn[3]) { + case 'ColBreaks': break; + case 'ColBreak': break; + case 'RowBreaks': break; + case 'RowBreak': break; + case 'ColStart': break; + case 'ColEnd': break; + case 'RowEnd': break; + default: seen = false; + } break; + + /* AutoFilter */ + case 'AutoFilter': switch(Rn[3]) { + case 'AutoFilterColumn': break; + case 'AutoFilterCondition': break; + case 'AutoFilterAnd': break; + case 'AutoFilterOr': break; + default: seen = false; + } break; + + /* QueryTable */ + case 'QueryTable': switch(Rn[3]) { + case 'Id': break; + case 'AutoFormatFont': break; + case 'AutoFormatPattern': break; + case 'QuerySource': break; + case 'QueryType': break; + case 'EnableRedirections': break; + case 'RefreshedInXl9': break; + case 'URLString': break; + case 'HTMLTables': break; + case 'Connection': break; + case 'CommandText': break; + case 'RefreshInfo': break; + case 'NoTitles': break; + case 'NextId': break; + case 'ColumnInfo': break; + case 'OverwriteCells': break; + case 'DoNotPromptForFile': break; + case 'TextWizardSettings': break; + case 'Source': break; + case 'Number': break; + case 'Decimal': break; + case 'ThousandSeparator': break; + case 'TrailingMinusNumbers': break; + case 'FormatSettings': break; + case 'FieldType': break; + case 'Delimiters': break; + case 'Tab': break; + case 'Comma': break; + case 'AutoFormatName': break; + case 'VersionLastEdit': break; + case 'VersionLastRefresh': break; + default: seen = false; + } break; + + case 'Sorting': + case 'ConditionalFormatting': + case 'DataValidation': + switch(Rn[3]) { + case 'Range': break; + case 'Type': break; + case 'Min': break; + case 'Max': break; + case 'Sort': break; + case 'Descending': break; + case 'Order': break; + case 'CaseSensitive': break; + case 'Value': break; + case 'ErrorStyle': break; + case 'ErrorMessage': break; + case 'ErrorTitle': break; + case 'CellRangeList': break; + case 'InputMessage': break; + case 'InputTitle': break; + case 'ComboHide': break; + case 'InputHide': break; + case 'Condition': break; + case 'Qualifier': break; + case 'UseBlank': break; + case 'Value1': break; + case 'Value2': break; + case 'Format': break; + default: seen = false; + } break; + + /* MapInfo (schema) */ + case 'MapInfo': case 'Schema': case 'data': switch(Rn[3]) { + case 'Map': break; + case 'Entry': break; + case 'Range': break; + case 'XPath': break; + case 'Field': break; + case 'XSDType': break; + case 'FilterOn': break; + case 'Aggregate': break; + case 'ElementType': break; + case 'AttributeType': break; + /* These are from xsd (XML Schema Definition) */ + case 'schema': + case 'element': + case 'complexType': + case 'datatype': + case 'all': + case 'attribute': + case 'extends': break; + + case 'row': break; + default: seen = false; + } break; + + /* SmartTags (can be anything) */ + case 'SmartTags': break; + + default: seen = false; break; + } + if(seen) break; + /* CustomDocumentProperties */ + if(!state[state.length-1][1]) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|"); + if(state[state.length-1][0]==='CustomDocumentProperties') { + if(Rn[0].slice(-2) === "/>") break; + else if(Rn[1]==="/") xlml_set_custprop(Custprops, Rn[3], cp, str.slice(pidx, Rn.index)); + else { cp = Rn; pidx = Rn.index + Rn[0].length; } + break; + } + if(opts.WTF) throw 'Unrecognized tag: ' + Rn[3] + "|" + state.join("|"); + } + var out = ({}); + if(!opts.bookSheets && !opts.bookProps) out.Sheets = sheets; + out.SheetNames = sheetnames; + out.Workbook = Workbook; + out.SSF = SSF.get_table(); + out.Props = Props; + out.Custprops = Custprops; + return out; + } + + function parse_xlml(data, opts) { + fix_read_opts(opts=opts||{}); + switch(opts.type||"base64") { + case "base64": return parse_xlml_xml(Base64.decode(data), opts); + case "binary": case "buffer": case "file": return parse_xlml_xml(data, opts); + case "array": return parse_xlml_xml(a2s(data), opts); + } + } + + /* TODO */ + function write_props_xlml(wb, opts) { + var o = []; + /* DocumentProperties */ + if(wb.Props) o.push(xlml_write_docprops(wb.Props, opts)); + /* CustomDocumentProperties */ + if(wb.Custprops) o.push(xlml_write_custprops(wb.Props, wb.Custprops, opts)); + return o.join(""); + } + /* TODO */ + function write_wb_xlml() { + /* OfficeDocumentSettings */ + /* ExcelWorkbook */ + return ""; + } + /* TODO */ + function write_sty_xlml(wb, opts) { + /* Styles */ + var styles = ['']; + opts.cellXfs.forEach(function(xf, id) { + var payload = []; + payload.push(writextag('NumberFormat', null, {"ss:Format": escapexml(SSF._table[xf.numFmtId])})); + styles.push(writextag('Style', payload.join(""), {"ss:ID": "s" + (21+id)})); + }); + return writextag("Styles", styles.join("")); + } + function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); } + function write_names_xlml(wb) { + if(!((wb||{}).Workbook||{}).Names) return ""; + var names = wb.Workbook.Names; + var out = []; + for(var i = 0; i < names.length; ++i) { + var n = names[i]; + if(n.Sheet != null) continue; + if(n.Name.match(/^_xlfn\./)) continue; + out.push(write_name_xlml(n)); + } + return writextag("Names", out.join("")); + } + function write_ws_xlml_names(ws, opts, idx, wb) { + if(!ws) return ""; + if(!((wb||{}).Workbook||{}).Names) return ""; + var names = wb.Workbook.Names; + var out = []; + for(var i = 0; i < names.length; ++i) { + var n = names[i]; + if(n.Sheet != idx) continue; + /*switch(n.Name) { + case "_": continue; + }*/ + if(n.Name.match(/^_xlfn\./)) continue; + out.push(write_name_xlml(n)); + } + return out.join(""); + } + /* WorksheetOptions */ + function write_ws_xlml_wsopts(ws, opts, idx, wb) { + if(!ws) return ""; + var o = []; + /* NOTE: spec technically allows any order, but stick with implied order */ + + /* FitToPage */ + /* DoNotDisplayColHeaders */ + /* DoNotDisplayRowHeaders */ + /* ViewableRange */ + /* Selection */ + /* GridlineColor */ + /* Name */ + /* ExcelWorksheetType */ + /* IntlMacro */ + /* Unsynced */ + /* Selected */ + /* CodeName */ + + if(ws['!margins']) { + o.push(""); + if(ws['!margins'].header) o.push(writextag("Header", null, {'x:Margin':ws['!margins'].header})); + if(ws['!margins'].footer) o.push(writextag("Footer", null, {'x:Margin':ws['!margins'].footer})); + o.push(writextag("PageMargins", null, { + 'x:Bottom': ws['!margins'].bottom || "0.75", + 'x:Left': ws['!margins'].left || "0.7", + 'x:Right': ws['!margins'].right || "0.7", + 'x:Top': ws['!margins'].top || "0.75" + })); + o.push(""); + } + + /* PageSetup */ + /* DisplayPageBreak */ + /* TransitionExpressionEvaluation */ + /* TransitionFormulaEntry */ + /* Print */ + /* Zoom */ + /* PageLayoutZoom */ + /* PageBreakZoom */ + /* ShowPageBreakZoom */ + /* DefaultRowHeight */ + /* DefaultColumnWidth */ + /* StandardWidth */ + + if(wb && wb.Workbook && wb.Workbook.Sheets && wb.Workbook.Sheets[idx]) { + /* Visible */ + if(wb.Workbook.Sheets[idx].Hidden) o.push(writextag("Visible", (wb.Workbook.Sheets[idx].Hidden == 1 ? "SheetHidden" : "SheetVeryHidden"), {})); + else { + /* Selected */ + for(var i = 0; i < idx; ++i) if(wb.Workbook.Sheets[i] && !wb.Workbook.Sheets[i].Hidden) break; + if(i == idx) o.push(""); + } + } + + /* LeftColumnVisible */ + + if(((((wb||{}).Workbook||{}).Views||[])[0]||{}).RTL) o.push(""); + + /* GridlineColorIndex */ + /* DisplayFormulas */ + /* DoNotDisplayGridlines */ + /* DoNotDisplayHeadings */ + /* DoNotDisplayOutline */ + /* ApplyAutomaticOutlineStyles */ + /* NoSummaryRowsBelowDetail */ + /* NoSummaryColumnsRightDetail */ + /* DoNotDisplayZeros */ + /* ActiveRow */ + /* ActiveColumn */ + /* FilterOn */ + /* RangeSelection */ + /* TopRowVisible */ + /* TopRowBottomPane */ + /* LeftColumnRightPane */ + /* ActivePane */ + /* SplitHorizontal */ + /* SplitVertical */ + /* FreezePanes */ + /* FrozenNoSplit */ + /* TabColorIndex */ + /* Panes */ + + /* NOTE: Password not supported in XLML Format */ + if(ws['!protect']) { + o.push(writetag("ProtectContents", "True")); + if(ws['!protect'].objects) o.push(writetag("ProtectObjects", "True")); + if(ws['!protect'].scenarios) o.push(writetag("ProtectScenarios", "True")); + if(ws['!protect'].selectLockedCells != null && !ws['!protect'].selectLockedCells) o.push(writetag("EnableSelection", "NoSelection")); + else if(ws['!protect'].selectUnlockedCells != null && !ws['!protect'].selectUnlockedCells) o.push(writetag("EnableSelection", "UnlockedCells")); + [ + [ "formatCells", "AllowFormatCells" ], + [ "formatColumns", "AllowSizeCols" ], + [ "formatRows", "AllowSizeRows" ], + [ "insertColumns", "AllowInsertCols" ], + [ "insertRows", "AllowInsertRows" ], + [ "insertHyperlinks", "AllowInsertHyperlinks" ], + [ "deleteColumns", "AllowDeleteCols" ], + [ "deleteRows", "AllowDeleteRows" ], + [ "sort", "AllowSort" ], + [ "autoFilter", "AllowFilter" ], + [ "pivotTables", "AllowUsePivotTables" ] + ].forEach(function(x) { if(ws['!protect'][x[0]]) o.push("<"+x[1]+"/>"); }); + } + + if(o.length == 0) return ""; + return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x}); + } + function write_ws_xlml_comment(comments) { + return comments.map(function(c) { + // TODO: formatted text + var t = xlml_unfixstr(c.t||""); + var d =writextag("ss:Data", t, {"xmlns":"http://www.w3.org/TR/REC-html40"}); + return writextag("Comment", d, {"ss:Author":c.a}); + }).join(""); + } + function write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr){ + if(!cell || (cell.v == undefined && cell.f == undefined)) return ""; + + var attr = {}; + if(cell.f) attr["ss:Formula"] = "=" + escapexml(a1_to_rc(cell.f, addr)); + if(cell.F && cell.F.slice(0, ref.length) == ref) { + var end = decode_cell(cell.F.slice(ref.length + 1)); + attr["ss:ArrayRange"] = "RC:R" + (end.r == addr.r ? "" : "[" + (end.r - addr.r) + "]") + "C" + (end.c == addr.c ? "" : "[" + (end.c - addr.c) + "]"); + } + + if(cell.l && cell.l.Target) { + attr["ss:HRef"] = escapexml(cell.l.Target); + if(cell.l.Tooltip) attr["x:HRefScreenTip"] = escapexml(cell.l.Tooltip); + } + + if(ws['!merges']) { + var marr = ws['!merges']; + for(var mi = 0; mi != marr.length; ++mi) { + if(marr[mi].s.c != addr.c || marr[mi].s.r != addr.r) continue; + if(marr[mi].e.c > marr[mi].s.c) attr['ss:MergeAcross'] = marr[mi].e.c - marr[mi].s.c; + if(marr[mi].e.r > marr[mi].s.r) attr['ss:MergeDown'] = marr[mi].e.r - marr[mi].s.r; + } + } + + var t = "", p = ""; + switch(cell.t) { + case 'z': return ""; + case 'n': t = 'Number'; p = String(cell.v); break; + case 'b': t = 'Boolean'; p = (cell.v ? "1" : "0"); break; + case 'e': t = 'Error'; p = BErr[cell.v]; break; + case 'd': t = 'DateTime'; p = new Date(cell.v).toISOString(); if(cell.z == null) cell.z = cell.z || SSF._table[14]; break; + case 's': t = 'String'; p = escapexlml(cell.v||""); break; + } + /* TODO: cell style */ + var os = get_cell_style(opts.cellXfs, cell, opts); + attr["ss:StyleID"] = "s" + (21+os); + attr["ss:Index"] = addr.c + 1; + var _v = (cell.v != null ? p : ""); + var m = '' + _v + ''; + + if((cell.c||[]).length > 0) m += write_ws_xlml_comment(cell.c); + + return writextag("Cell", m, attr); + } + function write_ws_xlml_row(R, row) { + var o = ''; + } + /* TODO */ + function write_ws_xlml_table(ws, opts, idx, wb) { + if(!ws['!ref']) return ""; + var range = safe_decode_range(ws['!ref']); + var marr = ws['!merges'] || [], mi = 0; + var o = []; + if(ws['!cols']) ws['!cols'].forEach(function(n, i) { + process_col(n); + var w = !!n.width; + var p = col_obj_w(i, n); + var k = {"ss:Index":i+1}; + if(w) k['ss:Width'] = width2px(p.width); + if(n.hidden) k['ss:Hidden']="1"; + o.push(writextag("Column",null,k)); + }); + var dense = Array.isArray(ws); + for(var R = range.s.r; R <= range.e.r; ++R) { + var row = [write_ws_xlml_row(R, (ws['!rows']||[])[R])]; + for(var C = range.s.c; C <= range.e.c; ++C) { + var skip = false; + for(mi = 0; mi != marr.length; ++mi) { + if(marr[mi].s.c > C) continue; + if(marr[mi].s.r > R) continue; + if(marr[mi].e.c < C) continue; + if(marr[mi].e.r < R) continue; + if(marr[mi].s.c != C || marr[mi].s.r != R) skip = true; + break; + } + if(skip) continue; + var addr = {r:R,c:C}; + var ref = encode_cell(addr), cell = dense ? (ws[R]||[])[C] : ws[ref]; + row.push(write_ws_xlml_cell(cell, ref, ws, opts, idx, wb, addr)); + } + row.push(""); + if(row.length > 2) o.push(row.join("")); + } + return o.join(""); + } + function write_ws_xlml(idx, opts, wb) { + var o = []; + var s = wb.SheetNames[idx]; + var ws = wb.Sheets[s]; + + var t = ws ? write_ws_xlml_names(ws, opts, idx, wb) : ""; + if(t.length > 0) o.push("" + t + ""); + + /* Table */ + t = ws ? write_ws_xlml_table(ws, opts, idx, wb) : ""; + if(t.length > 0) o.push("" + t + "
                "); + + /* WorksheetOptions */ + o.push(write_ws_xlml_wsopts(ws, opts, idx, wb)); + + return o.join(""); + } + function write_xlml(wb, opts) { + if(!opts) opts = {}; + if(!wb.SSF) wb.SSF = SSF.get_table(); + if(wb.SSF) { + make_ssf(SSF); SSF.load_table(wb.SSF); + // $FlowIgnore + opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0; + opts.ssf = wb.SSF; + opts.cellXfs = []; + get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}}); + } + var d = []; + d.push(write_props_xlml(wb, opts)); + d.push(write_wb_xlml(wb, opts)); + d.push(""); + d.push(""); + for(var i = 0; i < wb.SheetNames.length; ++i) + d.push(writextag("Worksheet", write_ws_xlml(i, opts, wb), {"ss:Name":escapexml(wb.SheetNames[i])})); + d[2] = write_sty_xlml(wb, opts); + d[3] = write_names_xlml(wb, opts); + return XML_HEADER + writextag("Workbook", d.join(""), { + 'xmlns': XLMLNS.ss, + 'xmlns:o': XLMLNS.o, + 'xmlns:x': XLMLNS.x, + 'xmlns:ss': XLMLNS.ss, + 'xmlns:dt': XLMLNS.dt, + 'xmlns:html': XLMLNS.html + }); + } + /* [MS-OLEDS] 2.3.8 CompObjStream */ + function parse_compobj(obj) { + var v = {}; + var o = obj.content; + /* [MS-OLEDS] 2.3.7 CompObjHeader -- All fields MUST be ignored */ + o.l = 28; + + v.AnsiUserType = o.read_shift(0, "lpstr-ansi"); + v.AnsiClipboardFormat = parse_ClipboardFormatOrAnsiString(o); + + if(o.length - o.l <= 4) return v; + + var m = o.read_shift(4); + if(m == 0 || m > 40) return v; + o.l-=4; v.Reserved1 = o.read_shift(0, "lpstr-ansi"); + + if(o.length - o.l <= 4) return v; + m = o.read_shift(4); + if(m !== 0x71b239f4) return v; + v.UnicodeClipboardFormat = parse_ClipboardFormatOrUnicodeString(o); + + m = o.read_shift(4); + if(m == 0 || m > 40) return v; + o.l-=4; v.Reserved2 = o.read_shift(0, "lpwstr"); + } + + /* + Continue logic for: + - 2.4.58 Continue + - 2.4.59 ContinueBigName + - 2.4.60 ContinueFrt + - 2.4.61 ContinueFrt11 + - 2.4.62 ContinueFrt12 +*/ + function slurp(R, blob, length, opts) { + var l = length; + var bufs = []; + var d = blob.slice(blob.l,blob.l+l); + if(opts && opts.enc && opts.enc.insitu) switch(R.n) { + case 'BOF': case 'FilePass': case 'FileLock': case 'InterfaceHdr': case 'RRDInfo': case 'RRDHead': case 'UsrExcl': break; + default: + if(d.length === 0) break; + opts.enc.insitu(d); + } + bufs.push(d); + blob.l += l; + var next = (XLSRecordEnum[__readUInt16LE(blob,blob.l)]); + var start = 0; + while(next != null && next.n.slice(0,8) === 'Continue') { + l = __readUInt16LE(blob,blob.l+2); + start = blob.l + 4; + if(next.n == 'ContinueFrt') start += 4; + else if(next.n.slice(0,11) == 'ContinueFrt') start += 12; + bufs.push(blob.slice(start,blob.l+4+l)); + blob.l += 4+l; + next = (XLSRecordEnum[__readUInt16LE(blob, blob.l)]); + } + var b = (bconcat(bufs)); + prep_blob(b, 0); + var ll = 0; b.lens = []; + for(var j = 0; j < bufs.length; ++j) { b.lens.push(ll); ll += bufs[j].length; } + return R.f(b, b.length, opts); + } + + function safe_format_xf(p, opts, date1904) { + if(p.t === 'z') return; + if(!p.XF) return; + var fmtid = 0; + try { + fmtid = p.z || p.XF.numFmtId || 0; + if(opts.cellNF) p.z = SSF._table[fmtid]; + } catch(e) { if(opts.WTF) throw e; } + if(!opts || opts.cellText !== false) try { + if(p.t === 'e') { p.w = p.w || BErr[p.v]; } + else if(fmtid === 0 || fmtid == "General") { + if(p.t === 'n') { + if((p.v|0) === p.v) p.w = SSF._general_int(p.v); + else p.w = SSF._general_num(p.v); + } + else p.w = SSF._general(p.v); + } + else p.w = SSF.format(fmtid,p.v, {date1904:!!date1904}); + } catch(e) { if(opts.WTF) throw e; } + if(opts.cellDates && fmtid && p.t == 'n' && SSF.is_date(SSF._table[fmtid] || String(fmtid))) { + var _d = SSF.parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); } + } + } + + function make_cell(val, ixfe, t) { + return ({v:val, ixfe:ixfe, t:t}); + } + +// 2.3.2 + function parse_workbook(blob, options) { + var wb = ({opts:{}}); + var Sheets = {}; + if(DENSE != null && options.dense == null) options.dense = DENSE; + var out = ((options.dense ? [] : {})); + var Directory = {}; + var range = ({}); + var last_formula = null; + var sst = ([]); + var cur_sheet = ""; + var Preamble = {}; + var lastcell, last_cell = "", cc, cmnt, rngC, rngR; + var sharedf = {}; + var arrayf = []; + var temp_val; + var country; + var cell_valid = true; + var XFs = []; /* XF records */ + var palette = []; + var Workbook = ({ Sheets:[], WBProps:{date1904:false}, Views:[{}] }), wsprops = {}; + var get_rgb = function getrgb(icv) { + if(icv < 8) return XLSIcv[icv]; + if(icv < 64) return palette[icv-8] || XLSIcv[icv]; + return XLSIcv[icv]; + }; + var process_cell_style = function pcs(cell, line, options) { + var xfd = line.XF.data; + if(!xfd || !xfd.patternType || !options || !options.cellStyles) return; + line.s = ({}); + line.s.patternType = xfd.patternType; + var t; + if((t = rgb2Hex(get_rgb(xfd.icvFore)))) { line.s.fgColor = {rgb:t}; } + if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; } + }; + var addcell = function addcell(cell, line, options) { + if(file_depth > 1) return; + if(options.sheetRows && cell.r >= options.sheetRows) cell_valid = false; + if(!cell_valid) return; + if(options.cellStyles && line.XF && line.XF.data) process_cell_style(cell, line, options); + delete line.ixfe; delete line.XF; + lastcell = cell; + last_cell = encode_cell(cell); + if(!range || !range.s || !range.e) range = {s:{r:0,c:0},e:{r:0,c:0}}; + if(cell.r < range.s.r) range.s.r = cell.r; + if(cell.c < range.s.c) range.s.c = cell.c; + if(cell.r + 1 > range.e.r) range.e.r = cell.r + 1; + if(cell.c + 1 > range.e.c) range.e.c = cell.c + 1; + if(options.cellFormula && line.f) { + for(var afi = 0; afi < arrayf.length; ++afi) { + if(arrayf[afi][0].s.c > cell.c || arrayf[afi][0].s.r > cell.r) continue; + if(arrayf[afi][0].e.c < cell.c || arrayf[afi][0].e.r < cell.r) continue; + line.F = encode_range(arrayf[afi][0]); + if(arrayf[afi][0].s.c != cell.c || arrayf[afi][0].s.r != cell.r) delete line.f; + if(line.f) line.f = "" + stringify_formula(arrayf[afi][1], range, cell, supbooks, opts); + break; + } + } + { + if(options.dense) { + if(!out[cell.r]) out[cell.r] = []; + out[cell.r][cell.c] = line; + } else out[last_cell] = line; + } + }; + var opts = ({ + enc: false, // encrypted + sbcch: 0, // cch in the preceding SupBook + snames: [], // sheetnames + sharedf: sharedf, // shared formulae by address + arrayf: arrayf, // array formulae array + rrtabid: [], // RRTabId + lastuser: "", // Last User from WriteAccess + biff: 8, // BIFF version + codepage: 0, // CP from CodePage record + winlocked: 0, // fLockWn from WinProtect + cellStyles: !!options && !!options.cellStyles, + WTF: !!options && !!options.wtf + }); + if(options.password) opts.password = options.password; + var themes; + var merges = []; + var objects = []; + var colinfo = [], rowinfo = []; + // eslint-disable-next-line no-unused-vars + var defwidth = 0, defheight = 0; // twips / MDW respectively + var seencol = false; + var supbooks = ([]); // 1-indexed, will hold extern names + supbooks.SheetNames = opts.snames; + supbooks.sharedf = opts.sharedf; + supbooks.arrayf = opts.arrayf; + supbooks.names = []; + supbooks.XTI = []; + var last_Rn = ''; + var file_depth = 0; /* TODO: make a real stack */ + var BIFF2Fmt = 0, BIFF2FmtTable = []; + var FilterDatabases = []; /* TODO: sort out supbooks and process elsewhere */ + var last_lbl; + + /* explicit override for some broken writers */ + opts.codepage = 1200; + set_cp(1200); + var seen_codepage = false; + while(blob.l < blob.length - 1) { + var s = blob.l; + var RecordType = blob.read_shift(2); + if(RecordType === 0 && last_Rn === 'EOF') break; + var length = (blob.l === blob.length ? 0 : blob.read_shift(2)); + var R = XLSRecordEnum[RecordType]; + //console.log(RecordType.toString(16), RecordType, R, blob.l, length, blob.length); + //if(!R) console.log(blob.slice(blob.l, blob.l + length)); + if(R && R.f) { + if(options.bookSheets) { + if(last_Rn === 'BoundSheet8' && R.n !== 'BoundSheet8') break; + } + last_Rn = R.n; + if(R.r === 2 || R.r == 12) { + var rt = blob.read_shift(2); length -= 2; + if(!opts.enc && rt !== RecordType && (((rt&0xFF)<<8)|(rt>>8)) !== RecordType) throw new Error("rt mismatch: " + rt + "!=" + RecordType); + if(R.r == 12){ blob.l += 10; length -= 10; } // skip FRT + } + //console.error(R,blob.l,length,blob.length); + var val; + if(R.n === 'EOF') val = R.f(blob, length, opts); + else val = slurp(R, blob, length, opts); + var Rn = R.n; + if(file_depth == 0 && Rn != 'BOF') continue; + /* nested switch statements to workaround V8 128 limit */ + switch(Rn) { + /* Workbook Options */ + case 'Date1904': + wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break; + case 'WriteProtect': wb.opts.WriteProtect = true; break; + case 'FilePass': + if(!opts.enc) blob.l = 0; + opts.enc = val; + if(!options.password) throw new Error("File is password-protected"); + if(val.valid == null) throw new Error("Encryption scheme unsupported"); + if(!val.valid) throw new Error("Password is incorrect"); + break; + case 'WriteAccess': opts.lastuser = val; break; + case 'FileSharing': break; //TODO + case 'CodePage': + /* overrides based on test cases */ + switch(val) { + case 0x5212: val = 1200; break; + case 0x8000: val = 10000; break; + case 0x8001: val = 1252; break; + } + set_cp(opts.codepage = val); + seen_codepage = true; + break; + case 'RRTabId': opts.rrtabid = val; break; + case 'WinProtect': opts.winlocked = val; break; + case 'Template': break; // TODO + case 'BookBool': break; // TODO + case 'UsesELFs': break; + case 'MTRSettings': break; + case 'RefreshAll': + case 'CalcCount': + case 'CalcDelta': + case 'CalcIter': + case 'CalcMode': + case 'CalcPrecision': + case 'CalcSaveRecalc': + wb.opts[Rn] = val; break; + case 'CalcRefMode': opts.CalcRefMode = val; break; // TODO: implement R1C1 + case 'Uncalced': break; + case 'ForceFullCalculation': wb.opts.FullCalc = val; break; + case 'WsBool': + if(val.fDialog) out["!type"] = "dialog"; + break; // TODO + case 'XF': + XFs.push(val); break; + case 'ExtSST': break; // TODO + case 'BookExt': break; // TODO + case 'RichTextStream': break; + case 'BkHim': break; + + case 'SupBook': + supbooks.push([val]); + supbooks[supbooks.length-1].XTI = []; + break; + case 'ExternName': + supbooks[supbooks.length-1].push(val); + break; + case 'Index': break; // TODO + case 'Lbl': + last_lbl = ({ + Name: val.Name, + Ref: stringify_formula(val.rgce,range,null,supbooks,opts) + }); + if(val.itab > 0) last_lbl.Sheet = val.itab - 1; + supbooks.names.push(last_lbl); + if(!supbooks[0]) { supbooks[0] = []; supbooks[0].XTI = []; } + supbooks[supbooks.length-1].push(val); + if(val.Name == "_xlnm._FilterDatabase" && val.itab > 0) + if(val.rgce && val.rgce[0] && val.rgce[0][0] && val.rgce[0][0][0] == 'PtgArea3d') + FilterDatabases[val.itab - 1] = { ref: encode_range(val.rgce[0][0][1][2]) }; + break; + case 'ExternCount': opts.ExternCount = val; break; + case 'ExternSheet': + if(supbooks.length == 0) { supbooks[0] = []; supbooks[0].XTI = []; } + supbooks[supbooks.length - 1].XTI = supbooks[supbooks.length - 1].XTI.concat(val); supbooks.XTI = supbooks.XTI.concat(val); break; + case 'NameCmt': + /* TODO: search for correct name */ + if(opts.biff < 8) break; + if(last_lbl != null) last_lbl.Comment = val[1]; + break; + + case 'Protect': out["!protect"] = val; break; /* for sheet or book */ + case 'Password': if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break; + case 'Prot4Rev': case 'Prot4RevPass': break; /*TODO: Revision Control*/ + + case 'BoundSheet8': { + Directory[val.pos] = val; + opts.snames.push(val.name); + } break; + case 'EOF': { + if(--file_depth) break; + if(range.e) { + if(range.e.r > 0 && range.e.c > 0) { + range.e.r--; range.e.c--; + out["!ref"] = encode_range(range); + if(options.sheetRows && options.sheetRows <= range.e.r) { + var tmpri = range.e.r; + range.e.r = options.sheetRows - 1; + out["!fullref"] = out["!ref"]; + out["!ref"] = encode_range(range); + range.e.r = tmpri; + } + range.e.r++; range.e.c++; + } + if(merges.length > 0) out["!merges"] = merges; + if(objects.length > 0) out["!objects"] = objects; + if(colinfo.length > 0) out["!cols"] = colinfo; + if(rowinfo.length > 0) out["!rows"] = rowinfo; + Workbook.Sheets.push(wsprops); + } + if(cur_sheet === "") Preamble = out; else Sheets[cur_sheet] = out; + out = ((options.dense ? [] : {})); + } break; + case 'BOF': { + if(opts.biff === 8) opts.biff = { + 0x0009:2, + 0x0209:3, + 0x0409:4 + }[RecordType] || { + 0x0200:2, + 0x0300:3, + 0x0400:4, + 0x0500:5, + 0x0600:8, + 0x0002:2, + 0x0007:2 + }[val.BIFFVer] || 8; + if(opts.biff == 8 && val.BIFFVer == 0 && val.dt == 16) opts.biff = 2; + if(file_depth++) break; + cell_valid = true; + out = ((options.dense ? [] : {})); + + if(opts.biff < 8 && !seen_codepage) { seen_codepage = true; set_cp(opts.codepage = options.codepage || 1252); } + if(opts.biff < 5) { + if(cur_sheet === "") cur_sheet = "Sheet1"; + range = {s:{r:0,c:0},e:{r:0,c:0}}; + /* fake BoundSheet8 */ + var fakebs8 = {pos: blob.l - length, name:cur_sheet}; + Directory[fakebs8.pos] = fakebs8; + opts.snames.push(cur_sheet); + } + else cur_sheet = (Directory[s] || {name:""}).name; + if(val.dt == 0x20) out["!type"] = "chart"; + if(val.dt == 0x40) out["!type"] = "macro"; + merges = []; + objects = []; + opts.arrayf = arrayf = []; + colinfo = []; rowinfo = []; + defwidth = defheight = 0; + seencol = false; + wsprops = {Hidden:(Directory[s]||{hs:0}).hs, name:cur_sheet }; + } break; + + case 'Number': case 'BIFF2NUM': case 'BIFF2INT': { + if(out["!type"] == "chart") if(options.dense ? (out[val.r]||[])[val.c]: out[encode_cell({c:val.c, r:val.r})]) ++val.c; + temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe]||{}, v:val.val, t:'n'}); + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; + safe_format_xf(temp_val, options, wb.opts.Date1904); + addcell({c:val.c, r:val.r}, temp_val, options); + } break; + case 'BoolErr': { + temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t}); + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; + safe_format_xf(temp_val, options, wb.opts.Date1904); + addcell({c:val.c, r:val.r}, temp_val, options); + } break; + case 'RK': { + temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'}); + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; + safe_format_xf(temp_val, options, wb.opts.Date1904); + addcell({c:val.c, r:val.r}, temp_val, options); + } break; + case 'MulRk': { + for(var j = val.c; j <= val.C; ++j) { + var ixfe = val.rkrec[j-val.c][0]; + temp_val= ({ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'}); + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; + safe_format_xf(temp_val, options, wb.opts.Date1904); + addcell({c:j, r:val.r}, temp_val, options); + } + } break; + case 'Formula': { + if(val.val == 'String') { last_formula = val; break; } + temp_val = make_cell(val.val, val.cell.ixfe, val.tt); + temp_val.XF = XFs[temp_val.ixfe]; + if(options.cellFormula) { + var _f = val.formula; + if(_f && _f[0] && _f[0][0] && _f[0][0][0] == 'PtgExp') { + var _fr = _f[0][0][1][0], _fc = _f[0][0][1][1]; + var _fe = encode_cell({r:_fr, c:_fc}); + if(sharedf[_fe]) temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); + else temp_val.F = ((options.dense ? (out[_fr]||[])[_fc]: out[_fe]) || {}).F; + } else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts); + } + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; + safe_format_xf(temp_val, options, wb.opts.Date1904); + addcell(val.cell, temp_val, options); + last_formula = val; + } break; + case 'String': { + if(last_formula) { /* technically always true */ + last_formula.val = val; + temp_val = make_cell(val, last_formula.cell.ixfe, 's'); + temp_val.XF = XFs[temp_val.ixfe]; + if(options.cellFormula) { + temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts); + } + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; + safe_format_xf(temp_val, options, wb.opts.Date1904); + addcell(last_formula.cell, temp_val, options); + last_formula = null; + } else throw new Error("String record expects Formula"); + } break; + case 'Array': { + arrayf.push(val); + var _arraystart = encode_cell(val[0].s); + cc = options.dense ? (out[val[0].s.r]||[])[val[0].s.c] : out[_arraystart]; + if(options.cellFormula && cc) { + if(!last_formula) break; /* technically unreachable */ + if(!_arraystart || !cc) break; + cc.f = ""+stringify_formula(val[1], range, val[0], supbooks, opts); + cc.F = encode_range(val[0]); + } + } break; + case 'ShrFmla': { + if(!cell_valid) break; + if(!options.cellFormula) break; + if(last_cell) { + /* TODO: capture range */ + if(!last_formula) break; /* technically unreachable */ + sharedf[encode_cell(last_formula.cell)]= val[0]; + cc = options.dense ? (out[last_formula.cell.r]||[])[last_formula.cell.c] : out[encode_cell(last_formula.cell)]; + (cc||{}).f = ""+stringify_formula(val[0], range, lastcell, supbooks, opts); + } + } break; + case 'LabelSst': + temp_val=make_cell(sst[val.isst].t, val.ixfe, 's'); + temp_val.XF = XFs[temp_val.ixfe]; + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; + safe_format_xf(temp_val, options, wb.opts.Date1904); + addcell({c:val.c, r:val.r}, temp_val, options); + break; + case 'Blank': if(options.sheetStubs) { + temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'}); + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; + safe_format_xf(temp_val, options, wb.opts.Date1904); + addcell({c:val.c, r:val.r}, temp_val, options); + } break; + case 'MulBlank': if(options.sheetStubs) { + for(var _j = val.c; _j <= val.C; ++_j) { + var _ixfe = val.ixfe[_j-val.c]; + temp_val= ({ixfe:_ixfe, XF:XFs[_ixfe], t:'z'}); + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; + safe_format_xf(temp_val, options, wb.opts.Date1904); + addcell({c:_j, r:val.r}, temp_val, options); + } + } break; + case 'RString': + case 'Label': case 'BIFF2STR': + temp_val=make_cell(val.val, val.ixfe, 's'); + temp_val.XF = XFs[temp_val.ixfe]; + if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x1F]; + safe_format_xf(temp_val, options, wb.opts.Date1904); + addcell({c:val.c, r:val.r}, temp_val, options); + break; + + case 'Dimensions': { + if(file_depth === 1) range = val; /* TODO: stack */ + } break; + case 'SST': { + sst = val; + } break; + case 'Format': { /* val = [id, fmt] */ + if(opts.biff == 4) { + BIFF2FmtTable[BIFF2Fmt++] = val[1]; + for(var b4idx = 0; b4idx < BIFF2Fmt + 163; ++b4idx) if(SSF._table[b4idx] == val[1]) break; + if(b4idx >= 163) SSF.load(val[1], BIFF2Fmt + 163); + } + else SSF.load(val[1], val[0]); + } break; + case 'BIFF2FORMAT': { + BIFF2FmtTable[BIFF2Fmt++] = val; + for(var b2idx = 0; b2idx < BIFF2Fmt + 163; ++b2idx) if(SSF._table[b2idx] == val) break; + if(b2idx >= 163) SSF.load(val, BIFF2Fmt + 163); + } break; + + case 'MergeCells': merges = merges.concat(val); break; + + case 'Obj': objects[val.cmo[0]] = opts.lastobj = val; break; + case 'TxO': opts.lastobj.TxO = val; break; + case 'ImData': opts.lastobj.ImData = val; break; + + case 'HLink': { + for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR) + for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) { + cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})]; + if(cc) cc.l = val[1]; + } + } break; + case 'HLinkTooltip': { + for(rngR = val[0].s.r; rngR <= val[0].e.r; ++rngR) + for(rngC = val[0].s.c; rngC <= val[0].e.c; ++rngC) { + cc = options.dense ? (out[rngR]||[])[rngC] : out[encode_cell({c:rngC,r:rngR})]; + if(cc && cc.l) cc.l.Tooltip = val[1]; + } + } break; + + /* Comments */ + case 'Note': { + if(opts.biff <= 5 && opts.biff >= 2) break; /* TODO: BIFF5 */ + cc = options.dense ? (out[val[0].r]||[])[val[0].c] : out[encode_cell(val[0])]; + var noteobj = objects[val[2]]; + if(!cc) break; + if(!cc.c) cc.c = []; + cmnt = {a:val[1],t:noteobj.TxO.t}; + cc.c.push(cmnt); + } break; + + default: switch(R.n) { /* nested */ + case 'ClrtClient': break; + case 'XFExt': update_xfext(XFs[val.ixfe], val.ext); break; + + case 'DefColWidth': defwidth = val; break; + case 'DefaultRowHeight': defheight = val[1]; break; // TODO: flags + + case 'ColInfo': { + if(!opts.cellStyles) break; + while(val.e >= val.s) { + colinfo[val.e--] = { width: val.w/256 }; + if(!seencol) { seencol = true; find_mdw_colw(val.w/256); } + process_col(colinfo[val.e+1]); + } + } break; + case 'Row': { + var rowobj = {}; + if(val.level != null) { rowinfo[val.r] = rowobj; rowobj.level = val.level; } + if(val.hidden) { rowinfo[val.r] = rowobj; rowobj.hidden = true; } + if(val.hpt) { + rowinfo[val.r] = rowobj; + rowobj.hpt = val.hpt; rowobj.hpx = pt2px(val.hpt); + } + } break; + + case 'LeftMargin': + case 'RightMargin': + case 'TopMargin': + case 'BottomMargin': + if(!out['!margins']) default_margins(out['!margins'] = {}); + out['!margins'][Rn.slice(0,-6).toLowerCase()] = val; + break; + + case 'Setup': // TODO + if(!out['!margins']) default_margins(out['!margins'] = {}); + out['!margins'].header = val.header; + out['!margins'].footer = val.footer; + break; + + case 'Window2': // TODO + // $FlowIgnore + if(val.RTL) Workbook.Views[0].RTL = true; + break; + + case 'Header': break; // TODO + case 'Footer': break; // TODO + case 'HCenter': break; // TODO + case 'VCenter': break; // TODO + case 'Pls': break; // TODO + case 'GCW': break; + case 'LHRecord': break; + case 'DBCell': break; // TODO + case 'EntExU2': break; // TODO + case 'SxView': break; // TODO + case 'Sxvd': break; // TODO + case 'SXVI': break; // TODO + case 'SXVDEx': break; // TODO + case 'SxIvd': break; // TODO + case 'SXString': break; // TODO + case 'Sync': break; + case 'Addin': break; + case 'SXDI': break; // TODO + case 'SXLI': break; // TODO + case 'SXEx': break; // TODO + case 'QsiSXTag': break; // TODO + case 'Selection': break; + case 'Feat': break; + case 'FeatHdr': case 'FeatHdr11': break; + case 'Feature11': case 'Feature12': case 'List12': break; + case 'Country': country = val; break; + case 'RecalcId': break; + case 'DxGCol': break; // TODO: htmlify + case 'Fbi': case 'Fbi2': case 'GelFrame': break; + case 'Font': break; // TODO + case 'XFCRC': break; // TODO + case 'Style': break; // TODO + case 'StyleExt': break; // TODO + case 'Palette': palette = val; break; + case 'Theme': themes = val; break; + /* Protection */ + case 'ScenarioProtect': break; + case 'ObjProtect': break; + + /* Conditional Formatting */ + case 'CondFmt12': break; + + /* Table */ + case 'Table': break; // TODO + case 'TableStyles': break; // TODO + case 'TableStyle': break; // TODO + case 'TableStyleElement': break; // TODO + + /* PivotTable */ + case 'SXStreamID': break; // TODO + case 'SXVS': break; // TODO + case 'DConRef': break; // TODO + case 'SXAddl': break; // TODO + case 'DConBin': break; // TODO + case 'DConName': break; // TODO + case 'SXPI': break; // TODO + case 'SxFormat': break; // TODO + case 'SxSelect': break; // TODO + case 'SxRule': break; // TODO + case 'SxFilt': break; // TODO + case 'SxItm': break; // TODO + case 'SxDXF': break; // TODO + + /* Scenario Manager */ + case 'ScenMan': break; + + /* Data Consolidation */ + case 'DCon': break; + + /* Watched Cell */ + case 'CellWatch': break; + + /* Print Settings */ + case 'PrintRowCol': break; + case 'PrintGrid': break; + case 'PrintSize': break; + + case 'XCT': break; + case 'CRN': break; + + case 'Scl': { + //console.log("Zoom Level:", val[0]/val[1],val); + } break; + case 'SheetExt': { + /* empty */ + } break; + case 'SheetExtOptional': { + /* empty */ + } break; + + /* VBA */ + case 'ObNoMacros': { + /* empty */ + } break; + case 'ObProj': { + /* empty */ + } break; + case 'CodeName': { + if(!cur_sheet) Workbook.WBProps.CodeName = val || "ThisWorkbook"; + else wsprops.CodeName = val || wsprops.name; + } break; + case 'GUIDTypeLib': { + /* empty */ + } break; + + case 'WOpt': break; // TODO: WTF? + case 'PhoneticInfo': break; + + case 'OleObjectSize': break; + + /* Differential Formatting */ + case 'DXF': case 'DXFN': case 'DXFN12': case 'DXFN12List': case 'DXFN12NoCB': break; + + /* Data Validation */ + case 'Dv': case 'DVal': break; + + /* Data Series */ + case 'BRAI': case 'Series': case 'SeriesText': break; + + /* Data Connection */ + case 'DConn': break; + case 'DbOrParamQry': break; + case 'DBQueryExt': break; + + case 'OleDbConn': break; + case 'ExtString': break; + + /* Formatting */ + case 'IFmtRecord': break; + case 'CondFmt': case 'CF': case 'CF12': case 'CFEx': break; + + /* Explicitly Ignored */ + case 'Excel9File': break; + case 'Units': break; + case 'InterfaceHdr': case 'Mms': case 'InterfaceEnd': case 'DSF': break; + case 'BuiltInFnGroupCount': /* 2.4.30 0x0E or 0x10 but excel 2011 generates 0x11? */ break; + /* View Stuff */ + case 'Window1': case 'HideObj': case 'GridSet': case 'Guts': + case 'UserBView': case 'UserSViewBegin': case 'UserSViewEnd': + case 'Pane': break; + default: switch(R.n) { /* nested */ + /* Chart */ + case 'Dat': + case 'Begin': case 'End': + case 'StartBlock': case 'EndBlock': + case 'Frame': case 'Area': + case 'Axis': case 'AxisLine': case 'Tick': break; + case 'AxesUsed': + case 'CrtLayout12': case 'CrtLayout12A': case 'CrtLink': case 'CrtLine': case 'CrtMlFrt': case 'CrtMlFrtContinue': break; + case 'LineFormat': case 'AreaFormat': + case 'Chart': case 'Chart3d': case 'Chart3DBarShape': case 'ChartFormat': case 'ChartFrtInfo': break; + case 'PlotArea': case 'PlotGrowth': break; + case 'SeriesList': case 'SerParent': case 'SerAuxTrend': break; + case 'DataFormat': case 'SerToCrt': case 'FontX': break; + case 'CatSerRange': case 'AxcExt': case 'SerFmt': break; + case 'ShtProps': break; + case 'DefaultText': case 'Text': case 'CatLab': break; + case 'DataLabExtContents': break; + case 'Legend': case 'LegendException': break; + case 'Pie': case 'Scatter': break; + case 'PieFormat': case 'MarkerFormat': break; + case 'StartObject': case 'EndObject': break; + case 'AlRuns': case 'ObjectLink': break; + case 'SIIndex': break; + case 'AttachedLabel': case 'YMult': break; + + /* Chart Group */ + case 'Line': case 'Bar': break; + case 'Surf': break; + + /* Axis Group */ + case 'AxisParent': break; + case 'Pos': break; + case 'ValueRange': break; + + /* Pivot Chart */ + case 'SXViewEx9': break; // TODO + case 'SXViewLink': break; + case 'PivotChartBits': break; + case 'SBaseRef': break; + case 'TextPropsStream': break; + + /* Chart Misc */ + case 'LnExt': break; + case 'MkrExt': break; + case 'CrtCoopt': break; + + /* Query Table */ + case 'Qsi': case 'Qsif': case 'Qsir': case 'QsiSXTag': break; + case 'TxtQry': break; + + /* Filter */ + case 'FilterMode': break; + case 'AutoFilter': case 'AutoFilterInfo': break; + case 'AutoFilter12': break; + case 'DropDownObjIds': break; + case 'Sort': break; + case 'SortData': break; + + /* Drawing */ + case 'ShapePropsStream': break; + case 'MsoDrawing': case 'MsoDrawingGroup': case 'MsoDrawingSelection': break; + /* Pub Stuff */ + case 'WebPub': case 'AutoWebPub': break; + + /* Print Stuff */ + case 'HeaderFooter': case 'HFPicture': case 'PLV': + case 'HorizontalPageBreaks': case 'VerticalPageBreaks': break; + /* Behavioral */ + case 'Backup': case 'CompressPictures': case 'Compat12': break; + + /* Should not Happen */ + case 'Continue': case 'ContinueFrt12': break; + + /* Future Records */ + case 'FrtFontList': case 'FrtWrapper': break; + + default: switch(R.n) { /* nested */ + /* BIFF5 records */ + case 'TabIdConf': case 'Radar': case 'RadarArea': case 'DropBar': case 'Intl': case 'CoordList': case 'SerAuxErrBar': break; + + /* BIFF2-4 records */ + case 'BIFF2FONTCLR': case 'BIFF2FMTCNT': case 'BIFF2FONTXTRA': break; + case 'BIFF2XF': case 'BIFF3XF': case 'BIFF4XF': break; + case 'BIFF4FMTCNT': case 'BIFF2ROW': case 'BIFF2WINDOW2': break; + + /* Miscellaneous */ + case 'SCENARIO': case 'DConBin': case 'PicF': case 'DataLabExt': + case 'Lel': case 'BopPop': case 'BopPopCustom': case 'RealTimeData': + case 'Name': break; + case 'LHNGraph': case 'FnGroupName': case 'AddMenu': case 'LPr': break; + case 'ListObj': case 'ListField': break; + case 'RRSort': break; + case 'BigName': break; + case 'ToolbarHdr': case 'ToolbarEnd': break; + case 'DDEObjName': break; + case 'FRTArchId$': break; + default: if(options.WTF) throw 'Unrecognized Record ' + R.n; + }}}} + } else blob.l += length; + } + wb.SheetNames=keys(Directory).sort(function(a,b) { return Number(a) - Number(b); }).map(function(x){return Directory[x].name;}); + if(!options.bookSheets) wb.Sheets=Sheets; + if(wb.Sheets) FilterDatabases.forEach(function(r,i) { wb.Sheets[wb.SheetNames[i]]['!autofilter'] = r; }); + wb.Preamble=Preamble; + wb.Strings = sst; + wb.SSF = SSF.get_table(); + if(opts.enc) wb.Encryption = opts.enc; + if(themes) wb.Themes = themes; + wb.Metadata = {}; + if(country !== undefined) wb.Metadata.Country = country; + if(supbooks.names.length > 0) Workbook.Names = supbooks.names; + wb.Workbook = Workbook; + return wb; + } + + /* TODO: split props*/ + var PSCLSID = { + SI: "e0859ff2f94f6810ab9108002b27b3d9", + DSI: "02d5cdd59c2e1b10939708002b2cf9ae", + UDI: "05d5cdd59c2e1b10939708002b2cf9ae" + }; + function parse_xls_props(cfb, props, o) { + /* [MS-OSHARED] 2.3.3.2.2 Document Summary Information Property Set */ + var DSI = CFB.find(cfb, '!DocumentSummaryInformation'); + if(DSI && DSI.size > 0) try { + var DocSummary = parse_PropertySetStream(DSI, DocSummaryPIDDSI, PSCLSID.DSI); + for(var d in DocSummary) props[d] = DocSummary[d]; + } catch(e) {if(o.WTF) throw e;/* empty */} + + /* [MS-OSHARED] 2.3.3.2.1 Summary Information Property Set*/ + var SI = CFB.find(cfb, '!SummaryInformation'); + if(SI && SI.size > 0) try { + var Summary = parse_PropertySetStream(SI, SummaryPIDSI, PSCLSID.SI); + for(var s in Summary) if(props[s] == null) props[s] = Summary[s]; + } catch(e) {if(o.WTF) throw e;/* empty */} + + if(props.HeadingPairs && props.TitlesOfParts) { + load_props_pairs(props.HeadingPairs, props.TitlesOfParts, props, o); + delete props.HeadingPairs; delete props.TitlesOfParts; + } + } + function write_xls_props(wb, cfb) { + var DSEntries = [], SEntries = [], CEntries = []; + var i = 0, Keys; + if(wb.Props) { + Keys = keys(wb.Props); + // $FlowIgnore + for(i = 0; i < Keys.length; ++i) (DocSummaryRE.hasOwnProperty(Keys[i]) ? DSEntries : SummaryRE.hasOwnProperty(Keys[i]) ? SEntries : CEntries).push([Keys[i], wb.Props[Keys[i]]]); + } + if(wb.Custprops) { + Keys = keys(wb.Custprops); + // $FlowIgnore + for(i = 0; i < Keys.length; ++i) if(!(wb.Props||{}).hasOwnProperty(Keys[i])) (DocSummaryRE.hasOwnProperty(Keys[i]) ? DSEntries : SummaryRE.hasOwnProperty(Keys[i]) ? SEntries : CEntries).push([Keys[i], wb.Custprops[Keys[i]]]); + } + var CEntries2 = []; + for(i = 0; i < CEntries.length; ++i) { + if(XLSPSSkip.indexOf(CEntries[i][0]) > -1) continue; + if(CEntries[i][1] == null) continue; + CEntries2.push(CEntries[i]); + } + if(SEntries.length) CFB.utils.cfb_add(cfb, "/\u0005SummaryInformation", write_PropertySetStream(SEntries, PSCLSID.SI, SummaryRE, SummaryPIDSI)); + if(DSEntries.length || CEntries2.length) CFB.utils.cfb_add(cfb, "/\u0005DocumentSummaryInformation", write_PropertySetStream(DSEntries, PSCLSID.DSI, DocSummaryRE, DocSummaryPIDDSI, CEntries2.length ? CEntries2 : null, PSCLSID.UDI)); + } + + function parse_xlscfb(cfb, options) { + if(!options) options = {}; + fix_read_opts(options); + reset_cp(); + if(options.codepage) set_ansi(options.codepage); + var CompObj, WB; + if(cfb.FullPaths) { + if(CFB.find(cfb, '/encryption')) throw new Error("File is password-protected"); + CompObj = CFB.find(cfb, '!CompObj'); + WB = CFB.find(cfb, '/Workbook') || CFB.find(cfb, '/Book'); + } else { + switch(options.type) { + case 'base64': cfb = s2a(Base64.decode(cfb)); break; + case 'binary': cfb = s2a(cfb); break; + case 'buffer': break; + case 'array': if(!Array.isArray(cfb)) cfb = Array.prototype.slice.call(cfb); break; + } + prep_blob(cfb, 0); + WB = ({content: cfb}); + } + var WorkbookP; + + var _data; + if(CompObj) parse_compobj(CompObj); + if(options.bookProps && !options.bookSheets) WorkbookP = ({}); + else { + var T = has_buf ? 'buffer' : 'array'; + if(WB && WB.content) WorkbookP = parse_workbook(WB.content, options); + /* Quattro Pro 7-8 */ + else if((_data=CFB.find(cfb, 'PerfectOffice_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options)); + /* Quattro Pro 9 */ + else if((_data=CFB.find(cfb, 'NativeContent_MAIN')) && _data.content) WorkbookP = WK_.to_workbook(_data.content, (options.type = T, options)); + else throw new Error("Cannot find Workbook stream"); + if(options.bookVBA && cfb.FullPaths && CFB.find(cfb, '/_VBA_PROJECT_CUR/VBA/dir')) WorkbookP.vbaraw = make_vba_xls(cfb); + } + + var props = {}; + if(cfb.FullPaths) parse_xls_props(cfb, props, options); + + WorkbookP.Props = WorkbookP.Custprops = props; /* TODO: split up properties */ + if(options.bookFiles) WorkbookP.cfb = cfb; + /*WorkbookP.CompObjP = CompObjP; // TODO: storage? */ + return WorkbookP; + } + + + function write_xlscfb(wb, opts) { + var o = opts || {}; + var cfb = CFB.utils.cfb_new({root:"R"}); + var wbpath = "/Workbook"; + switch(o.bookType || "xls") { + case "xls": o.bookType = "biff8"; + /* falls through */ + case "xla": if(!o.bookType) o.bookType = "xla"; + /* falls through */ + case "biff8": wbpath = "/Workbook"; o.biff = 8; break; + case "biff5": wbpath = "/Book"; o.biff = 5; break; + default: throw new Error("invalid type " + o.bookType + " for XLS CFB"); + } + CFB.utils.cfb_add(cfb, wbpath, write_biff_buf(wb, o)); + if(o.biff == 8 && (wb.Props || wb.Custprops)) write_xls_props(wb, cfb); + // TODO: SI, DSI, CO + if(o.biff == 8 && wb.vbaraw) fill_vba_xls(cfb, CFB.read(wb.vbaraw, {type: typeof wb.vbaraw == "string" ? "binary" : "buffer"})); + return cfb; + } + /* [MS-XLSB] 2.3 Record Enumeration */ + var XLSBRecordEnum = { + 0x0000: { n:"BrtRowHdr", f:parse_BrtRowHdr }, + 0x0001: { n:"BrtCellBlank", f:parse_BrtCellBlank }, + 0x0002: { n:"BrtCellRk", f:parse_BrtCellRk }, + 0x0003: { n:"BrtCellError", f:parse_BrtCellError }, + 0x0004: { n:"BrtCellBool", f:parse_BrtCellBool }, + 0x0005: { n:"BrtCellReal", f:parse_BrtCellReal }, + 0x0006: { n:"BrtCellSt", f:parse_BrtCellSt }, + 0x0007: { n:"BrtCellIsst", f:parse_BrtCellIsst }, + 0x0008: { n:"BrtFmlaString", f:parse_BrtFmlaString }, + 0x0009: { n:"BrtFmlaNum", f:parse_BrtFmlaNum }, + 0x000A: { n:"BrtFmlaBool", f:parse_BrtFmlaBool }, + 0x000B: { n:"BrtFmlaError", f:parse_BrtFmlaError }, + 0x0010: { n:"BrtFRTArchID$", f:parse_BrtFRTArchID$ }, + 0x0013: { n:"BrtSSTItem", f:parse_RichStr }, + 0x0014: { n:"BrtPCDIMissing" }, + 0x0015: { n:"BrtPCDINumber" }, + 0x0016: { n:"BrtPCDIBoolean" }, + 0x0017: { n:"BrtPCDIError" }, + 0x0018: { n:"BrtPCDIString" }, + 0x0019: { n:"BrtPCDIDatetime" }, + 0x001A: { n:"BrtPCDIIndex" }, + 0x001B: { n:"BrtPCDIAMissing" }, + 0x001C: { n:"BrtPCDIANumber" }, + 0x001D: { n:"BrtPCDIABoolean" }, + 0x001E: { n:"BrtPCDIAError" }, + 0x001F: { n:"BrtPCDIAString" }, + 0x0020: { n:"BrtPCDIADatetime" }, + 0x0021: { n:"BrtPCRRecord" }, + 0x0022: { n:"BrtPCRRecordDt" }, + 0x0023: { n:"BrtFRTBegin" }, + 0x0024: { n:"BrtFRTEnd" }, + 0x0025: { n:"BrtACBegin" }, + 0x0026: { n:"BrtACEnd" }, + 0x0027: { n:"BrtName", f:parse_BrtName }, + 0x0028: { n:"BrtIndexRowBlock" }, + 0x002A: { n:"BrtIndexBlock" }, + 0x002B: { n:"BrtFont", f:parse_BrtFont }, + 0x002C: { n:"BrtFmt", f:parse_BrtFmt }, + 0x002D: { n:"BrtFill", f:parse_BrtFill }, + 0x002E: { n:"BrtBorder", f:parse_BrtBorder }, + 0x002F: { n:"BrtXF", f:parse_BrtXF }, + 0x0030: { n:"BrtStyle" }, + 0x0031: { n:"BrtCellMeta" }, + 0x0032: { n:"BrtValueMeta" }, + 0x0033: { n:"BrtMdb" }, + 0x0034: { n:"BrtBeginFmd" }, + 0x0035: { n:"BrtEndFmd" }, + 0x0036: { n:"BrtBeginMdx" }, + 0x0037: { n:"BrtEndMdx" }, + 0x0038: { n:"BrtBeginMdxTuple" }, + 0x0039: { n:"BrtEndMdxTuple" }, + 0x003A: { n:"BrtMdxMbrIstr" }, + 0x003B: { n:"BrtStr" }, + 0x003C: { n:"BrtColInfo", f:parse_ColInfo }, + 0x003E: { n:"BrtCellRString" }, + 0x003F: { n:"BrtCalcChainItem$", f:parse_BrtCalcChainItem$ }, + 0x0040: { n:"BrtDVal" }, + 0x0041: { n:"BrtSxvcellNum" }, + 0x0042: { n:"BrtSxvcellStr" }, + 0x0043: { n:"BrtSxvcellBool" }, + 0x0044: { n:"BrtSxvcellErr" }, + 0x0045: { n:"BrtSxvcellDate" }, + 0x0046: { n:"BrtSxvcellNil" }, + 0x0080: { n:"BrtFileVersion" }, + 0x0081: { n:"BrtBeginSheet" }, + 0x0082: { n:"BrtEndSheet" }, + 0x0083: { n:"BrtBeginBook", f:parsenoop, p:0 }, + 0x0084: { n:"BrtEndBook" }, + 0x0085: { n:"BrtBeginWsViews" }, + 0x0086: { n:"BrtEndWsViews" }, + 0x0087: { n:"BrtBeginBookViews" }, + 0x0088: { n:"BrtEndBookViews" }, + 0x0089: { n:"BrtBeginWsView", f:parse_BrtBeginWsView }, + 0x008A: { n:"BrtEndWsView" }, + 0x008B: { n:"BrtBeginCsViews" }, + 0x008C: { n:"BrtEndCsViews" }, + 0x008D: { n:"BrtBeginCsView" }, + 0x008E: { n:"BrtEndCsView" }, + 0x008F: { n:"BrtBeginBundleShs" }, + 0x0090: { n:"BrtEndBundleShs" }, + 0x0091: { n:"BrtBeginSheetData" }, + 0x0092: { n:"BrtEndSheetData" }, + 0x0093: { n:"BrtWsProp", f:parse_BrtWsProp }, + 0x0094: { n:"BrtWsDim", f:parse_BrtWsDim, p:16 }, + 0x0097: { n:"BrtPane" }, + 0x0098: { n:"BrtSel" }, + 0x0099: { n:"BrtWbProp", f:parse_BrtWbProp }, + 0x009A: { n:"BrtWbFactoid" }, + 0x009B: { n:"BrtFileRecover" }, + 0x009C: { n:"BrtBundleSh", f:parse_BrtBundleSh }, + 0x009D: { n:"BrtCalcProp" }, + 0x009E: { n:"BrtBookView" }, + 0x009F: { n:"BrtBeginSst", f:parse_BrtBeginSst }, + 0x00A0: { n:"BrtEndSst" }, + 0x00A1: { n:"BrtBeginAFilter", f:parse_UncheckedRfX }, + 0x00A2: { n:"BrtEndAFilter" }, + 0x00A3: { n:"BrtBeginFilterColumn" }, + 0x00A4: { n:"BrtEndFilterColumn" }, + 0x00A5: { n:"BrtBeginFilters" }, + 0x00A6: { n:"BrtEndFilters" }, + 0x00A7: { n:"BrtFilter" }, + 0x00A8: { n:"BrtColorFilter" }, + 0x00A9: { n:"BrtIconFilter" }, + 0x00AA: { n:"BrtTop10Filter" }, + 0x00AB: { n:"BrtDynamicFilter" }, + 0x00AC: { n:"BrtBeginCustomFilters" }, + 0x00AD: { n:"BrtEndCustomFilters" }, + 0x00AE: { n:"BrtCustomFilter" }, + 0x00AF: { n:"BrtAFilterDateGroupItem" }, + 0x00B0: { n:"BrtMergeCell", f:parse_BrtMergeCell }, + 0x00B1: { n:"BrtBeginMergeCells" }, + 0x00B2: { n:"BrtEndMergeCells" }, + 0x00B3: { n:"BrtBeginPivotCacheDef" }, + 0x00B4: { n:"BrtEndPivotCacheDef" }, + 0x00B5: { n:"BrtBeginPCDFields" }, + 0x00B6: { n:"BrtEndPCDFields" }, + 0x00B7: { n:"BrtBeginPCDField" }, + 0x00B8: { n:"BrtEndPCDField" }, + 0x00B9: { n:"BrtBeginPCDSource" }, + 0x00BA: { n:"BrtEndPCDSource" }, + 0x00BB: { n:"BrtBeginPCDSRange" }, + 0x00BC: { n:"BrtEndPCDSRange" }, + 0x00BD: { n:"BrtBeginPCDFAtbl" }, + 0x00BE: { n:"BrtEndPCDFAtbl" }, + 0x00BF: { n:"BrtBeginPCDIRun" }, + 0x00C0: { n:"BrtEndPCDIRun" }, + 0x00C1: { n:"BrtBeginPivotCacheRecords" }, + 0x00C2: { n:"BrtEndPivotCacheRecords" }, + 0x00C3: { n:"BrtBeginPCDHierarchies" }, + 0x00C4: { n:"BrtEndPCDHierarchies" }, + 0x00C5: { n:"BrtBeginPCDHierarchy" }, + 0x00C6: { n:"BrtEndPCDHierarchy" }, + 0x00C7: { n:"BrtBeginPCDHFieldsUsage" }, + 0x00C8: { n:"BrtEndPCDHFieldsUsage" }, + 0x00C9: { n:"BrtBeginExtConnection" }, + 0x00CA: { n:"BrtEndExtConnection" }, + 0x00CB: { n:"BrtBeginECDbProps" }, + 0x00CC: { n:"BrtEndECDbProps" }, + 0x00CD: { n:"BrtBeginECOlapProps" }, + 0x00CE: { n:"BrtEndECOlapProps" }, + 0x00CF: { n:"BrtBeginPCDSConsol" }, + 0x00D0: { n:"BrtEndPCDSConsol" }, + 0x00D1: { n:"BrtBeginPCDSCPages" }, + 0x00D2: { n:"BrtEndPCDSCPages" }, + 0x00D3: { n:"BrtBeginPCDSCPage" }, + 0x00D4: { n:"BrtEndPCDSCPage" }, + 0x00D5: { n:"BrtBeginPCDSCPItem" }, + 0x00D6: { n:"BrtEndPCDSCPItem" }, + 0x00D7: { n:"BrtBeginPCDSCSets" }, + 0x00D8: { n:"BrtEndPCDSCSets" }, + 0x00D9: { n:"BrtBeginPCDSCSet" }, + 0x00DA: { n:"BrtEndPCDSCSet" }, + 0x00DB: { n:"BrtBeginPCDFGroup" }, + 0x00DC: { n:"BrtEndPCDFGroup" }, + 0x00DD: { n:"BrtBeginPCDFGItems" }, + 0x00DE: { n:"BrtEndPCDFGItems" }, + 0x00DF: { n:"BrtBeginPCDFGRange" }, + 0x00E0: { n:"BrtEndPCDFGRange" }, + 0x00E1: { n:"BrtBeginPCDFGDiscrete" }, + 0x00E2: { n:"BrtEndPCDFGDiscrete" }, + 0x00E3: { n:"BrtBeginPCDSDTupleCache" }, + 0x00E4: { n:"BrtEndPCDSDTupleCache" }, + 0x00E5: { n:"BrtBeginPCDSDTCEntries" }, + 0x00E6: { n:"BrtEndPCDSDTCEntries" }, + 0x00E7: { n:"BrtBeginPCDSDTCEMembers" }, + 0x00E8: { n:"BrtEndPCDSDTCEMembers" }, + 0x00E9: { n:"BrtBeginPCDSDTCEMember" }, + 0x00EA: { n:"BrtEndPCDSDTCEMember" }, + 0x00EB: { n:"BrtBeginPCDSDTCQueries" }, + 0x00EC: { n:"BrtEndPCDSDTCQueries" }, + 0x00ED: { n:"BrtBeginPCDSDTCQuery" }, + 0x00EE: { n:"BrtEndPCDSDTCQuery" }, + 0x00EF: { n:"BrtBeginPCDSDTCSets" }, + 0x00F0: { n:"BrtEndPCDSDTCSets" }, + 0x00F1: { n:"BrtBeginPCDSDTCSet" }, + 0x00F2: { n:"BrtEndPCDSDTCSet" }, + 0x00F3: { n:"BrtBeginPCDCalcItems" }, + 0x00F4: { n:"BrtEndPCDCalcItems" }, + 0x00F5: { n:"BrtBeginPCDCalcItem" }, + 0x00F6: { n:"BrtEndPCDCalcItem" }, + 0x00F7: { n:"BrtBeginPRule" }, + 0x00F8: { n:"BrtEndPRule" }, + 0x00F9: { n:"BrtBeginPRFilters" }, + 0x00FA: { n:"BrtEndPRFilters" }, + 0x00FB: { n:"BrtBeginPRFilter" }, + 0x00FC: { n:"BrtEndPRFilter" }, + 0x00FD: { n:"BrtBeginPNames" }, + 0x00FE: { n:"BrtEndPNames" }, + 0x00FF: { n:"BrtBeginPName" }, + 0x0100: { n:"BrtEndPName" }, + 0x0101: { n:"BrtBeginPNPairs" }, + 0x0102: { n:"BrtEndPNPairs" }, + 0x0103: { n:"BrtBeginPNPair" }, + 0x0104: { n:"BrtEndPNPair" }, + 0x0105: { n:"BrtBeginECWebProps" }, + 0x0106: { n:"BrtEndECWebProps" }, + 0x0107: { n:"BrtBeginEcWpTables" }, + 0x0108: { n:"BrtEndECWPTables" }, + 0x0109: { n:"BrtBeginECParams" }, + 0x010A: { n:"BrtEndECParams" }, + 0x010B: { n:"BrtBeginECParam" }, + 0x010C: { n:"BrtEndECParam" }, + 0x010D: { n:"BrtBeginPCDKPIs" }, + 0x010E: { n:"BrtEndPCDKPIs" }, + 0x010F: { n:"BrtBeginPCDKPI" }, + 0x0110: { n:"BrtEndPCDKPI" }, + 0x0111: { n:"BrtBeginDims" }, + 0x0112: { n:"BrtEndDims" }, + 0x0113: { n:"BrtBeginDim" }, + 0x0114: { n:"BrtEndDim" }, + 0x0115: { n:"BrtIndexPartEnd" }, + 0x0116: { n:"BrtBeginStyleSheet" }, + 0x0117: { n:"BrtEndStyleSheet" }, + 0x0118: { n:"BrtBeginSXView" }, + 0x0119: { n:"BrtEndSXVI" }, + 0x011A: { n:"BrtBeginSXVI" }, + 0x011B: { n:"BrtBeginSXVIs" }, + 0x011C: { n:"BrtEndSXVIs" }, + 0x011D: { n:"BrtBeginSXVD" }, + 0x011E: { n:"BrtEndSXVD" }, + 0x011F: { n:"BrtBeginSXVDs" }, + 0x0120: { n:"BrtEndSXVDs" }, + 0x0121: { n:"BrtBeginSXPI" }, + 0x0122: { n:"BrtEndSXPI" }, + 0x0123: { n:"BrtBeginSXPIs" }, + 0x0124: { n:"BrtEndSXPIs" }, + 0x0125: { n:"BrtBeginSXDI" }, + 0x0126: { n:"BrtEndSXDI" }, + 0x0127: { n:"BrtBeginSXDIs" }, + 0x0128: { n:"BrtEndSXDIs" }, + 0x0129: { n:"BrtBeginSXLI" }, + 0x012A: { n:"BrtEndSXLI" }, + 0x012B: { n:"BrtBeginSXLIRws" }, + 0x012C: { n:"BrtEndSXLIRws" }, + 0x012D: { n:"BrtBeginSXLICols" }, + 0x012E: { n:"BrtEndSXLICols" }, + 0x012F: { n:"BrtBeginSXFormat" }, + 0x0130: { n:"BrtEndSXFormat" }, + 0x0131: { n:"BrtBeginSXFormats" }, + 0x0132: { n:"BrtEndSxFormats" }, + 0x0133: { n:"BrtBeginSxSelect" }, + 0x0134: { n:"BrtEndSxSelect" }, + 0x0135: { n:"BrtBeginISXVDRws" }, + 0x0136: { n:"BrtEndISXVDRws" }, + 0x0137: { n:"BrtBeginISXVDCols" }, + 0x0138: { n:"BrtEndISXVDCols" }, + 0x0139: { n:"BrtEndSXLocation" }, + 0x013A: { n:"BrtBeginSXLocation" }, + 0x013B: { n:"BrtEndSXView" }, + 0x013C: { n:"BrtBeginSXTHs" }, + 0x013D: { n:"BrtEndSXTHs" }, + 0x013E: { n:"BrtBeginSXTH" }, + 0x013F: { n:"BrtEndSXTH" }, + 0x0140: { n:"BrtBeginISXTHRws" }, + 0x0141: { n:"BrtEndISXTHRws" }, + 0x0142: { n:"BrtBeginISXTHCols" }, + 0x0143: { n:"BrtEndISXTHCols" }, + 0x0144: { n:"BrtBeginSXTDMPS" }, + 0x0145: { n:"BrtEndSXTDMPs" }, + 0x0146: { n:"BrtBeginSXTDMP" }, + 0x0147: { n:"BrtEndSXTDMP" }, + 0x0148: { n:"BrtBeginSXTHItems" }, + 0x0149: { n:"BrtEndSXTHItems" }, + 0x014A: { n:"BrtBeginSXTHItem" }, + 0x014B: { n:"BrtEndSXTHItem" }, + 0x014C: { n:"BrtBeginMetadata" }, + 0x014D: { n:"BrtEndMetadata" }, + 0x014E: { n:"BrtBeginEsmdtinfo" }, + 0x014F: { n:"BrtMdtinfo" }, + 0x0150: { n:"BrtEndEsmdtinfo" }, + 0x0151: { n:"BrtBeginEsmdb" }, + 0x0152: { n:"BrtEndEsmdb" }, + 0x0153: { n:"BrtBeginEsfmd" }, + 0x0154: { n:"BrtEndEsfmd" }, + 0x0155: { n:"BrtBeginSingleCells" }, + 0x0156: { n:"BrtEndSingleCells" }, + 0x0157: { n:"BrtBeginList" }, + 0x0158: { n:"BrtEndList" }, + 0x0159: { n:"BrtBeginListCols" }, + 0x015A: { n:"BrtEndListCols" }, + 0x015B: { n:"BrtBeginListCol" }, + 0x015C: { n:"BrtEndListCol" }, + 0x015D: { n:"BrtBeginListXmlCPr" }, + 0x015E: { n:"BrtEndListXmlCPr" }, + 0x015F: { n:"BrtListCCFmla" }, + 0x0160: { n:"BrtListTrFmla" }, + 0x0161: { n:"BrtBeginExternals" }, + 0x0162: { n:"BrtEndExternals" }, + 0x0163: { n:"BrtSupBookSrc", f:parse_RelID}, + 0x0165: { n:"BrtSupSelf" }, + 0x0166: { n:"BrtSupSame" }, + 0x0167: { n:"BrtSupTabs" }, + 0x0168: { n:"BrtBeginSupBook" }, + 0x0169: { n:"BrtPlaceholderName" }, + 0x016A: { n:"BrtExternSheet", f:parse_ExternSheet }, + 0x016B: { n:"BrtExternTableStart" }, + 0x016C: { n:"BrtExternTableEnd" }, + 0x016E: { n:"BrtExternRowHdr" }, + 0x016F: { n:"BrtExternCellBlank" }, + 0x0170: { n:"BrtExternCellReal" }, + 0x0171: { n:"BrtExternCellBool" }, + 0x0172: { n:"BrtExternCellError" }, + 0x0173: { n:"BrtExternCellString" }, + 0x0174: { n:"BrtBeginEsmdx" }, + 0x0175: { n:"BrtEndEsmdx" }, + 0x0176: { n:"BrtBeginMdxSet" }, + 0x0177: { n:"BrtEndMdxSet" }, + 0x0178: { n:"BrtBeginMdxMbrProp" }, + 0x0179: { n:"BrtEndMdxMbrProp" }, + 0x017A: { n:"BrtBeginMdxKPI" }, + 0x017B: { n:"BrtEndMdxKPI" }, + 0x017C: { n:"BrtBeginEsstr" }, + 0x017D: { n:"BrtEndEsstr" }, + 0x017E: { n:"BrtBeginPRFItem" }, + 0x017F: { n:"BrtEndPRFItem" }, + 0x0180: { n:"BrtBeginPivotCacheIDs" }, + 0x0181: { n:"BrtEndPivotCacheIDs" }, + 0x0182: { n:"BrtBeginPivotCacheID" }, + 0x0183: { n:"BrtEndPivotCacheID" }, + 0x0184: { n:"BrtBeginISXVIs" }, + 0x0185: { n:"BrtEndISXVIs" }, + 0x0186: { n:"BrtBeginColInfos" }, + 0x0187: { n:"BrtEndColInfos" }, + 0x0188: { n:"BrtBeginRwBrk" }, + 0x0189: { n:"BrtEndRwBrk" }, + 0x018A: { n:"BrtBeginColBrk" }, + 0x018B: { n:"BrtEndColBrk" }, + 0x018C: { n:"BrtBrk" }, + 0x018D: { n:"BrtUserBookView" }, + 0x018E: { n:"BrtInfo" }, + 0x018F: { n:"BrtCUsr" }, + 0x0190: { n:"BrtUsr" }, + 0x0191: { n:"BrtBeginUsers" }, + 0x0193: { n:"BrtEOF" }, + 0x0194: { n:"BrtUCR" }, + 0x0195: { n:"BrtRRInsDel" }, + 0x0196: { n:"BrtRREndInsDel" }, + 0x0197: { n:"BrtRRMove" }, + 0x0198: { n:"BrtRREndMove" }, + 0x0199: { n:"BrtRRChgCell" }, + 0x019A: { n:"BrtRREndChgCell" }, + 0x019B: { n:"BrtRRHeader" }, + 0x019C: { n:"BrtRRUserView" }, + 0x019D: { n:"BrtRRRenSheet" }, + 0x019E: { n:"BrtRRInsertSh" }, + 0x019F: { n:"BrtRRDefName" }, + 0x01A0: { n:"BrtRRNote" }, + 0x01A1: { n:"BrtRRConflict" }, + 0x01A2: { n:"BrtRRTQSIF" }, + 0x01A3: { n:"BrtRRFormat" }, + 0x01A4: { n:"BrtRREndFormat" }, + 0x01A5: { n:"BrtRRAutoFmt" }, + 0x01A6: { n:"BrtBeginUserShViews" }, + 0x01A7: { n:"BrtBeginUserShView" }, + 0x01A8: { n:"BrtEndUserShView" }, + 0x01A9: { n:"BrtEndUserShViews" }, + 0x01AA: { n:"BrtArrFmla", f:parse_BrtArrFmla }, + 0x01AB: { n:"BrtShrFmla", f:parse_BrtShrFmla }, + 0x01AC: { n:"BrtTable" }, + 0x01AD: { n:"BrtBeginExtConnections" }, + 0x01AE: { n:"BrtEndExtConnections" }, + 0x01AF: { n:"BrtBeginPCDCalcMems" }, + 0x01B0: { n:"BrtEndPCDCalcMems" }, + 0x01B1: { n:"BrtBeginPCDCalcMem" }, + 0x01B2: { n:"BrtEndPCDCalcMem" }, + 0x01B3: { n:"BrtBeginPCDHGLevels" }, + 0x01B4: { n:"BrtEndPCDHGLevels" }, + 0x01B5: { n:"BrtBeginPCDHGLevel" }, + 0x01B6: { n:"BrtEndPCDHGLevel" }, + 0x01B7: { n:"BrtBeginPCDHGLGroups" }, + 0x01B8: { n:"BrtEndPCDHGLGroups" }, + 0x01B9: { n:"BrtBeginPCDHGLGroup" }, + 0x01BA: { n:"BrtEndPCDHGLGroup" }, + 0x01BB: { n:"BrtBeginPCDHGLGMembers" }, + 0x01BC: { n:"BrtEndPCDHGLGMembers" }, + 0x01BD: { n:"BrtBeginPCDHGLGMember" }, + 0x01BE: { n:"BrtEndPCDHGLGMember" }, + 0x01BF: { n:"BrtBeginQSI" }, + 0x01C0: { n:"BrtEndQSI" }, + 0x01C1: { n:"BrtBeginQSIR" }, + 0x01C2: { n:"BrtEndQSIR" }, + 0x01C3: { n:"BrtBeginDeletedNames" }, + 0x01C4: { n:"BrtEndDeletedNames" }, + 0x01C5: { n:"BrtBeginDeletedName" }, + 0x01C6: { n:"BrtEndDeletedName" }, + 0x01C7: { n:"BrtBeginQSIFs" }, + 0x01C8: { n:"BrtEndQSIFs" }, + 0x01C9: { n:"BrtBeginQSIF" }, + 0x01CA: { n:"BrtEndQSIF" }, + 0x01CB: { n:"BrtBeginAutoSortScope" }, + 0x01CC: { n:"BrtEndAutoSortScope" }, + 0x01CD: { n:"BrtBeginConditionalFormatting" }, + 0x01CE: { n:"BrtEndConditionalFormatting" }, + 0x01CF: { n:"BrtBeginCFRule" }, + 0x01D0: { n:"BrtEndCFRule" }, + 0x01D1: { n:"BrtBeginIconSet" }, + 0x01D2: { n:"BrtEndIconSet" }, + 0x01D3: { n:"BrtBeginDatabar" }, + 0x01D4: { n:"BrtEndDatabar" }, + 0x01D5: { n:"BrtBeginColorScale" }, + 0x01D6: { n:"BrtEndColorScale" }, + 0x01D7: { n:"BrtCFVO" }, + 0x01D8: { n:"BrtExternValueMeta" }, + 0x01D9: { n:"BrtBeginColorPalette" }, + 0x01DA: { n:"BrtEndColorPalette" }, + 0x01DB: { n:"BrtIndexedColor" }, + 0x01DC: { n:"BrtMargins", f:parse_BrtMargins }, + 0x01DD: { n:"BrtPrintOptions" }, + 0x01DE: { n:"BrtPageSetup" }, + 0x01DF: { n:"BrtBeginHeaderFooter" }, + 0x01E0: { n:"BrtEndHeaderFooter" }, + 0x01E1: { n:"BrtBeginSXCrtFormat" }, + 0x01E2: { n:"BrtEndSXCrtFormat" }, + 0x01E3: { n:"BrtBeginSXCrtFormats" }, + 0x01E4: { n:"BrtEndSXCrtFormats" }, + 0x01E5: { n:"BrtWsFmtInfo", f:parse_BrtWsFmtInfo }, + 0x01E6: { n:"BrtBeginMgs" }, + 0x01E7: { n:"BrtEndMGs" }, + 0x01E8: { n:"BrtBeginMGMaps" }, + 0x01E9: { n:"BrtEndMGMaps" }, + 0x01EA: { n:"BrtBeginMG" }, + 0x01EB: { n:"BrtEndMG" }, + 0x01EC: { n:"BrtBeginMap" }, + 0x01ED: { n:"BrtEndMap" }, + 0x01EE: { n:"BrtHLink", f:parse_BrtHLink }, + 0x01EF: { n:"BrtBeginDCon" }, + 0x01F0: { n:"BrtEndDCon" }, + 0x01F1: { n:"BrtBeginDRefs" }, + 0x01F2: { n:"BrtEndDRefs" }, + 0x01F3: { n:"BrtDRef" }, + 0x01F4: { n:"BrtBeginScenMan" }, + 0x01F5: { n:"BrtEndScenMan" }, + 0x01F6: { n:"BrtBeginSct" }, + 0x01F7: { n:"BrtEndSct" }, + 0x01F8: { n:"BrtSlc" }, + 0x01F9: { n:"BrtBeginDXFs" }, + 0x01FA: { n:"BrtEndDXFs" }, + 0x01FB: { n:"BrtDXF" }, + 0x01FC: { n:"BrtBeginTableStyles" }, + 0x01FD: { n:"BrtEndTableStyles" }, + 0x01FE: { n:"BrtBeginTableStyle" }, + 0x01FF: { n:"BrtEndTableStyle" }, + 0x0200: { n:"BrtTableStyleElement" }, + 0x0201: { n:"BrtTableStyleClient" }, + 0x0202: { n:"BrtBeginVolDeps" }, + 0x0203: { n:"BrtEndVolDeps" }, + 0x0204: { n:"BrtBeginVolType" }, + 0x0205: { n:"BrtEndVolType" }, + 0x0206: { n:"BrtBeginVolMain" }, + 0x0207: { n:"BrtEndVolMain" }, + 0x0208: { n:"BrtBeginVolTopic" }, + 0x0209: { n:"BrtEndVolTopic" }, + 0x020A: { n:"BrtVolSubtopic" }, + 0x020B: { n:"BrtVolRef" }, + 0x020C: { n:"BrtVolNum" }, + 0x020D: { n:"BrtVolErr" }, + 0x020E: { n:"BrtVolStr" }, + 0x020F: { n:"BrtVolBool" }, + 0x0210: { n:"BrtBeginCalcChain$" }, + 0x0211: { n:"BrtEndCalcChain$" }, + 0x0212: { n:"BrtBeginSortState" }, + 0x0213: { n:"BrtEndSortState" }, + 0x0214: { n:"BrtBeginSortCond" }, + 0x0215: { n:"BrtEndSortCond" }, + 0x0216: { n:"BrtBookProtection" }, + 0x0217: { n:"BrtSheetProtection" }, + 0x0218: { n:"BrtRangeProtection" }, + 0x0219: { n:"BrtPhoneticInfo" }, + 0x021A: { n:"BrtBeginECTxtWiz" }, + 0x021B: { n:"BrtEndECTxtWiz" }, + 0x021C: { n:"BrtBeginECTWFldInfoLst" }, + 0x021D: { n:"BrtEndECTWFldInfoLst" }, + 0x021E: { n:"BrtBeginECTwFldInfo" }, + 0x0224: { n:"BrtFileSharing" }, + 0x0225: { n:"BrtOleSize" }, + 0x0226: { n:"BrtDrawing", f:parse_RelID }, + 0x0227: { n:"BrtLegacyDrawing" }, + 0x0228: { n:"BrtLegacyDrawingHF" }, + 0x0229: { n:"BrtWebOpt" }, + 0x022A: { n:"BrtBeginWebPubItems" }, + 0x022B: { n:"BrtEndWebPubItems" }, + 0x022C: { n:"BrtBeginWebPubItem" }, + 0x022D: { n:"BrtEndWebPubItem" }, + 0x022E: { n:"BrtBeginSXCondFmt" }, + 0x022F: { n:"BrtEndSXCondFmt" }, + 0x0230: { n:"BrtBeginSXCondFmts" }, + 0x0231: { n:"BrtEndSXCondFmts" }, + 0x0232: { n:"BrtBkHim" }, + 0x0234: { n:"BrtColor" }, + 0x0235: { n:"BrtBeginIndexedColors" }, + 0x0236: { n:"BrtEndIndexedColors" }, + 0x0239: { n:"BrtBeginMRUColors" }, + 0x023A: { n:"BrtEndMRUColors" }, + 0x023C: { n:"BrtMRUColor" }, + 0x023D: { n:"BrtBeginDVals" }, + 0x023E: { n:"BrtEndDVals" }, + 0x0241: { n:"BrtSupNameStart" }, + 0x0242: { n:"BrtSupNameValueStart" }, + 0x0243: { n:"BrtSupNameValueEnd" }, + 0x0244: { n:"BrtSupNameNum" }, + 0x0245: { n:"BrtSupNameErr" }, + 0x0246: { n:"BrtSupNameSt" }, + 0x0247: { n:"BrtSupNameNil" }, + 0x0248: { n:"BrtSupNameBool" }, + 0x0249: { n:"BrtSupNameFmla" }, + 0x024A: { n:"BrtSupNameBits" }, + 0x024B: { n:"BrtSupNameEnd" }, + 0x024C: { n:"BrtEndSupBook" }, + 0x024D: { n:"BrtCellSmartTagProperty" }, + 0x024E: { n:"BrtBeginCellSmartTag" }, + 0x024F: { n:"BrtEndCellSmartTag" }, + 0x0250: { n:"BrtBeginCellSmartTags" }, + 0x0251: { n:"BrtEndCellSmartTags" }, + 0x0252: { n:"BrtBeginSmartTags" }, + 0x0253: { n:"BrtEndSmartTags" }, + 0x0254: { n:"BrtSmartTagType" }, + 0x0255: { n:"BrtBeginSmartTagTypes" }, + 0x0256: { n:"BrtEndSmartTagTypes" }, + 0x0257: { n:"BrtBeginSXFilters" }, + 0x0258: { n:"BrtEndSXFilters" }, + 0x0259: { n:"BrtBeginSXFILTER" }, + 0x025A: { n:"BrtEndSXFilter" }, + 0x025B: { n:"BrtBeginFills" }, + 0x025C: { n:"BrtEndFills" }, + 0x025D: { n:"BrtBeginCellWatches" }, + 0x025E: { n:"BrtEndCellWatches" }, + 0x025F: { n:"BrtCellWatch" }, + 0x0260: { n:"BrtBeginCRErrs" }, + 0x0261: { n:"BrtEndCRErrs" }, + 0x0262: { n:"BrtCrashRecErr" }, + 0x0263: { n:"BrtBeginFonts" }, + 0x0264: { n:"BrtEndFonts" }, + 0x0265: { n:"BrtBeginBorders" }, + 0x0266: { n:"BrtEndBorders" }, + 0x0267: { n:"BrtBeginFmts" }, + 0x0268: { n:"BrtEndFmts" }, + 0x0269: { n:"BrtBeginCellXFs" }, + 0x026A: { n:"BrtEndCellXFs" }, + 0x026B: { n:"BrtBeginStyles" }, + 0x026C: { n:"BrtEndStyles" }, + 0x0271: { n:"BrtBigName" }, + 0x0272: { n:"BrtBeginCellStyleXFs" }, + 0x0273: { n:"BrtEndCellStyleXFs" }, + 0x0274: { n:"BrtBeginComments" }, + 0x0275: { n:"BrtEndComments" }, + 0x0276: { n:"BrtBeginCommentAuthors" }, + 0x0277: { n:"BrtEndCommentAuthors" }, + 0x0278: { n:"BrtCommentAuthor", f:parse_BrtCommentAuthor }, + 0x0279: { n:"BrtBeginCommentList" }, + 0x027A: { n:"BrtEndCommentList" }, + 0x027B: { n:"BrtBeginComment", f:parse_BrtBeginComment}, + 0x027C: { n:"BrtEndComment" }, + 0x027D: { n:"BrtCommentText", f:parse_BrtCommentText }, + 0x027E: { n:"BrtBeginOleObjects" }, + 0x027F: { n:"BrtOleObject" }, + 0x0280: { n:"BrtEndOleObjects" }, + 0x0281: { n:"BrtBeginSxrules" }, + 0x0282: { n:"BrtEndSxRules" }, + 0x0283: { n:"BrtBeginActiveXControls" }, + 0x0284: { n:"BrtActiveX" }, + 0x0285: { n:"BrtEndActiveXControls" }, + 0x0286: { n:"BrtBeginPCDSDTCEMembersSortBy" }, + 0x0288: { n:"BrtBeginCellIgnoreECs" }, + 0x0289: { n:"BrtCellIgnoreEC" }, + 0x028A: { n:"BrtEndCellIgnoreECs" }, + 0x028B: { n:"BrtCsProp", f:parse_BrtCsProp }, + 0x028C: { n:"BrtCsPageSetup" }, + 0x028D: { n:"BrtBeginUserCsViews" }, + 0x028E: { n:"BrtEndUserCsViews" }, + 0x028F: { n:"BrtBeginUserCsView" }, + 0x0290: { n:"BrtEndUserCsView" }, + 0x0291: { n:"BrtBeginPcdSFCIEntries" }, + 0x0292: { n:"BrtEndPCDSFCIEntries" }, + 0x0293: { n:"BrtPCDSFCIEntry" }, + 0x0294: { n:"BrtBeginListParts" }, + 0x0295: { n:"BrtListPart" }, + 0x0296: { n:"BrtEndListParts" }, + 0x0297: { n:"BrtSheetCalcProp" }, + 0x0298: { n:"BrtBeginFnGroup" }, + 0x0299: { n:"BrtFnGroup" }, + 0x029A: { n:"BrtEndFnGroup" }, + 0x029B: { n:"BrtSupAddin" }, + 0x029C: { n:"BrtSXTDMPOrder" }, + 0x029D: { n:"BrtCsProtection" }, + 0x029F: { n:"BrtBeginWsSortMap" }, + 0x02A0: { n:"BrtEndWsSortMap" }, + 0x02A1: { n:"BrtBeginRRSort" }, + 0x02A2: { n:"BrtEndRRSort" }, + 0x02A3: { n:"BrtRRSortItem" }, + 0x02A4: { n:"BrtFileSharingIso" }, + 0x02A5: { n:"BrtBookProtectionIso" }, + 0x02A6: { n:"BrtSheetProtectionIso" }, + 0x02A7: { n:"BrtCsProtectionIso" }, + 0x02A8: { n:"BrtRangeProtectionIso" }, + 0x0400: { n:"BrtRwDescent" }, + 0x0401: { n:"BrtKnownFonts" }, + 0x0402: { n:"BrtBeginSXTupleSet" }, + 0x0403: { n:"BrtEndSXTupleSet" }, + 0x0404: { n:"BrtBeginSXTupleSetHeader" }, + 0x0405: { n:"BrtEndSXTupleSetHeader" }, + 0x0406: { n:"BrtSXTupleSetHeaderItem" }, + 0x0407: { n:"BrtBeginSXTupleSetData" }, + 0x0408: { n:"BrtEndSXTupleSetData" }, + 0x0409: { n:"BrtBeginSXTupleSetRow" }, + 0x040A: { n:"BrtEndSXTupleSetRow" }, + 0x040B: { n:"BrtSXTupleSetRowItem" }, + 0x040C: { n:"BrtNameExt" }, + 0x040D: { n:"BrtPCDH14" }, + 0x040E: { n:"BrtBeginPCDCalcMem14" }, + 0x040F: { n:"BrtEndPCDCalcMem14" }, + 0x0410: { n:"BrtSXTH14" }, + 0x0411: { n:"BrtBeginSparklineGroup" }, + 0x0412: { n:"BrtEndSparklineGroup" }, + 0x0413: { n:"BrtSparkline" }, + 0x0414: { n:"BrtSXDI14" }, + 0x0415: { n:"BrtWsFmtInfoEx14" }, + 0x0416: { n:"BrtBeginConditionalFormatting14" }, + 0x0417: { n:"BrtEndConditionalFormatting14" }, + 0x0418: { n:"BrtBeginCFRule14" }, + 0x0419: { n:"BrtEndCFRule14" }, + 0x041A: { n:"BrtCFVO14" }, + 0x041B: { n:"BrtBeginDatabar14" }, + 0x041C: { n:"BrtBeginIconSet14" }, + 0x041D: { n:"BrtDVal14" }, + 0x041E: { n:"BrtBeginDVals14" }, + 0x041F: { n:"BrtColor14" }, + 0x0420: { n:"BrtBeginSparklines" }, + 0x0421: { n:"BrtEndSparklines" }, + 0x0422: { n:"BrtBeginSparklineGroups" }, + 0x0423: { n:"BrtEndSparklineGroups" }, + 0x0425: { n:"BrtSXVD14" }, + 0x0426: { n:"BrtBeginSXView14" }, + 0x0427: { n:"BrtEndSXView14" }, + 0x0428: { n:"BrtBeginSXView16" }, + 0x0429: { n:"BrtEndSXView16" }, + 0x042A: { n:"BrtBeginPCD14" }, + 0x042B: { n:"BrtEndPCD14" }, + 0x042C: { n:"BrtBeginExtConn14" }, + 0x042D: { n:"BrtEndExtConn14" }, + 0x042E: { n:"BrtBeginSlicerCacheIDs" }, + 0x042F: { n:"BrtEndSlicerCacheIDs" }, + 0x0430: { n:"BrtBeginSlicerCacheID" }, + 0x0431: { n:"BrtEndSlicerCacheID" }, + 0x0433: { n:"BrtBeginSlicerCache" }, + 0x0434: { n:"BrtEndSlicerCache" }, + 0x0435: { n:"BrtBeginSlicerCacheDef" }, + 0x0436: { n:"BrtEndSlicerCacheDef" }, + 0x0437: { n:"BrtBeginSlicersEx" }, + 0x0438: { n:"BrtEndSlicersEx" }, + 0x0439: { n:"BrtBeginSlicerEx" }, + 0x043A: { n:"BrtEndSlicerEx" }, + 0x043B: { n:"BrtBeginSlicer" }, + 0x043C: { n:"BrtEndSlicer" }, + 0x043D: { n:"BrtSlicerCachePivotTables" }, + 0x043E: { n:"BrtBeginSlicerCacheOlapImpl" }, + 0x043F: { n:"BrtEndSlicerCacheOlapImpl" }, + 0x0440: { n:"BrtBeginSlicerCacheLevelsData" }, + 0x0441: { n:"BrtEndSlicerCacheLevelsData" }, + 0x0442: { n:"BrtBeginSlicerCacheLevelData" }, + 0x0443: { n:"BrtEndSlicerCacheLevelData" }, + 0x0444: { n:"BrtBeginSlicerCacheSiRanges" }, + 0x0445: { n:"BrtEndSlicerCacheSiRanges" }, + 0x0446: { n:"BrtBeginSlicerCacheSiRange" }, + 0x0447: { n:"BrtEndSlicerCacheSiRange" }, + 0x0448: { n:"BrtSlicerCacheOlapItem" }, + 0x0449: { n:"BrtBeginSlicerCacheSelections" }, + 0x044A: { n:"BrtSlicerCacheSelection" }, + 0x044B: { n:"BrtEndSlicerCacheSelections" }, + 0x044C: { n:"BrtBeginSlicerCacheNative" }, + 0x044D: { n:"BrtEndSlicerCacheNative" }, + 0x044E: { n:"BrtSlicerCacheNativeItem" }, + 0x044F: { n:"BrtRangeProtection14" }, + 0x0450: { n:"BrtRangeProtectionIso14" }, + 0x0451: { n:"BrtCellIgnoreEC14" }, + 0x0457: { n:"BrtList14" }, + 0x0458: { n:"BrtCFIcon" }, + 0x0459: { n:"BrtBeginSlicerCachesPivotCacheIDs" }, + 0x045A: { n:"BrtEndSlicerCachesPivotCacheIDs" }, + 0x045B: { n:"BrtBeginSlicers" }, + 0x045C: { n:"BrtEndSlicers" }, + 0x045D: { n:"BrtWbProp14" }, + 0x045E: { n:"BrtBeginSXEdit" }, + 0x045F: { n:"BrtEndSXEdit" }, + 0x0460: { n:"BrtBeginSXEdits" }, + 0x0461: { n:"BrtEndSXEdits" }, + 0x0462: { n:"BrtBeginSXChange" }, + 0x0463: { n:"BrtEndSXChange" }, + 0x0464: { n:"BrtBeginSXChanges" }, + 0x0465: { n:"BrtEndSXChanges" }, + 0x0466: { n:"BrtSXTupleItems" }, + 0x0468: { n:"BrtBeginSlicerStyle" }, + 0x0469: { n:"BrtEndSlicerStyle" }, + 0x046A: { n:"BrtSlicerStyleElement" }, + 0x046B: { n:"BrtBeginStyleSheetExt14" }, + 0x046C: { n:"BrtEndStyleSheetExt14" }, + 0x046D: { n:"BrtBeginSlicerCachesPivotCacheID" }, + 0x046E: { n:"BrtEndSlicerCachesPivotCacheID" }, + 0x046F: { n:"BrtBeginConditionalFormattings" }, + 0x0470: { n:"BrtEndConditionalFormattings" }, + 0x0471: { n:"BrtBeginPCDCalcMemExt" }, + 0x0472: { n:"BrtEndPCDCalcMemExt" }, + 0x0473: { n:"BrtBeginPCDCalcMemsExt" }, + 0x0474: { n:"BrtEndPCDCalcMemsExt" }, + 0x0475: { n:"BrtPCDField14" }, + 0x0476: { n:"BrtBeginSlicerStyles" }, + 0x0477: { n:"BrtEndSlicerStyles" }, + 0x0478: { n:"BrtBeginSlicerStyleElements" }, + 0x0479: { n:"BrtEndSlicerStyleElements" }, + 0x047A: { n:"BrtCFRuleExt" }, + 0x047B: { n:"BrtBeginSXCondFmt14" }, + 0x047C: { n:"BrtEndSXCondFmt14" }, + 0x047D: { n:"BrtBeginSXCondFmts14" }, + 0x047E: { n:"BrtEndSXCondFmts14" }, + 0x0480: { n:"BrtBeginSortCond14" }, + 0x0481: { n:"BrtEndSortCond14" }, + 0x0482: { n:"BrtEndDVals14" }, + 0x0483: { n:"BrtEndIconSet14" }, + 0x0484: { n:"BrtEndDatabar14" }, + 0x0485: { n:"BrtBeginColorScale14" }, + 0x0486: { n:"BrtEndColorScale14" }, + 0x0487: { n:"BrtBeginSxrules14" }, + 0x0488: { n:"BrtEndSxrules14" }, + 0x0489: { n:"BrtBeginPRule14" }, + 0x048A: { n:"BrtEndPRule14" }, + 0x048B: { n:"BrtBeginPRFilters14" }, + 0x048C: { n:"BrtEndPRFilters14" }, + 0x048D: { n:"BrtBeginPRFilter14" }, + 0x048E: { n:"BrtEndPRFilter14" }, + 0x048F: { n:"BrtBeginPRFItem14" }, + 0x0490: { n:"BrtEndPRFItem14" }, + 0x0491: { n:"BrtBeginCellIgnoreECs14" }, + 0x0492: { n:"BrtEndCellIgnoreECs14" }, + 0x0493: { n:"BrtDxf14" }, + 0x0494: { n:"BrtBeginDxF14s" }, + 0x0495: { n:"BrtEndDxf14s" }, + 0x0499: { n:"BrtFilter14" }, + 0x049A: { n:"BrtBeginCustomFilters14" }, + 0x049C: { n:"BrtCustomFilter14" }, + 0x049D: { n:"BrtIconFilter14" }, + 0x049E: { n:"BrtPivotCacheConnectionName" }, + 0x0800: { n:"BrtBeginDecoupledPivotCacheIDs" }, + 0x0801: { n:"BrtEndDecoupledPivotCacheIDs" }, + 0x0802: { n:"BrtDecoupledPivotCacheID" }, + 0x0803: { n:"BrtBeginPivotTableRefs" }, + 0x0804: { n:"BrtEndPivotTableRefs" }, + 0x0805: { n:"BrtPivotTableRef" }, + 0x0806: { n:"BrtSlicerCacheBookPivotTables" }, + 0x0807: { n:"BrtBeginSxvcells" }, + 0x0808: { n:"BrtEndSxvcells" }, + 0x0809: { n:"BrtBeginSxRow" }, + 0x080A: { n:"BrtEndSxRow" }, + 0x080C: { n:"BrtPcdCalcMem15" }, + 0x0813: { n:"BrtQsi15" }, + 0x0814: { n:"BrtBeginWebExtensions" }, + 0x0815: { n:"BrtEndWebExtensions" }, + 0x0816: { n:"BrtWebExtension" }, + 0x0817: { n:"BrtAbsPath15" }, + 0x0818: { n:"BrtBeginPivotTableUISettings" }, + 0x0819: { n:"BrtEndPivotTableUISettings" }, + 0x081B: { n:"BrtTableSlicerCacheIDs" }, + 0x081C: { n:"BrtTableSlicerCacheID" }, + 0x081D: { n:"BrtBeginTableSlicerCache" }, + 0x081E: { n:"BrtEndTableSlicerCache" }, + 0x081F: { n:"BrtSxFilter15" }, + 0x0820: { n:"BrtBeginTimelineCachePivotCacheIDs" }, + 0x0821: { n:"BrtEndTimelineCachePivotCacheIDs" }, + 0x0822: { n:"BrtTimelineCachePivotCacheID" }, + 0x0823: { n:"BrtBeginTimelineCacheIDs" }, + 0x0824: { n:"BrtEndTimelineCacheIDs" }, + 0x0825: { n:"BrtBeginTimelineCacheID" }, + 0x0826: { n:"BrtEndTimelineCacheID" }, + 0x0827: { n:"BrtBeginTimelinesEx" }, + 0x0828: { n:"BrtEndTimelinesEx" }, + 0x0829: { n:"BrtBeginTimelineEx" }, + 0x082A: { n:"BrtEndTimelineEx" }, + 0x082B: { n:"BrtWorkBookPr15" }, + 0x082C: { n:"BrtPCDH15" }, + 0x082D: { n:"BrtBeginTimelineStyle" }, + 0x082E: { n:"BrtEndTimelineStyle" }, + 0x082F: { n:"BrtTimelineStyleElement" }, + 0x0830: { n:"BrtBeginTimelineStylesheetExt15" }, + 0x0831: { n:"BrtEndTimelineStylesheetExt15" }, + 0x0832: { n:"BrtBeginTimelineStyles" }, + 0x0833: { n:"BrtEndTimelineStyles" }, + 0x0834: { n:"BrtBeginTimelineStyleElements" }, + 0x0835: { n:"BrtEndTimelineStyleElements" }, + 0x0836: { n:"BrtDxf15" }, + 0x0837: { n:"BrtBeginDxfs15" }, + 0x0838: { n:"brtEndDxfs15" }, + 0x0839: { n:"BrtSlicerCacheHideItemsWithNoData" }, + 0x083A: { n:"BrtBeginItemUniqueNames" }, + 0x083B: { n:"BrtEndItemUniqueNames" }, + 0x083C: { n:"BrtItemUniqueName" }, + 0x083D: { n:"BrtBeginExtConn15" }, + 0x083E: { n:"BrtEndExtConn15" }, + 0x083F: { n:"BrtBeginOledbPr15" }, + 0x0840: { n:"BrtEndOledbPr15" }, + 0x0841: { n:"BrtBeginDataFeedPr15" }, + 0x0842: { n:"BrtEndDataFeedPr15" }, + 0x0843: { n:"BrtTextPr15" }, + 0x0844: { n:"BrtRangePr15" }, + 0x0845: { n:"BrtDbCommand15" }, + 0x0846: { n:"BrtBeginDbTables15" }, + 0x0847: { n:"BrtEndDbTables15" }, + 0x0848: { n:"BrtDbTable15" }, + 0x0849: { n:"BrtBeginDataModel" }, + 0x084A: { n:"BrtEndDataModel" }, + 0x084B: { n:"BrtBeginModelTables" }, + 0x084C: { n:"BrtEndModelTables" }, + 0x084D: { n:"BrtModelTable" }, + 0x084E: { n:"BrtBeginModelRelationships" }, + 0x084F: { n:"BrtEndModelRelationships" }, + 0x0850: { n:"BrtModelRelationship" }, + 0x0851: { n:"BrtBeginECTxtWiz15" }, + 0x0852: { n:"BrtEndECTxtWiz15" }, + 0x0853: { n:"BrtBeginECTWFldInfoLst15" }, + 0x0854: { n:"BrtEndECTWFldInfoLst15" }, + 0x0855: { n:"BrtBeginECTWFldInfo15" }, + 0x0856: { n:"BrtFieldListActiveItem" }, + 0x0857: { n:"BrtPivotCacheIdVersion" }, + 0x0858: { n:"BrtSXDI15" }, + 0x0859: { n:"BrtBeginModelTimeGroupings" }, + 0x085A: { n:"BrtEndModelTimeGroupings" }, + 0x085B: { n:"BrtBeginModelTimeGrouping" }, + 0x085C: { n:"BrtEndModelTimeGrouping" }, + 0x085D: { n:"BrtModelTimeGroupingCalcCol" }, + 0x0C00: { n:"BrtUid" }, + 0x0C01: { n:"BrtRevisionPtr" }, + 0x13e7: { n:"BrtBeginCalcFeatures" }, + 0x13e8: { n:"BrtEndCalcFeatures" }, + 0x13e9: { n:"BrtCalcFeature" }, + 0xFFFF: { n:"" } + }; + + var XLSBRE = evert_key(XLSBRecordEnum, 'n'); + + /* [MS-XLS] 2.3 Record Enumeration */ + var XLSRecordEnum = { + 0x0003: { n:"BIFF2NUM", f:parse_BIFF2NUM }, + 0x0004: { n:"BIFF2STR", f:parse_BIFF2STR }, + 0x0006: { n:"Formula", f:parse_Formula }, + 0x0009: { n:'BOF', f:parse_BOF }, + 0x000a: { n:'EOF', f:parsenoop2 }, + 0x000c: { n:"CalcCount", f:parseuint16 }, + 0x000d: { n:"CalcMode", f:parseuint16 }, + 0x000e: { n:"CalcPrecision", f:parsebool }, + 0x000f: { n:"CalcRefMode", f:parsebool }, + 0x0010: { n:"CalcDelta", f:parse_Xnum }, + 0x0011: { n:"CalcIter", f:parsebool }, + 0x0012: { n:"Protect", f:parsebool }, + 0x0013: { n:"Password", f:parseuint16 }, + 0x0014: { n:"Header", f:parse_XLHeaderFooter }, + 0x0015: { n:"Footer", f:parse_XLHeaderFooter }, + 0x0017: { n:"ExternSheet", f:parse_ExternSheet }, + 0x0018: { n:"Lbl", f:parse_Lbl }, + 0x0019: { n:"WinProtect", f:parsebool }, + 0x001a: { n:"VerticalPageBreaks" }, + 0x001b: { n:"HorizontalPageBreaks" }, + 0x001c: { n:"Note", f:parse_Note }, + 0x001d: { n:"Selection" }, + 0x0022: { n:"Date1904", f:parsebool }, + 0x0023: { n:"ExternName", f:parse_ExternName }, + 0x0026: { n:"LeftMargin", f:parse_Xnum }, + 0x0027: { n:"RightMargin", f:parse_Xnum }, + 0x0028: { n:"TopMargin", f:parse_Xnum }, + 0x0029: { n:"BottomMargin", f:parse_Xnum }, + 0x002a: { n:"PrintRowCol", f:parsebool }, + 0x002b: { n:"PrintGrid", f:parsebool }, + 0x002f: { n:"FilePass", f:parse_FilePass }, + 0x0031: { n:"Font", f:parse_Font }, + 0x0033: { n:"PrintSize", f:parseuint16 }, + 0x003c: { n:"Continue" }, + 0x003d: { n:"Window1", f:parse_Window1 }, + 0x0040: { n:"Backup", f:parsebool }, + 0x0041: { n:"Pane" }, + 0x0042: { n:'CodePage', f:parseuint16 }, + 0x004d: { n:"Pls" }, + 0x0050: { n:"DCon" }, + 0x0051: { n:"DConRef" }, + 0x0052: { n:"DConName" }, + 0x0055: { n:"DefColWidth", f:parseuint16 }, + 0x0059: { n:"XCT" }, + 0x005a: { n:"CRN" }, + 0x005b: { n:"FileSharing" }, + 0x005c: { n:'WriteAccess', f:parse_WriteAccess }, + 0x005d: { n:"Obj", f:parse_Obj }, + 0x005e: { n:"Uncalced" }, + 0x005f: { n:"CalcSaveRecalc", f:parsebool }, + 0x0060: { n:"Template" }, + 0x0061: { n:"Intl" }, + 0x0063: { n:"ObjProtect", f:parsebool }, + 0x007d: { n:"ColInfo", f:parse_ColInfo }, + 0x0080: { n:"Guts", f:parse_Guts }, + 0x0081: { n:"WsBool", f:parse_WsBool }, + 0x0082: { n:"GridSet", f:parseuint16 }, + 0x0083: { n:"HCenter", f:parsebool }, + 0x0084: { n:"VCenter", f:parsebool }, + 0x0085: { n:'BoundSheet8', f:parse_BoundSheet8 }, + 0x0086: { n:"WriteProtect" }, + 0x008c: { n:"Country", f:parse_Country }, + 0x008d: { n:"HideObj", f:parseuint16 }, + 0x0090: { n:"Sort" }, + 0x0092: { n:"Palette", f:parse_Palette }, + 0x0097: { n:"Sync" }, + 0x0098: { n:"LPr" }, + 0x0099: { n:"DxGCol" }, + 0x009a: { n:"FnGroupName" }, + 0x009b: { n:"FilterMode" }, + 0x009c: { n:"BuiltInFnGroupCount", f:parseuint16 }, + 0x009d: { n:"AutoFilterInfo" }, + 0x009e: { n:"AutoFilter" }, + 0x00a0: { n:"Scl", f:parse_Scl }, + 0x00a1: { n:"Setup", f:parse_Setup }, + 0x00ae: { n:"ScenMan" }, + 0x00af: { n:"SCENARIO" }, + 0x00b0: { n:"SxView" }, + 0x00b1: { n:"Sxvd" }, + 0x00b2: { n:"SXVI" }, + 0x00b4: { n:"SxIvd" }, + 0x00b5: { n:"SXLI" }, + 0x00b6: { n:"SXPI" }, + 0x00b8: { n:"DocRoute" }, + 0x00b9: { n:"RecipName" }, + 0x00bd: { n:"MulRk", f:parse_MulRk }, + 0x00be: { n:"MulBlank", f:parse_MulBlank }, + 0x00c1: { n:'Mms', f:parsenoop2 }, + 0x00c5: { n:"SXDI" }, + 0x00c6: { n:"SXDB" }, + 0x00c7: { n:"SXFDB" }, + 0x00c8: { n:"SXDBB" }, + 0x00c9: { n:"SXNum" }, + 0x00ca: { n:"SxBool", f:parsebool }, + 0x00cb: { n:"SxErr" }, + 0x00cc: { n:"SXInt" }, + 0x00cd: { n:"SXString" }, + 0x00ce: { n:"SXDtr" }, + 0x00cf: { n:"SxNil" }, + 0x00d0: { n:"SXTbl" }, + 0x00d1: { n:"SXTBRGIITM" }, + 0x00d2: { n:"SxTbpg" }, + 0x00d3: { n:"ObProj" }, + 0x00d5: { n:"SXStreamID" }, + 0x00d7: { n:"DBCell" }, + 0x00d8: { n:"SXRng" }, + 0x00d9: { n:"SxIsxoper" }, + 0x00da: { n:"BookBool", f:parseuint16 }, + 0x00dc: { n:"DbOrParamQry" }, + 0x00dd: { n:"ScenarioProtect", f:parsebool }, + 0x00de: { n:"OleObjectSize" }, + 0x00e0: { n:"XF", f:parse_XF }, + 0x00e1: { n:'InterfaceHdr', f:parse_InterfaceHdr }, + 0x00e2: { n:'InterfaceEnd', f:parsenoop2 }, + 0x00e3: { n:"SXVS" }, + 0x00e5: { n:"MergeCells", f:parse_MergeCells }, + 0x00e9: { n:"BkHim" }, + 0x00eb: { n:"MsoDrawingGroup" }, + 0x00ec: { n:"MsoDrawing" }, + 0x00ed: { n:"MsoDrawingSelection" }, + 0x00ef: { n:"PhoneticInfo" }, + 0x00f0: { n:"SxRule" }, + 0x00f1: { n:"SXEx" }, + 0x00f2: { n:"SxFilt" }, + 0x00f4: { n:"SxDXF" }, + 0x00f5: { n:"SxItm" }, + 0x00f6: { n:"SxName" }, + 0x00f7: { n:"SxSelect" }, + 0x00f8: { n:"SXPair" }, + 0x00f9: { n:"SxFmla" }, + 0x00fb: { n:"SxFormat" }, + 0x00fc: { n:"SST", f:parse_SST }, + 0x00fd: { n:"LabelSst", f:parse_LabelSst }, + 0x00ff: { n:"ExtSST", f:parse_ExtSST }, + 0x0100: { n:"SXVDEx" }, + 0x0103: { n:"SXFormula" }, + 0x0122: { n:"SXDBEx" }, + 0x0137: { n:"RRDInsDel" }, + 0x0138: { n:"RRDHead" }, + 0x013b: { n:"RRDChgCell" }, + 0x013d: { n:"RRTabId", f:parseuint16a }, + 0x013e: { n:"RRDRenSheet" }, + 0x013f: { n:"RRSort" }, + 0x0140: { n:"RRDMove" }, + 0x014a: { n:"RRFormat" }, + 0x014b: { n:"RRAutoFmt" }, + 0x014d: { n:"RRInsertSh" }, + 0x014e: { n:"RRDMoveBegin" }, + 0x014f: { n:"RRDMoveEnd" }, + 0x0150: { n:"RRDInsDelBegin" }, + 0x0151: { n:"RRDInsDelEnd" }, + 0x0152: { n:"RRDConflict" }, + 0x0153: { n:"RRDDefName" }, + 0x0154: { n:"RRDRstEtxp" }, + 0x015f: { n:"LRng" }, + 0x0160: { n:"UsesELFs", f:parsebool }, + 0x0161: { n:"DSF", f:parsenoop2 }, + 0x0191: { n:"CUsr" }, + 0x0192: { n:"CbUsr" }, + 0x0193: { n:"UsrInfo" }, + 0x0194: { n:"UsrExcl" }, + 0x0195: { n:"FileLock" }, + 0x0196: { n:"RRDInfo" }, + 0x0197: { n:"BCUsrs" }, + 0x0198: { n:"UsrChk" }, + 0x01a9: { n:"UserBView" }, + 0x01aa: { n:"UserSViewBegin" }, + 0x01ab: { n:"UserSViewEnd" }, + 0x01ac: { n:"RRDUserView" }, + 0x01ad: { n:"Qsi" }, + 0x01ae: { n:"SupBook", f:parse_SupBook }, + 0x01af: { n:"Prot4Rev", f:parsebool }, + 0x01b0: { n:"CondFmt" }, + 0x01b1: { n:"CF" }, + 0x01b2: { n:"DVal" }, + 0x01b5: { n:"DConBin" }, + 0x01b6: { n:"TxO", f:parse_TxO }, + 0x01b7: { n:"RefreshAll", f:parsebool }, + 0x01b8: { n:"HLink", f:parse_HLink }, + 0x01b9: { n:"Lel" }, + 0x01ba: { n:"CodeName", f:parse_XLUnicodeString }, + 0x01bb: { n:"SXFDBType" }, + 0x01bc: { n:"Prot4RevPass", f:parseuint16 }, + 0x01bd: { n:"ObNoMacros" }, + 0x01be: { n:"Dv" }, + 0x01c0: { n:"Excel9File", f:parsenoop2 }, + 0x01c1: { n:"RecalcId", f:parse_RecalcId, r:2}, + 0x01c2: { n:"EntExU2", f:parsenoop2 }, + 0x0200: { n:"Dimensions", f:parse_Dimensions }, + 0x0201: { n:"Blank", f:parse_Blank }, + 0x0203: { n:"Number", f:parse_Number }, + 0x0204: { n:"Label", f:parse_Label }, + 0x0205: { n:"BoolErr", f:parse_BoolErr }, + 0x0206: { n:"Formula", f:parse_Formula }, + 0x0207: { n:"String", f:parse_String }, + 0x0208: { n:'Row', f:parse_Row }, + 0x020b: { n:"Index" }, + 0x0221: { n:"Array", f:parse_Array }, + 0x0225: { n:"DefaultRowHeight", f:parse_DefaultRowHeight }, + 0x0236: { n:"Table" }, + 0x023e: { n:"Window2", f:parse_Window2 }, + 0x027e: { n:"RK", f:parse_RK }, + 0x0293: { n:"Style" }, + 0x0406: { n:"Formula", f:parse_Formula }, + 0x0418: { n:"BigName" }, + 0x041e: { n:"Format", f:parse_Format }, + 0x043c: { n:"ContinueBigName" }, + 0x04bc: { n:"ShrFmla", f:parse_ShrFmla }, + 0x0800: { n:"HLinkTooltip", f:parse_HLinkTooltip }, + 0x0801: { n:"WebPub" }, + 0x0802: { n:"QsiSXTag" }, + 0x0803: { n:"DBQueryExt" }, + 0x0804: { n:"ExtString" }, + 0x0805: { n:"TxtQry" }, + 0x0806: { n:"Qsir" }, + 0x0807: { n:"Qsif" }, + 0x0808: { n:"RRDTQSIF" }, + 0x0809: { n:'BOF', f:parse_BOF }, + 0x080a: { n:"OleDbConn" }, + 0x080b: { n:"WOpt" }, + 0x080c: { n:"SXViewEx" }, + 0x080d: { n:"SXTH" }, + 0x080e: { n:"SXPIEx" }, + 0x080f: { n:"SXVDTEx" }, + 0x0810: { n:"SXViewEx9" }, + 0x0812: { n:"ContinueFrt" }, + 0x0813: { n:"RealTimeData" }, + 0x0850: { n:"ChartFrtInfo" }, + 0x0851: { n:"FrtWrapper" }, + 0x0852: { n:"StartBlock" }, + 0x0853: { n:"EndBlock" }, + 0x0854: { n:"StartObject" }, + 0x0855: { n:"EndObject" }, + 0x0856: { n:"CatLab" }, + 0x0857: { n:"YMult" }, + 0x0858: { n:"SXViewLink" }, + 0x0859: { n:"PivotChartBits" }, + 0x085a: { n:"FrtFontList" }, + 0x0862: { n:"SheetExt" }, + 0x0863: { n:"BookExt", r:12}, + 0x0864: { n:"SXAddl" }, + 0x0865: { n:"CrErr" }, + 0x0866: { n:"HFPicture" }, + 0x0867: { n:'FeatHdr', f:parsenoop2 }, + 0x0868: { n:"Feat" }, + 0x086a: { n:"DataLabExt" }, + 0x086b: { n:"DataLabExtContents" }, + 0x086c: { n:"CellWatch" }, + 0x0871: { n:"FeatHdr11" }, + 0x0872: { n:"Feature11" }, + 0x0874: { n:"DropDownObjIds" }, + 0x0875: { n:"ContinueFrt11" }, + 0x0876: { n:"DConn" }, + 0x0877: { n:"List12" }, + 0x0878: { n:"Feature12" }, + 0x0879: { n:"CondFmt12" }, + 0x087a: { n:"CF12" }, + 0x087b: { n:"CFEx" }, + 0x087c: { n:"XFCRC", f:parse_XFCRC, r:12 }, + 0x087d: { n:"XFExt", f:parse_XFExt, r:12 }, + 0x087e: { n:"AutoFilter12" }, + 0x087f: { n:"ContinueFrt12" }, + 0x0884: { n:"MDTInfo" }, + 0x0885: { n:"MDXStr" }, + 0x0886: { n:"MDXTuple" }, + 0x0887: { n:"MDXSet" }, + 0x0888: { n:"MDXProp" }, + 0x0889: { n:"MDXKPI" }, + 0x088a: { n:"MDB" }, + 0x088b: { n:"PLV" }, + 0x088c: { n:"Compat12", f:parsebool, r:12 }, + 0x088d: { n:"DXF" }, + 0x088e: { n:"TableStyles", r:12 }, + 0x088f: { n:"TableStyle" }, + 0x0890: { n:"TableStyleElement" }, + 0x0892: { n:"StyleExt" }, + 0x0893: { n:"NamePublish" }, + 0x0894: { n:"NameCmt", f:parse_NameCmt, r:12 }, + 0x0895: { n:"SortData" }, + 0x0896: { n:"Theme", f:parse_Theme, r:12 }, + 0x0897: { n:"GUIDTypeLib" }, + 0x0898: { n:"FnGrp12" }, + 0x0899: { n:"NameFnGrp12" }, + 0x089a: { n:"MTRSettings", f:parse_MTRSettings, r:12 }, + 0x089b: { n:"CompressPictures", f:parsenoop2 }, + 0x089c: { n:"HeaderFooter" }, + 0x089d: { n:"CrtLayout12" }, + 0x089e: { n:"CrtMlFrt" }, + 0x089f: { n:"CrtMlFrtContinue" }, + 0x08a3: { n:"ForceFullCalculation", f:parse_ForceFullCalculation }, + 0x08a4: { n:"ShapePropsStream" }, + 0x08a5: { n:"TextPropsStream" }, + 0x08a6: { n:"RichTextStream" }, + 0x08a7: { n:"CrtLayout12A" }, + 0x1001: { n:"Units" }, + 0x1002: { n:"Chart" }, + 0x1003: { n:"Series" }, + 0x1006: { n:"DataFormat" }, + 0x1007: { n:"LineFormat" }, + 0x1009: { n:"MarkerFormat" }, + 0x100a: { n:"AreaFormat" }, + 0x100b: { n:"PieFormat" }, + 0x100c: { n:"AttachedLabel" }, + 0x100d: { n:"SeriesText" }, + 0x1014: { n:"ChartFormat" }, + 0x1015: { n:"Legend" }, + 0x1016: { n:"SeriesList" }, + 0x1017: { n:"Bar" }, + 0x1018: { n:"Line" }, + 0x1019: { n:"Pie" }, + 0x101a: { n:"Area" }, + 0x101b: { n:"Scatter" }, + 0x101c: { n:"CrtLine" }, + 0x101d: { n:"Axis" }, + 0x101e: { n:"Tick" }, + 0x101f: { n:"ValueRange" }, + 0x1020: { n:"CatSerRange" }, + 0x1021: { n:"AxisLine" }, + 0x1022: { n:"CrtLink" }, + 0x1024: { n:"DefaultText" }, + 0x1025: { n:"Text" }, + 0x1026: { n:"FontX", f:parseuint16 }, + 0x1027: { n:"ObjectLink" }, + 0x1032: { n:"Frame" }, + 0x1033: { n:"Begin" }, + 0x1034: { n:"End" }, + 0x1035: { n:"PlotArea" }, + 0x103a: { n:"Chart3d" }, + 0x103c: { n:"PicF" }, + 0x103d: { n:"DropBar" }, + 0x103e: { n:"Radar" }, + 0x103f: { n:"Surf" }, + 0x1040: { n:"RadarArea" }, + 0x1041: { n:"AxisParent" }, + 0x1043: { n:"LegendException" }, + 0x1044: { n:"ShtProps", f:parse_ShtProps }, + 0x1045: { n:"SerToCrt" }, + 0x1046: { n:"AxesUsed" }, + 0x1048: { n:"SBaseRef" }, + 0x104a: { n:"SerParent" }, + 0x104b: { n:"SerAuxTrend" }, + 0x104e: { n:"IFmtRecord" }, + 0x104f: { n:"Pos" }, + 0x1050: { n:"AlRuns" }, + 0x1051: { n:"BRAI" }, + 0x105b: { n:"SerAuxErrBar" }, + 0x105c: { n:"ClrtClient", f:parse_ClrtClient }, + 0x105d: { n:"SerFmt" }, + 0x105f: { n:"Chart3DBarShape" }, + 0x1060: { n:"Fbi" }, + 0x1061: { n:"BopPop" }, + 0x1062: { n:"AxcExt" }, + 0x1063: { n:"Dat" }, + 0x1064: { n:"PlotGrowth" }, + 0x1065: { n:"SIIndex" }, + 0x1066: { n:"GelFrame" }, + 0x1067: { n:"BopPopCustom" }, + 0x1068: { n:"Fbi2" }, + + 0x0000: { n:"Dimensions", f:parse_Dimensions }, + 0x0002: { n:"BIFF2INT", f:parse_BIFF2INT }, + 0x0005: { n:"BoolErr", f:parse_BoolErr }, + 0x0007: { n:"String", f:parse_BIFF2STRING }, + 0x0008: { n:"BIFF2ROW" }, + 0x000b: { n:"Index" }, + 0x0016: { n:"ExternCount", f:parseuint16 }, + 0x001e: { n:"BIFF2FORMAT", f:parse_BIFF2Format }, + 0x001f: { n:"BIFF2FMTCNT" }, /* 16-bit cnt of BIFF2FORMAT records */ + 0x0020: { n:"BIFF2COLINFO" }, + 0x0021: { n:"Array", f:parse_Array }, + 0x0025: { n:"DefaultRowHeight", f:parse_DefaultRowHeight }, + 0x0032: { n:"BIFF2FONTXTRA", f:parse_BIFF2FONTXTRA }, + 0x0034: { n:"DDEObjName" }, + 0x003e: { n:"BIFF2WINDOW2" }, + 0x0043: { n:"BIFF2XF" }, + 0x0045: { n:"BIFF2FONTCLR" }, + 0x0056: { n:"BIFF4FMTCNT" }, /* 16-bit cnt, similar to BIFF2 */ + 0x007e: { n:"RK" }, /* Not necessarily same as 0x027e */ + 0x007f: { n:"ImData", f:parse_ImData }, + 0x0087: { n:"Addin" }, + 0x0088: { n:"Edg" }, + 0x0089: { n:"Pub" }, + 0x0091: { n:"Sub" }, + 0x0094: { n:"LHRecord" }, + 0x0095: { n:"LHNGraph" }, + 0x0096: { n:"Sound" }, + 0x00a9: { n:"CoordList" }, + 0x00ab: { n:"GCW" }, + 0x00bc: { n:"ShrFmla" }, /* Not necessarily same as 0x04bc */ + 0x00bf: { n:"ToolbarHdr" }, + 0x00c0: { n:"ToolbarEnd" }, + 0x00c2: { n:"AddMenu" }, + 0x00c3: { n:"DelMenu" }, + 0x00d6: { n:"RString", f:parse_RString }, + 0x00df: { n:"UDDesc" }, + 0x00ea: { n:"TabIdConf" }, + 0x0162: { n:"XL5Modify" }, + 0x01a5: { n:"FileSharing2" }, + 0x0209: { n:'BOF', f:parse_BOF }, + 0x0218: { n:"Lbl", f:parse_Lbl }, + 0x0223: { n:"ExternName", f:parse_ExternName }, + 0x0231: { n:"Font" }, + 0x0243: { n:"BIFF3XF" }, + 0x0409: { n:'BOF', f:parse_BOF }, + 0x0443: { n:"BIFF4XF" }, + 0x086d: { n:"FeatInfo" }, + 0x0873: { n:"FeatInfo11" }, + 0x0881: { n:"SXAddl12" }, + 0x08c0: { n:"AutoWebPub" }, + 0x08c1: { n:"ListObj" }, + 0x08c2: { n:"ListField" }, + 0x08c3: { n:"ListDV" }, + 0x08c4: { n:"ListCondFmt" }, + 0x08c5: { n:"ListCF" }, + 0x08c6: { n:"FMQry" }, + 0x08c7: { n:"FMSQry" }, + 0x08c8: { n:"PLV" }, + 0x08c9: { n:"LnExt" }, + 0x08ca: { n:"MkrExt" }, + 0x08cb: { n:"CrtCoopt" }, + 0x08d6: { n:"FRTArchId$", r:12 }, + + 0x7262: {} + }; + + var XLSRE = evert_key(XLSRecordEnum, 'n'); + function write_biff_rec(ba, type, payload, length) { + var t = +type || +XLSRE[type]; + if(isNaN(t)) return; + var len = length || (payload||[]).length || 0; + var o = ba.next(4); + o.write_shift(2, t); + o.write_shift(2, len); + if(len > 0 && is_buf(payload)) ba.push(payload); + } + + function write_BIFF2Cell(out, r, c) { + if(!out) out = new_buf(7); + out.write_shift(2, r); + out.write_shift(2, c); + out.write_shift(2, 0); + out.write_shift(1, 0); + return out; + } + + function write_BIFF2BERR(r, c, val, t) { + var out = new_buf(9); + write_BIFF2Cell(out, r, c); + if(t == 'e') { out.write_shift(1, val); out.write_shift(1, 1); } + else { out.write_shift(1, val?1:0); out.write_shift(1, 0); } + return out; + } + + /* TODO: codepage, large strings */ + function write_BIFF2LABEL(r, c, val) { + var out = new_buf(8 + 2*val.length); + write_BIFF2Cell(out, r, c); + out.write_shift(1, val.length); + out.write_shift(val.length, val, 'sbcs'); + return out.l < out.length ? out.slice(0, out.l) : out; + } + + function write_ws_biff2_cell(ba, cell, R, C) { + if(cell.v != null) switch(cell.t) { + case 'd': case 'n': + var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v; + if((v == (v|0)) && (v >= 0) && (v < 65536)) + write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v)); + else + write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v)); + return; + case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return; + /* TODO: codepage, sst */ + case 's': case 'str': + write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v)); + return; + } + write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C)); + } + + function write_ws_biff2(ba, ws, idx, opts) { + var dense = Array.isArray(ws); + var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols = []; + if(range.e.c > 0xFF || range.e.r > 0x3FFF) { + if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384"); + range.e.c = Math.min(range.e.c, 0xFF); + range.e.r = Math.min(range.e.c, 0x3FFF); + ref = encode_range(range); + } + for(var R = range.s.r; R <= range.e.r; ++R) { + rr = encode_row(R); + for(var C = range.s.c; C <= range.e.c; ++C) { + if(R === range.s.r) cols[C] = encode_col(C); + ref = cols[C] + rr; + var cell = dense ? (ws[R]||[])[C] : ws[ref]; + if(!cell) continue; + /* write cell */ + write_ws_biff2_cell(ba, cell, R, C, opts); + } + } + } + + /* Based on test files */ + function write_biff2_buf(wb, opts) { + var o = opts || {}; + if(DENSE != null && o.dense == null) o.dense = DENSE; + var ba = buf_array(); + var idx = 0; + for(var i=0;i 0xFF || range.e.r >= MAX_ROWS) { + if(opts.WTF) throw new Error("Range " + (ws['!ref'] || "A1") + " exceeds format limit A1:IV16384"); + range.e.c = Math.min(range.e.c, 0xFF); + range.e.r = Math.min(range.e.c, MAX_ROWS-1); + } + + write_biff_rec(ba, 0x0809, write_BOF(wb, 0x10, opts)); + /* ... */ + write_biff_rec(ba, "CalcMode", writeuint16(1)); + write_biff_rec(ba, "CalcCount", writeuint16(100)); + write_biff_rec(ba, "CalcRefMode", writebool(true)); + write_biff_rec(ba, "CalcIter", writebool(false)); + write_biff_rec(ba, "CalcDelta", write_Xnum(0.001)); + write_biff_rec(ba, "CalcSaveRecalc", writebool(true)); + write_biff_rec(ba, "PrintRowCol", writebool(false)); + write_biff_rec(ba, "PrintGrid", writebool(false)); + write_biff_rec(ba, "GridSet", writeuint16(1)); + write_biff_rec(ba, "Guts", write_Guts([0,0])); + /* ... */ + write_biff_rec(ba, "HCenter", writebool(false)); + write_biff_rec(ba, "VCenter", writebool(false)); + /* ... */ + write_biff_rec(ba, 0x200, write_Dimensions(range, opts)); + /* ... */ + + if(b8) ws['!links'] = []; + for(var R = range.s.r; R <= range.e.r; ++R) { + rr = encode_row(R); + for(var C = range.s.c; C <= range.e.c; ++C) { + if(R === range.s.r) cols[C] = encode_col(C); + ref = cols[C] + rr; + var cell = dense ? (ws[R]||[])[C] : ws[ref]; + if(!cell) continue; + /* write cell */ + write_ws_biff8_cell(ba, cell, R, C, opts); + if(b8 && cell.l) ws['!links'].push([ref, cell.l]); + } + } + var cname = _sheet.CodeName || _sheet.name || s; + /* ... */ + if(b8 && _WB.Views) write_biff_rec(ba, "Window2", write_Window2(_WB.Views[0])); + /* ... */ + if(b8 && (ws['!merges']||[]).length) write_biff_rec(ba, "MergeCells", write_MergeCells(ws['!merges'])); + /* ... */ + if(b8) write_ws_biff8_hlinks(ba, ws); + /* ... */ + write_biff_rec(ba, "CodeName", write_XLUnicodeString(cname, opts)); + /* ... */ + if(b8) write_FEAT(ba, ws); + /* ... */ + write_biff_rec(ba, "EOF"); + return ba.end(); + } + + /* [MS-XLS] 2.1.7.20.3 */ + function write_biff8_global(wb, bufs, opts) { + var A = buf_array(); + var _WB = ((wb||{}).Workbook||{}); + var _sheets = (_WB.Sheets||[]); + var _wb = _WB.WBProps||{}; + var b8 = opts.biff == 8, b5 = opts.biff == 5; + write_biff_rec(A, 0x0809, write_BOF(wb, 0x05, opts)); + if(opts.bookType == "xla") write_biff_rec(A, "Addin"); + write_biff_rec(A, "InterfaceHdr", b8 ? writeuint16(0x04b0) : null); + write_biff_rec(A, "Mms", writezeroes(2)); + if(b5) write_biff_rec(A, "ToolbarHdr"); + if(b5) write_biff_rec(A, "ToolbarEnd"); + write_biff_rec(A, "InterfaceEnd"); + write_biff_rec(A, "WriteAccess", write_WriteAccess("SheetJS", opts)); + write_biff_rec(A, "CodePage", writeuint16(b8 ? 0x04b0 : 0x04E4)); + if(b8) write_biff_rec(A, "DSF", writeuint16(0)); + if(b8) write_biff_rec(A, "Excel9File"); + write_biff_rec(A, "RRTabId", write_RRTabId(wb.SheetNames.length)); + if(b8 && wb.vbaraw) { + write_biff_rec(A, "ObProj"); + var cname = _wb.CodeName || "ThisWorkbook"; + write_biff_rec(A, "CodeName", write_XLUnicodeString(cname, opts)); + } + write_biff_rec(A, "BuiltInFnGroupCount", writeuint16(0x11)); + write_biff_rec(A, "WinProtect", writebool(false)); + write_biff_rec(A, "Protect", writebool(false)); + write_biff_rec(A, "Password", writeuint16(0)); + if(b8) write_biff_rec(A, "Prot4Rev", writebool(false)); + if(b8) write_biff_rec(A, "Prot4RevPass", writeuint16(0)); + write_biff_rec(A, "Window1", write_Window1(opts)); + write_biff_rec(A, "Backup", writebool(false)); + write_biff_rec(A, "HideObj", writeuint16(0)); + write_biff_rec(A, "Date1904", writebool(safe1904(wb)=="true")); + write_biff_rec(A, "CalcPrecision", writebool(true)); + if(b8) write_biff_rec(A, "RefreshAll", writebool(false)); + write_biff_rec(A, "BookBool", writeuint16(0)); + /* ... */ + write_FONTS_biff8(A, wb, opts); + write_FMTS_biff8(A, wb.SSF, opts); + write_CELLXFS_biff8(A, opts); + /* ... */ + if(b8) write_biff_rec(A, "UsesELFs", writebool(false)); + var a = A.end(); + + var C = buf_array(); + if(b8) write_biff_rec(C, "Country", write_Country()); + /* BIFF8: [SST *Continue] ExtSST */ + write_biff_rec(C, "EOF"); + var c = C.end(); + + var B = buf_array(); + var blen = 0, j = 0; + for(j = 0; j < wb.SheetNames.length; ++j) blen += (b8 ? 12 : 11) + (b8 ? 2 : 1) * wb.SheetNames[j].length; + var start = a.length + blen + c.length; + for(j = 0; j < wb.SheetNames.length; ++j) { + var _sheet = _sheets[j] || ({}); + write_biff_rec(B, "BoundSheet8", write_BoundSheet8({pos:start, hs:_sheet.Hidden||0, dt:0, name:wb.SheetNames[j]}, opts)); + start += bufs[j].length; + } + /* 1*BoundSheet8 */ + var b = B.end(); + if(blen != b.length) throw new Error("BS8 " + blen + " != " + b.length); + + var out = []; + if(a.length) out.push(a); + if(b.length) out.push(b); + if(c.length) out.push(c); + return __toBuffer([out]); + } + + /* [MS-XLS] 2.1.7.20 Workbook Stream */ + function write_biff8_buf(wb, opts) { + var o = opts || {}; + var bufs = []; + + if(wb && !wb.SSF) { + wb.SSF = SSF.get_table(); + } + if(wb && wb.SSF) { + make_ssf(SSF); SSF.load_table(wb.SSF); + // $FlowIgnore + o.revssf = evert_num(wb.SSF); o.revssf[wb.SSF[65535]] = 0; + o.ssf = wb.SSF; + } + o.cellXfs = []; + o.Strings = []; o.Strings.Count = 0; o.Strings.Unique = 0; + get_cell_style(o.cellXfs, {}, {revssf:{"General":0}}); + + for(var i = 0; i < wb.SheetNames.length; ++i) bufs[bufs.length] = write_ws_biff8(i, o, wb); + bufs.unshift(write_biff8_global(wb, bufs, o)); + return __toBuffer([bufs]); + } + + function write_biff_buf(wb, opts) { + var o = opts || {}; + switch(o.biff || 2) { + case 8: case 5: return write_biff8_buf(wb, opts); + case 4: case 3: case 2: return write_biff2_buf(wb, opts); + } + throw new Error("invalid type " + o.bookType + " for BIFF"); + } + /* note: browser DOM element cannot see mso- style attrs, must parse */ + var HTML_ = (function() { + function html_to_sheet(str, _opts) { + var opts = _opts || {}; + if(DENSE != null && opts.dense == null) opts.dense = DENSE; + var ws = opts.dense ? ([]) : ({}); + var mtch = str.match(/"); + var mtch2 = str.match(/<\/table/i); + var i = mtch.index, j = mtch2 && mtch2.index || str.length; + var rows = split_regex(str.slice(i, j), /(:?]*>)/i, ""); + var R = -1, C = 0, RS = 0, CS = 0; + var range = {s:{r:10000000, c:10000000},e:{r:0,c:0}}; + var merges = []; + for(i = 0; i < rows.length; ++i) { + var row = rows[i].trim(); + var hd = row.slice(0,3).toLowerCase(); + if(hd == "/i); + for(j = 0; j < cells.length; ++j) { + var cell = cells[j].trim(); + if(!cell.match(/")) > -1) m = m.slice(cc+1); + var tag = parsexmltag(cell.slice(0, cell.indexOf(">"))); + CS = tag.colspan ? +tag.colspan : 1; + if((RS = +tag.rowspan)>1 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}}); + var _t = tag.t || ""; + /* TODO: generate stub cells */ + if(!m.length) { C += CS; continue; } + m = htmldecode(m); + if(range.s.r > R) range.s.r = R; if(range.e.r < R) range.e.r = R; + if(range.s.c > C) range.s.c = C; if(range.e.c < C) range.e.c = C; + if(!m.length) continue; + var o = {t:'s', v:m}; + if(opts.raw || !m.trim().length || _t == 's'){} + else if(m === 'TRUE') o = {t:'b', v:true}; + else if(m === 'FALSE') o = {t:'b', v:false}; + else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)}; + else if(!isNaN(fuzzydate(m).getDate())) { + o = ({t:'d', v:parseDate(m)}); + if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}); + o.z = opts.dateNF || SSF._table[14]; + } + if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; } + else ws[encode_cell({r:R, c:C})] = o; + C += CS; + } + } + ws['!ref'] = encode_range(range); + return ws; + } + function html_to_book(str, opts) { + return sheet_to_workbook(html_to_sheet(str, opts), opts); + } + function make_html_row(ws, r, R, o) { + var M = (ws['!merges'] ||[]); + var oo = []; + for(var C = r.s.c; C <= r.e.c; ++C) { + var RS = 0, CS = 0; + for(var j = 0; j < M.length; ++j) { + if(M[j].s.r > R || M[j].s.c > C) continue; + if(M[j].e.r < R || M[j].e.c < C) continue; + if(M[j].s.r < R || M[j].s.c < C) { RS = -1; break; } + RS = M[j].e.r - M[j].s.r + 1; CS = M[j].e.c - M[j].s.c + 1; break; + } + if(RS < 0) continue; + var coord = encode_cell({r:R,c:C}); + var cell = o.dense ? (ws[R]||[])[C] : ws[coord]; + var sp = {}; + if(RS > 1) sp.rowspan = RS; + if(CS > 1) sp.colspan = CS; + /* TODO: html entities */ + var w = (cell && cell.v != null) && (cell.h || escapehtml(cell.w || (format_cell(cell), cell.w) || "")) || ""; + sp.t = cell && cell.t || 'z'; + if(o.editable) w = '' + w + ''; + sp.id = "sjs-" + coord; + oo.push(writextag('td', w, sp)); + } + var preamble = ""; + return preamble + oo.join("") + ""; + } + function make_html_preamble(ws, R, o) { + var out = []; + return out.join("") + ''; + } + var _BEGIN = 'SheetJS Table Export'; + var _END = ''; + function sheet_to_html(ws, opts/*, wb:?Workbook*/) { + var o = opts || {}; + var header = o.header != null ? o.header : _BEGIN; + var footer = o.footer != null ? o.footer : _END; + var out = [header]; + var r = decode_range(ws['!ref']); + o.dense = Array.isArray(ws); + out.push(make_html_preamble(ws, r, o)); + for(var R = r.s.r; R <= r.e.r; ++R) out.push(make_html_row(ws, r, R, o)); + out.push("
                " + footer); + return out.join(""); + } + + return { + to_workbook: html_to_book, + to_sheet: html_to_sheet, + _row: make_html_row, + BEGIN: _BEGIN, + END: _END, + _preamble: make_html_preamble, + from_sheet: sheet_to_html + }; + })(); + + function parse_dom_table(table, _opts) { + var opts = _opts || {}; + if(DENSE != null) opts.dense = DENSE; + var ws = opts.dense ? ([]) : ({}); + var rows = table.getElementsByTagName('tr'); + var sheetRows = opts.sheetRows || 10000000; + var range = {s:{r:0,c:0},e:{r:0,c:0}}; + var merges = [], midx = 0; + var rowinfo = []; + var _R = 0, R = 0, _C, C, RS, CS; + for(; _R < rows.length && R < sheetRows; ++_R) { + var row = rows[_R]; + if (is_dom_element_hidden(row)) { + if (opts.display) continue; + rowinfo[R] = {hidden: true}; + } + var elts = (row.children); + for(_C = C = 0; _C < elts.length; ++_C) { + var elt = elts[_C]; + if (opts.display && is_dom_element_hidden(elt)) continue; + var v = htmldecode(elt.innerHTML); + for(midx = 0; midx < merges.length; ++midx) { + var m = merges[midx]; + if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; } + } + /* TODO: figure out how to extract nonstandard mso- style */ + CS = +elt.getAttribute("colspan") || 1; + if((RS = +elt.getAttribute("rowspan"))>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}}); + var o = {t:'s', v:v}; + var _t = elt.getAttribute("t") || ""; + if(v != null) { + if(v.length == 0) o.t = _t || 'z'; + else if(opts.raw || v.trim().length == 0 || _t == "s"){} + else if(v === 'TRUE') o = {t:'b', v:true}; + else if(v === 'FALSE') o = {t:'b', v:false}; + else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)}; + else if(!isNaN(fuzzydate(v).getDate())) { + o = ({t:'d', v:parseDate(v)}); + if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}); + o.z = opts.dateNF || SSF._table[14]; + } + } + if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; } + else ws[encode_cell({c:C, r:R})] = o; + if(range.e.c < C) range.e.c = C; + C += CS; + } + ++R; + } + if(merges.length) ws['!merges'] = merges; + if(rowinfo.length) ws['!rows'] = rowinfo; + range.e.r = R - 1; + ws['!ref'] = encode_range(range); + if(R >= sheetRows) ws['!fullref'] = encode_range((range.e.r = rows.length-_R+R-1,range)); // We can count the real number of rows to parse but we don't to improve the performance + return ws; + } + + function table_to_book(table, opts) { + return sheet_to_workbook(parse_dom_table(table, opts), opts); + } + + function is_dom_element_hidden(element) { + var display = ''; + var get_computed_style = get_get_computed_style_function(element); + if(get_computed_style) display = get_computed_style(element).getPropertyValue('display'); + if(!display) display = element.style.display; // Fallback for cases when getComputedStyle is not available (e.g. an old browser or some Node.js environments) or doesn't work (e.g. if the element is not inserted to a document) + return display === 'none'; + } + + /* global getComputedStyle */ + function get_get_computed_style_function(element) { + // The proper getComputedStyle implementation is the one defined in the element window + if(element.ownerDocument.defaultView && typeof element.ownerDocument.defaultView.getComputedStyle === 'function') return element.ownerDocument.defaultView.getComputedStyle; + // If it is not available, try to get one from the global namespace + if(typeof getComputedStyle === 'function') return getComputedStyle; + return null; + } + /* OpenDocument */ + var parse_content_xml = (function() { + + var parse_text_p = function(text) { + /* 6.1.2 White Space Characters */ + var fixed = text + .replace(/[\t\r\n]/g, " ").trim().replace(/ +/g, " ") + .replace(//g," ") + .replace(//g, function($$,$1) { return Array(parseInt($1,10)+1).join(" "); }) + .replace(/]*\/>/g,"\t") + .replace(//g,"\n"); + var v = unescapexml(fixed.replace(/<[^>]*>/g,"")); + + return [v]; + }; + + var number_formats = { + /* ods name: [short ssf fmt, long ssf fmt] */ + day: ["d", "dd"], + month: ["m", "mm"], + year: ["y", "yy"], + hours: ["h", "hh"], + minutes: ["m", "mm"], + seconds: ["s", "ss"], + "am-pm": ["A/P", "AM/PM"], + "day-of-week": ["ddd", "dddd"], + era: ["e", "ee"], + /* there is no native representation of LO "Q" format */ + quarter: ["\\Qm", "m\\\"th quarter\""] + }; + + return function pcx(d, _opts) { + var opts = _opts || {}; + if(DENSE != null && opts.dense == null) opts.dense = DENSE; + var str = xlml_normalize(d); + var state = [], tmp; + var tag; + var NFtag = {name:""}, NF = "", pidx = 0; + var sheetag; + var rowtag; + var Sheets = {}, SheetNames = []; + var ws = opts.dense ? ([]) : ({}); + var Rn, q; + var ctag = ({value:""}); + var textp = "", textpidx = 0, textptag; + var textR = []; + var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}}; + var row_ol = 0; + var number_format_map = {}; + var merges = [], mrange = {}, mR = 0, mC = 0; + var rowinfo = [], rowpeat = 1, colpeat = 1; + var arrayf = []; + var WB = {Names:[]}; + var atag = ({}); + var _Ref = ["", ""]; + var comments = [], comment = ({}); + var creator = "", creatoridx = 0; + var isstub = false, intable = false; + var i = 0; + xlmlregex.lastIndex = 0; + str = str.replace(//mg,"").replace(//gm,""); + while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) { + + case 'table': case '工作表': // 9.1.2 + if(Rn[1]==='/') { + if(range.e.c >= range.s.c && range.e.r >= range.s.r) ws['!ref'] = encode_range(range); + if(opts.sheetRows > 0 && opts.sheetRows <= range.e.r) { + ws['!fullref'] = ws['!ref']; + range.e.r = opts.sheetRows - 1; + ws['!ref'] = encode_range(range); + } + if(merges.length) ws['!merges'] = merges; + if(rowinfo.length) ws["!rows"] = rowinfo; + sheetag.name = sheetag['名称'] || sheetag.name; + if(typeof JSON !== 'undefined') JSON.stringify(sheetag); + SheetNames.push(sheetag.name); + Sheets[sheetag.name] = ws; + intable = false; + } + else if(Rn[0].charAt(Rn[0].length-2) !== '/') { + sheetag = parsexmltag(Rn[0], false); + R = C = -1; + range.s.r = range.s.c = 10000000; range.e.r = range.e.c = 0; + ws = opts.dense ? ([]) : ({}); merges = []; + rowinfo = []; + intable = true; + } + break; + + case 'table-row-group': // 9.1.9 + if(Rn[1] === "/") --row_ol; else ++row_ol; + break; + case 'table-row': case '行': // 9.1.3 + if(Rn[1] === '/') { R+=rowpeat; rowpeat = 1; break; } + rowtag = parsexmltag(Rn[0], false); + if(rowtag['行号']) R = rowtag['行号'] - 1; else if(R == -1) R = 0; + rowpeat = +rowtag['number-rows-repeated'] || 1; + /* TODO: remove magic */ + if(rowpeat < 10) for(i = 0; i < rowpeat; ++i) if(row_ol > 0) rowinfo[R + i] = {level: row_ol}; + C = -1; break; + case 'covered-table-cell': // 9.1.5 + if(Rn[1] !== '/') ++C; + if(opts.sheetStubs) { + if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = {t:'z'}; } + else ws[encode_cell({r:R,c:C})] = {t:'z'}; + } + textp = ""; textR = []; + break; /* stub */ + case 'table-cell': case '数据': + if(Rn[0].charAt(Rn[0].length-2) === '/') { + ++C; + ctag = parsexmltag(Rn[0], false); + colpeat = parseInt(ctag['number-columns-repeated']||"1", 10); + q = ({t:'z', v:null}); + if(ctag.formula && opts.cellFormula != false) q.f = ods_to_csf_formula(unescapexml(ctag.formula)); + if((ctag['数据类型'] || ctag['value-type']) == "string") { + q.t = "s"; q.v = unescapexml(ctag['string-value'] || ""); + if(opts.dense) { + if(!ws[R]) ws[R] = []; + ws[R][C] = q; + } else { + ws[encode_cell({r:R,c:C})] = q; + } + } + C+= colpeat-1; + } else if(Rn[1]!=='/') { + ++C; + colpeat = 1; + var rptR = rowpeat ? R + rowpeat - 1 : R; + if(C > range.e.c) range.e.c = C; + if(C < range.s.c) range.s.c = C; + if(R < range.s.r) range.s.r = R; + if(rptR > range.e.r) range.e.r = rptR; + ctag = parsexmltag(Rn[0], false); + comments = []; comment = ({}); + q = ({t:ctag['数据类型'] || ctag['value-type'], v:null}); + if(opts.cellFormula) { + if(ctag.formula) ctag.formula = unescapexml(ctag.formula); + if(ctag['number-matrix-columns-spanned'] && ctag['number-matrix-rows-spanned']) { + mR = parseInt(ctag['number-matrix-rows-spanned'],10) || 0; + mC = parseInt(ctag['number-matrix-columns-spanned'],10) || 0; + mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}}; + q.F = encode_range(mrange); + arrayf.push([mrange, q.F]); + } + if(ctag.formula) q.f = ods_to_csf_formula(ctag.formula); + else for(i = 0; i < arrayf.length; ++i) + if(R >= arrayf[i][0].s.r && R <= arrayf[i][0].e.r) + if(C >= arrayf[i][0].s.c && C <= arrayf[i][0].e.c) + q.F = arrayf[i][1]; + } + if(ctag['number-columns-spanned'] || ctag['number-rows-spanned']) { + mR = parseInt(ctag['number-rows-spanned'],10) || 0; + mC = parseInt(ctag['number-columns-spanned'],10) || 0; + mrange = {s: {r:R,c:C}, e:{r:R + mR-1,c:C + mC-1}}; + merges.push(mrange); + } + + /* 19.675.2 table:number-columns-repeated */ + if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10); + + /* 19.385 office:value-type */ + switch(q.t) { + case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']); break; + case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break; + case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break; + case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break; + case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']); + if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v); } + q.z = 'm/d/yy'; break; + case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400; break; + case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break; + default: + if(q.t === 'string' || q.t === 'text' || !q.t) { + q.t = 's'; + if(ctag['string-value'] != null) { textp = unescapexml(ctag['string-value']); textR = []; } + } else throw new Error('Unsupported value type ' + q.t); + } + } else { + isstub = false; + if(q.t === 's') { + q.v = textp || ''; + if(textR.length) q.R = textR; + isstub = textpidx == 0; + } + if(atag.Target) q.l = atag; + if(comments.length > 0) { q.c = comments; comments = []; } + if(textp && opts.cellText !== false) q.w = textp; + if(!isstub || opts.sheetStubs) { + if(!(opts.sheetRows && opts.sheetRows <= R)) { + for(var rpt = 0; rpt < rowpeat; ++rpt) { + colpeat = parseInt(ctag['number-columns-repeated']||"1", 10); + if(opts.dense) { + if(!ws[R + rpt]) ws[R + rpt] = []; + ws[R + rpt][C] = rpt == 0 ? q : dup(q); + while(--colpeat > 0) ws[R + rpt][C + colpeat] = dup(q); + } else { + ws[encode_cell({r:R + rpt,c:C})] = q; + while(--colpeat > 0) ws[encode_cell({r:R + rpt,c:C + colpeat})] = dup(q); + } + if(range.e.c <= C) range.e.c = C; + } + } + } + colpeat = parseInt(ctag['number-columns-repeated']||"1", 10); + C += colpeat-1; colpeat = 0; + q = {}; + textp = ""; textR = []; + } + atag = ({}); + break; // 9.1.4 + + /* pure state */ + case 'document': // TODO: is the root for FODS + case 'document-content': case '电子表格文档': // 3.1.3.2 + case 'spreadsheet': case '主体': // 3.7 + case 'scripts': // 3.12 + case 'styles': // TODO + case 'font-face-decls': // 3.14 + if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;} + else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], true]); + break; + + case 'annotation': // 14.1 + if(Rn[1]==='/'){ + if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp; + comment.t = textp; + if(textR.length) comment.R = textR; + comment.a = creator; + comments.push(comment); + } + else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);} + creator = ""; creatoridx = 0; + textp = ""; textpidx = 0; textR = []; + break; + + case 'creator': // 4.3.2.7 + if(Rn[1]==='/') { creator = str.slice(creatoridx,Rn.index); } + else creatoridx = Rn.index + Rn[0].length; + break; + + /* ignore state */ + case 'meta': case '元数据': // TODO: FODS/UOF + case 'settings': // TODO: + case 'config-item-set': // TODO: + case 'config-item-map-indexed': // TODO: + case 'config-item-map-entry': // TODO: + case 'config-item-map-named': // TODO: + case 'shapes': // 9.2.8 + case 'frame': // 10.4.2 + case 'text-box': // 10.4.3 + case 'image': // 10.4.4 + case 'data-pilot-tables': // 9.6.2 + case 'list-style': // 16.30 + case 'form': // 13.13 + case 'dde-links': // 9.8 + case 'event-listeners': // TODO + case 'chart': // TODO + if(Rn[1]==='/'){if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp;} + else if(Rn[0].charAt(Rn[0].length-2) !== '/') state.push([Rn[3], false]); + textp = ""; textpidx = 0; textR = []; + break; + + case 'scientific-number': // TODO: + break; + case 'currency-symbol': // TODO: + break; + case 'currency-style': // TODO: + break; + case 'number-style': // 16.27.2 + case 'percentage-style': // 16.27.9 + case 'date-style': // 16.27.10 + case 'time-style': // 16.27.18 + if(Rn[1]==='/'){ + number_format_map[NFtag.name] = NF; + if((tmp=state.pop())[0]!==Rn[3]) throw "Bad state: "+tmp; + } else if(Rn[0].charAt(Rn[0].length-2) !== '/') { + NF = ""; + NFtag = parsexmltag(Rn[0], false); + state.push([Rn[3], true]); + } break; + + case 'script': break; // 3.13 + case 'libraries': break; // TODO: + case 'automatic-styles': break; // 3.15.3 + case 'master-styles': break; // TODO: + + case 'default-style': // TODO: + case 'page-layout': break; // TODO: + case 'style': // 16.2 + break; + case 'map': break; // 16.3 + case 'font-face': break; // 16.21 + + case 'paragraph-properties': break; // 17.6 + case 'table-properties': break; // 17.15 + case 'table-column-properties': break; // 17.16 + case 'table-row-properties': break; // 17.17 + case 'table-cell-properties': break; // 17.18 + + case 'number': // 16.27.3 + switch(state[state.length-1][0]) { + case 'time-style': + case 'date-style': + tag = parsexmltag(Rn[0], false); + NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break; + } break; + + case 'fraction': break; // TODO 16.27.6 + + case 'day': // 16.27.11 + case 'month': // 16.27.12 + case 'year': // 16.27.13 + case 'era': // 16.27.14 + case 'day-of-week': // 16.27.15 + case 'week-of-year': // 16.27.16 + case 'quarter': // 16.27.17 + case 'hours': // 16.27.19 + case 'minutes': // 16.27.20 + case 'seconds': // 16.27.21 + case 'am-pm': // 16.27.22 + switch(state[state.length-1][0]) { + case 'time-style': + case 'date-style': + tag = parsexmltag(Rn[0], false); + NF += number_formats[Rn[3]][tag.style==='long'?1:0]; break; + } break; + + case 'boolean-style': break; // 16.27.23 + case 'boolean': break; // 16.27.24 + case 'text-style': break; // 16.27.25 + case 'text': // 16.27.26 + if(Rn[0].slice(-2) === "/>") break; + else if(Rn[1]==="/") switch(state[state.length-1][0]) { + case 'number-style': + case 'date-style': + case 'time-style': + NF += str.slice(pidx, Rn.index); + break; + } + else pidx = Rn.index + Rn[0].length; + break; + + case 'named-range': // 9.4.12 + tag = parsexmltag(Rn[0], false); + _Ref = ods_to_csf_3D(tag['cell-range-address']); + var nrange = ({Name:tag.name, Ref:_Ref[0] + '!' + _Ref[1]}); + if(intable) nrange.Sheet = SheetNames.length; + WB.Names.push(nrange); + break; + + case 'text-content': break; // 16.27.27 + case 'text-properties': break; // 16.27.27 + case 'embedded-text': break; // 16.27.4 + + case 'body': case '电子表格': break; // 3.3 16.9.6 19.726.3 + + case 'forms': break; // 12.25.2 13.2 + case 'table-column': break; // 9.1.6 + case 'table-header-rows': break; // 9.1.7 + case 'table-rows': break; // 9.1.12 + /* TODO: outline levels */ + case 'table-column-group': break; // 9.1.10 + case 'table-header-columns': break; // 9.1.11 + case 'table-columns': break; // 9.1.12 + + case 'null-date': break; // 9.4.2 TODO: date1904 + + case 'graphic-properties': break; // 17.21 + case 'calculation-settings': break; // 9.4.1 + case 'named-expressions': break; // 9.4.11 + case 'label-range': break; // 9.4.9 + case 'label-ranges': break; // 9.4.10 + case 'named-expression': break; // 9.4.13 + case 'sort': break; // 9.4.19 + case 'sort-by': break; // 9.4.20 + case 'sort-groups': break; // 9.4.22 + + case 'tab': break; // 6.1.4 + case 'line-break': break; // 6.1.5 + case 'span': break; // 6.1.7 + case 'p': case '文本串': // 5.1.3 + if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) { + var ptp = parse_text_p(str.slice(textpidx,Rn.index), textptag); + textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0]; + } else { textptag = parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; } + break; // + case 's': break; // + + case 'database-range': // 9.4.15 + if(Rn[1]==='/') break; + try { + _Ref = ods_to_csf_3D(parsexmltag(Rn[0])['target-range-address']); + Sheets[_Ref[0]]['!autofilter'] = { ref:_Ref[1] }; + } catch(e) {/* empty */} + break; + + case 'date': break; // <*:date> + + case 'object': break; // 10.4.6.2 + case 'title': case '标题': break; // <*:title> OR + case 'desc': break; // <*:desc> + case 'binary-data': break; // 10.4.5 TODO: b64 blob + + /* 9.2 Advanced Tables */ + case 'table-source': break; // 9.2.6 + case 'scenario': break; // 9.2.6 + + case 'iteration': break; // 9.4.3 + case 'content-validations': break; // 9.4.4 + case 'filter': break; // 9.5.2 + case 'filter-and': break; // 9.5.3 + case 'filter-or': break; // 9.5.4 + case 'filter-condition': break; // 9.5.5 + + case 'list-level-style-bullet': break; // 16.31 + case 'page-count': break; // TODO + case 'time': break; // TODO + + /* 9.3 Advanced Table Cells */ + case 'cell-range-source': break; // 9.3.1 + case 'property': break; // 13.8 + + case 'a': // 6.1.8 hyperlink + if(Rn[1]!== '/') { + atag = parsexmltag(Rn[0], false); + if(!atag.href) break; + atag.Target = atag.href; delete atag.href; + if(atag.Target.charAt(0) == "#" && atag.Target.indexOf(".") > -1) { + _Ref = ods_to_csf_3D(atag.Target.slice(1)); + atag.Target = "#" + _Ref[0] + "!" + _Ref[1]; + } + } + break; + + /* non-standard */ + case 'table-protection': break; + case 'data-pilot-grand-total': break; // '; + return function wso() { + return XML_HEADER + payload; + }; + })(); + var write_content_ods = (function() { + /* 6.1.2 White Space Characters */ + var write_text_p = function(text) { + return escapexml(text) + .replace(/ +/g, function($$){return '';}) + .replace(/\t/g, "") + .replace(/\n/g, "") + .replace(/^ /, "").replace(/ $/, ""); + }; + + var null_cell_xml = ' \n'; + var covered_cell_xml = ' \n'; + var write_ws = function(ws, wb, i) { + /* Section 9 Tables */ + var o = []; + o.push(' \n'); + var R=0,C=0, range = decode_range(ws['!ref']); + var marr = ws['!merges'] || [], mi = 0; + var dense = Array.isArray(ws); + for(R = 0; R < range.s.r; ++R) o.push(' \n'); + for(; R <= range.e.r; ++R) { + o.push(' \n'); + for(C=0; C < range.s.c; ++C) o.push(null_cell_xml); + for(; C <= range.e.c; ++C) { + var skip = false, ct = {}, textp = ""; + for(mi = 0; mi != marr.length; ++mi) { + if(marr[mi].s.c > C) continue; + if(marr[mi].s.r > R) continue; + if(marr[mi].e.c < C) continue; + if(marr[mi].e.r < R) continue; + if(marr[mi].s.c != C || marr[mi].s.r != R) skip = true; + ct['table:number-columns-spanned'] = (marr[mi].e.c - marr[mi].s.c + 1); + ct['table:number-rows-spanned'] = (marr[mi].e.r - marr[mi].s.r + 1); + break; + } + if(skip) { o.push(covered_cell_xml); continue; } + var ref = encode_cell({r:R, c:C}), cell = dense ? (ws[R]||[])[C]: ws[ref]; + if(cell && cell.f) { + ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f)); + if(cell.F) { + if(cell.F.slice(0, ref.length) == ref) { + var _Fref = decode_range(cell.F); + ct['table:number-matrix-columns-spanned'] = (_Fref.e.c - _Fref.s.c + 1); + ct['table:number-matrix-rows-spanned'] = (_Fref.e.r - _Fref.s.r + 1); + } + } + } + if(!cell) { o.push(null_cell_xml); continue; } + switch(cell.t) { + case 'b': + textp = (cell.v ? 'TRUE' : 'FALSE'); + ct['office:value-type'] = "boolean"; + ct['office:boolean-value'] = (cell.v ? 'true' : 'false'); + break; + case 'n': + textp = (cell.w||String(cell.v||0)); + ct['office:value-type'] = "float"; + ct['office:value'] = (cell.v||0); + break; + case 's': case 'str': + textp = cell.v; + ct['office:value-type'] = "string"; + break; + case 'd': + textp = (cell.w||(parseDate(cell.v).toISOString())); + ct['office:value-type'] = "date"; + ct['office:date-value'] = (parseDate(cell.v).toISOString()); + ct['table:style-name'] = "ce1"; + break; + //case 'e': + default: o.push(null_cell_xml); continue; + } + var text_p = write_text_p(textp); + if(cell.l && cell.l.Target) { + var _tgt = cell.l.Target; _tgt = _tgt.charAt(0) == "#" ? "#" + csf_to_ods_3D(_tgt.slice(1)) : _tgt; + text_p = writextag('text:a', text_p, {'xlink:href': _tgt}); + } + o.push(' ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n'); + } + o.push(' \n'); + } + o.push(' \n'); + return o.join(""); + }; + + var write_automatic_styles_ods = function(o) { + o.push(' \n'); + o.push(' \n'); + o.push(' \n'); + o.push(' /\n'); + o.push(' \n'); + o.push(' /\n'); + o.push(' \n'); + o.push(' \n'); + o.push(' \n'); + o.push(' \n'); + }; + + return function wcx(wb, opts) { + var o = [XML_HEADER]; + /* 3.1.3.2 */ + var attr = wxt_helper({ + 'xmlns:office': "urn:oasis:names:tc:opendocument:xmlns:office:1.0", + 'xmlns:table': "urn:oasis:names:tc:opendocument:xmlns:table:1.0", + 'xmlns:style': "urn:oasis:names:tc:opendocument:xmlns:style:1.0", + 'xmlns:text': "urn:oasis:names:tc:opendocument:xmlns:text:1.0", + 'xmlns:draw': "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0", + 'xmlns:fo': "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0", + 'xmlns:xlink': "http://www.w3.org/1999/xlink", + 'xmlns:dc': "http://purl.org/dc/elements/1.1/", + 'xmlns:meta': "urn:oasis:names:tc:opendocument:xmlns:meta:1.0", + 'xmlns:number': "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0", + 'xmlns:presentation': "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0", + 'xmlns:svg': "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0", + 'xmlns:chart': "urn:oasis:names:tc:opendocument:xmlns:chart:1.0", + 'xmlns:dr3d': "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0", + 'xmlns:math': "http://www.w3.org/1998/Math/MathML", + 'xmlns:form': "urn:oasis:names:tc:opendocument:xmlns:form:1.0", + 'xmlns:script': "urn:oasis:names:tc:opendocument:xmlns:script:1.0", + 'xmlns:ooo': "http://openoffice.org/2004/office", + 'xmlns:ooow': "http://openoffice.org/2004/writer", + 'xmlns:oooc': "http://openoffice.org/2004/calc", + 'xmlns:dom': "http://www.w3.org/2001/xml-events", + 'xmlns:xforms': "http://www.w3.org/2002/xforms", + 'xmlns:xsd': "http://www.w3.org/2001/XMLSchema", + 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance", + 'xmlns:sheet': "urn:oasis:names:tc:opendocument:sh33tjs:1.0", + 'xmlns:rpt': "http://openoffice.org/2005/report", + 'xmlns:of': "urn:oasis:names:tc:opendocument:xmlns:of:1.2", + 'xmlns:xhtml': "http://www.w3.org/1999/xhtml", + 'xmlns:grddl': "http://www.w3.org/2003/g/data-view#", + 'xmlns:tableooo': "http://openoffice.org/2009/table", + 'xmlns:drawooo': "http://openoffice.org/2010/draw", + 'xmlns:calcext': "urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0", + 'xmlns:loext': "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0", + 'xmlns:field': "urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0", + 'xmlns:formx': "urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0", + 'xmlns:css3t': "http://www.w3.org/TR/css3-text/", + 'office:version': "1.2" + }); + + var fods = wxt_helper({ + 'xmlns:config': "urn:oasis:names:tc:opendocument:xmlns:config:1.0", + 'office:mimetype': "application/vnd.oasis.opendocument.spreadsheet" + }); + + if(opts.bookType == "fods") o.push('\n'); + else o.push('\n'); + write_automatic_styles_ods(o); + o.push(' \n'); + o.push(' \n'); + for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts)); + o.push(' \n'); + o.push(' \n'); + if(opts.bookType == "fods") o.push(''); + else o.push(''); + return o.join(""); + }; + })(); + + function write_ods(wb, opts) { + if(opts.bookType == "fods") return write_content_ods(wb, opts); + + var zip = new jszip(); + var f = ""; + + var manifest = []; + var rdf = []; + + /* Part 3 Section 3.3 MIME Media Type */ + f = "mimetype"; + zip.file(f, "application/vnd.oasis.opendocument.spreadsheet"); + + /* Part 1 Section 2.2 Documents */ + f = "content.xml"; + zip.file(f, write_content_ods(wb, opts)); + manifest.push([f, "text/xml"]); + rdf.push([f, "ContentFile"]); + + /* TODO: these are hard-coded styles to satiate excel */ + f = "styles.xml"; + zip.file(f, write_styles_ods(wb, opts)); + manifest.push([f, "text/xml"]); + rdf.push([f, "StylesFile"]); + + /* TODO: this is hard-coded to satiate excel */ + f = "meta.xml"; + zip.file(f, write_meta_ods()); + manifest.push([f, "text/xml"]); + rdf.push([f, "MetadataFile"]); + + /* Part 3 Section 6 Metadata Manifest File */ + f = "manifest.rdf"; + zip.file(f, write_rdf(rdf/*, opts*/)); + manifest.push([f, "application/rdf+xml"]); + + /* Part 3 Section 4 Manifest File */ + f = "META-INF/manifest.xml"; + zip.file(f, write_manifest(manifest/*, opts*/)); + + return zip; + } + + function write_sheet_index(wb, sheet) { + if(!sheet) return 0; + var idx = wb.SheetNames.indexOf(sheet); + if(idx == -1) throw new Error("Sheet not found: " + sheet); + return idx; + } + + function write_obj_str(factory) { + return function write_str(wb, o) { + var idx = write_sheet_index(wb, o.sheet); + return factory.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb); + }; + } + + var write_htm_str = write_obj_str(HTML_); + var write_csv_str = write_obj_str({from_sheet:sheet_to_csv}); + var write_slk_str = write_obj_str(SYLK); + var write_dif_str = write_obj_str(DIF); + var write_prn_str = write_obj_str(PRN); + var write_rtf_str = write_obj_str(RTF); + var write_txt_str = write_obj_str({from_sheet:sheet_to_txt}); + var write_dbf_buf = write_obj_str(DBF); + var write_eth_str = write_obj_str(ETH); + + function fix_opts_func(defaults) { + return function fix_opts(opts) { + for(var i = 0; i != defaults.length; ++i) { + var d = defaults[i]; + if(opts[d[0]] === undefined) opts[d[0]] = d[1]; + if(d[2] === 'n') opts[d[0]] = Number(opts[d[0]]); + } + }; + } + + var fix_read_opts = fix_opts_func([ + ['cellNF', false], /* emit cell number format string as .z */ + ['cellHTML', true], /* emit html string as .h */ + ['cellFormula', true], /* emit formulae as .f */ + ['cellStyles', false], /* emits style/theme as .s */ + ['cellText', true], /* emit formatted text as .w */ + ['cellDates', false], /* emit date cells with type `d` */ + + ['sheetStubs', false], /* emit empty cells */ + ['sheetRows', 0, 'n'], /* read n rows (0 = read all rows) */ + + ['bookDeps', false], /* parse calculation chains */ + ['bookSheets', false], /* only try to get sheet names (no Sheets) */ + ['bookProps', false], /* only try to get properties (no Sheets) */ + ['bookFiles', false], /* include raw file structure (keys, files, cfb) */ + ['bookVBA', false], /* include vba raw data (vbaraw) */ + + ['password',''], /* password */ + ['WTF', false] /* WTF mode (throws errors) */ + ]); + + + var fix_write_opts = fix_opts_func([ + ['cellDates', false], /* write date cells with type `d` */ + + ['bookSST', false], /* Generate Shared String Table */ + + ['bookType', 'xlsx'], /* Type of workbook (xlsx/m/b) */ + + ['compression', false], /* Use file compression */ + + ['WTF', false] /* WTF mode (throws errors) */ + ]); + function get_sheet_type(n) { + if(RELS.WS.indexOf(n) > -1) return "sheet"; + if(RELS.CS && n == RELS.CS) return "chart"; + if(RELS.DS && n == RELS.DS) return "dialog"; + if(RELS.MS && n == RELS.MS) return "macro"; + return (n && n.length) ? n : "sheet"; + } + function safe_parse_wbrels(wbrels, sheets) { + if(!wbrels) return 0; + try { + wbrels = sheets.map(function pwbr(w) { if(!w.id) w.id = w.strRelID; return [w.name, wbrels['!id'][w.id].Target, get_sheet_type(wbrels['!id'][w.id].Type)]; }); + } catch(e) { return null; } + return !wbrels || wbrels.length === 0 ? null : wbrels; + } + + function safe_parse_sheet(zip, path, relsPath, sheet, idx, sheetRels, sheets, stype, opts, wb, themes, styles) { + try { + sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path); + var data = getzipdata(zip, path); + var _ws; + switch(stype) { + case 'sheet': _ws = parse_ws(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break; + case 'chart': _ws = parse_cs(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); + if(!_ws || !_ws['!chart']) break; + var dfile = resolve_path(_ws['!chart'].Target, path); + var drelsp = get_rels_path(dfile); + var draw = parse_drawing(getzipstr(zip, dfile, true), parse_rels(getzipstr(zip, drelsp, true), dfile)); + var chartp = resolve_path(draw, dfile); + var crelsp = get_rels_path(chartp); + _ws = parse_chart(getzipstr(zip, chartp, true), chartp, opts, parse_rels(getzipstr(zip, crelsp, true), chartp), wb, _ws); + break; + case 'macro': _ws = parse_ms(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break; + case 'dialog': _ws = parse_ds(data, path, idx, opts, sheetRels[sheet], wb, themes, styles); break; + } + sheets[sheet] = _ws; + } catch(e) { if(opts.WTF) throw e; } + } + + function strip_front_slash(x) { return x.charAt(0) == '/' ? x.slice(1) : x; } + + function parse_zip(zip, opts) { + make_ssf(SSF); + opts = opts || {}; + fix_read_opts(opts); + + /* OpenDocument Part 3 Section 2.2.1 OpenDocument Package */ + if(safegetzipfile(zip, 'META-INF/manifest.xml')) return parse_ods(zip, opts); + /* UOC */ + if(safegetzipfile(zip, 'objectdata.xml')) return parse_ods(zip, opts); + /* Numbers */ + if(safegetzipfile(zip, 'Index/Document.iwa')) throw new Error('Unsupported NUMBERS file'); + + var entries = zipentries(zip); + var dir = parse_ct((getzipstr(zip, '[Content_Types].xml'))); + var xlsb = false; + var sheets, binname; + if(dir.workbooks.length === 0) { + binname = "xl/workbook.xml"; + if(getzipdata(zip,binname, true)) dir.workbooks.push(binname); + } + if(dir.workbooks.length === 0) { + binname = "xl/workbook.bin"; + if(!getzipdata(zip,binname,true)) throw new Error("Could not find workbook"); + dir.workbooks.push(binname); + xlsb = true; + } + if(dir.workbooks[0].slice(-3) == "bin") xlsb = true; + + var themes = ({}); + var styles = ({}); + if(!opts.bookSheets && !opts.bookProps) { + strs = []; + if(dir.sst) try { strs=parse_sst(getzipdata(zip, strip_front_slash(dir.sst)), dir.sst, opts); } catch(e) { if(opts.WTF) throw e; } + + if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts); + + if(dir.style) styles = parse_sty(getzipdata(zip, strip_front_slash(dir.style)), dir.style, themes, opts); + } + + /*var externbooks = */dir.links.map(function(link) { + return parse_xlink(getzipdata(zip, strip_front_slash(link)), link, opts); + }); + + var wb = parse_wb(getzipdata(zip, strip_front_slash(dir.workbooks[0])), dir.workbooks[0], opts); + + var props = {}, propdata = ""; + + if(dir.coreprops.length) { + propdata = getzipdata(zip, strip_front_slash(dir.coreprops[0]), true); + if(propdata) props = parse_core_props(propdata); + if(dir.extprops.length !== 0) { + propdata = getzipdata(zip, strip_front_slash(dir.extprops[0]), true); + if(propdata) parse_ext_props(propdata, props, opts); + } + } + + var custprops = {}; + if(!opts.bookSheets || opts.bookProps) { + if (dir.custprops.length !== 0) { + propdata = getzipstr(zip, strip_front_slash(dir.custprops[0]), true); + if(propdata) custprops = parse_cust_props(propdata, opts); + } + } + + var out = ({}); + if(opts.bookSheets || opts.bookProps) { + if(wb.Sheets) sheets = wb.Sheets.map(function pluck(x){ return x.name; }); + else if(props.Worksheets && props.SheetNames.length > 0) sheets=props.SheetNames; + if(opts.bookProps) { out.Props = props; out.Custprops = custprops; } + if(opts.bookSheets && typeof sheets !== 'undefined') out.SheetNames = sheets; + if(opts.bookSheets ? out.SheetNames : opts.bookProps) return out; + } + sheets = {}; + + var deps = {}; + if(opts.bookDeps && dir.calcchain) deps=parse_cc(getzipdata(zip, strip_front_slash(dir.calcchain)),dir.calcchain,opts); + + var i=0; + var sheetRels = ({}); + var path, relsPath; + + { + var wbsheets = wb.Sheets; + props.Worksheets = wbsheets.length; + props.SheetNames = []; + for(var j = 0; j != wbsheets.length; ++j) { + props.SheetNames[j] = wbsheets[j].name; + } + } + + var wbext = xlsb ? "bin" : "xml"; + var wbrelsi = dir.workbooks[0].lastIndexOf("/"); + var wbrelsfile = (dir.workbooks[0].slice(0, wbrelsi+1) + "_rels/" + dir.workbooks[0].slice(wbrelsi+1) + ".rels").replace(/^\//,""); + if(!safegetzipfile(zip, wbrelsfile)) wbrelsfile = 'xl/_rels/workbook.' + wbext + '.rels'; + var wbrels = parse_rels(getzipstr(zip, wbrelsfile, true), wbrelsfile); + if(wbrels) wbrels = safe_parse_wbrels(wbrels, wb.Sheets); + + /* Numbers iOS hack */ + var nmode = (getzipdata(zip,"xl/worksheets/sheet.xml",true))?1:0; + for(i = 0; i != props.Worksheets; ++i) { + var stype = "sheet"; + if(wbrels && wbrels[i]) { + path = 'xl/' + (wbrels[i][1]).replace(/[\/]?xl\//, ""); + if(!safegetzipfile(zip, path)) path = wbrels[i][1]; + if(!safegetzipfile(zip, path)) path = wbrelsfile.replace(/_rels\/.*$/,"") + wbrels[i][1]; + stype = wbrels[i][2]; + } else { + path = 'xl/worksheets/sheet'+(i+1-nmode)+"." + wbext; + path = path.replace(/sheet0\./,"sheet."); + } + relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels"); + safe_parse_sheet(zip, path, relsPath, props.SheetNames[i], i, sheetRels, sheets, stype, opts, wb, themes, styles); + } + + if(dir.comments) parse_comments(zip, dir.comments, sheets, sheetRels, opts); + + out = ({ + Directory: dir, + Workbook: wb, + Props: props, + Custprops: custprops, + Deps: deps, + Sheets: sheets, + SheetNames: props.SheetNames, + Strings: strs, + Styles: styles, + Themes: themes, + SSF: SSF.get_table() + }); + if(opts.bookFiles) { + out.keys = entries; + out.files = zip.files; + } + if(opts.bookVBA) { + if(dir.vba.length > 0) out.vbaraw = getzipdata(zip,strip_front_slash(dir.vba[0]),true); + else if(dir.defaults && dir.defaults.bin === CT_VBA) out.vbaraw = getzipdata(zip, 'xl/vbaProject.bin',true); + } + return out; + } + + /* [MS-OFFCRYPTO] 2.1.1 */ + function parse_xlsxcfb(cfb, _opts) { + var opts = _opts || {}; + var f = 'Workbook', data = CFB.find(cfb, f); + try { + f = '/!DataSpaces/Version'; + data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f); + /*var version = */parse_DataSpaceVersionInfo(data.content); + + /* 2.3.4.1 */ + f = '/!DataSpaces/DataSpaceMap'; + data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f); + var dsm = parse_DataSpaceMap(data.content); + if(dsm.length !== 1 || dsm[0].comps.length !== 1 || dsm[0].comps[0].t !== 0 || dsm[0].name !== "StrongEncryptionDataSpace" || dsm[0].comps[0].v !== "EncryptedPackage") + throw new Error("ECMA-376 Encrypted file bad " + f); + + /* 2.3.4.2 */ + f = '/!DataSpaces/DataSpaceInfo/StrongEncryptionDataSpace'; + data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f); + var seds = parse_DataSpaceDefinition(data.content); + if(seds.length != 1 || seds[0] != "StrongEncryptionTransform") + throw new Error("ECMA-376 Encrypted file bad " + f); + + /* 2.3.4.3 */ + f = '/!DataSpaces/TransformInfo/StrongEncryptionTransform/!Primary'; + data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f); + /*var hdr = */parse_Primary(data.content); + } catch(e) {} + + f = '/EncryptionInfo'; + data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f); + var einfo = parse_EncryptionInfo(data.content); + + /* 2.3.4.4 */ + f = '/EncryptedPackage'; + data = CFB.find(cfb, f); if(!data || !data.content) throw new Error("ECMA-376 Encrypted file missing " + f); + + /*global decrypt_agile */ + if(einfo[0] == 0x04 && typeof decrypt_agile !== 'undefined') return decrypt_agile(einfo[1], data.content, opts.password || "", opts); + /*global decrypt_std76 */ + if(einfo[0] == 0x02 && typeof decrypt_std76 !== 'undefined') return decrypt_std76(einfo[1], data.content, opts.password || "", opts); + throw new Error("File is password-protected"); + } + + function write_zip(wb, opts) { + _shapeid = 1024; + if(opts.bookType == "ods") return write_ods(wb, opts); + if(wb && !wb.SSF) { + wb.SSF = SSF.get_table(); + } + if(wb && wb.SSF) { + make_ssf(SSF); SSF.load_table(wb.SSF); + // $FlowIgnore + opts.revssf = evert_num(wb.SSF); opts.revssf[wb.SSF[65535]] = 0; + opts.ssf = wb.SSF; + } + opts.rels = {}; opts.wbrels = {}; + opts.Strings = []; opts.Strings.Count = 0; opts.Strings.Unique = 0; + if(browser_has_Map) opts.revStrings = new Map(); + else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; } + var wbext = opts.bookType == "xlsb" ? "bin" : "xml"; + var vbafmt = VBAFMTS.indexOf(opts.bookType) > -1; + var ct = new_ct(); + fix_write_opts(opts = opts || {}); + var zip = new jszip(); + var f = "", rId = 0; + + opts.cellXfs = []; + get_cell_style(opts.cellXfs, {}, {revssf:{"General":0}}); + + if(!wb.Props) wb.Props = {}; + + f = "docProps/core.xml"; + zip.file(f, write_core_props(wb.Props, opts)); + ct.coreprops.push(f); + add_rels(opts.rels, 2, f, RELS.CORE_PROPS); + + f = "docProps/app.xml"; + if(wb.Props && wb.Props.SheetNames){/* empty */} + else if(!wb.Workbook || !wb.Workbook.Sheets) wb.Props.SheetNames = wb.SheetNames; + else { + var _sn = []; + for(var _i = 0; _i < wb.SheetNames.length; ++_i) + if((wb.Workbook.Sheets[_i]||{}).Hidden != 2) _sn.push(wb.SheetNames[_i]); + wb.Props.SheetNames = _sn; + } + wb.Props.Worksheets = wb.Props.SheetNames.length; + zip.file(f, write_ext_props(wb.Props, opts)); + ct.extprops.push(f); + add_rels(opts.rels, 3, f, RELS.EXT_PROPS); + + if(wb.Custprops !== wb.Props && keys(wb.Custprops||{}).length > 0) { + f = "docProps/custom.xml"; + zip.file(f, write_cust_props(wb.Custprops, opts)); + ct.custprops.push(f); + add_rels(opts.rels, 4, f, RELS.CUST_PROPS); + } + + for(rId=1;rId <= wb.SheetNames.length; ++rId) { + var wsrels = {'!id':{}}; + var ws = wb.Sheets[wb.SheetNames[rId-1]]; + var _type = (ws || {})["!type"] || "sheet"; + switch(_type) { + case "chart": /* + f = "xl/chartsheets/sheet" + rId + "." + wbext; + zip.file(f, write_cs(rId-1, f, opts, wb, wsrels)); + ct.charts.push(f); + add_rels(wsrels, -1, "chartsheets/sheet" + rId + "." + wbext, RELS.CS); + break; */ + /* falls through */ + default: + f = "xl/worksheets/sheet" + rId + "." + wbext; + zip.file(f, write_ws(rId-1, f, opts, wb, wsrels)); + ct.sheets.push(f); + add_rels(opts.wbrels, -1, "worksheets/sheet" + rId + "." + wbext, RELS.WS[0]); + } + + if(ws) { + var comments = ws['!comments']; + var need_vml = false; + if(comments && comments.length > 0) { + var cf = "xl/comments" + rId + "." + wbext; + zip.file(cf, write_cmnt(comments, cf, opts)); + ct.comments.push(cf); + add_rels(wsrels, -1, "../comments" + rId + "." + wbext, RELS.CMNT); + need_vml = true; + } + if(ws['!legacy']) { + if(need_vml) zip.file("xl/drawings/vmlDrawing" + (rId) + ".vml", write_comments_vml(rId, ws['!comments'])); + } + delete ws['!comments']; + delete ws['!legacy']; + } + + if(wsrels['!id'].rId1) zip.file(get_rels_path(f), write_rels(wsrels)); + } + + if(opts.Strings != null && opts.Strings.length > 0) { + f = "xl/sharedStrings." + wbext; + zip.file(f, write_sst(opts.Strings, f, opts)); + ct.strs.push(f); + add_rels(opts.wbrels, -1, "sharedStrings." + wbext, RELS.SST); + } + + f = "xl/workbook." + wbext; + zip.file(f, write_wb(wb, f, opts)); + ct.workbooks.push(f); + add_rels(opts.rels, 1, f, RELS.WB); + + /* TODO: something more intelligent with themes */ + + f = "xl/theme/theme1.xml"; + zip.file(f, write_theme(wb.Themes, opts)); + ct.themes.push(f); + add_rels(opts.wbrels, -1, "theme/theme1.xml", RELS.THEME); + + /* TODO: something more intelligent with styles */ + + f = "xl/styles." + wbext; + zip.file(f, write_sty(wb, f, opts)); + ct.styles.push(f); + add_rels(opts.wbrels, -1, "styles." + wbext, RELS.STY); + + if(wb.vbaraw && vbafmt) { + f = "xl/vbaProject.bin"; + zip.file(f, wb.vbaraw); + ct.vba.push(f); + add_rels(opts.wbrels, -1, "vbaProject.bin", RELS.VBA); + } + + zip.file("[Content_Types].xml", write_ct(ct, opts)); + zip.file('_rels/.rels', write_rels(opts.rels)); + zip.file('xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels)); + + delete opts.revssf; delete opts.ssf; + return zip; + } + function firstbyte(f,o) { + var x = ""; + switch((o||{}).type || "base64") { + case 'buffer': return [f[0], f[1], f[2], f[3]]; + case 'base64': x = Base64.decode(f.slice(0,24)); break; + case 'binary': x = f; break; + case 'array': return [f[0], f[1], f[2], f[3]]; + default: throw new Error("Unrecognized type " + (o && o.type || "undefined")); + } + return [x.charCodeAt(0), x.charCodeAt(1), x.charCodeAt(2), x.charCodeAt(3)]; + } + + function read_cfb(cfb, opts) { + if(CFB.find(cfb, "EncryptedPackage")) return parse_xlsxcfb(cfb, opts); + return parse_xlscfb(cfb, opts); + } + + function read_zip(data, opts) { + var zip, d = data; + var o = opts||{}; + if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64"; + switch(o.type) { + case "base64": zip = new jszip(d, { base64:true }); break; + case "binary": case "array": zip = new jszip(d, { base64:false }); break; + case "buffer": zip = new jszip(d); break; + default: throw new Error("Unrecognized type " + o.type); + } + return parse_zip(zip, o); + } + + function read_plaintext(data, o) { + var i = 0; + main: while(i < data.length) switch(data.charCodeAt(i)) { + case 0x0A: case 0x0D: case 0x20: ++i; break; + case 0x3C: return parse_xlml(data.slice(i),o); + default: break main; + } + return PRN.to_workbook(data, o); + } + + function read_plaintext_raw(data, o) { + var str = "", bytes = firstbyte(data, o); + switch(o.type) { + case 'base64': str = Base64.decode(data); break; + case 'binary': str = data; break; + case 'buffer': str = data.toString('binary'); break; + case 'array': str = cc2str(data); break; + default: throw new Error("Unrecognized type " + o.type); + } + if(bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) str = utf8read(str); + return read_plaintext(str, o); + } + + function read_utf16(data, o) { + var d = data; + if(o.type == 'base64') d = Base64.decode(d); + d = cptable.utils.decode(1200, d.slice(2), 'str'); + o.type = "binary"; + return read_plaintext(d, o); + } + + function bstrify(data) { + return !data.match(/[^\x00-\x7F]/) ? data : utf8write(data); + } + + function read_prn(data, d, o, str) { + if(str) { o.type = "string"; return PRN.to_workbook(data, o); } + return PRN.to_workbook(d, o); + } + + function readSync(data, opts) { + reset_cp(); + if(typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer) return readSync(new Uint8Array(data), opts); + var d = data, n = [0,0,0,0], str = false; + var o = opts||{}; + _ssfopts = {}; + if(o.dateNF) _ssfopts.dateNF = o.dateNF; + if(!o.type) o.type = (has_buf && Buffer.isBuffer(data)) ? "buffer" : "base64"; + if(o.type == "file") { o.type = has_buf ? "buffer" : "binary"; d = read_binary(data); } + if(o.type == "string") { str = true; o.type = "binary"; o.codepage = 65001; d = bstrify(data); } + if(o.type == 'array' && typeof Uint8Array !== 'undefined' && data instanceof Uint8Array && typeof ArrayBuffer !== 'undefined') { + // $FlowIgnore + var ab=new ArrayBuffer(3), vu=new Uint8Array(ab); vu.foo="bar"; + // $FlowIgnore + if(!vu.foo) {o=dup(o); o.type='array'; return readSync(ab2a(d), o);} + } + switch((n = firstbyte(d, o))[0]) { + case 0xD0: return read_cfb(CFB.read(d, o), o); + case 0x09: return parse_xlscfb(d, o); + case 0x3C: return parse_xlml(d, o); + case 0x49: if(n[1] === 0x44) return read_wb_ID(d, o); break; + case 0x54: if(n[1] === 0x41 && n[2] === 0x42 && n[3] === 0x4C) return DIF.to_workbook(d, o); break; + case 0x50: return (n[1] === 0x4B && n[2] < 0x09 && n[3] < 0x09) ? read_zip(d, o) : read_prn(data, d, o, str); + case 0xEF: return n[3] === 0x3C ? parse_xlml(d, o) : read_prn(data, d, o, str); + case 0xFF: if(n[1] === 0xFE) { return read_utf16(d, o); } break; + case 0x00: if(n[1] === 0x00 && n[2] >= 0x02 && n[3] === 0x00) return WK_.to_workbook(d, o); break; + case 0x03: case 0x83: case 0x8B: case 0x8C: return DBF.to_workbook(d, o); + case 0x7B: if(n[1] === 0x5C && n[2] === 0x72 && n[3] === 0x74) return RTF.to_workbook(d, o); break; + case 0x0A: case 0x0D: case 0x20: return read_plaintext_raw(d, o); + } + if(n[2] <= 12 && n[3] <= 31) return DBF.to_workbook(d, o); + return read_prn(data, d, o, str); + } + + function readFileSync(filename, opts) { + var o = opts||{}; o.type = 'file'; + return readSync(filename, o); + } + function write_cfb_ctr(cfb, o) { + switch(o.type) { + case "base64": case "binary": break; + case "buffer": case "array": o.type = ""; break; + case "file": return write_dl(o.file, CFB.write(cfb, {type:has_buf ? 'buffer' : ""})); + case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files"); + default: throw new Error("Unrecognized type " + o.type); + } + return CFB.write(cfb, o); + } + + /*global encrypt_agile */ + function write_zip_type(wb, opts) { + var o = opts||{}; + style_builder = new StyleBuilder(opts); + var z = write_zip(wb, o); + var oopts = {}; + if(o.compression) oopts.compression = 'DEFLATE'; + if(o.password) oopts.type = has_buf ? "nodebuffer" : "string"; + else switch(o.type) { + case "base64": oopts.type = "base64"; break; + case "binary": oopts.type = "string"; break; + case "string": throw new Error("'string' output type invalid for '" + o.bookType + "' files"); + case "buffer": + case "file": oopts.type = has_buf ? "nodebuffer" : "string"; break; + default: throw new Error("Unrecognized type " + o.type); + } + var out = z.generate(oopts); + if(o.password && typeof encrypt_agile !== 'undefined') return write_cfb_ctr(encrypt_agile(out, o.password), o); + if(o.type === "file") return write_dl(o.file, out); + return o.type == "string" ? utf8read(out) : out; + } + + function write_cfb_type(wb, opts) { + var o = opts||{}; + var cfb = write_xlscfb(wb, o); + return write_cfb_ctr(cfb, o); + } + + function write_string_type(out, opts, bom) { + if(!bom) bom = ""; + var o = bom + out; + switch(opts.type) { + case "base64": return Base64.encode(utf8write(o)); + case "binary": return utf8write(o); + case "string": return out; + case "file": return write_dl(opts.file, o, 'utf8'); + case "buffer": { + // $FlowIgnore + if(has_buf) return Buffer_from(o, 'utf8'); + else return write_string_type(o, {type:'binary'}).split("").map(function(c) { return c.charCodeAt(0); }); + } + } + throw new Error("Unrecognized type " + opts.type); + } + + function write_stxt_type(out, opts) { + switch(opts.type) { + case "base64": return Base64.encode(out); + case "binary": return out; + case "string": return out; /* override in sheet_to_txt */ + case "file": return write_dl(opts.file, out, 'binary'); + case "buffer": { + // $FlowIgnore + if(has_buf) return Buffer_from(out, 'binary'); + else return out.split("").map(function(c) { return c.charCodeAt(0); }); + } + } + throw new Error("Unrecognized type " + opts.type); + } + + /* TODO: test consistency */ + function write_binary_type(out, opts) { + switch(opts.type) { + case "string": + case "base64": + case "binary": + var bstr = ""; + // $FlowIgnore + for(var i = 0; i < out.length; ++i) bstr += String.fromCharCode(out[i]); + return opts.type == 'base64' ? Base64.encode(bstr) : opts.type == 'string' ? utf8read(bstr) : bstr; + case "file": return write_dl(opts.file, out); + case "buffer": return out; + default: throw new Error("Unrecognized type " + opts.type); + } + } + + function writeSync(wb, opts) { + check_wb(wb); + var o = opts||{}; + if(o.type == "array") { o.type = "binary"; var out = (writeSync(wb, o)); o.type = "array"; return s2ab(out); } + switch(o.bookType || 'xlsb') { + case 'xml': + case 'xlml': return write_string_type(write_xlml(wb, o), o); + case 'slk': + case 'sylk': return write_string_type(write_slk_str(wb, o), o); + case 'htm': + case 'html': return write_string_type(write_htm_str(wb, o), o); + case 'txt': return write_stxt_type(write_txt_str(wb, o), o); + case 'csv': return write_string_type(write_csv_str(wb, o), o, "\ufeff"); + case 'dif': return write_string_type(write_dif_str(wb, o), o); + case 'dbf': return write_binary_type(write_dbf_buf(wb, o), o); + case 'prn': return write_string_type(write_prn_str(wb, o), o); + case 'rtf': return write_string_type(write_rtf_str(wb, o), o); + case 'eth': return write_string_type(write_eth_str(wb, o), o); + case 'fods': return write_string_type(write_ods(wb, o), o); + case 'biff2': if(!o.biff) o.biff = 2; /* falls through */ + case 'biff3': if(!o.biff) o.biff = 3; /* falls through */ + case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o); + case 'biff5': if(!o.biff) o.biff = 5; /* falls through */ + case 'biff8': + case 'xla': + case 'xls': if(!o.biff) o.biff = 8; return write_cfb_type(wb, o); + case 'xlsx': + case 'xlsm': + case 'xlam': + case 'xlsb': + case 'ods': return write_zip_type(wb, o); + default: throw new Error ("Unrecognized bookType |" + o.bookType + "|"); + } + } + + function resolve_book_type(o) { + if(o.bookType) return; + var _BT = { + "xls": "biff8", + "htm": "html", + "slk": "sylk", + "socialcalc": "eth", + "Sh33tJS": "WTF" + }; + var ext = o.file.slice(o.file.lastIndexOf(".")).toLowerCase(); + if(ext.match(/^\.[a-z]+$/)) o.bookType = ext.slice(1); + o.bookType = _BT[o.bookType] || o.bookType; + } + + function writeFileSync(wb, filename, opts) { + var o = opts||{}; o.type = 'file'; + o.file = filename; + resolve_book_type(o); + return writeSync(wb, o); + } + + function writeFileAsync(filename, wb, opts, cb) { + var o = opts||{}; o.type = 'file'; + o.file = filename; + resolve_book_type(o); + o.type = 'buffer'; + var _cb = cb; if(!(_cb instanceof Function)) _cb = (opts); + return _fs.writeFile(filename, writeSync(wb, o), _cb); + } + function make_json_row(sheet, r, R, cols, header, hdr, dense, o) { + var rr = encode_row(R); + var defval = o.defval, raw = o.raw || !o.hasOwnProperty("raw"); + var isempty = true; + var row = (header === 1) ? [] : {}; + if(header !== 1) { + if(Object.defineProperty) try { Object.defineProperty(row, '__rowNum__', {value:R, enumerable:false}); } catch(e) { row.__rowNum__ = R; } + else row.__rowNum__ = R; + } + if(!dense || sheet[R]) for (var C = r.s.c; C <= r.e.c; ++C) { + var val = dense ? sheet[R][C] : sheet[cols[C] + rr]; + if(val === undefined || val.t === undefined) { + if(defval === undefined) continue; + if(hdr[C] != null) { row[hdr[C]] = defval; } + continue; + } + var v = val.v; + switch(val.t){ + case 'z': if(v == null) break; continue; + case 'e': v = void 0; break; + case 's': case 'd': case 'b': case 'n': break; + default: throw new Error('unrecognized type ' + val.t); + } + if(hdr[C] != null) { + if(v == null) { + if(defval !== undefined) row[hdr[C]] = defval; + else if(raw && v === null) row[hdr[C]] = null; + else continue; + } else { + row[hdr[C]] = raw ? v : format_cell(val,v,o); + } + if(v != null) isempty = false; + } + } + return { row: row, isempty: isempty }; + } + + + function sheet_to_json(sheet, opts) { + if(sheet == null || sheet["!ref"] == null) return []; + var val = {t:'n',v:0}, header = 0, offset = 1, hdr = [], v=0, vv=""; + var r = {s:{r:0,c:0},e:{r:0,c:0}}; + var o = opts || {}; + var range = o.range != null ? o.range : sheet["!ref"]; + if(o.header === 1) header = 1; + else if(o.header === "A") header = 2; + else if(Array.isArray(o.header)) header = 3; + switch(typeof range) { + case 'string': r = safe_decode_range(range); break; + case 'number': r = safe_decode_range(sheet["!ref"]); r.s.r = range; break; + default: r = range; + } + if(header > 0) offset = 0; + var rr = encode_row(r.s.r); + var cols = []; + var out = []; + var outi = 0, counter = 0; + var dense = Array.isArray(sheet); + var R = r.s.r, C = 0, CC = 0; + if(dense && !sheet[R]) sheet[R] = []; + for(C = r.s.c; C <= r.e.c; ++C) { + cols[C] = encode_col(C); + val = dense ? sheet[R][C] : sheet[cols[C] + rr]; + switch(header) { + case 1: hdr[C] = C - r.s.c; break; + case 2: hdr[C] = cols[C]; break; + case 3: hdr[C] = o.header[C - r.s.c]; break; + default: + if(val == null) val = {w: "__EMPTY", t: "s"}; + vv = v = format_cell(val, null, o); + counter = 0; + for(CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter); + hdr[C] = vv; + } + } + for (R = r.s.r + offset; R <= r.e.r; ++R) { + var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o); + if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) out[outi++] = row.row; + } + out.length = outi; + return out; + } + + var qreg = /"/g; + function make_csv_row(sheet, r, R, cols, fs, rs, FS, o) { + var isempty = true; + var row = [], txt = "", rr = encode_row(R); + for(var C = r.s.c; C <= r.e.c; ++C) { + if (!cols[C]) continue; + var val = o.dense ? (sheet[R]||[])[C]: sheet[cols[C] + rr]; + if(val == null) txt = ""; + else if(val.v != null) { + isempty = false; + txt = ''+format_cell(val, null, o); + for(var i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {txt = "\"" + txt.replace(qreg, '""') + "\""; break; } + if(txt == "ID") txt = '"ID"'; + } else if(val.f != null && !val.F) { + isempty = false; + txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"'; + } else txt = ""; + /* NOTE: Excel CSV does not support array formulae */ + row.push(txt); + } + if(o.blankrows === false && isempty) return null; + return row.join(FS); + } + + function sheet_to_csv(sheet, opts) { + var out = []; + var o = opts == null ? {} : opts; + if(sheet == null || sheet["!ref"] == null) return ""; + var r = safe_decode_range(sheet["!ref"]); + var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0); + var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0); + var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$"); + var row = "", cols = []; + o.dense = Array.isArray(sheet); + var colinfo = o.skipHidden && sheet["!cols"] || []; + var rowinfo = o.skipHidden && sheet["!rows"] || []; + for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C); + for(var R = r.s.r; R <= r.e.r; ++R) { + if ((rowinfo[R]||{}).hidden) continue; + row = make_csv_row(sheet, r, R, cols, fs, rs, FS, o); + if(row == null) { continue; } + if(o.strip) row = row.replace(endregex,""); + out.push(row + RS); + } + delete o.dense; + return out.join(""); + } + + function sheet_to_txt(sheet, opts) { + if(!opts) opts = {}; opts.FS = "\t"; opts.RS = "\n"; + var s = sheet_to_csv(sheet, opts); + if(typeof cptable == 'undefined' || opts.type == 'string') return s; + var o = cptable.utils.encode(1200, s, 'str'); + return String.fromCharCode(255) + String.fromCharCode(254) + o; + } + + function sheet_to_formulae(sheet) { + var y = "", x, val=""; + if(sheet == null || sheet["!ref"] == null) return []; + var r = safe_decode_range(sheet['!ref']), rr = "", cols = [], C; + var cmds = []; + var dense = Array.isArray(sheet); + for(C = r.s.c; C <= r.e.c; ++C) cols[C] = encode_col(C); + for(var R = r.s.r; R <= r.e.r; ++R) { + rr = encode_row(R); + for(C = r.s.c; C <= r.e.c; ++C) { + y = cols[C] + rr; + x = dense ? (sheet[R]||[])[C] : sheet[y]; + val = ""; + if(x === undefined) continue; + else if(x.F != null) { + y = x.F; + if(!x.f) continue; + val = x.f; + if(y.indexOf(":") == -1) y = y + ":" + y; + } + if(x.f != null) val = x.f; + else if(x.t == 'z') continue; + else if(x.t == 'n' && x.v != null) val = "" + x.v; + else if(x.t == 'b') val = x.v ? "TRUE" : "FALSE"; + else if(x.w !== undefined) val = "'" + x.w; + else if(x.v === undefined) continue; + else if(x.t == 's') val = "'" + x.v; + else val = ""+x.v; + cmds[cmds.length] = y + "=" + val; + } + } + return cmds; + } + + function sheet_add_json(_ws, js, opts) { + var o = opts || {}; + var offset = +!o.skipHeader; + var ws = _ws || ({}); + var _R = 0, _C = 0; + if(ws && o.origin != null) { + if(typeof o.origin == 'number') _R = o.origin; + else { + var _origin = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin; + _R = _origin.r; _C = _origin.c; + } + } + var cell; + var range = ({s: {c:0, r:0}, e: {c:_C, r:_R + js.length - 1 + offset}}); + if(ws['!ref']) { + var _range = safe_decode_range(ws['!ref']); + range.e.c = Math.max(range.e.c, _range.e.c); + range.e.r = Math.max(range.e.r, _range.e.r); + if(_R == -1) { _R = range.e.r + 1; range.e.r = _R + js.length - 1 + offset; } + } + var hdr = o.header || [], C = 0; + + js.forEach(function (JS, R) { + keys(JS).forEach(function(k) { + if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k; + var v = JS[k]; + var t = 'z'; + var z = ""; + if(v && typeof v === 'object' && !(v instanceof Date)){ + ws[encode_cell({c:_C + C,r:_R + R + offset})] = v; + } else { + if(typeof v == 'number') t = 'n'; + else if(typeof v == 'boolean') t = 'b'; + else if(typeof v == 'string') t = 's'; + else if(v instanceof Date) { + t = 'd'; + if(!o.cellDates) { t = 'n'; v = datenum(v); } + z = o.dateNF || SSF._table[14]; + } + ws[encode_cell({c:_C + C,r:_R + R + offset})] = cell = ({t:t, v:v}); + if(z) cell.z = z; + } + }); + }); + range.e.c = Math.max(range.e.c, _C + hdr.length - 1); + var __R = encode_row(_R); + if(offset) for(C = 0; C < hdr.length; ++C) ws[encode_col(C + _C) + __R] = {t:'s', v:hdr[C]}; + ws['!ref'] = encode_range(range); + return ws; + } + function json_to_sheet(js, opts) { return sheet_add_json(null, js, opts); } + + var utils = { + encode_col: encode_col, + encode_row: encode_row, + encode_cell: encode_cell, + encode_range: encode_range, + decode_col: decode_col, + decode_row: decode_row, + split_cell: split_cell, + decode_cell: decode_cell, + decode_range: decode_range, + format_cell: format_cell, + get_formulae: sheet_to_formulae, + make_csv: sheet_to_csv, + make_json: sheet_to_json, + make_formulae: sheet_to_formulae, + sheet_add_aoa: sheet_add_aoa, + sheet_add_json: sheet_add_json, + aoa_to_sheet: aoa_to_sheet, + json_to_sheet: json_to_sheet, + table_to_sheet: parse_dom_table, + table_to_book: table_to_book, + sheet_to_csv: sheet_to_csv, + sheet_to_txt: sheet_to_txt, + sheet_to_json: sheet_to_json, + sheet_to_html: HTML_.from_sheet, + sheet_to_dif: DIF.from_sheet, + sheet_to_slk: SYLK.from_sheet, + sheet_to_eth: ETH.from_sheet, + sheet_to_formulae: sheet_to_formulae, + sheet_to_row_object_array: sheet_to_json + }; + + (function(utils) { + utils.consts = utils.consts || {}; + function add_consts(R/*Array*/) { R.forEach(function(a){ utils.consts[a[0]] = a[1]; }); } + + function get_default(x, y, z) { return x[y] != null ? x[y] : (x[y] = z); } + + /* get cell, creating a stub if necessary */ + function ws_get_cell_stub(ws, R, C) { + /* A1 cell address */ + if(typeof R == "string") return ws[R] || (ws[R] = {t:'z'}); + /* cell address object */ + if(typeof R != "number") return ws_get_cell_stub(ws, encode_cell(R)); + /* R and C are 0-based indices */ + return ws_get_cell_stub(ws, encode_cell({r:R,c:C||0})); + } + + /* find sheet index for given name / validate index */ + function wb_sheet_idx(wb, sh) { + if(typeof sh == "number") { + if(sh >= 0 && wb.SheetNames.length > sh) return sh; + throw new Error("Cannot find sheet # " + sh); + } else if(typeof sh == "string") { + var idx = wb.SheetNames.indexOf(sh); + if(idx > -1) return idx; + throw new Error("Cannot find sheet name |" + sh + "|"); + } else throw new Error("Cannot find sheet |" + sh + "|"); + } + + /* simple blank workbook object */ + utils.book_new = function() { + return { SheetNames: [], Sheets: {} }; + }; + + /* add a worksheet to the end of a given workbook */ + utils.book_append_sheet = function(wb, ws, name) { + if(!name) for(var i = 1; i <= 0xFFFF; ++i) if(wb.SheetNames.indexOf(name = "Sheet" + i) == -1) break; + if(!name) throw new Error("Too many worksheets"); + check_ws_name(name); + if(wb.SheetNames.indexOf(name) >= 0) throw new Error("Worksheet with name |" + name + "| already exists!"); + + wb.SheetNames.push(name); + wb.Sheets[name] = ws; + }; + + /* set sheet visibility (visible/hidden/very hidden) */ + utils.book_set_sheet_visibility = function(wb, sh, vis) { + get_default(wb,"Workbook",{}); + get_default(wb.Workbook,"Sheets",[]); + + var idx = wb_sheet_idx(wb, sh); + // $FlowIgnore + get_default(wb.Workbook.Sheets,idx, {}); + + switch(vis) { + case 0: case 1: case 2: break; + default: throw new Error("Bad sheet visibility setting " + vis); + } + // $FlowIgnore + wb.Workbook.Sheets[idx].Hidden = vis; + }; + add_consts([ + ["SHEET_VISIBLE", 0], + ["SHEET_HIDDEN", 1], + ["SHEET_VERY_HIDDEN", 2] + ]); + + /* set number format */ + utils.cell_set_number_format = function(cell, fmt) { + cell.z = fmt; + return cell; + }; + + /* set cell hyperlink */ + utils.cell_set_hyperlink = function(cell, target, tooltip) { + if(!target) { + delete cell.l; + } else { + cell.l = ({ Target: target }); + if(tooltip) cell.l.Tooltip = tooltip; + } + return cell; + }; + utils.cell_set_internal_link = function(cell, range, tooltip) { return utils.cell_set_hyperlink(cell, "#" + range, tooltip); }; + + /* add to cell comments */ + utils.cell_add_comment = function(cell, text, author) { + if(!cell.c) cell.c = []; + cell.c.push({t:text, a:author||"SheetJS"}); + }; + + /* set array formula and flush related cells */ + utils.sheet_set_array_formula = function(ws, range, formula) { + var rng = typeof range != "string" ? range : safe_decode_range(range); + var rngstr = typeof range == "string" ? range : encode_range(range); + for(var R = rng.s.r; R <= rng.e.r; ++R) for(var C = rng.s.c; C <= rng.e.c; ++C) { + var cell = ws_get_cell_stub(ws, R, C); + cell.t = 'n'; + cell.F = rngstr; + delete cell.v; + if(R == rng.s.r && C == rng.s.c) cell.f = formula; + } + return ws; + }; + + return utils; + })(utils); + + if(has_buf && typeof require != 'undefined') (function() { + var Readable = {}.Readable; + + var write_csv_stream = function(sheet, opts) { + var stream = Readable(); + var o = opts == null ? {} : opts; + if(sheet == null || sheet["!ref"] == null) { stream.push(null); return stream; } + var r = safe_decode_range(sheet["!ref"]); + var FS = o.FS !== undefined ? o.FS : ",", fs = FS.charCodeAt(0); + var RS = o.RS !== undefined ? o.RS : "\n", rs = RS.charCodeAt(0); + var endregex = new RegExp((FS=="|" ? "\\|" : FS)+"+$"); + var row = "", cols = []; + o.dense = Array.isArray(sheet); + var colinfo = o.skipHidden && sheet["!cols"] || []; + var rowinfo = o.skipHidden && sheet["!rows"] || []; + for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C); + var R = r.s.r; + var BOM = false; + stream._read = function() { + if(!BOM) { BOM = true; return stream.push("\uFEFF"); } + if(R > r.e.r) return stream.push(null); + while(R <= r.e.r) { + ++R; + if ((rowinfo[R-1]||{}).hidden) continue; + row = make_csv_row(sheet, r, R-1, cols, fs, rs, FS, o); + if(row != null) { + if(o.strip) row = row.replace(endregex,""); + stream.push(row + RS); + break; + } + } + }; + return stream; + }; + + var write_html_stream = function(ws, opts) { + var stream = Readable(); + + var o = opts || {}; + var header = o.header != null ? o.header : HTML_.BEGIN; + var footer = o.footer != null ? o.footer : HTML_.END; + stream.push(header); + var r = decode_range(ws['!ref']); + o.dense = Array.isArray(ws); + stream.push(HTML_._preamble(ws, r, o)); + var R = r.s.r; + var end = false; + stream._read = function() { + if(R > r.e.r) { + if(!end) { end = true; stream.push("" + footer); } + return stream.push(null); + } + while(R <= r.e.r) { + stream.push(HTML_._row(ws, r, R, o)); + ++R; + break; + } + }; + return stream; + }; + + var write_json_stream = function(sheet, opts) { + var stream = Readable({objectMode:true}); + + if(sheet == null || sheet["!ref"] == null) { stream.push(null); return stream; } + var val = {t:'n',v:0}, header = 0, offset = 1, hdr = [], v=0, vv=""; + var r = {s:{r:0,c:0},e:{r:0,c:0}}; + var o = opts || {}; + var range = o.range != null ? o.range : sheet["!ref"]; + if(o.header === 1) header = 1; + else if(o.header === "A") header = 2; + else if(Array.isArray(o.header)) header = 3; + switch(typeof range) { + case 'string': r = safe_decode_range(range); break; + case 'number': r = safe_decode_range(sheet["!ref"]); r.s.r = range; break; + default: r = range; + } + if(header > 0) offset = 0; + var rr = encode_row(r.s.r); + var cols = []; + var counter = 0; + var dense = Array.isArray(sheet); + var R = r.s.r, C = 0, CC = 0; + if(dense && !sheet[R]) sheet[R] = []; + for(C = r.s.c; C <= r.e.c; ++C) { + cols[C] = encode_col(C); + val = dense ? sheet[R][C] : sheet[cols[C] + rr]; + switch(header) { + case 1: hdr[C] = C - r.s.c; break; + case 2: hdr[C] = cols[C]; break; + case 3: hdr[C] = o.header[C - r.s.c]; break; + default: + if(val == null) val = {w: "__EMPTY", t: "s"}; + vv = v = format_cell(val, null, o); + counter = 0; + for(CC = 0; CC < hdr.length; ++CC) if(hdr[CC] == vv) vv = v + "_" + (++counter); + hdr[C] = vv; + } + } + R = r.s.r + offset; + stream._read = function() { + if(R > r.e.r) return stream.push(null); + while(R <= r.e.r) { + //if ((rowinfo[R-1]||{}).hidden) continue; + var row = make_json_row(sheet, r, R, cols, header, hdr, dense, o); + ++R; + if((row.isempty === false) || (header === 1 ? o.blankrows !== false : !!o.blankrows)) { + stream.push(row.row); + break; + } + } + }; + return stream; + }; + + XLSX.stream = { + to_json: write_json_stream, + to_html: write_html_stream, + to_csv: write_csv_stream + }; + })(); + /** + * 样式魔改区 -- start + */ + ///////////////////////////////////////////////////////////////////////////////////////////////////// + var XmlNode = (function () { + function XmlNode(tagName, attributes, children) { + + if (!(this instanceof XmlNode)) { + return new XmlNode(tagName, attributes, children); + } + this.tagName = tagName; + this._attributes = attributes || {}; + this._children = children || []; + this._prefix = ''; + return this; + } + + XmlNode.prototype.createElement = function () { + return new XmlNode(arguments) + } + + XmlNode.prototype.children = function() { + return this._children; + } + + XmlNode.prototype.append = function (node) { + this._children.push(node); + return this; + } + + XmlNode.prototype.prefix = function (prefix) { + if (arguments.length==0) { return this._prefix;} + this._prefix = prefix; + return this; + } + + XmlNode.prototype.attr = function (attr, value) { + if (value == undefined) { + delete this._attributes[attr]; + return this; + } + if (arguments.length == 0) { + return this._attributes; + } + else if (typeof attr == 'string' && arguments.length == 1) { + return this._attributes.attr[attr]; + } + if (typeof attr == 'object' && arguments.length == 1) { + for (var key in attr) { + this._attributes[key] = attr[key]; + } + } + else if (arguments.length == 2 && typeof attr == 'string') { + this._attributes[attr] = value; + } + return this; + } + + var APOS = "'"; QUOTE = '"' + var ESCAPED_QUOTE = { } + ESCAPED_QUOTE[QUOTE] = '"' + ESCAPED_QUOTE[APOS] = ''' + + XmlNode.prototype.escapeAttributeValue = function(att_value) { + return '"' + att_value.replace(/\"/g,'"') + '"';// TODO Extend with four other codes + + } + + XmlNode.prototype.toXml = function (node) { + if (!node) node = this; + var xml = node._prefix; + xml += '<' + node.tagName; + if (node._attributes) { + for (var key in node._attributes) { + xml += ' ' + key + '=' + this.escapeAttributeValue(''+node._attributes[key]) + '' + } + } + if (node._children && node._children.length > 0) { + xml += ">"; + for (var i = 0; i < node._children.length; i++) { + xml += this.toXml(node._children[i]); + } + xml += ''; + } + else { + xml += '/>'; + } + return xml; + } + return XmlNode; + })(); + ///////////////////////////////////////////////////////////////////////////////////////////////////// + var StyleBuilder = function (options) { + + var customNumFmtId = 164; + + + + var table_fmt = { + 0: 'General', + 1: '0', + 2: '0.00', + 3: '#,##0', + 4: '#,##0.00', + 9: '0%', + 10: '0.00%', + 11: '0.00E+00', + 12: '# ?/?', + 13: '# ??/??', + 14: 'm/d/yy', + 15: 'd-mmm-yy', + 16: 'd-mmm', + 17: 'mmm-yy', + 18: 'h:mm AM/PM', + 19: 'h:mm:ss AM/PM', + 20: 'h:mm', + 21: 'h:mm:ss', + 22: 'm/d/yy h:mm', + 37: '#,##0 ;(#,##0)', + 38: '#,##0 ;[Red](#,##0)', + 39: '#,##0.00;(#,##0.00)', + 40: '#,##0.00;[Red](#,##0.00)', + 45: 'mm:ss', + 46: '[h]:mm:ss', + 47: 'mmss.0', + 48: '##0.0E+0', + 49: '@', + 56: '"上午/下午 "hh"時"mm"分"ss"秒 "' }; + var fmt_table = {}; + + for (var idx in table_fmt) { + fmt_table[table_fmt[idx]] = idx; + } + + + // cache style specs to avoid excessive duplication + _hashIndex = {}; + _listIndex = []; + + return { + + initialize: function (options) { + + this.$fonts = XmlNode('fonts').attr('count',0).attr("x14ac:knownFonts","1"); + this.$fills = XmlNode('fills').attr('count',0); + this.$borders = XmlNode('borders').attr('count',0); + this.$numFmts = XmlNode('numFmts').attr('count',0); + this.$cellStyleXfs = XmlNode('cellStyleXfs'); + this.$xf = XmlNode('xf') + .attr('numFmtId', 0) + .attr('fontId', 0) + .attr('fillId', 0) + .attr('borderId', 0); + + this.$cellXfs = XmlNode('cellXfs').attr('count',0); + this.$cellStyles = XmlNode('cellStyles') + .append(XmlNode('cellStyle') + .attr('name', 'Normal') + .attr('xfId',0) + .attr('builtinId',0) + ); + this.$dxfs = XmlNode('dxfs').attr('count', "0"); + this.$tableStyles = XmlNode('tableStyles') + .attr('count','0') + .attr('defaultTableStyle','TableStyleMedium9') + .attr('defaultPivotStyle','PivotStyleMedium4') + + + this.$styles = XmlNode('styleSheet') + .attr('xmlns:mc','http://schemas.openxmlformats.org/markup-compatibility/2006') + .attr('xmlns:x14ac','http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac') + .attr('xmlns','http://schemas.openxmlformats.org/spreadsheetml/2006/main') + .attr('mc:Ignorable','x14ac') + .prefix('') + .append(this.$numFmts) + .append(this.$fonts) + .append(this.$fills) + .append(this.$borders) + .append(this.$cellStyleXfs.append(this.$xf)) + .append(this.$cellXfs) + .append(this.$cellStyles) + .append(this.$dxfs) + .append(this.$tableStyles); + + + // need to specify styles at index 0 and 1. + // the second style MUST be gray125 for some reason + + var defaultStyle = options.defaultCellStyle || {}; + if (!defaultStyle.font) defaultStyle.font = {name: 'Calibri', sz: '12'}; + if (!defaultStyle.font.name) defaultStyle.font.name = 'Calibri'; + if (!defaultStyle.font.sz) defaultStyle.font.sz = 11; + if (!defaultStyle.fill) defaultStyle.fill = { patternType: "none", fgColor: {}}; + if (!defaultStyle.border) defaultStyle.border = {}; + if (!defaultStyle.numFmt) defaultStyle.numFmt = 0; + + this.defaultStyle = defaultStyle; + + var gray125Style = JSON.parse(JSON.stringify(defaultStyle)); + gray125Style.fill = {patternType: "gray125", fgColor: { }} + + this.addStyles([defaultStyle, gray125Style]); + return this; + }, + + // create a style entry and returns an integer index that can be used in the cell .s property + // these format of this object follows the emerging Common Spreadsheet Format + addStyle: function (attributes) { + + var hashKey = JSON.stringify(attributes); + var index = _hashIndex[hashKey]; + if (index == undefined) { + + index = this._addXf(attributes); //_listIndex.push(attributes) -1; + _hashIndex[hashKey] = index; + } + else { + index = _hashIndex[hashKey]; + } + return index; + }, + + // create style entries and returns array of integer indexes that can be used in cell .s property + addStyles: function (styles) { + var self = this; + return styles.map(function (style) { + return self.addStyle(style); + }) + }, + + _duckTypeStyle: function(attributes) { + + if (typeof attributes == 'object' && (attributes.patternFill || attributes.fgColor)) { + return {fill: attributes }; // this must be read via XLSX.parseFile(...) + } + else if (attributes.font || attributes.numFmt || attributes.border || attributes.fill) { + return attributes; + } + else { + return this._getStyleCSS(attributes) + } + }, + + _getStyleCSS: function(css) { + return css; //TODO + }, + + // Create an record for the style as well as corresponding , , , + // Right now this is simple and creates a , , , for every + // We could perhaps get fancier and avoid duplicating auxiliary entries as Excel presumably intended, but bother. + _addXf: function (attributes) { + + + var fontId = this._addFont(attributes.font); + var fillId = this._addFill(attributes.fill); + var borderId = this._addBorder(attributes.border); + var numFmtId = this._addNumFmt(attributes.numFmt); + + var $xf = XmlNode('xf') + .attr("numFmtId", numFmtId) + .attr("fontId", fontId) + .attr("fillId", fillId) + .attr("borderId", borderId) + .attr("xfId", "0"); + + if (fontId > 0) { + $xf.attr('applyFont', "1"); + } + if (fillId > 0) { + $xf.attr('applyFill', "1"); + } + if (borderId > 0) { + $xf.attr('applyBorder', "1"); + } + if (numFmtId > 0) { + $xf.attr('applyNumberFormat', "1"); + } + + if (attributes.alignment) { + var $alignment = XmlNode('alignment'); + if (attributes.alignment.horizontal) { $alignment.attr('horizontal', attributes.alignment.horizontal);} + if (attributes.alignment.vertical) { $alignment.attr('vertical', attributes.alignment.vertical);} + if (attributes.alignment.indent) { $alignment.attr('indent', attributes.alignment.indent);} + if (attributes.alignment.readingOrder) { $alignment.attr('readingOrder', attributes.alignment.readingOrder);} + if (attributes.alignment.wrapText) { $alignment.attr('wrapText', attributes.alignment.wrapText);} + if (attributes.alignment.textRotation!=undefined) { $alignment.attr('textRotation', attributes.alignment.textRotation);} + + $xf.append($alignment).attr('applyAlignment',1) + + } + this.$cellXfs.append($xf); + var count = +this.$cellXfs.children().length; + + this.$cellXfs.attr('count', count); + return count - 1; + }, + + _addFont: function (attributes) { + + if (!attributes) { return 0; } + + var $font = XmlNode('font') + .append(XmlNode('sz').attr('val', attributes.sz || this.defaultStyle.font.sz)) + .append(XmlNode('name').attr('val', attributes.name || this.defaultStyle.font.name)) + + if (attributes.bold) $font.append(XmlNode('b')); + if (attributes.underline) $font.append(XmlNode('u')); + if (attributes.italic) $font.append(XmlNode('i')); + if (attributes.strike) $font.append(XmlNode('strike')); + if (attributes.outline) $font.append(XmlNode('outline')); + if (attributes.shadow) $font.append(XmlNode('shadow')); + + if (attributes.vertAlign) { + $font.append(XmlNode('vertAlign').attr('val', attributes.vertAlign)) + } + + + if (attributes.color) { + if (attributes.color.theme) { + $font.append(XmlNode('color').attr('theme', attributes.color.theme)) + + if (attributes.color.tint) { //tint only if theme + $font.append(XmlNode('tint').attr('theme', attributes.color.tint)) + } + + } else if (attributes.color.rgb) { // not both rgb and theme + $font.append(XmlNode('color').attr('rgb', attributes.color.rgb)) + } + } + + this.$fonts.append($font); + + var count = this.$fonts.children().length; + this.$fonts.attr('count', count); + return count - 1; + }, + + _addNumFmt: function (numFmt) { + if (!numFmt) { return 0; } + + if (typeof numFmt == 'string') { + var numFmtIdx = fmt_table[numFmt]; + if (numFmtIdx >= 0) { + return numFmtIdx; // we found a match against built in formats + } + } + + if (/^[0-9]+$/.exec(numFmt)) { + return numFmt; // we're matching an integer against some known code + } + numFmt = numFmt + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + + var $numFmt = XmlNode('numFmt') + .attr('numFmtId', (++customNumFmtId)) + .attr('formatCode', numFmt); + + this.$numFmts.append($numFmt); + + var count = this.$numFmts.children().length; + this.$numFmts.attr('count', count); + return customNumFmtId ; + }, + + _addFill: function (attributes) { + + if (!attributes) { return 0; } + + var $patternFill = XmlNode('patternFill') + .attr('patternType', attributes.patternType || 'solid'); + + if (attributes.fgColor) { + var $fgColor = XmlNode('fgColor'); + + //Excel doesn't like it when we set both rgb and theme+tint, but xlsx.parseFile() sets both + //var $fgColor = createElement('', null, null, {xmlMode: true}).attr(attributes.fgColor) + if (attributes.fgColor.rgb) { + + if (attributes.fgColor.rgb.length == 6) { + attributes.fgColor.rgb = "FF" + attributes.fgColor.rgb /// add alpha to an RGB as Excel expects aRGB + } + + $fgColor.attr('rgb', attributes.fgColor.rgb); + $patternFill.append($fgColor); + } + else if (attributes.fgColor.theme) { + $fgColor.attr('theme', attributes.fgColor.theme); + if (attributes.fgColor.tint) { + $fgColor.attr('tint', attributes.fgColor.tint); + } + $patternFill.append($fgColor); + } + + if (!attributes.bgColor) { + attributes.bgColor = { "indexed": "64"} + } + } + + if (attributes.bgColor) { + var $bgColor = XmlNode('bgColor').attr(attributes.bgColor); + $patternFill.append($bgColor); + } + + var $fill = XmlNode('fill') + .append($patternFill); + + this.$fills.append($fill); + + var count = this.$fills.children().length; + this.$fills.attr('count', count); + return count - 1; + }, + + _getSubBorder: function(direction, spec) { + + var $direction = XmlNode(direction); + if (spec){ + if (spec.style) $direction.attr('style', spec.style); + if (spec.color) { + var $color = XmlNode('color'); + if (spec.color.auto) { + $color.attr('auto', spec.color.auto); + } + else if (spec.color.rgb) { + $color.attr('rgb', spec.color.rgb); + } + else if (spec.color.theme || spec.color.tint) { + $color.attr('theme', spec.color.theme || "1"); + $color.attr('tint', spec.color.tint || "0"); + } + $direction.append($color) + } + } + return $direction; + }, + + _addBorder: function (attributes) { + if (!attributes) { return 0; } + + var self = this; + + var $border = XmlNode('border') + .attr("diagonalUp",attributes.diagonalUp) + .attr("diagonalDown",attributes.diagonalDown); + + var directions = ["left","right","top","bottom","diagonal"]; + + directions.forEach(function(direction) { + $border.append(self._getSubBorder(direction, attributes[direction])) + }); + this.$borders.append($border); + + var count = this.$borders.children().length; + this.$borders.attr('count', count); + return count -1; + }, + + toXml: function () { + return this.$styles.toXml(); + } + }.initialize(options||{}); + } + /** + * 样式魔改区 -- end + */ + + XLSX.parse_xlscfb = parse_xlscfb; + XLSX.parse_ods = parse_ods; + XLSX.parse_fods = parse_fods; + XLSX.write_ods = write_ods; + XLSX.parse_zip = parse_zip; + XLSX.read = readSync; //xlsread + XLSX.readFile = readFileSync; //readFile + XLSX.readFileSync = readFileSync; + XLSX.write = writeSync; + XLSX.writeFile = writeFileSync; + XLSX.writeFileSync = writeFileSync; + XLSX.writeFileAsync = writeFileAsync; + XLSX.utils = utils; + XLSX.SSF = SSF; + XLSX.CFB = CFB; +} +/*global define */ +if(typeof exports !== 'undefined') make_xlsx_lib(exports); +else if(typeof module !== 'undefined' && module.exports) make_xlsx_lib(module.exports); +else if(typeof define === 'function' && define.amd) define('xlsx', function() { if(!XLSX.version) make_xlsx_lib(XLSX); return XLSX; }); +else make_xlsx_lib(XLSX); +/*exported XLS, ODS */ +var XLS = XLSX, ODS = XLSX;/*---------split--------*//* + Copyright (c) 2010, Linden Research, Inc. + Copyright (c) 2014, Joshua Bell + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + $/LicenseInfo$ + */ + +// Original can be found at: +// https://bitbucket.org/lindenlab/llsd +// Modifications by Joshua Bell inexorabletash@gmail.com +// https://github.com/inexorabletash/polyfill + +// ES3/ES5 implementation of the Krhonos Typed Array Specification +// Ref: http://www.khronos.org/registry/typedarray/specs/latest/ +// Date: 2011-02-01 +// +// Variations: +// * Allows typed_array.get/set() as alias for subscripts (typed_array[]) +// * Gradually migrating structure from Khronos spec to ES2015 spec +// +// Caveats: +// * Beyond 10000 or so entries, polyfilled array accessors (ta[0], +// etc) become memory-prohibitive, so array creation will fail. Set +// self.TYPED_ARRAY_POLYFILL_NO_ARRAY_ACCESSORS=true to disable +// creation of accessors. Your code will need to use the +// non-standard get()/set() instead, and will need to add those to +// native arrays for interop. +(function(global) { + 'use strict'; + var undefined = (void 0); // Paranoia + + // Beyond this value, index getters/setters (i.e. array[0], array[1]) are so slow to + // create, and consume so much memory, that the browser appears frozen. + var MAX_ARRAY_LENGTH = 1e5; + + // Approximations of internal ECMAScript conversion functions + function Type(v) { + switch(typeof v) { + case 'undefined': return 'undefined'; + case 'boolean': return 'boolean'; + case 'number': return 'number'; + case 'string': return 'string'; + default: return v === null ? 'null' : 'object'; + } + } + + // Class returns internal [[Class]] property, used to avoid cross-frame instanceof issues: + function Class(v) { return Object.prototype.toString.call(v).replace(/^\[object *|\]$/g, ''); } + function IsCallable(o) { return typeof o === 'function'; } + function ToObject(v) { + if (v === null || v === undefined) throw TypeError(); + return Object(v); + } + function ToInt32(v) { return v >> 0; } + function ToUint32(v) { return v >>> 0; } + + // Snapshot intrinsics + var LN2 = Math.LN2, + abs = Math.abs, + floor = Math.floor, + log = Math.log, + max = Math.max, + min = Math.min, + pow = Math.pow, + round = Math.round; + + // emulate ES5 getter/setter API using legacy APIs + // http://blogs.msdn.com/b/ie/archive/2010/09/07/transitioning-existing-code-to-the-es5-getter-setter-apis.aspx + // (second clause tests for Object.defineProperty() in IE<9 that only supports extending DOM prototypes, but + // note that IE<9 does not support __defineGetter__ or __defineSetter__ so it just renders the method harmless) + + (function() { + var orig = Object.defineProperty; + var dom_only = !(function(){try{return Object.defineProperty({},'x',{});}catch(_){return false;}}()); + + if (!orig || dom_only) { + Object.defineProperty = function (o, prop, desc) { + // In IE8 try built-in implementation for defining properties on DOM prototypes. + if (orig) + try { return orig(o, prop, desc); } catch (_) {} + if (o !== Object(o)) + throw TypeError('Object.defineProperty called on non-object'); + if (Object.prototype.__defineGetter__ && ('get' in desc)) + Object.prototype.__defineGetter__.call(o, prop, desc.get); + if (Object.prototype.__defineSetter__ && ('set' in desc)) + Object.prototype.__defineSetter__.call(o, prop, desc.set); + if ('value' in desc) + o[prop] = desc.value; + return o; + }; + } + }()); + + // ES5: Make obj[index] an alias for obj._getter(index)/obj._setter(index, value) + // for index in 0 ... obj.length + function makeArrayAccessors(obj) { + if ('TYPED_ARRAY_POLYFILL_NO_ARRAY_ACCESSORS' in global) + return; + + if (obj.length > MAX_ARRAY_LENGTH) throw RangeError('Array too large for polyfill'); + + function makeArrayAccessor(index) { + Object.defineProperty(obj, index, { + 'get': function() { return obj._getter(index); }, + 'set': function(v) { obj._setter(index, v); }, + enumerable: true, + configurable: false + }); + } + + var i; + for (i = 0; i < obj.length; i += 1) { + makeArrayAccessor(i); + } + } + + // Internal conversion functions: + // pack() - take a number (interpreted as Type), output a byte array + // unpack() - take a byte array, output a Type-like number + + function as_signed(value, bits) { var s = 32 - bits; return (value << s) >> s; } + function as_unsigned(value, bits) { var s = 32 - bits; return (value << s) >>> s; } + + function packI8(n) { return [n & 0xff]; } + function unpackI8(bytes) { return as_signed(bytes[0], 8); } + + function packU8(n) { return [n & 0xff]; } + function unpackU8(bytes) { return as_unsigned(bytes[0], 8); } + + function packU8Clamped(n) { n = round(Number(n)); return [n < 0 ? 0 : n > 0xff ? 0xff : n & 0xff]; } + + function packI16(n) { return [n & 0xff, (n >> 8) & 0xff]; } + function unpackI16(bytes) { return as_signed(bytes[1] << 8 | bytes[0], 16); } + + function packU16(n) { return [n & 0xff, (n >> 8) & 0xff]; } + function unpackU16(bytes) { return as_unsigned(bytes[1] << 8 | bytes[0], 16); } + + function packI32(n) { return [n & 0xff, (n >> 8) & 0xff, (n >> 16) & 0xff, (n >> 24) & 0xff]; } + function unpackI32(bytes) { return as_signed(bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0], 32); } + + function packU32(n) { return [n & 0xff, (n >> 8) & 0xff, (n >> 16) & 0xff, (n >> 24) & 0xff]; } + function unpackU32(bytes) { return as_unsigned(bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0], 32); } + + function packIEEE754(v, ebits, fbits) { + + var bias = (1 << (ebits - 1)) - 1; + + function roundToEven(n) { + var w = floor(n), f = n - w; + if (f < 0.5) + return w; + if (f > 0.5) + return w + 1; + return w % 2 ? w + 1 : w; + } + + // Compute sign, exponent, fraction + var s, e, f; + if (v !== v) { + // NaN + // http://dev.w3.org/2006/webapi/WebIDL/#es-type-mapping + e = (1 << ebits) - 1; f = pow(2, fbits - 1); s = 0; + } else if (v === Infinity || v === -Infinity) { + e = (1 << ebits) - 1; f = 0; s = (v < 0) ? 1 : 0; + } else if (v === 0) { + e = 0; f = 0; s = (1 / v === -Infinity) ? 1 : 0; + } else { + s = v < 0; + v = abs(v); + + if (v >= pow(2, 1 - bias)) { + // Normalized + e = min(floor(log(v) / LN2), 1023); + var significand = v / pow(2, e); + if (significand < 1) { + e -= 1; + significand *= 2; + } + if (significand >= 2) { + e += 1; + significand /= 2; + } + var d = pow(2, fbits); + f = roundToEven(significand * d) - d; + e += bias; + if (f / d >= 1) { + e += 1; + f = 0; + } + if (e > 2 * bias) { + // Overflow + e = (1 << ebits) - 1; + f = 0; + } + } else { + // Denormalized + e = 0; + f = roundToEven(v / pow(2, 1 - bias - fbits)); + } + } + + // Pack sign, exponent, fraction + var bits = [], i; + for (i = fbits; i; i -= 1) { bits.push(f % 2 ? 1 : 0); f = floor(f / 2); } + for (i = ebits; i; i -= 1) { bits.push(e % 2 ? 1 : 0); e = floor(e / 2); } + bits.push(s ? 1 : 0); + bits.reverse(); + var str = bits.join(''); + + // Bits to bytes + var bytes = []; + while (str.length) { + bytes.unshift(parseInt(str.substring(0, 8), 2)); + str = str.substring(8); + } + return bytes; + } + + function unpackIEEE754(bytes, ebits, fbits) { + // Bytes to bits + var bits = [], i, j, b, str, + bias, s, e, f; + + for (i = 0; i < bytes.length; ++i) { + b = bytes[i]; + for (j = 8; j; j -= 1) { + bits.push(b % 2 ? 1 : 0); b = b >> 1; + } + } + bits.reverse(); + str = bits.join(''); + + // Unpack sign, exponent, fraction + bias = (1 << (ebits - 1)) - 1; + s = parseInt(str.substring(0, 1), 2) ? -1 : 1; + e = parseInt(str.substring(1, 1 + ebits), 2); + f = parseInt(str.substring(1 + ebits), 2); + + // Produce number + if (e === (1 << ebits) - 1) { + return f !== 0 ? NaN : s * Infinity; + } else if (e > 0) { + // Normalized + return s * pow(2, e - bias) * (1 + f / pow(2, fbits)); + } else if (f !== 0) { + // Denormalized + return s * pow(2, -(bias - 1)) * (f / pow(2, fbits)); + } else { + return s < 0 ? -0 : 0; + } + } + + function unpackF64(b) { return unpackIEEE754(b, 11, 52); } + function packF64(v) { return packIEEE754(v, 11, 52); } + function unpackF32(b) { return unpackIEEE754(b, 8, 23); } + function packF32(v) { return packIEEE754(v, 8, 23); } + + // + // 3 The ArrayBuffer Type + // + + (function() { + + function ArrayBuffer(length) { + length = ToInt32(length); + if (length < 0) throw RangeError('ArrayBuffer size is not a small enough positive integer.'); + Object.defineProperty(this, 'byteLength', {value: length}); + Object.defineProperty(this, '_bytes', {value: Array(length)}); + + for (var i = 0; i < length; i += 1) + this._bytes[i] = 0; + } + + global.ArrayBuffer = global.ArrayBuffer || ArrayBuffer; + + // + // 5 The Typed Array View Types + // + + function $TypedArray$() { + + // %TypedArray% ( length ) + if (!arguments.length || typeof arguments[0] !== 'object') { + return (function(length) { + length = ToInt32(length); + if (length < 0) throw RangeError('length is not a small enough positive integer.'); + Object.defineProperty(this, 'length', {value: length}); + Object.defineProperty(this, 'byteLength', {value: length * this.BYTES_PER_ELEMENT}); + Object.defineProperty(this, 'buffer', {value: new ArrayBuffer(this.byteLength)}); + Object.defineProperty(this, 'byteOffset', {value: 0}); + + }).apply(this, arguments); + } + + // %TypedArray% ( typedArray ) + if (arguments.length >= 1 && + Type(arguments[0]) === 'object' && + arguments[0] instanceof $TypedArray$) { + return (function(typedArray){ + if (this.constructor !== typedArray.constructor) throw TypeError(); + + var byteLength = typedArray.length * this.BYTES_PER_ELEMENT; + Object.defineProperty(this, 'buffer', {value: new ArrayBuffer(byteLength)}); + Object.defineProperty(this, 'byteLength', {value: byteLength}); + Object.defineProperty(this, 'byteOffset', {value: 0}); + Object.defineProperty(this, 'length', {value: typedArray.length}); + + for (var i = 0; i < this.length; i += 1) + this._setter(i, typedArray._getter(i)); + + }).apply(this, arguments); + } + + // %TypedArray% ( array ) + if (arguments.length >= 1 && + Type(arguments[0]) === 'object' && + !(arguments[0] instanceof $TypedArray$) && + !(arguments[0] instanceof ArrayBuffer || Class(arguments[0]) === 'ArrayBuffer')) { + return (function(array) { + + var byteLength = array.length * this.BYTES_PER_ELEMENT; + Object.defineProperty(this, 'buffer', {value: new ArrayBuffer(byteLength)}); + Object.defineProperty(this, 'byteLength', {value: byteLength}); + Object.defineProperty(this, 'byteOffset', {value: 0}); + Object.defineProperty(this, 'length', {value: array.length}); + + for (var i = 0; i < this.length; i += 1) { + var s = array[i]; + this._setter(i, Number(s)); + } + }).apply(this, arguments); + } + + // %TypedArray% ( buffer, byteOffset=0, length=undefined ) + if (arguments.length >= 1 && + Type(arguments[0]) === 'object' && + (arguments[0] instanceof ArrayBuffer || Class(arguments[0]) === 'ArrayBuffer')) { + return (function(buffer, byteOffset, length) { + + byteOffset = ToUint32(byteOffset); + if (byteOffset > buffer.byteLength) + throw RangeError('byteOffset out of range'); + + // The given byteOffset must be a multiple of the element + // size of the specific type, otherwise an exception is raised. + if (byteOffset % this.BYTES_PER_ELEMENT) + throw RangeError('buffer length minus the byteOffset is not a multiple of the element size.'); + + if (length === undefined) { + var byteLength = buffer.byteLength - byteOffset; + if (byteLength % this.BYTES_PER_ELEMENT) + throw RangeError('length of buffer minus byteOffset not a multiple of the element size'); + length = byteLength / this.BYTES_PER_ELEMENT; + + } else { + length = ToUint32(length); + byteLength = length * this.BYTES_PER_ELEMENT; + } + + if ((byteOffset + byteLength) > buffer.byteLength) + throw RangeError('byteOffset and length reference an area beyond the end of the buffer'); + + Object.defineProperty(this, 'buffer', {value: buffer}); + Object.defineProperty(this, 'byteLength', {value: byteLength}); + Object.defineProperty(this, 'byteOffset', {value: byteOffset}); + Object.defineProperty(this, 'length', {value: length}); + + }).apply(this, arguments); + } + + // %TypedArray% ( all other argument combinations ) + throw TypeError(); + } + + // Properties of the %TypedArray Instrinsic Object + + // %TypedArray%.from ( source , mapfn=undefined, thisArg=undefined ) + Object.defineProperty($TypedArray$, 'from', {value: function(iterable) { + return new this(iterable); + }}); + + // %TypedArray%.of ( ...items ) + Object.defineProperty($TypedArray$, 'of', {value: function(/*...items*/) { + return new this(arguments); + }}); + + // %TypedArray%.prototype + var $TypedArrayPrototype$ = {}; + $TypedArray$.prototype = $TypedArrayPrototype$; + + // WebIDL: getter type (unsigned long index); + Object.defineProperty($TypedArray$.prototype, '_getter', {value: function(index) { + if (arguments.length < 1) throw SyntaxError('Not enough arguments'); + + index = ToUint32(index); + if (index >= this.length) + return undefined; + + var bytes = [], i, o; + for (i = 0, o = this.byteOffset + index * this.BYTES_PER_ELEMENT; + i < this.BYTES_PER_ELEMENT; + i += 1, o += 1) { + bytes.push(this.buffer._bytes[o]); + } + return this._unpack(bytes); + }}); + + // NONSTANDARD: convenience alias for getter: type get(unsigned long index); + Object.defineProperty($TypedArray$.prototype, 'get', {value: $TypedArray$.prototype._getter}); + + // WebIDL: setter void (unsigned long index, type value); + Object.defineProperty($TypedArray$.prototype, '_setter', {value: function(index, value) { + if (arguments.length < 2) throw SyntaxError('Not enough arguments'); + + index = ToUint32(index); + if (index >= this.length) + return; + + var bytes = this._pack(value), i, o; + for (i = 0, o = this.byteOffset + index * this.BYTES_PER_ELEMENT; + i < this.BYTES_PER_ELEMENT; + i += 1, o += 1) { + this.buffer._bytes[o] = bytes[i]; + } + }}); + + // get %TypedArray%.prototype.buffer + // get %TypedArray%.prototype.byteLength + // get %TypedArray%.prototype.byteOffset + // -- applied directly to the object in the constructor + + // %TypedArray%.prototype.constructor + Object.defineProperty($TypedArray$.prototype, 'constructor', {value: $TypedArray$}); + + // %TypedArray%.prototype.copyWithin (target, start, end = this.length ) + Object.defineProperty($TypedArray$.prototype, 'copyWithin', {value: function(target, start) { + var end = arguments[2]; + + var o = ToObject(this); + var lenVal = o.length; + var len = ToUint32(lenVal); + len = max(len, 0); + var relativeTarget = ToInt32(target); + var to; + if (relativeTarget < 0) + to = max(len + relativeTarget, 0); + else + to = min(relativeTarget, len); + var relativeStart = ToInt32(start); + var from; + if (relativeStart < 0) + from = max(len + relativeStart, 0); + else + from = min(relativeStart, len); + var relativeEnd; + if (end === undefined) + relativeEnd = len; + else + relativeEnd = ToInt32(end); + var final; + if (relativeEnd < 0) + final = max(len + relativeEnd, 0); + else + final = min(relativeEnd, len); + var count = min(final - from, len - to); + var direction; + if (from < to && to < from + count) { + direction = -1; + from = from + count - 1; + to = to + count - 1; + } else { + direction = 1; + } + while (count > 0) { + o._setter(to, o._getter(from)); + from = from + direction; + to = to + direction; + count = count - 1; + } + return o; + }}); + + // %TypedArray%.prototype.entries ( ) + // -- defined in es6.js to shim browsers w/ native TypedArrays + + // %TypedArray%.prototype.every ( callbackfn, thisArg = undefined ) + Object.defineProperty($TypedArray$.prototype, 'every', {value: function(callbackfn) { + if (this === undefined || this === null) throw TypeError(); + var t = Object(this); + var len = ToUint32(t.length); + if (!IsCallable(callbackfn)) throw TypeError(); + var thisArg = arguments[1]; + for (var i = 0; i < len; i++) { + if (!callbackfn.call(thisArg, t._getter(i), i, t)) + return false; + } + return true; + }}); + + // %TypedArray%.prototype.fill (value, start = 0, end = this.length ) + Object.defineProperty($TypedArray$.prototype, 'fill', {value: function(value) { + var start = arguments[1], + end = arguments[2]; + + var o = ToObject(this); + var lenVal = o.length; + var len = ToUint32(lenVal); + len = max(len, 0); + var relativeStart = ToInt32(start); + var k; + if (relativeStart < 0) + k = max((len + relativeStart), 0); + else + k = min(relativeStart, len); + var relativeEnd; + if (end === undefined) + relativeEnd = len; + else + relativeEnd = ToInt32(end); + var final; + if (relativeEnd < 0) + final = max((len + relativeEnd), 0); + else + final = min(relativeEnd, len); + while (k < final) { + o._setter(k, value); + k += 1; + } + return o; + }}); + + // %TypedArray%.prototype.filter ( callbackfn, thisArg = undefined ) + Object.defineProperty($TypedArray$.prototype, 'filter', {value: function(callbackfn) { + if (this === undefined || this === null) throw TypeError(); + var t = Object(this); + var len = ToUint32(t.length); + if (!IsCallable(callbackfn)) throw TypeError(); + var res = []; + var thisp = arguments[1]; + for (var i = 0; i < len; i++) { + var val = t._getter(i); // in case fun mutates this + if (callbackfn.call(thisp, val, i, t)) + res.push(val); + } + return new this.constructor(res); + }}); + + // %TypedArray%.prototype.find (predicate, thisArg = undefined) + Object.defineProperty($TypedArray$.prototype, 'find', {value: function(predicate) { + var o = ToObject(this); + var lenValue = o.length; + var len = ToUint32(lenValue); + if (!IsCallable(predicate)) throw TypeError(); + var t = arguments.length > 1 ? arguments[1] : undefined; + var k = 0; + while (k < len) { + var kValue = o._getter(k); + var testResult = predicate.call(t, kValue, k, o); + if (Boolean(testResult)) + return kValue; + ++k; + } + return undefined; + }}); + + // %TypedArray%.prototype.findIndex ( predicate, thisArg = undefined ) + Object.defineProperty($TypedArray$.prototype, 'findIndex', {value: function(predicate) { + var o = ToObject(this); + var lenValue = o.length; + var len = ToUint32(lenValue); + if (!IsCallable(predicate)) throw TypeError(); + var t = arguments.length > 1 ? arguments[1] : undefined; + var k = 0; + while (k < len) { + var kValue = o._getter(k); + var testResult = predicate.call(t, kValue, k, o); + if (Boolean(testResult)) + return k; + ++k; + } + return -1; + }}); + + // %TypedArray%.prototype.forEach ( callbackfn, thisArg = undefined ) + Object.defineProperty($TypedArray$.prototype, 'forEach', {value: function(callbackfn) { + if (this === undefined || this === null) throw TypeError(); + var t = Object(this); + var len = ToUint32(t.length); + if (!IsCallable(callbackfn)) throw TypeError(); + var thisp = arguments[1]; + for (var i = 0; i < len; i++) + callbackfn.call(thisp, t._getter(i), i, t); + }}); + + // %TypedArray%.prototype.indexOf (searchElement, fromIndex = 0 ) + Object.defineProperty($TypedArray$.prototype, 'indexOf', {value: function(searchElement) { + if (this === undefined || this === null) throw TypeError(); + var t = Object(this); + var len = ToUint32(t.length); + if (len === 0) return -1; + var n = 0; + if (arguments.length > 0) { + n = Number(arguments[1]); + if (n !== n) { + n = 0; + } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) { + n = (n > 0 || -1) * floor(abs(n)); + } + } + if (n >= len) return -1; + var k = n >= 0 ? n : max(len - abs(n), 0); + for (; k < len; k++) { + if (t._getter(k) === searchElement) { + return k; + } + } + return -1; + }}); + + // %TypedArray%.prototype.join ( separator ) + Object.defineProperty($TypedArray$.prototype, 'join', {value: function(separator) { + if (this === undefined || this === null) throw TypeError(); + var t = Object(this); + var len = ToUint32(t.length); + var tmp = Array(len); + for (var i = 0; i < len; ++i) + tmp[i] = t._getter(i); + return tmp.join(separator === undefined ? ',' : separator); // Hack for IE7 + }}); + + // %TypedArray%.prototype.keys ( ) + // -- defined in es6.js to shim browsers w/ native TypedArrays + + // %TypedArray%.prototype.lastIndexOf ( searchElement, fromIndex = this.length-1 ) + Object.defineProperty($TypedArray$.prototype, 'lastIndexOf', {value: function(searchElement) { + if (this === undefined || this === null) throw TypeError(); + var t = Object(this); + var len = ToUint32(t.length); + if (len === 0) return -1; + var n = len; + if (arguments.length > 1) { + n = Number(arguments[1]); + if (n !== n) { + n = 0; + } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) { + n = (n > 0 || -1) * floor(abs(n)); + } + } + var k = n >= 0 ? min(n, len - 1) : len - abs(n); + for (; k >= 0; k--) { + if (t._getter(k) === searchElement) + return k; + } + return -1; + }}); + + // get %TypedArray%.prototype.length + // -- applied directly to the object in the constructor + + // %TypedArray%.prototype.map ( callbackfn, thisArg = undefined ) + Object.defineProperty($TypedArray$.prototype, 'map', {value: function(callbackfn) { + if (this === undefined || this === null) throw TypeError(); + var t = Object(this); + var len = ToUint32(t.length); + if (!IsCallable(callbackfn)) throw TypeError(); + var res = []; res.length = len; + var thisp = arguments[1]; + for (var i = 0; i < len; i++) + res[i] = callbackfn.call(thisp, t._getter(i), i, t); + return new this.constructor(res); + }}); + + // %TypedArray%.prototype.reduce ( callbackfn [, initialValue] ) + Object.defineProperty($TypedArray$.prototype, 'reduce', {value: function(callbackfn) { + if (this === undefined || this === null) throw TypeError(); + var t = Object(this); + var len = ToUint32(t.length); + if (!IsCallable(callbackfn)) throw TypeError(); + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw TypeError(); + var k = 0; + var accumulator; + if (arguments.length >= 2) { + accumulator = arguments[1]; + } else { + accumulator = t._getter(k++); + } + while (k < len) { + accumulator = callbackfn.call(undefined, accumulator, t._getter(k), k, t); + k++; + } + return accumulator; + }}); + + // %TypedArray%.prototype.reduceRight ( callbackfn [, initialValue] ) + Object.defineProperty($TypedArray$.prototype, 'reduceRight', {value: function(callbackfn) { + if (this === undefined || this === null) throw TypeError(); + var t = Object(this); + var len = ToUint32(t.length); + if (!IsCallable(callbackfn)) throw TypeError(); + // no value to return if no initial value, empty array + if (len === 0 && arguments.length === 1) throw TypeError(); + var k = len - 1; + var accumulator; + if (arguments.length >= 2) { + accumulator = arguments[1]; + } else { + accumulator = t._getter(k--); + } + while (k >= 0) { + accumulator = callbackfn.call(undefined, accumulator, t._getter(k), k, t); + k--; + } + return accumulator; + }}); + + // %TypedArray%.prototype.reverse ( ) + Object.defineProperty($TypedArray$.prototype, 'reverse', {value: function() { + if (this === undefined || this === null) throw TypeError(); + var t = Object(this); + var len = ToUint32(t.length); + var half = floor(len / 2); + for (var i = 0, j = len - 1; i < half; ++i, --j) { + var tmp = t._getter(i); + t._setter(i, t._getter(j)); + t._setter(j, tmp); + } + return t; + }}); + + // %TypedArray%.prototype.set(array, offset = 0 ) + // %TypedArray%.prototype.set(typedArray, offset = 0 ) + // WebIDL: void set(TypedArray array, optional unsigned long offset); + // WebIDL: void set(sequence array, optional unsigned long offset); + Object.defineProperty($TypedArray$.prototype, 'set', {value: function(index, value) { + if (arguments.length < 1) throw SyntaxError('Not enough arguments'); + var array, sequence, offset, len, + i, s, d, + byteOffset, byteLength, tmp; + + if (typeof arguments[0] === 'object' && arguments[0].constructor === this.constructor) { + // void set(TypedArray array, optional unsigned long offset); + array = arguments[0]; + offset = ToUint32(arguments[1]); + + if (offset + array.length > this.length) { + throw RangeError('Offset plus length of array is out of range'); + } + + byteOffset = this.byteOffset + offset * this.BYTES_PER_ELEMENT; + byteLength = array.length * this.BYTES_PER_ELEMENT; + + if (array.buffer === this.buffer) { + tmp = []; + for (i = 0, s = array.byteOffset; i < byteLength; i += 1, s += 1) { + tmp[i] = array.buffer._bytes[s]; + } + for (i = 0, d = byteOffset; i < byteLength; i += 1, d += 1) { + this.buffer._bytes[d] = tmp[i]; + } + } else { + for (i = 0, s = array.byteOffset, d = byteOffset; + i < byteLength; i += 1, s += 1, d += 1) { + this.buffer._bytes[d] = array.buffer._bytes[s]; + } + } + } else if (typeof arguments[0] === 'object' && typeof arguments[0].length !== 'undefined') { + // void set(sequence array, optional unsigned long offset); + sequence = arguments[0]; + len = ToUint32(sequence.length); + offset = ToUint32(arguments[1]); + + if (offset + len > this.length) { + throw RangeError('Offset plus length of array is out of range'); + } + + for (i = 0; i < len; i += 1) { + s = sequence[i]; + this._setter(offset + i, Number(s)); + } + } else { + throw TypeError('Unexpected argument type(s)'); + } + }}); + + // %TypedArray%.prototype.slice ( start, end ) + Object.defineProperty($TypedArray$.prototype, 'slice', {value: function(start, end) { + var o = ToObject(this); + var lenVal = o.length; + var len = ToUint32(lenVal); + var relativeStart = ToInt32(start); + var k = (relativeStart < 0) ? max(len + relativeStart, 0) : min(relativeStart, len); + var relativeEnd = (end === undefined) ? len : ToInt32(end); + var final = (relativeEnd < 0) ? max(len + relativeEnd, 0) : min(relativeEnd, len); + var count = final - k; + var c = o.constructor; + var a = new c(count); + var n = 0; + while (k < final) { + var kValue = o._getter(k); + a._setter(n, kValue); + ++k; + ++n; + } + return a; + }}); + + // %TypedArray%.prototype.some ( callbackfn, thisArg = undefined ) + Object.defineProperty($TypedArray$.prototype, 'some', {value: function(callbackfn) { + if (this === undefined || this === null) throw TypeError(); + var t = Object(this); + var len = ToUint32(t.length); + if (!IsCallable(callbackfn)) throw TypeError(); + var thisp = arguments[1]; + for (var i = 0; i < len; i++) { + if (callbackfn.call(thisp, t._getter(i), i, t)) { + return true; + } + } + return false; + }}); + + // %TypedArray%.prototype.sort ( comparefn ) + Object.defineProperty($TypedArray$.prototype, 'sort', {value: function(comparefn) { + if (this === undefined || this === null) throw TypeError(); + var t = Object(this); + var len = ToUint32(t.length); + var tmp = Array(len); + for (var i = 0; i < len; ++i) + tmp[i] = t._getter(i); + function sortCompare(x, y) { + if (x !== x && y !== y) return +0; + if (x !== x) return 1; + if (y !== y) return -1; + if (comparefn !== undefined) { + return comparefn(x, y); + } + if (x < y) return -1; + if (x > y) return 1; + return +0; + } + tmp.sort(sortCompare); + for (i = 0; i < len; ++i) + t._setter(i, tmp[i]); + return t; + }}); + + // %TypedArray%.prototype.subarray(begin = 0, end = this.length ) + // WebIDL: TypedArray subarray(long begin, optional long end); + Object.defineProperty($TypedArray$.prototype, 'subarray', {value: function(start, end) { + function clamp(v, min, max) { return v < min ? min : v > max ? max : v; } + + start = ToInt32(start); + end = ToInt32(end); + + if (arguments.length < 1) { start = 0; } + if (arguments.length < 2) { end = this.length; } + + if (start < 0) { start = this.length + start; } + if (end < 0) { end = this.length + end; } + + start = clamp(start, 0, this.length); + end = clamp(end, 0, this.length); + + var len = end - start; + if (len < 0) { + len = 0; + } + + return new this.constructor( + this.buffer, this.byteOffset + start * this.BYTES_PER_ELEMENT, len); + }}); + + // %TypedArray%.prototype.toLocaleString ( ) + // %TypedArray%.prototype.toString ( ) + // %TypedArray%.prototype.values ( ) + // %TypedArray%.prototype [ @@iterator ] ( ) + // get %TypedArray%.prototype [ @@toStringTag ] + // -- defined in es6.js to shim browsers w/ native TypedArrays + + function makeTypedArray(elementSize, pack, unpack) { + // Each TypedArray type requires a distinct constructor instance with + // identical logic, which this produces. + var TypedArray = function() { + Object.defineProperty(this, 'constructor', {value: TypedArray}); + $TypedArray$.apply(this, arguments); + makeArrayAccessors(this); + }; + if ('__proto__' in TypedArray) { + TypedArray.__proto__ = $TypedArray$; + } else { + TypedArray.from = $TypedArray$.from; + TypedArray.of = $TypedArray$.of; + } + + TypedArray.BYTES_PER_ELEMENT = elementSize; + + var TypedArrayPrototype = function() {}; + TypedArrayPrototype.prototype = $TypedArrayPrototype$; + + TypedArray.prototype = new TypedArrayPrototype(); + + Object.defineProperty(TypedArray.prototype, 'BYTES_PER_ELEMENT', {value: elementSize}); + Object.defineProperty(TypedArray.prototype, '_pack', {value: pack}); + Object.defineProperty(TypedArray.prototype, '_unpack', {value: unpack}); + + return TypedArray; + } + + var Int8Array = makeTypedArray(1, packI8, unpackI8); + var Uint8Array = makeTypedArray(1, packU8, unpackU8); + var Uint8ClampedArray = makeTypedArray(1, packU8Clamped, unpackU8); + var Int16Array = makeTypedArray(2, packI16, unpackI16); + var Uint16Array = makeTypedArray(2, packU16, unpackU16); + var Int32Array = makeTypedArray(4, packI32, unpackI32); + var Uint32Array = makeTypedArray(4, packU32, unpackU32); + var Float32Array = makeTypedArray(4, packF32, unpackF32); + var Float64Array = makeTypedArray(8, packF64, unpackF64); + + global.Int8Array = global.Int8Array || Int8Array; + global.Uint8Array = global.Uint8Array || Uint8Array; + global.Uint8ClampedArray = global.Uint8ClampedArray || Uint8ClampedArray; + global.Int16Array = global.Int16Array || Int16Array; + global.Uint16Array = global.Uint16Array || Uint16Array; + global.Int32Array = global.Int32Array || Int32Array; + global.Uint32Array = global.Uint32Array || Uint32Array; + global.Float32Array = global.Float32Array || Float32Array; + global.Float64Array = global.Float64Array || Float64Array; + }()); + + // + // 6 The DataView View Type + // + + (function() { + function r(array, index) { + return IsCallable(array.get) ? array.get(index) : array[index]; + } + + var IS_BIG_ENDIAN = (function() { + var u16array = new Uint16Array([0x1234]), + u8array = new Uint8Array(u16array.buffer); + return r(u8array, 0) === 0x12; + }()); + + // DataView(buffer, byteOffset=0, byteLength=undefined) + // WebIDL: Constructor(ArrayBuffer buffer, + // optional unsigned long byteOffset, + // optional unsigned long byteLength) + function DataView(buffer, byteOffset, byteLength) { + if (!(buffer instanceof ArrayBuffer || Class(buffer) === 'ArrayBuffer')) throw TypeError(); + + byteOffset = ToUint32(byteOffset); + if (byteOffset > buffer.byteLength) + throw RangeError('byteOffset out of range'); + + if (byteLength === undefined) + byteLength = buffer.byteLength - byteOffset; + else + byteLength = ToUint32(byteLength); + + if ((byteOffset + byteLength) > buffer.byteLength) + throw RangeError('byteOffset and length reference an area beyond the end of the buffer'); + + Object.defineProperty(this, 'buffer', {value: buffer}); + Object.defineProperty(this, 'byteLength', {value: byteLength}); + Object.defineProperty(this, 'byteOffset', {value: byteOffset}); + }; + + // get DataView.prototype.buffer + // get DataView.prototype.byteLength + // get DataView.prototype.byteOffset + // -- applied directly to instances by the constructor + + function makeGetter(arrayType) { + return function GetViewValue(byteOffset, littleEndian) { + byteOffset = ToUint32(byteOffset); + + if (byteOffset + arrayType.BYTES_PER_ELEMENT > this.byteLength) + throw RangeError('Array index out of range'); + + byteOffset += this.byteOffset; + + var uint8Array = new Uint8Array(this.buffer, byteOffset, arrayType.BYTES_PER_ELEMENT), + bytes = []; + for (var i = 0; i < arrayType.BYTES_PER_ELEMENT; i += 1) + bytes.push(r(uint8Array, i)); + + if (Boolean(littleEndian) === Boolean(IS_BIG_ENDIAN)) + bytes.reverse(); + + return r(new arrayType(new Uint8Array(bytes).buffer), 0); + }; + } + + Object.defineProperty(DataView.prototype, 'getUint8', {value: makeGetter(Uint8Array)}); + Object.defineProperty(DataView.prototype, 'getInt8', {value: makeGetter(Int8Array)}); + Object.defineProperty(DataView.prototype, 'getUint16', {value: makeGetter(Uint16Array)}); + Object.defineProperty(DataView.prototype, 'getInt16', {value: makeGetter(Int16Array)}); + Object.defineProperty(DataView.prototype, 'getUint32', {value: makeGetter(Uint32Array)}); + Object.defineProperty(DataView.prototype, 'getInt32', {value: makeGetter(Int32Array)}); + Object.defineProperty(DataView.prototype, 'getFloat32', {value: makeGetter(Float32Array)}); + Object.defineProperty(DataView.prototype, 'getFloat64', {value: makeGetter(Float64Array)}); + + function makeSetter(arrayType) { + return function SetViewValue(byteOffset, value, littleEndian) { + byteOffset = ToUint32(byteOffset); + if (byteOffset + arrayType.BYTES_PER_ELEMENT > this.byteLength) + throw RangeError('Array index out of range'); + + // Get bytes + var typeArray = new arrayType([value]), + byteArray = new Uint8Array(typeArray.buffer), + bytes = [], i, byteView; + + for (i = 0; i < arrayType.BYTES_PER_ELEMENT; i += 1) + bytes.push(r(byteArray, i)); + + // Flip if necessary + if (Boolean(littleEndian) === Boolean(IS_BIG_ENDIAN)) + bytes.reverse(); + + // Write them + byteView = new Uint8Array(this.buffer, byteOffset, arrayType.BYTES_PER_ELEMENT); + byteView.set(bytes); + }; + } + + Object.defineProperty(DataView.prototype, 'setUint8', {value: makeSetter(Uint8Array)}); + Object.defineProperty(DataView.prototype, 'setInt8', {value: makeSetter(Int8Array)}); + Object.defineProperty(DataView.prototype, 'setUint16', {value: makeSetter(Uint16Array)}); + Object.defineProperty(DataView.prototype, 'setInt16', {value: makeSetter(Int16Array)}); + Object.defineProperty(DataView.prototype, 'setUint32', {value: makeSetter(Uint32Array)}); + Object.defineProperty(DataView.prototype, 'setInt32', {value: makeSetter(Int32Array)}); + Object.defineProperty(DataView.prototype, 'setFloat32', {value: makeSetter(Float32Array)}); + Object.defineProperty(DataView.prototype, 'setFloat64', {value: makeSetter(Float64Array)}); + + global.DataView = global.DataView || DataView; + + }()); + +}(self)); diff --git a/WaterCloud.Web/wwwroot/js/lay-module/soulTable/soulTable.js b/WaterCloud.Web/wwwroot/js/lay-module/soulTable/soulTable.js new file mode 100644 index 0000000..c71d255 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/soulTable/soulTable.js @@ -0,0 +1,1571 @@ +/** + * + * @name: 表格增强插件 + * @author: yelog + * @link: https://github.com/yelog/layui-soul-table + * @license: MIT + * @version: v1.9.0 + */ +layui.define(['table', 'tableFilter', 'tableChild', 'tableMerge'], function (exports) { + + var tableFilter = layui.tableFilter, + tableChild = layui.tableChild, + tableMerge = layui.tableMerge, + $ = layui.$, + table = layui.table, + HIDE = 'layui-hide', + tables = {}, + originCols = {}, + defaultConfig = { // 默认配置开关 + fixTotal: false, // 修复合计行固定列问题 + drag: true, // 列拖动 + rowDrag: false, // 行拖动 + autoColumnWidth: true, // 自动列宽 + contextmenu: false, // 右键菜单 + fixResize: true, // 修改有固定列的拖动列宽的位置为左边线 + overflow: false, // 自定义内容超出样式 + fixFixedScroll: true, // 固定列支持鼠标滚轮滚动 + filter: false // 筛选及记忆相关 + }, + _BODY = $('body'), + _DOC = $(document); + + // 封装方法 + var mod = { + render: function (myTable) { + // 记录表格配置,方便直接通过 tableId 调用方法 + tables[myTable.id] = myTable + var curConfig = $.extend({}, defaultConfig, myTable); + if (curConfig.filter && curConfig.filter.cache) { + var storeKey = location.pathname + location.hash + myTable.id; + var colsStr = this.deepStringify(myTable.cols); + // 记录表格列的原始配置 + if (!originCols[myTable.id]) { // 只在第一次 render 时生效 + originCols[myTable.id] = this.deepClone(myTable.cols) + + var curTableSession = localStorage.getItem(storeKey); + if (curTableSession && colsStr === localStorage.getItem('origin' + storeKey)) { + this.updateCols(myTable, this.deepParse(curTableSession)); + } else { + localStorage.setItem('origin' + storeKey, colsStr) + localStorage.removeItem(storeKey) + } + } + } else { + // 如果没有开启记忆,则清除 + this.clearCache(myTable); + } + + tableFilter.render(myTable); + tableChild.render(myTable); + tableMerge.render(myTable); + + // 初始化暂停配置 + this.suspendConfig[myTable.id] = { + drag: false, + rowDrag: false + } + // 修复合计栏固定列问题 + if (curConfig.fixTotal) { + this.fixTotal(myTable) + } + if (curConfig.drag) { + this.drag(myTable, curConfig.drag); + } + if (curConfig.rowDrag) { + this.rowDrag(myTable, curConfig.rowDrag) + } + if (curConfig.autoColumnWidth) { + this.autoColumnWidth(myTable, curConfig.autoColumnWidth) + } + + this.contextmenu(myTable, curConfig.contextmenu); + + if (curConfig.fixResize) { + this.fixResizeRightFixed(myTable); + } + + if (curConfig.overflow) { + this.overflow(myTable, curConfig.overflow); + } + + if (curConfig.fixFixedScroll) { + this.fixFixedScroll(myTable); + } + } + , config: function (configObj) { + if (typeof configObj === 'object') { + $.extend(true, defaultConfig, configObj); + } + } + , updateCols: function (myTable, cols) { + var i, j, lastKeyMap = {}, columnKey, newCols = [], col = [], + $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + $fixedHead = $tableBox.children('.layui-table-fixed').children('.layui-table-header').children('table'), + $tableHead = $.merge($tableBox.children('.layui-table-header').children('table'), $fixedHead), + $noFixedHead = $tableBox.children('.layui-table-header').children('table'), + $fixedBody = $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table'), + $noFixedBody = $tableBox.children('.layui-table-body').children('table'), + $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $fixedBody); + + for (i = 0; i < myTable.cols.length; i++) { + for (j = 0; j < myTable.cols[i].length; j++) { + myTable.cols[i][j]['oldPos'] = i + '-' + j + lastKeyMap[myTable.cols[i][j].key] = myTable.cols[i][j] + } + } + + for (i = 0; i < cols.length; i++) { + col = [] + for (j = 0; j < cols[i].length; j++) { + columnKey = cols[i][j].key; + // 同步列宽 + if (cols[i][j].width && lastKeyMap[cols[i][j].key] !== cols[i][j].width) { + this.getCssRule(myTable, columnKey, function (item) { + item.style.width = (cols[i][j].width ? cols[i][j].width : 0) + 'px' + }) + } + // 同步隐藏 + if (lastKeyMap[cols[i][j].key].hide !== cols[i][j].hide) { + $tableHead.find('th[data-key="' + columnKey + '"]')[cols[i][j].hide ? 'addClass' : 'removeClass']('layui-hide') + $tableBody.find('td[data-key="' + columnKey + '"]')[cols[i][j].hide ? 'addClass' : 'removeClass']('layui-hide') + } + + // 同步顺序 + if (lastKeyMap[cols[i][j].key].oldPos !== (i + '-' + j) || lastKeyMap[cols[i][j].key].fixed !== cols[i][j].fixed) { + myTable.cols = cols; + table.reload(myTable.id) + return; + // 实现不 reload 调整列顺序 + + } + lastKeyMap[cols[i][j].key].fixed = cols[i][j].fixed; + lastKeyMap[cols[i][j].key].width = cols[i][j].width; + lastKeyMap[cols[i][j].key].hide = cols[i][j].hide; + col.push(lastKeyMap[cols[i][j].key]) + } + newCols.push(col) + } + $noFixedHead.children().children('tr').each(function () { + innerHandler(this, 'th') + }) + $noFixedBody.children().children('tr').each(function () { + innerHandler(this, 'td') + }) + + function innerHandler(_this, domName) { + for (i = 0; i < cols.length; i++) { + for (j = 0; j < cols[i].length; j++) { + columnKey = myTable.index + '-' + cols[i][j].key; + var curKey = $(_this).children(domName + ':eq(' + j + ')').attr('data-key'); + if (curKey !== columnKey) { + $(_this).children(domName + ':eq(' + j + ')').before($(_this).children(domName + '[data-key="' + columnKey + '"]')) + if (cols[i][j].fixed) { + var $curRow = (domName === 'th' ? $fixedHead : $fixedBody).children().children(domName === 'th' ? 'tr' : 'tr[data-index="' + $(_this).attr('data-index') + '"]') + $curRow.children(domName + '[data-key="' + curKey + '"]').before($curRow.children(domName + '[data-key="' + columnKey + '"]')) + } + } + } + } + } + + myTable.cols = newCols; + + table.resize(myTable.id) + } + /** + * excel表格导出 + * @param myTable + * @param curExcel + */ + , export: function (myTable, curExcel) { + tableFilter.export(myTable.config || myTable, curExcel); + } + , getCssRule: function (that, key, callback) { + var style = that.elem.next().find('style')[0] + , sheet = style.sheet || style.styleSheet || {} + , rules = sheet.cssRules || sheet.rules; + layui.each(rules, function (i, item) { + if (item.selectorText === ('.laytable-cell-' + key)) { + return callback(item), true; + } + }); + } + , autoColumnWidth: function (myTable, autoColumnWidthConfig) { + var _this = this; + if (typeof myTable === 'object') { + innerColumnWidth(_this, myTable) + } else if (typeof myTable === 'string') { + innerColumnWidth(_this, tables[myTable]) + } else if (typeof myTable === 'undefined') { + layui.each(tables, function () { + innerColumnWidth(_this, this) + }); + } + + function innerColumnWidth(_this, myTable) { + var $table = $(myTable.elem), + th = $table.next().children('.layui-table-box').children('.layui-table-header').children('table').children('thead').children('tr').children('th'), + fixTh = $table.next().children('.layui-table-box').children('.layui-table-fixed').children('.layui-table-header').children('table').children('thead').children('tr').children('th'), + $tableBodytr = $table.next().children('.layui-table-box').children('.layui-table-body').children('table').children('tbody').children('tr'), + $totalTr = $table.next().children('.layui-table-total').find('tr'); + String.prototype.width = function (font) { + var f = font || _BODY.css('font'), + o = $('
                ' + this + '
                ') + .css({ + 'position': 'absolute', + 'float': 'left', + 'white-space': 'nowrap', + 'visibility': 'hidden', + 'font': f + }) + .appendTo(_BODY), + w = o.width(); + + o.remove(); + return w; + } + if (typeof autoColumnWidthConfig === 'undefined' || typeof autoColumnWidthConfig.dblclick === 'undefined' || autoColumnWidthConfig.dblclick) { + th.add(fixTh).on('dblclick', function (e) { + var othis = $(this), + pLeft = e.clientX - othis.offset().left; + handleColumnWidth(myTable, othis, othis.parents('.layui-table-fixed-r').length > 0 ? pLeft <= 10 : othis.width() - pLeft <= 10); + }) + } + // 初始化表格后,自动调整所有列宽 + if (autoColumnWidthConfig && autoColumnWidthConfig.init) { + th.add(fixTh).each(function (e) { + var colKey = $(this).attr('data-key').split('-') + if (myTable.cols[colKey[1]][colKey[2]].autoWidth !== false && (!Array.isArray(autoColumnWidthConfig.init) || autoColumnWidthConfig.init.indexOf($(this).attr('data-field')) !== -1)) { + handleColumnWidth(myTable, $(this), true); + } + }) + } + + function handleColumnWidth(myTable, othis, isHandle) { + var key = othis.data('key') + if (othis.attr('colspan') > 1 || othis.data('unresize')) { + return; + } + if (isHandle) { + var maxWidth = othis.text().width(othis.css('font')) + 21, font = othis.css('font'); + $tableBodytr.children('td[data-key="' + key + '"]').each(function (index, elem) { + var curWidth = 0 + if ($(this).children().children() && $(this).children().children().length > 0) { + curWidth += $(this).children().html().width(font) + } else { + curWidth = $(this).text().width(font); + } + + // var curWidth = $(this).text().width(font); + if (maxWidth < curWidth) { + maxWidth = curWidth + } + }) + if ($totalTr.length > 0) { + var curWidth = $totalTr.children('td[data-key="' + key + '"]').text().width(font) + if (maxWidth < curWidth) { + maxWidth = curWidth + } + + } + + maxWidth += 32; + + _this.getCssRule(myTable, key, function (item) { + item.style.width = maxWidth + 'px' + }); + for (var i = 0; i < myTable.cols.length; i++) { + for (var j = 0; j < myTable.cols[i].length; j++) { + if (myTable.cols[i][j].key === key) { + myTable.cols[i][j].width = maxWidth; + break; + } + } + } + } + } + } + } + /** + * 左右拖拽调整列顺序、向上拖隐藏列 + * @param myTable + */ + , drag: function (myTable, dragConfig) { + if (myTable.cols.length > 1) { + // 如果是复杂表头,则自动禁用拖动效果 + return; + } + var _this = this, + $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + $tableHead = $.merge($tableBox.children('.layui-table-header').children('table'), $tableBox.children('.layui-table-fixed').children('.layui-table-header').children('table')), + $fixedBody = $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table'), + $noFixedBody = $tableBox.children('.layui-table-body').children('table'), + $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $fixedBody), + $totalTable = $table.next().children('.layui-table-total').children('table'), + $fixedTotalTable = $table.next().children('.layui-table-total').children('table.layui-table-total-fixed'), + $noFixedTotalTable = $table.next().children('.layui-table-total').children('table:eq(0)'), + tableId = myTable.id, + isSimple = dragConfig === 'simple' || (dragConfig && dragConfig.type === 'simple'), // 是否为简易拖拽 + toolbar = dragConfig && dragConfig.toolbar, // 是否开启工具栏 + isDragging = false, isStart = false; + + if (!$tableHead.attr('drag')) { + $tableHead.attr('drag', true); + if (toolbar) { + $tableBox.append('
                左固定
                不固定
                右固定
                ') + var $dragBar = $tableBox.children('.soul-drag-bar'); + $dragBar.children('div').on('mouseenter', function () { + $(this).addClass('active') + }).on('mouseleave', function () { + $(this).removeClass('active') + }) + } + + $tableHead.find('th').each(function () { + var $this = $(this), + field = $this.data('field'), + key = $this.data('key'); + if (!key) { + return; + } + + var keyArray = key.split('-'), + curColumn = myTable.cols[keyArray[1]][keyArray[2]], + curKey = myTable.index + '-' + keyArray[1] + '-' + keyArray[2], + isInFixed = $this.parents('.layui-table-fixed').length > 0; + // 绑定鼠标按下事件 + $(this).find('span:first,.laytable-cell-checkbox') + .css('cursor', 'move') + .on('mousedown', function (e) { + // 暂停或者非鼠标左键都不执行 + if (_this.suspendConfig[tableId].drag || e.button !== 0) { + return; + } + e.preventDefault(); + var $cloneHead = $this.clone().css('visibility', 'hidden'), + originLeft = $this.position().left, + originTop = $this.offset().top, + disX = e.clientX - originLeft, // 鼠标距离被移动元素左侧的距离 + color = $this.parents('tr:eq(0)').css("background-color"), + width = $this.width(), moveDistince = 0, + $that = $(this), + isFixed = curColumn.fixed; + isStart = true; + //区分click、drag事件 + + + // 阻止文本选中 + _DOC.bind("selectstart", function () { + return false; + }); + + // 移动事件 + _BODY.on('mousemove', function (e) { + if (isStart && $cloneHead) { + $tableBox.removeClass('no-left-border'); + if (!isDragging) { + if (toolbar) { + $dragBar.attr('data-type', isFixed || 'none') + $dragBar.addClass('active') + } + + $this.after($cloneHead); + $this.addClass('isDrag').css({ + 'position': 'absolute', + 'z-index': 1, + 'border-left': '1px solid #e6e6e6', + 'background-color': color, + 'width': width + 1 + }); + + if (isSimple) { + //设置蒙板 + } else { + (isInFixed ? $fixedBody : $tableBody).find('td[data-key="' + key + '"]').each(function () { + $(this).after($(this).clone().css('visibility', 'hidden').attr('data-clone', '')); + $(this).addClass('isDrag').css({ + 'position': 'absolute', + 'z-index': 1, + 'border-left': '1px solid #e6e6e6', + 'background-color': $(this).css('background-color'), + 'width': width + 1 + }); + }) + if ($totalTable.length > 0) { + (isInFixed ? $fixedTotalTable : $totalTable).find('td[data-key="' + key + '"]').each(function () { + $(this).after($(this).clone().css('visibility', 'hidden').attr('data-clone', '')); + $(this).addClass('isDrag').css({ + 'position': 'absolute', + 'z-index': 1, + 'background-color': $(this).parents('tr:eq(0)').css('background-color'), + 'width': width + 1 + }); + }) + } + } + } + isDragging = true; + var x, y, i, j, tempCols, + left = e.clientX - disX, // 计算当前被移动列左侧位置应该哪里 + $leftTh = $cloneHead.prev().prev(), + hasLeftTh = $leftTh.length > 0, + leftKey = hasLeftTh ? $leftTh.data('key').split('-') : [], + $rightTh = $cloneHead.next().hasClass('layui-table-patch') ? [] : $cloneHead.next(), + hasRightTh = $rightTh.length > 0, + rightKey = hasRightTh ? $rightTh.data('key').split('-') : [], + leftMove = hasLeftTh && ($cloneHead.position().left - left > $leftTh.width() / 2.0), + rightMove = hasRightTh && (left - $cloneHead.position().left > $rightTh.width() / 2.0); + moveDistince = Math.abs($cloneHead.position().left - left); //记录移动距离 + // 移动到左右两端、checbox/radio 固定列等停止移动 + if ($cloneHead.position().left - left > 0 + ? !hasLeftTh || !!isFixed !== !!myTable.cols[leftKey[1]][leftKey[2]].fixed + : !hasRightTh || !!isFixed !== !!myTable.cols[rightKey[1]][rightKey[2]].fixed) { + $this.css('left', $cloneHead.position().left); + $tableBody.find('td[data-key="' + key + '"][data-clone]').each(function (e) { + $(this).prev().css('left', $cloneHead.position().left); + }) + if ($totalTable.length > 0) { + $totalTable.find('td[data-key="' + key + '"][data-clone]').each(function (e) { + $(this).prev().css('left', $cloneHead.position().left); + }) + } + $tableBox.addClass('no-left-border'); + return; + } + $this.css('left', left); + + if (leftMove) { + $cloneHead.after($leftTh); + + // 更新隐藏列顺序 + $('#soul-columns' + tableId + '>li[data-value="' + field + '"]').after($('#soul-columns' + tableId + '>li[data-value="' + field + '"]').prev()) + + // 更新配置信息 + for (i = 0; i < myTable.cols.length; i++) { + for (j = 0; j < myTable.cols[i].length; j++) { + if (myTable.cols[i][j].key === curKey) { + x = i; + y = j; + break; + } + } + if (typeof x !== 'undefined' && typeof y !== 'undefined') { + break; + } + } + tempCols = myTable.cols[x][y - 1]; + myTable.cols[x][y - 1] = myTable.cols[x][y]; + myTable.cols[x][y] = tempCols; + _this.fixTableRemember(myTable); + } else if (rightMove) { + $cloneHead.prev().before($rightTh); + + // 更新隐藏列顺序 + $('#soul-columns' + tableId + '>li[data-value="' + field + '"]').before($('#soul-columns' + tableId + '>li[data-value="' + field + '"]').next()) + + // 更新配置信息 + for (i = 0; i < myTable.cols.length; i++) { + for (j = 0; j < myTable.cols[i].length; j++) { + if (myTable.cols[i][j].key === curKey) { + x = i; + y = j; + break; + } + } + if (typeof x !== 'undefined' && typeof y !== 'undefined') { + break; + } + } + tempCols = myTable.cols[x][y + 1]; + myTable.cols[x][y + 1] = myTable.cols[x][y]; + myTable.cols[x][y] = tempCols; + _this.fixTableRemember(myTable); + } + + $tableBody.find('td[data-key="' + key + '"][data-clone]').each(function () { + $(this).prev().css('left', left); + + if (leftMove) { + if ($(this).prev().prev().length !== 0) { + $(this).after($(this).prev().prev()); + } + } else if (rightMove) { + if ($(this).next().length !== 0) { + $(this).prev().before($(this).next()); + } + } + }) + if ($totalTable.length > 0) { + $totalTable.find('td[data-key="' + key + '"][data-clone]').each(function () { + $(this).prev().css('left', left); + + if (leftMove) { + if ($(this).prev().prev().length !== 0) { + $(this).after($(this).prev().prev()); + } + } else if (rightMove) { + if ($(this).next().length !== 0) { + $(this).prev().before($(this).next()); + } + } + }) + } + + /* 拖动隐藏列 */ + if (e.clientY - originTop < -15) { + if ($('#column-remove').length === 0) { + _BODY.append('') + } + $('#column-remove').css({ + top: e.clientY - $('#column-remove').height() / 2, + left: e.clientX - $('#column-remove').width() / 2, + 'font-size': (originTop - e.clientY) + 'px' + }) + $('#column-remove').show(); + } else { + $('#column-remove').hide(); + } + } + }).on('mouseup', function () { + _DOC.unbind("selectstart"); + _BODY.off('mousemove').off('mouseup') + if (isStart && $cloneHead) { + isStart = false; + if (isDragging) { + if (curColumn.type !== 'checkbox') { + $that.on('click', function (e) { + e.stopPropagation(); + }); + } + + isDragging = false; + $tableBox.removeClass('no-left-border') + $this.removeClass('isDrag').css({ + 'position': 'relative', + 'z-index': 'inherit', + 'left': 'inherit', + 'border-left': 'inherit', + 'width': 'inherit', + 'background-color': 'inherit' + }); + $this.next().remove(); + var prefKey = $this.prev().data('key'); + if (isFixed) { + var $noFixedTh = $tableBox.children('.layui-table-header').children('table').find('th[data-key="' + key + '"]'); + if (prefKey) { + $noFixedTh.parent().children('th[data-key="' + prefKey + '"]').after($noFixedTh) + } else { + if (isFixed === 'right') { + if ($this.siblings().length > 0) { + $tableBox.children('.layui-table-header').children('table').find('th[data-key="' + $this.next().data('key') + '"]').prev().after($noFixedTh); + } + } else { + $noFixedTh.parent().prepend(''); + $noFixedTh.parent().children('th:first').after($noFixedTh); + $noFixedTh.parent().children('th:first').remove(); + } + + } + } + if (isSimple) { + $tableBody.find('td[data-key="' + key + '"]').each(function () { + if (prefKey) { + $(this).parent().children('td[data-key="' + prefKey + '"]').after($(this)) + } else { + if (isFixed === 'right') { + if ($this.siblings().length > 0) { + var $preTd = $(this).parent().children('td[data-key="' + $this.next().data('key') + '"]').prev(); + if ($preTd.length > 0) { + $preTd.after($(this)); + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } + }); + if ($totalTable.length > 0) { + $totalTable.find('td[data-key="' + key + '"]').each(function () { + if (prefKey) { + $(this).parent().children('td[data-key="' + prefKey + '"]').after($(this)) + } else { + if (isFixed === 'right') { + var $preTd = $(this).parent().children('td[data-key="' + $this.next().data('key') + '"]').prev(); + if ($preTd.length > 0) { + $preTd.after($(this)); + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } + }); + } + } else if (isInFixed) { + $noFixedBody.find('td[data-key="' + key + '"]').each(function () { + if (prefKey) { + $(this).parent().children('td[data-key="' + prefKey + '"]').after($(this)) + } else { + if (isFixed === 'right') { + if ($this.siblings().length > 0) { + var $preTd = $(this).parent().children('td[data-key="' + $this.next().data('key') + '"]').prev(); + if ($preTd.length > 0) { + $preTd.after($(this)); + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } + }); + $fixedBody.find('td[data-key="' + key + '"][data-clone]').each(function () { + $(this).prev().removeClass('isDrag').css({ + 'position': 'relative', + 'z-index': 'inherit', + 'left': 'inherit', + 'border-left': 'inherit', + 'width': 'inherit', + 'background-color': 'inherit' + }); + $(this).remove(); + }); + if ($totalTable.length > 0) { + $noFixedTotalTable.find('td[data-key="' + key + '"]').each(function () { + if (prefKey) { + $(this).parent().children('td[data-key="' + prefKey + '"]').after($(this)) + } else { + if (isFixed === 'right') { + var $preTd = $(this).parent().children('td[data-key="' + $this.next().data('key') + '"]').prev(); + if ($preTd.length > 0) { + $preTd.after($(this)); + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } + }); + $fixedTotalTable.find('td[data-key="' + key + '"][data-clone]').each(function () { + $(this).prev().removeClass('isDrag').css({ + 'position': 'relative', + 'z-index': 'inherit', + 'left': 'inherit', + 'width': 'inherit', + 'background-color': 'inherit' + }); + $(this).remove(); + }); + } + } else { + $tableBody.find('td[data-key="' + key + '"][data-clone]').each(function () { + $(this).prev().removeClass('isDrag').css({ + 'position': 'relative', + 'z-index': 'inherit', + 'left': 'inherit', + 'width': 'inherit', + 'background-color': 'inherit' + }); + $(this).remove(); + }); + if ($totalTable.length > 0) { + $totalTable.find('td[data-key="' + key + '"][data-clone]').each(function () { + $(this).prev().removeClass('isDrag').css({ + 'position': 'relative', + 'z-index': 'inherit', + 'left': 'inherit', + 'width': 'inherit', + 'background-color': 'inherit' + }); + $(this).remove(); + }); + } + } + + $cloneHead = null; + + // 处理 toolbar 事件 + if (toolbar) { + if ($dragBar.children('.active').length > 0 && $dragBar.children('.active').attr('data-type') !== $dragBar.attr('data-type')) { + var targetFix = $dragBar.children('.active').attr('data-type'), + i, j, curPos, targetPos; + for (i = 0; i < myTable.cols.length; i++) { + for (j = 0; j < myTable.cols[i].length; j++) { + if (targetFix === 'right' || (targetFix === 'none' && $dragBar.attr('data-type') === 'right')) { + if (typeof targetPos === 'undefined') { + if (myTable.cols[i][j].fixed === 'right') { + targetPos = {x: i, y: j}; + } else if (j === myTable.cols[i].length - 1) { + targetPos = {x: i, y: j + 1}; + } + + } + } else { + if (typeof targetPos === 'undefined' && (!myTable.cols[i][j].fixed || myTable.cols[i][j].fixed === 'right')) { + targetPos = {x: i, y: j}; + } + } + if (myTable.cols[i][j].key === curKey) { + curPos = {x: i, y: j}; + } + } + } + curColumn['fixed'] = targetFix === 'none' ? false : targetFix; + + if (curPos.y !== targetPos.y) { + myTable.cols[curPos.x].splice(curPos.y, 1); + + if (curPos.y < targetPos.y) { + targetPos.y -= 1 + } + + myTable.cols[targetPos.x].splice(targetPos.y, 0, curColumn) + + _this.fixTableRemember(myTable); + } + table.reload(tableId) + } + $dragBar.removeClass('active') + } + + } else { + $that.unbind('click'); + } + if ($('#column-remove').is(':visible')) { + $tableHead.find('thead>tr>th[data-key=' + key + ']').addClass(HIDE); + $tableBody.find('tbody>tr>td[data-key="' + key + '"]').addClass(HIDE); + $totalTable.find('tbody>tr>td[data-key="' + key + '"]').addClass(HIDE); + // 同步配置 + curColumn['hide'] = true + _this.fixTableRemember(myTable); + // 更新下拉隐藏 + $('#soul-columns' + tableId).find('li[data-value="' + field + '"]>input').prop('checked', false); + tableFilter.resize(myTable) + } + $('#column-remove').hide(); + } + }) + }); + }) + } + }, + rowDrag: function (myTable, rowDragConfig) { + var _this = this, + $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + $fixedBody = $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table'), + $noFixedBody = $tableBox.children('.layui-table-body').children('table'), + $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $fixedBody), + tableId = myTable.id, + isDragging = false, + trigger = rowDragConfig.trigger || 'row', + syncNumber = rowDragConfig.numbers !== false, + numberColumnKey = null, numberStart = 0, + $trs = trigger === 'row' ? $tableBody.children('tbody').children('tr') : $tableBody.find(trigger), + i, j; + if (trigger !== 'row') { + $tableBody.find(trigger).css('cursor', 'move') + } + for (i = 0; i < myTable.cols.length; i++) { + for (j = 0; j < myTable.cols[i].length; j++) { + if (myTable.cols[i][j].type === 'numbers') { + numberColumnKey = myTable.index + '-' + i + '-' + j; + numberStart = parseInt($noFixedBody.find('td[data-key="' + numberColumnKey + '"]:first').text()); + break; + } + } + } + $trs.on('mousedown', function (e) { + // 被暂停 或者 不是鼠标左键 则取消拖拽效果 + if (_this.suspendConfig[tableId].rowDrag || e.button !== 0) { + return; + } + var $this = trigger === 'row' ? $(this) : $(this).parents('tr:eq(0)'), + index = parseInt($this.data('index')), // 被拖拽行索引 + $bodyTr = $noFixedBody.children('tbody').children('tr[data-index=' + index + ']'), // 被拖拽行(非固定列) + $cloneTr = $bodyTr.clone().css('visibility', 'hidden'), // 占位行 + $FixBodyTr = $fixedBody.children('tbody').children('tr[data-index=' + index + ']'), // 被拖拽行(固定列) + bodyScrollTop = $tableBox.children('.layui-table-body').scrollTop(), // 记录当前滚动条位置 + originTop = $this.position().top, // 被拖拽行当前位置 + disY = e.clientY - originTop; // 鼠标距离被拖拽行上侧的距离 + + _BODY.on('mousemove', function (e) { + + // 刚被拖动 + if (!isDragging) { + isDragging = true; + // 设置鼠标样式 + // $table.next().find('style').append('.layui-table-view .layui-table td{cursor: move;}.layui-table tr{transition: none}') + var style = $table.next().find('style')[0], + sheet = style.sheet || style.styleSheet || {}; + _this.addCSSRule(sheet, '.layui-table-view .layui-table td', 'cursor: move') + _this.addCSSRule(sheet, '.layui-table tr', 'transition: none') + + $tableBox.addClass('noselect'); // 禁止选中文本 + + $bodyTr.after($cloneTr); + $bodyTr.css({ + 'position': 'absolute', + 'z-index': 1 + }) + + $FixBodyTr.each(function () { + $(this).after($(this).clone().css('visibility', 'hidden')) + $(this).css({ + 'position': 'absolute', + 'z-index': 102 + }) + }) + } + + var top = e.clientY - disY + ($tableBox.children('.layui-table-body').scrollTop() - bodyScrollTop), // 计算当前被移动行top位置应该哪里 + trTop = $cloneTr.position().top, //当前行所在位置 + $UpTr = $bodyTr.prev(), + hasUpTr = $UpTr.length > 0, + $downTr = $cloneTr.next(), + hasDownTr = $downTr.length > 0, + upMove = hasUpTr && (trTop - top > $UpTr.height() / 2.0), + downMove = hasDownTr && (top - trTop > $downTr.height() / 2.0); + + if (trTop - top > 0 ? !hasUpTr : !hasDownTr) { + $bodyTr.css('top', trTop); + $FixBodyTr.each(function () { + $(this).css('top', trTop); + }) + return; + } + + $bodyTr.css('top', top); + $FixBodyTr.each(function () { + $(this).css('top', top); + }) + + if (upMove) { + updateDataIndex($bodyTr, -1) + $cloneTr.after(updateDataIndex($UpTr, 1)); + $FixBodyTr.each(function () { + updateDataIndex($(this), -1) + $(this).next().after(updateDataIndex($(this).prev(), 1)); + }) + } else if (downMove) { + updateDataIndex($bodyTr, 1).before(updateDataIndex($downTr, -1)) + $FixBodyTr.each(function () { + updateDataIndex($(this), 1); + $(this).before(updateDataIndex($(this).next().next(), -1)); + }) + } + + // 同步 data-index + function updateDataIndex($el, diff) { + var tempIndex = parseInt($el.data('index')) + diff; + $el.data('index', tempIndex); + $el.attr('data-index', tempIndex); + return $el + } + + }).on('mouseup', function (e) { + _BODY.off('mousemove').off('mouseup'); + + if (isDragging) { + isDragging = false; + + $tableBox.removeClass('noselect'); // 取消禁止选中文本 + $bodyTr.css({'position': 'inherit', 'z-index': 'inherit'}); + $bodyTr.next().remove(); + $FixBodyTr.each(function () { + $(this).css({'position': 'inherit', 'z-index': 'inherit'}); + $(this).next().remove() + }) + + // 恢复样式 + var style = $table.next().find('style')[0], + sheet = style.sheet || style.styleSheet || {}, + rules = sheet.cssRules || sheet.rules; + layui.each(rules, function (i, item) { + if (item.selectorText === ('.layui-table-view .layui-table td')) { + item.style.cursor = 'default'; + } + }); + + var newIndex = $this.index(), + cache = table.cache[tableId]; + + if (newIndex !== index) { // 有位置变动 + // 如果 before 返回 false,则还原拖拽 + if (typeof rowDragConfig.before === 'function' + && rowDragConfig.before.call(myTable, { + row: cache[index], + newIndex: newIndex, + oldIndex: index, + cache: cache + }) === false) { + + // 同步 data-index + function updateDataIndex($el, setIndex) { + $el.data('index', setIndex); + $el.attr('data-index', setIndex); + return $el + } + + // 还原位置和索引 + if (newIndex < index) { + for (i = newIndex; i < index; i++) { + updateDataIndex($noFixedBody.find('tr[data-index="'+(i+1)+'"]'), i) + updateDataIndex($fixedBody.find('tr[data-index="'+(i+1)+'"]'), i) + } + updateDataIndex($bodyTr, index) + $noFixedBody.find('tr[data-index="'+(index - 1)+'"]').after($bodyTr) + $FixBodyTr.each(function () { + updateDataIndex($(this), index) + $(this).parent().children('tr[data-index="'+(index - 1)+'"]').after($(this)) + }) + } else { + for (i = newIndex; i > index; i--) { + updateDataIndex($noFixedBody.find('tr[data-index="'+(i-1)+'"]'), i) + updateDataIndex($fixedBody.find('tr[data-index="'+(i-1)+'"]'), i) + } + updateDataIndex($bodyTr, index) + $noFixedBody.find('tr[data-index="'+(index + 1)+'"]').before($bodyTr) + $FixBodyTr.each(function () { + updateDataIndex($(this), index) + $(this).parent().children('tr[data-index="'+(index + 1)+'"]').before($(this)) + }) + } + return; + } + + var row = cache.splice(index, 1)[0]; + cache.splice(newIndex, 0, row); + if (numberColumnKey && syncNumber) { + // 进行序号重排 + var sortedIndexs = [newIndex, index].sort() + for (i = sortedIndexs[0]; i <= sortedIndexs[1]; i++) { + var curIndex = numberStart + i; + $fixedBody.find('td[data-key="' + numberColumnKey + '"]:eq(' + i + ')').children().html(curIndex) + $noFixedBody.find('td[data-key="' + numberColumnKey + '"]:eq(' + i + ')').children().html(curIndex) + cache[i][table.config.indexName] = curIndex - 1 + } + } + if (typeof rowDragConfig.done === 'function') { + + rowDragConfig.done.call(myTable, { + row: row, + newIndex: newIndex, + oldIndex: index, + cache: cache + }) + } + } + + } + }) + }) + }, + fixTableRemember: function (myTable, dict) { + + if (typeof myTable.filter === 'undefined' ? (defaultConfig.filter && defaultConfig.filter.cache) : myTable.filter.cache) { + if (dict && dict.rule) { + var curKey = dict.rule.selectorText.split('-')[3] + '-' + dict.rule.selectorText.split('-')[4]; + for (var i = 0; i < myTable.cols.length; i++) { + for (var j = 0; j < myTable.cols[i].length; j++) { + if (myTable.cols[i][j].key === curKey) { + myTable.cols[i][j].width = dict.rule.style.width.replace('px', ''); + break; + } + } + + } + } + var storeKey = location.pathname + location.hash + myTable.id; + localStorage.setItem(storeKey, this.deepStringify(myTable.cols)) + } + }, + clearCache: function (myTable) { + if (!myTable) { + return; + } + var tableId; + if (typeof myTable === 'object') { + if (typeof myTable.config !== 'undefined') { + tableId = myTable.config.id + } else { + tableId = myTable.id + } + } else { + tableId = myTable + } + localStorage.removeItem(location.pathname + location.hash + tableId) + if (originCols[tableId]) { + this.updateCols(tables[tableId], this.deepClone(originCols[tableId])) + } + }, + overflow: function (myTable, overflowConfig) { + var options = {}; + if (typeof overflowConfig === 'string') { + options = { + type: overflowConfig + } + } else if (typeof overflowConfig === 'object') { + options = overflowConfig + } else { + return; + } + var $table = $(myTable.elem), + layHeader = $table.next().find('.layui-table-header'), + layBody = $table.next().find('.layui-table-body'), + layTotal = $table.next().find('.layui-table-total'), + tooltipIndex, + hoverTime = options.hoverTime || 0, + tooltipTimeOut, + color = options.color || 'white', + bgColor = options.bgColor || 'black', + minWidth = options.minWidth || 300, + maxWidth = options.maxWidth || 300; + + if (options.type === 'tips') { + layBody.off('mouseenter', 'td').off('mouseleave', 'td').on('mouseenter', 'td', function () { + var _this = this; + tooltipTimeOut = setTimeout(function () { + toopTip.call(_this) + }, hoverTime) + }).on('mouseleave', 'td', function () { + toopTip.call(this, 'hide') + }) + if (options.header) { + layHeader.off('mouseenter', 'th').off('mouseleave', 'th').on('mouseenter', 'th', function () { + var _this = this; + tooltipTimeOut = setTimeout(function () { + toopTip.call(_this) + }, hoverTime) + }).on('mouseleave', 'th', function () { + toopTip.call(this, 'hide') + }) + } + if (options.total) { + layTotal.off('mouseenter', 'td').off('mouseleave', 'td').on('mouseenter', 'td', function () { + var _this = this; + tooltipTimeOut = setTimeout(function () { + toopTip.call(_this) + }, hoverTime) + }).on('mouseleave', 'td', function () { + toopTip.call(this, 'hide') + }) + } + + function toopTip(hide) { + clearTimeout(tooltipTimeOut); + var othis = $(this) + , elemCell = othis.children('.layui-table-cell') + , width = elemCell.outerWidth() + , layerWidth = width < minWidth ? minWidth : width > maxWidth ? maxWidth : width; + if (othis.data('off')) return; + + if (hide) { + layer.close(tooltipIndex) + } else if (elemCell.prop('scrollWidth') > width) { + tooltipIndex = layer.tips('' + $(this).text() + '', this, { + tips: [1, bgColor], + maxWidth: layerWidth, + time: 0 + }); + } + } + } else if (options.type === 'title') { + layBody.off('mouseenter', 'td').on('mouseenter', 'td', function () { + var othis = $(this) + , elemCell = othis.children('.layui-table-cell'); + if (othis.data('off')) return; + + if (elemCell.prop('scrollWidth') > elemCell.outerWidth()) { + elemCell.attr('title', $(this).text()) + } + }) + if (options.header) { + layHeader.off('mouseenter', 'th').on('mouseenter', 'th', function () { + var othis = $(this) + , elemCell = othis.children('.layui-table-cell'); + if (othis.data('off')) return; + + if (elemCell.prop('scrollWidth') > elemCell.outerWidth()) { + elemCell.attr('title', $(this).text()) + } + }) + } + if (options.total) { + layTotal.off('mouseenter', 'td').on('mouseenter', 'td', function () { + var othis = $(this) + , elemCell = othis.children('.layui-table-cell'); + if (othis.data('off')) return; + + if (elemCell.prop('scrollWidth') > elemCell.outerWidth()) { + elemCell.attr('title', $(this).text()) + } + }) + } + } + + }, + // 右键菜单配置 + contextmenu: function (myTable, contextmenuConfig) { + var $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + $tableHead = $.merge($tableBox.children('.layui-table-header').children('table'), $tableBox.children('.layui-table-fixed').children('.layui-table-header').children('table')), + $fixedBody = $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table'), + $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $fixedBody), + $totalTable = $table.next().children('.layui-table-total').children('table'), + tableId = myTable.id, + header = contextmenuConfig ? contextmenuConfig.header : '', + body = contextmenuConfig ? contextmenuConfig.body : '', + total = contextmenuConfig ? contextmenuConfig.total : '', + options = { + header: {box: $tableHead, tag: 'th', opts: header, cols: {}}, + body: {box: $tableBody, tag: 'td', opts: body, cols: {}, isBody: true}, + total: {box: $totalTable, tag: 'td', opts: total, cols: {}} + }, + hasColsContext = false; + + for (var i = 0; i < myTable.cols.length; i++) { + for (var j = 0; j < myTable.cols[i].length; j++) { + if (myTable.cols[i][j].contextmenu) { + hasColsContext = true + options.header.cols[myTable.cols[i][j].key] = myTable.cols[i][j].contextmenu.header + options.body.cols[myTable.cols[i][j].key] = myTable.cols[i][j].contextmenu.body + options.total.cols[myTable.cols[i][j].key] = myTable.cols[i][j].contextmenu.total + } + } + } + + if (!contextmenuConfig && !hasColsContext) { + return; + } + + + for (var name in options) { + (function (name) { + options[name].box.find(options[name].tag).on('contextmenu', function (e) { + $('#soul-table-contextmenu-wrapper').remove(); + _BODY.append('
                '); + $('#soul-table-contextmenu-wrapper').on('click', function (e) { + e.stopPropagation() + }) + var curColsOpts = options[name].cols[$(this).data('key')]; + if (curColsOpts === false) { + return false + } else if (curColsOpts && curColsOpts.length > 0) { + genePanel($('#soul-table-contextmenu-wrapper'), e.pageX, e.pageY, curColsOpts, $(this), options[name].box, options[name].tag, options[name].isBody); + return false + } else if (options[name].opts === false) { + return false + } else if (options[name].opts && options[name].opts.length > 0) { + genePanel($('#soul-table-contextmenu-wrapper'), e.pageX, e.pageY, options[name].opts, $(this), options[name].box, options[name].tag, options[name].isBody); + return false + } + }) + })(name) + } + + + _BODY.on('click', function () { + $('#soul-table-contextmenu-wrapper').remove(); + }) + + function genePanel($parent, left, top, options, $this, box, tag, isBody) { + var html = [], i; + + html.push('
                  '); + for (i = 0; i < options.length; i++) { + html.push('
                • ') + if (options[i].icon) { + html.push('') + } else { + html.push('') + } + html.push(options[i].name) + + if (options[i].children && options[i].children.length > 0) { + html.push('') + } + + html.push('
                • ') + } + html.push('
                '); + $parent.append(html.join('')); + var $curPanel = $parent.children().last(); + if (top + $curPanel.outerHeight() > _BODY.prop('scrollHeight')) { + top = top - $curPanel.outerHeight() + if (top < 0) { + top = 0 + } + } + if ($parent.parent().data('direction') === 'left' && ($parent.offset().left - $curPanel.outerWidth()) > 0) { + left = -$curPanel.outerWidth(); + $curPanel.data('direction', 'left') + } else if (left + $curPanel.outerWidth() + $parent.offset().left > _BODY.prop('scrollWidth')) { + left = left - $curPanel.outerWidth() - $parent.outerWidth() + if (left + $parent.offset().left < 0) { + left = -$parent.offset().left + } + $curPanel.data('direction', 'left') + } + $curPanel.css({ + top: top + 'px', + left: left + 'px' + }) + + for (i = 0; i < options.length; i++) { + if (typeof options[i].click === "function") { + (function (i) { + $parent.children('.soul-table-contextmenu:last').children('li[data-index="' + i + '"]').on('click', function () { + var index = $this.parents('tr:eq(0)').data('index'), + tr = box.find('tr[data-index="' + index + '"]'), + row = layui.table.cache[tableId][index]; + + options[i].click.call(myTable, { + cell: $this, + elem: tag === 'th' ? $this : isBody ? box.children('tbody').children('tr[data-index="' + index + '"]').children('[data-key="' + $this.data('key') + '"]') : box.find('[data-key="' + $this.data('key') + '"]'), + trElem: box.children('tbody').children('tr[data-index="' + index + '"]'), + text: $this.text(), + field: $this.data('field'), + del: !isBody ? '' : function () { + table.cache[tableId][index] = []; + tr.remove(); + table.resize(tableId); + }, + update: !isBody ? '' : function (fields) { + fields = fields || {}; + layui.each(fields, function (key, value) { + if (key in row) { + var templet, td = tr.children('td[data-field="' + key + '"]'); + row[key] = value; + table.eachCols(tableId, function (i, item2) { + if (item2.field == key && item2.templet) { + templet = item2.templet; + } + }); + td.children('.layui-table-cell').html(function () { + return templet ? function () { + return typeof templet === 'function' + ? templet(row) + : layui.laytpl($(templet).html() || value).render(row) + }() : value; + }()); + td.data('content', value); + } + }); + }, + row: isBody ? row : {}, + }) + $('#soul-table-contextmenu-wrapper').remove(); + }) + })(i) + } + } + $parent.children('.soul-table-contextmenu:last').children('li').on('mouseenter', function (e) { + e.stopPropagation() + $(this).siblings('.contextmenu-children').children('ul').remove(); + if ($(this).hasClass('contextmenu-children')) { + genePanel($(this), $(this).outerWidth(), $(this).position().top, options[$(this).data('index')].children, $this, box, tag, isBody) + } + }) + } + + }, + fixTotal: function (myTable) { + var $table = $(myTable.elem), + $total = $table.next().children('.layui-table-total'), + style = $table.next().find('style')[0], + sheet = style.sheet || style.styleSheet || {}; + if ($total.length > 0) { + var $tableBox = $table.next().children('.layui-table-box'), + $fixedLeft = $tableBox.children('.layui-table-fixed-l').children('.layui-table-body').children('table').children('tbody').children('tr:eq(0)').children('td'), + $fixedRight = $tableBox.children('.layui-table-fixed-r').children('.layui-table-body').children('table').children('tbody').children('tr:eq(0)').children('td'), + html = []; + + $total.children('.layui-table-total-fixed').remove() + + if ($fixedLeft.length > 0) { + this.addCSSRule(sheet, '.layui-table-total-fixed-l .layui-table-patch', 'display: none') + $table.next().css('position', 'relative'); + html.push(''); + $fixedLeft.each(function () { + if ($(this).data('key')) { + html.push($total.children('table:eq(0)').find('[data-key="' + $(this).data('key') + '"]').prop("outerHTML")) + } + }) + html.push('
                '); + $total.append(html.join('')) + } + if ($fixedRight.length > 0) { + this.addCSSRule(sheet, '.layui-table-total-fixed-r td:first-child', 'border-left:1px solid #e6e6e6') + this.addCSSRule(sheet, '.layui-table-total-fixed-r td:last-child', 'border-left: none') + $table.next().css('position', 'relative'); + html = []; + html.push(''); + $fixedRight.each(function () { + html.push($total.children('table:eq(0)').find('[data-key="' + $(this).data('key') + '"]').prop("outerHTML")) + }) + html.push('
                ') + $total.append(html.join('')) + } + } + + }, + fixResizeRightFixed: function (myTable) { + var _this = this, + $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + $fixedHead = $tableBox.children('.layui-table-fixed-r').children('.layui-table-header').children('table'), + dict = {}, resizing, ELEM_SORT = 'layui-table-sort', + ELEM_NO_SORT = 'layui-table-sort-invalid'; + if ($fixedHead.length > 0) { + $fixedHead.find('th').off('mousemove').on('mousemove', function (e) { + var othis = $(this) + , oLeft = othis.offset().left + , pLeft = e.clientX - oLeft; + if (othis.data('unresize') || dict.resizeStart) { + return; + } + if (othis.width() - pLeft <= 10) { + _BODY.css('cursor', 'initial') + } + dict.allowResize = pLeft <= 10; //是否处于拖拽允许区域 + _BODY.css('cursor', (dict.allowResize ? 'col-resize' : '')); + }).off('mousedown').on('mousedown', function (e) { + var othis = $(this); + if (dict.allowResize) { + othis.find('.' + ELEM_SORT).removeClass(ELEM_SORT).addClass(ELEM_NO_SORT) + var key = othis.data('key'); + e.preventDefault(); + dict.resizeStart = true; //开始拖拽 + dict.offset = [e.clientX, e.clientY]; //记录初始坐标 + + _this.getCssRule(myTable, key, function (item) { + var width = item.style.width || othis.outerWidth(); + dict.rule = item; + dict.ruleWidth = parseFloat(width); + dict.othis = othis; + dict.minWidth = othis.data('minwidth') || myTable.cellMinWidth; + }); + } + }); + //拖拽中 + _DOC.on('mousemove', function (e) { + if (dict.resizeStart) { + layui.soulTable.fixTableRemember(myTable, dict) + e.preventDefault(); + if (dict.rule) { + var setWidth = dict.ruleWidth - e.clientX + dict.offset[0]; + if (setWidth < dict.minWidth) setWidth = dict.minWidth; + dict.rule.style.width = setWidth + 'px'; + } + resizing = 1 + } + }).on('mouseup', function (e) { + if (dict.resizeStart) { + setTimeout(function () { + dict.othis.find('.' + ELEM_NO_SORT).removeClass(ELEM_NO_SORT).addClass(ELEM_SORT) + _BODY.css('cursor', ''); + dict = {}; + _this.scrollPatch(myTable); + }, 30) + } + if (resizing === 2) { + resizing = null; + } + }); + } + }, + fixFixedScroll: function (myTable) { + var $table = $(myTable.elem), + layFixed = $table.next().children('.layui-table-box').children('.layui-table-fixed'), + layMain = $table.next().children('.layui-table-box').children('.layui-table-main'); + + layFixed.on('mouseenter', function () { + $(this).children('.layui-table-body').addClass('soul-fixed-scroll').on('scroll', function () { + var scrollTop = $(this).scrollTop() + // layFixed.children('.layui-table-body[class!="soul-fixed-scroll"]').scrollTop(scrollTop); + layMain.scrollTop(scrollTop); + }) + }).on('mouseleave', function () { + $(this).children('.layui-table-body').removeClass('soul-fixed-scroll').off('scroll'); + }) + }, + scrollPatch: function (myTable) { + var $table = $(myTable.elem), + layHeader = $table.next().children('.layui-table-box').children('.layui-table-header'), + layTotal = $table.next().children('.layui-table-total'), + layMain = $table.next().children('.layui-table-box').children('.layui-table-main'), + layFixed = $table.next().children('.layui-table-box').children('.layui-table-fixed'), + layFixRight = $table.next().children('.layui-table-box').children('.layui-table-fixed-r'), + layMainTable = layMain.children('table'), + scollWidth = layMain.width() - layMain.prop('clientWidth'), + scollHeight = layMain.height() - layMain.prop('clientHeight'), + outWidth = layMainTable.outerWidth() - layMain.width() //表格内容器的超出宽度 + + //添加补丁 + , addPatch = function (elem) { + if (scollWidth && scollHeight) { + elem = elem.eq(0); + if (!elem.find('.layui-table-patch')[0]) { + var patchElem = $('
                '); //补丁元素 + patchElem.find('div').css({ + width: scollWidth + }); + elem.find('tr').append(patchElem); + } + } else { + elem.find('.layui-table-patch').remove(); + } + } + + addPatch(layHeader); + addPatch(layTotal); + + //固定列区域高度 + var mainHeight = layMain.height() + , fixHeight = mainHeight - scollHeight; + layFixed.find('.layui-table-body').css('height', layMainTable.height() >= fixHeight ? fixHeight : 'auto'); + + //表格宽度小于容器宽度时,隐藏固定列 + layFixRight[outWidth > 0 ? 'removeClass' : 'addClass'](HIDE); + + //操作栏 + layFixRight.css('right', scollWidth - 1); + }, + /** + * 一键粘贴 + * @param {String} text [需要 copy 的属性,默认是 innerText,主要用途例如赋值 a 标签上的 href 链接] + * + * range + selection + * + * 1.创建一个 range + * 2.把内容放入 range + * 3.把 range 放入 selection + * + * 注意:参数 attr 不能是自定义属性 + * 注意:对于 user-select: none 的元素无效 + * 注意:当 id 为 false 且 attr 不会空,会直接复制 attr 的内容 + */ + copy: function (text) { + var target; + + if (text) { + target = document.createElement('div'); + target.id = 'tempTarget'; + target.style.opacity = '0'; + target.innerText = text; + document.body.appendChild(target); + } else { + target = document.querySelector('#' + id); + } + + try { + var range = document.createRange(); + range.selectNode(target); + window.getSelection().removeAllRanges(); + window.getSelection().addRange(range); + document.execCommand('copy'); + window.getSelection().removeAllRanges(); + } catch (e) { + console.log('复制失败') + } + + if (text) { + // remove temp target + target.parentElement.removeChild(target); + } + }, + addCSSRule: function (sheet, selector, rules, index) { + if ('insertRule' in sheet) { + sheet.insertRule(selector + '{' + rules + '}', index) + } else if ('addRule' in sheet) { + sheet.addRule(selector, rules, index) + } + }, + deepStringify: function (obj) { + var JSON_SERIALIZE_FIX = { + PREFIX: "[[JSON_FUN_PREFIX_", + SUFFIX: "_JSON_FUN_SUFFIX]]" + }; + return JSON.stringify(obj, function (key, value) { + if (typeof value === 'function') { + return JSON_SERIALIZE_FIX.PREFIX + value.toString() + JSON_SERIALIZE_FIX.SUFFIX; + } + return value; + }); + }, + deepParse: function (str) { + var JSON_SERIALIZE_FIX = { + PREFIX: "[[JSON_FUN_PREFIX_", + SUFFIX: "_JSON_FUN_SUFFIX]]" + }; + return JSON.parse(str, function (key, value) { + if (typeof value === 'string' && + value.indexOf(JSON_SERIALIZE_FIX.SUFFIX) > 0 && value.indexOf(JSON_SERIALIZE_FIX.PREFIX) === 0) { + return eval("(" + value.replace(JSON_SERIALIZE_FIX.PREFIX, "").replace(JSON_SERIALIZE_FIX.SUFFIX, "") + ")"); + } + return value; + }) || {}; + }, + clearFilter: function (myTable) { + tableFilter.clearFilter(myTable); + }, + cache: tableFilter.cache, + // 深度克隆-不丢失方法 + deepClone: function (obj) { + var newObj = Array.isArray(obj) ? [] : {} + if (obj && typeof obj === "object") { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + newObj[key] = (obj && typeof obj[key] === 'object') ? this.deepClone(obj[key]) : obj[key]; + } + } + } + return newObj + }, + clearOriginCols: function (tableId) { + if (tableId) { + delete originCols[tableId] + } else { + originCols = {} + } + }, + suspendConfig: {}, + /** + * 暂停某个特性 + * @param tableId + * @param type 暂停的类型,支持 'drag' 'rowDrag' + * @param value true/false + */ + suspend: function (tableId, type, value) { + this.suspendConfig[tableId][type] = value + } + } + + // 输出 + exports('soulTable', mod); +}); diff --git a/WaterCloud.Web/wwwroot/js/lay-module/soulTable/soulTable.slim.js b/WaterCloud.Web/wwwroot/js/lay-module/soulTable/soulTable.slim.js new file mode 100644 index 0000000..93cfb88 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/soulTable/soulTable.slim.js @@ -0,0 +1,1549 @@ +/** + * + * @name: 表格增强插件-独立版本 + * @author: yelog + * @link: https://github.com/yelog/layui-soul-table + * @license: MIT + * @version: v1.9.0 + */ +layui.define(['table'], function (exports) { + + var $ = layui.$, + table = layui.table, + HIDE = 'layui-hide', + tables = {}, + originCols = {}, + defaultConfig = { // 默认配置开关 + fixTotal: false, // 修复合计行固定列问题 + drag: true, // 列拖动 + rowDrag: false, // 行拖动 + autoColumnWidth: true, // 自动列宽 + contextmenu: false, // 右键菜单 + fixResize: true, // 修改有固定列的拖动列宽的位置为左边线 + overflow: false, // 自定义内容超出样式 + fixFixedScroll: true, // 固定列支持鼠标滚轮滚动 + filter: false // 筛选及记忆相关 + }, + _BODY = $('body'), + _DOC = $(document); + + // 封装方法 + var mod = { + render: function (myTable) { + // 记录表格配置,方便直接通过 tableId 调用方法 + tables[myTable.id] = myTable + var curConfig = $.extend({}, defaultConfig, myTable); + if (curConfig.filter && curConfig.filter.cache) { + var storeKey = location.pathname + location.hash + myTable.id; + var colsStr = this.deepStringify(myTable.cols); + // 记录表格列的原始配置 + if (!originCols[myTable.id]) { // 只在第一次 render 时生效 + originCols[myTable.id] = this.deepClone(myTable.cols) + + var curTableSession = localStorage.getItem(storeKey); + if (curTableSession && colsStr === localStorage.getItem('origin' + storeKey)) { + this.updateCols(myTable, this.deepParse(curTableSession)); + } else { + localStorage.setItem('origin' + storeKey, colsStr) + localStorage.removeItem(storeKey) + } + } + } else { + // 如果没有开启记忆,则清除 + this.clearCache(myTable); + } + // 初始化暂停配置 + this.suspendConfig[myTable.id] = { + drag: false, + rowDrag: false + } + // 修复合计栏固定列问题 + if (curConfig.fixTotal) { + this.fixTotal(myTable) + } + if (curConfig.drag) { + this.drag(myTable, curConfig.drag); + } + if (curConfig.rowDrag) { + this.rowDrag(myTable, curConfig.rowDrag) + } + if (curConfig.autoColumnWidth) { + this.autoColumnWidth(myTable, curConfig.autoColumnWidth) + } + + this.contextmenu(myTable, curConfig.contextmenu); + + if (curConfig.fixResize) { + this.fixResizeRightFixed(myTable); + } + + if (curConfig.overflow) { + this.overflow(myTable, curConfig.overflow); + } + + if (curConfig.fixFixedScroll) { + this.fixFixedScroll(myTable); + } + } + , config: function (configObj) { + if (typeof configObj === 'object') { + $.extend(true, defaultConfig, configObj); + } + } + , updateCols: function (myTable, cols) { + var i, j, lastKeyMap = {}, columnKey, newCols = [], col = [], + $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + $fixedHead = $tableBox.children('.layui-table-fixed').children('.layui-table-header').children('table'), + $tableHead = $.merge($tableBox.children('.layui-table-header').children('table'), $fixedHead), + $noFixedHead = $tableBox.children('.layui-table-header').children('table'), + $fixedBody = $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table'), + $noFixedBody = $tableBox.children('.layui-table-body').children('table'), + $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $fixedBody); + + for (i = 0; i < myTable.cols.length; i++) { + for (j = 0; j < myTable.cols[i].length; j++) { + myTable.cols[i][j]['oldPos'] = i + '-' + j + lastKeyMap[myTable.cols[i][j].key] = myTable.cols[i][j] + } + } + + for (i = 0; i < cols.length; i++) { + col = [] + for (j = 0; j < cols[i].length; j++) { + columnKey = cols[i][j].key; + // 同步列宽 + if (cols[i][j].width && lastKeyMap[cols[i][j].key] !== cols[i][j].width) { + this.getCssRule(myTable, columnKey, function (item) { + item.style.width = (cols[i][j].width ? cols[i][j].width : 0) + 'px' + }) + } + // 同步隐藏 + if (lastKeyMap[cols[i][j].key].hide !== cols[i][j].hide) { + $tableHead.find('th[data-key="' + columnKey + '"]')[cols[i][j].hide ? 'addClass' : 'removeClass']('layui-hide') + $tableBody.find('td[data-key="' + columnKey + '"]')[cols[i][j].hide ? 'addClass' : 'removeClass']('layui-hide') + } + + // 同步顺序 + if (lastKeyMap[cols[i][j].key].oldPos !== (i + '-' + j) || lastKeyMap[cols[i][j].key].fixed !== cols[i][j].fixed) { + myTable.cols = cols; + table.reload(myTable.id) + return; + // 实现不 reload 调整列顺序 + + } + lastKeyMap[cols[i][j].key].fixed = cols[i][j].fixed; + lastKeyMap[cols[i][j].key].width = cols[i][j].width; + lastKeyMap[cols[i][j].key].hide = cols[i][j].hide; + col.push(lastKeyMap[cols[i][j].key]) + } + newCols.push(col) + } + $noFixedHead.children().children('tr').each(function () { + innerHandler(this, 'th') + }) + $noFixedBody.children().children('tr').each(function () { + innerHandler(this, 'td') + }) + + function innerHandler(_this, domName) { + for (i = 0; i < cols.length; i++) { + for (j = 0; j < cols[i].length; j++) { + columnKey = myTable.index + '-' + cols[i][j].key; + var curKey = $(_this).children(domName + ':eq(' + j + ')').attr('data-key'); + if (curKey !== columnKey) { + $(_this).children(domName + ':eq(' + j + ')').before($(_this).children(domName + '[data-key="' + columnKey + '"]')) + if (cols[i][j].fixed) { + var $curRow = (domName === 'th' ? $fixedHead : $fixedBody).children().children(domName === 'th' ? 'tr' : 'tr[data-index="' + $(_this).attr('data-index') + '"]') + $curRow.children(domName + '[data-key="' + curKey + '"]').before($curRow.children(domName + '[data-key="' + columnKey + '"]')) + } + } + } + } + } + + myTable.cols = newCols; + table.resize(myTable.id) + } + , getCssRule: function (that, key, callback) { + var style = that.elem.next().find('style')[0] + , sheet = style.sheet || style.styleSheet || {} + , rules = sheet.cssRules || sheet.rules; + layui.each(rules, function (i, item) { + if (item.selectorText === ('.laytable-cell-' + key)) { + return callback(item), true; + } + }); + } + , autoColumnWidth: function (myTable, autoColumnWidthConfig) { + var _this = this; + if (typeof myTable === 'object') { + innerColumnWidth(_this, myTable) + } else if (typeof myTable === 'string') { + innerColumnWidth(_this, tables[myTable]) + } else if (typeof myTable === 'undefined') { + layui.each(tables, function () { + innerColumnWidth(_this, this) + }); + } + + function innerColumnWidth(_this, myTable) { + var $table = $(myTable.elem), + th = $table.next().children('.layui-table-box').children('.layui-table-header').children('table').children('thead').children('tr').children('th'), + fixTh = $table.next().children('.layui-table-box').children('.layui-table-fixed').children('.layui-table-header').children('table').children('thead').children('tr').children('th'), + $tableBodytr = $table.next().children('.layui-table-box').children('.layui-table-body').children('table').children('tbody').children('tr'), + $totalTr = $table.next().children('.layui-table-total').find('tr'); + String.prototype.width = function (font) { + var f = font || _BODY.css('font'), + o = $('
                ' + this + '
                ') + .css({ + 'position': 'absolute', + 'float': 'left', + 'white-space': 'nowrap', + 'visibility': 'hidden', + 'font': f + }) + .appendTo(_BODY), + w = o.width(); + + o.remove(); + return w; + } + if (typeof autoColumnWidthConfig === 'undefined' || typeof autoColumnWidthConfig.dblclick === 'undefined' || autoColumnWidthConfig.dblclick) { + th.add(fixTh).on('dblclick', function (e) { + var othis = $(this), + pLeft = e.clientX - othis.offset().left; + handleColumnWidth(myTable, othis, othis.parents('.layui-table-fixed-r').length > 0 ? pLeft <= 10 : othis.width() - pLeft <= 10); + }) + } + // 初始化表格后,自动调整所有列宽 + if (autoColumnWidthConfig && autoColumnWidthConfig.init) { + th.add(fixTh).each(function (e) { + var colKey = $(this).attr('data-key').split('-') + if (myTable.cols[colKey[1]][colKey[2]].autoWidth !== false && (!Array.isArray(autoColumnWidthConfig.init) || autoColumnWidthConfig.init.indexOf($(this).attr('data-field')) !== -1)) { + handleColumnWidth(myTable, $(this), true); + } + }) + } + + function handleColumnWidth(myTable, othis, isHandle) { + var key = othis.data('key') + if (othis.attr('colspan') > 1 || othis.data('unresize')) { + return; + } + if (isHandle) { + var maxWidth = othis.text().width(othis.css('font')) + 21, font = othis.css('font'); + $tableBodytr.children('td[data-key="' + key + '"]').each(function (index, elem) { + var curWidth = 0 + if ($(this).children().children() && $(this).children().children().length > 0) { + curWidth += $(this).children().html().width(font) + } else { + curWidth = $(this).text().width(font); + } + + // var curWidth = $(this).text().width(font); + if (maxWidth < curWidth) { + maxWidth = curWidth + } + }) + if ($totalTr.length > 0) { + var curWidth = $totalTr.children('td[data-key="' + key + '"]').text().width(font) + if (maxWidth < curWidth) { + maxWidth = curWidth + } + + } + + maxWidth += 32; + + _this.getCssRule(myTable, key, function (item) { + item.style.width = maxWidth + 'px' + }); + for (var i = 0; i < myTable.cols.length; i++) { + for (var j = 0; j < myTable.cols[i].length; j++) { + if (myTable.cols[i][j].key === key) { + myTable.cols[i][j].width = maxWidth; + break; + } + } + } + } + } + } + } + /** + * 左右拖拽调整列顺序、向上拖隐藏列 + * @param myTable + */ + , drag: function (myTable, dragConfig) { + if (myTable.cols.length > 1) { + // 如果是复杂表头,则自动禁用拖动效果 + return; + } + var _this = this, + $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + $tableHead = $.merge($tableBox.children('.layui-table-header').children('table'), $tableBox.children('.layui-table-fixed').children('.layui-table-header').children('table')), + $fixedBody = $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table'), + $noFixedBody = $tableBox.children('.layui-table-body').children('table'), + $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $fixedBody), + $totalTable = $table.next().children('.layui-table-total').children('table'), + $fixedTotalTable = $table.next().children('.layui-table-total').children('table.layui-table-total-fixed'), + $noFixedTotalTable = $table.next().children('.layui-table-total').children('table:eq(0)'), + tableId = myTable.id, + isSimple = dragConfig === 'simple' || (dragConfig && dragConfig.type === 'simple'), // 是否为简易拖拽 + toolbar = dragConfig && dragConfig.toolbar, // 是否开启工具栏 + isDragging = false, isStart = false; + + if (!$tableHead.attr('drag')) { + $tableHead.attr('drag', true); + if (toolbar) { + $tableBox.append('
                左固定
                不固定
                右固定
                ') + var $dragBar = $tableBox.children('.soul-drag-bar'); + $dragBar.children('div').on('mouseenter', function () { + $(this).addClass('active') + }).on('mouseleave', function () { + $(this).removeClass('active') + }) + } + + $tableHead.find('th').each(function () { + var $this = $(this), + field = $this.data('field'), + key = $this.data('key'); + if (!key) { + return; + } + + var keyArray = key.split('-'), + curColumn = myTable.cols[keyArray[1]][keyArray[2]], + curKey = myTable.index + '-' + keyArray[1] + '-' + keyArray[2], + isInFixed = $this.parents('.layui-table-fixed').length > 0; + // 绑定鼠标按下事件 + $(this).find('span:first,.laytable-cell-checkbox') + .css('cursor', 'move') + .on('mousedown', function (e) { + // 暂停或者非鼠标左键都不执行 + if (_this.suspendConfig[tableId].drag || e.button !== 0) { + return; + } + e.preventDefault(); + var $cloneHead = $this.clone().css('visibility', 'hidden'), + originLeft = $this.position().left, + originTop = $this.offset().top, + disX = e.clientX - originLeft, // 鼠标距离被移动元素左侧的距离 + color = $this.parents('tr:eq(0)').css("background-color"), + width = $this.width(), moveDistince = 0, + $that = $(this), + isFixed = curColumn.fixed; + isStart = true; + //区分click、drag事件 + + + // 阻止文本选中 + _DOC.bind("selectstart", function () { + return false; + }); + + // 移动事件 + _BODY.on('mousemove', function (e) { + if (isStart && $cloneHead) { + $tableBox.removeClass('no-left-border'); + if (!isDragging) { + if (toolbar) { + $dragBar.attr('data-type', isFixed || 'none') + $dragBar.addClass('active') + } + + $this.after($cloneHead); + $this.addClass('isDrag').css({ + 'position': 'absolute', + 'z-index': 1, + 'border-left': '1px solid #e6e6e6', + 'background-color': color, + 'width': width + 1 + }); + + if (isSimple) { + //设置蒙板 + } else { + (isInFixed ? $fixedBody : $tableBody).find('td[data-key="' + key + '"]').each(function () { + $(this).after($(this).clone().css('visibility', 'hidden').attr('data-clone', '')); + $(this).addClass('isDrag').css({ + 'position': 'absolute', + 'z-index': 1, + 'border-left': '1px solid #e6e6e6', + 'background-color': $(this).css('background-color'), + 'width': width + 1 + }); + }) + if ($totalTable.length > 0) { + (isInFixed ? $fixedTotalTable : $totalTable).find('td[data-key="' + key + '"]').each(function () { + $(this).after($(this).clone().css('visibility', 'hidden').attr('data-clone', '')); + $(this).addClass('isDrag').css({ + 'position': 'absolute', + 'z-index': 1, + 'background-color': $(this).parents('tr:eq(0)').css('background-color'), + 'width': width + 1 + }); + }) + } + } + } + isDragging = true; + var x, y, i, j, tempCols, + left = e.clientX - disX, // 计算当前被移动列左侧位置应该哪里 + $leftTh = $cloneHead.prev().prev(), + hasLeftTh = $leftTh.length > 0, + leftKey = hasLeftTh ? $leftTh.data('key').split('-') : [], + $rightTh = $cloneHead.next().hasClass('layui-table-patch') ? [] : $cloneHead.next(), + hasRightTh = $rightTh.length > 0, + rightKey = hasRightTh ? $rightTh.data('key').split('-') : [], + leftMove = hasLeftTh && ($cloneHead.position().left - left > $leftTh.width() / 2.0), + rightMove = hasRightTh && (left - $cloneHead.position().left > $rightTh.width() / 2.0); + moveDistince = Math.abs($cloneHead.position().left - left); //记录移动距离 + // 移动到左右两端、checbox/radio 固定列等停止移动 + if ($cloneHead.position().left - left > 0 + ? !hasLeftTh || !!isFixed !== !!myTable.cols[leftKey[1]][leftKey[2]].fixed + : !hasRightTh || !!isFixed !== !!myTable.cols[rightKey[1]][rightKey[2]].fixed) { + $this.css('left', $cloneHead.position().left); + $tableBody.find('td[data-key="' + key + '"][data-clone]').each(function (e) { + $(this).prev().css('left', $cloneHead.position().left); + }) + if ($totalTable.length > 0) { + $totalTable.find('td[data-key="' + key + '"][data-clone]').each(function (e) { + $(this).prev().css('left', $cloneHead.position().left); + }) + } + $tableBox.addClass('no-left-border'); + return; + } + $this.css('left', left); + + if (leftMove) { + $cloneHead.after($leftTh); + + // 更新隐藏列顺序 + $('#soul-columns' + tableId + '>li[data-value="' + field + '"]').after($('#soul-columns' + tableId + '>li[data-value="' + field + '"]').prev()) + + // 更新配置信息 + for (i = 0; i < myTable.cols.length; i++) { + for (j = 0; j < myTable.cols[i].length; j++) { + if (myTable.cols[i][j].key === curKey) { + x = i; + y = j; + break; + } + } + if (typeof x !== 'undefined' && typeof y !== 'undefined') { + break; + } + } + tempCols = myTable.cols[x][y - 1]; + myTable.cols[x][y - 1] = myTable.cols[x][y]; + myTable.cols[x][y] = tempCols; + _this.fixTableRemember(myTable); + } else if (rightMove) { + $cloneHead.prev().before($rightTh); + + // 更新隐藏列顺序 + $('#soul-columns' + tableId + '>li[data-value="' + field + '"]').before($('#soul-columns' + tableId + '>li[data-value="' + field + '"]').next()) + + // 更新配置信息 + for (i = 0; i < myTable.cols.length; i++) { + for (j = 0; j < myTable.cols[i].length; j++) { + if (myTable.cols[i][j].key === curKey) { + x = i; + y = j; + break; + } + } + if (typeof x !== 'undefined' && typeof y !== 'undefined') { + break; + } + } + tempCols = myTable.cols[x][y + 1]; + myTable.cols[x][y + 1] = myTable.cols[x][y]; + myTable.cols[x][y] = tempCols; + _this.fixTableRemember(myTable); + } + + $tableBody.find('td[data-key="' + key + '"][data-clone]').each(function () { + $(this).prev().css('left', left); + + if (leftMove) { + if ($(this).prev().prev().length !== 0) { + $(this).after($(this).prev().prev()); + } + } else if (rightMove) { + if ($(this).next().length !== 0) { + $(this).prev().before($(this).next()); + } + } + }) + if ($totalTable.length > 0) { + $totalTable.find('td[data-key="' + key + '"][data-clone]').each(function () { + $(this).prev().css('left', left); + + if (leftMove) { + if ($(this).prev().prev().length !== 0) { + $(this).after($(this).prev().prev()); + } + } else if (rightMove) { + if ($(this).next().length !== 0) { + $(this).prev().before($(this).next()); + } + } + }) + } + + /* 拖动隐藏列 */ + if (e.clientY - originTop < -15) { + if ($('#column-remove').length === 0) { + _BODY.append('') + } + $('#column-remove').css({ + top: e.clientY - $('#column-remove').height() / 2, + left: e.clientX - $('#column-remove').width() / 2, + 'font-size': (originTop - e.clientY) + 'px' + }) + $('#column-remove').show(); + } else { + $('#column-remove').hide(); + } + } + }).on('mouseup', function () { + _DOC.unbind("selectstart"); + _BODY.off('mousemove').off('mouseup') + if (isStart && $cloneHead) { + isStart = false; + if (isDragging) { + if (curColumn.type !== 'checkbox') { + $that.on('click', function (e) { + e.stopPropagation(); + }); + } + + isDragging = false; + $tableBox.removeClass('no-left-border') + $this.removeClass('isDrag').css({ + 'position': 'relative', + 'z-index': 'inherit', + 'left': 'inherit', + 'border-left': 'inherit', + 'width': 'inherit', + 'background-color': 'inherit' + }); + $this.next().remove(); + var prefKey = $this.prev().data('key'); + if (isFixed) { + var $noFixedTh = $tableBox.children('.layui-table-header').children('table').find('th[data-key="' + key + '"]'); + if (prefKey) { + $noFixedTh.parent().children('th[data-key="' + prefKey + '"]').after($noFixedTh) + } else { + if (isFixed === 'right') { + if ($this.siblings().length > 0) { + $tableBox.children('.layui-table-header').children('table').find('th[data-key="' + $this.next().data('key') + '"]').prev().after($noFixedTh); + } + } else { + $noFixedTh.parent().prepend(''); + $noFixedTh.parent().children('th:first').after($noFixedTh); + $noFixedTh.parent().children('th:first').remove(); + } + + } + } + if (isSimple) { + $tableBody.find('td[data-key="' + key + '"]').each(function () { + if (prefKey) { + $(this).parent().children('td[data-key="' + prefKey + '"]').after($(this)) + } else { + if (isFixed === 'right') { + if ($this.siblings().length > 0) { + var $preTd = $(this).parent().children('td[data-key="' + $this.next().data('key') + '"]').prev(); + if ($preTd.length > 0) { + $preTd.after($(this)); + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } + }); + if ($totalTable.length > 0) { + $totalTable.find('td[data-key="' + key + '"]').each(function () { + if (prefKey) { + $(this).parent().children('td[data-key="' + prefKey + '"]').after($(this)) + } else { + if (isFixed === 'right') { + var $preTd = $(this).parent().children('td[data-key="' + $this.next().data('key') + '"]').prev(); + if ($preTd.length > 0) { + $preTd.after($(this)); + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } + }); + } + } else if (isInFixed) { + $noFixedBody.find('td[data-key="' + key + '"]').each(function () { + if (prefKey) { + $(this).parent().children('td[data-key="' + prefKey + '"]').after($(this)) + } else { + if (isFixed === 'right') { + if ($this.siblings().length > 0) { + var $preTd = $(this).parent().children('td[data-key="' + $this.next().data('key') + '"]').prev(); + if ($preTd.length > 0) { + $preTd.after($(this)); + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } + }); + $fixedBody.find('td[data-key="' + key + '"][data-clone]').each(function () { + $(this).prev().removeClass('isDrag').css({ + 'position': 'relative', + 'z-index': 'inherit', + 'left': 'inherit', + 'border-left': 'inherit', + 'width': 'inherit', + 'background-color': 'inherit' + }); + $(this).remove(); + }); + if ($totalTable.length > 0) { + $noFixedTotalTable.find('td[data-key="' + key + '"]').each(function () { + if (prefKey) { + $(this).parent().children('td[data-key="' + prefKey + '"]').after($(this)) + } else { + if (isFixed === 'right') { + var $preTd = $(this).parent().children('td[data-key="' + $this.next().data('key') + '"]').prev(); + if ($preTd.length > 0) { + $preTd.after($(this)); + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } else { + $(this).parent().prepend(''); + $(this).parent().children('td:first').after($(this)); + $(this).parent().children('td:first').remove(); + } + } + }); + $fixedTotalTable.find('td[data-key="' + key + '"][data-clone]').each(function () { + $(this).prev().removeClass('isDrag').css({ + 'position': 'relative', + 'z-index': 'inherit', + 'left': 'inherit', + 'width': 'inherit', + 'background-color': 'inherit' + }); + $(this).remove(); + }); + } + } else { + $tableBody.find('td[data-key="' + key + '"][data-clone]').each(function () { + $(this).prev().removeClass('isDrag').css({ + 'position': 'relative', + 'z-index': 'inherit', + 'left': 'inherit', + 'width': 'inherit', + 'background-color': 'inherit' + }); + $(this).remove(); + }); + if ($totalTable.length > 0) { + $totalTable.find('td[data-key="' + key + '"][data-clone]').each(function () { + $(this).prev().removeClass('isDrag').css({ + 'position': 'relative', + 'z-index': 'inherit', + 'left': 'inherit', + 'width': 'inherit', + 'background-color': 'inherit' + }); + $(this).remove(); + }); + } + } + + $cloneHead = null; + + // 处理 toolbar 事件 + if (toolbar) { + if ($dragBar.children('.active').length > 0 && $dragBar.children('.active').attr('data-type') !== $dragBar.attr('data-type')) { + var targetFix = $dragBar.children('.active').attr('data-type'), + i, j, curPos, targetPos; + for (i = 0; i < myTable.cols.length; i++) { + for (j = 0; j < myTable.cols[i].length; j++) { + if (targetFix === 'right' || (targetFix === 'none' && $dragBar.attr('data-type') === 'right')) { + if (typeof targetPos === 'undefined') { + if (myTable.cols[i][j].fixed === 'right') { + targetPos = {x: i, y: j}; + } else if (j === myTable.cols[i].length - 1) { + targetPos = {x: i, y: j + 1}; + } + + } + } else { + if (typeof targetPos === 'undefined' && (!myTable.cols[i][j].fixed || myTable.cols[i][j].fixed === 'right')) { + targetPos = {x: i, y: j}; + } + } + if (myTable.cols[i][j].key === curKey) { + curPos = {x: i, y: j}; + } + } + } + curColumn['fixed'] = targetFix === 'none' ? false : targetFix; + + if (curPos.y !== targetPos.y) { + myTable.cols[curPos.x].splice(curPos.y, 1); + + if (curPos.y < targetPos.y) { + targetPos.y -= 1 + } + + myTable.cols[targetPos.x].splice(targetPos.y, 0, curColumn) + + _this.fixTableRemember(myTable); + } + table.reload(tableId) + } + $dragBar.removeClass('active') + } + + } else { + $that.unbind('click'); + } + if ($('#column-remove').is(':visible')) { + $tableHead.find('thead>tr>th[data-key=' + key + ']').addClass(HIDE); + $tableBody.find('tbody>tr>td[data-key="' + key + '"]').addClass(HIDE); + $totalTable.find('tbody>tr>td[data-key="' + key + '"]').addClass(HIDE); + // 同步配置 + curColumn['hide'] = true + _this.fixTableRemember(myTable); + // 更新下拉隐藏 + $('#soul-columns' + tableId).find('li[data-value="' + field + '"]>input').prop('checked', false); + } + $('#column-remove').hide(); + } + }) + }); + }) + } + }, + rowDrag: function (myTable, rowDragConfig) { + var _this = this, + $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + $fixedBody = $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table'), + $noFixedBody = $tableBox.children('.layui-table-body').children('table'), + $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $fixedBody), + tableId = myTable.id, + isDragging = false, + trigger = rowDragConfig.trigger || 'row', + syncNumber = rowDragConfig.numbers !== false, + numberColumnKey = null, numberStart = 0, + $trs = trigger === 'row' ? $tableBody.children('tbody').children('tr') : $tableBody.find(trigger), + i, j; + if (trigger !== 'row') { + $tableBody.find(trigger).css('cursor', 'move') + } + for (i = 0; i < myTable.cols.length; i++) { + for (j = 0; j < myTable.cols[i].length; j++) { + if (myTable.cols[i][j].type === 'numbers') { + numberColumnKey = myTable.index + '-' + i + '-' + j; + numberStart = parseInt($noFixedBody.find('td[data-key="' + numberColumnKey + '"]:first').text()); + break; + } + } + } + $trs.on('mousedown', function (e) { + // 被暂停 或者 不是鼠标左键 则取消拖拽效果 + if (_this.suspendConfig[tableId].rowDrag || e.button !== 0) { + return; + } + var $this = trigger === 'row' ? $(this) : $(this).parents('tr:eq(0)'), + index = parseInt($this.data('index')), // 被拖拽行索引 + $bodyTr = $noFixedBody.children('tbody').children('tr[data-index=' + index + ']'), // 被拖拽行(非固定列) + $cloneTr = $bodyTr.clone().css('visibility', 'hidden'), // 占位行 + $FixBodyTr = $fixedBody.children('tbody').children('tr[data-index=' + index + ']'), // 被拖拽行(固定列) + bodyScrollTop = $tableBox.children('.layui-table-body').scrollTop(), // 记录当前滚动条位置 + originTop = $this.position().top, // 被拖拽行当前位置 + disY = e.clientY - originTop; // 鼠标距离被拖拽行上侧的距离 + + _BODY.on('mousemove', function (e) { + + // 刚被拖动 + if (!isDragging) { + isDragging = true; + // 设置鼠标样式 + // $table.next().find('style').append('.layui-table-view .layui-table td{cursor: move;}.layui-table tr{transition: none}') + var style = $table.next().find('style')[0], + sheet = style.sheet || style.styleSheet || {}; + _this.addCSSRule(sheet, '.layui-table-view .layui-table td', 'cursor: move') + _this.addCSSRule(sheet, '.layui-table tr', 'transition: none') + + $tableBox.addClass('noselect'); // 禁止选中文本 + + $bodyTr.after($cloneTr); + $bodyTr.css({ + 'position': 'absolute', + 'z-index': 1 + }) + + $FixBodyTr.each(function () { + $(this).after($(this).clone().css('visibility', 'hidden')) + $(this).css({ + 'position': 'absolute', + 'z-index': 102 + }) + }) + } + + var top = e.clientY - disY + ($tableBox.children('.layui-table-body').scrollTop() - bodyScrollTop), // 计算当前被移动行top位置应该哪里 + trTop = $cloneTr.position().top, //当前行所在位置 + $UpTr = $bodyTr.prev(), + hasUpTr = $UpTr.length > 0, + $downTr = $cloneTr.next(), + hasDownTr = $downTr.length > 0, + upMove = hasUpTr && (trTop - top > $UpTr.height() / 2.0), + downMove = hasDownTr && (top - trTop > $downTr.height() / 2.0); + + if (trTop - top > 0 ? !hasUpTr : !hasDownTr) { + $bodyTr.css('top', trTop); + $FixBodyTr.each(function () { + $(this).css('top', trTop); + }) + return; + } + + $bodyTr.css('top', top); + $FixBodyTr.each(function () { + $(this).css('top', top); + }) + + if (upMove) { + updateDataIndex($bodyTr, -1) + $cloneTr.after(updateDataIndex($UpTr, 1)); + $FixBodyTr.each(function () { + updateDataIndex($(this), -1) + $(this).next().after(updateDataIndex($(this).prev(), 1)); + }) + } else if (downMove) { + updateDataIndex($bodyTr, 1).before(updateDataIndex($downTr, -1)) + $FixBodyTr.each(function () { + updateDataIndex($(this), 1); + $(this).before(updateDataIndex($(this).next().next(), -1)); + }) + } + + // 同步 data-index + function updateDataIndex($el, diff) { + var tempIndex = parseInt($el.data('index')) + diff; + $el.data('index', tempIndex); + $el.attr('data-index', tempIndex); + return $el + } + + }).on('mouseup', function (e) { + _BODY.off('mousemove').off('mouseup'); + + if (isDragging) { + isDragging = false; + + $tableBox.removeClass('noselect'); // 取消禁止选中文本 + $bodyTr.css({'position': 'inherit', 'z-index': 'inherit'}); + $bodyTr.next().remove(); + $FixBodyTr.each(function () { + $(this).css({'position': 'inherit', 'z-index': 'inherit'}); + $(this).next().remove() + }) + + // 恢复样式 + var style = $table.next().find('style')[0], + sheet = style.sheet || style.styleSheet || {}, + rules = sheet.cssRules || sheet.rules; + layui.each(rules, function (i, item) { + if (item.selectorText === ('.layui-table-view .layui-table td')) { + item.style.cursor = 'default'; + } + }); + + var newIndex = $this.index(), + cache = table.cache[tableId]; + + if (newIndex !== index) { // 有位置变动 + // 如果 before 返回 false,则还原拖拽 + if (typeof rowDragConfig.before === 'function' + && rowDragConfig.before.call(myTable, { + row: cache[index], + newIndex: newIndex, + oldIndex: index, + cache: cache + }) === false) { + + // 同步 data-index + function updateDataIndex($el, setIndex) { + $el.data('index', setIndex); + $el.attr('data-index', setIndex); + return $el + } + + // 还原位置和索引 + if (newIndex < index) { + for (i = newIndex; i < index; i++) { + updateDataIndex($noFixedBody.find('tr[data-index="'+(i+1)+'"]'), i) + updateDataIndex($fixedBody.find('tr[data-index="'+(i+1)+'"]'), i) + } + updateDataIndex($bodyTr, index) + $noFixedBody.find('tr[data-index="'+(index - 1)+'"]').after($bodyTr) + $FixBodyTr.each(function () { + updateDataIndex($(this), index) + $(this).parent().children('tr[data-index="'+(index - 1)+'"]').after($(this)) + }) + } else { + for (i = newIndex; i > index; i--) { + updateDataIndex($noFixedBody.find('tr[data-index="'+(i-1)+'"]'), i) + updateDataIndex($fixedBody.find('tr[data-index="'+(i-1)+'"]'), i) + } + updateDataIndex($bodyTr, index) + $noFixedBody.find('tr[data-index="'+(index + 1)+'"]').before($bodyTr) + $FixBodyTr.each(function () { + updateDataIndex($(this), index) + $(this).parent().children('tr[data-index="'+(index + 1)+'"]').before($(this)) + }) + } + return; + } + + var row = cache.splice(index, 1)[0]; + cache.splice(newIndex, 0, row); + if (numberColumnKey && syncNumber) { + // 进行序号重排 + var sortedIndexs = [newIndex, index].sort() + for (i = sortedIndexs[0]; i <= sortedIndexs[1]; i++) { + var curIndex = numberStart + i; + $fixedBody.find('td[data-key="' + numberColumnKey + '"]:eq(' + i + ')').children().html(curIndex) + $noFixedBody.find('td[data-key="' + numberColumnKey + '"]:eq(' + i + ')').children().html(curIndex) + cache[i][table.config.indexName] = curIndex - 1 + } + } + if (typeof rowDragConfig.done === 'function') { + + rowDragConfig.done.call(myTable, { + row: row, + newIndex: newIndex, + oldIndex: index, + cache: cache + }) + } + } + + } + }) + }) + }, + fixTableRemember: function (myTable, dict) { + + if (typeof myTable.filter === 'undefined' ? (defaultConfig.filter && defaultConfig.filter.cache) : myTable.filter.cache) { + if (dict && dict.rule) { + var curKey = dict.rule.selectorText.split('-')[3] + '-' + dict.rule.selectorText.split('-')[4]; + for (var i = 0; i < myTable.cols.length; i++) { + for (var j = 0; j < myTable.cols[i].length; j++) { + if (myTable.cols[i][j].key === curKey) { + myTable.cols[i][j].width = dict.rule.style.width.replace('px', ''); + break; + } + } + + } + } + var storeKey = location.pathname + location.hash + myTable.id; + localStorage.setItem(storeKey, this.deepStringify(myTable.cols)) + } + }, + clearCache: function (myTable) { + if (!myTable) { + return; + } + var tableId; + if (typeof myTable === 'object') { + if (typeof myTable.config !== 'undefined') { + tableId = myTable.config.id + } else { + tableId = myTable.id + } + } else { + tableId = myTable + } + localStorage.removeItem(location.pathname + location.hash + tableId) + if (originCols[tableId]) { + this.updateCols(tables[tableId], this.deepClone(originCols[tableId])) + } + }, + overflow: function (myTable, overflowConfig) { + var options = {}; + if (typeof overflowConfig === 'string') { + options = { + type: overflowConfig + } + } else if (typeof overflowConfig === 'object') { + options = overflowConfig + } else { + return; + } + var $table = $(myTable.elem), + layHeader = $table.next().find('.layui-table-header'), + layBody = $table.next().find('.layui-table-body'), + layTotal = $table.next().find('.layui-table-total'), + tooltipIndex, + hoverTime = options.hoverTime || 0, + tooltipTimeOut, + color = options.color || 'white', + bgColor = options.bgColor || 'black', + minWidth = options.minWidth || 300, + maxWidth = options.maxWidth || 300; + + if (options.type === 'tips') { + layBody.off('mouseenter', 'td').off('mouseleave', 'td').on('mouseenter', 'td', function () { + var _this = this; + tooltipTimeOut = setTimeout(function () { + toopTip.call(_this) + }, hoverTime) + }).on('mouseleave', 'td', function () { + toopTip.call(this, 'hide') + }) + if (options.header) { + layHeader.off('mouseenter', 'th').off('mouseleave', 'th').on('mouseenter', 'th', function () { + var _this = this; + tooltipTimeOut = setTimeout(function () { + toopTip.call(_this) + }, hoverTime) + }).on('mouseleave', 'th', function () { + toopTip.call(this, 'hide') + }) + } + if (options.total) { + layTotal.off('mouseenter', 'td').off('mouseleave', 'td').on('mouseenter', 'td', function () { + var _this = this; + tooltipTimeOut = setTimeout(function () { + toopTip.call(_this) + }, hoverTime) + }).on('mouseleave', 'td', function () { + toopTip.call(this, 'hide') + }) + } + + function toopTip(hide) { + clearTimeout(tooltipTimeOut); + var othis = $(this) + , elemCell = othis.children('.layui-table-cell') + , width = elemCell.outerWidth() + , layerWidth = width < minWidth ? minWidth : width > maxWidth ? maxWidth : width; + if (othis.data('off')) return; + + if (hide) { + layer.close(tooltipIndex) + } else if (elemCell.prop('scrollWidth') > width) { + tooltipIndex = layer.tips('' + $(this).text() + '', this, { + tips: [1, bgColor], + maxWidth: layerWidth, + time: 0 + }); + } + } + } else if (options.type === 'title') { + layBody.off('mouseenter', 'td').on('mouseenter', 'td', function () { + var othis = $(this) + , elemCell = othis.children('.layui-table-cell'); + if (othis.data('off')) return; + + if (elemCell.prop('scrollWidth') > elemCell.outerWidth()) { + elemCell.attr('title', $(this).text()) + } + }) + if (options.header) { + layHeader.off('mouseenter', 'th').on('mouseenter', 'th', function () { + var othis = $(this) + , elemCell = othis.children('.layui-table-cell'); + if (othis.data('off')) return; + + if (elemCell.prop('scrollWidth') > elemCell.outerWidth()) { + elemCell.attr('title', $(this).text()) + } + }) + } + if (options.total) { + layTotal.off('mouseenter', 'td').on('mouseenter', 'td', function () { + var othis = $(this) + , elemCell = othis.children('.layui-table-cell'); + if (othis.data('off')) return; + + if (elemCell.prop('scrollWidth') > elemCell.outerWidth()) { + elemCell.attr('title', $(this).text()) + } + }) + } + } + + }, + // 右键菜单配置 + contextmenu: function (myTable, contextmenuConfig) { + var $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + $tableHead = $.merge($tableBox.children('.layui-table-header').children('table'), $tableBox.children('.layui-table-fixed').children('.layui-table-header').children('table')), + $fixedBody = $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table'), + $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $fixedBody), + $totalTable = $table.next().children('.layui-table-total').children('table'), + tableId = myTable.id, + header = contextmenuConfig ? contextmenuConfig.header : '', + body = contextmenuConfig ? contextmenuConfig.body : '', + total = contextmenuConfig ? contextmenuConfig.total : '', + options = { + header: {box: $tableHead, tag: 'th', opts: header, cols: {}}, + body: {box: $tableBody, tag: 'td', opts: body, cols: {}, isBody: true}, + total: {box: $totalTable, tag: 'td', opts: total, cols: {}} + }, + hasColsContext = false; + + for (var i = 0; i < myTable.cols.length; i++) { + for (var j = 0; j < myTable.cols[i].length; j++) { + if (myTable.cols[i][j].contextmenu) { + hasColsContext = true + options.header.cols[myTable.cols[i][j].key] = myTable.cols[i][j].contextmenu.header + options.body.cols[myTable.cols[i][j].key] = myTable.cols[i][j].contextmenu.body + options.total.cols[myTable.cols[i][j].key] = myTable.cols[i][j].contextmenu.total + } + } + } + + if (!contextmenuConfig && !hasColsContext) { + return; + } + + + for (var name in options) { + (function (name) { + options[name].box.find(options[name].tag).on('contextmenu', function (e) { + $('#soul-table-contextmenu-wrapper').remove(); + _BODY.append('
                '); + $('#soul-table-contextmenu-wrapper').on('click', function (e) { + e.stopPropagation() + }) + var curColsOpts = options[name].cols[$(this).data('key')]; + if (curColsOpts === false) { + return false + } else if (curColsOpts && curColsOpts.length > 0) { + genePanel($('#soul-table-contextmenu-wrapper'), e.pageX, e.pageY, curColsOpts, $(this), options[name].box, options[name].tag, options[name].isBody); + return false + } else if (options[name].opts === false) { + return false + } else if (options[name].opts && options[name].opts.length > 0) { + genePanel($('#soul-table-contextmenu-wrapper'), e.pageX, e.pageY, options[name].opts, $(this), options[name].box, options[name].tag, options[name].isBody); + return false + } + }) + })(name) + } + + + _BODY.on('click', function () { + $('#soul-table-contextmenu-wrapper').remove(); + }) + + function genePanel($parent, left, top, options, $this, box, tag, isBody) { + var html = [], i; + + html.push('
                  '); + for (i = 0; i < options.length; i++) { + html.push('
                • ') + if (options[i].icon) { + html.push('') + } else { + html.push('') + } + html.push(options[i].name) + + if (options[i].children && options[i].children.length > 0) { + html.push('') + } + + html.push('
                • ') + } + html.push('
                '); + $parent.append(html.join('')); + var $curPanel = $parent.children().last(); + if (top + $curPanel.outerHeight() > _BODY.prop('scrollHeight')) { + top = top - $curPanel.outerHeight() + if (top < 0) { + top = 0 + } + } + if ($parent.parent().data('direction') === 'left' && ($parent.offset().left - $curPanel.outerWidth()) > 0) { + left = -$curPanel.outerWidth(); + $curPanel.data('direction', 'left') + } else if (left + $curPanel.outerWidth() + $parent.offset().left > _BODY.prop('scrollWidth')) { + left = left - $curPanel.outerWidth() - $parent.outerWidth() + if (left + $parent.offset().left < 0) { + left = -$parent.offset().left + } + $curPanel.data('direction', 'left') + } + $curPanel.css({ + top: top + 'px', + left: left + 'px' + }) + + for (i = 0; i < options.length; i++) { + if (typeof options[i].click === "function") { + (function (i) { + $parent.children('.soul-table-contextmenu:last').children('li[data-index="' + i + '"]').on('click', function () { + var index = $this.parents('tr:eq(0)').data('index'), + tr = box.find('tr[data-index="' + index + '"]'), + row = layui.table.cache[tableId][index]; + + options[i].click.call(myTable, { + cell: $this, + elem: tag === 'th' ? $this : isBody ? box.children('tbody').children('tr[data-index="' + index + '"]').children('[data-key="' + $this.data('key') + '"]') : box.find('[data-key="' + $this.data('key') + '"]'), + trElem: box.children('tbody').children('tr[data-index="' + index + '"]'), + text: $this.text(), + field: $this.data('field'), + del: !isBody ? '' : function () { + table.cache[tableId][index] = []; + tr.remove(); + table.resize(tableId); + }, + update: !isBody ? '' : function (fields) { + fields = fields || {}; + layui.each(fields, function (key, value) { + if (key in row) { + var templet, td = tr.children('td[data-field="' + key + '"]'); + row[key] = value; + table.eachCols(tableId, function (i, item2) { + if (item2.field == key && item2.templet) { + templet = item2.templet; + } + }); + td.children('.layui-table-cell').html(function () { + return templet ? function () { + return typeof templet === 'function' + ? templet(row) + : layui.laytpl($(templet).html() || value).render(row) + }() : value; + }()); + td.data('content', value); + } + }); + }, + row: isBody ? row : {}, + }) + $('#soul-table-contextmenu-wrapper').remove(); + }) + })(i) + } + } + $parent.children('.soul-table-contextmenu:last').children('li').on('mouseenter', function (e) { + e.stopPropagation() + $(this).siblings('.contextmenu-children').children('ul').remove(); + if ($(this).hasClass('contextmenu-children')) { + genePanel($(this), $(this).outerWidth(), $(this).position().top, options[$(this).data('index')].children, $this, box, tag, isBody) + } + }) + } + + }, + fixTotal: function (myTable) { + var $table = $(myTable.elem), + $total = $table.next().children('.layui-table-total'), + style = $table.next().find('style')[0], + sheet = style.sheet || style.styleSheet || {}; + if ($total.length > 0) { + var $tableBox = $table.next().children('.layui-table-box'), + $fixedLeft = $tableBox.children('.layui-table-fixed-l').children('.layui-table-body').children('table').children('tbody').children('tr:eq(0)').children('td'), + $fixedRight = $tableBox.children('.layui-table-fixed-r').children('.layui-table-body').children('table').children('tbody').children('tr:eq(0)').children('td'), + html = []; + + $total.children('.layui-table-total-fixed').remove() + + if ($fixedLeft.length > 0) { + this.addCSSRule(sheet, '.layui-table-total-fixed-l .layui-table-patch', 'display: none') + $table.next().css('position', 'relative'); + html.push(''); + $fixedLeft.each(function () { + if ($(this).data('key')) { + html.push($total.children('table:eq(0)').find('[data-key="' + $(this).data('key') + '"]').prop("outerHTML")) + } + }) + html.push('
                '); + $total.append(html.join('')) + } + if ($fixedRight.length > 0) { + this.addCSSRule(sheet, '.layui-table-total-fixed-r td:first-child', 'border-left:1px solid #e6e6e6') + this.addCSSRule(sheet, '.layui-table-total-fixed-r td:last-child', 'border-left: none') + $table.next().css('position', 'relative'); + html = []; + html.push(''); + $fixedRight.each(function () { + html.push($total.children('table:eq(0)').find('[data-key="' + $(this).data('key') + '"]').prop("outerHTML")) + }) + html.push('
                ') + $total.append(html.join('')) + } + } + + }, + fixResizeRightFixed: function (myTable) { + var _this = this, + $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + $fixedHead = $tableBox.children('.layui-table-fixed-r').children('.layui-table-header').children('table'), + dict = {}, resizing, ELEM_SORT = 'layui-table-sort', + ELEM_NO_SORT = 'layui-table-sort-invalid'; + if ($fixedHead.length > 0) { + $fixedHead.find('th').off('mousemove').on('mousemove', function (e) { + var othis = $(this) + , oLeft = othis.offset().left + , pLeft = e.clientX - oLeft; + if (othis.data('unresize') || dict.resizeStart) { + return; + } + if (othis.width() - pLeft <= 10) { + _BODY.css('cursor', 'initial') + } + dict.allowResize = pLeft <= 10; //是否处于拖拽允许区域 + _BODY.css('cursor', (dict.allowResize ? 'col-resize' : '')); + }).off('mousedown').on('mousedown', function (e) { + var othis = $(this); + if (dict.allowResize) { + othis.find('.' + ELEM_SORT).removeClass(ELEM_SORT).addClass(ELEM_NO_SORT) + var key = othis.data('key'); + e.preventDefault(); + dict.resizeStart = true; //开始拖拽 + dict.offset = [e.clientX, e.clientY]; //记录初始坐标 + + _this.getCssRule(myTable, key, function (item) { + var width = item.style.width || othis.outerWidth(); + dict.rule = item; + dict.ruleWidth = parseFloat(width); + dict.othis = othis; + dict.minWidth = othis.data('minwidth') || myTable.cellMinWidth; + }); + } + }); + //拖拽中 + _DOC.on('mousemove', function (e) { + if (dict.resizeStart) { + layui.soulTable.fixTableRemember(myTable, dict) + e.preventDefault(); + if (dict.rule) { + var setWidth = dict.ruleWidth - e.clientX + dict.offset[0]; + if (setWidth < dict.minWidth) setWidth = dict.minWidth; + dict.rule.style.width = setWidth + 'px'; + } + resizing = 1 + } + }).on('mouseup', function (e) { + if (dict.resizeStart) { + setTimeout(function () { + dict.othis.find('.' + ELEM_NO_SORT).removeClass(ELEM_NO_SORT).addClass(ELEM_SORT) + _BODY.css('cursor', ''); + dict = {}; + _this.scrollPatch(myTable); + }, 30) + } + if (resizing === 2) { + resizing = null; + } + }); + } + }, + fixFixedScroll: function (myTable) { + var $table = $(myTable.elem), + layFixed = $table.next().children('.layui-table-box').children('.layui-table-fixed'), + layMain = $table.next().children('.layui-table-box').children('.layui-table-main'); + + layFixed.on('mouseenter', function () { + $(this).children('.layui-table-body').addClass('soul-fixed-scroll').on('scroll', function () { + var scrollTop = $(this).scrollTop() + // layFixed.children('.layui-table-body[class!="soul-fixed-scroll"]').scrollTop(scrollTop); + layMain.scrollTop(scrollTop); + }) + }).on('mouseleave', function () { + $(this).children('.layui-table-body').removeClass('soul-fixed-scroll').off('scroll'); + }) + }, + scrollPatch: function (myTable) { + var $table = $(myTable.elem), + layHeader = $table.next().children('.layui-table-box').children('.layui-table-header'), + layTotal = $table.next().children('.layui-table-total'), + layMain = $table.next().children('.layui-table-box').children('.layui-table-main'), + layFixed = $table.next().children('.layui-table-box').children('.layui-table-fixed'), + layFixRight = $table.next().children('.layui-table-box').children('.layui-table-fixed-r'), + layMainTable = layMain.children('table'), + scollWidth = layMain.width() - layMain.prop('clientWidth'), + scollHeight = layMain.height() - layMain.prop('clientHeight'), + outWidth = layMainTable.outerWidth() - layMain.width() //表格内容器的超出宽度 + + //添加补丁 + , addPatch = function (elem) { + if (scollWidth && scollHeight) { + elem = elem.eq(0); + if (!elem.find('.layui-table-patch')[0]) { + var patchElem = $('
                '); //补丁元素 + patchElem.find('div').css({ + width: scollWidth + }); + elem.find('tr').append(patchElem); + } + } else { + elem.find('.layui-table-patch').remove(); + } + } + + addPatch(layHeader); + addPatch(layTotal); + + //固定列区域高度 + var mainHeight = layMain.height() + , fixHeight = mainHeight - scollHeight; + layFixed.find('.layui-table-body').css('height', layMainTable.height() >= fixHeight ? fixHeight : 'auto'); + + //表格宽度小于容器宽度时,隐藏固定列 + layFixRight[outWidth > 0 ? 'removeClass' : 'addClass'](HIDE); + + //操作栏 + layFixRight.css('right', scollWidth - 1); + }, + /** + * 一键粘贴 + * @param {String} text [需要 copy 的属性,默认是 innerText,主要用途例如赋值 a 标签上的 href 链接] + * + * range + selection + * + * 1.创建一个 range + * 2.把内容放入 range + * 3.把 range 放入 selection + * + * 注意:参数 attr 不能是自定义属性 + * 注意:对于 user-select: none 的元素无效 + * 注意:当 id 为 false 且 attr 不会空,会直接复制 attr 的内容 + */ + copy: function (text) { + var target; + + if (text) { + target = document.createElement('div'); + target.id = 'tempTarget'; + target.style.opacity = '0'; + target.innerText = text; + document.body.appendChild(target); + } else { + target = document.querySelector('#' + id); + } + + try { + var range = document.createRange(); + range.selectNode(target); + window.getSelection().removeAllRanges(); + window.getSelection().addRange(range); + document.execCommand('copy'); + window.getSelection().removeAllRanges(); + } catch (e) { + console.log('复制失败') + } + + if (text) { + // remove temp target + target.parentElement.removeChild(target); + } + }, + addCSSRule: function (sheet, selector, rules, index) { + if ('insertRule' in sheet) { + sheet.insertRule(selector + '{' + rules + '}', index) + } else if ('addRule' in sheet) { + sheet.addRule(selector, rules, index) + } + }, + deepStringify: function (obj) { + var JSON_SERIALIZE_FIX = { + PREFIX: "[[JSON_FUN_PREFIX_", + SUFFIX: "_JSON_FUN_SUFFIX]]" + }; + return JSON.stringify(obj, function (key, value) { + if (typeof value === 'function') { + return JSON_SERIALIZE_FIX.PREFIX + value.toString() + JSON_SERIALIZE_FIX.SUFFIX; + } + return value; + }); + }, + deepParse: function (str) { + var JSON_SERIALIZE_FIX = { + PREFIX: "[[JSON_FUN_PREFIX_", + SUFFIX: "_JSON_FUN_SUFFIX]]" + }; + return JSON.parse(str, function (key, value) { + if (typeof value === 'string' && + value.indexOf(JSON_SERIALIZE_FIX.SUFFIX) > 0 && value.indexOf(JSON_SERIALIZE_FIX.PREFIX) === 0) { + return eval("(" + value.replace(JSON_SERIALIZE_FIX.PREFIX, "").replace(JSON_SERIALIZE_FIX.SUFFIX, "") + ")"); + } + return value; + }) || {}; + }, + // 深度克隆-不丢失方法 + deepClone: function (obj) { + var newObj = Array.isArray(obj) ? [] : {} + if (obj && typeof obj === "object") { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + newObj[key] = (obj && typeof obj[key] === 'object') ? this.deepClone(obj[key]) : obj[key]; + } + } + } + return newObj + }, + clearOriginCols: function (tableId) { + if (tableId) { + delete originCols[tableId] + } else { + originCols = {} + } + }, + suspendConfig: {}, + /** + * 暂停某个特性 + * @param tableId + * @param type 暂停的类型,支持 'drag' 'rowDrag' + * @param value true/false + */ + suspend: function (tableId, type, value) { + this.suspendConfig[tableId][type] = value + } + } + + // 输出 + exports('soulTable', mod); +}); diff --git a/WaterCloud.Web/wwwroot/js/lay-module/soulTable/tableChild.js b/WaterCloud.Web/wwwroot/js/lay-module/soulTable/tableChild.js new file mode 100644 index 0000000..751d09d --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/soulTable/tableChild.js @@ -0,0 +1,769 @@ +/** + * + * @name: 子表格扩展 + * @author: yelog + * @link: https://github.com/yelog/layui-soul-table + * @license: MIT + * @version: v1.9.0 + */ +layui.define(['table', 'element', 'form', 'laytpl'], function (exports) { + + var $ = layui.jquery, + table = layui.table, + laytpl = layui.laytpl, + tableChildren = {}, + HIDE = 'layui-hide', + ELEM_HOVER = 'soul-table-hover'; + + // 封装方法 + var mod = { + /** + * 渲染入口 + * @param myTable + */ + render: function (myTable) { + var _this = this, + $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + tableId = myTable.id, + $tableHead = $tableBox.children('.layui-table-header').children('table'), + $fixedBody = $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table'), + $noFixedBody = $tableBox.children('.layui-table-body').children('table'), + $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $fixedBody), + columns = _this.getCompleteCols(myTable.cols), + childIndex = [], + soulSort = typeof myTable.soulSort === 'undefined' || myTable.soulSort, + i; + + // 修复hover样式 + _this.fixHoverStyle(myTable) + // 获取子表配置信息 + for (i = 0; i < columns.length; i++) { + if (columns[i].children && columns[i].children.length > 0) { + childIndex.push(i); + } + } + if (typeof $table.attr('lay-filter') === 'undefined') { + $table.attr('lay-filter', tableId); + } + // 绑定一下主表事件 + if ($table.parents('.childTr').length === 0) { + // 行单击事件 + if (typeof myTable.rowEvent === 'function') { + table.on('row(' + $table.attr('lay-filter') + ')', function (obj) { + myTable.rowEvent(_this.commonMember.call(this, _this, myTable, obj)); + }) + } + // 行双击事件 + if (typeof myTable.rowDoubleEvent === 'function') { + table.on('rowDouble(' + $table.attr('lay-filter') + ')', function (obj) { + myTable.rowDoubleEvent(_this.commonMember.call(this, _this, myTable, obj)); + }) + } + // 绑定 checkbox 事件 + if (typeof myTable.checkboxEvent === 'function') { + table.on('checkbox(' + $table.attr('lay-filter') + ')', function (obj) { + myTable.checkboxEvent(_this.commonMember.call(this, _this, myTable, obj)); + }) + } + // 绑定 edit 事件 + if (typeof myTable.editEvent === 'function') { + table.on('edit(' + $table.attr('lay-filter') + ')', function (obj) { + myTable.editEvent(_this.commonMember.call(this, _this, myTable, obj)); + }) + } + // 绑定 tool 事件 + if (typeof myTable.toolEvent === 'function') { + table.on('tool(' + $table.attr('lay-filter') + ')', function (obj) { + myTable.toolEvent(_this.commonMember.call(this, _this, myTable, obj)); + }) + } + // 绑定 toolbar 事件 + if (typeof myTable.toolbarEvent === 'function') { + table.on('toolbar(' + $table.attr('lay-filter') + ')', function (obj) { + myTable.toolbarEvent(_this.commonMember.call(this, _this, myTable, obj)); + }) + } + } + + if (childIndex.length > 0) { + for (i = 0; i < childIndex.length; i++) { + (function f() { + var child = columns[childIndex[i]] + , curIndex = childIndex[i] + , icon = child.icon || ['layui-icon layui-icon-right', 'layui-icon layui-icon-down']; + + if (soulSort && !(myTable.url && myTable.page)) { + // 前台排序 + table.on('sort(' + $table.attr('lay-filter') + ')', function () { + _this.render(myTable) + }); + } + + if (child.isChild && typeof child.isChild === 'function') { + $tableBody.find('tr').find('td[data-key$="' + child.key + '"]>div').each(function () { + if (child.isChild(layui.table.cache[tableId][$(this).parents('tr:eq(0)').data('index')])) { + if (child.field) { + $(this).prepend(''); + } else { + $(this).html(''); + } + } + }) + } else { + if (child.field) { + $tableBody.find('tr').find('td[data-key$="' + child.key + '"]>div').prepend(''); + } else { + $tableBody.find('tr').find('td[data-key$="' + child.key + '"]>div').html(''); + } + } + + $tableBody.children('tbody').children('tr').each(function () { + $(this).children('td:eq(' + curIndex + ')').find('.childTable').on('click', function (e) { + layui.stope(e) + var rowIndex = $(this).parents('tr:eq(0)').data('index'), + tableId = myTable.id, + key = $(this).parents('td:eq(0)').data('key'), + $this = $noFixedBody.children('tbody').children('tr[data-index=' + rowIndex + ']').children('td[data-key="' + key + '"]').find('.childTable:eq(0)'), + $fixedThis = $fixedBody.find('tr[data-index=' + rowIndex + ']').children('td[data-key="' + key + '"]').find('.childTable:eq(0)'), + data = table.cache[tableId][rowIndex], + children = child.children, + isTpl = false, + tplContent = '', + tr = $tableBody.children('tbody').children('tr[data-index="' + rowIndex + '"]'), + obj = { + data: data, + tr: tr, + del: function () { + table.cache[tableId][rowIndex] = []; + _this.destroyChildren(rowIndex, myTable, icon) + tr.remove(); + table.resize(tableId); + }, + update: function (fields) { + fields = fields || {}; + layui.each(fields, function (key, value) { + if (key in data) { + var templet, td = tr.children('td[data-field="' + key + '"]'); + data[key] = value; + table.eachCols(tableId, function (i, item2) { + if (item2.field == key && item2.templet) { + templet = item2.templet; + } + }); + td.children('.layui-table-cell').html(function () { + return templet ? function () { + return typeof templet === 'function' + ? templet(data) + : laytpl($(templet).html() || value).render(data) + }() : value; + }()); + td.data('content', value); + } + }); + }, + close: function () { + _this.destroyChildren(rowIndex, myTable, icon) + table.resize(tableId); + } + + }; + if ($this.hasClass(icon[1])) { + if (typeof child.childClose === 'function') { + if (child.childClose(obj) === false) { + return; + } + } + } else { + // 展开事件 + if (typeof child.childOpen === 'function') { + if (child.childOpen(obj) === false) { + return; + } + } + } + + if (typeof children === 'function') { + children = children(data) + } + // 如果是 templet 自定义内容 + if (typeof children === 'string') { + isTpl = true + tplContent = _this.parseTempData(child, child.field ? data[child.field] : null, data) + } + if (child.show === 2) { // 弹窗模式 + + child.layerOption ? (typeof child.layerOption.title === 'function' ? (child.layerOption.title = child.layerOption.title(data)) : null) : null; + layer.open($.extend({ + type: 1, + title: '子表', + maxmin: true, + content: _this.getTables(this, data, child, myTable, children, isTpl, tplContent), + area: '1000px', + offset: '100px', + cancel: function () { + if (typeof child.childClose === 'function') { + if (child.childClose(obj) === false) { + return; + } + } + } + }, child.layerOption || {})); + + if (!isTpl) { + _this.renderTable(this, data, child, myTable, children, icon); + } + + } else { // 展开模式 + + // 开启手风琴模式 + if (!$this.hasClass(icon[1]) && child.collapse) { + $tableBody.children('tbody').children('tr').children('td').find('.childTable').each(function () { + if ($(this).hasClass(icon[1])) { + _this.destroyChildren($(this).parents('tr:eq(0)').data('index'), myTable, icon) + } + }) + } + + // 多个入口时,关闭其他入口 + if (!$this.hasClass(icon[1])) { + $this.parents('tr:eq(0)').children('td').find('.childTable').each(function () { + if ($(this).hasClass(icon[1])) { + $(this).removeClass(icon[1]).addClass(icon[0]) + _this.destroyChildren($(this).parents('tr:eq(0)').data('index'), myTable, icon) + } + }) + } + + if ($this.hasClass(icon[1])) { + $this.removeClass(icon[1]).addClass(icon[0]) + $fixedThis.removeClass(icon[1]).addClass(icon[0]) + } else { + $this.removeClass(icon[0]).addClass(icon[1]) + $fixedThis.removeClass(icon[0]).addClass(icon[1]) + } + var rowspanIndex = $this.parents('td:eq(0)').attr("rowspan"); + + if ($this.hasClass(icon[1])) { + var newTr = []; + newTr.push(''); + newTr.push(_this.getTables(this, data, child, myTable, children, isTpl, tplContent)); + newTr.push(''); + + if (rowspanIndex) { + var index = parseInt($this.parents('tr:eq(0)').data("index")) + parseInt(rowspanIndex) - 1; + $this.parents('table:eq(0)').children().children("[data-index='" + index + "']").after(newTr.join('')); + } else { + $this.parents('tr:eq(0)').after(newTr.join('')); + } + layui.element.init('tab') + if (!isTpl) { + _this.renderTable(this, data, child, myTable, children, icon); + // 阻止事件冒泡 + $this.parents('tr:eq(0)').next().children('td').children('.layui-tab').children('.layui-tab-content').on('click', function (e) { + // 不阻止 tab 切换点击事件 + if (!$(e.target.parentElement).hasClass('layui-tab-title')) { + e.stopPropagation() + } + }).off('dblclick').on('dblclick', function (e) { + e.stopPropagation() + }).on('mouseenter', 'td', function (e) { + e.stopPropagation() + }).on('change', function (e) { + layui.stope(e) + }) + } + if ($fixedBody.length > 0) { + var $tr = $this.parents('tr:eq(0)').next(), + height = $tr.children('td').height(), + $patchDiv = '
                '; + $tr.children('td').children('.soul-table-child-wrapper').css({ + position: 'absolute', + top: 0, + width: '100%', + background: 'white', + 'z-index': 200 + }) + $tr.children('td').append($patchDiv); + $fixedBody.find('tr[data-index="' + rowIndex + '"]').each(function () { + $(this).after('' + $patchDiv + '') + }) + table.resize(tableId) + } + if (child.show === 3) { + $this.parents('tr:eq(0)').next().find('.layui-table-view').css({margin: 0, 'border-width': 0}); + $this.parents('tr:eq(0)').next().find('.layui-table-header').css('display', 'none'); + } + + } else { + _this.destroyChildren(rowIndex, myTable, icon); + table.resize(tableId) + } + + } + }) + + }) + + if (child.spread && child.show !== 2) { + $tableBody.children('tbody').children('tr').children('td').find('.childTable').trigger('click'); + } + })() + + } + } + }, + /** + * 生成子表内容 + * @param _this + * @param data + * @param child + * @param myTable + * @param children 子表配置 + * @param isTpl 是否是自定义模版 + * @param tplContent 自定义模版内容 + * @returns {string} + */ + getTables: function (_this, data, child, myTable, children, isTpl, tplContent) { + var tables = [], + $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + tableId = myTable.id, + rowTableId = tableId + $(_this).parents('tr:eq(0)').data('index'), + $tableHead = $tableBox.children('.layui-table-header').children('table'), + $tableMain = $table.next().children('.layui-table-box').children('.layui-table-body'), + $tableBody = $tableMain.children('table'), + scrollWidth = 0, + i; + if (isTpl) { + tables.push('
                ') + } else if (child.show === 3) { + //不限制宽度 + tables.push('">') + } else { + if (child.childWidth === 'full') { + //不限制宽度 + tables.push('">') + } else { + // 如果有滚动条 + if ($tableMain.prop('scrollHeight') + (children.length > 0 ? children[0].height : 0) > $tableMain.height()) { + scrollWidth = this.getScrollWidth(); + } + var maxWidth = $tableMain.width() - 1 - scrollWidth; + tables.push('max-width: ' + (maxWidth > $tableHead.width() ? $tableHead.width() : maxWidth) + 'px">') + } + } + if (isTpl) { + tables.push(tplContent) + } else { + if (child.show !== 3 && (typeof child.childTitle === 'undefined' || child.childTitle)) { + tables.push('
                  ') + for (i = 0; i < children.length; i++) { + tables.push('
                • ' + (typeof children[i].title === 'function' ? children[i].title(data) : children[i].title) + '
                • '); + } + tables.push('
                ') + } + if (child.show === 3) { + tables.push('
                '); + } else { + tables.push('
                '); + } + for (i = 0; i < children.length; i++) { + var childTableId = rowTableId + i; + tables.push('
                '); + } + tables.push('
                '); + } + tables.push('
                '); + return tables.join('') + }, + /** + * 渲染子表 + * @param _this + * @param data 父表当前行数据 + * @param child 子表列 + * @param myTable 父表配置 + * @param children 子表配置 + * @param icon 自定义图标 + */ + renderTable: function (_this, data, child, myTable, children, icon) { + var tables = [] + , _that = this + , tableId = myTable.id + , rowTableId = tableId + $(_this).parents('tr:eq(0)').data('index'); + + if (child.lazy) { + tables.push(renderChildTable(_that, _this, data, child, myTable, 0, children, icon)); + } else { + for (var i = 0; i < children.length; i++) { + tables.push(renderChildTable(_that, _this, data, child, myTable, i, children, icon)); + } + } + tableChildren[rowTableId] = tables; + + + layui.element.on('tab(table-child-tab-' + rowTableId + ')', function (tabData) { + if (child.lazy) { + var isRender = false; // 是否已经渲染 + for (i = 0; i < tableChildren[rowTableId].length; i++) { + if (tableChildren[rowTableId][i].config.id === (rowTableId + tabData.index)) { + isRender = true; + break; + } + } + if (!isRender) { + tableChildren[rowTableId].push(renderChildTable(_that, _this, data, child, myTable, tabData.index, children)) + } + } + + var rowIndex = $(_this).parents('tr:eq(0)').data('index'), + height = $(tabData.elem).height(); + + $(_this).parents('.layui-table-box:eq(0)').children('.layui-table-body').children('table').children('tbody').children('tr[data-index=' + rowIndex + ']').next().children().children('.soul-table-child-patch').css('height', height) + $(_this).parents('.layui-table-box:eq(0)').children('.layui-table-fixed').children('.layui-table-body').children('table').children('tbody').children('tr[data-index=' + rowIndex + ']').next().children().children('.soul-table-child-patch').css('height', height) + table.resize(tableId) + + }); + + + function renderChildTable(_that, _this, data, child, myTable, i, children, icon) { + var param = _that.deepClone(children[i]), thisTableChild, + tableId = myTable.id, + rowIndex = $(_this).parents('tr:eq(0)').data('index'), + childTableId = tableId + rowIndex + i, + $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table')), + tr = $tableBody.children('tbody').children('tr[data-index="' + rowIndex + '"]'), + row = table.cache[tableId][rowIndex], + // 父表当前行对象 + pobj = { + data: row, + tr: tr, + del: function () { + table.cache[tableId][rowIndex] = []; + _that.destroyChildren(rowIndex, myTable, icon) + tr.remove(); + table.resize(tableId); + }, + update: function (fields) { + fields = fields || {}; + layui.each(fields, function (key, value) { + if (key in row) { + var templet, td = tr.children('td[data-field="' + key + '"]'); + row[key] = value; + table.eachCols(tableId, function (i, item2) { + if (item2.field == key && item2.templet) { + templet = item2.templet; + } + }); + td.children('.layui-table-cell').html(function () { + return templet ? function () { + return typeof templet === 'function' + ? templet(row) + : laytpl($(templet).html() || value).render(row) + }() : value; + }()); + td.data('content', value); + } + }); + }, + close: function () { + _that.destroyChildren(rowIndex, myTable, icon) + table.resize(tableId); + } + + }; + param.id = childTableId; + param.elem = '#' + childTableId; + typeof param.where === 'function' && (param.where = param.where(data)); + typeof param.data === 'function' && (param.data = param.data(data)); + typeof param.url === 'function' && (param.url = param.url(data)); + thisTableChild = table.render(param); + if (!child.lazy && i !== 0) { + $('#' + childTableId).parents('.layui-tab-item:eq(0)').removeClass('layui-show'); //解决隐藏时计算表格高度有问题 + } + // 绑定 checkbox 事件 + if (typeof param.checkboxEvent === 'function') { + table.on('checkbox(' + childTableId + ')', function (obj) { + param.checkboxEvent(_that.commonMember.call(this, _that, param, obj), pobj) + }) + } + // 绑定 edit 事件 + if (typeof param.editEvent === 'function') { + table.on('edit(' + childTableId + ')', function (obj) { + param.editEvent(_that.commonMember.call(this, _that, param, obj), pobj) + }) + } + // 绑定 tool 事件 + if (typeof param.toolEvent === 'function') { + table.on('tool(' + childTableId + ')', function (obj) { + param.toolEvent(_that.commonMember.call(this, _that, param, obj), pobj) + }) + } + // 绑定 toolbar 事件 + if (typeof param.toolbarEvent === 'function') { + table.on('toolbar(' + childTableId + ')', function (obj) { + param.toolbarEvent(_that.commonMember.call(this, _that, param, obj), pobj) + }) + } + // 绑定单击行事件 + if (typeof param.rowEvent === 'function') { + table.on('row(' + childTableId + ')', function (obj) { + param.rowEvent(_that.commonMember.call(this, _that, param, obj), pobj) + }) + } + // 绑定双击行事件 + if (typeof param.rowDoubleEvent === 'function') { + table.on('rowDouble(' + childTableId + ')', function (obj) { + param.rowDoubleEvent(_that.commonMember.call(this, _that, param, obj), pobj) + }) + } + return thisTableChild; + } + }, + destroyChildren: function (rowIndex, myTable, icon) { + var tableId = myTable.id, + $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + $fixedBody = $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table'), + $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $fixedBody), + $tr = $tableBody.children('tbody').children('tr[data-index="' + rowIndex + '"]'), + isTpl = $tr.next().data('tpl'); + + $tr.find('.childTable').removeClass(icon[1]).addClass(icon[0]); + + // 暂时不处理 rowspan 情况 + // var rowspanIndex = $this.parents('td:eq(0)').attr("rowspan"); + // if(rowspanIndex){ + // var index=$this.parents('tr:eq(0)').index()+parseInt(rowspanIndex); + // $this.parents('table:eq(0)').children().children('tr:eq('+index+')').remove() + // }else{ + // $this.parents('tr:eq(0)').next().remove(); + // } + $tr.next().remove() + if (isTpl === 'false') { + var tables = tableChildren[tableId + rowIndex]; + if (layui.tableFilter) { //如果使用了筛选功能,同时清理筛选渲染的数据 + layui.tableFilter.destroy(tables); + } + if (layui.soulTable) { // 清除记忆 + for (var i = 0; i < tableChildren[tableId + rowIndex].length; i++) { + layui.soulTable.clearOriginCols(tableChildren[tableId + rowIndex][i].config.id) + } + } + } + delete tableChildren[tableId + rowIndex] + + }, + cloneJSON: function (obj) { + var JSON_SERIALIZE_FIX = { + PREFIX: "[[JSON_FUN_PREFIX_", + SUFFIX: "_JSON_FUN_SUFFIX]]" + }; + var sobj = JSON.stringify(obj, function (key, value) { + if (typeof value === 'function') { + return JSON_SERIALIZE_FIX.PREFIX + value.toString() + JSON_SERIALIZE_FIX.SUFFIX; + } + return value; + }); + return JSON.parse(sobj, function (key, value) { + if (typeof value === 'string' && + value.indexOf(JSON_SERIALIZE_FIX.SUFFIX) > 0 && value.indexOf(JSON_SERIALIZE_FIX.PREFIX) === 0) { + return eval("(" + value.replace(JSON_SERIALIZE_FIX.PREFIX, "").replace(JSON_SERIALIZE_FIX.SUFFIX, "") + ")"); + } + return value; + }) || {}; + }, + fixHoverStyle: function (myTable) { + var $table = $(myTable.elem) + , $tableBody = $table.next().children('.layui-table-box').children('.layui-table-body').children('table') + , + $tableFixed = $table.next().children('.layui-table-box').children('.layui-table-fixed').children('.layui-table-body').children('table') + , style = $table.next().find('style')[0], + sheet = style.sheet || style.styleSheet || {}; + // 屏蔽掉layui原生 hover 样式 + this.addCSSRule(sheet, '.layui-table-hover', 'background-color: inherit'); + this.addCSSRule(sheet, '.layui-table-hover.soul-table-hover', 'background-color: #F2F2F2'); + $.merge($tableFixed.children('tbody').children('tr'), $tableBody.children('tbody').children('tr')) + .on('mouseenter', function () { + var othis = $(this) + , index = $(this).data('index'); + if (othis.data('off')) return; + $tableFixed.children('tbody').children('tr[data-index=' + index + ']').addClass(ELEM_HOVER); + $tableBody.children('tbody').children('tr[data-index=' + index + ']').addClass(ELEM_HOVER); + }).on('mouseleave', function () { + var othis = $(this) + , index = $(this).data('index'); + if (othis.data('off')) return; + $tableFixed.children('tbody').children('tr[data-index=' + index + ']').removeClass(ELEM_HOVER); + $tableBody.children('tbody').children('tr[data-index=' + index + ']').removeClass(ELEM_HOVER); + }) + }, + addCSSRule: function (sheet, selector, rules, index) { + if ('insertRule' in sheet) { + sheet.insertRule(selector + '{' + rules + '}', index) + } else if ('addRule' in sheet) { + sheet.addRule(selector, rules, index) + } + }, + // 深度克隆-不丢失方法 + deepClone: function (obj) { + var newObj = Array.isArray(obj) ? [] : {} + if (obj && typeof obj === "object") { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + newObj[key] = (obj && typeof obj[key] === 'object') ? this.deepClone(obj[key]) : obj[key]; + } + } + } + return newObj + }, + getCompleteCols: function (origin) { + var cols = this.deepClone(origin); + var i, j, k, cloneCol; + for (i = 0; i < cols.length; i++) { + for (j = 0; j < cols[i].length; j++) { + if (!cols[i][j].exportHandled) { + if (cols[i][j].rowspan > 1) { + cloneCol = this.deepClone(cols[i][j]) + cloneCol.exportHandled = true; + k = i + 1; + while (k < cols.length) { + cols[k].splice(j, 0, cloneCol) + k++ + } + } + if (cols[i][j].colspan > 1) { + cloneCol = this.deepClone(cols[i][j]) + cloneCol.exportHandled = true; + for (k = 1; k < cols[i][j].colspan; k++) { + cols[i].splice(j, 0, cloneCol) + } + j = j + parseInt(cols[i][j].colspan) - 1 + } + } + } + } + return cols[cols.length - 1]; + }, + getScrollWidth: function (elem) { + var width = 0; + if (elem) { + width = elem.offsetWidth - elem.clientWidth; + } else { + elem = document.createElement('div'); + elem.style.width = '100px'; + elem.style.height = '100px'; + elem.style.overflowY = 'scroll'; + + document.body.appendChild(elem); + width = elem.offsetWidth - elem.clientWidth; + document.body.removeChild(elem); + } + return width; + }, + //解析自定义模板数据 + parseTempData: function (item3, content, tplData, text) { //表头数据、原始内容、表体数据、是否只返回文本 + var str = item3.children ? function () { + return typeof item3.children === 'function' + ? item3.children(tplData) + : laytpl($(item3.children).html() || String(content)).render(tplData) + }() : content; + return text ? $('
                ' + str + '
                ').text() : str; + }, + commonMember: function (_this, myTable, sets) { + var othis = $(this) + , tableId = myTable.id + , $table = $(myTable.elem) + , $tableBox = $table.next().children('.layui-table-box') + , $fixedBody = $tableBox.children('.layui-table-fixed').children('.layui-table-body').children('table') + , $tableBody = $.merge($tableBox.children('.layui-table-body').children('table'), $fixedBody) + , index = othis[0].tagName === 'TR' ? $(this).data('index') : othis.parents('tr:eq(0)').data('index') + , tr = $tableBody.children('tbody').children('tr[data-index="' + index + '"]') + , data = table.cache[tableId] || []; + + + data = data[index] || {}; + + return $.extend(sets, { + tr: tr //行元素 + , oldValue: othis.prev() ? othis.prev().text() : null + , del: function () { //删除行数据 + table.cache[tableId][index] = []; + tr.remove(); + _this.scrollPatch(myTable); + } + , update: function (fields) { //修改行数据 + fields = fields || {}; + layui.each(fields, function (key, value) { + if (key in data) { + var templet, td = tr.children('td[data-field="' + key + '"]'); + data[key] = value; + table.eachCols(tableId, function (i, item2) { + if (item2.field == key && item2.templet) { + templet = item2.templet; + } + }); + td.children('.layui-table-cell').html(_this.parseTempData({ + templet: templet + }, value, data)); + td.data('content', value); + } + }); + } + }); + }, + scrollPatch: function (myTable) { + var $table = $(myTable.elem), + layHeader = $table.next().children('.layui-table-box').children('.layui-table-header'), + layTotal = $table.next().children('.layui-table-total'), + layMain = $table.next().children('.layui-table-box').children('.layui-table-main'), + layFixed = $table.next().children('.layui-table-box').children('.layui-table-fixed'), + layFixRight = $table.next().children('.layui-table-box').children('.layui-table-fixed-r'), + layMainTable = layMain.children('table'), + scollWidth = layMain.width() - layMain.prop('clientWidth'), + scollHeight = layMain.height() - layMain.prop('clientHeight'), + outWidth = layMainTable.outerWidth() - layMain.width() //表格内容器的超出宽度 + + //添加补丁 + , addPatch = function (elem) { + if (scollWidth && scollHeight) { + elem = elem.eq(0); + if (!elem.find('.layui-table-patch')[0]) { + var patchElem = $('
                '); //补丁元素 + patchElem.find('div').css({ + width: scollWidth + }); + elem.find('tr').append(patchElem); + } + } else { + elem.find('.layui-table-patch').remove(); + } + } + + addPatch(layHeader); + addPatch(layTotal); + + //固定列区域高度 + var mainHeight = layMain.height() + , fixHeight = mainHeight - scollHeight; + layFixed.find('.layui-table-body').css('height', layMainTable.height() >= fixHeight ? fixHeight : 'auto'); + + //表格宽度小于容器宽度时,隐藏固定列 + layFixRight[outWidth > 0 ? 'removeClass' : 'addClass'](HIDE); + + //操作栏 + layFixRight.css('right', scollWidth - 1); + } + }; + + // 输出 + exports('tableChild', mod); +}); + diff --git a/WaterCloud.Web/wwwroot/js/lay-module/soulTable/tableFilter.js b/WaterCloud.Web/wwwroot/js/lay-module/soulTable/tableFilter.js new file mode 100644 index 0000000..122f8f5 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/soulTable/tableFilter.js @@ -0,0 +1,3224 @@ +/** + * + * @name: 表格筛选扩展 + * @author: yelog + * @link: https://github.com/yelog/layui-soul-table + * @license: MIT + * @version: v1.9.0 + */ +layui.define(['table', 'form', 'laydate', 'util', 'excel', 'laytpl'], function (exports) { + + var $ = layui.jquery, + table = layui.table, + form = layui.form, + laydate = layui.laydate, + laytpl = layui.laytpl, + util = layui.util, + excel = layui.excel, + columnsTimeOut, + dorpListTimeOut, + conditionTimeOut, + bfColumnTimeOut, + bfCond1TimeOut, + isFilterReload = {}, + SOUL_ROW_INDEX = 'SOUL_ROW_INDEX', + cache = {}, + HIDE = 'layui-hide', + maxId = 1, + UNHANDLED_VALUES = [undefined, '', null], + where_cache = {}, + isFilterCache = {}, + table_cache = {}, + conditionChangeItems = { + 'eq': '等于', + 'ne': '≠ 不等于', + 'gt': '> 大于', + 'ge': '≥ 大于等于', + 'lt': '< 小于', + 'le': '≤ 小于等于', + 'contain': '包含', + 'notContain': '不包含', + 'start': '以...开头', + 'end': '以...结尾', + 'null': '为空', + 'notNull': '不为空' + }, + dateTimeItems = { + 'all': '全部', + 'yesterday': '昨天', + 'thisWeek': '本周', + 'lastWeek': '上周', + 'thisMonth': '本月', + 'thisYear': '今年' + }, + defaultFilterItems = ['column', 'data', 'condition', 'editCondition', 'excel'], + itemsMap = { + 'column': 'soul-column', + 'data': 'soul-dropList', + 'condition': 'soul-condition', + 'editCondition': 'soul-edit-condition', + 'excel': 'soul-export', + 'clearCache': 'soul-clear-cache', + }, + modeMapItems = { + 'in': 'data', + 'condition': 'condition', + 'date': 'condition', + }, + revertMode = { + 'data': { + 'mode': 'condition', + 'type': 'eq', + 'value': '', + }, + 'condition': { + 'mode': 'in', + 'values': [], + }, + }; + + // 封装方法 + var mod = { + /** + * 摧毁render数据 + * @param myTables + */ + destroy: function (myTables) { + if (myTables) { + if (Array.isArray(myTables)) { + for (var i = 0; i < myTables.length; i++) { + deleteRender(myTables[i]) + } + } else { + deleteRender(myTables); + } + } + + function deleteRender(myTable) { + if (!myTable) { + return; + } + var tableId = myTable.config.id; + $('#soul-filter-list' + tableId).remove(); + $('#soulCondition' + tableId).remove(); + $('#soulDropList' + tableId).remove(); + + delete isFilterReload[tableId]; + delete where_cache[tableId]; + delete table_cache[tableId]; + } + }, + clearFilter: function (myTable) { + if (typeof myTable === 'string') { + myTable = table_cache[myTable] + } + if (!where_cache[myTable.id] || !where_cache[myTable.id].filterSos || where_cache[myTable.id].filterSos === "[]") { + return; + } + where_cache[myTable.id].filterSos = "[]" + this.soulReload(myTable, true) + if (table_cache[myTable.id].where && table_cache[myTable.id].where.filterSos && table_cache[myTable.id].where.filterSos !== "[]") { + table_cache[myTable.id].where.filterSos = "[]" + } + }, + render: function (myTable) { + var _this = this, + $table = $(myTable.elem), + $tableMain = $table.next().children('.layui-table-box').children('.layui-table-main'), + $tableHead = $table.next().children('.layui-table-box').children('.layui-table-header').children('table'), + $fixedLeftTableHead = $table.next().children('.layui-table-box').children('.layui-table-fixed-l').children('.layui-table-header').children('table'), + $fixedRigthTableHead = $table.next().children('.layui-table-box').children('.layui-table-fixed-r').children('.layui-table-header').children('table'), + tableId = myTable.id, + columns = _this.getCompleteCols(myTable.cols), + filterItems = myTable.filter ? myTable.filter.items || defaultFilterItems : defaultFilterItems, + needFilter = false, // 是否存在筛选列需要进行初始化 + initFilter = false, // 是否为第一次筛选 + mainExcel = typeof myTable.excel === 'undefined' || ((myTable.excel && (typeof myTable.excel.on === 'undefined' || myTable.excel.on)) ? myTable.excel : false), + i, j; + + for (i = 0; i < columns.length; i++) { + if (columns[i].field && columns[i].filter) { + needFilter = true; + if ($tableHead.find('th[data-field="' + columns[i].field + '"]').children().children('.soul-table-filter').length === 0) { + initFilter = true; + if ($tableHead.find('th[data-field="' + columns[i].field + '"]').children().children('.layui-table-sort').length > 0) { + $tableHead.find('th[data-field="' + columns[i].field + '"]').children().children('.layui-table-sort').hide() + $tableHead.find('th[data-field="' + columns[i].field + '"]').children().append('') + } else { + $tableHead.find('th[data-field="' + columns[i].field + '"]').children().append('') + } + if ($fixedLeftTableHead.find('th[data-field="' + columns[i].field + '"]').children().children('.layui-table-sort').length > 0) { + $fixedLeftTableHead.find('th[data-field="' + columns[i].field + '"]').children().children('.layui-table-sort').hide() + $fixedLeftTableHead.find('th[data-field="' + columns[i].field + '"]').children().append('') + } else { + $fixedLeftTableHead.find('th[data-field="' + columns[i].field + '"]').children().append('') + } + if ($fixedRigthTableHead.find('th[data-field="' + columns[i].field + '"]').children().children('.layui-table-sort').length > 0) { + $fixedRigthTableHead.find('th[data-field="' + columns[i].field + '"]').children().children('.layui-table-sort').hide() + $fixedRigthTableHead.find('th[data-field="' + columns[i].field + '"]').children().append('') + } else { + $fixedRigthTableHead.find('th[data-field="' + columns[i].field + '"]').children().append('') + } + } + } + } + table_cache[myTable.id] = myTable // 缓存table配置 + isFilterCache[myTable.id] = needFilter; + if (!needFilter) { + // 缓存所有数据 + if (myTable.url && !myTable.page) { + // 修复不分页时,前端筛选后,data不为空,造成所有数据丢失的问题 + cache[myTable.id] = layui.table.cache[myTable.id] + } else { + cache[myTable.id] = myTable.data || layui.table.cache[myTable.id] + } + return; + } //如果没筛选列,直接退出 + + // 渲染底部筛选条件 + if (!(myTable.filter && typeof myTable.filter.bottom !== 'undefined' && !myTable.filter.bottom) && $table.next().children('.soul-bottom-contion').length === 0) { + $table.next().children('.layui-table-box').after('') + var changeHeight = $table.next().children('.layui-table-box').children('.layui-table-body').outerHeight() - $table.next().children('.soul-bottom-contion').outerHeight(); + if (myTable.page && $table.next().children('.layui-table-page').hasClass('layui-hide')) { + changeHeight += $table.next().children('.layui-table-page').outerHeight() + } + $table.next().children('.layui-table-box').children('.layui-table-body').css('height', changeHeight) + var fixHeight = changeHeight - _this.getScrollWidth($tableMain[0]), + layMainTableHeight = $tableMain.children('table').height() + $table.next().children('.layui-table-box').children('.layui-table-fixed').children('.layui-table-body').css('height', layMainTableHeight >= fixHeight ? fixHeight : 'auto') + $table.next().children('.soul-bottom-contion').children('.condition-items').css('width', ($table.next().children('.soul-bottom-contion').width() - $table.next().children('.soul-bottom-contion').children('.editCondtion').width()) + 'px'); + $table.next().children('.soul-bottom-contion').children('.editCondtion').children('a').on('click', function () { + _this.showConditionBoard(myTable); + }) + } + + /** + * 不重载表头数据,重新绑定事件后结束 + */ + if (!initFilter || isFilterReload[myTable.id] || myTable.isSoulFrontFilter) { + isFilterReload[myTable.id] = false + myTable['isSoulFrontFilter'] = false + // 同步选中状态 + if (!myTable.url && myTable.page && myTable.data) { + myTable.data.forEach(function (row) { + for (i = 0; i < cache[myTable.id].length; i++) { + if (cache[myTable.id][i][SOUL_ROW_INDEX] === row[SOUL_ROW_INDEX]) { + cache[myTable.id][i] = row + break; + } + } + }) + } + this.bindFilterClick(myTable); + return; + } else { + if (!myTable.url && myTable.page && myTable.data && myTable.data.length > myTable.limit) { + // 前端分页大于一页,修复 index (用于排序恢复时需要通过这个排序) + layui.each(myTable.data, function (index, item) { + item[myTable.indexName] = index; + }) + } + /** + * 缓存所有数据 + */ + if (myTable.url && !myTable.page) { + // 修复不分页时,前端筛选后,data不为空,造成所有数据丢失的问题 + cache[myTable.id] = layui.table.cache[myTable.id] + } else { + cache[myTable.id] = myTable.data || layui.table.cache[myTable.id] + } + // 给表格数据添加位置标志 + cache[myTable.id].forEach(function (item, index) { + item[SOUL_ROW_INDEX] = index + }) + + if (myTable.filter && myTable.filter.clearFilter) { + if (myTable.where && myTable.where.filterSos && JSON.parse(myTable.where.filterSos).length > 0) { + // 重新查询新数据 + myTable.where.filterSos = '[]'; + where_cache[myTable.id] = myTable.where || {} + _this.soulReload(myTable, false); + return; + } else { + where_cache[myTable.id] = myTable.where || {} + } + } else if ((typeof myTable.url !== 'undefined' && myTable.page ? typeof myTable.where.filterSos === 'undefined' : true) && where_cache[myTable.id] && JSON.parse(where_cache[myTable.id].filterSos || '[]').length > 0) { + myTable.where['filterSos'] = where_cache[myTable.id].filterSos + where_cache[myTable.id] = myTable.where; + _this.soulReload(myTable, false); + return; + } else { + where_cache[myTable.id] = myTable.where || {} + } + } + + // 第一次渲染时,追加数据 + if ($('#soul-filter-list' + tableId).length === 0) { + + if (typeof myTable.soulSort === 'undefined' || myTable.soulSort) { + if (typeof $table.attr('lay-filter') === 'undefined') { + $table.attr('lay-filter', tableId); + } + table.on('sort(' + $table.attr('lay-filter') + ')', function (obj) { + + // 同步分页信息 + myTable.limit = table_cache[myTable.id].limit + + if (myTable.url && myTable.page) { + // 后台分页 + where_cache[myTable.id].field = obj.field; + where_cache[myTable.id].order = obj.type; + isFilterReload[myTable.id] = true; + table.render($.extend(myTable, { + initSort: obj + , where: where_cache[myTable.id] + , page: { + curr: 1 //重新从第 1 页开始 + } + })); + } else if (!myTable.url && myTable.page) { + // 前台分页 + if (obj.type === 'asc') { //升序 + cache[myTable.id] = layui.sort(cache[myTable.id], obj.field) + } else if (obj.type === 'desc') { //降序 + cache[myTable.id] = layui.sort(cache[myTable.id], obj.field, true) + } else { //清除排序 + cache[myTable.id] = layui.sort(cache[myTable.id], myTable.indexName) + } + myTable.initSort = obj; + myTable.page = {curr: 1}; + _this.soulReload(myTable, false) + } + }); + } + + var soulFilterList = [], + filterItemsHtml = { + column: '
              • 表格列
              • ', + data: '
              • 筛选数据
              • ', + condition: '
              • 筛选条件
              • ', + editCondition: '
              • 编辑筛选条件
              • ', + excel: '
              • 导出excel
              • ', + clearCache: '
              • 清除缓存
              • ' + }; + soulFilterList.push('
                '); + soulFilterList.push('
                '); + $('body').append(soulFilterList.join('')); + + + // 显示隐藏列 + var liClick = true; + form.on('checkbox(changeColumns' + tableId + ')', function (data) { + liClick = false; + var columnkey = data.value + if (data.elem.checked) { + $table.next().find('[data-key=' + columnkey + ']').removeClass(HIDE); + } else { + $table.next().find('[data-key=' + columnkey + ']').addClass(HIDE); + } + // 同步配置 + for (i = 0; i < myTable.cols.length; i++) { + for (j = 0; j < myTable.cols[i].length; j++) { + if ((myTable.index + '-' + myTable.cols[i][j].key) === columnkey) { + myTable.cols[i][j]['hide'] = !data.elem.checked + } + } + } + if (layui.soulTable) { + layui.soulTable.fixTableRemember(myTable) + } + $table.next().children('.layui-table-box').children('.layui-table-body').children('table').children('tbody').children('tr.childTr').children('td').attr('colspan', $table.next().children('.layui-table-box').children('.layui-table-header').find('thead>tr>th:visible').length) + table.resize(tableId) + }); + $('#soul-columns' + tableId + '>li[data-value]').on('click', function () { + if (!$(this).find(':checkbox').is(':disabled')) { //disabled禁止点击 + if (liClick) { + $(this).find('div.layui-form-checkbox').trigger('click'); + } + liClick = true; + } + }); + + // 全选-反选事件 + $('#soul-dropList' + tableId + ' .check [data-type]').on('click', function () { + + switch ($(this).data('type')) { + case 'all': + $(this).parents('#soul-dropList' + tableId).find('input[type=checkbox]:not(:checked)').prop('checked', true); + break; + case 'reverse': + $(this).parents('#soul-dropList' + tableId).find('input[type=checkbox]').each(function () { + $(this).prop('checked', !$(this).prop('checked')) + }); + break; + case 'none': + $(this).parents('#soul-dropList' + tableId).find('input[type=checkbox]:checked').prop('checked', false); + break; + } + form.render('checkbox', 'orm'); + _this.updateDropList(myTable, $('#main-list' + tableId).data('field')); + return false; + }); + + // 关键字搜索 + $('#soul-dropList' + tableId + ' .filter-search input').on('input', function () { + var key = $(this).val(); + if (key === '') { + $('#soul-dropList' + tableId + '>ul>li').show(); + } else { + $('#soul-dropList' + tableId + '>ul>li').hide(); + $('#soul-dropList' + tableId + '>ul>li[data-value*="' + key.toLowerCase() + '"]').show(); + } + }) + + // 显示表格列 + $('#main-list' + tableId + ' .soul-column').on('mouseover', function (e) { + _this.hideDropList(myTable); + _this.hideCondition(myTable); + e.stopPropagation(); + if (columnsTimeOut) { + clearTimeout(columnsTimeOut) + } + columns = _this.getCompleteCols(myTable.cols) + for (i = 0; i < columns.length; i++) { + $('#soul-columns' + tableId).find('li[data-value="' + columns[i].field + '"]>input').prop('checked', !columns[i].hide); + } + form.render('checkbox', 'orm'); + $('#soul-columns' + tableId).show(); + var left, animate; + if ($(this).parent().offset().left + $(this).parent().width() + $('#soul-columns' + tableId).width() < document.body.clientWidth) { + left = $(this).parent().offset().left + $(this).parent().width(); + animate = 'fadeInLeft' + } else { + left = $(this).parent().offset().left - $('#soul-columns' + tableId).width(); + animate = 'fadeInRight' + } + $('#soul-columns' + tableId).css({'top': $(this).offset().top, 'left': left}) + .removeClass().addClass(animate + ' animated'); + }); + // 显示数据下拉 + $('#main-list' + tableId + ' .soul-dropList').on('mouseover', function (e) { + if ($('#soul-dropList' + tableId).is(':visible') && !$('#soul-dropList' + tableId).hasClass('fadeOutLeft')) { + return false; + } + _this.hideColumns(myTable); + _this.hideCondition(myTable); + e.stopPropagation(); + if (dorpListTimeOut) { + clearTimeout(dorpListTimeOut); + } + $('#soul-dropList' + tableId + '>.filter-search>input').val(''); + $('#soul-dropList' + tableId).show(); + var left, animate, field = $('#main-list' + tableId).data('field'); + if ($('#main-list' + tableId).offset().left + $('#soul-dropList' + tableId).width() + $('#soul-dropList' + tableId).width() < document.body.clientWidth) { + left = $('#main-list' + tableId).offset().left + $('#main-list' + tableId).width(); + animate = 'fadeInLeft'; + } else { + left = $('#main-list' + tableId).offset().left - $('#soul-dropList' + tableId).width(); + animate = 'fadeInRight'; + } + + $('#soulDropList' + tableId).find('.' + field + 'DropList li input[type=checkbox]:checked').prop('checked', false); + var where = where_cache[myTable.id] || {}, + filterSos = JSON.parse(where.filterSos ? where.filterSos : null), + id = '', prefix = ''; + if (filterSos) { + for (i = 0; i < filterSos.length; i++) { + if (filterSos[i].head && filterSos[i].mode === "in" && filterSos[i].field === field) { + id = filterSos[i].id; + prefix = filterSos[i].prefix; + for (j = 0; j < filterSos[i].values.length; j++) { + $('#soulDropList' + tableId).find('.' + field + 'DropList li input[type=checkbox][value="' + filterSos[i].values[j] + '"]').prop('checked', true); + } + break; + } + } + } + $('#soul-dropList' + tableId + '>ul').data({ + head: true, + 'id': id, + prefix: prefix, + refresh: true, + split: $('#main-list' + tableId).data('split') + }).html($('#soulDropList' + tableId).find('.' + field + 'DropList li').clone()); + + $('#soul-dropList' + tableId).css({'top': $(this).offset().top, 'left': left}) + .show().removeClass().addClass(animate + ' animated'); + setTimeout(function () { + $('#soul-dropList' + tableId + '>.filter-search>input').focus() // 聚焦搜索框 + form.render('checkbox', 'orm'); + }, 1); + + // 监听筛选数据 + var liClick = true; + form.on('checkbox(soulDropList' + tableId + ')', function (data) { + liClick = false; + _this.updateDropList(myTable, field); + }); + + $('#soul-dropList' + tableId + '>ul>li[data-value]').on('click', function () { + if (liClick) { + $(this).find('div.layui-form-checkbox').trigger('click'); + } + liClick = true; + }) + }); + + // 显示筛选条件 + $('#main-list' + tableId + ' .soul-condition').on('mouseover', function (e) { + if ($('#soul-condition' + tableId).is(':visible') && !$('#soul-condition' + tableId).hasClass('fadeOutLeft')) { + return false; + } + _this.hideColumns(myTable); + _this.hideDropList(myTable); + e.stopPropagation(); + if (conditionTimeOut) { + clearTimeout(conditionTimeOut); + } + var documentWidth = document.body.clientWidth; + $('#soul-condition' + tableId).show(); + var left, animate, field = $(this).parent().data('field'); + if ($(this).parent().offset().left + $(this).parent().width() + $('#soul-condition' + tableId).width() < documentWidth) { + left = $(this).parent().offset().left + $(this).parent().width(); + animate = 'fadeInLeft' + } else { + left = $(this).parent().offset().left - $('#soul-condition' + tableId).width(); + animate = 'fadeInRight' + } + + var filterSo, conditionHtml = [], + where = where_cache[myTable.id] || {}, + filterSos = JSON.parse(where.filterSos ? where.filterSos : null); + if (filterSos) { + for (i = 0; i < filterSos.length; i++) { + if (filterSos[i].head && filterSos[i].field === field && (filterSos[i].mode === "date" || filterSos[i].mode === 'group')) { + filterSo = filterSos[i] + break; + } + } + } + + var filterType = $(this).parent().data('type'); + if (_this.startsWith(filterType, 'date')) { + _this.showDate(myTable, field, filterSo, animate, $(this).offset().top, $(this).parent().offset().left + $(this).parent().width(), 'down', true); + } else { + /** + * 筛选条件 + */ + var fieldMap = {}; + for (i = 0; i < columns.length; i++) { + if (columns[i].field) { + fieldMap[columns[i]['field']] = columns[i] + } + } + // 查询条件 + var selectStr = ""; + conditionHtml.push(''); + if (filterSo && filterSo.children && filterSo.children.length > 0) { + for (i = 0; i < filterSo.children.length; i++) { + var id = filterSo.children[i].id, + prefix = filterSo.children[i].prefix, + type = filterSo.children[i].type, + value = filterSo.children[i].value; + conditionHtml.push(''); + if (i === 0) { + conditionHtml.push('') + } else { + conditionHtml.push( + '') + } + conditionHtml.push('') + conditionHtml.push(''); + conditionHtml.push(''); + conditionHtml.push('') + } + } else { + conditionHtml.push('' + + '' + + '' + + '' + + '' + + ''); + } + conditionHtml.push('
                ' + fieldMap[field].title + '' + + '
                ' + + ' ' + + '
                ' + + '
                ' + fieldMap[field].title + '
                ' + selectStr + + '
                ') + + $('#soul-condition' + tableId).data({head: true, id: filterSo ? filterSo.id || '' : ''}) + .html(conditionHtml.join('')) + .css({'top': $(this).offset().top, 'left': left}) + .show().removeClass().addClass(animate + ' animated'); + + $('.condition-table').on('click', function () { + return false; + }) + + // 新增与查询 + $('#soul-condition' + tableId + ' button[data-type]').on('click', function () { + /** + * 新增 + */ + if ($(this).data('type') === 'add') { + var groupId = $('#soul-condition' + tableId).data('id'), + head = $('#soul-condition' + tableId).data('head'), + type = 'eq', + filterSo, + $tr1 = $('#soul-condition' + tableId).find('tr:eq(0)'); + + if (groupId) { + filterSo = { + head: head, + prefix: 'and', + field: field, + mode: 'condition', + type: type, + value: '', + groupId: groupId + } + } else { + filterSo = { + head: head, + prefix: head ? 'and' : 'and', + mode: 'group', + field: field, + children: [{ + id: _this.getDifId(), + prefix: 'and', + field: field, + mode: 'condition', + type: $tr1.find('select').val(), + value: $tr1.find('.value').val() + }, { + id: _this.getDifId(), + prefix: 'and', + field: field, + mode: 'condition', + type: type, + value: '' + }] + } + } + + _this.updateWhere(myTable, filterSo); + if (!groupId) { + $('#soul-condition' + tableId).data('id', filterSo.id); + $tr1.data('id', filterSo.children[0].id); + } + // $tableHead.find('thead>tr>th[data-field="'+field+'"] .soul-table-filter').attr('soul-filter','true'); + var newId = groupId ? filterSo.id : filterSo.children[1].id; + var newTr = '' + + '
                ' + + ' ' + + '
                ' + + '' + + '
                ' + selectStr + '
                ' + + '
                ' + + ''; + + $('#soul-condition' + tableId + ">table>tbody").append(newTr) + $('#soul-condition' + tableId).find('.del:last').on('click', function () { //删除 + delCurrentTr(this) + }); + + // input同步筛选条件 + $('#soul-condition' + tableId + ' input.value:last').on('input', function () { + updateTrWhere($(this).parents('tr:eq(0)')) + }); + } else if ($(this).data('type') === 'search') { + /** + * 查询 + */ + _this.soulReload(myTable); + } + form.render('select', 'orm'); + form.render('checkbox', 'orm'); + return false; + }); + + // input同步筛选条件 + $('#soul-condition' + tableId + ' input.value').on('input', function () { + updateTrWhere($(this).parents('tr:eq(0)')); + }); + + // 当前行改动时,同步where条件 + function updateTrWhere($tr) { + var id = $tr.data('id'), + groupId = $('#soul-condition' + tableId).data('id'), + prefix = $tr.find('input[lay-filter="soul-coondition-switch"]:checked').prop('checked') ? 'and' : 'or', + type = $tr.find('select').val(), + value = $tr.find('.value').val(), + head = $('#soul-condition' + tableId).data('head'); + + if (groupId) { + filterSo = { + id: id, + prefix: prefix, + mode: 'condition', + field: field, + type: type, + value: value, + groupId: groupId + } + } else { + filterSo = { + head: head, + prefix: head ? 'and' : 'and', + mode: 'group', + field: field, + children: [{ + id: _this.getDifId(), + prefix: prefix, + mode: 'condition', + field: field, + type: type, + value: value, + groupId: groupId + }] + } + } + _this.updateWhere(myTable, filterSo) + if (!groupId) { + $('#soul-condition' + tableId).data('id', filterSo.id); + $tr.data('id', filterSo.children[0].id) + } else if (!id) { + $tr.data('id', filterSo.id); + } + } + + // select同步筛选条件 + form.on('select(conditionChange)', function (data) { + if (data.value === 'null' || data.value === 'notNull') { + $(this).parents('tr').find('input.value').hide(); + } else { + $(this).parents('tr').find('input.value').show(); + } + updateTrWhere($(data.elem).parents('tr:eq(0)')); + }) + + // radio同步筛选条件 + form.on('switch(soul-coondition-switch)', function (data) { + updateTrWhere($(this).parents('tr:eq(0)')); + }); + + // 删除当前行 + $('#soul-condition' + tableId + ' .del').on('click', function () { + delCurrentTr(this) + }); + + function delCurrentTr(obj) { + + var id; + + if ($(obj).parents('table:eq(0)').find('tr').length === 1) { + id = $('#soul-condition' + tableId).data('id'); + $('#soul-condition' + tableId).data('id', ''); + $(obj).parents('tr:eq(0)').find('select').val('eq') + $(obj).parents('tr:eq(0)').find('.value').val('').show() + form.render('select', 'orm'); + } else { + id = $(obj).parents('tr:eq(0)').data('id'); + if ($(obj).parents('tr:eq(0)').index() === 0) { + $(obj).parents('table:eq(0)').find('tr:eq(1)>td:eq(0)').html(fieldMap[field].title).addClass('soul-condition-title') + } + $(obj).parents('tr:eq(0)').remove() + } + if (id) { + _this.updateWhere(myTable, { + id: id, + delete: true + }) + } + } + } + form.render('select', 'orm'); + form.render('checkbox', 'orm'); + + }); + + $('#soul-columns' + tableId + ', #soul-dropList' + tableId).on('mouseover', function (e) { + e.stopPropagation(); + }); + $('#main-list' + tableId + ' .soul-edit-condition').on('mouseover', function (e) { + _this.hideColumns(myTable) + _this.hideDropList(myTable) + _this.hideCondition(myTable) + e.stopPropagation(); + }).on('click', function () { + $('#main-list' + tableId).hide(); + _this.showConditionBoard(myTable) + }); + $('#main-list' + tableId + ' .soul-export').on('mouseover', function (e) { + _this.hideColumns(myTable) + _this.hideDropList(myTable) + _this.hideCondition(myTable) + e.stopPropagation(); + }).on('click', function () { + $('#main-list' + tableId).hide(); + _this.export(table_cache[myTable.id]) + }); + + $('#main-list' + tableId + ' .soul-clear-cache').on('mouseover', function (e) { + _this.hideColumns(myTable) + _this.hideDropList(myTable) + _this.hideCondition(myTable) + e.stopPropagation(); + }).on('click', function () { + $('#main-list' + tableId).hide(); + if (layui.soulTable) { + layui.soulTable.clearCache(myTable) + } + layer.msg('已还原!', {icon: 1, time: 1000}) + }); + + $('#main-list' + tableId).on('mouseover', function (e) { + var curX = e.pageX; + var curY = e.pageY; + var div = $(this); + var y1 = div.offset().top; //div上面两个的点的y值 + var y2 = y1 + div.height();//div下面两个点的y值 + var x1 = div.offset().left; //div左边两个的点的x值 + var x2 = x1 + div.width(); //div右边两个点的x的值 + if (curX <= x1 || curX >= x2 || curY <= y1 || curY >= y2) { + } else { + _this.hideColumns(myTable); + _this.hideDropList(myTable); + _this.hideCondition(myTable); + } + }); + } else { + + types = {}; //存储过滤数据的类型 + // 根据表格列显示 + for (i = 0; i < columns.length; i++) { + if (columns[i].type === 'checkbox' || !columns[i].field) { + continue; + } + //存储过滤数据的类型 + if (columns[i].filter && columns[i].filter.type) { + if (columns[i].filter.field) { + types[columns[i].filter.field] = columns[i].filter.type; + } else { + types[columns[i].field] = columns[i].filter.type; + } + } + } + if (JSON.stringify(types).length !== 2) { + myTable.where['tableFilterType'] = JSON.stringify(types); + } + + } + + // 初始化下拉数据 + if ($('#soulDropList' + tableId).length === 0) { + $('body').append(''); + } + + if ($tableHead.find('.soul-table-filter').length > 0) { + var columnField = [], mainDataSwitch = filterItems.indexOf('data') !== -1; + $tableHead.find('.soul-table-filter').each(function (index, elem) { + if ($(this).data('column') && (mainDataSwitch ? (!$(this).data('items') || $(this).data('items').split(',').indexOf('data') !== -1) : $(this).data('items').split(',').indexOf('data') !== -1)) { + columnField.push($(this).data('column')); + } + }); + if (columnField.length > 0) { + if (typeof myTable.url !== 'undefined' && myTable.page) { + var datas = JSON.parse(JSON.stringify(myTable.where)), url = myTable.url; + datas['columns'] = JSON.stringify(columnField); + $.ajax({ + url: url, + data: datas, + dataType: 'json', + method: 'post', + headers: myTable.headers || {}, + contentType: myTable.contentType, + success: function (result) { + + var uls = []; + for (var key in result) { + var list = result[key]; + if (!((list.length === 1 && list[0] === '') || list.length === 0)) { + var ul = []; + ul.push("
                  "); + + var columnsConfigs = columns; + for (j = 0; j < columnsConfigs.length; j++) { + if (columnsConfigs[j].field === key) { + if (columnsConfigs[j].filter.split) { + var tempList = [] + for (i = 0; i < list.length; i++) { + var tempList2 = list[i].split(columnsConfigs[j].filter.split) + for (var k = 0; k < tempList2.length; k++) { + if (tempList.indexOf(tempList2[k]) === -1) { + tempList.push(tempList2[k]); + } + } + } + list = tempList; + } + list.sort(function (a, b) { + if (isNaN(a) || isNaN(b)) { + return String(a) >= String(b) + } else { + return Number(a) - Number(b) + } + }) + for (i = 0; i < list.length; i++) { + if (UNHANDLED_VALUES.indexOf(list[i]) === -1) { + var line = {}; + line[key] = list[i]; + ul.push('
                • ') + } + } + break; + } + } + + ul.push("
                "); + uls.push(ul.join('')); + } else { + uls.push("
                • (无数据)
                ") + } + } + $('#soulDropList' + tableId).html(uls.join('')); + }, + error: function () { + // layer.msg('列筛选数据查询失败!', {icon: 2, anim: 6}) + } + }) + } else { + var tableDatas = cache[myTable.id]; + var dropDatas = {}; + for (i = 0; i < tableDatas.length; i++) { + for (j = 0; j < columnField.length; j++) { + var value = typeof tableDatas[i][columnField[j]] === 'undefined' ? '' : tableDatas[i][columnField[j]]; + if (dropDatas[columnField[j]]) { + if (dropDatas[columnField[j]].indexOf(value) === -1) { + dropDatas[columnField[j]].push(value); + } + } else { + dropDatas[columnField[j]] = [value] + } + } + } + + var columnsConfigs = columns; + var uls = []; + for (j = 0; j < columnsConfigs.length; j++) { + var key = columnsConfigs[j].field; + var list = dropDatas[key]; + if (list && !(list.length === 1 && list[0] === '')) { + if (columnsConfigs[j].filter && columnsConfigs[j].filter.split) { + var tempList = [] + for (i = 0; i < list.length; i++) { + var tempList2 = String(list[i]).split(columnsConfigs[j].filter.split); + for (var k = 0; k < tempList2.length; k++) { + if (tempList.indexOf(tempList2[k]) === -1) { + tempList.push(tempList2[k]) + } + } + } + list = tempList; + } + list.sort(function (a, b) { + if (isNaN(a) || isNaN(b)) { + return String(a) >= String(b) + } else { + return Number(a) - Number(b) + } + }) + var ul = []; + ul.push("
                  "); + for (i = 0; i < list.length; i++) { + if (UNHANDLED_VALUES.indexOf(list[i]) === -1) { + var line = {}; + line[key] = list[i]; + ul.push('
                • ') + } + } + ul.push("
                "); + uls.push(ul.join('')); + } else { + uls.push("
                • (无数据)
                ") + } + } + $('#soulDropList' + tableId).html(uls.join('')); + } + } else { + _this.bindFilterClick(myTable); + } + } + + this.bindFilterClick(myTable); + }, + showConditionBoard: function (myTable) { + var _this = this, + tableId = myTable.id, + where = where_cache[myTable.id] || {}, + tableFilterTypes = where.tableFilterType ? JSON.parse(where.tableFilterType) : {}, + filterSos = where.filterSos ? JSON.parse(where.filterSos) : [], + filterBoard = [], fieldMap = {}, firstColumn, curItems, + filterItems = myTable.filter ? myTable.filter.items || defaultFilterItems : defaultFilterItems, + columns = _this.getCompleteCols(myTable.cols), + i; + for (i = 0; i < columns.length; i++) { + if (columns[i].field && columns[i].filter) { + if (!firstColumn) { + firstColumn = columns[i] + } + curItems = columns[i].filter.items || filterItems; + fieldMap[columns[i]['field']] = { + title: columns[i].title, + items: curItems + } + } + } + filterBoard.push('
                ') + filterBoard.push('
                ') + filterBoard.push('') + filterBoard.push('
                ') + filterBoard.push('
                  ') + for (i = 0; i < filterSos.length; i++) { + groupHtml(filterSos[i], filterBoard, fieldMap, i === 0, i === (filterSos.length - 1)) + } + filterBoard.push('
                ') + filterBoard.push('
                ') + filterBoard.push('
                ') + var _width = document.body.clientWidth > parseInt('480') ? '480px' : document.body.clientWidth - 10 + 'px' + var _height = document.body.clientHeight > parseInt('480') ? '480px' : document.body.clientHeight - 10 + 'px' + layer.open({ + title: '编辑条件', + type: 1, + offset: 'auto', + area: [_width, _height], + content: filterBoard.join('') + }) + form.render(null, 'soul-edit-out'); + + form.on('checkbox(out_auto)', function (data) { + if (data.elem.checked) { + _this.soulReload(myTable); + } + }) + + function groupHtml(filterSo, filterBoard, fieldMap, isFirst, isLast) { + var id = filterSo.id, + field = filterSo.field, + mode = filterSo.mode, + type = filterSo.type, + isOr = filterSo.prefix === 'or'; + filterBoard.push('
              • '); + filterBoard.push('
                ') + // if (!isFirst) { //第一个隐藏 与或 + filterBoard.push('
                ') + // } + switch (mode) { + case 'in': + filterBoard.push('
                ' + (fieldMap[field].title) + '
                '); + filterBoard.push('
                筛选数据
                '); + filterBoard.push('
                共' + (filterSo.values ? filterSo.values.length : 0) + '条数据
                '); + filterBoard.push('
                '); + break; + case 'date': + filterBoard.push('
                ' + (fieldMap[field].title) + '
                '); + filterBoard.push('
                选择日期
                '); + filterBoard.push('
                ' + (filterSo.type === 'specific' ? filterSo.value || '请选择' : dateTimeItems[filterSo.type]) + '
                '); + filterBoard.push('
                '); + break; + case 'condition': + filterBoard.push('
                ' + (fieldMap[field].title) + '
                '); + filterBoard.push('
                ' + conditionChangeItems[filterSo.type] + '
                '); + if (type !== 'null' && type !== 'notNull') { + filterBoard.push('
                ' + (typeof filterSo.value === 'undefined' || filterSo.value === '' ? '请输入...' : filterSo.value) + '
                '); + } + filterBoard.push('
                '); + break; + case 'group': + filterBoard.push('
                分组
                ') + filterBoard.push('') + filterBoard.push('
                '); + filterBoard.push('
                  '); + if (filterSo.children) { + for (var i = 0; i < filterSo.children.length; i++) { + groupHtml(filterSo.children[i], filterBoard, fieldMap, i === 0, i === (filterSo.children.length - 1)); + } + } + filterBoard.push('
                '); + break; + } + filterBoard.push('
              • ') + } + + // prefix + form.on('switch(soul-edit-switch)', function (data) { + changePrefix(data) + }) + + // column + $('.soul-edit-out .item-field').on('click', function (e) { + e.stopPropagation(); + showColums(this) + }) + // type + $('.soul-edit-out .item-type').on('click', function (e) { + e.stopPropagation(); + showTypes(this) + }) + // value + $('.soul-edit-out .item-value').on('click', function (e) { + e.stopPropagation(); + showValue(this) + }) + // delete + $('.soul-edit-out .delete-item').on('click', function () { + var id = $(this).parent().data('id'), + refresh = $('.soul-edit-out .out_auto').prop('checked'); + $(this).parent().remove(); + _this.updateWhere(myTable, { + id: id, + delete: true + }) + if (refresh) { + _this.soulReload(myTable); + } + }) + + function changePrefix(data) { + var prefix = data.elem.checked ? 'and' : 'or', + id = $(data.elem).parents('li:eq(0)').data('id'), + refresh = $('.soul-edit-out .out_auto').prop('checked'); + + $(data.elem).parents('li:eq(0)').data('prefix', prefix); + _this.updateWhere(myTable, { + id: id, + prefix: prefix + }) + + if (refresh) { + _this.soulReload(myTable) + } + } + + function showColums(obj) { + _this.hideDropList(myTable); + _this.hideCondition(myTable); + _this.hideColumns(myTable); + _this.hideBfPrefix(myTable) + _this.hideBfType(myTable); + var top = $(obj).offset().top + $(obj).outerHeight(), + left = $(obj).offset().left; + + $('#soul-bf-column' + tableId).find('li.soul-bf-selected').removeClass('soul-bf-selected') + $('#soul-bf-column' + tableId) + .data('field', $(obj).parent().data('field')) + .data('id', $(obj).parent().data('id')) + .data('mode', $(obj).parent().data('mode')) + .data('group', $(obj).parents('li:eq(2)').data('id') || '') + .data('refresh', $('.soul-edit-out .out_auto').prop('checked')) + .show() + .css({top: top, left: left}) + .removeClass().addClass('fadeInUp animated') + .find('li[data-field="' + $(obj).parent().data('field') + '"]') + .addClass('soul-bf-selected') + } + + function showTypes(obj) { + _this.hideDropList(myTable); + _this.hideCondition(myTable); + _this.hideColumns(myTable); + _this.hideBfColumn(myTable); + _this.hideBfPrefix(myTable); + var top = $(obj).offset().top + $(obj).outerHeight(), + left = $(obj).offset().left, + field = $(obj).parent().data('field'); + + $('#soul-bf-type' + tableId + ' li').hide() + if (tableFilterTypes[field] && tableFilterTypes[field].indexOf('date') === 0) { + $('#soul-bf-type' + tableId + ' li[data-mode=date]').show() + } + if (fieldMap[field].items.indexOf('data') !== -1) { + $('#soul-bf-type' + tableId + ' li[data-mode=in]').show() + } + if (fieldMap[field].items.indexOf('condition') !== -1) { + $('#soul-bf-type' + tableId + ' li[data-mode=condition]').show() + } + + $('#soul-bf-type' + tableId).find('li.soul-bf-selected').removeClass('soul-bf-selected') + switch ($(obj).parent().data('mode')) { + case 'in': + $('#soul-bf-type' + tableId).find('li[data-mode="in"]') + .addClass('soul-bf-selected') + break; + case 'date': + $('#soul-bf-type' + tableId).find('li[data-mode="date"]') + .addClass('soul-bf-selected') + case 'condition': + $('#soul-bf-type' + tableId).find('li[data-value="' + $(obj).parent().data('type') + '"]') + .addClass('soul-bf-selected') + } + + $('#soul-bf-type' + tableId) + .data('type', $(obj).parent().data('type')) + .data('mode', $(obj).parent().data('mode')) + .data('id', $(obj).parent().data('id')) + .data('group', $(obj).parents('li:eq(2)').data('id') || '') + .data('refresh', $('.soul-edit-out .out_auto').prop('checked')) + .show() + .css({top: top, left: left}) + .removeClass().addClass('fadeInUp animated') + } + + function showValue(obj) { + _this.hideColumns(myTable); + _this.hideBfType(myTable); + _this.hideBfPrefix(myTable) + _this.hideBfColumn(myTable); + + var top, + left = $(obj).offset().left, + mode = $(obj).parent().data('mode'), + field = $(obj).parent().data('field'), + id = $(obj).parent().data('id'), + head = $(obj).parent().data('head'), + prefix = $(obj).parent().data('prefix'), + value = $(obj).parent().data('value'), + refresh = $('.soul-edit-out .out_auto').prop('checked'), + where = where_cache[myTable.id] || {}, + filterSos = where.filterSos ? JSON.parse(where.filterSos) : []; + + switch (mode) { + case 'in': + _this.hideCondition(myTable); + if (dorpListTimeOut) { + clearTimeout(dorpListTimeOut); + } + $('#soul-dropList' + tableId + '>.filter-search>input').val(''); + $('#soul-dropList' + tableId).show(); + $('#soulDropList' + tableId).find('.' + field + 'DropList li input[type=checkbox]:checked').prop('checked', false); + var filterSo = _this.getFilterSoById(filterSos, id); + if (filterSo.values) { + for (i = 0; i < filterSo.values.length; i++) { + $('#soulDropList' + tableId).find('.' + field + 'DropList li input[type=checkbox][value="' + filterSo.values[i] + '"]').prop('checked', true); + } + } + + $('#soul-dropList' + tableId + '>ul').data('id', id).data('head', head).data('refresh', refresh).data('prefix', prefix).html($('#soulDropList' + tableId).find('.' + field + 'DropList li').clone()); + form.render('checkbox', 'orm'); + top = $(obj).offset().top + $(obj).outerHeight(); + $('#soul-dropList' + tableId).css({'top': top, 'left': left}) + .show().removeClass().addClass('fadeInUp animated'); + setTimeout(function () { + $('#soul-dropList' + tableId + '>.filter-search>input').focus() // 聚焦搜索框 + }, 1); + + // 监听筛选数据 + var liClick = true; + form.on('checkbox(soulDropList' + tableId + ')', function (data) { + liClick = false; + _this.updateDropList(myTable, field); + }); + + $('#soul-dropList' + tableId + '>ul>li[data-value]').on('click', function () { + if (liClick) { + $(this).find('div.layui-form-checkbox').trigger('click'); + } + liClick = true; + }) + break; + case 'date': + _this.hideDropList(myTable); + if (conditionTimeOut) { + clearTimeout(conditionTimeOut); + } + var filterSo = _this.getFilterSoById(filterSos, id), + top = $(obj).offset().top + $(obj).height(); + + _this.showDate(myTable, field, filterSo, "fadeInUp", top, left, "down", refresh); + break; + case 'condition': + $(obj).hide(); + $(obj).after('
                ') + $(obj).next().children().val(value).select().on('keydown', function (e) { + if (e.keyCode === 13) { + $(this).blur(); + } + }).on('blur', function () { + var newValue = $(this).val(); + $(obj).html(typeof newValue === 'undefined' || newValue === '' ? '请输入...' : newValue); + $(obj).show(); + $(this).parent().remove() + if (newValue !== value) { + $(obj).parent().data('value', newValue); + _this.updateWhere(myTable, { + id: id, + value: newValue + }) + if (refresh) { + _this.soulReload(myTable); + } + } + }) + break; + } + + } + + $('.soul-edit-out a[data-type]').on('click', function () { + if ($(this).data('type') === 'search') { + _this.soulReload(myTable); + } else { + addLine(this) + } + }) + + function addLine(obj) { + var refresh = $('.soul-edit-out .out_auto').prop('checked'); + filterBoard = [] + switch ($(obj).data('type')) { + case 'addOne': + var filterSo = { + prefix: 'and', + field: firstColumn.field, + mode: 'condition', + type: 'eq', + value: '' + } + if ($(obj).parent().parent().data('id')) { + $.extend(filterSo, { + groupId: $(obj).parent().parent().data('id') + }) + } + + _this.updateWhere(myTable, filterSo); + + filterBoard.push('
              • '); + filterBoard.push('
                '); + filterBoard.push('
                ') + filterBoard.push('
                ' + fieldMap[filterSo.field].title + '
                '); + filterBoard.push('
                等于
                '); + filterBoard.push('
                请输入...
                '); + filterBoard.push('
                '); + filterBoard.push('
              • '); + break; + case 'addGroup': + var filterSo = { + prefix: 'and', + mode: 'group', + children: [] + } + if ($(obj).parent().parent().data('id')) { + $.extend(filterSo, { + groupId: $(obj).parent().parent().data('id') + }) + } + _this.updateWhere(myTable, filterSo); + + filterBoard.push('
              • '); + filterBoard.push('
                '); + filterBoard.push('
                ') + filterBoard.push('
                分组
                ') + filterBoard.push('') + filterBoard.push('
                '); + filterBoard.push('
                  '); + filterBoard.push('
                '); + filterBoard.push('
              • '); + break; + } + if (refresh) { + _this.soulReload(myTable); + } + if ($(obj).parent().parent().children('ul').children('li').length > 0) { + $(obj).parent().parent().children('ul').children('li:last').removeClass('last'); + if ($(obj).parent().parent().children('ul').children('li:last').children('ul.group').length > 0) { + $(obj).parent().parent().children('ul').children('li:last').children('ul.group').addClass('line') + } + } + $(obj).parent().parent().children('ul').append(filterBoard.join('')); + form.render('checkbox', 'soul-edit-out') + if ($(obj).data('type') === 'addGroup') { + $(obj).parent().parent().children('ul').children("li:last").find('a[data-type]').on('click', function () { + addLine(this) + }) + } else { + $(obj).parent().parent().children('ul').children("li:last").find('.item-field').on('click', function (e) { + e.stopPropagation(); + showColums(this); + }) + $(obj).parent().parent().children('ul').children("li:last").find('.item-type').on('click', function (e) { + e.stopPropagation(); + showTypes(this); + }) + $(obj).parent().parent().children('ul').children("li:last").find('.item-value').on('click', function (e) { + e.stopPropagation(); + showValue(this); + }) + } + $(obj).parent().parent().children('ul').children("li:last").children('.delete-item').on('click', function () { + var id = $(this).parent().data('id'), + refresh = $('.soul-edit-out .out_auto').prop('checked'); + $(this).parent().remove(); + _this.updateWhere(myTable, { + id: id, + delete: true + }) + if (refresh) { + _this.soulReload(myTable); + } + }) + } + } + , hideColumns: function (myTable, animate) { + var tableId = myTable.id; + + $('#soul-columns' + tableId).removeClass().addClass('fadeOutLeft animated') + if (columnsTimeOut) { + clearTimeout(columnsTimeOut) + } + if (typeof animate === 'undefined' || animate) { + columnsTimeOut = setTimeout(function (e) { + $('#soul-columns' + tableId).hide(); + }, 500) + } else { + $('[id^=soul-columns]').hide(); + } + + } + , hideDropList: function (myTable, animate) { + var tableId = myTable.id; + $('#soul-dropList' + tableId).removeClass().addClass('fadeOutLeft animated') + if (dorpListTimeOut) { + clearTimeout(dorpListTimeOut); + } + if (typeof animate === 'undefined' || animate) { + dorpListTimeOut = setTimeout(function (e) { + $('#soul-dropList' + tableId).hide(); + }, 500) + } else { + $('[id^=soul-dropList]').hide(); + } + + } + , hideCondition: function (myTable, animate) { + var tableId = myTable.id; + $('#soul-condition' + tableId).removeClass().addClass('fadeOutLeft animated') + if (conditionTimeOut) { + clearTimeout(conditionTimeOut); + } + if (typeof animate === 'undefined' || animate) { + conditionTimeOut = setTimeout(function (e) { + $('#soul-condition' + tableId).hide(); + }, 500) + } else { + $('[id^=soul-condition]').hide(); + } + } + , hideBfPrefix: function (myTable, animate) { + var tableId = myTable.id; + $('#soul-bf-prefix' + tableId).removeClass().addClass('fadeOutDown animated') + if (bfColumnTimeOut) { + clearTimeout(bfColumnTimeOut); + } + if (typeof animate === 'undefined' || animate) { + bfColumnTimeOut = setTimeout(function () { + $('#soul-bf-prefix' + tableId).hide(); + }, 500) + } else { + $('[id=soul-bf-prefix' + tableId + ']').hide(); + } + } + , hideBfColumn: function (myTable, animate) { + var tableId = myTable.id; + $('#soul-bf-column' + tableId).removeClass().addClass('fadeOutDown animated') + if (bfColumnTimeOut) { + clearTimeout(bfColumnTimeOut); + } + if (typeof animate === 'undefined' || animate) { + bfColumnTimeOut = setTimeout(function () { + $('#soul-bf-column' + tableId).hide(); + }, 500) + } else { + $('[id=soul-bf-column' + tableId + ']').hide(); + } + } + , hideBfType: function (myTable, animate) { + var tableId = myTable.id; + $('#soul-bf-type' + tableId).removeClass().addClass('fadeOutDown animated') + if (bfCond1TimeOut) { + clearTimeout(bfCond1TimeOut); + } + if (typeof animate === 'undefined' || animate) { + bfCond1TimeOut = setTimeout(function () { + $('#soul-bf-type' + tableId).hide(); + }, 500) + } else { + $('[id=soul-bf-type' + tableId + ']').hide(); + } + } + , bindFilterClick: function (myTable) { + var _this = this, + $table = $(myTable.elem), + $tableHead = $table.next().children('.layui-table-box').children('.layui-table-header').children('table'), + $fixedLeftTableHead = $table.next().children('.layui-table-box').children('.layui-table-fixed-l').children('.layui-table-header').children('table'), + $fixedRigthTableHead = $table.next().children('.layui-table-box').children('.layui-table-fixed-r').children('.layui-table-header').children('table'), + tableId = myTable.id, + filterItems = myTable.filter ? myTable.filter.items || defaultFilterItems : defaultFilterItems, + mainListTimeOut; + + // 显示筛选框 + $tableHead.find('.soul-table-filter').off('click').on('click', function (e) { + e.stopPropagation(); + showFilter($(this)) + }); + $fixedLeftTableHead.find('.soul-table-filter').off('click').on('click', function (e) { + e.stopPropagation(); + showFilter($(this)) + }); + $fixedRigthTableHead.find('.soul-table-filter').off('click').on('click', function (e) { + e.stopPropagation(); + showFilter($(this)) + }); + + function showFilter($that) { + var curItems = $that.data('items') ? $that.data('items').split(',') : filterItems + _this.hideColumns(myTable, false); + _this.hideDropList(myTable, false); + _this.hideCondition(myTable, false); + $('[id^=main-list]').hide(); + + $('#main-list' + tableId).data({'field': $that.data('column'), 'split': $that.data('split')}); + + $('#soul-columns' + tableId + ' [type=checkbox]').attr('disabled', false); + // if (myTable.cols[0][0].type=='checkbox') { + // $('#soul-columns'+tableId+' [type=checkbox]:eq('+($that.parents('th').data('key').split('-')[2]-1)+')').attr('disabled', true); + // } else { + $('#soul-columns' + tableId + ' li[data-key=' + $that.parents('th').data('key').split('-')[2] + '] [type=checkbox]').attr('disabled', true); + // } + + $('#main-list' + tableId + ' > li').hide() + // 是否显示排序框 + if ($that.hasClass('layui-table-sort')) { + $('#main-list' + tableId + ' .soul-sort').show() + } + for (var i = 0; i < curItems.length; i++) { + $('#main-list' + tableId + ' .' + itemsMap[curItems[i]]).show() + if ($('#main-list' + tableId + ' .' + itemsMap[curItems[i]]).index() !== (i + 2)) { + $('#main-list' + tableId + '>li:eq("' + (i + 2) + '")').before($('#main-list' + tableId + ' .' + itemsMap[curItems[i]])) + + } + } + if (mainListTimeOut) { + clearTimeout(mainListTimeOut) + } + var left, animate; + if ($that.offset().left + $('#main-list' + tableId).outerWidth() < document.body.clientWidth) { + left = $that.offset().left + 10; + animate = 'fadeInLeft'; + } else { + left = $that.offset().left - $('#main-list' + tableId).outerWidth(); + animate = 'fadeInRight'; + } + $('#main-list' + tableId).data('type', myTable.where.tableFilterType ? JSON.parse(myTable.where.tableFilterType)[$that.data('column')] || '' : '').hide().css({ + 'top': $that.offset().top + 10, + 'left': left + }).show().removeClass().addClass(animate + ' animated'); + + // 排序 + $('#main-list' + tableId + ' .soul-sort').on('click', function (e) { + $that.siblings('.layui-table-sort').find('.layui-table-sort-' + $(this).data('value')).trigger('click'); + $('#main-list' + tableId).hide(); + }) + form.render('checkbox', 'orm'); + } + + $(document).on('click', function (e) { + $('#main-list' + tableId).hide(); + _this.hideColumns(myTable, false); + _this.hideDropList(myTable, false); + _this.hideCondition(myTable, false); + _this.hideBfPrefix(myTable, false); + _this.hideBfColumn(myTable, false); + _this.hideBfType(myTable, false); + }); + $('#main-list' + tableId + ',#soul-columns' + tableId + ',#soul-dropList' + tableId + ',#soul-condition' + tableId).on('click', function (e) { + $(this).find('.layui-form-selected').removeClass('layui-form-selected') + e.stopPropagation(); + }); + + //渲染底部筛选条件 + _this.renderBottomCondition(myTable); + + // 表头样式 + var where = where_cache[myTable.id] || {}, + filterSos = JSON.parse(where.filterSos ? where.filterSos : '[]'); + + for (var i = 0; i < filterSos.length; i++) { + if (filterSos[i].head) { + var hasFilter = false; + switch (filterSos[i].mode) { + case 'in': + if (filterSos[i].values && filterSos[i].values.length > 0) { + hasFilter = true + } + break; + case 'date': + if (filterSos[i].type !== 'all' && typeof filterSos[i].value !== 'undefined' && filterSos[i].value !== '') { + hasFilter = true + } + break; + case 'group': + if (filterSos[i].children && filterSos[i].children.length > 0) { + hasFilter = true + } + default: + break; + } + $tableHead.find('thead>tr>th[data-field="' + filterSos[i].field + '"] .soul-table-filter').attr('soul-filter', '' + hasFilter); + $fixedLeftTableHead.find('thead>tr>th[data-field="' + filterSos[i].field + '"] .soul-table-filter').attr('soul-filter', '' + hasFilter); + $fixedRigthTableHead.find('thead>tr>th[data-field="' + filterSos[i].field + '"] .soul-table-filter').attr('soul-filter', '' + hasFilter); + } + } + } + , resize: function (myTable) { + var _this = this, + $table = $(myTable.elem), + $tableBox = $table.next().children('.layui-table-box'), + $tableMain = $tableBox.children('.layui-table-main') + // 减去底部筛选的高度 + if ($table.next().children('.soul-bottom-contion').length > 0) { + $table.next().children('.soul-bottom-contion').children('.condition-items').css('width', $table.next().children('.soul-bottom-contion').width() - $table.next().children('.soul-bottom-contion').children('.editCondtion').outerWidth()); + + var bodyHeight = $table.next().height() - $table.next().children('.soul-bottom-contion').outerHeight() + if ($table.next().children('.layui-table-tool').length > 0) { + bodyHeight = bodyHeight - $table.next().children('.layui-table-tool').outerHeight(); + } + if ($table.next().children('.layui-table-total').length > 0) { + bodyHeight = bodyHeight - $table.next().children('.layui-table-total').outerHeight(); + } + if ($table.next().children('.layui-table-page').length > 0) { + bodyHeight = bodyHeight - $table.next().children('.layui-table-page').outerHeight(); + } + + bodyHeight = bodyHeight - $table.next().children('.layui-table-box').children('.layui-table-header').outerHeight(); + + $table.next().children('.layui-table-box').children('.layui-table-body').height(bodyHeight) + var fixHeight = bodyHeight - _this.getScrollWidth($tableMain[0]), + layMainTableHeight = $tableMain.children('table').height() + $table.next().children('.layui-table-box').children('.layui-table-fixed').children('.layui-table-body').height(layMainTableHeight >= fixHeight ? fixHeight : 'auto') + + var scollWidth = $tableMain.width() - $tableMain.prop('clientWidth') //纵向滚动条宽度; + $tableBox.children('.layui-table-fixed-r').css('right', scollWidth - 1); + } + } + /** + * 同步当前 droplist + * @param myTable + * @param field + */ + , updateDropList: function (myTable, field) { + var _this = this, + $table = $(myTable.elem), + tableId = myTable.id, + id = $('#soul-dropList' + tableId + '>ul').data('id'), + $checkedDom = $('#soul-dropList' + tableId + '>ul input[type=checkbox]:checked'), + values = [], + head = $('#soul-dropList' + tableId + '>ul').data('head'), + prefix = $('#soul-dropList' + tableId + '>ul').data('prefix'), + refresh = $('#soul-dropList' + tableId + '>ul').data('refresh'), + split = $('#soul-dropList' + tableId + '>ul').data('split'); + if ($checkedDom.length > 0) { + $checkedDom.each(function () { + values.push($(this).val()) + }) + } + var filterSo = { + id: id, + head: head, + prefix: prefix || 'and', + mode: 'in', + field: field, + split: split, + values: values + }; + _this.updateWhere(myTable, filterSo); + if (!id) { + $('#soul-dropList' + tableId + '>ul').data('id', filterSo.id); + } + + if ($('.soul-edit-out').length > 0) { + $('.soul-edit-out li[data-id="' + filterSo.id + '"]>.item-value').html('共' + (filterSo.values ? filterSo.values.length : 0) + '条数据') + } + + if (refresh) { + _this.soulReload(myTable); + } + } + , getFilterSoById: function (filterSos, id) { + for (var i = 0; i < filterSos.length; i++) { + if (filterSos[i].id === id) { + return filterSos[i] + } else if (filterSos[i].mode === 'group') { + for (var j = 0; j < filterSos[i].children.length; j++) { + var filterSo = this.getFilterSoById(filterSos[i].children, id); + if (filterSo) return filterSo; + } + } + } + return null + } + /** + * 更新 filter 条件 + * @param myTable + * @param filterSo + */ + , updateWhere: function (myTable, filterSo) { + var _this = this, + where = where_cache[myTable.id] || {}, + filterSos = JSON.parse(where.filterSos ? where.filterSos : '[]'); + + if (filterSo.id || filterSo.groupId) { + for (var i = 0; i < filterSos.length; i++) { + if (filterSo.delete && filterSos[i].id === filterSo.id) { + filterSos.splice(i, 1); + break; + } + if (updateFilterSo(filterSos[i], filterSo)) { + break; + } + } + } else if (!(filterSo.mode === 'in' && !(filterSo.values && filterSo.values.length > 0))) { + filterSos.push($.extend(filterSo, { + id: _this.getDifId() + })) + } + where['filterSos'] = JSON.stringify(filterSos); + myTable.where = where; + where_cache[myTable.id] = where; + + function updateFilterSo(filterSo, newFilterSo) { + var isMatch = false; + + if (filterSo.id === newFilterSo.id) { + $.extend(filterSo, newFilterSo); + isMatch = true; + } + + // 在分组中新增 + if (!newFilterSo.id && filterSo.id === newFilterSo.groupId) { + filterSo.children.push($.extend(newFilterSo, { + id: _this.getDifId() + })) + } else if (filterSo.mode === 'group') { + for (var i = 0; i < filterSo.children.length; i++) { + if (newFilterSo.delete && filterSo.children[i].id === newFilterSo.id) { + filterSo.children.splice(i, 1); + return true; + } + if (updateFilterSo(filterSo.children[i], newFilterSo)) { + return true; + } + } + + } + + return isMatch; + } + } + /** + * 根据当前条件重载表格 + * @param myTable 需要重载的表格对象 + * @param isr 是否为筛选重载,为 true 时,不进行筛选的初始化动作(包括渲染dom、请求表头数据等) + */ + , soulReload: function (myTable, isr) { + var _this = this, + $table = $(myTable.elem), + scrollLeft = $table.next().children('.layui-table-box').children('.layui-table-main').scrollLeft(); + + isFilterReload[myTable.id] = typeof isr === 'undefined' ? true : isr; + if (typeof myTable.url !== 'undefined' && myTable.page) { + $table.data('scrollLeft', scrollLeft); + /** + * 后台筛选 + */ + table.reload(myTable.id, { + where: where_cache[myTable.id] || {}, + page: { + curr: 1 //重新从第 1 页开始 + } + }, true) + } else { + /** + * 前端筛选 + */ + var where = where_cache[myTable.id] || {}, + filterSos = JSON.parse(where.filterSos ? where.filterSos : '[]'), + tableFilterTypes = where.tableFilterType ? JSON.parse(where.tableFilterType) : {}, + loading = layer.load(2); + if (!myTable.page) { + // 修复前端不分页时,layui table bug 导致的只显示10条数据的问题 + myTable.limit = 100000000 + } + if (filterSos.length > 0) { + var newData = []; + layui.each(cache[myTable.id], function (index, item) { + var show = true; + + for (var i = 0; i < filterSos.length; i++) { + show = _this.handleFilterSo(filterSos[i], item, tableFilterTypes, show, i === 0) + } + + if (show) { + newData.push(item) + } + }) + if (myTable.page) { + table.reload(myTable.id, { + data: newData + , initSort: myTable.initSort + , isSoulFrontFilter: true + , page: { + curr: 1 //重新从第 1 页开始 + } + }, true) + } else { + var url = myTable.url; + $table.next().off('click') + var inst = table.reload(myTable.id, { + url: '' + , initSort: myTable.initSort + , isSoulFrontFilter: true + , data: newData + }, true) + inst.config.url = url; + } + myTable.data = newData + + } else { + if (myTable.page) { + table.reload(myTable.id, { + data: cache[myTable.id] + , initSort: myTable.initSort + , isSoulFrontFilter: true + , page: { + curr: 1 //重新从第 1 页开始 + } + }, true) + } else { + table.reload(myTable.id, { + data: cache[myTable.id] + , initSort: myTable.initSort + , isSoulFrontFilter: true + }, true) + } + myTable.data = cache[myTable.id] + } + $table.next().children('.layui-table-box').children('.layui-table-main').scrollLeft(scrollLeft); + layer.close(loading) + } + } + , handleFilterSo: function (filterSo, item, tableFilterTypes, show, first) { + var isOr = first ? false : filterSo.prefix === 'or', + field = filterSo.field, + value = filterSo.value, + status = true; + + // 如果有子元素 + if (filterSo.children && filterSo.children.length > 0) { + for (var i = 0; i < filterSo.children.length; i++) { + status = this.handleFilterSo(filterSo.children[i], item, tableFilterTypes, status, i === 0) + } + return isOr ? show || status : show && status; + } + + switch (filterSo.mode) { + case "in": + if (filterSo.values && filterSo.values.length > 0) { + if (filterSo.split) { + var tempList = (item[field] + '').split(filterSo.split); + var tempStatus = false; + for (var i = 0; i < tempList.length; i++) { + if (filterSo.values.indexOf(tempList[i]) !== -1) { + tempStatus = true; + } + } + status = tempStatus; + } else { + status = filterSo.values.indexOf(item[field] + '') !== -1 + } + } else { + return show; + } + break; + case "condition": + if (filterSo.type !== 'null' && filterSo.type !== 'notNull' && (typeof value === 'undefined' || value === '')) { + return show; + } + switch (filterSo.type) { + case "eq": + status = isNaN(item[field]) || isNaN(value) ? item[field] === value : Number(item[field]) === Number(value); + break; + case "ne": + status = isNaN(item[field]) || isNaN(value) ? item[field] !== value : Number(item[field]) !== Number(value); + break; + case "gt": + status = isNaN(item[field]) || isNaN(value) ? item[field] > value : Number(item[field]) > Number(value); + break; + case "ge": + status = isNaN(item[field]) || isNaN(value) ? item[field] >= value : Number(item[field]) >= Number(value); + break; + case "lt": + status = isNaN(item[field]) || isNaN(value) ? item[field] < value : Number(item[field]) < Number(value); + break; + case "le": + status = isNaN(item[field]) || isNaN(value) ? item[field] <= value : Number(item[field]) <= Number(value); + break; + case "contain": + status = (item[field] + '').indexOf(value) !== -1; + break; + case "notContain": + status = (item[field] + '').indexOf(value) === -1; + break; + case "start": + status = (item[field] + '').indexOf(value) === 0; + break; + case "end": + var d = (item[field] + '').length - (value + '').length; + status = d >= 0 && (item[field] + '').lastIndexOf(value) === d; + break; + case "null": + status = typeof item[field] === 'undefined' || item[field] === '' || item[field] === null; + break; + case "notNull": + status = typeof item[field] !== 'undefined' && item[field] !== '' && item[field] !== null; + break; + } + break; + case "date": + var dateVal = new Date(Date.parse(item[field].replace(/-/g, "/"))); + switch (filterSo.type) { + case 'all': + status = true; + break; + case 'yesterday': + status = item[field] && isBetween(dateVal, getToday() - 86400, getToday() - 1); + break; + case 'thisWeek': + status = item[field] && isBetween(dateVal, getFirstDayOfWeek(), getFirstDayOfWeek() + 86400 * 7 - 1); + break; + case 'lastWeek': + status = item[field] && isBetween(dateVal, getFirstDayOfWeek() - 86400 * 7, getFirstDayOfWeek() - 1); + break; + case 'thisMonth': + status = item[field] && isBetween(dateVal, getFirstDayOfMonth(), getCurrentMonthLast()); + break; + case 'thisYear': + status = item[field] && isBetween(dateVal, new Date(new Date().getFullYear(), 1, 1) / 1000, new Date(new Date().getFullYear() + 1, 1, 1) / 1000 - 1); + break; + case 'specific': + var dateFormat = dateVal.getFullYear(); + dateFormat += '-' + (timeAdd0(dateVal.getMonth() + 1)); + dateFormat += '-' + timeAdd0(dateVal.getDate()); + status = item[field] && dateFormat === value + break; + } + break; + } + + // 今天凌晨 + function getToday() { + return new Date().setHours(0, 0, 0, 0) / 1000; + } + + // 本周第一天 + function getFirstDayOfWeek() { + var now = new Date(); + var weekday = now.getDay() || 7; //获取星期几,getDay()返回值是 0(周日) 到 6(周六) 之间的一个整数。0||7为7,即weekday的值为1-7 + return new Date(now.setDate(now.getDate() - weekday + 1)).setHours(0, 0, 0, 0) / 1000;//往前算(weekday-1)天,年份、月份会自动变化 + } + + //获取当月第一天 + function getFirstDayOfMonth() { + return new Date(new Date().setDate(1)).setHours(0, 0, 0, 0) / 1000; + } + + //获取当月最后一天最后一秒 + function getCurrentMonthLast() { + var date = new Date(); + var currentMonth = date.getMonth(); + var nextMonth = ++currentMonth; + var nextMonthFirstDay = new Date(date.getFullYear(), nextMonth, 1); + return nextMonthFirstDay / 1000 - 1; + } + + function isBetween(v, a, b) { + return (v.getTime() / 1000) >= a && (v.getTime() / 1000) <= b; + } + + function timeAdd0(str) { + str += ""; + if (str.length <= 1) { + str = '0' + str; + } + return str + } + + return isOr ? show || status : show && status; + } + , getDifId: function () { + return maxId++; + } + , showDate: function (myTable, field, filterSo, animate, top, left, type, refresh) { + var _this = this, + tableId = myTable.id, + conditionHtml = [], + documentWidth = document.body.clientWidth, + animate; + conditionHtml.push('
                '); + conditionHtml.push('
                '); + for (var key in dateTimeItems) { + conditionHtml.push('
                '); + } + conditionHtml.push('
                '); + conditionHtml.push('
                '); + $('#soul-condition' + tableId).html(conditionHtml.join('')); + var filterDate = util.toDateString(new Date(), 'yyyy-MM-dd'); + if (filterSo) { + $('#soul-condition' + tableId).data({'id': filterSo.id, 'head': true}); + $('#soul-condition' + tableId + '>.' + field + 'Condition' + ' [name^=datetime][value="' + filterSo.type + '"]').prop('checked', true); + if (filterSo.type === 'specific') { + filterDate = filterSo.value + } + } else { + $('#soul-condition' + tableId).data({'id': '', 'head': true}); + $('#soul-condition' + tableId + '>.' + field + 'Condition' + ' [name^=datetime][value="all"]').prop('checked', true); + } + + $('#soul-condition' + tableId + ' .specific_value').val(filterDate); + laydate.render({ + elem: '#soul-condition' + tableId + ' .staticDate' + , position: 'static' + , calendar: true + , btns: ['now'] + , value: filterDate + , done: function (value) { + var id = $('#soul-condition' + tableId).data('id'), + head = $('#soul-condition' + tableId).data('head') + $('#soul-condition' + tableId + ' .specific_value').val(value); + $('#soul-condition' + tableId + ' [name^=datetime]:checked').prop('checked', false); + $('#soul-condition' + tableId + ' [name^=datetime][value=specific]').prop('checked', true); + var filterSo = { + id: id, + head: head, + prefix: head ? 'and' : 'and', + mode: 'date', + field: field, + type: 'specific', + value: value + } + _this.updateWhere(myTable, filterSo); + if (!id) { + $('#soul-condition' + tableId).data('id', filterSo.id) + } + if ($('.soul-edit-out').length > 0) { + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').children('.item-value').html(filterSo.value) + } + if (refresh) { + _this.soulReload(myTable); + } + form.render('radio', 'orm'); + } + }); + form.on('radio(datetime' + tableId + ')', function (data) { + var id = $('#soul-condition' + tableId).data('id'), + head = $('#soul-condition' + tableId).data('head') + var filterSo = { + id: id, + head: head, + prefix: head ? 'and' : 'and', + mode: 'date', + field: field, + type: data.value, + value: $('#soul-condition' + tableId + ' .specific_value').val() + } + _this.updateWhere(myTable, filterSo); + if (!id) { + $('#soul-condition' + tableId).data('id', filterSo.id) + } + if ($('.soul-edit-out').length > 0) { + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').children('.item-value').html(dateTimeItems[filterSo.type] || filterSo.value) + } + if (refresh) { + _this.soulReload(myTable); + } + }); + form.render('radio', 'orm') + if (type === 'down') { + if (left + $('#soul-condition' + tableId).width() < documentWidth) { + animate = 'fadeInLeft' + } else { + left = left - $('#main-list' + tableId).width() - $('#soul-condition' + tableId).width(); + animate = 'fadeInRight' + } + } else { + top = top - $('#soul-condition' + tableId).outerHeight() - 10; + } + $('#soul-condition' + tableId).css({'top': top, 'left': left}) + .show().removeClass().addClass(animate + ' animated'); + + } + , bottomConditionHtml: function (bcHtml, filterSo, fieldMap, first) { + var _this = this, + isOr = filterSo.prefix === 'or', + field = filterSo.field; + + if (filterSo.mode === 'group') { + if (filterSo.children && filterSo.children.length > 0) { + bcHtml.push('
                '); + if (!first) { + bcHtml.push('
                ' + (isOr ? '或' : '与') + '
                '); + } + + for (var i = 0; i < filterSo.children.length; i++) { + _this.bottomConditionHtml(bcHtml, filterSo.children[i], fieldMap, i === 0); + } + bcHtml.push(''); + bcHtml.push('
                ') + } + return; + } + bcHtml.push('
                '); + if (!first) { + bcHtml.push('
                ' + (isOr ? '或' : '与') + '
                '); + } + bcHtml.push('
                ' + fieldMap[field].title + '
                '); + bcHtml.push('
                '); + switch (filterSo.mode) { + case 'in': + bcHtml.push('筛选数据'); + break; + case 'condition': + bcHtml.push(conditionChangeItems[filterSo.type]); + break; + case 'date': + bcHtml.push('选择日期'); + break; + default: + bcHtml.push('未知'); + break; + } + bcHtml.push('
                '); + if (filterSo.type !== 'null' && filterSo.type !== 'notNull') { + bcHtml.push('
                '); + switch (filterSo.mode) { + case 'in': + bcHtml.push('共' + (filterSo.values ? filterSo.values.length : 0) + '条数据'); + break; + case 'date': + bcHtml.push(filterSo.type === 'specific' ? filterSo.value || '请选择' : dateTimeItems[filterSo.type]) + break; + case 'condition': + default: + bcHtml.push(typeof filterSo.value === 'undefined' || filterSo.value === '' ? '请输入...' : filterSo.value); + break; + } + + bcHtml.push('
                ') + } + bcHtml.push(''); + bcHtml.push('
                ') + } + , renderBottomCondition: function (myTable) { + var _this = this, + where = where_cache[myTable.id] || {}, + filterSos = where.filterSos ? JSON.parse(where.filterSos) : [], + tableFilterTypes = where.tableFilterType ? JSON.parse(where.tableFilterType) : {}, + $table = $(myTable.elem), + tableId = myTable.id, + $bottomCondition = $table.next().children('.soul-bottom-contion'), + fieldMap = {}, bcHtml = [], curItems, + filterItems = myTable.filter ? myTable.filter.items || defaultFilterItems : defaultFilterItems, + columns = _this.getCompleteCols(myTable.cols); + for (var i = 0; i < columns.length; i++) { + if (columns[i].field && columns[i].filter) { + curItems = columns[i].filter.items || filterItems; + if (curItems.indexOf('data') !== -1 || curItems.indexOf('condition') !== -1) { + fieldMap[columns[i]['field']] = { + title: columns[i].title, + items: curItems + } + } + } + } + + /** + * 一、拼装底部内容 + */ + for (var i = 0; i < filterSos.length; i++) { + _this.bottomConditionHtml(bcHtml, filterSos[i], fieldMap, i === 0); + } + $bottomCondition.children('.condition-items').html(bcHtml.join('')) + + /** + * 二、组装底部弹窗条件 + */ + bcHtml = []; + // 1. prefix + if ($('#soul-bf-prefix' + tableId).length === 0) { + bcHtml.push('') + } + // 2. 列选择 + if ($('#soul-bf-column' + tableId).length === 0) { + bcHtml.push('') + } + + // 3. 条件选择 + if ($('#soul-bf-type' + tableId).length === 0) { + bcHtml.push('') + } + + // 4. 值选择 + if ($('#soul-bf-cond2-dropList' + tableId).length === 0) { + bcHtml.push('') + } + + + $('body').append(bcHtml.join('')) + + /** + * 三、底部弹窗事件 + */ + // 1. prefix弹出事件 + $bottomCondition.find('.item-prefix').off('click').on('click', function (e) { + e.stopPropagation(); + $('#main-list' + tableId).hide(); + _this.hideDropList(myTable); + _this.hideCondition(myTable); + _this.hideColumns(myTable); + _this.hideBfColumn(myTable); + _this.hideBfType(myTable); + var top = $(this).offset().top - $('#soul-bf-prefix' + tableId).outerHeight() - 10, + left = $(this).offset().left; + + $('#soul-bf-prefix' + tableId).find('li.soul-bf-selected').removeClass('soul-bf-selected') + $('#soul-bf-prefix' + tableId) + .data('id', $(this).parent().data('id')) + .data('prefix', $(this).parent().data('prefix')) + .data('refresh', true) + .show() + .css({top: top, left: left}) + .removeClass().addClass('fadeInUp animated') + .find('li[data-value="' + $(this).parent().data('prefix') + '"]') + .addClass('soul-bf-selected') + + }) + // 2. 弹出列选择 + $bottomCondition.find('.item-field').off('click').on('click', function (e) { + e.stopPropagation(); + $('#main-list' + tableId).hide(); + _this.hideDropList(myTable); + _this.hideCondition(myTable); + _this.hideColumns(myTable); + _this.hideBfPrefix(myTable) + _this.hideBfType(myTable); + var top = $(this).offset().top - $('#soul-bf-column' + tableId).outerHeight() - 10, + left = $(this).offset().left; + + $('#soul-bf-column' + tableId).find('li.soul-bf-selected').removeClass('soul-bf-selected') + $('#soul-bf-column' + tableId) + .data('field', $(this).parent().data('field')) + .data('id', $(this).parent().data('id')) + .data('mode', $(this).parent().data('mode')) + .data('group', $(this).parent().parent().data('id') || '') + .data('refresh', true) + .show() + .css({top: top, left: left}) + .removeClass().addClass('fadeInUp animated') + .find('li[data-field="' + $(this).parent().data('field') + '"]') + .addClass('soul-bf-selected') + }) + + // 3. 弹出方式选择 + $bottomCondition.find('.item-type').on('click', function (e) { + e.stopPropagation(); + $('#main-list' + tableId).hide(); + _this.hideDropList(myTable); + _this.hideCondition(myTable); + _this.hideColumns(myTable); + _this.hideBfColumn(myTable); + _this.hideBfPrefix(myTable); + var field = $(this).parent().data('field') + $('#soul-bf-type' + tableId + ' li').hide() + if (tableFilterTypes[field] && tableFilterTypes[field].indexOf('date') === 0) { + $('#soul-bf-type' + tableId + ' li[data-mode=date]').show() + } + if (fieldMap[field].items.indexOf('data') !== -1) { + $('#soul-bf-type' + tableId + ' li[data-mode=in]').show() + } + if (fieldMap[field].items.indexOf('condition') !== -1) { + $('#soul-bf-type' + tableId + ' li[data-mode=condition]').show() + } + + var top = $(this).offset().top - $('#soul-bf-type' + tableId).outerHeight() - 10, + left = $(this).offset().left; + $('#soul-bf-type' + tableId).find('li.soul-bf-selected').removeClass('soul-bf-selected') + switch ($(this).parent().data('mode')) { + case 'in': + $('#soul-bf-type' + tableId).find('li[data-mode="in"]') + .addClass('soul-bf-selected') + break; + case 'date': + $('#soul-bf-type' + tableId).find('li[data-mode="date"]') + .addClass('soul-bf-selected') + case 'condition': + $('#soul-bf-type' + tableId).find('li[data-value="' + $(this).parent().data('type') + '"]') + .addClass('soul-bf-selected') + } + + $('#soul-bf-type' + tableId) + .data('type', $(this).parent().data('type')) + .data('mode', $(this).parent().data('mode')) + .data('id', $(this).parent().data('id')) + .data('group', $(this).parent().parent().data('id') || '') + .data('refresh', true) + .show() + .css({top: top, left: left}) + .removeClass().addClass('fadeInUp animated') + }) + + // 4. 弹出值选择 + $bottomCondition.find('.item-value').on('click', function (e) { + e.stopPropagation(); + $('#main-list' + tableId).hide(); + _this.hideColumns(myTable); + _this.hideBfType(myTable); + _this.hideBfPrefix(myTable) + _this.hideBfColumn(myTable); + var top, + left = $(this).offset().left, + mode = $(this).parent().data('mode'), + field = $(this).parent().data('field'), + id = $(this).parent().data('id'), + head = $(this).parent().data('head'), + prefix = $(this).parent().data('prefix'); + + switch (mode) { + case 'in': + _this.hideCondition(myTable); + if (dorpListTimeOut) { + clearTimeout(dorpListTimeOut); + } + $('#soul-dropList' + tableId + '>.filter-search>input').val(''); + $('#soul-dropList' + tableId).show(); + $('#soulDropList' + tableId).find('.' + field + 'DropList li input[type=checkbox]:checked').prop('checked', false); + var filterSo = _this.getFilterSoById(filterSos, id); + for (var i = 0; i < filterSo.values.length; i++) { + $('#soulDropList' + tableId).find('.' + field + 'DropList li input[type=checkbox][value="' + filterSo.values[i] + '"]').prop('checked', true); + } + + $('#soul-dropList' + tableId + '>ul').data('id', id).data('head', head).data('refresh', true).data('prefix', prefix).html($('#soulDropList' + tableId).find('.' + field + 'DropList li').clone()); + form.render('checkbox', 'orm'); + top = $(this).offset().top - $('#soul-dropList' + tableId).outerHeight() - 10; + $('#soul-dropList' + tableId).css({'top': top, 'left': left}) + .show().removeClass().addClass('fadeInUp animated'); + setTimeout(function () { + $('#soul-dropList' + tableId + '>.filter-search>input').focus() // 聚焦搜索框 + }, 1); + + + // 监听筛选数据 + var liClick = true; + form.on('checkbox(soulDropList' + tableId + ')', function (data) { + liClick = false; + _this.updateDropList(myTable, field); + }); + + $('#soul-dropList' + tableId + '>ul>li[data-value]').on('click', function () { + if (liClick) { + $(this).find('div.layui-form-checkbox').trigger('click'); + } + liClick = true; + }) + break; + case 'date': + _this.hideDropList(myTable); + if (conditionTimeOut) { + clearTimeout(conditionTimeOut); + } + var filterSo = _this.getFilterSoById(filterSos, id), + top = $(this).offset().top - 10; + + _this.showDate(myTable, field, filterSo, "fadeInUp", top, left, "up", true); + break; + default: + _this.hideDropList(myTable); + if (conditionTimeOut) { + clearTimeout(conditionTimeOut); + } + var obj = this, + value = $(this).parents('.condition-item:eq(0)').data('value'); + $(obj).hide(); + $(obj).after('
                ') + $(obj).next().children().val(value).select().on('keydown', function (e) { + if (e.keyCode === 13) { + $(this).blur(); + } + }).on('blur', function () { + var newValue = $(this).val(); + $(obj).html(typeof newValue === 'undefined' || newValue === '' ? '请输入...' : newValue); + $(obj).show(); + $(this).parent().remove() + if (newValue !== value) { + _this.updateWhere(myTable, { + id: id, + value: newValue + }) + _this.soulReload(myTable); + } + }) + + break; + } + }) + + /** + * 三、选择事件 + */ + // 1. 选择prefix + $('#soul-bf-prefix' + tableId + '>ul>li').off('click').on('click', function () { + var id = $(this).parent().parent().data('id'), + newPrefix = $(this).data('value'), + oldPrefix = $(this).parent().parent().data('prefix'), + refresh = $(this).parent().parent().data('refresh'); + + if (oldPrefix !== newPrefix) { + _this.updateWhere(myTable, { + id: id, + prefix: newPrefix + }); + if (refresh === true) { + _this.soulReload(myTable); + } + } + }) + // 1. 选择列 + $('#soul-bf-column' + tableId + '>ul>li').off('click').on('click', function () { + var oldField = $(this).parent().parent().data('field'), + newField = $(this).data('field'), + mode = $(this).parent().parent().data('mode'), + group = $(this).parent().parent().data('group'), + refresh = $(this).parent().parent().data('refresh'); + + if (oldField !== newField) { + var filterSo = { + id: $(this).parent().parent().data('id'), + field: newField + } + if (fieldMap[newField].items.indexOf(modeMapItems[mode]) === -1) { + $.extend(filterSo, $.extend({}, revertMode[modeMapItems[mode]], + revertMode[modeMapItems[mode]].mode === 'condition' && _this.startsWith(tableFilterTypes[newField], 'date') + ? { + mode: 'date', + type: 'all' + } : {})) + } else { + // 重置values值 + if (mode === 'in') { + $.extend(filterSo, { + values: [] + }) + } else if (mode === 'date' && !(_this.startsWith(tableFilterTypes[newField], 'date'))) { + $.extend(filterSo, { + mode: 'condition', + type: 'eq', + value: '' + }) + } else if (mode !== 'date' && _this.startsWith(tableFilterTypes[newField], 'date')) { + $.extend(filterSo, { + mode: 'date', + type: 'all' + }) + } + } + // 如果是头部条件,选择列是清除 + if (group) { + _this.updateWhere(myTable, { + id: group, + head: false + }) + } + _this.updateWhere(myTable, filterSo); + + if ($('.soul-edit-out').length > 0) { + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').data(filterSo).children('.item-field').html(fieldMap[newField].title); + if (filterSo.mode === 'in') { + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').children('.item-type').html('筛选数据') + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').children('.item-value').html('共0条数据') + } else if (mode !== filterSo.mode) { + if (filterSo.mode === 'date') { + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').children('.item-type').html('选择日期') + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').children('.item-value').html(dateTimeItems[filterSo.type]) + } else if (filterSo.mode === 'condition') { + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').children('.item-type').html(conditionChangeItems[filterSo.type]) + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').children('.item-value').html(filterSo.value === '' ? '请输入...' : filterSo.value) + } + } + } + + if (refresh === true) { + _this.soulReload(myTable); + } + } + }) + + // 2. 选择类型 + $('#soul-bf-type' + tableId + '>ul>li').off('click').on('click', function () { + var newType = $(this).data('value') + "" // 引号修复为空(null值)传递问题 + , newMode = $(this).data('mode') + , type = $(this).parent().parent().data('type') + , mode = $(this).parent().parent().data('mode') + , group = $(this).parent().parent().data('group') + , refresh = $(this).parent().parent().data('refresh') + if (type !== newType) { + + var filterSo = { + id: $(this).parent().parent().data('id'), + type: newType, + mode: newMode + } + if (mode !== newMode) { + $.extend(filterSo, { + value: '', + values: [] + }) + } + + // 如果是头部条件,选择列是清除 + if (group && newMode === 'in') { + _this.updateWhere(myTable, { + id: group, + head: false + }) + } + _this.updateWhere(myTable, filterSo) + + if ($('.soul-edit-out').length > 0) { + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').data(filterSo).children('.item-value').show(); + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').data(filterSo).children('.item-type').html(conditionChangeItems[newType] || (newMode === 'in' ? '筛选数据' : '选择日期')); + switch (newMode) { + case 'in': + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').data(filterSo).children('.item-value').html('共0条数据'); + break; + case 'date': + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').data(filterSo).children('.item-value').html(dateTimeItems[newType]); + break; + case 'condition': + if (mode !== newMode) { + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').data(filterSo).children('.item-value').html('请输入...'); + } + $('.soul-edit-out li[data-id="' + filterSo.id + '"]').data(filterSo).children('.item-value')[newType === 'null' || newType === 'notNull' ? 'hide' : 'show']() + + break; + } + } + + // 是否立即更新 + if (refresh === true) { + _this.soulReload(myTable); + } + } + }) + + /** + * 五、底部筛选条件删除事件 + */ + $bottomCondition.find('.condition-items .condition-item .condition-item-close').on('click', function () { + _this.updateWhere(myTable, { + id: $(this).parents('.condition-item:eq(0)').data('id'), + delete: true + }) + _this.soulReload(myTable); + }) + + } + /** + * 导出 excel 文件 + * @param myTable + * @param curExcel + */ + , export: function (myTable, curExcel) { + if (typeof myTable === 'string') { + myTable = table_cache[myTable] // tableId 转 myTable + } + var loading = layer.msg('文件下载中', { + icon: 16 + , time: -1 + , anim: -1 + , fixed: false + }); + var cols = this.deepClone(myTable.cols) + , style = myTable.elem.next().find('style')[0] + , sheet = style.sheet || style.styleSheet || {} + , rules = sheet.cssRules || sheet.rules; + + layui.each(rules, function (i, item) { + if (item.style.width) { + var keys = item.selectorText.split('-'); + cols[keys[3]][keys[4]]['width'] = parseInt(item.style.width) + } + }) + + var data = JSON.parse(JSON.stringify(myTable.data || cache[myTable.id])), + showField = {}, + widths = {}, + mergeArrays = [], // 合并配置 + heightConfig = {}, + $table = $(myTable.elem), + $tableBody = $table.next().children('.layui-table-box').children('.layui-table-body').children('table'), + $tableTotal = myTable.totalRow ? $table.next().children('.layui-table-total').children(":first") : null, + finalExcel = Object.assign({}, myTable.excel, curExcel); + + var filename = finalExcel.filename ? (typeof finalExcel.filename === 'function' ? finalExcel.filename.call(this) : finalExcel.filename) : '表格数据.xlsx', + checked = finalExcel.checked === true, + curPage = finalExcel.curPage === true, + customColumns = finalExcel.columns, + totalRow = finalExcel.totalRow, + type = filename.substring(filename.lastIndexOf('.') + 1, filename.length), + tableStartIndex = finalExcel.add && finalExcel.add.top && Array.isArray(finalExcel.add.top.data) ? finalExcel.add.top.data.length + 1 : 1, //表格内容从哪一行开始 + bottomLength = finalExcel.add && finalExcel.add.bottom && Array.isArray(finalExcel.add.bottom.data) ? finalExcel.add.bottom.data.length : 0,// 底部自定义行数 + i, j, k; + + if (finalExcel.data){ + if(Array.isArray(finalExcel.data)) { + data = finalExcel.data + } else { + console.error('导出指定数据 data 不符合数组格式', finalExcel.data) + layer.close(loading) + return; + } + } else if (checked) { // 获取选中行数据 + // data = table.checkStatus(myTable.id).data; + data = [] + if (cache[myTable.id] && cache[myTable.id].length > 0) { + for (i = 0; i < cache[myTable.id].length; i++) { + if (cache[myTable.id][i][table.config.checkName]) { + data.push(cache[myTable.id][i]) + } + } + } + } else if (curPage) { + data = layui.table.cache[myTable.id] + } else if (myTable.url && myTable.page) { + var ajaxStatus = true; + var searchParam = isFilterCache[myTable.id] ? where_cache[myTable.id] : table_cache[myTable.id].where; + if (myTable.contentType && myTable.contentType.indexOf("application/json") == 0) { //提交 json 格式 + searchParam = JSON.stringify(searchParam); + } + $.ajax({ + url: myTable.url, + data: searchParam, + dataType: 'json', + method: myTable.method || 'post', + async: false, + cache: false, + headers: myTable.headers || {}, + contentType: myTable.contentType, + success: function (res) { + if (typeof myTable.parseData === 'function') { + res = myTable.parseData(res) || res; + } + //检查数据格式是否符合规范 + if (res[myTable.response.statusName] != myTable.response.statusCode) { + layer.msg('返回的数据不符合规范,正确的成功状态码应为:"' + myTable.response.statusName + '": ' + myTable.response.statusCode, { + icon: 2, + anim: 6 + }); + } else { + data = res[myTable.response.dataName] + } + }, + error: function (res) { + layer.msg('请求异常!', {icon: 2, anim: 6}); + ajaxStatus = false; + } + }) + if (!ajaxStatus) { + return; + } + } else { + var $sortDoom = $table.next().children('.layui-table-box').children('.layui-table-header').find('.layui-table-sort[lay-sort$="sc"]:eq(0)') + if ($sortDoom.length > 0) { + var sortField = $sortDoom.parent().parent().data('field'); + var sortOrder = $sortDoom.attr('lay-sort'); + switch (sortOrder) { + case 'asc': + data = layui.sort(data, sortField); + break; + case 'desc': + data = layui.sort(data, sortField, true); + break; + default: + break; + } + } + } + + // 制定显示列和顺序 + var tempArray, cloneCol, columnsMap = [], curRowUnShowCount; + for (i = 0; i < cols.length; i++) { + curRowUnShowCount = 0; + for (j = 0; j < cols[i].length; j++) { + if (!cols[i][j].exportHandled) { + if (cols[i][j].rowspan > 1) { + if ((cols[i][j].field || cols[i][j].type === 'numbers') && !cols[i][j].hide) { + mergeArrays.push([numberToLetter(j + 1 - curRowUnShowCount) + (i + tableStartIndex), numberToLetter(j + 1 - curRowUnShowCount) + (i + parseInt(cols[i][j].rowspan) + tableStartIndex - 1)]) + } else { + curRowUnShowCount++; + } + cloneCol = this.deepClone(cols[i][j]) + cloneCol.exportHandled = true; + k = i + 1; + while (k < cols.length) { + cols[k].splice(j, 0, cloneCol) + k++ + } + } + if (cols[i][j].colspan > 1) { + mergeArrays.push([numberToLetter(j + 1 - curRowUnShowCount) + (i + tableStartIndex), numberToLetter(j + parseInt(cols[i][j].colspan) - curRowUnShowCount) + (i + tableStartIndex)]) + cloneCol = this.deepClone(cols[i][j]) + cloneCol.exportHandled = true; + for (k = 1; k < cols[i][j].colspan; k++) { + cols[i].splice(j, 0, cloneCol) + } + j = j + parseInt(cols[i][j].colspan) - 1 + + } + } else if (!((cols[i][j].field || cols[i][j].type === 'numbers') && !cols[i][j].hide)) { + curRowUnShowCount++; + } + } + } + var columns = cols[cols.length - 1]; // 获取真实列 + + // 处理数据 + for (i = 0; i < data.length; i++) { + for (j = 0; j < columns.length; j++) { + if ((columns[j].field || columns[j].type === 'numbers') && (customColumns && Array.isArray(customColumns) || !columns[j].hide)) { + data[i][columns[j].key] = data[i][columns[j].field || columns[j]['LAY_INDEX']] + } + } + } + + // 处理合计行 + if (totalRow !== false && myTable.totalRow) { + var obj = {}, totalRows = {}; + if (typeof totalRow === 'object' && totalRow.type === 'origin') { + // 通过 dom 解析 + for (i = 0; i < columns.length; i++) { + if (columns[i].field) { + obj[columns[i].key] = $tableTotal.find('[data-field="'+columns[i].field+'"]').text().trim() + } + } + data.push(obj); + } else { + // 通过数据解析 + for (i = 0; i < columns.length; i++) { + if (columns[i].totalRowText) { + obj[columns[i].key] = columns[i].totalRowText + } else if (columns[i].totalRow) { + totalRows[columns[i].key] = 0 + } + } + if (JSON.stringify(totalRows) !== '{}') { + for (i = 0; i < data.length; i++) { + for (var key in totalRows) { + totalRows[key] = (parseFloat(totalRows[key]) + (parseFloat(data[i][key]) || 0)).toFixed(2) + } + } + } + data.push(Object.assign(obj, totalRows)); + } + } + + if (customColumns && Array.isArray(customColumns)) { + // 自定义表头 + var tempCustomColumns = []; + tempArray = {}; + mergeArrays = []; // 重置表头合并列 + columnsMap[0] = {}; + for (i = 0; i < customColumns.length; i++) { + for (j = 0; j < columns.length; j++) { + if (columns[j].field === customColumns[i]) { + columns[j].hide = false + tempCustomColumns.push(columns[j]); + columnsMap[0][columns[j].key] = columns[j]; + tempArray[columns[j].key] = $('
                '+columns[j].title+'
                ').text() + break; + } + } + } + columns = tempCustomColumns; + data.splice(0, 0, tempArray) + } else { + // 拼接表头数据 + for (i = 0; i < cols.length; i++) { + columnsMap[i] = {} + tempArray = {} + for (j = 0; j < cols[i].length; j++) { + columnsMap[i][cols[cols.length - 1][j].key] = cols[i][j]; + tempArray[cols[cols.length - 1][j].key] = $('
                '+cols[i][j].title+'
                ').text() + } + data.splice(i, 0, tempArray) + } + } + + //添加自定义内容 + if (finalExcel.add) { + var addTop = finalExcel.add.top, + addBottom = finalExcel.add.bottom, + startPos, endPos, jumpColsNum; + + if (addTop && Array.isArray(addTop.data) && addTop.data.length > 0) { + + for (i = 0; i < addTop.data.length; i++) { + tempArray = {}, jumpColsNum = 0; + for (j = 0; j < (addTop.data[i].length > columns.length ? addTop.data[i].length : columns.length); j++) { + if ((columns[j].field || columns[j].type === 'numbers') && !columns[j].hide) { + tempArray[columns[j] ? columns[j].key : j + ''] = addTop.data[i][j - jumpColsNum] || '' + } else { + jumpColsNum++ + } + } + data.splice(i, 0, tempArray); + } + + if (Array.isArray(addTop.heights) && addTop.heights.length > 0) { + for (i = 0; i < addTop.heights.length; i++) { + heightConfig[i] = addTop.heights[i] + } + } + + if (Array.isArray(addTop.merge) && addTop.merge.length > 0) { + for (i = 0; i < addTop.merge.length; i++) { + if (addTop.merge[i].length === 2) { + startPos = addTop.merge[i][0].split(','); + endPos = addTop.merge[i][1].split(','); + mergeArrays.push([numberToLetter(startPos[1]) + startPos[0], numberToLetter(endPos[1]) + endPos[0]]) + } + + } + } + } + if (addBottom && Array.isArray(addBottom.data) && addBottom.data.length > 0) { + for (i = 0; i < addBottom.data.length; i++) { + tempArray = {}, jumpColsNum = 0; + for (j = 0; j < (addBottom.data[i].length > columns.length ? addBottom.data[i].length : columns.length); j++) { + if ((columns[j].field || columns[j].type === 'numbers') && !columns[j].hide) { + tempArray[columns[j] ? columns[j].key : j + ''] = addBottom.data[i][j - jumpColsNum] || '' + } else { + jumpColsNum++ + } + } + data.push(tempArray); + } + + if (Array.isArray(addBottom.heights) && addBottom.heights.length > 0) { + for (i = 0; i < addBottom.heights.length; i++) { + heightConfig[data.length - addBottom.data.length + i] = addBottom.heights[i] + } + } + + if (Array.isArray(addBottom.merge) && addBottom.merge.length > 0) { + for (i = 0; i < addBottom.merge.length; i++) { + if (addBottom.merge[i].length === 2) { + startPos = addBottom.merge[i][0].split(','); + endPos = addBottom.merge[i][1].split(','); + mergeArrays.push([numberToLetter(startPos[1]) + (data.length - addBottom.data.length + parseInt(startPos[0])), numberToLetter(endPos[1]) + (data.length - addBottom.data.length + parseInt(endPos[0]))]) + } + } + } + } + } + + var index = 0, alignTrans = {'left': 'left', 'center': 'center', 'right': 'right'}, + borderTypes = ['top', 'bottom', 'left', 'right']; + for (i = 0; i < columns.length; i++) { + if ((columns[i].field || columns[i].type === 'numbers') && !columns[i].hide) { + if (columns[i].width) { + widths[String.fromCharCode(64 + parseInt(++index))] = columns[i].width + } + showField[columns[i].key] = function (field, line, data, curIndex) { + var bgColor = 'ffffff', color = '000000', family = 'Calibri', size = 12, cellType = 's', + bodyIndex = curIndex - (customColumns ? 1 : cols.length) - tableStartIndex + 1, + border = { + top: { + style: 'thin', + color: {indexed: 64} + }, + bottom: { + style: 'thin', + color: {indexed: 64} + }, + left: { + style: 'thin', + color: {indexed: 64} + }, + right: { + style: 'thin', + color: {indexed: 64} + } + } + if (finalExcel.border) { + for (j = 0; j < borderTypes.length; j++) { + if (finalExcel.border[borderTypes[j]]) { + border[borderTypes[j]].style = finalExcel.border[borderTypes[j]].style || border[borderTypes[j]].style + border[borderTypes[j]].color = handleRgb(finalExcel.border[borderTypes[j]].color) || border[borderTypes[j]].color + } else if (finalExcel.border['color'] || finalExcel.border['style']) { + border[borderTypes[j]].style = finalExcel.border['style'] || border[borderTypes[j]].style + border[borderTypes[j]].color = handleRgb(finalExcel.border['color']) || border[borderTypes[j]].color + } + } + } + if (curIndex < tableStartIndex - 1 || curIndex >= data.length - bottomLength) { + return { + v: line[field] || '', + s: {// s 代表样式 + alignment: { + horizontal: 'center', + vertical: 'center' + }, + font: {name: family, sz: size, color: {rgb: color}}, + fill: { + fgColor: {rgb: bgColor, bgColor: {indexed: 64}} + }, + border: border + }, + t: cellType + } + } else if (bodyIndex < 0) { + // 头部样式 + bgColor = 'C7C7C7'; + if (finalExcel.head) { + bgColor = finalExcel.head.bgColor || bgColor; + color = finalExcel.head.color || color; + family = finalExcel.head.family || family; + size = finalExcel.head.size || size; + } + } else { + // 默认全局字体样式 + if (finalExcel.font) { + bgColor = finalExcel.font.bgColor || bgColor; + color = finalExcel.font.color || color; + family = finalExcel.font.family || family; + size = finalExcel.font.size || size; + } + // 默认全局边框样式 + if (finalExcel.border) { + for (j = 0; j < borderTypes.length; j++) { + if (finalExcel.border[borderTypes[j]]) { + border[borderTypes[j]].style = finalExcel.border[borderTypes[j]].style || border[borderTypes[j]].style + border[borderTypes[j]].color = handleRgb(finalExcel.border[borderTypes[j]].color) || border[borderTypes[j]].color + } else if (finalExcel.border['color'] || finalExcel.border['style']) { + border[borderTypes[j]].style = finalExcel.border['style'] || border[borderTypes[j]].style + border[borderTypes[j]].color = handleRgb(finalExcel.border['color']) || border[borderTypes[j]].color + } + } + } + // 列上配置了自定义样式 + if (columnsMap[columnsMap.length - 1][field].excel) { + var colExcel = typeof columnsMap[columnsMap.length - 1][field].excel === 'function' ? columnsMap[columnsMap.length - 1][field].excel.call(this, line, bodyIndex, data.length - cols.length - tableStartIndex + 1 - bottomLength) : columnsMap[columnsMap.length - 1][field].excel + if (colExcel) { + bgColor = colExcel.bgColor || bgColor; + color = colExcel.color || color; + family = colExcel.family || family; + size = colExcel.size || size; + cellType = colExcel.cellType || cellType; + + if (colExcel.border) { + for (j = 0; j < borderTypes.length; j++) { + if (colExcel.border[borderTypes[j]]) { + border[borderTypes[j]].style = colExcel.border[borderTypes[j]].style || border[borderTypes[j]].style + border[borderTypes[j]].color = handleRgb(colExcel.border[borderTypes[j]].color) || border[borderTypes[j]].color + } else if (colExcel.border['color'] || colExcel.border['style']) { + border[borderTypes[j]].style = colExcel.border['style'] || border[borderTypes[j]].style + border[borderTypes[j]].color = handleRgb(colExcel.border['color']) || border[borderTypes[j]].color + } + } + } + } + } + } + + function handleNull(val) { + if (typeof val === 'undefined' || val === null) { + return "" + } + return val; + } + + var value = bodyIndex >= 0 && columnsMap[columnsMap.length - 1][field].templet ? + typeof columnsMap[columnsMap.length - 1][field].templet === 'function' ? + $('
                ' + columnsMap[columnsMap.length - 1][field].templet(line) + '
                ').find(':input').length === 0 ? $('
                ' + columnsMap[columnsMap.length - 1][field].templet(line) + '
                ').text() : $tableBody.children('tbody').children('tr[data-index=' + bodyIndex + ']').children('td[data-key="' + field + '"]').find(':input').val() || handleNull(line[field]) + : $('
                ' + laytpl($(columnsMap[columnsMap.length - 1][field].templet).html() || String(columnsMap[columnsMap.length - 1][field].templet)).render(line) + '
                ').find(':input').length === 0 ? $('
                ' + laytpl($(columnsMap[columnsMap.length - 1][field].templet).html() || String(columnsMap[columnsMap.length - 1][field].templet)).render(line) + '
                ').text() : $tableBody.children('tbody').children('tr[data-index=' + bodyIndex + ']').children('td[data-key="' + field + '"]').find(':input').val() || handleNull(line[field]) + : bodyIndex >= 0 && columnsMap[columnsMap.length - 1][field].type === 'numbers' ? bodyIndex + 1 : handleNull(line[field]); + return { + v: value,// v 代表单元格的值 + s: {// s 代表样式 + alignment: { + horizontal: columnsMap[bodyIndex < -1 ? curIndex - tableStartIndex + 1 : columnsMap.length - 1][field].align ? alignTrans[columnsMap[bodyIndex < -1 ? curIndex - tableStartIndex + 1 : columnsMap.length - 1][field].align] : 'top', + vertical: 'center' + }, + font: {name: family, sz: size, color: {rgb: color}}, + fill: { + fgColor: {rgb: bgColor, bgColor: {indexed: 64}} + }, + border: border + }, + t: UNHANDLED_VALUES.indexOf(value) === -1 ? cellType : 's' + }; + } + } + } + + excel.exportExcel({ + sheet1: excel.filterExportData(data, showField) + }, filename, type, { + extend: { + '!cols': excel.makeColConfig(widths, 80), + '!merges': excel.makeMergeConfig(mergeArrays), + '!rows': excel.makeRowConfig(heightConfig, 16) + } + }); + layer.close(loading); + + // 合成 excel.js 识别的 rgb + function handleRgb(rgb) { + return rgb ? {rgb: rgb} : rgb + } + + function numberToLetter(num) { + var result = []; + while (num) { + var t = num % 26; + if (!t) { + t = 26; + --num; + } + // Polyfill 兼容旧浏览器 + if (!String.fromCodePoint) (function (stringFromCharCode) { + var fromCodePoint = function (_) { + var codeUnits = [], codeLen = 0, result = ""; + for (var index = 0, len = arguments.length; index !== len; ++index) { + var codePoint = +arguments[index]; + // correctly handles all cases including `NaN`, `-Infinity`, `+Infinity` + // The surrounding `!(...)` is required to correctly handle `NaN` cases + // The (codePoint>>>0) === codePoint clause handles decimals and negatives + if (!(codePoint < 0x10FFFF && (codePoint >>> 0) === codePoint)) + throw RangeError("Invalid code point: " + codePoint); + if (codePoint <= 0xFFFF) { // BMP code point + codeLen = codeUnits.push(codePoint); + } else { // Astral code point; split in surrogate halves + // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + codePoint -= 0x10000; + codeLen = codeUnits.push( + (codePoint >> 10) + 0xD800, // highSurrogate + (codePoint % 0x400) + 0xDC00 // lowSurrogate + ); + } + if (codeLen >= 0x3fff) { + result += stringFromCharCode.apply(null, codeUnits); + codeUnits.length = 0; + } + } + return result + stringFromCharCode.apply(null, codeUnits); + }; + try { // IE 8 only supports `Object.defineProperty` on DOM elements + Object.defineProperty(String, "fromCodePoint", { + "value": fromCodePoint, "configurable": true, "writable": true + }); + } catch (e) { + String.fromCodePoint = fromCodePoint; + } + }(String.fromCharCode)); + result.push(String.fromCodePoint(t + 64)); + if (!String.fromCodePoint) (function (stringFromCharCode) { + var fromCodePoint = function (_) { + var codeUnits = [], codeLen = 0, result = ""; + for (var index = 0, len = arguments.length; index !== len; ++index) { + var codePoint = +arguments[index]; + // correctly handles all cases including `NaN`, `-Infinity`, `+Infinity` + // The surrounding `!(...)` is required to correctly handle `NaN` cases + // The (codePoint>>>0) === codePoint clause handles decimals and negatives + if (!(codePoint < 0x10FFFF && (codePoint >>> 0) === codePoint)) + throw RangeError("Invalid code point: " + codePoint); + if (codePoint <= 0xFFFF) { // BMP code point + codeLen = codeUnits.push(codePoint); + } else { // Astral code point; split in surrogate halves + // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + codePoint -= 0x10000; + codeLen = codeUnits.push( + (codePoint >> 10) + 0xD800, // highSurrogate + (codePoint % 0x400) + 0xDC00 // lowSurrogate + ); + } + if (codeLen >= 0x3fff) { + result += stringFromCharCode.apply(null, codeUnits); + codeUnits.length = 0; + } + } + return result + stringFromCharCode.apply(null, codeUnits); + }; + try { // IE 8 only supports `Object.defineProperty` on DOM elements + Object.defineProperty(String, "fromCodePoint", { + "value": fromCodePoint, "configurable": true, "writable": true + }); + } catch (e) { + String.fromCodePoint = fromCodePoint; + } + }(String.fromCharCode)); + num = ~~(num / 26); + } + return result.reverse().join(''); + } + }, + startsWith: function (content, str) { + var reg = new RegExp("^" + str); + return content && reg.test(content); + }, + // 深度克隆-不丢失方法 + deepClone: function (obj) { + var newObj = Array.isArray(obj) ? [] : {} + if (obj && typeof obj === "object") { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + newObj[key] = (obj && typeof obj[key] === 'object') ? this.deepClone(obj[key]) : obj[key]; + } + } + } + return newObj + }, + deepStringify: function (obj) { + var JSON_SERIALIZE_FIX = { + PREFIX: "[[JSON_FUN_PREFIX_", + SUFFIX: "_JSON_FUN_SUFFIX]]" + }; + return JSON.stringify(obj, function (key, value) { + if (typeof value === 'function') { + return JSON_SERIALIZE_FIX.PREFIX + value.toString() + JSON_SERIALIZE_FIX.SUFFIX; + } + return value; + }); + }, + /* layui table 中原生的方法 */ + getScrollWidth: function (elem) { + var width = 0; + if (elem) { + width = elem.offsetWidth - elem.clientWidth; + } else { + elem = document.createElement('div'); + elem.style.width = '100px'; + elem.style.height = '100px'; + elem.style.overflowY = 'scroll'; + + document.body.appendChild(elem); + width = elem.offsetWidth - elem.clientWidth; + document.body.removeChild(elem); + } + return width; + } + , getCompleteCols: function (origin) { + var cols = this.deepClone(origin); + var i, j, k, cloneCol; + for (i = 0; i < cols.length; i++) { + for (j = 0; j < cols[i].length; j++) { + if (!cols[i][j].exportHandled) { + if (cols[i][j].rowspan > 1) { + cloneCol = this.deepClone(cols[i][j]) + cloneCol.exportHandled = true; + k = i + 1; + while (k < cols.length) { + cols[k].splice(j, 0, cloneCol) + k++ + } + } + if (cols[i][j].colspan > 1) { + cloneCol = this.deepClone(cols[i][j]) + cloneCol.exportHandled = true; + for (k = 1; k < cols[i][j].colspan; k++) { + cols[i].splice(j, 0, cloneCol) + } + j = j + parseInt(cols[i][j].colspan) - 1 + } + } + } + } + return cols[cols.length - 1]; + } + , parseTempData: function (item3, content, tplData, text) { //表头数据、原始内容、表体数据、是否只返回文本 + var str = item3.templet ? function () { + return typeof item3.templet === 'function' + ? item3.templet(tplData) + : laytpl($(item3.templet).html() || String(content)).render(tplData) + }() : content; + return text ? $('
                ' + str + '
                ').text() : str; + } + , cache: cache + }; + + // 输出 + exports('tableFilter', mod); +}); diff --git a/WaterCloud.Web/wwwroot/js/lay-module/soulTable/tableMerge.js b/WaterCloud.Web/wwwroot/js/lay-module/soulTable/tableMerge.js new file mode 100644 index 0000000..fa98da3 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/soulTable/tableMerge.js @@ -0,0 +1,103 @@ +/** + * + * @name: 子表格扩展 + * @author: yelog + * @link: https://github.com/yelog/layui-soul-table + * @license: MIT + * @version: v1.9.0 + */ +layui.define(['table'], function (exports) { + + var $ = layui.jquery; + + // 封装方法 + var mod = { + /** + * 渲染入口 + * @param myTable + */ + render: function (myTable) { + var tableBox = $(myTable.elem).next().children('.layui-table-box'), + $main = $(tableBox.children('.layui-table-body').children('table').children('tbody').children('tr').toArray().reverse()), + $fixLeft = $(tableBox.children('.layui-table-fixed-l').children('.layui-table-body').children('table').children('tbody').children('tr').toArray().reverse()), + $fixRight = $(tableBox.children('.layui-table-fixed-r').children('.layui-table-body').children('table').children('tbody').children('tr').toArray().reverse()), + mergeRecord = {}; + + layui.each(myTable.cols, function (i1, item1) { + layui.each(item1, function (i2, item2) { + if (item2.merge && item2.field) { + var mergeField = [item2.field]; + if (item2.merge !== true) { + if (typeof item2.merge === 'string') { + mergeField = [item2.merge] + } else { + mergeField = item2.merge + } + } + mergeRecord[myTable.index + '-' + i1 + '-' + i2] = {mergeField: mergeField, rowspan: 1} + } + }) + }) + + $main.each(function (i) { + + for (var item in mergeRecord) { + if (i === $main.length - 1 || isMaster(i, item)) { + var tdHeight = $(this).children('[data-key="' + item + '"]').outerHeight(), patchHeight = 0; // 获取td高度 + if ($main.eq(i).data('index') === 0) { + patchHeight = 1 + } + $(this).children('[data-key="' + item + '"]').attr('rowspan', mergeRecord[item].rowspan).css({ + 'position': 'static', + 'height': tdHeight * mergeRecord[item].rowspan + patchHeight + }).children().css({ + height: 'auto', + 'white-space': 'normal', + 'max-height': tdHeight * mergeRecord[item].rowspan + patchHeight - 10 + }); + $fixLeft.eq(i).children('[data-key="' + item + '"]').attr('rowspan', mergeRecord[item].rowspan).css({ + 'position': 'static', + 'height': tdHeight * mergeRecord[item].rowspan + patchHeight + }).children().css({ + height: 'auto', + 'white-space': 'normal', + 'max-height': tdHeight * mergeRecord[item].rowspan + patchHeight - 10 + }); + $fixRight.eq(i).children('[data-key="' + item + '"]').attr('rowspan', mergeRecord[item].rowspan).css({ + 'position': 'static', + 'height': tdHeight * mergeRecord[item].rowspan + patchHeight + }).children().css({ + height: 'auto', + 'white-space': 'normal', + 'max-height': tdHeight * mergeRecord[item].rowspan + patchHeight - 10 + }); + mergeRecord[item].rowspan = 1; + } else { + $(this).children('[data-key="' + item + '"]').remove(); + $fixLeft.eq(i).children('[data-key="' + item + '"]').remove(); + $fixRight.eq(i).children('[data-key="' + item + '"]').remove(); + mergeRecord[item].rowspan += 1; + } + } + }) + + function isMaster(index, item) { + var mergeField = mergeRecord[item].mergeField; + var dataLength = layui.table.cache[myTable.id].length; + for (var i = 0; i < mergeField.length; i++) { + + if (layui.table.cache[myTable.id][dataLength - 2 - index][mergeField[i]] + !== layui.table.cache[myTable.id][dataLength - 1 - index][mergeField[i]]) { + return true; + } + } + return false; + } + + } + }; + + // 输出 + exports('tableMerge', mod); +}); + diff --git a/WaterCloud.Web/wwwroot/js/lay-module/step-lay/step.css b/WaterCloud.Web/wwwroot/js/lay-module/step-lay/step.css new file mode 100644 index 0000000..cceb5c6 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/step-lay/step.css @@ -0,0 +1,79 @@ +.lay-step { + font-size: 0; + width: 400px; + margin: 0 auto; + max-width: 100%; + padding-left: 30%; +} + +.step-item { + display: inline-block; + line-height: 26px; + position: relative; + font-size: 14px; +} + +.step-item-tail { + width: 100%; + padding: 0 10px; + position: absolute; + left: 0; + top: 13px; +} + +.step-item-tail i { + display: inline-block; + width: 100%; + height: 1px; + vertical-align: top; + background: #c2c2c2; + position: relative; +} + +.step-item-tail .step-item-tail-done { + background: #009688; +} + +.step-item-head { + position: relative; + display: inline-block; + height: 26px; + width: 26px; + text-align: center; + vertical-align: top; + color: #009688; + border: 1px solid #009688; + border-radius: 50%; + background: #ffffff; +} + +.step-item-head.step-item-head-active { + background: #009688; + color: #ffffff; +} + +.step-item-main { + display: block; + position: relative; + margin-left: -50%; + margin-right: 50%; + padding-left: 26px; + text-align: center; +} + +.step-item-main-title { + font-weight: bolder; + color: #555555; +} + +.step-item-main-desc { + color: #aaaaaa; +} + +.lay-step + [carousel-item]:before { + display: none; +} + +.lay-step + [carousel-item] > * { + background-color: transparent; +} \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/step-lay/step.js b/WaterCloud.Web/wwwroot/js/lay-module/step-lay/step.js new file mode 100644 index 0000000..baa015b --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/step-lay/step.js @@ -0,0 +1,101 @@ +layui.define(['layer', 'carousel'], function (exports) { + var $ = layui.jquery; + var layer = layui.layer; + var carousel = layui.carousel; + + // 添加步骤条dom节点 + var renderDom = function (elem, stepItems, postion) { + var stepDiv = '
                '; + for (var i = 0; i < stepItems.length; i++) { + stepDiv += '
                '; + // 线 + if (i < (stepItems.length - 1)) { + if (i < postion) { + stepDiv += '
                '; + } else { + stepDiv += '
                '; + } + } + + // 数字 + var number = stepItems[i].number; + if (!number) { + number = i + 1; + } + if (i == postion) { + stepDiv += '
                ' + number + '
                '; + } else if (i < postion) { + stepDiv += '
                '; + } else { + stepDiv += '
                ' + number + '
                '; + } + + // 标题和描述 + var title = stepItems[i].title; + var desc = stepItems[i].desc; + if (title || desc) { + stepDiv += '
                '; + if (title) { + stepDiv += '
                ' + title + '
                '; + } + if (desc) { + stepDiv += '
                ' + desc + '
                '; + } + stepDiv += '
                '; + } + stepDiv += '
                '; + } + stepDiv += '
                '; + + $(elem).prepend(stepDiv); + + // 计算每一个条目的宽度 + var bfb = 100 / stepItems.length; + $('.step-item').css('width', bfb + '%'); + }; + + var step = { + // 渲染步骤条 + render: function (param) { + param.indicator = 'none'; // 不显示指示器 + param.arrow = 'always'; // 始终显示箭头 + param.autoplay = false; // 关闭自动播放 + if (!param.stepWidth) { + param.stepWidth = '400px'; + } + + // 渲染轮播图 + carousel.render(param); + + // 渲染步骤条 + var stepItems = param.stepItems; + renderDom(param.elem, stepItems, 0); + $('.lay-step').css('width', param.stepWidth); + + //监听轮播切换事件 + carousel.on('change(' + param.filter + ')', function (obj) { + $(param.elem).find('.lay-step').remove(); + renderDom(param.elem, stepItems, obj.index); + $('.lay-step').css('width', param.stepWidth); + }); + + // 隐藏左右箭头按钮 + $(param.elem).find('.layui-carousel-arrow').css('display', 'none'); + + // 去掉轮播图的背景颜色 + $(param.elem).css('background-color', 'transparent'); + }, + // 下一步 + next: function (elem) { + $(elem).find('.layui-carousel-arrow[lay-type=add]').trigger('click'); + }, + // 上一步 + pre: function (elem) { + $(elem).find('.layui-carousel-arrow[lay-type=sub]').trigger('click'); + } + }; + + layui.link(layui.cache.base + 'step-lay/step.css'); + + exports('step', step); +}); diff --git a/WaterCloud.Web/wwwroot/js/lay-module/tableSelect/tableEdit.js b/WaterCloud.Web/wwwroot/js/lay-module/tableSelect/tableEdit.js new file mode 100644 index 0000000..958436f --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/tableSelect/tableEdit.js @@ -0,0 +1,472 @@ +layui.define(["laydate","laytpl","table","layer"],function(exports) { + "use strict"; + var moduleName = 'tableEdit',_layui = layui,laytpl = _layui.laytpl + , $ = _layui.$, + laydate = _layui.laydate, + table = _layui.table, + layer = _layui.layer + ,selectTpl = [ //单选下拉框模板 + '
                ' + ,'
                  ' + ,'{{# d.data = typeof(d.data) === "function"? d.data(d):d.data; if(d.data){ }}' + ,'{{# d.data.forEach(function(item){ }}' + ,'{{# var selectedClass = d.callbackFn(item) }}' + ,'
                • ' + ,'
                  {{ item.name }}
                  ' + ,'
                • ' + ,'{{# }); }}' + ,'{{# } else { }}' + ,'
                • 无数据
                • ' + ,'{{# } }}' + ,'
                ' + , '
                ' + ].join('') + ,selectMoreTpl = [ //多选下拉框模板 + '
                ' + ,'
                ' + ,'
                  ' + ,'{{# if(d.data){ }}' + ,'{{# d.data.forEach(function(item){ }}' + ,'{{# var selectedClass = d.callbackFn(item) }}' + ,'
                • ' + ,'
                  {{ item.name }}
                  ' + ,'
                • ' + ,'{{# }); }}' + ,'{{# } else { }}' + ,'
                • 无数据
                • ' + ,'{{# } }}' + ,'
                ' + ,'
                ' + ,'
                ' + ,'
                ' + ,'' + ,'
                ' + ,'
                ' + ,'' + ,'
                ' + ,'
                ' + ,'
                ' + ].join(''); + //组件用到的css样式 + var thisCss = []; + thisCss.push('.layui-tableEdit-div{position:absolute;background-color:#fff;font-size:14px;border:1px solid #d2d2d2;z-index:19910908445;max-height: 252px;}'); + thisCss.push('.layui-tableEdit-tpl{max-height:216px;overflow-y:auto;}'); + thisCss.push('.layui-tableEdit-div li{line-height:36px;padding-left:5px;}'); + thisCss.push('.layui-tableEdit-div li:hover{background-color:#f2f2f2;}'); + thisCss.push('.layui-tableEdit-selected{background-color:#5FB878;}'); + thisCss.push('.layui-tableEdit-checked i{background-color:#60b979!important;}'); + thisCss.push('.layui-tableEdit-ul div{padding-left:0px!important;}'); + thisCss.push('.layui-tableEdit-input{text-align:center;position:absolute;left:0;bottom:0;width:100%;height:38px;z-index: 19910908;}'); + thisCss.push('.layui-tableEdit-add{position: absolute;right: 3px;top: 21px;margin-top: -15px;z-index: 199109084;}') + thisCss.push('.layui-tableEdit-sub{position: absolute;left: 3px;top: 21px;margin-top: -15px;z-index: 199109084;}') + var thisStyle = document.createElement('style'); + thisStyle.innerHTML = thisCss.join('\n'),document.getElementsByTagName('head')[0].appendChild(thisStyle); + + var configs = { + callbacks:{} + , + verify: { + required: [ + /[\S]+/ + ,'必填项不能为空' + ] + ,phone: [ + /^1[34578]\d{9}$/ + ,'请输入正确的手机号' + ] + ,email: [ + /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/ + ,'邮箱格式不正确' + ] + ,url: [ + /(^#)|(^http(s*):\/\/[^\s]+\.[^\s]+)/ + ,'链接格式不正确' + ] + ,number:[ + /(^[-+]?\d+$)|(^[-+]?\d+\.\d+$)/ + ,'只能填写数字' + ] + ,date: [ + /^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/ + ,'日期格式不正确' + ] + ,identity: [ + /(^\d{15}$)|(^\d{17}(x|X|\d)$)/ + ,'请输入正确的身份证号' + ] + } + }; + + var Class = function () { //单列模式 也就是只能new一个对象。 + var instance; + Class = function Class() { + return instance; + }; + Class.prototype = this; //保留原型属性 + instance = new Class(); + instance.constructor = Class; //重置构造函数指针 + return instance + }; //构造器 + var singleInstance = new Class(); + var inFunc = function () {singleInstance.leaveStat = false;},outFunc = function () {singleInstance.leaveStat = true;}; + document.onclick = function () {if(singleInstance.leaveStat)singleInstance.deleteAll();}; + + //日期选择框 + Class.prototype.date = function (options) { + var othis = this; + othis.callback = options.callback,othis.element = options.element,othis.dateType = options.dateType; + othis.dateType = othis.isEmpty(othis.dateType) ? "datetime":othis.dateType; + var that = options.element; + if ($(that).find('input').length>0)return; + othis.deleteAll(),othis.leaveStat = false; + var input = $(''); + (39 - that.offsetHeight > 3) && input.css('height','30px'); + (that.offsetHeight - 39 > 3) && input.css('height','50px'); + $(that).append(input),input.focus(); + //日期时间选择器 (show: true 表示直接显示) + laydate.render({ + elem: input[0], value: options.element.innerText,type: othis.dateType,show: true,done:function (value, date) { + othis.deleteAll(); + if(othis.callback)othis.callback.call(that,value); + }}); + $('div.layui-laydate').hover(inFunc,outFunc),$(that).hover(inFunc,outFunc); + _layui.stope(); + }; + + //输入框 + Class.prototype.input = function (options) { + var othis = this; + othis.callback = options.callback,othis.element = options.element; + othis.oldValue = options.oldValue; + othis.oldValue = othis.oldValue ? othis.oldValue : ''; + var that = options.element; + if ($(that).find('input').length>0)return; + othis.deleteAll(),othis.leaveStat = false; + var input = $(''); + (39 - that.offsetHeight > 3) && input.css('height','30px'); + (that.offsetHeight - 39 > 3) && input.css('height','50px'); + input.val(othis.oldValue); + $(that).append(input),input.focus(); + input.click(function (e) { + _layui.stope(e); + }); + input.bind('change', function(e){othis.callback.call(othis.element,this.value)}); + $(that).hover(inFunc,outFunc); + _layui.stope(); + }; + + //带加号和减号的输入框(只支持输入数字) + Class.prototype.signedInput = function (options) { + var othis = this; + othis.callback = options.callback,othis.element = options.element; + othis.oldValue = options.oldValue; + othis.oldValue = othis.oldValue ? othis.oldValue : ''; + var that = options.element; + if ($(that).find('input').length>0)return; + othis.deleteAll(),othis.leaveStat = false; + var thisWidth = that.offsetWidth-49; + var input = $('');// + var leftBtn = $(''); + var rightBtn = $(''); + if(39 - that.offsetHeight > 3){ + input.css('height','30px');leftBtn.css('top','16px');rightBtn.css('top','16px'); + } + if(that.offsetHeight - 39 > 3){ + input.css('height','50px');leftBtn.css('top','25px');rightBtn.css('top','25px'); + } + input.val(othis.oldValue); + $(that).append(leftBtn);leftBtn.find('i').html(''); + $(that).append(input),input.focus();$(that).append(rightBtn);rightBtn.find('i').html(''); + input.click(function (e) { + _layui.stope(e); + }); + input.bind('change', function(e){othis.callback.call(othis.element,this.value)}); + $(that).hover(inFunc,outFunc); + _layui.stope(); + $(that).find('button.layui-tableEdit-sub,button.layui-tableEdit-add').bind('click',function () { + var input = $(that).find('input.layui-tableEdit-input'); + var val = input.val(); + if(!val || val.length<=0)val=0; + val = parseInt(val); + if($(this).hasClass('layui-tableEdit-add')){ + ++val;input.val(val); + othis.callback.call(othis.element,val) + }else{ + --val;input.val(val); + othis.callback.call(othis.element,val) + } + }) + }; + + //判断是否为空函数 + Class.prototype.isEmpty = function(dataStr){return typeof dataStr === 'undefined' || dataStr === null || dataStr.length <= 0;}; + + //生成下拉框函数入口 + Class.prototype.register = function(options){ + var othis = this; + othis.enabled = options.enabled,othis.callback = options.callback; + othis.data = options.data,othis.element = options.element; + othis.selectedData = options.selectedData; + var that = othis.element; + if($(that).find('input.layui-tableEdit-input')[0]) return; + othis.deleteAll(),othis.leaveStat = false; + var input = $('') + ,tableEdit = $('
                ') + ,tableBody = $(that).parents('div.layui-table-body') + ,tablePage = $(that).parents('div.layui-table-box').eq(0).next(); + (39 - that.offsetHeight > 3) && input.css('height','30px'); + (that.offsetHeight - 39 > 3) && input.css('height','50px'); + tableEdit.append(input),$(that).append(tableEdit),input.focus(); + var thisY = input[0].getBoundingClientRect().top //输入框y坐标 + ,thisHeight = ((39 - that.offsetHeight > 3) ? 30 : input[0].offsetHeight) //输入框高度 + ,thisHeight = ((that.offsetHeight - 39 > 3) ? 50 :thisHeight) + ,thisWidth = input[0].offsetWidth //输入框宽度 + ,elemY = that.getBoundingClientRect().top //输入框y坐标 + ,tableBodyY = tableBody[0].getBoundingClientRect().top + ,pageY = tablePage[0].getBoundingClientRect().top + ,tableBodyHeight = tableBody.height() //表格高度 + ,isType = thisY-tableBodyY > 0.8*tableBodyHeight + ,type = isType ? 'top: auto;bottom: '+(thisHeight+2)+'px;' : 'bottom: auto;top: '+(thisHeight+2)+'px;'; + if(elemY pageY) && !isType && (tableBody[0].scrollTop = that.offsetTop);//调整滚动条位置 + othis.events(); + }; + + //删除所有下拉框和时间选择框 + Class.prototype.deleteAll = function(){ + $('div.layui-tableEdit-div,div.layui-tableEdit,div.layui-laydate,input.layui-tableEdit-input,button.layui-tableEdit-sub,button.layui-tableEdit-add').remove(); + delete this.leaveStat;//清除(离开状态属性) + }; + + //注册事件 + Class.prototype.events = function(){ + var othis = this; + var searchFunc = function(val){ //关键字搜索 + $('div.layui-tableEdit-div li').each(function () { + othis.isEmpty(val) || $(this).data('value').toString().indexOf(val) > -1 ? $(this).show() : $(this).hide(); + }); + },liClickFunc = function(){ //给li元素注册点击事件 + var liArr = $('div.layui-tableEdit-div li'); + liArr.unbind('click'),liArr.bind('click',function (e) { + _layui.stope(e); + if(othis.enabled){//多选 + $(this).hasClass("layui-tableEdit-checked") ? ($(this).removeClass("layui-tableEdit-checked"), + $(this).removeClass("layui-tableEdit-selected")) + : $(this).addClass("layui-tableEdit-checked") + }else {//单选 + othis.deleteAll(); + if(othis.callback)othis.callback.call(othis.element,{name:$(this).data("name"),value:$(this).data("value")}); + } + }); + },btnClickFunc = function (){ //给button按钮注册点击事件 + $("div.layui-tableEdit-div button").bind('click',function () { + var eventType = $(this).attr("event-type"), btn = this,dataList = new Array(); + if(eventType === 'close') singleInstance.deleteAll(); //“关闭”按钮 + if(eventType === 'confirm') { //“确定”按钮 + $('div.layui-tableEdit-div li').each(function (e) { + if(!$(this).hasClass("layui-tableEdit-checked"))return; + dataList.push({name:$(this).data("name"),value:$(this).data("value")}); + }); + othis.deleteAll(); + if(othis.callback)othis.callback.call(othis.element,dataList); + } + }); + }; + //事件注册 + $(othis.element).find('input.layui-tableEdit-input').bind('input propertychange', function(){searchFunc(this.value)}); + othis.enabled ? (liClickFunc(),btnClickFunc()) : liClickFunc(); + $(othis.element).hover(inFunc,outFunc); + }; + + var AopEvent = function(cols){this.config = {colsConfig:{}};this.parseCols(cols)};//aop构造器 + /** + * 解析出tableEdit组件所需要的配置信息 + * @param cols + */ + AopEvent.prototype.parseCols = function(cols){ + var that = this; + cols.forEach(function (ite) { + ite.forEach(function (item) { + if(!item.config)return; + that.config.colsConfig[item.field] = item.config; + }); + }); + }; + /** + * aop代理event + * @param event 事件名称 + * @param callback 回调函数 + */ + AopEvent.prototype.on = function(event,callback){ + var othis = this;othis.config.event = event,othis.config.callback = callback; + table.on(othis.config.event,function (obj) { + var zthis = this,field = $(zthis).data('field'),config = othis.config.colsConfig[field]; + if(!config){ + othis.config.callback.call(zthis,obj);return; + } + obj.field = field; + var callbackFn = function (res) { + if(config.verify && !othis.verify(res,config.verify,this))return; //验证为空 + obj.value = Array.isArray(res) ? (res.length>0 ? res : [{name:'',value:''}]) : res; + othis.config.callback.call(zthis,obj); + if(!singleInstance.isEmpty(config.cascadeSelectField)){ + var csElement = $(this.parentNode).find("td[data-field='"+config.cascadeSelectField+"']"); + $(csElement).attr("cascadeSelect-data",JSON.stringify({data:res,field:field})); + } + }; + var csd = $(this).attr("cascadeSelect-data");//联动数据 + if(singleInstance.isEmpty(csd)){ //非联动事件 + if(config.type === 'select'){ + singleInstance.register({data:config.data,element:zthis,enabled:config.enabled,selectedData:obj.data[field],callback:callbackFn}); + }else if(config.type === 'date'){ + singleInstance.date({dateType:config.dateType,element:zthis,callback:callbackFn}); + }else if(config.type === 'input'){ + singleInstance.input({element:zthis,oldValue:obj.data[field],callback:callbackFn}); + }else if(config.type === 'signedInput'){ + singleInstance.signedInput({element:zthis,oldValue:obj.data[field],callback:callbackFn}); + }else othis.config.callback.call(zthis,obj); + } else {//联动事件 + if(config.type === 'date') return; + //获取当前单元格的table表格的lay-filter属性值 + var filter = $(zthis).parents('div.layui-table-view').eq(0).prev().attr('lay-filter') + ,rs = active.callbackFn.call(zthis,'clickBefore('+filter+')',JSON.parse(csd)); + //异步操作,由使用者调用。 + //判断条件为rs为空时。 + if(singleInstance.isEmpty(rs)){ + active.on("async("+filter+")",function (result) { + singleInstance.register({data:result.data,element:zthis,enabled:result.enabled,selectedData:obj.data[field],callback:callbackFn}); + }) + }else { + singleInstance.register({data:rs.data,element:zthis,enabled:rs.enabled,selectedData:obj.data[field],callback:callbackFn}); + } + } + + }); + }; + + /** + * 验证数据是否符合要求 + * @param data 被验证数据 + * @param verify 正则参数 + * @param td 当前单元格 + * @returns {boolean} true验证通过 false验证未通过 + */ + AopEvent.prototype.verify = function (data,verify,td) { + var verifyObj = configs.verify[verify.type]; + var verifyMsg = verify.msg; + verifyMsg = verifyMsg ? verifyMsg : (verifyObj ? verifyObj[1] : '必填项不能为空'); + if(singleInstance.isEmpty(data)){ + layer.tips(verifyMsg, td,{tipsMore:true}); + return false; + } + if (Array.isArray(data)) { + if (data.length <= 0) { + layer.tips(verifyMsg, td, { tipsMore: true }); + return false; + } + } + else if ((typeof data === 'object' && singleInstance.isEmpty(data.name)) + || data.name === 'undefined'){ + layer.tips(verifyMsg, td,{tipsMore:true}); + return false; + } + if(!verifyObj && !verify.regx){ + return true; + } + if(verify.regx){ //自定义正则判断 + if(typeof verify.regx === "function"){//为函数时 + if(verify.regx(data))return true; + layer.tips(verifyMsg, td,{tipsMore:true}); + return false; + } + if(typeof verify.regx === "string"){ //为字符串正则时 + var regx = new RegExp(verify.regx); + if(regx.test(data))return true; + layer.tips(verifyMsg, td,{tipsMore:true}); + return false; + } + if(verify.regx.test(data))return true; //为正则时 + layer.tips(verifyMsg, td,{tipsMore:true}); + return false; + } + if(!verifyObj[0].test(data)){ + layer.tips(verifyMsg, td,{tipsMore:true}); + return false; + } + return true; + }; + + /** + * 提交数据的验证 + * @param options {elem:'#test',data:[],verifyKey:'id'} + * elem: 表格id,带井号 data: 验证数据,数组类型。 + * verifyKey: data中的元素的唯一值字段,且必须在表格中有此字段的单元格。 + * @returns {*} + */ + AopEvent.prototype.submitValidate = function (options) { + var that = this,failedTds = []; + if(!options || singleInstance.isEmpty(options.verifyKey) + || singleInstance.isEmpty(options.data) + || singleInstance.isEmpty(options.elem))return failedTds; + var body = $(options.elem).next().find('div.layui-table-box div.layui-table-body tr'); + options.data.forEach(function (item) { + for(var field in item){ + var config = that.config.colsConfig[field]; + if(!config || !config.verify)continue; + var verify = config.verify; + var tds = body.find('td[data-field="'+options.verifyKey+'"]'); + var thisTd; + tds.each(function () { + var text = $(this).find('div.layui-table-cell').text(); + if(text+'' === item[options.verifyKey]+''){ + thisTd = $(this); + } + }); + if(!thisTd)continue; + var td = thisTd.parent().children('td[data-field="'+field+'"]'); + if(!that.verify(item[field],verify,td))failedTds.push(td[0]); + } + }); + return failedTds; + }; + + var active = { + aopObj:function(cols){return new AopEvent(cols);}, + on:function (event,callback) { + var filter = event.match(/\((.*)\)$/),eventName = (filter ? (event.replace(filter[0],'')+'_'+ filter[1]) : event); + configs.callbacks[moduleName+'_'+eventName]=callback; + }, + callbackFn:function (event,params) { + var filter = event.match(/\((.*)\)$/),eventName = (filter ? (event.replace(filter[0],'')+'_'+ filter[1]) : event); + var key = moduleName+'_'+eventName,func = configs.callbacks[key]; + if(!func) return; + return func.call(this,params); + } + }; + + active.on("tableEdit(getEntity)",function () { + return singleInstance; + }); + + exports(moduleName, active); +}); \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/tableSelect/tableSelect.js b/WaterCloud.Web/wwwroot/js/lay-module/tableSelect/tableSelect.js new file mode 100644 index 0000000..676092a --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/tableSelect/tableSelect.js @@ -0,0 +1,265 @@ +layui.define(['table', 'jquery', 'form'], function (exports) { + "use strict"; + + var MOD_NAME = 'tableSelect', + $ = layui.jquery, + table = layui.table, + form = layui.form; + var tableSelect = function () { + this.v = '1.1.0'; + }; + + /** + * 初始化表格选择器 + */ + tableSelect.prototype.render = function (opt) { + var elem = $(opt.elem); + var tableDone = opt.table.done || function () { }; + + //默认设置 + opt.searchKey = opt.searchKey || 'keyword'; + opt.searchPlaceholder = opt.searchPlaceholder || '关键词搜索'; + opt.checkedKey = opt.checkedKey; + opt.table.page = opt.table.page || false; + opt.table.height = opt.table.height || 315; + + elem.off('click').on('click', function (e) { + e.stopPropagation(); + + if ($('div.tableSelect').length >= 1) { + return false; + } + + var t = elem.offset().top + elem.outerHeight() + "px"; + var l = elem.offset().left + "px"; + var tableName = "tableSelect_table_" + new Date().getTime(); + var tableBox = '
                '; + tableBox += '
                '; + tableBox += '
                '; + tableBox += ''; + tableBox += '
                '; + tableBox += ''; + tableBox += ''; + tableBox += '
                '; + tableBox += '
                '; + tableBox += '
                '; + tableBox = $(tableBox); + $('body').append(tableBox); + + //数据缓存 + var checkedData = [], firstLoad = true;; + + //渲染TABLE + opt.table.elem = "#" + tableName; + opt.table.id = tableName; + opt.table.done = function (res, curr, count) { + defaultChecked(res, curr, count); + setChecked(res, curr, count); + tableDone(res, curr, count); + }; + var tableSelect_table = table.render(opt.table); + + //分页选中保存数组 + table.on('radio(' + tableName + ')', function (obj) { + if (opt.checkedKey) { + checkedData = table.checkStatus(tableName).data + } + updateButton(table.checkStatus(tableName).data.length) + }) + table.on('checkbox(' + tableName + ')', function (obj) { + if (opt.checkedKey) { + if (obj.checked) { + for (var i = 0; i < table.checkStatus(tableName).data.length; i++) { + checkedData.push(table.checkStatus(tableName).data[i]) + } + } else { + if (obj.type == 'all') { + for (var j = 0; j < table.cache[tableName].length; j++) { + for (var i = 0; i < checkedData.length; i++) { + if (checkedData[i][opt.checkedKey] == table.cache[tableName][j][opt.checkedKey]) { + checkedData.splice(i, 1) + } + } + } + } else { + //因为LAYUI问题,操作到变化全选状态时获取到的obj为空,这里用函数获取未选中的项。 + function nu() { + var noCheckedKey = ''; + for (var i = 0; i < table.cache[tableName].length; i++) { + if (!table.cache[tableName][i].LAY_CHECKED) { + noCheckedKey = table.cache[tableName][i][opt.checkedKey]; + } + } + return noCheckedKey + } + var noCheckedKey = obj.data[opt.checkedKey] || nu(); + for (var i = 0; i < checkedData.length; i++) { + if (checkedData[i][opt.checkedKey] == noCheckedKey) { + checkedData.splice(i, 1); + } + } + } + } + checkedData = uniqueObjArray(checkedData, opt.checkedKey); + updateButton(checkedData.length) + } else { + updateButton(table.checkStatus(tableName).data.length) + } + }); + + //渲染表格后选中 + function setChecked(res, curr, count) { + for (var i = 0; i < res.data.length; i++) { + for (var j = 0; j < checkedData.length; j++) { + if (res.data[i][opt.checkedKey] == checkedData[j][opt.checkedKey]) { + res.data[i].LAY_CHECKED = true; + var index = res.data[i]['LAY_INDEX']; + var checkbox = $('#' + tableName + '').next().find('tr[data-index=' + index + '] input[type="checkbox"]'); + checkbox.prop('checked', true).next().addClass('layui-form-checked'); + var radio = $('#' + tableName + '').next().find('tr[data-index=' + index + '] input[type="radio"]'); + radio.prop('checked', true).next().addClass('layui-form-radioed').find("i").html(''); + } + } + } + var checkStatus = table.checkStatus(tableName); + if (checkStatus.isAll) { + $('#' + tableName + '').next().find('.layui-table-header th[data-field="0"] input[type="checkbox"]').prop('checked', true); + $('#' + tableName + '').next().find('.layui-table-header th[data-field="0"] input[type="checkbox"]').next().addClass('layui-form-checked'); + } + updateButton(checkedData.length) + } + + //写入默认选中值(puash checkedData) + function defaultChecked(res, curr, count) { + if (firstLoad) { + if (opt.checkedKey && elem.attr('ts-selected')) { + var selected = elem.attr('ts-selected').split(","); + for (var i = 0; i < res.data.length; i++) { + for (var j = 0; j < selected.length; j++) { + if (res.data[i][opt.checkedKey] == selected[j]) { + checkedData.push(res.data[i]) + } + } + } + checkedData = uniqueObjArray(checkedData, opt.checkedKey); + } + firstLoad = false; + } + } + + //更新选中数量 + function updateButton(n) { + tableBox.find('.tableSelect_btn_select span').html(n == 0 ? '' : '(' + n + ')') + } + + //数组去重 + function uniqueObjArray(arr, type) { + var newArr = []; + var tArr = []; + if (arr.length == 0) { + return arr; + } else { + if (type) { + for (var i = 0; i < arr.length; i++) { + if (!tArr[arr[i][type]]) { + newArr.push(arr[i]); + tArr[arr[i][type]] = true; + } + } + return newArr; + } else { + for (var i = 0; i < arr.length; i++) { + if (!tArr[arr[i]]) { + newArr.push(arr[i]); + tArr[arr[i]] = true; + } + } + return newArr; + } + } + } + + //FIX位置 + var overHeight = (elem.offset().top + elem.outerHeight() + tableBox.outerHeight() - $(window).scrollTop()) > $(window).height(); + var overWidth = (elem.offset().left + tableBox.outerWidth()) > $(window).width(); + overHeight && tableBox.css({ 'top': 'auto', 'bottom': '0px' }); + overWidth && tableBox.css({ 'left': 'auto', 'right': '5px' }) + + //关键词搜索 + form.on('submit(tableSelect_btn_search)', function (data) { + checkedData = []; + updateButton(0); + tableSelect_table.reload({ + where: data.field, + page: false + }); + return false; + }); + + //双击行选中 + table.on('rowDouble(' + tableName + ')', function (obj) { + var checkStatus = { data: [obj.data] }; + selectDone(checkStatus); + }) + + //按钮选中 + tableBox.find('.tableSelect_btn_select').on('click', function () { + var checkStatus = table.checkStatus(tableName); + if (checkedData.length > 1) { + checkStatus.data = checkedData; + } + selectDone(checkStatus); + }) + // 清空 + tableBox.find('.tableSelect_btn_clear').on('click', function () { + checkedData = []; + updateButton(0); + tableSelect_table.reload(); + }); + + //写值回调和关闭 + function selectDone(checkStatus) { + if (opt.checkedKey) { + var selected = []; + for (var i = 0; i < checkStatus.data.length; i++) { + selected.push(checkStatus.data[i][opt.checkedKey]) + } + elem.attr("ts-selected", selected.join(",")); + } + opt.done(elem, checkStatus); + tableBox.remove(); + delete table.cache[tableName]; + checkedData = []; + } + + //点击其他区域关闭 + $(document).mouseup(function (e) { + var userSet_con = $('' + opt.elem + ',.tableSelect'); + if (!userSet_con.is(e.target) && userSet_con.has(e.target).length === 0) { + tableBox.remove(); + delete table.cache[tableName]; + checkedData = []; + } + }); + }) + } + + /** + * 隐藏选择器 + */ + tableSelect.prototype.hide = function (opt) { + $('.tableSelect').remove(); + } + + //自动完成渲染 + var tableSelect = new tableSelect(); + + //FIX 滚动时错位 + if (window.top == window.self) { + $(window).scroll(function () { + tableSelect.hide(); + }); + } + + exports(MOD_NAME, tableSelect); +}) \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/js/lay-module/tabletree/tabletree.css b/WaterCloud.Web/wwwroot/js/lay-module/tabletree/tabletree.css new file mode 100644 index 0000000..c108521 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/tabletree/tabletree.css @@ -0,0 +1,52 @@ +.treeTable-empty { + width: 20px; + display: inline-block; +} + +.treeTable-icon { + cursor: pointer; +} + +.treeTable-icon .layui-icon-triangle-d:before { + content: "\e623"; +} + +.treeTable-icon.open .layui-icon-triangle-d:before { + content: "\e625"; + background-color: transparent; +} +/** չͼ */ +.treeTable .tree-icon-folder:after, .treeTable .tree-icon-file:after { + content: ""; + padding: 2px 10px; + -webkit-background-size: cover; + -moz-background-size: cover; + -o-background-size: cover; + background-size: cover; + background-repeat: no-repeat; + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAE6UlEQVR4Xu2ZPYhcVRiGny9hC0FsTEBCGkFTWIQE/IlpgmKpWAiLyR0XLbYTxEKxkCAEhRCxEOwsjJnJioKIYClWKgqiskIIaCoLYyASVJT87JGspN37LrOXvec777Tzzrnvz7Nn2dnAr6YbiKbTOzwGoHEIDIABaLyBxuP7BjAAjTfQeHzfAAag8QYaj+8bwAA03kDj8X0DGIDGG2g8/lw3QFlhD9fZN7oOF7gYT3NudL5GaGjTAJQP2c1VXgIOExyGkf4/oXCe4I3oeH+EvY/G0qYAKFOWCV4Hdo8mQb+RL7jBE7HE3/3S9hQyAGXGCeDVSiv6lqscief4t1L/g9mWAChTHiD4ZrTXvVbPu9GxrEnbUWkAzPgeOJCglsXo+ChBji2L0AtAmfEgrP/0Z3hdZoF7Y5HLGcJsRQYFgLeAF7fiYSM540x0LI3Ey7bb6AdgytcEh7bd6VYa2MGhOJrmVpurmX4AZlwCds31lPF9+AI32O8/DYUvccqUKwR3jG/DuR29Gd36F1pNv/pvgKwAFK5RuC+e4eeWCWgXgJurFz6LCY8bgA0aSPwr4P/UhVNc43ir3xK2fQPcAr/wO/AewU/Ar6xRqroVdvAnC6zGIlc369sAbLax8er/ofAJOzkVR9e/uZVeBkCqqTrRyeh4RXFtAJSWatQUno0Jp/usG4C+hup9/yJ72BuPcH2jCAag3oEV50vRccYAKFXl1LwdHS8YgJzj9qcqfBoTnjQA/VVlVXwXHfcbgKzz9uf6IToOGoD+orIqDEDWZcVcBkAsKqvMAGRdVsxlAMSissoMQNZlxVwGQCwqq8wAZF1WzGUAxKKyygxA1mXFXAZALCqrzABkXVbMZQDEorLKDEDWZcVcBkAsKqvMAGRdVsxlAMSissoMQNZlxVwGQCwqq8wAZF1WzGUAxKKyygxA1mXFXAZALCqrzABkXVbMZQDEorLKDEDWZcVcBkAsKqvMAGRdVsxlAMSissoMQNZlxVwGQCwqq8wAZF1WzGUAxKKyygxA1mXFXAZALCqrzABkXVbMZQDEorLKDEDWZcVcBkAsKqvMAGRdVsxlAMSissoMQNZlxVwGQCwqq8wAZF1WzGUAxKKyygxA1mXFXAZALCqrzABkXVbMZQDEorLKDEDWZcVcBkAsKqvMAGRdVsxlAMSissoMQNZlxVwGQCwqq8wAZF1WzGUAxKKyygxA1mXFXAZALCqrzABkXVbMZQDEorLKDEDWZcVcBkAsKqvMAGRdVsxlAMSissoMQNZlxVwGQCwqq8wAZF1WzLUFAMy4BOwSH2jZmBoorMaE/RtZij6/ZcoFgrv7dH5/lA38Eh33zAfAjM+BR0cZz6Y2bqDwY0w4MB8AU04SvOyuq2zg4+h4aj4AzvIwha+qjN+66cLzMeGduQC4+eEy4zywr/U+K8t/hQX2xiJ/zQ/ACgdZ40vgtspKaNducCyOsdJXQO9fAbcOKGc5whofENzVd6jf3/YGTkTHccWFDMD6r4LT3MlOloHHCB4CblceYs3gDfxB4TeCcxReiwmr6hM3BYB6qHX1NGAA6tlqEKcGYJBa6znUANSz1SBODcAgtdZzqAGoZ6tBnBqAQWqt51ADUM9Wgzg1AIPUWs+hBqCerQZxagAGqbWeQw1APVsN4tQADFJrPYcagHq2GsTpf+KxwJB5Cd5mAAAAAElFTkSuQmCC"); +} +.treeTable-icon.open .tree-icon-folder:after { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAKwElEQVR4Xu2df9AVVRnHP899gUxmYKhsCpJREEeMakSoiGGCbIxSizIJ7i5OksZkMIxQjlOQyOCQ5o/8RWmkMdz7wjDC5I+hcFSKxEENh4YsEwPJAbVQ8AeQL733NPcKyn3v7r17d8/uvfvus//ec57n+3yf7z179uw5zwp6ZZoByXT0GjwqgIyLQAWgAsg4AxkPX0cAFUDGGch4+DoCqAAyzkDGw9cRQAWQcQYyHr6OACqA5hkw63kfr3IyOQZTIte8BUs9OnibEi/isEcEY8lqpswEHgHMGgbSxTyEyRjGIC1MfM8UGQ4CfyLHWp7jbllEKVNZjBBsIAGYAi7CrcCgCL6S6voM4IrDtqQcptlPQwGYAksRrkpVkIZD5JgmeR5IFe4WgK0rAFPkamBRC3BFd2k4AkwSl83RjfVeC74CMCuZSI6NqQ7d8G9KDJOLK3MEvTwY8BdAga0Io3sBa0vEYWEviCOWEDwFYDoZh+HxWDwmb/R18gzSx0Rv4r0FUORa4EfJ5yomj8IEyfNYTNZTbdZbAAU2IJyb6siOB2+4Qlx+3mvisRiInwC2I4yy6Ke1pgw/E5crWwuiPb373QL+BZzcnpBDobpLHGaF6tnLO6kAenmCG4WXFQH8WhwubURGFn/PhgAMD4nLl7KY4EYxZ0MAcBhhqOTZ14iQrP2eFQGU8/ogeb6qC0LVEs+SAMqRL+ctLpdZlRdFeoH32UBTpLc9Br6XbMMuhLUIm+jmzbZSQUdlV9M++rBTpnI4CWxZGwGS4NSWj2eBh4CbxGG3LaM97agA4mLWnt23gZ+yg8VxbHVTAdhLVNyWHqabKbb3NqgA4k6bTfuG+3GYYvNJRgVgM0FJ2DL8QFxutOVKBWCLyaTsGN6gH0NlKq/bcKkCsMFi0jYMs8XlDhtuVQA2WEzahuH34vJlG25VADZYTN7GPnE4yYZbFYANFlth4y362VjSVgG0Ink2fAon2Xi7qQKwkYxW2OglAtiP4QlgN8LLreAxtT4HcL1cwKGo+FsxAnQDv6HEbTKDv0QNQPtHYyBpAZSPm7mSp/ymS682YCA5ARiWMYS5Mon/tUHcCuEoA0kJ4AZx+KGy3n4MJCGA9eJwXqPQzSJyjGAMJU5s1FZ/r8NAH7roYIdM5T9BeIpXAIaXOMKZcgkH/MCYIp8GvgN8A/hQENDaJhADrwG/oy9X1BNDvAIQZkqee+okfwGGa9qq4FQgblPVaC85xsp09nqhjlMAO9nBCK9tTGYjfdhLJ3BRqqhMK1jDdoYw2msCHqcAypsZ53txZoqVo9pz08pnKnEbLhKXe3tij1MAk8VhQ0+HZjWj6GZ7KklMM2jD3eJW5lpVV5wC+IA47K8RQJEVwMVp5jKV2H3OR8YjAMPL4vLRmuSvoYMjvAoMTCWJ6Qa9Vhy+mdQIsEEcJtcIYCWjybE13TymFL2wVPK1dZ/iGgE8S7KYTi7F8KuUUphu2AlPAsu1eose9/9lwPfSzWRq0Q8Xh53J3AI6+IRM4681AiiwBeEzqaUwrcANh8Slvxf8OG4BXezg/T0XgCpr/afxX4S+aeUxtbgNfxCXSUkJYJs4nKXP/20ll5vFYV4yAjCsEJdve9z/y8/+5TUAvZJmwDBDXArJCADmicPNHgLQ5d+kE3/Mn+Hj4vK3ZARg+KK4POIxAdyEMKFVHGTWb/m7Cc9zgl9tgTgmgd5LwAUOIrrZI3EhGraIyzg/v7YFsFcchnhMAE+nm38kHrw6BMMycfl+MgLwObRoikwDVmk+WsCAcJnkWZ6MAOA6cWo/MGUKXI/optAWpB9KnC0zeDoZAQh5ydf+002BhxHOaQkBWXZqKHGQE+odIrU7BxBGSZ7yd/uqLlOsbArVV8DJi9FzUe54GDYF4L0EvIpTKLEr+djVIz67gOIRgOFpcTnb499f3u69VtPREgbmiMPt9TzbHAHuEYeZHgtASxB+3JLws+40x3iZXv/rb/YE4PNhJlNgPWKnnk3W89l0/APo3+gIuT0BwBfEqf3SqCnwCsKHmwavHaIy8Kw4jGxkxKYAapaAzSoGU2JPIxD6ewwMGDrFxWlk2Y4ADHvE5WMe9//zEf2Cd6MkxPJ7wIqidgQAnieATYGfIFwTS4BqtD4DwjmS59FGNNkRgM+WY1Pkt8DXGoHQ32NgoItB9U5lH/NoRwAwXRxWe6wB9N4vj8SQM4smXxCHU4PYsyOADs6Uafz9eIdmDQM54l8XIAg4bROagXXicGGQ3jYE4L0EXOBcpPZwaBBQ2iYiA4YF4la+AN/wsiGAP4vDWI8ngKsQljZEoA3iYOA8cVgfxHB0Afi8cDBF1mgBiCApiKGN8BHJ80oQy9EFAHPF4VaPCeDzwPAgILSNRQYML4nL4KAWowtAmCh5/lg1AXyAE3mDg0FBaDurDASqynbMY3QBQO0S8Eomkqt9L2A1TDXmx8AScVgYlJ6oAnhRHIZ6TADnI9wQFIS2s8rAheKwLqjFqAJ4UBwu8BBAESEfFIS2s8hAjlNlOi8EtRhNAIZrxWWBxwSwvCh0RlAQ2s4SA4YD4jKoGWvRBCB8S/KVx713L6MTwGb4t932UXGa230dTQAlzpAZ1Sd+TIHxCI/ZjkztBWKg6aLcUQTgtwQ8B6ldFwgEXxtFY8DnXEY9o+EFYHhK3Eqh56rLFCu1gWvqA0SLTHsHYkAY2ezHOMILAJaLw2UeAih/BuaTgQBrI3sM1KkDFM8IADV7zs2d9KV/pQ5Qzl5kaikQA4bHxWV8oLbHNYoyAnxeHDZVPQEUGIvwZLMgtL0VBm4XhznNWgovAI8956aTWRh+2SwIbW+BgQbfZvDzEFYAu8XhFI/7/53Ady2EoyaaZ+AscdjWbLdwAjDcL27tZk9T5ClgTLMgtH1EBhrUAYpjEljzxkkLQUZMYrTuW8UJ98cLOwLUfH3CrORT5JofgqLFrb2PMuD5SB6EnXACgNPFYUfVE0Anl5TPowdxqm2sM3C5OPwijNXmBeCz4GCK3AbMDgNC+0RkwDBOXLaEseIngOeAEZ4GDU+Iy2drngAKbEb4XBgQ2icCAwHqADU/CSzwJFK71fuoobvEYVbV8P9OJfA3tRBkhESG7/qMOIwK2917BCiwDuHrPiPAbHG5o0oAqxlJt3ct2rDAtF9ABnyKcwfsjd8tYDH4bCwUJki++n2/KVbOoXtWow4KRNuFZsDzXGZQa34jgP+xLq8l4CI3gnc9+qBAtF0IBgwH6MdgmcrhEL0rXbwFUP68WxevIQyoMmzYJS7DPCaAGxEmhgWh/UIyIMyXPDeF7O0vgPIvpsB1CFf2MH6fOEzxEIBWAo+ShXB915PnfBFMuO7v9PIcASoCWMEH6VNZ7Hlvl6lhsbhc3WMCOJxuysfA9EqKAUO5+P7MeiVgg0LxFUBFBEW+AtwH9DlqsObQgSlWvgBetTM4qHNt1zQD+zEs7PkU1rSV4zrUFcDRW0G50NMtwDBKjJAZ1f92U2ApUlshPAoo7fsuA12YCt+bgXvpxyMylW6b/DQUwDFnZiWn4fLPqPccm+DVVnQGAgsguiu10I4MqADaMSsJYlIBJEh2O7pSAbRjVhLEpAJIkOx2dKUCaMesJIhJBZAg2e3oSgXQjllJEJMKIEGy29GVCqAds5IgJhVAgmS3oysVQDtmJUFM/wdaDlOuM5Eu/AAAAABJRU5ErkJggg=="); +} +.treeTable .tree-icon-file:after { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAJNUlEQVR4Xu2dXYxdVRXHf2tghhYaoba1Qk1owIwmfVBaTKRgQqMPlGjig2nDnDsF0whSnwqJ4SNoU2OLUSNPVDSx2t47hEkxaQMBI1hB/EiE6osYqjGUYPGjCihN6Uy525wzt7UdZu7ZZ87a5949Z52XeVl77bX//9/d52vvM4IdtVZAaj16GzwGQM0hMAAMgJorUPPh2wxgANRcgZoP32YAA6DmCtR8+DYDGADVKuB2s4BB1gMbEYZxLEFYDlxQbSU97+0Ejn8hHMPxR4R9LOZxuZGTVVZW2QzgxlnGBNuBUYSLqhxkNH05jgN7GeIrsoF/VlF3cADcQc7nKHfiuM+M97Q0BUH4GpfxbVnHKc9WcwoLCoBrsRjHYwhr51Rd3Rs5foXwaUl4PZQUwQBwLa4AngZWhiq+JnlfBj4pCX8JMd4gALgxluJ4Hrg8RNE1zHkE4WoZ4Zj22NUBcOMsZILnEFZrF1vrfI5DDHGdbOCEpg76ADTZiXCXZpGWq6OAsFNGuEdTD1UA3B7exwDpdLUgt0jHqwjjwH6EF0NMb7k19DAgO03CKtp8pvNM5AO55TjeZoCVMsLfc2M9A3QBaPEQcGtO328hbOYw+2Qbbc8653WY28YAw3yONrsRLswZ7Pck4TYtQdQAcOMMMckbwMIuxaVPua6VhBe0BjCf8rgWa4Bf5jwVPcEgl8gGJjTGrgfAGDfgeCKnqC2SsEuj8Pmaw7W4HXiw6/iE9TLCkxoa6AHQyopOi5/5cLzCCq4M/WRLQ5Re5ug8Of1z11tox3el0UXrAgPQA6DJQYTru/R9ryTsKFBbbUNdK7vS/3qXH9PPpcE6DYH0AGjxEjA8a1Ft1sgohzSKnu853MNcRburVocl4UMaOugB0MxeYMx+BTt14fKmRtHzPYcb5+LOBfVsp9Pj0mCRhg56ALRw3QqSxPYgFDHMVaSnAVDElQpjDYAKxe7HrgyAfnSlwpoMgArF7seuDIB+dKXCmgyACsXux64MgH50pcKaDIAKxe7HrgyAfnSlwpoMgBnEduO8n0m+j+MahCUV+pHf1dQun18zyBdkA3/Lb9A9wgCYpk9nj8EfEC4tK27Q9o7XGOIjZXf2GADTAWjyQ4Sbg5qnl3yvJGwqk84AePcMkO6VSxdSxnAck4RlZQo1AN4NwF+By8qIWmHbo5Kwokx/BkDcp4A9kpQ7XRkA0wGY2nPw+yguAoVVZTd0GgAz3Qbu5VIGsr0H1wLvLTPFBmj772xJd5vbZJTXyuY3AMoqGHl7AyByA8uWbwCUVTDy9gZA5AaWLd8AKKtg5O0NgMgNLFu+AVBWwcjbGwCRG1i2fAOgrIKRtzcAIjewbPkGQFkFI29vAERuYNnyDYCZXgbZmsAzqmjtto5md7CtCTz3F1E/AGxN4DkE1A+AVvb9fFsT2MGgjgDYmsCz5oD6ARDXKcDWBE6/iC9LbOc7xLYmsK6ngHTcztYE1vc2sOyDldja24Og2BxTrtcAUBY0tnQGQGyOKddrACgLGls6AyA2x5TrNQCUBY0tnQEQm2PK9RoAyoLGls4AiM0x5XoNAGVBY0tnAMTmmHK9BsAMgqp+J1D5u37K/mMATFM02JpApe/6GQCB/8eNC7sgpPR3/QyA0ACEXRNY+rt+BkB4AEKuCSz9XT8DIDQAYU8BpdfwGQChAQj1ncD0IlDhu34GQGAAUoGV1wSqftfPAKgAAG2RQ+Rzu1nAIOuBjQjDOJYgLAcu0Oyv7Crr07VEszdQU7wQudw4y5hgOzCKcFGIPs7OaQCEVtgzvzvI+RzlThz3VWF8p6wJSXRmFJsBPI2eKazzdPIxhLUl0syl6RFJWDmXhtPbGABzVNG1uAJ4GnSMKFSG4zfS4JpCbWYJNgDmoKIbYymO54HL59C8fBPHj6TBLeUTgQFQUEU3zkImeA5hdcGmeuHCRhlhXCOhAVBQRddkJ8JdBZtphr/DIEtkA29qJDUACqjY2aF8BGFBbjPHq0j2K92P8KKMcKxbGzfGKhy/ABbn5N4vCZ/N7d8zwADwFCoNc63sv5XcmtPkLYTNHGafbKPtk76A+dDmwzLKSz55fWIMAB+VUvPHGWKSN4CFXZqcTP+djSS84JmWQuY7xqRB4pvbJ84A8FEpBWCMG3A8kRO+RRJ2eaZMZ5SPAj/zmPbTlEd5h6tkE//wze8TZwD4qDQ1/T8I3D5ruOMVVnClrOOUT8rMfMczCO/JjXdM4vi4jHIoN7ZggAHgKZhrchDh+i7h90rCDp90hcwHB9wiCXt8cheNMQA8FXOt7MJreNbwNmt8fqEFzU/t3ywNfuBZZuEwA8BTMtfkOMKFs4YPcknevblr8jHgKa9pf6qjQtcUnkM5J8wA8FSt7Dr9zHzJLvgWeXYZ3Py0DgPA040yABQ237FVGjzgWVqpME0A/tuVbsfF0uA/partYeO5AtDP5uvOAE3+hPDBWT0aYLXcxO966GGprucCQL+brw3AswifmFVlxz3SYGcpF3rYuCgA7mHW0uYn3ud8x93S4P6qh6h3CmiyC+GLXQAo9KCkaiHy+isCQMf8p3IeG/+/yx6ZrzsDtLgReLyrkI4vSSN7ohbd4QvAHMzfLg2+2itB9GaA9GXJBK93vVeGk7RZ6/PApFeCzNavDwCuxaeAAwV++fdLg7t7OVY1ANJBeL8udXyehEdFssecURx5AAB3AN8EzvMakOMBabDVKzZgkC4AYyynzcveCybgEYQDPgsmAmrgldoDAK88WVCfmK96DXB69K7JNxC+7K9GzSL7yPwwAKSLJid5Fri6Ztb6DHeXJGzxCawqRvUUcGYWmFo2/duerJmvSrni/fSd+UFmgDMQTG2c+Clkf+t+fEeS7CKx744gM8BZEKQrXNPbouv6buTVFHQSx83S4JFquiveS1AAsgvehxhkEXdUvHmyuBL6LZ5hgK39/v4jOABnZoN0+/QkO3DcVOEuWn1bu2V0vA38mPP4Vr8bf3oYlQFwFgjpXcJ6HBshe3u4NMQHFII7ny7UlOy/maYbPtI3oY9yigOyiePB+1bsoHIAFGu3VAoKGAAKIsacwgCI2T2F2g0ABRFjTmEAxOyeQu0GgIKIMacwAGJ2T6F2A0BBxJhTGAAxu6dQuwGgIGLMKf4HAR/hrhUhGSQAAAAASUVORK5CYII="); +} +.treeTable .tree-table-arrow { + font-size: 12px; + font-weight: 600; + line-height: 16px; + height: 16px; + width: 16px; + display: inline-block; + text-align: center; + color: #888; + margin-right: 5px; +} +.treeTable .tree-table-arrow:before { + content: "\e602"; +} +.treeTable .open .tree-table-arrow:before { + content: "\e61a"; +} + diff --git a/WaterCloud.Web/wwwroot/js/lay-module/tabletree/tabletree.js b/WaterCloud.Web/wwwroot/js/lay-module/tabletree/tabletree.js new file mode 100644 index 0000000..920a53c --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/tabletree/tabletree.js @@ -0,0 +1,224 @@ +layui.define(['layer', 'table','soulTable'], function (exports) { + var $ = layui.jquery; + var layer = layui.layer; + var soulTable = layui.soulTable; + var table = layui.table; + var _instances = {}; // 记录所有实例 + var tabletree = { + // 渲染树形表格 + render: function (param) { + var id = param.elem.substring(1); + var isclick = true; + if (!!_instances[id]) { + isclick = false; + } + else { + _instances[id] = param; + } + // 检查参数 + if (!tabletree.checkParam(param)) { + return; + } + // 获取数据 + if (param.data) { + tabletree.init(param, param.data); + } else { + $.getJSON(param.url, param.where, function (res) { + tabletree.init(param, res.data); + }); + } + if (isclick) { + // 给图标列绑定事件 + $('body').on('click', '.treeTable .treeTable-icon', function () { + var treeLinkage = $(this).parents('.treeTable').attr('treeLinkage'); + if ('true' == treeLinkage) { + tabletree.toggleRows($(this), true, id); + } else { + tabletree.toggleRows($(this), false, id); + } + + $('div[lay-id=' + id + ']').find('.layui-table-main tbody tr').each(function () { + + + }); + }); + } + }, + // 渲染表格 + init: function (param, data) { + var mData = []; + var doneCallback = param.done; + var tNodes = data; + // 补上id和pid字段 + for (var i = 0; i < tNodes.length; i++) { + var tt = tNodes[i]; + if (!tt.id) { + if (!param.treeIdName) { + layer.msg('参数treeIdName不能为空', {icon: 5}); + return; + } + tt.id = tt[param.treeIdName]; + } + if (!tt.pid) { + if (!param.treePidName) { + layer.msg('参数treePidName不能为空', {icon: 5}); + return; + } + tt.pid = tt[param.treePidName]; + } + } + + // 对数据进行排序 + var sort = function (s_pid, data) { + for (var i = 0; i < data.length; i++) { + if (data[i].pid == s_pid) { + var len = mData.length; + if (len > 0 && mData[len - 1].id == s_pid) { + mData[len - 1].isParent = true; + } + mData.push(data[i]); + sort(data[i].id, data); + } + } + }; + sort(param.treeSpid, tNodes); + + // 重写参数 + param.url = undefined; + param.data = mData; + param.cols[0][param.treeColIndex].templet = function (d) { + var mId = d.id; + var mPid = d.pid; + var isDir = d.isParent; + var emptyNum = tabletree.getEmptyNum(mPid, mData); + var iconHtml = ''; + for (var i = 0; i < emptyNum; i++) { + iconHtml += ''; + } + if (isDir) { + iconHtml += ''; + } else { + iconHtml += ''; + } + iconHtml += '  '; + var ttype = isDir ? 'dir' : 'file'; + var vg = ''; + return vg + iconHtml + d[param.cols[0][param.treeColIndex].field] + '' + }; + + param.done = function (res, curr, count) { + $(param.elem).next().addClass('treeTable'); + $(param.elem).next().attr('treeLinkage', param.treeLinkage); + // 绑定事件换成对body绑定 + /*$('.tabletree .treeTable-icon').click(function () { + tabletree.toggleRows($(this), param.treeLinkage); + });*/ + if (param.treeDefaultClose) { + tabletree.foldAll(param.elem); + } + if (doneCallback) { + doneCallback(res, curr, count); + } + if (!!param.filter) { + soulTable.render(this); + } + table.resize(); + }; + + // 渲染表格 + table.render(param); + }, + // 计算缩进的数量 + getEmptyNum: function (pid, data) { + var num = 0; + if (!pid) { + return num; + } + var tPid; + for (var i = 0; i < data.length; i++) { + if (pid == data[i].id) { + num += 1; + tPid = data[i].pid; + break; + } + } + return num + tabletree.getEmptyNum(tPid, data); + }, + // 展开/折叠行 + toggleRows: function ($dom, linkage,id) { + var type = $dom.attr('lay-ttype'); + if ('file' == type) { + return; + } + var mId = $dom.attr('lay-tid'); + var isOpen = $dom.hasClass('open'); + if (isOpen) { + $dom.removeClass('open'); + } else { + $dom.addClass('open'); + } + $dom.closest('tbody').find('tr').each(function () { + var $ti = $(this).find('.treeTable-icon'); + var pid = $ti.attr('lay-tpid'); + var ttype = $ti.attr('lay-ttype'); + var tOpen = $ti.hasClass('open'); + if (mId == pid) { + if (isOpen) { + $(this).hide(); + var index = $(this).attr('data-index'); + $('div[lay-table-id=' + id + ']').find('.layui-table-fixed tbody tr[data-index= ' + index + ']').hide(); + if ('dir' == ttype && tOpen == isOpen) { + $ti.trigger('click'); + } + } else { + $(this).show(); + var index = $(this).attr('data-index'); + $('div[lay-table-id=' + id + ']').find('.layui-table-fixed tbody tr[data-index= ' + index + ']').show(); + if (linkage && 'dir' == ttype && tOpen == isOpen) { + $ti.trigger('click'); + } + } + } + }); + }, + // 检查参数 + checkParam: function (param) { + if (!param.treeSpid && param.treeSpid != 0) { + layer.msg('参数treeSpid不能为空', {icon: 5}); + return false; + } + + if (!param.treeColIndex && param.treeColIndex != 0) { + layer.msg('参数treeColIndex不能为空', {icon: 5}); + return false; + } + return true; + }, + // 展开所有 + expandAll: function (dom) { + $(dom).next('.treeTable').find('.layui-table-body tbody tr').each(function () { + var $ti = $(this).find('.treeTable-icon'); + var ttype = $ti.attr('lay-ttype'); + var tOpen = $ti.hasClass('open'); + if ('dir' == ttype && !tOpen) { + $ti.trigger('click'); + } + }); + }, + // 折叠所有 + foldAll: function (dom) { + $(dom).next('.treeTable').find('.layui-table-body tbody tr').each(function () { + var $ti = $(this).find('.treeTable-icon'); + var ttype = $ti.attr('lay-ttype'); + var tOpen = $ti.hasClass('open'); + if ('dir' == ttype && tOpen) { + $ti.trigger('click'); + } + }); + } + }; + + layui.link(layui.cache.base + 'tabletree/tabletree.css'); + + exports('tabletree', tabletree); +}); diff --git a/WaterCloud.Web/wwwroot/js/lay-module/treetable-lay/treeTable.js b/WaterCloud.Web/wwwroot/js/lay-module/treetable-lay/treeTable.js new file mode 100644 index 0000000..ca51f53 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/treetable-lay/treeTable.js @@ -0,0 +1,2280 @@ +/** 树形表格3.x Created by wangfan on 2020-05-12 https://gitee.com/whvse/treetable-lay */ + +layui.define(['laytpl', 'form', 'util'], function (exports) { + var $ = layui.jquery; + var laytpl = layui.laytpl; + var form = layui.form; + var util = layui.util; + var device = layui.device(); + var MOD_NAME = 'treeTablelay'; // 模块名 + var _instances = {}; // 记录所有实例 + + /* 表格默认参数 */ + var defaultOption = { + elem: undefined, // 容器 + loading: true, //加载 + cols: undefined, // 列参数 + url: undefined, // url模式请求 + method: undefined, // url模式请求方式 + where: undefined, // url模式请求条件 + contentType: undefined, // url模式请求类型 + headers: undefined, // url模式请求headers + parseData: undefined, // url模式处理请求数据 + request: { pidName: 'pid' }, // url模式请求字段自定义 + toolbar: undefined, // 表头工具栏 + defaultToolbar: undefined, // 表头工具栏右侧按钮 + width: undefined, // 容器宽度 + height: undefined, // 容器高度 + cellMinWidth: 90, // 单元格最小宽度 + done: undefined, // 数据处理完回调 + data: undefined, // 直接赋值数据 + title: undefined, // 定义table大标题,文件导出会用到 + skin: undefined, // 表格风格 + even: undefined, // 是否开启隔行变色 + size: undefined, // 表格尺寸 + checkOther: true, // 复选框联动 + text: { + none: '无数据' // 空数据提示 + }, + reqData: undefined, // 自定义加载数据方法 + useAdmin: false, // 是否使用admin.ajax + tree: { + idName: 'id', // id的字段名 + pidName: 'pid', // pid的字段名 + childName: 'children', // children的字段名 + haveChildName: 'haveChild', // 是否有children标识的字段名 + haveChildReverse: false, // 是否将children标识的字段取反 + openName: 'open', // 是否默认展开的字段名 + iconIndex: 0, // 图标列的索引 + arrowType: undefined, // 折叠箭头类型 + onlyIconControl: undefined, // 仅点击图标控制展开折叠 + getIcon: function (d) { // 自定义图标 + var haveChild = d[this.haveChildName]; + if (haveChild !== undefined) { + haveChild = haveChild === true || haveChild === 'true'; + if (this.haveChildReverse) haveChild = !haveChild; + } + else if (d[this.childName]) haveChild = d[this.childName].length > 0; + if (haveChild) return ''; + else return ''; + } + } + }; + /* 列默认参数 */ + var colDefaultOption = { + field: undefined, // 字段名 + title: undefined, // 标题 + width: undefined, // 宽度 + minWidth: undefined, // 最小宽度 + type: 'normal', // 列类型 + fixed: undefined, // 固定列 + hide: undefined, // 是否初始隐藏列 + unresize: undefined, // 禁用拖拽列宽 + style: undefined, // 单元格样式 + align: undefined, // 对齐方式 + colspan: undefined, // 单元格所占的列数 + rowspan: undefined, // 单元格所占的行数 + templet: undefined, // 自定义模板 + toolbar: undefined, // 工具列 + 'class': undefined, // 单元格class + singleLine: undefined // 是否一行显示 + }; + + /** TreeTable类构造方法 */ + var TreeTable = function (options) { + _instances[options.elem.substring(1)] = this; + this.reload(options); + }; + + /** + * 根据ID查找数据 + * @param id 数据条目的ID + */ + TreeTable.prototype.findDataById = function (id) { + var options = this.options; + function each(data) { + for (var i = 0; i < data.length; i++) { + if (data[i][options.tree.idName] === id) return data[i]; + if (data[i][options.tree.childName]) { + var res = each(data[i][options.tree.childName]); + if (res) return res; + } + } + } + return each(options.data); + } + + /** 参数设置 */ + TreeTable.prototype.initOptions = function (opt) { + var that = this; + + // 处理特殊列 + function initCol(item) { + if (!item.INIT_OK) item = $.extend({ INIT_OK: true }, colDefaultOption, item); + // 特殊列处理 + if (item.type === 'space') { // 空列 + if (!item.width) item.width = 15; + item.minWidth = item.width; + } else if (item.type === 'numbers') { // 序号列 + if (!item.width) item.width = 40; + item.minWidth = item.width; + if (!item.singleLine) item.singleLine = false; + if (!item.unresize) item.unresize = true; + if (!item.align) item.align = 'center'; + } else if (item.type === 'checkbox' || item.type === 'radio') { // 复/单选框列 + if (!item.width) item.width = 48; + item.minWidth = item.width; + if (!item.singleLine) item.singleLine = false; + if (!item.unresize) item.unresize = true; + if (!item.align) item.align = 'center'; + } + if (item.toolbar) item.type = 'tool'; + return item; + } + + // 初始化列参数 + if ('Array' !== isClass(opt.cols[0])) opt.cols = [opt.cols]; + + // 恢复cols参数初始状态 + for (var m = 0; m < opt.cols.length; m++) { + for (var n = 0; n < opt.cols[m].length; n++) { + opt.cols[m][n].INIT_OK = undefined; + opt.cols[m][n].key = undefined; + opt.cols[m][n].colGroup = undefined; + opt.cols[m][n].HAS_PARENT = undefined; + opt.cols[m][n].parentKey = undefined; + opt.cols[m][n].PARENT_COL_INDEX = undefined; + } + } + + // cols参数处理 + var colArrays = [], colIndex = 0; + for (var i1 = 0; i1 < opt.cols.length; i1++) { + var item1 = opt.cols[i1]; + for (var i2 = 0; i2 < item1.length; i2++) { + var item2 = item1[i2]; + if (!item2) { + item1.splice(i2, 1); + continue; + } + item2 = initCol(item2); + // 合并单元格处理 + item2.key = i1 + '-' + i2; + var CHILD_COLS = undefined; + if (item2.colGroup || item2.colspan > 1) { + item2.colGroup = true; + item2.type = 'group'; + CHILD_COLS = []; + colIndex++; + var childIndex = 0; + for (var i22 = 0; i22 < opt.cols[i1 + 1].length; i22++) { + var item22 = $.extend({ INIT_OK: true }, colDefaultOption, opt.cols[i1 + 1][i22]); + if (item22.HAS_PARENT || (childIndex > 1 && childIndex == item2.colspan)) { + opt.cols[i1 + 1][i22] = item22; + continue; + } + item22.HAS_PARENT = true; + item22.parentKey = i1 + '-' + i2; + item22.key = (i1 + 1) + '-' + i22; + item22.PARENT_COL_INDEX = colIndex; + item22 = initCol(item22); + CHILD_COLS.push(item22); + childIndex = childIndex + parseInt(item22.colspan > 1 ? item22.colspan : 1); + opt.cols[i1 + 1][i22] = item22; + } + } + item2.CHILD_COLS = CHILD_COLS; + if (!item2.PARENT_COL_INDEX) colArrays.push(item2); + opt.cols[i1][i2] = item2; + } + } + this.options = $.extend(true, {}, defaultOption, opt); + this.options.colArrays = colArrays; + + // url加载模式转为reqData模式 + if (this.options.url) { + this.options.reqData = function (data, callback) { + if (!that.options.where) that.options.where = {}; + if (data) that.options.where[that.options.request.pidName] = data[that.options.tree.idName]; + (that.options.useAdmin ? layui.admin : $).ajax({ + url: that.options.url, + data: that.options.contentType && that.options.contentType.indexOf('application/json') === 0 ? JSON.stringify(that.options.where) : that.options.where, + headers: that.options.headers, + type: that.options.method, + dataType: 'json', + contentType: that.options.contentType, + success: function (res) { + if (that.options.parseData) res = that.options.parseData(res); + if (res.code == 0) callback(res.data); + else callback(res.msg || '加载失败'); + }, + error: function (xhr) { + callback(xhr.status + ' - ' + xhr.statusText); + } + }); + }; + } else if (this.options.data && this.options.data.length > 0 && this.options.tree.isPidData) { // pid形式数据转children形式 + this.options.data = tt.pidToChildren(this.options.data, this.options.tree.idName, this.options.tree.pidName, this.options.tree.childName); + } + + // toolbar参数处理 + if ('default' === this.options.toolbar) { + this.options.toolbar = [ + '
                ', + '
                ', + ' ', + '
                ', + '
                ', + ' ', + '
                ', + '
                ', + ' ', + '
                ', + '
                ' + ].join(''); + } + if (this.options.defaultToolbar === undefined) this.options.defaultToolbar = ['filter', 'exports', 'print']; + + // 自定义图标参数处理 + if (typeof this.options.tree.getIcon === 'string') { + var icon = this.options.tree.getIcon; + this.options.tree.getIcon = function (d) { + if (icon !== 'ew-tree-icon-style2') return icon; + var haveChild = d[this.haveChildName]; + if (haveChild !== undefined) { + haveChild = haveChild === true || haveChild === 'true'; + if (this.haveChildReverse) haveChild = !haveChild; + } + else if (d[this.childName]) haveChild = d[this.childName].length > 0; + if (haveChild) return ''; + else return ''; + } + } + }; + /** 初始化表格 */ + TreeTable.prototype.init = function () { + var options = this.options; + var $elem = $(options.elem); // 原始表格 + var tbFilter = options.elem.substring(1); // 表格的filter + // 第一次生成树表格dom + $elem.removeAttr('lay-filter'); + if ($elem.next('.ew-tree-table').length === 0) { + $elem.css('display', 'none'); + $elem.after([ + '
                ', + ' ', + '
                ', + '
                ', + '
                ', + '
                ', + '
                ', + options.loading == true ? '
                ' : '
                ', + ' ', + '
                ', + '
                ', options.text.none || '', '
                ', + '
                ', + '
                ' + ].join('')); + } + // 获取各个组件 + var components = this.getComponents(); + + // 基础参数设置 + if (options.skin) components.$table.attr('lay-skin', options.skin); + if (options.size) components.$table.attr('lay-size', options.size); + if (options.even) components.$table.attr('lay-even', options.even); + + // 头部工具栏 + components.$toolbar.empty(); + if (options.toolbar === false || options.toolbar === undefined) { + components.$toolbar.hide(); + } else { + components.$toolbar.show(); + if (typeof options.toolbar === 'string') { + laytpl($(options.toolbar).html()).render({}, function (html) { + //按钮遮挡 + components.$toolbar.html('
                ' + html + '
                '); + //components.$toolbar.html('
                ' + html + '
                '); + }); + } + var tbRights = ['
                ']; + for (var i = 0; i < options.defaultToolbar.length; i++) { + var tbItem; + if ('filter' === options.defaultToolbar[i]) { + tbItem = { title: '筛选', layEvent: 'LAYTABLE_COLS', icon: 'layui-icon-cols' }; + } else if ('exports' === options.defaultToolbar[i]) { + tbItem = { title: '导出', layEvent: 'LAYTABLE_EXPORT', icon: 'layui-icon-export' }; + } else if ('print' === options.defaultToolbar[i]) { + tbItem = { title: '打印', layEvent: 'LAYTABLE_PRINT', icon: 'layui-icon-print' }; + } else { + tbItem = options.defaultToolbar[i]; + } + if (tbItem) { + tbRights.push('
                '); + tbRights.push('
                '); + } + } + components.$toolbar.append(tbRights.join('') + '
                '); + } + + // 固定宽度 + if (options.width) { + components.$view.css('width', options.width); + components.$tHeadGroup.css('width', options.width); + components.$tBodyGroup.css('width', options.width); + } + // 表格尺寸设置 + var colgroupHtml = this.resize(true); + // 生成thead + var headHtml = '' + this.renderBodyTh() + ''; + + // 渲染表头及空的表主体的结构 + components.$tBodyGroup.children('style').remove(); + if (options.height) { // 固定表头 + components.$tHead.html(colgroupHtml + headHtml); + components.$tBody.html(colgroupHtml + ''); + if (options.height.indexOf('full-') === 0) { // 差值高度 + var h = parseFloat(options.height.substring(5)) + components.$toolbar.outerHeight() + + components.$tHeadGroup.outerHeight() + 1; + components.$tBodyGroup.append([ + '' + ].join('')); + components.$tBodyGroup.data('full', h); + components.$tBodyGroup.css('height', ''); + } else { // 固定高度 + components.$tBodyGroup.css('height', options.height); + components.$tBodyGroup.data('full', ''); + } + components.$tHeadGroup.show(); + } else { + components.$tHeadGroup.hide(); + var trH = { lg: 50, sm: 30, md: 38 }; + components.$tBodyGroup.append([ + '' + ].join('')); + components.$tBody.html(colgroupHtml + headHtml + ''); + } + form.render('checkbox', tbFilter); // 渲染表头的表单元素 + + // 默认隐藏列修正colspan + function patchHide($tr) { + var parentKey = $tr.data('parent'), pCol; + if (!parentKey) return; + var $parent = components.$table.children('thead').children('tr').children('[data-key="' + parentKey + '"]'); + var colspan = $parent.attr('colspan') - 1; + $parent.attr('colspan', colspan); + if (colspan === 0) $parent.addClass('layui-hide'); + patchHide($parent); + } + + components.$table.children('thead').children('tr').children('th.layui-hide').each(function () { + patchHide($(this)); + }); + + // 渲染数据 + if (options.reqData) { // 异步加载 + this.options.data = undefined; + this.renderBodyAsync(); + } else if (options.data && options.data.length > 0) { + this.renderBodyData(options.data); + } else { + components.$loading.hide(); + components.$empty.show(); + } + }; + + /** 绑定各项事件 */ + TreeTable.prototype.bindEvents = function () { + var that = this; + var options = this.options; + var components = this.getComponents(); + var $allBody = components.$table.children('tbody'); + + /* 行事件公共返回对象 */ + var member = function (ext) { + // 获取行dom + var $tr = $(this); + if (!$tr.is('tr')) { + var $temp = $tr.parent('tr'); + if ($temp.length > 0) $tr = $temp; + else $tr = $tr.parentsUntil('tr').last().parent(); + } + var data = that.getDataByTr($tr); // 行对应数据 + var obj = { + tr: $tr, + data: data, + del: function () { // 删除行 + var index = $tr.data('index'); + var indent = parseInt($tr.data('indent')); + // 删除子级 + $tr.nextAll('tr').each(function () { + if (parseInt($(this).data('indent')) <= indent) return false; + $(this).remove(); + }); + // 更新后面同辈的index + var indexLength = (typeof index === 'number' ? 1 : index.split('-').length); + $tr.nextAll('tr').each(function () { + var $this = $(this); + if (parseInt($this.data('indent')) < indent) return false; + var _index = $this.data('index').toString().split('-'); + _index[indexLength - 1] = parseInt(_index[indexLength - 1]) - 1; + $this.data('index', _index.join('-')); + }); + // 删除当前行 + var $pTr = $tr.prevAll('tr'); + that.del(undefined, index); + $tr.remove(); + that.renderNumberCol(); // 渲染序号列 + // 联动父级多选框 + $pTr.each(function () { + var tInd = parseInt($(this).data('indent')); + if (tInd >= indent) return true; + that.checkParentCB($(this)); + indent = tInd; + }); + that.checkChooseAllCB(); // 联动全选框 + if (options.data.length === 0) components.$empty.show(); + updateFixedTbHead(components.$view); // 更新滚动条补丁 + }, + update: function (fields) { // 修改行 + data = $.extend(true, data, fields); + var indent = parseInt($tr.data('indent')); + that.renderBodyTr(data, indent, undefined, $tr); // 更新界面 + form.render(null, components.filter); // 渲染表单元素 + that.renderNumberCol(); // 渲染序号列 + // 联动父级多选框 + $tr.prevAll('tr').each(function () { + var tInd = parseInt($(this).data('indent')); + if (tInd >= indent) return true; + that.checkParentCB($(this)); + indent = tInd; + }); + that.checkChooseAllCB(); // 联动全选框 + } + }; + return $.extend(obj, ext); + }; + + // 绑定折叠展开事件 + $allBody.off('click.fold').on('click.fold', '.ew-tree-pack', function (e) { + layui.stope(e); + var $tr = $(this).parentsUntil('tr').last().parent(); + if ($tr.hasClass('ew-tree-table-loading')) return; // 已是加载中 + var haveChild = $tr.data('have-child'); + if (haveChild !== true && haveChild !== 'true') return; // 子节点 + var open = $tr.hasClass('ew-tree-table-open'); + var data = that.getDataByTr($tr); + if (!open && !data[options.tree.childName]) { + that.renderBodyAsync(data, $tr); + } else { + data[options.tree.openName] = toggleRow($tr); + } + }); + + // 绑定lay-event事件 + $allBody.off('click.tool').on('click.tool', '*[lay-event]', function (e) { + layui.stope(e); + var $this = $(this); + layui.event.call(this, MOD_NAME, 'tool(' + components.filter + ')', member.call(this, { + event: $this.attr('lay-event') + })); + }); + + // 绑定单选框事件 + form.on('radio(' + components.radioFilter + ')', function (data) { + var d = that.getDataByTr($(data.elem).parentsUntil('tr').last().parent()); + that.removeAllChecked(); + d.LAY_CHECKED = true; // 同时更新数据 + d.LAY_INDETERMINATE = false; + layui.event.call(this, MOD_NAME, 'radio(' + components.filter + ')', + { checked: true, data: d, type: 'one' }); + }); + + // 绑定复选框事件 + form.on('checkbox(' + components.checkboxFilter + ')', function (data) { + var checked = data.elem.checked; + var $cb = $(data.elem); + var $layCb = $cb.next('.layui-form-checkbox'); + // 如果是半选状态,点击全选 + if (!checked && $cb.hasClass('ew-form-indeterminate')) { + checked = true; + $cb.prop('checked', checked); + $layCb.addClass('layui-form-checked'); + $cb.removeClass('ew-form-indeterminate'); + } + var $tr = $cb.parentsUntil('tr').last().parent(); + var d = that.getDataByTr($tr); + d.LAY_CHECKED = checked; // 同时更新数据 + d.LAY_INDETERMINATE = false; + // 联动操作 + if (options.checkOther) { + if (d[options.tree.childName] && d[options.tree.childName].length > 0) { + that.checkSubCB($tr, checked); // 联动子级 + } + var indent = parseInt($tr.data('indent')); + $tr.prevAll('tr').each(function () { + var tInd = parseInt($(this).data('indent')); + if (tInd < indent) { + that.checkParentCB($(this)); // 联动父级 + indent = tInd; + } + }); + } + that.checkChooseAllCB(); // 联动全选框 + // 回调事件 + layui.event.call(this, MOD_NAME, 'checkbox(' + components.filter + ')', + { checked: checked, data: d, type: 'more' }); + }); + + // 绑定全选复选框事件 + form.on('checkbox(' + components.chooseAllFilter + ')', function (data) { + var checked = data.elem.checked; + var $cb = $(data.elem); + var $layCb = $cb.next('.layui-form-checkbox'); + if (!options.data || options.data.length === 0) { // 如果数据为空 + $cb.prop('checked', false); + $layCb.removeClass('layui-form-checked'); + $cb.removeClass('ew-form-indeterminate'); + return; + } + // 如果是半选状态,点击全选 + if (!checked && $cb.hasClass('ew-form-indeterminate')) { + checked = true; + $cb.prop('checked', checked); + $layCb.addClass('layui-form-checked'); + $cb.removeClass('ew-form-indeterminate'); + } + layui.event.call(this, MOD_NAME, 'checkbox(' + components.filter + ')', { checked: checked, type: 'all' }); + that.checkSubCB(components.$tBody.children('tbody'), checked); // 联动操作 + }); + + // 绑定行单击事件 + $allBody.off('click.row').on('click.row', 'tr', function () { + layui.event.call(this, MOD_NAME, 'row(' + components.filter + ')', member.call(this, {})); + }); + + // 绑定行双击事件 + $allBody.off('dblclick.rowDouble').on('dblclick.rowDouble', 'tr', function () { + layui.event.call(this, MOD_NAME, 'rowDouble(' + components.filter + ')', member.call(this, {})); + }); + + // 绑定单元格点击事件 + $allBody.off('click.cell').on('click.cell', 'td', function (e) { + var $td = $(this); + var type = $td.data('type'); + // 判断是否是复选框、单选框列 + if (type === 'checkbox' || type === 'radio') return layui.stope(e); + var edit = $td.data('edit'); + var field = $td.data('field'); + if (edit) { // 开启了单元格编辑 + layui.stope(e); + if ($allBody.find('.ew-tree-table-edit').length > 0) return; + var index = $td.data('index'); + var indent = $td.find('.ew-tree-table-indent').length; + var d = that.getDataByTr($td.parent()); + if ('text' === edit || 'number' === edit) { // 文本框 + var $input = $(''); + $input[0].value = d[field]; + $td.append($input); + $input.focus(); + $input.blur(function () { + var value = $(this).val(); + if (value == d[field]) return $(this).remove(); + var rs = layui.event.call(this, MOD_NAME, 'edit(' + components.filter + ')', member.call(this, + { value: value, field: field })); + if (rs === false) { + $(this).addClass('layui-form-danger'); + $(this).focus(); + } else { + d[field] = value; // 同步更新数据 + var keys = $td.data('key').split('-'); + that.renderBodyTd(d, indent, index, $td, options.cols[keys[0]][keys[1]]); // 更新单元格 + } + }); + } else { + console.error('不支持的单元格编辑类型:' + edit); + } + } else { // 回调单元格点击事件 + var rs = layui.event.call(this, MOD_NAME, 'cell(' + components.filter + ')', member.call(this, + { td: $td, field: field })); + if (rs === false) layui.stope(e); + } + }); + + // 绑定单元格双击事件 + $allBody.off('dblclick.cellDouble').on('dblclick.cellDouble', 'td', function (e) { + var $td = $(this); + var type = $td.data('type'); + // 判断是否是复选框、单选框列 + if (type === 'checkbox' || type === 'radio') return layui.stope(e); + var edit = $td.data('edit'); + var field = $td.data('field'); + if (edit) return layui.stope(e); // 开启了单元格编辑 + // 回调单元格双击事件 + var rs = layui.event.call(this, MOD_NAME, 'cellDouble(' + components.filter + ')', member.call(this, + { td: $td, field: field })); + if (rs === false) layui.stope(e); + }); + + // 绑定头部工具栏事件 + components.$toolbar.off('click.toolbar').on('click.toolbar', '*[lay-event]', function (e) { + layui.stope(e); + var $this = $(this); + var event = $this.attr('lay-event'); + if ('LAYTABLE_COLS' === event) that.toggleCol(); + else if ('LAYTABLE_EXPORT' === event) that.exportData('show'); + else if ('LAYTABLE_PRINT' === event) that.printTable(); + else layui.event.call(this, MOD_NAME, 'toolbar(' + components.filter + ')', { event: event, elem: $this }); + }); + + // 同步滚动条 + components.$tBodyGroup.on('scroll', function () { + var $this = $(this); + components.$tHeadGroup.scrollLeft($this.scrollLeft()); + }); + + // 导出数据 + components.$toolbar.off('click.export').on('click.export', '.layui-table-tool-panel>[data-type]', function () { + var type = $(this).data('type'); + if ('csv' === type || 'xls' === type) that.exportData(type); + }); + components.$toolbar.off('click.panel').on('click.panel', '.layui-table-tool-panel', function (e) { + layui.stope(e); + }); + + // 筛选列 + form.on('checkbox(' + components.colsToggleFilter + ')', function (data) { + that.toggleCol(data.elem.checked, undefined, data.value); + }); + + }; + + /** 获取各个组件 */ + TreeTable.prototype.getComponents = function () { + var $view = $(this.options.elem).next('.ew-tree-table'); // 容器 + var filter = $view.attr('lay-filter'); // 容器filter + var $tHeadGroup = $view.children('.ew-tree-table-head'); // 表头部分容器 + var $tBodyGroup = $view.children('.ew-tree-table-box'); // 主体部分容器 + return { + $view: $view, + filter: filter, + $tHeadGroup: $tHeadGroup, + $tBodyGroup: $tBodyGroup, + $tHead: $tHeadGroup.children('.layui-table'), // 表头表格 + $tBody: $tBodyGroup.children('.layui-table'), // 主体表格 + $table: $view.find('.layui-table'), // 所有表格 + $toolbar: $view.children('.ew-tree-table-tool'), // 头部工具栏 + $empty: $tBodyGroup.children('.ew-tree-table-empty'), // 空视图 + $loading: $tBodyGroup.children('.ew-tree-table-loading'), // 加载视图 + checkboxFilter: 'ew_tb_checkbox_' + filter, // 复选框filter + radioFilter: 'ew_tb_radio_' + filter, // 单选框filter + chooseAllFilter: 'ew_tb_choose_all_' + filter, // 全选按钮filter + colsToggleFilter: 'ew_tb_toggle_cols' + filter // 筛选列的filter + }; + }; + + /** + * 遍历表头 + * @param callback + * @param obj + */ + TreeTable.prototype.eachCols = function (callback, obj) { + if (!obj) obj = this.options.colArrays; + for (var i = 0; i < obj.length; i++) { + var item = obj[i]; + callback && callback(i, item); + if (item.CHILD_COLS) this.eachCols(callback, item.CHILD_COLS); + } + }; + + /** + * 遍历数据 + * @param callback + * @param data + */ + TreeTable.prototype.eachData = function (callback, data) { + if (!data) data = this.options.data; + for (var i = 0; i < data.length; i++) { + var item = data[i]; + callback && callback(i, item); + if (item[this.options.tree.childName]) this.eachData(callback, item[this.options.tree.childName]); + } + }; + + /** + * 异步加载渲染 + * @param d 父级数据 + * @param $tr 父级dom + */ + TreeTable.prototype.renderBodyAsync = function (d, $tr) { + var that = this; + var options = this.options; + var components = this.getComponents(); + // 显示loading + if ($tr) { + $tr.addClass('ew-tree-table-loading'); + $tr.find('.ew-tree-pack').children('.ew-tree-table-arrow').addClass('layui-anim layui-anim-rotate layui-anim-loop'); + } else { + components.$empty.hide(); + if (options.data && options.data.length > 0) components.$loading.addClass('ew-loading-float'); + components.$loading.show(); + } + // 请求数据 + options.reqData(d, function (data) { + if (typeof data !== 'string' && data && data.length > 0 && options.tree.isPidData) { + data = tt.pidToChildren(data, options.tree.idName, options.tree.pidName, options.tree.childName); + } + that.renderBodyData(data, d, $tr); // 渲染内容 + }); + }; + + /** + * 根据数据渲染body + * @param data 数据集合 + * @param d 父级数据 + * @param $tr 父级dom + */ + TreeTable.prototype.renderBodyData = function (data, d, $tr) { + var msg; + if (typeof data === 'string') { + msg = data; + data = []; + } + var that = this; + var options = this.options; + var components = this.getComponents(); + // 更新到数据 + if (d === undefined) options.data = data; + else d[options.tree.childName] = data; + var indent; + if ($tr) { + indent = parseInt($tr.data('indent')) + 1; + d[options.tree.openName] = true; + } + var htmlStr = this.renderBody(data, indent, d); + if ($tr) { + // 移除旧dom + $tr.nextAll('tr').each(function () { + if (parseInt($(this).data('indent')) <= (indent - 1)) return false; + $(this).remove(); + }); + // 渲染新dom + $tr.after(htmlStr).addClass('ew-tree-table-open'); + } else { + components.$tBody.children('tbody').html(htmlStr); + } + form.render(null, components.filter); // 渲染表单元素 + this.renderNumberCol(); // 渲染序号列 + if ($tr) { + // 更新父级复选框状态 + this.checkParentCB($tr); + $tr.prevAll('tr').each(function () { + var tInd = parseInt($(this).data('indent')); + if (tInd < (indent - 1)) { + that.checkParentCB($(this)); + indent = tInd + 1; + } + }); + // 移除loading + $tr.removeClass('ew-tree-table-loading'); + var $arrow = $tr.find('.ew-tree-pack').children('.ew-tree-table-arrow'); + $arrow.removeClass('layui-anim layui-anim-rotate layui-anim-loop'); + if (msg) { // 加载失败 + $tr.removeClass('ew-tree-table-open'); + } else if (data && data.length === 0) { // 无子集 + d[options.tree.haveChildName] = !!options.tree.haveChildReverse; + $tr.data('have-child', false); + $arrow.addClass('ew-tree-table-arrow-hide'); + $arrow.next('.ew-tree-icon').after(options.tree.getIcon(d)).remove(); + } + } else { + // 移除loading + components.$loading.hide(); + components.$loading.removeClass('ew-loading-float'); + // 显示空视图 + if (data && data.length > 0) { + components.$empty.hide(); + } else { + components.$empty.show(); + if (msg) components.$empty.text(msg); + else components.$empty.html(options.text.none); + } + } + this.checkChooseAllCB(); // 联动全选框 + updateFixedTbHead(components.$view); // 滚动条补丁 + options.done && options.done(data); + }; + + /** + * 递归渲染表格主体部分 + * @param data 数据列表 + * @param indent 缩进大小 + * @param parent 父级 + * @param h 父级是否隐藏 + * @returns {string} + */ + TreeTable.prototype.renderBody = function (data, indent, parent, h) { + var options = this.options; + if (!indent) indent = 0; + var html = ''; + if (!data || data.length === 0) return html; + var hide = parent ? !parent[options.tree.openName] : undefined; + if (h) hide = h;//当所有父级存在隐藏时,隐藏所有子集 + for (var i = 0; i < data.length; i++) { + var d = data[i]; + d.LAY_NUM = (parent ? parent.LAY_NUM + '-' : '') + i; + html += this.renderBodyTr(d, indent, hide); + // 递归渲染子集 + html += this.renderBody(d[options.tree.childName], indent + 1, d, h); + } + return html; + }; + + /** + * 渲染每一行数据 + * @param d 行数据 + * @param indent 缩进大小 + * @param hide 是否隐藏 + * @param $tr + * @returns {string} + */ + TreeTable.prototype.renderBodyTr = function (d, indent, hide, $tr) { + var that = this; + var options = this.options; + if (!indent) indent = 0; + var haveChild = d[options.tree.haveChildName]; + if (options.tree.haveChildReverse) haveChild = !haveChild; + if (haveChild === undefined) haveChild = d[options.tree.childName] && d[options.tree.childName].length > 0; + if ($tr) { + $tr.data('have-child', haveChild ? 'true' : 'false'); + $tr.data('indent', indent); + $tr.removeClass('ew-tree-table-loading'); + } + var html = ''); + var index = 0; + this.eachCols(function (i, col) { + if (col.colGroup) return; + html += that.renderBodyTd(d, indent, index, $tr ? $tr.children('td').eq(index) : undefined, col); + index++; + }); + html += ''; + return html; + }; + + /** + * 渲染每一个单元格数据 + * @param d 行数据 + * @param indent 缩进大小 + * @param index 第几列 + * @param $td + * @param col + * @returns {string} + */ + TreeTable.prototype.renderBodyTd = function (d, indent, index, $td, col) { + if (!col || col.colGroup) return ''; + var options = this.options; + var components = this.getComponents(); + if (!indent) indent = 0; + // 内容填充 + var content = '', cell = '', icon = ''; + if (col.type === 'numbers') { // 序号列 + content = ''; + } else if (col.type === 'checkbox') { // 复选框列 + content = [ + '' + ].join(''); + } else if (col.type === 'radio') { // 单选框列 + content = [ + '' + ].join(''); + } else if (col.templet) { // 自定义模板 + if (typeof col.templet === 'function') { + content = col.templet(d); + } else if (typeof col.templet === 'string') { + laytpl($(col.templet).html()).render(d, function (html) { + content = html; + }); + } + } else if (col.toolbar) { // 操作列 + if (typeof col.toolbar === 'function') { + content = col.toolbar(d); + } else if (typeof col.toolbar === 'string') { + laytpl($(col.toolbar).html()).render(d, function (html) { + content = html; + }); + } + } else if (col.field && d[col.field] !== undefined && d[col.field] !== null) { // 普通字段 + content = util.escape(d[col.field] === 0 ? '0' : d[col.field]); + } + // 图标列处理 + if (index === options.tree.iconIndex) { + // 缩进 + for (var i = 0; i < indent; i++) icon += ''; + icon += ''; + // 加箭头 + var haveChild = d[options.tree.haveChildName]; + if (options.tree.haveChildReverse) haveChild = !haveChild; + if (haveChild === undefined) haveChild = d[options.tree.childName] && d[options.tree.childName].length > 0; + icon += (''); + // 加图标 + icon += options.tree.getIcon(d); + content = '' + content + ''; + if (options.tree.onlyIconControl) content = icon + '' + content; + else content = icon + content + ''; + } + cell = [ + '
                ', + '
                ', content, '
                ', + ' ', + ' ', + '
                ' + ].join(''); + + if ($td) $td.html(cell); + + var html = '' + cell + ''); + return html; + }; + + /** + * 渲染表头 + * @returns {string} + */ + TreeTable.prototype.renderBodyTh = function () { + var options = this.options; + var components = this.getComponents(); + var html = []; + $.each(options.cols, function (i1, item1) { + html.push(''); + $.each(item1, function (i2, item2) { + html.push(''); + html.push('
                '); + html.push('
                '); + // 标题 + var ca = ''; + if (item2.type === 'checkbox') html.push(ca); + else html.push(item2.title || ''); + html.push('
                '); + html.push('
                '); + // 列宽拖拽 + if (!item2.colGroup && !item2.unresize) html.push(''); + html.push(''); + }); + html.push(''); + }); + return html.join(''); + }; + + /** 重置表格尺寸 */ + TreeTable.prototype.resize = function (returnColgroup) { + // 计算表格宽度、最小宽度、百分比宽度 + var options = this.options; + var components = this.getComponents(); + var minWidth = 1, width = 1, needSetWidth = true, mwPercent = 0; + this.eachCols(function (i, item) { + if (item.colGroup || item.hide) return; + if (item.width) { + width += (item.width + 1); + if (item.minWidth) { + if (item.width < item.minWidth) item.width = item.minWidth; + } else if (item.width < options.cellMinWidth) item.width = options.cellMinWidth; + } else needSetWidth = false; + if (item.width) minWidth += (item.width + 1); + else if (item.minWidth) { + minWidth += (item.minWidth + 1); + mwPercent += item.minWidth; + } else { + minWidth += (options.cellMinWidth + 1); + mwPercent += options.cellMinWidth; + } + }); + if (minWidth) { + components.$tHead.css('min-width', minWidth); + components.$tBody.css('min-width', minWidth); + } else { + components.$tHead.css('min-width', 'auto'); + components.$tBody.css('min-width', 'auto'); + } + if (needSetWidth) { + components.$tHead.css('width', width); + components.$tBody.css('width', width); + } else { + components.$tHead.css('width', '100%'); + components.$tBody.css('width', '100%'); + } + + // 生成colgroup + var colgroupHtml = []; + this.eachCols(function (i, item) { + if (item.colGroup || item.hide) return; + colgroupHtml.push(''); + }); + colgroupHtml = colgroupHtml.join(''); + if (returnColgroup) return '' + colgroupHtml + ''; + components.$table.children('colgroup').html(colgroupHtml); + }; + + /** 获取行对应数据 */ + TreeTable.prototype.getDataByTr = function ($tr) { + var data, index; + if (typeof $tr !== 'string' && typeof $tr !== 'number') { + if ($tr) index = $tr.data('index'); + } else index = $tr; + if (index === undefined) return; + if (typeof index === 'number') index = [index]; + else index = index.split('-'); + for (var i = 0; i < index.length; i++) { + if (data) data = data[this.options.tree.childName][index[i]]; + else data = this.options.data[index[i]]; + } + return data; + }; + + /** + * 联动子级复选框状态 + * @param $tr 当前tr的dom + * @param checked + */ + TreeTable.prototype.checkSubCB = function ($tr, checked) { + var that = this; + var components = this.getComponents(); + var indent = -1, $trList; + if ($tr.is('tbody')) { + $trList = $tr.children('tr'); + } else { + indent = parseInt($tr.data('indent')); + $trList = $tr.nextAll('tr'); + } + $trList.each(function () { + if (parseInt($(this).data('indent')) <= indent) return false; + var $cb = $(this).children('td').find('input[lay-filter="' + components.checkboxFilter + '"]'); + $cb.prop('checked', checked); + $cb.removeClass('ew-form-indeterminate'); + if (checked) $cb.next('.layui-form-checkbox').addClass('layui-form-checked'); + else $cb.next('.layui-form-checkbox').removeClass('layui-form-checked'); + var d = that.getDataByTr($(this)); + d.LAY_CHECKED = checked; // 同步更新数据 + d.LAY_INDETERMINATE = false; + }); + }; + + /** + * 联动父级复选框状态 + * @param $tr 父级的dom + */ + TreeTable.prototype.checkParentCB = function ($tr) { + var options = this.options; + var components = this.getComponents(); + var d = this.getDataByTr($tr); + var ckNum = 0, unCkNum = 0; + if (d[options.tree.childName]) { + function checkNum(data) { + for (var i = 0; i < data.length; i++) { + if (data[i].LAY_CHECKED) ckNum++; + else unCkNum++; + if (data[i][options.tree.childName]) checkNum(data[i][options.tree.childName]); + } + } + + checkNum(d[options.tree.childName]); + } + var $cb = $tr.children('td').find('input[lay-filter="' + components.checkboxFilter + '"]'); + if (ckNum > 0 && unCkNum === 0) { // 全选 + $cb.prop('checked', true); + $cb.removeClass('ew-form-indeterminate'); + $cb.next('.layui-form-checkbox').addClass('layui-form-checked'); + d.LAY_CHECKED = true; // 同步更新数据 + d.LAY_INDETERMINATE = false; + } else if (ckNum === 0 && unCkNum > 0) { // 全不选 + $cb.prop('checked', false); + $cb.removeClass('ew-form-indeterminate'); + $cb.next('.layui-form-checkbox').removeClass('layui-form-checked'); + d.LAY_CHECKED = false; // 同步更新数据 + d.LAY_INDETERMINATE = false; + } else if (ckNum > 0 && unCkNum > 0) { // 半选 + $cb.prop('checked', true); + $cb.data('indeterminate', 'true'); + $cb.addClass('ew-form-indeterminate'); + $cb.next('.layui-form-checkbox').addClass('layui-form-checked'); + d.LAY_CHECKED = true; // 同步更新数据 + d.LAY_INDETERMINATE = true; + } + }; + + /** 联动全选复选框 */ + TreeTable.prototype.checkChooseAllCB = function () { + var options = this.options; + var components = this.getComponents(); + var ckNum = 0, unCkNum = 0; + + function checkNum(data) { + for (var i = 0; i < data.length; i++) { + if (data[i].LAY_CHECKED) ckNum++; + else unCkNum++; + if (data[i][options.tree.childName]) checkNum(data[i][options.tree.childName]); + } + } + + checkNum(options.data); + + var $cb = components.$view.find('input[lay-filter="' + components.chooseAllFilter + '"]'); + if (ckNum > 0 && unCkNum === 0) { // 全选 + $cb.prop('checked', true); + $cb.removeClass('ew-form-indeterminate'); + $cb.next('.layui-form-checkbox').addClass('layui-form-checked'); + } else if ((ckNum === 0 && unCkNum > 0) || (ckNum === 0 && unCkNum === 0)) { // 全不选 + $cb.prop('checked', false); + $cb.removeClass('ew-form-indeterminate'); + $cb.next('.layui-form-checkbox').removeClass('layui-form-checked'); + } else if (ckNum > 0 && unCkNum > 0) { // 半选 + $cb.prop('checked', true); + $cb.addClass('ew-form-indeterminate'); + $cb.next('.layui-form-checkbox').addClass('layui-form-checked'); + } + }; + + /** 填充序号列 */ + TreeTable.prototype.renderNumberCol = function () { + this.getComponents().$tBody.children('tbody').children('tr').each(function (i) { + $(this).children('td').find('.ew-tree-table-numbers').text(i + 1); + }); + }; + + /** 根据id获取tr的index */ + TreeTable.prototype.getIndexById = function (id) { + var options = this.options; + + function each(data, pi) { + for (var i = 0; i < data.length; i++) { + if (data[i][options.tree.idName] == id) return pi !== undefined ? pi + '-' + i : i; + if (data[i][options.tree.idName] == id) { + if (data[i][options.tree.childName]) + return each(data[i][options.tree.childName], pi !== undefined ? pi + '-' + i : i); + } + if (each(data[i][options.tree.childName], pi !== undefined ? pi + '-' + i : i)) { + return each(data[i][options.tree.childName], pi !== undefined ? pi + '-' + i : i) + } + } + } + + return each(options.data); + }; + + /** 展开指定行 */ + TreeTable.prototype.expand = function (id, cascade) { + var components = this.getComponents(); + var $tr = components.$table.children('tbody').children('tr[data-index="' + this.getIndexById(id) + '"]'); + if (!$tr.hasClass('ew-tree-table-open')) $tr.children('td').find('.ew-tree-pack').trigger('click'); + if (cascade === false) return; + // 联动父级 + var indent = parseInt($tr.data('indent')); + $tr.prevAll('tr').each(function () { + var tInd = parseInt($(this).data('indent')); + if (tInd < indent) { + if (!$(this).hasClass('ew-tree-table-open')) { + $(this).children('td').find('.ew-tree-pack').trigger('click'); + } + indent = tInd; + } + }); + }; + + /** 折叠指定行 */ + TreeTable.prototype.fold = function (id) { + var components = this.getComponents(); + var $tr = components.$table.children('tbody').children('tr[data-index="' + this.getIndexById(id) + '"]'); + if ($tr.hasClass('ew-tree-table-open')) $tr.children('td').find('.ew-tree-pack').trigger('click'); + }; + + /** 全部展开 */ + TreeTable.prototype.expandAll = function () { + this.getComponents().$table.children('tbody').children('tr').each(function () { + if (!$(this).hasClass('ew-tree-table-open')) $(this).children('td').find('.ew-tree-pack').trigger('click'); + }); + }; + + /** 全部折叠 */ + TreeTable.prototype.foldAll = function () { + this.getComponents().$table.children('tbody').children('tr').each(function () { + if ($(this).hasClass('ew-tree-table-open')) $(this).children('td').find('.ew-tree-pack').trigger('click'); + }); + }; + + /** 获取当前数据 */ + TreeTable.prototype.getData = function () { + return this.options.data; + }; + + /** 重载表格 */ + TreeTable.prototype.reload = function (opt) { + this.initOptions(this.options ? $.extend(true, this.options, opt) : opt); + this.init(); // 初始化表格 + this.bindEvents(); // 绑定事件 + }; + + /** 获取当前选中行 */ + TreeTable.prototype.checkStatus = function (needIndeterminate) { + if (needIndeterminate === undefined) needIndeterminate = true; + var list = []; + this.eachData(function (i, item) { + if ((needIndeterminate || !item.LAY_INDETERMINATE) && item.LAY_CHECKED) + list.push($.extend({ isIndeterminate: item.LAY_INDETERMINATE }, item)); + }); + return list; + }; + + /** 设置复/单选框选中 */ + TreeTable.prototype.setChecked = function (ids) { + var that = this; + var components = this.getComponents(); + var $radio = components.$table.find('input[lay-filter="' + components.radioFilter + '"]'); + if ($radio.length > 0) { // 开启了单选框 + $radio.each(function () { + var d = that.getDataByTr($(this).parentsUntil('tr').parent()); + if (d && ids[ids.length - 1] == d[that.options.tree.idName]) { + $(this).next('.layui-form-radio').trigger('click'); + return false; + } + }); + } else { // 开启了复选框 + components.$table.find('input[lay-filter="' + components.checkboxFilter + '"]').each(function () { + var $cb = $(this); + var $layCb = $cb.next('.layui-form-checkbox'); + var checked = $cb.prop('checked'); + var indeterminate = $cb.hasClass('ew-form-indeterminate'); + var d = that.getDataByTr($cb.parentsUntil('tr').parent()); + for (var i = 0; i < ids.length; i++) { + if (d && ids[i] == d[that.options.tree.idName]) { + if (d[that.options.tree.childName] && d[that.options.tree.childName].length > 0) continue; + if (!checked || indeterminate) $layCb.trigger('click'); + } + } + }); + } + }; + + /** 移除全部选中 */ + TreeTable.prototype.removeAllChecked = function () { + this.checkSubCB(this.getComponents().$table.children('tbody'), false); + }; + + /** 导出 */ + TreeTable.prototype.exportData = function (type) { + var components = this.getComponents(); + if ('show' === type) { + components.$toolbar.find('.layui-table-tool-panel').remove(); + components.$toolbar.find('[lay-event="LAYTABLE_EXPORT"]').append([ + '
                  ', + '
                • 导出到 Csv 文件
                • ', + '
                • 导出到 Excel 文件
                • ', + '
                ' + ].join('')); + } else { + if (device.ie) return layer.msg('不支持ie导出'); + if (!type) type = 'xls'; + var head = [], body = []; + this.eachCols(function (i, item) { + if (item.type !== 'normal' || item.hide) return; + head.push(item.title || ''); + }); + components.$tBody.children('tbody').children('tr').each(function () { + var items = []; + $(this).children('td').each(function () { + var $this = $(this); + if ($this.data('type') !== 'normal' || $this.hasClass('layui-hide')) return true; + items.push($this.text().trim().replace(/,/g, ',')); + }); + body.push(items.join(',')); + }); + // 创建下载文件的a标签 + var alink = document.createElement('a'); + var content = encodeURIComponent(head.join(',') + '\r\n' + body.join('\r\n')); + var contentType = ({ csv: 'text/csv', xls: 'application/vnd.ms-excel' })[type]; + alink.href = 'data:' + contentType + ';charset=utf-8,\ufeff' + content; + alink.download = (this.options.title || 'table') + '.' + type; + document.body.appendChild(alink); + alink.click(); + document.body.removeChild(alink); + } + }; + + /** 打印 */ + TreeTable.prototype.printTable = function () { + var components = this.getComponents(); + var head = components.$tHead.children('thead').html(); + if (!head) head = components.$tBody.children('thead').html(); + var body = components.$tBody.children('tbody').html(); + var colgroup = components.$tBody.children('colgroup').html(); + var $html = $([ + '', + ' ', colgroup, '', + ' ', head, '', + ' ', body, '', + '
                ' + ].join('')); + + // 隐藏特殊列 + $html.find('col[data-type="checkbox"],col[data-type="radio"],col[data-type="tool"]').remove(); + $html.find('td[data-type="checkbox"],td[data-type="radio"],td[data-type="tool"],.layui-hide').remove(); + + function hideCol($temp) { + var parentKey = $temp.data('parent'), pCol; + if (!parentKey) return; + var $parent = $html.children('thead').children('tr').children('[data-key="' + parentKey + '"]'); + var colspan = parseInt($parent.attr('colspan')) - 1; + $parent.attr('colspan', colspan); + if (colspan === 0) $parent.remove(); + hideCol($parent); + } + + $html.find('th[data-type="checkbox"],th[data-type="radio"],th[data-type="tool"]').each(function () { + hideCol($(this)); + }).remove(); + + // 打印内容样式 + var style = [ + '' + ].join(''); + var pWindow = window.open('', '_blank'); + pWindow.focus(); + var pDocument = pWindow.document; + pDocument.open(); + pDocument.write($html[0].outerHTML + style); + pDocument.close(); + pWindow.print(); + pWindow.close(); + }; + + /** 筛选列 */ + TreeTable.prototype.toggleCol = function (show, field, key) { + var components = this.getComponents(); + if (show === undefined) { + components.$toolbar.find('.layui-table-tool-panel').remove(); + var cols = ['
                  ']; + this.eachCols(function (i, item) { + if (item.type !== 'normal') return; + cols.push('
                • '); + }); + components.$toolbar.find('[lay-event="LAYTABLE_COLS"]').append(cols.join('') + '
                '); + form.render('checkbox', components.filter); + } else { + if (key) { + var $td = components.$table.children('tbody').children('tr').children('[data-key="' + key + '"]'); + var $th = components.$table.children('thead').children('tr').children('[data-key="' + key + '"]'); + if (show) { + $td.removeClass('layui-hide'); + $th.removeClass('layui-hide'); + } else { + $td.addClass('layui-hide'); + $th.addClass('layui-hide'); + } + // 同步更新数据 + var ks = key.split('-'); + var col = this.options.cols[ks[0]][ks[1]]; + col.hide = !show; + + // 更新colspan数据 + function changeParent($temp) { + var parentKey = $temp.data('parent'), pCol; + if (!parentKey) return; + var $parent = components.$table.children('thead').children('tr').children('[data-key="' + parentKey + '"]'); + var colspan = $parent.attr('colspan'); + show ? colspan++ : colspan--; + $parent.attr('colspan', colspan); + if (colspan === 0) $parent.addClass('layui-hide'); + else $parent.removeClass('layui-hide'); + changeParent($parent); + } + + changeParent($th); + + // 同步eachCols数据 + this.eachCols(function (i, item) { + if (item.key === key) item.hide = col.hide; + }); + this.resize(); // 更新表格尺寸 + } + } + }; + + /** + * 搜索数据 + * @param ids 关键字或数据id集合 + */ + TreeTable.prototype.filterData = function (ids) { + var components = this.getComponents(); + components.$loading.show(); + if (this.options.data.length > 0) components.$loading.addClass('ew-loading-float'); + var $trList = components.$table.children('tbody').children('tr'); + var indexList = []; + if (typeof ids === 'string') { // 关键字 + $trList.each(function () { + var index = $(this).data('index'); + $(this).children('td').each(function () { + if ($(this).text().indexOf(ids) !== -1) { + indexList.push(index); + return false; + } + }); + }); + } else { + for (var i = 0; i < ids.length; i++) { + indexList.push(this.getIndexById(ids[i])); + } + } + $trList.addClass('ew-tree-table-filter-hide'); + for (var j = 0; j < indexList.length; j++) { + var $tr = $trList.filter('[data-index="' + indexList[j] + '"]'); + $tr.removeClass('ew-tree-table-filter-hide'); + var indent = parseInt($tr.data('indent')); + // 联动子级 + $tr.nextAll('tr').each(function () { + if (parseInt($(this).data('indent')) <= indent) return false; + $(this).removeClass('ew-tree-table-filter-hide'); + }); + if ($tr.hasClass('ew-tree-table-open')) toggleRow($tr); + // 联动父级 + $tr.prevAll('tr').each(function () { + var tInd = parseInt($(this).data('indent')); + if (tInd < indent) { + $(this).removeClass('ew-tree-table-filter-hide'); + if (!$(this).hasClass('ew-tree-table-open')) toggleRow($(this)); + indent = tInd; + } + }); + } + // 最后再检查一遍 + /*$trList.not('.ew-tree-table-filter-hide').not('.ew-tree-tb-hide').each(function () { + var index = $(this).data('index'), hide = true; + for (var k = 0; k < indexList.length; k++) { + if (indexList[k] === index) hide = false; + } + if (hide) $(this).addClass('ew-tree-table-filter-hide'); + });*/ + components.$loading.hide(); + components.$loading.removeClass('ew-loading-float'); + if (indexList.length === 0) components.$empty.show(); + updateFixedTbHead(components.$view); // 更新滚动条补丁 + }; + + /** 重置搜索 */ + TreeTable.prototype.clearFilter = function () { + var components = this.getComponents(); + components.$table.children('tbody').children('tr').removeClass('ew-tree-table-filter-hide'); + if (this.options.data.length > 0) components.$empty.hide(); + updateFixedTbHead(components.$view); // 更新滚动条补丁 + }; + + /** + * 刷新指定父级下的节点 + * @param id 父级id,空则全部刷新 + * @param data 非异步模式替换的数据 + */ + TreeTable.prototype.refresh = function (id, data) { + if (isClass(id) === 'Array') { + data = id; + id = undefined; + } + var components = this.getComponents(); + var d, $tr; + if (id !== undefined) { + $tr = components.$table.children('tbody').children('tr[data-index="' + this.getIndexById(id) + '"]'); + d = this.getDataByTr($tr); + } + if (data) { // 数据模式 + if (this.data.length > 0) components.$loading.addClass('ew-loading-float'); + components.$loading.show(); + if (data.length > 0 && this.options.tree.isPidData) { // pid形式数据 + this.renderBodyData(tt.pidToChildren(data, this.options.tree.idName, this.options.tree.pidName, this.options.tree.childName), d, $tr); + } else { + this.renderBodyData(data, d, $tr); + } + } else { // 异步模式 + this.renderBodyAsync(d, $tr); + + } + }; + + /** 删除数据 */ + TreeTable.prototype.del = function (id, index) { + if (index === undefined) index = this.getIndexById(id); + var indexList = (typeof index === 'number' ? [index] : index.split('-')); + var d = this.options.data; + if (indexList.length > 1) { + for (var i = 0; i < indexList.length - 1; i++) { + d = d[parseInt(indexList[i])][this.options.tree.childName]; + } + } + d.splice(indexList[indexList.length - 1], 1); + }; + + /** 更新数据 */ + TreeTable.prototype.update = function (id, fields) { + $.extend(true, this.getDataByTr(this.getIndexById(id)), fields); + }; + + /** 折叠/展开行 */ + function toggleRow($tr) { + var indent = parseInt($tr.data('indent')); + var open = $tr.hasClass('ew-tree-table-open'); + if (open) { // 折叠 + $tr.removeClass('ew-tree-table-open'); + $tr.nextAll('tr').each(function () { + if (parseInt($(this).data('indent')) <= indent) return false; + $(this).addClass('ew-tree-tb-hide'); + }); + } else { // 展开 + $tr.addClass('ew-tree-table-open'); + var hideInd; + $tr.nextAll('tr').each(function () { + var ind = parseInt($(this).data('indent')); + if (ind <= indent) return false; + if (hideInd !== undefined && ind > hideInd) return true; + $(this).removeClass('ew-tree-tb-hide'); + if (!$(this).hasClass('ew-tree-table-open')) hideInd = parseInt($(this).data('indent')); + else hideInd = undefined; + }); + } + updateFixedTbHead($tr.parentsUntil('.ew-tree-table').last().parent()); + return open; + } + + /** 固定表头滚动条补丁 */ + function updateFixedTbHead($view) { + var $headBox = $view.children('.ew-tree-table-head'); + var $tbBox = $view.children('.ew-tree-table-box'); + //修复滚动条出现时,表头宽度不对的问题 + var sWidth = $headBox.width() - $tbBox.prop('clientWidth'); + $headBox.css('border-right', (sWidth > 0 ? sWidth : 0) + 'px solid #f2f2f2'); + } + + // 监听窗口大小改变 + $(window).resize(function () { + $('.ew-tree-table').each(function () { + updateFixedTbHead($(this)); + var $tbBox = $(this).children('.ew-tree-table-box'); + var full = $tbBox.data('full'); + if (full && device.ie && device.ie < 10) { + $tbBox.css('height', getPageHeight() - full); + } + }); + }); + + /** 表格溢出点击展开功能 */ + $(document).on('mouseenter', '.ew-tree-table-cell.single-line', function () { + var $content = $(this).children('.ew-tree-table-cell-content'); + if ($content.prop('scrollWidth') > $content.outerWidth()) $(this).children('.layui-table-grid-down').show(); + }).on('mouseleave', '.ew-tree-table-cell.single-line', function () { + $(this).children('.layui-table-grid-down').hide(); + }); + // 点击箭头展开 + $(document).on('click', '.ew-tree-table-cell>.layui-table-grid-down', function (e) { + e.stopPropagation(); + hideAllTdTips(); + var $cell = $(this).parent(); + $cell.addClass('ew-tree-tips-open'); + $cell.children('.layui-table-grid-down').hide(); + var tw = $cell.parent().outerWidth() + 4; + if ($cell.outerWidth() < tw) $cell.children('.ew-tree-table-cell-content').css({ 'width': tw, 'max-width': tw }); + var $box = $cell.parents().filter('.ew-tree-table-box'); + if ($box.length === 0) $box = $cell.parents().filter('.ew-tree-table-head'); + if ($box.length === 0) return; + if (($cell.outerWidth() + $cell.offset().left) + 20 > $box.offset().left + $box.outerWidth()) { + $cell.addClass('ew-show-left'); + } + if (($cell.outerHeight() + $cell.offset().top + 10) > $box.offset().top + $box.outerHeight()) { + $cell.addClass('ew-show-bottom'); + } + }); + // 点击关闭按钮关闭 + $(document).on('click', '.ew-tree-table-cell>.ew-tree-tips-c', function () { + hideAllTdTips(); + }); + // 点击空白部分关闭 + $(document).on('click', function () { + hideAllTdTips(); + $('.ew-tree-table .layui-table-tool-panel').remove(); + }); + $(document).on('click', '.ew-tree-table-cell.ew-tree-tips-open', function (e) { + e.stopPropagation(); + }); + + /* 关闭所有单元格溢出提示框 */ + function hideAllTdTips() { + $('.ew-tree-table-cell').removeClass('ew-tree-tips-open ew-show-left ew-show-bottom'); + $('.ew-tree-table-cell>.ew-tree-table-cell-content').css({ 'width': '', 'max-width': '' }); + } + + /** 拖拽调整列宽 */ + $(document).on('mousedown', '.ew-tb-resize', function (e) { + layui.stope(e); + var $this = $(this); + $this.attr('move', 'true'); + var key = $this.parent().data('key'); + $this.data('x', e.clientX); + var w = $this.parent().parent().parent().parent().children('colgroup').children('col[data-key="' + key + '"]').attr('width'); + if (!w || w.toString().indexOf('%') !== -1) w = $this.parent().outerWidth(); + $this.data('width', w); + $('body').addClass('ew-tree-table-resizing'); + }).on('mousemove', function (e) { + var $rs = $('.ew-tree-table .ew-tb-resize[move="true"]'); + if ($rs.length === 0) return; + layui.stope(e); + var x = $rs.data('x'); + var w = $rs.data('width'); + var nw = parseFloat(w) + e.clientX - parseFloat(x); + if (nw <= 0) nw = 1; + // 更新实例options中的宽度 + var ins = _instances[$rs.parentsUntil('.ew-tree-table').last().parent().attr('lay-filter')]; + var key = $rs.parent().data('key'); + var ks = key.split('-'); + ins.options.cols[ks[0]][ks[1]].width = nw; + ins.eachCols(function (i, item) { + if (item.key === key) item.width = nw; + }); + ins.resize(); + }).on('mouseup', function (e) { + $('.ew-tree-table .ew-tb-resize[move="true"]').attr('move', 'false'); + $('body').removeClass('ew-tree-table-resizing'); + }).on('mouseleave', function (e) { + $('.ew-tree-table .ew-tb-resize[move="true"]').attr('move', 'false'); + $('body').removeClass('ew-tree-table-resizing'); + }); + + /** 获取顶级的pId */ + function getPids(data, idName, pidName) { + var pids = []; + for (var i = 0; i < data.length; i++) { + var hasPid = false; + for (var j = 0; j < data.length; j++) { + if (data[i][pidName] == data[j][idName]) { + hasPid = true; + break; + } + } + if (!hasPid) pids.push(data[i][pidName]); + } + return pids; + } + + /** 判断pId是否相等 */ + function pidEquals(pId, pIds) { + if (isClass(pIds) === 'Array') { + for (var i = 0; i < pIds.length; i++) + if (pId == pIds[i]) return true; + } + return pId == pIds; + } + + /** 获取变量类型 */ + function isClass(o) { + if (o === null) return 'Null'; + if (o === undefined) return 'Undefined'; + return Object.prototype.toString.call(o).slice(8, -1); + } + + /** 获取浏览器高度 */ + function getPageHeight() { + return document.documentElement.clientHeight || document.body.clientHeight; + } + + /** 对外提供的方法 */ + var tt = { + /* 渲染 */ + render: function (options) { + return new TreeTable(options); + }, + /* 重载 */ + reload: function (id, opt) { + _instances[id].reload(opt); + }, + /* 事件监听 */ + on: function (events, callback) { + return layui.onevent.call(this, MOD_NAME, events, callback); + }, + /* pid转children形式 */ + pidToChildren: function (data, idName, pidName, childName, pId) { + if (!childName) childName = 'children'; + var newList = []; + for (var i = 0; i < data.length; i++) { + if (data[i][idName] == data[i][pidName]) + return console.error('第' + i + '条数据的' + idName + '与' + pidName + '相同', data[i]); + if (pId === undefined) pId = getPids(data, idName, pidName); + if (pidEquals(data[i][pidName], pId)) { + var children = this.pidToChildren(data, idName, pidName, childName, data[i][idName]); + if (children.length > 0) data[i][childName] = children; + newList.push(data[i]); + } + } + return newList; + } + }; + + /** 添加样式 */ + $('head').append([ + '' + ].join('')); + + exports('treeTablelay', tt); +}); diff --git a/WaterCloud.Web/wwwroot/js/lay-module/wangEditor/fonts/w-e-icon.woff b/WaterCloud.Web/wwwroot/js/lay-module/wangEditor/fonts/w-e-icon.woff new file mode 100644 index 0000000..6dc5b5a Binary files /dev/null and b/WaterCloud.Web/wwwroot/js/lay-module/wangEditor/fonts/w-e-icon.woff differ diff --git a/WaterCloud.Web/wwwroot/js/lay-module/wangEditor/wangEditor.css b/WaterCloud.Web/wwwroot/js/lay-module/wangEditor/wangEditor.css new file mode 100644 index 0000000..5502c55 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/wangEditor/wangEditor.css @@ -0,0 +1,411 @@ +.w-e-toolbar, +.w-e-text-container, +.w-e-menu-panel { + padding: 0; + margin: 0; + box-sizing: border-box; +} +.w-e-toolbar *, +.w-e-text-container *, +.w-e-menu-panel * { + padding: 0; + margin: 0; + box-sizing: border-box; +} +.w-e-clear-fix:after { + content: ""; + display: table; + clear: both; +} + +.w-e-toolbar .w-e-droplist { + position: absolute; + left: 0; + top: 0; + background-color: #fff; + border: 1px solid #f1f1f1; + border-right-color: #ccc; + border-bottom-color: #ccc; +} +.w-e-toolbar .w-e-droplist .w-e-dp-title { + text-align: center; + color: #999; + line-height: 2; + border-bottom: 1px solid #f1f1f1; + font-size: 13px; +} +.w-e-toolbar .w-e-droplist ul.w-e-list { + list-style: none; + line-height: 1; +} +.w-e-toolbar .w-e-droplist ul.w-e-list li.w-e-item { + color: #333; + padding: 5px 0; +} +.w-e-toolbar .w-e-droplist ul.w-e-list li.w-e-item:hover { + background-color: #f1f1f1; +} +.w-e-toolbar .w-e-droplist ul.w-e-block { + list-style: none; + text-align: left; + padding: 5px; +} +.w-e-toolbar .w-e-droplist ul.w-e-block li.w-e-item { + display: inline-block; + *display: inline; + *zoom: 1; + padding: 3px 5px; +} +.w-e-toolbar .w-e-droplist ul.w-e-block li.w-e-item:hover { + background-color: #f1f1f1; +} + +@font-face { + font-family: 'w-e-icon'; + src: url(data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAABhQAAsAAAAAGAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABCAAAAGAAAABgDxIPBGNtYXAAAAFoAAABBAAAAQQrSf4BZ2FzcAAAAmwAAAAIAAAACAAAABBnbHlmAAACdAAAEvAAABLwfpUWUWhlYWQAABVkAAAANgAAADYQp00kaGhlYQAAFZwAAAAkAAAAJAfEA+FobXR4AAAVwAAAAIQAAACEeAcD7GxvY2EAABZEAAAARAAAAERBSEX+bWF4cAAAFogAAAAgAAAAIAAsALZuYW1lAAAWqAAAAYYAAAGGmUoJ+3Bvc3QAABgwAAAAIAAAACAAAwAAAAMD3gGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAA8fwDwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEAOgAAAA2ACAABAAWAAEAIOkG6Q3pEulH6Wbpd+m56bvpxunL6d/qDepc6l/qZepo6nHqefAN8BTxIPHc8fz//f//AAAAAAAg6QbpDekS6UfpZel36bnpu+nG6cvp3+oN6lzqX+pi6mjqcep38A3wFPEg8dzx/P/9//8AAf/jFv4W+Bb0FsAWoxaTFlIWURZHFkMWMBYDFbUVsxWxFa8VpxWiEA8QCQ7+DkMOJAADAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAACAAD/wAQAA8AABAATAAABNwEnAQMuAScTNwEjAQMlATUBBwGAgAHAQP5Anxc7MmOAAYDA/oDAAoABgP6ATgFAQAHAQP5A/p0yOxcBEU4BgP6A/YDAAYDA/oCAAAQAAAAABAADgAAQACEALQA0AAABOAExETgBMSE4ATEROAExITUhIgYVERQWMyEyNjURNCYjBxQGIyImNTQ2MzIWEyE1EwEzNwPA/IADgPyAGiYmGgOAGiYmGoA4KCg4OCgoOED9AOABAEDgA0D9AAMAQCYa/QAaJiYaAwAaJuAoODgoKDg4/biAAYD+wMAAAAIAAABABAADQAA4ADwAAAEmJy4BJyYjIgcOAQcGBwYHDgEHBhUUFx4BFxYXFhceARcWMzI3PgE3Njc2Nz4BNzY1NCcuAScmJwERDQED1TY4OXY8PT8/PTx2OTg2CwcICwMDAwMLCAcLNjg5djw9Pz89PHY5ODYLBwgLAwMDAwsIBwv9qwFA/sADIAgGBggCAgICCAYGCCkqKlktLi8vLi1ZKiopCAYGCAICAgIIBgYIKSoqWS0uLy8uLVkqKin94AGAwMAAAAAAAgDA/8ADQAPAABsAJwAAASIHDgEHBhUUFx4BFxYxMDc+ATc2NTQnLgEnJgMiJjU0NjMyFhUUBgIAQjs6VxkZMjJ4MjIyMngyMhkZVzo7QlBwcFBQcHADwBkZVzo7Qnh9fcxBQUFBzH19eEI7OlcZGf4AcFBQcHBQUHAAAAEAAAAABAADgAArAAABIgcOAQcGBycRISc+ATMyFx4BFxYVFAcOAQcGBxc2Nz4BNzY1NCcuAScmIwIANTIyXCkpI5YBgJA1i1BQRUZpHh4JCSIYGB5VKCAgLQwMKCiLXl1qA4AKCycbHCOW/oCQNDweHmlGRVArKClJICEaYCMrK2I2NjlqXV6LKCgAAQAAAAAEAAOAACoAABMUFx4BFxYXNyYnLgEnJjU0Nz4BNzYzMhYXByERByYnLgEnJiMiBw4BBwYADAwtICAoVR4YGCIJCR4eaUZFUFCLNZABgJYjKSlcMjI1al1eiygoAYA5NjZiKysjYBohIEkpKCtQRUZpHh48NJABgJYjHBsnCwooKIteXQAAAAACAAAAQAQBAwAAJgBNAAATMhceARcWFRQHDgEHBiMiJy4BJyY1JzQ3PgE3NjMVIgYHDgEHPgEhMhceARcWFRQHDgEHBiMiJy4BJyY1JzQ3PgE3NjMVIgYHDgEHPgHhLikpPRESEhE9KSkuLikpPRESASMjelJRXUB1LQkQBwgSAkkuKSk9ERISET0pKS4uKSk9ERIBIyN6UlFdQHUtCRAHCBICABIRPSkpLi4pKT0REhIRPSkpLiBdUVJ6IyOAMC4IEwoCARIRPSkpLi4pKT0REhIRPSkpLiBdUVJ6IyOAMC4IEwoCAQAABgBA/8AEAAPAAAMABwALABEAHQApAAAlIRUhESEVIREhFSEnESM1IzUTFTMVIzU3NSM1MxUVESM1MzUjNTM1IzUBgAKA/YACgP2AAoD9gMBAQECAwICAwMCAgICAgIACAIACAIDA/wDAQP3yMkCSPDJAku7+wEBAQEBAAAYAAP/ABAADwAADAAcACwAXACMALwAAASEVIREhFSERIRUhATQ2MzIWFRQGIyImETQ2MzIWFRQGIyImETQ2MzIWFRQGIyImAYACgP2AAoD9gAKA/YD+gEs1NUtLNTVLSzU1S0s1NUtLNTVLSzU1SwOAgP8AgP8AgANANUtLNTVLS/61NUtLNTVLS/61NUtLNTVLSwADAAAAAAQAA6AAAwANABQAADchFSElFSE1EyEVITUhJQkBIxEjEQAEAPwABAD8AIABAAEAAQD9YAEgASDggEBAwEBAAQCAgMABIP7g/wABAAAAAAACAB7/zAPiA7QAMwBkAAABIiYnJicmNDc2PwE+ATMyFhcWFxYUBwYPAQYiJyY0PwE2NCcuASMiBg8BBhQXFhQHDgEjAyImJyYnJjQ3Nj8BNjIXFhQPAQYUFx4BMzI2PwE2NCcmNDc2MhcWFxYUBwYPAQ4BIwG4ChMIIxISEhIjwCNZMTFZIyMSEhISI1gPLA8PD1gpKRQzHBwzFMApKQ8PCBMKuDFZIyMSEhISI1gPLA8PD1gpKRQzHBwzFMApKQ8PDysQIxISEhIjwCNZMQFECAckLS1eLS0kwCIlJSIkLS1eLS0kVxAQDysPWCl0KRQVFRTAKXQpDysQBwj+iCUiJC0tXi0tJFcQEA8rD1gpdCkUFRUUwCl0KQ8rEA8PJC0tXi0tJMAiJQAAAAAFAAD/wAQAA8AAGwA3AFMAXwBrAAAFMjc+ATc2NTQnLgEnJiMiBw4BBwYVFBceARcWEzIXHgEXFhUUBw4BBwYjIicuAScmNTQ3PgE3NhMyNz4BNzY3BgcOAQcGIyInLgEnJicWFx4BFxYnNDYzMhYVFAYjIiYlNDYzMhYVFAYjIiYCAGpdXosoKCgoi15dampdXosoKCgoi15dalZMTHEgISEgcUxMVlZMTHEgISEgcUxMVisrKlEmJiMFHBtWODc/Pzc4VhscBSMmJlEqK9UlGxslJRsbJQGAJRsbJSUbGyVAKCiLXl1qal1eiygoKCiLXl1qal1eiygoA6AhIHFMTFZWTExxICEhIHFMTFZWTExxICH+CQYGFRAQFEM6OlYYGRkYVjo6QxQQEBUGBvcoODgoKDg4KCg4OCgoODgAAAMAAP/ABAADwAAbADcAQwAAASIHDgEHBhUUFx4BFxYzMjc+ATc2NTQnLgEnJgMiJy4BJyY1NDc+ATc2MzIXHgEXFhUUBw4BBwYTBycHFwcXNxc3JzcCAGpdXosoKCgoi15dampdXosoKCgoi15dalZMTHEgISEgcUxMVlZMTHEgISEgcUxMSqCgYKCgYKCgYKCgA8AoKIteXWpqXV6LKCgoKIteXWpqXV6LKCj8YCEgcUxMVlZMTHEgISEgcUxMVlZMTHEgIQKgoKBgoKBgoKBgoKAAAQBl/8ADmwPAACkAAAEiJiMiBw4BBwYVFBYzLgE1NDY3MAcGAgcGBxUhEzM3IzceATMyNjcOAQMgRGhGcVNUbRobSUgGDWVKEBBLPDxZAT1sxizXNC1VJi5QGB09A7AQHh1hPj9BTTsLJjeZbwN9fv7Fj5AjGQIAgPYJDzdrCQcAAAAAAgAAAAAEAAOAAAkAFwAAJTMHJzMRIzcXIyURJyMRMxUhNTMRIwcRA4CAoKCAgKCggP8AQMCA/oCAwEDAwMACAMDAwP8AgP1AQEACwIABAAADAMAAAANAA4AAFgAfACgAAAE+ATU0Jy4BJyYjIREhMjc+ATc2NTQmATMyFhUUBisBEyMRMzIWFRQGAsQcIBQURi4vNf7AAYA1Ly5GFBRE/oRlKjw8KWafn58sPj4B2yJULzUvLkYUFPyAFBRGLi81RnQBRks1NUv+gAEASzU1SwAAAAACAMAAAANAA4AAHwAjAAABMxEUBw4BBwYjIicuAScmNREzERQWFx4BMzI2Nz4BNQEhFSECwIAZGVc6O0JCOzpXGRmAGxgcSSgoSRwYG/4AAoD9gAOA/mA8NDVOFhcXFk41NDwBoP5gHjgXGBsbGBc4Hv6ggAAAAAABAIAAAAOAA4AACwAAARUjATMVITUzASM1A4CA/sCA/kCAAUCAA4BA/QBAQAMAQAABAAAAAAQAA4AAPQAAARUjHgEVFAYHDgEjIiYnLgE1MxQWMzI2NTQmIyE1IS4BJy4BNTQ2Nz4BMzIWFx4BFSM0JiMiBhUUFjMyFhcEAOsVFjUwLHE+PnEsMDWAck5OcnJO/gABLAIEATA1NTAscT4+cSwwNYByTk5yck47bisBwEAdQSI1YiQhJCQhJGI1NExMNDRMQAEDASRiNTViJCEkJCEkYjU0TEw0NEwhHwAAAAcAAP/ABAADwAADAAcACwAPABMAGwAjAAATMxUjNzMVIyUzFSM3MxUjJTMVIwMTIRMzEyETAQMhAyMDIQMAgIDAwMABAICAwMDAAQCAgBAQ/QAQIBACgBD9QBADABAgEP2AEAHAQEBAQEBAQEBAAkD+QAHA/oABgPwAAYD+gAFA/sAAAAoAAAAABAADgAADAAcACwAPABMAFwAbAB8AIwAnAAATESERATUhFR0BITUBFSE1IxUhNREhFSElIRUhETUhFQEhFSEhNSEVAAQA/YABAP8AAQD/AED/AAEA/wACgAEA/wABAPyAAQD/AAKAAQADgPyAA4D9wMDAQMDAAgDAwMDA/wDAwMABAMDA/sDAwMAAAAUAAAAABAADgAADAAcACwAPABMAABMhFSEVIRUhESEVIREhFSERIRUhAAQA/AACgP2AAoD9gAQA/AAEAPwAA4CAQID/AIABQID/AIAAAAAABQAAAAAEAAOAAAMABwALAA8AEwAAEyEVIRchFSERIRUhAyEVIREhFSEABAD8AMACgP2AAoD9gMAEAPwABAD8AAOAgECA/wCAAUCA/wCAAAAFAAAAAAQAA4AAAwAHAAsADwATAAATIRUhBSEVIREhFSEBIRUhESEVIQAEAPwAAYACgP2AAoD9gP6ABAD8AAQA/AADgIBAgP8AgAFAgP8AgAAAAAABAD8APwLmAuYALAAAJRQPAQYjIi8BBwYjIi8BJjU0PwEnJjU0PwE2MzIfATc2MzIfARYVFA8BFxYVAuYQThAXFxCoqBAXFhBOEBCoqBAQThAWFxCoqBAXFxBOEBCoqBDDFhBOEBCoqBAQThAWFxCoqBAXFxBOEBCoqBAQThAXFxCoqBAXAAAABgAAAAADJQNuABQAKAA8AE0AVQCCAAABERQHBisBIicmNRE0NzY7ATIXFhUzERQHBisBIicmNRE0NzY7ATIXFhcRFAcGKwEiJyY1ETQ3NjsBMhcWExEhERQXFhcWMyEyNzY3NjUBIScmJyMGBwUVFAcGKwERFAcGIyEiJyY1ESMiJyY9ATQ3NjsBNzY3NjsBMhcWHwEzMhcWFQElBgUIJAgFBgYFCCQIBQaSBQUIJQgFBQUFCCUIBQWSBQUIJQgFBQUFCCUIBQVJ/gAEBAUEAgHbAgQEBAT+gAEAGwQGtQYEAfcGBQg3Ghsm/iUmGxs3CAUFBQUIsSgIFxYXtxcWFgkosAgFBgIS/rcIBQUFBQgBSQgFBgYFCP63CAUFBQUIAUkIBQYGBQj+twgFBQUFCAFJCAUGBgX+WwId/eMNCwoFBQUFCgsNAmZDBQICBVUkCAYF/eMwIiMhIi8CIAUGCCQIBQVgFQ8PDw8VYAUFCAACAAcASQO3Aq8AGgAuAAAJAQYjIi8BJjU0PwEnJjU0PwE2MzIXARYVFAcBFRQHBiMhIicmPQE0NzYzITIXFgFO/vYGBwgFHQYG4eEGBh0FCAcGAQoGBgJpBQUI/dsIBQUFBQgCJQgFBQGF/vYGBhwGCAcG4OEGBwcGHQUF/vUFCAcG/vslCAUFBQUIJQgFBQUFAAAAAQAjAAAD3QNuALMAACUiJyYjIgcGIyInJjU0NzY3Njc2NzY9ATQnJiMhIgcGHQEUFxYXFjMWFxYVFAcGIyInJiMiBwYjIicmNTQ3Njc2NzY3Nj0BETQ1NDU0JzQnJicmJyYnJicmIyInJjU0NzYzMhcWMzI3NjMyFxYVFAcGIwYHBgcGHQEUFxYzITI3Nj0BNCcmJyYnJjU0NzYzMhcWMzI3NjMyFxYVFAcGByIHBgcGFREUFxYXFhcyFxYVFAcGIwPBGTMyGhkyMxkNCAcJCg0MERAKEgEHFf5+FgcBFQkSEw4ODAsHBw4bNTUaGDExGA0HBwkJCwwQDwkSAQIBAgMEBAUIEhENDQoLBwcOGjU1GhgwMRgOBwcJCgwNEBAIFAEHDwGQDgcBFAoXFw8OBwcOGTMyGRkxMRkOBwcKCg0NEBEIFBQJEREODQoLBwcOAAICAgIMCw8RCQkBAQMDBQxE4AwFAwMFDNRRDQYBAgEICBIPDA0CAgICDAwOEQgJAQIDAwUNRSEB0AINDQgIDg4KCgsLBwcDBgEBCAgSDwwNAgICAg0MDxEICAECAQYMULYMBwEBBwy2UAwGAQEGBxYPDA0CAgICDQwPEQgIAQECBg1P/eZEDAYCAgEJCBEPDA0AAAIAAP+3A/8DtwATADkAAAEyFxYVFAcCBwYjIicmNTQ3ATYzARYXFh8BFgcGIyInJicmJyY1FhcWFxYXFjMyNzY3Njc2NzY3NjcDmygeHhq+TDdFSDQ0NQFtISn9+BcmJy8BAkxMe0c2NiEhEBEEExQQEBIRCRcIDxITFRUdHR4eKQO3GxooJDP+mUY0NTRJSTABSx/9sSsfHw0oek1MGhsuLzo6RAMPDgsLCgoWJRsaEREKCwQEAgABAAAAAAAA9evv618PPPUACwQAAAAAANbEBFgAAAAA1sQEWAAA/7cEAQPAAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAD//wQBAAEAAAAAAAAAAAAAAAAAAAAhBAAAAAAAAAAAAAAAAgAAAAQAAAAEAAAABAAAAAQAAMAEAAAABAAAAAQAAAAEAABABAAAAAQAAAAEAAAeBAAAAAQAAAAEAABlBAAAAAQAAMAEAADABAAAgAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAMlAD8DJQAAA74ABwQAACMD/wAAAAAAAAAKABQAHgBMAJQA+AE2AXwBwgI2AnQCvgLoA34EHgSIBMoE8gU0BXAFiAXgBiIGagaSBroG5AcoB+AIKgkcCXgAAQAAACEAtAAKAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGljb21vb24AaQBjAG8AbQBvAG8AblZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGljb21vb24AaQBjAG8AbQBvAG8Abmljb21vb24AaQBjAG8AbQBvAG8AblJlZ3VsYXIAUgBlAGcAdQBsAGEAcmljb21vb24AaQBjAG8AbQBvAG8AbkZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=) format('truetype'); + font-weight: normal; + font-style: normal; +} +[class^="w-e-icon-"], +[class*=" w-e-icon-"] { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: 'w-e-icon' !important; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.w-e-icon-close:before { + content: "\f00d"; +} +.w-e-icon-upload2:before { + content: "\e9c6"; +} +.w-e-icon-trash-o:before { + content: "\f014"; +} +.w-e-icon-header:before { + content: "\f1dc"; +} +.w-e-icon-pencil2:before { + content: "\e906"; +} +.w-e-icon-paint-brush:before { + content: "\f1fc"; +} +.w-e-icon-image:before { + content: "\e90d"; +} +.w-e-icon-play:before { + content: "\e912"; +} +.w-e-icon-location:before { + content: "\e947"; +} +.w-e-icon-undo:before { + content: "\e965"; +} +.w-e-icon-redo:before { + content: "\e966"; +} +.w-e-icon-quotes-left:before { + content: "\e977"; +} +.w-e-icon-list-numbered:before { + content: "\e9b9"; +} +.w-e-icon-list2:before { + content: "\e9bb"; +} +.w-e-icon-link:before { + content: "\e9cb"; +} +.w-e-icon-happy:before { + content: "\e9df"; +} +.w-e-icon-bold:before { + content: "\ea62"; +} +.w-e-icon-underline:before { + content: "\ea63"; +} +.w-e-icon-italic:before { + content: "\ea64"; +} +.w-e-icon-strikethrough:before { + content: "\ea65"; +} +.w-e-icon-table2:before { + content: "\ea71"; +} +.w-e-icon-paragraph-left:before { + content: "\ea77"; +} +.w-e-icon-paragraph-center:before { + content: "\ea78"; +} +.w-e-icon-paragraph-right:before { + content: "\ea79"; +} +.w-e-icon-terminal:before { + content: "\f120"; +} +.w-e-icon-page-break:before { + content: "\ea68"; +} +.w-e-icon-cancel-circle:before { + content: "\ea0d"; +} +.w-e-icon-font:before { + content: "\ea5c"; +} +.w-e-icon-text-heigh:before { + content: "\ea5f"; +} + +.w-e-toolbar { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + padding: 0 5px; + /* flex-wrap: wrap; */ + /* 单个菜单 */ +} +.w-e-toolbar .w-e-menu { + position: relative; + text-align: center; + padding: 5px 10px; + cursor: pointer; +} +.w-e-toolbar .w-e-menu i { + color: #999; +} +.w-e-toolbar .w-e-menu:hover i { + color: #333; +} +.w-e-toolbar .w-e-active i { + color: #1e88e5; +} +.w-e-toolbar .w-e-active:hover i { + color: #1e88e5; +} + +.w-e-text-container .w-e-panel-container { + position: absolute; + top: 0; + left: 50%; + border: 1px solid #ccc; + border-top: 0; + box-shadow: 1px 1px 2px #ccc; + color: #333; + background-color: #fff; + /* 为 emotion panel 定制的样式 */ + /* 上传图片的 panel 定制样式 */ +} +.w-e-text-container .w-e-panel-container .w-e-panel-close { + position: absolute; + right: 0; + top: 0; + padding: 5px; + margin: 2px 5px 0 0; + cursor: pointer; + color: #999; +} +.w-e-text-container .w-e-panel-container .w-e-panel-close:hover { + color: #333; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-title { + list-style: none; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + font-size: 14px; + margin: 2px 10px 0 10px; + border-bottom: 1px solid #f1f1f1; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-title .w-e-item { + padding: 3px 5px; + color: #999; + cursor: pointer; + margin: 0 3px; + position: relative; + top: 1px; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-title .w-e-active { + color: #333; + border-bottom: 1px solid #333; + cursor: default; + font-weight: 700; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content { + padding: 10px 15px 10px 15px; + font-size: 16px; + /* 输入框的样式 */ + /* 按钮的样式 */ +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input:focus, +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea:focus, +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content button:focus { + outline: none; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea { + width: 100%; + border: 1px solid #ccc; + padding: 5px; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea:focus { + border-color: #1e88e5; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text] { + border: none; + border-bottom: 1px solid #ccc; + font-size: 14px; + height: 20px; + color: #333; + text-align: left; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text].small { + width: 30px; + text-align: center; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text].block { + display: block; + width: 100%; + margin: 10px 0; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text]:focus { + border-bottom: 2px solid #1e88e5; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button { + font-size: 14px; + color: #1e88e5; + border: none; + padding: 5px 10px; + background-color: #fff; + cursor: pointer; + border-radius: 3px; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.left { + float: left; + margin-right: 10px; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.right { + float: right; + margin-left: 10px; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.gray { + color: #999; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.red { + color: #c24f4a; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button:hover { + background-color: #f1f1f1; +} +.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container:after { + content: ""; + display: table; + clear: both; +} +.w-e-text-container .w-e-panel-container .w-e-emoticon-container .w-e-item { + cursor: pointer; + font-size: 18px; + padding: 0 3px; + display: inline-block; + *display: inline; + *zoom: 1; +} +.w-e-text-container .w-e-panel-container .w-e-up-img-container { + text-align: center; +} +.w-e-text-container .w-e-panel-container .w-e-up-img-container .w-e-up-btn { + display: inline-block; + *display: inline; + *zoom: 1; + color: #999; + cursor: pointer; + font-size: 60px; + line-height: 1; +} +.w-e-text-container .w-e-panel-container .w-e-up-img-container .w-e-up-btn:hover { + color: #333; +} + +.w-e-text-container { + position: relative; +} +.w-e-text-container .w-e-progress { + position: absolute; + background-color: #1e88e5; + bottom: 0; + left: 0; + height: 1px; +} +.w-e-text { + padding: 0 10px; + overflow-y: scroll; +} +.w-e-text p, +.w-e-text h1, +.w-e-text h2, +.w-e-text h3, +.w-e-text h4, +.w-e-text h5, +.w-e-text table, +.w-e-text pre { + margin: 10px 0; + line-height: 1.5; +} +.w-e-text ul, +.w-e-text ol { + margin: 10px 0 10px 20px; +} +.w-e-text blockquote { + display: block; + border-left: 8px solid #d0e5f2; + padding: 5px 10px; + margin: 10px 0; + line-height: 1.4; + font-size: 100%; + background-color: #f1f1f1; +} +.w-e-text code { + display: inline-block; + *display: inline; + *zoom: 1; + background-color: #f1f1f1; + border-radius: 3px; + padding: 3px 5px; + margin: 0 3px; +} +.w-e-text pre code { + display: block; +} +.w-e-text table { + border-top: 1px solid #ccc; + border-left: 1px solid #ccc; +} +.w-e-text table td, +.w-e-text table th { + border-bottom: 1px solid #ccc; + border-right: 1px solid #ccc; + padding: 3px 5px; +} +.w-e-text table th { + border-bottom: 2px solid #ccc; + text-align: center; +} +.w-e-text:focus { + outline: none; +} +.w-e-text img { + cursor: pointer; +} +.w-e-text img:hover { + box-shadow: 0 0 5px #333; +} diff --git a/WaterCloud.Web/wwwroot/js/lay-module/wangEditor/wangEditor.js b/WaterCloud.Web/wwwroot/js/lay-module/wangEditor/wangEditor.js new file mode 100644 index 0000000..dac3d59 --- /dev/null +++ b/WaterCloud.Web/wwwroot/js/lay-module/wangEditor/wangEditor.js @@ -0,0 +1,10410 @@ +!function(t, e) { + "object" == typeof exports && "object" == typeof module ? module.exports = e() : + "function" == typeof define && define.amd ? define([], e) : + "object" == typeof exports ? exports.wangEditor = e() : + t.wangEditor = e() +}(window, (function() { + return function(t) { + var e = {}; + function n(o) { + if (e[o]) + return e[o].exports; + var r = e[o] = { + i: o, + l: !1, + exports: {} + }; + return t[o].call(r.exports, r, r.exports, n), + r.l = !0, + r.exports + } + return n.m = t, + n.c = e, + n.d = function(t, e, o) { + n.o(t, e) || Object.defineProperty(t, e, { + enumerable: !0, + get: o + }) + } + , + n.r = function(t) { + "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(t, Symbol.toStringTag, { + value: "Module" + }), + Object.defineProperty(t, "__esModule", { + value: !0 + }) + } + , + n.t = function(t, e) { + if (1 & e && (t = n(t)), + 8 & e) + return t; + if (4 & e && "object" == typeof t && t && t.__esModule) + return t; + var o = Object.create(null); + if (n.r(o), + Object.defineProperty(o, "default", { + enumerable: !0, + value: t + }), + 2 & e && "string" != typeof t) + for (var r in t) + n.d(o, r, function(e) { + return t[e] + } + .bind(null, r)); + return o + } + , + n.n = function(t) { + var e = t && t.__esModule ? function() { + return t.default + } + : function() { + return t + } + ; + return n.d(e, "a", e), + e + } + , + n.o = function(t, e) { + return Object.prototype.hasOwnProperty.call(t, e) + } + , + n.p = "", + n(n.s = 125) + }([function(t, e) { + t.exports = function(t) { + return t && t.__esModule ? t : { + default: t + } + } + } + , function(t, e, n) { + t.exports = n(126) + } + , function(t, e, n) { + "use strict"; + var o = n(0) + , r = o(n(105)) + , i = o(n(106)) + , a = o(n(107)) + , u = o(n(60)) + , l = o(n(108)) + , c = o(n(23)) + , s = o(n(39)) + , f = o(n(6)) + , d = o(n(113)) + , p = o(n(50)) + , A = o(n(1)); + (0, + A.default)(e, "__esModule", { + value: !0 + }), + e.DomElement = void 0; + var v = []; + function h(t) { + return (0, + p.default)(Array.prototype).call(t) + } + function g(t) { + var e = [] + , n = []; + return e = (0, + d.default)(t) ? t : t.split(";"), + (0, + f.default)(e).call(e, (function(t) { + var e, o = (0, + s.default)(e = t.split(":")).call(e, (function(t) { + return (0, + c.default)(t).call(t) + } + )); + 2 === o.length && n.push(o[0] + ":" + o[1]) + } + )), + n + } + var m = function() { + function t(e) { + if (this.selector = "", + this.elems = [], + this.length = this.elems.length, + this.dataSource = new l.default, + e) { + if (e instanceof t) + return e; + var n = []; + this.selector = e; + var o, r, i = e.nodeType; + if (9 === i) + n = [e]; + else if (1 === i) + n = [e]; + else if (function(t) { + return !!t && (t instanceof HTMLCollection || t instanceof NodeList) + }(e)) + n = h(e); + else if (e instanceof Array) + n = e; + else if ("string" == typeof e) { + var a; + e = (0, + c.default)(a = e.replace("/\n/mg", "")).call(a), + 0 === (0, + u.default)(e).call(e, "<") ? (o = e, + (r = document.createElement("div")).innerHTML = o, + n = h(r.children)) : n = function(t) { + return h(document.querySelectorAll(t)) + }(e) + } + var s = n.length; + if (!s) + return this; + for (var f = 0; f < s; f++) + this.elems.push(n[f]); + this.length = s + } + } + return (0, + A.default)(t.prototype, "id", { + get: function() { + return this.elems[0].id + }, + enumerable: !1, + configurable: !0 + }), + t.prototype.forEach = function(t) { + for (var e = 0; e < this.length; e++) { + var n = this.elems[e]; + if (!1 === t.call(n, n, e)) + break + } + return this + } + , + t.prototype.clone = function(t) { + var e; + void 0 === t && (t = !1); + var n = []; + return (0, + f.default)(e = this.elems).call(e, (function(e) { + n.push(e.cloneNode(!!t)) + } + )), + y(n) + } + , + t.prototype.get = function(t) { + void 0 === t && (t = 0); + var e = this.length; + return t >= e && (t %= e), + y(this.elems[t]) + } + , + t.prototype.first = function() { + return this.get(0) + } + , + t.prototype.last = function() { + var t = this.length; + return this.get(t - 1) + } + , + t.prototype.on = function(t, e, n) { + var o; + return t ? ("function" == typeof e && (n = e, + e = ""), + (0, + f.default)(o = this).call(o, (function(o) { + if (e) { + var r = function(t) { + var o = t.target; + o.matches(e) && n.call(o, t) + }; + o.addEventListener(t, r), + v.push({ + elem: o, + selector: e, + fn: n, + agentFn: r + }) + } else + o.addEventListener(t, n) + } + ))) : this + } + , + t.prototype.off = function(t, e, n) { + var o; + return t ? ("function" == typeof e && (n = e, + e = ""), + (0, + f.default)(o = this).call(o, (function(o) { + if (e) { + for (var r = -1, i = 0; i < v.length; i++) { + var u = v[i]; + if (u.selector === e && u.fn === n && u.elem === o) { + r = i; + break + } + } + if (-1 !== r) { + var l = (0, + a.default)(v).call(v, r, 1)[0].agentFn; + o.removeEventListener(t, l) + } + } else + o.removeEventListener(t, n) + } + ))) : this + } + , + t.prototype.attr = function(t, e) { + var n; + return null == e ? this.elems[0].getAttribute(t) || "" : (0, + f.default)(n = this).call(n, (function(n) { + n.setAttribute(t, e) + } + )) + } + , + t.prototype.addClass = function(t) { + var e; + return t ? (0, + f.default)(e = this).call(e, (function(e) { + if (e.className) { + var n = e.className.split(/\s/); + n = (0, + i.default)(n).call(n, (function(t) { + return !!(0, + c.default)(t).call(t) + } + )), + (0, + u.default)(n).call(n, t) < 0 && n.push(t), + e.className = n.join(" ") + } else + e.className = t + } + )) : this + } + , + t.prototype.removeClass = function(t) { + var e; + return t ? (0, + f.default)(e = this).call(e, (function(e) { + if (e.className) { + var n = e.className.split(/\s/); + n = (0, + i.default)(n).call(n, (function(e) { + return !(!(e = (0, + c.default)(e).call(e)) || e === t) + } + )), + e.className = n.join(" ") + } + } + )) : this + } + , + t.prototype.hasClass = function(t) { + if (void 0 === t && (t = ""), + !t) + return !1; + var e = this.elems[0]; + if (!e.className) + return !1; + var n = e.className.split(/\s/); + return (0, + r.default)(n).call(n, t) + } + , + t.prototype.css = function(t, e) { + var n, o; + return o = "" == e ? "" : t + ":" + e + ";", + (0, + f.default)(n = this).call(n, (function(e) { + var n, r = (0, + c.default)(n = e.getAttribute("style") || "").call(n); + if (r) { + var i = g(r); + i = (0, + s.default)(i).call(i, (function(e) { + return 0 === (0, + u.default)(e).call(e, t) ? o : e + } + )), + "" != o && (0, + u.default)(i).call(i, o) < 0 && i.push(o), + "" == o && (i = g(i)), + e.setAttribute("style", i.join("; ")) + } else + e.setAttribute("style", o) + } + )) + } + , + t.prototype.getBoundingClientRect = function() { + return this.elems[0].getBoundingClientRect() + } + , + t.prototype.show = function() { + return this.css("display", "block") + } + , + t.prototype.hide = function() { + return this.css("display", "none") + } + , + t.prototype.children = function() { + var t = this.elems[0]; + return t ? y(t.children) : null + } + , + t.prototype.childNodes = function() { + var t = this.elems[0]; + return t ? y(t.childNodes) : null + } + , + t.prototype.append = function(t) { + var e; + return (0, + f.default)(e = this).call(e, (function(e) { + (0, + f.default)(t).call(t, (function(t) { + e.appendChild(t) + } + )) + } + )) + } + , + t.prototype.remove = function() { + var t; + return (0, + f.default)(t = this).call(t, (function(t) { + if (t.remove) + t.remove(); + else { + var e = t.parentElement; + e && e.removeChild(t) + } + } + )) + } + , + t.prototype.isContain = function(t) { + var e = this.elems[0] + , n = t.elems[0]; + return e.contains(n) + } + , + t.prototype.getSizeData = function() { + return this.elems[0].getBoundingClientRect() + } + , + t.prototype.getNodeName = function() { + return this.elems[0].nodeName + } + , + t.prototype.getClientHeight = function() { + return this.elems[0].clientHeight + } + , + t.prototype.find = function(t) { + return y(this.elems[0].querySelectorAll(t)) + } + , + t.prototype.text = function(t) { + var e; + return t ? (0, + f.default)(e = this).call(e, (function(e) { + e.innerHTML = t + } + )) : this.elems[0].innerHTML.replace(/<[^>]+>/g, (function() { + return "" + } + )) + } + , + t.prototype.html = function(t) { + var e = this.elems[0]; + return t ? (e.innerHTML = t, + this) : e.innerHTML + } + , + t.prototype.val = function() { + var t, e = this.elems[0]; + return (0, + c.default)(t = e.value).call(t) + } + , + t.prototype.focus = function() { + var t; + return (0, + f.default)(t = this).call(t, (function(t) { + t.focus() + } + )) + } + , + t.prototype.prev = function() { + return y(this.elems[0].previousElementSibling) + } + , + t.prototype.next = function() { + return y(this.elems[0].nextElementSibling) + } + , + t.prototype.parent = function() { + return y(this.elems[0].parentElement) + } + , + t.prototype.parentUntil = function(t, e) { + var n = e || this.elems[0]; + if ("BODY" === n.nodeName) + return null; + var o = n.parentElement; + return null == o ? null : o.matches(t) ? y(o) : this.parentUntil(t, o) + } + , + t.prototype.equal = function(e) { + return e instanceof t ? this.elems[0] === e.elems[0] : e instanceof HTMLElement && this.elems[0] === e + } + , + t.prototype.insertBefore = function(t) { + var e, n = y(t).elems[0]; + return n ? (0, + f.default)(e = this).call(e, (function(t) { + n.parentNode.insertBefore(t, n) + } + )) : this + } + , + t.prototype.insertAfter = function(t) { + var e, n = y(t).elems[0], o = n && n.nextSibling; + return n ? (0, + f.default)(e = this).call(e, (function(t) { + var e = n.parentNode; + o ? e.insertBefore(t, o) : e.appendChild(t) + } + )) : this + } + , + t.prototype.data = function(t, e) { + if (null == e) + return this.dataSource.get(t); + this.dataSource.set(t, e) + } + , + t.prototype.getNodeTop = function(t) { + if (this.length < 1) + return this; + var e = this.parent(); + return t.$textElem.equal(e) ? this : e.getNodeTop(t) + } + , + t.prototype.getOffsetData = function() { + var t = this.elems[0]; + return { + top: t.offsetTop, + left: t.offsetLeft, + width: t.offsetWidth, + height: t.offsetHeight, + parent: t.offsetParent + } + } + , + t + }(); + function y(t) { + return new m(t) + } + e.DomElement = m, + e.default = y + } + , function(t, e, n) { + t.exports = n(173) + } + , function(t, e, n) { + "use strict"; + var o = n(7) + , r = n(62).f + , i = n(87) + , a = n(12) + , u = n(44) + , l = n(18) + , c = n(15) + , s = function(t) { + var e = function(e, n, o) { + if (this instanceof t) { + switch (arguments.length) { + case 0: + return new t; + case 1: + return new t(e); + case 2: + return new t(e,n) + } + return new t(e,n,o) + } + return t.apply(this, arguments) + }; + return e.prototype = t.prototype, + e + }; + t.exports = function(t, e) { + var n, f, d, p, A, v, h, g, m = t.target, y = t.global, w = t.stat, x = t.proto, E = y ? o : w ? o[m] : (o[m] || {}).prototype, b = y ? a : a[m] || (a[m] = {}), _ = b.prototype; + for (d in e) + n = !i(y ? d : m + (w ? "." : "#") + d, t.forced) && E && c(E, d), + A = b[d], + n && (v = t.noTargetGet ? (g = r(E, d)) && g.value : E[d]), + p = n && v ? v : e[d], + n && typeof A == typeof p || (h = t.bind && n ? u(p, o) : t.wrap && n ? s(p) : x && "function" == typeof p ? u(Function.call, p) : p, + (t.sham || p && p.sham || A && A.sham) && l(h, "sham", !0), + b[d] = h, + x && (c(a, f = m + "Prototype") || l(a, f, {}), + a[f][d] = p, + t.real && _ && !_[d] && l(_, d, p))) + } + } + , function(t, e, n) { + t.exports = n(290) + } + , function(t, e, n) { + t.exports = n(168) + } + , function(t, e, n) { + (function(e) { + var n = function(t) { + return t && t.Math == Math && t + }; + t.exports = n("object" == typeof globalThis && globalThis) || n("object" == typeof window && window) || n("object" == typeof self && self) || n("object" == typeof e && e) || Function("return this")() + } + ).call(this, n(129)) + } + , function(t, e, n) { + var o = n(7) + , r = n(66) + , i = n(15) + , a = n(56) + , u = n(68) + , l = n(92) + , c = r("wks") + , s = o.Symbol + , f = l ? s : s && s.withoutSetter || a; + t.exports = function(t) { + return i(c, t) || (u && i(s, t) ? c[t] = s[t] : c[t] = f("Symbol." + t)), + c[t] + } + } + , function(t, e, n) { + "use strict"; + var o = n(0) + , r = o(n(113)) + , i = o(n(114)) + , a = o(n(83)) + , u = o(n(50)) + , l = o(n(1)) + , c = function() { + for (var t = 0, e = 0, n = arguments.length; e < n; e++) + t += arguments[e].length; + var o = Array(t) + , r = 0; + for (e = 0; e < n; e++) + for (var i = arguments[e], a = 0, u = i.length; a < u; a++, + r++) + o[r] = i[a]; + return o + }; + (0, + l.default)(e, "__esModule", { + value: !0 + }), + e.deepClone = e.isFunction = e.debounce = e.throttle = e.arrForEach = e.forEach = e.replaceSpecialSymbol = e.replaceHtmlSymbol = e.getRandom = e.UA = void 0, + e.UA = { + _ua: navigator.userAgent, + isWebkit: function() { + return /webkit/i.test(this._ua) + }, + isIE: function() { + return "ActiveXObject"in window + } + }, + e.getRandom = function(t) { + var e; + return void 0 === t && (t = ""), + t + (0, + u.default)(e = Math.random().toString()).call(e, 2) + } + , + e.replaceHtmlSymbol = function(t) { + return t.replace(//gm, ">").replace(/"/gm, """).replace(/(\r\n|\r|\n)/g, "
                ") + } + , + e.replaceSpecialSymbol = function(t) { + return t.replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, '"') + } + , + e.forEach = function(t, e) { + for (var n in t) { + if (Object.prototype.hasOwnProperty.call(t, n)) + if (!1 === e(n, t[n])) + break + } + } + , + e.arrForEach = function(t, e) { + var n, o, r = t.length || 0; + for (n = 0; n < r && (o = t[n], + !1 !== e.call(t, o, n)); n++) + ; + } + , + e.throttle = function(t, e) { + void 0 === e && (e = 200); + var n = !1; + return function() { + for (var o = [], r = 0; r < arguments.length; r++) + o[r] = arguments[r]; + n || (n = !0, + (0, + a.default)((function() { + n = !1, + t.call.apply(t, c([null], o)) + } + ), e)) + } + } + , + e.debounce = function(t, e) { + void 0 === e && (e = 200); + var n = 0; + return function() { + for (var o = [], r = 0; r < arguments.length; r++) + o[r] = arguments[r]; + n && window.clearTimeout(n), + n = window.setTimeout((function() { + n = 0, + t.call.apply(t, c([null], o)) + } + ), e) + } + } + , + e.isFunction = function(t) { + return "function" == typeof t + } + , + e.deepClone = function t(e) { + if ("object" !== (0, + i.default)(e) || "function" == typeof e || null === e) + return e; + var n; + for (var o in (0, + r.default)(e) && (n = []), + (0, + r.default)(e) || (n = {}), + e) + Object.prototype.hasOwnProperty.call(e, o) && (n[o] = t(e[o])); + return n + } + } + , function(t, e, n) { + var o = n(12) + , r = n(15) + , i = n(82) + , a = n(16).f; + t.exports = function(t) { + var e = o.Symbol || (o.Symbol = {}); + r(e, t) || a(e, t, { + value: i.f(t) + }) + } + } + , function(t, e) { + t.exports = function(t) { + try { + return !!t() + } catch (t) { + return !0 + } + } + } + , function(t, e) { + t.exports = {} + } + , function(t, e) { + t.exports = function(t) { + return "object" == typeof t ? null !== t : "function" == typeof t + } + } + , function(t, e, n) { + var o = n(11); + t.exports = !o((function() { + return 7 != Object.defineProperty({}, 1, { + get: function() { + return 7 + } + })[1] + } + )) + } + , function(t, e) { + var n = {}.hasOwnProperty; + t.exports = function(t, e) { + return n.call(t, e) + } + } + , function(t, e, n) { + var o = n(14) + , r = n(86) + , i = n(20) + , a = n(51) + , u = Object.defineProperty; + e.f = o ? u : function(t, e, n) { + if (i(t), + e = a(e, !0), + i(n), + r) + try { + return u(t, e, n) + } catch (t) {} + if ("get"in n || "set"in n) + throw TypeError("Accessors not supported"); + return "value"in n && (t[e] = n.value), + t + } + } + , function(t, e, n) { + var o = n(12); + t.exports = function(t) { + return o[t + "Prototype"] + } + } + , function(t, e, n) { + var o = n(14) + , r = n(16) + , i = n(42); + t.exports = o ? function(t, e, n) { + return r.f(t, e, i(1, n)) + } + : function(t, e, n) { + return t[e] = n, + t + } + } + , function(t, e, n) { + "use strict"; + var o, r = n(0), i = r(n(6)), a = r(n(1)), u = r(n(3)), l = r(n(5)), c = (o = function(t, e) { + return (o = l.default || { + __proto__: [] + }instanceof Array && function(t, e) { + t.__proto__ = e + } + || function(t, e) { + for (var n in e) + e.hasOwnProperty(n) && (t[n] = e[n]) + } + )(t, e) + } + , + function(t, e) { + function n() { + this.constructor = t + } + o(t, e), + t.prototype = null === e ? (0, + u.default)(e) : (n.prototype = e.prototype, + new n) + } + ), s = function(t) { + return t && t.__esModule ? t : { + default: t + } + }; + (0, + a.default)(e, "__esModule", { + value: !0 + }); + var f = s(n(2)) + , d = s(n(84)) + , p = s(n(122)) + , A = function(t) { + function e(e, n, o) { + var r = t.call(this, e, n) || this; + o.title = n.i18next.t("menus.dropListMenu." + o.title); + var a, u = "zh-CN" === n.config.lang ? "" : "w-e-drop-list-tl"; + "" !== u && "list" === o.type && (0, + i.default)(a = o.list).call(a, (function(t) { + var e = t.$elem + , n = f.default(e.children()); + if (n.length > 0) { + var o = null == n ? void 0 : n.getNodeName(); + o && "I" === o && e.addClass(u) + } + } + )); + var l = new p.default(r,o); + return r.dropList = l, + e.on("mouseenter", (function() { + var t; + null != n.selection.getRange() && (e.css("z-index", n.zIndex.get("menu")), + (0, + i.default)(t = n.txt.eventHooks.dropListMenuHoverEvents).call(t, (function(t) { + return t() + } + )), + l.showTimeoutId = window.setTimeout((function() { + l.show() + } + ), 200)) + } + )).on("mouseleave", (function() { + e.css("z-index", "auto"), + l.hideTimeoutId = window.setTimeout((function() { + l.hide() + } + )) + } + )), + r + } + return c(e, t), + e + }(d.default); + e.default = A + } + , function(t, e, n) { + var o = n(13); + t.exports = function(t) { + if (!o(t)) + throw TypeError(String(t) + " is not an object"); + return t + } + } + , function(t, e, n) { + "use strict"; + var o, r = function() { + return void 0 === o && (o = Boolean(window && document && document.all && !window.atob)), + o + }, i = function() { + var t = {}; + return function(e) { + if (void 0 === t[e]) { + var n = document.querySelector(e); + if (window.HTMLIFrameElement && n instanceof window.HTMLIFrameElement) + try { + n = n.contentDocument.head + } catch (t) { + n = null + } + t[e] = n + } + return t[e] + } + }(), a = []; + function u(t) { + for (var e = -1, n = 0; n < a.length; n++) + if (a[n].identifier === t) { + e = n; + break + } + return e + } + function l(t, e) { + for (var n = {}, o = [], r = 0; r < t.length; r++) { + var i = t[r] + , l = e.base ? i[0] + e.base : i[0] + , c = n[l] || 0 + , s = "".concat(l, " ").concat(c); + n[l] = c + 1; + var f = u(s) + , d = { + css: i[1], + media: i[2], + sourceMap: i[3] + }; + -1 !== f ? (a[f].references++, + a[f].updater(d)) : a.push({ + identifier: s, + updater: h(d, e), + references: 1 + }), + o.push(s) + } + return o + } + function c(t) { + var e = document.createElement("style") + , o = t.attributes || {}; + if (void 0 === o.nonce) { + var r = n.nc; + r && (o.nonce = r) + } + if (Object.keys(o).forEach((function(t) { + e.setAttribute(t, o[t]) + } + )), + "function" == typeof t.insert) + t.insert(e); + else { + var a = i(t.insert || "head"); + if (!a) + throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid."); + a.appendChild(e) + } + return e + } + var s, f = (s = [], + function(t, e) { + return s[t] = e, + s.filter(Boolean).join("\n") + } + ); + function d(t, e, n, o) { + var r = n ? "" : o.media ? "@media ".concat(o.media, " {").concat(o.css, "}") : o.css; + if (t.styleSheet) + t.styleSheet.cssText = f(e, r); + else { + var i = document.createTextNode(r) + , a = t.childNodes; + a[e] && t.removeChild(a[e]), + a.length ? t.insertBefore(i, a[e]) : t.appendChild(i) + } + } + function p(t, e, n) { + var o = n.css + , r = n.media + , i = n.sourceMap; + if (r ? t.setAttribute("media", r) : t.removeAttribute("media"), + i && btoa && (o += "\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(i)))), " */")), + t.styleSheet) + t.styleSheet.cssText = o; + else { + for (; t.firstChild; ) + t.removeChild(t.firstChild); + t.appendChild(document.createTextNode(o)) + } + } + var A = null + , v = 0; + function h(t, e) { + var n, o, r; + if (e.singleton) { + var i = v++; + n = A || (A = c(e)), + o = d.bind(null, n, i, !1), + r = d.bind(null, n, i, !0) + } else + n = c(e), + o = p.bind(null, n, e), + r = function() { + !function(t) { + if (null === t.parentNode) + return !1; + t.parentNode.removeChild(t) + }(n) + } + ; + return o(t), + function(e) { + if (e) { + if (e.css === t.css && e.media === t.media && e.sourceMap === t.sourceMap) + return; + o(t = e) + } else + r() + } + } + t.exports = function(t, e) { + (e = e || {}).singleton || "boolean" == typeof e.singleton || (e.singleton = r()); + var n = l(t = t || [], e); + return function(t) { + if (t = t || [], + "[object Array]" === Object.prototype.toString.call(t)) { + for (var o = 0; o < n.length; o++) { + var r = u(n[o]); + a[r].references-- + } + for (var i = l(t, e), c = 0; c < n.length; c++) { + var s = u(n[c]); + 0 === a[s].references && (a[s].updater(), + a.splice(s, 1)) + } + n = i + } + } + } + } + , function(t, e, n) { + "use strict"; + t.exports = function(t) { + var e = []; + return e.toString = function() { + return this.map((function(e) { + var n = function(t, e) { + var n = t[1] || "" + , o = t[3]; + if (!o) + return n; + if (e && "function" == typeof btoa) { + var r = (a = o, + u = btoa(unescape(encodeURIComponent(JSON.stringify(a)))), + l = "sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(u), + "/*# ".concat(l, " */")) + , i = o.sources.map((function(t) { + return "/*# sourceURL=".concat(o.sourceRoot || "").concat(t, " */") + } + )); + return [n].concat(i).concat([r]).join("\n") + } + var a, u, l; + return [n].join("\n") + }(e, t); + return e[2] ? "@media ".concat(e[2], " {").concat(n, "}") : n + } + )).join("") + } + , + e.i = function(t, n, o) { + "string" == typeof t && (t = [[null, t, ""]]); + var r = {}; + if (o) + for (var i = 0; i < this.length; i++) { + var a = this[i][0]; + null != a && (r[a] = !0) + } + for (var u = 0; u < t.length; u++) { + var l = [].concat(t[u]); + o && r[l[0]] || (n && (l[2] ? l[2] = "".concat(n, " and ").concat(l[2]) : l[2] = n), + e.push(l)) + } + } + , + e + } + } + , function(t, e, n) { + t.exports = n(201) + } + , function(t, e, n) { + "use strict"; + var o, r = n(0), i = r(n(1)), a = r(n(3)), u = r(n(5)), l = (o = function(t, e) { + return (o = u.default || { + __proto__: [] + }instanceof Array && function(t, e) { + t.__proto__ = e + } + || function(t, e) { + for (var n in e) + e.hasOwnProperty(n) && (t[n] = e[n]) + } + )(t, e) + } + , + function(t, e) { + function n() { + this.constructor = t + } + o(t, e), + t.prototype = null === e ? (0, + a.default)(e) : (n.prototype = e.prototype, + new n) + } + ), c = function(t) { + return t && t.__esModule ? t : { + default: t + } + }; + (0, + i.default)(e, "__esModule", { + value: !0 + }); + var s = function(t) { + function e(e, n) { + return t.call(this, e, n) || this + } + return l(e, t), + e + }(c(n(84)).default); + e.default = s + } + , function(t, e, n) { + var o = n(14) + , r = n(11) + , i = n(15) + , a = Object.defineProperty + , u = {} + , l = function(t) { + throw t + }; + t.exports = function(t, e) { + if (i(u, t)) + return u[t]; + e || (e = {}); + var n = [][t] + , c = !!i(e, "ACCESSORS") && e.ACCESSORS + , s = i(e, 0) ? e[0] : l + , f = i(e, 1) ? e[1] : void 0; + return u[t] = !!n && !r((function() { + if (c && !o) + return !0; + var t = { + length: -1 + }; + c ? a(t, 1, { + enumerable: !0, + get: l + }) : t[1] = 1, + n.call(t, s, f) + } + )) + } + } + , function(t, e, n) { + "use strict"; + var o = n(0) + , r = o(n(120)) + , i = o(n(61)) + , a = o(n(6)) + , u = function(t) { + return t && t.__esModule ? t : { + default: t + } + }; + (0, + o(n(1)).default)(e, "__esModule", { + value: !0 + }); + var l = u(n(2)) + , c = n(40) + , s = function() { + function t(e, n) { + this.menu = e, + this.conf = n, + this.$container = l.default('
                '); + var o = e.editor; + o.txt.eventHooks.clickEvents.push(t.hideCurAllPanels), + o.txt.eventHooks.toolbarClickEvents.push(t.hideCurAllPanels), + o.txt.eventHooks.dropListMenuHoverEvents.push(t.hideCurAllPanels) + } + return t.prototype.create = function() { + var e = this + , n = this.menu; + if (!t.createdMenus.has(n)) { + var o = this.conf + , r = this.$container + , u = o.width || 300 + , s = n.editor.$toolbarElem.getBoundingClientRect() + , f = n.$elem.getBoundingClientRect() + , d = s.height + s.top - f.top + , p = (s.width - u) / 2 + s.left - f.left; + r.css("width", u + "px").css("margin-top", d + "px").css("margin-left", p + "px").css("z-index", n.editor.zIndex.get("panel")); + var A = l.default(''); + r.append(A), + A.on("click", (function() { + e.remove() + } + )); + var v = l.default('
                  ') + , h = l.default('
                  '); + r.append(v).append(h); + var g = o.height; + g && h.css("height", g + "px").css("overflow-y", "auto"); + var m = o.tabs || [] + , y = [] + , w = []; + (0, + a.default)(m).call(m, (function(t, e) { + if (t) { + var n = t.title || "" + , o = t.tpl || "" + , r = l.default('
                • ' + n + "
                • "); + v.append(r); + var i = l.default(o); + h.append(i), + y.push(r), + w.push(i), + 0 === e ? (r.data("active", !0), + r.addClass("w-e-active")) : i.hide(), + r.on("click", (function() { + r.data("active") || ((0, + a.default)(y).call(y, (function(t) { + t.data("active", !1), + t.removeClass("w-e-active") + } + )), + (0, + a.default)(w).call(w, (function(t) { + t.hide() + } + )), + r.data("active", !0), + r.addClass("w-e-active"), + i.show()) + } + )) + } + } + )), + r.on("click", (function(t) { + t.stopPropagation() + } + )), + n.$elem.append(r), + (0, + a.default)(m).call(m, (function(t, n) { + if (t) { + var o = t.events || []; + (0, + a.default)(o).call(o, (function(t) { + var o = t.selector + , r = t.type + , a = t.fn || c.EMPTY_FN + , u = w[n]; + (0, + i.default)(u).call(u, o).on(r, (function(t) { + t.stopPropagation(), + a(t) && e.remove() + } + )) + } + )) + } + } + )); + var x = (0, + i.default)(r).call(r, "input[type=text],textarea"); + x.length && x.get(0).focus(), + t.hideCurAllPanels(), + n.setPanel(this), + t.createdMenus.add(n) + } + } + , + t.prototype.remove = function() { + var e = this.menu + , n = this.$container; + n && n.remove(), + t.createdMenus.delete(e) + } + , + t.hideCurAllPanels = function() { + var e; + 0 !== t.createdMenus.size && (0, + a.default)(e = t.createdMenus).call(e, (function(t) { + var e = t.panel; + e && e.remove() + } + )) + } + , + t.createdMenus = new r.default, + t + }(); + e.default = s + } + , function(t, e, n) { + var o = n(64) + , r = n(43); + t.exports = function(t) { + return o(r(t)) + } + } + , function(t, e) { + var n = {}.toString; + t.exports = function(t) { + return n.call(t).slice(8, -1) + } + } + , function(t, e, n) { + var o = n(73) + , r = n(16).f + , i = n(18) + , a = n(15) + , u = n(154) + , l = n(8)("toStringTag"); + t.exports = function(t, e, n, c) { + if (t) { + var s = n ? t : t.prototype; + a(s, l) || r(s, l, { + configurable: !0, + value: e + }), + c && !o && i(s, "toString", u) + } + } + } + , function(t, e, n) { + "use strict"; + var o, r = n(0), i = r(n(1)), a = r(n(3)), u = r(n(5)), l = (o = function(t, e) { + return (o = u.default || { + __proto__: [] + }instanceof Array && function(t, e) { + t.__proto__ = e + } + || function(t, e) { + for (var n in e) + e.hasOwnProperty(n) && (t[n] = e[n]) + } + )(t, e) + } + , + function(t, e) { + function n() { + this.constructor = t + } + o(t, e), + t.prototype = null === e ? (0, + a.default)(e) : (n.prototype = e.prototype, + new n) + } + ), c = function(t) { + return t && t.__esModule ? t : { + default: t + } + }; + (0, + i.default)(e, "__esModule", { + value: !0 + }); + var s = function(t) { + function e(e, n) { + return t.call(this, e, n) || this + } + return l(e, t), + e.prototype.setPanel = function(t) { + this.panel = t + } + , + e + }(c(n(84)).default); + e.default = s + } + , function(t, e) { + t.exports = function(t) { + if ("function" != typeof t) + throw TypeError(String(t) + " is not a function"); + return t + } + } + , function(t, e, n) { + var o, r, i, a = n(149), u = n(7), l = n(13), c = n(18), s = n(15), f = n(55), d = n(45), p = u.WeakMap; + if (a) { + var A = new p + , v = A.get + , h = A.has + , g = A.set; + o = function(t, e) { + return g.call(A, t, e), + e + } + , + r = function(t) { + return v.call(A, t) || {} + } + , + i = function(t) { + return h.call(A, t) + } + } else { + var m = f("state"); + d[m] = !0, + o = function(t, e) { + return c(t, m, e), + e + } + , + r = function(t) { + return s(t, m) ? t[m] : {} + } + , + i = function(t) { + return s(t, m) + } + } + t.exports = { + set: o, + get: r, + has: i, + enforce: function(t) { + return i(t) ? r(t) : o(t, {}) + }, + getterFor: function(t) { + return function(e) { + var n; + if (!l(e) || (n = r(e)).type !== t) + throw TypeError("Incompatible receiver, " + t + " required"); + return n + } + } + } + } + , function(t, e) { + t.exports = !0 + } + , function(t, e, n) { + var o = n(43); + t.exports = function(t) { + return Object(o(t)) + } + } + , function(t, e, n) { + var o = n(54) + , r = Math.min; + t.exports = function(t) { + return t > 0 ? r(o(t), 9007199254740991) : 0 + } + } + , function(t, e, n) { + var o = n(12) + , r = n(7) + , i = function(t) { + return "function" == typeof t ? t : void 0 + }; + t.exports = function(t, e) { + return arguments.length < 2 ? i(o[t]) || i(r[t]) : o[t] && o[t][e] || r[t] && r[t][e] + } + } + , function(t, e) { + t.exports = {} + } + , function(t, e, n) { + var o = n(44) + , r = n(64) + , i = n(34) + , a = n(35) + , u = n(79) + , l = [].push + , c = function(t) { + var e = 1 == t + , n = 2 == t + , c = 3 == t + , s = 4 == t + , f = 6 == t + , d = 5 == t || f; + return function(p, A, v, h) { + for (var g, m, y = i(p), w = r(y), x = o(A, v, 3), E = a(w.length), b = 0, _ = h || u, S = e ? _(p, E) : n ? _(p, 0) : void 0; E > b; b++) + if ((d || b in w) && (m = x(g = w[b], b, y), + t)) + if (e) + S[b] = m; + else if (m) + switch (t) { + case 3: + return !0; + case 5: + return g; + case 6: + return b; + case 2: + l.call(S, g) + } + else if (s) + return !1; + return f ? -1 : c || s ? s : S + } + }; + t.exports = { + forEach: c(0), + map: c(1), + filter: c(2), + some: c(3), + every: c(4), + find: c(5), + findIndex: c(6) + } + } + , function(t, e, n) { + t.exports = n(206) + } + , function(t, e, n) { + "use strict"; + (0, + n(0)(n(1)).default)(e, "__esModule", { + value: !0 + }), + e.urlRegex = e.imgRegex = e.EMPTY_FN = void 0, + e.EMPTY_FN = function() {} + , + e.imgRegex = /\.(gif|jpg|jpeg|png)$/i, + e.urlRegex = /^(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-.,@?^=%&:/~+#]*[\w\-@?^=%&/~+#])?/ + } + , function(t, e, n) { + "use strict"; + var o = n(0) + , r = o(n(6)) + , i = o(n(1)) + , a = function(t) { + return t && t.__esModule ? t : { + default: t + } + }; + (0, + i.default)(e, "__esModule", { + value: !0 + }); + var u = a(n(2)) + , l = function() { + function t(t, e, n) { + this.editor = t, + this.$targetElem = e, + this.conf = n, + this._show = !1, + this._isInsertTextContainer = !1; + var o = u.default("
                  "); + o.addClass("w-e-tooltip"), + this.$container = o + } + return t.prototype.getPositionData = function() { + var t = this.$container + , e = 0 + , n = 0 + , o = document.documentElement.scrollTop + , r = this.$targetElem.getBoundingClientRect() + , i = this.editor.$textElem.getBoundingClientRect() + , a = this.$targetElem.getOffsetData() + , l = u.default(a.parent) + , c = this.editor.$textElem.elems[0].scrollTop; + if (this._isInsertTextContainer = l.equal(this.editor.$textContainerElem), + this._isInsertTextContainer) { + var s = l.getClientHeight() + , f = a.top + , d = a.left + , p = a.height + , A = f - c; + A > 25 ? (e = A - 20 - 15, + t.addClass("w-e-tooltip-up")) : A + p + 20 < s ? (e = A + p + 10, + t.addClass("w-e-tooltip-down")) : (e = (A > 0 ? A : 0) + 20 + 10, + t.addClass("w-e-tooltip-down")), + n = d < 0 ? 0 : d + } else + r.top < 20 || r.top - i.top < 20 ? (e = r.bottom + o + 5, + t.addClass("w-e-tooltip-down")) : (e = r.top + o - 20 - 15, + t.addClass("w-e-tooltip-up")), + n = r.left < 0 ? 0 : r.left; + return { + top: e, + left: n + } + } + , + t.prototype.appendMenus = function() { + var t = this + , e = this.conf + , n = this.editor + , o = this.$targetElem + , i = this.$container; + e.length; + (0, + r.default)(e).call(e, (function(e, r) { + var a = e.$elem + , l = u.default("
                  "); + l.addClass("w-e-tooltip-item-wrapper "), + l.append(a), + i.append(l), + a.on("click", (function(r) { + r.preventDefault(), + e.onClick(n, o) && t.remove() + } + )) + } + )) + } + , + t.prototype.create = function() { + var t = this.editor + , e = this.$container; + this.appendMenus(); + var n = this.getPositionData() + , o = n.top + , r = n.left; + e.css("top", o + "px"), + e.css("left", r + "px"), + e.css("z-index", t.zIndex.get("tooltip")), + this._isInsertTextContainer ? this.editor.$textContainerElem.append(e) : u.default("body").append(e), + this._show = !0 + } + , + t.prototype.remove = function() { + this.$container.remove(), + this._show = !1 + } + , + (0, + i.default)(t.prototype, "isShow", { + get: function() { + return this._show + }, + enumerable: !1, + configurable: !0 + }), + t + }(); + e.default = l + } + , function(t, e) { + t.exports = function(t, e) { + return { + enumerable: !(1 & t), + configurable: !(2 & t), + writable: !(4 & t), + value: e + } + } + } + , function(t, e) { + t.exports = function(t) { + if (null == t) + throw TypeError("Can't call method on " + t); + return t + } + } + , function(t, e, n) { + var o = n(31); + t.exports = function(t, e, n) { + if (o(t), + void 0 === e) + return t; + switch (n) { + case 0: + return function() { + return t.call(e) + } + ; + 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, r) { + return t.call(e, n, o, r) + } + } + return function() { + return t.apply(e, arguments) + } + } + } + , function(t, e) { + t.exports = {} + } + , function(t, e, n) { + var o = n(18); + t.exports = function(t, e, n, r) { + r && r.enumerable ? t[e] = n : o(t, e, n) + } + } + , function(t, e, n) { + n(156); + var o = n(157) + , r = n(7) + , i = n(58) + , a = n(18) + , u = n(37) + , l = n(8)("toStringTag"); + for (var c in o) { + var s = r[c] + , f = s && s.prototype; + f && i(f) !== l && a(f, l, c), + u[c] = u.Array + } + } + , function(t, e, n) { + var o = n(28); + t.exports = Array.isArray || function(t) { + return "Array" == o(t) + } + } + , function(t, e, n) { + var o = n(11) + , r = n(8) + , i = n(78) + , a = r("species"); + t.exports = function(t) { + return i >= 51 || !o((function() { + var e = []; + return (e.constructor = {})[a] = function() { + return { + foo: 1 + } + } + , + 1 !== e[t](Boolean).foo + } + )) + } + } + , function(t, e, n) { + t.exports = n(213) + } + , function(t, e, n) { + var o = n(13); + t.exports = function(t, e) { + if (!o(t)) + return t; + var n, r; + if (e && "function" == typeof (n = t.toString) && !o(r = n.call(t))) + return r; + if ("function" == typeof (n = t.valueOf) && !o(r = n.call(t))) + return r; + if (!e && "function" == typeof (n = t.toString) && !o(r = n.call(t))) + return r; + throw TypeError("Can't convert object to primitive value") + } + } + , function(t, e) {} + , function(t, e, n) { + "use strict"; + var o = n(148).charAt + , r = n(32) + , i = n(67) + , a = r.set + , u = r.getterFor("String Iterator"); + i(String, "String", (function(t) { + a(this, { + type: "String Iterator", + string: String(t), + index: 0 + }) + } + ), (function() { + var t, e = u(this), n = e.string, r = e.index; + return r >= n.length ? { + value: void 0, + done: !0 + } : (t = o(n, r), + e.index += t.length, + { + value: t, + done: !1 + }) + } + )) + } + , function(t, e) { + var n = Math.ceil + , o = Math.floor; + t.exports = function(t) { + return isNaN(t = +t) ? 0 : (t > 0 ? o : n)(t) + } + } + , function(t, e, n) { + var o = n(66) + , r = n(56) + , i = o("keys"); + t.exports = function(t) { + return i[t] || (i[t] = r(t)) + } + } + , function(t, e) { + var n = 0 + , o = Math.random(); + t.exports = function(t) { + return "Symbol(" + String(void 0 === t ? "" : t) + ")_" + (++n + o).toString(36) + } + } + , function(t, e, n) { + var o, r = n(20), i = n(153), a = n(72), u = n(45), l = n(94), c = n(65), s = n(55), f = s("IE_PROTO"), d = function() {}, p = function(t) { + return " + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/page/area.html b/WaterCloud.Web/wwwroot/page/area.html new file mode 100644 index 0000000..840bdaa --- /dev/null +++ b/WaterCloud.Web/wwwroot/page/area.html @@ -0,0 +1,103 @@ + + + + + 省市县区选择区 + + + + + + + + + + + + +
                  +
                  + +
                  +
                  +
                  选择地区
                  +
                  + +
                  +
                  + +
                  +
                  + +
                  +
                  +
                  +
                  +
                  + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/page/cardTable.html b/WaterCloud.Web/wwwroot/page/cardTable.html new file mode 100644 index 0000000..782b91d --- /dev/null +++ b/WaterCloud.Web/wwwroot/page/cardTable.html @@ -0,0 +1,85 @@ + + + + + + + + + + + +
                  +
                  +
                  +
                  +
                  +
                  + +
                  + +
                  + +
                  + +
                  +
                  + + +
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/page/color-select.html b/WaterCloud.Web/wwwroot/page/color-select.html new file mode 100644 index 0000000..d4fab92 --- /dev/null +++ b/WaterCloud.Web/wwwroot/page/color-select.html @@ -0,0 +1,57 @@ + + + + + 颜色选择器 + + + + +
                  +
                  + +
                  + 颜色选择器使用开源项目:paigusu
                  + TableSelect +
                  + +
                  +
                  + +
                  + + +
                  +
                  +
                  + +
                  +    $(function () {
                  +        $('.paigusu').paigusu({
                  +            color: '#1926dc',//初始色  支持两种配置方案
                  +        }, function (event, obj) {
                  +            console.log(event);
                  +            console.log(obj);
                  +            $(event).css('color', '#' + obj.hex)
                  +        });
                  +    });
                  +        
                  +
                  +
                  + + + + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/page/designer.html b/WaterCloud.Web/wwwroot/page/designer.html new file mode 100644 index 0000000..7746577 --- /dev/null +++ b/WaterCloud.Web/wwwroot/page/designer.html @@ -0,0 +1,42 @@ + + + + + + + 表单设计器 + + + + + + + + + +
                  + +
                  + + + + + + + + + + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/page/designerPreview.html b/WaterCloud.Web/wwwroot/page/designerPreview.html new file mode 100644 index 0000000..5c187d4 --- /dev/null +++ b/WaterCloud.Web/wwwroot/page/designerPreview.html @@ -0,0 +1,238 @@ + + + + + + layout 后台大布局 - Layui + + + + + + + + +
                  +
                  + + + + +
                  +
                  + +
                  +
                  + + + + + + + + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/page/editor.html b/WaterCloud.Web/wwwroot/page/editor.html new file mode 100644 index 0000000..ab5aaf0 --- /dev/null +++ b/WaterCloud.Web/wwwroot/page/editor.html @@ -0,0 +1,101 @@ + + + + + 富文本编辑器 + + + + + + + +
                  +
                  + +
                  + 富文本编辑器使用开源项目:wangEditor
                  + 具体使用请参考下方官网,以下仅做示例,上传接口请改为实际后端接口
                  + 目前上传接口返回数据是写死在json里面的
                  + wangEditor +
                  + +
                  +

                  欢迎使用 wangEditor 富文本编辑器

                  +
                  + +
                  +        var E = window.wangEditor;
                  +        var editor = new E('#editor');
                  +        editor.customConfig.uploadImgServer = "../api/upload.json";
                  +        editor.customConfig.uploadFileName = 'image';
                  +        editor.customConfig.pasteFilterStyle = false;
                  +        editor.customConfig.uploadImgMaxLength = 5;
                  +        editor.customConfig.uploadImgHooks = {
                  +            // 上传超时
                  +            timeout: function (xhr, editor) {
                  +                layer.msg('上传超时!')
                  +            },
                  +            // 如果服务器端返回的不是 {errno:0, data: [...]} 这种格式,可使用该配置
                  +            customInsert: function (insertImg, result, editor) {
                  +                console.log(result);
                  +                if (result.code == 1) {
                  +                    var url = result.data.url;
                  +                    url.forEach(function (e) {
                  +                        insertImg(e);
                  +                    })
                  +                } else {
                  +                    layer.msg(result.msg);
                  +                }
                  +            }
                  +        };
                  +        editor.customConfig.customAlert = function (info) {
                  +            layer.msg(info);
                  +        };
                  +        editor.create();
                  +        
                  + +
                  +
                  + + + + + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/page/error.html b/WaterCloud.Web/wwwroot/page/error.html new file mode 100644 index 0000000..636bbda --- /dev/null +++ b/WaterCloud.Web/wwwroot/page/error.html @@ -0,0 +1,66 @@ + + + + + + + 页面不存在 + + + + + + + +
                  +
                  + +
                  +
                  +
                  + +
                  +

                  Error

                  +
                  + 页面不存在 +
                  +
                  + +
                  +
                  +
                  + + + + + + + + diff --git a/WaterCloud.Web/wwwroot/page/handwrittenSignature.html b/WaterCloud.Web/wwwroot/page/handwrittenSignature.html new file mode 100644 index 0000000..cbc7986 --- /dev/null +++ b/WaterCloud.Web/wwwroot/page/handwrittenSignature.html @@ -0,0 +1,41 @@ + + + + + + + 表单设计器 + + + + + +
                  + +
                  + + + + + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/page/icon-picker.html b/WaterCloud.Web/wwwroot/page/icon-picker.html new file mode 100644 index 0000000..cd6ef59 --- /dev/null +++ b/WaterCloud.Web/wwwroot/page/icon-picker.html @@ -0,0 +1,119 @@ + + + + + 图标选择器 + + + + + + +
                  +
                  + +
                  + fa图标选择器根据开源Layui-IconPicker插件修改而来。
                  + 不同的参数的地方是,去掉了type参数,新增url参数,url参数为fa图标less/variables.less文件路径。
                  + Layui-IconPicker +
                  + +
                  +
                  + +
                  + +
                  +
                  + +
                  + +
                  + +
                  +
                  +
                  + +
                  +        iconPickerFa.render({
                  +            // 选择器,推荐使用input
                  +            elem: '#iconPicker',
                  +            // fa 图标接口
                  +            url: "/lib/font-awesome-4.7.0/less/variables.less",
                  +            // 是否开启搜索:true/false,默认true
                  +            search: true,
                  +            // 是否开启分页:true/false,默认true
                  +            page: true,
                  +            // 每页显示数量,默认12
                  +            limit: 12,
                  +            // 点击回调
                  +            click: function (data) {
                  +                console.log(data);
                  +            },
                  +            // 渲染成功后的回调
                  +            success: function (d) {
                  +                console.log(d);
                  +            }
                  +        });
                  +        
                  + +
                  +
                  + + + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/page/icon.html b/WaterCloud.Web/wwwroot/page/icon.html new file mode 100644 index 0000000..2c1eb8a --- /dev/null +++ b/WaterCloud.Web/wwwroot/page/icon.html @@ -0,0 +1,777 @@ + + + + + + 图标列表 + + + + + + + + + + + + +
                  +
                  + +
                  +

                  全部图标

                  +
                  +
                    +
                  • fa-adjust
                  • +
                  • fa-anchor
                  • +
                  • fa-archive
                  • +
                  • fa-area-chart
                  • +
                  • fa-arrows
                  • +
                  • fa-arrows-h
                  • +
                  • fa-arrows-v
                  • +
                  • fa-asterisk
                  • +
                  • fa-at
                  • +
                  • fa-automobile
                  • +
                  • fa-ban
                  • +
                  • fa-bank
                  • +
                  • fa-bar-chart
                  • +
                  • fa-bar-chart-o
                  • +
                  • fa-barcode
                  • +
                  • fa-bars
                  • +
                  • fa-bed
                  • +
                  • fa-beer
                  • +
                  • fa-bell
                  • +
                  • fa-bell-o
                  • +
                  • fa-bell-slash
                  • +
                  • fa-bell-slash-o
                  • +
                  • fa-bicycle
                  • +
                  • fa-binoculars
                  • +
                  • fa-birthday-cake
                  • +
                  • fa-bolt
                  • +
                  • fa-bomb
                  • +
                  • fa-book
                  • +
                  • fa-bookmark
                  • +
                  • fa-bookmark-o
                  • +
                  • fa-briefcase
                  • +
                  • fa-bug
                  • +
                  • fa-building
                  • +
                  • fa-building-o
                  • +
                  • fa-bullhorn
                  • +
                  • fa-bullseye
                  • +
                  • fa-bus
                  • +
                  • fa-cab
                  • +
                  • fa-calculator
                  • +
                  • fa-calendar
                  • +
                  • fa-calendar-o
                  • +
                  • fa-camera
                  • +
                  • fa-camera-retro
                  • +
                  • fa-car
                  • +
                  • fa-caret-square-o-down
                  • +
                  • fa-caret-square-o-left
                  • +
                  • fa-caret-square-o-right
                  • +
                  • fa-caret-square-o-up
                  • +
                  • fa-cart-arrow-down
                  • +
                  • fa-cart-plus
                  • +
                  • fa-cc
                  • +
                  • fa-certificate
                  • +
                  • fa-check
                  • +
                  • fa-check-circle
                  • +
                  • fa-check-circle-o
                  • +
                  • fa-check-square
                  • +
                  • fa-check-square-o
                  • +
                  • fa-child
                  • +
                  • fa-circle
                  • +
                  • fa-circle-o
                  • +
                  • fa-circle-o-notch
                  • +
                  • fa-circle-thin
                  • +
                  • fa-clock-o
                  • +
                  • fa-close
                  • +
                  • fa-cloud
                  • +
                  • fa-cloud-download
                  • +
                  • fa-cloud-upload
                  • +
                  • fa-code
                  • +
                  • fa-code-fork
                  • +
                  • fa-coffee
                  • +
                  • fa-cog
                  • +
                  • fa-cogs
                  • +
                  • fa-comment
                  • +
                  • fa-comment-o
                  • +
                  • fa-comments
                  • +
                  • fa-comments-o
                  • +
                  • fa-compass
                  • +
                  • fa-copyright
                  • +
                  • fa-credit-card
                  • +
                  • fa-crop
                  • +
                  • fa-crosshairs
                  • +
                  • fa-cube
                  • +
                  • fa-cubes
                  • +
                  • fa-cutlery
                  • +
                  • fa-dashboard
                  • +
                  • fa-database
                  • +
                  • fa-desktop
                  • +
                  • fa-diamond
                  • +
                  • fa-dot-circle-o
                  • +
                  • fa-download
                  • +
                  • fa-edit
                  • +
                  • fa-ellipsis-h
                  • +
                  • fa-ellipsis-v
                  • +
                  • fa-envelope
                  • +
                  • fa-envelope-o
                  • +
                  • fa-envelope-square
                  • +
                  • fa-eraser
                  • +
                  • fa-exchange
                  • +
                  • fa-exclamation
                  • +
                  • fa-exclamation-circle
                  • +
                  • fa-exclamation-triangle
                  • +
                  • fa-external-link
                  • +
                  • fa-external-link-square
                  • +
                  • fa-eye
                  • +
                  • fa-eye-slash
                  • +
                  • fa-eyedropper
                  • +
                  • fa-fax
                  • +
                  • fa-female
                  • +
                  • fa-fighter-jet
                  • +
                  • fa-file-archive-o
                  • +
                  • fa-file-audio-o
                  • +
                  • fa-file-code-o
                  • +
                  • fa-file-excel-o
                  • +
                  • fa-file-image-o
                  • +
                  • fa-file-movie-o
                  • +
                  • fa-file-pdf-o
                  • +
                  • fa-file-photo-o
                  • +
                  • fa-file-picture-o
                  • +
                  • fa-file-powerpoint-o
                  • +
                  • fa-file-sound-o
                  • +
                  • fa-file-video-o
                  • +
                  • fa-file-word-o
                  • +
                  • fa-file-zip-o
                  • +
                  • fa-film
                  • +
                  • fa-filter
                  • +
                  • fa-fire
                  • +
                  • fa-fire-extinguisher
                  • +
                  • fa-flag
                  • +
                  • fa-flag-checkered
                  • +
                  • fa-flag-o
                  • +
                  • fa-flash
                  • +
                  • fa-flask
                  • +
                  • fa-folder
                  • +
                  • fa-folder-o
                  • +
                  • fa-folder-open
                  • +
                  • fa-folder-open-o
                  • +
                  • fa-frown-o
                  • +
                  • fa-futbol-o
                  • +
                  • fa-gamepad
                  • +
                  • fa-gavel
                  • +
                  • fa-gear
                  • +
                  • fa-gears
                  • +
                  • fa-genderless
                  • +
                  • fa-gift
                  • +
                  • fa-glass
                  • +
                  • fa-globe
                  • +
                  • fa-graduation-cap
                  • +
                  • fa-group
                  • +
                  • fa-hdd-o
                  • +
                  • fa-headphones
                  • +
                  • fa-heart
                  • +
                  • fa-heart-o
                  • +
                  • fa-heartbeat
                  • +
                  • fa-history
                  • +
                  • fa-home
                  • +
                  • fa-hotel
                  • +
                  • fa-image
                  • +
                  • fa-inbox
                  • +
                  • fa-info
                  • +
                  • fa-info-circle
                  • +
                  • fa-institution
                  • +
                  • fa-key
                  • +
                  • fa-keyboard-o
                  • +
                  • fa-language
                  • +
                  • fa-laptop
                  • +
                  • fa-leaf
                  • +
                  • fa-legal
                  • +
                  • fa-lemon-o
                  • +
                  • fa-level-down
                  • +
                  • fa-level-up
                  • +
                  • fa-life-bouy
                  • +
                  • fa-life-buoy
                  • +
                  • fa-life-ring
                  • +
                  • fa-life-saver
                  • +
                  • fa-lightbulb-o
                  • +
                  • fa-line-chart
                  • +
                  • fa-location-arrow
                  • +
                  • fa-lock
                  • +
                  • fa-magic
                  • +
                  • fa-magnet
                  • +
                  • fa-mail-forward
                  • +
                  • fa-mail-reply
                  • +
                  • fa-mail-reply-all
                  • +
                  • fa-male
                  • +
                  • fa-map-marker
                  • +
                  • fa-meh-o
                  • +
                  • fa-microphone
                  • +
                  • fa-microphone-slash
                  • +
                  • fa-minus
                  • +
                  • fa-minus-circle
                  • +
                  • fa-minus-square
                  • +
                  • fa-minus-square-o
                  • +
                  • fa-mobile
                  • +
                  • fa-mobile-phone
                  • +
                  • fa-money
                  • +
                  • fa-moon-o
                  • +
                  • fa-mortar-board
                  • +
                  • fa-motorcycle
                  • +
                  • fa-music
                  • +
                  • fa-navicon
                  • +
                  • fa-newspaper-o
                  • +
                  • fa-paint-brush
                  • +
                  • fa-paper-plane
                  • +
                  • fa-paper-plane-o
                  • +
                  • fa-paw
                  • +
                  • fa-pencil
                  • +
                  • fa-pencil-square
                  • +
                  • fa-pencil-square-o
                  • +
                  • fa-phone
                  • +
                  • fa-phone-square
                  • +
                  • fa-photo
                  • +
                  • fa-picture-o
                  • +
                  • fa-pie-chart
                  • +
                  • fa-plane
                  • +
                  • fa-plug
                  • +
                  • fa-plus
                  • +
                  • fa-plus-circle
                  • +
                  • fa-plus-square
                  • +
                  • fa-plus-square-o
                  • +
                  • fa-power-off
                  • +
                  • fa-print
                  • +
                  • fa-puzzle-piece
                  • +
                  • fa-qrcode
                  • +
                  • fa-question
                  • +
                  • fa-question-circle
                  • +
                  • fa-quote-left
                  • +
                  • fa-quote-right
                  • +
                  • fa-random
                  • +
                  • fa-recycle
                  • +
                  • fa-refresh
                  • +
                  • fa-remove
                  • +
                  • fa-reorder
                  • +
                  • fa-reply
                  • +
                  • fa-reply-all
                  • +
                  • fa-retweet
                  • +
                  • fa-road
                  • +
                  • fa-rocket
                  • +
                  • fa-rss
                  • +
                  • fa-rss-square
                  • +
                  • fa-search
                  • +
                  • fa-search-minus
                  • +
                  • fa-search-plus
                  • +
                  • fa-send
                  • +
                  • fa-send-o
                  • +
                  • fa-server
                  • +
                  • fa-share
                  • +
                  • fa-share-alt
                  • +
                  • fa-share-alt-square
                  • +
                  • fa-share-square
                  • +
                  • fa-share-square-o
                  • +
                  • fa-shield
                  • +
                  • fa-ship
                  • +
                  • fa-shopping-cart
                  • +
                  • fa-sign-in
                  • +
                  • fa-sign-out
                  • +
                  • fa-signal
                  • +
                  • fa-sitemap
                  • +
                  • fa-sliders
                  • +
                  • fa-smile-o
                  • +
                  • fa-soccer-ball-o
                  • +
                  • fa-sort
                  • +
                  • fa-sort-alpha-asc
                  • +
                  • fa-sort-alpha-desc
                  • +
                  • fa-sort-amount-asc
                  • +
                  • fa-sort-amount-desc
                  • +
                  • fa-sort-asc
                  • +
                  • fa-sort-desc
                  • +
                  • fa-sort-down
                  • +
                  • fa-sort-numeric-asc
                  • +
                  • fa-sort-numeric-desc
                  • +
                  • fa-sort-up
                  • +
                  • fa-space-shuttle
                  • +
                  • fa-spinner
                  • +
                  • fa-spoon
                  • +
                  • fa-square
                  • +
                  • fa-square-o
                  • +
                  • fa-star
                  • +
                  • fa-star-half
                  • +
                  • fa-star-half-empty
                  • +
                  • fa-star-half-full
                  • +
                  • fa-star-half-o
                  • +
                  • fa-star-o
                  • +
                  • fa-street-view
                  • +
                  • fa-suitcase
                  • +
                  • fa-sun-o
                  • +
                  • fa-support
                  • +
                  • fa-tablet
                  • +
                  • fa-tachometer
                  • +
                  • fa-tag
                  • +
                  • fa-tags
                  • +
                  • fa-tasks
                  • +
                  • fa-taxi
                  • +
                  • fa-terminal
                  • +
                  • fa-thumb-tack
                  • +
                  • fa-thumbs-down
                  • +
                  • fa-thumbs-o-down
                  • +
                  • fa-thumbs-o-up
                  • +
                  • fa-thumbs-up
                  • +
                  • fa-ticket
                  • +
                  • fa-times
                  • +
                  • fa-times-circle
                  • +
                  • fa-times-circle-o
                  • +
                  • fa-tint
                  • +
                  • fa-toggle-down
                  • +
                  • fa-toggle-left
                  • +
                  • fa-toggle-off
                  • +
                  • fa-toggle-on
                  • +
                  • fa-toggle-right
                  • +
                  • fa-toggle-up
                  • +
                  • fa-trash
                  • +
                  • fa-trash-o
                  • +
                  • fa-tree
                  • +
                  • fa-trophy
                  • +
                  • fa-truck
                  • +
                  • fa-tty
                  • +
                  • fa-umbrella
                  • +
                  • fa-university
                  • +
                  • fa-unlock
                  • +
                  • fa-unlock-alt
                  • +
                  • fa-unsorted
                  • +
                  • fa-upload
                  • +
                  • fa-user
                  • +
                  • fa-user-plus
                  • +
                  • fa-user-secret
                  • +
                  • fa-user-times
                  • +
                  • fa-users
                  • +
                  • fa-video-camera
                  • +
                  • fa-volume-down
                  • +
                  • fa-volume-off
                  • +
                  • fa-volume-up
                  • +
                  • fa-warning
                  • +
                  • fa-wheelchair
                  • +
                  • fa-wifi
                  • +
                  • fa-wrench
                  • +
                  +
                  + +
                  +

                  运输工具

                  +
                  +
                    +
                  • fa-ambulance
                  • +
                  • fa-car
                  • +
                  • fa-bicycle
                  • +
                  • fa-bus
                  • +
                  • fa-taxi
                  • +
                  • fa-fighter-jet
                  • +
                  • fa-motorcycle
                  • +
                  • fa-plane
                  • +
                  • fa-rocket
                  • +
                  • fa-ship
                  • +
                  • fa-space-shuttle
                  • +
                  • fa-subway
                  • +
                  • fa-train
                  • +
                  • fa-truck
                  • +
                  • fa-wheelchair
                  • +
                  +
                  + +
                  +

                  性别

                  +
                  +
                    +
                  • fa-circle-thin
                  • +
                  • fa-mars
                  • +
                  • fa-mars-double
                  • +
                  • fa-mars-stroke
                  • +
                  • fa-mars-stroke-h
                  • +
                  • fa-mars-stroke-v
                  • +
                  • fa-mercury
                  • +
                  • fa-neuter
                  • +
                  • fa-transgender
                  • +
                  • fa-transgender-alt
                  • +
                  • fa-venus
                  • +
                  • fa-venus-double
                  • +
                  • fa-venus-mars
                  • +
                  +
                  + +
                  +

                  文件类型

                  +
                  +
                    +
                  • fa-file
                  • +
                  • fa-file-archive-o
                  • +
                  • fa-file-audio-o
                  • +
                  • fa-file-code-o
                  • +
                  • fa-file-excel-o
                  • +
                  • fa-file-image-o
                  • +
                  • fa-file-video-o
                  • +
                  • fa-file-o
                  • +
                  • fa-file-pdf-o
                  • +
                  • fa-file-powerpoint-o
                  • +
                  • fa-file-text
                  • +
                  • fa-file-text-o
                  • +
                  • fa-file-word-o
                  • +
                  +
                  + +
                  +

                  旋转加载

                  +
                  +
                    +
                  • fa-cog
                  • +
                  • fa-circle-o-notch
                  • +
                  • fa-refresh
                  • +
                  • fa-spinner
                  • +
                  +
                  + +
                  +

                  表单控件

                  +
                  +
                    +
                  • fa-check-square
                  • +
                  • fa-check-square-o
                  • +
                  • fa-circle
                  • +
                  • fa-circle-o
                  • +
                  • fa-dot-circle-o
                  • +
                  • fa-minus-square
                  • +
                  • fa-minus-square-o
                  • +
                  • fa-plus-square
                  • +
                  • fa-plus-square-o
                  • +
                  • fa-square
                  • +
                  • fa-square-o
                  • +
                  +
                  + +
                  +

                  支付方式

                  +
                  +
                    +
                  • fa-cc-amex
                  • +
                  • fa-cc-discover
                  • +
                  • fa-cc-mastercard
                  • +
                  • fa-cc-paypal
                  • +
                  • fa-cc-stripe
                  • +
                  • fa-cc-visa
                  • +
                  • fa-credit-card
                  • +
                  • fa-google-wallet
                  • +
                  • fa-paypal
                  • +
                  +
                  + +
                  +

                  统计

                  +
                  +
                    +
                  • fa-area-chart
                  • +
                  • fa-bar-chart
                  • +
                  • fa-line-chart
                  • +
                  • fa-pie-chart
                  • +
                  +
                  + +
                  +

                  货币

                  +
                  +
                    +
                  • fa-btc
                  • +
                  • fa-jpy
                  • +
                  • fa-usd
                  • +
                  • fa-eur
                  • +
                  • fa-gbp
                  • +
                  • fa-ils
                  • +
                  • fa-inr
                  • +
                  • fa-krw
                  • +
                  • fa-money
                  • +
                  • fa-rub
                  • +
                  • fa-try
                  • +
                  +
                  + +
                  +

                  文本编辑

                  +
                  +
                    +
                  • fa-align-center
                  • +
                  • fa-align-justify
                  • +
                  • fa-align-left
                  • +
                  • fa-align-right
                  • +
                  • fa-bold
                  • +
                  • fa-font
                  • +
                  • fa-italic
                  • +
                  • fa-header
                  • +
                  • fa-underline
                  • +
                  • fa-text-width
                  • +
                  • fa-text-height
                  • +
                  • fa-strikethrough
                  • +
                  • fa-subscript
                  • +
                  • fa-superscript
                  • +
                  • fa-link
                  • +
                  • fa-chain-broken
                  • +
                  • fa-clipboard
                  • +
                  • fa-files-o
                  • +
                  • fa-scissors
                  • +
                  • fa-columns
                  • +
                  • fa-eraser
                  • +
                  • fa-file
                  • +
                  • fa-file-o
                  • +
                  • fa-file-text
                  • +
                  • fa-file-text-o
                  • +
                  • fa-floppy-o
                  • +
                  • fa-repeat
                  • +
                  • fa-undo
                  • +
                  • fa-outdent
                  • +
                  • fa-indent
                  • +
                  • fa-list
                  • +
                  • fa-list-alt
                  • +
                  • fa-list-ol
                  • +
                  • fa-list-ul
                  • +
                  • fa-paperclip
                  • +
                  • fa-paragraph
                  • +
                  • fa-table
                  • +
                  • fa-th
                  • +
                  • fa-th-large
                  • +
                  • fa-th-list
                  • +
                  +
                  + +
                  +

                  方向性

                  +
                  +
                    +
                  • fa-angle-double-down
                  • +
                  • fa-angle-double-left
                  • +
                  • fa-angle-double-right
                  • +
                  • fa-angle-double-up
                  • +
                  • fa-angle-down
                  • +
                  • fa-angle-left
                  • +
                  • fa-angle-right
                  • +
                  • fa-angle-up
                  • +
                  • fa-arrow-circle-down
                  • +
                  • fa-arrow-circle-left
                  • +
                  • fa-arrow-circle-right
                  • +
                  • fa-arrow-circle-up
                  • +
                  • fa-arrow-circle-o-down
                  • +
                  • fa-arrow-circle-o-left
                  • +
                  • fa-arrow-circle-o-right
                  • +
                  • fa-arrow-circle-o-up
                  • +
                  • fa-arrow-down
                  • +
                  • fa-arrow-left
                  • +
                  • fa-arrow-right
                  • +
                  • fa-arrow-up
                  • +
                  • fa-arrows
                  • +
                  • fa-arrows-alt
                  • +
                  • fa-arrows-h
                  • +
                  • fa-arrows-v
                  • +
                  • fa-caret-down
                  • +
                  • fa-caret-left
                  • +
                  • fa-caret-right
                  • +
                  • fa-caret-up
                  • +
                  • fa-caret-square-o-down
                  • +
                  • fa-caret-square-o-left
                  • +
                  • fa-caret-square-o-right
                  • +
                  • fa-caret-square-o-up
                  • +
                  • fa-chevron-circle-down
                  • +
                  • fa-chevron-circle-left
                  • +
                  • fa-chevron-circle-right
                  • +
                  • fa-chevron-circle-up
                  • +
                  • fa-chevron-down
                  • +
                  • fa-chevron-left
                  • +
                  • fa-chevron-right
                  • +
                  • fa-chevron-up
                  • +
                  • fa-hand-o-down
                  • +
                  • fa-hand-o-left
                  • +
                  • fa-hand-o-right
                  • +
                  • fa-hand-o-up
                  • +
                  • fa-long-arrow-down
                  • +
                  • fa-long-arrow-left
                  • +
                  • fa-long-arrow-right
                  • +
                  • fa-long-arrow-up
                  • +
                  +
                  + +
                  +

                  播放器控件

                  +
                  +
                    +
                  • fa-arrows-alt
                  • +
                  • fa-backward
                  • +
                  • fa-compress
                  • +
                  • fa-eject
                  • +
                  • fa-expand
                  • +
                  • fa-fast-backward
                  • +
                  • fa-fast-forward
                  • +
                  • fa-forward
                  • +
                  • fa-pause
                  • +
                  • fa-play
                  • +
                  • fa-play-circle
                  • +
                  • fa-play-circle-o
                  • +
                  • fa-step-backward
                  • +
                  • fa-step-forward
                  • +
                  • fa-stop
                  • +
                  • fa-youtube-play
                  • +
                  • fa-volume-off
                  • +
                  • fa-volume-down
                  • +
                  • fa-volume-up
                  • +
                  • fa-random
                  • +
                  +
                  + +
                  +

                  医疗

                  +
                  +
                    +
                  • fa-ambulance
                  • +
                  • fa-h-square
                  • +
                  • fa-heart
                  • +
                  • fa-heart-o
                  • +
                  • fa-heartbeat
                  • +
                  • fa-hospital-o
                  • +
                  • fa-medkit
                  • +
                  • fa-plus-square
                  • +
                  • fa-stethoscope
                  • +
                  • fa-user-md
                  • +
                  • fa-wheelchair
                  • +
                  +
                  + +
                  +

                  品牌

                  +
                  +
                    +
                  • fa-adn
                  • +
                  • fa-android
                  • +
                  • fa-angellist
                  • +
                  • fa-apple
                  • +
                  • fa-behance
                  • +
                  • fa-behance-square
                  • +
                  • fa-bitbucket
                  • +
                  • fa-bitbucket-square
                  • +
                  • fa-btc
                  • +
                  • fa-buysellads
                  • +
                  • fa-cc-amex
                  • +
                  • fa-cc-discover
                  • +
                  • fa-cc-mastercard
                  • +
                  • fa-cc-paypal
                  • +
                  • fa-cc-stripe
                  • +
                  • fa-cc-visa
                  • +
                  • fa-codepen
                  • +
                  • fa-connectdevelop
                  • +
                  • fa-css3
                  • +
                  • fa-dashcube
                  • +
                  • fa-delicious
                  • +
                  • fa-deviantart
                  • +
                  • fa-digg
                  • +
                  • fa-dribbble
                  • +
                  • fa-dropbox
                  • +
                  • fa-drupal
                  • +
                  • fa-empire
                  • +
                  • fa-facebook
                  • +
                  • fa-facebook-official
                  • +
                  • fa-facebook-square
                  • +
                  • fa-flickr
                  • +
                  • fa-forumbee
                  • +
                  • fa-foursquare
                  • +
                  • fa-git
                  • +
                  • fa-git-square
                  • +
                  • fa-github
                  • +
                  • fa-github-alt
                  • +
                  • fa-github-square
                  • +
                  • fa-gratipay
                  • +
                  • fa-google
                  • +
                  • fa-google-plus
                  • +
                  • fa-google-plus-square
                  • +
                  • fa-google-wallet
                  • +
                  • fa-hacker-news
                  • +
                  • fa-html5
                  • +
                  • fa-instagram
                  • +
                  • fa-ioxhost
                  • +
                  • fa-joomla
                  • +
                  • fa-jsfiddle
                  • +
                  • fa-lastfm
                  • +
                  • fa-lastfm-square
                  • +
                  • fa-leanpub
                  • +
                  • fa-linkedin
                  • +
                  • fa-linkedin-square
                  • +
                  • fa-linux
                  • +
                  • fa-maxcdn
                  • +
                  • fa-meanpath
                  • +
                  • fa-medium
                  • +
                  • fa-openid
                  • +
                  • fa-pagelines
                  • +
                  • fa-paypal
                  • +
                  • fa-pied-piper
                  • +
                  • fa-pied-piper-alt
                  • +
                  • fa-pinterest
                  • +
                  • fa-pinterest-p
                  • +
                  • fa-pinterest-square
                  • +
                  • fa-qq
                  • +
                  • fa-rebel
                  • +
                  • fa-reddit
                  • +
                  • fa-reddit-square
                  • +
                  • fa-renren
                  • +
                  • fa-sellsy
                  • +
                  • fa-share-alt
                  • +
                  • fa-share-alt-square
                  • +
                  • fa-shirtsinbulk
                  • +
                  • fa-simplybuilt
                  • +
                  • fa-skyatlas
                  • +
                  • fa-skype
                  • +
                  • fa-slack
                  • +
                  • fa-slideshare
                  • +
                  • fa-soundcloud
                  • +
                  • fa-spotify
                  • +
                  • fa-stack-exchange
                  • +
                  • fa-stack-overflow
                  • +
                  • fa-steam
                  • +
                  • fa-steam-square
                  • +
                  • fa-stumbleupon
                  • +
                  • fa-stumbleupon-circle
                  • +
                  • fa-tencent-weibo
                  • +
                  • fa-trello
                  • +
                  • fa-tumblr
                  • +
                  • fa-tumblr-square
                  • +
                  • fa-twitch
                  • +
                  • fa-twitter
                  • +
                  • fa-twitter-square
                  • +
                  • fa-viacoin
                  • +
                  • fa-vimeo-square
                  • +
                  • fa-vine
                  • +
                  • fa-vk
                  • +
                  • fa-weixin
                  • +
                  • fa-weibo
                  • +
                  • fa-whatsapp
                  • +
                  • fa-windows
                  • +
                  • fa-wordpress
                  • +
                  • fa-xing
                  • +
                  • fa-xing-square
                  • +
                  • fa-yahoo
                  • +
                  • fa-yelp
                  • +
                  • fa-youtube
                  • +
                  • fa-youtube-play
                  • +
                  • fa-youtube-square
                  • +
                  +
                  +
                  +
                  + + + diff --git a/WaterCloud.Web/wwwroot/page/smartscreen.html b/WaterCloud.Web/wwwroot/page/smartscreen.html new file mode 100644 index 0000000..bc6c0d4 --- /dev/null +++ b/WaterCloud.Web/wwwroot/page/smartscreen.html @@ -0,0 +1,1047 @@ + + + + + 智慧大屏-水之云出品 + + + + + + + + + + + + + + + +
                  +
                  页面加载中...
                  +
                  +
                  +

                  智慧大屏-水之云出品

                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  模块A
                  +
                  +
                  +
                  +
                  +
                  模块B
                  +
                  +
                  +
                  +
                  +
                  模块C
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                    +
                  • 12581189
                  • +
                  • 3912410
                  • +
                  +
                  +
                  +
                    +
                  • 计划数量
                  • +
                  • 实际数量
                  • +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  模块D
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  模块E
                  +
                  +
                  +
                  +
                  +
                  模块F
                  +
                  +
                  +
                  +
                  +
                  模块G
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + + + + + + diff --git a/WaterCloud.Web/wwwroot/page/table-select.html b/WaterCloud.Web/wwwroot/page/table-select.html new file mode 100644 index 0000000..657132c --- /dev/null +++ b/WaterCloud.Web/wwwroot/page/table-select.html @@ -0,0 +1,182 @@ + + + + + table下拉选择器 + + + + +
                  +
                  + +
                  + table下拉选择器使用开源项目:TableSelect
                  + 在开源的基础上修改支持多条件搜索、宽以及高的自定义
                  + TableSelect +
                  + +
                  +
                  + +
                  + +
                  +
                  本地演示数据,分页选中和其他页一样,这不是BUG
                  +
                  + +
                  + +
                  + +
                  +
                  + +
                  + +
                  + +
                  +
                  + +
                  + +
                  +
                  +            //开始使用
                  +            var tableSelect = layui.tableSelect;
                  +            tableSelect.render({
                  +                elem: '#demo',	//定义输入框input对象 必填
                  +                checkedKey: 'id', //表格的唯一建值,非常重要,影响到选中状态 必填
                  +                searchKey: 'keyword',	//搜索输入框的name值 默认keyword
                  +                searchPlaceholder: '关键词搜索',	//搜索输入框的提示文字 默认关键词搜索
                  +                height:'400',  //自定义高度
                  +                width:'900',  //自定义宽度
                  +                table: {	//定义表格参数,与LAYUI的TABLE模块一致,只是无需再定义表格elem
                  +                    url:'',
                  +                    cols: [[]]
                  +                },
                  +                done: function (elem, data) {
                  +                //选择完后的回调,包含2个返回值 elem:返回之前input对象;data:表格返回的选中的数据 []
                  +                //拿到data[]后 就按照业务需求做想做的事情啦~比如加个隐藏域放ID...
                  +                }
                  +            })
                  +
                  +            //默认值
                  +            只需要在触发input上添加 ts-selected="1,2,3" 属性即可 值需与checkedKey对应
                  +
                  +            //多条件搜索
                  +            tableSelect.render({
                  +                elem: '#demo3',
                  +                checkedKey: 'id',
                  +                searchType: 'more', //开启多条件搜索
                  +                searchList: [
                  +                    {searchKey: 'name', searchPlaceholder: '搜索用户姓名'}, //搜索条件1
                  +                    {searchKey: 'sex', searchPlaceholder: '搜索用户性别'},  //搜索条件2
                  +                ],
                  +                table: {
                  +                    url: '../api/tableSelect.json',
                  +                    cols: [[
                  +                        { type: 'radio' },
                  +                        { field: 'id', title: 'ID' },
                  +                        { field: 'username', title: '姓名' },
                  +                        { field: 'sex', title: '性别' }
                  +                    ]]
                  +                },
                  +                done: function (elem, data) {
                  +                //选择完后的回调,包含2个返回值 elem:返回之前input对象;data:表格返回的选中的数据 []
                  +                //拿到data[]后 就按照业务需求做想做的事情啦~比如加个隐藏域放ID...
                  +                }
                  +            })
                  +        
                  + +
                  +
                  + + + + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/page/upload.html b/WaterCloud.Web/wwwroot/page/upload.html new file mode 100644 index 0000000..9072692 --- /dev/null +++ b/WaterCloud.Web/wwwroot/page/upload.html @@ -0,0 +1,110 @@ + + + + + zyupload上传实例 + + + + + +
                  +
                  +
                  + 上传组件使用开源项目:zyupload
                  + zyupload +
                  +
                  +
                  +        // 初始化插件
                  +        $("#zyupload").zyUpload({
                  +            width: "650px",                 // 宽度
                  +            height: "400px",                 // 宽度
                  +            itemWidth: "140px",                 // 文件项的宽度
                  +            itemHeight: "115px",                 // 文件项的高度
                  +            url: "api/upload",  // 上传文件的路径
                  +            fileType: ["jpg", "png", "txt", "js", "exe"],// 上传文件的类型
                  +            fileSize: 51200000,                // 上传文件的大小
                  +            multiple: true,                    // 是否可以多个文件上传
                  +            dragDrop: true,                    // 是否可以拖动上传文件
                  +            tailor: true,                    // 是否可以裁剪图片
                  +            del: true,                    // 是否可以删除文件
                  +            finishDel: false,  				  // 是否在上传文件完成后删除预览
                  +            /* 外部获得的回调接口 */
                  +            onSelect: function (selectFiles, allFiles) {    // 选择文件的回调方法  selectFile:当前选中的文件  allFiles:还没上传的全部文件
                  +                console.info("当前选择了以下文件:");
                  +                console.info(selectFiles);
                  +            },
                  +            onDelete: function (file, files) {              // 删除一个文件的回调方法 file:当前删除的文件  files:删除之后的文件
                  +                console.info("当前删除了此文件:");
                  +                console.info(file.name);
                  +            },
                  +            onSuccess: function (file, response) {          // 文件上传成功的回调方法
                  +                console.info("此文件上传成功:");
                  +                console.info(file.name);
                  +                console.info("此文件上传到服务器地址:");
                  +                console.info(response);
                  +                $("#uploadInf").append("

                  上传成功,文件地址是:" + response + "

                  "); + }, + onFailure: function (file, response) { // 文件上传失败的回调方法 + console.info("此文件上传失败:"); + console.info(file.name); + }, + onComplete: function (response) { // 上传完成的回调方法 + console.info("文件上传完成"); + console.info(response); + } + }); +
                  +
                  +
                  + + + + + + + \ No newline at end of file diff --git a/WaterCloud.Web/wwwroot/page/welcome-1.html b/WaterCloud.Web/wwwroot/page/welcome-1.html new file mode 100644 index 0000000..c45d06a --- /dev/null +++ b/WaterCloud.Web/wwwroot/page/welcome-1.html @@ -0,0 +1,455 @@ + + + + + 首页二 + + + + + + + + + +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  数据统计
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + 实时 +
                  用户统计
                  +
                  +
                  +

                  1234

                  + 当前分类总记录数 +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + 实时 +
                  商品统计
                  +
                  +
                  +

                  1234

                  + 当前分类总记录数 +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + 实时 +
                  浏览统计
                  +
                  +
                  +

                  1234

                  + 当前分类总记录数 +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + 实时 +
                  订单统计
                  +
                  +
                  +

                  1234

                  + 当前分类总记录数 +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + +
                  +
                  +
                  报表统计
                  +
                  +
                  +
                  +
                  +
                  +
                  +
                  + +
                  + +
                  +
                  系统公告
                  +
                  +
                  +
                  修改选项卡样式
                  +
                  2019-07-11 23:06
                  +
                  + 界面足够简洁清爽。
                  + 一个接口几行代码而已直接初始化整个框架,无需复杂操作。
                  + 支持多tab,可以打开多窗口。
                  + 支持无限级菜单和对font-awesome图标库的完美支持。
                  + 失效以及报错菜单无法直接打开,并给出弹出层提示完美的线上用户体验。
                  + url地址hash定位,可以清楚看到当前tab的地址信息。
                  + 刷新页面会保留当前的窗口,并且会定位当前窗口对应左侧菜单栏。
                  + 移动端的友好支持。
                  +
                  +
                  +
                  +
                  新增系统404模板
                  +
                  2019-07-11 12:57
                  +
                  + 界面足够简洁清爽。
                  + 一个接口几行代码而已直接初始化整个框架,无需复杂操作。
                  + 支持多tab,可以打开多窗口。
                  + 支持无限级菜单和对font-awesome图标库的完美支持。
                  + 失效以及报错菜单无法直接打开,并给出弹出层提示完美的线上用户体验。
                  + url地址hash定位,可以清楚看到当前tab的地址信息。
                  + 刷新页面会保留当前的窗口,并且会定位当前窗口对应左侧菜单栏。
                  + 移动端的友好支持。
                  +
                  +
                  +
                  +
                  新增treetable插件和菜单管理样式
                  +
                  2019-07-05 14:28
                  +
                  + 界面足够简洁清爽。
                  + 一个接口几行代码而已直接初始化整个框架,无需复杂操作。
                  + 支持多tab,可以打开多窗口。
                  + 支持无限级菜单和对font-awesome图标库的完美支持。
                  + 失效以及报错菜单无法直接打开,并给出弹出层提示完美的线上用户体验。
                  + url地址hash定位,可以清楚看到当前tab的地址信息。
                  + 刷新页面会保留当前的窗口,并且会定位当前窗口对应左侧菜单栏。
                  + 移动端的友好支持。
                  +
                  +
                  +
                  +
                  修改logo缩放问题
                  +
                  2019-07-04 11:02
                  +
                  + 界面足够简洁清爽。
                  + 一个接口几行代码而已直接初始化整个框架,无需复杂操作。
                  + 支持多tab,可以打开多窗口。
                  + 支持无限级菜单和对font-awesome图标库的完美支持。
                  + 失效以及报错菜单无法直接打开,并给出弹出层提示完美的线上用户体验。
                  + url地址hash定位,可以清楚看到当前tab的地址信息。
                  + 刷新页面会保留当前的窗口,并且会定位当前窗口对应左侧菜单栏。
                  + 移动端的友好支持。
                  +
                  +
                  +
                  +
                  修复左侧菜单缩放tab无法移动
                  +
                  2019-06-17 11:55
                  +
                  + 界面足够简洁清爽。
                  + 一个接口几行代码而已直接初始化整个框架,无需复杂操作。
                  + 支持多tab,可以打开多窗口。
                  + 支持无限级菜单和对font-awesome图标库的完美支持。
                  + 失效以及报错菜单无法直接打开,并给出弹出层提示完美的线上用户体验。
                  + url地址hash定位,可以清楚看到当前tab的地址信息。
                  + 刷新页面会保留当前的窗口,并且会定位当前窗口对应左侧菜单栏。
                  + 移动端的友好支持。
                  +
                  +
                  +
                  +
                  修复多模块菜单栏展开有问题
                  +
                  2019-06-13 14:53
                  +
                  + 界面足够简洁清爽。
                  + 一个接口几行代码而已直接初始化整个框架,无需复杂操作。
                  + 支持多tab,可以打开多窗口。
                  + 支持无限级菜单和对font-awesome图标库的完美支持。
                  + 失效以及报错菜单无法直接打开,并给出弹出层提示完美的线上用户体验。
                  + url地址hash定位,可以清楚看到当前tab的地址信息。
                  + 刷新页面会保留当前的窗口,并且会定位当前窗口对应左侧菜单栏。
                  + 移动端的友好支持。
                  +
                  +
                  +
                  +
                  + +
                  +
                  版本信息
                  +
                  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                  框架名称 + layuimini +
                  当前版本v2.0.0
                  主要特色零门槛 / 响应式 / 清爽 / 极简
                  演示地址 + iframe版-v2:点击查看
                  + 单页版-v2:点击查看
                  +
                  下载地址 + iframe版-v2:github / gitee
                  + 单页版-v2:github / gitee
                  +
                  Gitee +
                  + star + fork +
                  +
                  Github +
                  + + +
                  +
                  +
                  +
                  + +
                  +
                  作者心语
                  +
                  +

                  本模板基于layui2.5.4以及font-awesome-4.7.0进行实现。layui开发文档地址:layui文档

                  +

                  技术交流QQ群(667813249):layuimini(加群请备注来源:如gitee、github、官网等)

                  +

                  喜欢此后台模板的可以给我的GitHub和Gitee加个Star支持一下

                  +
                  +
                  + +
                  +
                  +
                  +
                  + + + + + diff --git a/WaterCloud.Web/wwwroot/picture/digitization.jpg b/WaterCloud.Web/wwwroot/picture/digitization.jpg new file mode 100644 index 0000000..80b13bb Binary files /dev/null and b/WaterCloud.Web/wwwroot/picture/digitization.jpg differ diff --git a/WaterCloud.Web/wwwroot/picture/head_bg.png b/WaterCloud.Web/wwwroot/picture/head_bg.png new file mode 100644 index 0000000..a2e45f6 Binary files /dev/null and b/WaterCloud.Web/wwwroot/picture/head_bg.png differ diff --git a/WaterCloud.Web/wwwroot/picture/jt.png b/WaterCloud.Web/wwwroot/picture/jt.png new file mode 100644 index 0000000..1eb5cb0 Binary files /dev/null and b/WaterCloud.Web/wwwroot/picture/jt.png differ diff --git a/WaterCloud.Web/wwwroot/picture/lbx.png b/WaterCloud.Web/wwwroot/picture/lbx.png new file mode 100644 index 0000000..cefb215 Binary files /dev/null and b/WaterCloud.Web/wwwroot/picture/lbx.png differ diff --git a/WaterCloud.Web/wwwroot/picture/line.png b/WaterCloud.Web/wwwroot/picture/line.png new file mode 100644 index 0000000..05db7f8 Binary files /dev/null and b/WaterCloud.Web/wwwroot/picture/line.png differ diff --git a/WaterCloud.Web/wwwroot/picture/loading.gif b/WaterCloud.Web/wwwroot/picture/loading.gif new file mode 100644 index 0000000..db3a483 Binary files /dev/null and b/WaterCloud.Web/wwwroot/picture/loading.gif differ diff --git a/WaterCloud.Web/wwwroot/picture/map.png b/WaterCloud.Web/wwwroot/picture/map.png new file mode 100644 index 0000000..2138288 Binary files /dev/null and b/WaterCloud.Web/wwwroot/picture/map.png differ diff --git a/WaterCloud3.sln b/WaterCloud3.sln new file mode 100644 index 0000000..302ce70 --- /dev/null +++ b/WaterCloud3.sln @@ -0,0 +1,55 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32112.339 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WaterCloud.Web", "WaterCloud.Web\WaterCloud.Web.csproj", "{FE158A99-8B94-4F95-9DAA-AC14B7738BB7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WaterCloud.Code", "WaterCloud.Code\WaterCloud.Code.csproj", "{2F494D2F-8687-46B6-A6D3-C183B7E1B3EB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WaterCloud.DataBase", "WaterCloud.Data\WaterCloud.DataBase.csproj", "{586E88DF-7EFA-4281-9371-EA45B877C9A4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WaterCloud.Domain", "WaterCloud.Domain\WaterCloud.Domain.csproj", "{40732569-0516-4E72-9475-06A217998944}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WaterCloud.CodeGenerator", "WaterCloud.CodeGenerator\WaterCloud.CodeGenerator.csproj", "{25C1E690-0B45-4994-87C0-F1997F4227A6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WaterCloud.Service", "WaterCloud.Service\WaterCloud.Service.csproj", "{55C15DA5-2666-4EE2-81F4-244AAC5D2691}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FE158A99-8B94-4F95-9DAA-AC14B7738BB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FE158A99-8B94-4F95-9DAA-AC14B7738BB7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FE158A99-8B94-4F95-9DAA-AC14B7738BB7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FE158A99-8B94-4F95-9DAA-AC14B7738BB7}.Release|Any CPU.Build.0 = Release|Any CPU + {2F494D2F-8687-46B6-A6D3-C183B7E1B3EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2F494D2F-8687-46B6-A6D3-C183B7E1B3EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F494D2F-8687-46B6-A6D3-C183B7E1B3EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F494D2F-8687-46B6-A6D3-C183B7E1B3EB}.Release|Any CPU.Build.0 = Release|Any CPU + {586E88DF-7EFA-4281-9371-EA45B877C9A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {586E88DF-7EFA-4281-9371-EA45B877C9A4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {586E88DF-7EFA-4281-9371-EA45B877C9A4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {586E88DF-7EFA-4281-9371-EA45B877C9A4}.Release|Any CPU.Build.0 = Release|Any CPU + {40732569-0516-4E72-9475-06A217998944}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {40732569-0516-4E72-9475-06A217998944}.Debug|Any CPU.Build.0 = Debug|Any CPU + {40732569-0516-4E72-9475-06A217998944}.Release|Any CPU.ActiveCfg = Release|Any CPU + {40732569-0516-4E72-9475-06A217998944}.Release|Any CPU.Build.0 = Release|Any CPU + {25C1E690-0B45-4994-87C0-F1997F4227A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {25C1E690-0B45-4994-87C0-F1997F4227A6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {25C1E690-0B45-4994-87C0-F1997F4227A6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {25C1E690-0B45-4994-87C0-F1997F4227A6}.Release|Any CPU.Build.0 = Release|Any CPU + {55C15DA5-2666-4EE2-81F4-244AAC5D2691}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {55C15DA5-2666-4EE2-81F4-244AAC5D2691}.Debug|Any CPU.Build.0 = Debug|Any CPU + {55C15DA5-2666-4EE2-81F4-244AAC5D2691}.Release|Any CPU.ActiveCfg = Release|Any CPU + {55C15DA5-2666-4EE2-81F4-244AAC5D2691}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {30EA3764-674F-48E9-908A-3B962BD30291} + EndGlobalSection +EndGlobal diff --git a/codeql-analysis.yml b/codeql-analysis.yml new file mode 100644 index 0000000..7929979 --- /dev/null +++ b/codeql-analysis.yml @@ -0,0 +1,70 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ net5-SqlSugar ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ net5-SqlSugar ] + schedule: + - cron: '27 1 * * 5' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'csharp', 'javascript' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://git.io/codeql-language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1