step.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /**
  2. @Name : layui.step 基于layui的步骤条面板
  3. @Author:hsianglee
  4. @License:MIT
  5. */
  6. layui.define(["jquery"], function (exports) {
  7. var $ = layui.jquery;
  8. function Step(option) {
  9. this.option=option; // 获取传入的数据
  10. this.elem=option.elem;
  11. // this.methods=option.methods?option.methods:"";
  12. this.title=option.title?option.title:[];
  13. this.description=option.description?option.description:[];
  14. this.canIconClick=option.canIconClick?option.canIconClick:false;
  15. this.isOpenStepLevel=option.isOpenStepLevel?option.isOpenStepLevel:false;
  16. this.len=0; // 页面个数
  17. this.currentStep=(option.currentStep && option.currentStep>=1)?option.currentStep:1; // 当前走到第几步
  18. this.disabledStep=[];
  19. this.finalStep=1; // 当前走到最远的步骤
  20. this.parameterInit();
  21. this.domRender();
  22. this.init();
  23. this.openStepLevel();
  24. this.changeStep();
  25. }
  26. Step.prototype={
  27. constructor: Step,
  28. // 初始化参数数据
  29. parameterInit: function() {
  30. var self=this;
  31. this.len=$(this.elem).find(".layui-step-content-item").length; // 页面个数
  32. // 不传title参数
  33. if(this.title.length<=0){
  34. $(this.elem).find(".layui-step-content-item").each(function(index,val) {
  35. self.title.push("第"+(index+1)+"步");
  36. })
  37. }
  38. if(this.len!==this.title.length){
  39. throw "title参数长度与页面长度不匹配";
  40. }
  41. // 不传description参数
  42. if(this.description.length<=0){
  43. $(this.elem).find(".layui-step-content-item").each(function(index,val) {
  44. self.description.push("");
  45. })
  46. }
  47. if(this.len!==this.description.length){
  48. throw "description参数长度与页面长度不匹配";
  49. }
  50. // 若当前步超过最大步,则默认为最后一步
  51. this.currentStep=this.currentStep>=this.len?this.len:this.currentStep;
  52. },
  53. domRender: function() {
  54. var self=this;
  55. var titleStr='<div class="layui-step-title layui-clear">'+
  56. '<div class="layui-step-title-item step-first" style="width: '+(100/this.len)+'%;">'+
  57. '<div class="step-icon">'+
  58. '<i>1</i>'+
  59. '</div>'+
  60. '<div class="step-text">'+
  61. this.title[0]+
  62. '</div>'+
  63. '<div class="step-description">'+
  64. this.description[0]+
  65. '</div>'+
  66. '</div>';
  67. for(var i=1;i<this.title.length-1;i++){
  68. titleStr+='<div class="layui-step-title-item" style="width: '+(100/this.len)+'%;">'+
  69. '<div class="step-icon">'+
  70. '<i>'+(i+1)+'</i>'+
  71. '</div>'+
  72. '<div class="step-text">'+
  73. this.title[i]+
  74. '</div>'+
  75. '<div class="step-description">'+
  76. this.description[i]+
  77. '</div>'+
  78. '</div>';
  79. };
  80. titleStr+='<div class="layui-step-title-item step-last" style="width: '+(100/this.len)+'%;">'+
  81. '<div class="step-icon">'+
  82. '<i>'+this.len+'</i>'+
  83. '</div>'+
  84. '<div class="step-text">'+
  85. this.title[this.title.length-1]+
  86. '</div>'+
  87. '<div class="step-description">'+
  88. this.description[this.title.length-1]+
  89. '</div>'+
  90. '</div>'+
  91. '</div>'
  92. $(this.elem).prepend(titleStr);
  93. // 生成三角
  94. $(this.elem).find(".layui-step-content-item").each(function(index,val) {
  95. $(this).append("<span class='content-item-before' style='left: calc("+((100/(self.len*2))+((100*index)/self.len))+"% - 10px);'></span>");
  96. })
  97. },
  98. // 添加样式
  99. init: function() {
  100. var self=this;
  101. this.disabledStep.forEach(function(val){
  102. $(self.elem).find(".layui-step-title-item").eq(val-1).addClass("step-disabled");
  103. })
  104. $(this.elem).find(".layui-step-title-item").eq(this.currentStep-1).addClass("step-current");
  105. $(this.elem).find(".layui-step-content-item").eq(this.currentStep-1).show();
  106. if(this.currentStep<2) return;
  107. for(var i=this.currentStep-2;i>=0;i--){
  108. $(this.elem).find(".layui-step-title-item").eq(i).addClass("step-finish");
  109. }
  110. },
  111. // 恢复默认样式
  112. reInit: function() {
  113. $(this.elem).find(".layui-step-title-item").each(function(index,val) {
  114. $(val).removeClass("step-disabled");
  115. })
  116. $(this.elem).find(".layui-step-title-item").eq(this.currentStep-1).removeClass("step-current");
  117. $(this.elem).find(".layui-step-content-item").eq(this.currentStep-1).hide();
  118. if(this.currentStep<2) return;
  119. for(var i=this.currentStep-2;i>=0;i--){
  120. $(this.elem).find(".layui-step-title-item").eq(i).removeClass("step-finish");
  121. }
  122. },
  123. // 给上面的icon添加事件
  124. changeStep: function() {
  125. var self=this;
  126. this.canIconClick?(function() {
  127. $(self.elem).on("click",".layui-step-title-item .step-icon",function() {
  128. var index=$(this).parent(".layui-step-title-item").index()+1;
  129. // 判断点击的是否为disabled
  130. if($.inArray(index, self.disabledStep) === -1){
  131. self.goStep(index);
  132. }
  133. })
  134. })():"";
  135. },
  136. // 是否严格按照步骤条顺序执行步骤
  137. openStepLevel: function() {
  138. var self=this;
  139. this.isOpenStepLevel?(function() {
  140. // 如果开启这一项,则默认关闭icon点击事件
  141. self.canIconClick=false;
  142. $(self.elem).off().on("click",".layui-step-title-item .step-icon",function() {
  143. var index=$(this).parent(".layui-step-title-item").index()+1;
  144. // 判断如果当前点击的步骤超过已走过的最大步,则不跳转
  145. if(index>self.finalStep){
  146. return;
  147. }
  148. // 判断点击的是否为disabled
  149. if($.inArray(index, self.disabledStep) === -1){
  150. self.goStep(index);
  151. }
  152. })
  153. })():"";
  154. },
  155. // 跳转第几步
  156. goStep: function(i) {
  157. if((i<1 || i>this.len)){
  158. throw "goStep函数参数不在范围内";
  159. }
  160. // 判断当前页是否禁用,即i是否在数组中
  161. if($.inArray(i, this.disabledStep) === -1){
  162. this.reInit();
  163. this.currentStep=i;
  164. this.init();
  165. }else{
  166. throw "该页已禁用";
  167. }
  168. },
  169. // 跳到第一步
  170. goFirst: function() {
  171. this.goStep(1);
  172. },
  173. // 跳到最后一步
  174. goLast: function() {
  175. this.goStep(this.len);
  176. this.finalStep=this.len;
  177. this.openStepLevel();
  178. },
  179. // 跳到上一步
  180. prev: function () {
  181. if(this.currentStep<=1){
  182. return;
  183. }
  184. this.reInit();
  185. // 先保存当前位置,若前面的全都已经禁用,则可以回到当前位置
  186. var origin=this.currentStep;
  187. this.PrevGo(origin);
  188. },
  189. PrevGo: function(origin) {
  190. this.currentStep--;
  191. // 判断前面的是否全都已经禁用
  192. if(this.currentStep<1){
  193. this.currentStep=origin;
  194. this.init();
  195. return;
  196. }
  197. // 判断当前页是否禁用
  198. if($.inArray(this.currentStep, this.disabledStep) === -1){
  199. this.init();
  200. }else{
  201. this.PrevGo(origin);
  202. }
  203. },
  204. // 跳到下一部
  205. next: function () {
  206. if(this.currentStep>=this.len){
  207. return;
  208. }
  209. this.reInit();
  210. // 先保存当前位置,若后面的全都已经禁用,则可以回到当前位置
  211. var origin=this.currentStep;
  212. this.nextGo(origin);
  213. },
  214. nextGo: function(origin) {
  215. if(this.currentStep===this.finalStep){
  216. // 更新最远步
  217. this.finalStep++;
  218. this.openStepLevel();
  219. }
  220. this.currentStep++;
  221. // 判断后面的是否全都已经禁用
  222. if(this.currentStep>this.len){
  223. this.currentStep=origin;
  224. this.init();
  225. return;
  226. }
  227. // 判断当前步是否禁用
  228. if($.inArray(this.currentStep, this.disabledStep) === -1){
  229. this.init();
  230. }else{
  231. this.nextGo(origin);
  232. }
  233. },
  234. // 禁用某一步
  235. disabled: function (j) {
  236. if(j<=this.currentStep){
  237. throw "已经走过的步骤不能禁用";
  238. }
  239. // 当前步不存在则加入数组,否存重复添加
  240. if($.inArray(j,this.disabledStep)===-1){
  241. this.disabledStep.push(j);
  242. }
  243. //默认为起始从第一步开始,若第一步为disabled,则从前往后找到第一个不是disabled的作为第一步
  244. for(var i=this.currentStep;i<this.len;i++){
  245. if($.inArray(i, this.disabledStep) === -1){
  246. this.reInit();
  247. this.currentStep=i;
  248. this.init();
  249. i=this.len+1;
  250. }
  251. }
  252. },
  253. // 解除禁用
  254. abled: function (j) {
  255. if(j<=this.currentStep){
  256. throw "已经走过的步骤不能解除禁用";
  257. }
  258. // 删除数组数据
  259. var tem=this.disabledStep.concat();
  260. if($.inArray(j, tem) !== -1){
  261. this.disabledStep.splice($.inArray(j, tem),1);
  262. }
  263. this.reInit();
  264. this.init();
  265. }
  266. }
  267. var stepObj; // new的对象,作为内部变量
  268. var step={
  269. option: "",
  270. currentStep: 1,
  271. render: function(option) {
  272. var self=this;
  273. this.option=option || {};
  274. this.option.elem?"":(function() {
  275. throw '缺少参数,需要传入elem元素';
  276. })();
  277. !$(this.option.elem)[0]?(function() {
  278. throw '没有找到'+ self.option.elem +'元素';
  279. })():"";
  280. stepObj=new Step(this.option);
  281. this.currentStep=stepObj.currentStep;
  282. },
  283. goStep: function(i) {
  284. if(typeof i !== "number"){
  285. throw 'goStep参数不合法';
  286. }
  287. stepObj.goStep(i);
  288. this.currentStep=stepObj.currentStep;
  289. },
  290. goFirst: function() {
  291. stepObj.goFirst();
  292. this.currentStep=stepObj.currentStep;
  293. },
  294. goLast: function() {
  295. stepObj.goLast();
  296. this.currentStep=stepObj.currentStep;
  297. },
  298. prev: function() {
  299. stepObj.prev();
  300. this.currentStep=stepObj.currentStep;
  301. },
  302. next: function() {
  303. stepObj.next();
  304. this.currentStep=stepObj.currentStep;
  305. },
  306. disabled: function(i) {
  307. stepObj.disabled(i);
  308. },
  309. abled: function(i) {
  310. stepObj.abled(i);
  311. }
  312. }
  313. exports('step', step);
  314. })