欢迎访问 licqi IT技术
我们一直在努力

jQuery 自制上传头像插件-附带Demo实例(ajaxfileupload.js第三弹)

licqi阅读(132)

这篇文章主要是对前两篇关于ajaxfileupload.js插件的文章

《ASP.NET 使用js插件出现上传较大文件失败的解决方法(ajaxfileupload.js第一弹》

《jQuery 关于ajaxfileupload.js插件的逐步解析(ajaxfileupload.js第二弹)》

的一个收关。但是最初也是因为想做这么一个功能,一点一点的引发出了好多问题,不断去学习,研究,才写了这三篇。

早些时候已经实现了上传头像的功能,但是代码却是零零散散的,有html,有jQuery还有c#,所以就决定把这个功能独立出来,当个插件用会方便很多。而事实是在封装成插件的过程中,也学到了很多知识。

下面给大家看一下界面:

1、初始情况下

2、点击上传头像,弹出选择,预览浮动框

3、选择图片

4、确定后,符合要求,会提示成功,不符合要求,也会做出相应的提示

5、预览

6、确定上传

下面是部分代码

js部分:

$.fn.extend({

    ShowTheFloatDiv: function (obj) {
        $(this).click(function () {
            $("body").find("*").not("div.float-outer").attr("disabled", "disabled");
            var $float = jQuery.CreateTheFloatDiv();
            $img_outer_obj = obj;
        });
    }

});

$.extend({
    CreateTheFloatDiv: function () {
        if ($(".float-outer").size() == 1) {
            return $(".float-outer");
        }
        var left_offset = ($(window).width() - 600) / 2;//显示在浏览器窗口比较正的位置,看着比较舒服
        var top_offset = ($(window).height() - 278) / 3;
        var theFloatDivHtml = "
"; theFloatDivHtml += "
上传头像
"; theFloatDivHtml += "
"; theFloatDivHtml += "
文件名:"; theFloatDivHtml += " "; theFloatDivHtml += ""; theFloatDivHtml += ""; theFloatDivHtml += "
"; theFloatDivHtml += "
"; theFloatDivHtml += "图片预览:"; theFloatDivHtml += "
"; theFloatDivHtml += ""; theFloatDivHtml += "60*60"; theFloatDivHtml += "
"; theFloatDivHtml += "
"; theFloatDivHtml += ""; theFloatDivHtml += "120*120"; theFloatDivHtml += "
"; theFloatDivHtml += "
"; theFloatDivHtml += "
"; theFloatDivHtml += ""; theFloatDivHtml += "
"; $("body").append(theFloatDivHtml);return $(".float-outer"); } }); var $img_outer_obj; $(function () { //取消事件 $("body").delegate("#btn_cancel", "click", function () { $(".float-outer").remove(); $("body").find("*").removeAttr("disabled"); }); //选择图片事件 $("body").delegate("#btn_selectfile", "click", function () { $("#btn_upload").trigger(e); }); var e = jQuery.Event("click"); $("body").delegate("#btn_upload", "click", function () { }).delegate("#btn_upload", "change", function () { var curPATH = getFilePath($(this).get(0)); var fileName = curPATH.substring(curPATH.lastIndexOf("\") + 1); var type = curPATH.substring(curPATH.lastIndexOf('.') + 1).toLowerCase(); if (type == "jpg" || type == "gif" || type == "bmp") { $("input#tb_filename").val(fileName); if ($("input#tb_filename").val() == "") { alert("请先上传文件!"); return; } $.ajaxFileUpload ( { url: '/UploadPortrait.aspx', //用于文件上传的服务器端请求地址,需要根据实际情况进行修改 secureuri: false, //一般设置为false fileElementId: $("input#btn_upload").attr("id"), //文件上传空间的id属性 //$("form").serialize(),表单序列化。指吧所有元素的ID,NAME 等全部发过去 dataType: 'json', //返回值类型 一般设置为json complete: function () {//只要完成即执行,最后执行 }, success: function (data, status) //服务器成功响应处理函数 { if (typeof (data.error) != 'undefined') { if (data.error != '') { if (data.error == "1001") { } else if (data.error == "1002") { $("input#tb_filename").val(""); $(".preview60").attr("src", ""); $(".preview120").attr("src", ""); } alert(data.msg); return; } else { alert(data.msg); } } $(".preview60").attr("src", data.imgurl); $(".preview120").attr("src", data.imgurl); }, error: function (data, status, e)//服务器响应失败处理函数 { alert(e); } } ) return false; } else { alert("请选择正确的图片格式(.jpg|.gif|.bmp)"); } }); $("body").delegate("#btn_ok", "click", function () { $img_outer_obj.attr("src", $(".preview120").attr("src")); $(".float-outer").remove(); $("body").find("*").removeAttr("disabled"); }); //移动浮动框 var offset_left, offset_top, moveFlag; $("body").delegate(".float-header", "mousedown", function (e) { moveFlag = true; offset_left = e.pageX - $(this).offset().left; offset_top = e.pageY - $(this).offset().top; $("body").delegate(".float-header", "mousemove", function (e) { if (moveFlag) { $(".float-outer").css("left", e.pageX - offset_left + "px").css("top", e.pageY - offset_top + "px"); } }).delegate(".float-header", "mouseup", function () { moveFlag = false; }) }) });

C#部分:

因为上传文件用到了ajax,需要先将图片上传到本地,这里也算是一个比较纠结的事情吧,因为如果想预览,除非用一些插件,否则使用的方法都得是先上传,再预览这样。这种来者都要不拒的事,看起来比较流氓哈~~

        HttpFileCollection files = System.Web.HttpContext.Current.Request.Files;
        string msg = string.Empty;
        string error = string.Empty;
        string imgurl = string.Empty;
        protected void Page_Load(object sender, EventArgs e)
        {
            if (files.Count > 0)
            {
                 if (System.IO.File.Exists(Server.MapPath("/UploadImages/") + files[0].FileName))
                {
                    msg = "图片已存在";
                    error = "1001";
                    string res1 = "{ error:'" + error + "', msg:'" + msg + "',imgurl:'" + imgurl + "'}";
                    Response.Write(res1);
                    Response.End();return;
                }
                if (files[0].ContentLength > 4 * 1024 * 1024)
                {
                    msg = "图片大小不能超过4M";
                    error = "1002";
                    string res1 = "{ error:'" + error + "', msg:'" + msg + "',imgurl:'" + imgurl + "'}";
                    Response.Write(res1);
                    Response.End();return;
                }
                try
                {
                    files[0].SaveAs(Server.MapPath("/UploadImages/") + System.IO.Path.GetFileName(files[0].FileName));
                }
                catch (System.IO.DirectoryNotFoundException)
                {
                }
                msg = " 上传成功! 图片大小为:" + files[0].ContentLength + "K";
                imgurl = "/UploadImages/" + files[0].FileName;
                string res = "{ error:'" + error + "', msg:'" + msg + "',imgurl:'" + imgurl + "'}";
                Response.Write(res);
                Response.End();
            }
        }

如何调用此插件

    
        $(function () {
            $("#btn_portrait").ShowTheFloatDiv($("#img_portrait"));
        })
        
    

注意事项

必须在“上传头像”按钮所在页面引入以下几个文件

UploadPortrait.css

ajaxfileupload.js

jquery-2.0.3.min.js(jQuery插件要求在1.4.2版本之上)

UploadPortrait.js

如果大家在使用过程中出现问题,可以先把前面相关的两篇文章略读一下,大概就能找到原因了。

大致这个功能就是如上这样,感兴趣的朋友可以从下面的地址下载Demo运行看看。此外想说的是,因为是头像嘛,一定要存数据库的,但是在Demo里我并没有写,这个东西就是看大家想怎么实现了,要是我的话,因为之前预览都要将图片存到本地,所以如果存数据库的话,当然是会存图片的url了,那这样就比较好办了。

总的来说,要比想像中的快些完成了这个插件,功能倒是达到了自己的预期,但是界面来说,还有很长的一段路要走。第一次写jQuery插件,很多东西都不太专业,希望大牛们能多多给予指正和帮助。

Demo下载地址:http://down.51cto.com/data/1871944

关于上传的Demo补充内容:

上传的demo有两个问题需要说明一下,希望下载的朋友能够注意到,并流畅运行。

1、因为demo是ASP.NET项目,所以大家如想正常运行,需要在本地新建一个web项目,把我上传的uploadportrait.csproj这个文件添加进去。下次我会直接打包一个完整的web项目再上传,这次没做好希望大家给予谅解。另,我开发的时候Visual Studio版本为2010,这个望大家注意一下。

2、在调用插件的代码部分,demo里写的是

    
        $(function () {
            $("#btn_portrait").ShowTheFloatDiv($(img_portrait));
        })
        
    

应该把$(img_portrait)改成$(“#img_portrait”),这个也是自己的失误,下回会注意。

补充:

《jQuery 关于IE9上传文件无法进入后台原因及解决办法(ajaxfileupload.js第四弹)》

SpringMVC环境下实现的Ajax异步请求(JSON格式数据)

licqi阅读(111)

一 环境搭建

首先是常规的spring mvc环境搭建,不用多说,需要注意的是,这里需要引入jackson相关jar包,然后在spring配置文件“springmvc-servlet.xml”中添加json解析相关配置,我这里的完整代码如下:


	
	
	
		
			
				text/html;charset=UTF-8
				application/json;charset=UTF-8
			
		
		
			
				
					
						
					
				
			
		
	
	
	
		
			
				
			
		
	
	
	
		
		
		
		
		
		
		
			
				atom=application/atom+xml
				html=text/html
				json=application/json
				xml=application/xml
				*=*/*
			
		
	
	
	
	

	
	
	
		
		
		
		
		
	

项目结构:

注:我这里测试使用的完整jar包:http://pan.baidu.com/s/1dEUwdmL

仅供参考

二 测试实例

(1)在WEB-INF/jsp目录下新建了一个index.jsp文件,包含了简单的jQuery的ajax请求,请求数据的格式是JSON,具体代码如下:






<base href="">






jQuery i18n

	$().ready(
			function() {
				$("#sub").click(
						function() {
							var name = $("#username").val();	
							var age = 18;
							var user = {"username":name,"age":age};
							$.ajax({
										url : 'hello.json',
										type : 'POST',
										data : JSON.stringify(user), // Request body 
										contentType : 'application/json; charset=utf-8',
										dataType : 'json',
										success : function(response) {
											//请求成功
											alert("你好" + response.username + "[" + response.age + "],当前时间是:" + response.time + ",欢迎访问:http://www.zifangsky.cn");
											
										},
										error : function(msg) {
											alert(msg);
										}
									});
						});
			});



	
	
	

(2)一个简单的model类User,代码如下:

package cn.zifangsky.controller;

public class User {
	private String username;
	private int age;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
}

(3)controller类TestController.java:

package cn.zifangsky.controller;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

@Controller
@Scope("prototype")
public class TestController {

	/**
	 * 转到页面
	 */
	@RequestMapping(value = "/hello.html")
	public ModelAndView list() {
		ModelAndView view = new ModelAndView("index");
		return view;
	}

	/**
	 * ajax异步请求, 请求格式是json
	 */
	@RequestMapping(value = "/hello.json", method = { RequestMethod.POST })
	@ResponseBody
	public Map hello(@RequestBody User user) {
		// 返回数据的Map集合
		Map result = new HashMap();

		Format format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		// 返回请求的username
		result.put("username", user.getUsername());
		// 返回年龄
		result.put("age", String.valueOf(user.getAge()));
		// 返回当前时间
		result.put("time", format.format(new Date()));

		return result;
	}
}

关于具体的执行步骤我简单说一下:

i)项目启动后,在浏览器中访问:http://localhost:8089/SpringDemo/hello.html,然后会转到执行controller中的list方法,接着会转到/WEB-INF/jsp/index.jsp(PS:在controller中返回的是逻辑视图,跟在springmvc-servlet.xml文件中定义的路径前缀和后缀进行拼接后合成文件的真正路径)

ii)在index.jsp页面输入文字然后点击按钮,将会触发ajax请求,这个请求会获取输入框中的数据和默认的“age”参数拼接成json格式字符串最后提交到“hello.json”这个请求,也就是执行controller中的hello方法

iii)hello方法执行完毕后会返回一系列数据最后在页面中显示出来

(4)效果如下:

WebApp(JqueryMobile) 实战(一)

licqi阅读(150)

其实WebApp这个版块已经放置一段时间了,但是一直没有写文章,那是因为我还在学习中。今天的话,我们就来写一篇关于布局的,以前在没有BootStrap,Jquery EasyUI,Jquery Mobile之前不论是做web项目还是web 移动站点都是那么费劲,尤其是我这种学不会css的人,实在是搞不了前台。OK,废话不多说,我们来看一下今天要仿制的页面,手机头条网。

看到了吧,这个界面如果用BootStrap的话可能更简单一些,因为它是单纯的三列或者两列布局,利用Bootstrap的网格系统可以很好的布局出来。那今天的话还是用Jquery Mobile css。

首先看一下最顶端的头部,我的代码如下

@section Header
{
    

今日头条

  • 推荐
  • 热点
  • 社会
  • 娱乐
  • 科技
}

其实这里我们使用Jquery Mobile css中的一些样式及属性。我们看一下data-role=”header”

在这里我们设置头部不会在点击屏幕的时候缩回去data-tap-toggle=”false”,这样当页面内容随着滚动条上移时,会被头部盖住。data-theme=”f”这个是我自己定义的主题,主题可以是a-z。而Jquery Mobile css默认只提供了五种主题。

所以f需要自己定义,我们来看一下

.ui-bar-f {
    background-color: red;
    color: white;
    font-weight: bold;
    height:45px;
    font-family:微软雅黑;
}

.img-corner {
    border-radius: 50%;
}

.a-header {
    text-decoration:none;
    color:white;
}

body {
    font-family:微软雅黑;
    background-color:white;
}

.img-shrink {
    height:150px;
    width:100%;
    border:1px solid white;
}

.news-footer {
    font-size:10px;
}

第一个css就是我们自己定义的主题,必须是以ui-bar-[a-z]来命名。头部的话在这里共分了三列,因为我们的第一个div是

这个css就把屏幕分成了相等的三份。

然后我们在每一份放我们的元素。

效果如上,那么这个圆圈图片是怎么实现的呢,很简单,css3很好实现,将下面的css应用到图片即可。

.img-corner {
    border-radius: 50%;
}

OK,头部还有一个Nav bar,这个其实将div的data-role设置为navbar,然后在div中嵌套

头部的这个导航条如果被点击的话,它的颜色会变,这个功能是Jquery Mobile实现的,我们不需要做什么。

头部说完了我们看内容页,为了简单,有一些css我直接写在元素上。

什么人会买二手车?这四类人才是最精明的消费者


《芈月转》孙俪近照曝光网友:太美了!

初二女生收到情书,超牛老妈只说了五句话!

那些发生在汽车历史上的第一次!

其实我们观察一下,就会发现,第一行是标题,第二行是三个图片,第三行是一些其他的信息。

那么第一部分我们布局就可以采用

完成这三部分。第一行没什么说的,第二行我们使用网格系统,将屏幕分成三列,每列一张图,最后一行需要注意这个”刚刚+”是在右边,需要使用float=”right”,看一下效果

怎么样,还行吧。OK,我们接着看下面的布局,下面的布局我在使用Jquery mobile的网格系统的时候没有查到像BootStrap那样的跨列功能。所以我暂时先用50%/50%的网格。

第一个网格我们放置文字,第二个网格我们放置图片。

需要注意的是上面的两个height,我们设置总高度为150,设置文字的高度为135,那么小文字的高度为15,此时我们设置小文字所在的层的float:left,因为高度不够,它就会自动沉底。

如上图,小字都沉底了。OK,其实真个头条网都采用这样的布局方式,其实我们只需要在数据库表创建好类型(是一行文字+一行3图片+小字或者是左边文字(打字加小字)+右边图片),标题,小字内容,图片我们就可以动态生成或者加载页面,这个是我下节要实现的内容。

最后我们还给这个页面加了foot。

@section Footer
{
    

}

头条网,一个神奇的网站。这个脚我们设置点击屏幕时该脚会收缩。好了,我们看一下全部页面的效果

收缩掉脚,我们再看看

OK,页面今天就到这里,最后告诉大家怎么创建移动项目的

点击确定

选择移动应用程序,确定,项目就创建好了。

最后,大家如果需要源码的话去下载,下载请点击这里源码

网站前端_EasyUI.基础入门.0008.带你玩转jQuery EasyUI Layout组件?

licqi阅读(156)

简单介绍:


说明: ($.fn.layout)布局,依赖panel和resizable,默认分为5个区东east,西west,南south,北north,中center,中间的区域面板是必须的,边缘区域面板是可选的,每个边缘区域面板可通过拖拽边框调整尺寸,也可以通过点击折叠触发器来折叠面板.布局可嵌套,因此用户可建立复杂的布局.

基础用法:


body { padding: 0; margin: 0; } var width = $(document).width(); var height = $(document).height(); $('#l').layout({ width: width, height: height, });

布局属性:


fit -> boolean

说明: 当设置为true时,就设置布局的尺寸适应它的父容器,当在body标签上创建布局时,它将自动最大化到整个页面的全部尺寸


    

布局接口:


resize -> function

说明: 设置面板尺寸并且做布局,需要传入包含width/height/left/top的对象

panel -> function

说明: 返回指定面板,需要传递region参数,参数支持north,south,east,west,center

collapse -> function

说明: 折叠指定的面板,需要传递region参数,参数支持north,south,east,west,center

expand -> function

说明: 展开指定的面板,需要传递region参数,参数支持north,south,east,west,center

add -> function

说明: 添加一个指定的面板,options参数一个配置对象

remove -> function

说明: 移除指定的面板,需要传递region参数,参数支持north,south,east,west,center


    
操作区 左侧加载远程数据 左侧面板缓慢合并 左侧面板缓慢展开 删除中间左边面板 添加中间左边面板
function westLoad(that) { var $wpanel = $('body').layout('panel', 'west'); $wpanel.panel({ extractor: function(data){ var h = ''; return h; }, }); $wpanel.panel('refresh', '/easyui/data.json'); }; function westCollapse(that){ $('body').layout('collapse', 'west'); }; function westExpand(that){ $('body').layout('expand', 'west'); }; function centerRemove(that){ $('#ll').layout('remove', 'west'); }; function centerAdd(that){ $('#ll').layout('add', {region:'west',title:'sub west title',width:200}) };

面板扩展:


title -> string

说明: 布局面板的标题文本.

region -> string

说明: 定义布局面板的位置,其值可以为north,south,east,west,center

border -> boolean

说明: 当设置为true时,就显示布局面板的边框

split -> boolean

说明: 当设置为true时,就显示拆分栏,用户可以改变面板的尺寸.

iconCls -> string

说明: 当面板头部显示一个图表的css class

href -> string

说明: 从远程站点加载数据的url

collapsible -> boolean

说明: 定义是否显示可折叠按钮.

minWidth -> number

说明: 面板的最小宽度

maxWidth -> number

说明: 面板的最大宽度

minHeigit -> number

说明: 面板的最小高度

maxHeight -> number

说明: 面板的最大高度

jQuery温度计,支持摄氏度华氏度同时展示

licqi阅读(113)

[沫沫金原创]

特色

纯jQuery+Css原生,无任何第三方。同时支持摄氏度、华氏度同时显示,并可随意定义温度计颜色,例如小于10度绿色、小于20度红色等等。

  • 同时支持摄氏度、华氏度

  • 支持自定义温度计颜色

  • 支持自定义温度计款式(Psd原图提供)

以上,谢谢。沫沫金祝你工作一路顺,步步高!

提供源码下载http://down.51cto.com/data/2317776

利用Node.js进行构建本地

licqi阅读(124)

Node.js是一个基于Google Chrome浏览器v8 javascript执行引擎的异步I/O事件驱动的运行平台。直从2009年诞生开始,已经在业界得到了很多的关注,在这里也必要多说,如果你还不清楚的,请移步到Node官网

在这里我们要讲的是用Node.js来构建本地Build。构建本地Build,我们已经有很多选择,如AntMavenGradle等。为什么我们还需要Node.js?对于我们的开发中会有一些小的基本自动化构建,如文件的监控(Less编译)javascript的压缩,不稳定集成服务代理,快速的集成反馈,文件的迁移而对于项目来说我并不像引入太多的技术战, Node.js所使用的javascript是做web项目开发的一门必备技能,javascript作为一门比较容易入门语言,直从第一次接触Node.js,我爱不释手,由于我对Javascript基础,能够快速使用它,并不需要付出更多的学习成本,而且我感觉在服务端和客户端用同一种语言,在能一定代码重用妙不可言。而且Node.js提供了内置的web服务器,简单的文件监听,事件机制等也为做本地Build提供了很好的条件。

1:文件监听

  1. var fs = require("fs");
  2. var exec = require('child_process').exec
  3. var underscore = require("underscore");
  4. var configs = [
  5. {file:/.*.less/g, command:" dotless.Compiler.exe style.less style.css"}
  6. ];
  7. var source = "E:\Project\xxx\style";
  8. String.format = function () {
  9. var s = arguments[0];
  10. for (var i = 0; i < arguments.length - 1; i++) {
  11. var reg = new RegExp("\{" + i + "\}", "gm");
  12. s = s.replace(reg, arguments[i + 1]);
  13. }
  14. return s;
  15. };
  16. (function (fs, exec, underscore) {
  17. var readFiles = function (dir, done) {
  18. var results = [];
  19. fs.readdir(dir, function (err, list) {
  20. if (err) return done(err);
  21. var pending = list.length;
  22. if (!pending) return done(null, results);
  23. list.forEach(function (file) {
  24. file = dir + '/' + file;
  25. fs.stat(file, function (err, stat) {
  26. if (stat && stat.isDirectory()) {
  27. readFiles(file, function (err, res) {
  28. results = results.concat(res);
  29. if (!--pending) done(null, results);
  30. });
  31. } else {
  32. results.push(file);
  33. if (!--pending) done(null, results);
  34. }
  35. });
  36. });
  37. });
  38. };
  39. var start = function (source, configs) {
  40. var watch = function (error, list) {
  41. configs.forEach(function (cmd) {
  42. var files = underscore.filter(list, function (n) {
  43. return n.match(cmd.file);
  44. });
  45. files.forEach(function (file) {
  46. fs.watch(file, function (oper, f) {
  47. var changeCommand = String.format(cmd.command, f);
  48. console.log(String.format("{0} changed,command '{1}' execute...", f, changeCommand));
  49. exec(changeCommand, function (err, stdout, stderr) {
  50. console.log(err ? stderr : stdout);
  51. });
  52. });
  53. });
  54. });
  55. };
  56. readFiles(source, watch);
  57. };
  58. return {start:start};
  59. })(fs, exec, underscore).start(source, configs);

在这里提供的示例是Less的编译,虽然Less本也提供了Node的编译工具和watchr监听工具,但是在项目中我会监听Less文件,却只有编译几个固定的Less引导文件。同样我们可以根据不同的文件执行不同的命令实现一些自动化。如:.js文件的同步到测试目录。

2:文件的合并

如果你用jasmine运行你的Javascript测试,你需要吧js文件的测试文件引入到runner head中,我一直很懒,喜欢一键搞定的感觉。利用node.js的模板引擎。

3javascript 产品包压缩

  1. var FILE_ENCODING = 'utf-8';
  2. function uglify(srcPath, jsMinPath) {
  3. var uglyfyJS = require('uglify-js'),
  4. jsp = uglyfyJS.parser,
  5. pro = uglyfyJS.uglify,
  6. ast = jsp.parse( _fs.readFileSync(srcPath, FILE_ENCODING) );
  7. ast = pro.ast_mangle(ast);
  8. ast = pro.ast_a squeeze(ast);
  9. _fs.writeFileSync(jsMinPath, pro.gen_code(ast), FILE_ENCODING);
  10. console.log(' '+ jsMinPath +'完成.');
  11. }
  12. uglify(js/test.js', js/test.min.js');

我们可以尽力发挥自己的想象,如本地Build自动运行,快速集成快速反馈;代理服务器,处理不稳定服务的集成,带来稳定的开发。。。

网站前端_EasyUI.基础入门.0005.使用EasyUI Accordion组件的最佳姿势?

licqi阅读(140)

1. 基础的手风琴

Accordion for jQuery

Accordion is a part of easyui framework for jQuery. It lets you define your accordion component on web page more easily.

The accordion allows you to provide multiple panels and display one or more at a time. Each panel has built-in support for expanding and collapsing. Clicking on a panel header to expand or collapse that panel body. The panel content can be loaded via ajax by specifying a 'href' property. Users can define a panel to be selected. If it is not specified, then the first panel is taken by default.

  • 第一层
    • 第1层
    • 第2层
    • 第3层
  • 第二层
  • 第三层

2. 流式的手风琴

width: 100%


3. 异步加载数据


4. 手风琴的控制

选中 添加 删除

about
help
function select(){ $.messager.prompt('信息', '请输入你要选中的面板标题或面板索引?', function(data){ var n = parseInt(data); console.log(data, typeof(data)); if(!isNaN(n)){ $('#a').accordion('select', n); }else{ $('#a').accordion('select', data); }; }); }; function add(){ var options = { iconCls: 'icon-reload', title: 'reload', content: 'reload', bodyCls: 'accordion_padding', }; $('#a').accordion('add', options); }; function remove(){ var selectedItem = $('#a').accordion('getSelected'); var selectedIndex = $('#a').accordion('getPanelIndex', selectedItem); $('#a').accordion('remove', selectedIndex); };


5. 手风琴工具组

姓名 年龄 性别


6. 打开的手风琴

Accordion for jQuery

Accordion is a part of easyui framework for jQuery. It lets you define your accordion component on web page more easily.


7. 开多个手风琴

PYTHON
HTML

注意: 配合容器multiple属性可支持同时展开多个,但是此模式下千万别设置容器的高度,不然由于上一个面板已经展开,下一个面板由于空间被占且高度被限制会导致显示不出来.

利用Node.js为Node.js生成HttpStatusCode辅助类并发布到npm

licqi阅读(145)

作为一个好的Restfull Api不仅在于service url的语义,可读性,幂等,正交,作为http状态码也很重要,一个好的Http Status Code给使用者一个很好的响应,比如200表示正常成功,201表示创建成功,409冲突,404资源不存在等等。所以在做一个基于node.js+mongodb+angularjs的demo时发现node.js express没有提供相应的辅助类,但是本人不喜欢将201,404这类毫无语言层次语义的东西到处充斥着,所以最后决定自己写一个,但是同时本人也很懒,不喜欢做重复的苦力活,怎么办?那就从我最熟悉的c#中HttpStatusCode枚举中copy出来吧,最后为了简便在mac上所以采用了利用node.js去解析msdn关于httpstatuscode的文档生成node.js的辅助类。

代码很简单:

var http = require('http');

var fs = require('fs');

var $ = require('jquery');

var output = "httpStatusCode/index.js";

(function(){

String.format = function() {

var s = arguments[0];

for (var i = 0; i < arguments.length - 1; i++) {

var reg = new RegExp("\{" + i + "\}", "gm");

s = s.replace(reg, arguments[i + 1]);

}


return s;

};


var options = {

host:'msdn.microsoft.com',

port:80,

path:'/zh-cn/library/system.net.httpstatuscode.aspx'

};


http.get(options,function (response) {

var html = "";

response.on("data",function (chunk) {

html += chunk;

}).on("end", function () {

handler(html);

}).on('error', function (e) {

console.log("Got error: " + e.message);

});


function getHttpStatusCode(htmlString) {

var $doc = $(html);

var rows = $doc.find("table#memberList tr:gt(0)");

var status = {};

rows.each(function(i,row){

status[$(row).find("td:eq(1)").text()] =

parseInt($(row).find("td:eq(2)").text().match(/d+/).toString());

});

return status;

};

function generateCode(status){

var code = "";

code += "exports.httpStatusCode = " + JSON.stringify(status) + ";";

return code;

};

function writeFile(code){

fs.writeFile(output, code, function(err) {

if(err) {

console.log(err);

} else {

console.log("The file was saved " + output + "!");

}

});

};


function handler(html){

var status = getHttpStatusCode(html);

var code = generateCode(status);

writeFile(code);

};


});

})();

代码寄宿在github:https://github.com/greengerong/node-httpstatuscode

最终生成类为:

exports.httpStatusCode = {
“Continue”: 100,
“SwitchingProtocols”: 101,
“OK”: 200,
“Created”: 201,
“Accepted”: 202,
“NonAuthoritativeInformation”: 203,
“NoContent”: 204,
“ResetContent”: 205,
“PartialContent”: 206,
“MultipleChoices”: 300,
“Ambiguous”: 300,
“MovedPermanently”: 301,
“Moved”: 301,
“Found”: 302,
“Redirect”: 302,
“SeeOther”: 303,
“RedirectMethod”: 303,
“NotModified”: 304,
“UseProxy”: 305,
“Unused”: 306,
“TemporaryRedirect”: 307,
“RedirectKeepVerb”: 307,
“BadRequest”: 400,
“Unauthorized”: 401,
“PaymentRequired”: 402,
“Forbidden”: 403,
“NotFound”: 404,
“MethodNotAllowed”: 405,
“NotAcceptable”: 406,
“ProxyAuthenticationRequired”: 407,
“RequestTimeout”: 408,
“Conflict”: 409,
“Gone”: 410,
“LengthRequired”: 411,
“PreconditionFailed”: 412,
“RequestEntityTooLarge”: 413,
“RequestUriTooLong”: 414,
“UnsupportedMediaType”: 415,
“RequestedRangeNotSatisfiable”: 416,
“ExpectationFailed”: 417,
“UpgradeRequired”: 426,
“InternalServerError”: 500,
“NotImplemented”: 501,
“BadGateway”: 502,
“ServiceUnavailable”: 503,
“GatewayTimeout”: 504,
“HttpVersionNotSupported”: 505
};

最后考虑到或许还有很多像我一样懒散的人,所以共享此代码发布到了npm,只需要npm install httpstatuscode,便可以简单实用,如下是一个测试demo:

var httpStatusCode = require("httpstatuscode").httpStatusCode;


var toBeEqual = function (actual,expected){

if(actual !== expected){

throw (actual + " not equal " + expected);

}

};


toBeEqual(httpStatusCode.OK,200);

toBeEqual(httpStatusCode.Created,201);

toBeEqual(httpStatusCode.BadRequest,400);

toBeEqual(httpStatusCode.InternalServerError,500);


console.log(httpStatusCode);

console.log("success");

懒人的文章总是代码多余文字,我喜欢代码说明一切,感谢各位能阅读此随笔。

JQuery实例

licqi阅读(127)

前面学习了原生的DOM,现在看看如何使用JQuery。JQuery建议使用1.12的版本,这样对旧版本的IE兼容性比较好。

例1.添加,删除class

知识要点:

1. 通过调用jquery

2. 相对于Dom的document.getElementbyID(” i1′),=”” jquery直接使用$(‘#i1’);

类似的,查找类可以用$(‘.c1’),查找p标签 $(‘p’),查找form的元素 $(‘:text’) ,还可以组合使用。具体的选择器可以参考https://www.w3schools.com/jquery/jquery_ref_selectors.asp

3. addclass(‘hide’)直接给找到的标签添加一个样式class,removeClass(‘hide’)删除一个class,无需使用classlist了



    
    
    
        .hide{
            display: none;
        }
    


    
    
123
百度
flag=true; function hides() { if (flag==true){ $('#i1').addClass('hide'); console.log(flag) flag=false; }else{ $('#i1').removeClass('hide'); console.log(flag) flag=true; } }

点击hide按钮切换隐藏效果



例2. 全选和反选

这个例子在前面的Dom里面出现过,现在看看JQuery如何实现


知识点:

1. 选择器可以组合使用 比如 $('#tb :checkbox') 表示id=tb下面所有的checkbox元素

2. 对于checkbox的属性,通过prop()来实现,如果是自定义的其他的属性,通过attr()实现

3. each()可以实现循环,循环里面如果输出this,可以看见他是一个dom的格式,如果把他转换成jquery对象的格式(数组格式),可以通过$(this)实现,如果想把jquery转为dom的格式,那么直接取第一个数组的值就行了,例子里面实现了3种方式,dom,jquery以及三元运算符的格式



    
    Title


    
    
    
    
选项 IP PORT
1.1.1.1 80
1.1.1.1 80
1.1.1.1 80
function checkAll() { $('#tb :checkbox').prop('checked',true); } function cancleAll() { $('#tb :checkbox').prop('checked',false); } function reverseAll() { $(':checkbox').each(function(k){ // this,代指当前循环的每一个元素 // Dom /* if(this.checked){ this.checked = false; }else{ this.checked = true; } */ /* if($(this).prop('checked')){ $(this).prop('checked', false); }else{ $(this).prop('checked', true); } */ // 三元运算var v = 条件? 真值:假值 var v = $(this).prop('checked')?false:true; $(this).prop('checked',v); }) }

例3 隐藏菜单

知识点:

1. click的事件可以直接选择到标签之后执行,这个比在html里面使用onclick事件要好很多。

2. Jquery支持链式的编程,因此如下所示可以一行实现很多功能



    
    Title
    
        .header{
            background-color: black;
            color: wheat;
        }
        .content{
            min-height: 50px;
        }
        .hide{
            display: none;
        }
    


    
标题一
内容
标题二
内容
标题三
内容
$('.header').click(function(){ $(this).next().removeClass('hide').parent().siblings().find('.content').addClass('hide') })

例4. 复制,删除文本框

clone()克隆标签

find()查找标签

attr()添加一个事件



    
    


    

+

function Add(ths){ var p = $(ths).parent().clone(); p.find('a').text(' - '); p.find('a').attr('onclick', 'Remove(this);'); $(ths).parent().parent().append(p); } function Remove(ths){ $(ths).parent().remove(); }

效果:点击+自动复制一行,点击-删除自己所在

例5. 绑定事件-例2的升级版

例2里面我们需要给每个标签都手动的添加onclick事件,如果可以统一绑定事件,会省事很多。有两种方式,如下所示;


$(function){

....

}里面执行的...会在文档树加载之后自动执行,不会等待所有的图片内容的加载




    
    
    
        .hide{
            display: none;
        }
        .menu{
            width: 200px;
            height: 600px;
            border: 1px solid #dddddd;
            overflow: auto;
        }
        .menu .item .title{
            height: 40px;
            line-height: 40px;
            background-color: #2459a2;
            color: white;
        }
    


    
    
    
//方法一
//        $(function(){
//            // 当文档树加载完毕后,自动执行
//            $('.item .title').click(function(){
//                // this,$(this)
//                $(this).next().removeClass('hide');
//                $(this).parent().siblings().find('.body').addClass('hide');
//            });
//        });
        
        
//方法二        
        $('.item .title').bind('focus', function () {
            $(this).next().removeClass('hide');
            $(this).parent().siblings().find('.body').addClass('hide');
        })
        
    

例6 事件的延迟绑定

比如通过javascript创建的新标签,如何让他自动绑定事件?可以通过delegate实现



    
    


    
    
  • 123
  • 456
  • 789
$(function(){ /* $('li').click(function () { alert($(this).text()); }); */ $("ul").delegate("li","click",function(){ alert($(this).text()); }); }); function Add(){ var tag = document.createElement('li'); tag.innerText = '666'; $('ul').append(tag); }

例7 模态对话框 (高级版)

之前用DOM实现过模态对话框,现在用JQuery实现同样的功能。

知识要点:


1.模态对话框的HTML和CSS布局,3层,最上层居中,中间一个阴影层,最下面是主界面,上面两层默认隐藏,通过z-index区分上下顺序

2. 可以通过attr()方法来获取和设置自定义的属性;如果是checkbox或者radio,那么通过prop()方法来获取和设定属性

3.通过属性来定位元素,比如 $("[editable='false']")则可以获取editable属性为false的那个标签元素

4. 文本编辑,对于InnerText的值是通过text()实现,对于input的表单内容则是通过val()实现

5. 添加class,删除class通过addClass()和removeClass()实现

6. delegate 延迟绑定的实现,一般用于未来的新的标签,比如通过脚本创建的标签

7. 动态的创建标签,可以直接插入html字符串或者通过CreateElement()实现



    
    Title
    
        .hide{
            display: none;
        }
        .modal{
            position: fixed;
            top: 50%;
            left: 50%;
            width: 500px;
            height: 400px;
            margin-left: -250px;
            margin-top: -250px;
            background-color: #eeeeee;
            z-index: 10;
        }
        .shadow{
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            opacity: 0.6;
            background-color: black;
            z-index: 9;
        }

        .item{
            position: relative;
            width: 100px;
            margin-top: 20px;
            margin-left: 30px;

        }
        .label{
            width: 40px;
            color: chocolate;
        }
        .content{
            width:100px;
            position: absolute;
            right:-80px;

        }
        .buttons{
            margin-top: 20px;
            margin-left: 30px;
        }
    


    添加

    
1.1.1.11 80 80 编辑 | 删除
1.1.1.12 80 80 编辑 | 删除
1.1.1.13 80 80 编辑 | 删除
1.1.1.14 80 80 编辑 | 删除
$("#tb").delegate('.del',"click",function () { $(this).parent().parent().remove(); }) function addModal() { var tr = document.createElement('tr'); var td1 = document.createElement('td'); td1.innerHTML = $(".modal input[name='hostname']").val(); var att1=document.createAttribute('target'); att1.value='hostname'; td1.setAttributeNode(att1); var td2 = document.createElement('td'); td2.innerHTML = $(".modal input[name='port']").val(); var att2=document.createAttribute('target'); att2.value='port'; td2.setAttributeNode(att2); var td3 = document.createElement('td'); td3.innerHTML = $(".modal input[name='ip']").val();; var att3=document.createAttribute('target'); att3.value='ip'; td3.setAttributeNode(att3); var td4 = document.createElement('td'); td4.innerHTML = " 编辑 | 删除" $(tr).append(td1); $(tr).append(td2); $(tr).append(td3); $(tr).append(td4); $('#tb').append(tr); $(".modal,.shadow").addClass('hide'); } function addElement() { $(".modal,.shadow").removeClass('hide'); } function cancelModal() { $(".modal,.shadow").addClass('hide'); $('.modal input[type="text"]').val(""); } function updateModal(){ var host=$(".modal input[name='hostname']").val() var port=$(".modal input[name='port']").val() var ip=$(".modal input[name='ip']").val() var tds=$("[editable='false']").prevAll() console.log(tds) tds.each( function () { console.log($(this).attr('target')) if($(this).attr('target')=='ip'){ $(this).text(ip); console.log('update ip') } else if($(this).attr('target')=='port'){ $(this).text(port); console.log('update port') } else if($(this).attr('target')=='hostname'){ $(this).text(host) console.log('update host') } } ) $(".modal,.shadow").addClass('hide'); $("[editable='false']").attr('editable','true') } $("#tb").delegate(".edit","click",function() { $(".modal,.shadow").removeClass('hide'); // this $(this).parent().attr('editable', 'false') var tds = $(this).parent().prevAll(); tds.each(function () { // 获取td的target属性值 var n = $(this).attr('target'); // 获取td中的内容 var text = $(this).text(); var a1 = '.modal input[name="'; var a2 = '"]'; var temp = a1 + n + a2; $(temp).val(text); }) })

例8 TAB效果


知识点:

1.AddClass和RemoveClass的使用

2.小技巧,通过自定义的属性值进行匹配,定位标签的时候因为格式为[attr=‘value’]的格式,因此做了一个字符串的拼接

3.注释掉的代码是另外一种方法,可以通过索引来进行匹配



    
    Title
    
        .hide{
            display: none;
        }
        .menu{
            height: 38px;
            background-color: #eeeeee;
            line-height: 38px;
        }
        .active{
            background-color: brown;
        }
        .menu .menu-item{
            float: left;
            border-right: 1px solid red;
            padding: 0 5px;
            cursor: pointer;
        }
        .content{
            min-height: 100px;
            border: 1px solid #eeeeee;
        }
    


    
内容一
内容二
内容三
$('.menu-item').click(function(){ $(this).addClass('active').siblings().removeClass('active'); var target = $(this).attr('a'); # $('.content').children().eq($(this).index()).removeClass('hide').siblings().addClass('hide'); $('.content').children("[b='"+ target+"']").removeClass('hide').siblings().addClass('hide'); });

例9 点赞


知识点:

1. Jquery里面通过css()来改变一个标签的style

2. 思路和Dom一样的,动态创建一个span标签,通过定时器改变大小和位置,当透明度低于一定程度,结束定时器



    
    Title
    
        .container{
            padding: 50px;
            border: 1px solid #dddddd;
        }
        .item{
            position: relative;
            width: 30px;
        }
    


    
$('.item').click(function () { AddFavor(this); }); function AddFavor(self) { // DOM对象 var fontSize = 15; var top = 0; var right = 0; var opacity = 1; var tag = document.createElement('span'); $(tag).text('+1'); $(tag).css('color','green'); $(tag).css('position','absolute'); $(tag).css('fontSize',fontSize + "px"); $(tag).css('right',right + "px"); $(tag).css('top',top + 'px'); $(tag).css('opacity',opacity); $(self).append(tag); var obj = setInterval(function () { fontSize = fontSize + 10; top = top - 10; right = right - 10; opacity = opacity - 0.1; $(tag).css('fontSize',fontSize + "px"); $(tag).css('right',right + "px"); $(tag).css('top',top + 'px'); $(tag).css('opacity',opacity); if(opacity < 0){ clearInterval(obj); $(tag).remove(); } }, 40); }

例10 鼠标移动窗口

下面这个例子可以通过鼠标拖曳窗口


知识点:


1. offset()显示的是当前标签在整个html里面的坐标,还有一个position()显示的是在absolute在relative标签里面的位置


2. event=e || windows.event 是为了兼容旧版的IE来获取当前的事件, _event.clientX和_event.clientY这里获取的是鼠标的坐标


3. 绑定事件有几种方式,比如直接通过标签执行 $(''#title).mousover(function(){}); 或者通过on绑定,off接触绑定,例如$(''#title).on('mousemove',function(){}), $(''#title).off('mousemove'); 或者可以通bind和unbind绑定和接触绑定,比如例5;最后还可以通过delegate()来延迟绑定,比如例6




    
    


    
$(function(){ //鼠标放在标签上面自动变成移动的符号 $('#title').mouseover(function(){ $(this).css('cursor','move'); }); //鼠标单击的事件 $("#title").mousedown(function(e){ console.log($(this).offset()); //鼠标所在的坐标 var _event = e || window.event; var ord_x = _event.clientX; var ord_y = _event.clientY; console.log(ord_x) console.log(ord_y) //标签左上角在html里面的坐标 var parent_left = $(this).parent().offset().left; var parent_top = $(this).parent().offset().top; $('#title').on('mousemove', function(e){ var _new_event = e || window.event; var new_x = _new_event.clientX; var new_y = _new_event.clientY; //获取标签左上角的新坐标 var x = parent_left + (new_x - ord_x); var y = parent_top + (new_y - ord_y); $(this).parent().css('left',x+'px'); $(this).parent().css('top',y+'px'); }) }); $("#title").mouseup(function(){ //撤销绑定事件 $("#title").off('mousemove'); }); })


例11 阻止事件的发生

有的时候,我们会希望根据一定的条件阻止某个事件的发生,比如表单验证,如果不符合格式或者内容,则无法提交。

知识点:

默认情况下,当我们执行了自定义的Click事件后,他会自动跳转到href指定的地址。但是如果我们把自定义的事件返回值为false,那么他就不会执行后面的操作



    
    Title


    走你1
    走你2
    
    
        function ClickOn() {
            alert(123);
            return false;
        }
        $('#i1').click(function () {
            alert(456);
            return false;
        })
    

例12 JQuery的扩展事件


如果希望自己定义一个事件,然后让JQuery来调用的,可以通过extend

知识点:

1. extend的使用有两种方式:$. extend('name':function(){})定义,然后$.name来调用; 或者是$.fn.extend()定义,然后通过$('#id').name的方式来调用


2. 可以把这些扩展方法都写入一个专门的js文件,注意在plugin文件里面,我们是把他放在了一个自执行的方法里面,这个是为了避免和其他js文件里面变量名的冲突。这里我可以直接把JQuery作为参数传进去,这样arg.extend 就相当于$.extend了


plugin1.js

(function (arg) {
    var status = 1;
    arg.extend({
       'Hellow': function () {
           return 'HOHOH';
       }
    });
})(jQuery);


test.html



    
    Title


    
    
    
        var v = $.Hellow();
        alert(v);
    

node.js pm2 占用CPu100% 自动重启脚本

licqi阅读(117)

公司使用了nodejs开发了一部分业务,使用pm2管理node进程。

但是总是莫名其妙的占用100%CPU,又一时查不出什么问题。

为了避免node进程占用100%CPU导致业务卡死情况,写了一个针对pm2 管理node.js进程的脚本。

大概方式:

使用pm2 json得到pm2 的当前信息。

如果发现pm2 的某一个进程占用CPU90%,并且5s内该进程对应的日志没有变化,则重启该进程。

算是治标不治本吧,先凑合用着。

使用:php pm2AutoCheck.php 2>&1 >/dev/null &

&1 >/dev/null &;fi
set_time_limit(0);
//获取pm2信息
$comGetPm2Info="pm2 jlist";
$pm2OutPut = "";
$pm2OutPut=exec($comGetPm2Info);
//解析json
$pm2Info = json_decode($pm2OutPut,true);
$pm2InstanceNum = count($pm2Info);
//重启PM2进程
function restartPm2Instance($pm_id){
        $commRestart = "pm2 restart ".$pm_id;
        system($commRestart);
}
//通过检查日志是否有变化
//来确定PM2进程是否在处理请求
function isLogModified($pm2Info,$pm_id){
    $pm2InstanceLog = $pm2Info[$pm_id]['pm2_env']['pm_out_log_path'];
    if( file_exists($pm2InstanceLog)){
        $lastModified = filemtime($pm2InstanceLog);
        sleep(5);
        $newModified = filemtime($pm2InstanceLog);
        if( $newModified <= $lastmodified="" ){="" echo="" "file="" not="" modifed";="" return="" 0;="" }else{="" 1;="" }="" }else="" {="" 2;="" 死循环,间隔60s来检查一次="" while(1){="" for(="" $i="0" ;$i= 90 ){
        $needRestart = isLogModified($pm2Info,$pm_id);
        if( $needRestart == 0 ){
            restartPm2Instance($pm_id);
        }
    }
}
    sleep(60);
}