作者 申海龙

设置分类 去掉 列表 货物品名名称

@@ -26,7 +26,9 @@ import org.springframework.web.bind.annotation.RequestMethod; @@ -26,7 +26,9 @@ import org.springframework.web.bind.annotation.RequestMethod;
26 import org.springframework.web.bind.annotation.ResponseBody; 26 import org.springframework.web.bind.annotation.ResponseBody;
27 27
28 import javax.servlet.http.HttpServletRequest; 28 import javax.servlet.http.HttpServletRequest;
  29 +import javax.sound.midi.Soundbank;
29 import java.util.ArrayList; 30 import java.util.ArrayList;
  31 +import java.util.HashSet;
30 import java.util.List; 32 import java.util.List;
31 import java.util.Map; 33 import java.util.Map;
32 34
@@ -219,12 +221,19 @@ public class SDCARGONAMEController { @@ -219,12 +221,19 @@ public class SDCARGONAMEController {
219 public DataGrid<SdTwoTypeVo> twogrid(HttpServletRequest request, EasyPage<SDTWOTYPEEntity> pageForm) { 221 public DataGrid<SdTwoTypeVo> twogrid(HttpServletRequest request, EasyPage<SDTWOTYPEEntity> pageForm) {
220 222
221 Map<String, Object> searchParams = Servlets.getParametersStartingWith(request, "search_"); 223 Map<String, Object> searchParams = Servlets.getParametersStartingWith(request, "search_");
  224 +
222 pageForm.setSearchParams(searchParams); 225 pageForm.setSearchParams(searchParams);
223 - pageForm.parseData(sdtwotypeService.getPage(pageForm)); 226 +
  227 +// pageForm.parseData(sdtwotypeService.getPage(pageForm));
  228 + List<SDTWOTYPEEntity> sdtwotypeEntities = sdtwotypeService.twoFindAll();
  229 +// pageForm.parseData();
  230 +
224 DataGrid<SDTWOTYPEEntity> hzshipperinformationEntityDataGrid = pageForm.getData(); 231 DataGrid<SDTWOTYPEEntity> hzshipperinformationEntityDataGrid = pageForm.getData();
  232 +
225 List<SdTwoTypeVo> rows = new ArrayList<>(); 233 List<SdTwoTypeVo> rows = new ArrayList<>();
226 - if (CollectionUtils.isNotEmpty(hzshipperinformationEntityDataGrid.getRows())){  
227 - for (SDTWOTYPEEntity sd: hzshipperinformationEntityDataGrid.getRows()){ 234 +
  235 +// if (CollectionUtils.isNotEmpty(hzshipperinformationEntityDataGrid.getRows())){
  236 + for (SDTWOTYPEEntity sd: sdtwotypeEntities){
228 SdTwoTypeVo sdTwoTypeVo = new SdTwoTypeVo(); 237 SdTwoTypeVo sdTwoTypeVo = new SdTwoTypeVo();
229 238
230 SDBIGTYPEEntity one = sdbigtypeService.findOne(sd.getBig_type_id()); 239 SDBIGTYPEEntity one = sdbigtypeService.findOne(sd.getBig_type_id());
@@ -235,13 +244,13 @@ public class SDCARGONAMEController { @@ -235,13 +244,13 @@ public class SDCARGONAMEController {
235 sdTwoTypeVo.setCargo_name_id(sd.getCargo_name_id()); 244 sdTwoTypeVo.setCargo_name_id(sd.getCargo_name_id());
236 sdTwoTypeVo.setTwo_type_name(sd.getTwo_type_name()); 245 sdTwoTypeVo.setTwo_type_name(sd.getTwo_type_name());
237 sdTwoTypeVo.setTwo_type_order(sd.getTwo_type_order()); 246 sdTwoTypeVo.setTwo_type_order(sd.getTwo_type_order());
238 -  
239 rows.add(sdTwoTypeVo); 247 rows.add(sdTwoTypeVo);
240 } 248 }
241 - } 249 +// }
  250 +
242 DataGrid<SdTwoTypeVo> vos = new DataGrid<>(); 251 DataGrid<SdTwoTypeVo> vos = new DataGrid<>();
243 vos.setRows(rows); 252 vos.setRows(rows);
244 - vos.setTotal(hzshipperinformationEntityDataGrid.getTotal()); 253 +// vos.setTotal(hzshipperinformationEntityDataGrid.getTotal());
245 return vos; 254 return vos;
246 } 255 }
247 256
@@ -374,7 +383,7 @@ public class SDCARGONAMEController { @@ -374,7 +383,7 @@ public class SDCARGONAMEController {
374 } 383 }
375 384
376 /** 385 /**
377 - * 分类添加 386 + * 添加货物和二级类关系
378 * @param sd 387 * @param sd
379 * @param request 388 * @param request
380 * @return 389 * @return
@@ -384,20 +393,90 @@ public class SDCARGONAMEController { @@ -384,20 +393,90 @@ public class SDCARGONAMEController {
384 public ResponseModel doSave(SDTWOTYPEEntity sd, String names, HttpServletRequest request){ 393 public ResponseModel doSave(SDTWOTYPEEntity sd, String names, HttpServletRequest request){
385 ResponseModel model = new ResponseModel(); 394 ResponseModel model = new ResponseModel();
386 try { 395 try {
387 - // 如果为空 默认为0  
388 - if (sd.getTwo_type_order() == null){  
389 - sd.setTwo_type_order("0"); 396 + if(names != null){
  397 + // 如果为空 默认为0
  398 + if (sd.getTwo_type_order() == null){
  399 + sd.setTwo_type_order("0");
  400 + }
  401 + String[] split = names.split(",");
  402 + for (int i = 0; i < split.length; i++){
  403 + SDTWOTYPEEntity sdtwotypeEntity = new SDTWOTYPEEntity();
  404 + sdtwotypeEntity.setTwo_type_name(sd.getTwo_type_name());
  405 + sdtwotypeEntity.setBig_type_id(sd.getBig_type_id());
  406 + sdtwotypeEntity.setCargo_name(split[i]);
  407 + sdtwotypeEntity.setTwo_type_order(sd.getTwo_type_order());
  408 + sdtwotypeService.saves(sdtwotypeEntity);
  409 + }
  410 + model.setStatus(200);
  411 + }else {
  412 + model.setStatus(201);
390 } 413 }
391 - String[] split = names.split(",");  
392 - for (int i = 0; i < split.length; i++){  
393 - SDTWOTYPEEntity sdtwotypeEntity = new SDTWOTYPEEntity();  
394 - sdtwotypeEntity.setTwo_type_name(sd.getTwo_type_name());  
395 - sdtwotypeEntity.setBig_type_id(sd.getBig_type_id());  
396 - sdtwotypeEntity.setCargo_name(split[i]);  
397 - sdtwotypeEntity.setTwo_type_order(sd.getTwo_type_order());  
398 - sdtwotypeService.saves(sdtwotypeEntity); 414 + return model;
  415 + }catch (Exception e){
  416 + e.printStackTrace();
  417 + model.setStatus(500);
  418 + return model;
  419 + }
  420 + }
  421 +
  422 +
  423 + /**
  424 + * 编辑分类
  425 + * @param model
  426 + * @param id
  427 + * @return
  428 + */
  429 + @RequestMapping(value = "/doEdit")
  430 + public String doEdit(Model model, Long id){
  431 +
  432 + // 拿到二级类名字
  433 + SDTWOTYPEEntity one = sdtwotypeService.findOne(id);
  434 +
  435 + List<String> nameAll = sdCargoNameService.selectAll();
  436 + // 查询这个二级类下所有货物品名
  437 + List<String> cargoname = sdtwotypeService.twoCargoName(one.getTwo_type_name());
  438 + model.addAttribute("cargoName", cargoname);
  439 + model.addAttribute("nameAll", nameAll);
  440 + model.addAttribute("one", one);
  441 + return "sdtype/doEdit";
  442 + }
  443 +
  444 +
  445 + /**
  446 + * 编辑货物和二级类关系
  447 + * @param sd
  448 + * @param request
  449 + * @return
  450 + */
  451 + @RequestMapping(value = "/doAdd")
  452 + @ResponseBody
  453 + public ResponseModel doAdd(SDTWOTYPEEntity sd, String names, HttpServletRequest request){
  454 + ResponseModel model = new ResponseModel();
  455 + try {
  456 + if(names != null){
  457 + // 删除所有该二级类下的货物 再添加
  458 + if (sdtwotypeService.cargoNameDelete(sd.getTwo_type_name()) > 0){
  459 + // 如果为空 默认为0
  460 + if (sd.getTwo_type_order() == null){
  461 + sd.setTwo_type_order("0");
  462 + }
  463 + String[] split = names.split(",");
  464 + for (int i = 0; i < split.length; i++){
  465 + System.out.println();
  466 + SDTWOTYPEEntity sdtwotypeEntity = new SDTWOTYPEEntity();
  467 + sdtwotypeEntity.setTwo_type_name(sd.getTwo_type_name());
  468 + sdtwotypeEntity.setBig_type_id(sd.getBig_type_id());
  469 + sdtwotypeEntity.setCargo_name(split[i]);
  470 + sdtwotypeEntity.setTwo_type_order(sd.getTwo_type_order());
  471 + sdtwotypeService.saves(sdtwotypeEntity);
  472 + }
  473 + model.setStatus(200);
  474 + }else {
  475 + model.setStatus(500);
  476 + }
  477 + }else {
  478 + model.setStatus(201);
399 } 479 }
400 - model.setStatus(200);  
401 return model; 480 return model;
402 }catch (Exception e){ 481 }catch (Exception e){
403 e.printStackTrace(); 482 e.printStackTrace();
@@ -30,7 +30,10 @@ public interface SDCargoNameRepository extends PagingAndSortingRepository<SDCarg @@ -30,7 +30,10 @@ public interface SDCargoNameRepository extends PagingAndSortingRepository<SDCarg
30 @Query(value = "delete from SD_CARGO_NAME where sd_waybill = ?1", nativeQuery = true) 30 @Query(value = "delete from SD_CARGO_NAME where sd_waybill = ?1", nativeQuery = true)
31 int deletes(String waybillnomaster); 31 int deletes(String waybillnomaster);
32 32
33 - @Query(value = "select distinct SD_CARGO_NAME from SD_CARGO_NAME where SD_CARGO_NAME not in (select CARGO_NAME from SD_TWO_TYPE)", nativeQuery = true) 33 + @Query(value = "select distinct SD_CARGO_NAME from SD_CARGO_NAME where SD_CARGO_NAME not in (select CARGO_NAME from SD_TWO_TYPE where CARGO_NAME is not null)", nativeQuery = true)
34 List<String> findAlls(); 34 List<String> findAlls();
35 35
  36 + @Query(value = "select distinct SD_CARGO_NAME from SD_CARGO_NAME", nativeQuery = true)
  37 + List<String> selectAll();
  38 +
36 } 39 }
@@ -8,6 +8,8 @@ import org.springframework.data.jpa.repository.Query; @@ -8,6 +8,8 @@ import org.springframework.data.jpa.repository.Query;
8 import org.springframework.data.repository.PagingAndSortingRepository; 8 import org.springframework.data.repository.PagingAndSortingRepository;
9 import org.springframework.transaction.annotation.Transactional; 9 import org.springframework.transaction.annotation.Transactional;
10 10
  11 +import java.util.List;
  12 +
11 /** 13 /**
12 * @Auther: shenhl 14 * @Auther: shenhl
13 * @Date: 2019/6/18 19:15 15 * @Date: 2019/6/18 19:15
@@ -31,5 +33,15 @@ public interface SDTWOTYPERepository extends PagingAndSortingRepository<SDTWOTYP @@ -31,5 +33,15 @@ public interface SDTWOTYPERepository extends PagingAndSortingRepository<SDTWOTYP
31 @Query(value = "update SD_TWO_TYPE set TWO_TYPE_NAME = ?2, BIG_TYPE_ID = ?3, TWO_TYPE_ORDER = ?4 where id = ?1", nativeQuery = true) 33 @Query(value = "update SD_TWO_TYPE set TWO_TYPE_NAME = ?2, BIG_TYPE_ID = ?3, TWO_TYPE_ORDER = ?4 where id = ?1", nativeQuery = true)
32 int tUpdate(Long id, String name, Long bigid, String order); 34 int tUpdate(Long id, String name, Long bigid, String order);
33 35
  36 + @Query(value = "select CARGO_NAME from SD_TWO_TYPE where TWO_TYPE_NAME = ?1", nativeQuery = true)
  37 + List<String> twoCargoName(String twoTypeName);
  38 +
  39 +
  40 + @Transactional
  41 + @Modifying
  42 + @Query(value = "DELETE FROM SD_TWO_TYPE WHERE TWO_TYPE_NAME = ?1", nativeQuery = true)
  43 + int cargoNameDelete(String twoName);
34 44
  45 + @Query(value = "select * from (select stt.*, row_number() over(partition by stt.TWO_TYPE_NAME order by 1) rn from SD_TWO_TYPE stt) stt where stt.rn = 1", nativeQuery = true)
  46 + List<SDTWOTYPEEntity> twoFindAll();
35 } 47 }
@@ -42,4 +42,9 @@ public class SDCargoNameService extends BasicService<SDCargoNameEntity> { @@ -42,4 +42,9 @@ public class SDCargoNameService extends BasicService<SDCargoNameEntity> {
42 return sdCargoNameRepository.findAlls(); 42 return sdCargoNameRepository.findAlls();
43 } 43 }
44 44
  45 + public List<String> selectAll(){
  46 +
  47 + return sdCargoNameRepository.selectAll();
  48 + }
  49 +
45 } 50 }
@@ -71,4 +71,21 @@ public class SDTWOTYPEService extends BasicService<SDTWOTYPEEntity> { @@ -71,4 +71,21 @@ public class SDTWOTYPEService extends BasicService<SDTWOTYPEEntity> {
71 return sdtwotypeRepository.tUpdate(sd.getId(), sd.getTwo_type_name(), sd.getBig_type_id(), sd.getTwo_type_order()); 71 return sdtwotypeRepository.tUpdate(sd.getId(), sd.getTwo_type_name(), sd.getBig_type_id(), sd.getTwo_type_order());
72 } 72 }
73 73
  74 +
  75 + public List<String> twoCargoName(String twoTypeName){
  76 +
  77 + return sdtwotypeRepository.twoCargoName(twoTypeName);
  78 + }
  79 +
  80 + @Transactional
  81 + public int cargoNameDelete(String twoName){
  82 +
  83 + return sdtwotypeRepository.cargoNameDelete(twoName);
  84 + }
  85 +
  86 + public List<SDTWOTYPEEntity> twoFindAll(){
  87 +
  88 + return sdtwotypeRepository.twoFindAll();
  89 + }
  90 +
74 } 91 }
  1 +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  2 +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
  3 +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
  4 +<%
  5 + String path = request.getContextPath();
  6 + String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
  7 +%>
  8 +<!DOCTYPE html>
  9 +<html lang="en">
  10 +<head>
  11 + <meta charset="utf-8">
  12 + <meta name="viewport" content="width=device-width, initial-scale=1">
  13 + <link href="<%=basePath %>resource/css/base.css" rel="stylesheet">
  14 + <link href="<%=basePath %>resource/css/basic_info.css" rel="stylesheet">
  15 + <link rel="stylesheet" href="<%=basePath %>resource/easyui/uimaker/easyui.css">
  16 + <link href="<%=basePath %>resource/css/form.css" rel="stylesheet">
  17 + <script type="text/javascript" src="<%=basePath %>resource/easyui/jquery.min.js"></script>
  18 + <script type="text/javascript" src="<%=basePath %>resource/validate/jquery.validate.js"></script>
  19 + <script type="text/javascript" src="<%=basePath %>resource/validate/validate-extends.js"></script>
  20 + <link rel="stylesheet" href="<%=basePath %>resource/css/form.css">
  21 + <script type="text/javascript" src="<%=basePath %>resource/js/tools.js"></script>
  22 + <!-- validate 验证中英文 -->
  23 + <script type="text/javascript" src="<%=basePath %>resource/validate/jquery.validate-${pageContext.response.locale}.js"></script>
  24 +</head>
  25 +<body>
  26 + <div class="container">
  27 +
  28 + <div class="content">
  29 + <form class="layui-form" id="form">
  30 + <table class="kv-table">
  31 + <tbody>
  32 + <input type="hidden" name="big_type_id" id="big_type_id" value="${one.big_type_id}">
  33 + <input type="hidden" name="two_type_name" id="two_type_name" value="${one.two_type_name}">
  34 + <tr>
  35 + <td class="kv-content">
  36 +
  37 + <c:forEach items="${nameAll}" var="nameAll">
  38 + <li style="list-style : none; weight: 20% ; float:left">
  39 + <input type="checkbox" name="names" id="nams" <c:forEach items="${cargoName}" var="cargoName"> ${nameAll eq cargoName ?"checked":""} </c:forEach> value="${nameAll}" lay-skin="primary">${nameAll}
  40 + </li>
  41 + </c:forEach>
  42 + </td>
  43 + </tr>
  44 + <tr>
  45 + <td colspan="6">
  46 + <div class="opt-buttons" style="padding-top:20px;">
  47 + <button type="submit" class="easyui-linkbutton l-btn l-btn-small l-btn-selected " data-options="selected:true">
  48 + <span class="l-btn-left"><span class="l-btn-text"><spring:message code="opt.save" /></span></span>
  49 + </button>
  50 + </div>
  51 + </td>
  52 + </tr>
  53 + </tbody>
  54 + </table>
  55 + </form>
  56 + </div>
  57 + </div>
  58 + <script type="text/javascript" src="<%=basePath %>resource/layer-v3.0.3/layer/layer.js"></script>
  59 + <script src="<%=basePath %>resource/easyui/jquery.easyui.min.js"></script>
  60 + <script src="<%=basePath %>resource/js/tools.js"></script>
  61 + <script type="text/javascript">
  62 + $("#form").validate({
  63 + submitHandler:function(form){
  64 + submit();
  65 + }
  66 + });
  67 +
  68 + var selectFals = false;
  69 + function submit(){
  70 + // if (selectFals == true){
  71 + var data = $("#form").serialize();
  72 + $.post("<%=basePath%>type/doAdd",data,function(data){
  73 + if(data.status==200){
  74 + layer.confirm("<spring:message code="opt.savesuccess" />!",{btn:['<spring:message code="opt.confirm" />','<spring:message code="opt.cancel" />']},function(){
  75 + var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引
  76 + parent.layer.close(index);
  77 + window.parent.location.reload();
  78 + })
  79 + }else if(data.status == 201){
  80 + alert("请选择一项")
  81 + }else{
  82 + alert("网络异常");
  83 + }
  84 + })
  85 +
  86 + }
  87 +
  88 + $(document).ready(function () {
  89 + var form = layui.form;
  90 + form.render();
  91 + })
  92 + </script>
  93 +</body>
  94 +</html>
@@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
30 <body> 30 <body>
31 <div class="container"> 31 <div class="container">
32 <div data-options="closable:true"> 32 <div data-options="closable:true">
33 - <table id="dg" style="width:100%;" title="货主信息管理" 33 + <table id="dg" style="width:100%;" title="二级类管理"
34 data-options=" 34 data-options="
35 rownumbers:true, 35 rownumbers:true,
36 singleSelect:false, 36 singleSelect:false,
@@ -46,7 +46,7 @@ @@ -46,7 +46,7 @@
46 <th field="." formatter="editFormat"><spring:message code="opt.edit" /></th> 46 <th field="." formatter="editFormat"><spring:message code="opt.edit" /></th>
47 <th field="bigName">一级类名称</th> 47 <th field="bigName">一级类名称</th>
48 <th field="two_type_name">二级类名称</th> 48 <th field="two_type_name">二级类名称</th>
49 - <th field="cargo_name">货物品名</th> 49 + <%--<th field="cargo_name">货物品名</th>--%>
50 <th field=".." formatter="operatorFormat">操作</th> 50 <th field=".." formatter="operatorFormat">操作</th>
51 </tr> 51 </tr>
52 </thead> 52 </thead>
@@ -115,7 +115,9 @@ @@ -115,7 +115,9 @@
115 } 115 }
116 116
117 function operatorFormat(val, row, index) { 117 function operatorFormat(val, row, index) {
118 - var html = "<a href='javascript:void(0)' onclick='doSaves("+row.id+")' style='text-decoration:none;color:blue;'>设置分类</a>"; 118 + var html = "<a href='javascript:void(0)' onclick='doSaves("+row.id+")' style='text-decoration:none;color:blue;'>设置分类</a>"+
  119 + "&nbsp;&nbsp;&nbsp;&nbsp;<a href='javascript:void(0)' onclick='doEdit("+row.id+")' style='text-decoration:none;color:blue;'>编辑分类</a>";
  120 +
119 return html; 121 return html;
120 } 122 }
121 123
@@ -167,6 +169,17 @@ @@ -167,6 +169,17 @@
167 }); 169 });
168 } 170 }
169 171
  172 + function doEdit(id) {
  173 + // iframe层
  174 + layer.open({
  175 + type : 2,
  176 + title : '编辑分类',
  177 + maxmin : true,
  178 + shadeClose : false, // 点击遮罩关闭层
  179 + area : [ '1000px', '500px' ],
  180 + content : '<%=basePath %>type/doEdit?id='+id
  181 + });
  182 + }
170 183
171 $("#manifnum").keyup(function(){ 184 $("#manifnum").keyup(function(){
172 var leng = $("#manifnum").val().length; 185 var leng = $("#manifnum").val().length;
@@ -35,11 +35,13 @@ @@ -35,11 +35,13 @@
35 <%--<td class="kv-label">--%> 35 <%--<td class="kv-label">--%>
36 <%--货物品名<span class="required_span"></span>--%> 36 <%--货物品名<span class="required_span"></span>--%>
37 <%--</td>--%> 37 <%--</td>--%>
38 - <th class="kv-content"> 38 + <td class="kv-content">
39 <c:forEach items="${cargo}" var="cargo"> 39 <c:forEach items="${cargo}" var="cargo">
40 - <input type="checkbox" name="names" id="nams" title="${cargo}" value="${cargo}" lay-skin="primary">${cargo} 40 + <li style="list-style : none; weight: 20% ; float:left">
  41 + <input type="checkbox" name="names" id="nams" title="${cargo}" value="${cargo}" lay-skin="primary">${cargo}
  42 + </li>
41 </c:forEach> 43 </c:forEach>
42 - </th> 44 + </td>
43 </tr> 45 </tr>
44 <tr> 46 <tr>
45 <td colspan="6"> 47 <td colspan="6">
@@ -76,8 +78,10 @@ @@ -76,8 +78,10 @@
76 parent.layer.close(index); 78 parent.layer.close(index);
77 window.parent.location.reload(); 79 window.parent.location.reload();
78 }) 80 })
79 - }else {  
80 - alert("网络异常") 81 + }else if(data.status == 201){
  82 + alert("请选择一项")
  83 + }else{
  84 + alert("网络异常");
81 } 85 }
82 }) 86 })
83 87
  1 +
  2 +jQuery.extend({
  3 + createUploadIframe: function(id, uri)
  4 + {
  5 + //create frame
  6 + var frameId = 'jUploadFrame' + id;
  7 +
  8 + if(window.ActiveXObject) {
  9 + var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
  10 + if(typeof uri== 'boolean'){
  11 + io.src = 'javascript:false';
  12 + }
  13 + else if(typeof uri== 'string'){
  14 + io.src = uri;
  15 + }
  16 + }
  17 + else {
  18 + var io = document.createElement('iframe');
  19 + io.id = frameId;
  20 + io.name = frameId;
  21 + }
  22 + io.style.position = 'absolute';
  23 + io.style.top = '-1000px';
  24 + io.style.left = '-1000px';
  25 +
  26 + document.body.appendChild(io);
  27 +
  28 + return io
  29 + },
  30 + createUploadForm: function(id, fileElementId)
  31 + {
  32 + //create form
  33 + var formId = 'jUploadForm' + id;
  34 + var fileId = 'jUploadFile' + id;
  35 + var form = $('<form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');
  36 + var oldElement = $('#' + fileElementId);
  37 + var newElement = $(oldElement).clone();
  38 + $(oldElement).attr('id', fileId);
  39 + $(oldElement).before(newElement);
  40 + $(oldElement).appendTo(form);
  41 + //set attributes
  42 + $(form).css('position', 'absolute');
  43 + $(form).css('top', '-1200px');
  44 + $(form).css('left', '-1200px');
  45 + $(form).appendTo('body');
  46 + return form;
  47 + },
  48 + addOtherRequestsToForm: function(form,data)
  49 + {
  50 + // add extra parameter
  51 + var originalElement = $('<input type="hidden" name="" value="">');
  52 + for (var key in data) {
  53 + name = key;
  54 + value = data[key];
  55 + var cloneElement = originalElement.clone();
  56 + cloneElement.attr({'name':name,'value':value});
  57 + $(cloneElement).appendTo(form);
  58 + }
  59 + return form;
  60 + },
  61 +
  62 + ajaxFileUpload: function(s) {
  63 + // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
  64 + s = jQuery.extend({}, jQuery.ajaxSettings, s);
  65 + var id = new Date().getTime()
  66 + var form = jQuery.createUploadForm(id, s.fileElementId);
  67 + if ( s.data ) form = jQuery.addOtherRequestsToForm(form,s.data);
  68 + var io = jQuery.createUploadIframe(id, s.secureuri);
  69 + var frameId = 'jUploadFrame' + id;
  70 + var formId = 'jUploadForm' + id;
  71 + // Watch for a new set of requests
  72 + if ( s.global && ! jQuery.active++ )
  73 + {
  74 + jQuery.event.trigger( "ajaxStart" );
  75 + }
  76 + var requestDone = false;
  77 + // Create the request object
  78 + var xml = {}
  79 + if ( s.global )
  80 + jQuery.event.trigger("ajaxSend", [xml, s]);
  81 + // Wait for a response to come back
  82 + var uploadCallback = function(isTimeout)
  83 + {
  84 + var io = document.getElementById(frameId);
  85 + try
  86 + {
  87 + if(io.contentWindow)
  88 + {
  89 + xml.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null;
  90 + xml.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;
  91 +
  92 + }else if(io.contentDocument)
  93 + {
  94 + xml.responseText = io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:null;
  95 + xml.responseXML = io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocument:io.contentDocument.document;
  96 + }
  97 + }catch(e)
  98 + {
  99 + jQuery.handleError(s, xml, null, e);
  100 + }
  101 + if ( xml || isTimeout == "timeout")
  102 + {
  103 + requestDone = true;
  104 + var status;
  105 + try {
  106 + status = isTimeout != "timeout" ? "success" : "error";
  107 + // Make sure that the request was successful or notmodified
  108 + if ( status != "error" )
  109 + {
  110 + // process the data (runs the xml through httpData regardless of callback)
  111 + var data = jQuery.uploadHttpData( xml, s.dataType );
  112 + // If a local callback was specified, fire it and pass it the data
  113 + if ( s.success )
  114 + s.success( data, status );
  115 +
  116 + // Fire the global callback
  117 + if( s.global )
  118 + jQuery.event.trigger( "ajaxSuccess", [xml, s] );
  119 + } else
  120 + jQuery.handleError(s, xml, status);
  121 + } catch(e)
  122 + {
  123 + status = "error";
  124 + jQuery.handleError(s, xml, status, e);
  125 + }
  126 +
  127 + // The request was completed
  128 + if( s.global )
  129 + jQuery.event.trigger( "ajaxComplete", [xml, s] );
  130 +
  131 + // Handle the global AJAX counter
  132 + if ( s.global && ! --jQuery.active )
  133 + jQuery.event.trigger( "ajaxStop" );
  134 +
  135 + // Process result
  136 + if ( s.complete )
  137 + s.complete(xml, status);
  138 +
  139 + jQuery(io).unbind()
  140 +
  141 + setTimeout(function()
  142 + { try
  143 + {
  144 + $(io).remove();
  145 + $(form).remove();
  146 +
  147 + } catch(e)
  148 + {
  149 + jQuery.handleError(s, xml, null, e);
  150 + }
  151 +
  152 + }, 100)
  153 +
  154 + xml = null
  155 +
  156 + }
  157 + }
  158 + // Timeout checker
  159 + if ( s.timeout > 0 )
  160 + {
  161 + setTimeout(function(){
  162 + // Check to see if the request is still happening
  163 + if( !requestDone ) uploadCallback( "timeout" );
  164 + }, s.timeout);
  165 + }
  166 + try
  167 + {
  168 + // var io = $('#' + frameId);
  169 + var form = $('#' + formId);
  170 + $(form).attr('action', s.url);
  171 + $(form).attr('method', 'POST');
  172 + $(form).attr('target', frameId);
  173 + if(form.encoding)
  174 + {
  175 + form.encoding = 'multipart/form-data';
  176 + }
  177 + else
  178 + {
  179 + form.enctype = 'multipart/form-data';
  180 + }
  181 + $(form).submit();
  182 +
  183 + } catch(e)
  184 + {
  185 + jQuery.handleError(s, xml, null, e);
  186 + }
  187 + if(window.attachEvent){
  188 + document.getElementById(frameId).attachEvent('onload', uploadCallback);
  189 + }
  190 + else{
  191 + document.getElementById(frameId).addEventListener('load', uploadCallback, false);
  192 + }
  193 + return {abort: function () {}};
  194 +
  195 + },
  196 +
  197 + uploadHttpData: function( r, type ) {
  198 + var data = !type;
  199 + data = type == "xml" || data ? r.responseXML : r.responseText;
  200 + // If the type is "script", eval it in global context
  201 + if ( type == "script" )
  202 + jQuery.globalEval( data );
  203 + // Get the JavaScript object, if JSON is used.
  204 + if ( type == "json" )
  205 + {
  206 + // If you add mimetype in your response,
  207 + // you have to delete the '<pre></pre>' tag.
  208 + // The pre tag in Chrome has attribute, so have to use regex to remove
  209 + var data = r.responseText;
  210 + var rx = new RegExp("<pre.*?>(.*?)</pre>","i");
  211 + var am = rx.exec(data);
  212 + //this is the desired data extracted
  213 + var data = (am) ? am[1] : ""; //the only submatch or empty
  214 + eval( "data = " + data );
  215 + }
  216 + // evaluate scripts within html
  217 + if ( type == "html" )
  218 + jQuery("<div>").html(data).evalScripts();
  219 + //alert($('param', data).each(function(){alert($(this).attr('value'));}));
  220 + return data;
  221 + },
  222 +
  223 +
  224 + handleError: function( s, xhr, status, e ){
  225 + // If a local callback was specified, fire it
  226 + if ( s.error ) {
  227 + s.error.call( s.context || s, xhr, status, e );
  228 + }
  229 +
  230 + // Fire the global callback
  231 + if ( s.global ) {
  232 + (s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
  233 + }
  234 + }
  235 +
  236 +})
  237 +
  1 +/*!
  2 + * jQuery Form Plugin
  3 + * version: 3.51.0-2014.06.20
  4 + * Requires jQuery v1.5 or later
  5 + * Copyright (c) 2014 M. Alsup
  6 + * Examples and documentation at: http://malsup.com/jquery/form/
  7 + * Project repository: https://github.com/malsup/form
  8 + * Dual licensed under the MIT and GPL licenses.
  9 + * https://github.com/malsup/form#copyright-and-license
  10 + */
  11 +/*global ActiveXObject */
  12 +
  13 +// AMD support
  14 +(function (factory) {
  15 + "use strict";
  16 + if (typeof define === 'function' && define.amd) {
  17 + // using AMD; register as anon module
  18 + define(['jquery'], factory);
  19 + } else {
  20 + // no AMD; invoke directly
  21 + factory( (typeof(jQuery) != 'undefined') ? jQuery : window.Zepto );
  22 + }
  23 +}
  24 +
  25 +(function($) {
  26 +"use strict";
  27 +
  28 +/*
  29 + Usage Note:
  30 + -----------
  31 + Do not use both ajaxSubmit and ajaxForm on the same form. These
  32 + functions are mutually exclusive. Use ajaxSubmit if you want
  33 + to bind your own submit handler to the form. For example,
  34 +
  35 + $(document).ready(function() {
  36 + $('#myForm').on('submit', function(e) {
  37 + e.preventDefault(); // <-- important
  38 + $(this).ajaxSubmit({
  39 + target: '#output'
  40 + });
  41 + });
  42 + });
  43 +
  44 + Use ajaxForm when you want the plugin to manage all the event binding
  45 + for you. For example,
  46 +
  47 + $(document).ready(function() {
  48 + $('#myForm').ajaxForm({
  49 + target: '#output'
  50 + });
  51 + });
  52 +
  53 + You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
  54 + form does not have to exist when you invoke ajaxForm:
  55 +
  56 + $('#myForm').ajaxForm({
  57 + delegation: true,
  58 + target: '#output'
  59 + });
  60 +
  61 + When using ajaxForm, the ajaxSubmit function will be invoked for you
  62 + at the appropriate time.
  63 +*/
  64 +
  65 +/**
  66 + * Feature detection
  67 + */
  68 +var feature = {};
  69 +feature.fileapi = $("<input type='file'/>").get(0).files !== undefined;
  70 +feature.formdata = window.FormData !== undefined;
  71 +
  72 +var hasProp = !!$.fn.prop;
  73 +
  74 +// attr2 uses prop when it can but checks the return type for
  75 +// an expected string. this accounts for the case where a form
  76 +// contains inputs with names like "action" or "method"; in those
  77 +// cases "prop" returns the element
  78 +$.fn.attr2 = function() {
  79 + if ( ! hasProp ) {
  80 + return this.attr.apply(this, arguments);
  81 + }
  82 + var val = this.prop.apply(this, arguments);
  83 + if ( ( val && val.jquery ) || typeof val === 'string' ) {
  84 + return val;
  85 + }
  86 + return this.attr.apply(this, arguments);
  87 +};
  88 +
  89 +/**
  90 + * ajaxSubmit() provides a mechanism for immediately submitting
  91 + * an HTML form using AJAX.
  92 + */
  93 +$.fn.ajaxSubmit = function(options) {
  94 + /*jshint scripturl:true */
  95 +
  96 + // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
  97 + if (!this.length) {
  98 + log('ajaxSubmit: skipping submit process - no element selected');
  99 + return this;
  100 + }
  101 +
  102 + var method, action, url, $form = this;
  103 +
  104 + if (typeof options == 'function') {
  105 + options = { success: options };
  106 + }
  107 + else if ( options === undefined ) {
  108 + options = {};
  109 + }
  110 +
  111 + method = options.type || this.attr2('method');
  112 + action = options.url || this.attr2('action');
  113 +
  114 + url = (typeof action === 'string') ? $.trim(action) : '';
  115 + url = url || window.location.href || '';
  116 + if (url) {
  117 + // clean url (don't include hash vaue)
  118 + url = (url.match(/^([^#]+)/)||[])[1];
  119 + }
  120 +
  121 + options = $.extend(true, {
  122 + url: url,
  123 + success: $.ajaxSettings.success,
  124 + type: method || $.ajaxSettings.type,
  125 + iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
  126 + }, options);
  127 +
  128 + // hook for manipulating the form data before it is extracted;
  129 + // convenient for use with rich editors like tinyMCE or FCKEditor
  130 + var veto = {};
  131 + this.trigger('form-pre-serialize', [this, options, veto]);
  132 + if (veto.veto) {
  133 + log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
  134 + return this;
  135 + }
  136 +
  137 + // provide opportunity to alter form data before it is serialized
  138 + if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
  139 + log('ajaxSubmit: submit aborted via beforeSerialize callback');
  140 + return this;
  141 + }
  142 +
  143 + var traditional = options.traditional;
  144 + if ( traditional === undefined ) {
  145 + traditional = $.ajaxSettings.traditional;
  146 + }
  147 +
  148 + var elements = [];
  149 + var qx, a = this.formToArray(options.semantic, elements);
  150 + if (options.data) {
  151 + options.extraData = options.data;
  152 + qx = $.param(options.data, traditional);
  153 + }
  154 +
  155 + // give pre-submit callback an opportunity to abort the submit
  156 + if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
  157 + log('ajaxSubmit: submit aborted via beforeSubmit callback');
  158 + return this;
  159 + }
  160 +
  161 + // fire vetoable 'validate' event
  162 + this.trigger('form-submit-validate', [a, this, options, veto]);
  163 + if (veto.veto) {
  164 + log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
  165 + return this;
  166 + }
  167 +
  168 + var q = $.param(a, traditional);
  169 + if (qx) {
  170 + q = ( q ? (q + '&' + qx) : qx );
  171 + }
  172 + if (options.type.toUpperCase() == 'GET') {
  173 + options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
  174 + options.data = null; // data is null for 'get'
  175 + }
  176 + else {
  177 + options.data = q; // data is the query string for 'post'
  178 + }
  179 +
  180 + var callbacks = [];
  181 + if (options.resetForm) {
  182 + callbacks.push(function() { $form.resetForm(); });
  183 + }
  184 + if (options.clearForm) {
  185 + callbacks.push(function() { $form.clearForm(options.includeHidden); });
  186 + }
  187 +
  188 + // perform a load on the target only if dataType is not provided
  189 + if (!options.dataType && options.target) {
  190 + var oldSuccess = options.success || function(){};
  191 + callbacks.push(function(data) {
  192 + var fn = options.replaceTarget ? 'replaceWith' : 'html';
  193 + $(options.target)[fn](data).each(oldSuccess, arguments);
  194 + });
  195 + }
  196 + else if (options.success) {
  197 + callbacks.push(options.success);
  198 + }
  199 +
  200 + options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
  201 + var context = options.context || this ; // jQuery 1.4+ supports scope context
  202 + for (var i=0, max=callbacks.length; i < max; i++) {
  203 + callbacks[i].apply(context, [data, status, xhr || $form, $form]);
  204 + }
  205 + };
  206 +
  207 + if (options.error) {
  208 + var oldError = options.error;
  209 + options.error = function(xhr, status, error) {
  210 + var context = options.context || this;
  211 + oldError.apply(context, [xhr, status, error, $form]);
  212 + };
  213 + }
  214 +
  215 + if (options.complete) {
  216 + var oldComplete = options.complete;
  217 + options.complete = function(xhr, status) {
  218 + var context = options.context || this;
  219 + oldComplete.apply(context, [xhr, status, $form]);
  220 + };
  221 + }
  222 +
  223 + // are there files to upload?
  224 +
  225 + // [value] (issue #113), also see comment:
  226 + // https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219
  227 + var fileInputs = $('input[type=file]:enabled', this).filter(function() { return $(this).val() !== ''; });
  228 +
  229 + var hasFileInputs = fileInputs.length > 0;
  230 + var mp = 'multipart/form-data';
  231 + var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
  232 +
  233 + var fileAPI = feature.fileapi && feature.formdata;
  234 + log("fileAPI :" + fileAPI);
  235 + var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
  236 +
  237 + var jqxhr;
  238 +
  239 + // options.iframe allows user to force iframe mode
  240 + // 06-NOV-09: now defaulting to iframe mode if file input is detected
  241 + if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
  242 + // hack to fix Safari hang (thanks to Tim Molendijk for this)
  243 + // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
  244 + if (options.closeKeepAlive) {
  245 + $.get(options.closeKeepAlive, function() {
  246 + jqxhr = fileUploadIframe(a);
  247 + });
  248 + }
  249 + else {
  250 + jqxhr = fileUploadIframe(a);
  251 + }
  252 + }
  253 + else if ((hasFileInputs || multipart) && fileAPI) {
  254 + jqxhr = fileUploadXhr(a);
  255 + }
  256 + else {
  257 + jqxhr = $.ajax(options);
  258 + }
  259 +
  260 + $form.removeData('jqxhr').data('jqxhr', jqxhr);
  261 +
  262 + // clear element array
  263 + for (var k=0; k < elements.length; k++) {
  264 + elements[k] = null;
  265 + }
  266 +
  267 + // fire 'notify' event
  268 + this.trigger('form-submit-notify', [this, options]);
  269 + return this;
  270 +
  271 + // utility fn for deep serialization
  272 + function deepSerialize(extraData){
  273 + var serialized = $.param(extraData, options.traditional).split('&');
  274 + var len = serialized.length;
  275 + var result = [];
  276 + var i, part;
  277 + for (i=0; i < len; i++) {
  278 + // #252; undo param space replacement
  279 + serialized[i] = serialized[i].replace(/\+/g,' ');
  280 + part = serialized[i].split('=');
  281 + // #278; use array instead of object storage, favoring array serializations
  282 + result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);
  283 + }
  284 + return result;
  285 + }
  286 +
  287 + // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
  288 + function fileUploadXhr(a) {
  289 + var formdata = new FormData();
  290 +
  291 + for (var i=0; i < a.length; i++) {
  292 + formdata.append(a[i].name, a[i].value);
  293 + }
  294 +
  295 + if (options.extraData) {
  296 + var serializedData = deepSerialize(options.extraData);
  297 + for (i=0; i < serializedData.length; i++) {
  298 + if (serializedData[i]) {
  299 + formdata.append(serializedData[i][0], serializedData[i][1]);
  300 + }
  301 + }
  302 + }
  303 +
  304 + options.data = null;
  305 +
  306 + var s = $.extend(true, {}, $.ajaxSettings, options, {
  307 + contentType: false,
  308 + processData: false,
  309 + cache: false,
  310 + type: method || 'POST'
  311 + });
  312 +
  313 + if (options.uploadProgress) {
  314 + // workaround because jqXHR does not expose upload property
  315 + s.xhr = function() {
  316 + var xhr = $.ajaxSettings.xhr();
  317 + if (xhr.upload) {
  318 + xhr.upload.addEventListener('progress', function(event) {
  319 + var percent = 0;
  320 + var position = event.loaded || event.position; /*event.position is deprecated*/
  321 + var total = event.total;
  322 + if (event.lengthComputable) {
  323 + percent = Math.ceil(position / total * 100);
  324 + }
  325 + options.uploadProgress(event, position, total, percent);
  326 + }, false);
  327 + }
  328 + return xhr;
  329 + };
  330 + }
  331 +
  332 + s.data = null;
  333 + var beforeSend = s.beforeSend;
  334 + s.beforeSend = function(xhr, o) {
  335 + //Send FormData() provided by user
  336 + if (options.formData) {
  337 + o.data = options.formData;
  338 + }
  339 + else {
  340 + o.data = formdata;
  341 + }
  342 + if(beforeSend) {
  343 + beforeSend.call(this, xhr, o);
  344 + }
  345 + };
  346 + return $.ajax(s);
  347 + }
  348 +
  349 + // private function for handling file uploads (hat tip to YAHOO!)
  350 + function fileUploadIframe(a) {
  351 + var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
  352 + var deferred = $.Deferred();
  353 +
  354 + // #341
  355 + deferred.abort = function(status) {
  356 + xhr.abort(status);
  357 + };
  358 +
  359 + if (a) {
  360 + // ensure that every serialized input is still enabled
  361 + for (i=0; i < elements.length; i++) {
  362 + el = $(elements[i]);
  363 + if ( hasProp ) {
  364 + el.prop('disabled', false);
  365 + }
  366 + else {
  367 + el.removeAttr('disabled');
  368 + }
  369 + }
  370 + }
  371 +
  372 + s = $.extend(true, {}, $.ajaxSettings, options);
  373 + s.context = s.context || s;
  374 + id = 'jqFormIO' + (new Date().getTime());
  375 + if (s.iframeTarget) {
  376 + $io = $(s.iframeTarget);
  377 + n = $io.attr2('name');
  378 + if (!n) {
  379 + $io.attr2('name', id);
  380 + }
  381 + else {
  382 + id = n;
  383 + }
  384 + }
  385 + else {
  386 + $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
  387 + $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
  388 + }
  389 + io = $io[0];
  390 +
  391 +
  392 + xhr = { // mock object
  393 + aborted: 0,
  394 + responseText: null,
  395 + responseXML: null,
  396 + status: 0,
  397 + statusText: 'n/a',
  398 + getAllResponseHeaders: function() {},
  399 + getResponseHeader: function() {},
  400 + setRequestHeader: function() {},
  401 + abort: function(status) {
  402 + var e = (status === 'timeout' ? 'timeout' : 'aborted');
  403 + log('aborting upload... ' + e);
  404 + this.aborted = 1;
  405 +
  406 + try { // #214, #257
  407 + if (io.contentWindow.document.execCommand) {
  408 + io.contentWindow.document.execCommand('Stop');
  409 + }
  410 + }
  411 + catch(ignore) {}
  412 +
  413 + $io.attr('src', s.iframeSrc); // abort op in progress
  414 + xhr.error = e;
  415 + if (s.error) {
  416 + s.error.call(s.context, xhr, e, status);
  417 + }
  418 + if (g) {
  419 + $.event.trigger("ajaxError", [xhr, s, e]);
  420 + }
  421 + if (s.complete) {
  422 + s.complete.call(s.context, xhr, e);
  423 + }
  424 + }
  425 + };
  426 +
  427 + g = s.global;
  428 + // trigger ajax global events so that activity/block indicators work like normal
  429 + if (g && 0 === $.active++) {
  430 + $.event.trigger("ajaxStart");
  431 + }
  432 + if (g) {
  433 + $.event.trigger("ajaxSend", [xhr, s]);
  434 + }
  435 +
  436 + if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
  437 + if (s.global) {
  438 + $.active--;
  439 + }
  440 + deferred.reject();
  441 + return deferred;
  442 + }
  443 + if (xhr.aborted) {
  444 + deferred.reject();
  445 + return deferred;
  446 + }
  447 +
  448 + // add submitting element to data if we know it
  449 + sub = form.clk;
  450 + if (sub) {
  451 + n = sub.name;
  452 + if (n && !sub.disabled) {
  453 + s.extraData = s.extraData || {};
  454 + s.extraData[n] = sub.value;
  455 + if (sub.type == "image") {
  456 + s.extraData[n+'.x'] = form.clk_x;
  457 + s.extraData[n+'.y'] = form.clk_y;
  458 + }
  459 + }
  460 + }
  461 +
  462 + var CLIENT_TIMEOUT_ABORT = 1;
  463 + var SERVER_ABORT = 2;
  464 +
  465 + function getDoc(frame) {
  466 + /* it looks like contentWindow or contentDocument do not
  467 + * carry the protocol property in ie8, when running under ssl
  468 + * frame.document is the only valid response document, since
  469 + * the protocol is know but not on the other two objects. strange?
  470 + * "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy
  471 + */
  472 +
  473 + var doc = null;
  474 +
  475 + // IE8 cascading access check
  476 + try {
  477 + if (frame.contentWindow) {
  478 + doc = frame.contentWindow.document;
  479 + }
  480 + } catch(err) {
  481 + // IE8 access denied under ssl & missing protocol
  482 + log('cannot get iframe.contentWindow document: ' + err);
  483 + }
  484 +
  485 + if (doc) { // successful getting content
  486 + return doc;
  487 + }
  488 +
  489 + try { // simply checking may throw in ie8 under ssl or mismatched protocol
  490 + doc = frame.contentDocument ? frame.contentDocument : frame.document;
  491 + } catch(err) {
  492 + // last attempt
  493 + log('cannot get iframe.contentDocument: ' + err);
  494 + doc = frame.document;
  495 + }
  496 + return doc;
  497 + }
  498 +
  499 + // Rails CSRF hack (thanks to Yvan Barthelemy)
  500 + var csrf_token = $('meta[name=csrf-token]').attr('content');
  501 + var csrf_param = $('meta[name=csrf-param]').attr('content');
  502 + if (csrf_param && csrf_token) {
  503 + s.extraData = s.extraData || {};
  504 + s.extraData[csrf_param] = csrf_token;
  505 + }
  506 +
  507 + // take a breath so that pending repaints get some cpu time before the upload starts
  508 + function doSubmit() {
  509 + // make sure form attrs are set
  510 + var t = $form.attr2('target'),
  511 + a = $form.attr2('action'),
  512 + mp = 'multipart/form-data',
  513 + et = $form.attr('enctype') || $form.attr('encoding') || mp;
  514 +
  515 + // update form attrs in IE friendly way
  516 + form.setAttribute('target',id);
  517 + if (!method || /post/i.test(method) ) {
  518 + form.setAttribute('method', 'POST');
  519 + }
  520 + if (a != s.url) {
  521 + form.setAttribute('action', s.url);
  522 + }
  523 +
  524 + // ie borks in some cases when setting encoding
  525 + if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
  526 + $form.attr({
  527 + encoding: 'multipart/form-data',
  528 + enctype: 'multipart/form-data'
  529 + });
  530 + }
  531 +
  532 + // support timout
  533 + if (s.timeout) {
  534 + timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
  535 + }
  536 +
  537 + // look for server aborts
  538 + function checkState() {
  539 + try {
  540 + var state = getDoc(io).readyState;
  541 + log('state = ' + state);
  542 + if (state && state.toLowerCase() == 'uninitialized') {
  543 + setTimeout(checkState,50);
  544 + }
  545 + }
  546 + catch(e) {
  547 + log('Server abort: ' , e, ' (', e.name, ')');
  548 + cb(SERVER_ABORT);
  549 + if (timeoutHandle) {
  550 + clearTimeout(timeoutHandle);
  551 + }
  552 + timeoutHandle = undefined;
  553 + }
  554 + }
  555 +
  556 + // add "extra" data to form if provided in options
  557 + var extraInputs = [];
  558 + try {
  559 + if (s.extraData) {
  560 + for (var n in s.extraData) {
  561 + if (s.extraData.hasOwnProperty(n)) {
  562 + // if using the $.param format that allows for multiple values with the same name
  563 + if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
  564 + extraInputs.push(
  565 + $('<input type="hidden" name="'+s.extraData[n].name+'">').val(s.extraData[n].value)
  566 + .appendTo(form)[0]);
  567 + } else {
  568 + extraInputs.push(
  569 + $('<input type="hidden" name="'+n+'">').val(s.extraData[n])
  570 + .appendTo(form)[0]);
  571 + }
  572 + }
  573 + }
  574 + }
  575 +
  576 + if (!s.iframeTarget) {
  577 + // add iframe to doc and submit the form
  578 + $io.appendTo('body');
  579 + }
  580 + if (io.attachEvent) {
  581 + io.attachEvent('onload', cb);
  582 + }
  583 + else {
  584 + io.addEventListener('load', cb, false);
  585 + }
  586 + setTimeout(checkState,15);
  587 +
  588 + try {
  589 + form.submit();
  590 + } catch(err) {
  591 + // just in case form has element with name/id of 'submit'
  592 + var submitFn = document.createElement('form').submit;
  593 + submitFn.apply(form);
  594 + }
  595 + }
  596 + finally {
  597 + // reset attrs and remove "extra" input elements
  598 + form.setAttribute('action',a);
  599 + form.setAttribute('enctype', et); // #380
  600 + if(t) {
  601 + form.setAttribute('target', t);
  602 + } else {
  603 + $form.removeAttr('target');
  604 + }
  605 + $(extraInputs).remove();
  606 + }
  607 + }
  608 +
  609 + if (s.forceSync) {
  610 + doSubmit();
  611 + }
  612 + else {
  613 + setTimeout(doSubmit, 10); // this lets dom updates render
  614 + }
  615 +
  616 + var data, doc, domCheckCount = 50, callbackProcessed;
  617 +
  618 + function cb(e) {
  619 + if (xhr.aborted || callbackProcessed) {
  620 + return;
  621 + }
  622 +
  623 + doc = getDoc(io);
  624 + if(!doc) {
  625 + log('cannot access response document');
  626 + e = SERVER_ABORT;
  627 + }
  628 + if (e === CLIENT_TIMEOUT_ABORT && xhr) {
  629 + xhr.abort('timeout');
  630 + deferred.reject(xhr, 'timeout');
  631 + return;
  632 + }
  633 + else if (e == SERVER_ABORT && xhr) {
  634 + xhr.abort('server abort');
  635 + deferred.reject(xhr, 'error', 'server abort');
  636 + return;
  637 + }
  638 +
  639 + if (!doc || doc.location.href == s.iframeSrc) {
  640 + // response not received yet
  641 + if (!timedOut) {
  642 + return;
  643 + }
  644 + }
  645 + if (io.detachEvent) {
  646 + io.detachEvent('onload', cb);
  647 + }
  648 + else {
  649 + io.removeEventListener('load', cb, false);
  650 + }
  651 +
  652 + var status = 'success', errMsg;
  653 + try {
  654 + if (timedOut) {
  655 + throw 'timeout';
  656 + }
  657 +
  658 + var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
  659 + log('isXml='+isXml);
  660 + if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
  661 + if (--domCheckCount) {
  662 + // in some browsers (Opera) the iframe DOM is not always traversable when
  663 + // the onload callback fires, so we loop a bit to accommodate
  664 + log('requeing onLoad callback, DOM not available');
  665 + setTimeout(cb, 250);
  666 + return;
  667 + }
  668 + // let this fall through because server response could be an empty document
  669 + //log('Could not access iframe DOM after mutiple tries.');
  670 + //throw 'DOMException: not available';
  671 + }
  672 +
  673 + //log('response detected');
  674 + var docRoot = doc.body ? doc.body : doc.documentElement;
  675 + xhr.responseText = docRoot ? docRoot.innerHTML : null;
  676 + xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
  677 + if (isXml) {
  678 + s.dataType = 'xml';
  679 + }
  680 + xhr.getResponseHeader = function(header){
  681 + var headers = {'content-type': s.dataType};
  682 + return headers[header.toLowerCase()];
  683 + };
  684 + // support for XHR 'status' & 'statusText' emulation :
  685 + if (docRoot) {
  686 + xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
  687 + xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
  688 + }
  689 +
  690 + var dt = (s.dataType || '').toLowerCase();
  691 + var scr = /(json|script|text)/.test(dt);
  692 + if (scr || s.textarea) {
  693 + // see if user embedded response in textarea
  694 + var ta = doc.getElementsByTagName('textarea')[0];
  695 + if (ta) {
  696 + xhr.responseText = ta.value;
  697 + // support for XHR 'status' & 'statusText' emulation :
  698 + xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
  699 + xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
  700 + }
  701 + else if (scr) {
  702 + // account for browsers injecting pre around json response
  703 + var pre = doc.getElementsByTagName('pre')[0];
  704 + var b = doc.getElementsByTagName('body')[0];
  705 + if (pre) {
  706 + xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
  707 + }
  708 + else if (b) {
  709 + xhr.responseText = b.textContent ? b.textContent : b.innerText;
  710 + }
  711 + }
  712 + }
  713 + else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
  714 + xhr.responseXML = toXml(xhr.responseText);
  715 + }
  716 +
  717 + try {
  718 + data = httpData(xhr, dt, s);
  719 + }
  720 + catch (err) {
  721 + status = 'parsererror';
  722 + xhr.error = errMsg = (err || status);
  723 + }
  724 + }
  725 + catch (err) {
  726 + log('error caught: ',err);
  727 + status = 'error';
  728 + xhr.error = errMsg = (err || status);
  729 + }
  730 +
  731 + if (xhr.aborted) {
  732 + log('upload aborted');
  733 + status = null;
  734 + }
  735 +
  736 + if (xhr.status) { // we've set xhr.status
  737 + status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
  738 + }
  739 +
  740 + // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
  741 + if (status === 'success') {
  742 + if (s.success) {
  743 + s.success.call(s.context, data, 'success', xhr);
  744 + }
  745 + deferred.resolve(xhr.responseText, 'success', xhr);
  746 + if (g) {
  747 + $.event.trigger("ajaxSuccess", [xhr, s]);
  748 + }
  749 + }
  750 + else if (status) {
  751 + if (errMsg === undefined) {
  752 + errMsg = xhr.statusText;
  753 + }
  754 + if (s.error) {
  755 + s.error.call(s.context, xhr, status, errMsg);
  756 + }
  757 + deferred.reject(xhr, 'error', errMsg);
  758 + if (g) {
  759 + $.event.trigger("ajaxError", [xhr, s, errMsg]);
  760 + }
  761 + }
  762 +
  763 + if (g) {
  764 + $.event.trigger("ajaxComplete", [xhr, s]);
  765 + }
  766 +
  767 + if (g && ! --$.active) {
  768 + $.event.trigger("ajaxStop");
  769 + }
  770 +
  771 + if (s.complete) {
  772 + s.complete.call(s.context, xhr, status);
  773 + }
  774 +
  775 + callbackProcessed = true;
  776 + if (s.timeout) {
  777 + clearTimeout(timeoutHandle);
  778 + }
  779 +
  780 + // clean up
  781 + setTimeout(function() {
  782 + if (!s.iframeTarget) {
  783 + $io.remove();
  784 + }
  785 + else { //adding else to clean up existing iframe response.
  786 + $io.attr('src', s.iframeSrc);
  787 + }
  788 + xhr.responseXML = null;
  789 + }, 100);
  790 + }
  791 +
  792 + var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
  793 + if (window.ActiveXObject) {
  794 + doc = new ActiveXObject('Microsoft.XMLDOM');
  795 + doc.async = 'false';
  796 + doc.loadXML(s);
  797 + }
  798 + else {
  799 + doc = (new DOMParser()).parseFromString(s, 'text/xml');
  800 + }
  801 + return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
  802 + };
  803 + var parseJSON = $.parseJSON || function(s) {
  804 + /*jslint evil:true */
  805 + return window['eval']('(' + s + ')');
  806 + };
  807 +
  808 + var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
  809 +
  810 + var ct = xhr.getResponseHeader('content-type') || '',
  811 + xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
  812 + data = xml ? xhr.responseXML : xhr.responseText;
  813 +
  814 + if (xml && data.documentElement.nodeName === 'parsererror') {
  815 + if ($.error) {
  816 + $.error('parsererror');
  817 + }
  818 + }
  819 + if (s && s.dataFilter) {
  820 + data = s.dataFilter(data, type);
  821 + }
  822 + if (typeof data === 'string') {
  823 + if (type === 'json' || !type && ct.indexOf('json') >= 0) {
  824 + data = parseJSON(data);
  825 + } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
  826 + $.globalEval(data);
  827 + }
  828 + }
  829 + return data;
  830 + };
  831 +
  832 + return deferred;
  833 + }
  834 +};
  835 +
  836 +/**
  837 + * ajaxForm() provides a mechanism for fully automating form submission.
  838 + *
  839 + * The advantages of using this method instead of ajaxSubmit() are:
  840 + *
  841 + * 1: This method will include coordinates for <input type="image" /> elements (if the element
  842 + * is used to submit the form).
  843 + * 2. This method will include the submit element's name/value data (for the element that was
  844 + * used to submit the form).
  845 + * 3. This method binds the submit() method to the form for you.
  846 + *
  847 + * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
  848 + * passes the options argument along after properly binding events for submit elements and
  849 + * the form itself.
  850 + */
  851 +$.fn.ajaxForm = function(options) {
  852 + options = options || {};
  853 + options.delegation = options.delegation && $.isFunction($.fn.on);
  854 +
  855 + // in jQuery 1.3+ we can fix mistakes with the ready state
  856 + if (!options.delegation && this.length === 0) {
  857 + var o = { s: this.selector, c: this.context };
  858 + if (!$.isReady && o.s) {
  859 + log('DOM not ready, queuing ajaxForm');
  860 + $(function() {
  861 + $(o.s,o.c).ajaxForm(options);
  862 + });
  863 + return this;
  864 + }
  865 + // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
  866 + log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
  867 + return this;
  868 + }
  869 +
  870 + if ( options.delegation ) {
  871 + $(document)
  872 + .off('submit.form-plugin', this.selector, doAjaxSubmit)
  873 + .off('click.form-plugin', this.selector, captureSubmittingElement)
  874 + .on('submit.form-plugin', this.selector, options, doAjaxSubmit)
  875 + .on('click.form-plugin', this.selector, options, captureSubmittingElement);
  876 + return this;
  877 + }
  878 +
  879 + return this.ajaxFormUnbind()
  880 + .bind('submit.form-plugin', options, doAjaxSubmit)
  881 + .bind('click.form-plugin', options, captureSubmittingElement);
  882 +};
  883 +
  884 +// private event handlers
  885 +function doAjaxSubmit(e) {
  886 + /*jshint validthis:true */
  887 + var options = e.data;
  888 + if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
  889 + e.preventDefault();
  890 + $(e.target).ajaxSubmit(options); // #365
  891 + }
  892 +}
  893 +
  894 +function captureSubmittingElement(e) {
  895 + /*jshint validthis:true */
  896 + var target = e.target;
  897 + var $el = $(target);
  898 + if (!($el.is("[type=submit],[type=image]"))) {
  899 + // is this a child element of the submit el? (ex: a span within a button)
  900 + var t = $el.closest('[type=submit]');
  901 + if (t.length === 0) {
  902 + return;
  903 + }
  904 + target = t[0];
  905 + }
  906 + var form = this;
  907 + form.clk = target;
  908 + if (target.type == 'image') {
  909 + if (e.offsetX !== undefined) {
  910 + form.clk_x = e.offsetX;
  911 + form.clk_y = e.offsetY;
  912 + } else if (typeof $.fn.offset == 'function') {
  913 + var offset = $el.offset();
  914 + form.clk_x = e.pageX - offset.left;
  915 + form.clk_y = e.pageY - offset.top;
  916 + } else {
  917 + form.clk_x = e.pageX - target.offsetLeft;
  918 + form.clk_y = e.pageY - target.offsetTop;
  919 + }
  920 + }
  921 + // clear form vars
  922 + setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
  923 +}
  924 +
  925 +
  926 +// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
  927 +$.fn.ajaxFormUnbind = function() {
  928 + return this.unbind('submit.form-plugin click.form-plugin');
  929 +};
  930 +
  931 +/**
  932 + * formToArray() gathers form element data into an array of objects that can
  933 + * be passed to any of the following ajax functions: $.get, $.post, or load.
  934 + * Each object in the array has both a 'name' and 'value' property. An example of
  935 + * an array for a simple login form might be:
  936 + *
  937 + * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
  938 + *
  939 + * It is this array that is passed to pre-submit callback functions provided to the
  940 + * ajaxSubmit() and ajaxForm() methods.
  941 + */
  942 +$.fn.formToArray = function(semantic, elements) {
  943 + var a = [];
  944 + if (this.length === 0) {
  945 + return a;
  946 + }
  947 +
  948 + var form = this[0];
  949 + var formId = this.attr('id');
  950 + var els = semantic ? form.getElementsByTagName('*') : form.elements;
  951 + var els2;
  952 +
  953 + if (els && !/MSIE [678]/.test(navigator.userAgent)) { // #390
  954 + els = $(els).get(); // convert to standard array
  955 + }
  956 +
  957 + // #386; account for inputs outside the form which use the 'form' attribute
  958 + if ( formId ) {
  959 + els2 = $(':input[form="' + formId + '"]').get(); // hat tip @thet
  960 + if ( els2.length ) {
  961 + els = (els || []).concat(els2);
  962 + }
  963 + }
  964 +
  965 + if (!els || !els.length) {
  966 + return a;
  967 + }
  968 +
  969 + var i,j,n,v,el,max,jmax;
  970 + for(i=0, max=els.length; i < max; i++) {
  971 + el = els[i];
  972 + n = el.name;
  973 + if (!n || el.disabled) {
  974 + continue;
  975 + }
  976 +
  977 + if (semantic && form.clk && el.type == "image") {
  978 + // handle image inputs on the fly when semantic == true
  979 + if(form.clk == el) {
  980 + a.push({name: n, value: $(el).val(), type: el.type });
  981 + a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
  982 + }
  983 + continue;
  984 + }
  985 +
  986 + v = $.fieldValue(el, true);
  987 + if (v && v.constructor == Array) {
  988 + if (elements) {
  989 + elements.push(el);
  990 + }
  991 + for(j=0, jmax=v.length; j < jmax; j++) {
  992 + a.push({name: n, value: v[j]});
  993 + }
  994 + }
  995 + else if (feature.fileapi && el.type == 'file') {
  996 + if (elements) {
  997 + elements.push(el);
  998 + }
  999 + var files = el.files;
  1000 + if (files.length) {
  1001 + for (j=0; j < files.length; j++) {
  1002 + a.push({name: n, value: files[j], type: el.type});
  1003 + }
  1004 + }
  1005 + else {
  1006 + // #180
  1007 + a.push({ name: n, value: '', type: el.type });
  1008 + }
  1009 + }
  1010 + else if (v !== null && typeof v != 'undefined') {
  1011 + if (elements) {
  1012 + elements.push(el);
  1013 + }
  1014 + a.push({name: n, value: v, type: el.type, required: el.required});
  1015 + }
  1016 + }
  1017 +
  1018 + if (!semantic && form.clk) {
  1019 + // input type=='image' are not found in elements array! handle it here
  1020 + var $input = $(form.clk), input = $input[0];
  1021 + n = input.name;
  1022 + if (n && !input.disabled && input.type == 'image') {
  1023 + a.push({name: n, value: $input.val()});
  1024 + a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
  1025 + }
  1026 + }
  1027 + return a;
  1028 +};
  1029 +
  1030 +/**
  1031 + * Serializes form data into a 'submittable' string. This method will return a string
  1032 + * in the format: name1=value1&amp;name2=value2
  1033 + */
  1034 +$.fn.formSerialize = function(semantic) {
  1035 + //hand off to jQuery.param for proper encoding
  1036 + return $.param(this.formToArray(semantic));
  1037 +};
  1038 +
  1039 +/**
  1040 + * Serializes all field elements in the jQuery object into a query string.
  1041 + * This method will return a string in the format: name1=value1&amp;name2=value2
  1042 + */
  1043 +$.fn.fieldSerialize = function(successful) {
  1044 + var a = [];
  1045 + this.each(function() {
  1046 + var n = this.name;
  1047 + if (!n) {
  1048 + return;
  1049 + }
  1050 + var v = $.fieldValue(this, successful);
  1051 + if (v && v.constructor == Array) {
  1052 + for (var i=0,max=v.length; i < max; i++) {
  1053 + a.push({name: n, value: v[i]});
  1054 + }
  1055 + }
  1056 + else if (v !== null && typeof v != 'undefined') {
  1057 + a.push({name: this.name, value: v});
  1058 + }
  1059 + });
  1060 + //hand off to jQuery.param for proper encoding
  1061 + return $.param(a);
  1062 +};
  1063 +
  1064 +/**
  1065 + * Returns the value(s) of the element in the matched set. For example, consider the following form:
  1066 + *
  1067 + * <form><fieldset>
  1068 + * <input name="A" type="text" />
  1069 + * <input name="A" type="text" />
  1070 + * <input name="B" type="checkbox" value="B1" />
  1071 + * <input name="B" type="checkbox" value="B2"/>
  1072 + * <input name="C" type="radio" value="C1" />
  1073 + * <input name="C" type="radio" value="C2" />
  1074 + * </fieldset></form>
  1075 + *
  1076 + * var v = $('input[type=text]').fieldValue();
  1077 + * // if no values are entered into the text inputs
  1078 + * v == ['','']
  1079 + * // if values entered into the text inputs are 'foo' and 'bar'
  1080 + * v == ['foo','bar']
  1081 + *
  1082 + * var v = $('input[type=checkbox]').fieldValue();
  1083 + * // if neither checkbox is checked
  1084 + * v === undefined
  1085 + * // if both checkboxes are checked
  1086 + * v == ['B1', 'B2']
  1087 + *
  1088 + * var v = $('input[type=radio]').fieldValue();
  1089 + * // if neither radio is checked
  1090 + * v === undefined
  1091 + * // if first radio is checked
  1092 + * v == ['C1']
  1093 + *
  1094 + * The successful argument controls whether or not the field element must be 'successful'
  1095 + * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
  1096 + * The default value of the successful argument is true. If this value is false the value(s)
  1097 + * for each element is returned.
  1098 + *
  1099 + * Note: This method *always* returns an array. If no valid value can be determined the
  1100 + * array will be empty, otherwise it will contain one or more values.
  1101 + */
  1102 +$.fn.fieldValue = function(successful) {
  1103 + for (var val=[], i=0, max=this.length; i < max; i++) {
  1104 + var el = this[i];
  1105 + var v = $.fieldValue(el, successful);
  1106 + if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
  1107 + continue;
  1108 + }
  1109 + if (v.constructor == Array) {
  1110 + $.merge(val, v);
  1111 + }
  1112 + else {
  1113 + val.push(v);
  1114 + }
  1115 + }
  1116 + return val;
  1117 +};
  1118 +
  1119 +/**
  1120 + * Returns the value of the field element.
  1121 + */
  1122 +$.fieldValue = function(el, successful) {
  1123 + var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
  1124 + if (successful === undefined) {
  1125 + successful = true;
  1126 + }
  1127 +
  1128 + if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
  1129 + (t == 'checkbox' || t == 'radio') && !el.checked ||
  1130 + (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
  1131 + tag == 'select' && el.selectedIndex == -1)) {
  1132 + return null;
  1133 + }
  1134 +
  1135 + if (tag == 'select') {
  1136 + var index = el.selectedIndex;
  1137 + if (index < 0) {
  1138 + return null;
  1139 + }
  1140 + var a = [], ops = el.options;
  1141 + var one = (t == 'select-one');
  1142 + var max = (one ? index+1 : ops.length);
  1143 + for(var i=(one ? index : 0); i < max; i++) {
  1144 + var op = ops[i];
  1145 + if (op.selected) {
  1146 + var v = op.value;
  1147 + if (!v) { // extra pain for IE...
  1148 + v = (op.attributes && op.attributes.value && !(op.attributes.value.specified)) ? op.text : op.value;
  1149 + }
  1150 + if (one) {
  1151 + return v;
  1152 + }
  1153 + a.push(v);
  1154 + }
  1155 + }
  1156 + return a;
  1157 + }
  1158 + return $(el).val();
  1159 +};
  1160 +
  1161 +/**
  1162 + * Clears the form data. Takes the following actions on the form's input fields:
  1163 + * - input text fields will have their 'value' property set to the empty string
  1164 + * - select elements will have their 'selectedIndex' property set to -1
  1165 + * - checkbox and radio inputs will have their 'checked' property set to false
  1166 + * - inputs of type submit, button, reset, and hidden will *not* be effected
  1167 + * - button elements will *not* be effected
  1168 + */
  1169 +$.fn.clearForm = function(includeHidden) {
  1170 + return this.each(function() {
  1171 + $('input,select,textarea', this).clearFields(includeHidden);
  1172 + });
  1173 +};
  1174 +
  1175 +/**
  1176 + * Clears the selected form elements.
  1177 + */
  1178 +$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
  1179 + var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
  1180 + return this.each(function() {
  1181 + var t = this.type, tag = this.tagName.toLowerCase();
  1182 + if (re.test(t) || tag == 'textarea') {
  1183 + this.value = '';
  1184 + }
  1185 + else if (t == 'checkbox' || t == 'radio') {
  1186 + this.checked = false;
  1187 + }
  1188 + else if (tag == 'select') {
  1189 + this.selectedIndex = -1;
  1190 + }
  1191 + else if (t == "file") {
  1192 + if (/MSIE/.test(navigator.userAgent)) {
  1193 + $(this).replaceWith($(this).clone(true));
  1194 + } else {
  1195 + $(this).val('');
  1196 + }
  1197 + }
  1198 + else if (includeHidden) {
  1199 + // includeHidden can be the value true, or it can be a selector string
  1200 + // indicating a special test; for example:
  1201 + // $('#myForm').clearForm('.special:hidden')
  1202 + // the above would clean hidden inputs that have the class of 'special'
  1203 + if ( (includeHidden === true && /hidden/.test(t)) ||
  1204 + (typeof includeHidden == 'string' && $(this).is(includeHidden)) ) {
  1205 + this.value = '';
  1206 + }
  1207 + }
  1208 + });
  1209 +};
  1210 +
  1211 +/**
  1212 + * Resets the form data. Causes all form elements to be reset to their original value.
  1213 + */
  1214 +$.fn.resetForm = function() {
  1215 + return this.each(function() {
  1216 + // guard against an input with the name of 'reset'
  1217 + // note that IE reports the reset function as an 'object'
  1218 + if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
  1219 + this.reset();
  1220 + }
  1221 + });
  1222 +};
  1223 +
  1224 +/**
  1225 + * Enables or disables any matching elements.
  1226 + */
  1227 +$.fn.enable = function(b) {
  1228 + if (b === undefined) {
  1229 + b = true;
  1230 + }
  1231 + return this.each(function() {
  1232 + this.disabled = !b;
  1233 + });
  1234 +};
  1235 +
  1236 +/**
  1237 + * Checks/unchecks any matching checkboxes or radio buttons and
  1238 + * selects/deselects and matching option elements.
  1239 + */
  1240 +$.fn.selected = function(select) {
  1241 + if (select === undefined) {
  1242 + select = true;
  1243 + }
  1244 + return this.each(function() {
  1245 + var t = this.type;
  1246 + if (t == 'checkbox' || t == 'radio') {
  1247 + this.checked = select;
  1248 + }
  1249 + else if (this.tagName.toLowerCase() == 'option') {
  1250 + var $sel = $(this).parent('select');
  1251 + if (select && $sel[0] && $sel[0].type == 'select-one') {
  1252 + // deselect all other options
  1253 + $sel.find('option').selected(false);
  1254 + }
  1255 + this.selected = select;
  1256 + }
  1257 + });
  1258 +};
  1259 +
  1260 +// expose debug var
  1261 +$.fn.ajaxSubmit.debug = false;
  1262 +
  1263 +// helper fn for console logging
  1264 +function log() {
  1265 + if (!$.fn.ajaxSubmit.debug) {
  1266 + return;
  1267 + }
  1268 + var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
  1269 + if (window.console && window.console.log) {
  1270 + window.console.log(msg);
  1271 + }
  1272 + else if (window.opera && window.opera.postError) {
  1273 + window.opera.postError(msg);
  1274 + }
  1275 +}
  1276 +
  1277 +}));