jquery.linkdiv.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /**带有连接线的嵌套div插件**/
  2. ;(function($){
  3. var default_options = {
  4. updateContent:null, /**更新div中内容的事件**/
  5. lineColor:'#696969', /**连接线的线条颜色**/
  6. rule2json:null /**生成json数据的事件**/
  7. };
  8. var methods = {
  9. //初始化
  10. init: function(options) {
  11. var settings = $.extend({}, default_options, options || {});
  12. return this.each(function () {
  13. $(this).data("linkdivData", new $.LinkDivList(this, settings));
  14. });
  15. },
  16. //添加一个新div
  17. addDiv:function(data){
  18. this.data("linkdivData").addDiv(data);
  19. return this;
  20. },
  21. //移除选中的div
  22. removeDiv:function(){
  23. this.data("linkdivData").removeDiv();
  24. return this;
  25. },
  26. //组合选中的div
  27. assembleDiv:function(){
  28. this.data("linkdivData").assembleDiv();
  29. return this;
  30. },
  31. //拆分组合的div
  32. splitDiv:function(){
  33. this.data("linkdivData").splitDiv();
  34. return this;
  35. },
  36. //获取数据
  37. getData:function(){
  38. return this.data("linkdivData").getData();
  39. }
  40. };
  41. $.LinkDivList = function($div,options){
  42. $div = $($div);
  43. //获取线条的span标签
  44. function getLineHtml(s){
  45. var span = $('<span class="line-span"></span>').css(s);
  46. return span;
  47. };
  48. //画线
  49. function drawLine(x0, y0, x1, y1, color) {
  50. var rs = [];
  51. if (y0 == y1) // 画横线
  52. {
  53. if (x0 > x1) {
  54. var t = x0;
  55. x0 = x1;
  56. x1 = t
  57. }
  58. var css = {top:y0,left:x0,width:Math.abs(x1 - x0),background:color,height:2};
  59. rs.push(getLineHtml(css));
  60. } else if (x0 == x1) // 画竖线
  61. {
  62. if (y0 > y1) {
  63. var t = y0;
  64. y0 = y1;
  65. y1 = t
  66. }
  67. var css = {top:y0,left:x0,height:Math.abs(y1 - y0),background:color,width:2};
  68. rs.push(getLineHtml(css));
  69. } else {
  70. var lx = x1 - x0
  71. var ly = y1 - y0
  72. var l = Math.sqrt(lx * lx + ly * ly)
  73. for ( var i = 0; i < l; i += 2) {
  74. var p = i / l;
  75. var px = parseInt(x0 + lx * p);
  76. var py = parseInt(y0 + ly * p);
  77. var css = {top:py,left:px,height:2,background:color,width:2};
  78. rs.push(getLineHtml(css));
  79. }
  80. }
  81. return rs
  82. };
  83. //添加连接线
  84. function addLine(item,count,size){
  85. var top = item.offset().top,
  86. left = item.offset().left,
  87. width = item.width(),
  88. height = item.height(),
  89. lineAry = [],
  90. color = options.lineColor;
  91. //线段①
  92. $.merge(lineAry,drawLine(left+width,top+height/2,left+width+40,top+height/2,color));
  93. if(count+1!=size){
  94. //线段②
  95. $.merge(lineAry,drawLine(left+width+40,top+height/2,left+width+40,top+height,color));
  96. }
  97. if(count!=0){
  98. //线段③
  99. $.merge(lineAry,drawLine(left+width+40,top+height/2,left+width+40,top,color));
  100. }
  101. for(var i =0,c;c=lineAry[i++];){
  102. item.append(c);
  103. }
  104. };
  105. //添加运算类型
  106. function addComputing(item){
  107. var select,
  108. computing = item.attr("computing"),
  109. computingSelect = $("select.computing-select",item);
  110. if(computingSelect.length>0){
  111. select = computingSelect;
  112. }
  113. if(!computing){
  114. computing = "and";
  115. }
  116. var top = item.offset().top,
  117. left = item.offset().left,
  118. width = item.width(),
  119. height = item.height();
  120. if(!select){
  121. select = $('<select class="computing-select"><option value="and">且</option><option value="or">或</option></span>').val(computing);
  122. }
  123. select.css({top:top-16,left:left+width+12,width:50,height:25});
  124. item.append(select);
  125. };
  126. function showLinkLine(p){
  127. p.each(function(){
  128. var assem = $(this),
  129. itemAry = assem.children("div.con-item"),
  130. size = itemAry.length,
  131. count = 0;
  132. itemAry.each(function(){
  133. var me = $(this);
  134. $("span.line-span",me).remove();
  135. if(size>=1){
  136. $("select.computing-select",me).remove();
  137. }
  138. if(size>1){
  139. addLine(me,count,size);
  140. }
  141. if(count>0){
  142. addComputing(me);
  143. }
  144. count++;
  145. //如果是组合条件,则递归显示 线条
  146. if(me.hasClass("con-branch")){
  147. showLinkLine(me);
  148. }
  149. });
  150. });
  151. };
  152. function bindEvent(){
  153. $div.delegate("span.label-span","click",function(e){
  154. stopBubulle(e);
  155. var parentDiv = $(this).parents("div.con-item");
  156. $(parentDiv[0]).toggleClass("con-item-selected");
  157. });
  158. };
  159. //终止事件冒泡
  160. function stopBubulle(e){
  161. if(e && e.stopPropagation)
  162. e.stopPropagation();
  163. else
  164. window.event.cancelBubble = true;
  165. };
  166. //添加
  167. function add_Div(data){
  168. var div = $('<div class="con-item con-leaf"></div>'),
  169. selectedBranch = $("div.con-item-selected.con-branch"),
  170. pdiv = $div;
  171. if(selectedBranch&&selectedBranch.length>0)
  172. pdiv = $(selectedBranch[0]);
  173. pdiv.append(div);
  174. updateSpan(pdiv);
  175. if(options.updateContent){
  176. options.updateContent(div,data);
  177. }
  178. };
  179. //删除
  180. function remove_Div(){
  181. $("div.con-item-selected").remove();
  182. updateSpan();
  183. };
  184. //组合
  185. function assemble_Div(){
  186. var selected = $("div.con-item-selected").toggleClass("con-item-selected"),
  187. branch = $('<div class="con-item con-branch"><span class="label-span">组合规则</span></div>');
  188. $(selected[0]).before(branch);
  189. branch.append(selected);
  190. updateSpan();
  191. };
  192. //拆分
  193. function split_Div(){
  194. var selectedBranch = $("div.con-item-selected.con-branch").toggleClass("con-item-selected");
  195. selectedBranch.each(function(){
  196. var me = $(this);
  197. me.before(me.children("div.con-item")).remove();
  198. });
  199. updateSpan();
  200. };
  201. //更新线条和运算类型
  202. function updateSpan(p){
  203. if(!p)p = $div;
  204. showLinkLine(p);
  205. };
  206. //解析数据为div
  207. function initData2Div(ary,div){
  208. for(var i=0,c;c=ary[i++];){
  209. var itemDiv;
  210. if(c.branch){
  211. itemDiv = $('<div class="con-item con-branch"><span class="label-span">组合规则</span></div>');
  212. div.append(itemDiv);
  213. initData2Div(c.sub,itemDiv);
  214. }
  215. else{
  216. itemDiv = $('<div class="con-item con-leaf"></div>');
  217. div.append(itemDiv);
  218. if(options.updateContent){
  219. options.updateContent(itemDiv,c);
  220. }
  221. }
  222. if(c.compType){
  223. itemDiv.attr("computing",c.compType);
  224. }
  225. }
  226. };
  227. //获取数据
  228. function get_Data(p,json){
  229. if(!p)return;
  230. var items = p.children("div.con-item");
  231. items.each(function(){
  232. var me = $(this),
  233. jobject = {};
  234. if(me.hasClass("con-branch")){//组合规则
  235. var sub = [],
  236. compType = me.children("select.computing-select").val();
  237. jobject.branch = true;
  238. jobject.sub = sub;
  239. if(compType){
  240. jobject.compType = compType;
  241. }
  242. get_Data(me,sub);
  243. }
  244. else{
  245. if(options.rule2json){
  246. jobject = options.rule2json(me);
  247. }
  248. }
  249. if(jobject)json.push(jobject);
  250. });
  251. };
  252. this.addDiv = function(data) {
  253. add_Div(data);
  254. };
  255. this.removeDiv = function() {
  256. remove_Div();
  257. };
  258. this.assembleDiv = function() {
  259. assemble_Div();
  260. };
  261. this.splitDiv = function() {
  262. split_Div();
  263. };
  264. this.getData = function(){
  265. var json = [];
  266. get_Data($div,json);
  267. return json;
  268. };
  269. bindEvent();
  270. if(options.data){
  271. initData2Div(options.data,$div);
  272. }
  273. updateSpan();
  274. };
  275. $.fn.linkdiv = $.fn.linkDiv = function(method){
  276. if(methods[method]) {
  277. return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
  278. } else {
  279. return methods.init.apply(this, arguments);
  280. }
  281. };
  282. })(jQuery);