12

JS批量删除和全选

由于本人刚接触javascript,理解起来有些吃力,所以如果有不对的地方希望大家提出来,我再加以改正。这次写的主要是针对JS的批量删除和全选。

先说说我对JS的理解吧,javascript是一种脚本语言,它往往不能独立使用,而是配合html/jsp/php/.net等等使用的,它是客户端脚本语言,也就是说,它是给用户们看的,既然是给用户们看的,那么,恰当的应用JS就会增强用户体验效果,让用户们看起来觉得好看,方便,才会愿意去看。程序员做一个程序目的不就是为了让他所做的能够得到更多的人认可么,谁也不想自己做一个网站没人关注。

下面就针对我用JS做的批量删除和全选说一下,我做的是用户列表页,先把数据从数据库里取出来,做成表,这样样就有数据了,我想实现的效果是,当我选N项,点击批量删除的时候,弹出一个对话框,提示”确认删除N项吗?“,点击”确定“按钮,提示”批量删除成功“,点击”取消“按钮,返回当前页面。

首先,加一个“批量删除”的按钮

<input class=”alldel” onclick=”return batchdel()” type=”submit”  value=”批量删除”>  //“onclick”意思是当点击的时候,会触发一个事件,会执行batchdel()这个函数里的内容。

<li><input type=”checkbox”  id=”check” name=”checks[]” value=”<?php echo $row[“id”];?>” ></li>    //我是用复选框实现我想要的效果。”value”=我所选择的id.

然后定义batchdel()函数里的内容

function batchdel()
{
var checkbox = document.getElementsByName(“checks[]”);  //定义一个变量checkbox,找到name为‘checks[]’的元素。
var number = 0;  //初始化一下number
if(checkbox.length != 0)  //判断条件是当选择的个数不为0时
{
for( i = 0; i < checkbox.length; i )  //循环遍历复选框
{
if (checkbox[i].checked == true)  //如果[i]个复选框为选中状态
{
number ;  //累加所选的个数
}
}
if(number == 0)  //如果个数=0,也就是没有选中内容的时候
{
alert(“请选择”);   //弹出一个提示框,提示用户请选择内容

}else
{
var txt=”确定删除这” number “项吗?”;   //定义一个变量txt ,显示内容是确认删除这number项吗?number为几,显示的就是几。
if (confirm(txt))   //判断txt,这里用到的是confirm函数,confirm的意思就是弹出一个带有“确定”和“取消”的提示框。
{
return true;
}
else
{
return false;
}
}
}

}

接下来说JS实现全选和取消全选

我想实现的是点击“全选”按钮的时候,复选框全部是选中状态,同时按钮上的字变成“取消全选”,再点击“取消全选“的时候,复选框全部都是没被选中的状态,同时按钮上的字再变回”全选“。

先定义一个按钮

<input type=”button” id=”all_checked” name=”all_checked” value=”全选” onclick=”checkedAll()” >

再定义checkedAll()

function checkedAll()
{
var allCheckVal = document.getElementById(“all_checked”).value;     //定义变量    allCheckVal = 按钮上的字(“全选”)
var checked = false;
if(allCheckVal == “全选”)  //当按钮上的字为“全选”时
{
document.getElementById(“all_checked”).value = “取消全选”;   //点击变成取消全选
checked = true;   //同时checked值为true
}
else
{
document.getElementById(“all_checked”).value = “全选”;
checked = false;
}

var allcheck=document.getElementsByName(“checks[]”);
for(var i=0;i<allcheck.length;i )
{
allcheck[i].checked = checked;
}
}

因为变量checked只可能有两个值,一个是true,一个是false,当点击’全选‘时,字变’取消全选‘,checked值为true,点击’取消全选‘时,字变’全选‘,checked值为false。

GCDAsyncSocket类库,IOS下TCP通讯使用心得

关于在IOS下使用Socket进行通讯的技术文章也许诺很久了,今日又是一个还债的日子,网上虽然很多介绍过AsyncSocket或GCDAsyncSocket的文章,但其实就那么一两篇大部分都是转载,于是我义正言辞、慷慨激昂的批判他们这种不负责任的态度,学习,不是给自己学的,是要和大家分享的。技术的共享有利于整体行业的进步,也可以使自身更深入全面的了解。

之前的文章中我们讲到过TCP通讯协议,并且也对其进行了较为详细的介绍和描述,关于TCP通讯的原理此处我们不再赘述,如有需要的看官可自行翻阅本人所写的《IOS、安卓IM语音聊天开发初探部分心得——网络基础篇》一文。

正如名称一样GCDAsyncSocket开源类库是以苹果的GCD多任务处理机制完成的一个异步交互套接字通讯。使用方法其实并不复杂,主要说的是在使用这个类库的时候我的一些心得和理解,若有不妥之处望看官指点。首先,每一个GCDAsyncSocket对象(以下简称GCDSocket对象)都可以理解为一个socket套接字,我们的操作都是针对于这个socket执行的各种命令,可以打开一个端口侦听,同样也可以连接其他计算机的端口进行数据通讯等等等等。首先我们来创建一个socket。当然这之前先要将CGDAsyncSocket的.h文件及.m文件加入到我们的项目,并且在需要使用socket连接的地方将.h头文件包含,这些废话我觉得不需要复述了应该(那你还嘚吧嘚的说半天干嘛啊喂!)。具体代码如下

GCDAsyncSocket  socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];

代码并不复杂,我们只需要给出一个委托对象也就是第一个参数中的self,以及一个委托运行的GCD队列即可创建一个GCDAsyncSocket,当前代码中我们是使用静态全局函数取得的主消息队列。当然也可以使用其他方法获得其他的GCD队列,比如:dispatch_get_global_queue().

创建了Socket对象我们即可以立即为,当前我们的socket已经进入程序以供操作。但如果你想和服务器进行通讯,那么我们还需要和服务器进行连接。可能有的使用习惯了http协议的人会问,初始化函数中我们为何不直接指定服务器以及端口号?其实这些肯定都是需要的,但是你要理解到,你的socket对象功能不只是可以用来连接服务器,换而言之我们的socket对象一样可以侦听某端口来等待他人连接,所以在通过套接字编程使用TCP协议的时候是我们从http协议过度到TCP协议的一个转变(虽然本文并不会教你如何在IOS上构架服务器。),但并不是第一个,第一个转变是要记得,我们要使用的是协议,并非某个类,所以我上述说明中都是说从http协议过度到TCP而不是跟大家说现在我们将从NSURLRequest和NSURLConnection过度到GCDAsyncSocket。

好了接下来我们看看如何连接服务器。源代码如下:

NSError *err;

[socket connectToHost:@“192.168.10.111” onPort@”60000″ error:&err];

if (err != nil)

{

NSLog(@”%@”,err);

}

代码比前面稍微长了一点,不过实质上完全不复杂,我们只是先声明了一个错误信息的指针,然后使用之前创建的对象调用他的连接方法,第一个参数不难看出是一个IP,第二个参数则是一个端口,如果这里还不理解何为IP和端口的话,就先去看看在开头就提到的我之前写过的那边网络基础篇文章吧…最后一个是出参,如果连接的过程中出现了错误,该方法会把这根指针指向一个具体的错误信息,最后我们再判断一下之前我们创建错误信息的指针是否还是指向空,如果并非指向空那么代表我们连接的过程中出现了错误,将错误信息打印一下吧~不过请切记,此处的错误信息并非你创建连接时所有的错误都会在此处得到反映。

说到这里我们该说一点真正有用的了,GCDAsyncSocket具有一系列完整的委托机制,我们所做的一切处理基本都是异步处理的状态,换句话说,连接之后是否连接成功,连接成功要执行什么懂并非应该写在此处而应该写在相应的委托之中,同样的道理一样适用于发送、读取数据等等。也就是说我们在此处读出的错误只是同步执行的代码处理一些连接时会发生的错误,而更多的处理我们应在相对应的委托中进行处理。首先请看下面这个方法:

-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port

这个方法就是在成功连接服务器之后的委托方法。关于委托该如何使用我在此处就不赘述了和本文的关系实在不大,不过给诸位看管一个建议,也是我才刚刚纠正的一个编码错误习惯,之前碰到所有委托的地方我都会将直接将当前的类对象设置成委托处理对象,并且遵循委托协议扩充代码,这么做的坏处显而易见,显示层与逻辑层的混淆是一方面,另一方面是一旦需要使用过多的委托,将造成大量不必要的代码都堆积在一个类中,并且我们很容易直接在委托方法中直接使用一些类内成员属性或者甚至是私有成员,而实际上这种做法是很不好的,因为这种最发会使得逻辑出现混乱,处理委托应当是单独处于后台的逻辑,如果需要一些必要的数据传递也应该采取属性侦听、甚至是通知等方式来实现而并非直接在显示层中编写逻辑代码来实现。使得代码耦合性大增的同时也使得很多时候在切换操作对象时对委托对象的处理变得复杂,甚至可能完全相同的代码要难免的复制粘贴。所以我给大家的建议是单独编写一个委托类,在每个类中设置一个该类类型的成员指针,将委托设置到专门的委托对象上去处理,这样不仅效率更高,代码可读性更强,更便于维护,同时也更符合面向对象的编程思想。

回到对GCDAsyncSocket使用的讲解上来,在这个委托方法中,我们可以取到一个socket对象一个服务器IP和一个端口号,你可以处理一切在连接建立之后应该马上执行的事情,比如与服务器进行通信确认连接端以免出现其他人通过IP及端口随意的和你的服务器通信,再比如开启心跳包的发送,让服务器一直可以确认你的存在。不管做什么,都是你和服务器的编写者事前约定好的,就像数据传输格式什么的,如果没有当面约定我坚信他也一定要给你出个文档什么的,否则你的工作接下来将举步维艰。但是不管你要在此处都做什么工作,都要处理哪些事宜,请务必记得,在此处你必须要在函数的最后加上一句:

[socket readDataWithTimeout:-1 tag:0];

这是什么?别慌,按照你看到这个函数的第一反应取理解,没错他就是读取数据的方法,两个参数也略显简单,一个超时时间,如果你设置成-1则认为永不超时,而第二参数则是区别该次读取与其他读取的标志,通常我们在设计视图上的控件时也会有这样的一个属性就是tag。如果你做过web开发,那你应该知道Http标签上的id,如果你做过一些桌面级开发,你的控件或许有个id或者是index再或者是tag的属性来区别这些控件,没错此tag和彼tag功效基本一样。

我们可以这样理解,socket在开启之前是一个巨大门,开启这道门之后(也就是连接之后)就是一个宽敞的通道,通过这条通道所达到的地点就是我们连接的目标服务器,或者是连接过来的客户端,两面都是一样的。我们现在不论是发送数据还是读取数据都是往返于这个大门之中的一个个门卫与邮递员,我们可以把读取数据的方法看作是门卫,而发送数据的人看做是邮递员,没错服务器与客户端都一样,我们都会派出一个个邮递员去我们连接的另一端送信,但是如果你没有命令你的门卫去吧门口邮箱中的信拿过来,那么你的邮递员就会假装看不见邮递员,然后呼呼睡大觉,好吧看起来这些门卫实在没什么责任心不是么,其实他们也是有苦衷的,因为这是最初设计者给他们的命令,不接到命令绝对不要出门,万一收到的是金刚葫芦娃高清全集的种子怎么办!好的就这样,为了避免我们的邮件不被错过,所以建立连接之后就让一个门卫跑去门口等着吧~慢着,万一我需要派出很多个门卫我分不清他们该怎么办,其实他们已经被你分配了工号,这个工号就是tag。

现在我们的连接动作算是完整的做完了,接下来我们要做的就只有两件事,第一个在需要发送数据的时候派出邮递员,以及当门卫接到消息的时候在我们的手机端上根据门卫的消息做出反应。等等,好像少了点什么,没错 少点委托,我们来看一下读取和写入的委托,读取的委托即是门卫接到信息的报告,写入的委托就是邮递员将邮件送完的回复:

-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag

-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag

好的让我们来看看这些委托中我们都能得到什么,首先是读取的委托,是一个socket对象,一个读取到的数据以及一个“门卫的工号”,嗯,大概也就这些,我们还能要什么的,没错这些足够了,别抱怨第二个参数的数据类型,要知道其实最开始接到数据的时候只是字节数组啊,已经给你转换成NSData对象了你就要学会感恩啊,谁让你要用套接字传输了,这就是活该的,所以改怎么读取转换解析这些数据你需要好好的和服务器编写者沟通。除此之外你还要详细的了解如何将NSData转换成各种各样的数据或者文件如果你还不知道该怎么做我这里实在帮不了你,因为我总不能吧多如牛毛的情况都列举在这一篇文章中吧,要知道我每篇文章的篇幅都够长了。。。不过也别因此而气馁百度和谷歌肯定可以帮到你~

接下来我们再看看“邮递员的委托”,嗯一个socket的对象,一个tag嗯,没错,哎哎,慢着,好像哪里不太对啊,我来看看,哪里不对呢,哦对了!发送的数据呢!怎么没有!哎也不对。。。明明是我自己发的数据我还要来干嘛,有了工号我不就知道发送的是什么了么。那是哪里不太对呢。。。哦!是名字!我们的数据传输来说接受可以是读取read而发送通常我们应该写成Send一类的单词,为何这里是Write?写入?没错就是写入,向TCP的通讯流之中写入数据。TCP通讯协议是一个基于字节流的运输层通信协议,其数据传输的形式也是以流的形式提现,而我感觉在使用GCDAsyncSocket的过程中我们可以很好的体会到流的概念,首先来说为什么这种TCP的这种传输形式要叫流而不像UDP中的那样叫做包?流之中又写入和读出的概念,我们可以把整个TCP通讯的连接看作为一条无水的河流,当然因为他没水所以你可以称它为沟,而向其写入数据即是向河流注入水,被写入的数据会向水一样流向连接的另一端。读即是从河流中取水,只要读得动作在继续,并且河流之中有水,那么我们就可以不停的取到数据,不论是河流之中有水你确没有去读亦或者是你去读了而河流之中没有水都会引发看起来完全相同的反应就是没有数据返回,所以在很多时候我们要处理更多的关于接收数据的逻辑的处理。正如我们目前使用的方法就是一种比较粗暴有效的方法——一旦开启连接读取的动作就永不停歇。

接下来我们还要记住使用TCP流式传输数据时的一个关键性问题,数据是不会自己分段的。没错,就如一次次倒入河流中的水一样,数据也同样会向水一样融合为一个整体,换句话说,数据在TCP中传输本身是没有起始或结尾之分,如果我先向数据流中写入两个人的聊天记录,第一句是“你好”,对方回复了一句“不好”,结果发到了服务器,服务器读取出的信息是“你好不好”,同样类似的情况会发生很多,比我举出的这个例子要常见的多比如我先发了一段音频,又发了一段图片,又发了一段文字,最后服务器接收到了一个带语音和字母的静态图片。实际情况上比我说的要遭的多,因为由于字节之间并没有边界,所以字符、文字、音频,我们根本无法确定他们各有多长,胡乱截取,只会导致无法编码解析成图片、文字及音频,所以如何界定数据之间的边界是你开始使用TCP协议之后又一个问题。你可以使用一个固定的字节数组组合来区分开头以及结尾,也可以将所有的字符串都添加一个特殊的界定字符来区分不同的命令与操作。

如果看到这里的看官有心使用GCDAsyncSocket去编写了一个服务器端,并且使用它来接受客户端的数据,比如传输了一些音频,图片等从字节单位看来将会不小的长串数据的话就会发现,服务器端接到的程序是一段一段的,没错,但我没有欺骗你,TCP协议并不会区分你发送数据的头尾,被划分为段知识GCDAsyncSocket为了保证在并不通常的移动互联网之中一样可以安全的传输数据,于是将你所有写入到流的数据都一分割为一段一段的内容,所以请正确理解我在上一段开头所说的“数据是不会自己分段的。”这句话,不要较真哦亲~

写到这里,GCDAsyncSocket的基本操作及其核心思想就全部写完了,对于思想部分皆为笔者本人个人理解,若有缺少或意见不同之处,欢迎交换意见相互学习,感谢您的阅读。

文本框间传值——JS

[singlepic id=224]

如果文本框有内容时,当我点击文本框时,当前内容会复制到今天1里,如果1里有内容,就会复制到2里,依次类推。

<textarea onclick=”oCopy1(this);” id=”yesterdayWork1″ name=”yesterdayWork1″ >

JS部分
if(document.getElementById(“todayWork1″).value==””)
{
document.getElementById(“todayWork1”).value=document.getElementById(“yesterdayWork1”).value;
}

展示部分代码,重要的是思路。

知识共享  资源共享  心得共享

MySql 数据表关联查询

当数据库中有两个表。当我想查询A表中某一字段和B表中的某些字段在一起查出并显示时。要用到联合查询。但前提是两个表中必须包含一个字段,下面请看详细例子。

以日志系统为例,我想查出某人某天的工作。在用户表里查出用户名,在工作表里查出工作和某天。

SELECT a.userName, b.* FROM user as a left join work_log as b on(a.userId=b.userId) where `date`=”2013-07-07″ order by `reorder`

根据字段进行排序

前一阵用PHP做了个工作日志系统用户名排序功能,首先在user表里增加reorder字段,通过reorder字段里的数字来进行排序。实现的方法先将遍历出来的用户表,每条数据对应用户ID和reorder字段的值,点击排序按钮后,将reorder值全部提交,并在数据库里更新。最后在查询时根据reorder排序即可。

<input type=”text” name=”<?=$r[“userId”]?>” id=”<?php echo $r[“userId”]; ?>” value=”<?php echo $r[“reorder”];?>” onkeyup=”value=value.replace(/[^\d]/g,””)” />

$reorder = $this->input->post();
foreach($reorder as $k=>$v)
{
$this->adduser_mdl->update1($k,$v);
}

关于CSS Sprites图片整合技术

CSS Sprites 的目的就是通过整合图片,减少对服务器的请求数量,同时缩短了悬停加载图片所需要的时间延迟,使效果更流畅,不会停顿,当页面加载时,不是加载每个单独图片,而是一次加载整个组合图片,即加快页面加载速度。本质是将用到的图片都集成为一张大图片,然后通过CSS的background-image和background-position属性进行定位,显示图片的不同部分。

一、适用哪里:CSS Sprites常用来合并频繁使用的图形元素,如导航、LOGO、分割线、RSS图标、按钮等。通常它们不会作为网页内容出现,因为涉及内容的图片并不是每个页面都一样。

CSS Sprites一般只能使用到固定大小的容器里,这样才能够遮挡住不应该看到的部分。必须限制容器的大小才能使用CSS Sprites,否则可能会出现出现干扰图片的情况。这就是说,在一些需要非单向的平铺背景和需要网页缩放的情况下,CSS Sprites并不合适。当然,加大图片之间的距离,这样可以保持有限度的缩放。

二、具体实现:

1、图片合并:用photoshop将小图片们合并到一张大图上。

①合并之前就要仔细考虑它们的布局问题,以免不该出现的图片扰乱页面。例如下图这种背景一般用在文本列表中,实际应用的时候列表的行高往往比背景中的序号要大,所以在背景合并图片中间距应该比一般小图要大些,这样在页面中就不会将其它的小图给显示出来。

②在页面小图很多,需要做成多个sprites图片时,可以按颜色分类,尽量将相同、相近颜色的小图整合在一张大图上,这样可以有效减小合成后图片的体积。

③ 如果是规模较大的站,可以把需要横向平铺的所有图片做成一个图,需要纵向平铺的做成第二个图,把双向的和颜色非常复杂的单独放,其它的都做在一个图里。

④在size相同的CSS Sprites图片中,垂直排列的图片会比水平排列的文件体积要大;在面积相同的CSS Sprites图片中,水平排列的图片会比垂直排列的文件体积要大。

2、图片定位background-position:大图片的左上角坐标为(0,0),用photoshop分别读取各个子图片的坐标值(窗口→信息)。

举例:用ps把红、黄、蓝色三个子图50px*50px整合到一张图片上。

css样式如下:css

html代码:

html

网页效果:

关于 background-position负值的理解:固定好大小的容器,相当于一个窗口,这个窗口的位置是固定不动的,想通过这个窗口来显示背景图片上的指定子图片,就得移动这个背景图片,使指定子图出现在这个窗口。这个背景图片向左、向上移动是负值,那么相反,向右、向下移动就是正值。

一点心得

小仙刚刚修改了某项目中的一个查询列表显示过慢的问题,用时3天,总体来说,用两个 sql 语句就可以搞定的,一个 sql 是更新整个数据库,另一个修改原有的 sql 。编写代码加数据测试本来可以一天就搞定了,而我在电脑面前苦熬了3天时间啊!!!总结如下,也希望菜鸟们吸取教训,咱们共同进步吧。

一、阻碍我的第一个因素就是:对所做项目的基本流程没有彻底弄懂。这一条就可以直接把小仙我贬下凡间了,原因很简单,小仙跟了这个项目已经很长时间了,同时,也做过这个项目的测试,知道这项目是干啥的,但是,真到了某一个环节的时候就不怎么明白了,还是一知半解。什么也别说了,作为本项目程序员,严重不合格,小仙我愧对领导的培养啊!

二、其二,本小仙菜鸟一个,初来咋到的,程序思想还没有形成,那就像修仙者丹田之内连个气儿都没有是一个样的。所以我要从头学起了,不是你掌握了某一门语言你就是一位合格的程序员了,最基本的程序员得有思想!  思想!  思想很重要。身为程序员,在做某一个项目或项目中的某一个功能之前,首先,应该分析分析该功能的目的是啥,怎么实现,如何解决,在脑海里一定要有整体的思路,先做哪个,再做哪个,分析结束;然后,习惯性的画一张流程图,把功能从头到尾如何实现的阐述明白;那最后就是编码了,如果跳过“首先”和“然后”直接进行编码,那就像我一样,做出来的东西,漏洞百出,连功能的目的都达不到,熟话说,磨刀不费砍材工,在没有成为“大湿”之前,还是按部就班的“首先-然后-最后”吧。

三、前两个因素,可能也是菜鸟们的通病,要想脱离菜鸟团,必须养成良好的编程习惯啊!习惯可以养成,但还有一个问题,功能可以实现,但是,这是不是最好的?有木有比这更好的?小仙说有,因为编程是个细腻的工程,盖个楼,少几粒沙子不重要,但是,一大堆的程序里,因为几粒沙子就可能多走了几步道儿,也有可能走歪道儿啊!我们在编写代码的时候应该把所有可能出现的问题及无关的条件都要考虑进来,程序里该不要的不要,必须写的一定要精简,嗯!

好了,大家比我强,认识的比我多,话不多说,其中有不妥之处,就看在小仙依然很菜的份上,轻轻吐槽啊?!希望可以帮助和小仙一样正在长身子的初学者和菜鸟团,我们菜鸟先分!!!

小仙想说,这是一个技术博客,那么,我用到的技术就和大家分享一下吧!

|—————————————--tab1(表)-—————————————|

id(主键)                          submitCnt(提交次数)                       lastTime(最后一次提交时间)

1                                                    0                                                         0

|—————————————--tab2(表)-————————————–|

id(主键)                       tab1_id(表tab1的id)                               createTime(创建时间)

1                                            1                                                         2013-07-16

2                                            1                                                         2013-07-17

3                                            1                                                         2013-07-18

我要实现的功能就是:统计  表tab2  中  tab1_id  出现的次数,并记录在  表tab1submitCnt(提交次数)  字段里,还有,统计  表tab2  中关于  tab1_id createTime(创建时间)字段里,最后一次创建的时间,并记录在 表tab1 的  lastTime(最后一次提交时间) 字段里,用一条  sql  语句搞定。

update tab1 b, (select  a.tab1_id as tid, count(a.id) as bcnt, max(a.createTime) as lastime

from  tab2  a ,  tab1   b

where  a.tab1_id  =  b.id

group  by  tid)  c

set  b.submitCnt=c.bcnt,b.lastTime= c.lastime

where b.id=c.tid;

 

12