<!DOCTYPE html> <html lang="en" ng-app="myModel"> <head> <meta charset="UTF-8"> <title>勾選和分頁組件之angular1.6.2版</title> <script type="text/javascript" src="https://cdn.bootcss.com/angular.js/1.6.2/angular.js"></script> <style> .simpleDialog { position: fixed; width: 100%; height: 100%; top: 0; left: 0; display: flex; justify-content: center; align-items: center; } .simpleDialog .mask { position: fixed; width: 100%; height: 100%; top: 0; left: 0; background: black; opacity: 0.5; } .simpleDialog .content { position: fixed; background: white; opacity: 1; display: flex; flex-direction: column; } .simpleDialog .content .title { display: flex; background: blue; color: white; padding: 10px; cursor: pointer; } .simpleDialog .content .title .titleText { flex: 1; } .simpleDialog .content .title .titleCross { width: 10px; padding: 0 5px; } .simpleDialog .content .tip { flex: 1; display: flex; align-items: center; justify-content: center; } .simpleDialog .content .conform { display: flex; justify-content: center; padding: 10px; background: blue; } .complexDialog { position: fixed; width: 100%; height: 100%; top: 0; left: 0; display: flex; justify-content: center; align-items: center; } .complexDialog .mask { position: fixed; width: 100%; height: 100%; top: 0; left: 0; background: black; opacity: 0.5; } .complexDialog .content { position: fixed; background: white; opacity: 1; display: flex; flex-direction: column; } .complexDialog .content .title { display: flex; background: blue; color: white; padding: 10px; cursor: pointer; } .complexDialog .content .title .titleText { flex: 1; } .complexDialog .content .title .titleCross { width: 10px; padding: 0 5px; } .complexDialog .content .tip { flex: 1; display: flex; align-items: center; justify-content: center; } .complexDialog .content .conform { display: flex; justify-content: center; padding: 10px; background: blue; } table { border-collapse: collapse; border: 1px solid #cbcbcb; } table td, table th { padding: 5px; border: 1px solid #cbcbcb; } table thead { background-color: #e0e0e0; color: #000; text-align: left; } .filter { width: 998px; border: 1px solid gray; padding: 10px 0px; } .filter .line { display: flex; } .filter .line .group { width: 330px; } .filter .line .group .label { display: inline-block; width: 120px; height: 24px; line-height: 24px; text-align: right; } .filter .line .group .input { display: inline-block; width: 180px; height: 24px; line-height: 24px; border-radius: 3px; } .filter .line .group .select { display: inline-block; width: 188px; height: 26px; line-height: 26x; border-radius: 3px; } .wholeCircle { position: fixed; width: 100%; height: 100%; left: 0; top: 0; background: rgb(145, 138, 138); opacity: 0.5; z-index: 100; user-select: none; display: flex; justify-content: center; align-items: center; } .wholeCircle .content { background: #fff; border-radius: 5px; overflow: hidden; z-index: 101; box-shadow: 5px 2px 6px #000; width: 100px; display: flex; flex-direction: column; align-items: center; } @keyframes customCircle { 0% { transform: rotate(0deg); } 100% { transform: rotate(-360deg); } } .circle { animation: customCircle 1s infinite linear; } </style> </head> <body> <div ng-controller="thisCtrl"> <div>onkeydown:按下鍵盤上的某個鍵時,鼠標聚焦的網頁元素的onkeydown事件將被觸發</div> <button ng-click="clickButtonSimple()" style="margin-top: 30px; z-index: 250"> 點擊出現簡單彈窗 </button> <simple-dialog required-data="requiredDataSimple"></simple-dialog> <button ng-click="clickButtonComplex()" style="margin-top: 30px; z-index: 250"> 點擊出現復雜彈窗 </button> <complex-dialog required-data="requiredDataComplex"> <div> <div> <div style="padding: 5px 0; color: red"> <button style="color: red" ng-click="divideDatas.getResultOfCheckAndFilter(divideDatas.isShowFilter,divideDatas.isUseFilter,divideDatas.filterOptions)" > 獲取勾選和過濾結果 </button> <span ng-bind="divideDatas.toServerDatas"></span> </div> <div style="padding-bottom: 5px"> <img src="{{checkDatas.stateAllPages&&checkDatas.allExcludedIds.length===0?checkImg.yes:checkImg.no}}" ng-click="checkDatas.clickAllPages(divideDatas.tableDatas)" /> <span ng-bind="checkDatas.textAllPages"></span> </div> <div style="padding-bottom: 5px"> <button ng-click="divideDatas.toggleShowFilter()"> {{divideDatas.isShowFilter?'關閉過濾':'使用過濾'}} </button> <button ng-click="divideDatas.emptyFilterOptions({value5:'已讀后台'})"> 清空過濾 </button> <button ng-click="divideDatas.request(1)">刷新</button> </div> <div style="margin-bottom: 5px" class="filter" ng-show="divideDatas.isShowFilter" > <div class="line"> <div class="group"> <label class="label">標簽</label> <input class="input" type="text" ng-model="divideDatas.filterOptions.value1" /> </div> <div class="group"> <label class="label">這就是長標簽</label> <input class="input" type="text" ng-model="divideDatas.filterOptions.value2" /> </div> <div class="group"> <label class="label">標簽</label> <input class="input" type="text" ng-model="divideDatas.filterOptions.value3" /> </div> </div> <div class="line" style="padding-top: 10px"> <div class="group"> <label class="label">這就是長標簽</label> <input class="input" type="text" ng-model="divideDatas.filterOptions.value4" /> </div> <div class="group"> <label class="label">下拉框</label> <select class="select" ng-model="divideDatas.filterOptions.value5" ng-options="item.back as item.front for item in resultDo" ></select> </div> <div class="group"> <label class="label"></label> <button style="width: 188px; height: 28px" ng-click="divideDatas.useFilter()" > 過濾 </button> </div> </div> </div> <table style="width: 1000px"> <thead> <tr> <th> <img src="{{checkDatas.stateThisPage?checkImg.yes:checkImg.no}}" ng-click="checkDatas.clickThisPage(divideDatas.tableDatas,divideDatas.allItemsNum)" /> </th> <th>序號</th> <th>數據1</th> <th>數據2</th> <th>數據3</th> <th>數據4</th> <th>數據5</th> <th>數據6</th> </tr> </thead> <tbody> <tr ng-repeat="data in divideDatas.tableDatas track by $index"> <td> <img src="{{data.state?checkImg.yes:checkImg.no}}" ng-click="checkDatas.clickSingleItem(data,divideDatas.tableDatas,divideDatas.allItemsNum)" /> </td> <td ng-bind="(divideDatas.nowPageNum-1)*10 + ($index+1)"></td> <td ng-bind="data.key1"></td> <td ng-bind="data.key2"></td> <td ng-bind="data.key3"></td> <td ng-bind="data.key4"></td> <td ng-bind="data.key5"></td> <td ng-bind="data.key6"></td> </tr> </tbody> </table> <divide-page divide-datas="divideDatas" check-datas="checkDatas" ></divide-page> </div> <div style="background: cornflowerblue; margin-top: 10px"> 除了上面的表格(含過濾、勾選、分頁),此處也可以放入表單 </div> </div> </complex-dialog> </div> </body> <script> var app = angular.module('myModel', []); app.controller('thisCtrl', function ($scope,dividePage,checkBox,checkImg) { $scope.modelData = { value: 5 }; $scope.change = function (value) { console.log(value); }; $scope.submit = function () { console.log('此處向后台發送請求'); }; $scope.requiredDataSimple = { simpleDialogTitleId: 'wholeTitleId', simpleDialogContentId: 'wholeContentId' }; $scope.clickButtonSimple = function () { $scope.requiredDataSimple.isShow = true; $scope.requiredDataSimple.width = '600px'; $scope.requiredDataSimple.title = '詳情'; $scope.requiredDataSimple.tip = '提交失敗'; $scope.requiredDataSimple.zIndex = 10; }; $scope.requiredDataComplex = { complexDialogTitleId: 'wholeTitleId1', complexDialogContentId: 'wholeContentId1' }; $scope.clickButtonComplex = function () { $scope.requiredDataComplex.isShow = true; $scope.requiredDataComplex.width = '1060px'; $scope.requiredDataComplex.height = '700px'; $scope.requiredDataComplex.title = '詳情'; $scope.requiredDataComplex.zIndex = 10; $scope.requiredDataComplex.cancel = function () { console.log('cancel'); }; }; $scope.checkImg = checkImg; $scope.divideDatas = dividePage({ url: '', method: 'post', nowPageNumFromServer: 'nowPageNumFromServer111', allPagesNumFromServer: 'allPagesNumFromServer111', allItemsNumFromServer: 'allItemsNumFromServer111', eachPageItemsNumFromServer: 'eachPageItemsNumFromServer111', tableDatasKey: 'tableDatasArray' }); $scope.checkDatas = checkBox('id'); $scope.divideDatas.filterOptions.value5 = '已讀后台'; //$scope.divideDatas.trueCb = function (result) { }; //$scope.divideDatas.errorCb = function (result) { }; $scope.myLog = { resultDo: '已讀后台' }; $scope.resultDo = [ { front: '全部前端', back: '全部后台' }, { front: '已讀前端', back: '已讀后台' }, { front: '未讀前端', back: '未讀后台' } ]; }); app.directive('complexDialog', function () { var html = ` <div class="complexDialog" ng-show="requiredData.isShow" ng-style="{ 'z-index': requiredData.zIndex? requiredData.zIndex:10}"> <div class="mask" ng-show="requiredData.isShow" ng-click="close()"></div> <div class="content" ng-show="requiredData.isShow" id="{{requiredData.complexDialogContentId}}" ng-style="{ 'width': requiredData.width? requiredData.width:'400px','height': requiredData.height? requiredData.height:'400px', }"> <div class="title"> <span class="titleText" id="{{requiredData.complexDialogTitleId}}" ng-bind="requiredData.title||'系統消息'"></span> <span class="titleCross" ng-click="close()">X</span> </div> <div class="tip"> <div ng-transclude></div> </div> <div class="conform" ng-hide="requiredData.isHideBottom"> <button ng-hide="requiredData.isHideCancel" ng-click="cancel()" style="margin-right:30px">{{requiredData.cancelText||"取消"}}</button> <button ng-hide="requiredData.isHideSubmit" ng-click="submit()">{{requiredData.submitText||"提交"}}</button> </div> <div> </div> `; return { restrict: 'E', template: html, transclude: true, scope: { requiredData: '=' }, controller: function ($scope, drag, $timeout) { $scope.drag = drag; $scope.close = function () { $scope.requiredData.isShow = false; angular .element( document.getElementById( $scope.requiredData.complexDialogContentId ) ) .css({ top: '50%', left: '50%', transform: 'translate(-50%, -50%)' }); }; $scope.cancel = function () { if (angular.isFunction($scope.requiredData.cancel)) { $scope.requiredData.cancel(); } $scope.close(); }; $scope.submit = function () { if (angular.isFunction($scope.requiredData.submit)) { $scope.requiredData.submit(); } $scope.close(); }; $timeout(function () { $scope.drag( $scope.requiredData.complexDialogTitleId, $scope.requiredData.complexDialogContentId ); }); }, link: function () {} }; }); app.factory('checkBox', function () { return function (idKey) { return { idKey: idKey ? idKey : 'id', //每條數據的唯一標志 stateThisPage: false, //當前頁所有項是否全選 allIncludedIds: [], //所有被選中數據的ID構成的數組 allExcludedIds: [], //所有沒被選中數據的ID構成的數組 textAllPages: '全選未啟用,沒有選擇任何項!', //復選框被點擊后的提示文字。 stateAllPages: false, //復選框被點擊后的提示文字。 init: function () { //點擊“刷新”、“過濾”、“清除過濾”時執行 this.idKey = idKey ? idKey : 'id'; this.allIncludedIds = []; this.allExcludedIds = []; this.textAllPages = '全選未啟用,沒有選擇任何項!'; this.stateAllPages = false; this.stateThisPage = false; }, clickAllPages: function (itemArray) { //所有頁所有條目全選復選框被點擊時執行的函數 if (this.stateAllPages) { if (this.allExcludedIds.length > 0) { this.stateAllPages = true; this.stateThisPage = true; this.textAllPages = '全選已啟用,沒有排除任何項!'; angular.forEach(itemArray, function (item) { item.state = true; }); } else if (this.allExcludedIds.length == 0) { this.stateAllPages = false; this.stateThisPage = false; this.textAllPages = '全選未啟用,沒有選擇任何項!'; angular.forEach(itemArray, function (item) { item.state = false; }); } } else { this.stateAllPages = true; this.stateThisPage = true; this.textAllPages = '全選已啟用,沒有排除任何項!'; angular.forEach(itemArray, function (item) { item.state = true; }); } this.allExcludedIds = []; this.allIncludedIds = []; }, clickThisPage: function (itemsArray, allItemsNum) { //當前頁所有條目全選復選框被點擊時執行的函數 var that = this; this.stateThisPage = !this.stateThisPage; angular.forEach(itemsArray, function (item) { item.state = that.stateThisPage; if (item.state) { that.delID(item[that.idKey], that.allExcludedIds); that.addID(item[that.idKey], that.allIncludedIds); } else { that.delID(item[that.idKey], that.allIncludedIds); that.addID(item[that.idKey], that.allExcludedIds); } }); if (this.stateAllPages) { if (this.stateThisPage && this.allExcludedIds.length === 0) { this.textAllPages = '全選已啟用,沒有排除任何項!'; } else { this.textAllPages = '全選已啟用,已排除' + this.allExcludedIds.length + '項!排除項的ID為:' + this.allExcludedIds; } } else { if (!this.stateThisPage && this.allIncludedIds.length === 0) { this.textAllPages = '全選未啟用,沒有選擇任何項!'; } else { this.textAllPages = '全選未啟用,已選擇' + this.allIncludedIds.length + '項!選擇項的ID為:' + this.allIncludedIds; } } }, clickSingleItem: function (item, itemsArray, allItemsNum) { //當前頁單個條目復選框被點擊時執行的函數 var that = this; item.state = !item.state; if (item.state) { this.stateThisPage = true; this.addID(item[this.idKey], this.allIncludedIds); this.delID(item[this.idKey], this.allExcludedIds); angular.forEach(itemsArray, function (item) { if (!item.state) { that.stateThisPage = false; } }); } else { this.stateThisPage = false; this.addID(item[this.idKey], this.allExcludedIds); this.delID(item[this.idKey], this.allIncludedIds); } if (this.stateAllPages) { if (this.stateThisPage && this.allExcludedIds.length === 0) { this.textAllPages = '全選已啟用,沒有排除任何項!'; } else { this.textAllPages = '全選已啟用,已排除' + this.allExcludedIds.length + '項!排除項的ID為:' + this.allExcludedIds; } } else { if (!this.stateThisPage && this.allIncludedIds.length === 0) { this.textAllPages = '全選未啟用,沒有選擇任何項!'; } else { this.textAllPages = '全選未啟用,已選擇' + this.allIncludedIds.length + '項!選擇項的ID為:' + this.allIncludedIds; } } }, signCheckbox: function (itemsArray) { //標注當前頁被選中的條目,在翻頁成功后執行。 var that = this; if (this.stateAllPages) { this.stateThisPage = true; angular.forEach(itemsArray, function (item) { var thisID = item[that.idKey]; var index = that.allExcludedIds.indexOf(thisID); if (index > -1) { item.state = false; that.stateThisPage = false; } else { item.state = true; } }); } else { this.stateThisPage = true; angular.forEach(itemsArray, function (item) { var thisID = item[that.idKey]; var index = that.allIncludedIds.indexOf(thisID); if (index === -1) { item.state = false; that.stateThisPage = false; }else{ item.state = true; } }); } }, addID: function (id, idArray) { var index = idArray.indexOf(id); if (index === -1) { idArray.push(id); //如果當前頁的單項既有勾選又有非勾選,這時勾選當前頁全選,需要這個判斷,以免重復添加 } }, delID: function (id, idArray) { var index = idArray.indexOf(id); if (index > -1) { idArray.splice(index, 1); } } }; }; }); app.factory('checkImg', function () { return { yes: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAADqADAAQAAAABAAAADgAAAAC98Dn6AAAA+UlEQVQoFZWSMU4DMRBF/584G7QSRcIxuAZKEykNEiUVHVTQRaKh4AIcgAvQpkukVDlBOAYNSGSlXXuwpViyYYFdS9aMZ/6bsezh5HZ3T2KhqkfosEhWqnjkyd1u3xWKdQMsfaEAB0Zilf8swfdU0w0klmpGpz1BvpbHcklbPf8Okts0CfJtWBTz/Yc++Jc8S3PZVQfKGwiuvMD6XYsMzm1dT/1jXKdQ8E0asHRrAzOzbC6UGINWHPQp1UQ/6wjF2LpmJSKfhti4Bi8+lhWP4I+gAqV1uqSi8j9WRuF3m3eMWVUJBeKxzUoYn7bEX7HDyPmB7QEHbRjyL+/+VnuXDUFOAAAAAElFTkSuQmCC', no: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAADqADAAQAAAABAAAADgAAAAC98Dn6AAAAbklEQVQoFWM8c+ZMLQMDQxUQcwAxMeAHUFEbC5CoYmNj02ZmZn5FjK6/f/+K/fr16ypIIwdIk7a29hdiNF69ehWkjIOJGMXY1IxqxBYqULEhFDiglPMDlIygKQKPryBSILUgPSCNbaC0B6RJSuQAbowizhJuOsAAAAAASUVORK5CYII=' }; }); app.factory('cyRequest', function ($http, wholeService) { function thisHttp(clientDatas, deferred) { var toServerDatas = { method: clientDatas.method, url: clientDatas.url }; var dataOrParams = clientDatas.dataOrParams || 'data'; toServerDatas[dataOrParams] = clientDatas.AllParams; if (clientDatas.responseType) { toServerDatas.responseType = clientDatas.responseType; } if (clientDatas.isUseWholeCircle) { //多條件全局轉圈時,不在這里配置,使用時才配置 wholeService.isShow = true; } if (clientDatas.isUsePartCircle) { clientDatas.partCircle.isShow = true; } $http(toServerDatas) .then(function (result) { //result.status(不是result.clientDatas.status)===200時進入這里,否則進入catch if (clientDatas.isDirectUseDatas) { deferred.resolve(result); //如果出錯就一直轉圈,那么可以把finally里的代碼放到這里 } else { if (result.clientDatas.status === 1000) { //全局彈窗告知結果 } else if (result.clientDatas.status === 0) { //全局彈窗告知結果 } else { deferred.resolve(result.clientDatas); //如果出錯就一直轉圈,那么可以把finally里的代碼放到這里 } } }) .catch(function (err) { deferred.reject(err); }) .finally(function () { if (clientDatas.isUseWholeCircle) { //多條件全局轉圈時,不在這里配置,使用時才配置 wholeService.isShow = false; } if (clientDatas.isUsePartCircle) { clientDatas.partCircle.isShow = false; } }); } return function (clientDatas) { var deferred = $q.defer(); if (clientDatas.warn) { //全局彈窗告知結果 $scope.requiredData = { isShow: true, width: '400px', title: '詳情', tip: '確認提交', submit: function () { thisHttp(clientDatas, deferred); } }; } else { thisHttp(clientDatas, deferred); } return deferred.promise; }; // cyRequest({ // method: 'post', // url: 'a/b/c', // warn: '確定提交嗎?', // dataOrParams: 'data', // AllParams: {key:1}, // isUseWholeCircle: false,//是否使用全局轉圈 // isUsePartCircle: true,//是否使用局部轉圈 // partCircle: $scope.thisCircle,//把當前頁控制局部轉圈隱現的變量告訴cyRequest // }) //$scope.thisCircle = { isShow : false } //<part-circle is-show='thisCircle'></part-circle> }); app.factory('dividePage', function () { return function (divideDatas) { //下面這些數據,在實例化后,發送給后台之前,有可能會改變 return { //1、請求配置1(路由和方式) url: divideDatas.url || '', method: divideDatas.method || 'post', //2、請求配置2(請求參數的key,前端通過這個配置,發送數據給后台) nowPageNumToServer: divideDatas.nowPageNumToServer || 'nowPageNumToServer', //發送給后台的當前頁碼key allPagesNumToServer: divideDatas.allPagesNumToServer || 'allPagesNumToServer', //發送給后台的所有頁頁數key allItemsNumToServer: divideDatas.allItemsNumToServer || 'allItemsNumToServer', //發送給后台的所有頁數據數key eachPageItemsNumToServer: divideDatas.eachPageItemsNumToServer || 'eachPageItemsNumToServer', //發送給后台的每頁最多數據數key //3、響應配置(返回數據的key,前端通過這個配置,獲取后台的數據) nowPageNumFromServer: divideDatas.nowPageNumFromServer || 'nowPageNumFromServer', //來自服務器的當前頁碼key allPagesNumFromServer: divideDatas.allPagesNumFromServer || 'allPagesNumFromServer', //來自服務器的所有頁頁數key allItemsNumFromServer: divideDatas.allItemsNumFromServer || 'allItemsNumFromServer', //來自服務器的所有頁數據數key eachPageItemsNumFromServer: divideDatas.eachPageItemsNumFromServer || 'eachPageItemsNumFromServer', //來自服務器的每頁最多數據數key tableDatasKey: divideDatas.tableDatasKey || 'tableDatasArray', //來自服務器的表格數據key //4、分頁初始化配置(分頁在本頁面首次渲染時,使用該數據) nowPageNum: 0, //當前頁數 allPagesNum: 0, //所有頁數 allItemsNum: 0, //所有頁所有條目數 eachPageItemsNum: divideDatas.eachPageItemsNum || 10, //每頁展示條目數 //5、初始化以下數據,供頁面使用(前端根據需要決定,不受后台影響) otherDatas: {}, //頁碼、頁條目數、過濾條件外的參數,調用divideDatas.request函數,重新渲染頁面。 dataOrParams: 'data', //參數放在哪個配置下,只有data和Params兩個選擇 filterOptions: {}, //過濾條件 isShowFilter: false, //是否顯示過濾條件。有時默認false時,顯示一部分過濾條件,點擊“展開”后,顯示剩余過濾條件 isUseFilter: false, //是否使用過濾條件。點擊過濾后,才使用過濾條件。 isInit: divideDatas.isInit || false, //是否立即向后台發送請求 isNoUsePartCircle: divideDatas.isNoUsePartCircle || false, //是否不使用局部轉圈 partCircle: divideDatas.partCircle || {}, //把當前頁控制局部轉圈隱現的變量告訴cyRequest frontMoreText: divideDatas.frontMoreText || '', //('文字 ')或者("文字 "+result.numOne+" 文字 "), totalText: divideDatas.totalText || '共', //, totalUnit: divideDatas.totalUnit || '條', //總數據的單位 backMoreText: divideDatas.backMoreText || '', //(' 文字')或者("文字 "+result.numThree+" 文字"), //6、以下是現成方法,調用即可 toggleShowFilter: function () { //過濾條件打開或關閉時執行的函數 this.isUseFilter = false; this.isShowFilter = !this.isShowFilter; if (!this.isShowFilter) { this.request(1); } }, useFilter: function () { //點擊過濾時執行的函數 this.isUseFilter = true; this.request(1); }, emptyFilterOptions: function (extraObject) { //清空過濾條件時執行的函數 //清空選項時,所有值恢復成默認 var that = this; angular.forEach(that.filterOptions, function (value, key) { //大部分選項的默認值是undefined that.filterOptions[key] = undefined; }); if (extraObject) { //小部分選項的默認值不是undefined angular.forEach(extraObject, function (value, key) { that.filterOptions[key] = value; }); } this.request(1); } }; }; }); app.factory('drag', function () { return function (wholeTitleId, wholeContentId) { var oDiv = document.getElementById(wholeContentId); oDiv.onmousedown = down; function processThis(fn, nowThis) { return function (event) { fn.call(nowThis, event); }; } function down(event) { event = event || window.event; if (event.target.id != wholeTitleId) return; this.initOffsetLeft = this.offsetLeft; this.initOffsetTop = this.offsetTop; this.initClientX = event.clientX; this.initClientY = event.clientY; this.maxOffsetWidth = (document.documentElement.clientWidth || document.body.clientWidth) - this.offsetWidth; this.maxOffsetHeight = (document.documentElement.clientHeight || document.body.clientHeight) - this.offsetHeight; if (this.setCapture) { this.setCapture(); this.onmousemove = processThis(move, this); this.onmouseup = processThis(up, this); } else { document.onmousemove = processThis(move, this); document.onmouseup = processThis(up, this); } } function move(event) { var nowLeft = this.initOffsetLeft + (event.clientX - this.initClientX); var nowTop = this.initOffsetTop + (event.clientY - this.initClientY); this.style.left = nowLeft + 'px'; this.style.top = nowTop + 'px'; } function up() { if (this.releaseCapture) { this.releaseCapture(); this.onmousemove = null; this.onmouseup = null; } else { document.onmousemove = null; document.onmouseup = null; } } }; }); app.directive('dividePage', function () { var html = ` <div ng-show="divideDatas.allPagesNum>=1" style="display:flex;width:1000px;margin-top:20px;"> <div> <div> <button ng-hide="divideDatas.allPagesNum<=10" ng-click="clickDividePage('front') " ng-disabled="divideDatas.nowPageNum===1" >上一頁</button> <button ng-repeat="num in divideArray track by $index" ng-bind="num" ng-click="clickDividePage(num) " ng-style="num===divideDatas.nowPageNum?{ 'color':'red'}:{'color':'black'}" ng-disabled="num==='...'" style="margin:0 3px;" > </button> <button ng-hide="divideDatas.allPagesNum<=10" ng-click="clickDividePage('back') " ng-disabled="divideDatas.nowPageNum===divideDatas.allPagesNum" >下一頁</button> </div> </div> <div style="display:flex; flex:1; justify-content:flex-end;"> <div style="margin-right:20px;"> <span>轉到第</span> <input type="text" ng-model="customString" ng-keydown="clickDividePage('leap',$event)" style="width:30px;"> <span>頁</span> <button ng-click="clickDividePage('leap',{which:13})">Go</button> </div> <div> <span>每頁顯示</span> <select ng-model="divideDatas.eachPageItemsNum" ng-options="item.back as item.front for item in numOptions" ng-disabled="true"></select> <span>條,</span> </div> <div> <span ng-bind="divideDatas.frontMoreText"></span> <span ng-bind="divideDatas.totalText"></span> <span ng-bind="divideDatas.allItemsNum"></span> <span ng-bind="divideDatas.totalUnit"></span> <span ng-bind="divideDatas.backMoreText"></span> </div> </div> </div> `; return { restrict: 'E', template: html, scope: { divideDatas: '=divideDatas', checkDatas: '=checkDatas' }, controller: function ($scope, $timeout /* , cyRequest */) { $scope.request = $scope.divideDatas.request = function (pageNum) { var AllParams = $scope.getResultOfCheckAndFilter( $scope.divideDatas.isShowFilter, $scope.divideDatas.isUseFilter, $scope.divideDatas.filterOptions ); AllParams.nowPageNum = pageNum; console.log(AllParams); // //具體分頁頁面增加下列操作 // //$scope.divideDatas = dividePage({ // // partCircle: $scope.thisCircle // //}); // //$scope.thisCircle = { isShow : false } // //<part-circle is-show='thisCircle'></part-circle> // cyRequest({ // url: $scope.divideDatas.url, // method: $scope.divideDatas.method, // dataOrParams: $scope.divideDatas.dataOrParams, // AllParams: AllParams, // isUsePartCircle: !$scope.divideDatas.isNoUsePartCircle // partCircle: $scope.divideDatas.partCircle // }).then(function () { var data = []; for (var i = 1; i <= 144; i++) { var obj = { id: 'id' + i, key1: '數據' + (i + 0), key2: '數據' + (i + 1), key3: '數據' + (i + 2), key4: '數據' + (i + 3), key5: '數據' + (i + 4), key6: '數據' + (i + 5), key7: '數據' + (i + 6) }; data.push(obj); } var result = { tableDatasArray: [], nowPageNumFromServer111: 5, allPagesNumFromServer111: 15, allItemsNumFromServer111: 144, eachPageItemsNumFromServer111: 10 }; if (angular.isFunction($scope.divideDatas.trueCb)) { $scope.divideDatas.trueCb(result); } else { result.tableDatasArray = data.slice( (pageNum - 1) * 10, pageNum * 10 ); $scope.customString = pageNum || result[$scope.divideDatas.nowPageNumFromServer]; $scope.divideDatas.tableDatas = result[$scope.divideDatas.tableDatasKey]; $scope.divideDatas.nowPageNum = pageNum || result[$scope.divideDatas.nowPageNumFromServer]; $scope.divideDatas.allPagesNum = result[$scope.divideDatas.allPagesNumFromServer]; $scope.divideDatas.allItemsNum = result[$scope.divideDatas.allItemsNumFromServer]; $scope.divideDatas.eachPageItemsNum = result[$scope.divideDatas.eachPageItemsNumFromServer]; if ( $scope.checkDatas && angular.isFunction($scope.checkDatas.signCheckbox) ) { console.log($scope.divideDatas.tableDatas) $scope.checkDatas.signCheckbox($scope.divideDatas.tableDatas); } } $scope.createDividePage(); // }).catch(function(){ // if (angular.isFunction($scope.divideDatas.errorCb)) { // $scope.divideDatas.errorCb(result); // } // }) }; $scope.numOptions = [ { back: 10, front: 10 }, { back: 20, front: 20 }, { back: 30, front: 30 }, { back: 40, front: 40 }, { back: 50, front: 50 } ]; $scope.getResultOfCheckAndFilter = $scope.divideDatas.getResultOfCheckAndFilter = function ( isShowFilter, isUseFilter, filterOptions ) { var checkboxDatas; var toServerDatas; if (!$scope.checkDatas.stateAllPages) { if ($scope.checkDatas.allIncludedIds.length === 0) { //return 彈窗告知:沒有勾選項 } checkboxDatas = { isSelectAll: false, allIncludedIds: $scope.checkDatas.allIncludedIds }; } else { checkboxDatas = { isSelectAll: true, allExcludedIds: $scope.checkDatas.allExcludedIds }; } if (isShowFilter||isUseFilter) { toServerDatas = angular.merge( {}, { checkboxDatas: checkboxDatas }, { filterOptions: filterOptions } ); } else { toServerDatas = angular.merge({}, { checkboxDatas: checkboxDatas }); } this.toServerDatas = toServerDatas; //這行代碼在實際項目中不需要 return toServerDatas; }; $scope.createDividePage = function () { var divideArray = []; var allPagesNum = $scope.divideDatas.allPagesNum; var nowPageNum = $scope.divideDatas.nowPageNum; if (allPagesNum >= 1 && allPagesNum <= 10) { for (var i = 1; i <= allPagesNum; i++) { divideArray.push(i); } } else if (allPagesNum >= 11) { if (nowPageNum > 6) { divideArray.push(1); divideArray.push(2); divideArray.push(3); divideArray.push('...'); divideArray.push(nowPageNum - 1); divideArray.push(nowPageNum); } else { for (i = 1; i <= nowPageNum; i++) { divideArray.push(i); } } // 以上當前頁的左邊,以下當前頁的右邊 if (allPagesNum - nowPageNum >= 6) { divideArray.push(nowPageNum + 1); divideArray.push(nowPageNum + 2); divideArray.push('...'); divideArray.push(allPagesNum - 2); divideArray.push(allPagesNum - 1); divideArray.push(allPagesNum); } else { for (var i = nowPageNum + 1; i <= allPagesNum; i++) { divideArray.push(i); } } } $scope.divideArray = divideArray; }; $scope.clickDividePage = function (stringOfNum, event) { var allPagesNum = $scope.divideDatas.allPagesNum; var nowPageNum = $scope.divideDatas.nowPageNum; if (stringOfNum === 'front' && nowPageNum != 1) { nowPageNum--; } else if (stringOfNum === 'back' && nowPageNum != allPagesNum) { nowPageNum++; } else if (stringOfNum === 'leap') { if (event.which != 13) return; //不攔截情形:(1)聚焦輸入框、按“Enter”鍵時;(2)點擊“GO”時 var customNum = Math.ceil(parseFloat($scope.customString)); if (customNum < 1 || customNum == 'NaN') { nowPageNum = 1; //不給提示 } else if (customNum > allPagesNum) { nowPageNum = allPagesNum; //不給提示 } else { nowPageNum = customNum; } } else { nowPageNum = Math.ceil(parseFloat(stringOfNum)); } $scope.customString = nowPageNum; $scope.request(nowPageNum); }; if (!$scope.divideDatas.isInit) { $scope.request(1); } } }; }); app.factory('waitCircleImg', function () { return { waitCircleImg: 'data:image/png;base64,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' }; }); app.directive('simpleDialog', function () { var html = ` <div class="simpleDialog" ng-show="requiredData.isShow" ng-style="{ 'z-index': requiredData.zIndex? requiredData.zIndex:10}"> <div class="mask" ng-show="requiredData.isShow" ng-click="close()"></div> <div class="content" ng-show="requiredData.isShow" id="{{requiredData.simpleDialogContentId}}" ng-style="{ 'width': requiredData.width? requiredData.width:'400px','height': requiredData.height? requiredData.height:'400px', }"> <div class="title"> <span class="titleText" id="{{requiredData.simpleDialogTitleId}}" ng-bind="requiredData.title||'系統消息'"></span> <span class="titleCross" ng-click="close()">X</span> </div> <div class="tip"> <div ng-bind="requiredData.tip"></div> </div> <div class="conform"> <button ng-click="close()" id="confirm" ng-bind="requiredData.confirmText||'確認'"></button> </div> <div> </div> `; return { restrict: 'E', template: html, scope: { requiredData: '=' }, controller: function ($scope, drag, $timeout) { $scope.drag = drag; $scope.close = function () { $scope.requiredData.isShow = false; angular .element( document.getElementById($scope.requiredData.simpleDialogContentId) ) .css({ top: '50%', left: '50%', transform: 'translate(-50%, -50%)' }); }; $timeout(function () { $scope.drag( $scope.requiredData.simpleDialogTitleId, $scope.requiredData.simpleDialogContentId ); }); }, link: function () { } }; }); app.directive('wholeCircle', function () { var html = ` <div class="wholeCircle" ng-show="thisShow.isShow"> <div class="content"> <img src="{{waitCircleImg.waitCircleImg}}" class="circle" width="50px" height="50px" /> <p ng-transclude ></p> </div> </div> `; return { restrict: 'E', template: html, scope: {}, replace: true, transclude: true, controller: function ($scope, wholeCircle, waitCircleImg) { $scope.waitCircleImg = waitCircleImg; $scope.thisShow = wholeCircle; }, link: function () {} }; }); app.factory('wholeCircle', function () { return { showArray: [], isShow: false, set: function (showArray) { var flag = false; angular.forEach(showArray, function (item) { if (item === true) flag = true; //有一個請求發出,轉圈就出現 }); this.isShow = flag; //所有請求都結束,轉圈消失 } }; }); app.directive('partCircle', function () { var html = ` <div ng-show="isShow"> <img src="{{waitCircle.waitCircle}}" class="circle" width="50px" height="50px"> <p ng-transclude></p> </div> `; return { restrict: 'E', template: html, scope: { isShow: '=isShow' }, replace: true, transclude: true, controller: function ($scope, waitCircle) { $scope.waitCircle = waitCircle; }, link: function () {} }; }); </script> </html>