diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/CdMajorController.cs b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/CdMajorController.cs index caea2b776..a02d01306 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/CdMajorController.cs +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/CdMajorController.cs @@ -200,16 +200,16 @@ namespace Learun.Application.Web.Areas.EducationalAdministration.Controllers return Fail("不能修改关联学科"); } cdMajorIBLL.SaveEntity(keyValue, entity); - #region 给关联表添加科目 - MajorAndSubjectEntity majorAndSubjectEntity = new MajorAndSubjectEntity(); - string[] SubNo = entity.SubjectNo.Split(','); - for (int i = 0; i < SubNo.Length; i++) - { - majorAndSubjectEntity.MajorId = entity.ID;//关联专业主键 - majorAndSubjectEntity.SubId = SubNo[i];//考试科目的主键 - majorAndSubjectIBLL.SaveEntity("", majorAndSubjectEntity); - } - #endregion + //#region 给关联表添加科目 + //MajorAndSubjectEntity majorAndSubjectEntity = new MajorAndSubjectEntity(); + //string[] SubNo = entity.SubjectNo.Split(','); + //for (int i = 0; i < SubNo.Length; i++) + //{ + // majorAndSubjectEntity.MajorId = entity.ID;//关联专业主键 + // majorAndSubjectEntity.SubId = SubNo[i];//考试科目的主键 + // majorAndSubjectIBLL.SaveEntity("", majorAndSubjectEntity); + //} + //#endregion return Success("保存成功!"); } diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/StuEnrollController.cs b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/StuEnrollController.cs index 89e5b88b9..cc9770279 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/StuEnrollController.cs +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/StuEnrollController.cs @@ -385,10 +385,10 @@ namespace Learun.Application.Web.Areas.EducationalAdministration.Controllers var StuEnrollData = stuEnrollIBLL.GetStuEnrollEntity(keyValue); //获取中考成绩 var MidExamScoreData = stuEnrollIBLL.GetMidExamScoreData(keyValue).OrderBy(x => x.sort); + if (string.IsNullOrEmpty(StuEnrollData.CheckInUrl)) { StuEnrollData.CheckInUrl = Guid.NewGuid().ToString(); - } if (string.IsNullOrEmpty(StuEnrollData.SubsidizeUrl)) { @@ -948,6 +948,12 @@ namespace Learun.Application.Web.Areas.EducationalAdministration.Controllers /// public ActionResult UpdateEnrollStatus(string keyValue, string strEntity) { + var StuEnrollData = stuEnrollIBLL.GetStuEnrollEntity(keyValue); + if (string.IsNullOrEmpty(StuEnrollData.SubjectNo) ) + { + return Fail("考试科目不能为空!"); + } + stuEnrollIBLL.UpdateEnrollStatus(keyValue, 2); return Success("保存成功"); } diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/StuEnrollPhoneController.cs b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/StuEnrollPhoneController.cs index fe1805a70..78b3935d2 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/StuEnrollPhoneController.cs +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/StuEnrollPhoneController.cs @@ -15,14 +15,17 @@ namespace Learun.Application.Web.Areas.EducationalAdministration.Controllers { private StuEnrollIBLL stuEnrollIBLL = new StuEnrollBLL(); + #region 视图 public ActionResult Link() { return View(); } + public ActionResult Form() { return View(); } + public ActionResult Search(int type) { if (type == 1) @@ -37,11 +40,24 @@ namespace Learun.Application.Web.Areas.EducationalAdministration.Controllers } return View(); } + public ActionResult SearchResult() { return View(); } + /// + /// 招生简章 + /// + /// + public ActionResult StuRecruitmentBrochure() + { + return View(); + } + + #endregion + + /// /// 报名 /// @@ -57,7 +73,7 @@ namespace Learun.Application.Web.Areas.EducationalAdministration.Controllers List scoreData = scoreList.ToObject>(); if (string.IsNullOrEmpty(keyValue)) { - var model = stuEnrollIBLL.GetEntityByPersonalData(entity.IDCard, entity.StuMobile); + var model = stuEnrollIBLL.GetEntityByPersonalData(entity.IDCard, entity.StuName); if (model != null) { return Fail("您已报名,请耐心等待结果!"); @@ -99,20 +115,20 @@ namespace Learun.Application.Web.Areas.EducationalAdministration.Controllers return Success(jsonData); } /// - /// 下载入学须知 + /// 下载 /// + /// 文件名称 + /// 原文件名称 /// - [HttpPost] - [AjaxOnly] - public ActionResult FileDownLoad() + public ActionResult FileDownLoad(string name, string pathName) { FileStreamResult result = null; try { var path = Server.MapPath("~/Content/otherFile/"); - var pathoffull = path + "入学须知.pdf"; - FileStream fsread = fsread = new FileStream(pathoffull, FileMode.OpenOrCreate, FileAccess.ReadWrite); - result = File(fsread, "application/pdf", "入学须知.pdf"); + var pathoffull = path + pathName; + FileStream fsread = new FileStream(pathoffull, FileMode.OpenOrCreate, FileAccess.ReadWrite); + result = File(fsread, "application/pdf", name + ".pdf"); return result; } diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/StuLeaveManagementController.cs b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/StuLeaveManagementController.cs index 8ddafdca0..97b9b5d0e 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/StuLeaveManagementController.cs +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/StuLeaveManagementController.cs @@ -119,6 +119,7 @@ namespace Learun.Application.Web.Areas.EducationalAdministration.Controllers public ActionResult GetFormData(string keyValue) { var StuLeaveManagementData = stuLeaveManagementIBLL.GetStuLeaveManagementEntity(keyValue); + StuLeaveManagementData.num = stuLeaveManagementIBLL.Num(StuLeaveManagementData.CreateUserNo); var jsonData = new { StuLeaveManagement = StuLeaveManagementData, @@ -136,6 +137,7 @@ namespace Learun.Application.Web.Areas.EducationalAdministration.Controllers public ActionResult GetFormDataByProcessId(string processId) { var StuLeaveManagementData = stuLeaveManagementIBLL.GetEntityByProcessId(processId); + StuLeaveManagementData.num = stuLeaveManagementIBLL.Num(StuLeaveManagementData.CreateUserNo); var jsonData = new { StuLeaveManagement = StuLeaveManagementData, diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/VaccinationInfoController.cs b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/VaccinationInfoController.cs new file mode 100644 index 000000000..9170e59cf --- /dev/null +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Controllers/VaccinationInfoController.cs @@ -0,0 +1,142 @@ +using Learun.Util; +using System.Data; +using Learun.Application.TwoDevelopment.EducationalAdministration; +using System.Web.Mvc; +using System.Collections.Generic; + +namespace Learun.Application.Web.Areas.EducationalAdministration.Controllers +{ + /// + /// 版 本 Learun-ADMS V7.0.6 力软敏捷开发框架 + /// Copyright (c) 2013-2020 力软信息技术(苏州)有限公司 + /// 创 建:超级管理员 + /// 日 期:2022-07-18 17:52 + /// 描 述:疫情 + /// + public class VaccinationInfoController : MvcControllerBase + { + private VaccinationInfoIBLL vaccinationInfoIBLL = new VaccinationInfoBLL(); + + #region 视图功能 + + /// + /// 主页面 + /// + /// + [HttpGet] + public ActionResult Index() + { + return View(); + } + /// + /// 表单页 + /// + /// + [HttpGet] + public ActionResult Form() + { + return View(); + } + /// + /// 主页面 + /// + /// + [HttpGet] + public ActionResult TeachIndex() + { + return View(); + } + /// + /// 表单页 + /// + /// + [HttpGet] + public ActionResult TeachForm() + { + return View(); + } + #endregion + + #region 获取数据 + + /// + /// 获取页面显示列表数据 + /// + /// 分页参数 + /// 查询参数 + /// + [HttpGet] + [AjaxOnly] + public ActionResult GetPageList(string pagination, string queryJson) + { + Pagination paginationobj = pagination.ToObject(); + var data = vaccinationInfoIBLL.GetPageList(paginationobj, queryJson); + var jsonData = new + { + rows = data, + total = paginationobj.total, + page = paginationobj.page, + records = paginationobj.records + }; + return Success(jsonData); + } + /// + /// 获取表单数据 + /// + /// 主键 + /// + [HttpGet] + [AjaxOnly] + public ActionResult GetFormData(string keyValue) + { + var VaccinationInfoData = vaccinationInfoIBLL.GetVaccinationInfoEntity(keyValue); + var jsonData = new + { + VaccinationInfo = VaccinationInfoData, + }; + return Success(jsonData); + } + #endregion + + #region 提交数据 + + /// + /// 删除实体数据 + /// + /// 主键 + /// + [HttpPost] + [AjaxOnly] + public ActionResult DeleteForm(string keyValue) + { + vaccinationInfoIBLL.DeleteEntity(keyValue); + return Success("删除成功!"); + } + /// + /// 保存实体数据(新增、修改) + /// + /// 主键 + /// 实体 + /// + [HttpPost] + [ValidateAntiForgeryToken] + [AjaxOnly] + public ActionResult SaveForm(string keyValue, string strEntity) + { + VaccinationInfoEntity entity = strEntity.ToObject(); + vaccinationInfoIBLL.SaveEntity(keyValue, entity); + return Success("保存成功!"); + } + #endregion + + #region 扩展代码 + [HttpPost] + [AjaxOnly] + public ActionResult CreateFrom(string userId,string Description) + { + vaccinationInfoIBLL.CreateEntity(userId, Description); + return Success("生成成功!"); + } + #endregion + } +} diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/CdMajor/Form.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/CdMajor/Form.cshtml index c35a6aa7d..4c54dde0e 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/CdMajor/Form.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/CdMajor/Form.cshtml @@ -23,11 +23,12 @@
校区*
-
-
考试科目*
-
- -
+ @*考试科目在报名管理下维护 +
+
考试科目*
+
+ +
*@
年度*
@@ -45,13 +46,13 @@
@*
-
名称缩写
- -
-
-
英文名称
- -
*@ +
名称缩写
+ + +
+
英文名称
+ +
*@
教委专业代码
diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollForm.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollForm.cshtml index 647322a22..a82eba669 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollForm.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollForm.cshtml @@ -47,22 +47,25 @@
县区*
- @* *@
-
+
专业*
+
+
考试科目*
+
+
-
身份证正面照片*
+
身份证正面照*
-
身份证反面照片*
+
身份证反面照*
-
初中毕业证照片*
+
初中毕业证照*
diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollForm.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollForm.js index 01787dfaf..a68f072fd 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollForm.js +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollForm.js @@ -23,7 +23,13 @@ var bootstrap = function ($, learun) { $('#MidAchievementPto').lrUploader(); $('#Gender').lrDataItemSelect({ code: 'usersexbit' }); $('#Nationals').lrDataItemSelect({ code: 'National' }); - + $('#SubjectNo').lrselect({ + type: 'multiple', + url: top.$.rootUrl + '/LR_SystemModule/DataSource/GetDataTable?code=' + 'ExamSubject', + value: 'subjectno', + text: 'subjectname', + maxHeight: 200 + }); //地市 $('#City').lrselect({ allowSearch: true, @@ -58,42 +64,33 @@ var bootstrap = function ($, learun) { value: "acode", text: "aname", maxHeight: 200, - select: function (item) { - if (item) { - var countyCode = $("#County").lrselectGet(); + //select: function (item) { + // if (item) { + // var countyCode = $("#County").lrselectGet(); - //专业 - $('#MajorNo').lrselectRefresh({ - url: top.$.rootUrl + - '/LR_SystemModule/DataSource/GetDataTable?code=CdMajorInfo', - param: { - //strWhere: "1=1 and Area='" + countyCode + "'" - strWhere: "1=1" - }, - value: "id", - text: "majorname", - maxHeight: 200, - }); - if (MajorNo) { - $('#MajorNo').lrselectSet(MajorNo); - MajorNo = ''; - } - } + // //专业 + // $('#MajorNo').lrselectRefresh({ + // url: top.$.rootUrl + + // '/LR_SystemModule/DataSource/GetDataTable?code=CdMajorInfo', + // param: { + // //strWhere: "1=1 and Area='" + countyCode + "'" + // strWhere: "1=1" + // }, + // value: "id", + // text: "majorname", + // maxHeight: 200, + // }); + // if (MajorNo) { + // $('#MajorNo').lrselectSet(MajorNo); + // MajorNo = ''; + // } + // } - } + //} }); //专业 $('#MajorNo').lrDataSourceSelect({ code: 'CdMajorInfo', value: 'id', text: 'majorname' }); - //$('#MajorNo').lrselectRefresh({ - // url: top.$.rootUrl + - // '/LR_SystemModule/DataSource/GetDataTable?code=CdMajorInfo', - // param: { - // strWhere: "1=1" - // }, - // value: "id", - // text: "majorname", - // maxHeight: 200, - //}); + $('#EmpNo').lrDataSourceSelect({ code: 'EmpInfo', value: 'empno', text: 'empname' }); @@ -131,9 +128,10 @@ var bootstrap = function ($, learun) { if (!!data.StuEnrollMidExamScore) { $.each(data.StuEnrollMidExamScore, function (i, item) { + var score = item.score > 0 ? item.score : ''; str += '
'; str += '
' + item.subjectName + '
'; - str += ''; + str += ''; str += '
'; }); $('#scoreDiv').html(str); @@ -146,7 +144,8 @@ var bootstrap = function ($, learun) { acceptClick = function (callBack) { if (!$('body').lrValidform()) { return false; - } var scoreList = []; + } + var scoreList = []; $.each($("#scoreDiv .SEMidExamScore"), function (i, item) { @@ -156,8 +155,10 @@ var bootstrap = function ($, learun) { }; scoreList.push(entity); }); + var entity = $('body').lrGetFormData(); + entity.MajorName = $('#MajorNo').lrselectGetText(); var postData = { - strEntity: JSON.stringify($('body').lrGetFormData()), + strEntity: JSON.stringify(entity), scoreList: JSON.stringify(scoreList) }; $.lrSaveForm(top.$.rootUrl + '/EducationalAdministration/StuEnrollPhone/SaveForm?keyValue=' + keyValue, postData, function (res) { diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollFormView.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollFormView.cshtml index 1240a8a86..f05b81ebe 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollFormView.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollFormView.cshtml @@ -57,20 +57,24 @@
县区*
-
+
专业*
-
+
+
+
+
考试科目*
+
-
身份证正面照片*
+
身份证正面照*
-
身份证反面照片*
+
身份证反面照*
-
初中毕业证照片*
+
初中毕业证照*
diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollFormView.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollFormView.js index 6d2fe7bb1..70d989ab8 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollFormView.js +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollFormView.js @@ -32,6 +32,13 @@ var bootstrap = function ($, learun) { $('#Nationals').lrDataItemSelect({ code: 'National' }); $('#MajorNo').lrDataSourceSelect({ code: 'CdMajorInfo', value: 'id', text: 'majorname' }); $('#EmpNo').lrDataSourceSelect({ code: 'EmpInfo', value: 'empno', text: 'empname' }); + $('#SubjectNo').lrselect({ + type: 'multiple', + url: top.$.rootUrl + '/LR_SystemModule/DataSource/GetDataTable?code=' + 'ExamSubject', + value: 'subjectno', + text: 'subjectname', + maxHeight: 200 + }); //地市 $('#City').lrselect({ allowSearch: true, @@ -102,9 +109,10 @@ var bootstrap = function ($, learun) { if (data.StuEnrollMidExamScore) { $.each(data.StuEnrollMidExamScore, function (i, item) { + var score = item.score > 0 ? item.score : ''; str += '
'; str += '
' + item.subjectName + '
'; - str += ''; + str += ''; str += '
'; }); $('#scoreDiv').html(str); diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollIndex.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollIndex.js index 2f3967c22..b120e0f3f 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollIndex.js +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollIndex.js @@ -89,7 +89,7 @@ var bootstrap = function ($, learun) { id: 'form', title: '查看', url: top.$.rootUrl + '/EducationalAdministration/StuEnroll/EnrollFormView?keyValue=' + keyValue, - width: 800, + width: 900, height: 700, btn: null }); @@ -108,7 +108,7 @@ var bootstrap = function ($, learun) { id: 'form', title: '审核', url: top.$.rootUrl + '/EducationalAdministration/StuEnroll/EnrollSH?keyValue=' + keyValue, - width: 700, + width: 900, height: 700, btn: ['确认审核', '取消'], callBack: function (id) { @@ -263,8 +263,10 @@ var bootstrap = function ($, learun) { formatter: function (value) { if (value == 1) { return ""; - } else { + } else if (value == 0) { return ""; + } else { + return ""; } } }, diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollSH.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollSH.cshtml index c7ad0787d..431dd281c 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollSH.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollSH.cshtml @@ -40,6 +40,7 @@
中考总分*
+
毕业学校*
@@ -56,9 +57,13 @@
县区*
-
+
专业*
-
+
+
+
+
考试科目*
+
身份证正面照片*
diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollSH.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollSH.js index f2bde2911..ccf81131f 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollSH.js +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnroll/EnrollSH.js @@ -22,6 +22,13 @@ var bootstrap = function ($, learun) { type: 'radio', code: 'YesOrNoBit', }); + $('#SubjectNo').lrselect({ + type: 'multiple', + url: top.$.rootUrl + '/LR_SystemModule/DataSource/GetDataTable?code=' + 'ExamSubject', + value: 'subjectno', + text: 'subjectname', + maxHeight: 200 + }); $('#IdCardPto1').lrUploader(); $('#IdCardPto2').lrUploader(); $('#MidDiplomaPto').lrUploader(); @@ -96,6 +103,17 @@ var bootstrap = function ($, learun) { } } MajorNo = data.StuEnroll.MajorNo; + var str = ''; + if (!!data.StuEnrollMidExamScore) { + $.each(data.StuEnrollMidExamScore, + function (i, item) { + str += '
'; + str += '
' + item.subjectName + '
'; + str += ''; + str += '
'; + }); + $('#scoreDiv').html(str); + } }); learun.httpAsyncGet(top.$.rootUrl + '/EducationalAdministration/StuEnroll/GetExamDataByStuId?keyValue=' + keyValue, function (res) { var html = ''; diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/Form.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/Form.cshtml index 7ac492bd5..f5b37ebe7 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/Form.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/Form.cshtml @@ -522,21 +522,21 @@ $("#MajorNo").html(str); }, }); - //民族 $.ajax({ - url: "/EducationalAdministration/EmpInfoEnternal/GetMap?code=" + "BCdNationality", + url: "/EducationalAdministration/EmpInfoEnternal/GetDataItemMap?code=" + "National", async: false, success: function (msg) { - var companys = $.parseJSON(msg).data.data; + var companys = $.parseJSON(msg).data; var str = ''; $.each(companys, function (i, item) { - str += '' + str += '' }) $("#Nationals").html(str); }, }); + //地市 $.ajax({ url: "/EducationalAdministration/EmpInfoEnternal/GetMap?code=" + "DIC_CITY" + "&where=" + "cparent='650000'", diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/Link.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/Link.cshtml index fdbdd8740..1a412c3f3 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/Link.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/Link.cshtml @@ -32,6 +32,8 @@
+ +
@@ -45,7 +47,14 @@ $('#loc').attr('href', '/EducationalAdministration/StuEnrollPhone/Search?type=1'); //查询录取结果 $('#res').attr('href', '/EducationalAdministration/StuEnrollPhone/Search?type=2'); - }) + //招生简章 + $('#stuRecruitmentBrochure').attr('href', '/EducationalAdministration/StuEnrollPhone/StuRecruitmentBrochure'); + + $('.major').find('a').on('click', + function () { + location.href = "/EducationalAdministration/StuEnrollPhone/FileDownLoad?name=" + '2022年各专业介绍'+'&pathName='+'各专业介绍.pdf'; + }); + }); diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/Search.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/Search.cshtml index 68a3ad432..7ea8a53f9 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/Search.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/Search.cshtml @@ -61,42 +61,9 @@ var form = layui.form; //按钮点击 form.on('submit(*)', function (data) { - //var strEntity = JSON.stringify(data.field); - location.href = '/EducationalAdministration/StuEnrollPhone/SearchResult?type=' + type + '&StuName=' + encodeURI(encodeURI($('#StuName').val())) + '&IDCard=' + $('#IDCard').val(); - //$.ajax({ - // url: '/EducationalAdministration/StuEnrollPhone/SearchForm?type=' + type, - // data: { strEntity: strEntity }, - // type: "GET", - // dataType: "json", - // async: true, - // cache: false, - // success: function (data) { - // if (data.code == 200) { - // alert("报名成功,请等待考试通知!"); - // } else { - // alert(data.info); - // } - // }, - // error: function (XMLHttpRequest, textStatus, errorThrown) { - // }, - // beforeSend: function () { - // }, - // complete: function () { - // } - //}); - //return false; //阻止表单跳转。如果需要表单跳转,去掉这段即可。 - + }); - - //var laydate = layui.laydate; - - //时间选择 - //laydate.render({ - // elem: '#Birthday', - // min: today.y + '-' + today.m + '-' + today.d - //}); - }); $(window).load(function () { diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/SearchResult.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/SearchResult.cshtml index 5283b9fe5..2eeb225b2 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/SearchResult.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/SearchResult.cshtml @@ -17,7 +17,22 @@ +
@@ -37,9 +52,9 @@
@*
- * 手机号 - -
*@ + * 手机号 + +
*@
* 考试信息
@@ -47,15 +62,16 @@
- * 是否录取 + * 录取结果信息
- 录取成功,请手机截屏,保存结果图片,报名时出示此图片! - +     备注:请手机截屏此录取界面,保存图片。报名时出示此图片换取录取通知书! +
+
- +
@@ -76,8 +92,6 @@ //var StuMobile = request('StuMobile'); layui.use(['form', 'laydate', 'upload'], function () { var form = layui.form; - - }); $(window).load(function () { $('#admmsg').hide(); @@ -103,23 +117,37 @@ if (data.StuEnroll) { $('#StuName').val(decodeURI(StuName)); $('#IDCard').val(IDCard); - // $('#StuMobile').val(StuMobile); - //$('#ExamLocation').val(data.StuEnroll.ExamLocation); - //if (data.StuEnroll.ExamStartTime) { - // $('#ExamStartTime').val(data.StuEnroll.ExamStartTime + '~' + data.StuEnroll.ExamEndTime); - //} - if (data.StuEnroll.IsAdmission && data.StuEnroll.IsAdmission == 1) { - $('#IsAdmission').val('是'); - if (type == '2') { - //查询录取结果 - $('#admmsg').show(); - } - } else { - $('#IsAdmission').val('否'); + // $('#StuMobile').val(StuMobile); + var IsAdmission = data.StuEnroll.IsAdmission; + + var majorName = ''; + //专业 + $.ajax({ + url: "/EducationalAdministration/EmpInfoEnternal/GetMap?code=" + "CdMajorInfo" + '&where=' + "id='" + data.StuEnroll.MajorNo + "'", + async: false, + success: function (msg) { + var majorData = $.parseJSON(msg).data.data; + majorName = majorData[0].MajorName; + }, + }); + if (!majorName) { + majorName = data.StuEnroll.MajorName; + } + if (IsAdmission == 1 || IsAdmission == true) { + var major = data.StuEnroll.MajorName; + $('#IsAdmission').val('恭喜您,已被我校录取' + majorName + '专业'); + //查询录取结果 + $('#admmsg').show(); + } else if (IsAdmission === false) { + $('#IsAdmission').val('很抱歉,您未被录取'); + } + else { + $('#IsAdmission').val('很抱歉,请您等待录取结果'); } } else { - $('#app').html(''); + $('#app').html( + ''); } if (data.examData) { var examData = data.examData; @@ -129,11 +157,15 @@ var etime = examData[i].BeginTime + '~' + examData[i].EndTime; html += '
'; html += ' 科目'; - html += ''; + html += ''; html += '
'; html += '
'; html += ' 时间'; - html += ''; + html += ''; html += '
'; html += '
'; @@ -155,42 +187,12 @@ }); $('#fileDownLoad').find('a').on('click', - function() { + function () { //下载入学须知 - //var url = ""; - //var a = document.createElement('a'); - //a.download = 'text.zip'; - //a.href = url; - //a.target = '_bank'; - //document.appendChild(a); - //a.click(); - //document.removeChild(); - $.ajax({ - url: '/EducationalAdministration/StuEnrollPhone/FileDownLoad', - type: "Post", - dataType: "json", - async: true, - cache: false, - success: function (data) { - if (data.code == 200) { - - - } else { - alert(data.info); - } - }, - error: function (XMLHttpRequest, textStatus, errorThrown) { - }, - beforeSend: function () { - }, - complete: function () { - } - }); + location.href = "/EducationalAdministration/StuEnrollPhone/FileDownLoad?name=" + '2022年新生入学须知' + '&pathName=' + '新生入学须知.pdf';; }); - renderForm(); - - }) + }); //重新渲染表单 diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/StuRecruitmentBrochure.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/StuRecruitmentBrochure.cshtml new file mode 100644 index 000000000..d4f548940 --- /dev/null +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollPhone/StuRecruitmentBrochure.cshtml @@ -0,0 +1,67 @@ +@{ + + Layout = null; +} + + + + + + + + + + 招生简章 + + + + + + + + + + +
+ +
+
+ @*
招生简章
*@ + +
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/AdmissionForm.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/AdmissionForm.js index d2137ce1b..642cfa145 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/AdmissionForm.js +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/AdmissionForm.js @@ -28,7 +28,7 @@ var bootstrap = function ($, learun) { for (var i = 0; i < data.length; i++) { html += '
'; html += '
' + data[i].SubjectName + ':
'; - html += ''; + html += ''; html += '
'; } $('#form').html(html); diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/AdmissionIndex.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/AdmissionIndex.cshtml index 1683efd84..4d91bb910 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/AdmissionIndex.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/AdmissionIndex.cshtml @@ -41,7 +41,7 @@ diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/AdmissionIndex.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/AdmissionIndex.js index ee19b45a6..9d7371526 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/AdmissionIndex.js +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/AdmissionIndex.js @@ -79,11 +79,11 @@ var bootstrap = function ($, learun) { $('#lr_nolq').on('click', function () { var keyValue = $('#gridtable').jfGridValue('StuId'); if (learun.checkrow(keyValue)) { - var IsAdmission = $('#gridtable').jfGridValue('IsAdmission'); - if (IsAdmission == 0) { - return learun.alert.warning('该学生未被录取!'); - } - learun.layerConfirm('是否确认取消录取当前学生!', function (res) { + //var IsAdmission = $('#gridtable').jfGridValue('IsAdmission'); + //if (IsAdmission == 0) { + // return learun.alert.warning('该学生未被录取!'); + //} + learun.layerConfirm('是否确认不录取当前学生!', function (res) { if (res) { learun.postForm(top.$.rootUrl + '/EducationalAdministration/StuEnroll/Admission?keyValue=' + keyValue, { IsAdmission: 0 }, function () { refreshGirdData(); @@ -165,14 +165,16 @@ var bootstrap = function ($, learun) { }); } }, - { label: "总分", name: "ExamScore", width: 100, align: "left" }, + //{ label: "总分", name: "ExamScore", width: 100, align: "left" }, { label: "是否录取", name: "IsAdmission", width: 100, align: "left", formatter: function (value) { if (value == 1) { return ""; - } else { + } else if (value == 0) { return ""; + } else { + return ""; } } }, diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/Index.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/Index.js index cbd956220..9b6eb2c19 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/Index.js +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuEnrollScore/Index.js @@ -54,7 +54,7 @@ var bootstrap = function ($, learun) { learun.clientdata.getAsync('custmerData', { url: '/LR_SystemModule/DataSource/GetDataTable?code=' + 'ExamSubject', key: value, - keyId: 'id', + keyId: 'subjectno', callback: function (_data) { callback(_data['subjectname']); } @@ -65,16 +65,27 @@ var bootstrap = function ($, learun) { ]; headDataEdit = [ { - label: '成绩', name: 'Score', width: 100, align: "left", - edit: { - type: 'input', - inputType: 'number', - change: function (row, rownum) { - //row.Score = (parseFloat(row.OrdinaryScore || '0') * (Number($('#OrdinaryScoreScale').html()) / 100) + parseFloat(row.TermInScore || '0') * (Number($('#TermInScoreScale').html()) / 100) + parseFloat(row.TermEndScore || '0') * (Number($('#TermEndScoreScale').html()) / 100) + parseFloat(row.OtherScore || '0') * (Number($('#OtherScoreScale').html()) / 100)).toFixed(0); - $('#gridtable').jfGridSet('updateRow', rownum); + label: '成绩', name: 'Grade', width: 100, align: 'left' + , edit: { + type: 'select', + init: function (data, $edit) { + }, + datatype: 'dataItem', + code: 'StuScoreGrade' } }, + //{ + // label: '成绩', name: 'Score', width: 100, align: "left", + // edit: { + // type: 'input', + // inputType: 'number', + // change: function (row, rownum) { + // //row.Score = (parseFloat(row.OrdinaryScore || '0') * (Number($('#OrdinaryScoreScale').html()) / 100) + parseFloat(row.TermInScore || '0') * (Number($('#TermInScoreScale').html()) / 100) + parseFloat(row.TermEndScore || '0') * (Number($('#TermEndScoreScale').html()) / 100) + parseFloat(row.OtherScore || '0') * (Number($('#OtherScoreScale').html()) / 100)).toFixed(0); + // $('#gridtable').jfGridSet('updateRow', rownum); + // }, + // } + //}, { label: '备注', name: 'Remark', width: 100, align: "left", edit: { @@ -83,7 +94,7 @@ var bootstrap = function ($, learun) { }, ]; headDataNoEdit = [ - { label: '成绩', name: 'Score', width: 80, align: "left" }, + { label: '成绩', name: 'Grade', width: 80, align: "left" }, { label: '备注', name: 'Remark', width: 100, align: "left" }, @@ -132,7 +143,6 @@ var bootstrap = function ($, learun) { if (res) { var query = judgeSelect(); if (query) { - //判断是否已审核;判断是否被其他教师占用 $.lrSetForm(top.$.rootUrl + '/EducationalAdministration/StuEnrollScore/GetEntityByJson?queryJson=' + JSON.stringify(query), function (data) { if (data != null) { diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/Form.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/Form.cshtml index 212155cab..754bfa7d3 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/Form.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/Form.cshtml @@ -94,7 +94,7 @@
高考总分 *
- +
语文成绩
diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/Form.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/Form.js index c0321d48e..6451fe1c3 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/Form.js +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/Form.js @@ -147,7 +147,6 @@ var bootstrap = function ($, learun) { $("#photoBtn").on('click', function () { takeImg(); }); - }, initData: function () { if (!!keyValue) { @@ -176,6 +175,11 @@ var bootstrap = function ($, learun) { return false; } + var Score1 = $('#ChineseScore').val(); + var Score2 = $('#MathScore').val(); + var Score3 = $('#ForeignLangScore').val(); + var Score4 = $('#ComprehensiveScore').val(); + $('#HighAmountScore').val(Number(Score1) + Number(Score2) + Number(Score3) + Number(Score4)); var postData = {}; postData.strEntity = JSON.stringify($('[data-table="StuInfoFresh"]').lrGetFormData()); postData.strstuInfoFreshEmergePeopleList = JSON.stringify($('#StuInfoFreshEmergePeople').jfGridGet('rowdatas')); diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/FormView.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/FormView.cshtml index a528eb6f4..a44a860e5 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/FormView.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/FormView.cshtml @@ -62,7 +62,7 @@
出生日期
- +
政治面貌 *
@@ -147,7 +147,7 @@
精准贫困户
-
+
diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/FormView.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/FormView.js index 1d1fbd919..69ff96a1f 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/FormView.js +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/FormView.js @@ -31,44 +31,44 @@ var bootstrap = function ($, learun) { headData: [ { label: '姓名', name: 'Name', width: 100, align: 'left' - , edit: { - type: 'input' - } }, { label: '与本人关系', name: 'Relation', width: 100, align: 'left' - , edit: { - type: 'select', - datatype: 'dataItem', - code: 'FamilyRelation' + , formatterAsync: function (callback, value, row, op, $cell) { + learun.clientdata.getAsync('dataItem', { + key: value, + code: 'FamilyRelation', + callback: function (_data) { + callback(_data.text); + } + }); } }, { - label: '性别', name: 'Sex', width: 100, align: 'left' - , edit: { - type: 'select', - datatype: 'dataItem', - code: 'usersex' + label: '性别', name: 'Sex', width: 100, align: 'left', + formatterAsync: function (callback, value, row, op, $cell) { + learun.clientdata.getAsync('dataItem', { + key: value, + code: 'usersex', + callback: function (_data) { + callback(_data.text); + } + }); } }, { label: '年龄', name: 'Age', width: 100, align: 'left' - , edit: { - type: 'input' - } }, { label: '政治面貌', name: 'Politicy', width: 100, align: 'left' - , edit: { - type: 'select', - datatype: 'dataItem', - code: 'PolityStatus' - } - }, - { - label: '身份证号', name: 'IdCard', width: 100, align: 'left' - , edit: { - type: 'input' + , formatterAsync: function (callback, value, row, op, $cell) { + learun.clientdata.getAsync('dataItem', { + key: value, + code: 'BCdPartyFace', + callback: function (_data) { + callback(_data.text); + } + }); } }, ], @@ -78,36 +78,11 @@ var bootstrap = function ($, learun) { $('#StuInfoFreshEmergePeople').jfGrid({ headData: [ - { - label: '姓名', name: 'Name', width: 100, align: 'left' - , edit: { - type: 'input' - } - }, - { - label: '与本人关系', name: 'Relation', width: 100, align: 'left' - , edit: { - type: 'input' - } - }, - { - label: '手机号码', name: 'Mobile', width: 100, align: 'left' - , edit: { - type: 'input' - } - }, - { - label: '座机电话', name: 'Telephone', width: 100, align: 'left' - , edit: { - type: 'input' - } - }, - { - label: '联系地址', name: 'Address', width: 100, align: 'left' - , edit: { - type: 'input' - } - }, + { label: '姓名', name: 'Name', width: 100, align: 'left' }, + { label: '与本人关系', name: 'Relation', width: 100, align: 'left' }, + { label: '手机号码', name: 'Mobile', width: 100, align: 'left' }, + { label: '座机电话', name: 'Telephone', width: 100, align: 'left' }, + { label: '联系地址', name: 'Address', width: 100, align: 'left' }, ], isEdit: false, height: 200 diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuLeaveManagement/Form.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuLeaveManagement/Form.cshtml index 08574f89c..c6e7e5af0 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuLeaveManagement/Form.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuLeaveManagement/Form.cshtml @@ -15,9 +15,13 @@
返校时间*
-
+
请假天数*
- + +
+
+
未销假次数
+
附件上传
diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuLeaveManagement/FormView.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuLeaveManagement/FormView.cshtml index 9dd976407..19728f453 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuLeaveManagement/FormView.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuLeaveManagement/FormView.cshtml @@ -15,10 +15,14 @@
返校时间*
-
+
请假天数*
+
+
未销假次数
+ +
附件上传
diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/Form.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/Form.cshtml new file mode 100644 index 000000000..7c1cc3174 --- /dev/null +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/Form.cshtml @@ -0,0 +1,44 @@ +@{ + ViewBag.Title = "疫情"; + Layout = "~/Views/Shared/_Form.cshtml"; +} +
+
+
学号
+ + +
+
+
姓名
+ +
+
+
接种地
+ +
+
+
疫苗类型
+
+
+
+
第一针时间
+ +
+
+
第二针时间
+ +
+
+
第三针时间
+ +
+
+
未接种原因
+ +
+
+
备注
+ +
+
+@Html.AppendJsFile("/Areas/EducationalAdministration/Views/VaccinationInfo/Form.js") diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/Form.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/Form.js new file mode 100644 index 000000000..db719b6e8 --- /dev/null +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/Form.js @@ -0,0 +1,51 @@ +/* * 版 本 Learun-ADMS V7.0.6 力软敏捷开发框架(http://www.learun.cn) + * Copyright (c) 2013-2020 力软信息技术(苏州)有限公司 + * 创建人:超级管理员 + * 日 期:2022-07-18 17:52 + * 描 述:疫情 + */ +var acceptClick; +var keyValue = request('keyValue'); +var bootstrap = function ($, learun) { + "use strict"; + var page = { + init: function () { + $('.lr-form-wrap').lrscroll(); + page.bind(); + page.initData(); + }, + bind: function () { + $('#VaccineType').lrDataItemSelect({ code: 'VaccineType' }); + }, + initData: function () { + if (!!keyValue) { + $.lrSetForm(top.$.rootUrl + '/EducationalAdministration/VaccinationInfo/GetFormData?keyValue=' + keyValue, function (data) { + for (var id in data) { + if (!!data[id].length && data[id].length > 0) { + $('#' + id).jfGridSet('refreshdata', data[id]); + } + else { + $('[data-table="' + id + '"]').lrSetFormData(data[id]); + } + } + }); + } + } + }; + // 保存数据 + acceptClick = function (callBack) { + if (!$('body').lrValidform()) { + return false; + } + var postData = { + strEntity: JSON.stringify($('body').lrGetFormData()) + }; + $.lrSaveForm(top.$.rootUrl + '/EducationalAdministration/VaccinationInfo/SaveForm?keyValue=' + keyValue, postData, function (res) { + // 保存成功后才回调 + if (!!callBack) { + callBack(); + } + }); + }; + page.init(); +} diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/Index.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/Index.cshtml new file mode 100644 index 000000000..d901b249f --- /dev/null +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/Index.cshtml @@ -0,0 +1,56 @@ +@{ + ViewBag.Title = "疫情"; + Layout = "~/Views/Shared/_Index.cshtml"; +} +
+
+
+
+
+
+
+
+
+
学号
+ +
+
+
姓名
+ +
+
+
系部
+
+
+
+
专业
+
+
+
+
班级
+
+
+
+
接种类型
+
+
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+@Html.AppendJsFile("/Areas/EducationalAdministration/Views/VaccinationInfo/Index.js") diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/Index.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/Index.js new file mode 100644 index 000000000..d1e183a34 --- /dev/null +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/Index.js @@ -0,0 +1,232 @@ +/* * 版 本 Learun-ADMS V7.0.6 力软敏捷开发框架(http://www.learun.cn) + * Copyright (c) 2013-2020 力软信息技术(苏州)有限公司 + * 创建人:超级管理员 + * 日 期:2022-07-18 17:52 + * 描 述:疫情 + */ +var refreshGirdData; +var bootstrap = function ($, learun) { + "use strict"; + var page = { + init: function () { + page.initGird(); + page.bind(); + }, + bind: function () { + $('#multiple_condition_query').lrMultipleQuery(function (queryJson) { + page.search(queryJson); + }, 220, 400); + $('#VaccineType').lrDataItemSelect({ code: 'VaccineType' }); + $('#DeptNo').lrselect({ + value: "deptno", + text: "deptname", + url: top.$.rootUrl + '/LR_SystemModule/DataSource/GetDataTable?code=CdDeptInfo', + select: function (item) { + if (item) { + $('#MajorNo').lrselectRefresh({ + url: top.$.rootUrl + '/LR_SystemModule/DataSource/GetDataTable', + param: { code: "CdMajorInfo", strWhere: "DeptNo='" + item.deptno + "'" } + }); + } + else { + $('#MajorNo').lrselectRefresh({ + url: "", + data: [] + }); + } + $('#ClassNo').lrselectRefresh({ + url: "", + data: [] + }); + } + }); + $('#MajorNo').lrselect({ + value: "majorno", + text: "majorname", + select: function (item) { + if (item) { + $('#ClassNo').lrselectRefresh({ + url: top.$.rootUrl + '/LR_SystemModule/DataSource/GetDataTable', + param: { code: "bjsj", strWhere: "DeptNo='" + item.deptno + "' and majorno='" + item.majorno + "'" } + }); + } + + } + }); + $('#MajorNo').on("click", + function () { + var data = $('#DeptNo').lrselectGet(); + if (!data) { + learun.alert.error('请先选择系'); + } + }); + $('#ClassNo').on("click", + function () { + var data1 = $('#DeptNo').lrselectGet(); + var data2 = $('#MajorNo').lrselectGet(); + if (!data1 || !data2) { + learun.alert.error('请先选择系和专业'); + } + }); + $('#ClassNo').lrselect({ + value: "classno", + text: "classname" + }); + // 刷新 + $('#lr_refresh').on('click', function () { + location.reload(); + }); + //// 新增 + //$('#lr_add').on('click', function () { + // learun.layerForm({ + // id: 'form', + // title: '新增', + // url: top.$.rootUrl + '/EducationalAdministration/VaccinationInfo/Form', + // width: 600, + // height: 400, + // callBack: function (id) { + // return top[id].acceptClick(refreshGirdData); + // } + // }); + //}); + // 编辑 + $('#lr_edit').on('click', function () { + var keyValue = $('#gridtable').jfGridValue('Id'); + if (learun.checkrow(keyValue)) { + learun.layerForm({ + id: 'form', + title: '编辑', + url: top.$.rootUrl + '/EducationalAdministration/VaccinationInfo/Form?keyValue=' + keyValue, + width: 600, + height: 430, + callBack: function (id) { + return top[id].acceptClick(refreshGirdData); + } + }); + } + }); + // 删除 + $('#lr_delete').on('click', function () { + var keyValue = $('#gridtable').jfGridValue('Id'); + if (learun.checkrow(keyValue)) { + learun.layerConfirm('是否确认删除该项!', function (res) { + if (res) { + learun.deleteForm(top.$.rootUrl + '/EducationalAdministration/VaccinationInfo/DeleteForm', { keyValue: keyValue }, function () { + refreshGirdData(); + }); + } + }); + } + }); + // 一键生成 + $('#lr_create').on('click', function () { + var userId = learun.clientdata.get(['userinfo']).userId; + learun.layerConfirm('是否确认一键生成!', function (res) { + if (res) { + learun.postForm(top.$.rootUrl + '/EducationalAdministration/VaccinationInfo/CreateFrom', { userId: userId, Description: 0 }, function () { + refreshGirdData(); + }); + } + }); + }); + }, + // 初始化列表 + initGird: function () { + $('#gridtable').lrAuthorizeJfGrid({ + url: top.$.rootUrl + '/EducationalAdministration/VaccinationInfo/GetPageList', + headData: [ + { label: "学号", name: "StuNo", width: 100, align: "left" }, + { label: "姓名", name: "StuName", width: 160, align: "left" }, + { label: "年龄", name: "Age", width: 80, align: "left" }, + { label: "身份证", name: "CardId", width: 150, align: "left" }, + { + label: "院系", name: "DeptNo", width: 160, align: "left", + formatterAsync: function (callback, value, row, op, $cell) { + learun.clientdata.getAsync('custmerData', { + url: '/LR_SystemModule/DataSource/GetDataTable?code=' + 'CdDeptInfo', + key: value, + keyId: 'deptno', + callback: function (_data) { + callback(_data['deptname']); + } + }); + } + }, + { + label: "专业", name: "MajorNo", width: 160, align: "left", + formatterAsync: function (callback, value, row, op, $cell) { + learun.clientdata.getAsync('custmerData', { + url: '/LR_SystemModule/DataSource/GetDataTable?code=' + 'CdMajorInfo', + key: value, + keyId: 'majorno', + callback: function (_data) { + callback(_data['majorname']); + } + }); + } + }, + { + label: "班级", name: "ClassNo", width: 160, align: "left", + formatterAsync: function (callback, value, row, op, $cell) { + learun.clientdata.getAsync('custmerData', { + url: '/LR_SystemModule/DataSource/GetDataTable?code=' + 'bjsj', + key: value, + keyId: 'classno', + callback: function (_data) { + callback(_data['classname']); + } + }); + } + }, + { label: "电话号码", name: "Mobile", width: 120, align: "left" }, + { + label: "疫苗类型", name: "VaccineType", width: 100, align: "left", + formatterAsync: function (callback, value, row, op, $cell) { + learun.clientdata.getAsync('dataItem', { + key: value, + code: 'VaccineType', + callback: function (_data) { + callback(_data.text); + } + }); + } + }, + { label: "接种地", name: "VaccineAddress", width: 100, align: "left" }, + { + label: "第一针时间", name: "FirstNeedle", width: 80, align: "left", + formatter: function (cellvalue) { + return learun.formatDate(cellvalue, 'yyyy-MM-dd'); + } + }, + { + label: "第二针时间", name: "SecondNeedle", width: 80, align: "left", + formatter: function (cellvalue) { + return learun.formatDate(cellvalue, 'yyyy-MM-dd'); + } + }, + { + label: "第三针时间", name: "ThirdNeedle", width: 80, align: "left", + formatter: function (cellvalue) { + return learun.formatDate(cellvalue, 'yyyy-MM-dd'); + } + }, + { label: "未接种原因", name: "NotReason", width: 150, align: "left" }, + { label: "备注", name: "Remark", width: 200, align: "left" }, + ], + mainId: 'Id', + sidx: 'CreateTime desc', + isPage: true + }); + page.search(); + }, + search: function (param) { + param = param || {}; + param.StuOrTeach = 0; + $('#gridtable').jfGridSet('reload', { queryJson: JSON.stringify(param) }); + } + }; + refreshGirdData = function () { + $('#gridtable').jfGridSet('reload'); + }; + page.init(); +} diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/TeachForm.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/TeachForm.cshtml new file mode 100644 index 000000000..942763c83 --- /dev/null +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/TeachForm.cshtml @@ -0,0 +1,44 @@ +@{ + ViewBag.Title = "疫情"; + Layout = "~/Views/Shared/_Form.cshtml"; +} +
+
+
职工号
+ + +
+
+
姓名
+ +
+
+
接种地
+ +
+
+
疫苗类型
+
+
+
+
第一针时间
+ +
+
+
第二针时间
+ +
+
+
第三针时间
+ +
+
+
未接种原因
+ +
+
+
备注
+ +
+
+@Html.AppendJsFile("/Areas/EducationalAdministration/Views/VaccinationInfo/TeachForm.js") diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/TeachForm.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/TeachForm.js new file mode 100644 index 000000000..db719b6e8 --- /dev/null +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/TeachForm.js @@ -0,0 +1,51 @@ +/* * 版 本 Learun-ADMS V7.0.6 力软敏捷开发框架(http://www.learun.cn) + * Copyright (c) 2013-2020 力软信息技术(苏州)有限公司 + * 创建人:超级管理员 + * 日 期:2022-07-18 17:52 + * 描 述:疫情 + */ +var acceptClick; +var keyValue = request('keyValue'); +var bootstrap = function ($, learun) { + "use strict"; + var page = { + init: function () { + $('.lr-form-wrap').lrscroll(); + page.bind(); + page.initData(); + }, + bind: function () { + $('#VaccineType').lrDataItemSelect({ code: 'VaccineType' }); + }, + initData: function () { + if (!!keyValue) { + $.lrSetForm(top.$.rootUrl + '/EducationalAdministration/VaccinationInfo/GetFormData?keyValue=' + keyValue, function (data) { + for (var id in data) { + if (!!data[id].length && data[id].length > 0) { + $('#' + id).jfGridSet('refreshdata', data[id]); + } + else { + $('[data-table="' + id + '"]').lrSetFormData(data[id]); + } + } + }); + } + } + }; + // 保存数据 + acceptClick = function (callBack) { + if (!$('body').lrValidform()) { + return false; + } + var postData = { + strEntity: JSON.stringify($('body').lrGetFormData()) + }; + $.lrSaveForm(top.$.rootUrl + '/EducationalAdministration/VaccinationInfo/SaveForm?keyValue=' + keyValue, postData, function (res) { + // 保存成功后才回调 + if (!!callBack) { + callBack(); + } + }); + }; + page.init(); +} diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/TeachIndex.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/TeachIndex.cshtml new file mode 100644 index 000000000..852d8a88a --- /dev/null +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/TeachIndex.cshtml @@ -0,0 +1,53 @@ +@using Learun.Application.Web +@{ + ViewBag.Title = "疫情"; + Layout = "~/Views/Shared/_Index.cshtml"; +} +
+
+
+
+
+
+
+
+
+
部门
+
+
+
+
职工号
+ +
+
+
姓名
+ +
+
+
接种类型
+
+
+
+
身份证号
+ +
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+@Html.AppendJsFile("/Areas/EducationalAdministration/Views/VaccinationInfo/TeachIndex.js") diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/TeachIndex.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/TeachIndex.js new file mode 100644 index 000000000..ca687fd0b --- /dev/null +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/VaccinationInfo/TeachIndex.js @@ -0,0 +1,211 @@ +/* * 版 本 Learun-ADMS V7.0.6 力软敏捷开发框架(http://www.learun.cn) + * Copyright (c) 2013-2020 力软信息技术(苏州)有限公司 + * 创建人:超级管理员 + * 日 期:2022-07-18 17:52 + * 描 述:疫情 + */ +var refreshGirdData; +var bootstrap = function ($, learun) { + "use strict"; + var page = { + init: function () { + page.initGird(); + page.bind(); + }, + bind: function () { + $('#multiple_condition_query').lrMultipleQuery(function (queryJson) { + page.search(queryJson); + }, 220, 400); + $('#VaccineType').lrDataItemSelect({ code: 'VaccineType' }); + $('#DepartmentId').lrselect({ + type: 'tree', + allowSearch: true, + url: top.$.rootUrl + '/LR_OrganizationModule/Department/GetTree', + param: {} + }); + $('#DeptNo').lrselect({ + value: "deptno", + text: "deptname", + url: top.$.rootUrl + '/LR_SystemModule/DataSource/GetDataTable?code=CdDeptInfo', + select: function (item) { + if (item) { + $('#MajorNo').lrselectRefresh({ + url: top.$.rootUrl + '/LR_SystemModule/DataSource/GetDataTable', + param: { code: "CdMajorInfo", strWhere: "DeptNo='" + item.deptno + "'" } + }); + } + else { + $('#MajorNo').lrselectRefresh({ + url: "", + data: [] + }); + } + $('#ClassNo').lrselectRefresh({ + url: "", + data: [] + }); + } + }); + $('#MajorNo').lrselect({ + value: "majorno", + text: "majorname", + select: function (item) { + if (item) { + $('#ClassNo').lrselectRefresh({ + url: top.$.rootUrl + '/LR_SystemModule/DataSource/GetDataTable', + param: { code: "bjsj", strWhere: "DeptNo='" + item.deptno + "' and majorno='" + item.majorno + "'" } + }); + } + + } + }); + $('#MajorNo').on("click", + function () { + var data = $('#DeptNo').lrselectGet(); + if (!data) { + learun.alert.error('请先选择系'); + } + }); + $('#ClassNo').on("click", + function () { + var data1 = $('#DeptNo').lrselectGet(); + var data2 = $('#MajorNo').lrselectGet(); + if (!data1 || !data2) { + learun.alert.error('请先选择系和专业'); + } + }); + $('#ClassNo').lrselect({ + value: "classno", + text: "classname" + }); + // 刷新 + $('#lr_refresh').on('click', function () { + location.reload(); + }); + //// 新增 + //$('#lr_add').on('click', function () { + // learun.layerForm({ + // id: 'form', + // title: '新增', + // url: top.$.rootUrl + '/EducationalAdministration/VaccinationInfo/Form', + // width: 600, + // height: 400, + // callBack: function (id) { + // return top[id].acceptClick(refreshGirdData); + // } + // }); + //}); + // 编辑 + $('#lr_edit').on('click', function () { + var keyValue = $('#gridtable').jfGridValue('Id'); + if (learun.checkrow(keyValue)) { + learun.layerForm({ + id: 'form', + title: '编辑', + url: top.$.rootUrl + '/EducationalAdministration/VaccinationInfo/TeachForm?keyValue=' + keyValue, + width: 600, + height: 430, + callBack: function (id) { + return top[id].acceptClick(refreshGirdData); + } + }); + } + }); + // 删除 + $('#lr_delete').on('click', function () { + var keyValue = $('#gridtable').jfGridValue('Id'); + if (learun.checkrow(keyValue)) { + learun.layerConfirm('是否确认删除该项!', function (res) { + if (res) { + learun.deleteForm(top.$.rootUrl + '/EducationalAdministration/VaccinationInfo/DeleteForm', { keyValue: keyValue }, function () { + refreshGirdData(); + }); + } + }); + } + }); + // 一键生成 + $('#lr_create').on('click', function () { + var userId = learun.clientdata.get(['userinfo']).userId; + learun.layerConfirm('是否确认一键生成!', function (res) { + if (res) { + learun.postForm(top.$.rootUrl + '/EducationalAdministration/VaccinationInfo/CreateFrom', { userId: userId, Description: 1 }, function () { + refreshGirdData(); + }); + } + }); + }); + }, + // 初始化列表 + initGird: function () { + $('#gridtable').jfGrid({ + url: top.$.rootUrl + '/EducationalAdministration/VaccinationInfo/GetPageList', + headData: [ + { label: "职工编号", name: "EmpNo", width: 100, align: "left" }, + { label: "姓名", name: "EmpName", width: 150, align: "left" }, + { label: "身份证", name: "CardId", width: 160, align: "left" }, + { + label: "部门", name: "DepartmentId", width: 200, align: "left", + formatterAsync: function (callback, value, row, op, $cell) { + learun.clientdata.getAsync('custmerData', { + url: '/LR_SystemModule/DataSource/GetDataTable?code=' + 'classdata', + key: value, + keyId: 'id', + callback: function (_data) { + callback(_data['name']); + } + }); + } + }, + { label: "电话号码", name: "Mobile", width: 120, align: "left" }, + { + label: "疫苗类型", name: "VaccineType", width: 100, align: "left", + formatterAsync: function (callback, value, row, op, $cell) { + learun.clientdata.getAsync('dataItem', { + key: value, + code: 'VaccineType', + callback: function (_data) { + callback(_data.text); + } + }); + } + }, + { label: "接种地", name: "VaccineAddress", width: 100, align: "left" }, + { + label: "第一针时间", name: "FirstNeedle", width: 100, align: "left", + formatter: function (cellvalue) { + return learun.formatDate(cellvalue, 'yyyy-MM-dd'); + } + }, + { + label: "第二针时间", name: "SecondNeedle", width: 100, align: "left", + formatter: function (cellvalue) { + return learun.formatDate(cellvalue, 'yyyy-MM-dd'); + } + }, + { + label: "第三针时间", name: "ThirdNeedle", width: 100, align: "left", + formatter: function (cellvalue) { + return learun.formatDate(cellvalue, 'yyyy-MM-dd'); + } + }, + { label: "未接种原因", name: "NotReason", width: 200, align: "left" }, + { label: "备注", name: "Remark", width: 300, align: "left" }, + ], + mainId: 'Id', + sidx: 'CreateTime desc', + isPage: true + }); + page.search(); + }, + search: function (param) { + param = param || {}; + param.StuOrTeach = 1; + $('#gridtable').jfGridSet('reload', { queryJson: JSON.stringify(param) }); + } + }; + refreshGirdData = function () { + $('#gridtable').jfGridSet('reload'); + }; + page.init(); +} diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Controllers/CompanyController.cs b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Controllers/CompanyController.cs index eeca1f1b5..e7baf2ceb 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Controllers/CompanyController.cs +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Controllers/CompanyController.cs @@ -51,6 +51,11 @@ namespace Learun.Application.Web.Areas.LR_OrganizationModule.Controllers public ActionResult GetList(string keyword) { var data = companyIBLL.GetList(keyword); + foreach (var item in data) + { + item.F_BriefIntroduction = WebHelper.HtmlDecode(item.F_BriefIntroduction); + item.F_EnrollmentInformation = WebHelper.HtmlDecode(item.F_EnrollmentInformation); + } return JsonResult(data); } /// @@ -101,9 +106,13 @@ namespace Learun.Application.Web.Areas.LR_OrganizationModule.Controllers [HttpPost] [ValidateAntiForgeryToken] [AjaxOnly] - public ActionResult SaveForm(string keyValue, CompanyEntity entity) + [ValidateInput(false)] + public ActionResult SaveForm(string keyValue, string strEntity) { + CompanyEntity entity = strEntity.ToObject(); entity.SyncFlag = false; + entity.F_BriefIntroduction = WebHelper.HtmlEncode(entity.F_BriefIntroduction); + entity.F_EnrollmentInformation = WebHelper.HtmlEncode(entity.F_EnrollmentInformation); var list = companyIBLL.GetList(); if (!string.IsNullOrEmpty(keyValue)) { diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Views/Company/Form.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Views/Company/Form.cshtml index 1c4675d7b..80801f5ea 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Views/Company/Form.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Views/Company/Form.cshtml @@ -2,78 +2,85 @@ ViewBag.Title = "学校添加"; Layout = "~/Views/Shared/_Form.cshtml"; } -
-
-
学校名称*
- -
-
-
学校编码*
- -
-
-
学校简称*
- -
-
-
上级学校
-
-
-
-
成立时间
- -
-
-
负责人
- -
-
-
电话
- -
+
+
+
学校名称*
+ +
+
+
学校编码*
+ +
+
+
学校简称*
+ +
+
+
上级学校
+
+
+
+
成立时间*
+ +
+
+
负责人
+ +
+
+
电话
+ +
-
-
电子邮箱
- -
-
-
照片
-
-
-
-
校区简介
-
-
-
-
招生简介
-
-
-
-
传真
- -
-
-
学校地点
-
-
-
-
-
-
- -
-
-
-
邮编
- -
-
-
学校官网
- +
+
电子邮箱
+ +
+
+
照片
+
+
+
+
校区简介
+ @*
*@ + +
+
+
招生简介
+ @*
*@ + +
+
+
传真
+ +
+
+
学校地点
+
+
+
+
-
-
备注
- +
+
+
+
邮编
+ +
+
+
学校官网
+ +
+
+
备注
+ +
+
+ + + @Html.AppendJsFile("/Areas/LR_OrganizationModule/Views/Company/Form.js") diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Views/Company/Form.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Views/Company/Form.js index 7314020ad..dfeacc4d3 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Views/Company/Form.js +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Views/Company/Form.js @@ -10,6 +10,8 @@ var acceptClick; var keyValue = ''; var bootstrap = function ($, learun) { "use strict"; + var F_BriefIntroductionUE; + var F_EnrollmentInformationUE; var selectedRow = learun.frameTab.currentIframe().selectedRow; var page = { init: function () { @@ -24,15 +26,25 @@ var bootstrap = function ($, learun) { // 省市区 $('#area').lrAreaSelect(); $('#F_Photo').lrUploader(); - var F_BriefIntroductionUE = UE.getEditor('F_BriefIntroduction'); - $('#F_BriefIntroduction')[0].ue = F_BriefIntroductionUE; - var F_EnrollmentInformationUE = UE.getEditor('F_EnrollmentInformation'); - $('#F_EnrollmentInformation')[0].ue = F_EnrollmentInformationUE; + F_BriefIntroductionUE = UE.getEditor('F_BriefIntroduction'); + F_EnrollmentInformationUE = UE.getEditor('F_EnrollmentInformation'); }, initData: function () { if (!!selectedRow) { keyValue = selectedRow.F_CompanyId; $('#form').lrSetFormData(selectedRow); + if (selectedRow.F_BriefIntroduction) { + setTimeout(function () { + F_BriefIntroductionUE.setContent(selectedRow.F_BriefIntroduction); + }, 100); + + }; + if (selectedRow.F_EnrollmentInformation) { + setTimeout(function () { + F_EnrollmentInformationUE.setContent(selectedRow.F_EnrollmentInformation); + }, 100); + + }; } } }; @@ -45,7 +57,12 @@ var bootstrap = function ($, learun) { if (postData["F_ParentId"] == '' || postData["F_ParentId"] == ' ') { postData["F_ParentId"] = '0'; } - $.lrSaveForm(top.$.rootUrl + '/LR_OrganizationModule/Company/SaveForm?keyValue=' + keyValue, postData, function (res) { + postData["F_BriefIntroduction"] = F_BriefIntroductionUE.getContent(null, null, true); + postData["F_EnrollmentInformation"] = F_EnrollmentInformationUE.getContent(null, null, true); + var postDatas = { + strEntity: JSON.stringify(postData) + }; + $.lrSaveForm(top.$.rootUrl + '/LR_OrganizationModule/Company/SaveForm?keyValue=' + keyValue, postDatas, function (res) { // 保存成功后才回调 if (!!callBack) { callBack(); diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Views/Company/Index.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Views/Company/Index.js index 491a608b2..08293666a 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Views/Company/Index.js +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/LR_OrganizationModule/Views/Company/Index.js @@ -28,7 +28,7 @@ var bootstrap = function ($, learun) { title: '添加学校', url: top.$.rootUrl + '/LR_OrganizationModule/Company/Form', width: 750, - height: 500, + height: 800, callBack: function (id) { return top[id].acceptClick(refreshGirdData); } @@ -44,7 +44,7 @@ var bootstrap = function ($, learun) { title: '编辑学校', url: top.$.rootUrl + '/LR_OrganizationModule/Company/Form', width: 750, - height: 500, + height: 800, callBack: function (id) { return top[id].acceptClick(refreshGirdData); } diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Controllers/TimeTableController.cs b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Controllers/TimeTableController.cs index 1590f5ba2..06493a9a2 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Controllers/TimeTableController.cs +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Controllers/TimeTableController.cs @@ -121,7 +121,24 @@ namespace Learun.Application.Web.Areas.PersonnelManagement.Controllers { return View(); } - + /// + /// 表单--修改教师所带的课程【教务】 + /// + /// + [HttpGet] + public ActionResult SchoolLesson() + { + return View(); + } + /// + /// 表单--修改教师所带的课程【教务】 + /// + /// + [HttpGet] + public ActionResult PrintSchedule() + { + return View(); + } /// /// 获取表单数据 /// @@ -337,7 +354,7 @@ namespace Learun.Application.Web.Areas.PersonnelManagement.Controllers //最大节次 int maxlessontime = timeTables.Max(m =>Convert.ToInt32(m.LessonTime.Substring(1))); //班级列表 - var classinfolist = timeTables.Select(m => new {m.TeachClassNo, m.ClassName}).OrderBy(m => m.TeachClassNo).GroupBy(m=>new {m.TeachClassNo,m.ClassName}); + var classinfolist = timeTables.Select(m => new { m.TeachClassNo, m.ClassName}).OrderBy(m => m.TeachClassNo).GroupBy(m=>new {m.TeachClassNo,m.ClassName}); var formatData = from d in timeTables let tt = d.LessonTime.Substring(1) group d by tt into g diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TeacherCancelEmploy/Index.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TeacherCancelEmploy/Index.js index deeb2e6c6..f50f2f302 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TeacherCancelEmploy/Index.js +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TeacherCancelEmploy/Index.js @@ -38,6 +38,11 @@ var bootstrap = function ($, learun) { $('#lr_edit').on('click', function () { var keyValue = $('#gridtable').jfGridValue('Id'); if (learun.checkrow(keyValue)) { + var checkMark = $('#gridtable').jfGridValue('CheckMark'); + if (checkMark == true) { + learun.alert.warning("已审核项不可编辑!"); + return false; + } learun.layerForm({ id: 'form', title: '编辑', @@ -54,6 +59,11 @@ var bootstrap = function ($, learun) { $('#lr_delete').on('click', function () { var keyValue = $('#gridtable').jfGridValue('Id'); if (learun.checkrow(keyValue)) { + var checkMark = $('#gridtable').jfGridValue('CheckMark'); + if (checkMark == true) { + learun.alert.warning("已审核项不可删除!"); + return false; + } learun.layerConfirm('是否确认删除该项!', function (res) { if (res) { learun.deleteForm(top.$.rootUrl + '/PersonnelManagement/TeacherCancelEmploy/DeleteForm', { keyValue: keyValue }, function () { diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TeacherEncourgement/Form.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TeacherEncourgement/Form.cshtml index 2afbf5d07..34533b694 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TeacherEncourgement/Form.cshtml +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TeacherEncourgement/Form.cshtml @@ -3,25 +3,25 @@ Layout = "~/Views/Shared/_Form.cshtml"; }
-
+
教师*
-
+
-
+
奖励名称*
-
+
奖励原因
- +
-
-
奖励金额
- +
+
奖励金额*
+
-
+
奖励日期*
- +
@Html.AppendJsFile("/Areas/PersonnelManagement/Views/TeacherEncourgement/Form.js") diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TeacherLeaveManagement/FormView.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TeacherLeaveManagement/FormView.js index 7cc9d33c3..7ff9eccb7 100644 --- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TeacherLeaveManagement/FormView.js +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TeacherLeaveManagement/FormView.js @@ -47,7 +47,7 @@ var bootstrap = function ($, learun) { $('#CreateTime').val(learun.formatDate(new Date(), 'yyyy-MM-dd hh:mm:ss')); $('#LeaveType').lrDataItemSelect({ code: 'LeaveType' }); $('#LeaveDay').lrDataItemSelect({ code: 'LeaveDay' }); - $('#Files').lrUploader(); + $('#Files').lrUploader({ isUpload: false }); }, initData: function () { if (!!keyValue) { diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TimeTable/PrintSchedule.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TimeTable/PrintSchedule.cshtml new file mode 100644 index 000000000..c466fe2d7 --- /dev/null +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TimeTable/PrintSchedule.cshtml @@ -0,0 +1,204 @@ + + + + + 课程表打印 + + + +
+
+
+
导出
+ + + + + + diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TimeTable/SchoolLesson.cshtml b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TimeTable/SchoolLesson.cshtml new file mode 100644 index 000000000..1097c7a23 --- /dev/null +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TimeTable/SchoolLesson.cshtml @@ -0,0 +1,88 @@ +@{ + ViewBag.Title = "课程表"; + Layout = "~/Views/Shared/_Index.cshtml"; +} + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 查询 +
+
+
+
+ +  导出 +
+
+
+
+
+
+
+ @*
导出
*@ +
+
+
+
+@Html.AppendJsFile("/Areas/PersonnelManagement/Views/TimeTable/SchoolLesson.js") + diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TimeTable/SchoolLesson.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TimeTable/SchoolLesson.js new file mode 100644 index 000000000..570c79305 --- /dev/null +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/PersonnelManagement/Views/TimeTable/SchoolLesson.js @@ -0,0 +1,276 @@ +var refreshGirdData; +var bootstrap = function ($, learun) { + var startTime; + var endTime; + var Printdata; + var page = { + init: function () { + page.bind(); + page.bindSelect(); + }, + loadData: function (param) { + $.lrSetFormWithParam(top.$.rootUrl + '/PersonnelManagement/TimeTable/GetDataInEducation', param, + function (data) { + Printdata = ''; + for (var key in param) { + Printdata += key + '=' + param[key]+'&' + } + //console.log(data, "data") + var classList = data.classinfolist; + var classListNow = []; + if (classList == '' || classList == undefined) { + learun.alert.warning('未查询到数据,请更换搜索条件'); + return + } + for (var i = 0; i < classList.length; i++) { + classListNow.push(classList[i][0]); + } + + data.classinfolist = classListNow; + var dom = '' + var week = 7 + var weekObj = { + 0: '一', + 1: '二', + 2: '三', + 3: '四', + 4: '五', + 5: '六', + 6: '日', + } + // 生成一周七天表头 + for (var i = 0; i < week; i++) { + dom += '星期' + weekObj[i] + '' + } + dom += '班级|节次' + // 生成课程节次表头 + for (var j = 0; j < week; j++) { + var index = 0 + for (var i = 0; i < data.maxlessontime; i++) { + index++ + dom += '' + (index) + '' + } + } + dom += '' + // 生成每个班级的课程 + for (var i = 0; i < data.classinfolist.length; i++) { + var classMsg = data.classinfolist[i] + dom += '' + classMsg.ClassName + '' + for (var j = 0; j < week; j++) { + var index = 0 + for (var k = 0; k < data.maxlessontime; k++) { + index++ + dom += '' + } + } + dom += '' + } + table.innerHTML = dom + + var tableWidth = data.maxlessontime * 7 * 100 + table.style.width = tableWidth + 'px' + // 开始渲染数据 + var domObj = {} + var trsObj = {} + var trs = document.getElementsByTagName('tr') + for (var j = 0; j < trs.length; j++) { + var id = trs[j].getAttribute('classId') + if (id) { + trsObj[id] = trs[j] + } + + } + //console.log(trsObj,'trsObj') + for (var i = 0; i < data.weekList.length; i++) { + var weekObj = data.weekList[i] + for (var j = 0; j < weekObj.list.length; j++) { + var weekList = weekObj.list[j] + weekList['time'] = weekObj.time + + var tds = trsObj[weekList.teachClassNo].getElementsByTagName('td') + for (var k = 0; k < tds.length; k++) { + var time = tds[k].getAttribute('time') + var classId = tds[k].getAttribute('classId') + var week = tds[k].getAttribute('week') + if (week == weekList.day && classId == weekList.teachClassNo && time == weekList.time) { + tds[k].innerHTML = '
课程:' + weekList.curriculum + '
教师:' + weekList.teacher + '
教室:' + weekList.classRoom + '
' + } + } + } + } + } + + ); + }, + bind: function () { + // 刷新 + $('#lr_refresh').on('click', function () { + location.reload(); + }); + $('#datesearch').lrdate({ + dfdata: [ + { + name: '上周', + begin: function () { return learun.getTime(7); }, + end: function () { + return learun.getTime(1); + } + }, + { + name: '本周', + begin: function () { return learun.getTime(0); }, + end: function () { + return learun.getTime(-6); + } + }, + { + name: '下周', + begin: function () { return learun.getTime(-7); }, + end: function () { + return learun.getTime(-13); + } + }], + // 月 + mShow: false, + premShow: false, + // 季度 + jShow: false, + prejShow: false, + // 年 + ysShow: false, + yxShow: false, + preyShow: false, + yShow: false, + // 默认 + dfvalue: 'currentWeek', + selectfn: function (begin, end) { + startTime = begin; + endTime = end; + page.search(); + } + }); + //查询 + $('#lr_search').on('click', function () { + var p = {}; + p.schoolId = $('#F_SchoolId').lrselectGet(); + p.ClassNo = $('#ClassNo').lrselectGet(); + p.EmpNo = $('#EmpNo').lrselectGet(); + page.search(p); + }); + // 按条件清空排课数据 + $('#emptyByCondition').on('click', function () { + learun.layerForm({ + id: 'EmptyByConditionForm', + title: '按条件清空排课数据', + url: top.$.rootUrl + '/EducationalAdministration/ArrangeLessonTerm/EmptyByConditionForm', + width: 600, + height: 400, + callBack: function (id) { + return top[id].acceptClick(refreshGirdData); + } + }); + }); + // 按条件同步排课数据 + $('#syncByCondition').on('click', function () { + learun.layerForm({ + id: 'SyncByConditionForm', + title: '按条件同步排课数据', + url: top.$.rootUrl + '/EducationalAdministration/ArrangeLessonTerm/SyncByConditionForm', + width: 600, + height: 400, + callBack: function (id) { + return top[id].acceptClick(refreshGirdData); + } + }); + }); + + //按条件重置基础数据同步状态 + $('#initByCondition').on('click', function () { + learun.layerForm({ + id: 'SyncByConditionForm', + title: '按条件重置基础数据同步状态', + url: top.$.rootUrl + '/EducationalAdministration/ArrangeLessonTerm/ClearByConditionForm', + width: 600, + height: 400, + callBack: function (id) { + return top[id].acceptClick(); + } + }); + }); + $('#lr_export').on('click', + function () { + window.open(window.origin+"/PersonnelManagement/TimeTable/PrintSchedule?" + Printdata.slice(0, Printdata.length-1)); + //console.log(Printdata, "data"); + }); + }, + bindSelect: function () { + //校区 + $('#F_SchoolId').lrDataSourceSelect({ + code: 'company', value: 'f_companyid', text: 'f_fullname', select: function (item) { + if (!!item) { + // 班级 + $('#ClassNo').lrselectRefresh({ + placeholder: "请选择班级", + allowSearch: true, + url: top.$.rootUrl + '/PersonnelManagement/TimeTable/GetClassData', + param: { schoolId: item.f_companyid }, + value: 'value', + text: 'text' + }); + // 教师 + $('#EmpNo').lrselectRefresh({ + placeholder: "请选择教师", + allowSearch: true, + url: top.$.rootUrl + '/PersonnelManagement/TimeTable/GetTeacherData', + param: { schoolId: item.f_companyid }, + value: 'value', + text: 'text' + }); + } else { + //班级 + $('#ClassNo').lrselectRefresh({ + placeholder: "请选择班级", + allowSearch: true, + url: top.$.rootUrl + '/PersonnelManagement/TimeTable/GetClassData', + param: { schoolId: "" }, + value: 'value', + text: 'text' + }); + //教师 + $('#EmpNo').lrselectRefresh({ + placeholder: "请选择教师", + allowSearch: true, + url: top.$.rootUrl + '/PersonnelManagement/TimeTable/GetTeacherData', + param: { schoolId: "" }, + value: 'value', + text: 'text' + }); + } + } + }); + //班级 + $('#ClassNo').lrselect({ + placeholder: "请选择班级", + allowSearch: true, + url: top.$.rootUrl + '/PersonnelManagement/TimeTable/GetClassData', + value: 'value', + text: 'text' + }); + //教师 + $('#EmpNo').lrselect({ + placeholder: "请选择教师", + allowSearch: true, + url: top.$.rootUrl + '/PersonnelManagement/TimeTable/GetTeacherData', + value: 'value', + text: 'text' + }); + }, + search: function (param) { + param = param || {}; + param.StartTime = startTime; + param.EndTime = endTime; + page.loadData(param); + } + }; + page.init(); +}; diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Content/images/StuRecruitmentBrochure.jpg b/Learun.Framework.Ultimate V7/Learun.Application.Web/Content/images/StuRecruitmentBrochure.jpg new file mode 100644 index 000000000..46b72076b Binary files /dev/null and b/Learun.Framework.Ultimate V7/Learun.Application.Web/Content/images/StuRecruitmentBrochure.jpg differ diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Content/js/PrintLesson/debug.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Content/js/PrintLesson/debug.js new file mode 100644 index 000000000..4b63bf91e --- /dev/null +++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Content/js/PrintLesson/debug.js @@ -0,0 +1,9359 @@ +/** @preserve + * jsPDF - PDF Document creation from JavaScript + * Version 1.0.272-git Built on 2014-09-29T15:09 + * CommitID d4770725ca + * + * Copyright (c) 2010-2014 James Hall, https://github.com/MrRio/jsPDF + * 2010 Aaron Spike, https://github.com/acspike + * 2012 Willow Systems Corporation, willow-systems.com + * 2012 Pablo Hess, https://github.com/pablohess + * 2012 Florian Jenett, https://github.com/fjenett + * 2013 Warren Weckesser, https://github.com/warrenweckesser + * 2013 Youssef Beddad, https://github.com/lifof + * 2013 Lee Driscoll, https://github.com/lsdriscoll + * 2013 Stefan Slonevskiy, https://github.com/stefslon + * 2013 Jeremy Morel, https://github.com/jmorel + * 2013 Christoph Hartmann, https://github.com/chris-rock + * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria + * 2014 James Makes, https://github.com/dollaruw + * 2014 Diego Casorran, https://github.com/diegocr + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Contributor(s): + * siefkenj, ahwolf, rickygu, Midnith, saintclair, eaparango, + * kim3er, mfo, alnorth, + */ + +/** + * Creates new jsPDF document object instance. + * + * @class + * @param orientation One of "portrait" or "landscape" (or shortcuts "p" (Default), "l") + * @param unit Measurement unit to be used when coordinates are specified. + * One of "pt" (points), "mm" (Default), "cm", "in" + * @param format One of 'pageFormats' as shown below, default: a4 + * @returns {jsPDF} + * @name jsPDF + */ +var jsPDF = (function(global) { + 'use strict'; + var pdfVersion = '1.3', + pageFormats = { // Size in pt of various paper formats + 'a0' : [2383.94, 3370.39], 'a1' : [1683.78, 2383.94], + 'a2' : [1190.55, 1683.78], 'a3' : [ 841.89, 1190.55], + 'a4' : [ 595.28, 841.89], 'a5' : [ 419.53, 595.28], + 'a6' : [ 297.64, 419.53], 'a7' : [ 209.76, 297.64], + 'a8' : [ 147.40, 209.76], 'a9' : [ 104.88, 147.40], + 'a10' : [ 73.70, 104.88], 'b0' : [2834.65, 4008.19], + 'b1' : [2004.09, 2834.65], 'b2' : [1417.32, 2004.09], + 'b3' : [1000.63, 1417.32], 'b4' : [ 708.66, 1000.63], + 'b5' : [ 498.90, 708.66], 'b6' : [ 354.33, 498.90], + 'b7' : [ 249.45, 354.33], 'b8' : [ 175.75, 249.45], + 'b9' : [ 124.72, 175.75], 'b10' : [ 87.87, 124.72], + 'c0' : [2599.37, 3676.54], 'c1' : [1836.85, 2599.37], + 'c2' : [1298.27, 1836.85], 'c3' : [ 918.43, 1298.27], + 'c4' : [ 649.13, 918.43], 'c5' : [ 459.21, 649.13], + 'c6' : [ 323.15, 459.21], 'c7' : [ 229.61, 323.15], + 'c8' : [ 161.57, 229.61], 'c9' : [ 113.39, 161.57], + 'c10' : [ 79.37, 113.39], 'dl' : [ 311.81, 623.62], + 'letter' : [612, 792], + 'government-letter' : [576, 756], + 'legal' : [612, 1008], + 'junior-legal' : [576, 360], + 'ledger' : [1224, 792], + 'tabloid' : [792, 1224], + 'credit-card' : [153, 243] + }; + + /** + * jsPDF's Internal PubSub Implementation. + * See mrrio.github.io/jsPDF/doc/symbols/PubSub.html + * Backward compatible rewritten on 2014 by + * Diego Casorran, https://github.com/diegocr + * + * @class + * @name PubSub + */ + function PubSub(context) { + var topics = {}; + + this.subscribe = function(topic, callback, once) { + if(typeof callback !== 'function') { + return false; + } + + if(!topics.hasOwnProperty(topic)) { + topics[topic] = {}; + } + + var id = Math.random().toString(35); + topics[topic][id] = [callback,!!once]; + + return id; + }; + + this.unsubscribe = function(token) { + for(var topic in topics) { + if(topics[topic][token]) { + delete topics[topic][token]; + return true; + } + } + return false; + }; + + this.publish = function(topic) { + if(topics.hasOwnProperty(topic)) { + var args = Array.prototype.slice.call(arguments, 1), idr = []; + + for(var id in topics[topic]) { + var sub = topics[topic][id]; + try { + sub[0].apply(context, args); + } catch(ex) { + if(global.console) { + console.error('jsPDF PubSub Error', ex.message, ex); + } + } + if(sub[1]) idr.push(id); + } + if(idr.length) idr.forEach(this.unsubscribe); + } + }; + } + + /** + * @constructor + * @private + */ + function jsPDF(orientation, unit, format, compressPdf) { + var options = {}; + + if (typeof orientation === 'object') { + options = orientation; + + orientation = options.orientation; + unit = options.unit || unit; + format = options.format || format; + compressPdf = options.compress || options.compressPdf || compressPdf; + } + + // Default options + unit = unit || 'mm'; + format = format || 'a4'; + orientation = ('' + (orientation || 'P')).toLowerCase(); + + var format_as_string = ('' + format).toLowerCase(), + compress = !!compressPdf && typeof Uint8Array === 'function', + textColor = options.textColor || '0 g', + drawColor = options.drawColor || '0 G', + activeFontSize = options.fontSize || 16, + lineHeightProportion = options.lineHeight || 1.15, + lineWidth = options.lineWidth || 0.200025, // 2mm + objectNumber = 2, // 'n' Current object number + outToPages = !1, // switches where out() prints. outToPages true = push to pages obj. outToPages false = doc builder content + offsets = [], // List of offsets. Activated and reset by buildDocument(). Pupulated by various calls buildDocument makes. + fonts = {}, // collection of font objects, where key is fontKey - a dynamically created label for a given font. + fontmap = {}, // mapping structure fontName > fontStyle > font key - performance layer. See addFont() + activeFontKey, // will be string representing the KEY of the font as combination of fontName + fontStyle + k, // Scale factor + tmp, + page = 0, + currentPage, + pages = [], + pagedim = {}, + content = [], + lineCapID = 0, + lineJoinID = 0, + content_length = 0, + pageWidth, + pageHeight, + pageMode, + zoomMode, + layoutMode, + documentProperties = { + 'title' : '', + 'subject' : '', + 'author' : '', + 'keywords' : '', + 'creator' : '' + }, + API = {}, + events = new PubSub(API), + + ///////////////////// + // Private functions + ///////////////////// + f2 = function(number) { + return number.toFixed(2); // Ie, %.2f + }, + f3 = function(number) { + return number.toFixed(3); // Ie, %.3f + }, + padd2 = function(number) { + return ('0' + parseInt(number)).slice(-2); + }, + out = function(string) { + if (outToPages) { + /* set by beginPage */ + pages[currentPage].push(string); + } else { + // +1 for '\n' that will be used to join 'content' + content_length += string.length + 1; + content.push(string); + } + }, + newObject = function() { + // Begin a new object + objectNumber++; + offsets[objectNumber] = content_length; + out(objectNumber + ' 0 obj'); + return objectNumber; + }, + putStream = function(str) { + out('stream'); + out(str); + out('endstream'); + }, + putPages = function() { + var n,p,arr,i,deflater,adler32,adler32cs,wPt,hPt; + + adler32cs = global.adler32cs || jsPDF.adler32cs; + if (compress && typeof adler32cs === 'undefined') { + compress = false; + } + + // outToPages = false as set in endDocument(). out() writes to content. + + for (n = 1; n <= page; n++) { + newObject(); + wPt = (pageWidth = pagedim[n].width) * k; + hPt = (pageHeight = pagedim[n].height) * k; + out('<>'); + out('endobj'); + + // Page content + p = pages[n].join('\n'); + newObject(); + if (compress) { + arr = []; + i = p.length; + while(i--) { + arr[i] = p.charCodeAt(i); + } + adler32 = adler32cs.from(p); + deflater = new Deflater(6); + deflater.append(new Uint8Array(arr)); + p = deflater.flush(); + arr = new Uint8Array(p.length + 6); + arr.set(new Uint8Array([120, 156])), + arr.set(p, 2); + arr.set(new Uint8Array([adler32 & 0xFF, (adler32 >> 8) & 0xFF, (adler32 >> 16) & 0xFF, (adler32 >> 24) & 0xFF]), p.length+2); + p = String.fromCharCode.apply(null, arr); + out('<>'); + } else { + out('<>'); + } + putStream(p); + out('endobj'); + } + offsets[1] = content_length; + out('1 0 obj'); + out('<>'); + out('endobj'); + }, + putFont = function(font) { + font.objectNumber = newObject(); + out('<>'); + out('endobj'); + }, + putFonts = function() { + for (var fontKey in fonts) { + if (fonts.hasOwnProperty(fontKey)) { + putFont(fonts[fontKey]); + } + } + }, + putXobjectDict = function() { + // Loop through images, or other data objects + events.publish('putXobjectDict'); + }, + putResourceDictionary = function() { + out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'); + out('/Font <<'); + + // Do this for each font, the '1' bit is the index of the font + for (var fontKey in fonts) { + if (fonts.hasOwnProperty(fontKey)) { + out('/' + fontKey + ' ' + fonts[fontKey].objectNumber + ' 0 R'); + } + } + out('>>'); + out('/XObject <<'); + putXobjectDict(); + out('>>'); + }, + putResources = function() { + putFonts(); + events.publish('putResources'); + // Resource dictionary + offsets[2] = content_length; + out('2 0 obj'); + out('<<'); + putResourceDictionary(); + out('>>'); + out('endobj'); + events.publish('postPutResources'); + }, + addToFontDictionary = function(fontKey, fontName, fontStyle) { + // this is mapping structure for quick font key lookup. + // returns the KEY of the font (ex: "F1") for a given + // pair of font name and type (ex: "Arial". "Italic") + if (!fontmap.hasOwnProperty(fontName)) { + fontmap[fontName] = {}; + } + fontmap[fontName][fontStyle] = fontKey; + }, + /** + * FontObject describes a particular font as member of an instnace of jsPDF + * + * It's a collection of properties like 'id' (to be used in PDF stream), + * 'fontName' (font's family name), 'fontStyle' (font's style variant label) + * + * @class + * @public + * @property id {String} PDF-document-instance-specific label assinged to the font. + * @property PostScriptName {String} PDF specification full name for the font + * @property encoding {Object} Encoding_name-to-Font_metrics_object mapping. + * @name FontObject + */ + addFont = function(PostScriptName, fontName, fontStyle, encoding) { + var fontKey = 'F' + (Object.keys(fonts).length + 1).toString(10), + // This is FontObject + font = fonts[fontKey] = { + 'id' : fontKey, + 'PostScriptName' : PostScriptName, + 'fontName' : fontName, + 'fontStyle' : fontStyle, + 'encoding' : encoding, + 'metadata' : {} + }; + addToFontDictionary(fontKey, fontName, fontStyle); + events.publish('addFont', font); + + return fontKey; + }, + addFonts = function() { + + var HELVETICA = "helvetica", + TIMES = "times", + COURIER = "courier", + NORMAL = "normal", + BOLD = "bold", + ITALIC = "italic", + BOLD_ITALIC = "bolditalic", + encoding = 'StandardEncoding', + standardFonts = [ + ['Helvetica', HELVETICA, NORMAL], + ['Helvetica-Bold', HELVETICA, BOLD], + ['Helvetica-Oblique', HELVETICA, ITALIC], + ['Helvetica-BoldOblique', HELVETICA, BOLD_ITALIC], + ['Courier', COURIER, NORMAL], + ['Courier-Bold', COURIER, BOLD], + ['Courier-Oblique', COURIER, ITALIC], + ['Courier-BoldOblique', COURIER, BOLD_ITALIC], + ['Times-Roman', TIMES, NORMAL], + ['Times-Bold', TIMES, BOLD], + ['Times-Italic', TIMES, ITALIC], + ['Times-BoldItalic', TIMES, BOLD_ITALIC] + ]; + + for (var i = 0, l = standardFonts.length; i < l; i++) { + var fontKey = addFont( + standardFonts[i][0], + standardFonts[i][1], + standardFonts[i][2], + encoding); + + // adding aliases for standard fonts, this time matching the capitalization + var parts = standardFonts[i][0].split('-'); + addToFontDictionary(fontKey, parts[0], parts[1] || ''); + } + events.publish('addFonts', { fonts : fonts, dictionary : fontmap }); + }, + SAFE = function __safeCall(fn) { + fn.foo = function __safeCallWrapper() { + try { + return fn.apply(this, arguments); + } catch (e) { + var stack = e.stack || ''; + if(~stack.indexOf(' at ')) stack = stack.split(" at ")[1]; + var m = "Error in function " + stack.split("\n")[0].split('<')[0] + ": " + e.message; + if(global.console) { + global.console.error(m, e); + if(global.alert) alert(m); + } else { + throw new Error(m); + } + } + }; + fn.foo.bar = fn; + return fn.foo; + }, + to8bitStream = function(text, flags) { + /** + * PDF 1.3 spec: + * "For text strings encoded in Unicode, the first two bytes must be 254 followed by + * 255, representing the Unicode byte order marker, U+FEFF. (This sequence conflicts + * with the PDFDocEncoding character sequence thorn ydieresis, which is unlikely + * to be a meaningful beginning of a word or phrase.) The remainder of the + * string consists of Unicode character codes, according to the UTF-16 encoding + * specified in the Unicode standard, version 2.0. Commonly used Unicode values + * are represented as 2 bytes per character, with the high-order byte appearing first + * in the string." + * + * In other words, if there are chars in a string with char code above 255, we + * recode the string to UCS2 BE - string doubles in length and BOM is prepended. + * + * HOWEVER! + * Actual *content* (body) text (as opposed to strings used in document properties etc) + * does NOT expect BOM. There, it is treated as a literal GID (Glyph ID) + * + * Because of Adobe's focus on "you subset your fonts!" you are not supposed to have + * a font that maps directly Unicode (UCS2 / UTF16BE) code to font GID, but you could + * fudge it with "Identity-H" encoding and custom CIDtoGID map that mimics Unicode + * code page. There, however, all characters in the stream are treated as GIDs, + * including BOM, which is the reason we need to skip BOM in content text (i.e. that + * that is tied to a font). + * + * To signal this "special" PDFEscape / to8bitStream handling mode, + * API.text() function sets (unless you overwrite it with manual values + * given to API.text(.., flags) ) + * flags.autoencode = true + * flags.noBOM = true + * + * =================================================================================== + * `flags` properties relied upon: + * .sourceEncoding = string with encoding label. + * "Unicode" by default. = encoding of the incoming text. + * pass some non-existing encoding name + * (ex: 'Do not touch my strings! I know what I am doing.') + * to make encoding code skip the encoding step. + * .outputEncoding = Either valid PDF encoding name + * (must be supported by jsPDF font metrics, otherwise no encoding) + * or a JS object, where key = sourceCharCode, value = outputCharCode + * missing keys will be treated as: sourceCharCode === outputCharCode + * .noBOM + * See comment higher above for explanation for why this is important + * .autoencode + * See comment higher above for explanation for why this is important + */ + + var i,l,sourceEncoding,encodingBlock,outputEncoding,newtext,isUnicode,ch,bch; + + flags = flags || {}; + sourceEncoding = flags.sourceEncoding || 'Unicode'; + outputEncoding = flags.outputEncoding; + + // This 'encoding' section relies on font metrics format + // attached to font objects by, among others, + // "Willow Systems' standard_font_metrics plugin" + // see jspdf.plugin.standard_font_metrics.js for format + // of the font.metadata.encoding Object. + // It should be something like + // .encoding = {'codePages':['WinANSI....'], 'WinANSI...':{code:code, ...}} + // .widths = {0:width, code:width, ..., 'fof':divisor} + // .kerning = {code:{previous_char_code:shift, ..., 'fof':-divisor},...} + if ((flags.autoencode || outputEncoding) && + fonts[activeFontKey].metadata && + fonts[activeFontKey].metadata[sourceEncoding] && + fonts[activeFontKey].metadata[sourceEncoding].encoding) { + encodingBlock = fonts[activeFontKey].metadata[sourceEncoding].encoding; + + // each font has default encoding. Some have it clearly defined. + if (!outputEncoding && fonts[activeFontKey].encoding) { + outputEncoding = fonts[activeFontKey].encoding; + } + + // Hmmm, the above did not work? Let's try again, in different place. + if (!outputEncoding && encodingBlock.codePages) { + outputEncoding = encodingBlock.codePages[0]; // let's say, first one is the default + } + + if (typeof outputEncoding === 'string') { + outputEncoding = encodingBlock[outputEncoding]; + } + // we want output encoding to be a JS Object, where + // key = sourceEncoding's character code and + // value = outputEncoding's character code. + if (outputEncoding) { + isUnicode = false; + newtext = []; + for (i = 0, l = text.length; i < l; i++) { + ch = outputEncoding[text.charCodeAt(i)]; + if (ch) { + newtext.push( + String.fromCharCode(ch)); + } else { + newtext.push( + text[i]); + } + + // since we are looping over chars anyway, might as well + // check for residual unicodeness + if (newtext[i].charCodeAt(0) >> 8) { + /* more than 255 */ + isUnicode = true; + } + } + text = newtext.join(''); + } + } + + i = text.length; + // isUnicode may be set to false above. Hence the triple-equal to undefined + while (isUnicode === undefined && i !== 0) { + if (text.charCodeAt(i - 1) >> 8) { + /* more than 255 */ + isUnicode = true; + } + i--; + } + if (!isUnicode) { + return text; + } + + newtext = flags.noBOM ? [] : [254, 255]; + for (i = 0, l = text.length; i < l; i++) { + ch = text.charCodeAt(i); + bch = ch >> 8; // divide by 256 + if (bch >> 8) { + /* something left after dividing by 256 second time */ + throw new Error("Character at position " + i + " of string '" + + text + "' exceeds 16bits. Cannot be encoded into UCS-2 BE"); + } + newtext.push(bch); + newtext.push(ch - (bch << 8)); + } + return String.fromCharCode.apply(undefined, newtext); + }, + pdfEscape = function(text, flags) { + /** + * Replace '/', '(', and ')' with pdf-safe versions + * + * Doing to8bitStream does NOT make this PDF display unicode text. For that + * we also need to reference a unicode font and embed it - royal pain in the rear. + * + * There is still a benefit to to8bitStream - PDF simply cannot handle 16bit chars, + * which JavaScript Strings are happy to provide. So, while we still cannot display + * 2-byte characters property, at least CONDITIONALLY converting (entire string containing) + * 16bit chars to (USC-2-BE) 2-bytes per char + BOM streams we ensure that entire PDF + * is still parseable. + * This will allow immediate support for unicode in document properties strings. + */ + return to8bitStream(text, flags).replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)'); + }, + putInfo = function() { + out('/Producer (jsPDF ' + jsPDF.version + ')'); + for(var key in documentProperties) { + if(documentProperties.hasOwnProperty(key) && documentProperties[key]) { + out('/'+key.substr(0,1).toUpperCase() + key.substr(1) + +' (' + pdfEscape(documentProperties[key]) + ')'); + } + } + var created = new Date(), + tzoffset = created.getTimezoneOffset(), + tzsign = tzoffset < 0 ? '+' : '-', + tzhour = Math.floor(Math.abs(tzoffset / 60)), + tzmin = Math.abs(tzoffset % 60), + tzstr = [tzsign, padd2(tzhour), "'", padd2(tzmin), "'"].join(''); + out(['/CreationDate (D:', + created.getFullYear(), + padd2(created.getMonth() + 1), + padd2(created.getDate()), + padd2(created.getHours()), + padd2(created.getMinutes()), + padd2(created.getSeconds()), tzstr, ')'].join('')); + }, + putCatalog = function() { + out('/Type /Catalog'); + out('/Pages 1 0 R'); + // PDF13ref Section 7.2.1 + if (!zoomMode) zoomMode = 'fullwidth'; + switch(zoomMode) { + case 'fullwidth' : out('/OpenAction [3 0 R /FitH null]'); break; + case 'fullheight' : out('/OpenAction [3 0 R /FitV null]'); break; + case 'fullpage' : out('/OpenAction [3 0 R /Fit]'); break; + case 'original' : out('/OpenAction [3 0 R /XYZ null null 1]'); break; + default: + var pcn = '' + zoomMode; + if (pcn.substr(pcn.length-1) === '%') + zoomMode = parseInt(zoomMode) / 100; + if (typeof zoomMode === 'number') { + out('/OpenAction [3 0 R /XYZ null null '+f2(zoomMode)+']'); + } + } + if (!layoutMode) layoutMode = 'continuous'; + switch(layoutMode) { + case 'continuous' : out('/PageLayout /OneColumn'); break; + case 'single' : out('/PageLayout /SinglePage'); break; + case 'two': + case 'twoleft' : out('/PageLayout /TwoColumnLeft'); break; + case 'tworight' : out('/PageLayout /TwoColumnRight'); break; + } + if (pageMode) { + /** + * A name object specifying how the document should be displayed when opened: + * UseNone : Neither document outline nor thumbnail images visible -- DEFAULT + * UseOutlines : Document outline visible + * UseThumbs : Thumbnail images visible + * FullScreen : Full-screen mode, with no menu bar, window controls, or any other window visible + */ + out('/PageMode /' + pageMode); + } + events.publish('putCatalog'); + }, + putTrailer = function() { + out('/Size ' + (objectNumber + 1)); + out('/Root ' + objectNumber + ' 0 R'); + out('/Info ' + (objectNumber - 1) + ' 0 R'); + }, + beginPage = function(width,height) { + // Dimensions are stored as user units and converted to points on output + var orientation = typeof height === 'string' && height.toLowerCase(); + if (typeof width === 'string') { + var format = width.toLowerCase(); + if (pageFormats.hasOwnProperty(format)) { + width = pageFormats[format][0] / k; + height = pageFormats[format][1] / k; + } + } + if (Array.isArray(width)) { + height = width[1]; + width = width[0]; + } + if (orientation) { + switch(orientation.substr(0,1)) { + case 'l': if (height > width ) orientation = 's'; break; + case 'p': if (width > height ) orientation = 's'; break; + } + if (orientation === 's') { tmp = width; width = height; height = tmp; } + } + outToPages = true; + pages[++page] = []; + pagedim[page] = { + width : Number(width) || pageWidth, + height : Number(height) || pageHeight + }; + _setPage(page); + }, + _addPage = function() { + beginPage.apply(this, arguments); + // Set line width + out(f2(lineWidth * k) + ' w'); + // Set draw color + out(drawColor); + // resurrecting non-default line caps, joins + if (lineCapID !== 0) { + out(lineCapID + ' J'); + } + if (lineJoinID !== 0) { + out(lineJoinID + ' j'); + } + events.publish('addPage', { pageNumber : page }); + }, + _setPage = function(n) { + if (n > 0 && n <= page) { + currentPage = n; + pageWidth = pagedim[n].width; + pageHeight = pagedim[n].height; + } + }, + /** + * Returns a document-specific font key - a label assigned to a + * font name + font type combination at the time the font was added + * to the font inventory. + * + * Font key is used as label for the desired font for a block of text + * to be added to the PDF document stream. + * @private + * @function + * @param fontName {String} can be undefined on "falthy" to indicate "use current" + * @param fontStyle {String} can be undefined on "falthy" to indicate "use current" + * @returns {String} Font key. + */ + getFont = function(fontName, fontStyle) { + var key; + + fontName = fontName !== undefined ? fontName : fonts[activeFontKey].fontName; + fontStyle = fontStyle !== undefined ? fontStyle : fonts[activeFontKey].fontStyle; + + try { + // get a string like 'F3' - the KEY corresponding tot he font + type combination. + key = fontmap[fontName][fontStyle]; + } catch (e) {} + + if (!key) { + throw new Error("Unable to look up font label for font '" + fontName + "', '" + + fontStyle + "'. Refer to getFontList() for available fonts."); + } + return key; + }, + buildDocument = function() { + + outToPages = false; // switches out() to content + objectNumber = 2; + content = []; + offsets = []; + + // putHeader() + out('%PDF-' + pdfVersion); + + putPages(); + + putResources(); + + // Info + newObject(); + out('<<'); + putInfo(); + out('>>'); + out('endobj'); + + // Catalog + newObject(); + out('<<'); + putCatalog(); + out('>>'); + out('endobj'); + + // Cross-ref + var o = content_length, i, p = "0000000000"; + out('xref'); + out('0 ' + (objectNumber + 1)); + out(p+' 65535 f '); + for (i = 1; i <= objectNumber; i++) { + out((p + offsets[i]).slice(-10) + ' 00000 n '); + } + // Trailer + out('trailer'); + out('<<'); + putTrailer(); + out('>>'); + out('startxref'); + out(o); + out('%%EOF'); + + outToPages = true; + + return content.join('\n'); + }, + getStyle = function(style) { + // see path-painting operators in PDF spec + var op = 'S'; // stroke + if (style === 'F') { + op = 'f'; // fill + } else if (style === 'FD' || style === 'DF') { + op = 'B'; // both + } else if (style === 'f' || style === 'f*' || style === 'B' || style === 'B*') { + /* + Allow direct use of these PDF path-painting operators: + - f fill using nonzero winding number rule + - f* fill using even-odd rule + - B fill then stroke with fill using non-zero winding number rule + - B* fill then stroke with fill using even-odd rule + */ + op = style; + } + return op; + }, + getArrayBuffer = function() { + var data = buildDocument(), len = data.length, + ab = new ArrayBuffer(len), u8 = new Uint8Array(ab); + + while(len--) u8[len] = data.charCodeAt(len); + return ab; + }, + getBlob = function() { + return new Blob([getArrayBuffer()], { type : "application/pdf" }); + }, + /** + * Generates the PDF document. + * + * If `type` argument is undefined, output is raw body of resulting PDF returned as a string. + * + * @param {String} type A string identifying one of the possible output types. + * @param {Object} options An object providing some additional signalling to PDF generator. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name output + */ + output = SAFE(function(type, options) { + var datauri = ('' + type).substr(0,6) === 'dataur' + ? 'data:application/pdf;base64,'+btoa(buildDocument()):0; + + switch (type) { + case undefined: + return buildDocument(); + case 'save': + if (navigator.getUserMedia) { + if (global.URL === undefined + || global.URL.createObjectURL === undefined) { + return API.output('dataurlnewwindow'); + } + } + saveAs(getBlob(), options); + if(typeof saveAs.unload === 'function') { + if(global.setTimeout) { + setTimeout(saveAs.unload,911); + } + } + break; + case 'arraybuffer': + return getArrayBuffer(); + case 'blob': + return getBlob(); + case 'bloburi': + case 'bloburl': + // User is responsible of calling revokeObjectURL + return global.URL && global.URL.createObjectURL(getBlob()) || void 0; + case 'datauristring': + case 'dataurlstring': + return datauri; + case 'dataurlnewwindow': + var nW = global.open(datauri); + if (nW || typeof safari === "undefined") return nW; + /* pass through */ + case 'datauri': + case 'dataurl': + return global.document.location.href = datauri; + default: + throw new Error('Output type "' + type + '" is not supported.'); + } + // @TODO: Add different output options + }); + + switch (unit) { + case 'pt': k = 1; break; + case 'mm': k = 72 / 25.4; break; + case 'cm': k = 72 / 2.54; break; + case 'in': k = 72; break; + case 'px': k = 96 / 72; break; + case 'pc': k = 12; break; + case 'em': k = 12; break; + case 'ex': k = 6; break; + default: + throw ('Invalid unit: ' + unit); + } + + //--------------------------------------- + // Public API + + /** + * Object exposing internal API to plugins + * @public + */ + API.internal = { + 'pdfEscape' : pdfEscape, + 'getStyle' : getStyle, + /** + * Returns {FontObject} describing a particular font. + * @public + * @function + * @param fontName {String} (Optional) Font's family name + * @param fontStyle {String} (Optional) Font's style variation name (Example:"Italic") + * @returns {FontObject} + */ + 'getFont' : function() { + return fonts[getFont.apply(API, arguments)]; + }, + 'getFontSize' : function() { + return activeFontSize; + }, + 'getLineHeight' : function() { + return activeFontSize * lineHeightProportion; + }, + 'write' : function(string1 /*, string2, string3, etc */) { + out(arguments.length === 1 ? string1 : Array.prototype.join.call(arguments, ' ')); + }, + 'getCoordinateString' : function(value) { + return f2(value * k); + }, + 'getVerticalCoordinateString' : function(value) { + return f2((pageHeight - value) * k); + }, + 'collections' : {}, + 'newObject' : newObject, + 'putStream' : putStream, + 'events' : events, + // ratio that you use in multiplication of a given "size" number to arrive to 'point' + // units of measurement. + // scaleFactor is set at initialization of the document and calculated against the stated + // default measurement units for the document. + // If default is "mm", k is the number that will turn number in 'mm' into 'points' number. + // through multiplication. + 'scaleFactor' : k, + 'pageSize' : { + get width() { + return pageWidth + }, + get height() { + return pageHeight + } + }, + 'output' : function(type, options) { + return output(type, options); + }, + 'getNumberOfPages' : function() { + return pages.length - 1; + }, + 'pages' : pages + }; + + /** + * Adds (and transfers the focus to) new page to the PDF document. + * @function + * @returns {jsPDF} + * + * @methodOf jsPDF# + * @name addPage + */ + API.addPage = function() { + _addPage.apply(this, arguments); + return this; + }; + API.setPage = function() { + _setPage.apply(this, arguments); + return this; + }; + API.setDisplayMode = function(zoom, layout, pmode) { + zoomMode = zoom; + layoutMode = layout; + pageMode = pmode; + return this; + }, + + /** + * Adds text to page. Supports adding multiline text when 'text' argument is an Array of Strings. + * + * @function + * @param {String|Array} text String or array of strings to be added to the page. Each line is shifted one line down per font, spacing settings declared before this call. + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Object} flags Collection of settings signalling how the text must be encoded. Defaults are sane. If you think you want to pass some flags, you likely can read the source. + * @returns {jsPDF} + * @methodOf jsPDF# + * @name text + */ + API.text = function(text, x, y, flags, angle) { + /** + * Inserts something like this into PDF + * BT + * /F1 16 Tf % Font name + size + * 16 TL % How many units down for next line in multiline text + * 0 g % color + * 28.35 813.54 Td % position + * (line one) Tj + * T* (line two) Tj + * T* (line three) Tj + * ET + */ + function ESC(s) { + s = s.split("\t").join(Array(options.TabLen||9).join(" ")); + return pdfEscape(s, flags); + } + + // Pre-August-2012 the order of arguments was function(x, y, text, flags) + // in effort to make all calls have similar signature like + // function(data, coordinates... , miscellaneous) + // this method had its args flipped. + // code below allows backward compatibility with old arg order. + if (typeof text === 'number') { + tmp = y; + y = x; + x = text; + text = tmp; + } + + // If there are any newlines in text, we assume + // the user wanted to print multiple lines, so break the + // text up into an array. If the text is already an array, + // we assume the user knows what they are doing. + if (typeof text === 'string' && text.match(/[\n\r]/)) { + text = text.split(/\r\n|\r|\n/g); + } + if (typeof flags === 'number') { + angle = flags; + flags = null; + } + var xtra = '',mode = 'Td', todo; + if (angle) { + angle *= (Math.PI / 180); + var c = Math.cos(angle), + s = Math.sin(angle); + xtra = [f2(c), f2(s), f2(s * -1), f2(c), ''].join(" "); + mode = 'Tm'; + } + flags = flags || {}; + if (!('noBOM' in flags)) + flags.noBOM = true; + if (!('autoencode' in flags)) + flags.autoencode = true; + + if (typeof text === 'string') { + text = ESC(text); + } else if (text instanceof Array) { + // we don't want to destroy original text array, so cloning it + var sa = text.concat(), da = [], len = sa.length; + // we do array.join('text that must not be PDFescaped") + // thus, pdfEscape each component separately + while (len--) { + da.push(ESC(sa.shift())); + } + var linesLeft = Math.ceil((pageHeight - y) * k / (activeFontSize * lineHeightProportion)); + if (0 <= linesLeft && linesLeft < da.length + 1) { + todo = da.splice(linesLeft-1); + } + text = da.join(") Tj\nT* ("); + } else { + throw new Error('Type of text must be string or Array. "' + text + '" is not recognized.'); + } + // Using "'" ("go next line and render text" mark) would save space but would complicate our rendering code, templates + + // BT .. ET does NOT have default settings for Tf. You must state that explicitely every time for BT .. ET + // if you want text transformation matrix (+ multiline) to work reliably (which reads sizes of things from font declarations) + // Thus, there is NO useful, *reliable* concept of "default" font for a page. + // The fact that "default" (reuse font used before) font worked before in basic cases is an accident + // - readers dealing smartly with brokenness of jsPDF's markup. + out( + 'BT\n/' + + activeFontKey + ' ' + activeFontSize + ' Tf\n' + // font face, style, size + (activeFontSize * lineHeightProportion) + ' TL\n' + // line spacing + textColor + + '\n' + xtra + f2(x * k) + ' ' + f2((pageHeight - y) * k) + ' ' + mode + '\n(' + + text + + ') Tj\nET'); + + if (todo) { + this.addPage(); + this.text( todo, x, activeFontSize * 1.7 / k); + } + + return this; + }; + + API.lstext = function(text, x, y, spacing) { + for (var i = 0, len = text.length ; i < len; i++, x += spacing) this.text(text[i], x, y); + }; + + API.line = function(x1, y1, x2, y2) { + return this.lines([[x2 - x1, y2 - y1]], x1, y1); + }; + + API.clip = function() { + // By patrick-roberts, github.com/MrRio/jsPDF/issues/328 + // Call .clip() after calling .rect() with a style argument of null + out('W') // clip + out('S') // stroke path; necessary for clip to work + }; + + /** + * Adds series of curves (straight lines or cubic bezier curves) to canvas, starting at `x`, `y` coordinates. + * All data points in `lines` are relative to last line origin. + * `x`, `y` become x1,y1 for first line / curve in the set. + * For lines you only need to specify [x2, y2] - (ending point) vector against x1, y1 starting point. + * For bezier curves you need to specify [x2,y2,x3,y3,x4,y4] - vectors to control points 1, 2, ending point. All vectors are against the start of the curve - x1,y1. + * + * @example .lines([[2,2],[-2,2],[1,1,2,2,3,3],[2,1]], 212,110, 10) // line, line, bezier curve, line + * @param {Array} lines Array of *vector* shifts as pairs (lines) or sextets (cubic bezier curves). + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} scale (Defaults to [1.0,1.0]) x,y Scaling factor for all vectors. Elements can be any floating number Sub-one makes drawing smaller. Over-one grows the drawing. Negative flips the direction. + * @param {String} style A string specifying the painting style or null. Valid styles include: 'S' [default] - stroke, 'F' - fill, and 'DF' (or 'FD') - fill then stroke. A null value postpones setting the style so that a shape may be composed using multiple method calls. The last drawing method call used to define the shape should not have a null style argument. + * @param {Boolean} closed If true, the path is closed with a straight line from the end of the last curve to the starting point. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name lines + */ + API.lines = function(lines, x, y, scale, style, closed) { + var scalex,scaley,i,l,leg,x2,y2,x3,y3,x4,y4; + + // Pre-August-2012 the order of arguments was function(x, y, lines, scale, style) + // in effort to make all calls have similar signature like + // function(content, coordinateX, coordinateY , miscellaneous) + // this method had its args flipped. + // code below allows backward compatibility with old arg order. + if (typeof lines === 'number') { + tmp = y; + y = x; + x = lines; + lines = tmp; + } + + scale = scale || [1, 1]; + + // starting point + out(f3(x * k) + ' ' + f3((pageHeight - y) * k) + ' m '); + + scalex = scale[0]; + scaley = scale[1]; + l = lines.length; + //, x2, y2 // bezier only. In page default measurement "units", *after* scaling + //, x3, y3 // bezier only. In page default measurement "units", *after* scaling + // ending point for all, lines and bezier. . In page default measurement "units", *after* scaling + x4 = x; // last / ending point = starting point for first item. + y4 = y; // last / ending point = starting point for first item. + + for (i = 0; i < l; i++) { + leg = lines[i]; + if (leg.length === 2) { + // simple line + x4 = leg[0] * scalex + x4; // here last x4 was prior ending point + y4 = leg[1] * scaley + y4; // here last y4 was prior ending point + out(f3(x4 * k) + ' ' + f3((pageHeight - y4) * k) + ' l'); + } else { + // bezier curve + x2 = leg[0] * scalex + x4; // here last x4 is prior ending point + y2 = leg[1] * scaley + y4; // here last y4 is prior ending point + x3 = leg[2] * scalex + x4; // here last x4 is prior ending point + y3 = leg[3] * scaley + y4; // here last y4 is prior ending point + x4 = leg[4] * scalex + x4; // here last x4 was prior ending point + y4 = leg[5] * scaley + y4; // here last y4 was prior ending point + out( + f3(x2 * k) + ' ' + + f3((pageHeight - y2) * k) + ' ' + + f3(x3 * k) + ' ' + + f3((pageHeight - y3) * k) + ' ' + + f3(x4 * k) + ' ' + + f3((pageHeight - y4) * k) + ' c'); + } + } + + if (closed) { + out(' h'); + } + + // stroking / filling / both the path + if (style !== null) { + out(getStyle(style)); + } + return this; + }; + + /** + * Adds a rectangle to PDF + * + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} w Width (in units declared at inception of PDF document) + * @param {Number} h Height (in units declared at inception of PDF document) + * @param {String} style A string specifying the painting style or null. Valid styles include: 'S' [default] - stroke, 'F' - fill, and 'DF' (or 'FD') - fill then stroke. A null value postpones setting the style so that a shape may be composed using multiple method calls. The last drawing method call used to define the shape should not have a null style argument. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name rect + */ + API.rect = function(x, y, w, h, style) { + var op = getStyle(style); + out([ + f2(x * k), + f2((pageHeight - y) * k), + f2(w * k), + f2(-h * k), + 're' + ].join(' ')); + + if (style !== null) { + out(getStyle(style)); + } + + return this; + }; + + /** + * Adds a triangle to PDF + * + * @param {Number} x1 Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y1 Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} x2 Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y2 Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} x3 Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y3 Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {String} style A string specifying the painting style or null. Valid styles include: 'S' [default] - stroke, 'F' - fill, and 'DF' (or 'FD') - fill then stroke. A null value postpones setting the style so that a shape may be composed using multiple method calls. The last drawing method call used to define the shape should not have a null style argument. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name triangle + */ + API.triangle = function(x1, y1, x2, y2, x3, y3, style) { + this.lines( + [ + [x2 - x1, y2 - y1], // vector to point 2 + [x3 - x2, y3 - y2], // vector to point 3 + [x1 - x3, y1 - y3]// closing vector back to point 1 + ], + x1, + y1, // start of path + [1, 1], + style, + true); + return this; + }; + + /** + * Adds a rectangle with rounded corners to PDF + * + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} w Width (in units declared at inception of PDF document) + * @param {Number} h Height (in units declared at inception of PDF document) + * @param {Number} rx Radius along x axis (in units declared at inception of PDF document) + * @param {Number} rx Radius along y axis (in units declared at inception of PDF document) + * @param {String} style A string specifying the painting style or null. Valid styles include: 'S' [default] - stroke, 'F' - fill, and 'DF' (or 'FD') - fill then stroke. A null value postpones setting the style so that a shape may be composed using multiple method calls. The last drawing method call used to define the shape should not have a null style argument. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name roundedRect + */ + API.roundedRect = function(x, y, w, h, rx, ry, style) { + var MyArc = 4 / 3 * (Math.SQRT2 - 1); + this.lines( + [ + [(w - 2 * rx), 0], + [(rx * MyArc), 0, rx, ry - (ry * MyArc), rx, ry], + [0, (h - 2 * ry)], + [0, (ry * MyArc), - (rx * MyArc), ry, -rx, ry], + [(-w + 2 * rx), 0], + [ - (rx * MyArc), 0, -rx, - (ry * MyArc), -rx, -ry], + [0, (-h + 2 * ry)], + [0, - (ry * MyArc), (rx * MyArc), -ry, rx, -ry] + ], + x + rx, + y, // start of path + [1, 1], + style); + return this; + }; + + /** + * Adds an ellipse to PDF + * + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} rx Radius along x axis (in units declared at inception of PDF document) + * @param {Number} rx Radius along y axis (in units declared at inception of PDF document) + * @param {String} style A string specifying the painting style or null. Valid styles include: 'S' [default] - stroke, 'F' - fill, and 'DF' (or 'FD') - fill then stroke. A null value postpones setting the style so that a shape may be composed using multiple method calls. The last drawing method call used to define the shape should not have a null style argument. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name ellipse + */ + API.ellipse = function(x, y, rx, ry, style) { + var lx = 4 / 3 * (Math.SQRT2 - 1) * rx, + ly = 4 / 3 * (Math.SQRT2 - 1) * ry; + + out([ + f2((x + rx) * k), + f2((pageHeight - y) * k), + 'm', + f2((x + rx) * k), + f2((pageHeight - (y - ly)) * k), + f2((x + lx) * k), + f2((pageHeight - (y - ry)) * k), + f2(x * k), + f2((pageHeight - (y - ry)) * k), + 'c' + ].join(' ')); + out([ + f2((x - lx) * k), + f2((pageHeight - (y - ry)) * k), + f2((x - rx) * k), + f2((pageHeight - (y - ly)) * k), + f2((x - rx) * k), + f2((pageHeight - y) * k), + 'c' + ].join(' ')); + out([ + f2((x - rx) * k), + f2((pageHeight - (y + ly)) * k), + f2((x - lx) * k), + f2((pageHeight - (y + ry)) * k), + f2(x * k), + f2((pageHeight - (y + ry)) * k), + 'c' + ].join(' ')); + out([ + f2((x + lx) * k), + f2((pageHeight - (y + ry)) * k), + f2((x + rx) * k), + f2((pageHeight - (y + ly)) * k), + f2((x + rx) * k), + f2((pageHeight - y) * k), + 'c' + ].join(' ')); + + if (style !== null) { + out(getStyle(style)); + } + + return this; + }; + + /** + * Adds an circle to PDF + * + * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page + * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page + * @param {Number} r Radius (in units declared at inception of PDF document) + * @param {String} style A string specifying the painting style or null. Valid styles include: 'S' [default] - stroke, 'F' - fill, and 'DF' (or 'FD') - fill then stroke. A null value postpones setting the style so that a shape may be composed using multiple method calls. The last drawing method call used to define the shape should not have a null style argument. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name circle + */ + API.circle = function(x, y, r, style) { + return this.ellipse(x, y, r, r, style); + }; + + /** + * Adds a properties to the PDF document + * + * @param {Object} A property_name-to-property_value object structure. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setProperties + */ + API.setProperties = function(properties) { + // copying only those properties we can render. + for (var property in documentProperties) { + if (documentProperties.hasOwnProperty(property) && properties[property]) { + documentProperties[property] = properties[property]; + } + } + return this; + }; + + /** + * Sets font size for upcoming text elements. + * + * @param {Number} size Font size in points. + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setFontSize + */ + API.setFontSize = function(size) { + activeFontSize = size; + return this; + }; + + /** + * Sets text font face, variant for upcoming text elements. + * See output of jsPDF.getFontList() for possible font names, styles. + * + * @param {String} fontName Font name or family. Example: "times" + * @param {String} fontStyle Font style or variant. Example: "italic" + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setFont + */ + API.setFont = function(fontName, fontStyle) { + activeFontKey = getFont(fontName, fontStyle); + // if font is not found, the above line blows up and we never go further + return this; + }; + + /** + * Switches font style or variant for upcoming text elements, + * while keeping the font face or family same. + * See output of jsPDF.getFontList() for possible font names, styles. + * + * @param {String} style Font style or variant. Example: "italic" + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setFontStyle + */ + API.setFontStyle = API.setFontType = function(style) { + activeFontKey = getFont(undefined, style); + // if font is not found, the above line blows up and we never go further + return this; + }; + + /** + * Returns an object - a tree of fontName to fontStyle relationships available to + * active PDF document. + * + * @public + * @function + * @returns {Object} Like {'times':['normal', 'italic', ... ], 'arial':['normal', 'bold', ... ], ... } + * @methodOf jsPDF# + * @name getFontList + */ + API.getFontList = function() { + // TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added. + var list = {},fontName,fontStyle,tmp; + + for (fontName in fontmap) { + if (fontmap.hasOwnProperty(fontName)) { + list[fontName] = tmp = []; + for (fontStyle in fontmap[fontName]) { + if (fontmap[fontName].hasOwnProperty(fontStyle)) { + tmp.push(fontStyle); + } + } + } + } + + return list; + }; + + /** + * Sets line width for upcoming lines. + * + * @param {Number} width Line width (in units declared at inception of PDF document) + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setLineWidth + */ + API.setLineWidth = function(width) { + out((width * k).toFixed(2) + ' w'); + return this; + }; + + /** + * Sets the stroke color for upcoming elements. + * + * Depending on the number of arguments given, Gray, RGB, or CMYK + * color space is implied. + * + * When only ch1 is given, "Gray" color space is implied and it + * must be a value in the range from 0.00 (solid black) to to 1.00 (white) + * if values are communicated as String types, or in range from 0 (black) + * to 255 (white) if communicated as Number type. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each + * value must be in the range from 0.00 (minimum intensity) to to 1.00 + * (max intensity) if values are communicated as String types, or + * from 0 (min intensity) to to 255 (max intensity) if values are communicated + * as Number types. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each + * value must be a in the range from 0.00 (0% concentration) to to + * 1.00 (100% concentration) + * + * Because JavaScript treats fixed point numbers badly (rounds to + * floating point nearest to binary representation) it is highly advised to + * communicate the fractional numbers as String types, not JavaScript Number type. + * + * @param {Number|String} ch1 Color channel value + * @param {Number|String} ch2 Color channel value + * @param {Number|String} ch3 Color channel value + * @param {Number|String} ch4 Color channel value + * + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setDrawColor + */ + API.setDrawColor = function(ch1, ch2, ch3, ch4) { + var color; + if (ch2 === undefined || (ch4 === undefined && ch1 === ch2 === ch3)) { + // Gray color space. + if (typeof ch1 === 'string') { + color = ch1 + ' G'; + } else { + color = f2(ch1 / 255) + ' G'; + } + } else if (ch4 === undefined) { + // RGB + if (typeof ch1 === 'string') { + color = [ch1, ch2, ch3, 'RG'].join(' '); + } else { + color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), 'RG'].join(' '); + } + } else { + // CMYK + if (typeof ch1 === 'string') { + color = [ch1, ch2, ch3, ch4, 'K'].join(' '); + } else { + color = [f2(ch1), f2(ch2), f2(ch3), f2(ch4), 'K'].join(' '); + } + } + + out(color); + return this; + }; + + /** + * Sets the fill color for upcoming elements. + * + * Depending on the number of arguments given, Gray, RGB, or CMYK + * color space is implied. + * + * When only ch1 is given, "Gray" color space is implied and it + * must be a value in the range from 0.00 (solid black) to to 1.00 (white) + * if values are communicated as String types, or in range from 0 (black) + * to 255 (white) if communicated as Number type. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When only ch1,ch2,ch3 are given, "RGB" color space is implied and each + * value must be in the range from 0.00 (minimum intensity) to to 1.00 + * (max intensity) if values are communicated as String types, or + * from 0 (min intensity) to to 255 (max intensity) if values are communicated + * as Number types. + * The RGB-like 0-255 range is provided for backward compatibility. + * + * When ch1,ch2,ch3,ch4 are given, "CMYK" color space is implied and each + * value must be a in the range from 0.00 (0% concentration) to to + * 1.00 (100% concentration) + * + * Because JavaScript treats fixed point numbers badly (rounds to + * floating point nearest to binary representation) it is highly advised to + * communicate the fractional numbers as String types, not JavaScript Number type. + * + * @param {Number|String} ch1 Color channel value + * @param {Number|String} ch2 Color channel value + * @param {Number|String} ch3 Color channel value + * @param {Number|String} ch4 Color channel value + * + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setFillColor + */ + API.setFillColor = function(ch1, ch2, ch3, ch4) { + var color; + + if (ch2 === undefined || (ch4 === undefined && ch1 === ch2 === ch3)) { + // Gray color space. + if (typeof ch1 === 'string') { + color = ch1 + ' g'; + } else { + color = f2(ch1 / 255) + ' g'; + } + } else if (ch4 === undefined) { + // RGB + if (typeof ch1 === 'string') { + color = [ch1, ch2, ch3, 'rg'].join(' '); + } else { + color = [f2(ch1 / 255), f2(ch2 / 255), f2(ch3 / 255), 'rg'].join(' '); + } + } else { + // CMYK + if (typeof ch1 === 'string') { + color = [ch1, ch2, ch3, ch4, 'k'].join(' '); + } else { + color = [f2(ch1), f2(ch2), f2(ch3), f2(ch4), 'k'].join(' '); + } + } + + out(color); + return this; + }; + + /** + * Sets the text color for upcoming elements. + * If only one, first argument is given, + * treats the value as gray-scale color value. + * + * @param {Number} r Red channel color value in range 0-255 or {String} r color value in hexadecimal, example: '#FFFFFF' + * @param {Number} g Green channel color value in range 0-255 + * @param {Number} b Blue channel color value in range 0-255 + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setTextColor + */ + API.setTextColor = function(r, g, b) { + if ((typeof r === 'string') && /^#[0-9A-Fa-f]{6}$/.test(r)) { + var hex = parseInt(r.substr(1), 16); + r = (hex >> 16) & 255; + g = (hex >> 8) & 255; + b = (hex & 255); + } + + if ((r === 0 && g === 0 && b === 0) || (typeof g === 'undefined')) { + textColor = f3(r / 255) + ' g'; + } else { + textColor = [f3(r / 255), f3(g / 255), f3(b / 255), 'rg'].join(' '); + } + return this; + }; + + /** + * Is an Object providing a mapping from human-readable to + * integer flag values designating the varieties of line cap + * and join styles. + * + * @returns {Object} + * @fieldOf jsPDF# + * @name CapJoinStyles + */ + API.CapJoinStyles = { + 0 : 0, + 'butt' : 0, + 'but' : 0, + 'miter' : 0, + 1 : 1, + 'round' : 1, + 'rounded' : 1, + 'circle' : 1, + 2 : 2, + 'projecting' : 2, + 'project' : 2, + 'square' : 2, + 'bevel' : 2 + }; + + /** + * Sets the line cap styles + * See {jsPDF.CapJoinStyles} for variants + * + * @param {String|Number} style A string or number identifying the type of line cap + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setLineCap + */ + API.setLineCap = function(style) { + var id = this.CapJoinStyles[style]; + if (id === undefined) { + throw new Error("Line cap style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles"); + } + lineCapID = id; + out(id + ' J'); + + return this; + }; + + /** + * Sets the line join styles + * See {jsPDF.CapJoinStyles} for variants + * + * @param {String|Number} style A string or number identifying the type of line join + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name setLineJoin + */ + API.setLineJoin = function(style) { + var id = this.CapJoinStyles[style]; + if (id === undefined) { + throw new Error("Line join style of '" + style + "' is not recognized. See or extend .CapJoinStyles property for valid styles"); + } + lineJoinID = id; + out(id + ' j'); + + return this; + }; + + // Output is both an internal (for plugins) and external function + API.output = output; + + /** + * Saves as PDF document. An alias of jsPDF.output('save', 'filename.pdf') + * @param {String} filename The filename including extension. + * + * @function + * @returns {jsPDF} + * @methodOf jsPDF# + * @name save + */ + API.save = function(filename) { + API.output('save', filename); + }; + + // applying plugins (more methods) ON TOP of built-in API. + // this is intentional as we allow plugins to override + // built-ins + for (var plugin in jsPDF.API) { + if (jsPDF.API.hasOwnProperty(plugin)) { + if (plugin === 'events' && jsPDF.API.events.length) { + (function(events, newEvents) { + + // jsPDF.API.events is a JS Array of Arrays + // where each Array is a pair of event name, handler + // Events were added by plugins to the jsPDF instantiator. + // These are always added to the new instance and some ran + // during instantiation. + var eventname,handler_and_args,i; + + for (i = newEvents.length - 1; i !== -1; i--) { + // subscribe takes 3 args: 'topic', function, runonce_flag + // if undefined, runonce is false. + // users can attach callback directly, + // or they can attach an array with [callback, runonce_flag] + // that's what the "apply" magic is for below. + eventname = newEvents[i][0]; + handler_and_args = newEvents[i][1]; + events.subscribe.apply( + events, + [eventname].concat( + typeof handler_and_args === 'function' ? + [handler_and_args] : handler_and_args)); + } + }(events, jsPDF.API.events)); + } else { + API[plugin] = jsPDF.API[plugin]; + } + } + } + + ////////////////////////////////////////////////////// + // continuing initialization of jsPDF Document object + ////////////////////////////////////////////////////// + // Add the first page automatically + addFonts(); + activeFontKey = 'F1'; + _addPage(format, orientation); + + events.publish('initialized'); + return API; + } + + /** + * jsPDF.API is a STATIC property of jsPDF class. + * jsPDF.API is an object you can add methods and properties to. + * The methods / properties you add will show up in new jsPDF objects. + * + * One property is prepopulated. It is the 'events' Object. Plugin authors can add topics, + * callbacks to this object. These will be reassigned to all new instances of jsPDF. + * Examples: + * jsPDF.API.events['initialized'] = function(){ 'this' is API object } + * jsPDF.API.events['addFont'] = function(added_font_object){ 'this' is API object } + * + * @static + * @public + * @memberOf jsPDF + * @name API + * + * @example + * jsPDF.API.mymethod = function(){ + * // 'this' will be ref to internal API object. see jsPDF source + * // , so you can refer to built-in methods like so: + * // this.line(....) + * // this.text(....) + * } + * var pdfdoc = new jsPDF() + * pdfdoc.mymethod() // <- !!!!!! + */ + jsPDF.API = {events:[]}; + jsPDF.version = "1.0.272-debug 2014-09-29T15:09:diegocr"; + + if (typeof define === 'function' && define.amd) { + define('jsPDF', function() { + return jsPDF; + }); + } else { + global.jsPDF = jsPDF; + } + return jsPDF; +}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this)); +/** + * jsPDF addHTML PlugIn + * Copyright (c) 2014 Diego Casorran + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + +(function (jsPDFAPI) { + 'use strict'; + + /** + * Renders an HTML element to canvas object which added as an image to the PDF + * + * This PlugIn requires html2canvas: https://github.com/niklasvh/html2canvas + * OR rasterizeHTML: https://github.com/cburgmer/rasterizeHTML.js + * + * @public + * @function + * @param element {Mixed} HTML Element, or anything supported by html2canvas. + * @param x {Number} starting X coordinate in jsPDF instance's declared units. + * @param y {Number} starting Y coordinate in jsPDF instance's declared units. + * @param options {Object} Additional options, check the code below. + * @param callback {Function} to call when the rendering has finished. + * + * NOTE: Every parameter is optional except 'element' and 'callback', in such + * case the image is positioned at 0x0 covering the whole PDF document + * size. Ie, to easily take screenshoots of webpages saving them to PDF. + */ + jsPDFAPI.addHTML = function (element, x, y, options, callback) { + 'use strict'; + + if(typeof html2canvas === 'undefined' && typeof rasterizeHTML === 'undefined') + throw new Error('You need either ' + +'https://github.com/niklasvh/html2canvas' + +' or https://github.com/cburgmer/rasterizeHTML.js'); + + if(typeof x !== 'number') { + options = x; + callback = y; + } + + if(typeof options === 'function') { + callback = options; + options = null; + } + + var I = this.internal, K = I.scaleFactor, W = I.pageSize.width, H = I.pageSize.height; + + options = options || {}; + options.onrendered = function(obj) { + x = parseInt(x) || 0; + y = parseInt(y) || 0; + var dim = options.dim || {}; + var h = dim.h || 0; + var w = dim.w || Math.min(W,obj.width/K) - x; + + var format = 'JPEG'; + if(options.format) + format = options.format; + + if(obj.height > H && options.pagesplit) { + var crop = function() { + var cy = 0; + while(1) { + var canvas = document.createElement('canvas'); + canvas.width = Math.min(W*K,obj.width); + canvas.height = Math.min(H*K,obj.height-cy); + var ctx = canvas.getContext('2d'); + ctx.drawImage(obj,0,cy,obj.width,canvas.height,0,0,canvas.width,canvas.height); + var args = [canvas, x,cy?0:y,canvas.width/K,canvas.height/K, format,null,'SLOW']; + this.addImage.apply(this, args); + cy += canvas.height; + if(cy >= obj.height) break; + this.addPage(); + } + callback(w,cy,null,args); + }.bind(this); + if(obj.nodeName === 'CANVAS') { + var img = new Image(); + img.onload = crop; + img.src = obj.toDataURL("image/png"); + obj = img; + } else { + crop(); + } + } else { + var alias = Math.random().toString(35); + var args = [obj, x,y,w,h, format,alias,'SLOW']; + + this.addImage.apply(this, args); + + callback(w,h,alias,args); + } + }.bind(this); + + if(typeof html2canvas !== 'undefined' && !options.rstz) { + return html2canvas(element, options); + } + + if(typeof rasterizeHTML !== 'undefined') { + var meth = 'drawDocument'; + if(typeof element === 'string') { + meth = /^http/.test(element) ? 'drawURL' : 'drawHTML'; + } + options.width = options.width || (W*K); + return rasterizeHTML[meth](element, void 0, options).then(function(r) { + options.onrendered(r.image); + }, function(e) { + callback(null,e); + }); + } + + return null; + }; +})(jsPDF.API); +/** @preserve + * jsPDF addImage plugin + * Copyright (c) 2012 Jason Siefken, https://github.com/siefkenj/ + * 2013 Chris Dowling, https://github.com/gingerchris + * 2013 Trinh Ho, https://github.com/ineedfat + * 2013 Edwin Alejandro Perez, https://github.com/eaparango + * 2013 Norah Smith, https://github.com/burnburnrocket + * 2014 Diego Casorran, https://github.com/diegocr + * 2014 James Robb, https://github.com/jamesbrobb + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +;(function(jsPDFAPI) { + 'use strict' + + var namespace = 'addImage_', + supported_image_types = ['jpeg', 'jpg', 'png']; + + // Image functionality ported from pdf.js + var putImage = function(img) { + + var objectNumber = this.internal.newObject() + , out = this.internal.write + , putStream = this.internal.putStream + + img['n'] = objectNumber + + out('<>'); + } + if ('trns' in img && img['trns'].constructor == Array) { + var trns = '', + i = 0, + len = img['trns'].length; + for (; i < len; i++) + trns += (img['trns'][i] + ' ' + img['trns'][i] + ' '); + out('/Mask [' + trns + ']'); + } + if ('smask' in img) { + out('/SMask ' + (objectNumber + 1) + ' 0 R'); + } + out('/Length ' + img['data'].length + '>>'); + + putStream(img['data']); + + out('endobj'); + + // Soft mask + if ('smask' in img) { + var dp = '/Predictor 15 /Colors 1 /BitsPerComponent ' + img['bpc'] + ' /Columns ' + img['w']; + var smask = {'w': img['w'], 'h': img['h'], 'cs': 'DeviceGray', 'bpc': img['bpc'], 'dp': dp, 'data': img['smask']}; + if ('f' in img) + smask.f = img['f']; + putImage.call(this, smask); + } + + //Palette + if (img['cs'] === this.color_spaces.INDEXED) { + + this.internal.newObject(); + //out('<< /Filter / ' + img['f'] +' /Length ' + img['pal'].length + '>>'); + //putStream(zlib.compress(img['pal'])); + out('<< /Length ' + img['pal'].length + '>>'); + putStream(this.arrayBufferToBinaryString(new Uint8Array(img['pal']))); + out('endobj'); + } + } + , putResourcesCallback = function() { + var images = this.internal.collections[namespace + 'images'] + for ( var i in images ) { + putImage.call(this, images[i]) + } + } + , putXObjectsDictCallback = function(){ + var images = this.internal.collections[namespace + 'images'] + , out = this.internal.write + , image + for (var i in images) { + image = images[i] + out( + '/I' + image['i'] + , image['n'] + , '0' + , 'R' + ) + } + } + , checkCompressValue = function(value) { + if(value && typeof value === 'string') + value = value.toUpperCase(); + return value in jsPDFAPI.image_compression ? value : jsPDFAPI.image_compression.NONE; + } + , getImages = function() { + var images = this.internal.collections[namespace + 'images']; + //first run, so initialise stuff + if(!images) { + this.internal.collections[namespace + 'images'] = images = {}; + this.internal.events.subscribe('putResources', putResourcesCallback); + this.internal.events.subscribe('putXobjectDict', putXObjectsDictCallback); + } + + return images; + } + , getImageIndex = function(images) { + var imageIndex = 0; + + if (images){ + // this is NOT the first time this method is ran on this instance of jsPDF object. + imageIndex = Object.keys ? + Object.keys(images).length : + (function(o){ + var i = 0 + for (var e in o){if(o.hasOwnProperty(e)){ i++ }} + return i + })(images) + } + + return imageIndex; + } + , notDefined = function(value) { + return typeof value === 'undefined' || value === null; + } + , generateAliasFromData = function(data) { + return typeof data === 'string' && jsPDFAPI.sHashCode(data); + } + , doesNotSupportImageType = function(type) { + return supported_image_types.indexOf(type) === -1; + } + , processMethodNotEnabled = function(type) { + return typeof jsPDFAPI['process' + type.toUpperCase()] !== 'function'; + } + , isDOMElement = function(object) { + return typeof object === 'object' && object.nodeType === 1; + } + , createDataURIFromElement = function(element, format, angle) { + + //if element is an image which uses data url defintion, just return the dataurl + if (element.nodeName === 'IMG' && element.hasAttribute('src')) { + var src = ''+element.getAttribute('src'); + if (!angle && src.indexOf('data:image/') === 0) return src; + + // only if the user doesn't care about a format + if (!format && /\.png(?:[?#].*)?$/i.test(src)) format = 'png'; + } + + if(element.nodeName === 'CANVAS') { + var canvas = element; + } else { + var canvas = document.createElement('canvas'); + canvas.width = element.clientWidth || element.width; + canvas.height = element.clientHeight || element.height; + + var ctx = canvas.getContext('2d'); + if (!ctx) { + throw ('addImage requires canvas to be supported by browser.'); + } + if (angle) { + var x, y, b, c, s, w, h, to_radians = Math.PI/180, angleInRadians; + + if (typeof angle === 'object') { + x = angle.x; + y = angle.y; + b = angle.bg; + angle = angle.angle; + } + angleInRadians = angle*to_radians; + c = Math.abs(Math.cos(angleInRadians)); + s = Math.abs(Math.sin(angleInRadians)); + w = canvas.width; + h = canvas.height; + canvas.width = h * s + w * c; + canvas.height = h * c + w * s; + + if (isNaN(x)) x = canvas.width / 2; + if (isNaN(y)) y = canvas.height / 2; + + ctx.clearRect(0,0,canvas.width, canvas.height); + ctx.fillStyle = b || 'white'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ctx.save(); + ctx.translate(x, y); + ctx.rotate(angleInRadians); + ctx.drawImage(element, -(w/2), -(h/2)); + ctx.rotate(-angleInRadians); + ctx.translate(-x, -y); + ctx.restore(); + } else { + ctx.drawImage(element, 0, 0, canvas.width, canvas.height); + } + } + return canvas.toDataURL((''+format).toLowerCase() == 'png' ? 'image/png' : 'image/jpeg'); + } + ,checkImagesForAlias = function(alias, images) { + var cached_info; + if(images) { + for(var e in images) { + if(alias === images[e].alias) { + cached_info = images[e]; + break; + } + } + } + return cached_info; + } + ,determineWidthAndHeight = function(w, h, info) { + if (!w && !h) { + w = -96; + h = -96; + } + if (w < 0) { + w = (-1) * info['w'] * 72 / w / this.internal.scaleFactor; + } + if (h < 0) { + h = (-1) * info['h'] * 72 / h / this.internal.scaleFactor; + } + if (w === 0) { + w = h * info['w'] / info['h']; + } + if (h === 0) { + h = w * info['h'] / info['w']; + } + + return [w, h]; + } + , writeImageToPDF = function(x, y, w, h, info, index, images) { + var dims = determineWidthAndHeight.call(this, w, h, info), + coord = this.internal.getCoordinateString, + vcoord = this.internal.getVerticalCoordinateString; + + w = dims[0]; + h = dims[1]; + + images[index] = info; + + this.internal.write( + 'q' + , coord(w) + , '0 0' + , coord(h) // TODO: check if this should be shifted by vcoord + , coord(x) + , vcoord(y + h) + , 'cm /I'+info['i'] + , 'Do Q' + ) + }; + + /** + * COLOR SPACES + */ + jsPDFAPI.color_spaces = { + DEVICE_RGB:'DeviceRGB', + DEVICE_GRAY:'DeviceGray', + DEVICE_CMYK:'DeviceCMYK', + CAL_GREY:'CalGray', + CAL_RGB:'CalRGB', + LAB:'Lab', + ICC_BASED:'ICCBased', + INDEXED:'Indexed', + PATTERN:'Pattern', + SEPERATION:'Seperation', + DEVICE_N:'DeviceN' + }; + + /** + * DECODE METHODS + */ + jsPDFAPI.decode = { + DCT_DECODE:'DCTDecode', + FLATE_DECODE:'FlateDecode', + LZW_DECODE:'LZWDecode', + JPX_DECODE:'JPXDecode', + JBIG2_DECODE:'JBIG2Decode', + ASCII85_DECODE:'ASCII85Decode', + ASCII_HEX_DECODE:'ASCIIHexDecode', + RUN_LENGTH_DECODE:'RunLengthDecode', + CCITT_FAX_DECODE:'CCITTFaxDecode' + }; + + /** + * IMAGE COMPRESSION TYPES + */ + jsPDFAPI.image_compression = { + NONE: 'NONE', + FAST: 'FAST', + MEDIUM: 'MEDIUM', + SLOW: 'SLOW' + }; + + jsPDFAPI.sHashCode = function(str) { + return Array.prototype.reduce && str.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0); + }; + + jsPDFAPI.isString = function(object) { + return typeof object === 'string'; + }; + + /** + * Strips out and returns info from a valid base64 data URI + * @param {String[dataURI]} a valid data URI of format 'data:[][;base64],' + * @returns an Array containing the following + * [0] the complete data URI + * [1] + * [2] format - the second part of the mime-type i.e 'png' in 'image/png' + * [4] + */ + jsPDFAPI.extractInfoFromBase64DataURI = function(dataURI) { + return /^data:([\w]+?\/([\w]+?));base64,(.+?)$/g.exec(dataURI); + }; + + /** + * Check to see if ArrayBuffer is supported + */ + jsPDFAPI.supportsArrayBuffer = function() { + return typeof ArrayBuffer !== 'undefined' && typeof Uint8Array !== 'undefined'; + }; + + /** + * Tests supplied object to determine if ArrayBuffer + * @param {Object[object]} + */ + jsPDFAPI.isArrayBuffer = function(object) { + if(!this.supportsArrayBuffer()) + return false; + return object instanceof ArrayBuffer; + }; + + /** + * Tests supplied object to determine if it implements the ArrayBufferView (TypedArray) interface + * @param {Object[object]} + */ + jsPDFAPI.isArrayBufferView = function(object) { + if(!this.supportsArrayBuffer()) + return false; + if(typeof Uint32Array === 'undefined') + return false; + return (object instanceof Int8Array || + object instanceof Uint8Array || + (typeof Uint8ClampedArray !== 'undefined' && object instanceof Uint8ClampedArray) || + object instanceof Int16Array || + object instanceof Uint16Array || + object instanceof Int32Array || + object instanceof Uint32Array || + object instanceof Float32Array || + object instanceof Float64Array ); + }; + + /** + * Exactly what it says on the tin + */ + jsPDFAPI.binaryStringToUint8Array = function(binary_string) { + /* + * not sure how efficient this will be will bigger files. Is there a native method? + */ + var len = binary_string.length; + var bytes = new Uint8Array( len ); + for (var i = 0; i < len; i++) { + bytes[i] = binary_string.charCodeAt(i); + } + return bytes; + }; + + /** + * @see this discussion + * http://stackoverflow.com/questions/6965107/converting-between-strings-and-arraybuffers + * + * As stated, i imagine the method below is highly inefficent for large files. + * + * Also of note from Mozilla, + * + * "However, this is slow and error-prone, due to the need for multiple conversions (especially if the binary data is not actually byte-format data, but, for example, 32-bit integers or floats)." + * + * https://developer.mozilla.org/en-US/Add-ons/Code_snippets/StringView + * + * Although i'm strugglig to see how StringView solves this issue? Doesn't appear to be a direct method for conversion? + * + * Async method using Blob and FileReader could be best, but i'm not sure how to fit it into the flow? + */ + jsPDFAPI.arrayBufferToBinaryString = function(buffer) { + if(this.isArrayBuffer(buffer)) + buffer = new Uint8Array(buffer); + + var binary_string = ''; + var len = buffer.byteLength; + for (var i = 0; i < len; i++) { + binary_string += String.fromCharCode(buffer[i]); + } + return binary_string; + /* + * Another solution is the method below - convert array buffer straight to base64 and then use atob + */ + //return atob(this.arrayBufferToBase64(buffer)); + }; + + /** + * Converts an ArrayBuffer directly to base64 + * + * Taken from here + * + * http://jsperf.com/encoding-xhr-image-data/31 + * + * Need to test if this is a better solution for larger files + * + */ + jsPDFAPI.arrayBufferToBase64 = function(arrayBuffer) { + var base64 = '' + var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + + var bytes = new Uint8Array(arrayBuffer) + var byteLength = bytes.byteLength + var byteRemainder = byteLength % 3 + var mainLength = byteLength - byteRemainder + + var a, b, c, d + var chunk + + // Main loop deals with bytes in chunks of 3 + for (var i = 0; i < mainLength; i = i + 3) { + // Combine the three bytes into a single integer + chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2] + + // Use bitmasks to extract 6-bit segments from the triplet + a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18 + b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12 + c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6 + d = chunk & 63 // 63 = 2^6 - 1 + + // Convert the raw binary segments to the appropriate ASCII encoding + base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d] + } + + // Deal with the remaining bytes and padding + if (byteRemainder == 1) { + chunk = bytes[mainLength] + + a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2 + + // Set the 4 least significant bits to zero + b = (chunk & 3) << 4 // 3 = 2^2 - 1 + + base64 += encodings[a] + encodings[b] + '==' + } else if (byteRemainder == 2) { + chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1] + + a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10 + b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4 + + // Set the 2 least significant bits to zero + c = (chunk & 15) << 2 // 15 = 2^4 - 1 + + base64 += encodings[a] + encodings[b] + encodings[c] + '=' + } + + return base64 + }; + + jsPDFAPI.createImageInfo = function(data, wd, ht, cs, bpc, f, imageIndex, alias, dp, trns, pal, smask) { + var info = { + alias:alias, + w : wd, + h : ht, + cs : cs, + bpc : bpc, + i : imageIndex, + data : data + // n: objectNumber will be added by putImage code + }; + + if(f) info.f = f; + if(dp) info.dp = dp; + if(trns) info.trns = trns; + if(pal) info.pal = pal; + if(smask) info.smask = smask; + + return info; + }; + + jsPDFAPI.addImage = function(imageData, format, x, y, w, h, alias, compression, rotation) { + 'use strict' + + if(typeof format !== 'string') { + var tmp = h; + h = w; + w = y; + y = x; + x = format; + format = tmp; + } + + if (typeof imageData === 'object' && !isDOMElement(imageData) && "imageData" in imageData) { + var options = imageData; + + imageData = options.imageData; + format = options.format || format; + x = options.x || x || 0; + y = options.y || y || 0; + w = options.w || w; + h = options.h || h; + alias = options.alias || alias; + compression = options.compression || compression; + rotation = options.rotation || options.angle || rotation; + } + + if (isNaN(x) || isNaN(y)) + { + console.error('jsPDF.addImage: Invalid coordinates', arguments); + throw new Error('Invalid coordinates passed to jsPDF.addImage'); + } + + var images = getImages.call(this), info; + + if (!(info = checkImagesForAlias(imageData, images))) { + var dataAsBinaryString; + + if(isDOMElement(imageData)) + imageData = createDataURIFromElement(imageData, format, rotation); + + if(notDefined(alias)) + alias = generateAliasFromData(imageData); + + if (!(info = checkImagesForAlias(alias, images))) { + + if(this.isString(imageData)) { + + var base64Info = this.extractInfoFromBase64DataURI(imageData); + + if(base64Info) { + + format = base64Info[2]; + imageData = atob(base64Info[3]);//convert to binary string + + } else { + + if (imageData.charCodeAt(0) === 0x89 && + imageData.charCodeAt(1) === 0x50 && + imageData.charCodeAt(2) === 0x4e && + imageData.charCodeAt(3) === 0x47 ) format = 'png'; + } + } + format = (format || 'JPEG').toLowerCase(); + + if(doesNotSupportImageType(format)) + throw new Error('addImage currently only supports formats ' + supported_image_types + ', not \''+format+'\''); + + if(processMethodNotEnabled(format)) + throw new Error('please ensure that the plugin for \''+format+'\' support is added'); + + /** + * need to test if it's more efficent to convert all binary strings + * to TypedArray - or should we just leave and process as string? + */ + if(this.supportsArrayBuffer()) { + dataAsBinaryString = imageData; + imageData = this.binaryStringToUint8Array(imageData); + } + + info = this['process' + format.toUpperCase()]( + imageData, + getImageIndex(images), + alias, + checkCompressValue(compression), + dataAsBinaryString + ); + + if(!info) + throw new Error('An unkwown error occurred whilst processing the image'); + } + } + + writeImageToPDF.call(this, x, y, w, h, info, info.i, images); + + return this + }; + + /** + * JPEG SUPPORT + **/ + + //takes a string imgData containing the raw bytes of + //a jpeg image and returns [width, height] + //Algorithm from: http://www.64lines.com/jpeg-width-height + var getJpegSize = function(imgData) { + 'use strict' + var width, height, numcomponents; + // Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00 + if (!imgData.charCodeAt(0) === 0xff || + !imgData.charCodeAt(1) === 0xd8 || + !imgData.charCodeAt(2) === 0xff || + !imgData.charCodeAt(3) === 0xe0 || + !imgData.charCodeAt(6) === 'J'.charCodeAt(0) || + !imgData.charCodeAt(7) === 'F'.charCodeAt(0) || + !imgData.charCodeAt(8) === 'I'.charCodeAt(0) || + !imgData.charCodeAt(9) === 'F'.charCodeAt(0) || + !imgData.charCodeAt(10) === 0x00) { + throw new Error('getJpegSize requires a binary string jpeg file') + } + var blockLength = imgData.charCodeAt(4)*256 + imgData.charCodeAt(5); + var i = 4, len = imgData.length; + while ( i < len ) { + i += blockLength; + if (imgData.charCodeAt(i) !== 0xff) { + throw new Error('getJpegSize could not find the size of the image'); + } + if (imgData.charCodeAt(i+1) === 0xc0 || //(SOF) Huffman - Baseline DCT + imgData.charCodeAt(i+1) === 0xc1 || //(SOF) Huffman - Extended sequential DCT + imgData.charCodeAt(i+1) === 0xc2 || // Progressive DCT (SOF2) + imgData.charCodeAt(i+1) === 0xc3 || // Spatial (sequential) lossless (SOF3) + imgData.charCodeAt(i+1) === 0xc4 || // Differential sequential DCT (SOF5) + imgData.charCodeAt(i+1) === 0xc5 || // Differential progressive DCT (SOF6) + imgData.charCodeAt(i+1) === 0xc6 || // Differential spatial (SOF7) + imgData.charCodeAt(i+1) === 0xc7) { + height = imgData.charCodeAt(i+5)*256 + imgData.charCodeAt(i+6); + width = imgData.charCodeAt(i+7)*256 + imgData.charCodeAt(i+8); + numcomponents = imgData.charCodeAt(i+9); + return [width, height, numcomponents]; + } else { + i += 2; + blockLength = imgData.charCodeAt(i)*256 + imgData.charCodeAt(i+1) + } + } + } + , getJpegSizeFromBytes = function(data) { + + var hdr = (data[0] << 8) | data[1]; + + if(hdr !== 0xFFD8) + throw new Error('Supplied data is not a JPEG'); + + var len = data.length, + block = (data[4] << 8) + data[5], + pos = 4, + bytes, width, height, numcomponents; + + while(pos < len) { + pos += block; + bytes = readBytes(data, pos); + block = (bytes[2] << 8) + bytes[3]; + if((bytes[1] === 0xC0 || bytes[1] === 0xC2) && bytes[0] === 0xFF && block > 7) { + bytes = readBytes(data, pos + 5); + width = (bytes[2] << 8) + bytes[3]; + height = (bytes[0] << 8) + bytes[1]; + numcomponents = bytes[4]; + return {width:width, height:height, numcomponents: numcomponents}; + } + + pos+=2; + } + + throw new Error('getJpegSizeFromBytes could not find the size of the image'); + } + , readBytes = function(data, offset) { + return data.subarray(offset, offset+ 5); + }; + + jsPDFAPI.processJPEG = function(data, index, alias, compression, dataAsBinaryString) { + 'use strict' + var colorSpace = this.color_spaces.DEVICE_RGB, + filter = this.decode.DCT_DECODE, + bpc = 8, + dims; + + if(this.isString(data)) { + dims = getJpegSize(data); + return this.createImageInfo(data, dims[0], dims[1], dims[3] == 1 ? this.color_spaces.DEVICE_GRAY:colorSpace, bpc, filter, index, alias); + } + + if(this.isArrayBuffer(data)) + data = new Uint8Array(data); + + if(this.isArrayBufferView(data)) { + + dims = getJpegSizeFromBytes(data); + + // if we already have a stored binary string rep use that + data = dataAsBinaryString || this.arrayBufferToBinaryString(data); + + return this.createImageInfo(data, dims.width, dims.height, dims.numcomponents == 1 ? this.color_spaces.DEVICE_GRAY:colorSpace, bpc, filter, index, alias); + } + + return null; + }; + + jsPDFAPI.processJPG = function(/*data, index, alias, compression, dataAsBinaryString*/) { + return this.processJPEG.apply(this, arguments); + } + +})(jsPDF.API); +(function (jsPDFAPI) { + 'use strict'; + + jsPDFAPI.autoPrint = function () { + 'use strict' + var refAutoPrintTag; + + this.internal.events.subscribe('postPutResources', function () { + refAutoPrintTag = this.internal.newObject() + this.internal.write("<< /S/Named /Type/Action /N/Print >>", "endobj"); + }); + + this.internal.events.subscribe("putCatalog", function () { + this.internal.write("/OpenAction " + refAutoPrintTag + " 0" + " R"); + }); + return this; + }; +})(jsPDF.API); +/** ==================================================================== + * jsPDF Cell plugin + * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com + * 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br + * 2013 Lee Driscoll, https://github.com/lsdriscoll + * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria + * 2014 James Hall, james@parall.ax + * 2014 Diego Casorran, https://github.com/diegocr + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ==================================================================== + */ + +(function (jsPDFAPI) { + 'use strict'; + /*jslint browser:true */ + /*global document: false, jsPDF */ + + var fontName, + fontSize, + fontStyle, + padding = 3, + margin = 13, + headerFunction, + lastCellPos = { x: undefined, y: undefined, w: undefined, h: undefined, ln: undefined }, + pages = 1, + setLastCellPosition = function (x, y, w, h, ln) { + lastCellPos = { 'x': x, 'y': y, 'w': w, 'h': h, 'ln': ln }; + }, + getLastCellPosition = function () { + return lastCellPos; + }, + NO_MARGINS = {left:0, top:0, bottom: 0}; + + jsPDFAPI.setHeaderFunction = function (func) { + headerFunction = func; + }; + + jsPDFAPI.getTextDimensions = function (txt) { + fontName = this.internal.getFont().fontName; + fontSize = this.table_font_size || this.internal.getFontSize(); + fontStyle = this.internal.getFont().fontStyle; + // 1 pixel = 0.264583 mm and 1 mm = 72/25.4 point + var px2pt = 0.264583 * 72 / 25.4, + dimensions, + text; + + text = document.createElement('font'); + text.id = "jsPDFCell"; + text.style.fontStyle = fontStyle; + text.style.fontName = fontName; + text.style.fontSize = fontSize + 'pt'; + text.textContent = txt; + + document.body.appendChild(text); + + dimensions = { w: (text.offsetWidth + 1) * px2pt, h: (text.offsetHeight + 1) * px2pt}; + + document.body.removeChild(text); + + return dimensions; + }; + + jsPDFAPI.cellAddPage = function () { + var margins = this.margins || NO_MARGINS; + + this.addPage(); + + setLastCellPosition(margins.left, margins.top, undefined, undefined); + //setLastCellPosition(undefined, undefined, undefined, undefined, undefined); + pages += 1; + }; + + jsPDFAPI.cellInitialize = function () { + lastCellPos = { x: undefined, y: undefined, w: undefined, h: undefined, ln: undefined }; + pages = 1; + }; + + jsPDFAPI.cell = function (x, y, w, h, txt, ln, align) { + var curCell = getLastCellPosition(); + + // If this is not the first cell, we must change its position + if (curCell.ln !== undefined) { + if (curCell.ln === ln) { + //Same line + x = curCell.x + curCell.w; + y = curCell.y; + } else { + //New line + var margins = this.margins || NO_MARGINS; + if ((curCell.y + curCell.h + h + margin) >= this.internal.pageSize.height - margins.bottom) { + this.cellAddPage(); + if (this.printHeaders && this.tableHeaderRow) { + this.printHeaderRow(ln, true); + } + } + //We ignore the passed y: the lines may have diferent heights + y = (getLastCellPosition().y + getLastCellPosition().h); + + } + } + + if (txt[0] !== undefined) { + if (this.printingHeaderRow) { + this.rect(x, y, w, h, 'FD'); + } else { + this.rect(x, y, w, h); + } + if (align === 'right') { + if (txt instanceof Array) { + for(var i = 0; i max) { + max = item; + } + } + } + + return max; + }; + + /** + * Create a table from a set of data. + * @param {Integer} [x] : left-position for top-left corner of table + * @param {Integer} [y] top-position for top-left corner of table + * @param {Object[]} [data] As array of objects containing key-value pairs corresponding to a row of data. + * @param {String[]} [headers] Omit or null to auto-generate headers at a performance cost + + * @param {Object} [config.printHeaders] True to print column headers at the top of every page + * @param {Object} [config.autoSize] True to dynamically set the column widths to match the widest cell value + * @param {Object} [config.margins] margin values for left, top, bottom, and width + * @param {Object} [config.fontSize] Integer fontSize to use (optional) + */ + + jsPDFAPI.table = function (x,y, data, headers, config) { + if (!data) { + throw 'No data for PDF table'; + } + + var headerNames = [], + headerPrompts = [], + header, + i, + ln, + cln, + columnMatrix = {}, + columnWidths = {}, + columnData, + column, + columnMinWidths = [], + j, + tableHeaderConfigs = [], + model, + jln, + func, + + //set up defaults. If a value is provided in config, defaults will be overwritten: + autoSize = false, + printHeaders = true, + fontSize = 12, + margins = NO_MARGINS; + + margins.width = this.internal.pageSize.width; + + if (config) { + //override config defaults if the user has specified non-default behavior: + if(config.autoSize === true) { + autoSize = true; + } + if(config.printHeaders === false) { + printHeaders = false; + } + if(config.fontSize){ + fontSize = config.fontSize; + } + if(config.margins){ + margins = config.margins; + } + } + + /** + * @property {Number} lnMod + * Keep track of the current line number modifier used when creating cells + */ + this.lnMod = 0; + lastCellPos = { x: undefined, y: undefined, w: undefined, h: undefined, ln: undefined }, + pages = 1; + + this.printHeaders = printHeaders; + this.margins = margins; + this.setFontSize(fontSize); + this.table_font_size = fontSize; + + // Set header values + if (headers === undefined || (headers === null)) { + // No headers defined so we derive from data + headerNames = Object.keys(data[0]); + + } else if (headers[0] && (typeof headers[0] !== 'string')) { + var px2pt = 0.264583 * 72 / 25.4; + + // Split header configs into names and prompts + for (i = 0, ln = headers.length; i < ln; i += 1) { + header = headers[i]; + headerNames.push(header.name); + headerPrompts.push(header.prompt); + columnWidths[header.name] = header.width *px2pt; + } + + } else { + headerNames = headers; + } + + if (autoSize) { + // Create a matrix of columns e.g., {column_title: [row1_Record, row2_Record]} + func = function (rec) { + return rec[header]; + }; + + for (i = 0, ln = headerNames.length; i < ln; i += 1) { + header = headerNames[i]; + + columnMatrix[header] = data.map( + func + ); + + // get header width + columnMinWidths.push(this.getTextDimensions(headerPrompts[i] || header).w); + column = columnMatrix[header]; + + // get cell widths + for (j = 0, cln = column.length; j < cln; j += 1) { + columnData = column[j]; + columnMinWidths.push(this.getTextDimensions(columnData).w); + } + + // get final column width + columnWidths[header] = jsPDFAPI.arrayMax(columnMinWidths); + } + } + + // -- Construct the table + + if (printHeaders) { + var lineHeight = this.calculateLineHeight(headerNames, columnWidths, headerPrompts.length?headerPrompts:headerNames); + + // Construct the header row + for (i = 0, ln = headerNames.length; i < ln; i += 1) { + header = headerNames[i]; + tableHeaderConfigs.push([x, y, columnWidths[header], lineHeight, String(headerPrompts.length ? headerPrompts[i] : header)]); + } + + // Store the table header config + this.setTableHeaderRow(tableHeaderConfigs); + + // Print the header for the start of the table + this.printHeaderRow(1, false); + } + + // Construct the data rows + for (i = 0, ln = data.length; i < ln; i += 1) { + var lineHeight; + model = data[i]; + lineHeight = this.calculateLineHeight(headerNames, columnWidths, model); + + for (j = 0, jln = headerNames.length; j < jln; j += 1) { + header = headerNames[j]; + this.cell(x, y, columnWidths[header], lineHeight, model[header], i + 2, header.align); + } + } + this.lastCellPos = lastCellPos; + this.table_x = x; + this.table_y = y; + return this; + }; + /** + * Calculate the height for containing the highest column + * @param {String[]} headerNames is the header, used as keys to the data + * @param {Integer[]} columnWidths is size of each column + * @param {Object[]} model is the line of data we want to calculate the height of + */ + jsPDFAPI.calculateLineHeight = function (headerNames, columnWidths, model) { + var header, lineHeight = 0; + for (var j = 0; j < headerNames.length; j++) { + header = headerNames[j]; + model[header] = this.splitTextToSize(String(model[header]), columnWidths[header] - padding); + var h = this.internal.getLineHeight() * model[header].length + padding; + if (h > lineHeight) + lineHeight = h; + } + return lineHeight; + }; + + /** + * Store the config for outputting a table header + * @param {Object[]} config + * An array of cell configs that would define a header row: Each config matches the config used by jsPDFAPI.cell + * except the ln parameter is excluded + */ + jsPDFAPI.setTableHeaderRow = function (config) { + this.tableHeaderRow = config; + }; + + /** + * Output the store header row + * @param lineNumber The line number to output the header at + */ + jsPDFAPI.printHeaderRow = function (lineNumber, new_page) { + if (!this.tableHeaderRow) { + throw 'Property tableHeaderRow does not exist.'; + } + + var tableHeaderCell, + tmpArray, + i, + ln; + + this.printingHeaderRow = true; + if (headerFunction !== undefined) { + var position = headerFunction(this, pages); + setLastCellPosition(position[0], position[1], position[2], position[3], -1); + } + this.setFontStyle('bold'); + var tempHeaderConf = []; + for (i = 0, ln = this.tableHeaderRow.length; i < ln; i += 1) { + this.setFillColor(200,200,200); + + tableHeaderCell = this.tableHeaderRow[i]; + if (new_page) { + tableHeaderCell[1] = this.margins && this.margins.top || 0; + tempHeaderConf.push(tableHeaderCell); + } + tmpArray = [].concat(tableHeaderCell); + this.cell.apply(this, tmpArray.concat(lineNumber)); + } + if (tempHeaderConf.length > 0){ + this.setTableHeaderRow(tempHeaderConf); + } + this.setFontStyle('normal'); + this.printingHeaderRow = false; + }; + +})(jsPDF.API); +/** @preserve + * jsPDF fromHTML plugin. BETA stage. API subject to change. Needs browser + * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com + * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria + * 2014 Diego Casorran, https://github.com/diegocr + * 2014 Daniel Husar, https://github.com/danielhusar + * 2014 Wolfgang Gassler, https://github.com/woolfg + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * ==================================================================== + */ + +(function (jsPDFAPI) { + var clone, + DrillForContent, + FontNameDB, + FontStyleMap, + FontWeightMap, + FloatMap, + ClearMap, + GetCSS, + PurgeWhiteSpace, + Renderer, + ResolveFont, + ResolveUnitedNumber, + UnitedNumberMap, + elementHandledElsewhere, + images, + loadImgs, + checkForFooter, + process, + tableToJson; + clone = (function () { + return function (obj) { + Clone.prototype = obj; + return new Clone() + }; + function Clone() {} + })(); + PurgeWhiteSpace = function (array) { + var fragment, + i, + l, + lTrimmed, + r, + rTrimmed, + trailingSpace; + i = 0; + l = array.length; + fragment = void 0; + lTrimmed = false; + rTrimmed = false; + while (!lTrimmed && i !== l) { + fragment = array[i] = array[i].trimLeft(); + if (fragment) { + lTrimmed = true; + } + i++; + } + i = l - 1; + while (l && !rTrimmed && i !== -1) { + fragment = array[i] = array[i].trimRight(); + if (fragment) { + rTrimmed = true; + } + i--; + } + r = /\s+$/g; + trailingSpace = true; + i = 0; + while (i !== l) { + fragment = array[i].replace(/\s+/g, " "); + if (trailingSpace) { + fragment = fragment.trimLeft(); + } + if (fragment) { + trailingSpace = r.test(fragment); + } + array[i] = fragment; + i++; + } + return array; + }; + Renderer = function (pdf, x, y, settings) { + this.pdf = pdf; + this.x = x; + this.y = y; + this.settings = settings; + //list of functions which are called after each element-rendering process + this.watchFunctions = []; + this.init(); + return this; + }; + ResolveFont = function (css_font_family_string) { + var name, + part, + parts; + name = void 0; + parts = css_font_family_string.split(","); + part = parts.shift(); + while (!name && part) { + name = FontNameDB[part.trim().toLowerCase()]; + part = parts.shift(); + } + return name; + }; + ResolveUnitedNumber = function (css_line_height_string) { + + //IE8 issues + css_line_height_string = css_line_height_string === "auto" ? "0px" : css_line_height_string; + if (css_line_height_string.indexOf("em") > -1 && !isNaN(Number(css_line_height_string.replace("em", "")))) { + css_line_height_string = Number(css_line_height_string.replace("em", "")) * 18.719 + "px"; + } + if (css_line_height_string.indexOf("pt") > -1 && !isNaN(Number(css_line_height_string.replace("pt", "")))) { + css_line_height_string = Number(css_line_height_string.replace("pt", "")) * 1.333 + "px"; + } + + var normal, + undef, + value; + undef = void 0; + normal = 16.00; + value = UnitedNumberMap[css_line_height_string]; + if (value) { + return value; + } + value = { + "xx-small" : 9, + "x-small" : 11, + small : 13, + medium : 16, + large : 19, + "x-large" : 23, + "xx-large" : 28, + auto : 0 + }[{ css_line_height_string : css_line_height_string }]; + + if (value !== undef) { + return UnitedNumberMap[css_line_height_string] = value / normal; + } + if (value = parseFloat(css_line_height_string)) { + return UnitedNumberMap[css_line_height_string] = value / normal; + } + value = css_line_height_string.match(/([\d\.]+)(px)/); + if (value.length === 3) { + return UnitedNumberMap[css_line_height_string] = parseFloat(value[1]) / normal; + } + return UnitedNumberMap[css_line_height_string] = 1; + }; + GetCSS = function (element) { + var css,tmp,computedCSSElement; + computedCSSElement = (function (el) { + var compCSS; + compCSS = (function (el) { + if (document.defaultView && document.defaultView.getComputedStyle) { + return document.defaultView.getComputedStyle(el, null); + } else if (el.currentStyle) { + return el.currentStyle; + } else { + return el.style; + } + })(el); + return function (prop) { + prop = prop.replace(/-\D/g, function (match) { + return match.charAt(1).toUpperCase(); + }); + return compCSS[prop]; + }; + })(element); + css = {}; + tmp = void 0; + css["font-family"] = ResolveFont(computedCSSElement("font-family")) || "times"; + css["font-style"] = FontStyleMap[computedCSSElement("font-style")] || "normal"; + css["text-align"] = TextAlignMap[computedCSSElement("text-align")] || "left"; + tmp = FontWeightMap[computedCSSElement("font-weight")] || "normal"; + if (tmp === "bold") { + if (css["font-style"] === "normal") { + css["font-style"] = tmp; + } else { + css["font-style"] = tmp + css["font-style"]; + } + } + css["font-size"] = ResolveUnitedNumber(computedCSSElement("font-size")) || 1; + css["line-height"] = ResolveUnitedNumber(computedCSSElement("line-height")) || 1; + css["display"] = (computedCSSElement("display") === "inline" ? "inline" : "block"); + + tmp = (css["display"] === "block"); + css["margin-top"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-top")) || 0; + css["margin-bottom"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-bottom")) || 0; + css["padding-top"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-top")) || 0; + css["padding-bottom"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-bottom")) || 0; + css["margin-left"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-left")) || 0; + css["margin-right"] = tmp && ResolveUnitedNumber(computedCSSElement("margin-right")) || 0; + css["padding-left"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-left")) || 0; + css["padding-right"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-right")) || 0; + + //float and clearing of floats + css["float"] = FloatMap[computedCSSElement("cssFloat")] || "none"; + css["clear"] = ClearMap[computedCSSElement("clear")] || "none"; + return css; + }; + elementHandledElsewhere = function (element, renderer, elementHandlers) { + var handlers, + i, + isHandledElsewhere, + l, + t; + isHandledElsewhere = false; + i = void 0; + l = void 0; + t = void 0; + handlers = elementHandlers["#" + element.id]; + if (handlers) { + if (typeof handlers === "function") { + isHandledElsewhere = handlers(element, renderer); + } else { + i = 0; + l = handlers.length; + while (!isHandledElsewhere && i !== l) { + isHandledElsewhere = handlers[i](element, renderer); + i++; + } + } + } + handlers = elementHandlers[element.nodeName]; + if (!isHandledElsewhere && handlers) { + if (typeof handlers === "function") { + isHandledElsewhere = handlers(element, renderer); + } else { + i = 0; + l = handlers.length; + while (!isHandledElsewhere && i !== l) { + isHandledElsewhere = handlers[i](element, renderer); + i++; + } + } + } + return isHandledElsewhere; + }; + tableToJson = function (table, renderer) { + var data, + headers, + i, + j, + rowData, + tableRow, + table_obj, + table_with, + cell, + l; + data = []; + headers = []; + i = 0; + l = table.rows[0].cells.length; + table_with = table.clientWidth; + while (i < l) { + cell = table.rows[0].cells[i]; + headers[i] = { + name : cell.textContent.toLowerCase().replace(/\s+/g, ''), + prompt : cell.textContent.replace(/\r?\n/g, ''), + width : (cell.clientWidth / table_with) * renderer.pdf.internal.pageSize.width + }; + i++; + } + i = 1; + while (i < table.rows.length) { + tableRow = table.rows[i]; + rowData = {}; + j = 0; + while (j < tableRow.cells.length) { + rowData[headers[j].name] = tableRow.cells[j].textContent.replace(/\r?\n/g, ''); + j++; + } + data.push(rowData); + i++; + } + return table_obj = { + rows : data, + headers : headers + }; + }; + var SkipNode = { + SCRIPT : 1, + STYLE : 1, + NOSCRIPT : 1, + OBJECT : 1, + EMBED : 1, + SELECT : 1 + }; + var listCount = 1; + DrillForContent = function (element, renderer, elementHandlers) { + var cn, + cns, + fragmentCSS, + i, + isBlock, + l, + px2pt, + table2json, + cb; + cns = element.childNodes; + cn = void 0; + fragmentCSS = GetCSS(element); + isBlock = fragmentCSS.display === "block"; + if (isBlock) { + renderer.setBlockBoundary(); + renderer.setBlockStyle(fragmentCSS); + } + px2pt = 0.264583 * 72 / 25.4; + i = 0; + l = cns.length; + while (i < l) { + cn = cns[i]; + if (typeof cn === "object") { + + //execute all watcher functions to e.g. reset floating + renderer.executeWatchFunctions(cn); + + /*** HEADER rendering **/ + if (cn.nodeType === 1 && cn.nodeName === 'HEADER') { + var header = cn; + //store old top margin + var oldMarginTop = renderer.pdf.margins_doc.top; + //subscribe for new page event and render header first on every page + renderer.pdf.internal.events.subscribe('addPage', function (pageInfo) { + //set current y position to old margin + renderer.y = oldMarginTop; + //render all child nodes of the header element + DrillForContent(header, renderer, elementHandlers); + //set margin to old margin + rendered header + 10 space to prevent overlapping + //important for other plugins (e.g. table) to start rendering at correct position after header + renderer.pdf.margins_doc.top = renderer.y + 10; + renderer.y += 10; + }, false); + } + + if (cn.nodeType === 8 && cn.nodeName === "#comment") { + if (~cn.textContent.indexOf("ADD_PAGE")) { + renderer.pdf.addPage(); + renderer.y = renderer.pdf.margins_doc.top; + } + + } else if (cn.nodeType === 1 && !SkipNode[cn.nodeName]) { + /*** IMAGE RENDERING ***/ + var cached_image; + if (cn.nodeName === "IMG") { + var url = cn.getAttribute("src"); + cached_image = images[renderer.pdf.sHashCode(url) || url]; + } + if (cached_image) { + if ((renderer.pdf.internal.pageSize.height - renderer.pdf.margins_doc.bottom < renderer.y + cn.height) && (renderer.y > renderer.pdf.margins_doc.top)) { + renderer.pdf.addPage(); + renderer.y = renderer.pdf.margins_doc.top; + //check if we have to set back some values due to e.g. header rendering for new page + renderer.executeWatchFunctions(cn); + } + + var imagesCSS = GetCSS(cn); + var imageX = renderer.x; + var fontToUnitRatio = 12 / renderer.pdf.internal.scaleFactor; + + //define additional paddings, margins which have to be taken into account for margin calculations + var additionalSpaceLeft = (imagesCSS["margin-left"] + imagesCSS["padding-left"])*fontToUnitRatio; + var additionalSpaceRight = (imagesCSS["margin-right"] + imagesCSS["padding-right"])*fontToUnitRatio; + var additionalSpaceTop = (imagesCSS["margin-top"] + imagesCSS["padding-top"])*fontToUnitRatio; + var additionalSpaceBottom = (imagesCSS["margin-bottom"] + imagesCSS["padding-bottom"])*fontToUnitRatio; + + //if float is set to right, move the image to the right border + //add space if margin is set + if (imagesCSS['float'] !== undefined && imagesCSS['float'] === 'right') { + imageX += renderer.settings.width - cn.width - additionalSpaceRight; + } else { + imageX += additionalSpaceLeft; + } + + renderer.pdf.addImage(cached_image, imageX, renderer.y + additionalSpaceTop, cn.width, cn.height); + cached_image = undefined; + //if the float prop is specified we have to float the text around the image + if (imagesCSS['float'] === 'right' || imagesCSS['float'] === 'left') { + //add functiont to set back coordinates after image rendering + renderer.watchFunctions.push((function(diffX , thresholdY, diffWidth, el) { + //undo drawing box adaptions which were set by floating + if (renderer.y >= thresholdY) { + renderer.x += diffX; + renderer.settings.width += diffWidth; + return true; + } else if(el && el.nodeType === 1 && !SkipNode[el.nodeName] && renderer.x+el.width > (renderer.pdf.margins_doc.left + renderer.pdf.margins_doc.width)) { + renderer.x += diffX; + renderer.y = thresholdY; + renderer.settings.width += diffWidth; + return true; + } else { + return false; + } + }).bind(this, (imagesCSS['float'] === 'left') ? -cn.width-additionalSpaceLeft-additionalSpaceRight : 0, renderer.y+cn.height+additionalSpaceTop+additionalSpaceBottom, cn.width)); + //reset floating by clear:both divs + //just set cursorY after the floating element + renderer.watchFunctions.push((function(yPositionAfterFloating, pages, el) { + if (renderer.y < yPositionAfterFloating && pages === renderer.pdf.internal.getNumberOfPages()) { + if (el.nodeType === 1 && GetCSS(el).clear === 'both') { + renderer.y = yPositionAfterFloating; + return true; + } else { + return false; + } + } else { + return true; + } + }).bind(this, renderer.y+cn.height, renderer.pdf.internal.getNumberOfPages())); + + //if floating is set we decrease the available width by the image width + renderer.settings.width -= cn.width+additionalSpaceLeft+additionalSpaceRight; + //if left just add the image width to the X coordinate + if (imagesCSS['float'] === 'left') { + renderer.x += cn.width+additionalSpaceLeft+additionalSpaceRight; + } + } else { + //if no floating is set, move the rendering cursor after the image height + renderer.y += cn.height + additionalSpaceBottom; + } + + /*** TABLE RENDERING ***/ + } else if (cn.nodeName === "TABLE") { + table2json = tableToJson(cn, renderer); + renderer.y += 10; + renderer.pdf.table(renderer.x, renderer.y, table2json.rows, table2json.headers, { + autoSize : false, + printHeaders : true, + margins : renderer.pdf.margins_doc + }); + renderer.y = renderer.pdf.lastCellPos.y + renderer.pdf.lastCellPos.h + 20; + } else if (cn.nodeName === "OL" || cn.nodeName === "UL") { + listCount = 1; + if (!elementHandledElsewhere(cn, renderer, elementHandlers)) { + DrillForContent(cn, renderer, elementHandlers); + } + renderer.y += 10; + } else if (cn.nodeName === "LI") { + var temp = renderer.x; + renderer.x += cn.parentNode.nodeName === "UL" ? 22 : 10; + renderer.y += 3; + if (!elementHandledElsewhere(cn, renderer, elementHandlers)) { + DrillForContent(cn, renderer, elementHandlers); + } + renderer.x = temp; + } else if (cn.nodeName === "BR") { + renderer.y += fragmentCSS["font-size"] * renderer.pdf.internal.scaleFactor; + } else { + if (!elementHandledElsewhere(cn, renderer, elementHandlers)) { + DrillForContent(cn, renderer, elementHandlers); + } + } + } else if (cn.nodeType === 3) { + var value = cn.nodeValue; + if (cn.nodeValue && cn.parentNode.nodeName === "LI") { + if (cn.parentNode.parentNode.nodeName === "OL") { + value = listCount++ + '. ' + value; + } else { + var fontPx = fragmentCSS["font-size"] * 16; + var radius = 2; + if (fontPx > 20) { + radius = 3; + } + cb = function (x, y) { + this.pdf.circle(x, y, radius, 'FD'); + }; + } + } + renderer.addText(value, fragmentCSS); + } else if (typeof cn === "string") { + renderer.addText(cn, fragmentCSS); + } + } + i++; + } + + if (isBlock) { + return renderer.setBlockBoundary(cb); + } + }; + images = {}; + loadImgs = function (element, renderer, elementHandlers, cb) { + var imgs = element.getElementsByTagName('img'), + l = imgs.length, found_images, + x = 0; + function done() { + renderer.pdf.internal.events.publish('imagesLoaded'); + cb(found_images); + } + function loadImage(url, width, height) { + if (!url) + return; + var img = new Image(); + found_images = ++x; + img.crossOrigin = ''; + img.onerror = img.onload = function () { + if(img.complete) { + //to support data urls in images, set width and height + //as those values are not recognized automatically + if (img.src.indexOf('data:image/') === 0) { + img.width = width || img.width || 0; + img.height = height || img.height || 0; + } + //if valid image add to known images array + if (img.width + img.height) { + var hash = renderer.pdf.sHashCode(url) || url; + images[hash] = images[hash] || img; + } + } + if(!--x) { + done(); + } + }; + img.src = url; + } + while (l--) + loadImage(imgs[l].getAttribute("src"),imgs[l].width,imgs[l].height); + return x || done(); + }; + checkForFooter = function (elem, renderer, elementHandlers) { + //check if we can found a