- 浏览: 292649 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
springdata_springmvc:
java程序语言学习教程 地址http://www.zuida ...
JAVA获取CLASSPATH路径 -
springdata-jpa:
可以参考最新的文档:如何在eclipse jee中检出项目并转 ...
Maven2创建项目 -
程序员是怎么炼成的:
嗯 , 谢谢!
JAVA获取CLASSPATH路径 -
svygh123:
写的非常好,我已经连接通过,谢谢分享
Oracle建立DBLINK的详细步骤记录 -
aa00aa00:
恩,看了主人的博客,不错,我也是用的DBLINK,进行orac ...
Oracle建立DBLINK的详细步骤记录
收藏列表
- 全部 [120]
- python [6]
- javascript [7]
- freemarker [2]
- jquery [7]
- firefox [1]
- linux [2]
- java [18]
- oracle [4]
- webservice [3]
- sqlserver [3]
- html [3]
- other [3]
- powerdesigner [1]
- maven [1]
- spring mvc [26]
- 保险 [2]
- vba [11]
- lhgdialog [1]
- jeasyui [11]
- docker [1]
- require.js [1]
- gooflow [3]
- jsplumb [1]
- emberjs [1]
- mvel2 [1]
- rancher [1]
标题 | 标签 | 来源 | |
【jquery】解析xml | jquery | Convert xml to string with jQuery | |
<!-- test2 --> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>jQuery XML</title> <link rel="stylesheet" type="text/css" href="../../lib/jeasyui/themes/easyui.css"> <link rel="stylesheet" type="text/css" href="../../lib/jeasyui/themes/icon.css"> <link rel="stylesheet" type="text/css" href="../../lib/common/project.css"> <script type="text/javascript" src="../../lib/jeasyui/jquery.min.js"></script> <script type="text/javascript" src="../../lib/jeasyui/jquery.easyui.min.js"></script> <script type="text/javascript" src="./jquery.xml.js"></script> <!-- <script type="text/javascript" src="./jquery.jxml.js"></script> --> </head> <body> <table> <tr> <td style="border: 1px solid;"> <xmp><data> <riskcode>APLP</riskcode> <riskname>的空格和换行会直接显示</riskname> </data> </xmp> </td> </tr> <tr> <td><textarea id="" name="" rows="15" cols="80" class="textarea"></textarea></td> <td><a href="javascript:void(0);" class="easyui-linkbutton">操作</a></td> </tr> </table> <script type="text/javascript"> (function($) { $.extend(jQuery, { loadXML: function(xmlString){ return $($.parseXML(xmlString)); } }); $.fn.extend({ appendXml: function(s){ return this.each(function() { if (typeof s != "string") return; // if (!jQuery.isXMLDoc(this)){ // console.log("isXMLDoc = " + false); // return; // } var node = $.parseXML(s).firstChild.cloneNode(true); // console.log(node); // console.log(node.nodeName); this.appendChild(node); }); }, toXMLString: function(){ var xmlDoc = $(this)[0]; // return xmlDoc.xml || (new XMLSerializer()).serializeToString(xmlDoc); if (window.ActiveXObject){ console.log("IE ..."); return xmlDoc.xml; } else { return (new XMLSerializer()).serializeToString(xmlDoc); } } }); })(jQuery); $(document).ready(function(){ var xml = $("xmp").html(); var $xml = $(xml); $xml.appendXml("<remark>daof想出来的</remark>"); console.log("@>> " + $xml.toXMLString()); }) </script> </body> </html> <!-----------------------------------------------------------------------> <!-----------------------------------------------------------------------> <!-----------------------------------------------------------------------> <!-- test1 --> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>jQuery XML</title> <link rel="stylesheet" type="text/css" href="../../lib/jeasyui/themes/easyui.css"> <link rel="stylesheet" type="text/css" href="../../lib/jeasyui/themes/icon.css"> <link rel="stylesheet" type="text/css" href="../../lib/common/project.css"> <script type="text/javascript" src="../../lib/jeasyui/jquery.min.js"></script> <script type="text/javascript" src="../../lib/jeasyui/jquery.easyui.min.js"></script> </head> <body> <table> <tr> <td style="border: 1px solid;"> <xmp><data> <riskcode>APLP</riskcode> <riskname>的空格和换行会直接显示</riskname> </data> </xmp> </td> </tr> <tr> <td><textarea id="" name="" rows="15" cols="80" class="textarea"></textarea></td> <td><a href="javascript:void(0);" class="easyui-linkbutton">操作</a></td> </tr> </table> <script type="text/javascript"> $(document).ready(function(){ $("a").click(function(){ var xml = $("xmp").html(); console.log(xml); var $xmlObj = null; if (window.ActiveXObject){ var xmldoc = new ActiveXObject("Microsoft.XMLDOM"); //创建XMLDOC 对象 xmldoc.async=false; //使用同步方式加载XML字符串 xmldoc.loadXML(xml); //加载XML字符串 $xmlObj = $(xmldoc); } else { $xmlObj = $(xml); } // var $xmlObj = $.parseXML(xml); console.log("riskcode = " + $xmlObj.find('riskcode').text()); // var $msg = $("<msg/>"); // $msg.text("jquery xml 消息"); // $xmlObj.append($("<msg/>").text("jquery xml 消息")); var xmlString; if (window.ActiveXObject){ // IE console.log("IE ..."); xmlString = $xmlObj[0].xml; } else { // code for Mozilla, Firefox, Opera, etc. var oSerializer = new XMLSerializer(); xmlString = oSerializer.serializeToString($xmlObj[0]); } $("textarea").val(xmlString); }); }) </script> </body> </html> |
|||
javascript stopPropagation() 方法 | javascript | stopPropagation() 方法 | |
定义和用法 不再派发事件。 终止事件在传播过程的捕获、目标处理或起泡阶段进一步传播。调用该方法后,该节点上处理该事件的处理程序将被调用,事件不再被分派到其他节点。 语法 event.stopPropagation() 说明 该方法将停止事件的传播,阻止它被分派到其他 Document 节点。在事件传播的任何阶段都可以调用它。注意,虽然该方法不能阻止同一个 Document 节点上的其他事件句柄被调用,但是它可以阻止把事件分派到其他节点。 |
|||
【jsch】sftp 文件上传 | java | ||
/** * sftp 文件上传 * 依赖: * <dependency> * <groupId>com.jcraft</groupId> * <artifactId>jsch</artifactId> * <version>0.1.50</version> * </dependency> */ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.util.Properties; import java.util.Vector; import org.apache.log4j.Logger; import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.ChannelSftp.LsEntry; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import com.jcraft.jsch.SftpException; /** * @author c1panx * @ 2015年5月8日 下午4:12:28 */ public class SFTPUtil { private static final Logger logger = Logger.getLogger(SFTPUtil.class); private static final String host = "10.140.130.50"; private static final String username = "uat"; private static final String password = "Aa123456"; private static final String cdPath = "/home/uat/backup/temp"; private static final String localPath = "D:\\LG\\jacob\\"; private static final String separator = "/"; public static void upload(){ long startTime = System.currentTimeMillis(); ChannelSftp sftp = null; Channel channel = null; try { JSch jsch = new JSch(); Session sshSession = jsch.getSession(username, host); logger.debug("Session created."); sshSession.setPassword(password); Properties sshConfig = new Properties(); sshConfig.put("StrictHostKeyChecking", "no"); sshSession.setConfig(sshConfig); sshSession.connect(); logger.debug("Session connected."); logger.debug("Opening Channel...."); channel = sshSession.openChannel("sftp"); channel.connect(); sftp = (ChannelSftp) channel; // 遍历上传 File file = new File(localPath); logger.info("start cleart remote folder ....."); clearRemoteFolder(sftp, cdPath, file); logger.info("=========================================="); logger.info("start upload files ....."); uploadFile(sftp, cdPath, file); channel.disconnect(); } catch (JSchException e) { logger.error(e.getMessage(), e); } catch (SftpException e) { logger.error(e.getMessage(), e); } catch (FileNotFoundException e) { logger.error(e.getMessage(), e); } finally { if (null != channel) { channel.disconnect(); } if (null != sftp) { sftp.disconnect(); } long endTime = System.currentTimeMillis(); logger.info("diff time: " + (endTime - startTime)); } } @SuppressWarnings("unchecked") private static void clearRemoteFolder(ChannelSftp sftp, String pwd, File file) throws SftpException { String childPwd = pwd + separator + file.getName(); logger.debug("start rm remote file ...[" + childPwd + "]"); boolean exists = false; Vector<LsEntry> v = sftp.ls(pwd); for (LsEntry lsEntry : v) { String fileName = lsEntry.getFilename(); if (fileName.equalsIgnoreCase(file.getName())) { exists = true; break; } } if (exists == false) { logger.debug("[" + childPwd + "] does not exist."); return; } deleteFile(sftp, pwd, file.getName()); } @SuppressWarnings("unchecked") private static void deleteFile(ChannelSftp sftp, String pwd, String delName) throws SftpException { String filePath = pwd + separator + delName; try { sftp.cd(filePath); Vector<LsEntry> v = sftp.ls(filePath); for (LsEntry lsEntry : v) { String fileName = lsEntry.getFilename(); if (fileName.equals(".") || fileName.equals("..")) { continue; } deleteFile(sftp, filePath, fileName); } logger.debug("rm dir: " + filePath); sftp.rmdir(pwd + separator + delName); } catch (SftpException e) { // 删除文件 logger.debug("rm file: " + filePath); sftp.rm(filePath); } } private static void uploadFile(ChannelSftp sftp, String pwd, File file) throws SftpException, FileNotFoundException { sftp.cd(pwd); if (file.isDirectory()) { String childPwd = pwd + separator + file.getName(); logger.debug("mkdir: " + childPwd); sftp.mkdir(file.getName()); sftp.cd(childPwd); File[] files = file.listFiles(); for (File file2 : files) { uploadFile(sftp, childPwd, file2); } } else { logger.debug("upload file: " + file.getName()); sftp.put(new FileInputStream(file), file.getName()); } } } |
|||
【html】pdf在线浏览 | html | ||
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>pdf在线浏览</title> </head> <body marginheight="0" marginwidth="0"> <!-- <embed> 标签是 HTML 5 中的新标签 --> <embed height="100%" width="100%" src="pdf.pdf" type="application/pdf" /> </body> </html> |
|||
【require.js】 | require.js | Javascript模块化编程(三):require.js的用法 | |
【spring mvc】多数据源配置2 | spring mvc | ||
<!-- self-dataSource.xml --> <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd" default-autowire="byName"> <!-- 配置数据源 --> <bean id="self_dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${self.jdbc.driverClassName}" /> <property name="url" value="${self.jdbc.url}" /> <property name="username" value="${self.jdbc.username}" /> <property name="password" value="${self.jdbc.password}" /> <property name="maxActive" value="100" /> <property name="maxWait" value="1000" /> <property name="poolPreparedStatements" value="false" /> <property name="defaultAutoCommit" value="false" /> </bean> <!--把mybatis SqlSessionFactory的创建交由spring管理 --> <bean id="self_sqlSessionFactoryBeanName" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="self_dataSource" /> <!-- <property name="typeAliasesPackage" value="com.cignacmb.selfhelp.dao.self" /> --> <property name="configLocation" value="classpath:mybatis-config.xml" /> <property name="mapperLocations"> <list> <value>classpath:com/cignacmb/selfhelp/self/mapper/*.xml</value> </list> </property> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="self_sqlSessionFactoryBeanName"/> <property name="basePackage" value="com.cignacmb.selfhelp.self.mapper" /> </bean> <!-- Local Transaction Management (txManager) --> <bean id="selfTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="self_dataSource" /> <qualifier value="selfTransaction" /> </bean> <!--启动spring注解功能 --> <tx:annotation-driven transaction-manager="selfTransactionManager" /> </beans> <!-------------------------------------------------------------------------------------> <!-- lis-dataSource.xml --> <!-- 配置数据源 --> <bean id="lis_dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${lis.jdbc.driverClassName}" /> <property name="url" value="${lis.jdbc.url}" /> <property name="username" value="${lis.jdbc.username}" /> <property name="password" value="${lis.jdbc.password}" /> <property name="maxActive" value="100" /> <property name="maxWait" value="1000" /> <property name="poolPreparedStatements" value="false" /> <property name="defaultAutoCommit" value="false" /> </bean> <bean id="lis_sqlSessionFactoryBeanName" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="lis_dataSource" /> <property name="configLocation" value="classpath:mybatis-config.xml" /> <property name="mapperLocations"> <list> <value>classpath:com/cignacmb/selfhelp/lis/mapper/*.xml</value> </list> </property> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="lis_sqlSessionFactoryBeanName"/> <property name="basePackage" value="com.cignacmb.selfhelp.lis.mapper" /> </bean> <bean id="lisTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="lis_dataSource" /> <qualifier value="lisTransaction" /> </bean> <tx:annotation-driven transaction-manager="lisTransactionManager" /> <!-------------------------------------------------------------------------------------> <!-- applicationContext.xml --> <context:property-placeholder location="classpath:system-config/dev.properties" ignore-unresolvable="true" /> <!-- 自动扫描Bean --> <context:component-scan base-package="com.cignacmb.selfhelp" > <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <!-- enable autowire --> <!-- <context:annotation-config /> --> <!-- 强制使用CGLIB代理 --> <aop:aspectj-autoproxy proxy-target-class="true" /> <import resource="datasource/self-dataSource.xml"/> <import resource="datasource/lis-dataSource.xml"/> |
|||
【jeasyui 1.4.2】methods扩展之autoMergeCells | jeasyui | ||
$.extend($.fn.datagrid.methods, { /** * 自动合并表体<br> * 从左向右合并,右边列能合并的行是右边列已合并的范围 * @param {} jq * @param [] fields 需合并的列,columns中的field值组成的数组 * @return {} */ autoMergeCells : function(jq, fields) { /** * * @param col 起始列 * @param startrow 起始索引 * @param endrow 结束索引 * @param allcols 列数据集合 * @param target grid对象 * @param [] fields 需合并的列,columns中的field值组成的数组 */ function megerCol(col,startrow,endrow,allcols,target,fields){ var colArrar = allcols[col]; var startIndex = startrow; var field = fields[col]; for(var i=(startIndex+1);i<=endrow;i++){ if(colArrar[i] == colArrar[startIndex]){ if(i == endrow){ var rowspan = i-startIndex+1; //合并单元格 target.datagrid('mergeCells', { index : startIndex, field : field, rowspan : rowspan }); if(col+1 < fields.length){ megerCol(col+1,startIndex,i,allcols,target,fields); } }else{ continue; } }else{ if(startIndex != (i-1)){ var rowspan = i-startIndex; //合并单元格 target.datagrid('mergeCells', { index : startIndex, field : field, rowspan : rowspan }); if(col+1 < fields.length){ megerCol(col+1,startIndex,i-1,allcols,target,fields); } } startIndex = i; } } }; return jq.each(function() { var target = $(this); if (!fields) { fields = target.datagrid("getColumnFields"); } var allfileldValue = []; var rows = target.datagrid("getRows"); //循环fileld得到所有行的数据数组 for (var j = 0; j < fields.length; j++) { var fileldValue = []; for (var i = 0; i < rows.length; i++) { var row = rows[i]; fileldValue.push(row[fields[j]]); } allfileldValue.push(fileldValue); } megerCol(0, 0, rows.length - 1, allfileldValue, target, fields); }); } }); 调用示例: $("#testTable").datagrid("autoMergeCells"); or $("#testTable").datagrid("autoMergeCells", ['price1', 'price2']); |
|||
【GooFlow】GooFlow Demo | gooflow | 主题:基于JQUERY的WEB在线流程图设计器GOOFLOW 0.7版 | |
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>gooFlow</title> <link rel="stylesheet" type="text/css" href="http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/default.css"> <link rel="stylesheet" type="text/css" href="./GooFlow.css"> <script type="text/javascript" src="http://sandbox.runjs.cn/js/sandbox/jquery/jquery-1.8.3.min.js"></script> <script type="text/javascript" src="http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/GooFunc.js"></script> </head> <body> <div id="demo" style="margin:10px"></div> <script type="text/javascript" src="./data.js"></script> <script type="text/javascript" src="./GooFlow.js"></script> <script type="text/javascript"> var property={ width:1200, height:450, // toolBtns:["start round","end round","task round","node","chat","state","plug","join","fork","complex mix"], // haveHead:true, // headBtns:["new","open","save","undo","redo","reload"],//如果haveHead=true,则定义HEAD区的按钮 // haveTool:true, haveGroup:true, useOperStack:true }; $(document).ready(function(){ var demo=$.createGooFlow($("#demo"),property); // demo.setNodeRemarks(remark); //demo.onItemDel=function(id,type){ // return confirm("确定要删除该单元吗?"); //} demo.loadData(jsondata); }); </script> </body> </html> // 参考 http://runjs.cn/detail/99epj1t2 http://sandbox.runjs.cn/show/99epj1t2 // product-data.js var jsondata = { title : "产品分类", nodes : { "node_101" : {name : "人身保险", left : 10, top : 220, width : 24, height : 24, type : "complex mix", alt : true}, "node_201" : {name : "人寿保险", left : 210, top : 80, width : 24, height : 24, type : "complex mix", alt : true}, "node_202" : {name : "年金保险", left : 210, top : 220, width : 24, height : 24, type : "complex mix", alt : true}, "node_203" : {name : "健康保险", left : 210, top : 325, width : 24, height : 24, type : "complex mix", alt : true}, "node_204" : {name : "意外伤害保险", left : 210, top : 430, width : 60, height : 24, type : "complex mix", alt : true}, "node_301" : {name : "定期寿险", left : 410, top : 10, width : 24, height : 24, type : "complex mix", alt : true}, "node_302" : {name : "终身寿险", left : 410, top : 80, width : 24, height : 24, type : "complex mix", alt : true}, "node_303" : {name : "两全保险", left : 410, top : 150, width : 24, height : 24, type : "complex mix", alt : true}, "node_304" : {name : "疾病保险", left : 410, top : 290, width : 24, height : 24, type : "complex mix", alt : true}, "node_305" : {name : "医疗保险", left : 410, top : 360, width : 24, height : 24, type : "complex mix", alt : true} }, lines : { "line101_201" : {type:"sl", M:81.5, from:"node_101", to:"node_201", name: ""}, "line101_202" : {type:"sl", M:81.5, from:"node_101", to:"node_202", name: ""}, "line101_203" : {type:"sl", M:81.5, from:"node_101", to:"node_203", name: ""}, "line101_204" : {type:"sl", M:81.5, from:"node_101", to:"node_204", name: ""}, "line201_301" : {type:"sl", M:81.5, from:"node_201", to:"node_301", name: ""}, "line201_302" : {type:"sl", M:81.5, from:"node_201", to:"node_302", name: ""}, "line201_303" : {type:"sl", M:81.5, from:"node_201", to:"node_303", name: ""}, "line203_304" : {type:"sl", M:81.5, from:"node_203", to:"node_304", name: ""}, "line203_305" : {type:"sl", M:81.5, from:"node_203", to:"node_305", name: ""} } }; // data.js jsondata={"title":"10086网状流程","nodes":{"demo_node_9":{"name":"桂中区","left":10,"top":10,"type":"start round","width":24,"height":24,"alt":true},"demo_node_10":{"name":"桂北区","left":10,"top":81,"type":"start round","width":24,"height":24,"alt":true},"demo_node_11":{"name":"桂西区","left":9,"top":143,"type":"start round","width":24,"height":24,"alt":true},"demo_node_12":{"name":"桂北区","left":11,"top":290,"type":"start round","width":24,"height":24,"alt":true},"demo_node_14":{"name":"桂东区","left":7,"top":339,"type":"start round","width":24,"height":24,"alt":true},"demo_node_2":{"name":"问候语2","left":232,"top":104,"type":"chat","width":86,"height":24,"alt":true},"demo_node_3":{"name":"问候语3","left":220,"top":260,"type":"chat","width":86,"height":24,"alt":true},"demo_node_4":{"name":"问候语4","left":222,"top":327,"type":"chat","width":86,"height":24,"alt":true},"demo_node_5":{"name":"停机判断","left":107,"top":47,"type":"fork","width":86,"height":24,"alt":true},"demo_node_13":{"name":"停机判断2","left":103,"top":289,"type":"fork","width":86,"height":24,"alt":true},"demo_node_20":{"name":"停机菜单","left":355,"top":12,"type":"join","width":86,"height":24,"alt":true},"demo_node_21":{"name":"正常菜单","left":368,"top":362,"type":"join","width":86,"height":24,"alt":true},"demo_node_27":{"name":"延时停机","left":492,"top":13,"type":"node","width":86,"height":24,"alt":true},"demo_node_28":{"name":"开机","left":491,"top":62,"type":"node","width":86,"height":24,"alt":true},"demo_node_29":{"name":"缴费","left":466,"top":162,"type":"node","width":86,"height":24,"alt":true},"demo_node_30":{"name":"历史话费查询","left":591,"top":116,"type":"node","width":111,"height":24,"alt":true},"demo_node_1":{"name":"问候语1","left":228,"top":42,"type":"chat","width":86,"height":24,"alt":true},"demo_node_38":{"name":"积分查询","left":506,"top":261,"type":"complex mix","width":86,"height":24,"alt":true},"demo_node_39":{"name":"剩余资源查询","left":499,"top":312,"type":"complex mix","width":107,"height":24,"alt":true},"demo_node_40":{"name":"常用业务办理","left":491,"top":356,"type":"complex mix","width":110,"height":24,"alt":true},"demo_node_42":{"name":"网络服务","left":492,"top":397,"type":"complex mix","width":86,"height":24,"alt":true},"demo_node_43":{"name":"转人工服务","left":479,"top":457,"type":"state","width":91,"height":24,"alt":true},"demo_node_44":{"name":"话费查询","left":477,"top":213,"type":"state","width":86,"height":24,"alt":true},"demo_node_52":{"name":"实时话费查询","left":609,"top":212,"type":"node","width":107,"height":24,"alt":true},"demo_node_54":{"name":"网络专区投诉","left":639,"top":399,"type":"task","width":106,"height":24,"alt":true},"demo_node_55":{"name":"普通转人工","left":641,"top":456,"type":"task","width":109,"height":24,"alt":true},"demo_node_59":{"name":"10088","left":500,"top":514,"type":"task","width":86,"height":24,"alt":true}},"lines":{"demo_line_6":{"type":"lr","M":81.5,"from":"demo_node_9","to":"demo_node_5","name":""},"demo_line_7":{"type":"lr","M":81.5,"from":"demo_node_10","to":"demo_node_5","name":""},"demo_line_9":{"type":"lr","M":81.5,"from":"demo_node_11","to":"demo_node_5","name":""},"demo_line_14":{"type":"sl","from":"demo_node_12","to":"demo_node_13","name":""},"demo_line_15":{"type":"lr","M":78.5,"from":"demo_node_14","to":"demo_node_13","name":""},"demo_line_17":{"type":"tb","M":152,"from":"demo_node_5","to":"demo_node_2","name":"F"},"demo_line_18":{"type":"tb","M":239,"from":"demo_node_13","to":"demo_node_3","name":"T"},"demo_line_19":{"type":"tb","M":383.5,"from":"demo_node_13","to":"demo_node_4","name":"F"},"demo_line_22":{"type":"lr","M":339,"from":"demo_node_4","to":"demo_node_21","name":""},"demo_line_23":{"type":"lr","M":337.5,"from":"demo_node_2","to":"demo_node_21","name":""},"demo_line_26":{"type":"lr","M":366.5,"from":"demo_node_3","to":"demo_node_20","name":""},"demo_line_31":{"type":"tb","M":176.5,"from":"demo_node_20","to":"demo_node_29","name":"4"},"demo_line_32":{"type":"tb","M":25.5,"from":"demo_node_20","to":"demo_node_27","name":"1"},"demo_line_33":{"type":"tb","M":128,"from":"demo_node_20","to":"demo_node_30","name":"3"},"demo_line_34":{"type":"tb","M":74.5,"from":"demo_node_20","to":"demo_node_28","name":"2"},"demo_line_36":{"type":"tb","M":21.5,"from":"demo_node_5","to":"demo_node_1","name":"T"},"demo_line_37":{"type":"lr","M":367,"from":"demo_node_1","to":"demo_node_20","name":""},"demo_line_45":{"type":"tb","M":225,"from":"demo_node_21","to":"demo_node_44","name":"1"},"demo_line_46":{"type":"tb","M":274.5,"from":"demo_node_21","to":"demo_node_38","name":"2"},"demo_line_47":{"type":"tb","M":325.5,"from":"demo_node_21","to":"demo_node_39","name":"3"},"demo_line_48":{"type":"sl","from":"demo_node_21","to":"demo_node_40","name":"4"},"demo_line_49":{"type":"tb","M":411.5,"from":"demo_node_21","to":"demo_node_42","name":"5"},"demo_line_50":{"type":"tb","M":470.5,"from":"demo_node_21","to":"demo_node_43","name":"0"},"demo_line_51":{"type":"sl","from":"demo_node_44","to":"demo_node_30","name":"2"},"demo_line_53":{"type":"sl","from":"demo_node_44","to":"demo_node_52","name":"1"},"demo_line_56":{"type":"sl","from":"demo_node_43","to":"demo_node_55","name":"0"},"demo_line_57":{"type":"sl","from":"demo_node_43","to":"demo_node_54","name":"1"},"demo_line_58":{"type":"sl","from":"demo_node_42","to":"demo_node_54","name":"0"},"demo_line_60":{"type":"sl","from":"demo_node_43","to":"demo_node_59","name":"2","alt":true}},"areas":{},"initNum":61}; |
|||
【GooFlow】GooFlow.css | gooflow | ||
v\:group,v\:rect,v\:imagedata,v\:oval,v\:line,v\:polyline,v\:stroke,v\:textbox { display:inline-block;background:transparent } .GooFlow{ background:#D2E1F0 url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_bg.png) repeat-x;border:#99BBE8 1px solid;font: 12px Arial, Helvetica, sans-serif; -moz-user-select:none;-webkit-user-select:none; } .GooFlow_head{clear:both;height:22px;padding:1px} .GooFlow_head label{ font-weight:bold; text-indent:18px;display:block inline;height:14px;margin:2px;border:#B7C8D7 1px solid;border-right:#E9F4FA 1px solid;border-bottom:#E9F4FA 1px solid;padding:1px;width:160px;text-align:center; background: url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -137px 1px;float:left;color:#15428B;-moz-border-radius:3px; -webkit-border-radius:3px;border-radius:3px;overflow:hidden; } .GooFlow_head span{float:left;height:22px;width:0px;overflow:hidden;border-left:#9AC6FF 1px solid;border-right:#FFFFFF 1px solid;margin:0px 1px;} .GooFlow_head_btn{display:block;border:0px;height:18px;width:18px;cursor:default;padding:2px;margin:0px 1px;float:left;outline:none;blr:expression(this.onFocus=this.blur());} .GooFlow_head_btn b{display:inline-block;overflow:hidden;width:18px;height:18px;border:0px;} .GooFlow_head_btn:hover{ -moz-border-radius:2px; -webkit-border-radius:2px;border-radius:2px;border:#8E9DA6 1px solid; padding:0px;border:#8B7654 1px solid; background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_btn_bg.png) repeat-x;width:20px;height:20px; } .GooFlow_head_btn:hover b{border:#F6A32D 1px solid;border-top-color:#B1905D;margin:0px;-moz-border-radius:1px; -webkit-border-radius:1px;border-radius:1px;} .GooFlow_tool{ border:#B7C8D7 1px solid;float:left;margin:0px 3px;overflow:hidden;clear:left; -moz-border-radius:3px; -webkit-border-radius:3px;border-radius:3px; } .GooFlow_tool_div{border:#E9F4FA 1px solid;overflow:hidden;-moz-border-radius:2px; -webkit-border-radius:2px;border-radius:2px;width:24px;} .GooFlow_tool span{height:0px;overflow:hidden;border-bottom:#9AC6FF 1px solid;border-top:#FFFFFF 1px solid;margin:1px;clear:both;display:block;} .GooFlow_tool_btn{display:block;border:0px;height:18px;width:18px;cursor:default;padding:2px;margin:1px;outline:none;blr:expression(this.onFocus=this.blur());} .GooFlow_tool_btn b{display:block;overflow:hidden;width:18px;height:18px;border:0px} .GooFlow_tool_btn:hover{-moz-border-radius:3px; -webkit-border-radius:3px;border-radius:3px;padding:0px;border:#8E9DA6 1px solid;width:20px;height:20px;} .GooFlow_tool_btn:hover b{border:#F5FAFC 1px solid;-moz-border-radius:2px; -webkit-border-radius:2px;border-radius:2px} .GooFlow_tool_btndown{ width:20px;height:20px;cursor:default;margin:1px;outline:none;blr:expression(this.onFocus=this.blur()); -moz-border-radius:3px; -webkit-border-radius:3px;border-radius:3px;border:#8E9DA6 1px solid;border:0px; padding:0px;border:#8B7654 1px solid; background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_btn_bg.png) repeat-x;display:block; } .GooFlow_tool_btndown b{ display:block;overflow:hidden;width:14px;height:14px;border:#F6A32D 1px solid; border-top-color:#B1905D;margin:0px;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px; } .GooFlow_work{float:right;margin:0px 3px 3px 0px;border:#99B1CE 1px solid;position:relative;overflow:scroll} .GooFlow_work .GooFlow_work_inner{background-image:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_blank.gif);position:relative;overflow:hidden} .GooFlow_work .GooFlow_work_group{position:absolute;overflow:hidden;top:0px;left:0px} .GooFlow_area{position:absolute;overflow:hidden;} .GooFlow_area .lock{cursor:default;} .GooFlow_area .bg{cursor:move;filter:Alpha(Opacity=30);-moz-opacity:0.3;opacity: 0.3;} .GooFlow_work .lock .bg{cursor:default;} .GooFlow_area label{cursor:text;top:1px;left:1px;position:absolute;display:block;font-size:12px;text-indent:18px;height:18px;line-height:18px} .GooFlow_work .lock label{cursor:default;} .GooFlow_area b{display:block;height:18px;widht:18px;top:0px;left:0px;position:absolute;cursor:pointer} .GooFlow_work .area_red .bg{border:1px solid red;background-color:#FF7865} .GooFlow_work .area_red label{color:red;background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_bullet.png) no-repeat 1px 1px} .GooFlow_work .area_yellow .bg{border:1px solid #CD925A;background-color:#FFD564} .GooFlow_work .area_yellow label{color:#FFBA1D;background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_bullet.png) no-repeat 1px -16px} .GooFlow_work .area_blue .bg{border:1px solid #347BB1;background-color:#549CDE} .GooFlow_work .area_blue label{color:#347BB1;background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_bullet.png) no-repeat 1px -33px} .GooFlow_work .area_green .bg{border:1px solid green;background-color:#84CA04} .GooFlow_work .area_green label{color:green;background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_bullet.png) no-repeat 1px -50px} .GooFlow_work svg{display:block;position:absolute} .GooFlow_work v\:group{position:relative;display:block} .GooFlow_work v\:group v\:line{overflow:visible} .GooFlow_work v\:group v\:polyline{overflow:visible} .GooFlow_work v\:group div{cursor:text;position:absolute;overflow:visible;display:inline;float:left;white-space: nowrap} .GooFlow_work .draw{color:#ff3300} .GooFlow_item{ position:absolute;background:#DDE7F4 url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_btn_bg.png) repeat-x 0px -72px;border:#7DA2CE solid 1px; -moz-border-radius:3px; -webkit-border-radius:3px;border-radius:3px;color:#15428B;background-color:#C1DCFC; box-shadow:1px 1px 2px rgba(148,170,194,2);-webkit-box-shadow:1px 1px 2px rgba(148,170,194,2);-moz-box-shadow:1px 1px 2px rgba(148,170,194,2); } .GooFlow table{border:1px #EBF4FD solid;padding:0px;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px} .GooFlow td{ vertical-align:middle;text-align:center;padding:0px;cursor:default;word-wrap: break-word;word-break:break-all} .GooFlow .ico{width:18px;cursor:move} .GooFlow b{display:block;width:18px;height:18px;overflow:hidden;} .GooFlow .item_round{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_bg.png) repeat-x;-moz-border-radius:11px;-webkit-border-radius:11px;border-radius:11px;border:#7DA2CE solid 1px;width:22px;height:22px; overflow:visible} .GooFlow .item_round table{border:0px;padding:2px;width:22px;height:22px} .GooFlow .item_round .span{ display:block;text-align:center; position:absolute;top:24px;left:-28px;width:80px;overflow:visible;text-align:center; padding:0px;cursor:default;word-wrap: break-word;word-break:break-all } .GooFlow .item_complex{background:#C2DB4E;} .GooFlow div .rs_right{overflow:hidden;position:absolute;right:-1px;top:-1px;height:100%;width:6px;cursor:w-resize} .GooFlow div .rs_bottom{overflow:hidden;position:absolute;left:-1px;bottom:-1px;width:100%;height:6px;cursor:n-resize} .GooFlow div .rs_rb{ position:absolute;right:-1px;bottom:-1px;width:9px;height:9px;overflow:hidden;cursor:nw-resize;background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_tip.png) no-repeat 0px -8px; } .GooFlow div .rs_close{ position:absolute;right:1px;top:1px;width:7px;height:7px;overflow:hidden;cursor:pointer;background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_tip.png) no-repeat 0px 0px } .GooFlow .rs_ghost{ position:absolute;display:none;overflow:hidden;border:#8EA4C1 1px dashed; background:#D9E8FB; filter:Alpha(Opacity=60);-moz-opacity:0.6;opacity: 0.6;z-index:10 } .GooFlow .item_focus{border:#5068AE 1px solid} .GooFlow .item_mark{border:#ff3300 1px solid} .GooFlow .item_mark td{cursor:crosshair} .GooFlow textarea{position:absolute;border:#5068AE 1px solid;display:none;font-size:12px;overflow-y:visible;width:100px;z-index:10001} .GooFlow .GooFlow_line_oper{ width:70px;height:15px;background-color:#D8E8FC;border:#7DA2CE 1px solid;position:absolute; filter:Alpha(Opacity=50);-moz-opacity:0.5;opacity: 0.5;z-index:10000; } .GooFlow .GooFlow_line_move{filter:Alpha(Opacity=50);-moz-opacity:0.5;opacity:0.5;overflow:hidden;position:absolute;z-index:9999;background:url(0) no-repeat} .GooFlow .GooFlow_line_oper b{display:inline-block;width:15px;height:15px;margin-left:2px;cursor:pointer} .GooFlow .b_l1{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/GooFlow_line_oper.png) no-repeat 1px 1px} .GooFlow .b_l2{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/GooFlow_line_oper.png) no-repeat 1px -14px} .GooFlow .b_l3{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/GooFlow_line_oper.png) no-repeat 1px -29px} .GooFlow .b_x{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/GooFlow_line_oper.png) no-repeat 1px -44px;margin-left:10px} .GooFlow .ico_cursor{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat 2px -20px} .GooFlow .ico_start{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -19px -20px} .GooFlow .ico_end{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -39px -20px} .GooFlow .ico_fork{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -59px -20px} .GooFlow .ico_join{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -78px -20px} .GooFlow .ico_direct{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -137px -20px} .GooFlow .ico_group{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -96px -20px} .GooFlow .ico_complex{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -116px -20px} .GooFlow .ico_node{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -19px -45px} .GooFlow .ico_task{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat 2px -45px} .GooFlow .ico_chat{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -38px -45px} .GooFlow .ico_state{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -59px -45px} .GooFlow .ico_plug{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -135px -45px} .GooFlow .ico_open{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -19px 1px} .GooFlow .ico_new{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat 2px 1px} .GooFlow .ico_reload{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -97px 1px} .GooFlow .ico_save{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -39px 1px} .GooFlow .ico_undo{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -58px 1px} .GooFlow .ico_redo{background:url(http://sandbox.runjs.cn/uploads/rs/370/6xjzaeph/gooflow_icon.png) no-repeat -78px 1px} |
|||
【GooFlow】GooFlow.js | gooflow | ||
//定义一个区域图类: function GooFlow(bgDiv,property){ if (navigator.userAgent.indexOf("MSIE 8.0")>0||navigator.userAgent.indexOf("MSIE 7.0")>0||navigator.userAgent.indexOf("MSIE 6.0")>0) GooFlow.prototype.useSVG=""; else GooFlow.prototype.useSVG="1"; //初始化区域图的对象 this.$id=bgDiv.attr("id"); this.$bgDiv=bgDiv;//最父框架的DIV this.$bgDiv.addClass("GooFlow"); var width=(property.width||800)-2; var height=(property.height||500)-2; this.$bgDiv.css({width:width+"px",height:height+"px"}); this.$tool=null;//左侧工具栏对象 this.$head=null;//顶部标签及工具栏按钮 this.$title="newFlow_1";//流程图的名称 this.$nodeRemark={};//每一种结点或按钮的说明文字,JSON格式,key为类名,value为用户自定义文字说明 this.$nowType="cursor";//当前要绘制的对象类型 this.$lineData={}; this.$lineCount=0; this.$nodeData={}; this.$nodeCount=0; this.$areaData={}; this.$areaCount=0; this.$lineDom={}; this.$nodeDom={}; this.$areaDom={}; this.$max=property.initNum||1;//计算默认ID值的起始SEQUENCE this.$focus="";//当前被选定的结点/转换线ID,如果没选中或者工作区被清空,则为"" this.$cursor="default";//鼠标指针在工作区内的样式 this.$editable=false;//工作区是否可编辑 this.$deletedItem={};//在流程图的编辑操作中被删除掉的元素ID集合,元素ID为KEY,元素类型(node,line.area)为VALUE var headHeight=0; var tmp=""; if(property.haveHead){ tmp="<div class='GooFlow_head'><label title='"+(property.initLabelText||"newFlow_1")+"'>"+(property.initLabelText||"newFlow_1")+"</label>"; for(var x=0;x<property.headBtns.length;++x){ tmp+="<a href='javascript:void(0)' class='GooFlow_head_btn'><b class='ico_"+property.headBtns[x]+"'></b></a>" } tmp+="</div>"; this.$head=$(tmp); this.$bgDiv.append(this.$head); headHeight=24; //以下是当工具栏按钮被点击时触发的事件自定义(虚函数),格式为function(),因为可直接用THIS操作对象本身,不用传参;用户可自行重定义: this.onBtnNewClick=null;//新建流程图按钮被点中 this.onBtnOpenClick=null;//打开流程图按钮定义 this.onBtnSaveClick=null;//保存流程图按钮定义 this.onFreshClick=null;//重载流程图按钮定义 if(property.headBtns) this.$head.on("click",{inthis:this},function(e){ if(!e)e=window.event; var tar=e.target; if(tar.tagName=="DIV"||tar.tagName=="SPAN") return; else if(tar.tagName=="a") tar=tar.childNode[0]; var This=e.data.inthis; //定义顶部操作栏按钮的事件 switch($(tar).attr("class")){ case "ico_new": if(This.onBtnNewClick!=null) This.onBtnNewClick();break; case "ico_open": if(This.onBtnOpenClick!=null) This.onBtnOpenClick();break; case "ico_save": if(This.onBtnSaveClick!=null) This.onBtnSaveClick();break; case "ico_undo": This.undo();break; case "ico_redo": This.redo();break; case "ico_reload" :if(This.onFreshClick!=null) This.onFreshClick();break; } }); } var toolWidth=0; if(property.haveTool){ this.$bgDiv.append("<div class='GooFlow_tool'"+(property.haveHead? "":" style='margin-top:3px'")+"><div style='height:"+(height-headHeight-(property.haveHead? 7:10))+"px' class='GooFlow_tool_div'></div></div>"); this.$tool=this.$bgDiv.find(".GooFlow_tool div"); //未加代码:加入绘图工具按钮 this.$tool.append("<a href='javascript:void(0)' type='cursor' class='GooFlow_tool_btndown' id='"+this.$id+"_btn_cursor'><b class='ico_cursor'/></a><a href='javascript:void(0)' type='direct' class='GooFlow_tool_btn' id='"+this.$id+"_btn_direct'><b class='ico_direct'/></a>"); if(property.toolBtns&&property.toolBtns.length>0){ tmp="<span/>"; for(var i=0;i<property.toolBtns.length;++i){ tmp+="<a href='javascript:void(0)' type='"+property.toolBtns[i]+"' id='"+this.$id+"_btn_"+property.toolBtns[i].split(" ")[0]+"' class='GooFlow_tool_btn'><b class='ico_"+property.toolBtns[i]+"'/></a>";//加入自定义按钮 } this.$tool.append(tmp); } //加入区域划分框工具开关按钮 if(property.haveGroup) this.$tool.append("<span/><a href='javascript:void(0)' type='group' class='GooFlow_tool_btn' id='"+this.$id+"_btn_group'><b class='ico_group'/></a>"); toolWidth=31; this.$nowType="cursor"; //绑定各个按钮的点击事件 this.$tool.on("click",{inthis:this},function(e){ if(!e)e=window.event; var tar; switch(e.target.tagName){ case "SPAN":return false; case "DIV":return false; case "B": tar=e.target.parentNode;break; case "A": tar=e.target; }; var type=$(tar).attr("type"); e.data.inthis.switchToolBtn(type); return false; }); this.$editable=true;//只有具有工具栏时可编辑 } width=width-toolWidth-8; height=height-headHeight-(property.haveHead? 5:8); this.$bgDiv.append("<div class='GooFlow_work' style='width:"+(width)+"px;height:"+(height)+"px;"+(property.haveHead? "":"margin-top:3px")+"'></div>"); this.$workArea=$("<div class='GooFlow_work_inner' style='width:"+width*3+"px;height:"+height*3+"px'></div>") .attr({"unselectable":"on","onselectstart":'return false',"onselect":'document.selection.empty()'}); this.$bgDiv.children(".GooFlow_work").append(this.$workArea); this.$draw=null;//画矢量线条的容器 this.initDraw("draw_"+this.$id,width,height); this.$group=null; if(property.haveGroup) this.initGroup(width,height); if(this.$editable){ this.$workArea.on("click",{inthis:this},function(e){ if(!e)e=window.event; if(!e.data.inthis.$editable)return; var type=e.data.inthis.$nowType; if(type=="cursor"){ var t=$(e.target); var n=t.prop("tagName"); if(n=="svg"||(n=="DIV"&&t.prop("class").indexOf("GooFlow_work")>-1)||n=="LABEL")e.data.inthis.blurItem(); return; } else if(type=="direct"||type=="group")return; var X,Y; var ev=mousePosition(e),t=getElCoordinate(this); X=ev.x-t.left+this.parentNode.scrollLeft-1; Y=ev.y-t.top+this.parentNode.scrollTop-1; e.data.inthis.addNode(e.data.inthis.$id+"_node_"+e.data.inthis.$max,{name:"node_"+e.data.inthis.$max,left:X,top:Y,type:e.data.inthis.$nowType}); e.data.inthis.$max++; }); //划线或改线时用的绑定 this.$workArea.mousemove({inthis:this},function(e){ if(e.data.inthis.$nowType!="direct"&&!e.data.inthis.$mpTo.data("p")) return; var lineStart=$(this).data("lineStart"); var lineEnd=$(this).data("lineEnd"); if(!lineStart&&!lineEnd)return; var ev=mousePosition(e),t=getElCoordinate(this); var X,Y; X=ev.x-t.left+this.parentNode.scrollLeft; Y=ev.y-t.top+this.parentNode.scrollTop; var line=document.getElementById("GooFlow_tmp_line"); if(lineStart){ if(GooFlow.prototype.useSVG!=""){ line.childNodes[0].setAttribute("d","M "+lineStart.x+" "+lineStart.y+" L "+X+" "+Y); line.childNodes[1].setAttribute("d","M "+lineStart.x+" "+lineStart.y+" L "+X+" "+Y); if(line.childNodes[1].getAttribute("marker-end")=="url(\"#arrow2\")") line.childNodes[1].setAttribute("marker-end","url(#arrow3)"); else line.childNodes[1].setAttribute("marker-end","url(#arrow2)"); } else line.points.value=lineStart.x+","+lineStart.y+" "+X+","+Y; }else if(lineEnd){ if(GooFlow.prototype.useSVG!=""){ line.childNodes[0].setAttribute("d","M "+X+" "+Y+" L "+lineEnd.x+" "+lineEnd.y); line.childNodes[1].setAttribute("d","M "+X+" "+Y+" L "+lineEnd.x+" "+lineEnd.y); if(line.childNodes[1].getAttribute("marker-end")=="url(\"#arrow2\")") line.childNodes[1].setAttribute("marker-end","url(#arrow3)"); else line.childNodes[1].setAttribute("marker-end","url(#arrow2)"); } else line.points.value=X+","+Y+" "+lineEnd.x+","+lineEnd.y; } }); this.$workArea.mouseup({inthis:this},function(e){ var This=e.data.inthis; if(This.$nowType!="direct"&&!This.$mpTo.data("p")) return; $(this).css("cursor","auto").removeData("lineStart").removeData("lineEnd"); This.$mpTo.removeData("p"); This.$mpFrom.removeData("p"); var tmp=document.getElementById("GooFlow_tmp_line"); if(tmp)This.$draw.removeChild(tmp); }); //为了结点而增加的一些集体delegate绑定 this.initWorkForNode(); //对结点进行移动或者RESIZE时用来显示的遮罩层 this.$ghost=$("<div class='rs_ghost'></div>").attr({"unselectable":"on","onselectstart":'return false',"onselect":'document.selection.empty()'}); this.$bgDiv.append(this.$ghost); this.$textArea=$("<textarea></textarea>"); this.$bgDiv.append(this.$textArea); this.$lineMove=$("<div class='GooFlow_line_move' style='display:none'></div>");//操作折线时的移动框 this.$workArea.append(this.$lineMove); this.$lineMove.on("mousedown",{inthis:this},function(e){ if(e.button==2)return false; var lm=$(this); lm.css({"background-color":"#333"}); var This=e.data.inthis; var ev=mousePosition(e),t=getElCoordinate(This.$workArea[0]); var X,Y; X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft; Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop; var p=This.$lineMove.position(); var vX=X-p.left,vY=Y-p.top; var isMove=false; document.onmousemove=function(e){ if(!e)e=window.event; var ev=mousePosition(e); var ps=This.$lineMove.position(); X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft; Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop; if(This.$lineMove.data("type")=="lr"){ X=X-vX; if(X<0) X=0; else if(X>This.$workArea.width()) X=This.$workArea.width(); This.$lineMove.css({left:X+"px"}); } else if(This.$lineMove.data("type")=="tb"){ Y=Y-vY; if(Y<0) Y=0; else if(Y>This.$workArea.height()) Y=This.$workArea.height(); This.$lineMove.css({top:Y+"px"}); } isMove=true; } document.onmouseup=function(e){ if(isMove){ var p=This.$lineMove.position(); if(This.$lineMove.data("type")=="lr") This.setLineM(This.$lineMove.data("tid"),p.left+3); else if(This.$lineMove.data("type")=="tb") This.setLineM(This.$lineMove.data("tid"),p.top+3); } This.$lineMove.css({"background-color":"transparent"}); if(This.$focus==This.$lineMove.data("tid")){ This.focusItem(This.$lineMove.data("tid")); } document.onmousemove=null; document.onmouseup=null; } }); //选定一条转换线后出现的浮动操作栏,有改变线的样式和删除线等按钮。 this.$lineOper=$("<div class='GooFlow_line_oper' style='display:none'><b class='b_l1'></b><b class='b_l2'></b><b class='b_l3'></b><b class='b_x'></b></div>");//选定线时显示的操作框 this.$workArea.append(this.$lineOper); this.$lineOper.on("click",{inthis:this},function(e){ if(!e)e=window.event; if(e.target.tagName!="B") return; var This=e.data.inthis; var id=$(this).data("tid"); switch($(e.target).attr("class")){ case "b_x": This.delLine(id); this.style.display="none";break; case "b_l1": This.setLineType(id,"lr");break; case "b_l2": This.setLineType(id,"tb");break; case "b_l3": This.setLineType(id,"sl");break; } }); //新增移动线两个端点至新的结点功能移动功能,这里要提供移动用的DOM this.$mpFrom=$("<div class='GooFlow_line_mp' style='display:none'></div>"); this.$mpTo=$("<div class='GooFlow_line_mp' style='display:none'></div>"); this.$workArea.append(this.$mpFrom).append(this.$mpTo); this.initLinePointsChg(); //下面绑定当结点/线/分组块的一些操作事件,这些事件可直接通过this访问对象本身 //当操作某个单元(结点/线/分组块)被添加时,触发的方法,返回FALSE可阻止添加事件的发生 //格式function(id,type,json):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值,json即addNode,addLine或addArea方法的第二个传参json. this.onItemAdd=null; //当操作某个单元(结点/线/分组块)被删除时,触发的方法,返回FALSE可阻止删除事件的发生 //格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值 this.onItemDel=null; //当操作某个单元(结点/分组块)被移动时,触发的方法,返回FALSE可阻止移动事件的发生 //格式function(id,type,left,top):id是单元的唯一标识ID,type是单元的种类,有"node","area"两种取值,线line不支持移动,left是新的左边距坐标,top是新的顶边距坐标 this.onItemMove=null; //当操作某个单元(结点/线/分组块)被重命名时,触发的方法,返回FALSE可阻止重命名事件的发生 //格式function(id,name,type):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值,name是新的名称 this.onItemRename=null; //当操作某个单元(结点/线)被由不选中变成选中时,触发的方法,返回FALSE可阻止选中事件的发生 //格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line"两种取值,"area"不支持被选中 this.onItemFocus=null; //当操作某个单元(结点/线)被由选中变成不选中时,触发的方法,返回FALSE可阻止取消选中事件的发生 //格式function(id,type):id是单元的唯一标识ID,type是单元的种类,有"node","line"两种取值,"area"不支持被取消选中 this.onItemBlur=null; //当操作某个单元(结点/分组块)被重定义大小或造型时,触发的方法,返回FALSE可阻止重定大小/造型事件的发生 //格式function(id,type,width,height):id是单元的唯一标识ID,type是单元的种类,有"node","line","area"三种取值;width是新的宽度,height是新的高度 this.onItemResize=null; //当移动某条折线中段的位置,触发的方法,返回FALSE可阻止重定大小/造型事件的发生 //格式function(id,M):id是单元的唯一标识ID,M是中段的新X(或Y)的坐标 this.onLineMove=null; //当变换某条连接线的类型,触发的方法,返回FALSE可阻止重定大小/造型事件的发生 //格式function(id,type):id是单元的唯一标识ID,type是连接线的新类型,"sl":直线,"lr":中段可左右移动的折线,"tb":中段可上下移动的折线 this.onLineSetType=null; //当变换某条连接线的端点变更连接的结点时,触发的方法,返回FALSE可阻止重定大小/造型事件的发生 //格式function(id,newStart,newEnd):id是连线单元的唯一标识ID,newStart,newEnd分别是起始结点的ID和到达结点的ID this.onLinePointMove=null; //当用重色标注某个结点/转换线时触发的方法,返回FALSE可阻止重定大小/造型事件的发生 //格式function(id,type,mark):id是单元的唯一标识ID,type是单元类型("node"结点,"line"转换线),mark为布尔值,表示是要标注TRUE还是取消标注FALSE this.onItemMark=null; if(property.useOperStack&&this.$editable){//如果要使用堆栈记录操作并提供“撤销/重做”的功能,只在编辑状态下有效 this.$undoStack=[]; this.$redoStack=[]; this.$isUndo=0; ///////////////以下是构造撤销操作/重做操作的方法 //为了节省浏览器内存空间,undo/redo中的操作缓存栈,最多只可放40步操作;超过40步时,将自动删掉最旧的一个缓存 this.pushOper=function(funcName,paras){ var len=this.$undoStack.length; if(this.$isUndo==1){ this.$redoStack.push([funcName,paras]); this.$isUndo=false; if(this.$redoStack.length>40) this.$redoStack.shift(); }else{ this.$undoStack.push([funcName,paras]); if(this.$undoStack.length>40) this.$undoStack.shift(); if(this.$isUndo==0){ this.$redoStack.splice(0,this.$redoStack.length); } this.$isUndo=0; } }; //将外部的方法加入到GooFlow对象的事务操作堆栈中,在过后的undo/redo操作中可以进行控制,一般用于对流程图以外的附加信息进行编辑的事务撤销/重做控制; //传参func为要执行方法对象,jsonPara为外部方法仅有的一个面向字面的JSON传参,由JSON对象带入所有要传的信息; //提示:为了让外部方法能够被UNDO/REDO,需要在编写这些外部方法实现时,加入对该方法执行后效果回退的另一个执行方法的pushExternalOper this.pushExternalOper=function(func,jsonPara){ this.pushOper("externalFunc",[func,jsonPara]); }; //撤销上一步操作 this.undo=function(){ if(this.$undoStack.length==0) return; this.blurItem(); var tmp=this.$undoStack.pop(); this.$isUndo=1; if(tmp[0]=="externalFunc"){ tmp[1][0](tmp[1][1]); } else{ //传参的数量,最多支持6个. switch(tmp[1].length){ case 0:this[tmp[0]]();break; case 1:this[tmp[0]](tmp[1][0]);break; case 2:this[tmp[0]](tmp[1][0],tmp[1][1]);break; case 3:this[tmp[0]](tmp[1][0],tmp[1][1],tmp[1][2]);break; case 4:this[tmp[0]](tmp[1][0],tmp[1][1],tmp[1][2],tmp[1][3]);break; case 5:this[tmp[0]](tmp[1][0],tmp[1][1],tmp[1][2],tmp[1][3],tmp[1][4]);break; case 6:this[tmp[0]](tmp[1][0],tmp[1][1],tmp[1][2],tmp[1][3],tmp[1][4],tmp[1][5]);break; } } }; //重做最近一次被撤销的操作 this.redo=function(){ if(this.$redoStack.length==0) return; this.blurItem(); var tmp=this.$redoStack.pop(); this.$isUndo=2; if(tmp[0]=="externalFunc"){ tmp[1][0](tmp[1][1]); } else{ //传参的数量,最多支持6个. switch(tmp[1].length){ case 0:this[tmp[0]]();break; case 1:this[tmp[0]](tmp[1][0]);break; case 2:this[tmp[0]](tmp[1][0],tmp[1][1]);break; case 3:this[tmp[0]](tmp[1][0],tmp[1][1],tmp[1][2]);break; case 4:this[tmp[0]](tmp[1][0],tmp[1][1],tmp[1][2],tmp[1][3]);break; case 5:this[tmp[0]](tmp[1][0],tmp[1][1],tmp[1][2],tmp[1][3],tmp[1][4]);break; case 6:this[tmp[0]](tmp[1][0],tmp[1][1],tmp[1][2],tmp[1][3],tmp[1][4],tmp[1][5]);break; } } }; } $(document).keydown({inthis:this},function(e){ //绑定键盘操作 var This=e.data.inthis; if(This.$focus=="")return; switch(e.keyCode){ case 46://删除 This.delNode(This.$focus,true); This.delLine(This.$focus); break; } }); } } GooFlow.prototype={ useSVG:"", getSvgMarker:function(id,color){ var m=document.createElementNS("http://www.w3.org/2000/svg","marker"); m.setAttribute("id",id); m.setAttribute("viewBox","0 0 6 6"); m.setAttribute("refX",5); m.setAttribute("refY",3); m.setAttribute("markerUnits","strokeWidth"); m.setAttribute("markerWidth",6); m.setAttribute("markerHeight",6); m.setAttribute("orient","auto"); var path=document.createElementNS("http://www.w3.org/2000/svg","path"); path.setAttribute("d","M 0 0 L 6 3 L 0 6 z"); path.setAttribute("fill",color); path.setAttribute("stroke-width",0); m.appendChild(path); return m; }, initDraw:function(id,width,height){ var elem; if(GooFlow.prototype.useSVG!=""){ this.$draw=document.createElementNS("http://www.w3.org/2000/svg","svg");//可创建带有指定命名空间的元素节点 this.$workArea.prepend(this.$draw); var defs=document.createElementNS("http://www.w3.org/2000/svg","defs"); this.$draw.appendChild(defs); defs.appendChild(GooFlow.prototype.getSvgMarker("arrow1","#15428B")); defs.appendChild(GooFlow.prototype.getSvgMarker("arrow2","#ff3300")); defs.appendChild(GooFlow.prototype.getSvgMarker("arrow3","#ff3300")); } else{ this.$draw = document.createElement("v:group"); this.$draw.coordsize = width*3+","+height*3; this.$workArea.prepend("<div class='GooFlow_work_vml' style='position:relative;width:"+width*3+"px;height:"+height*3+"px'></div>"); this.$workArea.children("div")[0].insertBefore(this.$draw,null); } this.$draw.id = id; this.$draw.style.width = width*3 + "px"; this.$draw.style.height = +height*3 + "px"; //绑定连线的点击选中以及双击编辑事件 var tmpClk=null; if(GooFlow.prototype.useSVG!="") tmpClk="g"; else tmpClk="PolyLine"; if(!this.$editable) return; $(this.$draw).delegate(tmpClk,"click",{inthis:this},function(e){ e.data.inthis.focusItem(this.id,true); }); $(this.$draw).delegate(tmpClk,"dblclick",{inthis:this},function(e){ var oldTxt,x,y,from,to; var This=e.data.inthis; if(GooFlow.prototype.useSVG!=""){ oldTxt=this.childNodes[2].textContent; from=this.getAttribute("from").split(","); to=this.getAttribute("to").split(","); }else{ oldTxt=this.childNodes[1].innerHTML; var n=this.getAttribute("fromTo").split(","); from=[n[0],n[1]]; to=[n[2],n[3]]; } if(This.$lineData[this.id].type=="lr"){ from[0]=This.$lineData[this.id].M; to[0]=from[0]; } else if(This.$lineData[this.id].type=="tb"){ from[1]=This.$lineData[this.id].M; to[1]=from[1]; } x=(parseInt(from[0],10)+parseInt(to[0],10))/2-60; y=(parseInt(from[1],10)+parseInt(to[1],10))/2-12; var t=getElCoordinate(This.$workArea[0]); This.$textArea.val(oldTxt).css({display:"block",width:120,height:14, left:t.left+x-This.$workArea[0].parentNode.scrollLeft, top:t.top+y-This.$workArea[0].parentNode.scrollTop}).data("id",This.$focus).focus(); This.$workArea.parent().one("mousedown",function(e){ if(e.button==2)return false; This.setName(This.$textArea.data("id"),This.$textArea.val(),"line"); This.$textArea.val("").removeData("id").hide(); }); }); }, initGroup:function(width,height){ this.$group=$("<div class='GooFlow_work_group' style='width:"+width*3+"px;height:"+height*3+"px'></div>");//存放背景区域的容器 this.$workArea.prepend(this.$group); if(!this.$editable) return; //区域划分框操作区的事件绑定 this.$group.on("mousedown",{inthis:this},function(e){//绑定RESIZE功能以及移动功能 if(e.button==2)return false; var This=e.data.inthis; if(This.$nowType!="group") return; if(This.$textArea.css("display")=="block"){ This.setName(This.$textArea.data("id"),This.$textArea.val(),"area"); This.$textArea.val("").removeData("id").hide(); return false; }; if(!e)e=window.event; var cursor=$(e.target).css("cursor"); var id=e.target.parentNode; switch(cursor){ case "nw-resize":id=id.parentNode;break; case "w-resize":id=id.parentNode;break; case "n-resize":id=id.parentNode;break; case "move":break; default:return; } id=id.id; var hack=1; if(navigator.userAgent.indexOf("8.0")!=-1) hack=0; var ev=mousePosition(e),t=getElCoordinate(This.$workArea[0]); var X,Y; X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft; Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop; if(cursor!="move"){ This.$ghost.css({display:"block", width:This.$areaData[id].width-2+"px", height:This.$areaData[id].height-2+"px", top:This.$areaData[id].top+t.top-This.$workArea[0].parentNode.scrollTop+hack+"px", left:This.$areaData[id].left+t.left-This.$workArea[0].parentNode.scrollLeft+hack+"px",cursor:cursor}); var vX=(This.$areaData[id].left+This.$areaData[id].width)-X; var vY=(This.$areaData[id].top+This.$areaData[id].height)-Y; } else{ var vX=X-This.$areaData[id].left; var vY=Y-This.$areaData[id].top; } var isMove=false; This.$ghost.css("cursor",cursor); document.onmousemove=function(e){ if(!e)e=window.event; var ev=mousePosition(e); if(cursor!="move"){ X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft-This.$areaData[id].left+vX; Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop-This.$areaData[id].top+vY; if(X<200) X=200; if(Y<100) Y=100; switch(cursor){ case "nw-resize":This.$ghost.css({width:X-2+"px",height:Y-2+"px"});break; case "w-resize":This.$ghost.css({width:X-2+"px"});break; case "n-resize":This.$ghost.css({height:Y-2+"px"});break; } } else{ if(This.$ghost.css("display")=="none"){ This.$ghost.css({display:"block", width:This.$areaData[id].width-2+"px", height:This.$areaData[id].height-2+"px", top:This.$areaData[id].top+t.top-This.$workArea[0].parentNode.scrollTop+hack+"px", left:This.$areaData[id].left+t.left-This.$workArea[0].parentNode.scrollLeft+hack+"px",cursor:cursor}); } X=ev.x-vX;Y=ev.y-vY; if(X<t.left-This.$workArea[0].parentNode.scrollLeft) X=t.left-This.$workArea[0].parentNode.scrollLeft; else if(X+This.$workArea[0].parentNode.scrollLeft+This.$areaData[id].width>t.left+This.$workArea.width()) X=t.left+This.$workArea.width()-This.$workArea[0].parentNode.scrollLeft-This.$areaData[id].width; if(Y<t.top-This.$workArea[0].parentNode.scrollTop) Y=t.top-This.$workArea[0].parentNode.scrollTop; else if(Y+This.$workArea[0].parentNode.scrollTop+This.$areaData[id].height>t.top+This.$workArea.height()) Y=t.top+This.$workArea.height()-This.$workArea[0].parentNode.scrollTop-This.$areaData[id].height; This.$ghost.css({left:X+hack+"px",top:Y+hack+"px"}); } isMove=true; } document.onmouseup=function(e){ This.$ghost.empty().hide(); document.onmousemove=null; document.onmouseup=null; if(!isMove)return; if(cursor!="move") This.resizeArea(id,This.$ghost.outerWidth(),This.$ghost.outerHeight()); else This.moveArea(id,X+This.$workArea[0].parentNode.scrollLeft-t.left,Y+This.$workArea[0].parentNode.scrollTop-t.top); return false; } }); //绑定修改文字说明功能 this.$group.on("dblclick",{inthis:this},function(e){ var This=e.data.inthis; if(This.$nowType!="group") return; if(!e)e=window.event; if(e.target.tagName!="LABEL") return false; var oldTxt=e.target.innerHTML; var p=e.target.parentNode; var x=parseInt(p.style.left,10)+18,y=parseInt(p.style.top,10)+1; var t=getElCoordinate(This.$workArea[0]); This.$textArea.val(oldTxt).css({display:"block",width:100,height:14, left:t.left+x-This.$workArea[0].parentNode.scrollLeft, top:t.top+y-This.$workArea[0].parentNode.scrollTop}).data("id",p.id).focus(); This.$workArea.parent().one("mousedown",function(e){ if(e.button==2)return false; if(This.$textArea.css("display")=="block"){ This.setName(This.$textArea.data("id"),This.$textArea.val(),"area"); This.$textArea.val("").removeData("id").hide(); } }); return false; }); //绑定点击事件 this.$group.mouseup({inthis:this},function(e){ var This=e.data.inthis; if(This.$nowType!="group") return; if(!e)e=window.event; switch($(e.target).attr("class")){ case "rs_close": This.delArea(e.target.parentNode.parentNode.id);return false;//删除该分组区域 case "bg": return; } switch(e.target.tagName){ case "LABEL": return false; case "B"://绑定变色功能 var id=e.target.parentNode.id; switch(This.$areaData[id].color){ case "red": This.setAreaColor(id,"yellow");break; case "yellow": This.setAreaColor(id,"blue");break; case "blue": This.setAreaColor(id,"green");break; case "green": This.setAreaColor(id,"red");break; } return false; } if(e.data.inthis.$ghost.css("display")=="none"){ var X,Y; var ev=mousePosition(e),t=getElCoordinate(this); X=ev.x-t.left+this.parentNode.parentNode.scrollLeft-1; Y=ev.y-t.top+this.parentNode.parentNode.scrollTop-1; var color=["red","yellow","blue","green"]; e.data.inthis.addArea(e.data.inthis.$id+"_area_"+e.data.inthis.$max,{name:"area_"+e.data.inthis.$max,left:X,top:Y,color:color[e.data.inthis.$max%4],width:200,height:100}); e.data.inthis.$max++; return false; } }); }, //初始化用来改变连线的连接端点的两个小方块的操作事件 initLinePointsChg:function(){ this.$mpFrom.on("mousedown",{inthis:this},function(e){ var This=e.data.inthis; This.switchToolBtn("cursor"); var ps=This.$mpFrom.data("p").split(","); var pe=This.$mpTo.data("p").split(","); $(this).hide(); This.$workArea.data("lineEnd",{"x":pe[0],"y":pe[1],"id":This.$lineData[This.$lineOper.data("tid")].to}).css("cursor","crosshair"); var line=GooFlow.prototype.drawLine("GooFlow_tmp_line",[ps[0],ps[1]],[pe[0],pe[1]],true,true); This.$draw.appendChild(line); }); this.$mpTo.on("mousedown",{inthis:this},function(e){ var This=e.data.inthis; This.switchToolBtn("cursor"); var ps=This.$mpFrom.data("p").split(","); var pe=This.$mpTo.data("p").split(","); $(this).hide(); This.$workArea.data("lineStart",{"x":ps[0],"y":ps[1],"id":This.$lineData[This.$lineOper.data("tid")].from}).css("cursor","crosshair"); var line=GooFlow.prototype.drawLine("GooFlow_tmp_line",[ps[0],ps[1]],[pe[0],pe[1]],true,true); This.$draw.appendChild(line); }); }, //每一种类型结点及其按钮的说明文字 setNodeRemarks:function(remark){ this.$tool.children("a").each(function(){ this.title=remark[$(this).attr("id").split("btn_")[1]]; }); this.$nodeRemark=remark; }, //切换左边工具栏按钮,传参TYPE表示切换成哪种类型的按钮 switchToolBtn:function(type){ this.$tool.children("#"+this.$id+"_btn_"+this.$nowType.split(" ")[0]).attr("class","GooFlow_tool_btn"); if(this.$nowType=="group"){ this.$workArea.prepend(this.$group); for(var key in this.$areaDom) this.$areaDom[key].addClass("lock").children("div:eq(1)").css("display","none"); } this.$nowType=type; this.$tool.children("#"+this.$id+"_btn_"+type.split(" ")[0]).attr("class","GooFlow_tool_btndown"); if(this.$nowType=="group"){ this.blurItem(); this.$workArea.append(this.$group); for(var key in this.$areaDom) this.$areaDom[key].removeClass("lock").children("div:eq(1)").css("display",""); } if(this.$textArea.css("display")=="none") this.$textArea.removeData("id").val("").hide(); }, //增加一个流程结点,传参为一个JSON,有id,name,top,left,width,height,type(结点类型)等属性 addNode:function(id,json){ if(this.onItemAdd!=null&&!this.onItemAdd(id,"node",json))return; if(this.$undoStack&&this.$editable){ this.pushOper("delNode",[id]); } var mark=json.mark? " item_mark":""; if(json.type.indexOf(" round")<0){ if(!json.width||json.width<86)json.width=86; if(!json.height||json.height<24)json.height=24; if(!json.top||json.top<0)json.top=0; if(!json.left||json.left<0)json.left=0; var hack=0; if(navigator.userAgent.indexOf("8.0")!=-1) hack=2; this.$nodeDom[id]=$("<div class='GooFlow_item"+mark+"' id='"+id+"' style='top:"+json.top+"px;left:"+json.left+"px'><table cellspacing='1' style='width:"+(json.width-2)+"px;height:"+(json.height-2)+"px;'><tr><td class='ico'><b class='ico_"+json.type+"'></b></td><td>"+json.name+"</td></tr></table><div style='display:none'><div class='rs_bottom'></div><div class='rs_right'></div><div class='rs_rb'></div><div class='rs_close'></div></div></div>"); if(json.type.indexOf(" mix")>-1) this.$nodeDom[id].addClass("item_mix"); } else{ json.width=24;json.height=24; this.$nodeDom[id]=$("<div class='GooFlow_item item_round"+mark+"' id='"+id+"' style='top:"+json.top+"px;left:"+json.left+"px'><table cellspacing='0'><tr><td class='ico'><b class='ico_"+json.type+"'></b></td></tr></table><div style='display:none'><div class='rs_close'></div></div><div class='span'>"+json.name+"</div></div>"); } var ua=navigator.userAgent.toLowerCase(); if(ua.indexOf('msie')!=-1 && ua.indexOf('8.0')!=-1) this.$nodeDom[id].css("filter","progid:DXImageTransform.Microsoft.Shadow(color=#94AAC2,direction=135,strength=2)"); this.$workArea.append(this.$nodeDom[id]); this.$nodeData[id]=json; ++this.$nodeCount; if(this.$editable){ this.$nodeData[id].alt=true; if(this.$deletedItem[id]) delete this.$deletedItem[id];//在回退删除操作时,去掉该元素的删除记录 } }, initWorkForNode:function(){ //绑定点击事件 this.$workArea.delegate(".GooFlow_item","click",{inthis:this},function(e){ e.data.inthis.focusItem(this.id,true); $(this).removeClass("item_mark"); }); //绑定用鼠标移动事件 this.$workArea.delegate(".ico","mousedown",{inthis:this},function(e){ if(!e)e=window.event; if(e.button==2)return false; var This=e.data.inthis; if(This.$nowType=="direct") return; var Dom=$(this).parents(".GooFlow_item"); var id=Dom.attr("id"); This.focusItem(id,true); var hack=1; if(navigator.userAgent.indexOf("8.0")!=-1) hack=0; var ev=mousePosition(e),t=getElCoordinate(This.$workArea[0]); Dom.children("table").clone().prependTo(This.$ghost); var X,Y; X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft; Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop; var vX=X-This.$nodeData[id].left,vY=Y-This.$nodeData[id].top; var isMove=false; document.onmousemove=function(e){ if(!e)e=window.event; var ev=mousePosition(e); if(X==ev.x-vX&&Y==ev.y-vY) return false; X=ev.x-vX;Y=ev.y-vY; if(isMove&&This.$ghost.css("display")=="none"){ This.$ghost.css({display:"block", width:This.$nodeData[id].width-2+"px", height:This.$nodeData[id].height-2+"px", top:This.$nodeData[id].top+t.top-This.$workArea[0].parentNode.scrollTop+hack+"px", left:This.$nodeData[id].left+t.left-This.$workArea[0].parentNode.scrollLeft+hack+"px",cursor:"move" }); } if(X<t.left-This.$workArea[0].parentNode.scrollLeft) X=t.left-This.$workArea[0].parentNode.scrollLeft; else if(X+This.$workArea[0].parentNode.scrollLeft+This.$nodeData[id].width>t.left+This.$workArea.width()) X=t.left+This.$workArea.width()-This.$workArea[0].parentNode.scrollLeft-This.$nodeData[id].width; if(Y<t.top-This.$workArea[0].parentNode.scrollTop) Y=t.top-This.$workArea[0].parentNode.scrollTop; else if(Y+This.$workArea[0].parentNode.scrollTop+This.$nodeData[id].height>t.top+This.$workArea.height()) Y=t.top+This.$workArea.height()-This.$workArea[0].parentNode.scrollTop-This.$nodeData[id].height; This.$ghost.css({left:X+hack+"px",top:Y+hack+"px"}); isMove=true; } document.onmouseup=function(e){ if(isMove)This.moveNode(id,X+This.$workArea[0].parentNode.scrollLeft-t.left,Y+This.$workArea[0].parentNode.scrollTop-t.top); This.$ghost.empty().hide(); document.onmousemove=null; document.onmouseup=null; } }); if(!this.$editable) return; //绑定鼠标覆盖/移出事件 this.$workArea.delegate(".GooFlow_item","mouseenter",{inthis:this},function(e){ if(e.data.inthis.$nowType!="direct"&&!e.data.inthis.$mpTo.data("p")) return; $(this).addClass("item_mark"); }); this.$workArea.delegate(".GooFlow_item","mouseleave",{inthis:this},function(e){ if(e.data.inthis.$nowType!="direct"&&!e.data.inthis.$mpTo.data("p")) return; $(this).removeClass("item_mark"); }); //绑定连线时确定初始点 this.$workArea.delegate(".GooFlow_item","mousedown",{inthis:this},function(e){ if(e.button==2)return false; var This=e.data.inthis; if(This.$nowType!="direct") return; var ev=mousePosition(e),t=getElCoordinate(This.$workArea[0]); var X,Y; X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft; Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop; This.$workArea.data("lineStart",{"x":X,"y":Y,"id":this.id}).css("cursor","crosshair"); var line=GooFlow.prototype.drawLine("GooFlow_tmp_line",[X,Y],[X,Y],true,true); This.$draw.appendChild(line); }); //绑定连线时确定结束点 this.$workArea.delegate(".GooFlow_item","mouseup",{inthis:this},function(e){ var This=e.data.inthis; if(This.$nowType!="direct"&&!This.$mpTo.data("p")) return; var lineStart=This.$workArea.data("lineStart"); var lineEnd=This.$workArea.data("lineEnd"); if(lineStart&&!This.$mpTo.data("p")){ This.addLine(This.$id+"_line_"+This.$max,{from:lineStart.id,to:this.id,name:""}); This.$max++; } else{ if(lineStart){ This.moveLinePoints(This.$focus,lineStart.id,this.id); }else if(lineEnd){ This.moveLinePoints(This.$focus,this.id,lineEnd.id); } } }); //绑定双击编辑事件 this.$workArea.delegate(".GooFlow_item > .span","dblclick",{inthis:this},function(e){ var oldTxt=this.innerHTML; var This=e.data.inthis; var id=this.parentNode.id; var t=getElCoordinate(This.$workArea[0]); This.$textArea.val(oldTxt).css({display:"block",height:$(this).height(),width:100, left:t.left+This.$nodeData[id].left-This.$workArea[0].parentNode.scrollLeft-24, top:t.top+This.$nodeData[id].top-This.$workArea[0].parentNode.scrollTop+26}) .data("id",This.$focus).focus(); This.$workArea.parent().one("mousedown",function(e){ if(e.button==2)return false; This.setName(This.$textArea.data("id"),This.$textArea.val(),"node"); This.$textArea.val("").removeData("id").hide(); }); }); this.$workArea.delegate(".ico + td","dblclick",{inthis:this},function(e){ var oldTxt=this.innerHTML; var This=e.data.inthis; var id=$(this).parents(".GooFlow_item").attr("id"); var t=getElCoordinate(This.$workArea[0]); This.$textArea.val(oldTxt).css({display:"block",width:$(this).width()+24,height:$(this).height(), left:t.left+24+This.$nodeData[id].left-This.$workArea[0].parentNode.scrollLeft, top:t.top+2+This.$nodeData[id].top-This.$workArea[0].parentNode.scrollTop}) .data("id",This.$focus).focus(); This.$workArea.parent().one("mousedown",function(e){ if(e.button==2)return false; This.setName(This.$textArea.data("id"),This.$textArea.val(),"node"); This.$textArea.val("").removeData("id").hide(); }); }); //绑定结点的删除功能 this.$workArea.delegate(".rs_close","click",{inthis:this},function(e){ if(!e)e=window.event; e.data.inthis.delNode(e.data.inthis.$focus); return false; }); //绑定结点的RESIZE功能 this.$workArea.delegate(".GooFlow_item > div > div[class!=rs_close]","mousedown",{inthis:this},function(e){ if(!e)e=window.event; if(e.button==2)return false; var cursor=$(this).css("cursor"); if(cursor=="pointer"){return;} var This=e.data.inthis; var id=This.$focus; This.switchToolBtn("cursor"); e.cancelBubble = true; e.stopPropagation(); var hack=1; if(navigator.userAgent.indexOf("8.0")!=-1) hack=0; var ev=mousePosition(e),t=getElCoordinate(This.$workArea[0]); This.$ghost.css({display:"block", width:This.$nodeData[id].width-2+"px", height:This.$nodeData[id].height-2+"px", top:This.$nodeData[id].top+t.top-This.$workArea[0].parentNode.scrollTop+hack+"px", left:This.$nodeData[id].left+t.left-This.$workArea[0].parentNode.scrollLeft+hack+"px",cursor:cursor }); var X,Y; X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft; Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop; var vX=(This.$nodeData[id].left+This.$nodeData[id].width)-X; var vY=(This.$nodeData[id].top+This.$nodeData[id].height)-Y; var isMove=false; This.$ghost.css("cursor",cursor); document.onmousemove=function(e){ if(!e)e=window.event; var ev=mousePosition(e); X=ev.x-t.left+This.$workArea[0].parentNode.scrollLeft-This.$nodeData[id].left+vX; Y=ev.y-t.top+This.$workArea[0].parentNode.scrollTop-This.$nodeData[id].top+vY; if(X<86) X=86; if(Y<24) Y=24; isMove=true; switch(cursor){ case "nw-resize":This.$ghost.css({width:X-2+"px",height:Y-2+"px"});break; case "w-resize":This.$ghost.css({width:X-2+"px"});break; case "n-resize":This.$ghost.css({height:Y-2+"px"});break; } } document.onmouseup=function(e){ This.$ghost.hide(); if(!isMove)return; if(!e)e=window.event; This.resizeNode(id,This.$ghost.outerWidth(),This.$ghost.outerHeight()); document.onmousemove=null; document.onmouseup=null; } }); }, //获取结点/连线/分组区域的详细信息 getItemInfo:function(id,type){ switch(type){ case "node": return this.$nodeData[id]||null; case "line": return this.$lineData[id]||null; case "area": return this.$areaData[id]||null; } }, //取消所有结点/连线被选定的状态 blurItem:function(){ if(this.$focus!=""){ var jq=$("#"+this.$focus); if(jq.prop("tagName")=="DIV"){ if(this.onItemBlur!=null&&!this.onItemBlur(id,"node")) return false; jq.removeClass("item_focus").children("div:eq(0)").css("display","none"); } else{ if(this.onItemBlur!=null&&!this.onItemBlur(id,"line")) return false; if(GooFlow.prototype.useSVG!=""){ if(!this.$lineData[this.$focus].marked){ jq[0].childNodes[1].setAttribute("stroke","#5068AE"); jq[0].childNodes[1].setAttribute("marker-end","url(#arrow1)"); } } else{ if(!this.$lineData[this.$focus].marked) jq[0].strokeColor="#5068AE"; } this.$lineMove.hide().removeData("type").removeData("tid"); if(this.$editable){ this.$lineOper.hide().removeData("tid"); this.$mpFrom.hide().removeData("p"); this.$mpTo.hide().removeData("p"); } } } this.$focus=""; return true; }, //选定某个结点/转换线 bool:TRUE决定了要触发选中事件,FALSE则不触发选中事件,多用在程序内部调用。 focusItem:function(id,bool){ var jq=$("#"+id); if(jq.length==0) return; if(!this.blurItem()) return;//先执行"取消选中",如果返回FLASE,则也会阻止选定事件继续进行. if(jq.prop("tagName")=="DIV"){ if(bool&&this.onItemFocus!=null&&!this.onItemFocus(id,"node")) return; jq.addClass("item_focus"); if(this.$editable)jq.children("div:eq(0)").css("display","block"); this.$workArea.append(jq); } else{//如果是连接线 if(this.onItemFocus!=null&&!this.onItemFocus(id,"line")) return; if(GooFlow.prototype.useSVG!=""){ jq[0].childNodes[1].setAttribute("stroke","#ff3300"); jq[0].childNodes[1].setAttribute("marker-end","url(#arrow2)"); } else jq[0].strokeColor="#ff3300"; this.$draw.appendChild(jq[0]); if(!this.$editable) return; var x,y,from,to,n; if(GooFlow.prototype.useSVG!=""){ from=jq.attr("from").split(","); to=jq.attr("to").split(","); n=[from[0],from[1],to[0],to[1]]; }else{ n=jq[0].getAttribute("fromTo").split(","); from=[n[0],n[1]]; to=[n[2],n[3]]; } from[0]=parseInt(from[0],10); from[1]=parseInt(from[1],10); to[0]=parseInt(to[0],10); to[1]=parseInt(to[1],10); //var t=getElCoordinate(this.$workArea[0]); if(this.$lineData[id].type=="lr"){ from[0]=this.$lineData[id].M; to[0]=from[0]; this.$lineMove.css({ width:"5px",height:(to[1]-from[1])*(to[1]>from[1]? 1:-1)+"px", left:from[0]-3+"px", top:(to[1]>from[1]? from[1]:to[1])+1+"px", cursor:"e-resize",display:"block" }).data({"type":"lr","tid":id}); } else if(this.$lineData[id].type=="tb"){ from[1]=this.$lineData[id].M; to[1]=from[1]; this.$lineMove.css({ width:(to[0]-from[0])*(to[0]>from[0]? 1:-1)+"px",height:"5px", left:(to[0]>from[0]? from[0]:to[0])+1+"px", top:from[1]-3+"px", cursor:"s-resize",display:"block" }).data({"type":"tb","tid":id}); } x=(from[0]+to[0])/2-35; y=(from[1]+to[1])/2+6; this.$lineOper.css({display:"block",left:x+"px",top:y+"px"}).data("tid",id); if(this.$editable){ this.$mpFrom.css({display:"block",left:n[0]-4+"px",top:n[1]-4+"px"}).data("p",n[0]+","+n[1]); this.$mpTo.css({display:"block",left:n[2]-4+"px",top:n[3]-4+"px"}).data("p",n[2]+","+n[3]); } } this.$focus=id; this.switchToolBtn("cursor"); }, //移动结点到一个新的位置 moveNode:function(id,left,top){ if(!this.$nodeData[id]) return; if(this.onItemMove!=null&&!this.onItemMove(id,"node",left,top)) return; if(this.$undoStack){ var paras=[id,this.$nodeData[id].left,this.$nodeData[id].top]; this.pushOper("moveNode",paras); } if(left<0) left=0; if(top<0) top=0; $("#"+id).css({left:left+"px",top:top+"px"}); this.$nodeData[id].left=left; this.$nodeData[id].top=top; //重画转换线 this.resetLines(id,this.$nodeData[id]); if(this.$editable){ this.$nodeData[id].alt=true; } }, //设置结点/连线/分组区域的文字信息 setName:function(id,name,type){ var oldName; if(type=="node"){//如果是结点 if(!this.$nodeData[id]) return; if(this.$nodeData[id].name==name) return; if(this.onItemRename!=null&&!this.onItemRename(id,name,"node")) return; oldName=this.$nodeData[id].name; this.$nodeData[id].name=name; if(this.$nodeData[id].type.indexOf("round")>1){ this.$nodeDom[id].children(".span").text(name); } else{ this.$nodeDom[id].find("td:eq(1)").text(name); var hack=0; if(navigator.userAgent.indexOf("8.0")!=-1) hack=2; var width=this.$nodeDom[id].outerWidth(); var height=this.$nodeDom[id].outerHeight(); this.$nodeDom[id].children("table").css({width:width-2+"px",height:height-2+"px"}); this.$nodeData[id].width=width; this.$nodeData[id].height=height; } if(this.$editable){ this.$nodeData[id].alt=true; } //重画转换线 this.resetLines(id,this.$nodeData[id]); } else if(type=="line"){//如果是线 if(!this.$lineData[id]) return; if(this.$lineData[id].name==name) return; if(this.onItemRename!=null&&!this.onItemRename(id,name,"line")) return; oldName=this.$lineData[id].name; this.$lineData[id].name=name; if(GooFlow.prototype.useSVG!=""){ this.$lineDom[id].childNodes[2].textContent=name; } else{ this.$lineDom[id].childNodes[1].innerHTML=name; var n=this.$lineDom[id].getAttribute("fromTo").split(","); var x; if(this.$lineData[id].type!="lr"){ x=(n[2]-n[0])/2; } else{ var Min=n[2]>n[0]? n[0]:n[2]; if(Min>this.$lineData[id].M) Min=this.$lineData[id].M; x=this.$lineData[id].M-Min; } if(x<0) x=x*-1; this.$lineDom[id].childNodes[1].style.left=x-this.$lineDom[id].childNodes[1].offsetWidth/2+4+"px"; } if(this.$editable){ this.$lineData[id].alt=true; } } else if(type=="area"){//如果是分组区域 if(!this.$areaData[id]) return; if(this.$areaData[id].name==name) return; if(this.onItemRename!=null&&!this.onItemRename(id,name,"area")) return; oldName=this.$areaData[id].name; this.$areaData[id].name=name; this.$areaDom[id].children("label").text(name); if(this.$editable){ this.$areaData[id].alt=true; } } if(this.$undoStack){ var paras=[id,oldName,type]; this.pushOper("setName",paras); } }, //设置结点的尺寸,仅支持非开始/结束结点 resizeNode:function(id,width,height){ if(!this.$nodeData[id]) return; if(this.onItemResize!=null&&!this.onItemResize(id,"node",width,height)) return; if(this.$nodeData[id].type=="start"||this.$nodeData[id].type=="end")return; if(this.$undoStack){ var paras=[id,this.$nodeData[id].width,this.$nodeData[id].height]; this.pushOper("resizeNode",paras); } var hack=0; if(navigator.userAgent.indexOf("8.0")!=-1) hack=2; this.$nodeDom[id].children("table").css({width:width-2+"px",height:height-2+"px"}); width=this.$nodeDom[id].outerWidth()-hack; height=this.$nodeDom[id].outerHeight()-hack; this.$nodeDom[id].children("table").css({width:width-2+"px",height:height-2+"px"}); this.$nodeData[id].width=width; this.$nodeData[id].height=height; if(this.$editable){ this.$nodeData[id].alt=true; } //重画转换线 this.resetLines(id,this.$nodeData[id]); }, //删除结点 delNode:function(id){ if(!this.$nodeData[id]) return; if(this.onItemDel!=null&&!this.onItemDel(id,"node")) return; //先删除可能的连线 for(var k in this.$lineData){ if(this.$lineData[k].from==id||this.$lineData[k].to==id){ //this.$draw.removeChild(this.$lineDom[k]); //delete this.$lineData[k]; //delete this.$lineDom[k]; this.delLine(k); } } //再删除结点本身 if(this.$undoStack){ var paras=[id,this.$nodeData[id]]; this.pushOper("addNode",paras); } delete this.$nodeData[id]; this.$nodeDom[id].remove(); delete this.$nodeDom[id]; --this.$nodeCount; if(this.$focus==id) this.$focus=""; if(this.$editable){ //在回退新增操作时,如果节点ID以this.$id+"_node_"开头,则表示为本次编辑时新加入的节点,这些节点的删除不用加入到$deletedItem中 if(id.indexOf(this.$id+"_node_")<0) this.$deletedItem[id]="node"; } }, //设置流程图的名称 setTitle:function(text){ this.$title=text; if(this.$head) this.$head.children("label").attr("title",text).text(text); }, //载入一组数据 loadData:function(data){ var t=this.$editable; this.$editable=false; if(data.title) this.setTitle(data.title); if(data.initNum) this.$max=data.initNum; for(var i in data.nodes) this.addNode(i,data.nodes[i]); for(var j in data.lines) this.addLine(j,data.lines[j]); for(var k in data.areas) this.addArea(k,data.areas[k]); this.$editable=t; this.$deletedItem={}; }, //用AJAX方式,远程读取一组数据 //参数para为JSON结构,与JQUERY中$.ajax()方法的传参一样 loadDataAjax:function(para){ var This=this; $.ajax({ type:para.type, url:para.url, dataType:"json", data:para.data, success: function(msg){ if(para.dataFilter) para.dataFilter(msg,"json"); This.loadData(msg); if(para.success) para.success(msg); }, error: function(XMLHttpRequest, textStatus, errorThrown){ if(para.error) para.error(textStatus,errorThrown); } }) }, //把画好的整个流程图导出到一个变量中(其实也可以直接访问GooFlow对象的$nodeData,$lineData,$areaData这三个JSON属性) exportData:function(){ var ret={title:this.$title,nodes:this.$nodeData,lines:this.$lineData,areas:this.$areaData,initNum:this.$max}; for(var k1 in ret.nodes){ if(!ret.nodes[k1].marked){ delete ret.nodes[k1]["marked"]; } } for(var k2 in ret.lines){ if(!ret.lines[k2].marked){ delete ret.lines[k2]["marked"]; } } return ret; }, //只把本次编辑流程图中作了变更(包括增删改)的元素导出到一个变量中,以方便用户每次编辑载入的流程图后只获取变更过的数据 exportAlter:function(){ var ret={nodes:{},lines:{},areas:{}}; for(var k1 in this.$nodeData){ if(this.$nodeData[k1].alt){ ret.nodes[k1]=this.$nodeData[k1]; } } for(var k2 in this.$lineData){ if(this.$lineData[k2].alt){ ret.lines[k2]=this.$lineData[k2]; } } for(var k3 in this.$areaData){ if(this.$areaData[k3].alt){ ret.areas[k3]=this.$areaData[k3]; } } ret.deletedItem=this.$deletedItem; return ret; }, //变更元素的ID,一般用于快速保存后,将后台返回新元素的ID更新到页面中;type为元素类型(节点,连线,区块) transNewId:function(oldId,newId,type){ var tmp; switch(type){ case "node": if(this.$nodeData[oldId]){ tmp=this.$nodeData[oldId]; delete this.$nodeData[oldId]; this.$nodeData[newId]=tmp; } break; case "line": if(this.$lineData[oldId]){ tmp=this.$lineData[oldId]; delete this.$lineData[oldId]; this.$lineData[newId]=tmp; } break; case "area": if(this.$areaData[oldId]){ tmp=this.$areaData[oldId]; delete this.$areaData[oldId]; this.$areaData[newId]=tmp; } break; } }, //清空工作区及已载入的数据 clearData:function(){ for(var key in this.$nodeData){ this.delNode(key); } for(var key in this.$lineData){ this.delLine(key); } for(var key in this.$areaData){ this.delArea(key); } this.$deletedItem={}; }, //销毁自己 destrory:function(){ this.$bgDiv.empty(); this.$lineData=null; this.$nodeData=null; this.$lineDom=null; this.$nodeDom=null; this.$areaDom=null; this.$areaData=null; this.$nodeCount=0; this.$areaCount=0; this.$areaCount=0; this.$deletedItem={}; }, ///////////以下为有关画线的方法 //绘制一条箭头线,并返回线的DOM drawLine:function(id,sp,ep,mark,dash){ var line; if(GooFlow.prototype.useSVG!=""){ line=document.createElementNS("http://www.w3.org/2000/svg","g"); var hi=document.createElementNS("http://www.w3.org/2000/svg","path"); var path=document.createElementNS("http://www.w3.org/2000/svg","path"); if(id!="") line.setAttribute("id",id); line.setAttribute("from",sp[0]+","+sp[1]); line.setAttribute("to",ep[0]+","+ep[1]); hi.setAttribute("visibility","hidden"); hi.setAttribute("stroke-width",9); hi.setAttribute("fill","none"); hi.setAttribute("stroke","white"); hi.setAttribute("d","M "+sp[0]+" "+sp[1]+" L "+ep[0]+" "+ep[1]); hi.setAttribute("pointer-events","stroke"); path.setAttribute("d","M "+sp[0]+" "+sp[1]+" L "+ep[0]+" "+ep[1]); path.setAttribute("stroke-width",1.4); path.setAttribute("stroke-linecap","round"); path.setAttribute("fill","none"); if(dash) path.setAttribute("style", "stroke-dasharray:6,5"); if(mark){ path.setAttribute("stroke","#ff3300"); path.setAttribute("marker-end","url(#arrow2)"); } else{ path.setAttribute("stroke","#5068AE"); path.setAttribute("marker-end","url(#arrow1)"); } line.appendChild(hi); line.appendChild(path); line.style.cursor="crosshair"; if(id!=""&&id!="GooFlow_tmp_line"){ var text=document.createElementNS("http://www.w3.org/2000/svg","text"); //text.textContent=id; line.appendChild(text); var x=(ep[0]+sp[0])/2; var y=(ep[1]+sp[1])/2; text.setAttribute("text-anchor","middle"); text.setAttribute("x",x); text.setAttribute("y",y); line.style.cursor="pointer"; text.style.cursor="text"; } }else{ line=document.createElement("v:polyline"); if(id!="") line.id=id; //line.style.position="absolute"; line.points.value=sp[0]+","+sp[1]+" "+ep[0]+","+ep[1]; line.setAttribute("fromTo",sp[0]+","+sp[1]+","+ep[0]+","+ep[1]); line.strokeWeight="1.2"; line.stroke.EndArrow="Block"; line.style.cursor="crosshair"; if(id!=""&&id!="GooFlow_tmp_line"){ var text=document.createElement("div"); //text.innerHTML=id; line.appendChild(text); var x=(ep[0]-sp[0])/2; var y=(ep[1]-sp[1])/2; if(x<0) x=x*-1; if(y<0) y=y*-1; text.style.left=x+"px"; text.style.top=y-6+"px"; line.style.cursor="pointer"; } if(dash) line.stroke.dashstyle="Dash"; if(mark) line.strokeColor="#ff3300"; else line.strokeColor="#5068AE"; } return line; }, //画一条只有两个中点的折线 drawPoly:function(id,sp,m1,m2,ep,mark){ var poly,strPath; if(GooFlow.prototype.useSVG!=""){ poly=document.createElementNS("http://www.w3.org/2000/svg","g"); var hi=document.createElementNS("http://www.w3.org/2000/svg","path"); var path=document.createElementNS("http://www.w3.org/2000/svg","path"); if(id!="") poly.setAttribute("id",id); poly.setAttribute("from",sp[0]+","+sp[1]); poly.setAttribute("to",ep[0]+","+ep[1]); hi.setAttribute("visibility","hidden"); hi.setAttribute("stroke-width",9); hi.setAttribute("fill","none"); hi.setAttribute("stroke","white"); strPath="M "+sp[0]+" "+sp[1]; if(m1[0]!=sp[0]||m1[1]!=sp[1]) strPath+=" L "+m1[0]+" "+m1[1]; if(m2[0]!=ep[0]||m2[1]!=ep[1]) strPath+=" L "+m2[0]+" "+m2[1]; strPath+=" L "+ep[0]+" "+ep[1]; hi.setAttribute("d",strPath); hi.setAttribute("pointer-events","stroke"); path.setAttribute("d",strPath); path.setAttribute("stroke-width",1.4); path.setAttribute("stroke-linecap","round"); path.setAttribute("fill","none"); if(mark){ path.setAttribute("stroke","#ff3300"); path.setAttribute("marker-end","url(#arrow2)"); } else{ path.setAttribute("stroke","#5068AE"); path.setAttribute("marker-end","url(#arrow1)"); } poly.appendChild(hi); poly.appendChild(path); var text=document.createElementNS("http://www.w3.org/2000/svg","text"); //text.textContent=id; poly.appendChild(text); var x=(m2[0]+m1[0])/2; var y=(m2[1]+m1[1])/2; text.setAttribute("text-anchor","middle"); text.setAttribute("x",x); text.setAttribute("y",y); text.style.cursor="text"; poly.style.cursor="pointer"; } else{ poly=document.createElement("v:Polyline"); if(id!="") poly.id=id; poly.filled="false"; strPath=sp[0]+","+sp[1]; if(m1[0]!=sp[0]||m1[1]!=sp[1]) strPath+=" "+m1[0]+","+m1[1]; if(m2[0]!=ep[0]||m2[1]!=ep[1]) strPath+=" "+m2[0]+","+m2[1]; strPath+=" "+ep[0]+","+ep[1]; poly.points.value=strPath; poly.setAttribute("fromTo",sp[0]+","+sp[1]+","+ep[0]+","+ep[1]); poly.strokeWeight="1.2"; poly.stroke.EndArrow="Block"; var text=document.createElement("div"); //text.innerHTML=id; poly.appendChild(text); var x=(m2[0]-m1[0])/2; var y=(m2[1]-m1[1])/2; if(x<0) x=x*-1; if(y<0) y=y*-1; text.style.left=x+"px"; text.style.top=y-4+"px"; poly.style.cursor="pointer"; if(mark) poly.strokeColor="#ff3300"; else poly.strokeColor="#5068AE"; } return poly; }, //计算两个结点间要连直线的话,连线的开始坐标和结束坐标 calcStartEnd:function(n1,n2){ var X_1,Y_1,X_2,Y_2; //X判断: var x11=n1.left,x12=n1.left+n1.width,x21=n2.left,x22=n2.left+n2.width; //结点2在结点1左边 if(x11>=x22){ X_1=x11;X_2=x22; } //结点2在结点1右边 else if(x12<=x21){ X_1=x12;X_2=x21; } //结点2在结点1水平部分重合 else if(x11<=x21&&x12>=x21&&x12<=x22){ X_1=(x12+x21)/2;X_2=X_1; } else if(x11>=x21&&x12<=x22){ X_1=(x11+x12)/2;X_2=X_1; } else if(x21>=x11&&x22<=x12){ X_1=(x21+x22)/2;X_2=X_1; } else if(x11<=x22&&x12>=x22){ X_1=(x11+x22)/2;X_2=X_1; } //Y判断: var y11=n1.top,y12=n1.top+n1.height,y21=n2.top,y22=n2.top+n2.height; //结点2在结点1上边 if(y11>=y22){ Y_1=y11;Y_2=y22; } //结点2在结点1下边 else if(y12<=y21){ Y_1=y12;Y_2=y21; } //结点2在结点1垂直部分重合 else if(y11<=y21&&y12>=y21&&y12<=y22){ Y_1=(y12+y21)/2;Y_2=Y_1; } else if(y11>=y21&&y12<=y22){ Y_1=(y11+y12)/2;Y_2=Y_1; } else if(y21>=y11&&y22<=y12){ Y_1=(y21+y22)/2;Y_2=Y_1; } else if(y11<=y22&&y12>=y22){ Y_1=(y11+y22)/2;Y_2=Y_1; } return {"start":[X_1,Y_1],"end":[X_2,Y_2]}; }, //计算两个结点间要连折线的话,连线的所有坐标 calcPolyPoints:function(n1,n2,type,M){ //开始/结束两个结点的中心 var SP={x:n1.left+n1.width/2,y:n1.top+n1.height/2}; var EP={x:n2.left+n2.width/2,y:n2.top+n2.height/2}; var sp=[],m1=[],m2=[],ep=[]; //如果是允许中段可左右移动的折线,则参数M为可移动中段线的X坐标 //粗略计算起始点 sp=[SP.x,SP.y]; ep=[EP.x,EP.y]; if(type=="lr"){ //粗略计算2个中点 m1=[M,SP.y]; m2=[M,EP.y]; //再具体分析修改开始点和中点1 if(m1[0]>n1.left&&m1[0]<n1.left+n1.width){ m1[1]=(SP.y>EP.y? n1.top:n1.top+n1.height); sp[0]=m1[0];sp[1]=m1[1]; } else{ sp[0]=(m1[0]<n1.left? n1.left:n1.left+n1.width) } //再具体分析中点2和结束点 if(m2[0]>n2.left&&m2[0]<n2.left+n2.width){ m2[1]=(SP.y>EP.y? n2.top+n2.height:n2.top); ep[0]=m2[0];ep[1]=m2[1]; } else{ ep[0]=(m2[0]<n2.left? n2.left:n2.left+n2.width) } } //如果是允许中段可上下移动的折线,则参数M为可移动中段线的Y坐标 else if(type=="tb"){ //粗略计算2个中点 m1=[SP.x,M]; m2=[EP.x,M]; //再具体分析修改开始点和中点1 if(m1[1]>n1.top&&m1[1]<n1.top+n1.height){ m1[0]=(SP.x>EP.x? n1.left:n1.left+n1.width); sp[0]=m1[0];sp[1]=m1[1]; } else{ sp[1]=(m1[1]<n1.top? n1.top:n1.top+n1.height) } //再具体分析中点2和结束点 if(m2[1]>n2.top&&m2[1]<n2.top+n2.height){ m2[0]=(SP.x>EP.x? n2.left+n2.width:n2.left); ep[0]=m2[0];ep[1]=m2[1]; } else{ ep[1]=(m2[1]<n2.top? n2.top:n2.top+n2.height); } } return {start:sp,m1:m1,m2:m2,end:ep}; }, //初始化折线中段的X/Y坐标,mType='rb'时为X坐标,mType='tb'时为Y坐标 getMValue:function(n1,n2,mType){ if(mType=="lr"){ return (n1.left+n1.width/2+n2.left+n2.width/2)/2; } else if(mType=="tb"){ return (n1.top+n1.height/2+n2.top+n2.height/2)/2; } }, //原lineData已经设定好的情况下,只在绘图工作区画一条线的页面元素 addLineDom:function(id,lineData){ var n1=this.$nodeData[lineData.from],n2=this.$nodeData[lineData.to];//获取开始/结束结点的数据 if(!n1||!n2) return; //开始计算线端点坐标 var res; if(lineData.type&&lineData.type!="sl") res=GooFlow.prototype.calcPolyPoints(n1,n2,lineData.type,lineData.M); else res=GooFlow.prototype.calcStartEnd(n1,n2); if(!res) return; if(lineData.type=="sl") this.$lineDom[id]=GooFlow.prototype.drawLine(id,res.start,res.end,lineData.mark); else this.$lineDom[id]=GooFlow.prototype.drawPoly(id,res.start,res.m1,res.m2,res.end,lineData.mark); this.$draw.appendChild(this.$lineDom[id]); if(GooFlow.prototype.useSVG==""){ this.$lineDom[id].childNodes[1].innerHTML=lineData.name; if(lineData.type!="sl"){ var Min=(res.start[0]>res.end[0]? res.end[0]:res.start[0]); if(Min>res.m2[0]) Min=res.m2[0]; if(Min>res.m1[0]) Min=res.m1[0]; this.$lineDom[id].childNodes[1].style.left = (res.m2[0]+res.m1[0])/2-Min-this.$lineDom[id].childNodes[1].offsetWidth/2+4; Min=(res.start[1]>res.end[1]? res.end[1]:res.start[1]); if(Min>res.m2[1]) Min=res.m2[1]; if(Min>res.m1[1]) Min=res.m1[1]; this.$lineDom[id].childNodes[1].style.top = (res.m2[1]+res.m1[1])/2-Min-this.$lineDom[id].childNodes[1].offsetHeight/2; }else this.$lineDom[id].childNodes[1].style.left= ((res.end[0]-res.start[0])*(res.end[0]>res.start[0]? 1:-1)-this.$lineDom[id].childNodes[1].offsetWidth)/2+4; } else this.$lineDom[id].childNodes[2].textContent=lineData.name; }, //增加一条线 addLine:function(id,json){ if(this.onItemAdd!=null&&!this.onItemAdd(id,"line",json))return; if(this.$undoStack&&this.$editable){ this.pushOper("delLine",[id]); } if(json.from==json.to) return; var n1=this.$nodeData[json.from],n2=this.$nodeData[json.to];//获取开始/结束结点的数据 if(!n1||!n2) return; //避免两个节点间不能有一条以上同向接连线 for(var k in this.$lineData){ if((json.from==this.$lineData[k].from&&json.to==this.$lineData[k].to)) return; } //设置$lineData[id] this.$lineData[id]={}; if(json.type){ this.$lineData[id].type=json.type; this.$lineData[id].M=json.M; } else this.$lineData[id].type="sl";//默认为直线 this.$lineData[id].from=json.from; this.$lineData[id].to=json.to; this.$lineData[id].name=json.name; if(json.mark) this.$lineData[id].marked=json.mark; else this.$lineData[id].marked=false; //设置$lineData[id]完毕 this.addLineDom(id,this.$lineData[id]); ++this.$lineCount; if(this.$editable){ this.$lineData[id].alt=true; if(this.$deletedItem[id]) delete this.$deletedItem[id];//在回退删除操作时,去掉该元素的删除记录 } }, //重构所有连向某个结点的线的显示,传参结构为$nodeData数组的一个单元结构 resetLines:function(id,node){ for(var i in this.$lineData){ var other=null;//获取结束/开始结点的数据 var res; if(this.$lineData[i].from==id){//找结束点 other=this.$nodeData[this.$lineData[i].to]||null; if(other==null) continue; if(this.$lineData[i].type=="sl") res=GooFlow.prototype.calcStartEnd(node,other); else res=GooFlow.prototype.calcPolyPoints(node,other,this.$lineData[i].type,this.$lineData[i].M) if(!res) break; } else if(this.$lineData[i].to==id){//找开始点 other=this.$nodeData[this.$lineData[i].from]||null; if(other==null) continue; if(this.$lineData[i].type=="sl") res=GooFlow.prototype.calcStartEnd(other,node); else res=GooFlow.prototype.calcPolyPoints(other,node,this.$lineData[i].type,this.$lineData[i].M); if(!res) break; } if(other==null) continue; this.$draw.removeChild(this.$l |
|||
【lhdialog】lhgDialog窗口组件 | lhgdialog | ||
【jeasyui 1.4.2】methods扩展之showCellTip | jeasyui | 基于1.3.3版本tooltip的datagrid单元格tip实现 | |
$.extend($.fn.datagrid.methods, { /** * 开打提示功能 * @param {} jq * @param {} params 提示消息框的样式 * @return {} */ showCellTip: function (jq, params) { function showTip(data, td, e) { if ($(td).text() == "") return; data.tooltip.text($(td).text()).css({ top: (e.pageY) + 'px', left: (e.pageX) + 'px', 'z-index': $.fn.window.defaults.zIndex, display: 'block' }); }; return jq.each(function () { var grid = $(this); var options = $(this).data('datagrid'); if (!options.tooltip) { var panel = grid.datagrid('getPanel').panel('panel'); var defaultCls = { 'border': '1px solid #333', 'padding': '0.5em', 'color': '#333', 'background': '#f7f5d1', 'position': 'absolute', 'max-width': '200px', 'border-radius': '4px', '-moz-border-radius': '4px', '-webkit-border-radius': '4px', 'display': 'none' } var tooltip = $("<div id='celltip'></div>").appendTo('body'); tooltip.css($.extend({}, defaultCls, params.cls)); options.tooltip = tooltip; panel.find('.datagrid-body').each(function () { var delegateEle = $(this).find('> div.datagrid-body-inner').length ? $(this).find('> div.datagrid-body-inner')[0] : this; $(delegateEle).undelegate('td', 'mouseover').undelegate( 'td', 'mouseout').undelegate('td', 'mousemove') .delegate('td', { 'mouseover': function (e) { if (params.delay) { if (options.tipDelayTime) clearTimeout(options.tipDelayTime); var that = this; options.tipDelayTime = setTimeout( function () { showTip(options, that, e); }, params.delay); } else { showTip(options, this, e); } }, 'mouseout': function (e) { if (options.tipDelayTime) clearTimeout(options.tipDelayTime); options.tooltip.css({ 'display': 'none' }); }, 'mousemove': function (e) { var that = this; if (options.tipDelayTime) { clearTimeout(options.tipDelayTime); options.tipDelayTime = setTimeout( function () { showTip(options, that, e); }, params.delay); } else { showTip(options, that, e); } } }); }); } }); }, /** * 关闭消息提示功能 * @param {} jq * @return {} */ hideCellTip: function (jq) { return jq.each(function () { var data = $(this).data('datagrid'); if (data.tooltip) { data.tooltip.remove(); data.tooltip = null; var panel = $(this).datagrid('getPanel').panel('panel'); panel.find('.datagrid-body').undelegate('td', 'mouseover').undelegate('td', 'mouseout') .undelegate('td', 'mousemove') } if (data.tipDelayTime) { clearTimeout(data.tipDelayTime); data.tipDelayTime = null; } }); } }); // 示例 $productTables.datagrid('showCellTip', { onlyShowInterrupt: false, //是否只有在文字被截断时才显示tip,默认值为false position: 'bottom', //tip的位置,可以为top,botom,right,left cls: { 'background-color': '#D1EEEE' }, //tip的样式 delay: 100 //tip 响应时间 }); $productTables.datagrid('hideCellTip'); |
|||
【jeasyui 1.3.6】methods扩展之showHideFieldsMenu表头右击字段显隐菜单【版本2】 | jeasyui | ||
$.extend($.fn.datagrid.methods,{ // 表头右击字段显隐菜单 showHideFieldsMenu : function(jq) { var menuID = jq.attr("id") + "_context_menu"; var $contextMenu = $("#" + menuID); if ($contextMenu.length > 0) { return; } var fieldArray = jq.datagrid('getColumnFields'); if (null == fieldArray || fieldArray == undefined) { return; } $contextMenu = $('<div class="easyui-menu" style="width:100px;"></div>').appendTo('body'); $contextMenu.attr("id", menuID); var $fieldHTML = $('<div><span>显示/隐藏列</span></div>').appendTo($contextMenu); var $filedsList = $('<div class="menu-content" style="text-align:left"/>').appendTo($fieldHTML); var $menuItemList = $("<ul class='menu-table-fields'/>"); for (var i = 0; i < fieldArray.length; i++) { var checkboxID = menuID + "_checkbox_" + i; var $checkBox = $('<input type="checkbox">').attr("id", checkboxID); var $label = $('<label>' + jq.datagrid('getColumnOption', fieldArray[i]).title + '</label>'); $label.attr("for", checkboxID); var $menuItem = $('<li />').append($checkBox).append($label); if (jq.datagrid('getColumnOption', fieldArray[i]).hidden == true) { $checkBox.attr('checked', true); } $checkBox.bind('click', { $jq : jq, field : fieldArray[i] }, function(ev) { var flag = ev.data.$jq.datagrid('getColumnOption', ev.data.field).hidden; $(this).attr('checked', !flag); var action = flag ? "showColumn" : "hideColumn"; ev.data.$jq.datagrid(action, ev.data.field); }); $checkBox.bind('mouseover', function(){ $(this).css('cursor', 'pointer'); }).bind('mouseleft', function() { $(this).css('cursor', 'none'); }); $label.bind('mouseover', function(){ $(this).css('cursor', 'pointer'); }).bind('mouseleft', function() { $(this).css('cursor', 'none'); }); $menuItemList.append($menuItem); } $filedsList.append($menuItemList); $.parser.parse(); jq.datagrid({ onHeaderContextMenu : function(e, field) { e.preventDefault(); $contextMenu.menu('show', { left : $(event.target).offset().left, top : $(event.target).offset().top + 10 }); } }); } }); 相关CSS: ul.menu-table-fields li{ list-style: none; line-height: 2.1em; margin-left: -3em; border-bottom: 1px solid #C1C1C1; } ul.menu-table-fields li:HOVER{ background-color: #C1CDCD; } |
|||
【SQLServer】常用查询 | sqlserver | ||
查询表下所有字段信息 SELECT * FROM SysColumns WHERE id=Object_Id('TableName') ; 查询包含指定字段的表 SELECT object_name(id), * FROM SysColumns WHERE name like 'campaign_code2' ; |
|||
【spring mvc】ObjectMapper之类型转换 | spring mvc | SpringMVC+MyBatis - 12 spring mvc4返回的json日期为Long的解决方案 | |
import java.io.IOException; import java.util.Date; import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.JsonProcessingException; import org.codehaus.jackson.map.JsonSerializer; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializerProvider; import org.codehaus.jackson.map.ser.CustomSerializerFactory; import org.springframework.stereotype.Service; @Service public class CustomObjectMapper extends ObjectMapper { public CustomObjectMapper() { CustomSerializerFactory factory = new CustomSerializerFactory(); factory.addGenericMapping(Date.class, new JsonSerializer<Date>() { @Override public void serialize(Date value, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException, JsonProcessingException { // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // jsonGenerator.writeString(sdf.format(value)); if(null != value){ jsonGenerator.writeString(String.valueOf(value.getTime())); } } }); this.setSerializerFactory(factory); } } xml 配置 <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="objectMapper" ref="customObjectMapper"/> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> </list> </property> </bean> |
|||
【spring mvc】多数据源配置 | spring mvc | Spring+Mybatis 多数据源配置 | |
【注意项】 1. spring-test 3 是根据autowired自动注入;与junit 4.8.1结合使用; 2. @Resource、@Autowired、@Qualifier的注解注入及区别 @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入; @Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用; @Resource注解是又J2EE提供,而@Autowired是由Spring提供,故减少系统对spring的依赖建议使用@Resource的方式; @Resource和@Autowired都可以书写标注在字段或者该字段的setter方法之上 3. spring-test 2.5.6 是通过set方法注入,而不是注解,可解决多数据库的问题; spring-test 2.5.6 与 junit 3.8.1结合使用;即: <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>2.5.6</version> </dependency> --------------------------------------------------------------------------------------- 1、注解式事务声明 @Transactional(value = "insurance", rollbackFor = Exception.class) @Transactional(value = "isap", rollbackFor = Exception.class) <bean id="transactionManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource2" /> <qualifier value="insurance" /> </bean> |
|||
【jeasyui 1.3.6】methods扩展之columnMoving表头拖拽 | jeasyui | ||
$.extend($.fn.datagrid.methods,{ columnMoving: function(jq){ return jq.each(function(){ var target = this; var cells = $(this).datagrid('getPanel').find('div.datagrid-header td[field]'); cells.draggable({ revert:true, cursor:'pointer', edge:5, proxy:function(source){ var p = $('<div class="tree-node-proxy tree-dnd-no" style="position:absolute;border:1px solid #ff0000"/>').appendTo('body'); p.html($(source).text()); p.hide(); return p; }, onBeforeDrag:function(e){ e.data.startLeft = $(this).offset().left; e.data.startTop = $(this).offset().top; }, onStartDrag: function(){ $(this).draggable('proxy').css({ left:-10000, top:-10000 }); }, onDrag:function(e){ $(this).draggable('proxy').show().css({ left:e.pageX+15, top:e.pageY+15 }); return false; } }).droppable({ accept:'td[field]', onDragOver:function(e,source){ $(source).draggable('proxy').removeClass('tree-dnd-no').addClass('tree-dnd-yes'); $(this).css('border-left','1px solid #ff0000'); }, onDragLeave:function(e,source){ $(source).draggable('proxy').removeClass('tree-dnd-yes').addClass('tree-dnd-no'); $(this).css('border-left',0); }, onDrop:function(e,source){ $(this).css('border-left',0); var fromField = $(source).attr('field'); var toField = $(this).attr('field'); setTimeout(function(){ moveField(fromField,toField); $(target).datagrid(); $(target).datagrid('columnMoving'); },0); } }); // move field to another location function moveField(from,to){ var columns = $(target).datagrid('options').columns; var cc = columns[0]; var c = _remove(from); if (c){ _insert(to,c); } function _remove(field){ for(var i=0; i<cc.length; i++){ if (cc[i].field == field){ var c = cc[i]; cc.splice(i,1); return c; } } return null; } function _insert(field,c){ var newcc = new Array(); for(var i=0; i<cc.length; i++){ if (cc[i].field == field){ newcc.push(c); } newcc.push(cc[i]); } columns[0] = newcc; } } }); } }); // 调用示例 $('#tt').datagrid({ // url: 'datagrid_data3.json', title: 'DataGrid', width: 700, height: 220, fitColumns: true, nowrap:false, rownumbers:true, showFooter:true, columns:[[ {field:'itemid',title:'Item ID',width:80}, {field:'productid',title:'Product ID',width:120}, {field:'listprice',title:'List Price',width:80,align:'right'}, {field:'unitcost',title:'Unit Cost',width:80,align:'right'}, {field:'attr1',title:'Attribute',width:250, hidden:true}, {field:'status',title:'Status',width:60,align:'center'} ]] }).datagrid("columnMoving"); |
|||
【jeasyui 1.3.6】methods扩展之showHideFieldsMenu表头右击字段显隐菜单 | jeasyui | ||
$.extend($.fn.datagrid.methods,{ showHideFieldsMenu : function(jq) { var menuID = jq.attr("id") + "_context_menu"; var $contextMenu = $("#" + menuID); if ($contextMenu.length > 0) { return; } var fieldArray = jq.datagrid('getColumnFields'); if (null == fieldArray || fieldArray == undefined) { return; } $contextMenu = $('<div class="easyui-menu" style="width:100px;"></div>').appendTo('body'); $contextMenu.attr("id", menuID); var $fieldHTML = $('<div><span>显示/隐藏列</span></div>').appendTo($contextMenu); var $filedsList = $('<div class="menu-content" style="text-align:left;padding:10px"/>').appendTo($fieldHTML); for (var i = 0; i < fieldArray.length; i++) { var $checkBox = $('<input type="checkbox">'); var $label = $('<span>' + jq.datagrid('getColumnOption', fieldArray[i]).title + '</span>'); var $menuItem = $('<div style="padding-left:-2em;"/>').append($checkBox).append($label); if (jq.datagrid('getColumnOption', fieldArray[i]).hidden == true) { $checkBox.attr('checked', true); } $checkBox.bind('click', { $jq : jq, field : fieldArray[i] }, function(ev) { var flag = ev.data.$jq.datagrid('getColumnOption', ev.data.field).hidden; $(this).attr('checked', !flag); var action = flag ? "showColumn" : "hideColumn"; ev.data.$jq.datagrid(action, ev.data.field); }); $label.bind('mouseover', function() { $(this).css('cursor', 'pointer'); }).bind('mouseleft', function() { $(this).css('cursor', 'none'); }).bind('click', {$jq : jq, checkbox : $checkBox, field : fieldArray[i] }, function(ev) { var flag = ev.data.$jq.datagrid('getColumnOption', ev.data.field).hidden; ev.data.checkbox.attr('checked', !flag); var action = flag ? "showColumn" : "hideColumn"; ev.data.$jq.datagrid(action, ev.data.field); }); $filedsList.append($menuItem); } $.parser.parse(); jq.datagrid({ onHeaderContextMenu : function(e, field) { e.preventDefault(); $contextMenu.menu('show', { left : event.pageX, top : event.pageY }); } }); } }); // 使用 $('#tt').datagrid({ // url: 'datagrid_data3.json', title: 'DataGrid', width: 700, height: 220, fitColumns: true, nowrap:false, rownumbers:true, showFooter:true, columns:[[ {field:'itemid',title:'Item ID',width:80}, {field:'productid',title:'Product ID',width:120}, {field:'listprice',title:'List Price',width:80,align:'right'}, {field:'unitcost',title:'Unit Cost',width:80,align:'right'}, {field:'attr1',title:'Attribute',width:250, hidden:true}, {field:'status',title:'Status',width:60,align:'center'} ]] }).datagrid("showHideFieldsMenu"); |
|||
【保险】投连险 | 保险 | 初始费用占大头 解读投连险的费用 | |
投连险的一个特点是费用透明,但收费项目较多。目前市场上的投连险产品层出不穷,但在收费上仍存在个体差异,在投保前,投保人不妨对投连险的7项费用做个梳理。 从珠海友邦保险了解到,根据2007年10月1日开始实施的《投资连结保险精算规定》(以下简称精算规定),投连险收取7项费用:初始费用、买入卖出差价、死亡风险保险费、保单管理费、资产管理费、手续费(账户转换、部分领取时)和退保费用。 初始费用占大头 初始费用是投保人所缴的保费在进入投资账户前扣除的那部分费用。 根据缴费方式的不同,趸缴型和期缴型扣除的比例也有区别。如果购买的是趸缴型产品,一般保险公司会根据投入资金的多少,来设定不同的扣除比例,投入越多,初始费用越低,比如瑞泰安裕之选(趸缴型)规定,缴费2万~10万元的部分收3%,10万~50万元的部分收2%,50万元以上收1.5%。也有一些保险公司不区分投入资金的高低,规定单一的初始费用比例。期缴型产品缴费时虽然分为年缴、季缴和月缴,但是初始费用的计费标准却都是按照年度来计算的,同一年内,收费比例不变。 期缴形式的投连险,对基本保费和额外保费部分所能收取的初始费用差别较大。基本保费不能高于保险金额(指保单签发时的死亡保险金额)除以20,并不得超过人民币6000元;如果单期所缴保费超出上面的数额,超出部分就要算作额外保费。按照精算规定,基本保费所能收取的初始费用比例首年可高达50%,而额外保费初始费用上限仅为5%。比如张先生投保某投连险(期缴型),保额10万元,首年投入1万元。收取初始费用时,基本保费部分(100000元÷20=5000元)按50%的比例收取2500元,额外保费部分(10000元-5000元=5000元)按5%的比例收取250元。 |
|||
【保险】万能险 | 保险 | ||
万能险 由于万能险集保障、储蓄与理财功能于一体,具有缴费灵活、存取方便、利率保底、保额自主等特点,所以通俗地称为“万能”。 万能险结算公式:riskprem=riskamnt*premrate/1000*n/365 死亡风险保额:指有效保额减去保单账户价值。其中有效保额是指被保险人因疾病和意外等身故时,保险公司支付的死亡保险金额。 风险保费:根据风险保额所得到的保费。 初始费用:即保险费进入万能账户之前扣除的费用。 万能结算公式 风险保额:riskamnt 主险保额:amnt 附加险保额:famnt 现价:av 风险保费:主险gl,附加重疾险kf,轻症重疾mc 费率:rate 1.AULA : riskamnt=max(amnt,av*1.05)-av gl=riskamnt*rate*日差/1000/365 附加险 ADDC riskamnt=max(famnt,av*1.05)-av*( max(famnt,av*1.05)/ max(amnt,av*1.05) ) kf =riskamnt*rate*日差/1000/365 2.AULC附加险ADDl多一个轻症重疾mc责任 mc=附加险基本保额*0.2*rate*日差/1000/365 3.AULB:直接使用保额 gl=amnt*rate*日差/1000/365 ; 附加险 ADDE kf =famnt*rate*日差/1000/365 4.BULA,BULB,BULC 只收取管理费,而且是一个固定值 10 12 前5个保单年度12,从第6个保单年度开始6. 期交产品 保单年度 初始费用上限 第一年 50% 第二年 25% 第三年 15% 第四、五年 10% 以后各年 5% 追加部分不得高于5% 趸交产品 保险费 初始费用上限 人民币50000元及以下部分 10% 人民币50000元以上部分 5% 趸交保险费保单追加保险费的初始费用比例的上限为5%。 万能险相关的表 --万能险费率表 select * from riskprem_aula; --万能险初始费用表 select * from initprem_aula; --万能险结算利率表 select * from lminsuaccrate; --万能险账户表 select * from lcinsureacc; --万能险账户子表 select * from lcinsureaccclass; --万能险结算轨迹表 select * from lcinsureacctrace; --万能险保额分层表 select * from lyamntlayer; --万能扣费表 select * from lcinsureaccfee; --万能扣费子账户表 select * from lcinsureaccclassfee; --扣费轨迹表 select * from lcinsureaccfeetrace; --万能险投资计划表 >6000部分的分配计划 select * from lcperinvestplan; --账户定义表 select * from lmriskinsuacc; --险种层变化的轨迹表 select * from lppolchangetrace; --账户轨迹表 select * from lpaccchangetrace; --账户定义表 select * from lmrisktoacc; |
|||
【oracle】常用脚本 | oracle | ||
使用rename关键字来实现字段名的修改:alter table 表名 rename column旧的字段名 to 新的字段名名; 使用modify关键字来实现对数据类型的修改:alter table 表名 modify 字段名 数据类型; -- 增加字段 alter table temp_user add sysdatestr varchar(40); alter table temp_user add (sysdatestr varchar(40) default 'tsfdwe'); -- 移除字段 alter table temp_user drop column sysdatestr; Oracle修改字段类型方法总结: http://blog.csdn.net/gdjlc/article/details/23762549 -- 假设字段数据为空,则不管改为什么字段类型,可以直接执行 alter table temp_user modify (sysdatestr varchar2(20)); |
|||
【oracle】提取字段中的数字 | oracle | ||
select TRIM(TRANSLATE('<ROOT><MPAGE32ID>20673</MP', trim( TRANSLATE('<ROOT><MPAGE32ID>20673</MP', '0123456789', ' ') ), ' ')) from dual 结果:3220673 内层的TRANSLATE将数字替换成空格 外层的TRANSLATE将数字之外的替换成空格,剩下的就是数字了 注意:全角数字也会被过滤掉 如: select TRIM(TRANSLATE('<ROOT><MPAGE32ID1526>20673</MP', trim( TRANSLATE('<ROOT><MPAGE32ID1526>20673</MP', '0123456789', ' ') ), ' ')) from dual 结果:3220673 电话号码字段非空,且仅包含数字的: select * from member_user t where t.user_mobile is not null and translate(t.user_mobile, '0123456789', '') is null; |
|||
【oracle】全角转换成半角 | oracle | ||
把一些全角数字转换成半角的数据,可利用oracle的 to_single_byte 这个函数就可以解决问题 比如: UPDATE ARCHIVES_IN T1 SET T1.IN_CODE = (SELECT TO_SINGLE_BYTE(T2.IN_CODE) FROM ARCHIVES_IN T2 WHERE T1.IN_ID = T2.IN_ID) WHERE NOT REGEXP_LIKE(T1.IN_CODE, '^(-{0,1}+{0,1})[0-9]+(.{0,1}[0-9]+) 但是有个问题,如果这个in_code字段中只有一个全角数字的话,需要手动的去修改一下。 |
|||
【oracle】正则表达式 | oracle | oracle正则表达式 | |
在oracle里正则表达式有四个函数可用,分别是regexp_like、regexp_substr、regexp_instr 和regexp_replace。 REGEXP_LIKE:比较一个字符串是否与正则表达式匹配 (srcstr, pattern [, match_option]) REGEXP_INSTR:在字符串中查找正则表达式,并且返回匹配的位置 (srcstr, pattern [, position [, occurrence [, return_option [, match_option]]]]) REGEXP_SUBSTR:返回与正则表达式匹配的子字符串 (srcstr, pattern [, position [, occurrence [, match_option]]]) REGEXP_REPLACE:搜索并且替换匹配的正则表达式 (srcstr, pattern [, replacestr [, position [, occurrence [, match_option]]]]) 1. select * from member_user t where regexp_like(t.user_mobile, '^1[[:digit:]]{10}'); ^代表开始, *表示出现0次或多次, +表示出现1次或多次, [:digit:]代表0-9的纯数字 (还有$代表以什么结尾,如果是[[:digit:]]+$代表以数字结尾) select * from test_table where regexp_like(name,'[[:alpha:]]') 这里是表示查询匹配任意字母,也包括中文字 select * from test_table where regexp_like(name,'[[:alnum:]]') 这里是表示查询匹配任意字母和数字 select * from test_table where regexp_like(name,'[[:digit:]]') 这里是表示查询匹配任意数字 Select * from test_table Where regexp_like(name,’of’,’i’) 这里就是of不区分大小写 Select * from test_table Where regexp_like(name,’^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$’) 这样我们可以查询是不是ip格式 REGEXP_SUBSTR与SUBSTR函数相同,返回截取的子字符串 REGEXP_SUBSTR(srcstr, pattern [, position [, occurrence [, match_option]]]) 注: srcstr 源字符串 pattern 正则表达式样式 position 开始匹配字符位置 occurrence 匹配出现次数 match_option 匹配选项(区分大小写) SELECT regexp_substr('1PSN/231_3253/ABc', '[[:alnum:]]+') FROM dual; Output: 1PSN [[:alnum:]]+ 表示匹配1个或者多个字母或数字字符 SELECT regexp_substr('1PSN/231_3253/ABc', '[[:alnum:]]+', 1, 2) FROM dual; Output: 231 与上面一个例子相比,多了两个参数 1 表示从源字符串的第一个字符开始查找匹配 2 表示第2次匹配到的字符串(默认值是“1”,如上例) |
|||
【maven】安装JAR到本地Maven仓库 | maven | ||
mvn install:install-file -Dfile=kaptcha-2.3.2.jar -Dpackaging=jar -DgroupId=com.google.code -DartifactId=kaptcha -Dversion=2.3.2 -Dfile:本地JAR文件位置; |
|||
【spring mvc】CrossDomainView | spring mvc | ||
/** * */ import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.springframework.util.CollectionUtils; import org.springframework.validation.BindingResult; import org.springframework.web.servlet.view.AbstractView; import com.google.gson.Gson; /** * 跨域请求视图 * @author c1panx * 2015-01-11 下午2:16:40 */ public class CrossDomainView extends AbstractView { public static final String DEFAULT_CONTENT_TYPE = "text/plain;charset=UTF-8"; public static final String DEFAULT_CHAR_ENCODING = "UTF-8"; private String encodeing = DEFAULT_CHAR_ENCODING; private Object jsonData = null; private Map<String, Object> _jsonDataMap = new HashMap<String, Object>(); private Set<String> renderedAttributes; public CrossDomainView() { setContentType(DEFAULT_CONTENT_TYPE); } public CrossDomainView(Object data) { setContentType(DEFAULT_CONTENT_TYPE); this.jsonData = data; } public void setEncodeing(String encodeing) { this.encodeing = encodeing; } @Override protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception { // 回调函数名 String jsoncallback = request.getParameter("jsoncallback"); String result = ""; if (jsonData != null) { result = new Gson().toJson(jsonData); } else if (!_jsonDataMap.isEmpty()) { result = new Gson().toJson(_jsonDataMap); } else { model = filterModel(model); result = new Gson().toJson(model); } // 若未传递jsoncallback参数,则返回普通的JSON串 if (StringUtils.isBlank(jsoncallback) == false) { result = jsoncallback + "(" + result + ")"; } logger.info("CrossDomainView jsoncallback:" + jsoncallback); logger.info("CrossDomainView result:" + result); response.setCharacterEncoding(encodeing); response.setContentType(getContentType()); PrintWriter out = null; try { out = response.getWriter(); out.print(result); } catch (Exception e) { logger.error(e.getMessage(), e); } finally { if (null != out) { out.flush(); out.close(); } } } /** * Filters out undesired attributes from the given model. * <p> * Default implementation removes {@link BindingResult} instances and * entries not included in the {@link #setRenderedAttributes(Set) * renderedAttributes} property. */ protected Map<String, Object> filterModel(Map<String, Object> model) { Map<String, Object> result = new HashMap<String, Object>(model.size()); Set<String> renderedAttributes = !CollectionUtils.isEmpty(this.renderedAttributes) ? this.renderedAttributes : model.keySet(); for (Map.Entry<String, Object> entry : model.entrySet()) { if (!(entry.getValue() instanceof BindingResult) && renderedAttributes.contains(entry.getKey())) { result.put(entry.getKey(), entry.getValue()); } } return result; } public void setJsonData(Object jsonData) { this.jsonData = jsonData; } public static CrossDomainView returnJson(Object jsonData) { CrossDomainView jsonView = new CrossDomainView(); jsonView.setJsonData(jsonData); return jsonView; } public CrossDomainView put(String key, Object value) { _jsonDataMap.put(key, value); return this; } } //跨域请求示例 $.ajax({ url:t_json.url + "?jsoncallback=?", data: {mobile:t_json.$mobile.val(), type:t_json.type}, dataType: "jsonp", // type: "POST", crossDomain: true, beforeSend: function(XMLHttpRequest){}, success: function(data, textStatus){ }, error: function(XMLHttpRequest, textStatus, errorThrown){ } }); |
|||
【spring mvc】kaptcha.ValidateCodeController | spring mvc | ||
/** * */ package com.cignacmb.member.center.controller; import java.awt.image.BufferedImage; import javax.imageio.ImageIO; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.google.code.kaptcha.Producer; /** * 图片动态码 * @author c1panx * 2015年2月5日 下午4:57:01 */ @Controller public class ValidateCodeController { private final Logger logger = Logger.getLogger(this.getClass()); @Autowired private Producer captchaProducer = null; @RequestMapping("/validate-code.xhtml") public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { response.setDateHeader("Expires", 0); // Set standard HTTP/1.1 no-cache headers. response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); // Set IE extended HTTP/1.1 no-cache headers (use addHeader). response.addHeader("Cache-Control", "post-check=0, pre-check=0"); // Set standard HTTP/1.0 no-cache header. response.setHeader("Pragma", "no-cache"); // return a jpeg response.setContentType("image/jpeg"); // create the text for the image String capText = captchaProducer.createText(); // store the text in the session request.getSession().setAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY, capText); // create the image with the text BufferedImage bi = captchaProducer.createImage(capText); ServletOutputStream out = null; try { out = response.getOutputStream(); // write the data out ImageIO.write(bi, "jpg", out); out.flush(); } catch (Exception e) { logger.error(e.getMessage(), e); } finally { if (null != out) { out.close(); } } return null; } } |
|||
【spring mvc】kaptcha.MemberWordRenderer | spring mvc | ||
/** * */ package com.cignacmb.member.center.validatecode; import java.awt.Font; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.font.GlyphVector; import java.awt.image.BufferedImage; import java.util.Random; import com.google.code.kaptcha.text.WordRenderer; import com.google.code.kaptcha.util.Configurable; /** * <a href='http://fancyboy2050.iteye.com/blog/1146763'>Kaptcha使用</a> * @author c1panx * 2015年2月6日 上午9:45:25 */ public class MemberWordRenderer extends Configurable implements WordRenderer { public MemberWordRenderer() { } @Override public BufferedImage renderWord(String word, int width, int height) { int fontSize = getConfig().getTextProducerFontSize(); // 这个地方我们自定义了验证码文本字符样式,虽然是可以配置的,但是字体展示都粗体,我们希望不是粗体就只有自定义这个渲染类了 String paramName = "kaptcha.textproducer.font.names"; String paramValue = (String) getConfig().getProperties().get(paramName); String fontNames[] = paramValue.split(","); Font fonts[] = new Font[fontNames.length]; for (int i = 0; i < fontNames.length; i++) { // fonts[i] = new Font(fontNames[i], Font.ITALIC, fontSize); fonts[i] = new Font(fontNames[i], Font.BOLD + Font.ITALIC, fontSize); } java.awt.Color color = getConfig().getTextProducerFontColor(); int charSpace = getConfig().getTextProducerCharSpace(); BufferedImage image = new BufferedImage(width, height, 2); Graphics2D g2D = image.createGraphics(); g2D.setColor(color); RenderingHints hints = new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); hints.add(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY)); g2D.setRenderingHints(hints); java.awt.font.FontRenderContext frc = g2D.getFontRenderContext(); Random random = new Random(); int startPosY = (height - fontSize) / 5 + fontSize; char wordChars[] = word.toCharArray(); Font chosenFonts[] = new Font[wordChars.length]; int charWidths[] = new int[wordChars.length]; int widthNeeded = 0; for (int i = 0; i < wordChars.length; i++) { chosenFonts[i] = fonts[random.nextInt(fonts.length)]; char charToDraw[] = { wordChars[i] }; GlyphVector gv = chosenFonts[i].createGlyphVector(frc, charToDraw); charWidths[i] = (int) gv.getVisualBounds().getWidth(); if (i > 0) widthNeeded += 2; widthNeeded += charWidths[i]; } int startPosX = (width - widthNeeded) / 2; for (int i = 0; i < wordChars.length; i++) { g2D.setFont(chosenFonts[i]); char charToDraw[] = { wordChars[i] }; g2D.drawChars(charToDraw, 0, charToDraw.length, startPosX, startPosY); startPosX = startPosX + charWidths[i] + charSpace; } return image; } } |
|||
【spring mvc】kaptcha.MemberWaterRipple | spring mvc | ||
/** * */ package com.cignacmb.member.center.validatecode; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import com.google.code.kaptcha.NoiseProducer; import com.google.code.kaptcha.impl.WaterRipple; import com.jhlabs.image.RippleFilter; import com.jhlabs.image.TransformFilter; import com.jhlabs.image.WaterFilter; /** * @author c1panx * 2015年2月9日 下午3:11:07 */ public class MemberWaterRipple extends WaterRipple { public BufferedImage getDistortedImage(BufferedImage baseImage) { // baseImage,无噪点文字图片 NoiseProducer noiseProducer = getConfig().getNoiseImpl(); BufferedImage distortedImage = new BufferedImage(baseImage.getWidth(), baseImage.getHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D graphics = (Graphics2D) distortedImage.getGraphics(); // http://javadox.com/com.jhlabs/filters/2.0.235-1/com/jhlabs/image/RippleFilter.html RippleFilter rippleFilter = new RippleFilter(); // RippleFilter.SINE 正弦波的涟漪 rippleFilter.setWaveType(RippleFilter.SINE); // 在 X 方向设置的波动幅度。 rippleFilter.setXAmplitude(2.6f); rippleFilter.setYAmplitude(1.7f); // 在 X 方向设置波长的波纹。 rippleFilter.setXWavelength(15); rippleFilter.setYWavelength(5); rippleFilter.setEdgeAction(TransformFilter.NEAREST_NEIGHBOUR); // http://www.2cto.com/kf/201302/188441.html WaterFilter waterFilter = new WaterFilter(); waterFilter.setAmplitude(0.5f); // 振幅 waterFilter.setPhase(10); // 相位 waterFilter.setWavelength(2); // 波长 // baseImage,无噪点文字图片 BufferedImage effectImage = baseImage; // waterFilter.filter 文字上添加噪点 // BufferedImage effectImage = waterFilter.filter(baseImage, null); effectImage = rippleFilter.filter(effectImage, null); graphics.drawImage(effectImage, 0, 0, null, null); graphics.dispose(); // 干扰线 noiseProducer.makeNoise(distortedImage, .1f, .1f, .25f, .25f); noiseProducer.makeNoise(distortedImage, .1f, .25f, .5f, .9f); return distortedImage; } } |
|||
【spring mvc】kaptcha.MemberNoise | spring mvc | ||
/** * */ package com.cignacmb.member.center.validatecode; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.CubicCurve2D; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.image.BufferedImage; import java.util.Random; import com.google.code.kaptcha.impl.DefaultNoise; /** * @author c1panx * 2015年2月5日 下午5:26:55 */ public class MemberNoise extends DefaultNoise { public void makeNoise(BufferedImage image, float factorOne, float factorTwo, float factorThree, float factorFour) { Color color = getConfig().getNoiseColor(); // image size int width = image.getWidth(); int height = image.getHeight(); // the points where the line changes the stroke and direction Point2D[] pts = null; Random rand = new Random(); // the curve from where the points are taken CubicCurve2D cc = new CubicCurve2D.Float(width * factorOne, height * rand.nextFloat(), width * factorTwo, height * rand.nextFloat(), width * factorThree, height * rand.nextFloat(), width * factorFour, height * rand.nextFloat()); // creates an iterator to define the boundary of the flattened curve PathIterator pi = cc.getPathIterator(null, 2); Point2D tmp[] = new Point2D[200]; int i = 0; // while pi is iterating the curve, adds points to tmp array while (!pi.isDone()) { float[] coords = new float[6]; switch (pi.currentSegment(coords)) { case PathIterator.SEG_MOVETO: case PathIterator.SEG_LINETO: tmp[i] = new Point2D.Float(coords[0], coords[1]); } i++; pi.next(); } pts = new Point2D[i]; System.arraycopy(tmp, 0, pts, 0, i); Graphics2D graph = (Graphics2D) image.getGraphics(); graph.setRenderingHints(new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); graph.setColor(color); // for the maximum 3 point change the stroke and direction for (i = 0; i < pts.length - 1; i++) { if (i < 3) graph.setStroke(new BasicStroke(0.9f * (4 - i))); graph.drawLine((int) pts[i].getX(), (int) pts[i].getY(), (int) pts[i + 1].getX(), (int) pts[i + 1].getY()); } graph.dispose(); } } |