diff --git a/index.html b/index.html new file mode 100644 index 000000000..643c31b06 --- /dev/null +++ b/index.html @@ -0,0 +1,688 @@ + + + + + + + OpenI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + +
+ + + + + + +
+
+
+

+ Explore Better AI +
+ OpenI AI Development Cooperation Platform +
+

+

The one-stop collaborative development environment for AI field provides AI development pipeline integrating code development, data management, model debugging, reasoning and evaluation

+ + + Use Now + +
+
+
+

* Only show the dynamics of open source projects

+
+
+
+
+ +
+
+
+
+
+ +
+
+ + +
+
+
+

Recommended Organizations

+

These excellent organizations are using the OpenI AI Collaboration Platform for collaborative development of projects. To show your organization here, Click here to submit.

+ More Organizations +
+
+
+
+ +
+
+ +
+
+ +
+

Community Activities

+

The community has prepared a wealth of activities, waiting for you to participate!

+
+
+
+
+ +
+
+
+
+
+ +
+
+ + +
+
+
+
+

Recommended Projects

+

Excellent AI projects recommendation. To show your project here, Click here to submit.Click here to explore more projects.

+
+ +
+
+ +
+
+
+ +
+ +
+
+
+

智算网络

+

人工智能算力网络推进联盟已接入10家智算中心,算力总规模1542P

+
+ +
+ + +
+ +
+ + +
+
+
+
+
+ +

+
+
+
+
+
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+
+
+
+
+
+
+ + +
+ +
+

Collaborative Development Environment

+

Provide a collaborative development environment for AI development, which is the biggest highlight that distinguishes the OpenI AI Collaboration Platform from other traditional Git platforms.

+
+
+
+
+ +
+
+

Unified Management of Development Elements

+
+ The platform provides four elements of AI development: unified management of model code, data set, model and execution environment. +
+
+
+
+
+ +
+
+

Data Collaboration and Sharing

+
+ By uploading data sets in the project, many project members cooperate to complete data preprocessing. You can also establish a better model with community developers by setting the data as a public dataset. +
+
+
+
+
+ +
+
+

Model Management and Sharing

+
+ Associate the model with the code version, you can adjust the model in different ways based on the historical version of the code and save the results. The trained model can be open and shared, so that more people can use the model to test and give feedback. +
+
+
+
+
+ +
+
+

Once Configuration, Multiple Reuse

+
+ Provide execution environment sharing, Once Configuration, Multiple Reuse. Lower the threshold of model development, and avoid spending repetitive time configuring complex environments. +
+
+
+
+
+ + +
+
+
+
+ +
+
+

PengCheng Cloudbrain Open Source Collaboration

+

+ The platform has been connected with Pengcheng Cloudbrain and can use the rich computing resources of Pengcheng Cloudbrain to complete AI development tasks.
+ Pengcheng Cloudbrain's existing AI computing power is 100p FLOPS@FP16 (billions of half precision floating-point calculations per second), the main hardware infrastructure is composed of GPU server equipped with NVIDIA Tesla V100 and Atlas 900 AI cluster equipped with Kunpeng and Ascend processors.
+ Developers can freely choose the corresponding computing resources according to their needs, and can test the adaptability, performance, stability of the model in different hardware environments.
+ If your model requires more computing resources, you can also apply for it separately.
+

+ + + Use Now + + + Apply Separately +
+
+
+
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/models/ai_model_manage.go b/models/ai_model_manage.go index ed696fcf0..0ea01d6e5 100644 --- a/models/ai_model_manage.go +++ b/models/ai_model_manage.go @@ -2,6 +2,7 @@ package models import ( "fmt" + "time" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -39,6 +40,40 @@ type AiModelManage struct { IsCanDelete bool } +type AiModelConvert struct { + ID string `xorm:"pk"` + Name string `xorm:"INDEX NOT NULL"` + Status string `xorm:"NULL"` + StatusResult string `xorm:"NULL"` + SrcEngine int `xorm:"NOT NULL DEFAULT 0"` + RepoId int64 `xorm:"INDEX NULL"` + ModelId string `xorm:"NOT NULL"` + ModelName string `xorm:"NULL"` + ModelVersion string `xorm:"NOT NULL"` + ModelPath string `xorm:"NULL"` + DestFormat int `xorm:"NOT NULL DEFAULT 0"` + NetOutputFormat int `xorm:"NULL"` + UserId int64 `xorm:"NOT NULL"` + CloudBrainTaskId string `xorm:"NULL"` + ModelArtsVersionId string `xorm:"NULL"` + ContainerID string + ContainerIp string + RunTime int64 `xorm:"NULL"` + TrainJobDuration string + InputShape string `xorm:"varchar(2000)"` + InputDataFormat string `xorm:"NOT NULL"` + Description string `xorm:"varchar(2000)"` + Path string `xorm:"varchar(400) NOT NULL"` + CreatedUnix timeutil.TimeStamp `xorm:"created"` + UpdatedUnix timeutil.TimeStamp `xorm:"updated"` + StartTime timeutil.TimeStamp + EndTime timeutil.TimeStamp + UserName string + UserRelAvatarLink string + IsCanOper bool + IsCanDelete bool +} + type AiModelQueryOptions struct { ListOptions RepoID int64 // include all repos if empty @@ -47,7 +82,124 @@ type AiModelQueryOptions struct { SortType string New int // JobStatus CloudbrainStatus - Type int + Type int + Status int +} + +func (a *AiModelConvert) IsGpuTrainTask() bool { + if a.SrcEngine == 0 || a.SrcEngine == 1 { + return true + } + return false +} + +func ModelComputeAndSetDuration(task *AiModelConvert, result JobResultPayload) { + if task.StartTime == 0 { + task.StartTime = timeutil.TimeStamp(result.JobStatus.CreatedTime / 1000) + } + if task.EndTime == 0 { + if result.JobStatus.CompletedTime > 0 { + task.EndTime = timeutil.TimeStamp(result.JobStatus.CompletedTime / 1000) + } + } + var d int64 + if task.StartTime == 0 { + d = 0 + } else if task.EndTime == 0 { + d = time.Now().Unix() - task.StartTime.AsTime().Unix() + } else { + d = task.EndTime.AsTime().Unix() - task.StartTime.AsTime().Unix() + } + + if d < 0 { + d = 0 + } + task.RunTime = d + task.TrainJobDuration = ConvertDurationToStr(d) +} + +func ModelConvertSetDuration(task *AiModelConvert) { + var d int64 + if task.StartTime == 0 { + d = 0 + } else if task.EndTime == 0 { + d = time.Now().Unix() - task.StartTime.AsTime().Unix() + } else { + d = task.EndTime.AsTime().Unix() - task.StartTime.AsTime().Unix() + } + + if d < 0 { + d = 0 + } + task.RunTime = d + task.TrainJobDuration = ConvertDurationToStr(d) +} + +func UpdateModelConvertModelArts(id string, CloudBrainTaskId string, VersionId string) error { + var sess *xorm.Session + sess = x.ID(id) + defer sess.Close() + re, err := sess.Cols("cloud_brain_task_id,model_arts_version_id").Update(&AiModelConvert{ + CloudBrainTaskId: CloudBrainTaskId, + ModelArtsVersionId: VersionId, + }) + if err != nil { + return err + } + log.Info("success to update cloud_brain_task_id from db.re=" + fmt.Sprint((re))) + return nil +} + +func UpdateModelConvertFailed(id string, status string, statusResult string) error { + var sess *xorm.Session + sess = x.ID(id) + defer sess.Close() + re, err := sess.Cols("status", "status_result").Update(&AiModelConvert{ + Status: status, + StatusResult: statusResult, + }) + if err != nil { + return err + } + log.Info("success to update cloud_brain_task_id from db.re=" + fmt.Sprint((re))) + return nil +} + +func UpdateModelConvertCBTI(id string, CloudBrainTaskId string) error { + var sess *xorm.Session + sess = x.ID(id) + defer sess.Close() + re, err := sess.Cols("cloud_brain_task_id").Update(&AiModelConvert{ + CloudBrainTaskId: CloudBrainTaskId, + }) + if err != nil { + return err + } + log.Info("success to update cloud_brain_task_id from db.re=" + fmt.Sprint((re))) + return nil +} + +func UpdateModelConvert(job *AiModelConvert) error { + return updateModelConvert(x, job) +} + +func updateModelConvert(e Engine, job *AiModelConvert) error { + var sess *xorm.Session + sess = e.Where("id = ?", job.ID) + _, err := sess.Cols("status", "train_job_duration", "run_time", "start_time", "end_time", "updated_unix").Update(job) + return err +} + +func SaveModelConvert(modelConvert *AiModelConvert) error { + sess := x.NewSession() + defer sess.Close() + re, err := sess.Insert(modelConvert) + if err != nil { + log.Info("insert modelConvert error." + err.Error()) + return err + } + log.Info("success to save modelConvert db.re=" + fmt.Sprint((re))) + return nil } func SaveModelToDb(model *AiModelManage) error { @@ -63,6 +215,20 @@ func SaveModelToDb(model *AiModelManage) error { return nil } +func QueryModelConvertById(id string) (*AiModelConvert, error) { + sess := x.NewSession() + defer sess.Close() + sess.Select("*").Table(new(AiModelConvert)).Where("id='" + id + "'") + aiModelManageConvertList := make([]*AiModelConvert, 0) + err := sess.Find(&aiModelManageConvertList) + if err == nil { + if len(aiModelManageConvertList) == 1 { + return aiModelManageConvertList[0], nil + } + } + return nil, err +} + func QueryModelById(id string) (*AiModelManage, error) { sess := x.NewSession() defer sess.Close() @@ -74,14 +240,28 @@ func QueryModelById(id string) (*AiModelManage, error) { if len(aiModelManageList) == 1 { return aiModelManageList[0], nil } + } else { + log.Info("error=" + err.Error()) } return nil, err } -func DeleteModelById(id string) error { +func DeleteModelConvertById(id string) error { sess := x.NewSession() defer sess.Close() + re, err := sess.Delete(&AiModelConvert{ + ID: id, + }) + if err != nil { + return err + } + log.Info("success to delete AiModelManageConvert from db.re=" + fmt.Sprint((re))) + return nil +} +func DeleteModelById(id string) error { + sess := x.NewSession() + defer sess.Close() re, err := sess.Delete(&AiModelManage{ ID: id, }) @@ -90,7 +270,6 @@ func DeleteModelById(id string) error { } log.Info("success to delete from db.re=" + fmt.Sprint((re))) return nil - } func ModifyModelDescription(id string, description string) error { @@ -201,3 +380,73 @@ func QueryModel(opts *AiModelQueryOptions) ([]*AiModelManage, int64, error) { return aiModelManages, count, nil } + +func QueryModelConvertByRepoID(repoId int64) ([]*AiModelConvert, error) { + sess := x.NewSession() + defer sess.Close() + var cond = builder.NewCond() + cond = cond.And( + builder.Eq{"ai_model_convert.repo_id": repoId}, + ) + sess.OrderBy("ai_model_convert.created_unix DESC") + aiModelManageConvert := make([]*AiModelConvert, 0) + if err := sess.Table(new(AiModelConvert)).Where(cond). + Find(&aiModelManageConvert); err != nil { + return nil, fmt.Errorf("Find: %v", err) + } + return aiModelManageConvert, nil +} + +func QueryModelConvertByUserID(userID int64) ([]*AiModelConvert, error) { + sess := x.NewSession() + defer sess.Close() + var cond = builder.NewCond() + cond = cond.And( + builder.Eq{"ai_model_convert.user_id": userID}, + ) + sess.OrderBy("ai_model_convert.created_unix DESC") + aiModelManageConvert := make([]*AiModelConvert, 0) + if err := sess.Table(new(AiModelConvert)).Where(cond). + Find(&aiModelManageConvert); err != nil { + return nil, fmt.Errorf("Find: %v", err) + } + return aiModelManageConvert, nil +} + +func QueryModelConvert(opts *AiModelQueryOptions) ([]*AiModelConvert, int64, error) { + sess := x.NewSession() + defer sess.Close() + var cond = builder.NewCond() + if opts.RepoID > 0 { + cond = cond.And( + builder.Eq{"ai_model_convert.repo_id": opts.RepoID}, + ) + } + if opts.UserID > 0 { + cond = cond.And( + builder.Eq{"ai_model_convert.user_id": opts.UserID}, + ) + } + count, err := sess.Where(cond).Count(new(AiModelConvert)) + if err != nil { + return nil, 0, fmt.Errorf("Count: %v", err) + } + + if opts.Page >= 0 && opts.PageSize > 0 { + var start int + if opts.Page == 0 { + start = 0 + } else { + start = (opts.Page - 1) * opts.PageSize + } + sess.Limit(opts.PageSize, start) + } + sess.OrderBy("ai_model_convert.created_unix DESC") + aiModelManageConvert := make([]*AiModelConvert, 0, setting.UI.IssuePagingNum) + if err := sess.Table(new(AiModelConvert)).Where(cond). + Find(&aiModelManageConvert); err != nil { + return nil, 0, fmt.Errorf("Find: %v", err) + } + + return aiModelManageConvert, count, nil +} diff --git a/models/cloudbrain.go b/models/cloudbrain.go index 13be39507..fa15f6ff0 100755 --- a/models/cloudbrain.go +++ b/models/cloudbrain.go @@ -166,12 +166,11 @@ type Cloudbrain struct { FlavorName string //规格名称 EngineName string //引擎名称 TotalVersionCount int //任务的所有版本数量,包括删除的 - - LabelName string //标签名称 - ModelName string //模型名称 - ModelVersion string //模型版本 - CkptName string //权重文件名称 - ResultUrl string //推理结果的obs路径 + LabelName string //标签名称 + ModelName string //模型名称 + ModelVersion string //模型版本 + CkptName string //权重文件名称 + ResultUrl string //推理结果的obs路径 User *User `xorm:"-"` Repo *Repository `xorm:"-"` @@ -308,6 +307,22 @@ type CreateJobResult struct { Payload map[string]interface{} `json:"payload"` } +type QueueDetailResult struct { + Code string `json:"code"` + Msg string `json:"msg"` + Payload map[string]QueueDetail `json:"payload"` +} + +type QueueDetail struct { + JobScheduleInfo JobScheduleInfo `json:"JobScheduleInfo"` +} + +type JobScheduleInfo struct { + Pending int `json:"Pending"` + Running int `json:"Running"` + MedianPendingJobDurationSec int `json:"MedianPendingJobDurationSec"` +} + type GetJobResult struct { Code string `json:"code"` Msg string `json:"msg"` @@ -920,6 +935,28 @@ type NotebookDelResult struct { InstanceID string `json:"instance_id"` } +type CreateUserImageTrainJobParams struct { + JobName string `json:"job_name"` + Description string `json:"job_desc"` + Config UserImageConfig `json:"config"` + WorkspaceID string `json:"workspace_id"` +} + +type UserImageConfig struct { + WorkServerNum int `json:"worker_server_num"` + AppUrl string `json:"app_url"` //训练作业的代码目录 + BootFileUrl string `json:"boot_file_url"` //训练作业的代码启动文件,需要在代码目录下 + Parameter []Parameter `json:"parameter"` + DataUrl string `json:"data_url"` //训练作业需要的数据集OBS路径URL + TrainUrl string `json:"train_url"` //训练作业的输出文件OBS路径URL + LogUrl string `json:"log_url"` + UserImageUrl string `json:"user_image_url"` + UserCommand string `json:"user_command"` + CreateVersion bool `json:"create_version"` + Flavor Flavor `json:"flavor"` + PoolID string `json:"pool_id"` +} + type CreateTrainJobParams struct { JobName string `json:"job_name"` Description string `json:"job_desc"` @@ -967,6 +1004,11 @@ type CreateTrainJobVersionParams struct { Config TrainJobVersionConfig `json:"config"` } +type CreateTrainJobVersionUserImageParams struct { + Description string `json:"job_desc"` + Config TrainJobVersionUserImageConfig `json:"config"` +} + type TrainJobVersionConfig struct { WorkServerNum int `json:"worker_server_num"` AppUrl string `json:"app_url"` //训练作业的代码目录 @@ -981,6 +1023,21 @@ type TrainJobVersionConfig struct { PreVersionId int64 `json:"pre_version_id"` } +type TrainJobVersionUserImageConfig struct { + WorkServerNum int `json:"worker_server_num"` + AppUrl string `json:"app_url"` //训练作业的代码目录 + BootFileUrl string `json:"boot_file_url"` //训练作业的代码启动文件,需要在代码目录下 + Parameter []Parameter `json:"parameter"` + DataUrl string `json:"data_url"` //训练作业需要的数据集OBS路径URL + TrainUrl string `json:"train_url"` //训练作业的输出文件OBS路径URL + LogUrl string `json:"log_url"` + Flavor Flavor `json:"flavor"` + PoolID string `json:"pool_id"` + PreVersionId int64 `json:"pre_version_id"` + UserImageUrl string `json:"user_image_url"` + UserCommand string `json:"user_command"` +} + type CreateConfigParams struct { ConfigName string `json:"config_name"` Description string `json:"config_desc"` @@ -1463,7 +1520,7 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { return cloudbrains, count, nil } -func QueryModelTrainJobVersionList(jobId string) ([]*CloudbrainInfo, int, error) { +func QueryModelTrainJobVersionList(jobId string) ([]*Cloudbrain, int, error) { sess := x.NewSession() defer sess.Close() @@ -1478,7 +1535,7 @@ func QueryModelTrainJobVersionList(jobId string) ([]*CloudbrainInfo, int, error) ) sess.OrderBy("cloudbrain.created_unix DESC") - cloudbrains := make([]*CloudbrainInfo, 0) + cloudbrains := make([]*Cloudbrain, 0) if err := sess.Table(&Cloudbrain{}).Where(cond). Find(&cloudbrains); err != nil { return nil, 0, fmt.Errorf("Find: %v", err) @@ -1500,9 +1557,9 @@ func QueryModelTrainJobList(repoId int64) ([]*CloudbrainInfo, int, error) { cond = cond.And( builder.Eq{"job_type": "TRAIN"}, ) - cond = cond.And( - builder.In("type", 0, 1), - ) + // cond = cond.And( + // builder.In("type", 0, 1), + // ) cloudbrains := make([]*CloudbrainInfo, 0) if err := sess.Select("job_id,display_job_name").Table(&Cloudbrain{}).Where(cond).OrderBy("created_unix DESC"). @@ -1798,6 +1855,17 @@ func GetBenchmarkCountByUserID(userID int64) (int, error) { return int(count), err } +func GetWaitingCloudbrainCount(cloudbrainType int, computeResource string, jobTypes ...JobType) (int64, error) { + sess := x.Where("status=? and type=?", JobWaiting, cloudbrainType) + if len(jobTypes) >= 0 { + sess.In("JobType", jobTypes) + } + if computeResource != "" { + sess.And("compute_resource=?", computeResource) + } + return sess.Count(new(Cloudbrain)) +} + func GetCloudbrainNotebookCountByUserID(userID int64) (int, error) { count, err := x.In("status", ModelArtsCreateQueue, ModelArtsCreating, ModelArtsStarting, ModelArtsReadyToStart, ModelArtsResizing, ModelArtsStartQueuing, ModelArtsRunning, ModelArtsRestarting). And("job_type = ? and user_id = ? and type = ?", JobTypeDebug, userID, TypeCloudBrainTwo).Count(new(Cloudbrain)) diff --git a/models/models.go b/models/models.go index 0459fc0a2..9eee9c9ec 100755 --- a/models/models.go +++ b/models/models.go @@ -145,6 +145,7 @@ func init() { new(OrgStatistic), new(SearchRecord), new(CloudbrainTemp), + new(AiModelConvert), ) tablesStatistic = append(tablesStatistic, diff --git a/models/user_business_analysis.go b/models/user_business_analysis.go index 6471636e3..cb503d669 100644 --- a/models/user_business_analysis.go +++ b/models/user_business_analysis.go @@ -362,7 +362,7 @@ func QueryUserStaticDataByTableName(start int, pageSize int, tableName string, q var cond = builder.NewCond() if len(userName) > 0 { cond = cond.And( - builder.Like{"name", userName}, + builder.Like{"lower(name)", strings.ToLower(userName)}, ) } allCount, err := statictisSess.Where(cond).Count(queryObj) diff --git a/modules/auth/cloudbrain.go b/modules/auth/cloudbrain.go index e5be38084..91fa8ad64 100755 --- a/modules/auth/cloudbrain.go +++ b/modules/auth/cloudbrain.go @@ -50,6 +50,27 @@ type EditImageCloudBrainForm struct { Topics string `form:"topics"` } +type CreateCloudBrainInferencForm struct { + JobName string `form:"job_name" binding:"Required"` + DisplayJobName string `form:"display_job_name" binding:"Required"` + Image string `form:"image" binding:"Required"` + Command string `form:"command" binding:"Required"` + Attachment string `form:"attachment" binding:"Required"` + JobType string `form:"job_type" binding:"Required"` + BenchmarkCategory string `form:"get_benchmark_category"` + GpuType string `form:"gpu_type"` + TrainUrl string `form:"train_url"` + TestUrl string `form:"test_url"` + Description string `form:"description"` + ResourceSpecId int `form:"resource_spec_id" binding:"Required"` + BootFile string `form:"boot_file"` + Params string `form:"run_para_list"` + BranchName string `form:"branch_name"` + ModelName string `form:"model_name" binding:"Required"` + ModelVersion string `form:"model_version" binding:"Required"` + CkptName string `form:"ckpt_name" binding:"Required"` +} + func (f *CreateCloudBrainForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { return validate(errs, ctx.Data, f, ctx.Locale) } @@ -61,3 +82,7 @@ func (f *CommitImageCloudBrainForm) Validate(ctx *macaron.Context, errs binding. func (f *EditImageCloudBrainForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { return validate(errs, ctx.Data, f, ctx.Locale) } + +func (f *CreateCloudBrainInferencForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { + return validate(errs, ctx.Data, f, ctx.Locale) +} diff --git a/modules/cloudbrain/cloudbrain.go b/modules/cloudbrain/cloudbrain.go index 5d6948acb..df5045218 100755 --- a/modules/cloudbrain/cloudbrain.go +++ b/modules/cloudbrain/cloudbrain.go @@ -3,6 +3,7 @@ package cloudbrain import ( "encoding/json" "errors" + "os" "strconv" "code.gitea.io/gitea/modules/timeutil" @@ -37,12 +38,15 @@ const ( Success = "S000" DefaultBranchName = "master" + + ResultPath = "/result" ) var ( - ResourceSpecs *models.ResourceSpecs - TrainResourceSpecs *models.ResourceSpecs - SpecialPools *models.SpecialPools + ResourceSpecs *models.ResourceSpecs + TrainResourceSpecs *models.ResourceSpecs + InferenceResourceSpecs *models.ResourceSpecs + SpecialPools *models.SpecialPools ) type GenerateCloudBrainTaskReq struct { @@ -69,6 +73,11 @@ type GenerateCloudBrainTaskReq struct { BenchmarkTypeID int BenchmarkChildTypeID int ResourceSpecId int + ResultPath string + TrainUrl string + ModelName string + ModelVersion string + CkptName string } func GetCloudbrainDebugCommand() string { @@ -219,7 +228,6 @@ func AdminOrImageCreaterRight(ctx *context.Context) { func GenerateTask(req GenerateCloudBrainTaskReq) error { var resourceSpec *models.ResourceSpec var versionCount int - if req.JobType == string(models.JobTypeTrain) { versionCount = 1 if TrainResourceSpecs == nil { @@ -231,6 +239,17 @@ func GenerateTask(req GenerateCloudBrainTaskReq) error { break } } + } else if req.JobType == string(models.JobTypeInference) { + if InferenceResourceSpecs == nil { + json.Unmarshal([]byte(setting.InferenceResourceSpecs), &InferenceResourceSpecs) + } + for _, spec := range InferenceResourceSpecs.ResourceSpec { + if req.ResourceSpecId == spec.Id { + resourceSpec = spec + break + } + } + } else { if ResourceSpecs == nil { json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) @@ -245,21 +264,7 @@ func GenerateTask(req GenerateCloudBrainTaskReq) error { } //如果没有匹配到spec信息,尝试从专属资源池获取 if resourceSpec == nil && SpecialPools != nil { - for _, specialPool := range SpecialPools.Pools { - if resourceSpec != nil { - break - } - if specialPool.ResourceSpec != nil { - if IsElementExist(specialPool.JobType, req.JobType) && IsQueueInSpecialtPool(specialPool.Pool, req.GpuQueue) { - for _, spec := range specialPool.ResourceSpec { - if req.ResourceSpecId == spec.Id { - resourceSpec = spec - break - } - } - } - } - } + resourceSpec = geMatchResourceSpec(req.JobType, req.GpuQueue, req.ResourceSpecId) } if resourceSpec == nil { @@ -303,6 +308,13 @@ func GenerateTask(req GenerateCloudBrainTaskReq) error { ReadOnly: true, }, }, + { + HostPath: models.StHostPath{ + Path: req.ResultPath, + MountPath: ResultPath, + ReadOnly: false, + }, + }, } if len(req.DatasetInfos) == 1 { @@ -383,6 +395,11 @@ func GenerateTask(req GenerateCloudBrainTaskReq) error { BootFile: req.BootFile, DatasetName: req.DatasetNames, Parameters: req.Params, + TrainUrl: req.TrainUrl, + ModelName: req.ModelName, + ModelVersion: req.ModelVersion, + CkptName: req.CkptName, + ResultUrl: req.ResultPath, CreatedUnix: createTime, UpdatedUnix: createTime, CommitID: req.CommitID, @@ -403,6 +420,8 @@ func GenerateTask(req GenerateCloudBrainTaskReq) error { notification.NotifyOtherTask(req.Ctx.User, req.Ctx.Repo.Repository, stringId, req.DisplayJobName, models.ActionCreateBenchMarkTask) } else if string(models.JobTypeTrain) == req.JobType { notification.NotifyOtherTask(req.Ctx.User, req.Ctx.Repo.Repository, jobID, req.DisplayJobName, models.ActionCreateGPUTrainTask) + } else if string(models.JobTypeInference) == req.JobType { + notification.NotifyOtherTask(req.Ctx.User, req.Ctx.Repo.Repository, jobID, req.DisplayJobName, models.ActionCreateInferenceTask) } else { notification.NotifyOtherTask(req.Ctx.User, req.Ctx.Repo.Repository, stringId, req.DisplayJobName, models.ActionCreateDebugGPUTask) } @@ -414,6 +433,15 @@ func IsBenchmarkJob(jobType string) bool { return string(models.JobTypeBenchmark) == jobType || string(models.JobTypeBrainScore) == jobType || string(models.JobTypeSnn4imagenet) == jobType } +func GetWaitingCloudbrainCount(cloudbrainType int, computeResource string, jobTypes ...models.JobType) int64 { + num, err := models.GetWaitingCloudbrainCount(cloudbrainType, computeResource, jobTypes...) + if err != nil { + log.Warn("Get waiting count err", err) + num = 0 + } + return num +} + func RestartTask(ctx *context.Context, task *models.Cloudbrain, newID *string) error { jobName := task.JobName @@ -427,6 +455,11 @@ func RestartTask(ctx *context.Context, task *models.Cloudbrain, newID *string) e } } + //如果没有匹配到spec信息,尝试从专属资源池获取 + if resourceSpec == nil && SpecialPools != nil { + resourceSpec = geMatchResourceSpec(task.JobType, task.GpuQueue, task.ResourceSpecId) + } + if resourceSpec == nil { log.Error("no such resourceSpecId(%d)", task.ResourceSpecId, ctx.Data["MsgID"]) return errors.New("no such resourceSpec") @@ -565,6 +598,63 @@ func RestartTask(ctx *context.Context, task *models.Cloudbrain, newID *string) e return nil } +func geMatchResourceSpec(jobType string, gpuQueue string, resourceSpecId int) *models.ResourceSpec { + + for _, specialPool := range SpecialPools.Pools { + + if specialPool.ResourceSpec != nil { + if IsElementExist(specialPool.JobType, jobType) && IsQueueInSpecialtPool(specialPool.Pool, gpuQueue) { + for _, spec := range specialPool.ResourceSpec { + if resourceSpecId == spec.Id { + return spec + } + } + } + } + } + return nil +} + +func DelCloudBrainJob(jobId string) string { + task, err := models.GetCloudbrainByJobID(jobId) + if err != nil { + log.Error("get cloud brain err:", err) + return "cloudbrain.Delete_failed" + + } + if task.Status != string(models.JobStopped) && task.Status != string(models.JobFailed) && task.Status != string(models.JobSucceeded) { + log.Error("the job(%s) has not been stopped", task.JobName) + return "cloudbrain.Not_Stopped" + } + + err = models.DeleteJob(task) + if err != nil { + log.Error("DeleteJob failed:", err) + return "cloudbrain.Delete_failed" + } + + deleteJobStorage(task.JobName) + + return "" +} + +func deleteJobStorage(jobName string) error { + //delete local + localJobPath := setting.JobPath + jobName + err := os.RemoveAll(localJobPath) + if err != nil { + log.Error("RemoveAll(%s) failed:%v", localJobPath, err) + } + + dirPath := setting.CBCodePathPrefix + jobName + "/" + err = storage.Attachments.DeleteDir(dirPath) + if err != nil { + log.Error("DeleteDir(%s) failed:%v", localJobPath, err) + } + + return nil +} + func InitSpecialPool() { if SpecialPools == nil && setting.SpecialPools != "" { json.Unmarshal([]byte(setting.SpecialPools), &SpecialPools) diff --git a/modules/cloudbrain/resty.go b/modules/cloudbrain/resty.go index e70dbdd2b..7b714c4b5 100755 --- a/modules/cloudbrain/resty.go +++ b/modules/cloudbrain/resty.go @@ -30,6 +30,7 @@ const ( LogPageSize = 500 LogPageTokenExpired = "5m" pageSize = 15 + QueuesDetailUrl = "/rest-server/api/v2/queuesdetail" ) func getRestyClient() *resty.Client { @@ -73,12 +74,44 @@ func loginCloudbrain() error { return nil } +func GetQueuesDetail() (*map[string]int, error) { + checkSetting() + client := getRestyClient() + var jobResult models.QueueDetailResult + + var result = make(map[string]int, 0) + + res, err := client.R(). + SetHeader("Content-Type", "application/json"). + SetAuthToken(TOKEN). + SetResult(&jobResult). + Get(HOST + QueuesDetailUrl) + + if err != nil { + return nil, fmt.Errorf("resty get queues detail failed: %s", err) + } + + if jobResult.Code != Success { + return nil, fmt.Errorf("jobResult err: %s", res.String()) + } + + for k, v := range jobResult.Payload { + + result[k] = v.JobScheduleInfo.Pending + + } + return &result, nil + +} + func CreateJob(jobName string, createJobParams models.CreateJobParams) (*models.CreateJobResult, error) { checkSetting() client := getRestyClient() var jobResult models.CreateJobResult retry := 0 + reqPara, _ := json.Marshal(createJobParams) + log.Warn("job req:", string(reqPara[:])) sendjob: res, err := client.R(). @@ -143,16 +176,6 @@ sendjob: return &getJobResult, nil } -func GetImages() (*models.GetImagesResult, error) { - - return GetImagesPageable(1, 100, Custom, "") - -} - -func GetPublicImages() (*models.GetImagesResult, error) { - return GetImagesPageable(1, 100, Public, "") -} - func GetImagesPageable(page int, size int, imageType string, name string) (*models.GetImagesResult, error) { checkSetting() client := getRestyClient() diff --git a/modules/modelarts/modelarts.go b/modules/modelarts/modelarts.go index dfd9413f8..b67e7f2c3 100755 --- a/modules/modelarts/modelarts.go +++ b/modules/modelarts/modelarts.go @@ -22,14 +22,14 @@ import ( const ( //notebook - storageTypeOBS = "obs" - autoStopDuration = 4 * 60 * 60 - autoStopDurationMs = 4 * 60 * 60 * 1000 - - DataSetMountPath = "/home/ma-user/work" - NotebookEnv = "Python3" - NotebookType = "Ascend" - FlavorInfo = "Ascend: 1*Ascend 910 CPU: 24 核 96GiB (modelarts.kat1.xlarge)" + storageTypeOBS = "obs" + autoStopDuration = 4 * 60 * 60 + autoStopDurationMs = 4 * 60 * 60 * 1000 + MORDELART_USER_IMAGE_ENGINE_ID = -1 + DataSetMountPath = "/home/ma-user/work" + NotebookEnv = "Python3" + NotebookType = "Ascend" + FlavorInfo = "Ascend: 1*Ascend 910 CPU: 24 核 96GiB (modelarts.kat1.xlarge)" //train-job // ResourcePools = "{\"resource_pool\":[{\"id\":\"pool1328035d\", \"value\":\"专属资源池\"}]}" @@ -101,6 +101,8 @@ type GenerateTrainJobReq struct { VersionCount int EngineName string TotalVersionCount int + UserImageUrl string + UserCommand string DatasetName string } @@ -139,6 +141,7 @@ type VersionInfo struct { Version []struct { ID int `json:"id"` Value string `json:"value"` + Url string `json:"url"` } `json:"version"` } @@ -386,28 +389,54 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error return err } - jobResult, err := createTrainJob(models.CreateTrainJobParams{ - JobName: req.JobName, - Description: req.Description, - Config: models.Config{ - WorkServerNum: req.WorkServerNumber, - AppUrl: req.CodeObsPath, - BootFileUrl: req.BootFileUrl, - DataUrl: req.DataUrl, - EngineID: req.EngineID, - TrainUrl: req.TrainUrl, - LogUrl: req.LogUrl, - PoolID: req.PoolID, - CreateVersion: true, - Flavor: models.Flavor{ - Code: req.FlavorCode, + var jobResult *models.CreateTrainJobResult + var createErr error + + if req.EngineID < 0 { + jobResult, createErr = createTrainJobUserImage(models.CreateUserImageTrainJobParams{ + JobName: req.JobName, + Description: req.Description, + Config: models.UserImageConfig{ + WorkServerNum: req.WorkServerNumber, + AppUrl: req.CodeObsPath, + BootFileUrl: req.BootFileUrl, + DataUrl: req.DataUrl, + TrainUrl: req.TrainUrl, + LogUrl: req.LogUrl, + PoolID: req.PoolID, + CreateVersion: true, + Flavor: models.Flavor{ + Code: req.FlavorCode, + }, + Parameter: req.Parameters, + UserImageUrl: req.UserImageUrl, + UserCommand: req.UserCommand, }, - Parameter: req.Parameters, - }, - }) - if err != nil { - log.Error("createTrainJob failed: %v", err.Error()) - if strings.HasPrefix(err.Error(), UnknownErrorPrefix) { + }) + } else { + jobResult, createErr = createTrainJob(models.CreateTrainJobParams{ + JobName: req.JobName, + Description: req.Description, + Config: models.Config{ + WorkServerNum: req.WorkServerNumber, + AppUrl: req.CodeObsPath, + BootFileUrl: req.BootFileUrl, + DataUrl: req.DataUrl, + EngineID: req.EngineID, + TrainUrl: req.TrainUrl, + LogUrl: req.LogUrl, + PoolID: req.PoolID, + CreateVersion: true, + Flavor: models.Flavor{ + Code: req.FlavorCode, + }, + Parameter: req.Parameters, + }, + }) + } + if createErr != nil { + log.Error("createTrainJob failed: %v", createErr.Error()) + if strings.HasPrefix(createErr.Error(), UnknownErrorPrefix) { log.Info("(%s)unknown error, set temp status", req.DisplayJobName) errTemp := models.InsertCloudbrainTemp(&models.CloudbrainTemp{ CloudbrainID: task.ID, @@ -430,7 +459,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error if errTemp != nil { log.Error("DeleteJob failed: %v", errTemp.Error()) } - return err + return createErr } } else { task.Status = TransTrainJobStatus(jobResult.Status) @@ -445,10 +474,33 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error } notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, task.JobID, req.DisplayJobName, models.ActionCreateTrainTask) - return nil } +func GenerateModelConvertTrainJob(req *GenerateTrainJobReq) (*models.CreateTrainJobResult, error) { + + return createTrainJobUserImage(models.CreateUserImageTrainJobParams{ + JobName: req.JobName, + Description: req.Description, + Config: models.UserImageConfig{ + WorkServerNum: req.WorkServerNumber, + AppUrl: req.CodeObsPath, + BootFileUrl: req.BootFileUrl, + DataUrl: req.DataUrl, + TrainUrl: req.TrainUrl, + LogUrl: req.LogUrl, + PoolID: req.PoolID, + CreateVersion: true, + Flavor: models.Flavor{ + Code: req.FlavorCode, + }, + Parameter: req.Parameters, + UserImageUrl: req.UserImageUrl, + UserCommand: req.UserCommand, + }, + }) +} + func GenerateTrainJobVersion(ctx *context.Context, req *GenerateTrainJobReq, jobId string) (err error) { var jobTypes []string jobTypes = append(jobTypes, string(models.JobTypeTrain)) @@ -512,25 +564,50 @@ func GenerateTrainJobVersion(ctx *context.Context, req *GenerateTrainJobReq, job return err } - jobResult, err := createTrainJobVersion(models.CreateTrainJobVersionParams{ - Description: req.Description, - Config: models.TrainJobVersionConfig{ - WorkServerNum: req.WorkServerNumber, - AppUrl: req.CodeObsPath, - BootFileUrl: req.BootFileUrl, - DataUrl: req.DataUrl, - EngineID: req.EngineID, - TrainUrl: req.TrainUrl, - LogUrl: req.LogUrl, - PoolID: req.PoolID, - Flavor: models.Flavor{ - Code: req.FlavorCode, + var jobResult *models.CreateTrainJobResult + var createErr error + + if req.EngineID < 0 { + jobResult, createErr = createTrainJobVersionUserImage(models.CreateTrainJobVersionUserImageParams{ + Description: req.Description, + Config: models.TrainJobVersionUserImageConfig{ + WorkServerNum: req.WorkServerNumber, + AppUrl: req.CodeObsPath, + BootFileUrl: req.BootFileUrl, + DataUrl: req.DataUrl, + TrainUrl: req.TrainUrl, + LogUrl: req.LogUrl, + PoolID: req.PoolID, + Flavor: models.Flavor{ + Code: req.FlavorCode, + }, + Parameter: req.Parameters, + PreVersionId: req.PreVersionId, + UserImageUrl: req.UserImageUrl, + UserCommand: req.UserCommand, }, - Parameter: req.Parameters, - PreVersionId: req.PreVersionId, - }, - }, jobId) - if err != nil { + }, jobId) + } else { + jobResult, createErr = createTrainJobVersion(models.CreateTrainJobVersionParams{ + Description: req.Description, + Config: models.TrainJobVersionConfig{ + WorkServerNum: req.WorkServerNumber, + AppUrl: req.CodeObsPath, + BootFileUrl: req.BootFileUrl, + DataUrl: req.DataUrl, + EngineID: req.EngineID, + TrainUrl: req.TrainUrl, + LogUrl: req.LogUrl, + PoolID: req.PoolID, + Flavor: models.Flavor{ + Code: req.FlavorCode, + }, + Parameter: req.Parameters, + PreVersionId: req.PreVersionId, + }, + }, jobId) + } + if createErr != nil { log.Error("createTrainJobVersion failed: %v", err.Error()) if strings.HasPrefix(err.Error(), UnknownErrorPrefix) { log.Info("(%s)unknown error, set temp status", req.DisplayJobName) @@ -555,7 +632,7 @@ func GenerateTrainJobVersion(ctx *context.Context, req *GenerateTrainJobReq, job if errTemp != nil { log.Error("DeleteJob failed: %v", errTemp.Error()) } - return err + return createErr } } else { task.Status = TransTrainJobStatus(jobResult.Status) @@ -572,6 +649,99 @@ func GenerateTrainJobVersion(ctx *context.Context, req *GenerateTrainJobReq, job return nil } +func GenerateTrainJobVersionByUserImage(ctx *context.Context, req *GenerateTrainJobReq, jobId string) (err error) { + createTime := timeutil.TimeStampNow() + jobResult, err := createTrainJobUserImage(models.CreateUserImageTrainJobParams{ + JobName: req.JobName, + Description: req.Description, + Config: models.UserImageConfig{ + WorkServerNum: req.WorkServerNumber, + AppUrl: req.CodeObsPath, + BootFileUrl: req.BootFileUrl, + DataUrl: req.DataUrl, + TrainUrl: req.TrainUrl, + LogUrl: req.LogUrl, + PoolID: req.PoolID, + CreateVersion: true, + Flavor: models.Flavor{ + Code: req.FlavorCode, + }, + Parameter: req.Parameters, + UserImageUrl: req.UserImageUrl, + UserCommand: req.UserCommand, + }, + }) + if err != nil { + log.Error("CreateJob failed: %v", err.Error()) + return err + } + + var jobTypes []string + jobTypes = append(jobTypes, string(models.JobTypeTrain)) + repo := ctx.Repo.Repository + VersionTaskList, VersionListCount, err := models.CloudbrainsVersionList(&models.CloudbrainsOptions{ + RepoID: repo.ID, + Type: models.TypeCloudBrainTwo, + JobTypes: jobTypes, + JobID: strconv.FormatInt(jobResult.JobID, 10), + }) + if err != nil { + ctx.ServerError("Cloudbrain", err) + return err + } + //将当前版本的isLatestVersion设置为"1"和任务数量更新,任务数量包括当前版本数VersionCount和历史创建的总版本数TotalVersionCount + + err = models.CreateCloudbrain(&models.Cloudbrain{ + Status: TransTrainJobStatus(jobResult.Status), + UserID: ctx.User.ID, + RepoID: ctx.Repo.Repository.ID, + JobID: strconv.FormatInt(jobResult.JobID, 10), + JobName: req.JobName, + DisplayJobName: req.DisplayJobName, + JobType: string(models.JobTypeTrain), + Type: models.TypeCloudBrainTwo, + VersionID: jobResult.VersionID, + VersionName: jobResult.VersionName, + Uuid: req.Uuid, + DatasetName: req.DatasetName, + CommitID: req.CommitID, + IsLatestVersion: req.IsLatestVersion, + PreVersionName: req.PreVersionName, + ComputeResource: models.NPUResource, + EngineID: MORDELART_USER_IMAGE_ENGINE_ID, + Image: req.UserImageUrl, + TrainUrl: req.TrainUrl, + BranchName: req.BranchName, + Parameters: req.Params, + BootFile: req.BootFile, + DataUrl: req.DataUrl, + LogUrl: req.LogUrl, + PreVersionId: req.PreVersionId, + FlavorCode: req.FlavorCode, + Description: req.Description, + WorkServerNumber: req.WorkServerNumber, + FlavorName: req.FlavorName, + EngineName: req.EngineName, + TotalVersionCount: VersionTaskList[0].TotalVersionCount + 1, + VersionCount: VersionListCount + 1, + CreatedUnix: createTime, + UpdatedUnix: createTime, + }) + if err != nil { + log.Error("CreateCloudbrain(%s) failed:%v", req.JobName, err.Error()) + return err + } + + //将训练任务的上一版本的isLatestVersion设置为"0" + err = models.SetVersionCountAndLatestVersion(strconv.FormatInt(jobResult.JobID, 10), VersionTaskList[0].VersionName, VersionListCount, NotLatestVersion, TotalVersionCount) + if err != nil { + ctx.ServerError("Update IsLatestVersion failed", err) + return err + } + + return err +} + func TransTrainJobStatus(status int) string { switch status { case 0: diff --git a/modules/modelarts/resty.go b/modules/modelarts/resty.go index 7d7f6cbcb..dd364ea44 100755 --- a/modules/modelarts/resty.go +++ b/modules/modelarts/resty.go @@ -477,6 +477,62 @@ sendjob: return &result, nil } +func createTrainJobUserImage(createJobParams models.CreateUserImageTrainJobParams) (*models.CreateTrainJobResult, error) { + checkSetting() + client := getRestyClient() + var result models.CreateTrainJobResult + + retry := 0 + +sendjob: + res, err := client.R(). + SetHeader("Content-Type", "application/json"). + SetAuthToken(TOKEN). + SetBody(createJobParams). + SetResult(&result). + Post(HOST + "/v1/" + setting.ProjectID + urlTrainJob) + + if err != nil { + return nil, fmt.Errorf("resty create train-job: %s", err) + } + + req, _ := json.Marshal(createJobParams) + log.Info("%s", req) + + if res.StatusCode() == http.StatusUnauthorized && retry < 1 { + retry++ + _ = getToken() + goto sendjob + } + + if res.StatusCode() != http.StatusOK { + var temp models.ErrorResult + if err = json.Unmarshal([]byte(res.String()), &temp); err != nil { + log.Error("json.Unmarshal failed(%s): %v", res.String(), err.Error()) + return &result, fmt.Errorf("json.Unmarshal failed(%s): %v", res.String(), err.Error()) + } + log.Error("createTrainJob failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) + BootFileErrorMsg := "Invalid OBS path '" + createJobParams.Config.BootFileUrl + "'." + DataSetErrorMsg := "Invalid OBS path '" + createJobParams.Config.DataUrl + "'." + if temp.ErrorMsg == BootFileErrorMsg { + log.Error("启动文件错误!createTrainJob failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) + return &result, fmt.Errorf("启动文件错误!") + } + if temp.ErrorMsg == DataSetErrorMsg { + log.Error("数据集错误!createTrainJob failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) + return &result, fmt.Errorf("数据集错误!") + } + return &result, fmt.Errorf("createTrainJob failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) + } + + if !result.IsSuccess { + log.Error("createTrainJob failed(%s): %s", result.ErrorCode, result.ErrorMsg) + return &result, fmt.Errorf("createTrainJob failed(%s): %s", result.ErrorCode, result.ErrorMsg) + } + + return &result, nil +} + func createTrainJob(createJobParams models.CreateTrainJobParams) (*models.CreateTrainJobResult, error) { checkSetting() client := getRestyClient() @@ -592,6 +648,61 @@ sendjob: return &result, nil } +func createTrainJobVersionUserImage(createJobVersionParams models.CreateTrainJobVersionUserImageParams, jobID string) (*models.CreateTrainJobResult, error) { + checkSetting() + client := getRestyClient() + var result models.CreateTrainJobResult + + retry := 0 + +sendjob: + res, err := client.R(). + SetHeader("Content-Type", "application/json"). + SetAuthToken(TOKEN). + SetBody(createJobVersionParams). + SetResult(&result). + Post(HOST + "/v1/" + setting.ProjectID + urlTrainJob + "/" + jobID + "/versions") + + if err != nil { + return nil, fmt.Errorf("resty create train-job version: %s", err) + } + + req, _ := json.Marshal(createJobVersionParams) + log.Info("%s", req) + + if res.StatusCode() == http.StatusUnauthorized && retry < 1 { + retry++ + _ = getToken() + goto sendjob + } + + if res.StatusCode() != http.StatusOK { + var temp models.ErrorResult + if err = json.Unmarshal([]byte(res.String()), &temp); err != nil { + log.Error("json.Unmarshal failed(%s): %v", res.String(), err.Error()) + return &result, fmt.Errorf("json.Unmarshal failed(%s): %v", res.String(), err.Error()) + } + BootFileErrorMsg := "Invalid OBS path '" + createJobVersionParams.Config.BootFileUrl + "'." + DataSetErrorMsg := "Invalid OBS path '" + createJobVersionParams.Config.DataUrl + "'." + if temp.ErrorMsg == BootFileErrorMsg { + log.Error("启动文件错误!createTrainJobVersion failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) + return &result, fmt.Errorf("启动文件错误!") + } + if temp.ErrorMsg == DataSetErrorMsg { + log.Error("数据集错误!createTrainJobVersion failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) + return &result, fmt.Errorf("数据集错误!") + } + return &result, fmt.Errorf("createTrainJobVersion failed(%d):%s(%s)", res.StatusCode(), temp.ErrorCode, temp.ErrorMsg) + } + + if !result.IsSuccess { + log.Error("createTrainJobVersion failed(%s): %s", result.ErrorCode, result.ErrorMsg) + return &result, fmt.Errorf("createTrainJobVersion failed(%s): %s", result.ErrorCode, result.ErrorMsg) + } + + return &result, nil +} + func GetResourceSpecs() (*models.GetResourceSpecsResult, error) { checkSetting() client := getRestyClient() diff --git a/modules/setting/setting.go b/modules/setting/setting.go index ca4768df8..6ec54fdff 100755 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -463,22 +463,26 @@ var ( DecompressOBSTaskName string //cloudbrain config - CBAuthUser string - CBAuthPassword string - RestServerHost string - JobPath string - CBCodePathPrefix string - JobType string - GpuTypes string - SpecialPools string - DebugServerHost string - ResourceSpecs string - MaxDuration int64 - TrainGpuTypes string - TrainResourceSpecs string - MaxDatasetNum int - CullIdleTimeout string - CullInterval string + + CBAuthUser string + CBAuthPassword string + RestServerHost string + JobPath string + CBCodePathPrefix string + JobType string + GpuTypes string + SpecialPools string + DebugServerHost string + ResourceSpecs string + MaxDuration int64 + TrainGpuTypes string + TrainResourceSpecs string + InferenceGpuTypes string + InferenceResourceSpecs string + MaxModelSize float64 + MaxDatasetNum int + CullIdleTimeout string + CullInterval string //benchmark config IsBenchmarkEnabled bool @@ -628,6 +632,24 @@ var ( OrgName string TeamName string }{} + + ModelConvert = struct { + GPU_PYTORCH_IMAGE string + GpuQueue string + GPU_TENSORFLOW_IMAGE string + NPU_MINDSPORE_16_IMAGE string + PytorchOnnxBootFile string + PytorchTrTBootFile string + MindsporeBootFile string + TensorFlowNpuBootFile string + TensorFlowGpuBootFile string + ConvertRepoPath string + GPU_Resource_Specs_ID int + NPU_FlavorCode string + NPU_PoolID string + NPU_MINDSPORE_IMAGE_ID int + NPU_TENSORFLOW_IMAGE_ID int + }{} ) // DateLang transforms standard language locale name to corresponding value in datetime plugin. @@ -1327,8 +1349,11 @@ func NewContext() { MaxDuration = sec.Key("MAX_DURATION").MustInt64(14400) TrainGpuTypes = sec.Key("TRAIN_GPU_TYPES").MustString("") TrainResourceSpecs = sec.Key("TRAIN_RESOURCE_SPECS").MustString("") + MaxModelSize = sec.Key("MAX_MODEL_SIZE").MustFloat64(500) + InferenceGpuTypes = sec.Key("INFERENCE_GPU_TYPES").MustString("") + InferenceResourceSpecs = sec.Key("INFERENCE_RESOURCE_SPECS").MustString("") SpecialPools = sec.Key("SPECIAL_POOL").MustString("") - + MaxDatasetNum = sec.Key("MAX_DATASET_NUM").MustInt(5) CullIdleTimeout = sec.Key("CULL_IDLE_TIMEOUT").MustString("900") CullInterval = sec.Key("CULL_INTERVAL").MustString("60") @@ -1426,6 +1451,27 @@ func NewContext() { Course.TeamName = sec.Key("team_name").MustString("") GetGrampusConfig() + + getModelConvertConfig() +} + +func getModelConvertConfig() { + sec := Cfg.Section("model_convert") + ModelConvert.GPU_PYTORCH_IMAGE = sec.Key("GPU_PYTORCH_IMAGE").MustString("dockerhub.pcl.ac.cn:5000/user-images/openi:tensorRT_7_zouap") + ModelConvert.GpuQueue = sec.Key("GpuQueue").MustString("openidgx") + ModelConvert.GPU_TENSORFLOW_IMAGE = sec.Key("GPU_TENSORFLOW_IMAGE").MustString("dockerhub.pcl.ac.cn:5000/user-images/openi:tf2onnx") + ModelConvert.NPU_MINDSPORE_16_IMAGE = sec.Key("NPU_MINDSPORE_16_IMAGE").MustString("swr.cn-south-222.ai.pcl.cn/openi/mindspore1.6.1_train_v1_openi:v3_ascend") + ModelConvert.PytorchOnnxBootFile = sec.Key("PytorchOnnxBootFile").MustString("convert_pytorch.py") + ModelConvert.PytorchTrTBootFile = sec.Key("PytorchTrTBootFile").MustString("convert_pytorch_tensorrt.py") + ModelConvert.MindsporeBootFile = sec.Key("MindsporeBootFile").MustString("convert_mindspore.py") + ModelConvert.TensorFlowNpuBootFile = sec.Key("TensorFlowNpuBootFile").MustString("convert_tensorflow.py") + ModelConvert.TensorFlowGpuBootFile = sec.Key("TensorFlowGpuBootFile").MustString("convert_tensorflow_gpu.py") + ModelConvert.ConvertRepoPath = sec.Key("ConvertRepoPath").MustString("https://git.openi.org.cn/zouap/npu_test") + ModelConvert.GPU_Resource_Specs_ID = sec.Key("GPU_Resource_Specs_ID").MustInt(1) + ModelConvert.NPU_FlavorCode = sec.Key("NPU_FlavorCode").MustString("modelarts.bm.910.arm.public.1") + ModelConvert.NPU_PoolID = sec.Key("NPU_PoolID").MustString("pool7908321a") + ModelConvert.NPU_MINDSPORE_IMAGE_ID = sec.Key("NPU_MINDSPORE_IMAGE_ID").MustInt(121) + ModelConvert.NPU_TENSORFLOW_IMAGE_ID = sec.Key("NPU_TENSORFLOW_IMAGE_ID").MustInt(35) } func GetGrampusConfig() { diff --git a/modules/storage/minio_ext.go b/modules/storage/minio_ext.go index 514ac7204..4ad83da82 100755 --- a/modules/storage/minio_ext.go +++ b/modules/storage/minio_ext.go @@ -217,6 +217,49 @@ func GetOneLevelAllObjectUnderDirMinio(bucket string, prefixRootPath string, rel } +func MinioGetFilesSize(bucketName string, Files []string) int64 { + _, core, err := getClients() + var fileTotalSize int64 + fileTotalSize = 0 + if err != nil { + log.Error("getClients failed:", err.Error()) + return fileTotalSize + } + for _, file := range Files { + log.Info("file=" + file) + meta, err := core.StatObject(bucketName, file, miniov6.StatObjectOptions{}) + if err != nil { + log.Info("Get file error:" + err.Error()) + } + fileTotalSize += meta.Size + } + return fileTotalSize +} + +func MinioCopyFiles(bucketName string, srcPath string, destPath string, Files []string) (int64, error) { + _, core, err := getClients() + var fileTotalSize int64 + fileTotalSize = 0 + if err != nil { + log.Error("getClients failed:", err.Error()) + return fileTotalSize, err + } + + for _, file := range Files { + srcObjectName := srcPath + file + destObjectName := destPath + file + log.Info("srcObjectName=" + srcObjectName + " destObjectName=" + destObjectName) + meta, err := core.StatObject(bucketName, srcObjectName, miniov6.StatObjectOptions{}) + if err != nil { + log.Info("Get file error:" + err.Error()) + } + core.CopyObject(bucketName, srcObjectName, bucketName, destObjectName, meta.UserMetadata) + fileTotalSize += meta.Size + } + + return fileTotalSize, nil +} + func MinioPathCopy(bucketName string, srcPath string, destPath string) (int64, error) { _, core, err := getClients() var fileTotalSize int64 diff --git a/modules/storage/obs.go b/modules/storage/obs.go index ab978b084..29b7998f7 100755 --- a/modules/storage/obs.go +++ b/modules/storage/obs.go @@ -264,7 +264,47 @@ func ObsModelDownload(JobName string, fileName string) (io.ReadCloser, error) { } } -func ObsCopyManyFile(srcBucket string, srcPath string, destBucket string, destPath string) (int64, error) { +func ObsGetFilesSize(srcBucket string, Files []string) int64 { + var fileTotalSize int64 + for _, file := range Files { + log.Info("file=" + file) + out, err := ObsCli.GetObjectMetadata(&obs.GetObjectMetadataInput{ + Bucket: srcBucket, + Key: file, + }) + if err != nil { + log.Info("Get File error, error=" + err.Error()) + continue + } + fileTotalSize += out.ContentLength + } + return fileTotalSize +} + +func ObsCopyManyFile(srcBucket string, srcPath string, destBucket string, destPath string, Files []string) (int64, error) { + + var fileTotalSize int64 + + for _, file := range Files { + srcKey := srcPath + file + destKey := destPath + file + log.Info("srcKey=" + srcKey + " destKey=" + destKey) + out, err := ObsCli.GetObjectMetadata(&obs.GetObjectMetadataInput{ + Bucket: srcBucket, + Key: srcKey, + }) + if err != nil { + log.Info("Get File error, error=" + err.Error()) + continue + } + obsCopyFile(srcBucket, srcKey, destBucket, destKey) + fileTotalSize += out.ContentLength + } + + return fileTotalSize, nil +} + +func ObsCopyAllFile(srcBucket string, srcPath string, destBucket string, destPath string) (int64, error) { input := &obs.ListObjectsInput{} input.Bucket = srcBucket // 设置每页100个对象 @@ -330,6 +370,7 @@ func GetOneLevelAllObjectUnderDir(bucket string, prefixRootPath string, relative output, err := ObsCli.ListObjects(input) fileInfos := make([]FileInfo, 0) prefixLen := len(input.Prefix) + fileMap := make(map[string]bool, 0) if err == nil { for _, val := range output.Contents { log.Info("val key=" + val.Key) @@ -338,23 +379,51 @@ func GetOneLevelAllObjectUnderDir(bucket string, prefixRootPath string, relative if val.Key == input.Prefix { continue } - if strings.Contains(val.Key[prefixLen:len(val.Key)-1], "/") { + fileName = val.Key[prefixLen:] + log.Info("fileName =" + fileName) + files := strings.Split(fileName, "/") + if fileMap[files[0]] { continue + } else { + fileMap[files[0]] = true } - if strings.HasSuffix(val.Key, "/") { + ParenDir := relativePath + fileName = files[0] + if len(files) > 1 { isDir = true - fileName = val.Key[prefixLen : len(val.Key)-1] - relativePath += val.Key[prefixLen:] + ParenDir += fileName + "/" } else { isDir = false - fileName = val.Key[prefixLen:] } + + // if strings.Contains(val.Key[prefixLen:len(val.Key)-1], "/") { + + // files := strings.Split(fileName, "/") + // fileName = files[0] + // isDir = true + // if fileMap[files[0]] { + // continue + // } else { + // fileMap[files[0]] = true + // } + // } else { + // if strings.HasSuffix(val.Key, "/") { + // isDir = true + // fileName = val.Key[prefixLen : len(val.Key)-1] + // relativePath += val.Key[prefixLen:] + // } else { + // isDir = false + // fileName = val.Key[prefixLen:] + // } + // fileMap[fileName] = true + // } + fileInfo := FileInfo{ ModTime: val.LastModified.Local().Format("2006-01-02 15:04:05"), FileName: fileName, Size: val.Size, IsDir: isDir, - ParenDir: relativePath, + ParenDir: ParenDir, } fileInfos = append(fileInfos, fileInfo) } @@ -424,6 +493,7 @@ func GetObsListObject(jobName, outPutPath, parentDir, versionName string) ([]Fil input := &obs.ListObjectsInput{} input.Bucket = setting.Bucket input.Prefix = strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, outPutPath, versionName, parentDir), "/") + log.Info("bucket=" + input.Bucket + " Prefix=" + input.Prefix) strPrefix := strings.Split(input.Prefix, "/") output, err := ObsCli.ListObjects(input) fileInfos := make([]FileInfo, 0) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 0c9852c12..b641f4011 100755 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -1037,8 +1037,9 @@ image_delete_fail=Failed to delete image, please try again later. image_overwrite=You had submitted the same name image before, are you sure to overwrite the original image? download=Download score=Score +wait_count_start = There are currently +wait_count_end = tasks queued file_limit_100 = Display up to 100 files or folders in a single directory - images.name = Image Tag images.name_placerholder = Please enter the image name image.label_tooltips = Example Python 3.7, Tensorflow 2.0, cuda 10, pytorch 1.6 @@ -1217,6 +1218,14 @@ model.manage.Recall = Recall model.manage.sava_model = Sava Model model.manage.model_manage = ModelManage model.manage.model_accuracy = Model Accuracy +model.convert=Model Transformation +model.list=Model List +model.manage.create_new_convert_task=Create Model Transformation Task + +modelconvert.manage.create_error1=A model transformation task with the same name already exists. +modelconvert.manage.create_error2=Only one running model transformation task can be created. +modelconvert.manage.model_not_exist=The model does not exist. +modelconvert.manage.no_operate_right=No operation permission. grampus.train_job.ai_center = AI Center grampus.dataset_path_rule = The code is storaged in /cache/code;the dataset is storaged in /cache/dataset;and please put your model into /cache/output, then you can download it online。 @@ -3122,4 +3131,10 @@ INFERENCE = INFERENCE BENCHMARK = BENCHMARK brain_area = Brain Area -error.dataset_select = dataset select error:the count exceed the limit or has same name \ No newline at end of file +Delete_failed=Fail to delete the job, please try again later. +Not_Stopped=The job is not stopped, can not be deleted. +Already_stopped=The job is already stopped. +Stopped_failed=Fail to stop the job, please try again later. +Stopped_success_update_status_fail=Succeed in stopping th job, but failed to update the job status and duration time. + +error.dataset_select = dataset select error:the count exceed the limit or has same name diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 350d0800d..87630d6c0 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -1037,8 +1037,9 @@ image_delete_fail=删除镜像失败,请稍后再试。 image_overwrite=您已经提交过相同名称的镜像,您确定要覆盖原来提交的镜像吗? download=模型下载 score=评分 +wait_count_start = 当前有 +wait_count_end = 个任务正在排队 file_limit_100 = 单目录下最多显示100个文件或文件夹 - images.name = 镜像Tag images.name_placerholder = 请输入镜像Tag image.label_tooltips = 如Python 3.7, Tensorflow 2.0, cuda 10, pytorch 1.6 @@ -1229,6 +1230,14 @@ model.manage.Recall = 召回率 model.manage.sava_model = 保存模型 model.manage.model_manage = 模型管理 model.manage.model_accuracy = 模型精度 +model.convert=模型转换任务 +model.list=模型列表 +model.manage.create_new_convert_task=创建模型转换任务 + +modelconvert.manage.create_error1=相同的名称模型转换任务已经存在。 +modelconvert.manage.create_error2=只能创建一个正在运行的模型转换任务。 +modelconvert.manage.model_not_exist=选择的模型不存在。 +modelconvert.manage.no_operate_right=无操作权限。 grampus.train_job.ai_center=智算中心 grampus.dataset_path_rule = 训练脚本存储在/cache/code中,数据集存储在/cache/dataset中,训练输出请存储在/cache/output中以供后续下载。 @@ -3136,4 +3145,11 @@ INFERENCE = 推理任务 BENCHMARK = 评测任务 brain_area = 脑区 -error.dataset_select = 数据集选择错误:数量超过限制或者有同名数据集 \ No newline at end of file +Delete_failed=任务删除失败,请稍后再试。 +Not_Stopped=任务还未终止,不能删除。 +Already_stopped=任务已停止。 +Stopped_failed=任务停止失败,请稍后再试。 +Stopped_success_update_status_fail=任务停止成功,状态及运行时间更新失败。 + + +error.dataset_select = 数据集选择错误:数量超过限制或者有同名数据集 diff --git a/public/self/ztree/css/awesomeStyle/awesome.css b/public/self/ztree/css/awesomeStyle/awesome.css new file mode 100644 index 000000000..5fa82249a --- /dev/null +++ b/public/self/ztree/css/awesomeStyle/awesome.css @@ -0,0 +1,386 @@ +/*------------------------------------- +zTree Style using fontawesome instead of images + +version: 1.1 +author: Mike King +email: mikkelking @ hotmail . com +website: http://code.google.com/p/jquerytree/ + +-------------------------------------*/ +/* Definitions ----------------------*/ +/* End of Definitions ---------------*/ +/* Imports -------------------------*/ +/* End of Imports ------------------*/ +.ztree * { + padding: 0; + margin: 0; + font-size: 12px; + font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif; + background-color: #af0000; +} +.ztree { + margin: 0; + padding: 5px; + color: #ffffff; + background-color: #af0000; +} +.ztree li { + padding: 0; + margin: 0; + list-style: none; + line-height: 17px; + text-align: left; + white-space: nowrap; + outline: 0; +} +.ztree li ul { + margin: 0px; + padding: 0 0 0 18px; +} +.ztree li a { + padding-right: 3px; + margin: 0; + cursor: pointer; + height: 17px; + color: #ffffff; + background-color: transparent; + text-decoration: none; + vertical-align: top; + display: inline-block; +} +.ztree li a input.rename { + height: 14px; + width: 80px; + padding: 0; + margin: 0; + color: #af0000; + background-color: #ffffff; + font-size: 12px; + border: 1px #585956 solid; + *border: 0px; +} +.ztree li a:hover { + text-decoration: underline; +} +.ztree li a.curSelectedNode { + padding-top: 0px; + background-color: #af4040; + color: #ffff00; + height: 17px; + opacity: 0.8; +} +.ztree li a.curSelectedNode_Edit { + padding-top: 0px; + background-color: transparent; + color: #ffff00; + height: 17px; + border: 1px #666 solid; + opacity: 0.8; +} +.ztree li a.tmpTargetNode_inner { + padding-top: 0px; + background-color: #aaa; + color: #ffff00; + height: 17px; + border: 1px #666 solid; + opacity: 0.8; + filter: alpha(opacity=80); +} +.ztree li span { + line-height: 17px; + margin-right: 2px; + background-color: transparent; +} +.ztree li span.button { + line-height: 0; + margin: 0; + padding: 0; + width: 15px; + height: 17px; + display: inline-block; + vertical-align: top; + border: 0px solid; + cursor: pointer; + outline: none; + background-color: transparent; + background-repeat: no-repeat; + background-attachment: scroll; +} +.ztree li span.button::before { + color: #ffffff; + font-family: FontAwesome; + padding-top: 10px; +} +.ztree li span.button.chk { + margin: 0px; + cursor: auto; + width: 12px; + display: inline-block; + padding-top: 10px; + padding-left: 2px; +} +.ztree li span.button.chk.checkbox_false_full::before { + content: "\f096"; +} +.ztree li span.button.chk.checkbox_false_full_focus::before { + content: "\f096"; + color: #ffff00; +} +.ztree li span.button.chk.checkbox_false_part::before { + content: "\f096"; + color: #aaaaaa; +} +.ztree li span.button.chk.checkbox_false_part_focus::before { + content: "\f096"; + color: #cad96c; +} +.ztree li span.button.chk.checkbox_false_disable::before { + content: "\f096"; + color: #808080; +} +.ztree li span.button.chk.checkbox_true_full::before { + content: "\f046"; +} +.ztree li span.button.chk.checkbox_true_full_focus::before { + content: "\f046"; +} +.ztree li span.button.chk.checkbox_true_part::before { + content: "\f14a"; +} +.ztree li span.button.chk.checkbox_true_part_focus::before { + content: "\f14a"; + color: #ffff00; +} +.ztree li span.button.chk.checkbox_true_full_focus::before { + content: "\f046"; + color: #ffff00; +} +.ztree li span.button.chk.checkbox_true_part::before { + content: "\f046"; + color: #aaaaaa; +} +.ztree li span.button.chk.checkbox_true_part_focus::before { + content: "\f046"; + color: #cad96c; +} +.ztree li span.button.chk.checkbox_true_disable::before { + content: "\f046"; + color: #808080; +} +.ztree li span.button.chk.radio_false_full::before { + content: "\f10c"; +} +.ztree li span.button.chk.radio_false_full_focus::before { + content: "\f10c"; + color: #ffff00; +} +.ztree li span.button.chk.radio_false_part::before { + content: "\f10c"; + color: #aaaaaa; +} +.ztree li span.button.chk.radio_false_part_focus::before { + content: "\f10c"; + color: #ffff00; +} +.ztree li span.button.chk.radio_false_disable::before { + content: "\f1db"; + color: #808080; +} +.ztree li span.button.chk.radio_true_full::before { + content: "\f192"; +} +.ztree li span.button.chk.radio_true_full_focus::before { + content: "\f192"; + color: #ffff00; +} +.ztree li span.button.chk.radio_true_part::before { + content: "\f192"; + color: #aaaaaa; +} +.ztree li span.button.chk.radio_true_part_focus::before { + content: "\f192"; + color: #aaaaaa; +} +.ztree li span.button.chk.radio_true_disable::before { + content: "\f1db"; + color: #808080; +} +.ztree li span.button.switch { + width: 15px; + height: 17px; +} +.ztree li span.button.root_open::before { + content: "\f078"; + padding-top: 10px; + padding-left: 2px; + display: inline-block; +} +.ztree li span.button.root_close::before { + content: "\f054"; + padding-top: 10px; + padding-left: 2px; + display: inline-block; +} +.ztree li span.button.roots_open::before { + content: "\f078"; + padding-top: 10px; + padding-left: 2px; + display: inline-block; +} +.ztree li span.button.roots_close::before { + content: "\f054"; + padding-top: 10px; + padding-left: 2px; + display: inline-block; +} +.ztree li span.button.center_open::before { + content: "\f078"; + padding-top: 10px; + padding-left: 2px; + display: inline-block; +} +.ztree li span.button.center_close::before { + content: "\f054"; + padding-top: 10px; + padding-left: 2px; + display: inline-block; +} +.ztree li span.button.bottom_open::before { + content: "\f078"; + padding-top: 10px; + padding-left: 2px; + display: inline-block; +} +.ztree li span.button.bottom_close::before { + content: "\f054"; + padding-top: 10px; + padding-left: 2px; + display: inline-block; +} +.ztree li span.button.root_docu { + background: none; +} +.ztree li span.button.roots_docu::before { + content: "\f022"; + padding-left: 2px; + display: inline-block; + color: #ffffff; +} +.ztree li span.button.center_docu::before { + padding-top: 10px; + padding-left: 2px; + display: inline-block; + color: #ffffff; +} +.ztree li span.button.bottom_docu::before { + padding-top: 10px; + padding-left: 2px; + display: inline-block; + color: #ffffff; +} +.ztree li span.button.noline_docu { + background: none; +} +.ztree li span.button.ico_open::before { + content: "\f115"; + font-family: FontAwesome; + padding-top: 10px; + padding-left: 2px; + display: inline-block; + color: #ffffff; +} +.ztree li span.button.ico_close::before { + content: "\f114"; + font-family: FontAwesome; + padding-top: 10px; + padding-left: 2px; + display: inline-block; + color: #ffffff; +} +.ztree li span.button.ico_docu::before { + content: "\f022"; + font-family: FontAwesome; + padding-top: 10px; + padding-left: 2px; + display: inline-block; + color: #ffffff; +} +.ztree li span.button.edit { + margin-left: 4px; + margin-right: -1px; + vertical-align: top; + *vertical-align: middle; + padding-top: 10px; +} +.ztree li span.button.edit::before { + content: "\f044"; + font-family: FontAwesome; +} +.ztree li span.button.remove { + margin-left: 4px; + margin-right: -1px; + vertical-align: top; + *vertical-align: middle; + padding-top: 10px; +} +.ztree li span.button.remove::before { + content: "\f1f8"; + font-family: FontAwesome; +} +.ztree li span.button.add { + margin-left: 4px; + margin-right: -1px; + vertical-align: top; + *vertical-align: middle; + padding-top: 10px; +} +.ztree li span.button.add::before { + content: "\f067"; + font-family: FontAwesome; +} +.ztree li span.button.ico_loading { + margin-right: 2px; + background: url(./img/loading.gif) no-repeat scroll 0 0 transparent; + vertical-align: top; + *vertical-align: middle; +} +ul.tmpTargetzTree { + background-color: #FFE6B0; + opacity: 0.8; + filter: alpha(opacity=80); +} +span.tmpzTreeMove_arrow { + width: 16px; + height: 17px; + display: inline-block; + padding: 0; + margin: 2px 0 0 1px; + border: 0 none; + position: absolute; + background-color: transparent; + background-attachment: scroll; +} +span.tmpzTreeMove_arrow::before { + content: "\f04b"; + font-family: FontAwesome; + color: #ffff00; +} +ul.ztree.zTreeDragUL { + margin: 0; + padding: 0; + position: absolute; + width: auto; + height: auto; + overflow: hidden; + background-color: #cfcfcf; + border: 1px #ffff00 dotted; + opacity: 0.8; + filter: alpha(opacity=80); +} +.ztreeMask { + z-index: 10000; + background-color: #cfcfcf; + opacity: 0.0; + filter: alpha(opacity=0); + position: absolute; +} diff --git a/public/self/ztree/css/awesomeStyle/awesome.less b/public/self/ztree/css/awesomeStyle/awesome.less new file mode 100644 index 000000000..bf8508e4d --- /dev/null +++ b/public/self/ztree/css/awesomeStyle/awesome.less @@ -0,0 +1,146 @@ +/*------------------------------------- +zTree Style using fontawesome instead of images + +version: 1.1 +author: Mike King +email: mikkelking @ hotmail . com +website: http://code.google.com/p/jquerytree/ + +-------------------------------------*/ + +/* Definitions ----------------------*/ +@font-size: 12px; +// Regular icon and text color is white, which suits any medium -> dark background +@color-normal: white; +// Background color +@color-bg: #af0000; +// Highlight color +@color-highlight: yellow; +// Partially selected (checkboxes, radio buttons) +@color-partial: #aaaaaa; +// Partially selected and focused (checkboxes, radio buttons) +@color-partfocus: #cad96c; +// Disabled altogether +@color-disabled: #808080; +// Editing color +@color-edit: yellow; +@w: 15px; +@h: 17px; +@pad-left: 2px; +@pad-top: 10px; +/* End of Definitions ---------------*/ + +/* Imports -------------------------*/ +@import "fa.less"; +/* End of Imports ------------------*/ + +.ztree * {padding:0; margin:0; font-size:@font-size; font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif; background-color: @color-bg;} +.ztree { + margin:0; padding:5px; color:@color-normal; background-color: @color-bg; + li { + padding:0; margin:0; list-style:none; line-height:17px; text-align:left; white-space:nowrap; outline:0; + ul { + margin: 0px; padding:0 0 0 18px; + } + ul.line { } + a {padding-right:3px; margin:0; cursor:pointer; height:@h; color:@color-normal; background-color: transparent; + text-decoration:none; vertical-align:top; display: inline-block; + input.rename {height:14px; width:80px; padding:0; margin:0; + color: @color-bg; background-color: @color-normal; + font-size:@font-size; border:1px #585956 solid; *border:0px} + } + a:hover {text-decoration:underline} + a.curSelectedNode {padding-top:0px; background-color:#af4040; color:@color-highlight; height:@h; opacity:0.8;} + a.curSelectedNode_Edit {padding-top:0px; background-color:transparent; color:@color-highlight; height:@h; border:1px #666 solid; opacity:0.8;} + a.tmpTargetNode_inner {padding-top:0px; background-color:#aaa; color:@color-highlight; height:@h; border:1px #666 solid; + opacity:0.8; filter:alpha(opacity=80)} + a.tmpTargetNode_prev {} + a.tmpTargetNode_next {} + span {line-height:@h; margin-right:2px; background-color:transparent;} + span.button {line-height:0; margin:0; padding: 0; width:@w; height:@h; display: inline-block; vertical-align:top; + border:0px solid; cursor: pointer;outline:none; + background-color:transparent; background-repeat:no-repeat; background-attachment: scroll; + + &::before{color: @color-normal; font-family: FontAwesome; padding-top:@pad-top;} + &.chk { margin:0px; cursor: auto; width: 12px; + display: inline-block;padding-top:@pad-top;padding-left:@pad-left; + + &.checkbox_false_full::before {content: @fa-square-o;} + &.checkbox_false_full_focus::before {content: @fa-square-o; color:@color-highlight;} + &.checkbox_false_part::before {content: @fa-square-o;color: @color-partial;} + &.checkbox_false_part_focus::before {content: @fa-square-o; color:@color-partfocus;} + &.checkbox_false_disable::before {content: @fa-square-o; color:@color-disabled;} + &.checkbox_true_full::before {content: @fa-check-square-o;} + &.checkbox_true_full_focus::before {content: @fa-check-square-o;} + &.checkbox_true_part::before {content: @fa-check-square;} + &.checkbox_true_part_focus::before {content: @fa-check-square; color: @color-highlight} + &.checkbox_true_full_focus::before {content: @fa-check-square-o; color: @color-highlight} + &.checkbox_true_part::before {content: @fa-check-square-o;color: @color-partial} + &.checkbox_true_part_focus::before {content: @fa-check-square-o;color: @color-partfocus;} + &.checkbox_true_disable::before {content: @fa-check-square-o;color: @color-disabled} + + &.radio_false_full::before {content: @fa-circle-o;} + &.radio_false_full_focus::before {content: @fa-circle-o;color: @color-highlight} + &.radio_false_part::before {content: @fa-circle-o;color: @color-partial} + &.radio_false_part_focus::before {content: @fa-circle-o;color: @color-highlight} + &.radio_false_disable::before {content: @fa-circle-thin;color: @color-disabled} + &.radio_true_full::before {content: @fa-dot-circle-o;} + &.radio_true_full_focus::before {content: @fa-dot-circle-o;color: @color-highlight} + &.radio_true_part::before {content: @fa-dot-circle-o;color: @color-partial} + &.radio_true_part_focus::before {content: @fa-dot-circle-o;color: @color-partial;} + &.radio_true_disable::before {content: @fa-circle-thin;color: @color-disabled} + + } + &.switch {width:@w; height:@h} + &.root_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;} + &.root_close::before{content: @fa-chevron-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;} + &.roots_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;} + &.roots_close::before{content: @fa-chevron-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;} + &.center_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;} + &.center_close::before{content: @fa-chevron-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;} + &.bottom_open::before{content: @fa-chevron-down;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;} + &.bottom_close::before{content: @fa-chevron-right;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;} + &.noline_open{} + &.noline_close{} + &.root_docu{ background:none;} + &.roots_docu::before{content: @fa-list-alt;padding-left:@pad-left;display: inline-block;color:@color-normal;} + &.center_docu::before{padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;} + &.bottom_docu::before{padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;} + &.noline_docu{ background:none;} + + &.ico_open::before {content: @fa-folder-open-o;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;} + &.ico_close::before {content: @fa-folder-o;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;} + &.ico_docu::before{content: @fa-list-alt;font-family: FontAwesome;padding-top:@pad-top;padding-left:@pad-left;display: inline-block;color:@color-normal;} + + &.edit {margin-left:4px; margin-right: -1px; vertical-align:top; *vertical-align:middle;padding-top:@pad-top;} + &.edit::before{content: @fa-pencil-square-o;font-family: FontAwesome;} + + &.remove {margin-left:4px; margin-right: -1px; vertical-align:top; *vertical-align:middle;padding-top:@pad-top;} + &.remove::before{content: @fa-trash;font-family: FontAwesome;} + + + &.add {margin-left:4px; margin-right: -1px; vertical-align:top; *vertical-align:middle;padding-top:@pad-top;} + &.add::before{content: @fa-plus;font-family: FontAwesome;} + + &.ico_loading{margin-right:2px; background:url(./img/loading.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle} + } + + } +} + + +ul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)} + +// this is the arrow that moves +span.tmpzTreeMove_arrow{width:16px; height:@h; display: inline-block; + padding:0; margin:2px 0 0 1px; border:0 none; position:absolute; + background-color:transparent; background-attachment: scroll; + } +span.tmpzTreeMove_arrow::before{content: @fa-play;font-family: FontAwesome;color: @color-highlight; + } +// outline + +ul.ztree.zTreeDragUL {margin:0; padding:0; position:absolute; width:auto; height:auto;overflow:hidden; + background-color:#cfcfcf; border:1px @color-highlight dotted; opacity:0.8; filter:alpha(opacity=80)} +.ztreeMask {z-index:10000; background-color:#cfcfcf; opacity:0.0; filter:alpha(opacity=0); position:absolute} + diff --git a/public/self/ztree/css/awesomeStyle/fa.less b/public/self/ztree/css/awesomeStyle/fa.less new file mode 100644 index 000000000..3714884a7 --- /dev/null +++ b/public/self/ztree/css/awesomeStyle/fa.less @@ -0,0 +1,480 @@ +@fa-glass: "\f000"; +@fa-music: "\f001"; +@fa-search: "\f002"; +@fa-envelope-o: "\f003"; +@fa-heart: "\f004"; +@fa-star: "\f005"; +@fa-star-o: "\f006"; +@fa-user: "\f007"; +@fa-film: "\f008"; +@fa-th-large: "\f009"; +@fa-th: "\f00a"; +@fa-th-list: "\f00b"; +@fa-check: "\f00c"; +@fa-times: "\f00d"; +@fa-search-plus: "\f00e"; +@fa-search-minus: "\f010"; +@fa-power-off: "\f011"; +@fa-signal: "\f012"; +@fa-cog: "\f013"; +@fa-trash-o: "\f014"; +@fa-home: "\f015"; +@fa-file-o: "\f016"; +@fa-clock-o: "\f017"; +@fa-road: "\f018"; +@fa-download: "\f019"; +@fa-arrow-circle-o-down: "\f01a"; +@fa-arrow-circle-o-up: "\f01b"; +@fa-inbox: "\f01c"; +@fa-play-circle-o: "\f01d"; +@fa-repeat: "\f01e"; +@fa-refresh: "\f021"; +@fa-list-alt: "\f022"; +@fa-lock: "\f023"; +@fa-flag: "\f024"; +@fa-headphones: "\f025"; +@fa-volume-off: "\f026"; +@fa-volume-down: "\f027"; +@fa-volume-up: "\f028"; +@fa-qrcode: "\f029"; +@fa-barcode: "\f02a"; +@fa-tag: "\f02b"; +@fa-tags: "\f02c"; +@fa-book: "\f02d"; +@fa-bookmark: "\f02e"; +@fa-print: "\f02f"; +@fa-camera: "\f030"; +@fa-font: "\f031"; +@fa-bold: "\f032"; +@fa-italic: "\f033"; +@fa-text-height: "\f034"; +@fa-text-width: "\f035"; +@fa-align-left: "\f036"; +@fa-align-center: "\f037"; +@fa-align-right: "\f038"; +@fa-align-justify: "\f039"; +@fa-list: "\f03a"; +@fa-outdent: "\f03b"; +@fa-indent: "\f03c"; +@fa-video-camera: "\f03d"; +@fa-picture-o: "\f03e"; +@fa-pencil: "\f040"; +@fa-map-marker: "\f041"; +@fa-adjust: "\f042"; +@fa-tint: "\f043"; +@fa-pencil-square-o: "\f044"; +@fa-share-square-o: "\f045"; +@fa-check-square-o: "\f046"; +@fa-arrows: "\f047"; +@fa-step-backward: "\f048"; +@fa-fast-backward: "\f049"; +@fa-backward: "\f04a"; +@fa-play: "\f04b"; +@fa-pause: "\f04c"; +@fa-stop: "\f04d"; +@fa-forward: "\f04e"; +@fa-fast-forward: "\f050"; +@fa-step-forward: "\f051"; +@fa-eject: "\f052"; +@fa-chevron-left: "\f053"; +@fa-chevron-right: "\f054"; +@fa-plus-circle: "\f055"; +@fa-minus-circle: "\f056"; +@fa-times-circle: "\f057"; +@fa-check-circle: "\f058"; +@fa-question-circle: "\f059"; +@fa-info-circle: "\f05a"; +@fa-crosshairs: "\f05b"; +@fa-times-circle-o: "\f05c"; +@fa-check-circle-o: "\f05d"; +@fa-ban: "\f05e"; +@fa-arrow-left: "\f060"; +@fa-arrow-right: "\f061"; +@fa-arrow-up: "\f062"; +@fa-arrow-down: "\f063"; +@fa-share: "\f064"; +@fa-expand: "\f065"; +@fa-compress: "\f066"; +@fa-plus: "\f067"; +@fa-minus: "\f068"; +@fa-asterisk: "\f069"; +@fa-exclamation-circle: "\f06a"; +@fa-gift: "\f06b"; +@fa-leaf: "\f06c"; +@fa-fire: "\f06d"; +@fa-eye: "\f06e"; +@fa-eye-slash: "\f070"; +@fa-exclamation-triangle: "\f071"; +@fa-plane: "\f072"; +@fa-calendar: "\f073"; +@fa-random: "\f074"; +@fa-comment: "\f075"; +@fa-magnet: "\f076"; +@fa-chevron-up: "\f077"; +@fa-chevron-down: "\f078"; +@fa-retweet: "\f079"; +@fa-shopping-cart: "\f07a"; +@fa-folder: "\f07b"; +@fa-folder-open: "\f07c"; +@fa-arrows-v: "\f07d"; +@fa-arrows-h: "\f07e"; +@fa-bar-chart: "\f080"; +@fa-twitter-square: "\f081"; +@fa-facebook-square: "\f082"; +@fa-camera-retro: "\f083"; +@fa-key: "\f084"; +@fa-cogs: "\f085"; +@fa-comments: "\f086"; +@fa-thumbs-o-up: "\f087"; +@fa-thumbs-o-down: "\f088"; +@fa-star-half: "\f089"; +@fa-heart-o: "\f08a"; +@fa-sign-out: "\f08b"; +@fa-linkedin-square: "\f08c"; +@fa-thumb-tack: "\f08d"; +@fa-external-link: "\f08e"; +@fa-sign-in: "\f090"; +@fa-trophy: "\f091"; +@fa-github-square: "\f092"; +@fa-upload: "\f093"; +@fa-lemon-o: "\f094"; +@fa-phone: "\f095"; +@fa-square-o: "\f096"; +@fa-bookmark-o: "\f097"; +@fa-phone-square: "\f098"; +@fa-twitter: "\f099"; +@fa-facebook: "\f09a"; +@fa-github: "\f09b"; +@fa-unlock: "\f09c"; +@fa-credit-card: "\f09d"; +@fa-rss: "\f09e"; +@fa-hdd-o: "\f0a0"; +@fa-bullhorn: "\f0a1"; +@fa-bell: "\f0f3"; +@fa-certificate: "\f0a3"; +@fa-hand-o-right: "\f0a4"; +@fa-hand-o-left: "\f0a5"; +@fa-hand-o-up: "\f0a6"; +@fa-hand-o-down: "\f0a7"; +@fa-arrow-circle-left: "\f0a8"; +@fa-arrow-circle-right: "\f0a9"; +@fa-arrow-circle-up: "\f0aa"; +@fa-arrow-circle-down: "\f0ab"; +@fa-globe: "\f0ac"; +@fa-wrench: "\f0ad"; +@fa-tasks: "\f0ae"; +@fa-filter: "\f0b0"; +@fa-briefcase: "\f0b1"; +@fa-arrows-alt: "\f0b2"; +@fa-users: "\f0c0"; +@fa-link: "\f0c1"; +@fa-cloud: "\f0c2"; +@fa-flask: "\f0c3"; +@fa-scissors: "\f0c4"; +@fa-files-o: "\f0c5"; +@fa-paperclip: "\f0c6"; +@fa-floppy-o: "\f0c7"; +@fa-square: "\f0c8"; +@fa-bars: "\f0c9"; +@fa-list-ul: "\f0ca"; +@fa-list-ol: "\f0cb"; +@fa-strikethrough: "\f0cc"; +@fa-underline: "\f0cd"; +@fa-table: "\f0ce"; +@fa-magic: "\f0d0"; +@fa-truck: "\f0d1"; +@fa-pinterest: "\f0d2"; +@fa-pinterest-square: "\f0d3"; +@fa-google-plus-square: "\f0d4"; +@fa-google-plus: "\f0d5"; +@fa-money: "\f0d6"; +@fa-caret-down: "\f0d7"; +@fa-caret-up: "\f0d8"; +@fa-caret-left: "\f0d9"; +@fa-caret-right: "\f0da"; +@fa-columns: "\f0db"; +@fa-sort: "\f0dc"; +@fa-sort-desc: "\f0dd"; +@fa-sort-asc: "\f0de"; +@fa-envelope: "\f0e0"; +@fa-linkedin: "\f0e1"; +@fa-undo: "\f0e2"; +@fa-gavel: "\f0e3"; +@fa-tachometer: "\f0e4"; +@fa-comment-o: "\f0e5"; +@fa-comments-o: "\f0e6"; +@fa-bolt: "\f0e7"; +@fa-sitemap: "\f0e8"; +@fa-umbrella: "\f0e9"; +@fa-clipboard: "\f0ea"; +@fa-lightbulb-o: "\f0eb"; +@fa-exchange: "\f0ec"; +@fa-cloud-download: "\f0ed"; +@fa-cloud-upload: "\f0ee"; +@fa-user-md: "\f0f0"; +@fa-stethoscope: "\f0f1"; +@fa-suitcase: "\f0f2"; +@fa-bell-o: "\f0a2"; +@fa-coffee: "\f0f4"; +@fa-cutlery: "\f0f5"; +@fa-file-text-o: "\f0f6"; +@fa-building-o: "\f0f7"; +@fa-hospital-o: "\f0f8"; +@fa-ambulance: "\f0f9"; +@fa-medkit: "\f0fa"; +@fa-fighter-jet: "\f0fb"; +@fa-beer: "\f0fc"; +@fa-h-square: "\f0fd"; +@fa-plus-square: "\f0fe"; +@fa-angle-double-left: "\f100"; +@fa-angle-double-right: "\f101"; +@fa-angle-double-up: "\f102"; +@fa-angle-double-down: "\f103"; +@fa-angle-left: "\f104"; +@fa-angle-right: "\f105"; +@fa-angle-up: "\f106"; +@fa-angle-down: "\f107"; +@fa-desktop: "\f108"; +@fa-laptop: "\f109"; +@fa-tablet: "\f10a"; +@fa-mobile: "\f10b"; +@fa-circle-o: "\f10c"; +@fa-quote-left: "\f10d"; +@fa-quote-right: "\f10e"; +@fa-spinner: "\f110"; +@fa-circle: "\f111"; +@fa-reply: "\f112"; +@fa-github-alt: "\f113"; +@fa-folder-o: "\f114"; +@fa-folder-open-o: "\f115"; +@fa-smile-o: "\f118"; +@fa-frown-o: "\f119"; +@fa-meh-o: "\f11a"; +@fa-gamepad: "\f11b"; +@fa-keyboard-o: "\f11c"; +@fa-flag-o: "\f11d"; +@fa-flag-checkered: "\f11e"; +@fa-terminal: "\f120"; +@fa-code: "\f121"; +@fa-reply-all: "\f122"; +@fa-star-half-o: "\f123"; +@fa-location-arrow: "\f124"; +@fa-crop: "\f125"; +@fa-code-fork: "\f126"; +@fa-chain-broken: "\f127"; +@fa-question: "\f128"; +@fa-info: "\f129"; +@fa-exclamation: "\f12a"; +@fa-superscript: "\f12b"; +@fa-subscript: "\f12c"; +@fa-eraser: "\f12d"; +@fa-puzzle-piece: "\f12e"; +@fa-microphone: "\f130"; +@fa-microphone-slash: "\f131"; +@fa-shield: "\f132"; +@fa-calendar-o: "\f133"; +@fa-fire-extinguisher: "\f134"; +@fa-rocket: "\f135"; +@fa-maxcdn: "\f136"; +@fa-chevron-circle-left: "\f137"; +@fa-chevron-circle-right: "\f138"; +@fa-chevron-circle-up: "\f139"; +@fa-chevron-circle-down: "\f13a"; +@fa-html5: "\f13b"; +@fa-css3: "\f13c"; +@fa-anchor: "\f13d"; +@fa-unlock-alt: "\f13e"; +@fa-bullseye: "\f140"; +@fa-ellipsis-h: "\f141"; +@fa-ellipsis-v: "\f142"; +@fa-rss-square: "\f143"; +@fa-play-circle: "\f144"; +@fa-ticket: "\f145"; +@fa-minus-square: "\f146"; +@fa-minus-square-o: "\f147"; +@fa-level-up: "\f148"; +@fa-level-down: "\f149"; +@fa-check-square: "\f14a"; +@fa-pencil-square: "\f14b"; +@fa-external-link-square: "\f14c"; +@fa-share-square: "\f14d"; +@fa-compass: "\f14e"; +@fa-caret-square-o-down: "\f150"; +@fa-caret-square-o-up: "\f151"; +@fa-caret-square-o-right: "\f152"; +@fa-eur: "\f153"; +@fa-gbp: "\f154"; +@fa-usd: "\f155"; +@fa-inr: "\f156"; +@fa-jpy: "\f157"; +@fa-rub: "\f158"; +@fa-krw: "\f159"; +@fa-btc: "\f15a"; +@fa-file: "\f15b"; +@fa-file-text: "\f15c"; +@fa-sort-alpha-asc: "\f15d"; +@fa-sort-alpha-desc: "\f15e"; +@fa-sort-amount-asc: "\f160"; +@fa-sort-amount-desc: "\f161"; +@fa-sort-numeric-asc: "\f162"; +@fa-sort-numeric-desc: "\f163"; +@fa-thumbs-up: "\f164"; +@fa-thumbs-down: "\f165"; +@fa-youtube-square: "\f166"; +@fa-youtube: "\f167"; +@fa-xing: "\f168"; +@fa-xing-square: "\f169"; +@fa-youtube-play: "\f16a"; +@fa-dropbox: "\f16b"; +@fa-stack-overflow: "\f16c"; +@fa-instagram: "\f16d"; +@fa-flickr: "\f16e"; +@fa-adn: "\f170"; +@fa-bitbucket: "\f171"; +@fa-bitbucket-square: "\f172"; +@fa-tumblr: "\f173"; +@fa-tumblr-square: "\f174"; +@fa-long-arrow-down: "\f175"; +@fa-long-arrow-up: "\f176"; +@fa-long-arrow-left: "\f177"; +@fa-long-arrow-right: "\f178"; +@fa-apple: "\f179"; +@fa-windows: "\f17a"; +@fa-android: "\f17b"; +@fa-linux: "\f17c"; +@fa-dribbble: "\f17d"; +@fa-skype: "\f17e"; +@fa-foursquare: "\f180"; +@fa-trello: "\f181"; +@fa-female: "\f182"; +@fa-male: "\f183"; +@fa-gittip: "\f184"; +@fa-sun-o: "\f185"; +@fa-moon-o: "\f186"; +@fa-archive: "\f187"; +@fa-bug: "\f188"; +@fa-vk: "\f189"; +@fa-weibo: "\f18a"; +@fa-renren: "\f18b"; +@fa-pagelines: "\f18c"; +@fa-stack-exchange: "\f18d"; +@fa-arrow-circle-o-right: "\f18e"; +@fa-arrow-circle-o-left: "\f190"; +@fa-caret-square-o-left: "\f191"; +@fa-dot-circle-o: "\f192"; +@fa-wheelchair: "\f193"; +@fa-vimeo-square: "\f194"; +@fa-try: "\f195"; +@fa-plus-square-o: "\f196"; +@fa-space-shuttle: "\f197"; +@fa-slack: "\f198"; +@fa-envelope-square: "\f199"; +@fa-wordpress: "\f19a"; +@fa-openid: "\f19b"; +@fa-university: "\f19c"; +@fa-graduation-cap: "\f19d"; +@fa-yahoo: "\f19e"; +@fa-google: "\f1a0"; +@fa-reddit: "\f1a1"; +@fa-reddit-square: "\f1a2"; +@fa-stumbleupon-circle: "\f1a3"; +@fa-stumbleupon: "\f1a4"; +@fa-delicious: "\f1a5"; +@fa-digg: "\f1a6"; +@fa-pied-piper: "\f1a7"; +@fa-pied-piper-alt: "\f1a8"; +@fa-drupal: "\f1a9"; +@fa-joomla: "\f1aa"; +@fa-language: "\f1ab"; +@fa-fax: "\f1ac"; +@fa-building: "\f1ad"; +@fa-child: "\f1ae"; +@fa-paw: "\f1b0"; +@fa-spoon: "\f1b1"; +@fa-cube: "\f1b2"; +@fa-cubes: "\f1b3"; +@fa-behance: "\f1b4"; +@fa-behance-square: "\f1b5"; +@fa-steam: "\f1b6"; +@fa-steam-square: "\f1b7"; +@fa-recycle: "\f1b8"; +@fa-car: "\f1b9"; +@fa-taxi: "\f1ba"; +@fa-tree: "\f1bb"; +@fa-spotify: "\f1bc"; +@fa-deviantart: "\f1bd"; +@fa-soundcloud: "\f1be"; +@fa-database: "\f1c0"; +@fa-file-pdf-o: "\f1c1"; +@fa-file-word-o: "\f1c2"; +@fa-file-excel-o: "\f1c3"; +@fa-file-powerpoint-o: "\f1c4"; +@fa-file-image-o: "\f1c5"; +@fa-file-archive-o: "\f1c6"; +@fa-file-audio-o: "\f1c7"; +@fa-file-video-o: "\f1c8"; +@fa-file-code-o: "\f1c9"; +@fa-vine: "\f1ca"; +@fa-codepen: "\f1cb"; +@fa-jsfiddle: "\f1cc"; +@fa-life-ring: "\f1cd"; +@fa-circle-o-notch: "\f1ce"; +@fa-rebel: "\f1d0"; +@fa-empire: "\f1d1"; +@fa-git-square: "\f1d2"; +@fa-git: "\f1d3"; +@fa-hacker-news: "\f1d4"; +@fa-tencent-weibo: "\f1d5"; +@fa-qq: "\f1d6"; +@fa-weixin: "\f1d7"; +@fa-paper-plane: "\f1d8"; +@fa-paper-plane-o: "\f1d9"; +@fa-history: "\f1da"; +@fa-circle-thin: "\f1db"; +@fa-header: "\f1dc"; +@fa-paragraph: "\f1dd"; +@fa-sliders: "\f1de"; +@fa-share-alt: "\f1e0"; +@fa-share-alt-square: "\f1e1"; +@fa-bomb: "\f1e2"; +@fa-futbol-o: "\f1e3"; +@fa-tty: "\f1e4"; +@fa-binoculars: "\f1e5"; +@fa-plug: "\f1e6"; +@fa-slideshare: "\f1e7"; +@fa-twitch: "\f1e8"; +@fa-yelp: "\f1e9"; +@fa-newspaper-o: "\f1ea"; +@fa-wifi: "\f1eb"; +@fa-calculator: "\f1ec"; +@fa-paypal: "\f1ed"; +@fa-google-wallet: "\f1ee"; +@fa-cc-visa: "\f1f0"; +@fa-cc-mastercard: "\f1f1"; +@fa-cc-discover: "\f1f2"; +@fa-cc-amex: "\f1f3"; +@fa-cc-paypal: "\f1f4"; +@fa-cc-stripe: "\f1f5"; +@fa-bell-slash: "\f1f6"; +@fa-bell-slash-o: "\f1f7"; +@fa-trash: "\f1f8"; +@fa-copyright: "\f1f9"; +@fa-at: "\f1fa"; +@fa-eyedropper: "\f1fb"; +@fa-paint-brush: "\f1fc"; +@fa-birthday-cake: "\f1fd"; +@fa-area-chart: "\f1fe"; +@fa-pie-chart: "\f200"; +@fa-line-chart: "\f201"; +@fa-lastfm: "\f202"; +@fa-lastfm-square: "\f203"; +@fa-toggle-off: "\f204"; +@fa-toggle-on: "\f205"; +@fa-bicycle: "\f206"; +@fa-bus: "\f207"; +@fa-ioxhost: "\f208"; +@fa-angellist: "\f209"; +@fa-cc: "\f20a"; +@fa-ils: "\f20b"; +@fa-meanpath: "\f20c"; + diff --git a/public/self/ztree/css/awesomeStyle/img/loading.gif b/public/self/ztree/css/awesomeStyle/img/loading.gif new file mode 100644 index 000000000..e8c289293 Binary files /dev/null and b/public/self/ztree/css/awesomeStyle/img/loading.gif differ diff --git a/public/self/ztree/css/demo.css b/public/self/ztree/css/demo.css new file mode 100644 index 000000000..f6dba0de8 --- /dev/null +++ b/public/self/ztree/css/demo.css @@ -0,0 +1,33 @@ +html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0;padding: 0;border: 0;outline: 0;font-weight: inherit;font-style: inherit;font-size: 100%;font-family: inherit;vertical-align: baseline;} +body {color: #2f332a;font: 15px/21px Arial, Helvetica, simsun, sans-serif;background: #f0f6e4 \9;} +h1, h2, h3, h4, h5, h6 {color: #2f332a;font-weight: bold;font-family: Helvetica, Arial, sans-serif;padding-bottom: 5px;} +h1 {font-size: 24px;line-height: 34px;text-align: center;} +h2 {font-size: 14px;line-height: 24px;padding-top: 5px;} +h6 {font-weight: normal;font-size: 12px;letter-spacing: 1px;line-height: 24px;text-align: center;} +a {color:#3C6E31;text-decoration: underline;} +a:hover {background-color:#3C6E31;color:white;} +input.radio {margin: 0 2px 0 8px;} +input.radio.first {margin-left:0;} +input.empty {color: lightgray;} +code {color: #2f332a;} +.highlight_red {color:#A60000;} +.highlight_green {color:#A7F43D;} +li {list-style: circle;font-size: 12px;} +li.title {list-style: none;} +ul.list {margin-left: 17px;} + +div.content_wrap {width: 600px;height:380px;} +div.content_wrap div.left{float: left;width: 250px;} +div.content_wrap div.right{float: right;width: 340px;} +div.zTreeDemoBackground {width:250px;height:362px;text-align:left;} + +ul.ztree {margin-top: 10px;border: 1px solid #617775;background: #f0f6e4;width:220px;height:360px;overflow-y:scroll;overflow-x:auto;} +ul.log {border: 1px solid #617775;background: #f0f6e4;width:300px;height:170px;overflow: hidden;} +ul.log.small {height:45px;} +ul.log li {color: #666666;list-style: none;padding-left: 10px;} +ul.log li.dark {background-color: #E3E3E3;} + +/* ruler */ +div.ruler {height:20px; width:220px; background-color:#f0f6e4;border: 1px solid #333; margin-bottom: 5px; cursor: pointer} +div.ruler div.cursor {height:20px; width:30px; background-color:#3C6E31; color:white; text-align: right; padding-right: 5px; cursor: pointer} \ No newline at end of file diff --git a/public/self/ztree/css/metroStyle/img/line_conn.png b/public/self/ztree/css/metroStyle/img/line_conn.png new file mode 100644 index 000000000..b211da2fa Binary files /dev/null and b/public/self/ztree/css/metroStyle/img/line_conn.png differ diff --git a/public/self/ztree/css/metroStyle/img/loading.gif b/public/self/ztree/css/metroStyle/img/loading.gif new file mode 100644 index 000000000..e8c289293 Binary files /dev/null and b/public/self/ztree/css/metroStyle/img/loading.gif differ diff --git a/public/self/ztree/css/metroStyle/img/metro.gif b/public/self/ztree/css/metroStyle/img/metro.gif new file mode 100644 index 000000000..664b969a2 Binary files /dev/null and b/public/self/ztree/css/metroStyle/img/metro.gif differ diff --git a/public/self/ztree/css/metroStyle/img/metro.png b/public/self/ztree/css/metroStyle/img/metro.png new file mode 100644 index 000000000..e9e58a3a7 Binary files /dev/null and b/public/self/ztree/css/metroStyle/img/metro.png differ diff --git a/public/self/ztree/css/metroStyle/metroStyle.css b/public/self/ztree/css/metroStyle/metroStyle.css new file mode 100644 index 000000000..af81f4239 --- /dev/null +++ b/public/self/ztree/css/metroStyle/metroStyle.css @@ -0,0 +1,96 @@ +/*------------------------------------- +zTree Style + +version: 3.4 +author: Hunter.z +email: hunter.z@263.net +website: http://code.google.com/p/jquerytree/ + +-------------------------------------*/ + +.ztree * {padding:0; margin:0; font-size:12px; font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif} +.ztree {margin:0; padding:5px; color:#333} +.ztree li{padding:0; margin:0; list-style:none; line-height:17px; text-align:left; white-space:nowrap; outline:0} +.ztree li ul{ margin:0; padding:0 0 0 18px} +.ztree li ul.line{ background:url(./img/line_conn.png) 0 0 repeat-y;} + +.ztree li a {padding-right:3px; margin:0; cursor:pointer; height:21px; color:#333; background-color: transparent; text-decoration:none; vertical-align:top; display: inline-block} +.ztree li a:hover {text-decoration:underline} +.ztree li a.curSelectedNode {padding-top:0px; background-color:#e5e5e5; color:black; height:21px; opacity:0.8;} +.ztree li a.curSelectedNode_Edit {padding-top:0px; background-color:#e5e5e5; color:black; height:21px; border:1px #666 solid; opacity:0.8;} +.ztree li a.tmpTargetNode_inner {padding-top:0px; background-color:#aaa; color:white; height:21px; border:1px #666 solid; + opacity:0.8; filter:alpha(opacity=80)} +.ztree li a.tmpTargetNode_prev {} +.ztree li a.tmpTargetNode_next {} +.ztree li a input.rename {height:14px; width:80px; padding:0; margin:0; + font-size:12px; border:1px #585956 solid; *border:0px} +.ztree li span {line-height:21px; margin-right:2px} +.ztree li span.button {line-height:0; margin:0; padding: 0; width:21px; height:21px; display: inline-block; vertical-align:middle; + border:0 none; cursor: pointer;outline:none; + background-color:transparent; background-repeat:no-repeat; background-attachment: scroll; + background-image:url("./img/metro.png"); *background-image:url("./img/metro.gif")} + +.ztree li span.button.chk {width:13px; height:13px; margin:0 2px; cursor: auto} +.ztree li span.button.chk.checkbox_false_full {background-position: -5px -5px;} +.ztree li span.button.chk.checkbox_false_full_focus {background-position: -5px -26px;} +.ztree li span.button.chk.checkbox_false_part {background-position: -5px -48px;} +.ztree li span.button.chk.checkbox_false_part_focus {background-position: -5px -68px;} +.ztree li span.button.chk.checkbox_false_disable {background-position: -5px -89px;} +.ztree li span.button.chk.checkbox_true_full {background-position: -26px -5px;} +.ztree li span.button.chk.checkbox_true_full_focus {background-position: -26px -26px;} +.ztree li span.button.chk.checkbox_true_part {background-position: -26px -48px;} +.ztree li span.button.chk.checkbox_true_part_focus {background-position: -26px -68px;} +.ztree li span.button.chk.checkbox_true_disable {background-position: -26px -89px;} +.ztree li span.button.chk.radio_false_full {background-position: -47px -5px;} +.ztree li span.button.chk.radio_false_full_focus {background-position: -47px -26px;} +.ztree li span.button.chk.radio_false_part {background-position: -47px -47px;} +.ztree li span.button.chk.radio_false_part_focus {background-position: -47px -68px;} +.ztree li span.button.chk.radio_false_disable {background-position: -47px -89px;} +.ztree li span.button.chk.radio_true_full {background-position: -68px -5px;} +.ztree li span.button.chk.radio_true_full_focus {background-position: -68px -26px;} +.ztree li span.button.chk.radio_true_part {background-position: -68px -47px;} +.ztree li span.button.chk.radio_true_part_focus {background-position: -68px -68px;} +.ztree li span.button.chk.radio_true_disable {background-position: -68px -89px;} + +.ztree li span.button.switch {width:21px; height:21px} +.ztree li span.button.root_open{background-position:-105px -63px} +.ztree li span.button.root_close{background-position:-126px -63px} +.ztree li span.button.roots_open{background-position: -105px 0;} +.ztree li span.button.roots_close{background-position: -126px 0;} +.ztree li span.button.center_open{background-position: -105px -21px;} +.ztree li span.button.center_close{background-position: -126px -21px;} +.ztree li span.button.bottom_open{background-position: -105px -42px;} +.ztree li span.button.bottom_close{background-position: -126px -42px;} +.ztree li span.button.noline_open{background-position: -105px -84px;} +.ztree li span.button.noline_close{background-position: -126px -84px;} +.ztree li span.button.root_docu{ background:none;} +.ztree li span.button.roots_docu{background-position: -84px 0;} +.ztree li span.button.center_docu{background-position: -84px -21px;} +.ztree li span.button.bottom_docu{background-position: -84px -42px;} +.ztree li span.button.noline_docu{ background:none;} + +.ztree li span.button.ico_open{margin-right:2px; background-position: -147px -21px; vertical-align:top; *vertical-align:middle} +.ztree li span.button.ico_close{margin-right:2px; margin-right:2px; background-position: -147px 0; vertical-align:top; *vertical-align:middle} +.ztree li span.button.ico_docu{margin-right:2px; background-position: -147px -42px; vertical-align:top; *vertical-align:middle} +.ztree li span.button.edit {margin-left:2px; margin-right: -1px; background-position: -189px -21px; vertical-align:top; *vertical-align:middle} +.ztree li span.button.edit:hover { + background-position: -168px -21px; +} +.ztree li span.button.remove {margin-left:2px; margin-right: -1px; background-position: -189px -42px; vertical-align:top; *vertical-align:middle} +.ztree li span.button.remove:hover { + background-position: -168px -42px; +} +.ztree li span.button.add {margin-left:2px; margin-right: -1px; background-position: -189px 0; vertical-align:top; *vertical-align:middle} +.ztree li span.button.add:hover { + background-position: -168px 0; +} +.ztree li span.button.ico_loading{margin-right:2px; background:url(./img/loading.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle} + +ul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)} + +span.tmpzTreeMove_arrow {width:16px; height:21px; display: inline-block; padding:0; margin:2px 0 0 1px; border:0 none; position:absolute; + background-color:transparent; background-repeat:no-repeat; background-attachment: scroll; + background-position:-168px -84px; background-image:url("./img/metro.png"); *background-image:url("./img/metro.gif")} + +ul.ztree.zTreeDragUL {margin:0; padding:0; position:absolute; width:auto; height:auto;overflow:hidden; background-color:#cfcfcf; border:1px #00B83F dotted; opacity:0.8; filter:alpha(opacity=80)} +.ztreeMask {z-index:10000; background-color:#cfcfcf; opacity:0.0; filter:alpha(opacity=0); position:absolute} diff --git a/public/self/ztree/css/zTreeStyle/img/diy/1_close.png b/public/self/ztree/css/zTreeStyle/img/diy/1_close.png new file mode 100644 index 000000000..68ccb3c3b Binary files /dev/null and b/public/self/ztree/css/zTreeStyle/img/diy/1_close.png differ diff --git a/public/self/ztree/css/zTreeStyle/img/diy/1_open.png b/public/self/ztree/css/zTreeStyle/img/diy/1_open.png new file mode 100644 index 000000000..d6ff36d3a Binary files /dev/null and b/public/self/ztree/css/zTreeStyle/img/diy/1_open.png differ diff --git a/public/self/ztree/css/zTreeStyle/img/diy/2.png b/public/self/ztree/css/zTreeStyle/img/diy/2.png new file mode 100644 index 000000000..9eff506ba Binary files /dev/null and b/public/self/ztree/css/zTreeStyle/img/diy/2.png differ diff --git a/public/self/ztree/css/zTreeStyle/img/diy/3.png b/public/self/ztree/css/zTreeStyle/img/diy/3.png new file mode 100644 index 000000000..d7ba6d0c6 Binary files /dev/null and b/public/self/ztree/css/zTreeStyle/img/diy/3.png differ diff --git a/public/self/ztree/css/zTreeStyle/img/diy/4.png b/public/self/ztree/css/zTreeStyle/img/diy/4.png new file mode 100644 index 000000000..753e2bfd5 Binary files /dev/null and b/public/self/ztree/css/zTreeStyle/img/diy/4.png differ diff --git a/public/self/ztree/css/zTreeStyle/img/diy/5.png b/public/self/ztree/css/zTreeStyle/img/diy/5.png new file mode 100644 index 000000000..0c5eccd56 Binary files /dev/null and b/public/self/ztree/css/zTreeStyle/img/diy/5.png differ diff --git a/public/self/ztree/css/zTreeStyle/img/diy/6.png b/public/self/ztree/css/zTreeStyle/img/diy/6.png new file mode 100644 index 000000000..070b8352d Binary files /dev/null and b/public/self/ztree/css/zTreeStyle/img/diy/6.png differ diff --git a/public/self/ztree/css/zTreeStyle/img/diy/7.png b/public/self/ztree/css/zTreeStyle/img/diy/7.png new file mode 100644 index 000000000..532b037f2 Binary files /dev/null and b/public/self/ztree/css/zTreeStyle/img/diy/7.png differ diff --git a/public/self/ztree/css/zTreeStyle/img/diy/8.png b/public/self/ztree/css/zTreeStyle/img/diy/8.png new file mode 100644 index 000000000..a8f3a86e7 Binary files /dev/null and b/public/self/ztree/css/zTreeStyle/img/diy/8.png differ diff --git a/public/self/ztree/css/zTreeStyle/img/diy/9.png b/public/self/ztree/css/zTreeStyle/img/diy/9.png new file mode 100644 index 000000000..4db73cd41 Binary files /dev/null and b/public/self/ztree/css/zTreeStyle/img/diy/9.png differ diff --git a/public/self/ztree/css/zTreeStyle/img/line_conn.gif b/public/self/ztree/css/zTreeStyle/img/line_conn.gif new file mode 100644 index 000000000..d561d36a9 Binary files /dev/null and b/public/self/ztree/css/zTreeStyle/img/line_conn.gif differ diff --git a/public/self/ztree/css/zTreeStyle/img/loading.gif b/public/self/ztree/css/zTreeStyle/img/loading.gif new file mode 100644 index 000000000..e8c289293 Binary files /dev/null and b/public/self/ztree/css/zTreeStyle/img/loading.gif differ diff --git a/public/self/ztree/css/zTreeStyle/img/zTreeStandard.gif b/public/self/ztree/css/zTreeStyle/img/zTreeStandard.gif new file mode 100644 index 000000000..4b640d22e Binary files /dev/null and b/public/self/ztree/css/zTreeStyle/img/zTreeStandard.gif differ diff --git a/public/self/ztree/css/zTreeStyle/img/zTreeStandard.png b/public/self/ztree/css/zTreeStyle/img/zTreeStandard.png new file mode 100644 index 000000000..cd46ddde9 Binary files /dev/null and b/public/self/ztree/css/zTreeStyle/img/zTreeStandard.png differ diff --git a/public/self/ztree/css/zTreeStyle/zTreeStyle.css b/public/self/ztree/css/zTreeStyle/zTreeStyle.css new file mode 100644 index 000000000..39e346a23 --- /dev/null +++ b/public/self/ztree/css/zTreeStyle/zTreeStyle.css @@ -0,0 +1,99 @@ +/*------------------------------------- +zTree Style + +version: 3.5.19 +author: Hunter.z +email: hunter.z@263.net +website: http://code.google.com/p/jquerytree/ + +-------------------------------------*/ + +.ztree * {padding:0; margin:0; font-size:12px; font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif} +.ztree {margin:0; padding:5px; color:#333;margin-top: 0; height: 100%; max-height: 400px; overflow-y: scroll;} +.ztree::-webkit-scrollbar-track{background-color: #FFF;} +.ztree li{padding:5px 0; margin:0; list-style:none; line-height:14px; text-align:left; white-space:nowrap; outline:0; position: relative;} +.ztree li ul{ margin:0; padding:0 0 0 18px} +/*.ztree li ul.line{ background:url(./img/line_conn.gif) 0 0 repeat-y;}*/ + +.ztree li a {padding:1px 3px 0 0; margin:0; cursor:pointer; height:17px; color:#333; background-color: transparent; + text-decoration:none; vertical-align:top; display: inline-block} +.ztree li a:hover {text-decoration:none;} +.ztree li a:hover .node_name::after{content: '';position: absolute;left: 0;right: 0;top: 0;background-color: #f7f7f7;height: 100%;z-index: -1;} +.ztree li a.curSelectedNode {padding-top:0px; background-color:#FFE6B0; color:black; height:16px; border:1px #FFB951 solid; opacity:0.8;} +.ztree li a.curSelectedNode_Edit {padding-top:0px; background-color:#FFE6B0; color:black; height:16px; border:1px #FFB951 solid; opacity:0.8;} +.ztree li a.tmpTargetNode_inner {padding-top:0px; background-color:#316AC5; color:white; height:16px; border:1px #316AC5 solid; + opacity:0.8; filter:alpha(opacity=80)} +.ztree li a.tmpTargetNode_prev {} +.ztree li a.tmpTargetNode_next {} +.ztree li a input.rename {height:14px; width:80px; padding:0; margin:0; + font-size:12px; border:1px #7EC4CC solid; *border:0px} +.ztree li span {line-height:16px; margin-right:2px} +.ztree li span.button {line-height:0; margin:0; width:16px; height:16px; display: inline-block; vertical-align:middle; + border:0 none; cursor: pointer;outline:none; + background-color:transparent; background-repeat:no-repeat; background-attachment: scroll; + background-image:url("./img/zTreeStandard.png"); *background-image:url("./img/zTreeStandard.gif")} + +.ztree li span.button.chk {width:13px; height:13px; margin:0 3px 0 0; cursor: auto} +.ztree li span.button.chk.checkbox_false_full {background-position:0 0} +.ztree li span.button.chk.checkbox_false_full_focus {background-position:0 -14px} +.ztree li span.button.chk.checkbox_false_part {background-position:0 -28px} +.ztree li span.button.chk.checkbox_false_part_focus {background-position:0 -42px} +.ztree li span.button.chk.checkbox_false_disable {background-position:0 -56px} +.ztree li span.button.chk.checkbox_true_full {background-position:-14px 0} +.ztree li span.button.chk.checkbox_true_full_focus {background-position:-14px -14px} +.ztree li span.button.chk.checkbox_true_part {background-position:-14px -28px} +.ztree li span.button.chk.checkbox_true_part_focus {background-position:-14px -42px} +.ztree li span.button.chk.checkbox_true_disable {background-position:-14px -56px} +.ztree li span.button.chk.radio_false_full {background-position:-28px 0} +.ztree li span.button.chk.radio_false_full_focus {background-position:-28px -14px} +.ztree li span.button.chk.radio_false_part {background-position:-28px -28px} +.ztree li span.button.chk.radio_false_part_focus {background-position:-28px -42px} +.ztree li span.button.chk.radio_false_disable {background-position:-28px -56px} +.ztree li span.button.chk.radio_true_full {background-position:-42px 0} +.ztree li span.button.chk.radio_true_full_focus {background-position:-42px -14px} +.ztree li span.button.chk.radio_true_part {background-position:-42px -28px} +.ztree li span.button.chk.radio_true_part_focus {background-position:-42px -42px} +.ztree li span.button.chk.radio_true_disable {background-position:-42px -56px} + +.ztree li span.button.switch {width:18px; height:18px} +.ztree li span.button.root_open{background-position:-92px -54px} +.ztree li span.button.root_close{background-position:-74px -54px} +.ztree li span.button.roots_open{background-position:-92px 0} +.ztree li span.button.roots_close{background-position:-74px 0} +.ztree li span.button.center_open{background-position:-92px -18px} +.ztree li span.button.center_close{background-position:-74px -18px} +.ztree li span.button.bottom_open{background-position:-92px -36px} +.ztree li span.button.bottom_close{background-position:-74px -36px} +.ztree li span.button.noline_open{background-position:-92px -72px} +.ztree li span.button.noline_close{background-position:-74px -72px} +.ztree li span.button.root_docu{ background:none;} +.ztree li span.button.roots_docu{background-position:-56px 0} +.ztree li span.button.center_docu{background-position:-56px -18px} +.ztree li span.button.bottom_docu{background-position:-56px -36px} +.ztree li span.button.noline_docu{ background:none;} + +.ztree li span.button.ico_open{margin-right:2px; background-position:-110px -16px; vertical-align:top; *vertical-align:middle} +.ztree li span.button.ico_close{margin-right:2px; background-position:-110px 0; vertical-align:top; *vertical-align:middle} +.ztree li span.button.ico_docu{margin-right:2px; background-position:-110px -32px; vertical-align:top; *vertical-align:middle} +.ztree li span.button.edit {margin-right:2px; background-position:-110px -48px; vertical-align:top; *vertical-align:middle} +.ztree li span.button.remove {margin-right:2px; background-position:-110px -64px; vertical-align:top; *vertical-align:middle} + +.ztree li span.button.ico_loading{margin-right:2px; background:url(./img/loading.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle} + +ul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)} + +span.tmpzTreeMove_arrow {width:16px; height:16px; display: inline-block; padding:0; margin:2px 0 0 1px; border:0 none; position:absolute; + background-color:transparent; background-repeat:no-repeat; background-attachment: scroll; + background-position:-110px -80px; background-image:url("./img/zTreeStandard.png"); *background-image:url("./img/zTreeStandard.gif")} + +ul.ztree.zTreeDragUL {margin:0; padding:0; position:absolute; width:auto; height:auto;overflow:hidden; background-color:#cfcfcf; border:1px #00B83F dotted; opacity:0.8; filter:alpha(opacity=80)} +.zTreeMask {z-index:10000; background-color:#cfcfcf; opacity:0.0; filter:alpha(opacity=0); position:absolute} + +/* level style*/ +/*.ztree li span.button.level0 { + display:none; +} +.ztree li ul.level0 { + padding:0; + background:none; +}*/ \ No newline at end of file diff --git a/public/self/ztree/js/jquery-1.4.4.min.js b/public/self/ztree/js/jquery-1.4.4.min.js new file mode 100644 index 000000000..8f3ca2e2d --- /dev/null +++ b/public/self/ztree/js/jquery-1.4.4.min.js @@ -0,0 +1,167 @@ +/*! + * jQuery JavaScript Library v1.4.4 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Nov 11 19:04:53 2010 -0500 + */ +(function(E,B){function ka(a,b,d){if(d===B&&a.nodeType===1){d=a.getAttribute("data-"+b);if(typeof d==="string"){try{d=d==="true"?true:d==="false"?false:d==="null"?null:!c.isNaN(d)?parseFloat(d):Ja.test(d)?c.parseJSON(d):d}catch(e){}c.data(a,b,d)}else d=B}return d}function U(){return false}function ca(){return true}function la(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ka(a){var b,d,e,f,h,l,k,o,x,r,A,C=[];f=[];h=c.data(this,this.nodeType?"events":"__events__");if(typeof h==="function")h= +h.events;if(!(a.liveFired===this||!h||!h.live||a.button&&a.type==="click")){if(a.namespace)A=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var J=h.live.slice(0);for(k=0;kd)break;a.currentTarget=f.elem;a.data=f.handleObj.data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f.level;if(A===false)b=false;if(a.isImmediatePropagationStopped())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(La, +"`").replace(Ma,"&")}function ma(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Na.test(b))return c.filter(b,e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function na(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this, +e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var l in e[h])c.event.add(this,h,e[h][l],e[h][l].data)}}})}function Oa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function oa(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?Pa:Qa,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a, +"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function da(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Ra.test(a)?e(a,h):da(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)?e(a,""):c.each(b,function(f,h){da(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(pa.concat.apply([],pa.slice(0,b)),function(){d[this]=a});return d}function qa(a){if(!ea[a]){var b=c("<"+ +a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";ea[a]=d}return ea[a]}function fa(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var t=E.document,c=function(){function a(){if(!b.isReady){try{t.documentElement.doScroll("left")}catch(j){setTimeout(a,1);return}b.ready()}}var b=function(j,s){return new b.fn.init(j,s)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,l=/\S/,k=/^\s+/,o=/\s+$/,x=/\W/,r=/\d/,A=/^<(\w+)\s*\/?>(?:<\/\1>)?$/, +C=/^[\],:{}\s]*$/,J=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,I=/(?:^|:|,)(?:\s*\[)+/g,L=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,i=/(msie) ([\w.]+)/,n=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false,q=[],u,y=Object.prototype.toString,F=Object.prototype.hasOwnProperty,M=Array.prototype.push,N=Array.prototype.slice,O=String.prototype.trim,D=Array.prototype.indexOf,R={};b.fn=b.prototype={init:function(j, +s){var v,z,H;if(!j)return this;if(j.nodeType){this.context=this[0]=j;this.length=1;return this}if(j==="body"&&!s&&t.body){this.context=t;this[0]=t.body;this.selector="body";this.length=1;return this}if(typeof j==="string")if((v=h.exec(j))&&(v[1]||!s))if(v[1]){H=s?s.ownerDocument||s:t;if(z=A.exec(j))if(b.isPlainObject(s)){j=[t.createElement(z[1])];b.fn.attr.call(j,s,true)}else j=[H.createElement(z[1])];else{z=b.buildFragment([v[1]],[H]);j=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this, +j)}else{if((z=t.getElementById(v[2]))&&z.parentNode){if(z.id!==v[2])return f.find(j);this.length=1;this[0]=z}this.context=t;this.selector=j;return this}else if(!s&&!x.test(j)){this.selector=j;this.context=t;j=t.getElementsByTagName(j);return b.merge(this,j)}else return!s||s.jquery?(s||f).find(j):b(s).find(j);else if(b.isFunction(j))return f.ready(j);if(j.selector!==B){this.selector=j.selector;this.context=j.context}return b.makeArray(j,this)},selector:"",jquery:"1.4.4",length:0,size:function(){return this.length}, +toArray:function(){return N.call(this,0)},get:function(j){return j==null?this.toArray():j<0?this.slice(j)[0]:this[j]},pushStack:function(j,s,v){var z=b();b.isArray(j)?M.apply(z,j):b.merge(z,j);z.prevObject=this;z.context=this.context;if(s==="find")z.selector=this.selector+(this.selector?" ":"")+v;else if(s)z.selector=this.selector+"."+s+"("+v+")";return z},each:function(j,s){return b.each(this,j,s)},ready:function(j){b.bindReady();if(b.isReady)j.call(t,b);else q&&q.push(j);return this},eq:function(j){return j=== +-1?this.slice(j):this.slice(j,+j+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(j){return this.pushStack(b.map(this,function(s,v){return j.call(s,v,s)}))},end:function(){return this.prevObject||b(null)},push:M,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var j,s,v,z,H,G=arguments[0]||{},K=1,Q=arguments.length,ga=false; +if(typeof G==="boolean"){ga=G;G=arguments[1]||{};K=2}if(typeof G!=="object"&&!b.isFunction(G))G={};if(Q===K){G=this;--K}for(;K0))if(q){var s=0,v=q;for(q=null;j=v[s++];)j.call(t,b);b.fn.trigger&&b(t).trigger("ready").unbind("ready")}}},bindReady:function(){if(!p){p=true;if(t.readyState==="complete")return setTimeout(b.ready,1);if(t.addEventListener){t.addEventListener("DOMContentLoaded",u,false);E.addEventListener("load",b.ready,false)}else if(t.attachEvent){t.attachEvent("onreadystatechange",u);E.attachEvent("onload", +b.ready);var j=false;try{j=E.frameElement==null}catch(s){}t.documentElement.doScroll&&j&&a()}}},isFunction:function(j){return b.type(j)==="function"},isArray:Array.isArray||function(j){return b.type(j)==="array"},isWindow:function(j){return j&&typeof j==="object"&&"setInterval"in j},isNaN:function(j){return j==null||!r.test(j)||isNaN(j)},type:function(j){return j==null?String(j):R[y.call(j)]||"object"},isPlainObject:function(j){if(!j||b.type(j)!=="object"||j.nodeType||b.isWindow(j))return false;if(j.constructor&& +!F.call(j,"constructor")&&!F.call(j.constructor.prototype,"isPrototypeOf"))return false;for(var s in j);return s===B||F.call(j,s)},isEmptyObject:function(j){for(var s in j)return false;return true},error:function(j){throw j;},parseJSON:function(j){if(typeof j!=="string"||!j)return null;j=b.trim(j);if(C.test(j.replace(J,"@").replace(w,"]").replace(I,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(j):(new Function("return "+j))();else b.error("Invalid JSON: "+j)},noop:function(){},globalEval:function(j){if(j&& +l.test(j)){var s=t.getElementsByTagName("head")[0]||t.documentElement,v=t.createElement("script");v.type="text/javascript";if(b.support.scriptEval)v.appendChild(t.createTextNode(j));else v.text=j;s.insertBefore(v,s.firstChild);s.removeChild(v)}},nodeName:function(j,s){return j.nodeName&&j.nodeName.toUpperCase()===s.toUpperCase()},each:function(j,s,v){var z,H=0,G=j.length,K=G===B||b.isFunction(j);if(v)if(K)for(z in j){if(s.apply(j[z],v)===false)break}else for(;H
a";var f=d.getElementsByTagName("*"),h=d.getElementsByTagName("a")[0],l=t.createElement("select"), +k=l.appendChild(t.createElement("option"));if(!(!f||!f.length||!h)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(h.getAttribute("style")),hrefNormalized:h.getAttribute("href")==="/a",opacity:/^0.55$/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:k.selected,deleteExpando:true,optDisabled:false,checkClone:false, +scriptEval:false,noCloneEvent:true,boxModel:null,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableHiddenOffsets:true};l.disabled=true;c.support.optDisabled=!k.disabled;b.type="text/javascript";try{b.appendChild(t.createTextNode("window."+e+"=1;"))}catch(o){}a.insertBefore(b,a.firstChild);if(E[e]){c.support.scriptEval=true;delete E[e]}try{delete b.test}catch(x){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function r(){c.support.noCloneEvent= +false;d.detachEvent("onclick",r)});d.cloneNode(true).fireEvent("onclick")}d=t.createElement("div");d.innerHTML="";a=t.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var r=t.createElement("div");r.style.width=r.style.paddingLeft="1px";t.body.appendChild(r);c.boxModel=c.support.boxModel=r.offsetWidth===2;if("zoom"in r.style){r.style.display="inline";r.style.zoom= +1;c.support.inlineBlockNeedsLayout=r.offsetWidth===2;r.style.display="";r.innerHTML="
";c.support.shrinkWrapBlocks=r.offsetWidth!==2}r.innerHTML="
t
";var A=r.getElementsByTagName("td");c.support.reliableHiddenOffsets=A[0].offsetHeight===0;A[0].style.display="";A[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&A[0].offsetHeight===0;r.innerHTML="";t.body.removeChild(r).style.display= +"none"});a=function(r){var A=t.createElement("div");r="on"+r;var C=r in A;if(!C){A.setAttribute(r,"return;");C=typeof A[r]==="function"}return C};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();var ra={},Ja=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?ra:a;var e=a.nodeType,f=e?a[c.expando]:null,h= +c.cache;if(!(e&&!f&&typeof b==="string"&&d===B)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]=c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==B)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?ra:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando); +else if(d)delete f[e];else for(var l in a)delete a[l]}},acceptData:function(a){if(a.nodeName){var b=c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){var d=null;if(typeof a==="undefined"){if(this.length){var e=this[0].attributes,f;d=c.data(this[0]);for(var h=0,l=e.length;h-1)return true;return false},val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one"; +if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h=0;else if(c.nodeName(this,"select")){var A=c.makeArray(r);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),A)>=0});if(!A.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true}, +attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return B;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==B;b=e&&c.props[b]||b;var h=Ta.test(b);if((b in a||a[b]!==B)&&e&&!h){if(f){b==="type"&&Ua.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&& +b.specified?b.value:Va.test(a.nodeName)||Wa.test(a.nodeName)&&a.href?0:B;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return B;a=!c.support.hrefNormalized&&e&&h?a.getAttribute(b,2):a.getAttribute(b);return a===null?B:a}});var X=/\.(.*)$/,ia=/^(?:textarea|input|select)$/i,La=/\./g,Ma=/ /g,Xa=/[^\w\s.|`]/g,Ya=function(a){return a.replace(Xa,"\\$&")},ua={focusin:0,focusout:0}; +c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;else if(!d)return;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var l=a.nodeType?"events":"__events__",k=h[l],o=h.handle;if(typeof k==="function"){o=k.handle;k=k.events}else if(!k){a.nodeType||(h[l]=h=function(){});h.events=k={}}if(!o)h.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem, +arguments):B};o.elem=a;b=b.split(" ");for(var x=0,r;l=b[x++];){h=f?c.extend({},f):{handler:d,data:e};if(l.indexOf(".")>-1){r=l.split(".");l=r.shift();h.namespace=r.slice(0).sort().join(".")}else{r=[];h.namespace=""}h.type=l;if(!h.guid)h.guid=d.guid;var A=k[l],C=c.event.special[l]||{};if(!A){A=k[l]=[];if(!C.setup||C.setup.call(a,e,r,o)===false)if(a.addEventListener)a.addEventListener(l,o,false);else a.attachEvent&&a.attachEvent("on"+l,o)}if(C.add){C.add.call(a,h);if(!h.handler.guid)h.handler.guid= +d.guid}A.push(h);c.event.global[l]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,l=0,k,o,x,r,A,C,J=a.nodeType?"events":"__events__",w=c.data(a),I=w&&w[J];if(w&&I){if(typeof I==="function"){w=I;I=I.events}if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in I)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[l++];){r=f;k=f.indexOf(".")<0;o=[];if(!k){o=f.split(".");f=o.shift();x=RegExp("(^|\\.)"+ +c.map(o.slice(0).sort(),Ya).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(A=I[f])if(d){r=c.event.special[f]||{};for(h=e||0;h=0){a.type=f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType=== +8)return B;a.result=B;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)===false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){var l;e=a.target;var k=f.replace(X,""),o=c.nodeName(e,"a")&&k=== +"click",x=c.event.special[k]||{};if((!x._default||x._default.call(d,a)===false)&&!o&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[k]){if(l=e["on"+k])e["on"+k]=null;c.event.triggered=true;e[k]()}}catch(r){}if(l)e["on"+k]=l;c.event.triggered=false}}},handle:function(a){var b,d,e,f;d=[];var h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+ +d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var l=d.length;f-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ia.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=xa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===B||f===e))if(e!=null||f){a.type="change";a.liveFired= +B;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",xa(a))}},setup:function(){if(this.type=== +"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ia.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ia.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}t.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){ua[b]++===0&&t.addEventListener(a,d,true)},teardown:function(){--ua[b]=== +0&&t.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=B}var l=b==="one"?c.proxy(f,function(o){c(this).unbind(o,l);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var k=this.length;h0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}}); +(function(){function a(g,i,n,m,p,q){p=0;for(var u=m.length;p0){F=y;break}}y=y[g]}m[p]=F}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,l=true;[0,0].sort(function(){l=false;return 0});var k=function(g,i,n,m){n=n||[];var p=i=i||t;if(i.nodeType!==1&&i.nodeType!==9)return[];if(!g||typeof g!=="string")return n;var q,u,y,F,M,N=true,O=k.isXML(i),D=[],R=g;do{d.exec("");if(q=d.exec(R)){R=q[3];D.push(q[1]);if(q[2]){F=q[3]; +break}}}while(q);if(D.length>1&&x.exec(g))if(D.length===2&&o.relative[D[0]])u=L(D[0]+D[1],i);else for(u=o.relative[D[0]]?[i]:k(D.shift(),i);D.length;){g=D.shift();if(o.relative[g])g+=D.shift();u=L(g,u)}else{if(!m&&D.length>1&&i.nodeType===9&&!O&&o.match.ID.test(D[0])&&!o.match.ID.test(D[D.length-1])){q=k.find(D.shift(),i,O);i=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]}if(i){q=m?{expr:D.pop(),set:C(m)}:k.find(D.pop(),D.length===1&&(D[0]==="~"||D[0]==="+")&&i.parentNode?i.parentNode:i,O);u=q.expr?k.filter(q.expr, +q.set):q.set;if(D.length>0)y=C(u);else N=false;for(;D.length;){q=M=D.pop();if(o.relative[M])q=D.pop();else M="";if(q==null)q=i;o.relative[M](y,q,O)}}else y=[]}y||(y=u);y||k.error(M||g);if(f.call(y)==="[object Array]")if(N)if(i&&i.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&k.contains(i,y[g])))n.push(u[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&n.push(u[g]);else n.push.apply(n,y);else C(y,n);if(F){k(F,p,n,m);k.uniqueSort(n)}return n};k.uniqueSort=function(g){if(w){h= +l;g.sort(w);if(h)for(var i=1;i0};k.find=function(g,i,n){var m;if(!g)return[];for(var p=0,q=o.order.length;p":function(g,i){var n,m=typeof i==="string",p=0,q=g.length;if(m&&!/\W/.test(i))for(i=i.toLowerCase();p=0))n||m.push(u);else if(n)i[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var i=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=i[1]+(i[2]||1)-0;g[3]=i[3]-0}g[0]=e++;return g},ATTR:function(g,i,n, +m,p,q){i=g[1].replace(/\\/g,"");if(!q&&o.attrMap[i])g[1]=o.attrMap[i];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,i,n,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,i);else{g=k.filter(g[3],i,n,true^p);n||m.push.apply(m,g);return false}else if(o.match.POS.test(g[0])||o.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled=== +true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,i,n){return!!k(n[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"=== +g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,i){return i===0},last:function(g,i,n,m){return i===m.length-1},even:function(g,i){return i%2===0},odd:function(g,i){return i%2===1},lt:function(g,i,n){return in[3]-0},nth:function(g,i,n){return n[3]- +0===i},eq:function(g,i,n){return n[3]-0===i}},filter:{PSEUDO:function(g,i,n,m){var p=i[1],q=o.filters[p];if(q)return q(g,n,i,m);else if(p==="contains")return(g.textContent||g.innerText||k.getText([g])||"").indexOf(i[3])>=0;else if(p==="not"){i=i[3];n=0;for(m=i.length;n=0}},ID:function(g,i){return g.nodeType===1&&g.getAttribute("id")===i},TAG:function(g,i){return i==="*"&&g.nodeType===1||g.nodeName.toLowerCase()=== +i},CLASS:function(g,i){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(i)>-1},ATTR:function(g,i){var n=i[1];n=o.attrHandle[n]?o.attrHandle[n](g):g[n]!=null?g[n]:g.getAttribute(n);var m=n+"",p=i[2],q=i[4];return n==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&n!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,i,n,m){var p=o.setFilters[i[2]]; +if(p)return p(g,n,i,m)}}},x=o.match.POS,r=function(g,i){return"\\"+(i-0+1)},A;for(A in o.match){o.match[A]=RegExp(o.match[A].source+/(?![^\[]*\])(?![^\(]*\))/.source);o.leftMatch[A]=RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[A].source.replace(/\\(\d+)/g,r))}var C=function(g,i){g=Array.prototype.slice.call(g,0);if(i){i.push.apply(i,g);return i}return g};try{Array.prototype.slice.call(t.documentElement.childNodes,0)}catch(J){C=function(g,i){var n=0,m=i||[];if(f.call(g)==="[object Array]")Array.prototype.push.apply(m, +g);else if(typeof g.length==="number")for(var p=g.length;n";n.insertBefore(g,n.firstChild);if(t.getElementById(i)){o.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:B:[]};o.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}n.removeChild(g); +n=g=null})();(function(){var g=t.createElement("div");g.appendChild(t.createComment(""));if(g.getElementsByTagName("*").length>0)o.find.TAG=function(i,n){var m=n.getElementsByTagName(i[1]);if(i[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML="";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")o.attrHandle.href=function(i){return i.getAttribute("href",2)};g=null})();t.querySelectorAll&& +function(){var g=k,i=t.createElement("div");i.innerHTML="

";if(!(i.querySelectorAll&&i.querySelectorAll(".TEST").length===0)){k=function(m,p,q,u){p=p||t;m=m.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!u&&!k.isXML(p))if(p.nodeType===9)try{return C(p.querySelectorAll(m),q)}catch(y){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var F=p.getAttribute("id"),M=F||"__sizzle__";F||p.setAttribute("id",M);try{return C(p.querySelectorAll("#"+M+" "+m),q)}catch(N){}finally{F|| +p.removeAttribute("id")}}return g(m,p,q,u)};for(var n in g)k[n]=g[n];i=null}}();(function(){var g=t.documentElement,i=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,n=false;try{i.call(t.documentElement,"[test!='']:sizzle")}catch(m){n=true}if(i)k.matchesSelector=function(p,q){q=q.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(p))try{if(n||!o.match.PSEUDO.test(q)&&!/!=/.test(q))return i.call(p,q)}catch(u){}return k(q,null,null,[p]).length>0}})();(function(){var g= +t.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){o.order.splice(1,0,"CLASS");o.find.CLASS=function(i,n,m){if(typeof n.getElementsByClassName!=="undefined"&&!m)return n.getElementsByClassName(i[1])};g=null}}})();k.contains=t.documentElement.contains?function(g,i){return g!==i&&(g.contains?g.contains(i):true)}:t.documentElement.compareDocumentPosition? +function(g,i){return!!(g.compareDocumentPosition(i)&16)}:function(){return false};k.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var L=function(g,i){for(var n,m=[],p="",q=i.nodeType?[i]:i;n=o.match.PSEUDO.exec(g);){p+=n[0];g=g.replace(o.match.PSEUDO,"")}g=o.relative[g]?g+"*":g;n=0;for(var u=q.length;n0)for(var h=d;h0},closest:function(a,b){var d=[],e,f,h=this[0];if(c.isArray(a)){var l,k={},o=1;if(h&&a.length){e=0;for(f=a.length;e-1:c(h).is(e))d.push({selector:l,elem:h,level:o})}h= +h.parentNode;o++}}return d}l=cb.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h||!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context): +c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a, +2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a, +b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Za.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||ab.test(e))&&$a.test(a))f=f.reverse();return this.pushStack(f,a,bb.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===B||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&& +e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var za=/ jQuery\d+="(?:\d+|null)"/g,$=/^\s+/,Aa=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Ba=/<([\w:]+)/,db=/\s]+\/)>/g,P={option:[1, +""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};P.optgroup=P.option;P.tbody=P.tfoot=P.colgroup=P.caption=P.thead;P.th=P.td;if(!c.support.htmlSerialize)P._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==B)return this.empty().append((this[0]&&this[0].ownerDocument||t).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*"));c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(za,"").replace(fb,'="$1">').replace($,"")],e)[0]}else return this.cloneNode(true)});if(a===true){na(this,b);na(this.find("*"),b.find("*"))}return b},html:function(a){if(a===B)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(za,""):null; +else if(typeof a==="string"&&!Ca.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!P[(Ba.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Aa,"<$1>");try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?h.cloneNode(true):h)}k.length&&c.each(k,Oa)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:t;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===t&&!Ca.test(a[0])&&(c.support.checkClone||!Da.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append", +prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h=d.length;f0?this.clone(true):this).get();c(d[f])[b](l);e=e.concat(l)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||t;if(typeof b.createElement==="undefined")b=b.ownerDocument|| +b[0]&&b[0].ownerDocument||t;for(var f=[],h=0,l;(l=a[h])!=null;h++){if(typeof l==="number")l+="";if(l){if(typeof l==="string"&&!eb.test(l))l=b.createTextNode(l);else if(typeof l==="string"){l=l.replace(Aa,"<$1>");var k=(Ba.exec(l)||["",""])[1].toLowerCase(),o=P[k]||P._default,x=o[0],r=b.createElement("div");for(r.innerHTML=o[1]+l+o[2];x--;)r=r.lastChild;if(!c.support.tbody){x=db.test(l);k=k==="table"&&!x?r.firstChild&&r.firstChild.childNodes:o[1]===""&&!x?r.childNodes:[];for(o=k.length- +1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script")))); +d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i, +jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true, +zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b), +h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b); +if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f= +d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left; +e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/)<[^<]*)*<\/script>/gi, +ob=/^(?:select|textarea)/i,pb=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,qb=/^(?:GET|HEAD)$/,Ra=/\[\]$/,T=/\=\?(&|$)/,ja=/\?/,rb=/([?&])_=[^&]*/,sb=/^(\w+:)?\/\/([^\/?#]+)/,tb=/%20/g,ub=/#.*$/,Ha=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!=="string"&&Ha)return Ha.apply(this,arguments);else if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b=== +"object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(l,k){if(k==="success"||k==="notmodified")h.html(f?c("
").append(l.responseText.replace(nb,"")).find(f):l.responseText);d&&h.each(d,[l.responseText,k,l])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&& +!this.disabled&&(this.checked||ob.test(this.nodeName)||pb.test(this.type))}).map(function(a,b){var d=c(this).val();return d==null?null:c.isArray(d)?c.map(d,function(e){return{name:b.name,value:e}}):{name:b.name,value:d}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})}, +getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return new E.XMLHttpRequest},accepts:{xml:"application/xml, text/xml",html:"text/html", +script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),l=qb.test(h);b.url=b.url.replace(ub,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)||(b.url+=(ja.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else if(!b.data|| +!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp||"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)||T.test(b.url))){d=b.jsonpCallback||"jsonp"+mb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var k=E[d];E[d]=function(m){if(c.isFunction(k))k(m);else{E[d]=B;try{delete E[d]}catch(p){}}f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);r&&r.removeChild(A)}}if(b.dataType==="script"&&b.cache===null)b.cache= +false;if(b.cache===false&&l){var o=c.now(),x=b.url.replace(rb,"$1_="+o);b.url=x+(x===b.url?(ja.test(b.url)?"&":"?")+"_="+o:"")}if(b.data&&l)b.url+=(ja.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");o=(o=sb.exec(b.url))&&(o[1]&&o[1].toLowerCase()!==location.protocol||o[2].toLowerCase()!==location.host);if(b.dataType==="script"&&h==="GET"&&o){var r=t.getElementsByTagName("head")[0]||t.documentElement,A=t.createElement("script");if(b.scriptCharset)A.charset=b.scriptCharset; +A.src=b.url;if(!d){var C=false;A.onload=A.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);A.onload=A.onreadystatechange=null;r&&A.parentNode&&r.removeChild(A)}}}r.insertBefore(A,r.firstChild);return B}var J=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!l||a&&a.contentType)w.setRequestHeader("Content-Type", +b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}o||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+", */*; q=0.01":b.accepts._default)}catch(I){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return false}b.global&& +c.triggerGlobal(b,"ajaxSend",[w,b]);var L=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){J||c.handleComplete(b,w,e,f);J=true;if(w)w.onreadystatechange=c.noop}else if(!J&&w&&(w.readyState===4||m==="timeout")){J=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"||e==="notmodified")d|| +c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var g=w.abort;w.abort=function(){w&&Function.prototype.call.call(g,w);L("abort")}}catch(i){}b.async&&b.timeout>0&&setTimeout(function(){w&&!J&&L("timeout")},b.timeout);try{w.send(l||b.data==null?null:b.data)}catch(n){c.handleError(b,w,null,n);c.handleComplete(b,w,e,f)}b.async||L();return w}},param:function(a,b){var d=[],e=function(h,l){l=c.isFunction(l)?l():l;d[d.length]= +encodeURIComponent(h)+"="+encodeURIComponent(l)};if(b===B)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){e(this.name,this.value)});else for(var f in a)da(f,a[f],b,e);return d.join("&").replace(tb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess", +[b,a])},handleComplete:function(a,b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"), +e=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return a.status===304},httpData:function(a,b,d){var e=a.getResponseHeader("content-type")||"",f=b==="xml"||!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return a}}); +if(E.ActiveXObject)c.ajaxSettings.xhr=function(){if(E.location.protocol!=="file:")try{return new E.XMLHttpRequest}catch(a){}try{return new E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var ea={},vb=/^(?:toggle|show|hide)$/,wb=/^([+\-]=)?([\d+.\-]+)(.*)$/,ba,pa=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a||a===0)return this.animate(S("show", +3),a,b,d);else{d=0;for(var e=this.length;d=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b||this.dequeue();return this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){c.fn[a]=function(d,e,f){return this.animate(b, +d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof a==="object"?c.extend({},a):{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,d,e){return d+e*a},swing:function(a,b,d,e){return(-Math.cos(a* +Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(c.css(this.elem,this.prop));return a&&a>-1E4?a:0},custom:function(a,b,d){function e(l){return f.step(l)} +var f=this,h=c.fx;this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;e.elem=this.elem;if(e()&&c.timers.push(e)&&!ba)ba=setInterval(h.tick,h.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true; +this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var e in this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var f=this.elem,h=this.options;c.each(["","X","Y"],function(k,o){f.style["overflow"+o]=h.overflow[k]})}this.options.hide&&c(this.elem).hide();if(this.options.hide|| +this.options.show)for(var l in this.options.curAnim)c.style(this.elem,l,this.options.orig[l]);this.options.complete.call(this.elem)}return false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a= +c.timers,b=0;b-1;e={};var x={};if(o)x=f.position();l=o?x.top:parseInt(l,10)||0;k=o?x.left:parseInt(k,10)||0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+l;if(b.left!=null)e.left=b.left-h.left+k;"using"in b?b.using.call(a, +e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),e=Ia.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))||0;d.left-=parseFloat(c.css(a,"marginLeft"))||0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||t.body;a&&!Ia.test(a.nodeName)&& +c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return null;if(e!==B)return this.each(function(){if(h=fa(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else this[d]=e});else return(h=fa(f))?"pageXOffset"in h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]||h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase(); +c.fn["inner"+b]=function(){return this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return this.each(function(l){var k=c(this);k[d](e.call(this,l,k[d]()))});if(c.isWindow(f))return f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]||f.document.body["client"+b];else if(f.nodeType===9)return Math.max(f.documentElement["client"+ +b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]);else if(e===B){f=c.css(f,d);var h=parseFloat(f);return c.isNaN(h)?f:h}else return this.css(d,typeof e==="string"?e:e+"px")}})})(window); diff --git a/public/self/ztree/js/jquery.ztree.all.js b/public/self/ztree/js/jquery.ztree.all.js new file mode 100644 index 000000000..dbca0e564 --- /dev/null +++ b/public/self/ztree/js/jquery.ztree.all.js @@ -0,0 +1,3878 @@ +/* + * JQuery zTree core + * v3.5.48 + * http://treejs.cn/ + * + * Copyright (c) 2010 Hunter.z + * + * Licensed same as jquery - MIT License + * http://www.opensource.org/licenses/mit-license.php + * + * Date: 2020-11-21 + */ + +(function ($) { + var settings = {}, roots = {}, caches = {}, + //default consts of core + _consts = { + className: { + BUTTON: "button", + LEVEL: "level", + ICO_LOADING: "ico_loading", + SWITCH: "switch", + NAME: 'node_name' + }, + event: { + NODECREATED: "ztree_nodeCreated", + CLICK: "ztree_click", + EXPAND: "ztree_expand", + COLLAPSE: "ztree_collapse", + ASYNC_SUCCESS: "ztree_async_success", + ASYNC_ERROR: "ztree_async_error", + REMOVE: "ztree_remove", + SELECTED: "ztree_selected", + UNSELECTED: "ztree_unselected" + }, + id: { + A: "_a", + ICON: "_ico", + SPAN: "_span", + SWITCH: "_switch", + UL: "_ul" + }, + line: { + ROOT: "root", + ROOTS: "roots", + CENTER: "center", + BOTTOM: "bottom", + NOLINE: "noline", + LINE: "line" + }, + folder: { + OPEN: "open", + CLOSE: "close", + DOCU: "docu" + }, + node: { + CURSELECTED: "curSelectedNode" + } + }, + //default setting of core + _setting = { + treeId: "", + treeObj: null, + view: { + addDiyDom: null, + autoCancelSelected: true, + dblClickExpand: true, + expandSpeed: "fast", + fontCss: {}, + nodeClasses: {}, + nameIsHTML: false, + selectedMulti: true, + showIcon: true, + showLine: true, + showTitle: true, + txtSelectedEnable: false + }, + data: { + key: { + isParent: "isParent", + children: "children", + name: "name", + title: "", + url: "url", + icon: "icon" + }, + render: { + name: null, + title: null, + }, + simpleData: { + enable: false, + idKey: "id", + pIdKey: "pId", + rootPId: null + }, + keep: { + parent: false, + leaf: false + } + }, + async: { + enable: false, + contentType: "application/x-www-form-urlencoded", + type: "post", + dataType: "text", + headers: {}, + xhrFields: {}, + url: "", + autoParam: [], + otherParam: [], + dataFilter: null + }, + callback: { + beforeAsync: null, + beforeClick: null, + beforeDblClick: null, + beforeRightClick: null, + beforeMouseDown: null, + beforeMouseUp: null, + beforeExpand: null, + beforeCollapse: null, + beforeRemove: null, + + onAsyncError: null, + onAsyncSuccess: null, + onNodeCreated: null, + onClick: null, + onDblClick: null, + onRightClick: null, + onMouseDown: null, + onMouseUp: null, + onExpand: null, + onCollapse: null, + onRemove: null + } + }, + //default root of core + //zTree use root to save full data + _initRoot = function (setting) { + var r = data.getRoot(setting); + if (!r) { + r = {}; + data.setRoot(setting, r); + } + data.nodeChildren(setting, r, []); + r.expandTriggerFlag = false; + r.curSelectedList = []; + r.noSelection = true; + r.createdNodes = []; + r.zId = 0; + r._ver = (new Date()).getTime(); + }, + //default cache of core + _initCache = function (setting) { + var c = data.getCache(setting); + if (!c) { + c = {}; + data.setCache(setting, c); + } + c.nodes = []; + c.doms = []; + }, + //default bindEvent of core + _bindEvent = function (setting) { + var o = setting.treeObj, + c = consts.event; + o.bind(c.NODECREATED, function (event, treeId, node) { + tools.apply(setting.callback.onNodeCreated, [event, treeId, node]); + }); + + o.bind(c.CLICK, function (event, srcEvent, treeId, node, clickFlag) { + tools.apply(setting.callback.onClick, [srcEvent, treeId, node, clickFlag]); + }); + + o.bind(c.EXPAND, function (event, treeId, node) { + tools.apply(setting.callback.onExpand, [event, treeId, node]); + }); + + o.bind(c.COLLAPSE, function (event, treeId, node) { + tools.apply(setting.callback.onCollapse, [event, treeId, node]); + }); + + o.bind(c.ASYNC_SUCCESS, function (event, treeId, node, msg) { + tools.apply(setting.callback.onAsyncSuccess, [event, treeId, node, msg]); + }); + + o.bind(c.ASYNC_ERROR, function (event, treeId, node, XMLHttpRequest, textStatus, errorThrown) { + tools.apply(setting.callback.onAsyncError, [event, treeId, node, XMLHttpRequest, textStatus, errorThrown]); + }); + + o.bind(c.REMOVE, function (event, treeId, treeNode) { + tools.apply(setting.callback.onRemove, [event, treeId, treeNode]); + }); + + o.bind(c.SELECTED, function (event, treeId, node) { + tools.apply(setting.callback.onSelected, [treeId, node]); + }); + o.bind(c.UNSELECTED, function (event, treeId, node) { + tools.apply(setting.callback.onUnSelected, [treeId, node]); + }); + }, + _unbindEvent = function (setting) { + var o = setting.treeObj, + c = consts.event; + o.unbind(c.NODECREATED) + .unbind(c.CLICK) + .unbind(c.EXPAND) + .unbind(c.COLLAPSE) + .unbind(c.ASYNC_SUCCESS) + .unbind(c.ASYNC_ERROR) + .unbind(c.REMOVE) + .unbind(c.SELECTED) + .unbind(c.UNSELECTED); + }, + //default event proxy of core + _eventProxy = function (event) { + var target = event.target, + setting = data.getSetting(event.data.treeId), + tId = "", node = null, + nodeEventType = "", treeEventType = "", + nodeEventCallback = null, treeEventCallback = null, + tmp = null; + + if (tools.eqs(event.type, "mousedown")) { + treeEventType = "mousedown"; + } else if (tools.eqs(event.type, "mouseup")) { + treeEventType = "mouseup"; + } else if (tools.eqs(event.type, "contextmenu")) { + treeEventType = "contextmenu"; + } else if (tools.eqs(event.type, "click")) { + if (tools.eqs(target.tagName, "span") && target.getAttribute("treeNode" + consts.id.SWITCH) !== null) { + tId = tools.getNodeMainDom(target).id; + nodeEventType = "switchNode"; + } else { + tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]); + if (tmp) { + tId = tools.getNodeMainDom(tmp).id; + nodeEventType = "clickNode"; + } + } + } else if (tools.eqs(event.type, "dblclick")) { + treeEventType = "dblclick"; + tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]); + if (tmp) { + tId = tools.getNodeMainDom(tmp).id; + nodeEventType = "switchNode"; + } + } + if (treeEventType.length > 0 && tId.length == 0) { + tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]); + if (tmp) { + tId = tools.getNodeMainDom(tmp).id; + } + } + // event to node + if (tId.length > 0) { + node = data.getNodeCache(setting, tId); + switch (nodeEventType) { + case "switchNode" : + var isParent = data.nodeIsParent(setting, node); + if (!isParent) { + nodeEventType = ""; + } else if (tools.eqs(event.type, "click") + || (tools.eqs(event.type, "dblclick") && tools.apply(setting.view.dblClickExpand, [setting.treeId, node], setting.view.dblClickExpand))) { + nodeEventCallback = handler.onSwitchNode; + } else { + nodeEventType = ""; + } + break; + case "clickNode" : + nodeEventCallback = handler.onClickNode; + break; + } + } + // event to zTree + switch (treeEventType) { + case "mousedown" : + treeEventCallback = handler.onZTreeMousedown; + break; + case "mouseup" : + treeEventCallback = handler.onZTreeMouseup; + break; + case "dblclick" : + treeEventCallback = handler.onZTreeDblclick; + break; + case "contextmenu" : + treeEventCallback = handler.onZTreeContextmenu; + break; + } + var proxyResult = { + stop: false, + node: node, + nodeEventType: nodeEventType, + nodeEventCallback: nodeEventCallback, + treeEventType: treeEventType, + treeEventCallback: treeEventCallback + }; + return proxyResult + }, + //default init node of core + _initNode = function (setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) { + if (!n) return; + var r = data.getRoot(setting), + children = data.nodeChildren(setting, n); + n.level = level; + n.tId = setting.treeId + "_" + (++r.zId); + n.parentTId = parentNode ? parentNode.tId : null; + n.open = (typeof n.open == "string") ? tools.eqs(n.open, "true") : !!n.open; + var isParent = data.nodeIsParent(setting, n); + if (tools.isArray(children)) { + data.nodeIsParent(setting, n, true); + n.zAsync = true; + } else { + isParent = data.nodeIsParent(setting, n, isParent); + n.open = (isParent && !setting.async.enable) ? n.open : false; + n.zAsync = !isParent; + } + n.isFirstNode = isFirstNode; + n.isLastNode = isLastNode; + n.getParentNode = function () { + return data.getNodeCache(setting, n.parentTId); + }; + n.getPreNode = function () { + return data.getPreNode(setting, n); + }; + n.getNextNode = function () { + return data.getNextNode(setting, n); + }; + n.getIndex = function () { + return data.getNodeIndex(setting, n); + }; + n.getPath = function () { + return data.getNodePath(setting, n); + }; + n.isAjaxing = false; + data.fixPIdKeyValue(setting, n); + }, + _init = { + bind: [_bindEvent], + unbind: [_unbindEvent], + caches: [_initCache], + nodes: [_initNode], + proxys: [_eventProxy], + roots: [_initRoot], + beforeA: [], + afterA: [], + innerBeforeA: [], + innerAfterA: [], + zTreeTools: [] + }, + //method of operate data + data = { + addNodeCache: function (setting, node) { + data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = node; + }, + getNodeCacheId: function (tId) { + return tId.substring(tId.lastIndexOf("_") + 1); + }, + addAfterA: function (afterA) { + _init.afterA.push(afterA); + }, + addBeforeA: function (beforeA) { + _init.beforeA.push(beforeA); + }, + addInnerAfterA: function (innerAfterA) { + _init.innerAfterA.push(innerAfterA); + }, + addInnerBeforeA: function (innerBeforeA) { + _init.innerBeforeA.push(innerBeforeA); + }, + addInitBind: function (bindEvent) { + _init.bind.push(bindEvent); + }, + addInitUnBind: function (unbindEvent) { + _init.unbind.push(unbindEvent); + }, + addInitCache: function (initCache) { + _init.caches.push(initCache); + }, + addInitNode: function (initNode) { + _init.nodes.push(initNode); + }, + addInitProxy: function (initProxy, isFirst) { + if (!!isFirst) { + _init.proxys.splice(0, 0, initProxy); + } else { + _init.proxys.push(initProxy); + } + }, + addInitRoot: function (initRoot) { + _init.roots.push(initRoot); + }, + addNodesData: function (setting, parentNode, index, nodes) { + var children = data.nodeChildren(setting, parentNode), params; + if (!children) { + children = data.nodeChildren(setting, parentNode, []); + index = -1; + } else if (index >= children.length) { + index = -1; + } + + if (children.length > 0 && index === 0) { + children[0].isFirstNode = false; + view.setNodeLineIcos(setting, children[0]); + } else if (children.length > 0 && index < 0) { + children[children.length - 1].isLastNode = false; + view.setNodeLineIcos(setting, children[children.length - 1]); + } + data.nodeIsParent(setting, parentNode, true); + + if (index < 0) { + data.nodeChildren(setting, parentNode, children.concat(nodes)); + } else { + params = [index, 0].concat(nodes); + children.splice.apply(children, params); + } + }, + addSelectedNode: function (setting, node) { + var root = data.getRoot(setting); + if (!data.isSelectedNode(setting, node)) { + root.curSelectedList.push(node); + } + }, + addCreatedNode: function (setting, node) { + if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) { + var root = data.getRoot(setting); + root.createdNodes.push(node); + } + }, + addZTreeTools: function (zTreeTools) { + _init.zTreeTools.push(zTreeTools); + }, + exSetting: function (s) { + $.extend(true, _setting, s); + }, + fixPIdKeyValue: function (setting, node) { + if (setting.data.simpleData.enable) { + node[setting.data.simpleData.pIdKey] = node.parentTId ? node.getParentNode()[setting.data.simpleData.idKey] : setting.data.simpleData.rootPId; + } + }, + getAfterA: function (setting, node, array) { + for (var i = 0, j = _init.afterA.length; i < j; i++) { + _init.afterA[i].apply(this, arguments); + } + }, + getBeforeA: function (setting, node, array) { + for (var i = 0, j = _init.beforeA.length; i < j; i++) { + _init.beforeA[i].apply(this, arguments); + } + }, + getInnerAfterA: function (setting, node, array) { + for (var i = 0, j = _init.innerAfterA.length; i < j; i++) { + _init.innerAfterA[i].apply(this, arguments); + } + }, + getInnerBeforeA: function (setting, node, array) { + for (var i = 0, j = _init.innerBeforeA.length; i < j; i++) { + _init.innerBeforeA[i].apply(this, arguments); + } + }, + getCache: function (setting) { + return caches[setting.treeId]; + }, + getNodeIndex: function (setting, node) { + if (!node) return null; + var p = node.parentTId ? node.getParentNode() : data.getRoot(setting), + children = data.nodeChildren(setting, p); + for (var i = 0, l = children.length - 1; i <= l; i++) { + if (children[i] === node) { + return i; + } + } + return -1; + }, + getNextNode: function (setting, node) { + if (!node) return null; + var p = node.parentTId ? node.getParentNode() : data.getRoot(setting), + children = data.nodeChildren(setting, p); + for (var i = 0, l = children.length - 1; i <= l; i++) { + if (children[i] === node) { + return (i == l ? null : children[i + 1]); + } + } + return null; + }, + getNodeByParam: function (setting, nodes, key, value) { + if (!nodes || !key) return null; + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (node[key] == value) { + return nodes[i]; + } + var children = data.nodeChildren(setting, node); + var tmp = data.getNodeByParam(setting, children, key, value); + if (tmp) return tmp; + } + return null; + }, + getNodeCache: function (setting, tId) { + if (!tId) return null; + var n = caches[setting.treeId].nodes[data.getNodeCacheId(tId)]; + return n ? n : null; + }, + getNodePath: function (setting, node) { + if (!node) return null; + + var path; + if (node.parentTId) { + path = node.getParentNode().getPath(); + } else { + path = []; + } + + if (path) { + path.push(node); + } + + return path; + }, + getNodes: function (setting) { + return data.nodeChildren(setting, data.getRoot(setting)); + }, + getNodesByParam: function (setting, nodes, key, value) { + if (!nodes || !key) return []; + var result = []; + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (node[key] == value) { + result.push(node); + } + var children = data.nodeChildren(setting, node); + result = result.concat(data.getNodesByParam(setting, children, key, value)); + } + return result; + }, + getNodesByParamFuzzy: function (setting, nodes, key, value) { + if (!nodes || !key) return []; + var result = []; + value = value.toLowerCase(); + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (typeof node[key] == "string" && nodes[i][key].toLowerCase().indexOf(value) > -1) { + result.push(node); + } + var children = data.nodeChildren(setting, node); + result = result.concat(data.getNodesByParamFuzzy(setting, children, key, value)); + } + return result; + }, + getNodesByFilter: function (setting, nodes, filter, isSingle, invokeParam) { + if (!nodes) return (isSingle ? null : []); + var result = isSingle ? null : []; + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (tools.apply(filter, [node, invokeParam], false)) { + if (isSingle) { + return node; + } + result.push(node); + } + var children = data.nodeChildren(setting, node); + var tmpResult = data.getNodesByFilter(setting, children, filter, isSingle, invokeParam); + if (isSingle && !!tmpResult) { + return tmpResult; + } + result = isSingle ? tmpResult : result.concat(tmpResult); + } + return result; + }, + getPreNode: function (setting, node) { + if (!node) return null; + var p = node.parentTId ? node.getParentNode() : data.getRoot(setting), + children = data.nodeChildren(setting, p); + for (var i = 0, l = children.length; i < l; i++) { + if (children[i] === node) { + return (i == 0 ? null : children[i - 1]); + } + } + return null; + }, + getRoot: function (setting) { + return setting ? roots[setting.treeId] : null; + }, + getRoots: function () { + return roots; + }, + getSetting: function (treeId) { + return settings[treeId]; + }, + getSettings: function () { + return settings; + }, + getZTreeTools: function (treeId) { + var r = this.getRoot(this.getSetting(treeId)); + return r ? r.treeTools : null; + }, + initCache: function (setting) { + for (var i = 0, j = _init.caches.length; i < j; i++) { + _init.caches[i].apply(this, arguments); + } + }, + initNode: function (setting, level, node, parentNode, preNode, nextNode) { + for (var i = 0, j = _init.nodes.length; i < j; i++) { + _init.nodes[i].apply(this, arguments); + } + }, + initRoot: function (setting) { + for (var i = 0, j = _init.roots.length; i < j; i++) { + _init.roots[i].apply(this, arguments); + } + }, + isSelectedNode: function (setting, node) { + var root = data.getRoot(setting); + for (var i = 0, j = root.curSelectedList.length; i < j; i++) { + if (node === root.curSelectedList[i]) return true; + } + return false; + }, + nodeChildren: function (setting, node, newChildren) { + if (!node) { + return null; + } + var key = setting.data.key.children; + if (typeof newChildren !== 'undefined') { + node[key] = newChildren; + } + return node[key]; + }, + nodeIsParent: function (setting, node, newIsParent) { + if (!node) { + return false; + } + var key = setting.data.key.isParent; + if (typeof newIsParent !== 'undefined') { + if (typeof newIsParent === "string") { + newIsParent = tools.eqs(newIsParent, "true"); + } + newIsParent = !!newIsParent; + node[key] = newIsParent; + } else if (typeof node[key] == "string"){ + node[key] = tools.eqs(node[key], "true"); + } else { + node[key] = !!node[key]; + } + return node[key]; + }, + nodeName: function (setting, node, newName) { + var key = setting.data.key.name; + if (typeof newName !== 'undefined') { + node[key] = newName; + } + var rawName = "" + node[key]; + if(typeof setting.data.render.name === 'function') { + return setting.data.render.name.call(this,rawName,node); + } + return rawName; + }, + nodeTitle: function (setting, node) { + var t = setting.data.key.title === "" ? setting.data.key.name : setting.data.key.title; + var rawTitle = "" + node[t]; + if(typeof setting.data.render.title === 'function') { + return setting.data.render.title.call(this,rawTitle,node); + } + return rawTitle; + }, + removeNodeCache: function (setting, node) { + var children = data.nodeChildren(setting, node); + if (children) { + for (var i = 0, l = children.length; i < l; i++) { + data.removeNodeCache(setting, children[i]); + } + } + data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = null; + }, + removeSelectedNode: function (setting, node) { + var root = data.getRoot(setting); + for (var i = 0, j = root.curSelectedList.length; i < j; i++) { + if (node === root.curSelectedList[i] || !data.getNodeCache(setting, root.curSelectedList[i].tId)) { + root.curSelectedList.splice(i, 1); + setting.treeObj.trigger(consts.event.UNSELECTED, [setting.treeId, node]); + i--; + j--; + } + } + }, + setCache: function (setting, cache) { + caches[setting.treeId] = cache; + }, + setRoot: function (setting, root) { + roots[setting.treeId] = root; + }, + setZTreeTools: function (setting, zTreeTools) { + for (var i = 0, j = _init.zTreeTools.length; i < j; i++) { + _init.zTreeTools[i].apply(this, arguments); + } + }, + transformToArrayFormat: function (setting, nodes) { + if (!nodes) return []; + var r = []; + if (tools.isArray(nodes)) { + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + _do(node); + } + } else { + _do(nodes); + } + return r; + + function _do(_node) { + r.push(_node); + var children = data.nodeChildren(setting, _node); + if (children) { + r = r.concat(data.transformToArrayFormat(setting, children)); + } + } + }, + transformTozTreeFormat: function (setting, sNodes) { + var i, l, + key = setting.data.simpleData.idKey, + parentKey = setting.data.simpleData.pIdKey; + if (!key || key == "" || !sNodes) return []; + + if (tools.isArray(sNodes)) { + var r = []; + var tmpMap = {}; + for (i = 0, l = sNodes.length; i < l; i++) { + tmpMap[sNodes[i][key]] = sNodes[i]; + } + for (i = 0, l = sNodes.length; i < l; i++) { + var p = tmpMap[sNodes[i][parentKey]]; + if (p && sNodes[i][key] != sNodes[i][parentKey]) { + var children = data.nodeChildren(setting, p); + if (!children) { + children = data.nodeChildren(setting, p, []); + } + children.push(sNodes[i]); + } else { + r.push(sNodes[i]); + } + } + return r; + } else { + return [sNodes]; + } + } + }, + //method of event proxy + event = { + bindEvent: function (setting) { + for (var i = 0, j = _init.bind.length; i < j; i++) { + _init.bind[i].apply(this, arguments); + } + }, + unbindEvent: function (setting) { + for (var i = 0, j = _init.unbind.length; i < j; i++) { + _init.unbind[i].apply(this, arguments); + } + }, + bindTree: function (setting) { + var eventParam = { + treeId: setting.treeId + }, + o = setting.treeObj; + if (!setting.view.txtSelectedEnable) { + // for can't select text + o.bind('selectstart', handler.onSelectStart).css({ + "-moz-user-select": "-moz-none" + }); + } + o.bind('click', eventParam, event.proxy); + o.bind('dblclick', eventParam, event.proxy); + o.bind('mouseover', eventParam, event.proxy); + o.bind('mouseout', eventParam, event.proxy); + o.bind('mousedown', eventParam, event.proxy); + o.bind('mouseup', eventParam, event.proxy); + o.bind('contextmenu', eventParam, event.proxy); + }, + unbindTree: function (setting) { + var o = setting.treeObj; + o.unbind('selectstart', handler.onSelectStart) + .unbind('click', event.proxy) + .unbind('dblclick', event.proxy) + .unbind('mouseover', event.proxy) + .unbind('mouseout', event.proxy) + .unbind('mousedown', event.proxy) + .unbind('mouseup', event.proxy) + .unbind('contextmenu', event.proxy); + }, + doProxy: function (e) { + var results = []; + for (var i = 0, j = _init.proxys.length; i < j; i++) { + var proxyResult = _init.proxys[i].apply(this, arguments); + results.push(proxyResult); + if (proxyResult.stop) { + break; + } + } + return results; + }, + proxy: function (e) { + var setting = data.getSetting(e.data.treeId); + if (!tools.uCanDo(setting, e)) return true; + var results = event.doProxy(e), + r = true, x = false; + for (var i = 0, l = results.length; i < l; i++) { + var proxyResult = results[i]; + if (proxyResult.nodeEventCallback) { + x = true; + r = proxyResult.nodeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r; + } + if (proxyResult.treeEventCallback) { + x = true; + r = proxyResult.treeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r; + } + } + return r; + } + }, + //method of event handler + handler = { + onSwitchNode: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (node.open) { + if (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false) return true; + data.getRoot(setting).expandTriggerFlag = true; + view.switchNode(setting, node); + } else { + if (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false) return true; + data.getRoot(setting).expandTriggerFlag = true; + view.switchNode(setting, node); + } + return true; + }, + onClickNode: function (event, node) { + var setting = data.getSetting(event.data.treeId), + clickFlag = ((setting.view.autoCancelSelected && (event.ctrlKey || event.metaKey)) && data.isSelectedNode(setting, node)) ? 0 : (setting.view.autoCancelSelected && (event.ctrlKey || event.metaKey) && setting.view.selectedMulti) ? 2 : 1; + if (tools.apply(setting.callback.beforeClick, [setting.treeId, node, clickFlag], true) == false) return true; + if (clickFlag === 0) { + view.cancelPreSelectedNode(setting, node); + } else { + view.selectNode(setting, node, clickFlag === 2); + } + setting.treeObj.trigger(consts.event.CLICK, [event, setting.treeId, node, clickFlag]); + return true; + }, + onZTreeMousedown: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (tools.apply(setting.callback.beforeMouseDown, [setting.treeId, node], true)) { + tools.apply(setting.callback.onMouseDown, [event, setting.treeId, node]); + } + return true; + }, + onZTreeMouseup: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (tools.apply(setting.callback.beforeMouseUp, [setting.treeId, node], true)) { + tools.apply(setting.callback.onMouseUp, [event, setting.treeId, node]); + } + return true; + }, + onZTreeDblclick: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (tools.apply(setting.callback.beforeDblClick, [setting.treeId, node], true)) { + tools.apply(setting.callback.onDblClick, [event, setting.treeId, node]); + } + return true; + }, + onZTreeContextmenu: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (tools.apply(setting.callback.beforeRightClick, [setting.treeId, node], true)) { + tools.apply(setting.callback.onRightClick, [event, setting.treeId, node]); + } + return (typeof setting.callback.onRightClick) != "function"; + }, + onSelectStart: function (e) { + var n = e.originalEvent.srcElement.nodeName.toLowerCase(); + return (n === "input" || n === "textarea"); + } + }, + //method of tools for zTree + tools = { + apply: function (fun, param, defaultValue) { + if ((typeof fun) == "function") { + return fun.apply(zt, param ? param : []); + } + return defaultValue; + }, + canAsync: function (setting, node) { + var children = data.nodeChildren(setting, node); + var isParent = data.nodeIsParent(setting, node); + return (setting.async.enable && node && isParent && !(node.zAsync || (children && children.length > 0))); + }, + clone: function (obj) { + if (obj === null) return null; + var o = tools.isArray(obj) ? [] : {}; + for (var i in obj) { + o[i] = (obj[i] instanceof Date) ? new Date(obj[i].getTime()) : (typeof obj[i] === "object" ? tools.clone(obj[i]) : obj[i]); + } + return o; + }, + eqs: function (str1, str2) { + return str1.toLowerCase() === str2.toLowerCase(); + }, + isArray: function (arr) { + return Object.prototype.toString.apply(arr) === "[object Array]"; + }, + isElement: function (o) { + return ( + typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2 + o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName === "string" + ); + }, + $: function (node, exp, setting) { + if (!!exp && typeof exp != "string") { + setting = exp; + exp = ""; + } + if (typeof node == "string") { + return $(node, setting ? setting.treeObj.get(0).ownerDocument : null); + } else { + return $("#" + node.tId + exp, setting ? setting.treeObj : null); + } + }, + getMDom: function (setting, curDom, targetExpr) { + if (!curDom) return null; + while (curDom && curDom.id !== setting.treeId) { + for (var i = 0, l = targetExpr.length; curDom.tagName && i < l; i++) { + if (tools.eqs(curDom.tagName, targetExpr[i].tagName) && curDom.getAttribute(targetExpr[i].attrName) !== null) { + return curDom; + } + } + curDom = curDom.parentNode; + } + return null; + }, + getNodeMainDom: function (target) { + return ($(target).parent("li").get(0) || $(target).parentsUntil("li").parent().get(0)); + }, + isChildOrSelf: function (dom, parentId) { + return ($(dom).closest("#" + parentId).length > 0); + }, + uCanDo: function (setting, e) { + return true; + } + }, + //method of operate ztree dom + view = { + addNodes: function (setting, parentNode, index, newNodes, isSilent) { + var isParent = data.nodeIsParent(setting, parentNode); + if (setting.data.keep.leaf && parentNode && !isParent) { + return; + } + if (!tools.isArray(newNodes)) { + newNodes = [newNodes]; + } + if (setting.data.simpleData.enable) { + newNodes = data.transformTozTreeFormat(setting, newNodes); + } + if (parentNode) { + var target_switchObj = $$(parentNode, consts.id.SWITCH, setting), + target_icoObj = $$(parentNode, consts.id.ICON, setting), + target_ulObj = $$(parentNode, consts.id.UL, setting); + + if (!parentNode.open) { + view.replaceSwitchClass(parentNode, target_switchObj, consts.folder.CLOSE); + view.replaceIcoClass(parentNode, target_icoObj, consts.folder.CLOSE); + parentNode.open = false; + target_ulObj.css({ + "display": "none" + }); + } + + data.addNodesData(setting, parentNode, index, newNodes); + view.createNodes(setting, parentNode.level + 1, newNodes, parentNode, index); + if (!isSilent) { + view.expandCollapseParentNode(setting, parentNode, true); + } + } else { + data.addNodesData(setting, data.getRoot(setting), index, newNodes); + view.createNodes(setting, 0, newNodes, null, index); + } + }, + appendNodes: function (setting, level, nodes, parentNode, index, initFlag, openFlag) { + if (!nodes) return []; + var html = []; + + var tmpPNode = (parentNode) ? parentNode : data.getRoot(setting), + tmpPChild = data.nodeChildren(setting, tmpPNode), + isFirstNode, isLastNode; + + if (!tmpPChild || index >= tmpPChild.length - nodes.length) { + index = -1; + } + + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (initFlag) { + isFirstNode = ((index === 0 || tmpPChild.length == nodes.length) && (i == 0)); + isLastNode = (index < 0 && i == (nodes.length - 1)); + data.initNode(setting, level, node, parentNode, isFirstNode, isLastNode, openFlag); + data.addNodeCache(setting, node); + } + var isParent = data.nodeIsParent(setting, node); + + var childHtml = []; + var children = data.nodeChildren(setting, node); + if (children && children.length > 0) { + //make child html first, because checkType + childHtml = view.appendNodes(setting, level + 1, children, node, -1, initFlag, openFlag && node.open); + } + if (openFlag) { + view.makeDOMNodeMainBefore(html, setting, node); + view.makeDOMNodeLine(html, setting, node); + data.getBeforeA(setting, node, html); + view.makeDOMNodeNameBefore(html, setting, node); + data.getInnerBeforeA(setting, node, html); + view.makeDOMNodeIcon(html, setting, node); + data.getInnerAfterA(setting, node, html); + view.makeDOMNodeNameAfter(html, setting, node); + data.getAfterA(setting, node, html); + if (isParent && node.open) { + view.makeUlHtml(setting, node, html, childHtml.join('')); + } + view.makeDOMNodeMainAfter(html, setting, node); + data.addCreatedNode(setting, node); + } + } + return html; + }, + appendParentULDom: function (setting, node) { + var html = [], + nObj = $$(node, setting); + if (!nObj.get(0) && !!node.parentTId) { + view.appendParentULDom(setting, node.getParentNode()); + nObj = $$(node, setting); + } + var ulObj = $$(node, consts.id.UL, setting); + if (ulObj.get(0)) { + ulObj.remove(); + } + var children = data.nodeChildren(setting, node), + childHtml = view.appendNodes(setting, node.level + 1, children, node, -1, false, true); + view.makeUlHtml(setting, node, html, childHtml.join('')); + nObj.append(html.join('')); + }, + asyncNode: function (setting, node, isSilent, callback) { + var i, l; + var isParent = data.nodeIsParent(setting, node); + if (node && !isParent) { + tools.apply(callback); + return false; + } else if (node && node.isAjaxing) { + return false; + } else if (tools.apply(setting.callback.beforeAsync, [setting.treeId, node], true) == false) { + tools.apply(callback); + return false; + } + if (node) { + node.isAjaxing = true; + var icoObj = $$(node, consts.id.ICON, setting); + icoObj.attr({"style": "", "class": consts.className.BUTTON + " " + consts.className.ICO_LOADING}); + } + + var tmpParam = {}; + var autoParam = tools.apply(setting.async.autoParam, [setting.treeId, node], setting.async.autoParam); + for (i = 0, l = autoParam.length; node && i < l; i++) { + var pKey = autoParam[i].split("="), spKey = pKey; + if (pKey.length > 1) { + spKey = pKey[1]; + pKey = pKey[0]; + } + tmpParam[spKey] = node[pKey]; + } + var otherParam = tools.apply(setting.async.otherParam, [setting.treeId, node], setting.async.otherParam); + if (tools.isArray(otherParam)) { + for (i = 0, l = otherParam.length; i < l; i += 2) { + tmpParam[otherParam[i]] = otherParam[i + 1]; + } + } else { + for (var p in otherParam) { + tmpParam[p] = otherParam[p]; + } + } + + var _tmpV = data.getRoot(setting)._ver; + $.ajax({ + contentType: setting.async.contentType, + cache: false, + type: setting.async.type, + url: tools.apply(setting.async.url, [setting.treeId, node], setting.async.url), + data: setting.async.contentType.indexOf('application/json') > -1 ? JSON.stringify(tmpParam) : tmpParam, + dataType: setting.async.dataType, + headers: setting.async.headers, + xhrFields: setting.async.xhrFields, + success: function (msg) { + if (_tmpV != data.getRoot(setting)._ver) { + return; + } + var newNodes = []; + try { + if (!msg || msg.length == 0) { + newNodes = []; + } else if (typeof msg == "string") { + newNodes = eval("(" + msg + ")"); + } else { + newNodes = msg; + } + } catch (err) { + newNodes = msg; + } + + if (node) { + node.isAjaxing = null; + node.zAsync = true; + } + view.setNodeLineIcos(setting, node); + if (newNodes && newNodes !== "") { + newNodes = tools.apply(setting.async.dataFilter, [setting.treeId, node, newNodes], newNodes); + view.addNodes(setting, node, -1, !!newNodes ? tools.clone(newNodes) : [], !!isSilent); + } else { + view.addNodes(setting, node, -1, [], !!isSilent); + } + setting.treeObj.trigger(consts.event.ASYNC_SUCCESS, [setting.treeId, node, msg]); + tools.apply(callback); + }, + error: function (XMLHttpRequest, textStatus, errorThrown) { + if (_tmpV != data.getRoot(setting)._ver) { + return; + } + if (node) node.isAjaxing = null; + view.setNodeLineIcos(setting, node); + setting.treeObj.trigger(consts.event.ASYNC_ERROR, [setting.treeId, node, XMLHttpRequest, textStatus, errorThrown]); + } + }); + return true; + }, + cancelPreSelectedNode: function (setting, node, excludeNode) { + var list = data.getRoot(setting).curSelectedList, + i, n; + for (i = list.length - 1; i >= 0; i--) { + n = list[i]; + if (node === n || (!node && (!excludeNode || excludeNode !== n))) { + $$(n, consts.id.A, setting).removeClass(consts.node.CURSELECTED); + if (node) { + data.removeSelectedNode(setting, node); + break; + } else { + list.splice(i, 1); + setting.treeObj.trigger(consts.event.UNSELECTED, [setting.treeId, n]); + } + } + } + }, + createNodeCallback: function (setting) { + if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) { + var root = data.getRoot(setting); + while (root.createdNodes.length > 0) { + var node = root.createdNodes.shift(); + tools.apply(setting.view.addDiyDom, [setting.treeId, node]); + if (!!setting.callback.onNodeCreated) { + setting.treeObj.trigger(consts.event.NODECREATED, [setting.treeId, node]); + } + } + } + }, + createNodes: function (setting, level, nodes, parentNode, index) { + if (!nodes || nodes.length == 0) return; + var root = data.getRoot(setting), + openFlag = !parentNode || parentNode.open || !!$$(data.nodeChildren(setting, parentNode)[0], setting).get(0); + root.createdNodes = []; + var zTreeHtml = view.appendNodes(setting, level, nodes, parentNode, index, true, openFlag), + parentObj, nextObj; + + if (!parentNode) { + parentObj = setting.treeObj; + //setting.treeObj.append(zTreeHtml.join('')); + } else { + var ulObj = $$(parentNode, consts.id.UL, setting); + if (ulObj.get(0)) { + parentObj = ulObj; + //ulObj.append(zTreeHtml.join('')); + } + } + if (parentObj) { + if (index >= 0) { + nextObj = parentObj.children()[index]; + } + if (index >= 0 && nextObj) { + $(nextObj).before(zTreeHtml.join('')); + } else { + parentObj.append(zTreeHtml.join('')); + } + } + + view.createNodeCallback(setting); + }, + destroy: function (setting) { + if (!setting) return; + data.initCache(setting); + data.initRoot(setting); + event.unbindTree(setting); + event.unbindEvent(setting); + setting.treeObj.empty(); + delete settings[setting.treeId]; + }, + expandCollapseNode: function (setting, node, expandFlag, animateFlag, callback) { + var root = data.getRoot(setting); + var tmpCb, _callback; + if (!node) { + tools.apply(callback, []); + return; + } + var children = data.nodeChildren(setting, node); + var isParent = data.nodeIsParent(setting, node); + if (root.expandTriggerFlag) { + _callback = callback; + tmpCb = function () { + if (_callback) _callback(); + if (node.open) { + setting.treeObj.trigger(consts.event.EXPAND, [setting.treeId, node]); + } else { + setting.treeObj.trigger(consts.event.COLLAPSE, [setting.treeId, node]); + } + }; + callback = tmpCb; + root.expandTriggerFlag = false; + } + if (!node.open && isParent && ((!$$(node, consts.id.UL, setting).get(0)) || (children && children.length > 0 && !$$(children[0], setting).get(0)))) { + view.appendParentULDom(setting, node); + view.createNodeCallback(setting); + } + if (node.open == expandFlag) { + tools.apply(callback, []); + return; + } + var ulObj = $$(node, consts.id.UL, setting), + switchObj = $$(node, consts.id.SWITCH, setting), + icoObj = $$(node, consts.id.ICON, setting); + + if (isParent) { + node.open = !node.open; + if (node.iconOpen && node.iconClose) { + icoObj.attr("style", view.makeNodeIcoStyle(setting, node)); + } + + if (node.open) { + view.replaceSwitchClass(node, switchObj, consts.folder.OPEN); + view.replaceIcoClass(node, icoObj, consts.folder.OPEN); + if (animateFlag == false || setting.view.expandSpeed == "") { + ulObj.show(); + tools.apply(callback, []); + } else { + if (children && children.length > 0) { + ulObj.slideDown(setting.view.expandSpeed, callback); + } else { + ulObj.show(); + tools.apply(callback, []); + } + } + } else { + view.replaceSwitchClass(node, switchObj, consts.folder.CLOSE); + view.replaceIcoClass(node, icoObj, consts.folder.CLOSE); + if (animateFlag == false || setting.view.expandSpeed == "" || !(children && children.length > 0)) { + ulObj.hide(); + tools.apply(callback, []); + } else { + ulObj.slideUp(setting.view.expandSpeed, callback); + } + } + } else { + tools.apply(callback, []); + } + }, + expandCollapseParentNode: function (setting, node, expandFlag, animateFlag, callback) { + if (!node) return; + if (!node.parentTId) { + view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback); + return; + } else { + view.expandCollapseNode(setting, node, expandFlag, animateFlag); + } + if (node.parentTId) { + view.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, animateFlag, callback); + } + }, + expandCollapseSonNode: function (setting, node, expandFlag, animateFlag, callback) { + var root = data.getRoot(setting), + treeNodes = (node) ? data.nodeChildren(setting, node) : data.nodeChildren(setting, root), + selfAnimateSign = (node) ? false : animateFlag, + expandTriggerFlag = data.getRoot(setting).expandTriggerFlag; + data.getRoot(setting).expandTriggerFlag = false; + if (treeNodes) { + for (var i = 0, l = treeNodes.length; i < l; i++) { + if (treeNodes[i]) view.expandCollapseSonNode(setting, treeNodes[i], expandFlag, selfAnimateSign); + } + } + data.getRoot(setting).expandTriggerFlag = expandTriggerFlag; + view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback); + }, + isSelectedNode: function (setting, node) { + if (!node) { + return false; + } + var list = data.getRoot(setting).curSelectedList, + i; + for (i = list.length - 1; i >= 0; i--) { + if (node === list[i]) { + return true; + } + } + return false; + }, + makeDOMNodeIcon: function (html, setting, node) { + var nameStr = data.nodeName(setting, node), + name = setting.view.nameIsHTML ? nameStr : nameStr.replace(/&/g, '&').replace(//g, '>'); + html.push("", name, ""); + }, + makeDOMNodeLine: function (html, setting, node) { + html.push(""); + }, + makeDOMNodeMainAfter: function (html, setting, node) { + html.push(""); + }, + makeDOMNodeMainBefore: function (html, setting, node) { + html.push("
  • "); + }, + makeDOMNodeNameAfter: function (html, setting, node) { + html.push(""); + }, + makeDOMNodeNameBefore: function (html, setting, node) { + var title = data.nodeTitle(setting, node), + url = view.makeNodeUrl(setting, node), + fontcss = view.makeNodeFontCss(setting, node), + nodeClasses = view.makeNodeClasses(setting, node), + fontStyle = []; + for (var f in fontcss) { + fontStyle.push(f, ":", fontcss[f], ";"); + } + html.push(" 0) ? " href='" + url + "'" : ""), " target='", view.makeNodeTarget(node), "' style='", fontStyle.join(''), + "'"); + if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle) && title) { + html.push("title='", title.replace(/'/g, "'").replace(//g, '>'), "'"); + } + html.push(">"); + }, + makeNodeFontCss: function (setting, node) { + var fontCss = tools.apply(setting.view.fontCss, [setting.treeId, node], setting.view.fontCss); + return (fontCss && ((typeof fontCss) != "function")) ? fontCss : {}; + }, + makeNodeClasses: function (setting, node) { + var classes = tools.apply(setting.view.nodeClasses, [setting.treeId, node], setting.view.nodeClasses); + return (classes && (typeof classes !== "function")) ? classes : {add:[], remove:[]}; + }, + makeNodeIcoClass: function (setting, node) { + var icoCss = ["ico"]; + if (!node.isAjaxing) { + var isParent = data.nodeIsParent(setting, node); + icoCss[0] = (node.iconSkin ? node.iconSkin + "_" : "") + icoCss[0]; + if (isParent) { + icoCss.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE); + } else { + icoCss.push(consts.folder.DOCU); + } + } + return consts.className.BUTTON + " " + icoCss.join('_'); + }, + makeNodeIcoStyle: function (setting, node) { + var icoStyle = []; + if (!node.isAjaxing) { + var isParent = data.nodeIsParent(setting, node); + var icon = (isParent && node.iconOpen && node.iconClose) ? (node.open ? node.iconOpen : node.iconClose) : node[setting.data.key.icon]; + if (icon) icoStyle.push("background:url(", icon, ") 0 0 no-repeat;"); + if (setting.view.showIcon == false || !tools.apply(setting.view.showIcon, [setting.treeId, node], true)) { + icoStyle.push("display:none;"); + } + } + return icoStyle.join(''); + }, + makeNodeLineClass: function (setting, node) { + var lineClass = []; + if (setting.view.showLine) { + if (node.level == 0 && node.isFirstNode && node.isLastNode) { + lineClass.push(consts.line.ROOT); + } else if (node.level == 0 && node.isFirstNode) { + lineClass.push(consts.line.ROOTS); + } else if (node.isLastNode) { + lineClass.push(consts.line.BOTTOM); + } else { + lineClass.push(consts.line.CENTER); + } + } else { + lineClass.push(consts.line.NOLINE); + } + if (data.nodeIsParent(setting, node)) { + lineClass.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE); + } else { + lineClass.push(consts.folder.DOCU); + } + return view.makeNodeLineClassEx(node) + lineClass.join('_'); + }, + makeNodeLineClassEx: function (node) { + return consts.className.BUTTON + " " + consts.className.LEVEL + node.level + " " + consts.className.SWITCH + " "; + }, + makeNodeTarget: function (node) { + return (node.target || "_blank"); + }, + makeNodeUrl: function (setting, node) { + var urlKey = setting.data.key.url; + return node[urlKey] ? node[urlKey] : null; + }, + makeUlHtml: function (setting, node, html, content) { + html.push("
      "); + html.push(content); + html.push("
    "); + }, + makeUlLineClass: function (setting, node) { + return ((setting.view.showLine && !node.isLastNode) ? consts.line.LINE : ""); + }, + removeChildNodes: function (setting, node) { + if (!node) return; + var nodes = data.nodeChildren(setting, node); + if (!nodes) return; + + for (var i = 0, l = nodes.length; i < l; i++) { + data.removeNodeCache(setting, nodes[i]); + } + data.removeSelectedNode(setting); + delete node[setting.data.key.children]; + + if (!setting.data.keep.parent) { + data.nodeIsParent(setting, node, false); + node.open = false; + var tmp_switchObj = $$(node, consts.id.SWITCH, setting), + tmp_icoObj = $$(node, consts.id.ICON, setting); + view.replaceSwitchClass(node, tmp_switchObj, consts.folder.DOCU); + view.replaceIcoClass(node, tmp_icoObj, consts.folder.DOCU); + $$(node, consts.id.UL, setting).remove(); + } else { + $$(node, consts.id.UL, setting).empty(); + } + }, + scrollIntoView: function (setting, dom) { + if (!dom) { + return; + } + // support IE 7 / 8 + if (typeof Element === 'undefined' || typeof HTMLElement === 'undefined') { + var contRect = setting.treeObj.get(0).getBoundingClientRect(), + findMeRect = dom.getBoundingClientRect(); + if (findMeRect.top < contRect.top || findMeRect.bottom > contRect.bottom + || findMeRect.right > contRect.right || findMeRect.left < contRect.left) { + dom.scrollIntoView(); + } + return; + } + // CC-BY jocki84@googlemail.com, https://gist.github.com/jocki84/6ffafd003387179a988e + if (!Element.prototype.scrollIntoViewIfNeeded) { + Element.prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) { + "use strict"; + + function makeRange(start, length) { + return {"start": start, "length": length, "end": start + length}; + } + + function coverRange(inner, outer) { + if ( + false === centerIfNeeded || + (outer.start < inner.end && inner.start < outer.end) + ) { + return Math.max( + inner.end - outer.length, + Math.min(outer.start, inner.start) + ); + } + return (inner.start + inner.end - outer.length) / 2; + } + + function makePoint(x, y) { + return { + "x": x, + "y": y, + "translate": function translate(dX, dY) { + return makePoint(x + dX, y + dY); + } + }; + } + + function absolute(elem, pt) { + while (elem) { + pt = pt.translate(elem.offsetLeft, elem.offsetTop); + elem = elem.offsetParent; + } + return pt; + } + + var target = absolute(this, makePoint(0, 0)), + extent = makePoint(this.offsetWidth, this.offsetHeight), + elem = this.parentNode, + origin; + + while (elem instanceof HTMLElement) { + // Apply desired scroll amount. + origin = absolute(elem, makePoint(elem.clientLeft, elem.clientTop)); + elem.scrollLeft = coverRange( + makeRange(target.x - origin.x, extent.x), + makeRange(elem.scrollLeft, elem.clientWidth) + ); + elem.scrollTop = coverRange( + makeRange(target.y - origin.y, extent.y), + makeRange(elem.scrollTop, elem.clientHeight) + ); + + // Determine actual scroll amount by reading back scroll properties. + target = target.translate(-elem.scrollLeft, -elem.scrollTop); + elem = elem.parentNode; + } + }; + } + dom.scrollIntoViewIfNeeded(); + }, + setFirstNode: function (setting, parentNode) { + var children = data.nodeChildren(setting, parentNode); + if (children.length > 0) { + children[0].isFirstNode = true; + } + }, + setLastNode: function (setting, parentNode) { + var children = data.nodeChildren(setting, parentNode); + if (children.length > 0) { + children[children.length - 1].isLastNode = true; + } + }, + removeNode: function (setting, node) { + var root = data.getRoot(setting), + parentNode = (node.parentTId) ? node.getParentNode() : root; + + node.isFirstNode = false; + node.isLastNode = false; + node.getPreNode = function () { + return null; + }; + node.getNextNode = function () { + return null; + }; + + if (!data.getNodeCache(setting, node.tId)) { + return; + } + + $$(node, setting).remove(); + data.removeNodeCache(setting, node); + data.removeSelectedNode(setting, node); + + var children = data.nodeChildren(setting, parentNode); + for (var i = 0, l = children.length; i < l; i++) { + if (children[i].tId == node.tId) { + children.splice(i, 1); + break; + } + } + view.setFirstNode(setting, parentNode); + view.setLastNode(setting, parentNode); + + var tmp_ulObj, tmp_switchObj, tmp_icoObj, + childLength = children.length; + + //repair nodes old parent + if (!setting.data.keep.parent && childLength == 0) { + //old parentNode has no child nodes + data.nodeIsParent(setting, parentNode, false); + parentNode.open = false; + delete parentNode[setting.data.key.children]; + tmp_ulObj = $$(parentNode, consts.id.UL, setting); + tmp_switchObj = $$(parentNode, consts.id.SWITCH, setting); + tmp_icoObj = $$(parentNode, consts.id.ICON, setting); + view.replaceSwitchClass(parentNode, tmp_switchObj, consts.folder.DOCU); + view.replaceIcoClass(parentNode, tmp_icoObj, consts.folder.DOCU); + tmp_ulObj.css("display", "none"); + + } else if (setting.view.showLine && childLength > 0) { + //old parentNode has child nodes + var newLast = children[childLength - 1]; + tmp_ulObj = $$(newLast, consts.id.UL, setting); + tmp_switchObj = $$(newLast, consts.id.SWITCH, setting); + tmp_icoObj = $$(newLast, consts.id.ICON, setting); + if (parentNode == root) { + if (children.length == 1) { + //node was root, and ztree has only one root after move node + view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.ROOT); + } else { + var tmp_first_switchObj = $$(children[0], consts.id.SWITCH, setting); + view.replaceSwitchClass(children[0], tmp_first_switchObj, consts.line.ROOTS); + view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM); + } + } else { + view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM); + } + tmp_ulObj.removeClass(consts.line.LINE); + } + }, + replaceIcoClass: function (node, obj, newName) { + if (!obj || node.isAjaxing) return; + var tmpName = obj.attr("class"); + if (tmpName == undefined) return; + var tmpList = tmpName.split("_"); + switch (newName) { + case consts.folder.OPEN: + case consts.folder.CLOSE: + case consts.folder.DOCU: + tmpList[tmpList.length - 1] = newName; + break; + } + obj.attr("class", tmpList.join("_")); + }, + replaceSwitchClass: function (node, obj, newName) { + if (!obj) return; + var tmpName = obj.attr("class"); + if (tmpName == undefined) return; + var tmpList = tmpName.split("_"); + switch (newName) { + case consts.line.ROOT: + case consts.line.ROOTS: + case consts.line.CENTER: + case consts.line.BOTTOM: + case consts.line.NOLINE: + tmpList[0] = view.makeNodeLineClassEx(node) + newName; + break; + case consts.folder.OPEN: + case consts.folder.CLOSE: + case consts.folder.DOCU: + tmpList[1] = newName; + break; + } + obj.attr("class", tmpList.join("_")); + if (newName !== consts.folder.DOCU) { + obj.removeAttr("disabled"); + } else { + obj.attr("disabled", "disabled"); + } + }, + selectNode: function (setting, node, addFlag) { + if (!addFlag) { + view.cancelPreSelectedNode(setting, null, node); + } + $$(node, consts.id.A, setting).addClass(consts.node.CURSELECTED); + data.addSelectedNode(setting, node); + setting.treeObj.trigger(consts.event.SELECTED, [setting.treeId, node]); + }, + setNodeFontCss: function (setting, treeNode) { + var aObj = $$(treeNode, consts.id.A, setting), + fontCss = view.makeNodeFontCss(setting, treeNode); + if (fontCss) { + aObj.css(fontCss); + } + }, + setNodeClasses: function (setting, treeNode) { + var aObj = $$(treeNode, consts.id.A, setting), + classes = view.makeNodeClasses(setting, treeNode); + if ('add' in classes && classes.add.length) { + aObj.addClass(classes.add.join(' ')); + } + if ('remove' in classes && classes.remove.length) { + aObj.removeClass(classes.remove.join(' ')); + } + }, + setNodeLineIcos: function (setting, node) { + if (!node) return; + var switchObj = $$(node, consts.id.SWITCH, setting), + ulObj = $$(node, consts.id.UL, setting), + icoObj = $$(node, consts.id.ICON, setting), + ulLine = view.makeUlLineClass(setting, node); + if (ulLine.length == 0) { + ulObj.removeClass(consts.line.LINE); + } else { + ulObj.addClass(ulLine); + } + switchObj.attr("class", view.makeNodeLineClass(setting, node)); + if (data.nodeIsParent(setting, node)) { + switchObj.removeAttr("disabled"); + } else { + switchObj.attr("disabled", "disabled"); + } + icoObj.removeAttr("style"); + icoObj.attr("style", view.makeNodeIcoStyle(setting, node)); + icoObj.attr("class", view.makeNodeIcoClass(setting, node)); + }, + setNodeName: function (setting, node) { + var title = data.nodeTitle(setting, node), + nObj = $$(node, consts.id.SPAN, setting); + nObj.empty(); + if (setting.view.nameIsHTML) { + nObj.html(data.nodeName(setting, node)); + } else { + nObj.text(data.nodeName(setting, node)); + } + if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle)) { + var aObj = $$(node, consts.id.A, setting); + aObj.attr("title", !title ? "" : title); + } + }, + setNodeTarget: function (setting, node) { + var aObj = $$(node, consts.id.A, setting); + aObj.attr("target", view.makeNodeTarget(node)); + }, + setNodeUrl: function (setting, node) { + var aObj = $$(node, consts.id.A, setting), + url = view.makeNodeUrl(setting, node); + if (url == null || url.length == 0) { + aObj.removeAttr("href"); + } else { + aObj.attr("href", url); + } + }, + switchNode: function (setting, node) { + if (node.open || !tools.canAsync(setting, node)) { + view.expandCollapseNode(setting, node, !node.open); + } else if (setting.async.enable) { + if (!view.asyncNode(setting, node)) { + view.expandCollapseNode(setting, node, !node.open); + return; + } + } else if (node) { + view.expandCollapseNode(setting, node, !node.open); + } + } + }; + // zTree defind + $.fn.zTree = { + consts: _consts, + _z: { + tools: tools, + view: view, + event: event, + data: data + }, + getZTreeObj: function (treeId) { + var o = data.getZTreeTools(treeId); + return o ? o : null; + }, + destroy: function (treeId) { + if (!!treeId && treeId.length > 0) { + view.destroy(data.getSetting(treeId)); + } else { + for (var s in settings) { + view.destroy(settings[s]); + } + } + }, + init: function (obj, zSetting, zNodes) { + var setting = tools.clone(_setting); + $.extend(true, setting, zSetting); + setting.treeId = obj.attr("id"); + setting.treeObj = obj; + setting.treeObj.empty(); + settings[setting.treeId] = setting; + //For some older browser,(e.g., ie6) + if (typeof document.body.style.maxHeight === "undefined") { + setting.view.expandSpeed = ""; + } + data.initRoot(setting); + var root = data.getRoot(setting); + zNodes = zNodes ? tools.clone(tools.isArray(zNodes) ? zNodes : [zNodes]) : []; + if (setting.data.simpleData.enable) { + data.nodeChildren(setting, root, data.transformTozTreeFormat(setting, zNodes)); + } else { + data.nodeChildren(setting, root, zNodes); + } + + data.initCache(setting); + event.unbindTree(setting); + event.bindTree(setting); + event.unbindEvent(setting); + event.bindEvent(setting); + + var zTreeTools = { + setting: setting, + addNodes: function (parentNode, index, newNodes, isSilent) { + if (!parentNode) parentNode = null; + var isParent = data.nodeIsParent(setting, parentNode); + if (parentNode && !isParent && setting.data.keep.leaf) return null; + + var i = parseInt(index, 10); + if (isNaN(i)) { + isSilent = !!newNodes; + newNodes = index; + index = -1; + } else { + index = i; + } + if (!newNodes) return null; + + + var xNewNodes = tools.clone(tools.isArray(newNodes) ? newNodes : [newNodes]); + + function addCallback() { + view.addNodes(setting, parentNode, index, xNewNodes, (isSilent == true)); + } + + if (tools.canAsync(setting, parentNode)) { + view.asyncNode(setting, parentNode, isSilent, addCallback); + } else { + addCallback(); + } + return xNewNodes; + }, + cancelSelectedNode: function (node) { + view.cancelPreSelectedNode(setting, node); + }, + destroy: function () { + view.destroy(setting); + }, + expandAll: function (expandFlag) { + expandFlag = !!expandFlag; + view.expandCollapseSonNode(setting, null, expandFlag, true); + return expandFlag; + }, + expandNode: function (node, expandFlag, sonSign, focus, callbackFlag) { + if (!node || !data.nodeIsParent(setting, node)) return null; + if (expandFlag !== true && expandFlag !== false) { + expandFlag = !node.open; + } + callbackFlag = !!callbackFlag; + + if (callbackFlag && expandFlag && (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false)) { + return null; + } else if (callbackFlag && !expandFlag && (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false)) { + return null; + } + if (expandFlag && node.parentTId) { + view.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, false); + } + if (expandFlag === node.open && !sonSign) { + return null; + } + + data.getRoot(setting).expandTriggerFlag = callbackFlag; + if (!tools.canAsync(setting, node) && sonSign) { + view.expandCollapseSonNode(setting, node, expandFlag, true, showNodeFocus); + } else { + node.open = !expandFlag; + view.switchNode(this.setting, node); + showNodeFocus(); + } + return expandFlag; + + function showNodeFocus() { + var a = $$(node, consts.id.A, setting).get(0); + if (a && focus !== false) { + view.scrollIntoView(setting, a); + } + } + }, + getNodes: function () { + return data.getNodes(setting); + }, + getNodeByParam: function (key, value, parentNode) { + if (!key) return null; + return data.getNodeByParam(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), key, value); + }, + getNodeByTId: function (tId) { + return data.getNodeCache(setting, tId); + }, + getNodesByParam: function (key, value, parentNode) { + if (!key) return null; + return data.getNodesByParam(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), key, value); + }, + getNodesByParamFuzzy: function (key, value, parentNode) { + if (!key) return null; + return data.getNodesByParamFuzzy(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), key, value); + }, + getNodesByFilter: function (filter, isSingle, parentNode, invokeParam) { + isSingle = !!isSingle; + if (!filter || (typeof filter != "function")) return (isSingle ? null : []); + return data.getNodesByFilter(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), filter, isSingle, invokeParam); + }, + getNodeIndex: function (node) { + if (!node) return null; + var parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting); + var children = data.nodeChildren(setting, parentNode); + for (var i = 0, l = children.length; i < l; i++) { + if (children[i] == node) return i; + } + return -1; + }, + getSelectedNodes: function () { + var r = [], list = data.getRoot(setting).curSelectedList; + for (var i = 0, l = list.length; i < l; i++) { + r.push(list[i]); + } + return r; + }, + isSelectedNode: function (node) { + return data.isSelectedNode(setting, node); + }, + reAsyncChildNodesPromise: function (parentNode, reloadType, isSilent) { + var promise = new Promise(function (resolve, reject) { + try { + zTreeTools.reAsyncChildNodes(parentNode, reloadType, isSilent, function () { + resolve(parentNode); + }); + } catch (e) { + reject(e); + } + }); + return promise; + }, + reAsyncChildNodes: function (parentNode, reloadType, isSilent, callback) { + if (!this.setting.async.enable) return; + var isRoot = !parentNode; + if (isRoot) { + parentNode = data.getRoot(setting); + } + if (reloadType == "refresh") { + var children = data.nodeChildren(setting, parentNode); + for (var i = 0, l = children ? children.length : 0; i < l; i++) { + data.removeNodeCache(setting, children[i]); + } + data.removeSelectedNode(setting); + data.nodeChildren(setting, parentNode, []); + if (isRoot) { + this.setting.treeObj.empty(); + } else { + var ulObj = $$(parentNode, consts.id.UL, setting); + ulObj.empty(); + } + } + view.asyncNode(this.setting, isRoot ? null : parentNode, !!isSilent, callback); + }, + refresh: function () { + this.setting.treeObj.empty(); + var root = data.getRoot(setting), + nodes = data.nodeChildren(setting, root); + data.initRoot(setting); + data.nodeChildren(setting, root, nodes); + data.initCache(setting); + view.createNodes(setting, 0, data.nodeChildren(setting, root), null, -1); + }, + removeChildNodes: function (node) { + if (!node) return null; + var nodes = data.nodeChildren(setting, node); + view.removeChildNodes(setting, node); + return nodes ? nodes : null; + }, + removeNode: function (node, callbackFlag) { + if (!node) return; + callbackFlag = !!callbackFlag; + if (callbackFlag && tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return; + view.removeNode(setting, node); + if (callbackFlag) { + this.setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]); + } + }, + selectNode: function (node, addFlag, isSilent) { + if (!node) return; + if (tools.uCanDo(setting)) { + addFlag = setting.view.selectedMulti && addFlag; + if (node.parentTId) { + view.expandCollapseParentNode(setting, node.getParentNode(), true, false, showNodeFocus); + } else if (!isSilent) { + try { + $$(node, setting).focus().blur(); + } catch (e) { + } + } + view.selectNode(setting, node, addFlag); + } + + function showNodeFocus() { + if (isSilent) { + return; + } + var a = $$(node, setting).get(0); + view.scrollIntoView(setting, a); + } + }, + transformTozTreeNodes: function (simpleNodes) { + return data.transformTozTreeFormat(setting, simpleNodes); + }, + transformToArray: function (nodes) { + return data.transformToArrayFormat(setting, nodes); + }, + updateNode: function (node, checkTypeFlag) { + if (!node) return; + var nObj = $$(node, setting); + if (nObj.get(0) && tools.uCanDo(setting)) { + view.setNodeName(setting, node); + view.setNodeTarget(setting, node); + view.setNodeUrl(setting, node); + view.setNodeLineIcos(setting, node); + view.setNodeFontCss(setting, node); + view.setNodeClasses(setting, node); + } + } + }; + root.treeTools = zTreeTools; + data.setZTreeTools(setting, zTreeTools); + var children = data.nodeChildren(setting, root); + if (children && children.length > 0) { + view.createNodes(setting, 0, children, null, -1); + } else if (setting.async.enable && setting.async.url && setting.async.url !== '') { + view.asyncNode(setting); + } + return zTreeTools; + } + }; + + var zt = $.fn.zTree, + $$ = tools.$, + consts = zt.consts; +})(jQuery); +/* + * JQuery zTree excheck + * v3.5.48 + * http://treejs.cn/ + * + * Copyright (c) 2010 Hunter.z + * + * Licensed same as jquery - MIT License + * http://www.opensource.org/licenses/mit-license.php + * + * Date: 2020-11-21 + */ + +(function ($) { + //default consts of excheck + var _consts = { + event: { + CHECK: "ztree_check" + }, + id: { + CHECK: "_check" + }, + checkbox: { + STYLE: "checkbox", + DEFAULT: "chk", + DISABLED: "disable", + FALSE: "false", + TRUE: "true", + FULL: "full", + PART: "part", + FOCUS: "focus" + }, + radio: { + STYLE: "radio", + TYPE_ALL: "all", + TYPE_LEVEL: "level" + } + }, + //default setting of excheck + _setting = { + check: { + enable: false, + autoCheckTrigger: false, + chkStyle: _consts.checkbox.STYLE, + nocheckInherit: false, + chkDisabledInherit: false, + radioType: _consts.radio.TYPE_LEVEL, + chkboxType: { + "Y": "ps", + "N": "ps" + } + }, + data: { + key: { + checked: "checked" + } + }, + callback: { + beforeCheck: null, + onCheck: null + } + }, + //default root of excheck + _initRoot = function (setting) { + var r = data.getRoot(setting); + r.radioCheckedList = []; + }, + //default cache of excheck + _initCache = function (treeId) { + }, + //default bind event of excheck + _bindEvent = function (setting) { + var o = setting.treeObj, + c = consts.event; + o.bind(c.CHECK, function (event, srcEvent, treeId, node) { + event.srcEvent = srcEvent; + tools.apply(setting.callback.onCheck, [event, treeId, node]); + }); + }, + _unbindEvent = function (setting) { + var o = setting.treeObj, + c = consts.event; + o.unbind(c.CHECK); + }, + //default event proxy of excheck + _eventProxy = function (e) { + var target = e.target, + setting = data.getSetting(e.data.treeId), + tId = "", node = null, + nodeEventType = "", treeEventType = "", + nodeEventCallback = null, treeEventCallback = null; + + if (tools.eqs(e.type, "mouseover")) { + if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode" + consts.id.CHECK) !== null) { + tId = tools.getNodeMainDom(target).id; + nodeEventType = "mouseoverCheck"; + } + } else if (tools.eqs(e.type, "mouseout")) { + if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode" + consts.id.CHECK) !== null) { + tId = tools.getNodeMainDom(target).id; + nodeEventType = "mouseoutCheck"; + } + } else if (tools.eqs(e.type, "click")) { + if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode" + consts.id.CHECK) !== null) { + tId = tools.getNodeMainDom(target).id; + nodeEventType = "checkNode"; + } + } + if (tId.length > 0) { + node = data.getNodeCache(setting, tId); + switch (nodeEventType) { + case "checkNode" : + nodeEventCallback = _handler.onCheckNode; + break; + case "mouseoverCheck" : + nodeEventCallback = _handler.onMouseoverCheck; + break; + case "mouseoutCheck" : + nodeEventCallback = _handler.onMouseoutCheck; + break; + } + } + var proxyResult = { + stop: nodeEventType === "checkNode", + node: node, + nodeEventType: nodeEventType, + nodeEventCallback: nodeEventCallback, + treeEventType: treeEventType, + treeEventCallback: treeEventCallback + }; + return proxyResult + }, + //default init node of excheck + _initNode = function (setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) { + if (!n) return; + var checked = data.nodeChecked(setting, n); + n.checkedOld = checked; + if (typeof n.nocheck == "string") n.nocheck = tools.eqs(n.nocheck, "true"); + n.nocheck = !!n.nocheck || (setting.check.nocheckInherit && parentNode && !!parentNode.nocheck); + if (typeof n.chkDisabled == "string") n.chkDisabled = tools.eqs(n.chkDisabled, "true"); + n.chkDisabled = !!n.chkDisabled || (setting.check.chkDisabledInherit && parentNode && !!parentNode.chkDisabled); + if (typeof n.halfCheck == "string") n.halfCheck = tools.eqs(n.halfCheck, "true"); + n.halfCheck = !!n.halfCheck; + n.check_Child_State = -1; + n.check_Focus = false; + n.getCheckStatus = function () { + return data.getCheckStatus(setting, n); + }; + + if (setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL && checked) { + var r = data.getRoot(setting); + r.radioCheckedList.push(n); + } + }, + //add dom for check + _beforeA = function (setting, node, html) { + if (setting.check.enable) { + data.makeChkFlag(setting, node); + html.push(""); + } + }, + //update zTreeObj, add method of check + _zTreeTools = function (setting, zTreeTools) { + zTreeTools.checkNode = function (node, checked, checkTypeFlag, callbackFlag) { + var nodeChecked = data.nodeChecked(setting, node); + if (node.chkDisabled === true) return; + if (checked !== true && checked !== false) { + checked = !nodeChecked; + } + callbackFlag = !!callbackFlag; + + if (nodeChecked === checked && !checkTypeFlag) { + return; + } else if (callbackFlag && tools.apply(this.setting.callback.beforeCheck, [this.setting.treeId, node], true) == false) { + return; + } + if (tools.uCanDo(this.setting) && this.setting.check.enable && node.nocheck !== true) { + data.nodeChecked(setting, node, checked); + var checkObj = $$(node, consts.id.CHECK, this.setting); + if (checkTypeFlag || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node); + view.setChkClass(this.setting, checkObj, node); + view.repairParentChkClassWithSelf(this.setting, node); + if (callbackFlag) { + this.setting.treeObj.trigger(consts.event.CHECK, [null, this.setting.treeId, node]); + } + } + } + + zTreeTools.checkAllNodes = function (checked) { + view.repairAllChk(this.setting, !!checked); + } + + zTreeTools.getCheckedNodes = function (checked) { + checked = (checked !== false); + var children = data.nodeChildren(setting, data.getRoot(this.setting)); + return data.getTreeCheckedNodes(this.setting, children, checked); + } + + zTreeTools.getChangeCheckedNodes = function () { + var children = data.nodeChildren(setting, data.getRoot(this.setting)); + return data.getTreeChangeCheckedNodes(this.setting, children); + } + + zTreeTools.setChkDisabled = function (node, disabled, inheritParent, inheritChildren) { + disabled = !!disabled; + inheritParent = !!inheritParent; + inheritChildren = !!inheritChildren; + view.repairSonChkDisabled(this.setting, node, disabled, inheritChildren); + view.repairParentChkDisabled(this.setting, node.getParentNode(), disabled, inheritParent); + } + + var _updateNode = zTreeTools.updateNode; + zTreeTools.updateNode = function (node, checkTypeFlag) { + if (_updateNode) _updateNode.apply(zTreeTools, arguments); + if (!node || !this.setting.check.enable) return; + var nObj = $$(node, this.setting); + if (nObj.get(0) && tools.uCanDo(this.setting)) { + var checkObj = $$(node, consts.id.CHECK, this.setting); + if (checkTypeFlag == true || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node); + view.setChkClass(this.setting, checkObj, node); + view.repairParentChkClassWithSelf(this.setting, node); + } + } + }, + //method of operate data + _data = { + getRadioCheckedList: function (setting) { + var checkedList = data.getRoot(setting).radioCheckedList; + for (var i = 0, j = checkedList.length; i < j; i++) { + if (!data.getNodeCache(setting, checkedList[i].tId)) { + checkedList.splice(i, 1); + i--; + j--; + } + } + return checkedList; + }, + getCheckStatus: function (setting, node) { + if (!setting.check.enable || node.nocheck || node.chkDisabled) return null; + var checked = data.nodeChecked(setting, node), + r = { + checked: checked, + half: node.halfCheck ? node.halfCheck : (setting.check.chkStyle == consts.radio.STYLE ? (node.check_Child_State === 2) : (checked ? (node.check_Child_State > -1 && node.check_Child_State < 2) : (node.check_Child_State > 0))) + }; + return r; + }, + getTreeCheckedNodes: function (setting, nodes, checked, results) { + if (!nodes) return []; + var onlyOne = (checked && setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL); + results = !results ? [] : results; + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + var children = data.nodeChildren(setting, node); + var nodeChecked = data.nodeChecked(setting, node); + if (node.nocheck !== true && node.chkDisabled !== true && nodeChecked == checked) { + results.push(node); + if (onlyOne) { + break; + } + } + data.getTreeCheckedNodes(setting, children, checked, results); + if (onlyOne && results.length > 0) { + break; + } + } + return results; + }, + getTreeChangeCheckedNodes: function (setting, nodes, results) { + if (!nodes) return []; + results = !results ? [] : results; + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + var children = data.nodeChildren(setting, node); + var nodeChecked = data.nodeChecked(setting, node); + if (node.nocheck !== true && node.chkDisabled !== true && nodeChecked != node.checkedOld) { + results.push(node); + } + data.getTreeChangeCheckedNodes(setting, children, results); + } + return results; + }, + makeChkFlag: function (setting, node) { + if (!node) return; + var chkFlag = -1; + var children = data.nodeChildren(setting, node); + if (children) { + for (var i = 0, l = children.length; i < l; i++) { + var cNode = children[i]; + var nodeChecked = data.nodeChecked(setting, cNode); + var tmp = -1; + if (setting.check.chkStyle == consts.radio.STYLE) { + if (cNode.nocheck === true || cNode.chkDisabled === true) { + tmp = cNode.check_Child_State; + } else if (cNode.halfCheck === true) { + tmp = 2; + } else if (nodeChecked) { + tmp = 2; + } else { + tmp = cNode.check_Child_State > 0 ? 2 : 0; + } + if (tmp == 2) { + chkFlag = 2; + break; + } else if (tmp == 0) { + chkFlag = 0; + } + } else if (setting.check.chkStyle == consts.checkbox.STYLE) { + if (cNode.nocheck === true || cNode.chkDisabled === true) { + tmp = cNode.check_Child_State; + } else if (cNode.halfCheck === true) { + tmp = 1; + } else if (nodeChecked) { + tmp = (cNode.check_Child_State === -1 || cNode.check_Child_State === 2) ? 2 : 1; + } else { + tmp = (cNode.check_Child_State > 0) ? 1 : 0; + } + if (tmp === 1) { + chkFlag = 1; + break; + } else if (tmp === 2 && chkFlag > -1 && i > 0 && tmp !== chkFlag) { + chkFlag = 1; + break; + } else if (chkFlag === 2 && tmp > -1 && tmp < 2) { + chkFlag = 1; + break; + } else if (tmp > -1) { + chkFlag = tmp; + } + } + } + } + node.check_Child_State = chkFlag; + } + }, + //method of event proxy + _event = {}, + //method of event handler + _handler = { + onCheckNode: function (event, node) { + if (node.chkDisabled === true) return false; + var setting = data.getSetting(event.data.treeId); + if (tools.apply(setting.callback.beforeCheck, [setting.treeId, node], true) == false) return true; + var nodeChecked = data.nodeChecked(setting, node); + data.nodeChecked(setting, node, !nodeChecked); + view.checkNodeRelation(setting, node); + var checkObj = $$(node, consts.id.CHECK, setting); + view.setChkClass(setting, checkObj, node); + view.repairParentChkClassWithSelf(setting, node); + setting.treeObj.trigger(consts.event.CHECK, [event, setting.treeId, node]); + return true; + }, + onMouseoverCheck: function (event, node) { + if (node.chkDisabled === true) return false; + var setting = data.getSetting(event.data.treeId), + checkObj = $$(node, consts.id.CHECK, setting); + node.check_Focus = true; + view.setChkClass(setting, checkObj, node); + return true; + }, + onMouseoutCheck: function (event, node) { + if (node.chkDisabled === true) return false; + var setting = data.getSetting(event.data.treeId), + checkObj = $$(node, consts.id.CHECK, setting); + node.check_Focus = false; + view.setChkClass(setting, checkObj, node); + return true; + } + }, + //method of tools for zTree + _tools = {}, + //method of operate ztree dom + _view = { + checkNodeRelation: function (setting, node) { + var pNode, i, l, + r = consts.radio; + var nodeChecked = data.nodeChecked(setting, node); + if (setting.check.chkStyle == r.STYLE) { + var checkedList = data.getRadioCheckedList(setting); + if (nodeChecked) { + if (setting.check.radioType == r.TYPE_ALL) { + for (i = checkedList.length - 1; i >= 0; i--) { + pNode = checkedList[i]; + var pNodeChecked = data.nodeChecked(setting, pNode); + if (pNodeChecked && pNode != node) { + data.nodeChecked(setting, pNode, false); + checkedList.splice(i, 1); + + view.setChkClass(setting, $$(pNode, consts.id.CHECK, setting), pNode); + if (pNode.parentTId != node.parentTId) { + view.repairParentChkClassWithSelf(setting, pNode); + } + } + } + checkedList.push(node); + } else { + var parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting); + var children = data.nodeChildren(setting, parentNode); + for (i = 0, l = children.length; i < l; i++) { + pNode = children[i]; + var pNodeChecked = data.nodeChecked(setting, pNode); + if (pNodeChecked && pNode != node) { + data.nodeChecked(setting, pNode, false); + view.setChkClass(setting, $$(pNode, consts.id.CHECK, setting), pNode); + } + } + } + } else if (setting.check.radioType == r.TYPE_ALL) { + for (i = 0, l = checkedList.length; i < l; i++) { + if (node == checkedList[i]) { + checkedList.splice(i, 1); + break; + } + } + } + + } else { + var children = data.nodeChildren(setting, node); + if (nodeChecked && (!children || children.length == 0 || setting.check.chkboxType.Y.indexOf("s") > -1)) { + view.setSonNodeCheckBox(setting, node, true); + } + if (!nodeChecked && (!children || children.length == 0 || setting.check.chkboxType.N.indexOf("s") > -1)) { + view.setSonNodeCheckBox(setting, node, false); + } + if (nodeChecked && setting.check.chkboxType.Y.indexOf("p") > -1) { + view.setParentNodeCheckBox(setting, node, true); + } + if (!nodeChecked && setting.check.chkboxType.N.indexOf("p") > -1) { + view.setParentNodeCheckBox(setting, node, false); + } + } + }, + makeChkClass: function (setting, node) { + var c = consts.checkbox, r = consts.radio, + fullStyle = ""; + var nodeChecked = data.nodeChecked(setting, node); + if (node.chkDisabled === true) { + fullStyle = c.DISABLED; + } else if (node.halfCheck) { + fullStyle = c.PART; + } else if (setting.check.chkStyle == r.STYLE) { + fullStyle = (node.check_Child_State < 1) ? c.FULL : c.PART; + } else { + fullStyle = nodeChecked ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL : c.PART) : ((node.check_Child_State < 1) ? c.FULL : c.PART); + } + var chkName = setting.check.chkStyle + "_" + (nodeChecked ? c.TRUE : c.FALSE) + "_" + fullStyle; + chkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + "_" + c.FOCUS : chkName; + return consts.className.BUTTON + " " + c.DEFAULT + " " + chkName; + }, + repairAllChk: function (setting, checked) { + if (setting.check.enable && setting.check.chkStyle === consts.checkbox.STYLE) { + var root = data.getRoot(setting); + var children = data.nodeChildren(setting, root); + for (var i = 0, l = children.length; i < l; i++) { + var node = children[i]; + if (node.nocheck !== true && node.chkDisabled !== true) { + data.nodeChecked(setting, node, checked); + } + view.setSonNodeCheckBox(setting, node, checked); + } + } + }, + repairChkClass: function (setting, node) { + if (!node) return; + data.makeChkFlag(setting, node); + if (node.nocheck !== true) { + var checkObj = $$(node, consts.id.CHECK, setting); + view.setChkClass(setting, checkObj, node); + } + }, + repairParentChkClass: function (setting, node) { + if (!node || !node.parentTId) return; + var pNode = node.getParentNode(); + view.repairChkClass(setting, pNode); + view.repairParentChkClass(setting, pNode); + }, + repairParentChkClassWithSelf: function (setting, node) { + if (!node) return; + var children = data.nodeChildren(setting, node); + if (children && children.length > 0) { + view.repairParentChkClass(setting, children[0]); + } else { + view.repairParentChkClass(setting, node); + } + }, + repairSonChkDisabled: function (setting, node, chkDisabled, inherit) { + if (!node) return; + if (node.chkDisabled != chkDisabled) { + node.chkDisabled = chkDisabled; + } + view.repairChkClass(setting, node); + var children = data.nodeChildren(setting, node); + if (children && inherit) { + for (var i = 0, l = children.length; i < l; i++) { + var sNode = children[i]; + view.repairSonChkDisabled(setting, sNode, chkDisabled, inherit); + } + } + }, + repairParentChkDisabled: function (setting, node, chkDisabled, inherit) { + if (!node) return; + if (node.chkDisabled != chkDisabled && inherit) { + node.chkDisabled = chkDisabled; + } + view.repairChkClass(setting, node); + view.repairParentChkDisabled(setting, node.getParentNode(), chkDisabled, inherit); + }, + setChkClass: function (setting, obj, node) { + if (!obj) return; + if (node.nocheck === true) { + obj.hide(); + } else { + obj.show(); + } + obj.attr('class', view.makeChkClass(setting, node)); + }, + setParentNodeCheckBox: function (setting, node, value, srcNode) { + var checkObj = $$(node, consts.id.CHECK, setting); + if (!srcNode) srcNode = node; + data.makeChkFlag(setting, node); + if (node.nocheck !== true && node.chkDisabled !== true) { + data.nodeChecked(setting, node, value); + view.setChkClass(setting, checkObj, node); + if (setting.check.autoCheckTrigger && node != srcNode) { + setting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]); + } + } + if (node.parentTId) { + var pSign = true; + if (!value) { + var pNodes = data.nodeChildren(setting, node.getParentNode()); + for (var i = 0, l = pNodes.length; i < l; i++) { + var pNode = pNodes[i]; + var nodeChecked = data.nodeChecked(setting, pNode); + if ((pNode.nocheck !== true && pNode.chkDisabled !== true && nodeChecked) + || ((pNode.nocheck === true || pNode.chkDisabled === true) && pNode.check_Child_State > 0)) { + pSign = false; + break; + } + } + } + if (pSign) { + view.setParentNodeCheckBox(setting, node.getParentNode(), value, srcNode); + } + } + }, + setSonNodeCheckBox: function (setting, node, value, srcNode) { + if (!node) return; + var checkObj = $$(node, consts.id.CHECK, setting); + if (!srcNode) srcNode = node; + + var hasDisable = false; + var children = data.nodeChildren(setting, node); + if (children) { + for (var i = 0, l = children.length; i < l; i++) { + var sNode = children[i]; + view.setSonNodeCheckBox(setting, sNode, value, srcNode); + if (sNode.chkDisabled === true) hasDisable = true; + } + } + + if (node != data.getRoot(setting) && node.chkDisabled !== true) { + if (hasDisable && node.nocheck !== true) { + data.makeChkFlag(setting, node); + } + if (node.nocheck !== true && node.chkDisabled !== true) { + data.nodeChecked(setting, node, value); + if (!hasDisable) node.check_Child_State = (children && children.length > 0) ? (value ? 2 : 0) : -1; + } else { + node.check_Child_State = -1; + } + view.setChkClass(setting, checkObj, node); + if (setting.check.autoCheckTrigger && node != srcNode && node.nocheck !== true && node.chkDisabled !== true) { + setting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]); + } + } + + } + }, + + _z = { + tools: _tools, + view: _view, + event: _event, + data: _data + }; + $.extend(true, $.fn.zTree.consts, _consts); + $.extend(true, $.fn.zTree._z, _z); + + var zt = $.fn.zTree, + tools = zt._z.tools, + consts = zt.consts, + view = zt._z.view, + data = zt._z.data, + event = zt._z.event, + $$ = tools.$; + + data.nodeChecked = function (setting, node, newChecked) { + if (!node) { + return false; + } + var key = setting.data.key.checked; + if (typeof newChecked !== 'undefined') { + if (typeof newChecked === "string") { + newChecked = tools.eqs(newChecked, "true"); + } + newChecked = !!newChecked; + node[key] = newChecked; + } else if (typeof node[key] == "string"){ + node[key] = tools.eqs(node[key], "true"); + } else { + node[key] = !!node[key]; + } + return node[key]; + }; + + data.exSetting(_setting); + data.addInitBind(_bindEvent); + data.addInitUnBind(_unbindEvent); + data.addInitCache(_initCache); + data.addInitNode(_initNode); + data.addInitProxy(_eventProxy, true); + data.addInitRoot(_initRoot); + data.addBeforeA(_beforeA); + data.addZTreeTools(_zTreeTools); + + var _createNodes = view.createNodes; + view.createNodes = function (setting, level, nodes, parentNode, index) { + if (_createNodes) _createNodes.apply(view, arguments); + if (!nodes) return; + view.repairParentChkClassWithSelf(setting, parentNode); + } + var _removeNode = view.removeNode; + view.removeNode = function (setting, node) { + var parentNode = node.getParentNode(); + if (_removeNode) _removeNode.apply(view, arguments); + if (!node || !parentNode) return; + view.repairChkClass(setting, parentNode); + view.repairParentChkClass(setting, parentNode); + } + + var _appendNodes = view.appendNodes; + view.appendNodes = function (setting, level, nodes, parentNode, index, initFlag, openFlag) { + var html = ""; + if (_appendNodes) { + html = _appendNodes.apply(view, arguments); + } + if (parentNode) { + data.makeChkFlag(setting, parentNode); + } + return html; + } +})(jQuery); +/* + * JQuery zTree exedit + * v3.5.48 + * http://treejs.cn/ + * + * Copyright (c) 2010 Hunter.z + * + * Licensed same as jquery - MIT License + * http://www.opensource.org/licenses/mit-license.php + * + * Date: 2020-11-21 + */ + +(function ($) { + //default consts of exedit + var _consts = { + event: { + DRAG: "ztree_drag", + DROP: "ztree_drop", + RENAME: "ztree_rename", + DRAGMOVE: "ztree_dragmove" + }, + id: { + EDIT: "_edit", + INPUT: "_input", + REMOVE: "_remove" + }, + move: { + TYPE_INNER: "inner", + TYPE_PREV: "prev", + TYPE_NEXT: "next" + }, + node: { + CURSELECTED_EDIT: "curSelectedNode_Edit", + TMPTARGET_TREE: "tmpTargetzTree", + TMPTARGET_NODE: "tmpTargetNode" + } + }, + //default setting of exedit + _setting = { + edit: { + enable: false, + editNameSelectAll: false, + showRemoveBtn: true, + showRenameBtn: true, + removeTitle: "remove", + renameTitle: "rename", + drag: { + autoExpandTrigger: false, + isCopy: true, + isMove: true, + prev: true, + next: true, + inner: true, + minMoveSize: 5, + borderMax: 10, + borderMin: -5, + maxShowNodeNum: 5, + autoOpenTime: 500 + } + }, + view: { + addHoverDom: null, + removeHoverDom: null + }, + callback: { + beforeDrag: null, + beforeDragOpen: null, + beforeDrop: null, + beforeEditName: null, + beforeRename: null, + onDrag: null, + onDragMove: null, + onDrop: null, + onRename: null + } + }, + //default root of exedit + _initRoot = function (setting) { + var r = data.getRoot(setting), rs = data.getRoots(); + r.curEditNode = null; + r.curEditInput = null; + r.curHoverNode = null; + r.dragFlag = 0; + r.dragNodeShowBefore = []; + r.dragMaskList = new Array(); + rs.showHoverDom = true; + }, + //default cache of exedit + _initCache = function (treeId) { + }, + //default bind event of exedit + _bindEvent = function (setting) { + var o = setting.treeObj; + var c = consts.event; + o.bind(c.RENAME, function (event, treeId, treeNode, isCancel) { + tools.apply(setting.callback.onRename, [event, treeId, treeNode, isCancel]); + }); + + o.bind(c.DRAG, function (event, srcEvent, treeId, treeNodes) { + tools.apply(setting.callback.onDrag, [srcEvent, treeId, treeNodes]); + }); + + o.bind(c.DRAGMOVE, function (event, srcEvent, treeId, treeNodes) { + tools.apply(setting.callback.onDragMove, [srcEvent, treeId, treeNodes]); + }); + + o.bind(c.DROP, function (event, srcEvent, treeId, treeNodes, targetNode, moveType, isCopy) { + tools.apply(setting.callback.onDrop, [srcEvent, treeId, treeNodes, targetNode, moveType, isCopy]); + }); + }, + _unbindEvent = function (setting) { + var o = setting.treeObj; + var c = consts.event; + o.unbind(c.RENAME); + o.unbind(c.DRAG); + o.unbind(c.DRAGMOVE); + o.unbind(c.DROP); + }, + //default event proxy of exedit + _eventProxy = function (e) { + var target = e.target, + setting = data.getSetting(e.data.treeId), + relatedTarget = e.relatedTarget, + tId = "", node = null, + nodeEventType = "", treeEventType = "", + nodeEventCallback = null, treeEventCallback = null, + tmp = null; + + if (tools.eqs(e.type, "mouseover")) { + tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]); + if (tmp) { + tId = tools.getNodeMainDom(tmp).id; + nodeEventType = "hoverOverNode"; + } + } else if (tools.eqs(e.type, "mouseout")) { + tmp = tools.getMDom(setting, relatedTarget, [{tagName: "a", attrName: "treeNode" + consts.id.A}]); + if (!tmp) { + tId = "remove"; + nodeEventType = "hoverOutNode"; + } + } else if (tools.eqs(e.type, "mousedown")) { + tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]); + if (tmp) { + tId = tools.getNodeMainDom(tmp).id; + nodeEventType = "mousedownNode"; + } + } + if (tId.length > 0) { + node = data.getNodeCache(setting, tId); + switch (nodeEventType) { + case "mousedownNode" : + nodeEventCallback = _handler.onMousedownNode; + break; + case "hoverOverNode" : + nodeEventCallback = _handler.onHoverOverNode; + break; + case "hoverOutNode" : + nodeEventCallback = _handler.onHoverOutNode; + break; + } + } + var proxyResult = { + stop: false, + node: node, + nodeEventType: nodeEventType, + nodeEventCallback: nodeEventCallback, + treeEventType: treeEventType, + treeEventCallback: treeEventCallback + }; + return proxyResult + }, + //default init node of exedit + _initNode = function (setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) { + if (!n) return; + n.isHover = false; + n.editNameFlag = false; + }, + //update zTreeObj, add method of edit + _zTreeTools = function (setting, zTreeTools) { + zTreeTools.cancelEditName = function (newName) { + var root = data.getRoot(this.setting); + if (!root.curEditNode) return; + view.cancelCurEditNode(this.setting, newName ? newName : null, true); + } + zTreeTools.copyNode = function (targetNode, node, moveType, isSilent) { + if (!node) return null; + var isParent = data.nodeIsParent(setting, targetNode); + if (targetNode && !isParent && this.setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) return null; + var _this = this, + newNode = tools.clone(node); + if (!targetNode) { + targetNode = null; + moveType = consts.move.TYPE_INNER; + } + if (moveType == consts.move.TYPE_INNER) { + function copyCallback() { + view.addNodes(_this.setting, targetNode, -1, [newNode], isSilent); + } + + if (tools.canAsync(this.setting, targetNode)) { + view.asyncNode(this.setting, targetNode, isSilent, copyCallback); + } else { + copyCallback(); + } + } else { + view.addNodes(this.setting, targetNode.parentNode, -1, [newNode], isSilent); + view.moveNode(this.setting, targetNode, newNode, moveType, false, isSilent); + } + return newNode; + } + zTreeTools.editName = function (node) { + if (!node || !node.tId || node !== data.getNodeCache(this.setting, node.tId)) return; + if (node.parentTId) view.expandCollapseParentNode(this.setting, node.getParentNode(), true); + view.editNode(this.setting, node) + } + zTreeTools.moveNode = function (targetNode, node, moveType, isSilent) { + if (!node) return node; + var isParent = data.nodeIsParent(setting, targetNode); + if (targetNode && !isParent && this.setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) { + return null; + } else if (targetNode && ((node.parentTId == targetNode.tId && moveType == consts.move.TYPE_INNER) || $$(node, this.setting).find("#" + targetNode.tId).length > 0)) { + return null; + } else if (!targetNode) { + targetNode = null; + } + var _this = this; + + function moveCallback() { + view.moveNode(_this.setting, targetNode, node, moveType, false, isSilent); + } + + if (tools.canAsync(this.setting, targetNode) && moveType === consts.move.TYPE_INNER) { + view.asyncNode(this.setting, targetNode, isSilent, moveCallback); + } else { + moveCallback(); + } + return node; + } + zTreeTools.setEditable = function (editable) { + this.setting.edit.enable = editable; + return this.refresh(); + } + }, + //method of operate data + _data = { + setSonNodeLevel: function (setting, parentNode, node) { + if (!node) return; + var children = data.nodeChildren(setting, node); + var oldLevel = node.level; + node.level = (parentNode) ? parentNode.level + 1 : 0; + view.repairNodeLevelClass(setting, node, oldLevel); + + if (!children) return; + for (var i = 0, l = children.length; i < l; i++) { + if (children[i]) data.setSonNodeLevel(setting, node, children[i]); + } + } + }, + //method of event proxy + _event = {}, + //method of event handler + _handler = { + onHoverOverNode: function (event, node) { + var setting = data.getSetting(event.data.treeId), + root = data.getRoot(setting); + if (root.curHoverNode != node) { + _handler.onHoverOutNode(event); + } + root.curHoverNode = node; + view.addHoverDom(setting, node); + }, + onHoverOutNode: function (event, node) { + var setting = data.getSetting(event.data.treeId), + root = data.getRoot(setting); + if (root.curHoverNode && !data.isSelectedNode(setting, root.curHoverNode)) { + view.removeTreeDom(setting, root.curHoverNode); + root.curHoverNode = null; + } + }, + onMousedownNode: function (eventMouseDown, _node) { + var i, l, + setting = data.getSetting(eventMouseDown.data.treeId), + root = data.getRoot(setting), roots = data.getRoots(); + //right click can't drag & drop + if (eventMouseDown.button == 2 || !setting.edit.enable || (!setting.edit.drag.isCopy && !setting.edit.drag.isMove)) return true; + + //input of edit node name can't drag & drop + var target = eventMouseDown.target, + _nodes = data.getRoot(setting).curSelectedList, + nodes = []; + if (!data.isSelectedNode(setting, _node)) { + nodes = [_node]; + } else { + for (i = 0, l = _nodes.length; i < l; i++) { + if (_nodes[i].editNameFlag && tools.eqs(target.tagName, "input") && target.getAttribute("treeNode" + consts.id.INPUT) !== null) { + return true; + } + nodes.push(_nodes[i]); + if (nodes[0].parentTId !== _nodes[i].parentTId) { + nodes = [_node]; + break; + } + } + } + + view.editNodeBlur = true; + view.cancelCurEditNode(setting); + + var doc = $(setting.treeObj.get(0).ownerDocument), + body = $(setting.treeObj.get(0).ownerDocument.body), curNode, tmpArrow, tmpTarget, + isOtherTree = false, + targetSetting = setting, + sourceSetting = setting, + preNode, nextNode, + preTmpTargetNodeId = null, + preTmpMoveType = null, + tmpTargetNodeId = null, + moveType = consts.move.TYPE_INNER, + mouseDownX = eventMouseDown.clientX, + mouseDownY = eventMouseDown.clientY, + startTime = (new Date()).getTime(); + + if (tools.uCanDo(setting)) { + doc.bind("mousemove", _docMouseMove); + } + + function _docMouseMove(event) { + //avoid start drag after click node + if (root.dragFlag == 0 && Math.abs(mouseDownX - event.clientX) < setting.edit.drag.minMoveSize + && Math.abs(mouseDownY - event.clientY) < setting.edit.drag.minMoveSize) { + return true; + } + var i, l, tmpNode, tmpDom, tmpNodes; + body.css("cursor", "pointer"); + + if (root.dragFlag == 0) { + if (tools.apply(setting.callback.beforeDrag, [setting.treeId, nodes], true) == false) { + _docMouseUp(event); + return true; + } + + for (i = 0, l = nodes.length; i < l; i++) { + if (i == 0) { + root.dragNodeShowBefore = []; + } + tmpNode = nodes[i]; + if (data.nodeIsParent(setting, tmpNode) && tmpNode.open) { + view.expandCollapseNode(setting, tmpNode, !tmpNode.open); + root.dragNodeShowBefore[tmpNode.tId] = true; + } else { + root.dragNodeShowBefore[tmpNode.tId] = false; + } + } + + root.dragFlag = 1; + roots.showHoverDom = false; + tools.showIfameMask(setting, true); + + //sort + var isOrder = true, lastIndex = -1; + if (nodes.length > 1) { + var pNodes = nodes[0].parentTId ? data.nodeChildren(setting, nodes[0].getParentNode()) : data.getNodes(setting); + tmpNodes = []; + for (i = 0, l = pNodes.length; i < l; i++) { + if (root.dragNodeShowBefore[pNodes[i].tId] !== undefined) { + if (isOrder && lastIndex > -1 && (lastIndex + 1) !== i) { + isOrder = false; + } + tmpNodes.push(pNodes[i]); + lastIndex = i; + } + if (nodes.length === tmpNodes.length) { + nodes = tmpNodes; + break; + } + } + } + if (isOrder) { + preNode = nodes[0].getPreNode(); + nextNode = nodes[nodes.length - 1].getNextNode(); + } + + //set node in selected + curNode = $$("
      ", setting); + for (i = 0, l = nodes.length; i < l; i++) { + tmpNode = nodes[i]; + tmpNode.editNameFlag = false; + view.selectNode(setting, tmpNode, i > 0); + view.removeTreeDom(setting, tmpNode); + + if (i > setting.edit.drag.maxShowNodeNum - 1) { + continue; + } + + tmpDom = $$("
    • ", setting); + tmpDom.append($$(tmpNode, consts.id.A, setting).clone()); + tmpDom.css("padding", "0"); + tmpDom.children("#" + tmpNode.tId + consts.id.A).removeClass(consts.node.CURSELECTED); + curNode.append(tmpDom); + if (i == setting.edit.drag.maxShowNodeNum - 1) { + tmpDom = $$("
    • ...
    • ", setting); + curNode.append(tmpDom); + } + } + curNode.attr("id", nodes[0].tId + consts.id.UL + "_tmp"); + curNode.addClass(setting.treeObj.attr("class")); + curNode.appendTo(body); + + tmpArrow = $$("", setting); + tmpArrow.attr("id", "zTreeMove_arrow_tmp"); + tmpArrow.appendTo(body); + + setting.treeObj.trigger(consts.event.DRAG, [event, setting.treeId, nodes]); + } + + if (root.dragFlag == 1) { + if (tmpTarget && tmpArrow.attr("id") == event.target.id && tmpTargetNodeId && (event.clientX + doc.scrollLeft() + 2) > ($("#" + tmpTargetNodeId + consts.id.A, tmpTarget).offset().left)) { + var xT = $("#" + tmpTargetNodeId + consts.id.A, tmpTarget); + event.target = (xT.length > 0) ? xT.get(0) : event.target; + } else if (tmpTarget) { + tmpTarget.removeClass(consts.node.TMPTARGET_TREE); + if (tmpTargetNodeId) $("#" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + "_" + consts.move.TYPE_PREV) + .removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_INNER); + } + tmpTarget = null; + tmpTargetNodeId = null; + + //judge drag & drop in multi ztree + isOtherTree = false; + targetSetting = setting; + var settings = data.getSettings(); + for (var s in settings) { + if (settings[s].treeId && settings[s].edit.enable && settings[s].treeId != setting.treeId + && (event.target.id == settings[s].treeId || $(event.target).parents("#" + settings[s].treeId).length > 0)) { + isOtherTree = true; + targetSetting = settings[s]; + } + } + + var docScrollTop = doc.scrollTop(), + docScrollLeft = doc.scrollLeft(), + treeOffset = targetSetting.treeObj.offset(), + scrollHeight = targetSetting.treeObj.get(0).scrollHeight, + scrollWidth = targetSetting.treeObj.get(0).scrollWidth, + dTop = (event.clientY + docScrollTop - treeOffset.top), + dBottom = (targetSetting.treeObj.height() + treeOffset.top - event.clientY - docScrollTop), + dLeft = (event.clientX + docScrollLeft - treeOffset.left), + dRight = (targetSetting.treeObj.width() + treeOffset.left - event.clientX - docScrollLeft), + isTop = (dTop < setting.edit.drag.borderMax && dTop > setting.edit.drag.borderMin), + isBottom = (dBottom < setting.edit.drag.borderMax && dBottom > setting.edit.drag.borderMin), + isLeft = (dLeft < setting.edit.drag.borderMax && dLeft > setting.edit.drag.borderMin), + isRight = (dRight < setting.edit.drag.borderMax && dRight > setting.edit.drag.borderMin), + isTreeInner = dTop > setting.edit.drag.borderMin && dBottom > setting.edit.drag.borderMin && dLeft > setting.edit.drag.borderMin && dRight > setting.edit.drag.borderMin, + isTreeTop = (isTop && targetSetting.treeObj.scrollTop() <= 0), + isTreeBottom = (isBottom && (targetSetting.treeObj.scrollTop() + targetSetting.treeObj.height() + 10) >= scrollHeight), + isTreeLeft = (isLeft && targetSetting.treeObj.scrollLeft() <= 0), + isTreeRight = (isRight && (targetSetting.treeObj.scrollLeft() + targetSetting.treeObj.width() + 10) >= scrollWidth); + + if (event.target && tools.isChildOrSelf(event.target, targetSetting.treeId)) { + //get node
    • dom + var targetObj = event.target; + while (targetObj && targetObj.tagName && !tools.eqs(targetObj.tagName, "li") && targetObj.id != targetSetting.treeId) { + targetObj = targetObj.parentNode; + } + + var canMove = true; + //don't move to self or children of self + for (i = 0, l = nodes.length; i < l; i++) { + tmpNode = nodes[i]; + if (targetObj.id === tmpNode.tId) { + canMove = false; + break; + } else if ($$(tmpNode, setting).find("#" + targetObj.id).length > 0) { + canMove = false; + break; + } + } + if (canMove && event.target && tools.isChildOrSelf(event.target, targetObj.id + consts.id.A)) { + tmpTarget = $(targetObj); + tmpTargetNodeId = targetObj.id; + } + } + + //the mouse must be in zTree + tmpNode = nodes[0]; + if (isTreeInner && tools.isChildOrSelf(event.target, targetSetting.treeId)) { + //judge mouse move in root of ztree + if (!tmpTarget && (event.target.id == targetSetting.treeId || isTreeTop || isTreeBottom || isTreeLeft || isTreeRight) && (isOtherTree || (!isOtherTree && tmpNode.parentTId))) { + tmpTarget = targetSetting.treeObj; + } + //auto scroll top + if (isTop) { + targetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop() - 10); + } else if (isBottom) { + targetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop() + 10); + } + if (isLeft) { + targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft() - 10); + } else if (isRight) { + targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft() + 10); + } + //auto scroll left + if (tmpTarget && tmpTarget != targetSetting.treeObj && tmpTarget.offset().left < targetSetting.treeObj.offset().left) { + targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft() + tmpTarget.offset().left - targetSetting.treeObj.offset().left); + } + } + + curNode.css({ + "top": (event.clientY + docScrollTop + 3) + "px", + "left": (event.clientX + docScrollLeft + 3) + "px" + }); + + var dX = 0; + var dY = 0; + if (tmpTarget && tmpTarget.attr("id") != targetSetting.treeId) { + var tmpTargetNode = tmpTargetNodeId == null ? null : data.getNodeCache(targetSetting, tmpTargetNodeId), + isCopy = ((event.ctrlKey || event.metaKey) && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy), + isPrev = !!(preNode && tmpTargetNodeId === preNode.tId), + isNext = !!(nextNode && tmpTargetNodeId === nextNode.tId), + isInner = (tmpNode.parentTId && tmpNode.parentTId == tmpTargetNodeId), + canPrev = (isCopy || !isNext) && tools.apply(targetSetting.edit.drag.prev, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.prev), + canNext = (isCopy || !isPrev) && tools.apply(targetSetting.edit.drag.next, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.next), + canInner = (isCopy || !isInner) && !(targetSetting.data.keep.leaf && !data.nodeIsParent(setting, tmpTargetNode)) && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.inner); + + function clearMove() { + tmpTarget = null; + tmpTargetNodeId = ""; + moveType = consts.move.TYPE_INNER; + tmpArrow.css({ + "display": "none" + }); + if (window.zTreeMoveTimer) { + clearTimeout(window.zTreeMoveTimer); + window.zTreeMoveTargetNodeTId = null + } + } + + if (!canPrev && !canNext && !canInner) { + clearMove(); + } else { + var tmpTargetA = $("#" + tmpTargetNodeId + consts.id.A, tmpTarget), + tmpNextA = tmpTargetNode.isLastNode ? null : $("#" + tmpTargetNode.getNextNode().tId + consts.id.A, tmpTarget.next()), + tmpTop = tmpTargetA.offset().top, + tmpLeft = tmpTargetA.offset().left, + prevPercent = canPrev ? (canInner ? 0.25 : (canNext ? 0.5 : 1)) : -1, + nextPercent = canNext ? (canInner ? 0.75 : (canPrev ? 0.5 : 0)) : -1, + dY_percent = (event.clientY + docScrollTop - tmpTop) / tmpTargetA.height(); + + if ((prevPercent == 1 || dY_percent <= prevPercent && dY_percent >= -.2) && canPrev) { + dX = 1 - tmpArrow.width(); + dY = tmpTop - tmpArrow.height() / 2; + moveType = consts.move.TYPE_PREV; + } else if ((nextPercent == 0 || dY_percent >= nextPercent && dY_percent <= 1.2) && canNext) { + dX = 1 - tmpArrow.width(); + dY = (tmpNextA == null || (data.nodeIsParent(setting, tmpTargetNode) && tmpTargetNode.open)) ? (tmpTop + tmpTargetA.height() - tmpArrow.height() / 2) : (tmpNextA.offset().top - tmpArrow.height() / 2); + moveType = consts.move.TYPE_NEXT; + } else if (canInner) { + dX = 5 - tmpArrow.width(); + dY = tmpTop; + moveType = consts.move.TYPE_INNER; + } else { + clearMove(); + } + + if (tmpTarget) { + tmpArrow.css({ + "display": "block", + "top": dY + "px", + "left": (tmpLeft + dX) + "px" + }); + tmpTargetA.addClass(consts.node.TMPTARGET_NODE + "_" + moveType); + + if (preTmpTargetNodeId != tmpTargetNodeId || preTmpMoveType != moveType) { + startTime = (new Date()).getTime(); + } + if (tmpTargetNode && data.nodeIsParent(setting, tmpTargetNode) && moveType == consts.move.TYPE_INNER) { + var startTimer = true; + if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId !== tmpTargetNode.tId) { + clearTimeout(window.zTreeMoveTimer); + window.zTreeMoveTargetNodeTId = null; + } else if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId === tmpTargetNode.tId) { + startTimer = false; + } + if (startTimer) { + window.zTreeMoveTimer = setTimeout(function () { + if (moveType != consts.move.TYPE_INNER) return; + if (tmpTargetNode && data.nodeIsParent(setting, tmpTargetNode) && !tmpTargetNode.open && (new Date()).getTime() - startTime > targetSetting.edit.drag.autoOpenTime + && tools.apply(targetSetting.callback.beforeDragOpen, [targetSetting.treeId, tmpTargetNode], true)) { + view.switchNode(targetSetting, tmpTargetNode); + if (targetSetting.edit.drag.autoExpandTrigger) { + targetSetting.treeObj.trigger(consts.event.EXPAND, [targetSetting.treeId, tmpTargetNode]); + } + } + }, targetSetting.edit.drag.autoOpenTime + 50); + window.zTreeMoveTargetNodeTId = tmpTargetNode.tId; + } + } + } + } + } else { + moveType = consts.move.TYPE_INNER; + if (tmpTarget && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, null], !!targetSetting.edit.drag.inner)) { + tmpTarget.addClass(consts.node.TMPTARGET_TREE); + } else { + tmpTarget = null; + } + tmpArrow.css({ + "display": "none" + }); + if (window.zTreeMoveTimer) { + clearTimeout(window.zTreeMoveTimer); + window.zTreeMoveTargetNodeTId = null; + } + } + preTmpTargetNodeId = tmpTargetNodeId; + preTmpMoveType = moveType; + + setting.treeObj.trigger(consts.event.DRAGMOVE, [event, setting.treeId, nodes]); + } + return false; + } + + doc.bind("mouseup", _docMouseUp); + + function _docMouseUp(event) { + if (window.zTreeMoveTimer) { + clearTimeout(window.zTreeMoveTimer); + window.zTreeMoveTargetNodeTId = null; + } + preTmpTargetNodeId = null; + preTmpMoveType = null; + doc.unbind("mousemove", _docMouseMove); + doc.unbind("mouseup", _docMouseUp); + doc.unbind("selectstart", _docSelect); + body.css("cursor", ""); + if (tmpTarget) { + tmpTarget.removeClass(consts.node.TMPTARGET_TREE); + if (tmpTargetNodeId) $("#" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + "_" + consts.move.TYPE_PREV) + .removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_INNER); + } + tools.showIfameMask(setting, false); + + roots.showHoverDom = true; + if (root.dragFlag == 0) return; + root.dragFlag = 0; + + var i, l, tmpNode; + for (i = 0, l = nodes.length; i < l; i++) { + tmpNode = nodes[i]; + if (data.nodeIsParent(setting, tmpNode) && root.dragNodeShowBefore[tmpNode.tId] && !tmpNode.open) { + view.expandCollapseNode(setting, tmpNode, !tmpNode.open); + delete root.dragNodeShowBefore[tmpNode.tId]; + } + } + + if (curNode) curNode.remove(); + if (tmpArrow) tmpArrow.remove(); + + var isCopy = ((event.ctrlKey || event.metaKey) && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy); + if (!isCopy && tmpTarget && tmpTargetNodeId && nodes[0].parentTId && tmpTargetNodeId == nodes[0].parentTId && moveType == consts.move.TYPE_INNER) { + tmpTarget = null; + } + if (tmpTarget) { + var dragTargetNode = tmpTargetNodeId == null ? null : data.getNodeCache(targetSetting, tmpTargetNodeId); + if (tools.apply(setting.callback.beforeDrop, [targetSetting.treeId, nodes, dragTargetNode, moveType, isCopy], true) == false) { + view.selectNodes(sourceSetting, nodes); + return; + } + var newNodes = isCopy ? tools.clone(nodes) : nodes; + + function dropCallback() { + if (isOtherTree) { + if (!isCopy) { + for (var i = 0, l = nodes.length; i < l; i++) { + view.removeNode(setting, nodes[i]); + } + } + if (moveType == consts.move.TYPE_INNER) { + view.addNodes(targetSetting, dragTargetNode, -1, newNodes); + } else { + view.addNodes(targetSetting, dragTargetNode.getParentNode(), moveType == consts.move.TYPE_PREV ? dragTargetNode.getIndex() : dragTargetNode.getIndex() + 1, newNodes); + } + } else { + if (isCopy && moveType == consts.move.TYPE_INNER) { + view.addNodes(targetSetting, dragTargetNode, -1, newNodes); + } else if (isCopy) { + view.addNodes(targetSetting, dragTargetNode.getParentNode(), moveType == consts.move.TYPE_PREV ? dragTargetNode.getIndex() : dragTargetNode.getIndex() + 1, newNodes); + } else { + if (moveType != consts.move.TYPE_NEXT) { + for (i = 0, l = newNodes.length; i < l; i++) { + view.moveNode(targetSetting, dragTargetNode, newNodes[i], moveType, false); + } + } else { + for (i = -1, l = newNodes.length - 1; i < l; l--) { + view.moveNode(targetSetting, dragTargetNode, newNodes[l], moveType, false); + } + } + } + } + view.selectNodes(targetSetting, newNodes); + + var a = $$(newNodes[0], setting).get(0); + view.scrollIntoView(setting, a); + + setting.treeObj.trigger(consts.event.DROP, [event, targetSetting.treeId, newNodes, dragTargetNode, moveType, isCopy]); + } + + if (moveType == consts.move.TYPE_INNER && tools.canAsync(targetSetting, dragTargetNode)) { + view.asyncNode(targetSetting, dragTargetNode, false, dropCallback); + } else { + dropCallback(); + } + + } else { + view.selectNodes(sourceSetting, nodes); + setting.treeObj.trigger(consts.event.DROP, [event, setting.treeId, nodes, null, null, null]); + } + } + + doc.bind("selectstart", _docSelect); + + function _docSelect() { + return false; + } + + // 2018-03-30 FireFox has fixed this issue. + //Avoid FireFox's Bug + //If zTree Div CSS set 'overflow', so drag node outside of zTree, and event.target is error. + // if(eventMouseDown.preventDefault) { + // eventMouseDown.preventDefault(); + // } + return true; + } + }, + //method of tools for zTree + _tools = { + getAbs: function (obj) { + var oRect = obj.getBoundingClientRect(), + scrollTop = document.body.scrollTop + document.documentElement.scrollTop, + scrollLeft = document.body.scrollLeft + document.documentElement.scrollLeft; + return [oRect.left + scrollLeft, oRect.top + scrollTop]; + }, + inputFocus: function (inputObj) { + if (inputObj.get(0)) { + inputObj.focus(); + tools.setCursorPosition(inputObj.get(0), inputObj.val().length); + } + }, + inputSelect: function (inputObj) { + if (inputObj.get(0)) { + inputObj.focus(); + inputObj.select(); + } + }, + setCursorPosition: function (obj, pos) { + if (obj.setSelectionRange) { + obj.focus(); + obj.setSelectionRange(pos, pos); + } else if (obj.createTextRange) { + var range = obj.createTextRange(); + range.collapse(true); + range.moveEnd('character', pos); + range.moveStart('character', pos); + range.select(); + } + }, + showIfameMask: function (setting, showSign) { + var root = data.getRoot(setting); + //clear full mask + while (root.dragMaskList.length > 0) { + root.dragMaskList[0].remove(); + root.dragMaskList.shift(); + } + if (showSign) { + //show mask + var iframeList = $$("iframe", setting); + for (var i = 0, l = iframeList.length; i < l; i++) { + var obj = iframeList.get(i), + r = tools.getAbs(obj), + dragMask = $$("
      ", setting); + dragMask.appendTo($$("body", setting)); + root.dragMaskList.push(dragMask); + } + } + } + }, + //method of operate ztree dom + _view = { + addEditBtn: function (setting, node) { + if (node.editNameFlag || $$(node, consts.id.EDIT, setting).length > 0) { + return; + } + if (!tools.apply(setting.edit.showRenameBtn, [setting.treeId, node], setting.edit.showRenameBtn)) { + return; + } + var aObj = $$(node, consts.id.A, setting), + editStr = ""; + aObj.append(editStr); + + $$(node, consts.id.EDIT, setting).bind('click', + function () { + if (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeEditName, [setting.treeId, node], true) == false) return false; + view.editNode(setting, node); + return false; + } + ).show(); + }, + addRemoveBtn: function (setting, node) { + if (node.editNameFlag || $$(node, consts.id.REMOVE, setting).length > 0) { + return; + } + if (!tools.apply(setting.edit.showRemoveBtn, [setting.treeId, node], setting.edit.showRemoveBtn)) { + return; + } + var aObj = $$(node, consts.id.A, setting), + removeStr = ""; + aObj.append(removeStr); + + $$(node, consts.id.REMOVE, setting).bind('click', + function () { + if (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return false; + view.removeNode(setting, node); + setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]); + return false; + } + ).bind('mousedown', + function (eventMouseDown) { + return true; + } + ).show(); + }, + addHoverDom: function (setting, node) { + if (data.getRoots().showHoverDom) { + node.isHover = true; + if (setting.edit.enable) { + view.addEditBtn(setting, node); + view.addRemoveBtn(setting, node); + } + tools.apply(setting.view.addHoverDom, [setting.treeId, node]); + } + }, + cancelCurEditNode: function (setting, forceName, isCancel) { + var root = data.getRoot(setting), + node = root.curEditNode; + + if (node) { + var inputObj = root.curEditInput, + newName = forceName ? forceName : (isCancel ? data.nodeName(setting, node) : inputObj.val()); + if (tools.apply(setting.callback.beforeRename, [setting.treeId, node, newName, isCancel], true) === false) { + return false; + } + data.nodeName(setting, node, newName); + var aObj = $$(node, consts.id.A, setting); + aObj.removeClass(consts.node.CURSELECTED_EDIT); + inputObj.unbind(); + view.setNodeName(setting, node); + node.editNameFlag = false; + root.curEditNode = null; + root.curEditInput = null; + view.selectNode(setting, node, false); + setting.treeObj.trigger(consts.event.RENAME, [setting.treeId, node, isCancel]); + } + root.noSelection = true; + return true; + }, + editNode: function (setting, node) { + var root = data.getRoot(setting); + view.editNodeBlur = false; + if (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) { + setTimeout(function () { + tools.inputFocus(root.curEditInput); + }, 0); + return; + } + node.editNameFlag = true; + view.removeTreeDom(setting, node); + view.cancelCurEditNode(setting); + view.selectNode(setting, node, false); + $$(node, consts.id.SPAN, setting).html(""); + var inputObj = $$(node, consts.id.INPUT, setting); + inputObj.attr("value", data.nodeName(setting, node)); + if (setting.edit.editNameSelectAll) { + tools.inputSelect(inputObj); + } else { + tools.inputFocus(inputObj); + } + + inputObj.bind('blur', function (event) { + if (!view.editNodeBlur) { + view.cancelCurEditNode(setting); + } + }).bind('keydown', function (event) { + if (event.keyCode == "13") { + view.editNodeBlur = true; + view.cancelCurEditNode(setting); + } else if (event.keyCode == "27") { + view.cancelCurEditNode(setting, null, true); + } + }).bind('click', function (event) { + return false; + }).bind('dblclick', function (event) { + return false; + }); + + $$(node, consts.id.A, setting).addClass(consts.node.CURSELECTED_EDIT); + root.curEditInput = inputObj; + root.noSelection = false; + root.curEditNode = node; + }, + moveNode: function (setting, targetNode, node, moveType, animateFlag, isSilent) { + var root = data.getRoot(setting); + if (targetNode == node) return; + if (setting.data.keep.leaf && targetNode && !data.nodeIsParent(setting, targetNode) && moveType == consts.move.TYPE_INNER) return; + var oldParentNode = (node.parentTId ? node.getParentNode() : root), + targetNodeIsRoot = (targetNode === null || targetNode == root); + if (targetNodeIsRoot && targetNode === null) targetNode = root; + if (targetNodeIsRoot) moveType = consts.move.TYPE_INNER; + var targetParentNode = (targetNode.parentTId ? targetNode.getParentNode() : root); + + if (moveType != consts.move.TYPE_PREV && moveType != consts.move.TYPE_NEXT) { + moveType = consts.move.TYPE_INNER; + } + + if (moveType == consts.move.TYPE_INNER) { + if (targetNodeIsRoot) { + //parentTId of root node is null + node.parentTId = null; + } else { + if (!data.nodeIsParent(setting, targetNode)) { + data.nodeIsParent(setting, targetNode, true); + targetNode.open = !!targetNode.open; + view.setNodeLineIcos(setting, targetNode); + } + node.parentTId = targetNode.tId; + } + } + + //move node Dom + var targetObj, target_ulObj; + if (targetNodeIsRoot) { + targetObj = setting.treeObj; + target_ulObj = targetObj; + } else { + if (!isSilent && moveType == consts.move.TYPE_INNER) { + view.expandCollapseNode(setting, targetNode, true, false); + } else if (!isSilent) { + view.expandCollapseNode(setting, targetNode.getParentNode(), true, false); + } + targetObj = $$(targetNode, setting); + target_ulObj = $$(targetNode, consts.id.UL, setting); + if (!!targetObj.get(0) && !target_ulObj.get(0)) { + var ulstr = []; + view.makeUlHtml(setting, targetNode, ulstr, ''); + targetObj.append(ulstr.join('')); + } + target_ulObj = $$(targetNode, consts.id.UL, setting); + } + var nodeDom = $$(node, setting); + if (!nodeDom.get(0)) { + nodeDom = view.appendNodes(setting, node.level, [node], null, -1, false, true).join(''); + } else if (!targetObj.get(0)) { + nodeDom.remove(); + } + if (target_ulObj.get(0) && moveType == consts.move.TYPE_INNER) { + target_ulObj.append(nodeDom); + } else if (targetObj.get(0) && moveType == consts.move.TYPE_PREV) { + targetObj.before(nodeDom); + } else if (targetObj.get(0) && moveType == consts.move.TYPE_NEXT) { + targetObj.after(nodeDom); + } + + //repair the data after move + var i, l, + tmpSrcIndex = -1, + tmpTargetIndex = 0, + oldNeighbor = null, + newNeighbor = null, + oldLevel = node.level; + var oldChildren = data.nodeChildren(setting, oldParentNode); + var targetParentChildren = data.nodeChildren(setting, targetParentNode); + var targetChildren = data.nodeChildren(setting, targetNode); + if (node.isFirstNode) { + tmpSrcIndex = 0; + if (oldChildren.length > 1) { + oldNeighbor = oldChildren[1]; + oldNeighbor.isFirstNode = true; + } + } else if (node.isLastNode) { + tmpSrcIndex = oldChildren.length - 1; + oldNeighbor = oldChildren[tmpSrcIndex - 1]; + oldNeighbor.isLastNode = true; + } else { + for (i = 0, l = oldChildren.length; i < l; i++) { + if (oldChildren[i].tId == node.tId) { + tmpSrcIndex = i; + break; + } + } + } + if (tmpSrcIndex >= 0) { + oldChildren.splice(tmpSrcIndex, 1); + } + if (moveType != consts.move.TYPE_INNER) { + for (i = 0, l = targetParentChildren.length; i < l; i++) { + if (targetParentChildren[i].tId == targetNode.tId) tmpTargetIndex = i; + } + } + if (moveType == consts.move.TYPE_INNER) { + if (!targetChildren) { + targetChildren = data.nodeChildren(setting, targetNode, []); + } + if (targetChildren.length > 0) { + newNeighbor = targetChildren[targetChildren.length - 1]; + newNeighbor.isLastNode = false; + } + targetChildren.splice(targetChildren.length, 0, node); + node.isLastNode = true; + node.isFirstNode = (targetChildren.length == 1); + } else if (targetNode.isFirstNode && moveType == consts.move.TYPE_PREV) { + targetParentChildren.splice(tmpTargetIndex, 0, node); + newNeighbor = targetNode; + newNeighbor.isFirstNode = false; + node.parentTId = targetNode.parentTId; + node.isFirstNode = true; + node.isLastNode = false; + + } else if (targetNode.isLastNode && moveType == consts.move.TYPE_NEXT) { + targetParentChildren.splice(tmpTargetIndex + 1, 0, node); + newNeighbor = targetNode; + newNeighbor.isLastNode = false; + node.parentTId = targetNode.parentTId; + node.isFirstNode = false; + node.isLastNode = true; + + } else { + if (moveType == consts.move.TYPE_PREV) { + targetParentChildren.splice(tmpTargetIndex, 0, node); + } else { + targetParentChildren.splice(tmpTargetIndex + 1, 0, node); + } + node.parentTId = targetNode.parentTId; + node.isFirstNode = false; + node.isLastNode = false; + } + data.fixPIdKeyValue(setting, node); + data.setSonNodeLevel(setting, node.getParentNode(), node); + + //repair node what been moved + view.setNodeLineIcos(setting, node); + view.repairNodeLevelClass(setting, node, oldLevel); + + //repair node's old parentNode dom + if (!setting.data.keep.parent && oldChildren.length < 1) { + //old parentNode has no child nodes + data.nodeIsParent(setting, oldParentNode, false); + oldParentNode.open = false; + var tmp_ulObj = $$(oldParentNode, consts.id.UL, setting), + tmp_switchObj = $$(oldParentNode, consts.id.SWITCH, setting), + tmp_icoObj = $$(oldParentNode, consts.id.ICON, setting); + view.replaceSwitchClass(oldParentNode, tmp_switchObj, consts.folder.DOCU); + view.replaceIcoClass(oldParentNode, tmp_icoObj, consts.folder.DOCU); + tmp_ulObj.css("display", "none"); + + } else if (oldNeighbor) { + //old neighbor node + view.setNodeLineIcos(setting, oldNeighbor); + } + + //new neighbor node + if (newNeighbor) { + view.setNodeLineIcos(setting, newNeighbor); + } + + //repair checkbox / radio + if (!!setting.check && setting.check.enable && view.repairChkClass) { + view.repairChkClass(setting, oldParentNode); + view.repairParentChkClassWithSelf(setting, oldParentNode); + if (oldParentNode != node.parent) + view.repairParentChkClassWithSelf(setting, node); + } + + //expand parents after move + if (!isSilent) { + view.expandCollapseParentNode(setting, node.getParentNode(), true, animateFlag); + } + }, + removeEditBtn: function (setting, node) { + $$(node, consts.id.EDIT, setting).unbind().remove(); + }, + removeRemoveBtn: function (setting, node) { + $$(node, consts.id.REMOVE, setting).unbind().remove(); + }, + removeTreeDom: function (setting, node) { + node.isHover = false; + view.removeEditBtn(setting, node); + view.removeRemoveBtn(setting, node); + tools.apply(setting.view.removeHoverDom, [setting.treeId, node]); + }, + repairNodeLevelClass: function (setting, node, oldLevel) { + if (oldLevel === node.level) return; + var liObj = $$(node, setting), + aObj = $$(node, consts.id.A, setting), + ulObj = $$(node, consts.id.UL, setting), + oldClass = consts.className.LEVEL + oldLevel, + newClass = consts.className.LEVEL + node.level; + liObj.removeClass(oldClass); + liObj.addClass(newClass); + aObj.removeClass(oldClass); + aObj.addClass(newClass); + ulObj.removeClass(oldClass); + ulObj.addClass(newClass); + }, + selectNodes: function (setting, nodes) { + for (var i = 0, l = nodes.length; i < l; i++) { + view.selectNode(setting, nodes[i], i > 0); + } + } + }, + + _z = { + tools: _tools, + view: _view, + event: _event, + data: _data + }; + $.extend(true, $.fn.zTree.consts, _consts); + $.extend(true, $.fn.zTree._z, _z); + + var zt = $.fn.zTree, + tools = zt._z.tools, + consts = zt.consts, + view = zt._z.view, + data = zt._z.data, + event = zt._z.event, + $$ = tools.$; + + data.exSetting(_setting); + data.addInitBind(_bindEvent); + data.addInitUnBind(_unbindEvent); + data.addInitCache(_initCache); + data.addInitNode(_initNode); + data.addInitProxy(_eventProxy); + data.addInitRoot(_initRoot); + data.addZTreeTools(_zTreeTools); + + var _cancelPreSelectedNode = view.cancelPreSelectedNode; + view.cancelPreSelectedNode = function (setting, node) { + var list = data.getRoot(setting).curSelectedList; + for (var i = 0, j = list.length; i < j; i++) { + if (!node || node === list[i]) { + view.removeTreeDom(setting, list[i]); + if (node) break; + } + } + if (_cancelPreSelectedNode) _cancelPreSelectedNode.apply(view, arguments); + } + + var _createNodes = view.createNodes; + view.createNodes = function (setting, level, nodes, parentNode, index) { + if (_createNodes) { + _createNodes.apply(view, arguments); + } + if (!nodes) return; + if (view.repairParentChkClassWithSelf) { + view.repairParentChkClassWithSelf(setting, parentNode); + } + } + + var _makeNodeUrl = view.makeNodeUrl; + view.makeNodeUrl = function (setting, node) { + return setting.edit.enable ? null : (_makeNodeUrl.apply(view, arguments)); + } + + var _removeNode = view.removeNode; + view.removeNode = function (setting, node) { + var root = data.getRoot(setting); + if (root.curEditNode === node) root.curEditNode = null; + if (_removeNode) { + _removeNode.apply(view, arguments); + } + } + + var _selectNode = view.selectNode; + view.selectNode = function (setting, node, addFlag) { + var root = data.getRoot(setting); + if (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) { + return false; + } + if (_selectNode) _selectNode.apply(view, arguments); + view.addHoverDom(setting, node); + return true; + } + + var _uCanDo = tools.uCanDo; + tools.uCanDo = function (setting, e) { + var root = data.getRoot(setting); + if (e && (tools.eqs(e.type, "mouseover") || tools.eqs(e.type, "mouseout") || tools.eqs(e.type, "mousedown") || tools.eqs(e.type, "mouseup"))) { + return true; + } + if (root.curEditNode) { + view.editNodeBlur = false; + root.curEditInput.focus(); + } + return (!root.curEditNode) && (_uCanDo ? _uCanDo.apply(view, arguments) : true); + } +})(jQuery); \ No newline at end of file diff --git a/public/self/ztree/js/jquery.ztree.core.js b/public/self/ztree/js/jquery.ztree.core.js new file mode 100644 index 000000000..9226f19d6 --- /dev/null +++ b/public/self/ztree/js/jquery.ztree.core.js @@ -0,0 +1,2019 @@ +/* + * JQuery zTree core + * v3.5.48 + * http://treejs.cn/ + * + * Copyright (c) 2010 Hunter.z + * + * Licensed same as jquery - MIT License + * http://www.opensource.org/licenses/mit-license.php + * + * Date: 2020-11-21 + */ + +(function ($) { + var settings = {}, roots = {}, caches = {}, + //default consts of core + _consts = { + className: { + BUTTON: "button", + LEVEL: "level", + ICO_LOADING: "ico_loading", + SWITCH: "switch", + NAME: 'node_name' + }, + event: { + NODECREATED: "ztree_nodeCreated", + CLICK: "ztree_click", + EXPAND: "ztree_expand", + COLLAPSE: "ztree_collapse", + ASYNC_SUCCESS: "ztree_async_success", + ASYNC_ERROR: "ztree_async_error", + REMOVE: "ztree_remove", + SELECTED: "ztree_selected", + UNSELECTED: "ztree_unselected" + }, + id: { + A: "_a", + ICON: "_ico", + SPAN: "_span", + SWITCH: "_switch", + UL: "_ul" + }, + line: { + ROOT: "root", + ROOTS: "roots", + CENTER: "center", + BOTTOM: "bottom", + NOLINE: "noline", + LINE: "line" + }, + folder: { + OPEN: "open", + CLOSE: "close", + DOCU: "docu" + }, + node: { + CURSELECTED: "curSelectedNode" + } + }, + //default setting of core + _setting = { + treeId: "", + treeObj: null, + view: { + addDiyDom: null, + autoCancelSelected: true, + dblClickExpand: true, + expandSpeed: "fast", + fontCss: {}, + nodeClasses: {}, + nameIsHTML: false, + selectedMulti: true, + showIcon: true, + showLine: true, + showTitle: true, + txtSelectedEnable: false + }, + data: { + key: { + isParent: "isParent", + children: "children", + name: "name", + title: "", + url: "url", + icon: "icon" + }, + render: { + name: null, + title: null, + }, + simpleData: { + enable: false, + idKey: "id", + pIdKey: "pId", + rootPId: null + }, + keep: { + parent: false, + leaf: false + } + }, + async: { + enable: false, + contentType: "application/x-www-form-urlencoded", + type: "post", + dataType: "text", + headers: {}, + xhrFields: {}, + url: "", + autoParam: [], + otherParam: [], + dataFilter: null + }, + callback: { + beforeAsync: null, + beforeClick: null, + beforeDblClick: null, + beforeRightClick: null, + beforeMouseDown: null, + beforeMouseUp: null, + beforeExpand: null, + beforeCollapse: null, + beforeRemove: null, + + onAsyncError: null, + onAsyncSuccess: null, + onNodeCreated: null, + onClick: null, + onDblClick: null, + onRightClick: null, + onMouseDown: null, + onMouseUp: null, + onExpand: null, + onCollapse: null, + onRemove: null + } + }, + //default root of core + //zTree use root to save full data + _initRoot = function (setting) { + var r = data.getRoot(setting); + if (!r) { + r = {}; + data.setRoot(setting, r); + } + data.nodeChildren(setting, r, []); + r.expandTriggerFlag = false; + r.curSelectedList = []; + r.noSelection = true; + r.createdNodes = []; + r.zId = 0; + r._ver = (new Date()).getTime(); + }, + //default cache of core + _initCache = function (setting) { + var c = data.getCache(setting); + if (!c) { + c = {}; + data.setCache(setting, c); + } + c.nodes = []; + c.doms = []; + }, + //default bindEvent of core + _bindEvent = function (setting) { + var o = setting.treeObj, + c = consts.event; + o.bind(c.NODECREATED, function (event, treeId, node) { + tools.apply(setting.callback.onNodeCreated, [event, treeId, node]); + }); + + o.bind(c.CLICK, function (event, srcEvent, treeId, node, clickFlag) { + tools.apply(setting.callback.onClick, [srcEvent, treeId, node, clickFlag]); + }); + + o.bind(c.EXPAND, function (event, treeId, node) { + tools.apply(setting.callback.onExpand, [event, treeId, node]); + }); + + o.bind(c.COLLAPSE, function (event, treeId, node) { + tools.apply(setting.callback.onCollapse, [event, treeId, node]); + }); + + o.bind(c.ASYNC_SUCCESS, function (event, treeId, node, msg) { + tools.apply(setting.callback.onAsyncSuccess, [event, treeId, node, msg]); + }); + + o.bind(c.ASYNC_ERROR, function (event, treeId, node, XMLHttpRequest, textStatus, errorThrown) { + tools.apply(setting.callback.onAsyncError, [event, treeId, node, XMLHttpRequest, textStatus, errorThrown]); + }); + + o.bind(c.REMOVE, function (event, treeId, treeNode) { + tools.apply(setting.callback.onRemove, [event, treeId, treeNode]); + }); + + o.bind(c.SELECTED, function (event, treeId, node) { + tools.apply(setting.callback.onSelected, [treeId, node]); + }); + o.bind(c.UNSELECTED, function (event, treeId, node) { + tools.apply(setting.callback.onUnSelected, [treeId, node]); + }); + }, + _unbindEvent = function (setting) { + var o = setting.treeObj, + c = consts.event; + o.unbind(c.NODECREATED) + .unbind(c.CLICK) + .unbind(c.EXPAND) + .unbind(c.COLLAPSE) + .unbind(c.ASYNC_SUCCESS) + .unbind(c.ASYNC_ERROR) + .unbind(c.REMOVE) + .unbind(c.SELECTED) + .unbind(c.UNSELECTED); + }, + //default event proxy of core + _eventProxy = function (event) { + var target = event.target, + setting = data.getSetting(event.data.treeId), + tId = "", node = null, + nodeEventType = "", treeEventType = "", + nodeEventCallback = null, treeEventCallback = null, + tmp = null; + + if (tools.eqs(event.type, "mousedown")) { + treeEventType = "mousedown"; + } else if (tools.eqs(event.type, "mouseup")) { + treeEventType = "mouseup"; + } else if (tools.eqs(event.type, "contextmenu")) { + treeEventType = "contextmenu"; + } else if (tools.eqs(event.type, "click")) { + if (tools.eqs(target.tagName, "span") && target.getAttribute("treeNode" + consts.id.SWITCH) !== null) { + tId = tools.getNodeMainDom(target).id; + nodeEventType = "switchNode"; + } else { + tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]); + if (tmp) { + tId = tools.getNodeMainDom(tmp).id; + nodeEventType = "clickNode"; + } + } + } else if (tools.eqs(event.type, "dblclick")) { + treeEventType = "dblclick"; + tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]); + if (tmp) { + tId = tools.getNodeMainDom(tmp).id; + nodeEventType = "switchNode"; + } + } + if (treeEventType.length > 0 && tId.length == 0) { + tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]); + if (tmp) { + tId = tools.getNodeMainDom(tmp).id; + } + } + // event to node + if (tId.length > 0) { + node = data.getNodeCache(setting, tId); + switch (nodeEventType) { + case "switchNode" : + var isParent = data.nodeIsParent(setting, node); + if (!isParent) { + nodeEventType = ""; + } else if (tools.eqs(event.type, "click") + || (tools.eqs(event.type, "dblclick") && tools.apply(setting.view.dblClickExpand, [setting.treeId, node], setting.view.dblClickExpand))) { + nodeEventCallback = handler.onSwitchNode; + } else { + nodeEventType = ""; + } + break; + case "clickNode" : + nodeEventCallback = handler.onClickNode; + break; + } + } + // event to zTree + switch (treeEventType) { + case "mousedown" : + treeEventCallback = handler.onZTreeMousedown; + break; + case "mouseup" : + treeEventCallback = handler.onZTreeMouseup; + break; + case "dblclick" : + treeEventCallback = handler.onZTreeDblclick; + break; + case "contextmenu" : + treeEventCallback = handler.onZTreeContextmenu; + break; + } + var proxyResult = { + stop: false, + node: node, + nodeEventType: nodeEventType, + nodeEventCallback: nodeEventCallback, + treeEventType: treeEventType, + treeEventCallback: treeEventCallback + }; + return proxyResult + }, + //default init node of core + _initNode = function (setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) { + if (!n) return; + var r = data.getRoot(setting), + children = data.nodeChildren(setting, n); + n.level = level; + n.tId = setting.treeId + "_" + (++r.zId); + n.parentTId = parentNode ? parentNode.tId : null; + n.open = (typeof n.open == "string") ? tools.eqs(n.open, "true") : !!n.open; + var isParent = data.nodeIsParent(setting, n); + if (tools.isArray(children)) { + data.nodeIsParent(setting, n, true); + n.zAsync = true; + } else { + isParent = data.nodeIsParent(setting, n, isParent); + n.open = (isParent && !setting.async.enable) ? n.open : false; + n.zAsync = !isParent; + } + n.isFirstNode = isFirstNode; + n.isLastNode = isLastNode; + n.getParentNode = function () { + return data.getNodeCache(setting, n.parentTId); + }; + n.getPreNode = function () { + return data.getPreNode(setting, n); + }; + n.getNextNode = function () { + return data.getNextNode(setting, n); + }; + n.getIndex = function () { + return data.getNodeIndex(setting, n); + }; + n.getPath = function () { + return data.getNodePath(setting, n); + }; + n.isAjaxing = false; + data.fixPIdKeyValue(setting, n); + }, + _init = { + bind: [_bindEvent], + unbind: [_unbindEvent], + caches: [_initCache], + nodes: [_initNode], + proxys: [_eventProxy], + roots: [_initRoot], + beforeA: [], + afterA: [], + innerBeforeA: [], + innerAfterA: [], + zTreeTools: [] + }, + //method of operate data + data = { + addNodeCache: function (setting, node) { + data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = node; + }, + getNodeCacheId: function (tId) { + return tId.substring(tId.lastIndexOf("_") + 1); + }, + addAfterA: function (afterA) { + _init.afterA.push(afterA); + }, + addBeforeA: function (beforeA) { + _init.beforeA.push(beforeA); + }, + addInnerAfterA: function (innerAfterA) { + _init.innerAfterA.push(innerAfterA); + }, + addInnerBeforeA: function (innerBeforeA) { + _init.innerBeforeA.push(innerBeforeA); + }, + addInitBind: function (bindEvent) { + _init.bind.push(bindEvent); + }, + addInitUnBind: function (unbindEvent) { + _init.unbind.push(unbindEvent); + }, + addInitCache: function (initCache) { + _init.caches.push(initCache); + }, + addInitNode: function (initNode) { + _init.nodes.push(initNode); + }, + addInitProxy: function (initProxy, isFirst) { + if (!!isFirst) { + _init.proxys.splice(0, 0, initProxy); + } else { + _init.proxys.push(initProxy); + } + }, + addInitRoot: function (initRoot) { + _init.roots.push(initRoot); + }, + addNodesData: function (setting, parentNode, index, nodes) { + var children = data.nodeChildren(setting, parentNode), params; + if (!children) { + children = data.nodeChildren(setting, parentNode, []); + index = -1; + } else if (index >= children.length) { + index = -1; + } + + if (children.length > 0 && index === 0) { + children[0].isFirstNode = false; + view.setNodeLineIcos(setting, children[0]); + } else if (children.length > 0 && index < 0) { + children[children.length - 1].isLastNode = false; + view.setNodeLineIcos(setting, children[children.length - 1]); + } + data.nodeIsParent(setting, parentNode, true); + + if (index < 0) { + data.nodeChildren(setting, parentNode, children.concat(nodes)); + } else { + params = [index, 0].concat(nodes); + children.splice.apply(children, params); + } + }, + addSelectedNode: function (setting, node) { + var root = data.getRoot(setting); + if (!data.isSelectedNode(setting, node)) { + root.curSelectedList.push(node); + } + }, + addCreatedNode: function (setting, node) { + if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) { + var root = data.getRoot(setting); + root.createdNodes.push(node); + } + }, + addZTreeTools: function (zTreeTools) { + _init.zTreeTools.push(zTreeTools); + }, + exSetting: function (s) { + $.extend(true, _setting, s); + }, + fixPIdKeyValue: function (setting, node) { + if (setting.data.simpleData.enable) { + node[setting.data.simpleData.pIdKey] = node.parentTId ? node.getParentNode()[setting.data.simpleData.idKey] : setting.data.simpleData.rootPId; + } + }, + getAfterA: function (setting, node, array) { + for (var i = 0, j = _init.afterA.length; i < j; i++) { + _init.afterA[i].apply(this, arguments); + } + }, + getBeforeA: function (setting, node, array) { + for (var i = 0, j = _init.beforeA.length; i < j; i++) { + _init.beforeA[i].apply(this, arguments); + } + }, + getInnerAfterA: function (setting, node, array) { + for (var i = 0, j = _init.innerAfterA.length; i < j; i++) { + _init.innerAfterA[i].apply(this, arguments); + } + }, + getInnerBeforeA: function (setting, node, array) { + for (var i = 0, j = _init.innerBeforeA.length; i < j; i++) { + _init.innerBeforeA[i].apply(this, arguments); + } + }, + getCache: function (setting) { + return caches[setting.treeId]; + }, + getNodeIndex: function (setting, node) { + if (!node) return null; + var p = node.parentTId ? node.getParentNode() : data.getRoot(setting), + children = data.nodeChildren(setting, p); + for (var i = 0, l = children.length - 1; i <= l; i++) { + if (children[i] === node) { + return i; + } + } + return -1; + }, + getNextNode: function (setting, node) { + if (!node) return null; + var p = node.parentTId ? node.getParentNode() : data.getRoot(setting), + children = data.nodeChildren(setting, p); + for (var i = 0, l = children.length - 1; i <= l; i++) { + if (children[i] === node) { + return (i == l ? null : children[i + 1]); + } + } + return null; + }, + getNodeByParam: function (setting, nodes, key, value) { + if (!nodes || !key) return null; + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (node[key] == value) { + return nodes[i]; + } + var children = data.nodeChildren(setting, node); + var tmp = data.getNodeByParam(setting, children, key, value); + if (tmp) return tmp; + } + return null; + }, + getNodeCache: function (setting, tId) { + if (!tId) return null; + var n = caches[setting.treeId].nodes[data.getNodeCacheId(tId)]; + return n ? n : null; + }, + getNodePath: function (setting, node) { + if (!node) return null; + + var path; + if (node.parentTId) { + path = node.getParentNode().getPath(); + } else { + path = []; + } + + if (path) { + path.push(node); + } + + return path; + }, + getNodes: function (setting) { + return data.nodeChildren(setting, data.getRoot(setting)); + }, + getNodesByParam: function (setting, nodes, key, value) { + if (!nodes || !key) return []; + var result = []; + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (node[key] == value) { + result.push(node); + } + var children = data.nodeChildren(setting, node); + result = result.concat(data.getNodesByParam(setting, children, key, value)); + } + return result; + }, + getNodesByParamFuzzy: function (setting, nodes, key, value) { + if (!nodes || !key) return []; + var result = []; + value = value.toLowerCase(); + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (typeof node[key] == "string" && nodes[i][key].toLowerCase().indexOf(value) > -1) { + result.push(node); + } + var children = data.nodeChildren(setting, node); + result = result.concat(data.getNodesByParamFuzzy(setting, children, key, value)); + } + return result; + }, + getNodesByFilter: function (setting, nodes, filter, isSingle, invokeParam) { + if (!nodes) return (isSingle ? null : []); + var result = isSingle ? null : []; + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (tools.apply(filter, [node, invokeParam], false)) { + if (isSingle) { + return node; + } + result.push(node); + } + var children = data.nodeChildren(setting, node); + var tmpResult = data.getNodesByFilter(setting, children, filter, isSingle, invokeParam); + if (isSingle && !!tmpResult) { + return tmpResult; + } + result = isSingle ? tmpResult : result.concat(tmpResult); + } + return result; + }, + getPreNode: function (setting, node) { + if (!node) return null; + var p = node.parentTId ? node.getParentNode() : data.getRoot(setting), + children = data.nodeChildren(setting, p); + for (var i = 0, l = children.length; i < l; i++) { + if (children[i] === node) { + return (i == 0 ? null : children[i - 1]); + } + } + return null; + }, + getRoot: function (setting) { + return setting ? roots[setting.treeId] : null; + }, + getRoots: function () { + return roots; + }, + getSetting: function (treeId) { + return settings[treeId]; + }, + getSettings: function () { + return settings; + }, + getZTreeTools: function (treeId) { + var r = this.getRoot(this.getSetting(treeId)); + return r ? r.treeTools : null; + }, + initCache: function (setting) { + for (var i = 0, j = _init.caches.length; i < j; i++) { + _init.caches[i].apply(this, arguments); + } + }, + initNode: function (setting, level, node, parentNode, preNode, nextNode) { + for (var i = 0, j = _init.nodes.length; i < j; i++) { + _init.nodes[i].apply(this, arguments); + } + }, + initRoot: function (setting) { + for (var i = 0, j = _init.roots.length; i < j; i++) { + _init.roots[i].apply(this, arguments); + } + }, + isSelectedNode: function (setting, node) { + var root = data.getRoot(setting); + for (var i = 0, j = root.curSelectedList.length; i < j; i++) { + if (node === root.curSelectedList[i]) return true; + } + return false; + }, + nodeChildren: function (setting, node, newChildren) { + if (!node) { + return null; + } + var key = setting.data.key.children; + if (typeof newChildren !== 'undefined') { + node[key] = newChildren; + } + return node[key]; + }, + nodeIsParent: function (setting, node, newIsParent) { + if (!node) { + return false; + } + var key = setting.data.key.isParent; + if (typeof newIsParent !== 'undefined') { + if (typeof newIsParent === "string") { + newIsParent = tools.eqs(newIsParent, "true"); + } + newIsParent = !!newIsParent; + node[key] = newIsParent; + } else if (typeof node[key] == "string"){ + node[key] = tools.eqs(node[key], "true"); + } else { + node[key] = !!node[key]; + } + return node[key]; + }, + nodeName: function (setting, node, newName) { + var key = setting.data.key.name; + if (typeof newName !== 'undefined') { + node[key] = newName; + } + var rawName = "" + node[key]; + if(typeof setting.data.render.name === 'function') { + return setting.data.render.name.call(this,rawName,node); + } + return rawName; + }, + nodeTitle: function (setting, node) { + var t = setting.data.key.title === "" ? setting.data.key.name : setting.data.key.title; + var rawTitle = "" + node[t]; + if(typeof setting.data.render.title === 'function') { + return setting.data.render.title.call(this,rawTitle,node); + } + return rawTitle; + }, + removeNodeCache: function (setting, node) { + var children = data.nodeChildren(setting, node); + if (children) { + for (var i = 0, l = children.length; i < l; i++) { + data.removeNodeCache(setting, children[i]); + } + } + data.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = null; + }, + removeSelectedNode: function (setting, node) { + var root = data.getRoot(setting); + for (var i = 0, j = root.curSelectedList.length; i < j; i++) { + if (node === root.curSelectedList[i] || !data.getNodeCache(setting, root.curSelectedList[i].tId)) { + root.curSelectedList.splice(i, 1); + setting.treeObj.trigger(consts.event.UNSELECTED, [setting.treeId, node]); + i--; + j--; + } + } + }, + setCache: function (setting, cache) { + caches[setting.treeId] = cache; + }, + setRoot: function (setting, root) { + roots[setting.treeId] = root; + }, + setZTreeTools: function (setting, zTreeTools) { + for (var i = 0, j = _init.zTreeTools.length; i < j; i++) { + _init.zTreeTools[i].apply(this, arguments); + } + }, + transformToArrayFormat: function (setting, nodes) { + if (!nodes) return []; + var r = []; + if (tools.isArray(nodes)) { + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + _do(node); + } + } else { + _do(nodes); + } + return r; + + function _do(_node) { + r.push(_node); + var children = data.nodeChildren(setting, _node); + if (children) { + r = r.concat(data.transformToArrayFormat(setting, children)); + } + } + }, + transformTozTreeFormat: function (setting, sNodes) { + var i, l, + key = setting.data.simpleData.idKey, + parentKey = setting.data.simpleData.pIdKey; + if (!key || key == "" || !sNodes) return []; + + if (tools.isArray(sNodes)) { + var r = []; + var tmpMap = {}; + for (i = 0, l = sNodes.length; i < l; i++) { + tmpMap[sNodes[i][key]] = sNodes[i]; + } + for (i = 0, l = sNodes.length; i < l; i++) { + var p = tmpMap[sNodes[i][parentKey]]; + if (p && sNodes[i][key] != sNodes[i][parentKey]) { + var children = data.nodeChildren(setting, p); + if (!children) { + children = data.nodeChildren(setting, p, []); + } + children.push(sNodes[i]); + } else { + r.push(sNodes[i]); + } + } + return r; + } else { + return [sNodes]; + } + } + }, + //method of event proxy + event = { + bindEvent: function (setting) { + for (var i = 0, j = _init.bind.length; i < j; i++) { + _init.bind[i].apply(this, arguments); + } + }, + unbindEvent: function (setting) { + for (var i = 0, j = _init.unbind.length; i < j; i++) { + _init.unbind[i].apply(this, arguments); + } + }, + bindTree: function (setting) { + var eventParam = { + treeId: setting.treeId + }, + o = setting.treeObj; + if (!setting.view.txtSelectedEnable) { + // for can't select text + o.bind('selectstart', handler.onSelectStart).css({ + "-moz-user-select": "-moz-none" + }); + } + o.bind('click', eventParam, event.proxy); + o.bind('dblclick', eventParam, event.proxy); + o.bind('mouseover', eventParam, event.proxy); + o.bind('mouseout', eventParam, event.proxy); + o.bind('mousedown', eventParam, event.proxy); + o.bind('mouseup', eventParam, event.proxy); + o.bind('contextmenu', eventParam, event.proxy); + }, + unbindTree: function (setting) { + var o = setting.treeObj; + o.unbind('selectstart', handler.onSelectStart) + .unbind('click', event.proxy) + .unbind('dblclick', event.proxy) + .unbind('mouseover', event.proxy) + .unbind('mouseout', event.proxy) + .unbind('mousedown', event.proxy) + .unbind('mouseup', event.proxy) + .unbind('contextmenu', event.proxy); + }, + doProxy: function (e) { + var results = []; + for (var i = 0, j = _init.proxys.length; i < j; i++) { + var proxyResult = _init.proxys[i].apply(this, arguments); + results.push(proxyResult); + if (proxyResult.stop) { + break; + } + } + return results; + }, + proxy: function (e) { + var setting = data.getSetting(e.data.treeId); + if (!tools.uCanDo(setting, e)) return true; + var results = event.doProxy(e), + r = true, x = false; + for (var i = 0, l = results.length; i < l; i++) { + var proxyResult = results[i]; + if (proxyResult.nodeEventCallback) { + x = true; + r = proxyResult.nodeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r; + } + if (proxyResult.treeEventCallback) { + x = true; + r = proxyResult.treeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r; + } + } + return r; + } + }, + //method of event handler + handler = { + onSwitchNode: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (node.open) { + if (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false) return true; + data.getRoot(setting).expandTriggerFlag = true; + view.switchNode(setting, node); + } else { + if (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false) return true; + data.getRoot(setting).expandTriggerFlag = true; + view.switchNode(setting, node); + } + return true; + }, + onClickNode: function (event, node) { + var setting = data.getSetting(event.data.treeId), + clickFlag = ((setting.view.autoCancelSelected && (event.ctrlKey || event.metaKey)) && data.isSelectedNode(setting, node)) ? 0 : (setting.view.autoCancelSelected && (event.ctrlKey || event.metaKey) && setting.view.selectedMulti) ? 2 : 1; + if (tools.apply(setting.callback.beforeClick, [setting.treeId, node, clickFlag], true) == false) return true; + if (clickFlag === 0) { + view.cancelPreSelectedNode(setting, node); + } else { + view.selectNode(setting, node, clickFlag === 2); + } + setting.treeObj.trigger(consts.event.CLICK, [event, setting.treeId, node, clickFlag]); + return true; + }, + onZTreeMousedown: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (tools.apply(setting.callback.beforeMouseDown, [setting.treeId, node], true)) { + tools.apply(setting.callback.onMouseDown, [event, setting.treeId, node]); + } + return true; + }, + onZTreeMouseup: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (tools.apply(setting.callback.beforeMouseUp, [setting.treeId, node], true)) { + tools.apply(setting.callback.onMouseUp, [event, setting.treeId, node]); + } + return true; + }, + onZTreeDblclick: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (tools.apply(setting.callback.beforeDblClick, [setting.treeId, node], true)) { + tools.apply(setting.callback.onDblClick, [event, setting.treeId, node]); + } + return true; + }, + onZTreeContextmenu: function (event, node) { + var setting = data.getSetting(event.data.treeId); + if (tools.apply(setting.callback.beforeRightClick, [setting.treeId, node], true)) { + tools.apply(setting.callback.onRightClick, [event, setting.treeId, node]); + } + return (typeof setting.callback.onRightClick) != "function"; + }, + onSelectStart: function (e) { + var n = e.originalEvent.srcElement.nodeName.toLowerCase(); + return (n === "input" || n === "textarea"); + } + }, + //method of tools for zTree + tools = { + apply: function (fun, param, defaultValue) { + if ((typeof fun) == "function") { + return fun.apply(zt, param ? param : []); + } + return defaultValue; + }, + canAsync: function (setting, node) { + var children = data.nodeChildren(setting, node); + var isParent = data.nodeIsParent(setting, node); + return (setting.async.enable && node && isParent && !(node.zAsync || (children && children.length > 0))); + }, + clone: function (obj) { + if (obj === null) return null; + var o = tools.isArray(obj) ? [] : {}; + for (var i in obj) { + o[i] = (obj[i] instanceof Date) ? new Date(obj[i].getTime()) : (typeof obj[i] === "object" ? tools.clone(obj[i]) : obj[i]); + } + return o; + }, + eqs: function (str1, str2) { + return str1.toLowerCase() === str2.toLowerCase(); + }, + isArray: function (arr) { + return Object.prototype.toString.apply(arr) === "[object Array]"; + }, + isElement: function (o) { + return ( + typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2 + o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName === "string" + ); + }, + $: function (node, exp, setting) { + if (!!exp && typeof exp != "string") { + setting = exp; + exp = ""; + } + if (typeof node == "string") { + return $(node, setting ? setting.treeObj.get(0).ownerDocument : null); + } else { + return $("#" + node.tId + exp, setting ? setting.treeObj : null); + } + }, + getMDom: function (setting, curDom, targetExpr) { + if (!curDom) return null; + while (curDom && curDom.id !== setting.treeId) { + for (var i = 0, l = targetExpr.length; curDom.tagName && i < l; i++) { + if (tools.eqs(curDom.tagName, targetExpr[i].tagName) && curDom.getAttribute(targetExpr[i].attrName) !== null) { + return curDom; + } + } + curDom = curDom.parentNode; + } + return null; + }, + getNodeMainDom: function (target) { + return ($(target).parent("li").get(0) || $(target).parentsUntil("li").parent().get(0)); + }, + isChildOrSelf: function (dom, parentId) { + return ($(dom).closest("#" + parentId).length > 0); + }, + uCanDo: function (setting, e) { + return true; + } + }, + //method of operate ztree dom + view = { + addNodes: function (setting, parentNode, index, newNodes, isSilent) { + var isParent = data.nodeIsParent(setting, parentNode); + if (setting.data.keep.leaf && parentNode && !isParent) { + return; + } + if (!tools.isArray(newNodes)) { + newNodes = [newNodes]; + } + if (setting.data.simpleData.enable) { + newNodes = data.transformTozTreeFormat(setting, newNodes); + } + if (parentNode) { + var target_switchObj = $$(parentNode, consts.id.SWITCH, setting), + target_icoObj = $$(parentNode, consts.id.ICON, setting), + target_ulObj = $$(parentNode, consts.id.UL, setting); + + if (!parentNode.open) { + view.replaceSwitchClass(parentNode, target_switchObj, consts.folder.CLOSE); + view.replaceIcoClass(parentNode, target_icoObj, consts.folder.CLOSE); + parentNode.open = false; + target_ulObj.css({ + "display": "none" + }); + } + + data.addNodesData(setting, parentNode, index, newNodes); + view.createNodes(setting, parentNode.level + 1, newNodes, parentNode, index); + if (!isSilent) { + view.expandCollapseParentNode(setting, parentNode, true); + } + } else { + data.addNodesData(setting, data.getRoot(setting), index, newNodes); + view.createNodes(setting, 0, newNodes, null, index); + } + }, + appendNodes: function (setting, level, nodes, parentNode, index, initFlag, openFlag) { + if (!nodes) return []; + var html = []; + + var tmpPNode = (parentNode) ? parentNode : data.getRoot(setting), + tmpPChild = data.nodeChildren(setting, tmpPNode), + isFirstNode, isLastNode; + + if (!tmpPChild || index >= tmpPChild.length - nodes.length) { + index = -1; + } + + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + if (initFlag) { + isFirstNode = ((index === 0 || tmpPChild.length == nodes.length) && (i == 0)); + isLastNode = (index < 0 && i == (nodes.length - 1)); + data.initNode(setting, level, node, parentNode, isFirstNode, isLastNode, openFlag); + data.addNodeCache(setting, node); + } + var isParent = data.nodeIsParent(setting, node); + + var childHtml = []; + var children = data.nodeChildren(setting, node); + if (children && children.length > 0) { + //make child html first, because checkType + childHtml = view.appendNodes(setting, level + 1, children, node, -1, initFlag, openFlag && node.open); + } + if (openFlag) { + view.makeDOMNodeMainBefore(html, setting, node); + view.makeDOMNodeLine(html, setting, node); + data.getBeforeA(setting, node, html); + view.makeDOMNodeNameBefore(html, setting, node); + data.getInnerBeforeA(setting, node, html); + view.makeDOMNodeIcon(html, setting, node); + data.getInnerAfterA(setting, node, html); + view.makeDOMNodeNameAfter(html, setting, node); + data.getAfterA(setting, node, html); + if (isParent && node.open) { + view.makeUlHtml(setting, node, html, childHtml.join('')); + } + view.makeDOMNodeMainAfter(html, setting, node); + data.addCreatedNode(setting, node); + } + } + return html; + }, + appendParentULDom: function (setting, node) { + var html = [], + nObj = $$(node, setting); + if (!nObj.get(0) && !!node.parentTId) { + view.appendParentULDom(setting, node.getParentNode()); + nObj = $$(node, setting); + } + var ulObj = $$(node, consts.id.UL, setting); + if (ulObj.get(0)) { + ulObj.remove(); + } + var children = data.nodeChildren(setting, node), + childHtml = view.appendNodes(setting, node.level + 1, children, node, -1, false, true); + view.makeUlHtml(setting, node, html, childHtml.join('')); + nObj.append(html.join('')); + }, + asyncNode: function (setting, node, isSilent, callback) { + var i, l; + var isParent = data.nodeIsParent(setting, node); + if (node && !isParent) { + tools.apply(callback); + return false; + } else if (node && node.isAjaxing) { + return false; + } else if (tools.apply(setting.callback.beforeAsync, [setting.treeId, node], true) == false) { + tools.apply(callback); + return false; + } + if (node) { + node.isAjaxing = true; + var icoObj = $$(node, consts.id.ICON, setting); + icoObj.attr({"style": "", "class": consts.className.BUTTON + " " + consts.className.ICO_LOADING}); + } + + var tmpParam = {}; + var autoParam = tools.apply(setting.async.autoParam, [setting.treeId, node], setting.async.autoParam); + for (i = 0, l = autoParam.length; node && i < l; i++) { + var pKey = autoParam[i].split("="), spKey = pKey; + if (pKey.length > 1) { + spKey = pKey[1]; + pKey = pKey[0]; + } + tmpParam[spKey] = node[pKey]; + } + var otherParam = tools.apply(setting.async.otherParam, [setting.treeId, node], setting.async.otherParam); + if (tools.isArray(otherParam)) { + for (i = 0, l = otherParam.length; i < l; i += 2) { + tmpParam[otherParam[i]] = otherParam[i + 1]; + } + } else { + for (var p in otherParam) { + tmpParam[p] = otherParam[p]; + } + } + + var _tmpV = data.getRoot(setting)._ver; + $.ajax({ + contentType: setting.async.contentType, + cache: false, + type: setting.async.type, + url: tools.apply(setting.async.url, [setting.treeId, node], setting.async.url), + data: setting.async.contentType.indexOf('application/json') > -1 ? JSON.stringify(tmpParam) : tmpParam, + dataType: setting.async.dataType, + headers: setting.async.headers, + xhrFields: setting.async.xhrFields, + success: function (msg) { + if (_tmpV != data.getRoot(setting)._ver) { + return; + } + var newNodes = []; + try { + if (!msg || msg.length == 0) { + newNodes = []; + } else if (typeof msg == "string") { + newNodes = eval("(" + msg + ")"); + } else { + newNodes = msg; + } + } catch (err) { + newNodes = msg; + } + + if (node) { + node.isAjaxing = null; + node.zAsync = true; + } + view.setNodeLineIcos(setting, node); + if (newNodes && newNodes !== "") { + newNodes = tools.apply(setting.async.dataFilter, [setting.treeId, node, newNodes], newNodes); + view.addNodes(setting, node, -1, !!newNodes ? tools.clone(newNodes) : [], !!isSilent); + } else { + view.addNodes(setting, node, -1, [], !!isSilent); + } + setting.treeObj.trigger(consts.event.ASYNC_SUCCESS, [setting.treeId, node, msg]); + tools.apply(callback); + }, + error: function (XMLHttpRequest, textStatus, errorThrown) { + if (_tmpV != data.getRoot(setting)._ver) { + return; + } + if (node) node.isAjaxing = null; + view.setNodeLineIcos(setting, node); + setting.treeObj.trigger(consts.event.ASYNC_ERROR, [setting.treeId, node, XMLHttpRequest, textStatus, errorThrown]); + } + }); + return true; + }, + cancelPreSelectedNode: function (setting, node, excludeNode) { + var list = data.getRoot(setting).curSelectedList, + i, n; + for (i = list.length - 1; i >= 0; i--) { + n = list[i]; + if (node === n || (!node && (!excludeNode || excludeNode !== n))) { + $$(n, consts.id.A, setting).removeClass(consts.node.CURSELECTED); + if (node) { + data.removeSelectedNode(setting, node); + break; + } else { + list.splice(i, 1); + setting.treeObj.trigger(consts.event.UNSELECTED, [setting.treeId, n]); + } + } + } + }, + createNodeCallback: function (setting) { + if (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) { + var root = data.getRoot(setting); + while (root.createdNodes.length > 0) { + var node = root.createdNodes.shift(); + tools.apply(setting.view.addDiyDom, [setting.treeId, node]); + if (!!setting.callback.onNodeCreated) { + setting.treeObj.trigger(consts.event.NODECREATED, [setting.treeId, node]); + } + } + } + }, + createNodes: function (setting, level, nodes, parentNode, index) { + if (!nodes || nodes.length == 0) return; + var root = data.getRoot(setting), + openFlag = !parentNode || parentNode.open || !!$$(data.nodeChildren(setting, parentNode)[0], setting).get(0); + root.createdNodes = []; + var zTreeHtml = view.appendNodes(setting, level, nodes, parentNode, index, true, openFlag), + parentObj, nextObj; + + if (!parentNode) { + parentObj = setting.treeObj; + //setting.treeObj.append(zTreeHtml.join('')); + } else { + var ulObj = $$(parentNode, consts.id.UL, setting); + if (ulObj.get(0)) { + parentObj = ulObj; + //ulObj.append(zTreeHtml.join('')); + } + } + if (parentObj) { + if (index >= 0) { + nextObj = parentObj.children()[index]; + } + if (index >= 0 && nextObj) { + $(nextObj).before(zTreeHtml.join('')); + } else { + parentObj.append(zTreeHtml.join('')); + } + } + + view.createNodeCallback(setting); + }, + destroy: function (setting) { + if (!setting) return; + data.initCache(setting); + data.initRoot(setting); + event.unbindTree(setting); + event.unbindEvent(setting); + setting.treeObj.empty(); + delete settings[setting.treeId]; + }, + expandCollapseNode: function (setting, node, expandFlag, animateFlag, callback) { + var root = data.getRoot(setting); + var tmpCb, _callback; + if (!node) { + tools.apply(callback, []); + return; + } + var children = data.nodeChildren(setting, node); + var isParent = data.nodeIsParent(setting, node); + if (root.expandTriggerFlag) { + _callback = callback; + tmpCb = function () { + if (_callback) _callback(); + if (node.open) { + setting.treeObj.trigger(consts.event.EXPAND, [setting.treeId, node]); + } else { + setting.treeObj.trigger(consts.event.COLLAPSE, [setting.treeId, node]); + } + }; + callback = tmpCb; + root.expandTriggerFlag = false; + } + if (!node.open && isParent && ((!$$(node, consts.id.UL, setting).get(0)) || (children && children.length > 0 && !$$(children[0], setting).get(0)))) { + view.appendParentULDom(setting, node); + view.createNodeCallback(setting); + } + if (node.open == expandFlag) { + tools.apply(callback, []); + return; + } + var ulObj = $$(node, consts.id.UL, setting), + switchObj = $$(node, consts.id.SWITCH, setting), + icoObj = $$(node, consts.id.ICON, setting); + + if (isParent) { + node.open = !node.open; + if (node.iconOpen && node.iconClose) { + icoObj.attr("style", view.makeNodeIcoStyle(setting, node)); + } + + if (node.open) { + view.replaceSwitchClass(node, switchObj, consts.folder.OPEN); + view.replaceIcoClass(node, icoObj, consts.folder.OPEN); + if (animateFlag == false || setting.view.expandSpeed == "") { + ulObj.show(); + tools.apply(callback, []); + } else { + if (children && children.length > 0) { + ulObj.slideDown(setting.view.expandSpeed, callback); + } else { + ulObj.show(); + tools.apply(callback, []); + } + } + } else { + view.replaceSwitchClass(node, switchObj, consts.folder.CLOSE); + view.replaceIcoClass(node, icoObj, consts.folder.CLOSE); + if (animateFlag == false || setting.view.expandSpeed == "" || !(children && children.length > 0)) { + ulObj.hide(); + tools.apply(callback, []); + } else { + ulObj.slideUp(setting.view.expandSpeed, callback); + } + } + } else { + tools.apply(callback, []); + } + }, + expandCollapseParentNode: function (setting, node, expandFlag, animateFlag, callback) { + if (!node) return; + if (!node.parentTId) { + view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback); + return; + } else { + view.expandCollapseNode(setting, node, expandFlag, animateFlag); + } + if (node.parentTId) { + view.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, animateFlag, callback); + } + }, + expandCollapseSonNode: function (setting, node, expandFlag, animateFlag, callback) { + var root = data.getRoot(setting), + treeNodes = (node) ? data.nodeChildren(setting, node) : data.nodeChildren(setting, root), + selfAnimateSign = (node) ? false : animateFlag, + expandTriggerFlag = data.getRoot(setting).expandTriggerFlag; + data.getRoot(setting).expandTriggerFlag = false; + if (treeNodes) { + for (var i = 0, l = treeNodes.length; i < l; i++) { + if (treeNodes[i]) view.expandCollapseSonNode(setting, treeNodes[i], expandFlag, selfAnimateSign); + } + } + data.getRoot(setting).expandTriggerFlag = expandTriggerFlag; + view.expandCollapseNode(setting, node, expandFlag, animateFlag, callback); + }, + isSelectedNode: function (setting, node) { + if (!node) { + return false; + } + var list = data.getRoot(setting).curSelectedList, + i; + for (i = list.length - 1; i >= 0; i--) { + if (node === list[i]) { + return true; + } + } + return false; + }, + makeDOMNodeIcon: function (html, setting, node) { + var nameStr = data.nodeName(setting, node), + name = setting.view.nameIsHTML ? nameStr : nameStr.replace(/&/g, '&').replace(//g, '>'); + html.push("", name, ""); + }, + makeDOMNodeLine: function (html, setting, node) { + html.push(""); + }, + makeDOMNodeMainAfter: function (html, setting, node) { + html.push("
    • "); + }, + makeDOMNodeMainBefore: function (html, setting, node) { + html.push("
    • "); + }, + makeDOMNodeNameAfter: function (html, setting, node) { + html.push(""); + }, + makeDOMNodeNameBefore: function (html, setting, node) { + var title = data.nodeTitle(setting, node), + url = view.makeNodeUrl(setting, node), + fontcss = view.makeNodeFontCss(setting, node), + nodeClasses = view.makeNodeClasses(setting, node), + fontStyle = []; + for (var f in fontcss) { + fontStyle.push(f, ":", fontcss[f], ";"); + } + html.push(" 0) ? " href='" + url + "'" : ""), " target='", view.makeNodeTarget(node), "' style='", fontStyle.join(''), + "'"); + if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle) && title) { + html.push("title='", title.replace(/'/g, "'").replace(//g, '>'), "'"); + } + html.push(">"); + }, + makeNodeFontCss: function (setting, node) { + var fontCss = tools.apply(setting.view.fontCss, [setting.treeId, node], setting.view.fontCss); + return (fontCss && ((typeof fontCss) != "function")) ? fontCss : {}; + }, + makeNodeClasses: function (setting, node) { + var classes = tools.apply(setting.view.nodeClasses, [setting.treeId, node], setting.view.nodeClasses); + return (classes && (typeof classes !== "function")) ? classes : {add:[], remove:[]}; + }, + makeNodeIcoClass: function (setting, node) { + var icoCss = ["ico"]; + if (!node.isAjaxing) { + var isParent = data.nodeIsParent(setting, node); + icoCss[0] = (node.iconSkin ? node.iconSkin + "_" : "") + icoCss[0]; + if (isParent) { + icoCss.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE); + } else { + icoCss.push(consts.folder.DOCU); + } + } + return consts.className.BUTTON + " " + icoCss.join('_'); + }, + makeNodeIcoStyle: function (setting, node) { + var icoStyle = []; + if (!node.isAjaxing) { + var isParent = data.nodeIsParent(setting, node); + var icon = (isParent && node.iconOpen && node.iconClose) ? (node.open ? node.iconOpen : node.iconClose) : node[setting.data.key.icon]; + if (icon) icoStyle.push("background:url(", icon, ") 0 0 no-repeat;"); + if (setting.view.showIcon == false || !tools.apply(setting.view.showIcon, [setting.treeId, node], true)) { + icoStyle.push("display:none;"); + } + } + return icoStyle.join(''); + }, + makeNodeLineClass: function (setting, node) { + var lineClass = []; + if (setting.view.showLine) { + if (node.level == 0 && node.isFirstNode && node.isLastNode) { + lineClass.push(consts.line.ROOT); + } else if (node.level == 0 && node.isFirstNode) { + lineClass.push(consts.line.ROOTS); + } else if (node.isLastNode) { + lineClass.push(consts.line.BOTTOM); + } else { + lineClass.push(consts.line.CENTER); + } + } else { + lineClass.push(consts.line.NOLINE); + } + if (data.nodeIsParent(setting, node)) { + lineClass.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE); + } else { + lineClass.push(consts.folder.DOCU); + } + return view.makeNodeLineClassEx(node) + lineClass.join('_'); + }, + makeNodeLineClassEx: function (node) { + return consts.className.BUTTON + " " + consts.className.LEVEL + node.level + " " + consts.className.SWITCH + " "; + }, + makeNodeTarget: function (node) { + return (node.target || "_blank"); + }, + makeNodeUrl: function (setting, node) { + var urlKey = setting.data.key.url; + return node[urlKey] ? node[urlKey] : null; + }, + makeUlHtml: function (setting, node, html, content) { + html.push("
        "); + html.push(content); + html.push("
      "); + }, + makeUlLineClass: function (setting, node) { + return ((setting.view.showLine && !node.isLastNode) ? consts.line.LINE : ""); + }, + removeChildNodes: function (setting, node) { + if (!node) return; + var nodes = data.nodeChildren(setting, node); + if (!nodes) return; + + for (var i = 0, l = nodes.length; i < l; i++) { + data.removeNodeCache(setting, nodes[i]); + } + data.removeSelectedNode(setting); + delete node[setting.data.key.children]; + + if (!setting.data.keep.parent) { + data.nodeIsParent(setting, node, false); + node.open = false; + var tmp_switchObj = $$(node, consts.id.SWITCH, setting), + tmp_icoObj = $$(node, consts.id.ICON, setting); + view.replaceSwitchClass(node, tmp_switchObj, consts.folder.DOCU); + view.replaceIcoClass(node, tmp_icoObj, consts.folder.DOCU); + $$(node, consts.id.UL, setting).remove(); + } else { + $$(node, consts.id.UL, setting).empty(); + } + }, + scrollIntoView: function (setting, dom) { + if (!dom) { + return; + } + // support IE 7 / 8 + if (typeof Element === 'undefined' || typeof HTMLElement === 'undefined') { + var contRect = setting.treeObj.get(0).getBoundingClientRect(), + findMeRect = dom.getBoundingClientRect(); + if (findMeRect.top < contRect.top || findMeRect.bottom > contRect.bottom + || findMeRect.right > contRect.right || findMeRect.left < contRect.left) { + dom.scrollIntoView(); + } + return; + } + // CC-BY jocki84@googlemail.com, https://gist.github.com/jocki84/6ffafd003387179a988e + if (!Element.prototype.scrollIntoViewIfNeeded) { + Element.prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) { + "use strict"; + + function makeRange(start, length) { + return {"start": start, "length": length, "end": start + length}; + } + + function coverRange(inner, outer) { + if ( + false === centerIfNeeded || + (outer.start < inner.end && inner.start < outer.end) + ) { + return Math.max( + inner.end - outer.length, + Math.min(outer.start, inner.start) + ); + } + return (inner.start + inner.end - outer.length) / 2; + } + + function makePoint(x, y) { + return { + "x": x, + "y": y, + "translate": function translate(dX, dY) { + return makePoint(x + dX, y + dY); + } + }; + } + + function absolute(elem, pt) { + while (elem) { + pt = pt.translate(elem.offsetLeft, elem.offsetTop); + elem = elem.offsetParent; + } + return pt; + } + + var target = absolute(this, makePoint(0, 0)), + extent = makePoint(this.offsetWidth, this.offsetHeight), + elem = this.parentNode, + origin; + + while (elem instanceof HTMLElement) { + // Apply desired scroll amount. + origin = absolute(elem, makePoint(elem.clientLeft, elem.clientTop)); + elem.scrollLeft = coverRange( + makeRange(target.x - origin.x, extent.x), + makeRange(elem.scrollLeft, elem.clientWidth) + ); + elem.scrollTop = coverRange( + makeRange(target.y - origin.y, extent.y), + makeRange(elem.scrollTop, elem.clientHeight) + ); + + // Determine actual scroll amount by reading back scroll properties. + target = target.translate(-elem.scrollLeft, -elem.scrollTop); + elem = elem.parentNode; + } + }; + } + dom.scrollIntoViewIfNeeded(); + }, + setFirstNode: function (setting, parentNode) { + var children = data.nodeChildren(setting, parentNode); + if (children.length > 0) { + children[0].isFirstNode = true; + } + }, + setLastNode: function (setting, parentNode) { + var children = data.nodeChildren(setting, parentNode); + if (children.length > 0) { + children[children.length - 1].isLastNode = true; + } + }, + removeNode: function (setting, node) { + var root = data.getRoot(setting), + parentNode = (node.parentTId) ? node.getParentNode() : root; + + node.isFirstNode = false; + node.isLastNode = false; + node.getPreNode = function () { + return null; + }; + node.getNextNode = function () { + return null; + }; + + if (!data.getNodeCache(setting, node.tId)) { + return; + } + + $$(node, setting).remove(); + data.removeNodeCache(setting, node); + data.removeSelectedNode(setting, node); + + var children = data.nodeChildren(setting, parentNode); + for (var i = 0, l = children.length; i < l; i++) { + if (children[i].tId == node.tId) { + children.splice(i, 1); + break; + } + } + view.setFirstNode(setting, parentNode); + view.setLastNode(setting, parentNode); + + var tmp_ulObj, tmp_switchObj, tmp_icoObj, + childLength = children.length; + + //repair nodes old parent + if (!setting.data.keep.parent && childLength == 0) { + //old parentNode has no child nodes + data.nodeIsParent(setting, parentNode, false); + parentNode.open = false; + delete parentNode[setting.data.key.children]; + tmp_ulObj = $$(parentNode, consts.id.UL, setting); + tmp_switchObj = $$(parentNode, consts.id.SWITCH, setting); + tmp_icoObj = $$(parentNode, consts.id.ICON, setting); + view.replaceSwitchClass(parentNode, tmp_switchObj, consts.folder.DOCU); + view.replaceIcoClass(parentNode, tmp_icoObj, consts.folder.DOCU); + tmp_ulObj.css("display", "none"); + + } else if (setting.view.showLine && childLength > 0) { + //old parentNode has child nodes + var newLast = children[childLength - 1]; + tmp_ulObj = $$(newLast, consts.id.UL, setting); + tmp_switchObj = $$(newLast, consts.id.SWITCH, setting); + tmp_icoObj = $$(newLast, consts.id.ICON, setting); + if (parentNode == root) { + if (children.length == 1) { + //node was root, and ztree has only one root after move node + view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.ROOT); + } else { + var tmp_first_switchObj = $$(children[0], consts.id.SWITCH, setting); + view.replaceSwitchClass(children[0], tmp_first_switchObj, consts.line.ROOTS); + view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM); + } + } else { + view.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM); + } + tmp_ulObj.removeClass(consts.line.LINE); + } + }, + replaceIcoClass: function (node, obj, newName) { + if (!obj || node.isAjaxing) return; + var tmpName = obj.attr("class"); + if (tmpName == undefined) return; + var tmpList = tmpName.split("_"); + switch (newName) { + case consts.folder.OPEN: + case consts.folder.CLOSE: + case consts.folder.DOCU: + tmpList[tmpList.length - 1] = newName; + break; + } + obj.attr("class", tmpList.join("_")); + }, + replaceSwitchClass: function (node, obj, newName) { + if (!obj) return; + var tmpName = obj.attr("class"); + if (tmpName == undefined) return; + var tmpList = tmpName.split("_"); + switch (newName) { + case consts.line.ROOT: + case consts.line.ROOTS: + case consts.line.CENTER: + case consts.line.BOTTOM: + case consts.line.NOLINE: + tmpList[0] = view.makeNodeLineClassEx(node) + newName; + break; + case consts.folder.OPEN: + case consts.folder.CLOSE: + case consts.folder.DOCU: + tmpList[1] = newName; + break; + } + obj.attr("class", tmpList.join("_")); + if (newName !== consts.folder.DOCU) { + obj.removeAttr("disabled"); + } else { + obj.attr("disabled", "disabled"); + } + }, + selectNode: function (setting, node, addFlag) { + if (!addFlag) { + view.cancelPreSelectedNode(setting, null, node); + } + $$(node, consts.id.A, setting).addClass(consts.node.CURSELECTED); + data.addSelectedNode(setting, node); + setting.treeObj.trigger(consts.event.SELECTED, [setting.treeId, node]); + }, + setNodeFontCss: function (setting, treeNode) { + var aObj = $$(treeNode, consts.id.A, setting), + fontCss = view.makeNodeFontCss(setting, treeNode); + if (fontCss) { + aObj.css(fontCss); + } + }, + setNodeClasses: function (setting, treeNode) { + var aObj = $$(treeNode, consts.id.A, setting), + classes = view.makeNodeClasses(setting, treeNode); + if ('add' in classes && classes.add.length) { + aObj.addClass(classes.add.join(' ')); + } + if ('remove' in classes && classes.remove.length) { + aObj.removeClass(classes.remove.join(' ')); + } + }, + setNodeLineIcos: function (setting, node) { + if (!node) return; + var switchObj = $$(node, consts.id.SWITCH, setting), + ulObj = $$(node, consts.id.UL, setting), + icoObj = $$(node, consts.id.ICON, setting), + ulLine = view.makeUlLineClass(setting, node); + if (ulLine.length == 0) { + ulObj.removeClass(consts.line.LINE); + } else { + ulObj.addClass(ulLine); + } + switchObj.attr("class", view.makeNodeLineClass(setting, node)); + if (data.nodeIsParent(setting, node)) { + switchObj.removeAttr("disabled"); + } else { + switchObj.attr("disabled", "disabled"); + } + icoObj.removeAttr("style"); + icoObj.attr("style", view.makeNodeIcoStyle(setting, node)); + icoObj.attr("class", view.makeNodeIcoClass(setting, node)); + }, + setNodeName: function (setting, node) { + var title = data.nodeTitle(setting, node), + nObj = $$(node, consts.id.SPAN, setting); + nObj.empty(); + if (setting.view.nameIsHTML) { + nObj.html(data.nodeName(setting, node)); + } else { + nObj.text(data.nodeName(setting, node)); + } + if (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle)) { + var aObj = $$(node, consts.id.A, setting); + aObj.attr("title", !title ? "" : title); + } + }, + setNodeTarget: function (setting, node) { + var aObj = $$(node, consts.id.A, setting); + aObj.attr("target", view.makeNodeTarget(node)); + }, + setNodeUrl: function (setting, node) { + var aObj = $$(node, consts.id.A, setting), + url = view.makeNodeUrl(setting, node); + if (url == null || url.length == 0) { + aObj.removeAttr("href"); + } else { + aObj.attr("href", url); + } + }, + switchNode: function (setting, node) { + if (node.open || !tools.canAsync(setting, node)) { + view.expandCollapseNode(setting, node, !node.open); + } else if (setting.async.enable) { + if (!view.asyncNode(setting, node)) { + view.expandCollapseNode(setting, node, !node.open); + return; + } + } else if (node) { + view.expandCollapseNode(setting, node, !node.open); + } + } + }; + // zTree defind + $.fn.zTree = { + consts: _consts, + _z: { + tools: tools, + view: view, + event: event, + data: data + }, + getZTreeObj: function (treeId) { + var o = data.getZTreeTools(treeId); + return o ? o : null; + }, + destroy: function (treeId) { + if (!!treeId && treeId.length > 0) { + view.destroy(data.getSetting(treeId)); + } else { + for (var s in settings) { + view.destroy(settings[s]); + } + } + }, + init: function (obj, zSetting, zNodes) { + var setting = tools.clone(_setting); + $.extend(true, setting, zSetting); + setting.treeId = obj.attr("id"); + setting.treeObj = obj; + setting.treeObj.empty(); + settings[setting.treeId] = setting; + //For some older browser,(e.g., ie6) + if (typeof document.body.style.maxHeight === "undefined") { + setting.view.expandSpeed = ""; + } + data.initRoot(setting); + var root = data.getRoot(setting); + zNodes = zNodes ? tools.clone(tools.isArray(zNodes) ? zNodes : [zNodes]) : []; + if (setting.data.simpleData.enable) { + data.nodeChildren(setting, root, data.transformTozTreeFormat(setting, zNodes)); + } else { + data.nodeChildren(setting, root, zNodes); + } + + data.initCache(setting); + event.unbindTree(setting); + event.bindTree(setting); + event.unbindEvent(setting); + event.bindEvent(setting); + + var zTreeTools = { + setting: setting, + addNodes: function (parentNode, index, newNodes, isSilent) { + if (!parentNode) parentNode = null; + var isParent = data.nodeIsParent(setting, parentNode); + if (parentNode && !isParent && setting.data.keep.leaf) return null; + + var i = parseInt(index, 10); + if (isNaN(i)) { + isSilent = !!newNodes; + newNodes = index; + index = -1; + } else { + index = i; + } + if (!newNodes) return null; + + + var xNewNodes = tools.clone(tools.isArray(newNodes) ? newNodes : [newNodes]); + + function addCallback() { + view.addNodes(setting, parentNode, index, xNewNodes, (isSilent == true)); + } + + if (tools.canAsync(setting, parentNode)) { + view.asyncNode(setting, parentNode, isSilent, addCallback); + } else { + addCallback(); + } + return xNewNodes; + }, + cancelSelectedNode: function (node) { + view.cancelPreSelectedNode(setting, node); + }, + destroy: function () { + view.destroy(setting); + }, + expandAll: function (expandFlag) { + expandFlag = !!expandFlag; + view.expandCollapseSonNode(setting, null, expandFlag, true); + return expandFlag; + }, + expandNode: function (node, expandFlag, sonSign, focus, callbackFlag) { + if (!node || !data.nodeIsParent(setting, node)) return null; + if (expandFlag !== true && expandFlag !== false) { + expandFlag = !node.open; + } + callbackFlag = !!callbackFlag; + + if (callbackFlag && expandFlag && (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false)) { + return null; + } else if (callbackFlag && !expandFlag && (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false)) { + return null; + } + if (expandFlag && node.parentTId) { + view.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, false); + } + if (expandFlag === node.open && !sonSign) { + return null; + } + + data.getRoot(setting).expandTriggerFlag = callbackFlag; + if (!tools.canAsync(setting, node) && sonSign) { + view.expandCollapseSonNode(setting, node, expandFlag, true, showNodeFocus); + } else { + node.open = !expandFlag; + view.switchNode(this.setting, node); + showNodeFocus(); + } + return expandFlag; + + function showNodeFocus() { + var a = $$(node, consts.id.A, setting).get(0); + if (a && focus !== false) { + view.scrollIntoView(setting, a); + } + } + }, + getNodes: function () { + return data.getNodes(setting); + }, + getNodeByParam: function (key, value, parentNode) { + if (!key) return null; + return data.getNodeByParam(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), key, value); + }, + getNodeByTId: function (tId) { + return data.getNodeCache(setting, tId); + }, + getNodesByParam: function (key, value, parentNode) { + if (!key) return null; + return data.getNodesByParam(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), key, value); + }, + getNodesByParamFuzzy: function (key, value, parentNode) { + if (!key) return null; + return data.getNodesByParamFuzzy(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), key, value); + }, + getNodesByFilter: function (filter, isSingle, parentNode, invokeParam) { + isSingle = !!isSingle; + if (!filter || (typeof filter != "function")) return (isSingle ? null : []); + return data.getNodesByFilter(setting, parentNode ? data.nodeChildren(setting, parentNode) : data.getNodes(setting), filter, isSingle, invokeParam); + }, + getNodeIndex: function (node) { + if (!node) return null; + var parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting); + var children = data.nodeChildren(setting, parentNode); + for (var i = 0, l = children.length; i < l; i++) { + if (children[i] == node) return i; + } + return -1; + }, + getSelectedNodes: function () { + var r = [], list = data.getRoot(setting).curSelectedList; + for (var i = 0, l = list.length; i < l; i++) { + r.push(list[i]); + } + return r; + }, + isSelectedNode: function (node) { + return data.isSelectedNode(setting, node); + }, + reAsyncChildNodesPromise: function (parentNode, reloadType, isSilent) { + var promise = new Promise(function (resolve, reject) { + try { + zTreeTools.reAsyncChildNodes(parentNode, reloadType, isSilent, function () { + resolve(parentNode); + }); + } catch (e) { + reject(e); + } + }); + return promise; + }, + reAsyncChildNodes: function (parentNode, reloadType, isSilent, callback) { + if (!this.setting.async.enable) return; + var isRoot = !parentNode; + if (isRoot) { + parentNode = data.getRoot(setting); + } + if (reloadType == "refresh") { + var children = data.nodeChildren(setting, parentNode); + for (var i = 0, l = children ? children.length : 0; i < l; i++) { + data.removeNodeCache(setting, children[i]); + } + data.removeSelectedNode(setting); + data.nodeChildren(setting, parentNode, []); + if (isRoot) { + this.setting.treeObj.empty(); + } else { + var ulObj = $$(parentNode, consts.id.UL, setting); + ulObj.empty(); + } + } + view.asyncNode(this.setting, isRoot ? null : parentNode, !!isSilent, callback); + }, + refresh: function () { + this.setting.treeObj.empty(); + var root = data.getRoot(setting), + nodes = data.nodeChildren(setting, root); + data.initRoot(setting); + data.nodeChildren(setting, root, nodes); + data.initCache(setting); + view.createNodes(setting, 0, data.nodeChildren(setting, root), null, -1); + }, + removeChildNodes: function (node) { + if (!node) return null; + var nodes = data.nodeChildren(setting, node); + view.removeChildNodes(setting, node); + return nodes ? nodes : null; + }, + removeNode: function (node, callbackFlag) { + if (!node) return; + callbackFlag = !!callbackFlag; + if (callbackFlag && tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return; + view.removeNode(setting, node); + if (callbackFlag) { + this.setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]); + } + }, + selectNode: function (node, addFlag, isSilent) { + if (!node) return; + if (tools.uCanDo(setting)) { + addFlag = setting.view.selectedMulti && addFlag; + if (node.parentTId) { + view.expandCollapseParentNode(setting, node.getParentNode(), true, false, showNodeFocus); + } else if (!isSilent) { + try { + $$(node, setting).focus().blur(); + } catch (e) { + } + } + view.selectNode(setting, node, addFlag); + } + + function showNodeFocus() { + if (isSilent) { + return; + } + var a = $$(node, setting).get(0); + view.scrollIntoView(setting, a); + } + }, + transformTozTreeNodes: function (simpleNodes) { + return data.transformTozTreeFormat(setting, simpleNodes); + }, + transformToArray: function (nodes) { + return data.transformToArrayFormat(setting, nodes); + }, + updateNode: function (node, checkTypeFlag) { + if (!node) return; + var nObj = $$(node, setting); + if (nObj.get(0) && tools.uCanDo(setting)) { + view.setNodeName(setting, node); + view.setNodeTarget(setting, node); + view.setNodeUrl(setting, node); + view.setNodeLineIcos(setting, node); + view.setNodeFontCss(setting, node); + view.setNodeClasses(setting, node); + } + } + }; + root.treeTools = zTreeTools; + data.setZTreeTools(setting, zTreeTools); + var children = data.nodeChildren(setting, root); + if (children && children.length > 0) { + view.createNodes(setting, 0, children, null, -1); + } else if (setting.async.enable && setting.async.url && setting.async.url !== '') { + view.asyncNode(setting); + } + return zTreeTools; + } + }; + + var zt = $.fn.zTree, + $$ = tools.$, + consts = zt.consts; +})(jQuery); \ No newline at end of file diff --git a/public/self/ztree/js/jquery.ztree.excheck.js b/public/self/ztree/js/jquery.ztree.excheck.js new file mode 100644 index 000000000..44b533672 --- /dev/null +++ b/public/self/ztree/js/jquery.ztree.excheck.js @@ -0,0 +1,652 @@ +/* + * JQuery zTree excheck + * v3.5.48 + * http://treejs.cn/ + * + * Copyright (c) 2010 Hunter.z + * + * Licensed same as jquery - MIT License + * http://www.opensource.org/licenses/mit-license.php + * + * Date: 2020-11-21 + */ + +(function ($) { + //default consts of excheck + var _consts = { + event: { + CHECK: "ztree_check" + }, + id: { + CHECK: "_check" + }, + checkbox: { + STYLE: "checkbox", + DEFAULT: "chk", + DISABLED: "disable", + FALSE: "false", + TRUE: "true", + FULL: "full", + PART: "part", + FOCUS: "focus" + }, + radio: { + STYLE: "radio", + TYPE_ALL: "all", + TYPE_LEVEL: "level" + } + }, + //default setting of excheck + _setting = { + check: { + enable: false, + autoCheckTrigger: false, + chkStyle: _consts.checkbox.STYLE, + nocheckInherit: false, + chkDisabledInherit: false, + radioType: _consts.radio.TYPE_LEVEL, + chkboxType: { + "Y": "ps", + "N": "ps" + } + }, + data: { + key: { + checked: "checked" + } + }, + callback: { + beforeCheck: null, + onCheck: null + } + }, + //default root of excheck + _initRoot = function (setting) { + var r = data.getRoot(setting); + r.radioCheckedList = []; + }, + //default cache of excheck + _initCache = function (treeId) { + }, + //default bind event of excheck + _bindEvent = function (setting) { + var o = setting.treeObj, + c = consts.event; + o.bind(c.CHECK, function (event, srcEvent, treeId, node) { + event.srcEvent = srcEvent; + tools.apply(setting.callback.onCheck, [event, treeId, node]); + }); + }, + _unbindEvent = function (setting) { + var o = setting.treeObj, + c = consts.event; + o.unbind(c.CHECK); + }, + //default event proxy of excheck + _eventProxy = function (e) { + var target = e.target, + setting = data.getSetting(e.data.treeId), + tId = "", node = null, + nodeEventType = "", treeEventType = "", + nodeEventCallback = null, treeEventCallback = null; + + if (tools.eqs(e.type, "mouseover")) { + if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode" + consts.id.CHECK) !== null) { + tId = tools.getNodeMainDom(target).id; + nodeEventType = "mouseoverCheck"; + } + } else if (tools.eqs(e.type, "mouseout")) { + if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode" + consts.id.CHECK) !== null) { + tId = tools.getNodeMainDom(target).id; + nodeEventType = "mouseoutCheck"; + } + } else if (tools.eqs(e.type, "click")) { + if (setting.check.enable && tools.eqs(target.tagName, "span") && target.getAttribute("treeNode" + consts.id.CHECK) !== null) { + tId = tools.getNodeMainDom(target).id; + nodeEventType = "checkNode"; + } + } + if (tId.length > 0) { + node = data.getNodeCache(setting, tId); + switch (nodeEventType) { + case "checkNode" : + nodeEventCallback = _handler.onCheckNode; + break; + case "mouseoverCheck" : + nodeEventCallback = _handler.onMouseoverCheck; + break; + case "mouseoutCheck" : + nodeEventCallback = _handler.onMouseoutCheck; + break; + } + } + var proxyResult = { + stop: nodeEventType === "checkNode", + node: node, + nodeEventType: nodeEventType, + nodeEventCallback: nodeEventCallback, + treeEventType: treeEventType, + treeEventCallback: treeEventCallback + }; + return proxyResult + }, + //default init node of excheck + _initNode = function (setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) { + if (!n) return; + var checked = data.nodeChecked(setting, n); + n.checkedOld = checked; + if (typeof n.nocheck == "string") n.nocheck = tools.eqs(n.nocheck, "true"); + n.nocheck = !!n.nocheck || (setting.check.nocheckInherit && parentNode && !!parentNode.nocheck); + if (typeof n.chkDisabled == "string") n.chkDisabled = tools.eqs(n.chkDisabled, "true"); + n.chkDisabled = !!n.chkDisabled || (setting.check.chkDisabledInherit && parentNode && !!parentNode.chkDisabled); + if (typeof n.halfCheck == "string") n.halfCheck = tools.eqs(n.halfCheck, "true"); + n.halfCheck = !!n.halfCheck; + n.check_Child_State = -1; + n.check_Focus = false; + n.getCheckStatus = function () { + return data.getCheckStatus(setting, n); + }; + + if (setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL && checked) { + var r = data.getRoot(setting); + r.radioCheckedList.push(n); + } + }, + //add dom for check + _beforeA = function (setting, node, html) { + if (setting.check.enable) { + data.makeChkFlag(setting, node); + html.push(""); + } + }, + //update zTreeObj, add method of check + _zTreeTools = function (setting, zTreeTools) { + zTreeTools.checkNode = function (node, checked, checkTypeFlag, callbackFlag) { + var nodeChecked = data.nodeChecked(setting, node); + if (node.chkDisabled === true) return; + if (checked !== true && checked !== false) { + checked = !nodeChecked; + } + callbackFlag = !!callbackFlag; + + if (nodeChecked === checked && !checkTypeFlag) { + return; + } else if (callbackFlag && tools.apply(this.setting.callback.beforeCheck, [this.setting.treeId, node], true) == false) { + return; + } + if (tools.uCanDo(this.setting) && this.setting.check.enable && node.nocheck !== true) { + data.nodeChecked(setting, node, checked); + var checkObj = $$(node, consts.id.CHECK, this.setting); + if (checkTypeFlag || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node); + view.setChkClass(this.setting, checkObj, node); + view.repairParentChkClassWithSelf(this.setting, node); + if (callbackFlag) { + this.setting.treeObj.trigger(consts.event.CHECK, [null, this.setting.treeId, node]); + } + } + } + + zTreeTools.checkAllNodes = function (checked) { + view.repairAllChk(this.setting, !!checked); + } + + zTreeTools.getCheckedNodes = function (checked) { + checked = (checked !== false); + var children = data.nodeChildren(setting, data.getRoot(this.setting)); + return data.getTreeCheckedNodes(this.setting, children, checked); + } + + zTreeTools.getChangeCheckedNodes = function () { + var children = data.nodeChildren(setting, data.getRoot(this.setting)); + return data.getTreeChangeCheckedNodes(this.setting, children); + } + + zTreeTools.setChkDisabled = function (node, disabled, inheritParent, inheritChildren) { + disabled = !!disabled; + inheritParent = !!inheritParent; + inheritChildren = !!inheritChildren; + view.repairSonChkDisabled(this.setting, node, disabled, inheritChildren); + view.repairParentChkDisabled(this.setting, node.getParentNode(), disabled, inheritParent); + } + + var _updateNode = zTreeTools.updateNode; + zTreeTools.updateNode = function (node, checkTypeFlag) { + if (_updateNode) _updateNode.apply(zTreeTools, arguments); + if (!node || !this.setting.check.enable) return; + var nObj = $$(node, this.setting); + if (nObj.get(0) && tools.uCanDo(this.setting)) { + var checkObj = $$(node, consts.id.CHECK, this.setting); + if (checkTypeFlag == true || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node); + view.setChkClass(this.setting, checkObj, node); + view.repairParentChkClassWithSelf(this.setting, node); + } + } + }, + //method of operate data + _data = { + getRadioCheckedList: function (setting) { + var checkedList = data.getRoot(setting).radioCheckedList; + for (var i = 0, j = checkedList.length; i < j; i++) { + if (!data.getNodeCache(setting, checkedList[i].tId)) { + checkedList.splice(i, 1); + i--; + j--; + } + } + return checkedList; + }, + getCheckStatus: function (setting, node) { + if (!setting.check.enable || node.nocheck || node.chkDisabled) return null; + var checked = data.nodeChecked(setting, node), + r = { + checked: checked, + half: node.halfCheck ? node.halfCheck : (setting.check.chkStyle == consts.radio.STYLE ? (node.check_Child_State === 2) : (checked ? (node.check_Child_State > -1 && node.check_Child_State < 2) : (node.check_Child_State > 0))) + }; + return r; + }, + getTreeCheckedNodes: function (setting, nodes, checked, results) { + if (!nodes) return []; + var onlyOne = (checked && setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL); + results = !results ? [] : results; + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + var children = data.nodeChildren(setting, node); + var nodeChecked = data.nodeChecked(setting, node); + if (node.nocheck !== true && node.chkDisabled !== true && nodeChecked == checked) { + results.push(node); + if (onlyOne) { + break; + } + } + data.getTreeCheckedNodes(setting, children, checked, results); + if (onlyOne && results.length > 0) { + break; + } + } + return results; + }, + getTreeChangeCheckedNodes: function (setting, nodes, results) { + if (!nodes) return []; + results = !results ? [] : results; + for (var i = 0, l = nodes.length; i < l; i++) { + var node = nodes[i]; + var children = data.nodeChildren(setting, node); + var nodeChecked = data.nodeChecked(setting, node); + if (node.nocheck !== true && node.chkDisabled !== true && nodeChecked != node.checkedOld) { + results.push(node); + } + data.getTreeChangeCheckedNodes(setting, children, results); + } + return results; + }, + makeChkFlag: function (setting, node) { + if (!node) return; + var chkFlag = -1; + var children = data.nodeChildren(setting, node); + if (children) { + for (var i = 0, l = children.length; i < l; i++) { + var cNode = children[i]; + var nodeChecked = data.nodeChecked(setting, cNode); + var tmp = -1; + if (setting.check.chkStyle == consts.radio.STYLE) { + if (cNode.nocheck === true || cNode.chkDisabled === true) { + tmp = cNode.check_Child_State; + } else if (cNode.halfCheck === true) { + tmp = 2; + } else if (nodeChecked) { + tmp = 2; + } else { + tmp = cNode.check_Child_State > 0 ? 2 : 0; + } + if (tmp == 2) { + chkFlag = 2; + break; + } else if (tmp == 0) { + chkFlag = 0; + } + } else if (setting.check.chkStyle == consts.checkbox.STYLE) { + if (cNode.nocheck === true || cNode.chkDisabled === true) { + tmp = cNode.check_Child_State; + } else if (cNode.halfCheck === true) { + tmp = 1; + } else if (nodeChecked) { + tmp = (cNode.check_Child_State === -1 || cNode.check_Child_State === 2) ? 2 : 1; + } else { + tmp = (cNode.check_Child_State > 0) ? 1 : 0; + } + if (tmp === 1) { + chkFlag = 1; + break; + } else if (tmp === 2 && chkFlag > -1 && i > 0 && tmp !== chkFlag) { + chkFlag = 1; + break; + } else if (chkFlag === 2 && tmp > -1 && tmp < 2) { + chkFlag = 1; + break; + } else if (tmp > -1) { + chkFlag = tmp; + } + } + } + } + node.check_Child_State = chkFlag; + } + }, + //method of event proxy + _event = {}, + //method of event handler + _handler = { + onCheckNode: function (event, node) { + if (node.chkDisabled === true) return false; + var setting = data.getSetting(event.data.treeId); + if (tools.apply(setting.callback.beforeCheck, [setting.treeId, node], true) == false) return true; + var nodeChecked = data.nodeChecked(setting, node); + data.nodeChecked(setting, node, !nodeChecked); + view.checkNodeRelation(setting, node); + var checkObj = $$(node, consts.id.CHECK, setting); + view.setChkClass(setting, checkObj, node); + view.repairParentChkClassWithSelf(setting, node); + setting.treeObj.trigger(consts.event.CHECK, [event, setting.treeId, node]); + return true; + }, + onMouseoverCheck: function (event, node) { + if (node.chkDisabled === true) return false; + var setting = data.getSetting(event.data.treeId), + checkObj = $$(node, consts.id.CHECK, setting); + node.check_Focus = true; + view.setChkClass(setting, checkObj, node); + return true; + }, + onMouseoutCheck: function (event, node) { + if (node.chkDisabled === true) return false; + var setting = data.getSetting(event.data.treeId), + checkObj = $$(node, consts.id.CHECK, setting); + node.check_Focus = false; + view.setChkClass(setting, checkObj, node); + return true; + } + }, + //method of tools for zTree + _tools = {}, + //method of operate ztree dom + _view = { + checkNodeRelation: function (setting, node) { + var pNode, i, l, + r = consts.radio; + var nodeChecked = data.nodeChecked(setting, node); + if (setting.check.chkStyle == r.STYLE) { + var checkedList = data.getRadioCheckedList(setting); + if (nodeChecked) { + if (setting.check.radioType == r.TYPE_ALL) { + for (i = checkedList.length - 1; i >= 0; i--) { + pNode = checkedList[i]; + var pNodeChecked = data.nodeChecked(setting, pNode); + if (pNodeChecked && pNode != node) { + data.nodeChecked(setting, pNode, false); + checkedList.splice(i, 1); + + view.setChkClass(setting, $$(pNode, consts.id.CHECK, setting), pNode); + if (pNode.parentTId != node.parentTId) { + view.repairParentChkClassWithSelf(setting, pNode); + } + } + } + checkedList.push(node); + } else { + var parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting); + var children = data.nodeChildren(setting, parentNode); + for (i = 0, l = children.length; i < l; i++) { + pNode = children[i]; + var pNodeChecked = data.nodeChecked(setting, pNode); + if (pNodeChecked && pNode != node) { + data.nodeChecked(setting, pNode, false); + view.setChkClass(setting, $$(pNode, consts.id.CHECK, setting), pNode); + } + } + } + } else if (setting.check.radioType == r.TYPE_ALL) { + for (i = 0, l = checkedList.length; i < l; i++) { + if (node == checkedList[i]) { + checkedList.splice(i, 1); + break; + } + } + } + + } else { + var children = data.nodeChildren(setting, node); + if (nodeChecked && (!children || children.length == 0 || setting.check.chkboxType.Y.indexOf("s") > -1)) { + view.setSonNodeCheckBox(setting, node, true); + } + if (!nodeChecked && (!children || children.length == 0 || setting.check.chkboxType.N.indexOf("s") > -1)) { + view.setSonNodeCheckBox(setting, node, false); + } + if (nodeChecked && setting.check.chkboxType.Y.indexOf("p") > -1) { + view.setParentNodeCheckBox(setting, node, true); + } + if (!nodeChecked && setting.check.chkboxType.N.indexOf("p") > -1) { + view.setParentNodeCheckBox(setting, node, false); + } + } + }, + makeChkClass: function (setting, node) { + var c = consts.checkbox, r = consts.radio, + fullStyle = ""; + var nodeChecked = data.nodeChecked(setting, node); + if (node.chkDisabled === true) { + fullStyle = c.DISABLED; + } else if (node.halfCheck) { + fullStyle = c.PART; + } else if (setting.check.chkStyle == r.STYLE) { + fullStyle = (node.check_Child_State < 1) ? c.FULL : c.PART; + } else { + fullStyle = nodeChecked ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL : c.PART) : ((node.check_Child_State < 1) ? c.FULL : c.PART); + } + var chkName = setting.check.chkStyle + "_" + (nodeChecked ? c.TRUE : c.FALSE) + "_" + fullStyle; + chkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + "_" + c.FOCUS : chkName; + return consts.className.BUTTON + " " + c.DEFAULT + " " + chkName; + }, + repairAllChk: function (setting, checked) { + if (setting.check.enable && setting.check.chkStyle === consts.checkbox.STYLE) { + var root = data.getRoot(setting); + var children = data.nodeChildren(setting, root); + for (var i = 0, l = children.length; i < l; i++) { + var node = children[i]; + if (node.nocheck !== true && node.chkDisabled !== true) { + data.nodeChecked(setting, node, checked); + } + view.setSonNodeCheckBox(setting, node, checked); + } + } + }, + repairChkClass: function (setting, node) { + if (!node) return; + data.makeChkFlag(setting, node); + if (node.nocheck !== true) { + var checkObj = $$(node, consts.id.CHECK, setting); + view.setChkClass(setting, checkObj, node); + } + }, + repairParentChkClass: function (setting, node) { + if (!node || !node.parentTId) return; + var pNode = node.getParentNode(); + view.repairChkClass(setting, pNode); + view.repairParentChkClass(setting, pNode); + }, + repairParentChkClassWithSelf: function (setting, node) { + if (!node) return; + var children = data.nodeChildren(setting, node); + if (children && children.length > 0) { + view.repairParentChkClass(setting, children[0]); + } else { + view.repairParentChkClass(setting, node); + } + }, + repairSonChkDisabled: function (setting, node, chkDisabled, inherit) { + if (!node) return; + if (node.chkDisabled != chkDisabled) { + node.chkDisabled = chkDisabled; + } + view.repairChkClass(setting, node); + var children = data.nodeChildren(setting, node); + if (children && inherit) { + for (var i = 0, l = children.length; i < l; i++) { + var sNode = children[i]; + view.repairSonChkDisabled(setting, sNode, chkDisabled, inherit); + } + } + }, + repairParentChkDisabled: function (setting, node, chkDisabled, inherit) { + if (!node) return; + if (node.chkDisabled != chkDisabled && inherit) { + node.chkDisabled = chkDisabled; + } + view.repairChkClass(setting, node); + view.repairParentChkDisabled(setting, node.getParentNode(), chkDisabled, inherit); + }, + setChkClass: function (setting, obj, node) { + if (!obj) return; + if (node.nocheck === true) { + obj.hide(); + } else { + obj.show(); + } + obj.attr('class', view.makeChkClass(setting, node)); + }, + setParentNodeCheckBox: function (setting, node, value, srcNode) { + var checkObj = $$(node, consts.id.CHECK, setting); + if (!srcNode) srcNode = node; + data.makeChkFlag(setting, node); + if (node.nocheck !== true && node.chkDisabled !== true) { + data.nodeChecked(setting, node, value); + view.setChkClass(setting, checkObj, node); + if (setting.check.autoCheckTrigger && node != srcNode) { + setting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]); + } + } + if (node.parentTId) { + var pSign = true; + if (!value) { + var pNodes = data.nodeChildren(setting, node.getParentNode()); + for (var i = 0, l = pNodes.length; i < l; i++) { + var pNode = pNodes[i]; + var nodeChecked = data.nodeChecked(setting, pNode); + if ((pNode.nocheck !== true && pNode.chkDisabled !== true && nodeChecked) + || ((pNode.nocheck === true || pNode.chkDisabled === true) && pNode.check_Child_State > 0)) { + pSign = false; + break; + } + } + } + if (pSign) { + view.setParentNodeCheckBox(setting, node.getParentNode(), value, srcNode); + } + } + }, + setSonNodeCheckBox: function (setting, node, value, srcNode) { + if (!node) return; + var checkObj = $$(node, consts.id.CHECK, setting); + if (!srcNode) srcNode = node; + + var hasDisable = false; + var children = data.nodeChildren(setting, node); + if (children) { + for (var i = 0, l = children.length; i < l; i++) { + var sNode = children[i]; + view.setSonNodeCheckBox(setting, sNode, value, srcNode); + if (sNode.chkDisabled === true) hasDisable = true; + } + } + + if (node != data.getRoot(setting) && node.chkDisabled !== true) { + if (hasDisable && node.nocheck !== true) { + data.makeChkFlag(setting, node); + } + if (node.nocheck !== true && node.chkDisabled !== true) { + data.nodeChecked(setting, node, value); + if (!hasDisable) node.check_Child_State = (children && children.length > 0) ? (value ? 2 : 0) : -1; + } else { + node.check_Child_State = -1; + } + view.setChkClass(setting, checkObj, node); + if (setting.check.autoCheckTrigger && node != srcNode && node.nocheck !== true && node.chkDisabled !== true) { + setting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]); + } + } + + } + }, + + _z = { + tools: _tools, + view: _view, + event: _event, + data: _data + }; + $.extend(true, $.fn.zTree.consts, _consts); + $.extend(true, $.fn.zTree._z, _z); + + var zt = $.fn.zTree, + tools = zt._z.tools, + consts = zt.consts, + view = zt._z.view, + data = zt._z.data, + event = zt._z.event, + $$ = tools.$; + + data.nodeChecked = function (setting, node, newChecked) { + if (!node) { + return false; + } + var key = setting.data.key.checked; + if (typeof newChecked !== 'undefined') { + if (typeof newChecked === "string") { + newChecked = tools.eqs(newChecked, "true"); + } + newChecked = !!newChecked; + node[key] = newChecked; + } else if (typeof node[key] == "string"){ + node[key] = tools.eqs(node[key], "true"); + } else { + node[key] = !!node[key]; + } + return node[key]; + }; + + data.exSetting(_setting); + data.addInitBind(_bindEvent); + data.addInitUnBind(_unbindEvent); + data.addInitCache(_initCache); + data.addInitNode(_initNode); + data.addInitProxy(_eventProxy, true); + data.addInitRoot(_initRoot); + data.addBeforeA(_beforeA); + data.addZTreeTools(_zTreeTools); + + var _createNodes = view.createNodes; + view.createNodes = function (setting, level, nodes, parentNode, index) { + if (_createNodes) _createNodes.apply(view, arguments); + if (!nodes) return; + view.repairParentChkClassWithSelf(setting, parentNode); + } + var _removeNode = view.removeNode; + view.removeNode = function (setting, node) { + var parentNode = node.getParentNode(); + if (_removeNode) _removeNode.apply(view, arguments); + if (!node || !parentNode) return; + view.repairChkClass(setting, parentNode); + view.repairParentChkClass(setting, parentNode); + } + + var _appendNodes = view.appendNodes; + view.appendNodes = function (setting, level, nodes, parentNode, index, initFlag, openFlag) { + var html = ""; + if (_appendNodes) { + html = _appendNodes.apply(view, arguments); + } + if (parentNode) { + data.makeChkFlag(setting, parentNode); + } + return html; + } +})(jQuery); \ No newline at end of file diff --git a/public/self/ztree/js/jquery.ztree.exedit.js b/public/self/ztree/js/jquery.ztree.exedit.js new file mode 100644 index 000000000..cfa83baf2 --- /dev/null +++ b/public/self/ztree/js/jquery.ztree.exedit.js @@ -0,0 +1,1207 @@ +/* + * JQuery zTree exedit + * v3.5.48 + * http://treejs.cn/ + * + * Copyright (c) 2010 Hunter.z + * + * Licensed same as jquery - MIT License + * http://www.opensource.org/licenses/mit-license.php + * + * Date: 2020-11-21 + */ + +(function ($) { + //default consts of exedit + var _consts = { + event: { + DRAG: "ztree_drag", + DROP: "ztree_drop", + RENAME: "ztree_rename", + DRAGMOVE: "ztree_dragmove" + }, + id: { + EDIT: "_edit", + INPUT: "_input", + REMOVE: "_remove" + }, + move: { + TYPE_INNER: "inner", + TYPE_PREV: "prev", + TYPE_NEXT: "next" + }, + node: { + CURSELECTED_EDIT: "curSelectedNode_Edit", + TMPTARGET_TREE: "tmpTargetzTree", + TMPTARGET_NODE: "tmpTargetNode" + } + }, + //default setting of exedit + _setting = { + edit: { + enable: false, + editNameSelectAll: false, + showRemoveBtn: true, + showRenameBtn: true, + removeTitle: "remove", + renameTitle: "rename", + drag: { + autoExpandTrigger: false, + isCopy: true, + isMove: true, + prev: true, + next: true, + inner: true, + minMoveSize: 5, + borderMax: 10, + borderMin: -5, + maxShowNodeNum: 5, + autoOpenTime: 500 + } + }, + view: { + addHoverDom: null, + removeHoverDom: null + }, + callback: { + beforeDrag: null, + beforeDragOpen: null, + beforeDrop: null, + beforeEditName: null, + beforeRename: null, + onDrag: null, + onDragMove: null, + onDrop: null, + onRename: null + } + }, + //default root of exedit + _initRoot = function (setting) { + var r = data.getRoot(setting), rs = data.getRoots(); + r.curEditNode = null; + r.curEditInput = null; + r.curHoverNode = null; + r.dragFlag = 0; + r.dragNodeShowBefore = []; + r.dragMaskList = new Array(); + rs.showHoverDom = true; + }, + //default cache of exedit + _initCache = function (treeId) { + }, + //default bind event of exedit + _bindEvent = function (setting) { + var o = setting.treeObj; + var c = consts.event; + o.bind(c.RENAME, function (event, treeId, treeNode, isCancel) { + tools.apply(setting.callback.onRename, [event, treeId, treeNode, isCancel]); + }); + + o.bind(c.DRAG, function (event, srcEvent, treeId, treeNodes) { + tools.apply(setting.callback.onDrag, [srcEvent, treeId, treeNodes]); + }); + + o.bind(c.DRAGMOVE, function (event, srcEvent, treeId, treeNodes) { + tools.apply(setting.callback.onDragMove, [srcEvent, treeId, treeNodes]); + }); + + o.bind(c.DROP, function (event, srcEvent, treeId, treeNodes, targetNode, moveType, isCopy) { + tools.apply(setting.callback.onDrop, [srcEvent, treeId, treeNodes, targetNode, moveType, isCopy]); + }); + }, + _unbindEvent = function (setting) { + var o = setting.treeObj; + var c = consts.event; + o.unbind(c.RENAME); + o.unbind(c.DRAG); + o.unbind(c.DRAGMOVE); + o.unbind(c.DROP); + }, + //default event proxy of exedit + _eventProxy = function (e) { + var target = e.target, + setting = data.getSetting(e.data.treeId), + relatedTarget = e.relatedTarget, + tId = "", node = null, + nodeEventType = "", treeEventType = "", + nodeEventCallback = null, treeEventCallback = null, + tmp = null; + + if (tools.eqs(e.type, "mouseover")) { + tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]); + if (tmp) { + tId = tools.getNodeMainDom(tmp).id; + nodeEventType = "hoverOverNode"; + } + } else if (tools.eqs(e.type, "mouseout")) { + tmp = tools.getMDom(setting, relatedTarget, [{tagName: "a", attrName: "treeNode" + consts.id.A}]); + if (!tmp) { + tId = "remove"; + nodeEventType = "hoverOutNode"; + } + } else if (tools.eqs(e.type, "mousedown")) { + tmp = tools.getMDom(setting, target, [{tagName: "a", attrName: "treeNode" + consts.id.A}]); + if (tmp) { + tId = tools.getNodeMainDom(tmp).id; + nodeEventType = "mousedownNode"; + } + } + if (tId.length > 0) { + node = data.getNodeCache(setting, tId); + switch (nodeEventType) { + case "mousedownNode" : + nodeEventCallback = _handler.onMousedownNode; + break; + case "hoverOverNode" : + nodeEventCallback = _handler.onHoverOverNode; + break; + case "hoverOutNode" : + nodeEventCallback = _handler.onHoverOutNode; + break; + } + } + var proxyResult = { + stop: false, + node: node, + nodeEventType: nodeEventType, + nodeEventCallback: nodeEventCallback, + treeEventType: treeEventType, + treeEventCallback: treeEventCallback + }; + return proxyResult + }, + //default init node of exedit + _initNode = function (setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) { + if (!n) return; + n.isHover = false; + n.editNameFlag = false; + }, + //update zTreeObj, add method of edit + _zTreeTools = function (setting, zTreeTools) { + zTreeTools.cancelEditName = function (newName) { + var root = data.getRoot(this.setting); + if (!root.curEditNode) return; + view.cancelCurEditNode(this.setting, newName ? newName : null, true); + } + zTreeTools.copyNode = function (targetNode, node, moveType, isSilent) { + if (!node) return null; + var isParent = data.nodeIsParent(setting, targetNode); + if (targetNode && !isParent && this.setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) return null; + var _this = this, + newNode = tools.clone(node); + if (!targetNode) { + targetNode = null; + moveType = consts.move.TYPE_INNER; + } + if (moveType == consts.move.TYPE_INNER) { + function copyCallback() { + view.addNodes(_this.setting, targetNode, -1, [newNode], isSilent); + } + + if (tools.canAsync(this.setting, targetNode)) { + view.asyncNode(this.setting, targetNode, isSilent, copyCallback); + } else { + copyCallback(); + } + } else { + view.addNodes(this.setting, targetNode.parentNode, -1, [newNode], isSilent); + view.moveNode(this.setting, targetNode, newNode, moveType, false, isSilent); + } + return newNode; + } + zTreeTools.editName = function (node) { + if (!node || !node.tId || node !== data.getNodeCache(this.setting, node.tId)) return; + if (node.parentTId) view.expandCollapseParentNode(this.setting, node.getParentNode(), true); + view.editNode(this.setting, node) + } + zTreeTools.moveNode = function (targetNode, node, moveType, isSilent) { + if (!node) return node; + var isParent = data.nodeIsParent(setting, targetNode); + if (targetNode && !isParent && this.setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) { + return null; + } else if (targetNode && ((node.parentTId == targetNode.tId && moveType == consts.move.TYPE_INNER) || $$(node, this.setting).find("#" + targetNode.tId).length > 0)) { + return null; + } else if (!targetNode) { + targetNode = null; + } + var _this = this; + + function moveCallback() { + view.moveNode(_this.setting, targetNode, node, moveType, false, isSilent); + } + + if (tools.canAsync(this.setting, targetNode) && moveType === consts.move.TYPE_INNER) { + view.asyncNode(this.setting, targetNode, isSilent, moveCallback); + } else { + moveCallback(); + } + return node; + } + zTreeTools.setEditable = function (editable) { + this.setting.edit.enable = editable; + return this.refresh(); + } + }, + //method of operate data + _data = { + setSonNodeLevel: function (setting, parentNode, node) { + if (!node) return; + var children = data.nodeChildren(setting, node); + var oldLevel = node.level; + node.level = (parentNode) ? parentNode.level + 1 : 0; + view.repairNodeLevelClass(setting, node, oldLevel); + + if (!children) return; + for (var i = 0, l = children.length; i < l; i++) { + if (children[i]) data.setSonNodeLevel(setting, node, children[i]); + } + } + }, + //method of event proxy + _event = {}, + //method of event handler + _handler = { + onHoverOverNode: function (event, node) { + var setting = data.getSetting(event.data.treeId), + root = data.getRoot(setting); + if (root.curHoverNode != node) { + _handler.onHoverOutNode(event); + } + root.curHoverNode = node; + view.addHoverDom(setting, node); + }, + onHoverOutNode: function (event, node) { + var setting = data.getSetting(event.data.treeId), + root = data.getRoot(setting); + if (root.curHoverNode && !data.isSelectedNode(setting, root.curHoverNode)) { + view.removeTreeDom(setting, root.curHoverNode); + root.curHoverNode = null; + } + }, + onMousedownNode: function (eventMouseDown, _node) { + var i, l, + setting = data.getSetting(eventMouseDown.data.treeId), + root = data.getRoot(setting), roots = data.getRoots(); + //right click can't drag & drop + if (eventMouseDown.button == 2 || !setting.edit.enable || (!setting.edit.drag.isCopy && !setting.edit.drag.isMove)) return true; + + //input of edit node name can't drag & drop + var target = eventMouseDown.target, + _nodes = data.getRoot(setting).curSelectedList, + nodes = []; + if (!data.isSelectedNode(setting, _node)) { + nodes = [_node]; + } else { + for (i = 0, l = _nodes.length; i < l; i++) { + if (_nodes[i].editNameFlag && tools.eqs(target.tagName, "input") && target.getAttribute("treeNode" + consts.id.INPUT) !== null) { + return true; + } + nodes.push(_nodes[i]); + if (nodes[0].parentTId !== _nodes[i].parentTId) { + nodes = [_node]; + break; + } + } + } + + view.editNodeBlur = true; + view.cancelCurEditNode(setting); + + var doc = $(setting.treeObj.get(0).ownerDocument), + body = $(setting.treeObj.get(0).ownerDocument.body), curNode, tmpArrow, tmpTarget, + isOtherTree = false, + targetSetting = setting, + sourceSetting = setting, + preNode, nextNode, + preTmpTargetNodeId = null, + preTmpMoveType = null, + tmpTargetNodeId = null, + moveType = consts.move.TYPE_INNER, + mouseDownX = eventMouseDown.clientX, + mouseDownY = eventMouseDown.clientY, + startTime = (new Date()).getTime(); + + if (tools.uCanDo(setting)) { + doc.bind("mousemove", _docMouseMove); + } + + function _docMouseMove(event) { + //avoid start drag after click node + if (root.dragFlag == 0 && Math.abs(mouseDownX - event.clientX) < setting.edit.drag.minMoveSize + && Math.abs(mouseDownY - event.clientY) < setting.edit.drag.minMoveSize) { + return true; + } + var i, l, tmpNode, tmpDom, tmpNodes; + body.css("cursor", "pointer"); + + if (root.dragFlag == 0) { + if (tools.apply(setting.callback.beforeDrag, [setting.treeId, nodes], true) == false) { + _docMouseUp(event); + return true; + } + + for (i = 0, l = nodes.length; i < l; i++) { + if (i == 0) { + root.dragNodeShowBefore = []; + } + tmpNode = nodes[i]; + if (data.nodeIsParent(setting, tmpNode) && tmpNode.open) { + view.expandCollapseNode(setting, tmpNode, !tmpNode.open); + root.dragNodeShowBefore[tmpNode.tId] = true; + } else { + root.dragNodeShowBefore[tmpNode.tId] = false; + } + } + + root.dragFlag = 1; + roots.showHoverDom = false; + tools.showIfameMask(setting, true); + + //sort + var isOrder = true, lastIndex = -1; + if (nodes.length > 1) { + var pNodes = nodes[0].parentTId ? data.nodeChildren(setting, nodes[0].getParentNode()) : data.getNodes(setting); + tmpNodes = []; + for (i = 0, l = pNodes.length; i < l; i++) { + if (root.dragNodeShowBefore[pNodes[i].tId] !== undefined) { + if (isOrder && lastIndex > -1 && (lastIndex + 1) !== i) { + isOrder = false; + } + tmpNodes.push(pNodes[i]); + lastIndex = i; + } + if (nodes.length === tmpNodes.length) { + nodes = tmpNodes; + break; + } + } + } + if (isOrder) { + preNode = nodes[0].getPreNode(); + nextNode = nodes[nodes.length - 1].getNextNode(); + } + + //set node in selected + curNode = $$("
        ", setting); + for (i = 0, l = nodes.length; i < l; i++) { + tmpNode = nodes[i]; + tmpNode.editNameFlag = false; + view.selectNode(setting, tmpNode, i > 0); + view.removeTreeDom(setting, tmpNode); + + if (i > setting.edit.drag.maxShowNodeNum - 1) { + continue; + } + + tmpDom = $$("
      • ", setting); + tmpDom.append($$(tmpNode, consts.id.A, setting).clone()); + tmpDom.css("padding", "0"); + tmpDom.children("#" + tmpNode.tId + consts.id.A).removeClass(consts.node.CURSELECTED); + curNode.append(tmpDom); + if (i == setting.edit.drag.maxShowNodeNum - 1) { + tmpDom = $$("
      • ...
      • ", setting); + curNode.append(tmpDom); + } + } + curNode.attr("id", nodes[0].tId + consts.id.UL + "_tmp"); + curNode.addClass(setting.treeObj.attr("class")); + curNode.appendTo(body); + + tmpArrow = $$("", setting); + tmpArrow.attr("id", "zTreeMove_arrow_tmp"); + tmpArrow.appendTo(body); + + setting.treeObj.trigger(consts.event.DRAG, [event, setting.treeId, nodes]); + } + + if (root.dragFlag == 1) { + if (tmpTarget && tmpArrow.attr("id") == event.target.id && tmpTargetNodeId && (event.clientX + doc.scrollLeft() + 2) > ($("#" + tmpTargetNodeId + consts.id.A, tmpTarget).offset().left)) { + var xT = $("#" + tmpTargetNodeId + consts.id.A, tmpTarget); + event.target = (xT.length > 0) ? xT.get(0) : event.target; + } else if (tmpTarget) { + tmpTarget.removeClass(consts.node.TMPTARGET_TREE); + if (tmpTargetNodeId) $("#" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + "_" + consts.move.TYPE_PREV) + .removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_INNER); + } + tmpTarget = null; + tmpTargetNodeId = null; + + //judge drag & drop in multi ztree + isOtherTree = false; + targetSetting = setting; + var settings = data.getSettings(); + for (var s in settings) { + if (settings[s].treeId && settings[s].edit.enable && settings[s].treeId != setting.treeId + && (event.target.id == settings[s].treeId || $(event.target).parents("#" + settings[s].treeId).length > 0)) { + isOtherTree = true; + targetSetting = settings[s]; + } + } + + var docScrollTop = doc.scrollTop(), + docScrollLeft = doc.scrollLeft(), + treeOffset = targetSetting.treeObj.offset(), + scrollHeight = targetSetting.treeObj.get(0).scrollHeight, + scrollWidth = targetSetting.treeObj.get(0).scrollWidth, + dTop = (event.clientY + docScrollTop - treeOffset.top), + dBottom = (targetSetting.treeObj.height() + treeOffset.top - event.clientY - docScrollTop), + dLeft = (event.clientX + docScrollLeft - treeOffset.left), + dRight = (targetSetting.treeObj.width() + treeOffset.left - event.clientX - docScrollLeft), + isTop = (dTop < setting.edit.drag.borderMax && dTop > setting.edit.drag.borderMin), + isBottom = (dBottom < setting.edit.drag.borderMax && dBottom > setting.edit.drag.borderMin), + isLeft = (dLeft < setting.edit.drag.borderMax && dLeft > setting.edit.drag.borderMin), + isRight = (dRight < setting.edit.drag.borderMax && dRight > setting.edit.drag.borderMin), + isTreeInner = dTop > setting.edit.drag.borderMin && dBottom > setting.edit.drag.borderMin && dLeft > setting.edit.drag.borderMin && dRight > setting.edit.drag.borderMin, + isTreeTop = (isTop && targetSetting.treeObj.scrollTop() <= 0), + isTreeBottom = (isBottom && (targetSetting.treeObj.scrollTop() + targetSetting.treeObj.height() + 10) >= scrollHeight), + isTreeLeft = (isLeft && targetSetting.treeObj.scrollLeft() <= 0), + isTreeRight = (isRight && (targetSetting.treeObj.scrollLeft() + targetSetting.treeObj.width() + 10) >= scrollWidth); + + if (event.target && tools.isChildOrSelf(event.target, targetSetting.treeId)) { + //get node
      • dom + var targetObj = event.target; + while (targetObj && targetObj.tagName && !tools.eqs(targetObj.tagName, "li") && targetObj.id != targetSetting.treeId) { + targetObj = targetObj.parentNode; + } + + var canMove = true; + //don't move to self or children of self + for (i = 0, l = nodes.length; i < l; i++) { + tmpNode = nodes[i]; + if (targetObj.id === tmpNode.tId) { + canMove = false; + break; + } else if ($$(tmpNode, setting).find("#" + targetObj.id).length > 0) { + canMove = false; + break; + } + } + if (canMove && event.target && tools.isChildOrSelf(event.target, targetObj.id + consts.id.A)) { + tmpTarget = $(targetObj); + tmpTargetNodeId = targetObj.id; + } + } + + //the mouse must be in zTree + tmpNode = nodes[0]; + if (isTreeInner && tools.isChildOrSelf(event.target, targetSetting.treeId)) { + //judge mouse move in root of ztree + if (!tmpTarget && (event.target.id == targetSetting.treeId || isTreeTop || isTreeBottom || isTreeLeft || isTreeRight) && (isOtherTree || (!isOtherTree && tmpNode.parentTId))) { + tmpTarget = targetSetting.treeObj; + } + //auto scroll top + if (isTop) { + targetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop() - 10); + } else if (isBottom) { + targetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop() + 10); + } + if (isLeft) { + targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft() - 10); + } else if (isRight) { + targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft() + 10); + } + //auto scroll left + if (tmpTarget && tmpTarget != targetSetting.treeObj && tmpTarget.offset().left < targetSetting.treeObj.offset().left) { + targetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft() + tmpTarget.offset().left - targetSetting.treeObj.offset().left); + } + } + + curNode.css({ + "top": (event.clientY + docScrollTop + 3) + "px", + "left": (event.clientX + docScrollLeft + 3) + "px" + }); + + var dX = 0; + var dY = 0; + if (tmpTarget && tmpTarget.attr("id") != targetSetting.treeId) { + var tmpTargetNode = tmpTargetNodeId == null ? null : data.getNodeCache(targetSetting, tmpTargetNodeId), + isCopy = ((event.ctrlKey || event.metaKey) && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy), + isPrev = !!(preNode && tmpTargetNodeId === preNode.tId), + isNext = !!(nextNode && tmpTargetNodeId === nextNode.tId), + isInner = (tmpNode.parentTId && tmpNode.parentTId == tmpTargetNodeId), + canPrev = (isCopy || !isNext) && tools.apply(targetSetting.edit.drag.prev, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.prev), + canNext = (isCopy || !isPrev) && tools.apply(targetSetting.edit.drag.next, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.next), + canInner = (isCopy || !isInner) && !(targetSetting.data.keep.leaf && !data.nodeIsParent(setting, tmpTargetNode)) && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.inner); + + function clearMove() { + tmpTarget = null; + tmpTargetNodeId = ""; + moveType = consts.move.TYPE_INNER; + tmpArrow.css({ + "display": "none" + }); + if (window.zTreeMoveTimer) { + clearTimeout(window.zTreeMoveTimer); + window.zTreeMoveTargetNodeTId = null + } + } + + if (!canPrev && !canNext && !canInner) { + clearMove(); + } else { + var tmpTargetA = $("#" + tmpTargetNodeId + consts.id.A, tmpTarget), + tmpNextA = tmpTargetNode.isLastNode ? null : $("#" + tmpTargetNode.getNextNode().tId + consts.id.A, tmpTarget.next()), + tmpTop = tmpTargetA.offset().top, + tmpLeft = tmpTargetA.offset().left, + prevPercent = canPrev ? (canInner ? 0.25 : (canNext ? 0.5 : 1)) : -1, + nextPercent = canNext ? (canInner ? 0.75 : (canPrev ? 0.5 : 0)) : -1, + dY_percent = (event.clientY + docScrollTop - tmpTop) / tmpTargetA.height(); + + if ((prevPercent == 1 || dY_percent <= prevPercent && dY_percent >= -.2) && canPrev) { + dX = 1 - tmpArrow.width(); + dY = tmpTop - tmpArrow.height() / 2; + moveType = consts.move.TYPE_PREV; + } else if ((nextPercent == 0 || dY_percent >= nextPercent && dY_percent <= 1.2) && canNext) { + dX = 1 - tmpArrow.width(); + dY = (tmpNextA == null || (data.nodeIsParent(setting, tmpTargetNode) && tmpTargetNode.open)) ? (tmpTop + tmpTargetA.height() - tmpArrow.height() / 2) : (tmpNextA.offset().top - tmpArrow.height() / 2); + moveType = consts.move.TYPE_NEXT; + } else if (canInner) { + dX = 5 - tmpArrow.width(); + dY = tmpTop; + moveType = consts.move.TYPE_INNER; + } else { + clearMove(); + } + + if (tmpTarget) { + tmpArrow.css({ + "display": "block", + "top": dY + "px", + "left": (tmpLeft + dX) + "px" + }); + tmpTargetA.addClass(consts.node.TMPTARGET_NODE + "_" + moveType); + + if (preTmpTargetNodeId != tmpTargetNodeId || preTmpMoveType != moveType) { + startTime = (new Date()).getTime(); + } + if (tmpTargetNode && data.nodeIsParent(setting, tmpTargetNode) && moveType == consts.move.TYPE_INNER) { + var startTimer = true; + if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId !== tmpTargetNode.tId) { + clearTimeout(window.zTreeMoveTimer); + window.zTreeMoveTargetNodeTId = null; + } else if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId === tmpTargetNode.tId) { + startTimer = false; + } + if (startTimer) { + window.zTreeMoveTimer = setTimeout(function () { + if (moveType != consts.move.TYPE_INNER) return; + if (tmpTargetNode && data.nodeIsParent(setting, tmpTargetNode) && !tmpTargetNode.open && (new Date()).getTime() - startTime > targetSetting.edit.drag.autoOpenTime + && tools.apply(targetSetting.callback.beforeDragOpen, [targetSetting.treeId, tmpTargetNode], true)) { + view.switchNode(targetSetting, tmpTargetNode); + if (targetSetting.edit.drag.autoExpandTrigger) { + targetSetting.treeObj.trigger(consts.event.EXPAND, [targetSetting.treeId, tmpTargetNode]); + } + } + }, targetSetting.edit.drag.autoOpenTime + 50); + window.zTreeMoveTargetNodeTId = tmpTargetNode.tId; + } + } + } + } + } else { + moveType = consts.move.TYPE_INNER; + if (tmpTarget && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, null], !!targetSetting.edit.drag.inner)) { + tmpTarget.addClass(consts.node.TMPTARGET_TREE); + } else { + tmpTarget = null; + } + tmpArrow.css({ + "display": "none" + }); + if (window.zTreeMoveTimer) { + clearTimeout(window.zTreeMoveTimer); + window.zTreeMoveTargetNodeTId = null; + } + } + preTmpTargetNodeId = tmpTargetNodeId; + preTmpMoveType = moveType; + + setting.treeObj.trigger(consts.event.DRAGMOVE, [event, setting.treeId, nodes]); + } + return false; + } + + doc.bind("mouseup", _docMouseUp); + + function _docMouseUp(event) { + if (window.zTreeMoveTimer) { + clearTimeout(window.zTreeMoveTimer); + window.zTreeMoveTargetNodeTId = null; + } + preTmpTargetNodeId = null; + preTmpMoveType = null; + doc.unbind("mousemove", _docMouseMove); + doc.unbind("mouseup", _docMouseUp); + doc.unbind("selectstart", _docSelect); + body.css("cursor", ""); + if (tmpTarget) { + tmpTarget.removeClass(consts.node.TMPTARGET_TREE); + if (tmpTargetNodeId) $("#" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + "_" + consts.move.TYPE_PREV) + .removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + "_" + _consts.move.TYPE_INNER); + } + tools.showIfameMask(setting, false); + + roots.showHoverDom = true; + if (root.dragFlag == 0) return; + root.dragFlag = 0; + + var i, l, tmpNode; + for (i = 0, l = nodes.length; i < l; i++) { + tmpNode = nodes[i]; + if (data.nodeIsParent(setting, tmpNode) && root.dragNodeShowBefore[tmpNode.tId] && !tmpNode.open) { + view.expandCollapseNode(setting, tmpNode, !tmpNode.open); + delete root.dragNodeShowBefore[tmpNode.tId]; + } + } + + if (curNode) curNode.remove(); + if (tmpArrow) tmpArrow.remove(); + + var isCopy = ((event.ctrlKey || event.metaKey) && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy); + if (!isCopy && tmpTarget && tmpTargetNodeId && nodes[0].parentTId && tmpTargetNodeId == nodes[0].parentTId && moveType == consts.move.TYPE_INNER) { + tmpTarget = null; + } + if (tmpTarget) { + var dragTargetNode = tmpTargetNodeId == null ? null : data.getNodeCache(targetSetting, tmpTargetNodeId); + if (tools.apply(setting.callback.beforeDrop, [targetSetting.treeId, nodes, dragTargetNode, moveType, isCopy], true) == false) { + view.selectNodes(sourceSetting, nodes); + return; + } + var newNodes = isCopy ? tools.clone(nodes) : nodes; + + function dropCallback() { + if (isOtherTree) { + if (!isCopy) { + for (var i = 0, l = nodes.length; i < l; i++) { + view.removeNode(setting, nodes[i]); + } + } + if (moveType == consts.move.TYPE_INNER) { + view.addNodes(targetSetting, dragTargetNode, -1, newNodes); + } else { + view.addNodes(targetSetting, dragTargetNode.getParentNode(), moveType == consts.move.TYPE_PREV ? dragTargetNode.getIndex() : dragTargetNode.getIndex() + 1, newNodes); + } + } else { + if (isCopy && moveType == consts.move.TYPE_INNER) { + view.addNodes(targetSetting, dragTargetNode, -1, newNodes); + } else if (isCopy) { + view.addNodes(targetSetting, dragTargetNode.getParentNode(), moveType == consts.move.TYPE_PREV ? dragTargetNode.getIndex() : dragTargetNode.getIndex() + 1, newNodes); + } else { + if (moveType != consts.move.TYPE_NEXT) { + for (i = 0, l = newNodes.length; i < l; i++) { + view.moveNode(targetSetting, dragTargetNode, newNodes[i], moveType, false); + } + } else { + for (i = -1, l = newNodes.length - 1; i < l; l--) { + view.moveNode(targetSetting, dragTargetNode, newNodes[l], moveType, false); + } + } + } + } + view.selectNodes(targetSetting, newNodes); + + var a = $$(newNodes[0], setting).get(0); + view.scrollIntoView(setting, a); + + setting.treeObj.trigger(consts.event.DROP, [event, targetSetting.treeId, newNodes, dragTargetNode, moveType, isCopy]); + } + + if (moveType == consts.move.TYPE_INNER && tools.canAsync(targetSetting, dragTargetNode)) { + view.asyncNode(targetSetting, dragTargetNode, false, dropCallback); + } else { + dropCallback(); + } + + } else { + view.selectNodes(sourceSetting, nodes); + setting.treeObj.trigger(consts.event.DROP, [event, setting.treeId, nodes, null, null, null]); + } + } + + doc.bind("selectstart", _docSelect); + + function _docSelect() { + return false; + } + + // 2018-03-30 FireFox has fixed this issue. + //Avoid FireFox's Bug + //If zTree Div CSS set 'overflow', so drag node outside of zTree, and event.target is error. + // if(eventMouseDown.preventDefault) { + // eventMouseDown.preventDefault(); + // } + return true; + } + }, + //method of tools for zTree + _tools = { + getAbs: function (obj) { + var oRect = obj.getBoundingClientRect(), + scrollTop = document.body.scrollTop + document.documentElement.scrollTop, + scrollLeft = document.body.scrollLeft + document.documentElement.scrollLeft; + return [oRect.left + scrollLeft, oRect.top + scrollTop]; + }, + inputFocus: function (inputObj) { + if (inputObj.get(0)) { + inputObj.focus(); + tools.setCursorPosition(inputObj.get(0), inputObj.val().length); + } + }, + inputSelect: function (inputObj) { + if (inputObj.get(0)) { + inputObj.focus(); + inputObj.select(); + } + }, + setCursorPosition: function (obj, pos) { + if (obj.setSelectionRange) { + obj.focus(); + obj.setSelectionRange(pos, pos); + } else if (obj.createTextRange) { + var range = obj.createTextRange(); + range.collapse(true); + range.moveEnd('character', pos); + range.moveStart('character', pos); + range.select(); + } + }, + showIfameMask: function (setting, showSign) { + var root = data.getRoot(setting); + //clear full mask + while (root.dragMaskList.length > 0) { + root.dragMaskList[0].remove(); + root.dragMaskList.shift(); + } + if (showSign) { + //show mask + var iframeList = $$("iframe", setting); + for (var i = 0, l = iframeList.length; i < l; i++) { + var obj = iframeList.get(i), + r = tools.getAbs(obj), + dragMask = $$("
        ", setting); + dragMask.appendTo($$("body", setting)); + root.dragMaskList.push(dragMask); + } + } + } + }, + //method of operate ztree dom + _view = { + addEditBtn: function (setting, node) { + if (node.editNameFlag || $$(node, consts.id.EDIT, setting).length > 0) { + return; + } + if (!tools.apply(setting.edit.showRenameBtn, [setting.treeId, node], setting.edit.showRenameBtn)) { + return; + } + var aObj = $$(node, consts.id.A, setting), + editStr = ""; + aObj.append(editStr); + + $$(node, consts.id.EDIT, setting).bind('click', + function () { + if (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeEditName, [setting.treeId, node], true) == false) return false; + view.editNode(setting, node); + return false; + } + ).show(); + }, + addRemoveBtn: function (setting, node) { + if (node.editNameFlag || $$(node, consts.id.REMOVE, setting).length > 0) { + return; + } + if (!tools.apply(setting.edit.showRemoveBtn, [setting.treeId, node], setting.edit.showRemoveBtn)) { + return; + } + var aObj = $$(node, consts.id.A, setting), + removeStr = ""; + aObj.append(removeStr); + + $$(node, consts.id.REMOVE, setting).bind('click', + function () { + if (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return false; + view.removeNode(setting, node); + setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]); + return false; + } + ).bind('mousedown', + function (eventMouseDown) { + return true; + } + ).show(); + }, + addHoverDom: function (setting, node) { + if (data.getRoots().showHoverDom) { + node.isHover = true; + if (setting.edit.enable) { + view.addEditBtn(setting, node); + view.addRemoveBtn(setting, node); + } + tools.apply(setting.view.addHoverDom, [setting.treeId, node]); + } + }, + cancelCurEditNode: function (setting, forceName, isCancel) { + var root = data.getRoot(setting), + node = root.curEditNode; + + if (node) { + var inputObj = root.curEditInput, + newName = forceName ? forceName : (isCancel ? data.nodeName(setting, node) : inputObj.val()); + if (tools.apply(setting.callback.beforeRename, [setting.treeId, node, newName, isCancel], true) === false) { + return false; + } + data.nodeName(setting, node, newName); + var aObj = $$(node, consts.id.A, setting); + aObj.removeClass(consts.node.CURSELECTED_EDIT); + inputObj.unbind(); + view.setNodeName(setting, node); + node.editNameFlag = false; + root.curEditNode = null; + root.curEditInput = null; + view.selectNode(setting, node, false); + setting.treeObj.trigger(consts.event.RENAME, [setting.treeId, node, isCancel]); + } + root.noSelection = true; + return true; + }, + editNode: function (setting, node) { + var root = data.getRoot(setting); + view.editNodeBlur = false; + if (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) { + setTimeout(function () { + tools.inputFocus(root.curEditInput); + }, 0); + return; + } + node.editNameFlag = true; + view.removeTreeDom(setting, node); + view.cancelCurEditNode(setting); + view.selectNode(setting, node, false); + $$(node, consts.id.SPAN, setting).html(""); + var inputObj = $$(node, consts.id.INPUT, setting); + inputObj.attr("value", data.nodeName(setting, node)); + if (setting.edit.editNameSelectAll) { + tools.inputSelect(inputObj); + } else { + tools.inputFocus(inputObj); + } + + inputObj.bind('blur', function (event) { + if (!view.editNodeBlur) { + view.cancelCurEditNode(setting); + } + }).bind('keydown', function (event) { + if (event.keyCode == "13") { + view.editNodeBlur = true; + view.cancelCurEditNode(setting); + } else if (event.keyCode == "27") { + view.cancelCurEditNode(setting, null, true); + } + }).bind('click', function (event) { + return false; + }).bind('dblclick', function (event) { + return false; + }); + + $$(node, consts.id.A, setting).addClass(consts.node.CURSELECTED_EDIT); + root.curEditInput = inputObj; + root.noSelection = false; + root.curEditNode = node; + }, + moveNode: function (setting, targetNode, node, moveType, animateFlag, isSilent) { + var root = data.getRoot(setting); + if (targetNode == node) return; + if (setting.data.keep.leaf && targetNode && !data.nodeIsParent(setting, targetNode) && moveType == consts.move.TYPE_INNER) return; + var oldParentNode = (node.parentTId ? node.getParentNode() : root), + targetNodeIsRoot = (targetNode === null || targetNode == root); + if (targetNodeIsRoot && targetNode === null) targetNode = root; + if (targetNodeIsRoot) moveType = consts.move.TYPE_INNER; + var targetParentNode = (targetNode.parentTId ? targetNode.getParentNode() : root); + + if (moveType != consts.move.TYPE_PREV && moveType != consts.move.TYPE_NEXT) { + moveType = consts.move.TYPE_INNER; + } + + if (moveType == consts.move.TYPE_INNER) { + if (targetNodeIsRoot) { + //parentTId of root node is null + node.parentTId = null; + } else { + if (!data.nodeIsParent(setting, targetNode)) { + data.nodeIsParent(setting, targetNode, true); + targetNode.open = !!targetNode.open; + view.setNodeLineIcos(setting, targetNode); + } + node.parentTId = targetNode.tId; + } + } + + //move node Dom + var targetObj, target_ulObj; + if (targetNodeIsRoot) { + targetObj = setting.treeObj; + target_ulObj = targetObj; + } else { + if (!isSilent && moveType == consts.move.TYPE_INNER) { + view.expandCollapseNode(setting, targetNode, true, false); + } else if (!isSilent) { + view.expandCollapseNode(setting, targetNode.getParentNode(), true, false); + } + targetObj = $$(targetNode, setting); + target_ulObj = $$(targetNode, consts.id.UL, setting); + if (!!targetObj.get(0) && !target_ulObj.get(0)) { + var ulstr = []; + view.makeUlHtml(setting, targetNode, ulstr, ''); + targetObj.append(ulstr.join('')); + } + target_ulObj = $$(targetNode, consts.id.UL, setting); + } + var nodeDom = $$(node, setting); + if (!nodeDom.get(0)) { + nodeDom = view.appendNodes(setting, node.level, [node], null, -1, false, true).join(''); + } else if (!targetObj.get(0)) { + nodeDom.remove(); + } + if (target_ulObj.get(0) && moveType == consts.move.TYPE_INNER) { + target_ulObj.append(nodeDom); + } else if (targetObj.get(0) && moveType == consts.move.TYPE_PREV) { + targetObj.before(nodeDom); + } else if (targetObj.get(0) && moveType == consts.move.TYPE_NEXT) { + targetObj.after(nodeDom); + } + + //repair the data after move + var i, l, + tmpSrcIndex = -1, + tmpTargetIndex = 0, + oldNeighbor = null, + newNeighbor = null, + oldLevel = node.level; + var oldChildren = data.nodeChildren(setting, oldParentNode); + var targetParentChildren = data.nodeChildren(setting, targetParentNode); + var targetChildren = data.nodeChildren(setting, targetNode); + if (node.isFirstNode) { + tmpSrcIndex = 0; + if (oldChildren.length > 1) { + oldNeighbor = oldChildren[1]; + oldNeighbor.isFirstNode = true; + } + } else if (node.isLastNode) { + tmpSrcIndex = oldChildren.length - 1; + oldNeighbor = oldChildren[tmpSrcIndex - 1]; + oldNeighbor.isLastNode = true; + } else { + for (i = 0, l = oldChildren.length; i < l; i++) { + if (oldChildren[i].tId == node.tId) { + tmpSrcIndex = i; + break; + } + } + } + if (tmpSrcIndex >= 0) { + oldChildren.splice(tmpSrcIndex, 1); + } + if (moveType != consts.move.TYPE_INNER) { + for (i = 0, l = targetParentChildren.length; i < l; i++) { + if (targetParentChildren[i].tId == targetNode.tId) tmpTargetIndex = i; + } + } + if (moveType == consts.move.TYPE_INNER) { + if (!targetChildren) { + targetChildren = data.nodeChildren(setting, targetNode, []); + } + if (targetChildren.length > 0) { + newNeighbor = targetChildren[targetChildren.length - 1]; + newNeighbor.isLastNode = false; + } + targetChildren.splice(targetChildren.length, 0, node); + node.isLastNode = true; + node.isFirstNode = (targetChildren.length == 1); + } else if (targetNode.isFirstNode && moveType == consts.move.TYPE_PREV) { + targetParentChildren.splice(tmpTargetIndex, 0, node); + newNeighbor = targetNode; + newNeighbor.isFirstNode = false; + node.parentTId = targetNode.parentTId; + node.isFirstNode = true; + node.isLastNode = false; + + } else if (targetNode.isLastNode && moveType == consts.move.TYPE_NEXT) { + targetParentChildren.splice(tmpTargetIndex + 1, 0, node); + newNeighbor = targetNode; + newNeighbor.isLastNode = false; + node.parentTId = targetNode.parentTId; + node.isFirstNode = false; + node.isLastNode = true; + + } else { + if (moveType == consts.move.TYPE_PREV) { + targetParentChildren.splice(tmpTargetIndex, 0, node); + } else { + targetParentChildren.splice(tmpTargetIndex + 1, 0, node); + } + node.parentTId = targetNode.parentTId; + node.isFirstNode = false; + node.isLastNode = false; + } + data.fixPIdKeyValue(setting, node); + data.setSonNodeLevel(setting, node.getParentNode(), node); + + //repair node what been moved + view.setNodeLineIcos(setting, node); + view.repairNodeLevelClass(setting, node, oldLevel); + + //repair node's old parentNode dom + if (!setting.data.keep.parent && oldChildren.length < 1) { + //old parentNode has no child nodes + data.nodeIsParent(setting, oldParentNode, false); + oldParentNode.open = false; + var tmp_ulObj = $$(oldParentNode, consts.id.UL, setting), + tmp_switchObj = $$(oldParentNode, consts.id.SWITCH, setting), + tmp_icoObj = $$(oldParentNode, consts.id.ICON, setting); + view.replaceSwitchClass(oldParentNode, tmp_switchObj, consts.folder.DOCU); + view.replaceIcoClass(oldParentNode, tmp_icoObj, consts.folder.DOCU); + tmp_ulObj.css("display", "none"); + + } else if (oldNeighbor) { + //old neighbor node + view.setNodeLineIcos(setting, oldNeighbor); + } + + //new neighbor node + if (newNeighbor) { + view.setNodeLineIcos(setting, newNeighbor); + } + + //repair checkbox / radio + if (!!setting.check && setting.check.enable && view.repairChkClass) { + view.repairChkClass(setting, oldParentNode); + view.repairParentChkClassWithSelf(setting, oldParentNode); + if (oldParentNode != node.parent) + view.repairParentChkClassWithSelf(setting, node); + } + + //expand parents after move + if (!isSilent) { + view.expandCollapseParentNode(setting, node.getParentNode(), true, animateFlag); + } + }, + removeEditBtn: function (setting, node) { + $$(node, consts.id.EDIT, setting).unbind().remove(); + }, + removeRemoveBtn: function (setting, node) { + $$(node, consts.id.REMOVE, setting).unbind().remove(); + }, + removeTreeDom: function (setting, node) { + node.isHover = false; + view.removeEditBtn(setting, node); + view.removeRemoveBtn(setting, node); + tools.apply(setting.view.removeHoverDom, [setting.treeId, node]); + }, + repairNodeLevelClass: function (setting, node, oldLevel) { + if (oldLevel === node.level) return; + var liObj = $$(node, setting), + aObj = $$(node, consts.id.A, setting), + ulObj = $$(node, consts.id.UL, setting), + oldClass = consts.className.LEVEL + oldLevel, + newClass = consts.className.LEVEL + node.level; + liObj.removeClass(oldClass); + liObj.addClass(newClass); + aObj.removeClass(oldClass); + aObj.addClass(newClass); + ulObj.removeClass(oldClass); + ulObj.addClass(newClass); + }, + selectNodes: function (setting, nodes) { + for (var i = 0, l = nodes.length; i < l; i++) { + view.selectNode(setting, nodes[i], i > 0); + } + } + }, + + _z = { + tools: _tools, + view: _view, + event: _event, + data: _data + }; + $.extend(true, $.fn.zTree.consts, _consts); + $.extend(true, $.fn.zTree._z, _z); + + var zt = $.fn.zTree, + tools = zt._z.tools, + consts = zt.consts, + view = zt._z.view, + data = zt._z.data, + event = zt._z.event, + $$ = tools.$; + + data.exSetting(_setting); + data.addInitBind(_bindEvent); + data.addInitUnBind(_unbindEvent); + data.addInitCache(_initCache); + data.addInitNode(_initNode); + data.addInitProxy(_eventProxy); + data.addInitRoot(_initRoot); + data.addZTreeTools(_zTreeTools); + + var _cancelPreSelectedNode = view.cancelPreSelectedNode; + view.cancelPreSelectedNode = function (setting, node) { + var list = data.getRoot(setting).curSelectedList; + for (var i = 0, j = list.length; i < j; i++) { + if (!node || node === list[i]) { + view.removeTreeDom(setting, list[i]); + if (node) break; + } + } + if (_cancelPreSelectedNode) _cancelPreSelectedNode.apply(view, arguments); + } + + var _createNodes = view.createNodes; + view.createNodes = function (setting, level, nodes, parentNode, index) { + if (_createNodes) { + _createNodes.apply(view, arguments); + } + if (!nodes) return; + if (view.repairParentChkClassWithSelf) { + view.repairParentChkClassWithSelf(setting, parentNode); + } + } + + var _makeNodeUrl = view.makeNodeUrl; + view.makeNodeUrl = function (setting, node) { + return setting.edit.enable ? null : (_makeNodeUrl.apply(view, arguments)); + } + + var _removeNode = view.removeNode; + view.removeNode = function (setting, node) { + var root = data.getRoot(setting); + if (root.curEditNode === node) root.curEditNode = null; + if (_removeNode) { + _removeNode.apply(view, arguments); + } + } + + var _selectNode = view.selectNode; + view.selectNode = function (setting, node, addFlag) { + var root = data.getRoot(setting); + if (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) { + return false; + } + if (_selectNode) _selectNode.apply(view, arguments); + view.addHoverDom(setting, node); + return true; + } + + var _uCanDo = tools.uCanDo; + tools.uCanDo = function (setting, e) { + var root = data.getRoot(setting); + if (e && (tools.eqs(e.type, "mouseover") || tools.eqs(e.type, "mouseout") || tools.eqs(e.type, "mousedown") || tools.eqs(e.type, "mouseup"))) { + return true; + } + if (root.curEditNode) { + view.editNodeBlur = false; + root.curEditInput.focus(); + } + return (!root.curEditNode) && (_uCanDo ? _uCanDo.apply(view, arguments) : true); + } +})(jQuery); \ No newline at end of file diff --git a/public/self/ztree/js/jquery.ztree.exhide.js b/public/self/ztree/js/jquery.ztree.exhide.js new file mode 100644 index 000000000..8cfe174bb --- /dev/null +++ b/public/self/ztree/js/jquery.ztree.exhide.js @@ -0,0 +1,405 @@ +/* + * JQuery zTree exHideNodes + * v3.5.48 + * http://treejs.cn/ + * + * Copyright (c) 2010 Hunter.z + * + * Licensed same as jquery - MIT License + * http://www.opensource.org/licenses/mit-license.php + * + * Date: 2020-11-21 + */ + +(function ($) { + var _setting = { + data: { + key: { + isHidden: "isHidden" + } + } + }; + //default init node of exLib + var _initNode = function (setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) { + var isHidden = data.isHidden(setting, n); + data.isHidden(setting, n, isHidden); + data.initHideForExCheck(setting, n); + }, + //add dom for check + _beforeA = function (setting, node, html) { + }, + //update zTreeObj, add method of exLib + _zTreeTools = function (setting, zTreeTools) { + zTreeTools.showNodes = function (nodes, options) { + view.showNodes(setting, nodes, options); + } + zTreeTools.showNode = function (node, options) { + if (!node) { + return; + } + view.showNodes(setting, [node], options); + } + zTreeTools.hideNodes = function (nodes, options) { + view.hideNodes(setting, nodes, options); + } + zTreeTools.hideNode = function (node, options) { + if (!node) { + return; + } + view.hideNodes(setting, [node], options); + } + + var _checkNode = zTreeTools.checkNode; + if (_checkNode) { + zTreeTools.checkNode = function (node, checked, checkTypeFlag, callbackFlag) { + if (!!node && !!data.isHidden(setting, node)) { + return; + } + _checkNode.apply(zTreeTools, arguments); + } + } + }, + //method of operate data + _data = { + initHideForExCheck: function (setting, n) { + var isHidden = data.isHidden(setting, n); + if (isHidden && setting.check && setting.check.enable) { + if (typeof n._nocheck == "undefined") { + n._nocheck = !!n.nocheck + n.nocheck = true; + } + n.check_Child_State = -1; + if (view.repairParentChkClassWithSelf) { + view.repairParentChkClassWithSelf(setting, n); + } + } + }, + initShowForExCheck: function (setting, n) { + var isHidden = data.isHidden(setting, n); + if (!isHidden && setting.check && setting.check.enable) { + if (typeof n._nocheck != "undefined") { + n.nocheck = n._nocheck; + delete n._nocheck; + } + if (view.setChkClass) { + var checkObj = $$(n, consts.id.CHECK, setting); + view.setChkClass(setting, checkObj, n); + } + if (view.repairParentChkClassWithSelf) { + view.repairParentChkClassWithSelf(setting, n); + } + } + } + }, + //method of operate ztree dom + _view = { + clearOldFirstNode: function (setting, node) { + var n = node.getNextNode(); + while (!!n) { + if (n.isFirstNode) { + n.isFirstNode = false; + view.setNodeLineIcos(setting, n); + break; + } + if (n.isLastNode) { + break; + } + n = n.getNextNode(); + } + }, + clearOldLastNode: function (setting, node, openFlag) { + var n = node.getPreNode(); + while (!!n) { + if (n.isLastNode) { + n.isLastNode = false; + if (openFlag) { + view.setNodeLineIcos(setting, n); + } + break; + } + if (n.isFirstNode) { + break; + } + n = n.getPreNode(); + } + }, + makeDOMNodeMainBefore: function (html, setting, node) { + var isHidden = data.isHidden(setting, node); + html.push("
      • "); + }, + showNode: function (setting, node, options) { + data.isHidden(setting, node, false); + data.initShowForExCheck(setting, node); + $$(node, setting).show(); + }, + showNodes: function (setting, nodes, options) { + if (!nodes || nodes.length == 0) { + return; + } + var pList = {}, i, j; + for (i = 0, j = nodes.length; i < j; i++) { + var n = nodes[i]; + if (!pList[n.parentTId]) { + var pn = n.getParentNode(); + pList[n.parentTId] = (pn === null) ? data.getRoot(setting) : n.getParentNode(); + } + view.showNode(setting, n, options); + } + for (var tId in pList) { + var children = data.nodeChildren(setting, pList[tId]); + view.setFirstNodeForShow(setting, children); + view.setLastNodeForShow(setting, children); + } + }, + hideNode: function (setting, node, options) { + data.isHidden(setting, node, true); + node.isFirstNode = false; + node.isLastNode = false; + data.initHideForExCheck(setting, node); + view.cancelPreSelectedNode(setting, node); + $$(node, setting).hide(); + }, + hideNodes: function (setting, nodes, options) { + if (!nodes || nodes.length == 0) { + return; + } + var pList = {}, i, j; + for (i = 0, j = nodes.length; i < j; i++) { + var n = nodes[i]; + if ((n.isFirstNode || n.isLastNode) && !pList[n.parentTId]) { + var pn = n.getParentNode(); + pList[n.parentTId] = (pn === null) ? data.getRoot(setting) : n.getParentNode(); + } + view.hideNode(setting, n, options); + } + for (var tId in pList) { + var children = data.nodeChildren(setting, pList[tId]); + view.setFirstNodeForHide(setting, children); + view.setLastNodeForHide(setting, children); + } + }, + setFirstNode: function (setting, parentNode) { + var children = data.nodeChildren(setting, parentNode); + var isHidden = data.isHidden(setting, children[0], false); + if (children.length > 0 && !isHidden) { + children[0].isFirstNode = true; + } else if (children.length > 0) { + view.setFirstNodeForHide(setting, children); + } + }, + setLastNode: function (setting, parentNode) { + var children = data.nodeChildren(setting, parentNode); + var isHidden = data.isHidden(setting, children[0]); + if (children.length > 0 && !isHidden) { + children[children.length - 1].isLastNode = true; + } else if (children.length > 0) { + view.setLastNodeForHide(setting, children); + } + }, + setFirstNodeForHide: function (setting, nodes) { + var n, i, j; + for (i = 0, j = nodes.length; i < j; i++) { + n = nodes[i]; + if (n.isFirstNode) { + break; + } + var isHidden = data.isHidden(setting, n); + if (!isHidden && !n.isFirstNode) { + n.isFirstNode = true; + view.setNodeLineIcos(setting, n); + break; + } else { + n = null; + } + } + return n; + }, + setFirstNodeForShow: function (setting, nodes) { + var n, i, j, first, old; + for (i = 0, j = nodes.length; i < j; i++) { + n = nodes[i]; + var isHidden = data.isHidden(setting, n); + if (!first && !isHidden && n.isFirstNode) { + first = n; + break; + } else if (!first && !isHidden && !n.isFirstNode) { + n.isFirstNode = true; + first = n; + view.setNodeLineIcos(setting, n); + } else if (first && n.isFirstNode) { + n.isFirstNode = false; + old = n; + view.setNodeLineIcos(setting, n); + break; + } else { + n = null; + } + } + return {"new": first, "old": old}; + }, + setLastNodeForHide: function (setting, nodes) { + var n, i; + for (i = nodes.length - 1; i >= 0; i--) { + n = nodes[i]; + if (n.isLastNode) { + break; + } + var isHidden = data.isHidden(setting, n); + if (!isHidden && !n.isLastNode) { + n.isLastNode = true; + view.setNodeLineIcos(setting, n); + break; + } else { + n = null; + } + } + return n; + }, + setLastNodeForShow: function (setting, nodes) { + var n, i, j, last, old; + for (i = nodes.length - 1; i >= 0; i--) { + n = nodes[i]; + var isHidden = data.isHidden(setting, n); + if (!last && !isHidden && n.isLastNode) { + last = n; + break; + } else if (!last && !isHidden && !n.isLastNode) { + n.isLastNode = true; + last = n; + view.setNodeLineIcos(setting, n); + } else if (last && n.isLastNode) { + n.isLastNode = false; + old = n; + view.setNodeLineIcos(setting, n); + break; + } else { + n = null; + } + } + return {"new": last, "old": old}; + } + }, + + _z = { + view: _view, + data: _data + }; + $.extend(true, $.fn.zTree._z, _z); + + var zt = $.fn.zTree, + tools = zt._z.tools, + consts = zt.consts, + view = zt._z.view, + data = zt._z.data, + event = zt._z.event, + $$ = tools.$; + + data.isHidden = function (setting, node, newIsHidden) { + if (!node) { + return false; + } + var key = setting.data.key.isHidden; + if (typeof newIsHidden !== 'undefined') { + if (typeof newIsHidden === "string") { + newIsHidden = tools.eqs(newIsHidden, "true"); + } + newIsHidden = !!newIsHidden; + node[key] = newIsHidden; + } else if (typeof node[key] == "string"){ + node[key] = tools.eqs(node[key], "true"); + } else { + node[key] = !!node[key]; + } + return node[key]; + }; + + data.exSetting(_setting); + data.addInitNode(_initNode); + data.addBeforeA(_beforeA); + data.addZTreeTools(_zTreeTools); + +// Override method in core + var _dInitNode = data.initNode; + data.initNode = function (setting, level, node, parentNode, isFirstNode, isLastNode, openFlag) { + var tmpPNode = (parentNode) ? parentNode : data.getRoot(setting), + children = tmpPNode[setting.data.key.children]; + data.tmpHideFirstNode = view.setFirstNodeForHide(setting, children); + data.tmpHideLastNode = view.setLastNodeForHide(setting, children); + if (openFlag) { + view.setNodeLineIcos(setting, data.tmpHideFirstNode); + view.setNodeLineIcos(setting, data.tmpHideLastNode); + } + isFirstNode = (data.tmpHideFirstNode === node); + isLastNode = (data.tmpHideLastNode === node); + if (_dInitNode) _dInitNode.apply(data, arguments); + if (openFlag && isLastNode) { + view.clearOldLastNode(setting, node, openFlag); + } + }; + + var _makeChkFlag = data.makeChkFlag; + if (!!_makeChkFlag) { + data.makeChkFlag = function (setting, node) { + if (!!node && !!data.isHidden(setting, node)) { + return; + } + _makeChkFlag.apply(data, arguments); + } + } + + var _getTreeCheckedNodes = data.getTreeCheckedNodes; + if (!!_getTreeCheckedNodes) { + data.getTreeCheckedNodes = function (setting, nodes, checked, results) { + if (!!nodes && nodes.length > 0) { + var p = nodes[0].getParentNode(); + if (!!p && !!data.isHidden(setting, p)) { + return []; + } + } + return _getTreeCheckedNodes.apply(data, arguments); + } + } + + var _getTreeChangeCheckedNodes = data.getTreeChangeCheckedNodes; + if (!!_getTreeChangeCheckedNodes) { + data.getTreeChangeCheckedNodes = function (setting, nodes, results) { + if (!!nodes && nodes.length > 0) { + var p = nodes[0].getParentNode(); + if (!!p && !!data.isHidden(setting, p)) { + return []; + } + } + return _getTreeChangeCheckedNodes.apply(data, arguments); + } + } + + var _expandCollapseSonNode = view.expandCollapseSonNode; + if (!!_expandCollapseSonNode) { + view.expandCollapseSonNode = function (setting, node, expandFlag, animateFlag, callback) { + if (!!node && !!data.isHidden(setting, node)) { + return; + } + _expandCollapseSonNode.apply(view, arguments); + } + } + + var _setSonNodeCheckBox = view.setSonNodeCheckBox; + if (!!_setSonNodeCheckBox) { + view.setSonNodeCheckBox = function (setting, node, value, srcNode) { + if (!!node && !!data.isHidden(setting, node)) { + return; + } + _setSonNodeCheckBox.apply(view, arguments); + } + } + + var _repairParentChkClassWithSelf = view.repairParentChkClassWithSelf; + if (!!_repairParentChkClassWithSelf) { + view.repairParentChkClassWithSelf = function (setting, node) { + if (!!node && !!data.isHidden(setting, node)) { + return; + } + _repairParentChkClassWithSelf.apply(view, arguments); + } + } +})(jQuery); \ No newline at end of file diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index f2ac802e1..9a4774fa3 100755 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -922,7 +922,20 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/stop_version", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo_ext.CloudBrainStop) }) }) + m.Group("/inference-job", func() { + m.Group("/:jobid", func() { + m.Get("", repo.GetCloudBrainInferenceJob) + m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.DelCloudBrainJob) + m.Get("/result_list", repo.InferencJobResultList) + }) + }) }, reqRepoReader(models.UnitTypeCloudBrain)) + m.Group("/modelmanage", func() { + m.Get("/:id", repo.GetCloudbrainModelConvertTask) + m.Get("/:id/log", repo.CloudbrainForModelConvertGetLog) + m.Get("/:id/modelartlog", repo.TrainJobForModelConvertGetLog) + m.Get("/:id/model_list", repo.CloudBrainModelConvertList) + }, reqRepoReader(models.UnitTypeModelManage)) m.Group("/modelarts", func() { m.Group("/notebook", func() { //m.Get("/:jobid", repo.GetModelArtsNotebook) diff --git a/routers/api/v1/repo/cloudbrain.go b/routers/api/v1/repo/cloudbrain.go index f0e9ad5f1..5ebbc9b46 100755 --- a/routers/api/v1/repo/cloudbrain.go +++ b/routers/api/v1/repo/cloudbrain.go @@ -6,17 +6,19 @@ package repo import ( - "code.gitea.io/gitea/modules/setting" "encoding/json" "net/http" "sort" "strings" "time" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/cloudbrain" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/modelarts" "code.gitea.io/gitea/modules/storage" routerRepo "code.gitea.io/gitea/routers/repo" ) @@ -101,21 +103,203 @@ func GetCloudbrainTask(ctx *context.APIContext) { } -func CloudbrainGetLog(ctx *context.Context) { +func GetCloudBrainInferenceJob(ctx *context.APIContext) { + + jobID := ctx.Params(":jobid") + job, err := models.GetCloudbrainByJobID(jobID) + if err != nil { + ctx.NotFound(err) + return + } + jobResult, err := cloudbrain.GetJob(job.JobID) + if err != nil { + ctx.NotFound(err) + log.Error("GetJob failed:", err) + return + } + result, err := models.ConvertToJobResultPayload(jobResult.Payload) + if err != nil { + ctx.NotFound(err) + log.Error("ConvertToJobResultPayload failed:", err) + return + } + + job.Status = result.JobStatus.State + if result.JobStatus.State != string(models.JobWaiting) && result.JobStatus.State != string(models.JobFailed) { + taskRoles := result.TaskRoles + taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) + + job.ContainerIp = taskRes.TaskStatuses[0].ContainerIP + job.ContainerID = taskRes.TaskStatuses[0].ContainerID + job.Status = taskRes.TaskStatuses[0].State + } + + if result.JobStatus.State != string(models.JobWaiting) { + models.ParseAndSetDurationFromCloudBrainOne(result, job) + err = models.UpdateJob(job) + if err != nil { + log.Error("UpdateJob failed:", err) + } + } + + ctx.JSON(http.StatusOK, map[string]interface{}{ + "JobID": jobID, + "JobStatus": job.Status, + "JobDuration": job.TrainJobDuration, + }) + +} + +func DelCloudBrainJob(ctx *context.APIContext) { + jobID := ctx.Params(":jobid") + + errStr := cloudbrain.DelCloudBrainJob(jobID) + + if errStr != "" { + ctx.JSON(http.StatusOK, map[string]interface{}{ + "message": ctx.Tr(errStr), + "VersionName": "1", + "code": 1, + }) + } else { + ctx.JSON(http.StatusOK, map[string]interface{}{ + "message": "", + "VersionName": "1", + "code": 0, + }) + } + +} + +func InferencJobResultList(ctx *context.APIContext) { + jobID := ctx.Params(":jobid") + parentDir := ctx.Query("parentDir") + dirArray := strings.Split(parentDir, "/") + + task, err := models.GetCloudbrainByJobID(jobID) + if err != nil { + log.Error("get cloud brain err:", err) + ctx.ServerError("get cloud brain information failed:", err) + + } + + //get dirs + dirs, err := routerRepo.GetResultDirs(task.JobName, parentDir) + if err != nil { + log.Error("GetModelDirs failed:%v", err.Error(), ctx.Data["msgID"]) + ctx.ServerError("GetModelDirs failed:", err) + return + } + + var fileInfos []storage.FileInfo + err = json.Unmarshal([]byte(dirs), &fileInfos) + if err != nil { + log.Error("json.Unmarshal failed:%v", err.Error(), ctx.Data["msgID"]) + ctx.ServerError("json.Unmarshal failed:", err) + return + } + + for i, fileInfo := range fileInfos { + temp, _ := time.Parse("2006-01-02 15:04:05", fileInfo.ModTime) + fileInfos[i].ModTime = temp.Local().Format("2006-01-02 15:04:05") + } + + sort.Slice(fileInfos, func(i, j int) bool { + return fileInfos[i].ModTime > fileInfos[j].ModTime + }) + + ctx.JSON(http.StatusOK, map[string]interface{}{ + "JobID": jobID, + "StatusOK": 0, + "Path": dirArray, + "Dirs": fileInfos, + "task": task, + "PageIsCloudBrain": true, + }) + +} + +func GetCloudbrainModelConvertTask(ctx *context.APIContext) { + var ( + err error + ) ID := ctx.Params(":id") - job, err := models.GetCloudbrainByID(ID) + job, err := models.QueryModelConvertById(ID) if err != nil { - log.Error("GetCloudbrainByJobName failed: %v", err, ctx.Data["MsgID"]) - ctx.ServerError(err.Error(), err) + ctx.NotFound(err) + log.Error("GetCloudbrainByID failed:", err) return } + if job.IsGpuTrainTask() { + jobResult, err := cloudbrain.GetJob(job.CloudBrainTaskId) + if err != nil { + ctx.NotFound(err) + log.Error("GetJob failed:", err) + return + } + result, _ := models.ConvertToJobResultPayload(jobResult.Payload) + if err != nil { + ctx.NotFound(err) + log.Error("ConvertToJobResultPayload failed:", err) + return + } + + job.Status = result.JobStatus.State + taskRoles := result.TaskRoles + taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) + if result.JobStatus.State != string(models.JobWaiting) && result.JobStatus.State != string(models.JobFailed) { + job.ContainerIp = taskRes.TaskStatuses[0].ContainerIP + job.ContainerID = taskRes.TaskStatuses[0].ContainerID + job.Status = taskRes.TaskStatuses[0].State + } + + if result.JobStatus.State != string(models.JobWaiting) { + models.ModelComputeAndSetDuration(job, result) + err = models.UpdateModelConvert(job) + if err != nil { + log.Error("UpdateJob failed:", err) + } + } + ctx.JSON(http.StatusOK, map[string]interface{}{ + "ID": ID, + "JobName": result.Config.JobName, + "JobStatus": result.JobStatus.State, + "SubState": result.JobStatus.SubState, + "CreatedTime": time.Unix(result.JobStatus.CreatedTime/1000, 0).Format("2006-01-02 15:04:05"), + "CompletedTime": time.Unix(result.JobStatus.CompletedTime/1000, 0).Format("2006-01-02 15:04:05"), + }) + } else { + + result, err := modelarts.GetTrainJob(job.CloudBrainTaskId, job.ModelArtsVersionId) + if err != nil { + log.Error("get modelart job failed:", err) + ctx.NotFound(err) + return + } + + job.Status = modelarts.TransTrainJobStatus(result.IntStatus) + job.RunTime = result.Duration / 1000 + job.TrainJobDuration = models.ConvertDurationToStr(job.RunTime) + err = models.UpdateModelConvert(job) + if err != nil { + log.Error("UpdateJob failed:", err) + } + ctx.JSON(http.StatusOK, map[string]interface{}{ + "ID": ID, + "JobStatus": job.Status, + }) + + } + +} + +func CloudbrainGetLogByJobId(jobId string, jobName string) map[string]interface{} { var hits []models.Hits - result, err := cloudbrain.GetJobLog(job.JobID) + result, err := cloudbrain.GetJobLog(jobId) if err != nil { - log.Error("GetJobLog failed: %v", err, ctx.Data["MsgID"]) - ctx.ServerError(err.Error(), err) - return + log.Error("GetJobLog failed: %v", err) + return nil } hits = result.Hits.Hits @@ -124,7 +308,7 @@ func CloudbrainGetLog(ctx *context.Context) { for { resultNext, err := cloudbrain.GetJobAllLog(result.ScrollID) if err != nil { - log.Error("GetJobAllLog failed: %v", err, ctx.Data["MsgID"]) + log.Error("GetJobAllLog failed: %v", err) } else { for _, hit := range resultNext.Hits.Hits { hits = append(hits, hit) @@ -149,12 +333,122 @@ func CloudbrainGetLog(ctx *context.Context) { content += log.Source.Message + "\n" } - ctx.JSON(http.StatusOK, map[string]interface{}{ - "JobName": job.JobName, + return map[string]interface{}{ + "JobName": jobName, "Content": content, - }) + } + +} + +func CloudbrainForModelConvertGetLog(ctx *context.Context) { + ID := ctx.Params(":id") + job, err := models.QueryModelConvertById(ID) + if err != nil { + log.Error("GetCloudbrainByJobName failed: %v", err, ctx.Data["MsgID"]) + ctx.ServerError(err.Error(), err) + return + } + + result := CloudbrainGetLogByJobId(job.CloudBrainTaskId, job.Name) + if result == nil { + log.Error("GetJobLog failed: %v", err, ctx.Data["MsgID"]) + ctx.ServerError(err.Error(), err) + return + } + ctx.JSON(http.StatusOK, result) +} + +func CloudbrainGetLog(ctx *context.Context) { + ID := ctx.Params(":id") + job, err := models.GetCloudbrainByID(ID) + if err != nil { + log.Error("GetCloudbrainByJobName failed: %v", err, ctx.Data["MsgID"]) + ctx.ServerError(err.Error(), err) + return + } + + result := CloudbrainGetLogByJobId(job.JobID, job.JobName) + if result == nil { + log.Error("GetJobLog failed: %v", err, ctx.Data["MsgID"]) + ctx.ServerError(err.Error(), err) + return + } + ctx.JSON(http.StatusOK, result) +} + +func CloudBrainModelConvertList(ctx *context.APIContext) { + var ( + err error + ) + + ID := ctx.Params(":id") + parentDir := ctx.Query("parentDir") + dirArray := strings.Split(parentDir, "/") + + job, err := models.QueryModelConvertById(ID) + if err != nil { + log.Error("GetCloudbrainByJobID(%s) failed:%v", job.Name, err.Error()) + return + } + if job.IsGpuTrainTask() { + //get dirs + dirs, err := routerRepo.GetModelDirs(job.ID, parentDir) + if err != nil { + log.Error("GetModelDirs failed:%v", err.Error(), ctx.Data["msgID"]) + ctx.ServerError("GetModelDirs failed:", err) + return + } + + var fileInfos []storage.FileInfo + err = json.Unmarshal([]byte(dirs), &fileInfos) + if err != nil { + log.Error("json.Unmarshal failed:%v", err.Error(), ctx.Data["msgID"]) + ctx.ServerError("json.Unmarshal failed:", err) + return + } + + for i, fileInfo := range fileInfos { + temp, _ := time.Parse("2006-01-02 15:04:05", fileInfo.ModTime) + fileInfos[i].ModTime = temp.Local().Format("2006-01-02 15:04:05") + } + + sort.Slice(fileInfos, func(i, j int) bool { + return fileInfos[i].ModTime > fileInfos[j].ModTime + }) + + ctx.JSON(http.StatusOK, map[string]interface{}{ + "JobID": ID, + "VersionName": "", + "StatusOK": 0, + "Path": dirArray, + "Dirs": fileInfos, + "task": job, + "PageIsCloudBrain": true, + }) + } else { + var jobID = ctx.Params(":id") + var versionName = "V0001" + parentDir := ctx.Query("parentDir") + dirArray := strings.Split(parentDir, "/") + + models, err := storage.GetObsListObject(job.ID, "output/", parentDir, versionName) + if err != nil { + log.Info("get TrainJobListModel failed:", err) + ctx.ServerError("GetObsListObject:", err) + return + } + + ctx.JSON(http.StatusOK, map[string]interface{}{ + "JobID": jobID, + "VersionName": versionName, + "StatusOK": 0, + "Path": dirArray, + "Dirs": models, + "task": job, + "PageIsCloudBrain": true, + }) + } - return } func CloudBrainModelList(ctx *context.APIContext) { diff --git a/routers/api/v1/repo/modelarts.go b/routers/api/v1/repo/modelarts.go index f639e0635..81f9bc03e 100755 --- a/routers/api/v1/repo/modelarts.go +++ b/routers/api/v1/repo/modelarts.go @@ -6,14 +6,15 @@ package repo import ( - "code.gitea.io/gitea/modules/grampus" - "code.gitea.io/gitea/modules/setting" "encoding/json" "net/http" "path" "strconv" "strings" + "code.gitea.io/gitea/modules/grampus" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/cloudbrain" "code.gitea.io/gitea/modules/context" @@ -161,6 +162,75 @@ func GetModelArtsTrainJobVersion(ctx *context.APIContext) { } +func TrainJobForModelConvertGetLog(ctx *context.APIContext) { + var ( + err error + ) + + var jobID = ctx.Params(":id") + var baseLine = ctx.Query("base_line") + var order = ctx.Query("order") + var lines = ctx.Query("lines") + lines_int, err := strconv.Atoi(lines) + if err != nil { + log.Error("change lines(%d) string to int failed", lines_int) + } + + if order != modelarts.OrderDesc && order != modelarts.OrderAsc { + log.Error("order(%s) check failed", order) + ctx.JSON(http.StatusBadRequest, map[string]interface{}{ + "err_msg": "order check failed", + }) + return + } + + resultLogFile, result, err := trainJobForModelConvertGetLogContent(jobID, baseLine, order, lines_int) + if err != nil { + log.Error("trainJobGetLog(%s) failed:%v", jobID, err.Error()) + // ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobShow, nil) + ctx.JSON(http.StatusOK, map[string]interface{}{ + "JobID": jobID, + "LogFileName": "", + "StartLine": "0", + "EndLine": "0", + "Content": "", + "Lines": 0, + }) + return + } + + ctx.Data["log_file_name"] = resultLogFile.LogFileList[0] + + ctx.JSON(http.StatusOK, map[string]interface{}{ + "JobID": jobID, + "LogFileName": resultLogFile.LogFileList[0], + "StartLine": result.StartLine, + "EndLine": result.EndLine, + "Content": result.Content, + "Lines": result.Lines, + }) +} + +func trainJobForModelConvertGetLogContent(jobID string, baseLine string, order string, lines int) (*models.GetTrainJobLogFileNamesResult, *models.GetTrainJobLogResult, error) { + task, err := models.QueryModelConvertById(jobID) + if err != nil { + log.Error("GetCloudbrainByJobID(%s) failed:%v", jobID, err.Error()) + return nil, nil, err + } + resultLogFile, err := modelarts.GetTrainJobLogFileNames(task.CloudBrainTaskId, task.ModelArtsVersionId) + if err != nil { + log.Error("GetTrainJobLogFileNames(%s) failed:%v", task.CloudBrainTaskId, err.Error()) + return nil, nil, err + } + result, err := modelarts.GetTrainJobLog(task.CloudBrainTaskId, task.ModelArtsVersionId, baseLine, resultLogFile.LogFileList[0], order, lines) + if err != nil { + log.Error("GetTrainJobLog(%s) failed:%v", task.CloudBrainTaskId, err.Error()) + return nil, nil, err + } + + return resultLogFile, result, err +} + func TrainJobGetLog(ctx *context.APIContext) { var ( err error diff --git a/routers/repo/ai_model_convert.go b/routers/repo/ai_model_convert.go new file mode 100644 index 000000000..9a5874956 --- /dev/null +++ b/routers/repo/ai_model_convert.go @@ -0,0 +1,795 @@ +package repo + +import ( + "bufio" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + "os" + "path" + "strings" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/cloudbrain" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/modelarts" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/storage" + "code.gitea.io/gitea/modules/timeutil" + uuid "github.com/satori/go.uuid" +) + +const ( + tplModelManageConvertIndex = "repo/modelmanage/convertIndex" + tplModelConvertInfo = "repo/modelmanage/convertshowinfo" + PYTORCH_ENGINE = 0 + TENSORFLOW_ENGINE = 1 + MINDSPORE_ENGIN = 2 + ModelMountPath = "/model" + CodeMountPath = "/code" + DataSetMountPath = "/dataset" + LogFile = "log.txt" + DefaultBranchName = "master" + SubTaskName = "task1" + //GpuQueue = "openidgx" + Success = "S000" + //GPU_PYTORCH_IMAGE = "dockerhub.pcl.ac.cn:5000/user-images/openi:tensorRT_7_zouap" + //GPU_TENSORFLOW_IMAGE = "dockerhub.pcl.ac.cn:5000/user-images/openi:tf2onnx" + //NPU_MINDSPORE_16_IMAGE = "swr.cn-south-222.ai.pcl.cn/openi/mindspore1.6.1_train_v1_openi:v3_ascend" + //PytorchOnnxBootFile = "convert_pytorch.py" + //PytorchTrTBootFile = "convert_pytorch_tensorrt.py" + //MindsporeBootFile = "convert_mindspore.py" + //TensorFlowNpuBootFile = "convert_tensorflow.py" + //TensorFlowGpuBootFile = "convert_tensorflow_gpu.py" + + //ConvertRepoPath = "https://git.openi.org.cn/zouap/npu_test" + + CONVERT_FORMAT_ONNX = 0 + CONVERT_FORMAT_TRT = 1 + + NetOutputFormat_FP32 = 0 + NetOutputFormat_FP16 = 1 + + NPU_MINDSPORE_IMAGE_ID = 35 + NPU_TENSORFLOW_IMAGE_ID = 121 + + //GPU_Resource_Specs_ID = 1 //cpu 1, gpu 1 + + //NPU_FlavorCode = "modelarts.bm.910.arm.public.1" + //NPU_PoolID = "pool7908321a" +) + +var ( + TrainResourceSpecs *models.ResourceSpecs +) + +func SaveModelConvert(ctx *context.Context) { + log.Info("save model convert start.") + if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { + ctx.JSON(200, map[string]string{ + "result_code": "1", + "message": ctx.Tr("repo.modelconvert.manage.no_operate_right"), + }) + return + } + name := ctx.Query("name") + desc := ctx.Query("desc") + modelId := ctx.Query("modelId") + modelPath := ctx.Query("ModelFile") + SrcEngine := ctx.QueryInt("SrcEngine") + InputShape := ctx.Query("inputshape") + InputDataFormat := ctx.Query("inputdataformat") + DestFormat := ctx.QueryInt("DestFormat") + NetOutputFormat := ctx.QueryInt("NetOutputFormat") + + task, err := models.QueryModelById(modelId) + if err != nil { + log.Error("no such model!", err.Error()) + ctx.JSON(200, map[string]string{ + "result_code": "1", + "message": ctx.Tr("repo.modelconvert.manage.model_not_exist"), + }) + return + } + + convertList, err := models.QueryModelConvertByRepoID(ctx.Repo.Repository.ID) + if err == nil { + for _, convert := range convertList { + if convert.Name == name { + log.Info("convert.Name=" + name + " convert.id=" + convert.ID) + ctx.JSON(200, map[string]string{ + "result_code": "1", + "message": ctx.Tr("repo.modelconvert.manage.create_error1"), + }) + return + } + } + } + + convertList, err = models.QueryModelConvertByUserID(ctx.User.ID) + if err == nil { + for _, convert := range convertList { + if isRunningTask(convert.Status) { + log.Info("convert.Status=" + convert.Status + " convert.id=" + convert.ID) + ctx.JSON(200, map[string]string{ + "result_code": "1", + "message": ctx.Tr("repo.modelconvert.manage.create_error2"), + }) + return + } + } + } + + uuid := uuid.NewV4() + id := uuid.String() + modelConvert := &models.AiModelConvert{ + ID: id, + Name: name, + Description: desc, + Status: string(models.JobWaiting), + SrcEngine: SrcEngine, + RepoId: ctx.Repo.Repository.ID, + ModelName: task.Name, + ModelVersion: task.Version, + ModelId: modelId, + ModelPath: modelPath, + DestFormat: DestFormat, + NetOutputFormat: NetOutputFormat, + InputShape: InputShape, + InputDataFormat: InputDataFormat, + UserId: ctx.User.ID, + } + models.SaveModelConvert(modelConvert) + go goCreateTask(modelConvert, ctx, task) + + ctx.JSON(200, map[string]string{ + "result_code": "0", + }) +} + +func isRunningTask(status string) bool { + stopStatus := []string{"COMPLETED", "STOPPED", "FAILED", "START_FAILED", "STOPPING", "SUCCEEDED"} + for _, sta := range stopStatus { + if sta == status { + return false + } + } + return true +} + +func goCreateTask(modelConvert *models.AiModelConvert, ctx *context.Context, task *models.AiModelManage) error { + if modelConvert.IsGpuTrainTask() { + log.Info("create gpu train job.") + return createGpuTrainJob(modelConvert, ctx, task) + } else { + //create npu job + log.Info("create npu train job.") + return createNpuTrainJob(modelConvert, ctx, task.Path) + } +} + +func createNpuTrainJob(modelConvert *models.AiModelConvert, ctx *context.Context, modelRelativePath string) error { + VersionOutputPath := "V0001" + codeLocalPath := setting.JobPath + modelConvert.ID + modelarts.CodePath + codeObsPath := "/" + setting.Bucket + modelarts.JobPath + modelConvert.ID + modelarts.CodePath + outputObsPath := "/" + setting.Bucket + modelarts.JobPath + modelConvert.ID + modelarts.OutputPath + VersionOutputPath + "/" + logObsPath := "/" + setting.Bucket + modelarts.JobPath + modelConvert.ID + modelarts.LogPath + VersionOutputPath + "/" + dataPath := "/" + modelRelativePath + + _, err := ioutil.ReadDir(codeLocalPath) + if err == nil { + deleteLocalDir(codeLocalPath) + } + if err := downloadConvertCode(setting.ModelConvert.ConvertRepoPath, codeLocalPath, DefaultBranchName); err != nil { + log.Error("downloadCode failed, server timed out: %s (%v)", setting.ModelConvert.ConvertRepoPath, err) + return err + } + if err := obsMkdir(setting.CodePathPrefix + modelConvert.ID + modelarts.OutputPath + VersionOutputPath + "/"); err != nil { + log.Error("Failed to obsMkdir_output: %s (%v)", modelConvert.ID+modelarts.OutputPath, err) + return err + } + if err := obsMkdir(setting.CodePathPrefix + modelConvert.ID + modelarts.LogPath + VersionOutputPath + "/"); err != nil { + log.Error("Failed to obsMkdir_log: %s (%v)", modelConvert.ID+modelarts.LogPath, err) + return err + } + if err := uploadCodeToObs(codeLocalPath, modelConvert.ID, ""); err != nil { + log.Error("Failed to uploadCodeToObs: %s (%v)", modelConvert.ID, err) + return err + } + deleteLocalDir(codeLocalPath) + + intputshape := strings.Split(modelConvert.InputShape, ",") + n := "256" + c := "1" + h := "28" + w := "28" + if len(intputshape) == 4 { + n = intputshape[0] + c = intputshape[1] + h = intputshape[2] + w = intputshape[3] + } + + var engineId int64 + engineId = int64(NPU_MINDSPORE_IMAGE_ID) + bootfile := setting.ModelConvert.MindsporeBootFile + if modelConvert.SrcEngine == TENSORFLOW_ENGINE { + engineId = int64(NPU_TENSORFLOW_IMAGE_ID) + bootfile = setting.ModelConvert.TensorFlowNpuBootFile + } + userCommand := "/bin/bash /home/work/run_train.sh 's3://" + codeObsPath + "' 'code/" + bootfile + "' '/tmp/log/train.log' --'data_url'='s3://" + dataPath + "' --'train_url'='s3://" + outputObsPath + "'" + userCommand += " --'model'='" + modelConvert.ModelPath + "'" + userCommand += " --'n'='" + fmt.Sprint(n) + "'" + userCommand += " --'c'='" + fmt.Sprint(c) + "'" + userCommand += " --'h'='" + fmt.Sprint(h) + "'" + userCommand += " --'w'='" + fmt.Sprint(w) + "'" + + req := &modelarts.GenerateTrainJobReq{ + JobName: modelConvert.ID, + DisplayJobName: modelConvert.Name, + DataUrl: dataPath, + Description: modelConvert.Description, + CodeObsPath: codeObsPath, + BootFileUrl: codeObsPath + bootfile, + BootFile: bootfile, + TrainUrl: outputObsPath, + FlavorCode: setting.ModelConvert.NPU_FlavorCode, + WorkServerNumber: 1, + IsLatestVersion: modelarts.IsLatestVersion, + EngineID: engineId, + LogUrl: logObsPath, + PoolID: setting.ModelConvert.NPU_PoolID, + //Parameters: param, + BranchName: DefaultBranchName, + UserImageUrl: setting.ModelConvert.NPU_MINDSPORE_16_IMAGE, + UserCommand: userCommand, + } + result, err := modelarts.GenerateModelConvertTrainJob(req) + if err == nil { + log.Info("jobId=" + fmt.Sprint(result.JobID) + " versionid=" + fmt.Sprint(result.VersionID)) + models.UpdateModelConvertModelArts(modelConvert.ID, fmt.Sprint(result.JobID), fmt.Sprint(result.VersionID)) + } else { + log.Info("create modelarts taks failed.error=" + err.Error()) + models.UpdateModelConvertFailed(modelConvert.ID, "FAILED", err.Error()) + } + return err +} + +func downloadConvertCode(repopath string, codePath, branchName string) error { + //add "file:///" prefix to make the depth valid + if err := git.Clone(repopath, codePath, git.CloneRepoOptions{Branch: branchName, Depth: 1}); err != nil { + log.Error("Failed to clone repository: %s (%v)", repopath, err) + return err + } + log.Info("srcPath=" + repopath + " codePath=" + codePath) + configFile, err := os.OpenFile(codePath+"/.git/config", os.O_RDWR, 0666) + if err != nil { + log.Error("open file(%s) failed:%v", codePath+"/,git/config", err) + return err + } + + defer configFile.Close() + + pos := int64(0) + reader := bufio.NewReader(configFile) + for { + line, err := reader.ReadString('\n') + if err != nil { + if err == io.EOF { + log.Error("not find the remote-url") + return nil + } else { + log.Error("read error: %v", err) + return err + } + } + + if strings.Contains(line, "url") && strings.Contains(line, ".git") { + originUrl := "\turl = " + repopath + "\n" + if len(line) > len(originUrl) { + originUrl += strings.Repeat(" ", len(line)-len(originUrl)) + } + bytes := []byte(originUrl) + _, err := configFile.WriteAt(bytes, pos) + if err != nil { + log.Error("WriteAt failed:%v", err) + return err + } + break + } + + pos += int64(len(line)) + } + + return nil +} + +func downloadFromObsToLocal(task *models.AiModelManage, localPath string) error { + path := Model_prefix + models.AttachmentRelativePath(task.ID) + "/" + allFile, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, path) + if err == nil { + _, errState := os.Stat(localPath) + if errState != nil { + if err = os.MkdirAll(localPath, os.ModePerm); err != nil { + return err + } + } + for _, oneFile := range allFile { + if oneFile.IsDir { + log.Info(" dir name:" + oneFile.FileName) + } else { + allFileName := localPath + "/" + oneFile.FileName + index := strings.LastIndex(allFileName, "/") + if index != -1 { + parentDir := allFileName[0:index] + if err = os.MkdirAll(parentDir, os.ModePerm); err != nil { + log.Info("make dir may be error," + err.Error()) + } + } + fDest, err := os.Create(allFileName) + if err != nil { + log.Info("create file error, download file failed: %s\n", err.Error()) + return err + } + body, err := storage.ObsDownloadAFile(setting.Bucket, path+oneFile.FileName) + if err != nil { + log.Info("download file failed: %s\n", err.Error()) + return err + } else { + defer body.Close() + p := make([]byte, 1024) + var readErr error + var readCount int + // 读取对象内容 + for { + readCount, readErr = body.Read(p) + if readCount > 0 { + fDest.Write(p[:readCount]) + } + if readErr != nil { + break + } + } + } + } + } + } else { + log.Info("error,msg=" + err.Error()) + return err + } + return nil +} + +func createGpuTrainJob(modelConvert *models.AiModelConvert, ctx *context.Context, model *models.AiModelManage) error { + modelRelativePath := model.Path + command := "" + IMAGE_URL := setting.ModelConvert.GPU_PYTORCH_IMAGE + dataActualPath := setting.Attachment.Minio.RealPath + modelRelativePath + + if modelConvert.SrcEngine == PYTORCH_ENGINE { + if modelConvert.DestFormat == CONVERT_FORMAT_ONNX { + command = getGpuModelConvertCommand(modelConvert.ID, modelConvert.ModelPath, modelConvert, setting.ModelConvert.PytorchOnnxBootFile) + } else if modelConvert.DestFormat == CONVERT_FORMAT_TRT { + command = getGpuModelConvertCommand(modelConvert.ID, modelConvert.ModelPath, modelConvert, setting.ModelConvert.PytorchTrTBootFile) + } else { + return errors.New("Not support the format.") + } + } else if modelConvert.SrcEngine == TENSORFLOW_ENGINE { + IMAGE_URL = setting.ModelConvert.GPU_TENSORFLOW_IMAGE + if modelConvert.DestFormat == CONVERT_FORMAT_ONNX { + command = getGpuModelConvertCommand(modelConvert.ID, modelConvert.ModelPath, modelConvert, setting.ModelConvert.TensorFlowGpuBootFile) + } else { + return errors.New("Not support the format.") + } + //如果模型在OBS上,需要下载到本地,并上传到minio中 + if model.Type == models.TypeCloudBrainTwo { + relatetiveModelPath := setting.JobPath + modelConvert.ID + "/dataset" + log.Info("local dataset path:" + relatetiveModelPath) + downloadFromObsToLocal(model, relatetiveModelPath) + uploadCodeToMinio(relatetiveModelPath+"/", modelConvert.ID, "/dataset/") + deleteLocalDir(relatetiveModelPath) + dataActualPath = setting.Attachment.Minio.RealPath + setting.Attachment.Minio.Bucket + "/" + setting.CBCodePathPrefix + modelConvert.ID + "/dataset" + } + } + log.Info("dataActualPath=" + dataActualPath) + + log.Info("command=" + command) + + codePath := setting.JobPath + modelConvert.ID + CodeMountPath + downloadConvertCode(setting.ModelConvert.ConvertRepoPath, codePath, DefaultBranchName) + + uploadCodeToMinio(codePath+"/", modelConvert.ID, CodeMountPath+"/") + deleteLocalDir(codePath) + + minioCodePath := setting.Attachment.Minio.RealPath + setting.Attachment.Minio.Bucket + "/" + setting.CBCodePathPrefix + modelConvert.ID + "/code" + log.Info("minio codePath=" + minioCodePath) + + modelPath := setting.JobPath + modelConvert.ID + ModelMountPath + "/" + log.Info("local modelPath=" + modelPath) + mkModelPath(modelPath) + + uploadCodeToMinio(modelPath, modelConvert.ID, ModelMountPath+"/") + deleteLocalDir(modelPath) + + minioModelPath := setting.Attachment.Minio.RealPath + setting.Attachment.Minio.Bucket + "/" + setting.CBCodePathPrefix + modelConvert.ID + "/model" + log.Info("minio model path=" + minioModelPath) + + if TrainResourceSpecs == nil { + json.Unmarshal([]byte(setting.TrainResourceSpecs), &TrainResourceSpecs) + } + resourceSpec := TrainResourceSpecs.ResourceSpec[setting.ModelConvert.GPU_Resource_Specs_ID] + jobResult, err := cloudbrain.CreateJob(modelConvert.ID, models.CreateJobParams{ + JobName: modelConvert.ID, + RetryCount: 1, + GpuType: setting.ModelConvert.GpuQueue, + Image: IMAGE_URL, + TaskRoles: []models.TaskRole{ + { + Name: SubTaskName, + TaskNumber: 1, + MinSucceededTaskCount: 1, + MinFailedTaskCount: 1, + CPUNumber: resourceSpec.CpuNum, + GPUNumber: resourceSpec.GpuNum, + MemoryMB: resourceSpec.MemMiB, + ShmMB: resourceSpec.ShareMemMiB, + Command: command, + NeedIBDevice: false, + IsMainRole: false, + UseNNI: false, + }, + }, + Volumes: []models.Volume{ + { + HostPath: models.StHostPath{ + Path: minioCodePath, + MountPath: CodeMountPath, + ReadOnly: false, + }, + }, + { + HostPath: models.StHostPath{ + Path: dataActualPath, + MountPath: DataSetMountPath, + ReadOnly: true, + }, + }, + { + HostPath: models.StHostPath{ + Path: minioModelPath, + MountPath: ModelMountPath, + ReadOnly: false, + }, + }, + }, + }) + if err != nil { + log.Error("CreateJob failed:", err.Error(), ctx.Data["MsgID"]) + models.UpdateModelConvertFailed(modelConvert.ID, "FAILED", err.Error()) + return err + } + if jobResult.Code != Success { + log.Error("CreateJob(%s) failed:%s", modelConvert.ID, jobResult.Msg, ctx.Data["MsgID"]) + models.UpdateModelConvertFailed(modelConvert.ID, "FAILED", err.Error()) + return errors.New(jobResult.Msg) + } + + var jobID = jobResult.Payload["jobId"].(string) + log.Info("jobId=" + jobID) + models.UpdateModelConvertCBTI(modelConvert.ID, jobID) + + return nil +} + +func deleteLocalDir(dirpath string) { + //TODO delete + _err := os.RemoveAll(dirpath) + if _err == nil { + log.Info("Delete local file:" + dirpath) + } else { + log.Info("Delete local file error: path=" + dirpath) + } +} + +func getGpuModelConvertCommand(name string, modelFile string, modelConvert *models.AiModelConvert, bootfile string) string { + var command string + + inputshape := strings.Split(modelConvert.InputShape, ",") + n := "256" + c := "1" + h := "28" + w := "28" + if len(inputshape) == 4 { + n = inputshape[0] + c = inputshape[1] + h = inputshape[2] + w = inputshape[3] + } + command += "python3 /code/" + bootfile + " --model " + modelFile + " --n " + n + " --c " + c + " --h " + h + " --w " + w + if modelConvert.DestFormat == CONVERT_FORMAT_TRT { + if modelConvert.NetOutputFormat == NetOutputFormat_FP16 { + command += " --fp16 True" + } else { + command += " --fp16 False" + } + } + command += " > " + ModelMountPath + "/" + name + "-" + LogFile + return command +} + +func DeleteModelConvert(ctx *context.Context) { + log.Info("delete model convert start.") + id := ctx.Params(":id") + task, err := models.QueryModelConvertById(id) + if err == nil { + go deleteCloudBrainTask(task) + } + err = models.DeleteModelConvertById(id) + //TODO delete OBS文件及云脑任务 + if err != nil { + ctx.JSON(500, err.Error()) + } else { + ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelmanage/convert_model") + } +} + +func deleteCloudBrainTask(task *models.AiModelConvert) { + if task.IsGpuTrainTask() { + log.Info("delete cloudbrain one resource.") + dirPath := setting.CBCodePathPrefix + task.ID + "/" + err := storage.Attachments.DeleteDir(dirPath) + if err != nil { + log.Error("DeleteDir(%s) failed:%v", dirPath, err) + } + } else { + log.Info("delete cloudbrain two resource.") + _, err := modelarts.DelTrainJob(task.CloudBrainTaskId) + if err != nil { + log.Error("DelTrainJob(%s) failed:%v", task.CloudBrainTaskId, err.Error()) + } + DeleteJobStorage(task.ID) + } +} + +func StopModelConvert(ctx *context.Context) { + id := ctx.Params(":id") + log.Info("stop model convert start.id=" + id) + job, err := models.QueryModelConvertById(id) + if err != nil { + ctx.ServerError("Not found task.", err) + return + } + if job.IsGpuTrainTask() { + err = cloudbrain.StopJob(job.CloudBrainTaskId) + if err != nil { + log.Error("Stop cloudbrain Job(%s) failed:%v", job.CloudBrainTaskId, err) + } + } else { + _, err = modelarts.StopTrainJob(job.CloudBrainTaskId, job.ModelArtsVersionId) + if err != nil { + log.Error("Stop modelarts Job(%s) failed:%v", job.CloudBrainTaskId, err) + } + } + job.Status = string(models.JobStopped) + if job.EndTime == 0 { + job.EndTime = timeutil.TimeStampNow() + } + models.ModelConvertSetDuration(job) + err = models.UpdateModelConvert(job) + if err != nil { + log.Error("UpdateModelConvert failed:", err) + } + ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelmanage/convert_model") +} + +func ShowModelConvertInfo(ctx *context.Context) { + ctx.Data["ID"] = ctx.Query("ID") + ctx.Data["isModelManage"] = true + ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage) + + job, err := models.QueryModelConvertById(ctx.Query("ID")) + if err == nil { + if job.TrainJobDuration == "" { + job.TrainJobDuration = "00:00:00" + } + ctx.Data["task"] = job + } else { + ctx.ServerError("Not found task.", err) + return + } + ctx.Data["Name"] = job.Name + ctx.Data["canDownload"] = isOper(ctx, job.UserId) + user, err := models.GetUserByID(job.UserId) + if err == nil { + job.UserName = user.Name + job.UserRelAvatarLink = user.RelAvatarLink() + } + + if job.IsGpuTrainTask() { + ctx.Data["npu_display"] = "none" + ctx.Data["gpu_display"] = "block" + if job.CloudBrainTaskId == "" { + ctx.Data["ExitDiagnostics"] = "" + ctx.Data["AppExitDiagnostics"] = "" + ctx.HTML(200, tplModelConvertInfo) + return + } + result, err := cloudbrain.GetJob(job.CloudBrainTaskId) + if err != nil { + log.Info("error:" + err.Error()) + ctx.Data["error"] = err.Error() + ctx.HTML(200, tplModelConvertInfo) + return + } + if result != nil { + jobRes, _ := models.ConvertToJobResultPayload(result.Payload) + ctx.Data["result"] = jobRes + taskRoles := jobRes.TaskRoles + taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) + ctx.Data["taskRes"] = taskRes + ctx.Data["ExitDiagnostics"] = taskRes.TaskStatuses[0].ExitDiagnostics + ctx.Data["AppExitDiagnostics"] = jobRes.JobStatus.AppExitDiagnostics + + job.Status = jobRes.JobStatus.State + + if jobRes.JobStatus.State != string(models.JobWaiting) && jobRes.JobStatus.State != string(models.JobFailed) { + job.ContainerIp = taskRes.TaskStatuses[0].ContainerIP + job.ContainerID = taskRes.TaskStatuses[0].ContainerID + job.Status = taskRes.TaskStatuses[0].State + } + if jobRes.JobStatus.State != string(models.JobWaiting) { + models.ModelComputeAndSetDuration(job, jobRes) + err = models.UpdateModelConvert(job) + if err != nil { + log.Error("UpdateModelConvert failed:", err) + } + } + } + } else { + if job.CloudBrainTaskId != "" { + result, err := modelarts.GetTrainJob(job.CloudBrainTaskId, job.ModelArtsVersionId) + if err != nil { + log.Info("error:" + err.Error()) + ctx.Data["error"] = err.Error() + return + } + job.Status = modelarts.TransTrainJobStatus(result.IntStatus) + job.RunTime = result.Duration / 1000 + job.TrainJobDuration = models.ConvertDurationToStr(job.RunTime) + err = models.UpdateModelConvert(job) + if err != nil { + log.Error("UpdateJob failed:", err) + } + } + ctx.Data["npu_display"] = "block" + ctx.Data["gpu_display"] = "none" + ctx.Data["ExitDiagnostics"] = "" + ctx.Data["AppExitDiagnostics"] = "" + } + + ctx.HTML(200, tplModelConvertInfo) +} + +func ConvertModelTemplate(ctx *context.Context) { + ctx.Data["isModelManage"] = true + ctx.Data["TRAIN_COUNT"] = 0 + SetModelCount(ctx) + ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage) + ShowModelConvertPageInfo(ctx) + ctx.HTML(200, tplModelManageConvertIndex) +} + +func ShowModelConvertPageInfo(ctx *context.Context) { + log.Info("ShowModelConvertInfo start.") + if !isQueryRight(ctx) { + log.Info("no right.") + ctx.NotFound(ctx.Req.URL.RequestURI(), nil) + return + } + page := ctx.QueryInt("page") + if page <= 0 { + page = 1 + } + pageSize := ctx.QueryInt("pageSize") + if pageSize <= 0 { + pageSize = setting.UI.IssuePagingNum + } + repoId := ctx.Repo.Repository.ID + modelResult, count, err := models.QueryModelConvert(&models.AiModelQueryOptions{ + ListOptions: models.ListOptions{ + Page: page, + PageSize: pageSize, + }, + RepoID: repoId, + }) + if err != nil { + log.Info("query db error." + err.Error()) + ctx.ServerError("Cloudbrain", err) + return + } + ctx.Data["MODEL_CONVERT_COUNT"] = count + userIds := make([]int64, len(modelResult)) + for i, model := range modelResult { + model.IsCanOper = isOper(ctx, model.UserId) + model.IsCanDelete = isCanDelete(ctx, model.UserId) + userIds[i] = model.UserId + } + userNameMap := queryUserName(userIds) + for _, model := range modelResult { + value := userNameMap[model.UserId] + if value != nil { + model.UserName = value.Name + model.UserRelAvatarLink = value.RelAvatarLink() + } + } + pager := context.NewPagination(int(count), page, pageSize, 5) + ctx.Data["Page"] = pager + ctx.Data["Tasks"] = modelResult + +} + +func ModelConvertDownloadModel(ctx *context.Context) { + log.Info("enter here......") + id := ctx.Params(":id") + job, err := models.QueryModelConvertById(id) + if err != nil { + ctx.ServerError("Not found task.", err) + return + } + AllDownload := ctx.QueryBool("AllDownload") + if AllDownload { + if job.IsGpuTrainTask() { + path := setting.CBCodePathPrefix + job.ID + "/model/" + allFile, err := storage.GetAllObjectByBucketAndPrefixMinio(setting.Attachment.Minio.Bucket, path) + if err == nil { + returnFileName := job.Name + ".zip" + MinioDownloadManyFile(path, ctx, returnFileName, allFile) + } else { + log.Info("error,msg=" + err.Error()) + ctx.ServerError("no file to download.", err) + } + } else { + Prefix := path.Join(setting.TrainJobModelPath, job.ID, "output/", "V0001", "") + "/" + log.Info("bucket=" + setting.Bucket + "prefix=" + Prefix) + allFile, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, Prefix) + if err == nil { + returnFileName := job.Name + ".zip" + ObsDownloadManyFile(Prefix, ctx, returnFileName, allFile) + } else { + log.Info("error,msg=" + err.Error()) + ctx.ServerError("no file to download.", err) + } + } + } else { + parentDir := ctx.Query("parentDir") + fileName := ctx.Query("fileName") + jobName := ctx.Query("jobName") + if job.IsGpuTrainTask() { + filePath := "jobs/" + jobName + "/model/" + parentDir + url, err := storage.Attachments.PresignedGetURL(filePath, fileName) + if err != nil { + log.Error("PresignedGetURL failed: %v", err.Error(), ctx.Data["msgID"]) + ctx.ServerError("PresignedGetURL", err) + return + } + //ctx.JSON(200, url) + http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusTemporaryRedirect) + } else { + ObjectKey := path.Join(setting.TrainJobModelPath, job.ID, "output/", "V0001", parentDir, fileName) + log.Info("ObjectKey=" + ObjectKey) + url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, ObjectKey) + if err != nil { + log.Error("GetObsCreateSignedUrl failed: %v", err.Error(), ctx.Data["msgID"]) + ctx.ServerError("GetObsCreateSignedUrl", err) + return + } + http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusTemporaryRedirect) + } + } + +} diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index 2c24527ce..0aef1a70c 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -26,6 +26,7 @@ const ( tplModelInfo = "repo/modelmanage/showinfo" MODEL_LATEST = 1 MODEL_NOT_LATEST = 0 + MODEL_MAX_SIZE = 1024 * 1024 * 1024 ) func saveModelByParameters(jobId string, versionName string, name string, version string, label string, description string, engine int, ctx *context.Context) error { @@ -58,14 +59,16 @@ func saveModelByParameters(jobId string, versionName string, name string, versio } } cloudType := aiTask.Type + modelSelectedFile := ctx.Query("modelSelectedFile") //download model zip //train type - if cloudType == models.TypeCloudBrainTwo { - modelPath, modelSize, err = downloadModelFromCloudBrainTwo(id, aiTask.JobName, "", aiTask.TrainUrl) + if aiTask.ComputeResource == models.NPUResource { + modelPath, modelSize, err = downloadModelFromCloudBrainTwo(id, aiTask.JobName, "", aiTask.TrainUrl, modelSelectedFile) if err != nil { log.Info("download model from CloudBrainTwo faild." + err.Error()) return err } - } else if cloudType == models.TypeCloudBrainOne { + cloudType = models.TypeCloudBrainTwo + } else if aiTask.ComputeResource == models.GPUResource { var ResourceSpecs *models.ResourceSpecs json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) for _, tmp := range ResourceSpecs.ResourceSpec { @@ -74,12 +77,24 @@ func saveModelByParameters(jobId string, versionName string, name string, versio aiTask.FlavorName = flaverName } } - modelPath, modelSize, err = downloadModelFromCloudBrainOne(id, aiTask.JobName, "", aiTask.TrainUrl) + modelPath, modelSize, err = downloadModelFromCloudBrainOne(id, aiTask.JobName, "", aiTask.TrainUrl, modelSelectedFile) if err != nil { log.Info("download model from CloudBrainOne faild." + err.Error()) return err } - } + cloudType = models.TypeCloudBrainOne + } + // else if cloudType == models.TypeC2Net { + // if aiTask.ComputeResource == models.NPUResource { + // modelPath, modelSize, err = downloadModelFromCloudBrainTwo(id, aiTask.JobName, "", aiTask.TrainUrl, modelSelectedFile) + // if err != nil { + // log.Info("download model from CloudBrainTwo faild." + err.Error()) + // return err + // } + // } else if aiTask.ComputeResource == models.GPUResource { + + // } + // } accuracy := make(map[string]string) accuracy["F1"] = "" accuracy["Recall"] = "" @@ -163,7 +178,8 @@ func SaveModel(ctx *context.Context) { description := ctx.Query("Description") engine := ctx.QueryInt("Engine") trainTaskCreate := ctx.QueryBool("trainTaskCreate") - log.Info("engine=" + fmt.Sprint(engine)) + modelSelectedFile := ctx.Query("modelSelectedFile") + log.Info("engine=" + fmt.Sprint(engine) + " modelSelectedFile=" + modelSelectedFile) if !trainTaskCreate { if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { //ctx.NotFound(ctx.Req.URL.RequestURI(), nil) @@ -176,6 +192,10 @@ func SaveModel(ctx *context.Context) { ctx.Error(500, fmt.Sprintf("JobId or VersionName is null.")) return } + if modelSelectedFile == "" { + ctx.Error(500, fmt.Sprintf("Not selected model file.")) + return + } if name == "" || version == "" { ctx.Error(500, fmt.Sprintf("name or version is null.")) @@ -193,11 +213,22 @@ func SaveModel(ctx *context.Context) { log.Info("save model end.") } -func downloadModelFromCloudBrainTwo(modelUUID string, jobName string, parentDir string, trainUrl string) (string, int64, error) { +func downloadModelFromCloudBrainTwo(modelUUID string, jobName string, parentDir string, trainUrl string, modelSelectedFile string) (string, int64, error) { objectkey := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, parentDir), "/") if trainUrl != "" { objectkey = strings.Trim(trainUrl[len(setting.Bucket)+1:], "/") } + prefix := objectkey + "/" + + filterFiles := strings.Split(modelSelectedFile, ";") + Files := make([]string, 0) + for _, shortFile := range filterFiles { + Files = append(Files, prefix+shortFile) + } + totalSize := storage.ObsGetFilesSize(setting.Bucket, Files) + if float64(totalSize) > setting.MaxModelSize*MODEL_MAX_SIZE { + return "", 0, errors.New("Cannot create model, as model is exceed " + fmt.Sprint(setting.MaxModelSize) + "G.") + } modelDbResult, err := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, objectkey, "") log.Info("bucket=" + setting.Bucket + " objectkey=" + objectkey) @@ -206,26 +237,33 @@ func downloadModelFromCloudBrainTwo(modelUUID string, jobName string, parentDir return "", 0, err } if len(modelDbResult) == 0 { - return "", 0, errors.New("cannot create model, as model is empty.") + return "", 0, errors.New("Cannot create model, as model is empty.") } - prefix := objectkey + "/" destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(modelUUID) + "/" - - size, err := storage.ObsCopyManyFile(setting.Bucket, prefix, setting.Bucket, destKeyNamePrefix) + size, err := storage.ObsCopyManyFile(setting.Bucket, prefix, setting.Bucket, destKeyNamePrefix, filterFiles) dataActualPath := setting.Bucket + "/" + destKeyNamePrefix return dataActualPath, size, nil } -func downloadModelFromCloudBrainOne(modelUUID string, jobName string, parentDir string, trainUrl string) (string, int64, error) { +func downloadModelFromCloudBrainOne(modelUUID string, jobName string, parentDir string, trainUrl string, modelSelectedFile string) (string, int64, error) { modelActualPath := storage.GetMinioPath(jobName, "/model/") log.Info("modelActualPath=" + modelActualPath) modelSrcPrefix := setting.CBCodePathPrefix + jobName + "/model/" destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(modelUUID) + "/" bucketName := setting.Attachment.Minio.Bucket log.Info("destKeyNamePrefix=" + destKeyNamePrefix + " modelSrcPrefix=" + modelSrcPrefix + " bucket=" + bucketName) - size, err := storage.MinioPathCopy(bucketName, modelSrcPrefix, destKeyNamePrefix) + filterFiles := strings.Split(modelSelectedFile, ";") + Files := make([]string, 0) + for _, shortFile := range filterFiles { + Files = append(Files, modelSrcPrefix+shortFile) + } + totalSize := storage.MinioGetFilesSize(bucketName, Files) + if float64(totalSize) > setting.MaxModelSize*MODEL_MAX_SIZE { + return "", 0, errors.New("Cannot create model, as model is exceed " + fmt.Sprint(setting.MaxModelSize) + "G.") + } + size, err := storage.MinioCopyFiles(bucketName, modelSrcPrefix, destKeyNamePrefix, filterFiles) if err == nil { dataActualPath := bucketName + "/" + destKeyNamePrefix return dataActualPath, size, nil @@ -459,6 +497,35 @@ func QueryTrainJobList(ctx *context.Context) { } +func QueryTrainModelList(ctx *context.Context) { + log.Info("query train job list. start.") + jobName := ctx.Query("jobName") + taskType := ctx.QueryInt("type") + VersionName := ctx.Query("VersionName") + if taskType == models.TypeCloudBrainTwo { + objectkey := path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, VersionName) + "/" + modelDbResult, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, objectkey) + log.Info("bucket=" + setting.Bucket + " objectkey=" + objectkey) + if err != nil { + log.Info("get TypeCloudBrainTwo TrainJobListModel failed:", err) + } else { + ctx.JSON(200, modelDbResult) + return + } + } else if taskType == models.TypeCloudBrainOne { + modelSrcPrefix := setting.CBCodePathPrefix + jobName + "/model/" + bucketName := setting.Attachment.Minio.Bucket + modelDbResult, err := storage.GetAllObjectByBucketAndPrefixMinio(bucketName, modelSrcPrefix) + if err != nil { + log.Info("get TypeCloudBrainOne TrainJobListModel failed:", err) + } else { + ctx.JSON(200, modelDbResult) + return + } + } + ctx.JSON(200, "") +} + func DownloadSingleModelFile(ctx *context.Context) { log.Info("DownloadSingleModelFile start.") id := ctx.Params(":ID") @@ -766,7 +833,7 @@ func QueryModelListForPredict(ctx *context.Context) { PageSize: -1, }, RepoID: repoId, - Type: -1, + Type: ctx.QueryInt("type"), New: -1, }) if err != nil { diff --git a/routers/repo/cloudbrain.go b/routers/repo/cloudbrain.go index 2d2b53e72..be0f8a5a2 100755 --- a/routers/repo/cloudbrain.go +++ b/routers/repo/cloudbrain.go @@ -47,6 +47,9 @@ const ( tplCloudBrainTrainJobNew base.TplName = "repo/cloudbrain/trainjob/new" tplCloudBrainTrainJobShow base.TplName = "repo/cloudbrain/trainjob/show" + + tplCloudBrainInferenceJobNew base.TplName = "repo/cloudbrain/inference/new" + tplCloudBrainInferenceJobShow base.TplName = "repo/cloudbrain/inference/show" ) var ( @@ -56,6 +59,7 @@ var ( benchmarkGpuInfos *models.GpuInfos benchmarkResourceSpecs *models.ResourceSpecs trainGpuInfos *models.GpuInfos + inferenceGpuInfos *models.GpuInfos ) const BENCHMARK_TYPE_CODE = "repo.cloudbrain.benchmark.types" @@ -97,45 +101,6 @@ func cloudBrainNewDataPrepare(ctx *context.Context) error { var displayJobName = jobNamePrefixValid(cutString(ctx.User.Name, 5)) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] ctx.Data["display_job_name"] = displayJobName - result, err := cloudbrain.GetImages() - if err != nil { - ctx.Data["error"] = err.Error() - log.Error("cloudbrain.GetImages failed:", err.Error(), ctx.Data["MsgID"]) - } - - for i, payload := range result.Payload.ImageInfo { - if strings.HasPrefix(result.Payload.ImageInfo[i].Place, "192.168") { - result.Payload.ImageInfo[i].PlaceView = payload.Place[strings.Index(payload.Place, "/"):len(payload.Place)] - } else { - result.Payload.ImageInfo[i].PlaceView = payload.Place - } - } - - ctx.Data["images"] = result.Payload.ImageInfo - - resultPublic, err := cloudbrain.GetPublicImages() - if err != nil { - ctx.Data["error"] = err.Error() - log.Error("cloudbrain.GetPublicImages failed:", err.Error(), ctx.Data["MsgID"]) - } - - for i, payload := range resultPublic.Payload.ImageInfo { - if strings.HasPrefix(resultPublic.Payload.ImageInfo[i].Place, "192.168") { - resultPublic.Payload.ImageInfo[i].PlaceView = payload.Place[strings.Index(payload.Place, "/"):len(payload.Place)] - } else { - resultPublic.Payload.ImageInfo[i].PlaceView = payload.Place - } - } - - ctx.Data["public_images"] = resultPublic.Payload.ImageInfo - - attachs, err := models.GetAllUserAttachments(ctx.User.ID) - if err != nil { - log.Error("GetAllUserAttachments failed: %v", err, ctx.Data["MsgID"]) - return err - } - - ctx.Data["attachments"] = attachs ctx.Data["command"] = cloudbrain.GetCloudbrainDebugCommand() ctx.Data["code_path"] = cloudbrain.CodeMountPath ctx.Data["dataset_path"] = cloudbrain.DataSetMountPath @@ -149,6 +114,10 @@ func cloudBrainNewDataPrepare(ctx *context.Context) error { ctx.Data["benchmark_categories"] = categories.Category ctx.Data["benchmark_types"] = GetBenchmarkTypes(ctx).BenchmarkType + queuesDetail, _ := cloudbrain.GetQueuesDetail() + if queuesDetail != nil { + ctx.Data["QueuesDetail"] = queuesDetail + } cloudbrain.InitSpecialPool() @@ -162,6 +131,11 @@ func cloudBrainNewDataPrepare(ctx *context.Context) error { } ctx.Data["train_gpu_types"] = trainGpuInfos.GpuInfo + if inferenceGpuInfos == nil { + json.Unmarshal([]byte(setting.InferenceGpuTypes), &inferenceGpuInfos) + } + ctx.Data["inference_gpu_types"] = inferenceGpuInfos.GpuInfo + if benchmarkGpuInfos == nil { json.Unmarshal([]byte(setting.BenchmarkGpuTypes), &benchmarkGpuInfos) } @@ -182,6 +156,11 @@ func cloudBrainNewDataPrepare(ctx *context.Context) error { } ctx.Data["train_resource_specs"] = cloudbrain.TrainResourceSpecs.ResourceSpec + if cloudbrain.InferenceResourceSpecs == nil { + json.Unmarshal([]byte(setting.InferenceResourceSpecs), &cloudbrain.InferenceResourceSpecs) + } + ctx.Data["inference_resource_specs"] = cloudbrain.InferenceResourceSpecs.ResourceSpec + if cloudbrain.SpecialPools != nil { var debugGpuTypes []*models.GpuInfo var trainGpuTypes []*models.GpuInfo @@ -372,6 +351,7 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { BenchmarkTypeID: 0, BenchmarkChildTypeID: 0, ResourceSpecId: resourceSpecId, + ResultPath: storage.GetMinioPath(jobName, cloudbrain.ResultPath+"/"), } err = cloudbrain.GenerateTask(req) @@ -388,6 +368,125 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { } } + +func CloudBrainInferenceJobCreate(ctx *context.Context, form auth.CreateCloudBrainInferencForm) { + ctx.Data["PageIsCloudBrain"] = true + displayJobName := form.DisplayJobName + jobName := util.ConvertDisplayJobNameToJobName(displayJobName) + image := strings.TrimSpace(form.Image) + uuid := form.Attachment + jobType := string(models.JobTypeInference) + gpuQueue := form.GpuType + codePath := setting.JobPath + jobName + cloudbrain.CodeMountPath + resourceSpecId := form.ResourceSpecId + branchName := form.BranchName + repo := ctx.Repo.Repository + + ckptUrl := setting.Attachment.Minio.RealPath + form.TrainUrl + form.CkptName + log.Info("ckpt url:" + ckptUrl) + tpl := tplCloudBrainInferenceJobNew + command, err := getInferenceJobCommand(form) + if err != nil { + log.Error("getTrainJobCommand failed: %v", err) + ctx.RenderWithErr(err.Error(), tpl, &form) + return + } + + tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName) + if err == nil { + if len(tasks) != 0 { + log.Error("the job name did already exist", ctx.Data["MsgID"]) + cloudBrainNewDataPrepare(ctx) + ctx.RenderWithErr("the job name did already exist", tpl, &form) + return + } + } else { + if !models.IsErrJobNotExist(err) { + log.Error("system error, %v", err, ctx.Data["MsgID"]) + cloudBrainNewDataPrepare(ctx) + ctx.RenderWithErr("system error", tpl, &form) + return + } + } + + if !jobNamePattern.MatchString(displayJobName) { + ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tpl, &form) + return + } + + count, err := models.GetCloudbrainCountByUserID(ctx.User.ID, jobType) + if err != nil { + log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"]) + cloudBrainNewDataPrepare(ctx) + ctx.RenderWithErr("system error", tpl, &form) + return + } else { + if count >= 1 { + log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) + cloudBrainNewDataPrepare(ctx) + ctx.RenderWithErr(ctx.Tr("repo.cloudbrain.morethanonejob"), tpl, &form) + return + } + } + + if branchName == "" { + branchName = cloudbrain.DefaultBranchName + } + downloadCode(repo, codePath, branchName) + uploadCodeToMinio(codePath+"/", jobName, cloudbrain.CodeMountPath+"/") + resultPath := setting.JobPath + jobName + cloudbrain.ResultPath + "/" + mkResultPath(resultPath) + uploadCodeToMinio(resultPath, jobName, cloudbrain.ResultPath+"/") + + commitID, _ := ctx.Repo.GitRepo.GetBranchCommitID(branchName) + + datasetInfos, datasetNames, err := models.GetDatasetInfo(uuid) + if err != nil { + log.Error("GetDatasetInfo failed: %v", err, ctx.Data["MsgID"]) + cloudBrainNewDataPrepare(ctx) + ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tpl, &form) + return + } + + req := cloudbrain.GenerateCloudBrainTaskReq{ + Ctx: ctx, + DisplayJobName: displayJobName, + JobName: jobName, + Image: image, + Command: command, + Uuids: uuid, + DatasetNames: datasetNames, + DatasetInfos: datasetInfos, + CodePath: storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), + ModelPath: setting.Attachment.Minio.RealPath + form.TrainUrl, + BenchmarkPath: storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), + Snn4ImageNetPath: storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), + BrainScorePath: storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), + JobType: jobType, + GpuQueue: gpuQueue, + Description: form.Description, + BranchName: branchName, + BootFile: form.BootFile, + Params: form.Params, + CommitID: commitID, + ResourceSpecId: resourceSpecId, + ResultPath: storage.GetMinioPath(jobName, cloudbrain.ResultPath+"/"), + ModelName: form.ModelName, + ModelVersion: form.ModelVersion, + CkptName: form.CkptName, + TrainUrl: form.TrainUrl, + } + + err = cloudbrain.GenerateTask(req) + if err != nil { + cloudBrainNewDataPrepare(ctx) + ctx.RenderWithErr(err.Error(), tpl, &form) + return + } + + ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/inference-job") + +} /** 检查用户传输的参数是否符合专属资源池 */ @@ -459,7 +558,18 @@ func CloudBrainRestart(ctx *context.Context) { for _, resourceType := range gpuInfos.GpuInfo { if resourceType.Queue == task.GpuQueue { hasSameResource = true - continue + break + } + } + if !hasSameResource && cloudbrain.SpecialPools != nil { + + for _, specialPool := range cloudbrain.SpecialPools.Pools { + cloudbrain.IsElementExist(specialPool.JobType, string(models.JobTypeDebug)) + for _, pool := range specialPool.Pool { + if pool.Queue == task.GpuQueue { + hasSameResource = true + } + } } } @@ -522,7 +632,7 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo var task *models.Cloudbrain var err error - if jobType == models.JobTypeTrain { + if jobType == models.JobTypeTrain || jobType == models.JobTypeInference { task, err = models.GetCloudbrainByJobID(ctx.Params(":jobid")) } else { task, err = models.GetCloudbrainByIDWithDeleted(ctx.Params(":id")) @@ -553,6 +663,18 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo ctx.Data["ShareMemMiB"] = tmp.ShareMemMiB } } + } else if task.JobType == string(models.JobTypeInference) { + if cloudbrain.InferenceResourceSpecs == nil { + json.Unmarshal([]byte(setting.InferenceResourceSpecs), &cloudbrain.InferenceResourceSpecs) + } + for _, tmp := range cloudbrain.InferenceResourceSpecs.ResourceSpec { + if tmp.Id == task.ResourceSpecId { + ctx.Data["GpuNum"] = tmp.GpuNum + ctx.Data["CpuNum"] = tmp.CpuNum + ctx.Data["MemMiB"] = tmp.MemMiB + ctx.Data["ShareMemMiB"] = tmp.ShareMemMiB + } + } } else { if cloudbrain.ResourceSpecs == nil { json.Unmarshal([]byte(setting.ResourceSpecs), &cloudbrain.ResourceSpecs) @@ -581,6 +703,15 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo ctx.Data["resource_type"] = resourceType.Value } } + } else if task.JobType == string(models.JobTypeInference) { + if inferenceGpuInfos == nil { + json.Unmarshal([]byte(setting.InferenceGpuTypes), &inferenceGpuInfos) + } + for _, resourceType := range inferenceGpuInfos.GpuInfo { + if resourceType.Queue == jobRes.Config.GpuType { + ctx.Data["resource_type"] = resourceType.Value + } + } } else if cloudbrain.IsBenchmarkJob(task.JobType) { if benchmarkGpuInfos == nil { json.Unmarshal([]byte(setting.BenchmarkGpuTypes), &benchmarkGpuInfos) @@ -938,7 +1069,7 @@ func CloudBrainStop(ctx *context.Context) { if task.Status == string(models.JobStopped) || task.Status == string(models.JobFailed) || task.Status == string(models.JobSucceeded) { log.Error("the job(%s) has been stopped", task.JobName, ctx.Data["msgID"]) resultCode = "-1" - errorMsg = "system error" + errorMsg = "cloudbrain.Already_stopped" break } @@ -946,7 +1077,7 @@ func CloudBrainStop(ctx *context.Context) { if err != nil { log.Error("StopJob(%s) failed:%v", task.JobName, err, ctx.Data["msgID"]) resultCode = "-1" - errorMsg = "system error" + errorMsg = "cloudbrain.Stopped_failed" break } @@ -959,7 +1090,7 @@ func CloudBrainStop(ctx *context.Context) { if err != nil { log.Error("UpdateJob(%s) failed:%v", task.JobName, err, ctx.Data["msgID"]) resultCode = "-1" - errorMsg = "system error" + errorMsg = "cloudbrain.Stopped_success_update_status_fail" break } @@ -969,7 +1100,7 @@ func CloudBrainStop(ctx *context.Context) { ctx.JSON(200, map[string]interface{}{ "result_code": resultCode, - "error_msg": errorMsg, + "error_msg": ctx.Tr(errorMsg), "status": status, "id": ID, "StatusOK": 0, @@ -1259,6 +1390,18 @@ func GetModelDirs(jobName string, parentDir string) (string, error) { return getDirs(req) } +func GetResultDirs(jobName string, parentDir string) (string, error) { + var req string + modelActualPath := storage.GetMinioPath(jobName, cloudbrain.ResultPath+"/") + if parentDir == "" { + req = "baseDir=" + modelActualPath + } else { + req = "baseDir=" + modelActualPath + "&parentDir=" + parentDir + } + + return getDirs(req) +} + func CloudBrainDownloadModel(ctx *context.Context) { parentDir := ctx.Query("parentDir") fileName := ctx.Query("fileName") @@ -1273,6 +1416,20 @@ func CloudBrainDownloadModel(ctx *context.Context) { ctx.Resp.Header().Set("Cache-Control", "max-age=0") http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) } +func CloudBrainDownloadInferenceResult(ctx *context.Context) { + parentDir := ctx.Query("parentDir") + fileName := ctx.Query("fileName") + jobName := ctx.Query("jobName") + filePath := "jobs/" + jobName + "/result/" + parentDir + url, err := storage.Attachments.PresignedGetURL(filePath, fileName) + if err != nil { + log.Error("PresignedGetURL failed: %v", err.Error(), ctx.Data["msgID"]) + ctx.ServerError("PresignedGetURL", err) + return + } + ctx.Resp.Header().Set("Cache-Control", "max-age=0") + http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) +} func GetRate(ctx *context.Context) { isObjectDetcionAll := ctx.QueryBool("isObjectDetcionAll") @@ -1426,13 +1583,21 @@ func uploadCodeToMinio(codePath, jobName, parentDir string) error { } func mkModelPath(modelPath string) error { - err := os.MkdirAll(modelPath, os.ModePerm) + return mkPathAndReadMeFile(modelPath, "You can put the model file into this directory and download it by the web page.") +} + +func mkResultPath(resultPath string) error { + return mkPathAndReadMeFile(resultPath, "You can put the result file into this directory and download it by the web page.") +} + +func mkPathAndReadMeFile(path string, text string) error { + err := os.MkdirAll(path, os.ModePerm) if err != nil { - log.Error("MkdirAll(%s) failed:%v", modelPath, err) + log.Error("MkdirAll(%s) failed:%v", path, err) return err } - fileName := modelPath + "README" + fileName := path + "README" f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm) if err != nil { log.Error("OpenFile failed", err.Error()) @@ -1441,7 +1606,7 @@ func mkModelPath(modelPath string) error { defer f.Close() - _, err = f.WriteString("You can put the model file into this directory and download it by the web page.") + _, err = f.WriteString(text) if err != nil { log.Error("WriteString failed", err.Error()) return err @@ -2140,6 +2305,7 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo BenchmarkTypeID: benchmarkTypeID, BenchmarkChildTypeID: benchmarkChildTypeID, ResourceSpecId: resourceSpecId, + ResultPath: storage.GetMinioPath(jobName, cloudbrain.ResultPath+"/"), } err = cloudbrain.GenerateTask(req) @@ -2268,6 +2434,7 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm) BenchmarkTypeID: 0, BenchmarkChildTypeID: benchmarkChildTypeID, ResourceSpecId: resourceSpecId, + ResultPath: storage.GetMinioPath(jobName, cloudbrain.ResultPath+"/"), } err = cloudbrain.GenerateTask(req) @@ -2318,6 +2485,64 @@ func CloudBrainTrainJobNew(ctx *context.Context) { ctx.HTML(http.StatusOK, tplCloudBrainTrainJobNew) } +func InferenceCloudBrainJobNew(ctx *context.Context) { + err := cloudBrainNewDataPrepare(ctx) + if err != nil { + ctx.ServerError("get new train-job info failed", err) + return + } + ctx.HTML(http.StatusOK, tplCloudBrainInferenceJobNew) +} + +func InferenceCloudBrainJobShow(ctx *context.Context) { + cloudBrainShow(ctx, tplCloudBrainInferenceJobShow, models.JobTypeInference) +} + +func DownloadInferenceResultFile(ctx *context.Context) { + var jobID = ctx.Params(":jobid") + var versionName = ctx.Query("version_name") + task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName) + if err != nil { + log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err.Error()) + return + } + + allFile, err := storage.GetAllObjectByBucketAndPrefixMinio(setting.Attachment.Minio.Bucket, task.ResultUrl) + returnFileName := task.DisplayJobName + ".zip" + MinioDownloadManyFile(task.ResultUrl, ctx, returnFileName, allFile) +} + +func getInferenceJobCommand(form auth.CreateCloudBrainInferencForm) (string, error) { + var command string + bootFile := strings.TrimSpace(form.BootFile) + params := form.Params + + if !strings.HasSuffix(bootFile, ".py") { + log.Error("bootFile(%s) format error", bootFile) + return command, errors.New("bootFile format error") + } + + var parameters models.Parameters + var param string + if len(params) != 0 { + err := json.Unmarshal([]byte(params), ¶meters) + if err != nil { + log.Error("Failed to Unmarshal params: %s (%v)", params, err) + return command, err + } + + for _, parameter := range parameters.Parameter { + param += " --" + parameter.Label + "=" + parameter.Value + } + } + + param += " --modelname" + "=" + form.CkptName + + command += "python /code/" + bootFile + param + " > " + cloudbrain.ResultPath + "/" + form.DisplayJobName + "-" + cloudbrain.LogFile + + return command, nil +} + func getTrainJobCommand(form auth.CreateCloudBrainForm) (string, error) { var command string bootFile := strings.TrimSpace(form.BootFile) diff --git a/routers/repo/grampus.go b/routers/repo/grampus.go index 976a3a1e5..6cfbe107d 100755 --- a/routers/repo/grampus.go +++ b/routers/repo/grampus.go @@ -43,6 +43,8 @@ func GrampusTrainJobGPUNew(ctx *context.Context) { ctx.ServerError("get new train-job info failed", err) return } + waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeC2Net, models.GPUResource, models.JobTypeTrain) + ctx.Data["WaitCount"] = waitCount ctx.HTML(http.StatusOK, tplGrampusTrainJobGPUNew) } @@ -53,6 +55,8 @@ func GrampusTrainJobNPUNew(ctx *context.Context) { ctx.ServerError("get new train-job info failed", err) return } + waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeC2Net, models.NPUResource, models.JobTypeTrain) + ctx.Data["WaitCount"] = waitCount ctx.HTML(200, tplGrampusTrainJobNPUNew) } diff --git a/routers/repo/modelarts.go b/routers/repo/modelarts.go index c66055003..446b32a0f 100755 --- a/routers/repo/modelarts.go +++ b/routers/repo/modelarts.go @@ -120,7 +120,8 @@ func MustEnableModelArts(ctx *context.Context) { func NotebookNew(ctx *context.Context) { notebookNewDataPrepare(ctx) - + waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "") + ctx.Data["WaitCount"] = waitCount ctx.HTML(200, tplModelArtsNotebookNew) } @@ -661,6 +662,8 @@ func TrainJobNew(ctx *context.Context) { ctx.ServerError("get new train-job info failed", err) return } + waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "") + ctx.Data["WaitCount"] = waitCount ctx.HTML(200, tplModelArtsTrainJobNew) } @@ -813,6 +816,8 @@ func TrainJobNewVersion(ctx *context.Context) { ctx.ServerError("get new train-job info failed", err) return } + waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "") + ctx.Data["WaitCount"] = waitCount ctx.HTML(200, tplModelArtsTrainJobVersionNew) } @@ -1010,7 +1015,7 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) flavorCode := form.Flavor params := form.Params poolID := form.PoolID - isSaveParam := form.IsSaveParam + //isSaveParam := form.IsSaveParam repo := ctx.Repo.Repository codeLocalPath := setting.JobPath + jobName + modelarts.CodePath codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath @@ -1155,45 +1160,45 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) } //save param config - if isSaveParam == "on" { - saveparams := append(param, models.Parameter{ - Label: modelarts.TrainUrl, - Value: outputObsPath, - }, models.Parameter{ - Label: modelarts.DataUrl, - Value: dataPath, - }) - if form.ParameterTemplateName == "" { - log.Error("ParameterTemplateName is empty") - trainJobNewDataPrepare(ctx) - ctx.RenderWithErr("保存作业参数时,作业参数名称不能为空", tplModelArtsTrainJobNew, &form) - return - } - - _, err := modelarts.CreateTrainJobConfig(models.CreateConfigParams{ - ConfigName: form.ParameterTemplateName, - Description: form.PrameterDescription, - DataUrl: dataPath, - AppUrl: codeObsPath, - BootFileUrl: codeObsPath + bootFile, - TrainUrl: outputObsPath, - Flavor: models.Flavor{ - Code: flavorCode, - }, - WorkServerNum: workServerNumber, - EngineID: int64(engineID), - LogUrl: logObsPath, - PoolID: poolID, - Parameter: saveparams, - }) - - if err != nil { - log.Error("Failed to CreateTrainJobConfig: %v", err) - trainJobErrorNewDataPrepare(ctx, form) - ctx.RenderWithErr("保存作业参数失败:"+err.Error(), tplModelArtsTrainJobNew, &form) - return - } - } + // if isSaveParam == "on" { + // saveparams := append(param, models.Parameter{ + // Label: modelarts.TrainUrl, + // Value: outputObsPath, + // }, models.Parameter{ + // Label: modelarts.DataUrl, + // Value: dataPath, + // }) + // if form.ParameterTemplateName == "" { + // log.Error("ParameterTemplateName is empty") + // trainJobNewDataPrepare(ctx) + // ctx.RenderWithErr("保存作业参数时,作业参数名称不能为空", tplModelArtsTrainJobNew, &form) + // return + // } + + // _, err := modelarts.CreateTrainJobConfig(models.CreateConfigParams{ + // ConfigName: form.ParameterTemplateName, + // Description: form.PrameterDescription, + // DataUrl: dataPath, + // AppUrl: codeObsPath, + // BootFileUrl: codeObsPath + bootFile, + // TrainUrl: outputObsPath, + // Flavor: models.Flavor{ + // Code: flavorCode, + // }, + // WorkServerNum: workServerNumber, + // EngineID: int64(engineID), + // LogUrl: logObsPath, + // PoolID: poolID, + // Parameter: saveparams, + // }) + + // if err != nil { + // log.Error("Failed to CreateTrainJobConfig: %v", err) + // trainJobErrorNewDataPrepare(ctx, form) + // ctx.RenderWithErr("保存作业参数失败:"+err.Error(), tplModelArtsTrainJobNew, &form) + // return + // } + // } req := &modelarts.GenerateTrainJobReq{ JobName: jobName, @@ -1221,6 +1226,9 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) TotalVersionCount: modelarts.TotalVersionCount, DatasetName: datasetNames, } + userCommand, userImageUrl := getUserCommand(engineID, req) + req.UserCommand = userCommand + req.UserImageUrl = userImageUrl //将params转换Parameters.Parameter,出错时返回给前端 var Parameters modelarts.Parameters @@ -1239,6 +1247,30 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") } +func getUserCommand(engineId int, req *modelarts.GenerateTrainJobReq) (string, string) { + userImageUrl := "" + userCommand := "" + if engineId < 0 { + userCommand = "/bin/bash /home/work/run_train.sh 's3://" + req.CodeObsPath + "' 'code/" + req.BootFile + "' '/tmp/log/train.log' --'data_url'='s3://" + req.DataUrl + "' --'train_url'='s3://" + req.TrainUrl + "'" + var versionInfos modelarts.VersionInfo + if err := json.Unmarshal([]byte(setting.EngineVersions), &versionInfos); err != nil { + log.Info("json parse err." + err.Error()) + } else { + for _, engine := range versionInfos.Version { + if engine.ID == engineId { + userImageUrl = engine.Url + break + } + } + } + for _, param := range req.Parameters { + userCommand += " --'" + param.Label + "'='" + param.Value + "'" + } + return userCommand, userImageUrl + } + return userCommand, userImageUrl +} + func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJobForm) { ctx.Data["PageIsTrainJob"] = true var jobID = ctx.Params(":jobid") @@ -1275,7 +1307,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ flavorCode := form.Flavor params := form.Params poolID := form.PoolID - isSaveParam := form.IsSaveParam + //isSaveParam := form.IsSaveParam repo := ctx.Repo.Repository codeLocalPath := setting.JobPath + jobName + modelarts.CodePath codeObsPath := "/" + setting.Bucket + modelarts.JobPath + jobName + modelarts.CodePath + VersionOutputPath + "/" @@ -1395,46 +1427,46 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ }) } - //save param config - if isSaveParam == "on" { - saveparams := append(param, models.Parameter{ - Label: modelarts.TrainUrl, - Value: outputObsPath, - }, models.Parameter{ - Label: modelarts.DataUrl, - Value: dataPath, - }) - if form.ParameterTemplateName == "" { - log.Error("ParameterTemplateName is empty") - versionErrorDataPrepare(ctx, form) - ctx.RenderWithErr("保存作业参数时,作业参数名称不能为空", tplModelArtsTrainJobVersionNew, &form) - return - } - - _, err := modelarts.CreateTrainJobConfig(models.CreateConfigParams{ - ConfigName: form.ParameterTemplateName, - Description: form.PrameterDescription, - DataUrl: dataPath, - AppUrl: codeObsPath, - BootFileUrl: codeObsPath + bootFile, - TrainUrl: outputObsPath, - Flavor: models.Flavor{ - Code: flavorCode, - }, - WorkServerNum: workServerNumber, - EngineID: int64(engineID), - LogUrl: logObsPath, - PoolID: poolID, - Parameter: saveparams, - }) - - if err != nil { - log.Error("Failed to CreateTrainJobConfig: %v", err) - versionErrorDataPrepare(ctx, form) - ctx.RenderWithErr("保存作业参数失败:"+err.Error(), tplModelArtsTrainJobVersionNew, &form) - return - } - } + // //save param config + // if isSaveParam == "on" { + // saveparams := append(param, models.Parameter{ + // Label: modelarts.TrainUrl, + // Value: outputObsPath, + // }, models.Parameter{ + // Label: modelarts.DataUrl, + // Value: dataPath, + // }) + // if form.ParameterTemplateName == "" { + // log.Error("ParameterTemplateName is empty") + // versionErrorDataPrepare(ctx, form) + // ctx.RenderWithErr("保存作业参数时,作业参数名称不能为空", tplModelArtsTrainJobVersionNew, &form) + // return + // } + + // _, err := modelarts.CreateTrainJobConfig(models.CreateConfigParams{ + // ConfigName: form.ParameterTemplateName, + // Description: form.PrameterDescription, + // DataUrl: dataPath, + // AppUrl: codeObsPath, + // BootFileUrl: codeObsPath + bootFile, + // TrainUrl: outputObsPath, + // Flavor: models.Flavor{ + // Code: flavorCode, + // }, + // WorkServerNum: workServerNumber, + // EngineID: int64(engineID), + // LogUrl: logObsPath, + // PoolID: poolID, + // Parameter: saveparams, + // }) + + // if err != nil { + // log.Error("Failed to CreateTrainJobConfig: %v", err) + // versionErrorDataPrepare(ctx, form) + // ctx.RenderWithErr("保存作业参数失败:"+err.Error(), tplModelArtsTrainJobVersionNew, &form) + // return + // } + // } task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, PreVersionName) if err != nil { @@ -1469,6 +1501,9 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ TotalVersionCount: latestTask.TotalVersionCount + 1, DatasetName: datasetNames, } + userCommand, userImageUrl := getUserCommand(engineID, req) + req.UserCommand = userCommand + req.UserImageUrl = userImageUrl err = modelarts.GenerateTrainJobVersion(ctx, req, jobID) if err != nil { @@ -1907,8 +1942,8 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference modelName := form.ModelName modelVersion := form.ModelVersion ckptName := form.CkptName - - ckptUrl := form.TrainUrl + form.CkptName + ckptUrl := "/" + form.TrainUrl + form.CkptName + log.Info("ckpt url:" + ckptUrl) count, err := models.GetCloudbrainInferenceJobCountByUserID(ctx.User.ID) if err != nil { @@ -2075,6 +2110,13 @@ func InferenceJobIndex(ctx *context.Context) { page = 1 } + listType := ctx.Query("listType") + ctx.Data["ListType"] = listType + + if listType == models.AllResource { + listType = "" + } + var jobTypes []string jobTypes = append(jobTypes, string(models.JobTypeInference)) tasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{ @@ -2082,9 +2124,10 @@ func InferenceJobIndex(ctx *context.Context) { Page: page, PageSize: setting.UI.IssuePagingNum, }, - RepoID: repo.ID, - Type: models.TypeCloudBrainTwo, - JobTypes: jobTypes, + RepoID: repo.ID, + ComputeResource: listType, + JobTypes: jobTypes, + Type: models.TypeCloudBrainAll, }) if err != nil { ctx.ServerError("Cloudbrain", err) @@ -2094,7 +2137,9 @@ func InferenceJobIndex(ctx *context.Context) { for i, task := range tasks { tasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) tasks[i].CanModify = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) - tasks[i].ComputeResource = models.NPUResource + if tasks[i].ComputeResource == "" { + tasks[i].ComputeResource = models.NPUResource + } } repoId := ctx.Repo.Repository.ID @@ -2126,6 +2171,8 @@ func InferenceJobNew(ctx *context.Context) { ctx.ServerError("get new inference-job info failed", err) return } + waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "") + ctx.Data["WaitCount"] = waitCount ctx.HTML(200, tplModelArtsInferenceJobNew) } func inferenceJobNewDataPrepare(ctx *context.Context) error { diff --git a/routers/repo/repo.go b/routers/repo/repo.go index c0803ed06..03d2d832a 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -195,8 +195,11 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { } ctx.Data["ContextUser"] = ctxUser if !form.AutoAgree { + ctx.Data["CheckedAutoAgree"] = "" ctx.RenderWithErr(ctx.Tr("repo.template.one_promise"), tplCreate, form) return + } else { + ctx.Data["CheckedAutoAgree"] = "checked" } if ctx.HasError() { ctx.HTML(200, tplCreate) diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 281edd385..d433335f4 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -1105,6 +1105,16 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, repo.CloudBrainTrainJobNew) m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainCreate) }) + m.Group("/inference-job", func() { + m.Group("/:jobid", func() { + m.Get("", reqRepoCloudBrainReader, repo.InferenceCloudBrainJobShow) + m.Get("/result_download", cloudbrain.AdminOrJobCreaterRightForTrain, repo.CloudBrainDownloadInferenceResult) + + m.Get("/downloadall", repo.DownloadInferenceResultFile) + }) + m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, repo.InferenceCloudBrainJobNew) + m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainInferencForm{}), repo.CloudBrainInferenceJobCreate) + }) }, context.RepoRef()) m.Group("/grampus", func() { m.Group("/train-job", func() { @@ -1126,19 +1136,26 @@ func RegisterRoutes(m *macaron.Macaron) { }, context.RepoRef()) m.Group("/modelmanage", func() { m.Post("/create_model", reqRepoModelManageWriter, repo.SaveModel) + m.Post("/create_model_convert", reqRepoModelManageWriter, repo.SaveModelConvert) m.Post("/create_new_model", repo.SaveNewNameModel) m.Delete("/delete_model", repo.DeleteModel) + m.Post("/delete_model_convert/:id", repo.DeleteModelConvert) + m.Post("/convert_stop/:id", repo.StopModelConvert) m.Put("/modify_model", repo.ModifyModelInfo) m.Get("/show_model", reqRepoModelManageReader, repo.ShowModelTemplate) + m.Get("/convert_model", reqRepoModelManageReader, repo.ConvertModelTemplate) m.Get("/show_model_info", repo.ShowModelInfo) + m.Get("/show_model_convert_info", repo.ShowModelConvertInfo) m.Get("/show_model_info_api", repo.ShowSingleModel) m.Get("/show_model_api", repo.ShowModelPageInfo) m.Get("/show_model_child_api", repo.ShowOneVersionOtherModel) m.Get("/query_train_job", reqRepoCloudBrainReader, repo.QueryTrainJobList) + m.Get("/query_train_model", reqRepoCloudBrainReader, repo.QueryTrainModelList) m.Get("/query_train_job_version", reqRepoCloudBrainReader, repo.QueryTrainJobVersionList) m.Get("/query_model_for_predict", reqRepoModelManageReader, repo.QueryModelListForPredict) m.Get("/query_modelfile_for_predict", reqRepoModelManageReader, repo.QueryModelFileForPredict) m.Get("/query_onelevel_modelfile", reqRepoModelManageReader, repo.QueryOneLevelModelFile) + m.Get("/download_model_convert/:id", reqRepoModelManageReader, repo.ModelConvertDownloadModel) m.Group("/:ID", func() { m.Get("", repo.ShowSingleModel) m.Get("/downloadsingle", repo.DownloadSingleModelFile) diff --git a/templates/admin/cloudbrain/list.tmpl b/templates/admin/cloudbrain/list.tmpl index 347b5658d..e66f40e84 100755 --- a/templates/admin/cloudbrain/list.tmpl +++ b/templates/admin/cloudbrain/list.tmpl @@ -204,7 +204,7 @@ {{else}} {{$.i18n.Tr "repo.stop"}} @@ -212,7 +212,7 @@
      • {{$.CsrfTokenHtml}}
        - {{if or (.benchmarkMode) (.newInference)}} + + {{if .benchmarkMode}}{{.i18n.Tr "repo.modelarts.infer_job.select_model"}}{{else}}{{.i18n.Tr "dataset.select_dataset"}}{{end}} {{if .benchmarkMode}} - 说明:先使用数据集功能上传模型,然后从数据集列表选模型。 + 说明:先使用数据集功能上传模型,然后从数据集列表选模型。 {{end}}
        diff --git a/templates/custom/wait_count.tmpl b/templates/custom/wait_count.tmpl new file mode 100644 index 000000000..77c49712d --- /dev/null +++ b/templates/custom/wait_count.tmpl @@ -0,0 +1,28 @@ +
        + {{$queue := ""}} + {{$gpuQueue := 0}} + {{range $k,$v :=.gpu_types}} + {{if eq $k 0}} + {{ $queue := $v.Queue }} + {{ end }} + {{ end }} + + {{ range $k,$v :=.QueuesDetail }} + {{if eq $k $queue}} + {{$gpuQueue :=$v}} + {{ end }} + {{ end }} + + {{.i18n.Tr "repo.wait_count_start"}} + {{if .QueuesDetail}} + {{ $gpuQueue }} + {{else}} + {{.WaitCount}} + {{ end }} + {{.i18n.Tr "repo.wait_count_end"}} +
        diff --git a/templates/custom/wait_count_train.tmpl b/templates/custom/wait_count_train.tmpl new file mode 100644 index 000000000..ef6c4ed61 --- /dev/null +++ b/templates/custom/wait_count_train.tmpl @@ -0,0 +1,28 @@ +
        + {{$queue := ""}} + {{$gpuQueue := 0}} + {{range $k,$v :=.gpu_types}} + {{if eq $k 0}} + {{ $queue := $v.Queue }} + {{ end }} + {{ end }} + + {{ range $k,$v :=.QueuesDetail }} + {{if eq $k $queue}} + {{$gpuQueue :=$v}} + {{ end }} + {{ end }} + + {{.i18n.Tr "repo.wait_count_start"}} + {{if .QueuesDetail}} + {{ $gpuQueue }} + {{else}} + {{.WaitCount}} + {{ end }} + {{.i18n.Tr "repo.wait_count_end"}} +
        diff --git a/templates/repo/cloudbrain/benchmark/index.tmpl b/templates/repo/cloudbrain/benchmark/index.tmpl index 8ded073b0..c6283e2e1 100755 --- a/templates/repo/cloudbrain/benchmark/index.tmpl +++ b/templates/repo/cloudbrain/benchmark/index.tmpl @@ -64,7 +64,7 @@
        -
        +
        {{$.i18n.Tr "repo.cloudbrain_task"}} diff --git a/templates/repo/cloudbrain/benchmark/new.tmpl b/templates/repo/cloudbrain/benchmark/new.tmpl index 76a4e5f0c..0509ce5bc 100755 --- a/templates/repo/cloudbrain/benchmark/new.tmpl +++ b/templates/repo/cloudbrain/benchmark/new.tmpl @@ -10,11 +10,9 @@ padding-left: 3rem !important; } - .min_title { + .min_title{ font-size: 14px !important; - padding-left: 6rem !important; margin-bottom: 2rem !important; - } .width81 { @@ -56,25 +54,26 @@ {{.CsrfTokenHtml}} -
        - +
        -
        - +
        + - {{.i18n.Tr "cloudbrain.job_name_rule"}} + {{.i18n.Tr "cloudbrain.job_name_rule"}}
        -
        -
        -
        - +
        +
        -
        +
        - +   @@ -136,7 +135,8 @@ {{end}}
        -
        +
        + @@ -149,27 +149,28 @@ {{.CsrfTokenHtml}} -
        - +
        + + {{template "custom/wait_count_train" .}}
        -
        - +
        + - {{.i18n.Tr "cloudbrain.job_name_rule"}} + {{.i18n.Tr "cloudbrain.job_name_rule"}}
        -
        - +
        +
        -
        - +
        +
        -
        +
         
        -   + @@ -228,18 +229,16 @@
        -
        - +
        + {{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_train"}}
        -
        - +
        + + @@ -273,7 +273,6 @@ $(document).ready(() => { $('.ui.search.dropdown.job_type').dropdown({ onChange: function (value, text, $selectedItem) { - console.log(value, text) if (value === "BRAINSCORE") { $('#brainscore_child_type').css('display', 'block') $('#benchmark_model_example').attr('href', 'https://git.openi.org.cn/BDIP/similarity2brain_ann') diff --git a/templates/repo/cloudbrain/inference/new.tmpl b/templates/repo/cloudbrain/inference/new.tmpl new file mode 100644 index 000000000..e42c7240a --- /dev/null +++ b/templates/repo/cloudbrain/inference/new.tmpl @@ -0,0 +1,480 @@ +{{template "base/head" .}} + +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        + {{template "repo/header" .}} +
        + {{template "base/alert" .}} + +

        + {{.i18n.Tr "repo.modelarts.train_job.new_infer"}} +

        +
        + + + {{.CsrfTokenHtml}} + + + + {{if $.model_version}} + + {{else}} + + {{end}} + {{if $.label_names}} + + {{else}} + + {{end}} +

        {{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:

        +
        +
        + + + {{.i18n.Tr "cloudbrain.job_name_rule"}} +
        + +
        + + +
        +
        + + +

        {{.i18n.Tr "repo.modelarts.train_job.parameter_setting"}}:

        +
        +
        + + +
        +
        + +
        +
        + + +
        + +
        + +
        + +
        + +
        + + +
        + +
        + + +
        + + {{template "custom/select_dataset_train" .}} + +
        + + {{if .bootFile}} + + {{else}} + + {{end}} + + + + {{.i18n.Tr "cloudbrain.view_sample"}} +
        + + +
        + + {{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}} + +
        + {{if ne 0 (len .params)}} + {{range $k ,$v := .params}} +
        +
        + +
        +
        + +
        + + + + +
        + {{end}} + {{end}} +
        +
        + + + +
        + + +
        + + +
        + + + {{.i18n.Tr "repo.cloudbrain.cancel"}} +
        + + +
        +
        +
        +{{template "base/footer" .}} + + diff --git a/templates/repo/cloudbrain/inference/show.tmpl b/templates/repo/cloudbrain/inference/show.tmpl new file mode 100644 index 000000000..7653376dd --- /dev/null +++ b/templates/repo/cloudbrain/inference/show.tmpl @@ -0,0 +1,605 @@ +{{template "base/head" .}} + +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        + {{template "repo/header" .}} +
        +

        + +

        + {{with .task}} +
        + +
        +
        +
        + + + +
        + {{TimeSinceUnix1 .CreatedUnix}} + + {{$.i18n.Tr "repo.modelarts.status"}}: + {{.Status}} + + {{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}: + {{$.duration}} + + +
        +
        +
        +
        +
        +
        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + {{$.i18n.Tr "repo.cloudbrain_task"}} + +
        + {{.DisplayJobName}} +
        +
        + {{$.i18n.Tr "repo.modelarts.status"}} + +
        + {{.Status}} +
        +
        + {{$.i18n.Tr "repo.modelarts.train_job.start_time"}} + +
        + + {{if not (eq .StartTime 0)}} + {{TimeSinceUnix1 .StartTime}} + {{else}} + {{TimeSinceUnix1 .CreatedUnix}} + {{end}} + +
        +
        + {{$.i18n.Tr "repo.modelarts.train_job.dura_time"}} + +
        + {{.TrainJobDuration}} +
        +
        + {{$.i18n.Tr "repo.modelarts.train_job.resource_type"}} + +
        + {{$.resource_type}} +
        +
        + {{$.i18n.Tr "repo.model.manage.description"}} + +
        + {{if .Description}} + {{.Description}} + {{else}} + -- + {{end}} +
        +
        + 创建人 + +
        + {{.User.Name}} +
        +
        + {{$.i18n.Tr "cloudbrain.mirror"}} + +
        + {{.Image}} +
        +
        + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + {{$.i18n.Tr "repo.modelarts.infer_job_model"}} + +
        + {{.ModelName}}   + {{$.i18n.Tr "repo.modelarts.version"}}:{{.ModelVersion}}   + +
        +
        + {{$.i18n.Tr "repo.modelarts.infer_job_model_file"}} + +
        + {{.CkptName}} +
        +
        + {{$.i18n.Tr "repo.modelarts.model_label"}} + +
        + + {{if .LabelName}} + {{range $.labelName}} + {{.}} + {{end}} + {{else}} + -- + {{end}} +
        +
        + {{$.i18n.Tr "repo.modelarts.code_version"}} + +
        + {{.BranchName}} +
        +
        + {{$.i18n.Tr "repo.modelarts.train_job.start_file"}} + +
        + {{.BootFile}} +
        +
        + {{$.i18n.Tr "repo.modelarts.infer_dataset"}} + +
        + {{.DatasetName}} +
        +
        + {{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}} + +
        + {{if .Parameters}} + {{.Parameters}} + {{else}} + -- + {{end}} +
        +
        + {{$.i18n.Tr "repo.modelarts.train_job.standard"}} + +
        + {{$.i18n.Tr "cloudbrain.gpu_num"}}:{{$.GpuNum}},{{$.i18n.Tr "cloudbrain.cpu_num"}}:{{$.CpuNum}},{{$.i18n.Tr "cloudbrain.memory"}}(MB):{{$.MemMiB}},{{$.i18n.Tr "cloudbrain.shared_memory"}}(MB):{{$.ShareMemMiB}} +
        +
        +
        + + + + + + +
        +
        + +
        + + + + + +
        + +
        + +
        + + + +
        + + + +
        + +
        +
        + + + + + + {{end}} + + + +{{template "base/footer" .}} + + \ No newline at end of file diff --git a/templates/repo/cloudbrain/new.tmpl b/templates/repo/cloudbrain/new.tmpl index 295fe0435..f0538261d 100755 --- a/templates/repo/cloudbrain/new.tmpl +++ b/templates/repo/cloudbrain/new.tmpl @@ -121,7 +121,7 @@ {{template "repo/header" .}}
        - + {{template "base/alert" .}}

        @@ -154,6 +154,7 @@ Ascend NPU
        + {{template "custom/wait_count" .}}
        @@ -208,7 +209,7 @@
        - {{end}}

        {{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:

        -
        - +
        + + + {{template "custom/wait_count_train" .}} +
        +
        + - {{.i18n.Tr "cloudbrain.job_name_rule"}} + {{.i18n.Tr "cloudbrain.job_name_rule"}}
        -
        -    +
        +   

        {{.i18n.Tr "repo.modelarts.train_job.parameter_setting"}}:

        -
        +
        -    + -
        -
        -       - {{range .engines}} - - {{end}} - -
        -
        - -
        +
        + +
        + + +
        +
        -
        -   +
        + {{else}} @@ -187,14 +215,14 @@
        -
        -    - {{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}} +
        + + {{.i18n.Tr "repo.modelarts.train_job.add_run_parameter"}}
        {{if ne 0 (len .params)}} {{range $k ,$v := .params}} -
        +
        @@ -220,8 +248,8 @@
        -
        -         +
        +
        -
        - +
        +
        - {{.i18n.Tr "cloudbrain.inference_output_path_rule"}} + {{.i18n.Tr "cloudbrain.inference_output_path_rule"}}
        -
        +
        + @@ -252,13 +281,14 @@ {{template "base/footer" .}} diff --git a/templates/repo/modelarts/notebook/new.tmpl b/templates/repo/modelarts/notebook/new.tmpl index 4e2b3951d..6ab16f941 100755 --- a/templates/repo/modelarts/notebook/new.tmpl +++ b/templates/repo/modelarts/notebook/new.tmpl @@ -46,6 +46,7 @@ Ascend NPU
        + {{template "custom/wait_count" .}}
        diff --git a/templates/repo/modelarts/trainjob/new.tmpl b/templates/repo/modelarts/trainjob/new.tmpl index 5022bd41b..39f9f30f5 100755 --- a/templates/repo/modelarts/trainjob/new.tmpl +++ b/templates/repo/modelarts/trainjob/new.tmpl @@ -96,6 +96,7 @@
        +
        + {{template "custom/wait_count_train" .}}
        diff --git a/templates/repo/modelarts/trainjob/show.tmpl b/templates/repo/modelarts/trainjob/show.tmpl index d5cd69ac4..aa0ab6836 100755 --- a/templates/repo/modelarts/trainjob/show.tmpl +++ b/templates/repo/modelarts/trainjob/show.tmpl @@ -1,4 +1,5 @@ {{template "base/head" .}} +
        @@ -509,7 +522,7 @@ -
        @@ -566,6 +579,10 @@
        +
        +
        +
        + +
        +
        + + +
        +
        {{template "base/footer" .}} + + + \ No newline at end of file diff --git a/templates/repo/modelmanage/convertIndex.tmpl b/templates/repo/modelmanage/convertIndex.tmpl new file mode 100644 index 000000000..3dc3652c5 --- /dev/null +++ b/templates/repo/modelmanage/convertIndex.tmpl @@ -0,0 +1,586 @@ + +{{template "base/head" .}} + + +
        +
        +
        +
        +
        +
        +
        +
        +
        +{{$repository := .Repository.ID}} + +
        + +
        + {{template "repo/header" .}} + +
        + {{template "base/alert" .}} + + {{if eq .MODEL_CONVERT_COUNT 0}} +
        +
        +
        未创建过模型转换任务
        +
        + {{if eq .MODEL_COUNT 0}} +
        请您先导入模型,然后再对其进行转换。
        + {{end}} +
        使用说明:可以参考启智AI协作平台小白训练营课程。
        + +
        +
        + {{else}} + +
        +
        +
        + +
        + +
        +
        +
        + 任务名称 +
        +
        + 状态 +
        +
        + 原模型框架 +
        +
        + 转换后格式 +
        +
        + 创建时间 +
        +
        + {{$.i18n.Tr "repo.cloudbrain_creator"}} +
        +
        + {{$.i18n.Tr "repo.cloudbrain_operate"}} +
        +
        +
        + {{range .Tasks}} +
        +
        + +
        + + {{.Status}} + +
        +
        + {{if eq .SrcEngine 0}}PyTorch {{else if eq .SrcEngine 1}}TensorFlow{{else if eq .SrcEngine 2}}MindSpore {{end}} +
        +
        + {{if eq .DestFormat 0}}ONNX {{else if eq .DestFormat 1}}TensorRT {{end}} +
        +
        + {{TimeSinceUnix .CreatedUnix $.Lang}} +
        +
        + +
        +
        +
        + +
        + {{$.CsrfTokenHtml}} + {{if .IsCanDelete}} + + {{$.i18n.Tr "repo.stop"}} + + {{else}} + {{$.i18n.Tr "repo.stop"}} + {{end}} +
        + + +
        + {{$.CsrfTokenHtml}} + {{if .IsCanDelete}} + + {{$.i18n.Tr "repo.delete"}} + + {{else}} + {{$.i18n.Tr "repo.delete"}} + {{end}} +
        + + {{if .IsCanOper}} + + 下载 + + {{else}} + 下载 + {{end}} +
        +
        +
        +
        + {{end}} +
        +
        + + +
        +
        +
        +
        +
        +
        + {{end}} +
        + +
        + +
        + + +
        + +
        +
        + + +
        + + +{{template "base/footer" .}} + + + diff --git a/templates/repo/modelmanage/convertshowinfo.tmpl b/templates/repo/modelmanage/convertshowinfo.tmpl new file mode 100644 index 000000000..984b5944f --- /dev/null +++ b/templates/repo/modelmanage/convertshowinfo.tmpl @@ -0,0 +1,854 @@ +{{template "base/head" .}} + +
        +
        +
        +
        +
        +
        +
        +
        +
        +
        +{{template "repo/header" .}} +
        +

        + +

        + {{with .task}} +
        + +
        +
        +
        + + + +
        + {{TimeSinceUnix1 .CreatedUnix}} + + {{$.i18n.Tr "repo.modelarts.status"}}: + {{.Status}} + + {{$.i18n.Tr "repo.modelarts.train_job.dura_time"}}: + {{.TrainJobDuration}} + +
        +
        +
        +
        +
        +
        +
        +
        + +
        +
        +
        +
        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + {{$.i18n.Tr "repo.cloudbrain_task"}} + +
        + {{.Name}} +
        +
        + {{$.i18n.Tr "repo.modelarts.status"}} + +
        + {{.Status}} +
        +
        + 输入张量形状 + +
        + {{.InputShape}} +
        +
        + 输入数据格式 + +
        + {{.InputDataFormat}} +
        +
        + {{$.i18n.Tr "repo.modelarts.train_job.start_time"}} + +
        + {{TimeSinceUnix1 .CreatedUnix}} +
        +
        + {{$.i18n.Tr "repo.modelarts.train_job.dura_time"}} + +
        + {{.TrainJobDuration}} +
        +
        + 网络输出数据类型 + +
        + {{if eq .NetOutputFormat 0}}FP32 {{else if eq .NetOutputFormat 1}}FP16 {{end}} +
        +
        +
        +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + 模型名称 + +
        + {{.ModelName}} +
        +
        + 模型版本 + +
        + {{.ModelVersion}} +
        +
        + 模型文件 + +
        + {{.ModelPath}} +
        +
        + 原模型框架 + +
        + {{if eq .SrcEngine 0}}PyTorch {{else if eq .SrcEngine 1}}Tensorflow{{else if eq .SrcEngine 2}}MindSpore {{end}} +
        +
        + 转换后格式 + +
        + {{if eq .DestFormat 0}}ONNX {{else if eq .DestFormat 1}}TensorRT {{end}} +
        +
        + {{$.i18n.Tr "repo.modelarts.train_job.description"}} + +
        + {{.Description}} +
        +
        + {{$.i18n.Tr "repo.cloudbrain_creator"}} + +
        + {{.UserName}} +
        +
        +
        +
        +
        + +
        +
        + +
        +
        + +
        + + + + + +
        + +
        + +
        + +
        +
        + +
        + + +
        
        +                            
        + +
        + +
        + +
        +
        + + + + + + + +
        + + +
        
        +                            
        +
        +
        + +
        + + + +
        + +
        +
        + + + +
        +
        +
        + {{end}} {{template "base/paginate" .}} +
        + + + + +
        +{{template "base/footer" .}} + + \ No newline at end of file diff --git a/templates/repo/modelmanage/index.tmpl b/templates/repo/modelmanage/index.tmpl index d42cf1c86..b54fa5cfa 100644 --- a/templates/repo/modelmanage/index.tmpl +++ b/templates/repo/modelmanage/index.tmpl @@ -1,10 +1,33 @@ {{template "base/head" .}} + + +
        @@ -25,7 +48,12 @@
        {{template "base/alert" .}} +