element.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /**
  2. @Name:layui.element 常用元素操作
  3. @Author:贤心
  4. @License:MIT
  5. */
  6. layui.define('jquery', function(exports){
  7. "use strict";
  8. var $ = layui.$
  9. ,hint = layui.hint()
  10. ,device = layui.device()
  11. ,MOD_NAME = 'element', THIS = 'layui-this', SHOW = 'layui-show'
  12. ,Element = function(){
  13. this.config = {};
  14. };
  15. //全局设置
  16. Element.prototype.set = function(options){
  17. var that = this;
  18. $.extend(true, that.config, options);
  19. return that;
  20. };
  21. //表单事件监听
  22. Element.prototype.on = function(events, callback){
  23. return layui.onevent.call(this, MOD_NAME, events, callback);
  24. };
  25. //外部Tab新增
  26. Element.prototype.tabAdd = function(filter, options){
  27. var TITLE = '.layui-tab-title'
  28. ,tabElem = $('.layui-tab[lay-filter='+ filter +']')
  29. ,titElem = tabElem.children(TITLE)
  30. ,barElem = titElem.children('.layui-tab-bar')
  31. ,contElem = tabElem.children('.layui-tab-content')
  32. ,li = '<li lay-id="'+ (options.id||'') +'">'+ (options.title||'unnaming') +'</li>';
  33. barElem[0] ? barElem.before(li) : titElem.append(li);
  34. contElem.append('<div class="layui-tab-item">'+ (options.content||'') +'</div>');
  35. call.hideTabMore(true);
  36. call.tabAuto();
  37. return this;
  38. };
  39. //外部Tab删除
  40. Element.prototype.tabDelete = function(filter, layid){
  41. var TITLE = '.layui-tab-title'
  42. ,tabElem = $('.layui-tab[lay-filter='+ filter +']')
  43. ,titElem = tabElem.children(TITLE)
  44. ,liElem = titElem.find('>li[lay-id="'+ layid +'"]');
  45. call.tabDelete(null, liElem);
  46. return this;
  47. };
  48. //外部Tab切换
  49. Element.prototype.tabChange = function(filter, layid){
  50. var TITLE = '.layui-tab-title'
  51. ,tabElem = $('.layui-tab[lay-filter='+ filter +']')
  52. ,titElem = tabElem.children(TITLE)
  53. ,liElem = titElem.find('>li[lay-id="'+ layid +'"]');
  54. call.tabClick(null, null, liElem);
  55. return this;
  56. };
  57. //动态改变进度条
  58. Element.prototype.progress = function(filter, percent){
  59. var ELEM = 'layui-progress'
  60. ,elem = $('.'+ ELEM +'[lay-filter='+ filter +']')
  61. ,elemBar = elem.find('.'+ ELEM +'-bar')
  62. ,text = elemBar.find('.'+ ELEM +'-text');
  63. elemBar.css('width', percent);
  64. text.text(percent);
  65. return this;
  66. };
  67. var NAV_ELEM = '.layui-nav', NAV_ITEM = 'layui-nav-item', NAV_BAR = 'layui-nav-bar'
  68. ,NAV_TREE = 'layui-nav-tree', NAV_CHILD = 'layui-nav-child', NAV_MORE = 'layui-nav-more'
  69. ,NAV_ANIM = 'layui-anim layui-anim-upbit'
  70. //基础事件体
  71. ,call = {
  72. //Tab点击
  73. tabClick: function(e, index, liElem){
  74. var othis = liElem || $(this)
  75. ,index = index || othis.parent().children('li').index(othis)
  76. ,parents = othis.parents('.layui-tab').eq(0)
  77. ,item = parents.children('.layui-tab-content').children('.layui-tab-item')
  78. ,elemA = othis.find('a')
  79. ,filter = parents.attr('lay-filter');
  80. if(!(elemA.attr('href') !== 'javascript:;' && elemA.attr('target') === '_blank')){
  81. othis.addClass(THIS).siblings().removeClass(THIS);
  82. item.eq(index).addClass(SHOW).siblings().removeClass(SHOW);
  83. }
  84. layui.event.call(this, MOD_NAME, 'tab('+ filter +')', {
  85. elem: parents
  86. ,index: index
  87. });
  88. }
  89. //Tab删除
  90. ,tabDelete: function(e, othis){
  91. var li = othis || $(this).parent(), index = li.index();
  92. var parents = li.parents('.layui-tab').eq(0);
  93. var item = parents.children('.layui-tab-content').children('.layui-tab-item')
  94. if(li.hasClass(THIS)){
  95. if(li.next()[0]){
  96. call.tabClick.call(li.next()[0], null, index + 1);
  97. } else if(li.prev()[0]){
  98. call.tabClick.call(li.prev()[0], null, index - 1);
  99. }
  100. }
  101. li.remove();
  102. item.eq(index).remove();
  103. setTimeout(function(){
  104. call.tabAuto();
  105. }, 50);
  106. }
  107. //Tab自适应
  108. ,tabAuto: function(){
  109. var SCROLL = 'layui-tab-scroll', MORE = 'layui-tab-more', BAR = 'layui-tab-bar'
  110. ,CLOSE = 'layui-tab-close', that = this;
  111. $('.layui-tab').each(function(){
  112. var othis = $(this)
  113. ,title = othis.children('.layui-tab-title')
  114. ,item = othis.children('.layui-tab-content').children('.layui-tab-item')
  115. ,STOPE = 'lay-stope="tabmore"'
  116. ,span = $('<span class="layui-unselect layui-tab-bar" '+ STOPE +'><i '+ STOPE +' class="layui-icon">&#xe61a;</i></span>');
  117. if(that === window && device.ie != 8){
  118. call.hideTabMore(true)
  119. }
  120. //允许关闭
  121. if(othis.attr('lay-allowClose')){
  122. title.find('li').each(function(){
  123. var li = $(this);
  124. if(!li.find('.'+CLOSE)[0]){
  125. var close = $('<i class="layui-icon layui-unselect '+ CLOSE +'">&#x1006;</i>');
  126. close.on('click', call.tabDelete);
  127. li.append(close);
  128. }
  129. });
  130. }
  131. //响应式
  132. if(title.prop('scrollWidth') > title.outerWidth()+1){
  133. if(title.find('.'+BAR)[0]) return;
  134. title.append(span);
  135. othis.attr('overflow', '');
  136. span.on('click', function(e){
  137. title[this.title ? 'removeClass' : 'addClass'](MORE);
  138. this.title = this.title ? '' : '收缩';
  139. });
  140. } else {
  141. title.find('.'+BAR).remove();
  142. othis.removeAttr('overflow');
  143. }
  144. });
  145. }
  146. //隐藏更多Tab
  147. ,hideTabMore: function(e){
  148. var tsbTitle = $('.layui-tab-title');
  149. if(e === true || $(e.target).attr('lay-stope') !== 'tabmore'){
  150. tsbTitle.removeClass('layui-tab-more');
  151. tsbTitle.find('.layui-tab-bar').attr('title','');
  152. }
  153. }
  154. //点击选中
  155. ,clickThis: function(){
  156. var othis = $(this), parents = othis.parents(NAV_ELEM)
  157. ,filter = parents.attr('lay-filter')
  158. ,elemA = othis.find('a');
  159. if(othis.find('.'+NAV_CHILD)[0]) return;
  160. if(!(elemA.attr('href') !== 'javascript:;' && elemA.attr('target') === '_blank')){
  161. parents.find('.'+THIS).removeClass(THIS);
  162. othis.addClass(THIS);
  163. }
  164. layui.event.call(this, MOD_NAME, 'nav('+ filter +')', othis);
  165. }
  166. //点击子菜单选中
  167. ,clickChild: function(){
  168. var othis = $(this), parents = othis.parents(NAV_ELEM)
  169. ,filter = parents.attr('lay-filter');
  170. parents.find('.'+THIS).removeClass(THIS);
  171. othis.addClass(THIS);
  172. layui.event.call(this, MOD_NAME, 'nav('+ filter +')', othis);
  173. }
  174. //展开二级菜单
  175. ,showChild: function(){
  176. var othis = $(this), parents = othis.parents(NAV_ELEM);
  177. var parent = othis.parent(), child = othis.siblings('.'+NAV_CHILD);
  178. if(parents.hasClass(NAV_TREE)){
  179. child.removeClass(NAV_ANIM);
  180. parent[child.css('display') === 'none' ? 'addClass': 'removeClass'](NAV_ITEM+'ed');
  181. }
  182. }
  183. //折叠面板
  184. ,collapse: function(){
  185. var othis = $(this), icon = othis.find('.layui-colla-icon')
  186. ,elemCont = othis.siblings('.layui-colla-content')
  187. ,parents = othis.parents('.layui-collapse').eq(0)
  188. ,filter = parents.attr('lay-filter')
  189. ,isNone = elemCont.css('display') === 'none';
  190. //是否手风琴
  191. if(typeof parents.attr('lay-accordion') === 'string'){
  192. var show = parents.children('.layui-colla-item').children('.'+SHOW);
  193. show.siblings('.layui-colla-title').children('.layui-colla-icon').html('&#xe602;');
  194. show.removeClass(SHOW);
  195. }
  196. elemCont[isNone ? 'addClass' : 'removeClass'](SHOW);
  197. icon.html(isNone ? '&#xe61a;' : '&#xe602;');
  198. layui.event.call(this, MOD_NAME, 'collapse('+ filter +')', {
  199. title: othis
  200. ,content: elemCont
  201. ,show: isNone
  202. });
  203. }
  204. };
  205. //初始化元素操作
  206. Element.prototype.init = function(type){
  207. var that = this, items = {
  208. //Tab选项卡
  209. tab: function(){
  210. call.tabAuto.call({});
  211. }
  212. //导航菜单
  213. ,nav: function(){
  214. var TIME = 200, timer = {}, timerMore = {}, timeEnd = {}, follow = function(bar, nav, index){
  215. var othis = $(this), child = othis.find('.'+NAV_CHILD);
  216. if(nav.hasClass(NAV_TREE)){
  217. bar.css({
  218. top: othis.position().top
  219. ,height: othis.children('a').height()
  220. ,opacity: 1
  221. });
  222. } else {
  223. child.addClass(NAV_ANIM);
  224. bar.css({
  225. left: othis.position().left + parseFloat(othis.css('marginLeft'))
  226. ,top: othis.position().top + othis.height() - 5
  227. });
  228. timer[index] = setTimeout(function(){
  229. bar.css({
  230. width: othis.width()
  231. ,opacity: 1
  232. });
  233. }, device.ie && device.ie < 10 ? 0 : TIME);
  234. clearTimeout(timeEnd[index]);
  235. if(child.css('display') === 'block'){
  236. clearTimeout(timerMore[index]);
  237. }
  238. timerMore[index] = setTimeout(function(){
  239. child.addClass(SHOW)
  240. othis.find('.'+NAV_MORE).addClass(NAV_MORE+'d');
  241. }, 300);
  242. }
  243. }
  244. $(NAV_ELEM).each(function(index){
  245. var othis = $(this)
  246. ,bar = $('<span class="'+ NAV_BAR +'"></span>')
  247. ,itemElem = othis.find('.'+NAV_ITEM);
  248. //Hover滑动效果
  249. if(!othis.find('.'+NAV_BAR)[0]){
  250. othis.append(bar);
  251. itemElem.on('mouseenter', function(){
  252. follow.call(this, bar, othis, index);
  253. }).on('mouseleave', function(){
  254. if(!othis.hasClass(NAV_TREE)){
  255. clearTimeout(timerMore[index]);
  256. timerMore[index] = setTimeout(function(){
  257. othis.find('.'+NAV_CHILD).removeClass(SHOW);
  258. othis.find('.'+NAV_MORE).removeClass(NAV_MORE+'d');
  259. }, 300);
  260. }
  261. });
  262. othis.on('mouseleave', function(){
  263. clearTimeout(timer[index])
  264. timeEnd[index] = setTimeout(function(){
  265. if(othis.hasClass(NAV_TREE)){
  266. bar.css({
  267. height: 0
  268. ,top: bar.position().top + bar.height()/2
  269. ,opacity: 0
  270. });
  271. } else {
  272. bar.css({
  273. width: 0
  274. ,left: bar.position().left + bar.width()/2
  275. ,opacity: 0
  276. });
  277. }
  278. }, TIME);
  279. });
  280. }
  281. itemElem.each(function(){
  282. var oitem = $(this), child = oitem.find('.'+NAV_CHILD);
  283. //二级菜单
  284. if(child[0] && !oitem.find('.'+NAV_MORE)[0]){
  285. var one = oitem.children('a');
  286. one.append('<span class="'+ NAV_MORE +'"></span>');
  287. }
  288. oitem.off('click', call.clickThis).on('click', call.clickThis); //点击选中
  289. oitem.children('a').off('click', call.showChild).on('click', call.showChild); //展开二级菜单
  290. child.children('dd').off('click', call.clickChild).on('click', call.clickChild); //点击子菜单选中
  291. });
  292. });
  293. }
  294. //面包屑
  295. ,breadcrumb: function(){
  296. var ELEM = '.layui-breadcrumb';
  297. $(ELEM).each(function(){
  298. var othis = $(this)
  299. ,separator = othis.attr('lay-separator') || '>'
  300. ,aNode = othis.find('a');
  301. if(aNode.find('.layui-box')[0]) return;
  302. aNode.each(function(index){
  303. if(index === aNode.length - 1) return;
  304. $(this).append('<span class="layui-box">'+ separator +'</span>');
  305. });
  306. othis.css('visibility', 'visible');
  307. });
  308. }
  309. //进度条
  310. ,progress: function(){
  311. var ELEM = 'layui-progress';
  312. $('.'+ELEM).each(function(){
  313. var othis = $(this)
  314. ,elemBar = othis.find('.layui-progress-bar')
  315. ,width = elemBar.attr('lay-percent');
  316. elemBar.css('width', width);
  317. if(othis.attr('lay-showPercent')){
  318. setTimeout(function(){
  319. var percent = Math.round(elemBar.width()/othis.width()*100);
  320. if(percent > 100) percent = 100;
  321. elemBar.html('<span class="'+ ELEM +'-text">'+ percent +'%</span>');
  322. },350);
  323. }
  324. });
  325. }
  326. //折叠面板
  327. ,collapse: function(){
  328. var ELEM = 'layui-collapse';
  329. $('.'+ELEM).each(function(){
  330. var elemItem = $(this).find('.layui-colla-item')
  331. elemItem.each(function(){
  332. var othis = $(this)
  333. ,elemTitle = othis.find('.layui-colla-title')
  334. ,elemCont = othis.find('.layui-colla-content')
  335. ,isNone = elemCont.css('display') === 'none';
  336. //初始状态
  337. elemTitle.find('.layui-colla-icon').remove();
  338. elemTitle.append('<i class="layui-icon layui-colla-icon">'+ (isNone ? '&#xe602;' : '&#xe61a;') +'</i>');
  339. //点击标题
  340. elemTitle.off('click', call.collapse).on('click', call.collapse);
  341. });
  342. });
  343. }
  344. };
  345. return layui.each(items, function(index, item){
  346. item();
  347. });
  348. };
  349. var element = new Element(), dom = $(document);
  350. element.init();
  351. var TITLE = '.layui-tab-title li';
  352. dom.on('click', TITLE, call.tabClick); //Tab切换
  353. dom.on('click', call.hideTabMore); //隐藏展开的Tab
  354. $(window).on('resize', call.tabAuto); //自适应
  355. exports(MOD_NAME, element);
  356. });