12

js控制下拉框选中项

昨天帮电商的同事在ecshop的后台添加了一个检索分类的小功能,
当在文本框中输入汉字时,会自动将下拉框中匹配的项设为选中项。
分享如下


<select id="cat_id" name="cat_id">
<option value="0">{$lang.goods_cat}</option>{$cat_list}
</select>
<input id="cat_search" name="cat_search" size="8" type="text" />
function catMatch()
{
var keyWord = document.getElementById("cat_search").value;
var cat = document.getElementById("cat_id");
var catItems;
for(var i=0;i<cat.length;i )
{
catItems = cat.options[i].text;

if(catItems.indexOf(keyWord) != -1)
{
cat.options[i].selected = true;
return
}
}
}

ecshop邮箱登录

由于,ecshop中本身注册时就有邮箱唯一的验证,同时用户名中也不能包含@符号。

所以,只需要考虑控制登录的login方法(public_htm/includes/modules/integrates/integrate.php中)。

在该方法中增加如下代码

function login($username, $password, $remember = null)
{
 if(is_email($username)) 
 { 
	$sql = "select ".$this->field_name." 
 from ".$this->table($this->user_table)." 
 where ".$this->field_email."="".$username."""; 
	$username = $this->db->getOne($sql); 
	if(!$username)
	  return false; 
 } 
 if ($this->check_user($username, $password) > 0)
 {
 if ($this->need_sync)
 {
 $this->sync($username,$password);
 }
 $this->set_session($username);
 $this->set_cookie($username, $remember);

 return true;
 }
 else
 {
 return false;
 }
}

其中用到了include/lib_common.php文件中的is_email()方法

function is_email($user_email)
{
 $chars = "/^([a-z0-9 _]|\\-|\\.) @(([a-z0-9_]|\\-) \\.) [a-z]{2,6}\$/i";
 //通过strpos()函数判断传入字符串是否包含@与.
 if (strpos($user_email, "@") !== false && strpos($user_email, ".") !== false)
 {
 if (preg_match($chars, $user_email))
 {
 return true;
 }
 else
 {
 return false;
 }
 }
 else
 {
 return false;
 }
}

也就是说先判断提交过来的$username是否为邮箱,如果是就去数据库里取相应的username,取到username以后继续执行原来的方法就可以了。如果邮箱在数据库中不存在就返回false。

ecshop 保存用户购物车数据

ecshop的购物车记录储存在cart表中,用户向购物车中添加商品时会在其中产生一条记录

靠session_id与用户产生映射关系。当注册用户退出登录或者游客关闭浏览器时,session被销毁,同时删除掉cart表中与之对应的记录。所以ecshop的购物车功能,无法在用户下次登录时记录之前的购物车信息。这在某些场景,如用户误关掉浏览器时十分不方便。
为了解决这个问题,首先要在用户登录时,将他以户已游客身份,产生的购物车数据加上user_id。
然后要将该用户的历史购物车记录中的session_id改为本次的session_id。
最后要在用户退出登录时,保存住注册用户在cart表中的购物车记录。
 
具体实现方法:
一、在includes/lib_main.php
中定义如下方法并在update_user_info()方法中的末尾处执行
/**
* 用户登陆后,载入上一次退出时的购物车信息,并与此次登录前购物车信息合并
*
* @access  public
* @return  void
*/
function merge_cart_history()
{
if (!$_SESSION[“user_id”])
{
return false;
}
$sql = “update ” . $GLOBALS[“ecs”]->table(“cart”) . ” set user_id = ” . $_SESSION[“user_id”] . ” where session_id = “”.SESS_ID.”””;//为用户以游客身份时(登录之前),产生的购物车记录添加user_id
$GLOBALS[“db”]->query($sql);

 $sql1 = “update ” . $GLOBALS[“ecs”]->table(“cart”) . ” set session_id =”” . SESS_ID . “” where user_id = “” . $_SESSION[“user_id”] . “””;//将用户历史购物车记录的session_id,改为本次的session_id
$GLOBALS[“db”]->query($sql1);
$re = $GLOBALS[“db”]->getAll(“select goods_id, rec_id, sum(goods_number) as goods_number from ” . $GLOBALS[“ecs”]->table(“cart”) . ” where user_id = “{$_SESSION[“user_id”]}” and session_id = “”.SESS_ID.”” group by goods_id”);//汇总历史购物记录与本次购物记录中,每一种商品的数量
if($re){
foreach ($re as $k => $v)
{
$sql = “update ” . $GLOBALS[“ecs”]->table(“cart”) . ” set goods_number = ” . $v[“goods_number”] . ” where rec_id = ” . $v[“rec_id”];
$GLOBALS[“db”]->query($sql); //每种商品保留一条记录

$sql = “delete from ” . $GLOBALS[“ecs”]->table(“cart”) . ” where rec_id <> {$v[“rec_id”]} and user_id = “{$_SESSION[“user_id”]}” and session_id = “” . SESS_ID . “” and goods_id = ” . $v[“goods_id”];//删除多余的记录
$GLOBALS[“db”]->query($sql);
}
}
}

二、将includes/cls_session.php中的destroy_session()方法做如下修改:

将$this->db->query(“DELETE FROM ” . $GLOBALS[“ecs”]->table(“cart”) . ” WHERE session_id = “$this->session_id””);

改为$this->db->query(“DELETE FROM ” . $GLOBALS[“ecs”]->table(“cart”) . ” WHERE session_id = “$this->session_id” AND `user_id`=0″);

既销毁当销毁session时,只将cart表中user_id等于0(未登录用户)的购物车记录删除。

改完收工。

 

AppCan 中的AJAX通讯实践

手机应用开发必不可少的就是与网络进行交互。常见的与网络交互都是通过http或https请求方式。这两种方式在以浏览器引擎为核心的Appcan平台中,都是支持的。为了减少数据大小,建议在与网络数据传输时采用json数据格式。
在浏览器中,用异步方式(Ajax)在A网站访问B网站的接口,这种行为被认为是不安全的。为什么呢?想象一个场景:通过Ajax异步请求别的网站接口,返回一个字符串,字符串内容为”<script>//dosomething</script>”,那么这个数据内容就危险了,浏览器会执行<script>标签里面的js代码。这种方式就是所谓的”跨域访问”。这种限制是浏览器做的,其实请求数据已经返回回来。
那么,如何解决跨域访问问题呢,可有几种解决方式
利用第三方网站,比如委托给google网站,google提供了一套跨域访问的js库。
Jquery的$.getJSON方法,这种需要返回数据格式为json格式
在返回头的content-type中设置为application/json
利用Appcan的Native模式开发的widget,也是属于跨域访问的范畴,因此,也会碰到上述情况,这里介绍两种Appcan中的解决方案:
一、Jquery的$.getJSON(url,function(data){});第一个参数是url获取数据地址,第二个参数成功取得数据时调用;
其中,url中必须带有jsoncallback参数,参数值为”?”,Jquery会在请求时替换为一个随机的唯一数:
http://xxxx.php?jsoncallback=?&name1=value1&name2=value2
用$.getJSON时,数据的返回格式要是xxx({“a”:”1″,”b”:”2″})
例如:
xxx({“status”:”true”,”listData”:[{“id”:”261803″,”title”:”虚拟投影键盘”,”name”:”前沿科技”,”summary”:”这款虚拟投影键盘设计独特,每一个敲击都不会相互干扰,可以同时接受。”},{“id”:”261994″,”title”:”科学家发现”最大黑洞””,”name”:”环球快递”,”summary”:”美国加州大学伯克利分校的天文学家尼古拉斯•麦克康纳尔和他的同事发现了两个目前已知最大的黑洞。”}}]})
注意:需验证{“a”:”1″,”b”:”2″}json格式的正确性,可在jsonlint.com网站上验证,如果格式不合法将获取不到数据
 
服务器端需要返回
echo  $[“jsoncallback”].”(“.json_encode($data).”)”; $data为PHP数组
 
二、Appcan封装的uexXmlHttpMgr对象方法如下:
uexXmlHttpMgr.open(String inXmlHttpID, String inMethods, String inUrl);第一个参数:

inXmlHttpID:异步请求操作ID;必须值。(随机不重复)

第二个参数:

inMethods:异步请求类型;(get,post)

第三个参数:

inUrl:异步请求地址;
通过uexXmlHttpMgr.onData函数获取值。
uexXmlHttpMgr.onData(inOpCode,inResult)
inOpCode:操作ID,由发起请求时传入的值,随机不重复;
inResult:服务器返回的任意数据;String类型。
使用方式:

function xmlHttp (){
             var url = document .getElementById ( “add”). value ;
             uexXmlHttpMgr .open (1 , “GET” , url ,“” );
             uexXmlHttpMgr .send (1 );
       }
       function httpSuccess (opid ,status ,result ){
             if (status ==1 ){
             uexXmlHttpMgr .close (1 );
             document .getElementById ( “adre”). value   = result ;
          }
       }

       window .uexOnload = function (){
             uexXmlHttpMgr .onData = httpSuccess ;
             uexWidgetOne .cbError = function( opCode , errorCode , errorInfo ){
                   alert (“errorCode:”   errorCode   “\nerrorInfo:”   errorInfo );
             }
       }
< div data-role =”header  class =” ui-header ui-bar-b ui-header-fixed ui-bar-glass >

< h1 class =”ui-title  tabindex =” 0 role =” heading aria-level=” 1 >
跨域异步请求
</ h1>
</ div>

< div id=” page_5 “ class =”ui-page ui-body-c ui-page-active  tabindex =” 0 >
< div class =”ui-content ui-body-c ui-fixed-top ui-fixed-bottom m-bottom  >
< label for =”text-6  class =” ui-input-text  >请求内容: </ label>
< textarea placeholder =”http://192.168.10.109/phdmyadmin/test.php?func=show    name =”textarea-2  id =” add class=” ui-input-text ui-body-null ui-btn-corner-all ui-shadow-inset ui-btn-d >http://192.168.10.109/phdmyadmin/test.php?func=show </ textarea>
< label for =”text-6  class =” ui-input-text  >请求结果: </ label>
< textarea placeholder =””  name =”textarea-3  id =” adre class =”ui-input-text ui-body-null ui-btn-corner-all ui-shadow-inset ui-btn-d ></textarea >
< div data-role =”button  class =” ui-btn-corner-all ui-btn  ui-btn-e  ui-shadow onclick =xmlHttp( )> < span class =” ui-btn-inner ui-btn-corner-all > <span class=” ui-btn-text “> 发送请求 </span > </ span></ div >

</ div>
</ div>

该方法返回数据只要是正确的json格式就可以;

 
<script>
       /*
       * 跨域异步post请求
       * arguments[0]请求的ID
       * arguments[1]请求php文件中的方法名
       * arguments[2]需要传输的POST键值对像
       */
       function xmlHttp()
       {
             var id    = arguments[0 ] ? arguments [0]: “0”;//真机环境下需要数字作为ID
             var func  = arguments [1] ? arguments[1 ]:“show”;
             var url     = “http://192.168.10.109/phpmyadmin/test.php?func=”  func ;//一定要加HTTP://
             uexXmlHttpMgr.open(id, “POST”, url,“” );
             if(arguments [2])
             {
                   var postKey = “”;
                   var postValue =“” ;
                   for(var key in arguments[2 ])
                   {
                         postKey = key ;
                         postValue = arguments [2][ key];
                         uexXmlHttpMgr.setPostData (id ,“0”, postKey,postValue );//post参数
                   }
             }
             uexXmlHttpMgr.send(id);
             //alert(“发送请求”)
       }
       /*
       * 查询
       */
       function httpSuccess (opid ,status ,result )
       {
             if(status == -1)
             {
                   //alert(“传输失败” )
             }
             if(status == 0)
             {
                   //alert(“正在传输”)
             }
             if(status == 1)
             {
                   //alert(“传输完成”)
                   uexXmlHttpMgr.close(opid);
                   var test = “<input type=”text” id=”content_add”>”
                                “<input type=”button” value=”添加” onclick=”insertItem()”>”;
                   var tmpl = “<div>”
                                “<input type=”text” id=”content_${index:}” value=”${content}”>”
                                “<input type=”button” value=”修改” onclick=”saveItem(${id},${index:})”>”
                                “<input type=”button” value=”删除” onclick=”deleteItem(${id},${id})”>”
                                “</div>”;         
                   var json = eval (result );
                  
                   test  = zy_tmpl (tmpl ,json ,zy_tmpl_count (json ));
                   $( “#content”).html(test);
             }
       }
       /*
       * 修改
       */
       function saveItem ()
       {
             var id = arguments [0];
             var input = $ (“#content_”  arguments[1 ]);
             var content =  input.val();
      
             xmlHttp(“1” ,“save”,{ “id”:id ,“content”: content})
       }
       /*
       * 添加
       */
       function insertItem ()
       {
             var input = $ (“#content_add”);
             var content = var  input.val();
             xmlHttp(“2” ,“insert”,{ “content”:var content })
       }
       /*
       * 删除
       */
       function deleteItem ()
       {
             var id = arguments [0];
             xmlHttp(“3” ,“delete”,{ “id”:id })
       }
       window.uexOnload = function()
       {
             uexXmlHttpMgr.onData = httpSuccess ;//请求数据成功后的回调函数
            
            
   }
</script>
<input class=”btn  type =”button value=” 开始 onclick=”xmlHttp() >
服务端PHP文件

<?php
$cfg_dbhost = “localhost”;
$cfg_dbname = “sitrust”;
$cfg_dbuser = “root”;
$cfg_dbpwd = “”;

$conn = mysql_connect($cfg_dbhost, $cfg_dbuser, $cfg_dbpwd) or die (“不能连接数据库服务器: ” . mysql_error());
mysql_select_db($cfg_dbname, $conn) or die (“不能选择数据库: ” . mysql_error());
mysql_query(“set names utf8”);
/*
**执行$_GET[“func”])传入的方法
*/
if(!empty($_GET[“func”]))
{
 $func = $_GET[“func”];
 $func();
}
/*
**查询
*/
function show()
{
 Global $conn;
 $sql = “select * from `test`”;
 $result = mysql_query($sql,$conn);
 while( $row = mysql_fetch_array($result) )
 {
  $content[] = $row;
 }
  //json数据返回客户端
  echo json_encode($content);
}
/*
**修改
*/
function save()
{
 Global $conn;
 $id = $_POST[“id”];
 $content = $_POST[“content”];
 $sql = “UPDATE `sitrust`.`test` SET `content` = “”.$content.”” WHERE `test`.`id` =”.$id;
 if(mysql_query($sql,$conn))
 { 
  show();
 }
 else
 {
  return false;
 }
}
/*
**删除
*/
function delete()
{
 Global $conn;
 $id = $_POST[“id”];
 $sql = “DELETE FROM `sitrust`.`test` WHERE `test`.`id` = “.$id;
 if(mysql_query($sql,$conn))
 { 
  show();
 }
 else
 {
  return false;
 }
}
/*
**添加
*/
function insert()
{
 Global $conn;
 $content = $_POST[“content”];
 $sql = “INSERT INTO `sitrust`.`test` (`content` ) VALUES (“”.$content.””);”;
 if(mysql_query($sql,$conn))
 { 
  show();
 }
 else
 {
  return false;
 }
}

 

AJAX学习笔记

一、json_encode()
该函数主要用来将数组和对象,转换为json格式。先看一个数组转换的例子:
  $arr = array (“a”=>1,”b”=>2,”c”=>3,”d”=>4,”e”=>5);
  echo json_encode($arr);
结果为
  {“a”:1,”b”:2,”c”:3,”d”:4,”e”:5}
再看一个对象转换的例子:
  $obj->body = “another post”;
  $obj->id = 21;
  $obj->approved = true;
  $obj->favorite_count = 1;
  $obj->status = NULL;
  echo json_encode($obj);
结果为
  {
    ”body”:”another post”,
    ”id”:21,
    ”approved”:true,
    ”favorite_count”:1,
    ”status”:null
  }
由于json只接受utf-8编码的字符,所以json_encode()的参数必须是utf-8编码,否则会得到空字符或者null。当中文使用GB2312编码,或者外文使用ISO-8859-1编码的时候,这一点要特别注意。
二、索引数组和关联数组
PHP支持两种数组,一种是只保存”值”(value)的索引数组(indexed array),另一种是保存”名值对”(name/value)的关联数组(associative array)。
由于javascript不支持关联数组,所以json_encode()只将索引数组(indexed array)转为数组格式,而将关联数组(associative array)转为对象格式。
比如,现在有一个索引数组
  $arr = Array(“one”, “two”, “three”);
  echo json_encode($arr);
结果为:
  [“one”,”two”,”three”]
如果将它改为关联数组:
  $arr = Array(“1″=>”one”, “2”=>”two”, “3”=>”three”);
  echo json_encode($arr);
结果就变了:
  {“1″:”one”,”2″:”two”,”3″:”three”}
注意,数据格式从”[]”(数组)变成了”{}”(对象)。
如果你需要将”索引数组”强制转化成”对象”,可以这样写
json_encode( (object)$arr );
或者
json_encode ( $arr, JSON_FORCE_OBJECT );
三、类(class)的转换
下面是一个PHP的类:
class Foo {
    const ERROR_CODE = “404”;
    public $public_ex = “this is public”;
    private $private_ex = “this is private!”;
    protected $protected_ex = “this should be protected”;
    public function getErrorCode() {
      return self::ERROR_CODE;
    }
  }
现在,对这个类的实例进行json转换:
$foo = new Foo;
$foo_json = json_encode($foo);
echo $foo_json;
输出结果是
{“public_ex”:”this is public”}
可以看到,除了公开变量(public),其他东西(常量、私有变量、方法等等)都遗失了。
四、json_decode()
该函数用于将json文本转换为相应的PHP数据结构。下面是一个例子:
$json = “{“foo”: 12345}”;
$obj = json_decode($json);
print $obj->{“foo”}; // 12345
通常情况下,json_decode()总是返回一个PHP对象,而不是数组。比如:
$json = “{“a”:1,”b”:2,”c”:3,”d”:4,”e”:5}”;
var_dump(json_decode($json));
结果就是生成一个PHP对象:
object(stdClass)#1 (5) {
    [“a”] => int(1)
    [“b”] => int(2)
    [“c”] => int(3)
    [“d”] => int(4)
    [“e”] => int(5)
  }
如果想要强制生成PHP关联数组,json_decode()需要加一个参数true:
$json = “{“a”:1,”b”:2,”c”:3,”d”:4,”e”:5}”;
var_dump(json_decode($json),true);
结果就生成了一个关联数组:
array(5) {

     [“a”] => int(1)
     [“b”] => int(2)
     [“c”] => int(3)
     [“d”] => int(4)
     [“e”] => int(5)
  }
五、json_decode()的常见错误
下面三种json写法都是错的,你能看出错在哪里吗?
$bad_json = “{ “bar”: “baz” }”;
$bad_json = “{ bar: “baz” }”;
$bad_json = “{ “bar”: “baz”, }”;
对这三个字符串执行json_decode()都将返回null,并且报错。
第一个的错误是,json的分隔符(delimiter)只允许使用双引号,不能使用单引号。第二个的错误是,json名值对的”名”(冒号左边的部分),任何情况下都必须使用双引号。第三个的错误是,最后一个值之后不能添加逗号(trailing comma)。
另外,json只能用来表示对象(object)和数组(array),如果对一个字符串或数值使用json_decode(),将会返回null。
var_dump(json_decode(“Hello World”)); //null
六、应用举例
1.PHP代码
$result = $_POST;
echo json_encode($result);
1.JS代码
$.ajax({
    url: “**.php”,
    type: “POST”,
    data:{
     company_id        :”数据1″,
     statement_year :”数据2″   },
    dataType: “json”,
    error: function(){alert(“PHP文件读取失败”);},
    success: function(result){
         alert(result.company_id);//会显示“数据1”
         }
  });

checkbox的全选,反选,删除

<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<script type=”text/javascript”>

//单项删除时的ONCLICK
function dropGet()
{
var f = confirm(“确认删除选定记录?”);
if(f)
{
return true;
}
else
{
return false;
}
}
function confirmDrop()
{
var d = false;
var items = document.getElementsByName(“a[]”);
//多项删除时,判断checkbox是否有选中项
for(var i = 0;i<items.length;i )
{
if(items[i].checked)
{
d = true;
}
}
//如果有选中项
if(d)
{
//确认删除对话框
dropGet()
}
//如果没有选中项
else
{
alert(“请选择要删除的费用记录”);
return false;
}
}
//全选
function checkedAll()
{
var items = document.getElementsByName(“a[]”);
for(var i = 0;i<items.length;i )
{
items[i].checked = true;
}
}
//反选
function checkedRev()
{
var items = document.getElementsByName(“a[]”);
for(var i = 0;i<items.length;i )
{
items[i].checked = !items[i].checked ;
}
}

</script>
</head>
<body>
<form name = “form1” id = “form1” onsubmit = “confirmDrop()”>
<input type = “checkbox” name = “a[]” id = “a” value = “1”>
<input type = “checkbox” name = “a[]” id = “a” value = “2”>
<input type = “checkbox” name = “a[]” id = “a” value = “3”>
<input type = “checkbox” name = “a[]” id = “a” value = “4”>
<input type = “checkbox” name = “a[]” id = “a” value = “5”>
<input type = “checkbox” name = “a[]” id = “a” value = “6”>
<input type = “button” onclick = “checkedAll()” value = “全选”>
<input type = “button”onclick = “checkedRev()” value = “反选”>
<input type = “submit” value = “删除”>
</form>
</body>
</html>

用document.getElementsByName()获得所有的checkbox需要每一个checkbox的名字都相同,但这会使PHP中$_POST[]接受到的checkbox值相互替换,只保存到最后一个。

解决的办法是在name后家上[] 如name = “a[]”,这样会使$_POST[“a”]作为一个数组,读取时只需要遍历$_POST[“a”]就可以了。

关于 checkbox的资料可以参考http://www.111cn.net/tags.php/checkbox

isset()和empty()的区别

isset()用于检测一个或多个变量是否被设置,如果被检测变量存在返回ture,不存在返回false。在以下三种情况当变量未被声明,或被赋值为NULL,或被unset()注销的时候返回false。

empty()用于检测一个变量是否为空,如过被检测变量为空返回ture,否则返回false。其中””、0、”0″、NULL、false、var、array()、没有任何属性的对象,都会被判断为ture,但空格” “不会被判断为空。

需要注意的是isset()和empty()不属于函数,而是一种语言结构,所以无法被变量函数调用,同时它们只接受变量,不接受其他形式的参数

12