add
|
@ -10,6 +10,7 @@ import org.apache.shiro.authc.LockedAccountException;
|
|||
import org.apache.shiro.authz.annotation.RequiresAuthentication;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.util.ThreadContext;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Lang;
|
||||
|
@ -28,8 +29,10 @@ import org.nutz.plugins.view.freemarker.FreemarkerView;
|
|||
import org.nutz.web.Webs;
|
||||
|
||||
import com.rekoe.domain.User;
|
||||
import com.rekoe.domain.Usr;
|
||||
import com.rekoe.exception.IncorrectCaptchaException;
|
||||
import com.rekoe.filter.AuthenticationFilter;
|
||||
import com.rekoe.service.UsrService;
|
||||
|
||||
/**
|
||||
* @author 科技㊣²º¹³<br />
|
||||
|
@ -44,6 +47,9 @@ public class AdminLoginAct {
|
|||
@Inject
|
||||
private FreeMarkerConfigurer freeMarkerConfigurer;
|
||||
|
||||
@Inject
|
||||
private UsrService usrService;
|
||||
|
||||
@At
|
||||
@Filters(@By(type = AuthenticationFilter.class))
|
||||
public View login(@Attr("loginToken") AuthenticationToken token, HttpSession session, HttpServletRequest req) {
|
||||
|
@ -51,6 +57,10 @@ public class AdminLoginAct {
|
|||
Subject subject = SecurityUtils.getSubject();
|
||||
ThreadContext.bind(subject);
|
||||
subject.login(token);
|
||||
Usr usr = usrService.fetch(Cnd.where("usr", "=", "admin"));
|
||||
if (!Lang.isEmpty(usr)) {
|
||||
session.setAttribute("usr", usr);
|
||||
}
|
||||
session.setAttribute(Webs.ME, subject.getPrincipal());
|
||||
return new ServerRedirectView("/admin/main.rk");
|
||||
} catch (IncorrectCaptchaException e) {
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
package com.rekoe.module.admin;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
|
@ -13,25 +19,31 @@ import com.rekoe.annotation.PermissionTag;
|
|||
import com.rekoe.common.Message;
|
||||
import com.rekoe.common.page.Pagination;
|
||||
import com.rekoe.domain.Pj;
|
||||
import com.rekoe.domain.PjAuth;
|
||||
import com.rekoe.module.BaseAction;
|
||||
import com.rekoe.service.ProjectAuthService;
|
||||
import com.rekoe.service.ProjectGroupService;
|
||||
import com.rekoe.service.ProjectService;
|
||||
import com.rekoe.service.RepositoryService;
|
||||
import com.rekoe.service.UsrService;
|
||||
import com.rekoe.utils.UsrProvider;
|
||||
|
||||
@IocBean
|
||||
@At("/admin/project")
|
||||
public class AdminProjectAct extends BaseAction{
|
||||
public class AdminProjectAct extends BaseAction {
|
||||
|
||||
@Inject
|
||||
private ProjectService projectService;
|
||||
|
||||
|
||||
@At
|
||||
@Ok("fm:template.admin.project.list")
|
||||
@RequiresPermissions({ "svn.project:view" })
|
||||
@PermissionTag(name = "SVN浏览项目", tag = "SVN项目管理")
|
||||
public Pagination list(@Param(value = "pageNumber", df = "1") int page) {
|
||||
System.out.println(UsrProvider.getCurrentUsr());
|
||||
return projectService.getObjListByPager(page, 20, null);
|
||||
}
|
||||
|
||||
|
||||
@At
|
||||
@Ok("fm:template.admin.project.add")
|
||||
@RequiresPermissions({ "svn.project:add" })
|
||||
|
@ -51,4 +63,74 @@ public class AdminProjectAct extends BaseAction{
|
|||
}
|
||||
return Message.error("error", req);
|
||||
}
|
||||
|
||||
@Inject
|
||||
private RepositoryService repositoryService;
|
||||
|
||||
@At
|
||||
@Ok("fm:template.admin.project.rep")
|
||||
@RequiresPermissions({ "svn.project:view" })
|
||||
public String rep(@Param("pj") String pj, HttpServletRequest req) {
|
||||
Pj project = projectService.fetch(Cnd.where("pj", "=", pj));
|
||||
String root = repositoryService.getRepositoryRoot(project);
|
||||
String svnUrl = RepositoryService.parseURL(project.getUrl());
|
||||
String path = "/";
|
||||
if (root != null) {
|
||||
try {
|
||||
root = URLDecoder.decode(root, "UTF-8");// @see issue 34
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
}
|
||||
if (svnUrl.indexOf(root) != -1) {
|
||||
path = StringUtils.substringAfter(svnUrl, root);
|
||||
if (!path.startsWith("/")) {
|
||||
path = "/" + path;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
root = svnUrl;
|
||||
}
|
||||
req.setAttribute("root", root);
|
||||
req.setAttribute("path", path);
|
||||
req.setAttribute("pj", pj);
|
||||
return pj;
|
||||
}
|
||||
|
||||
@Inject
|
||||
private ProjectAuthService projectAuthService;
|
||||
|
||||
@Inject
|
||||
private ProjectGroupService projectGroupService;
|
||||
|
||||
@Inject
|
||||
private UsrService usrService;
|
||||
|
||||
@At
|
||||
@Ok("fm:template.admin.project.pjauth")
|
||||
@RequiresPermissions({ "svn.project:view" })
|
||||
public String pjauth(@Param("pj") String pj, @Param("res") String res, HttpServletRequest req) {
|
||||
PjAuth entity = (PjAuth) req.getAttribute("entity");
|
||||
if (entity == null) {
|
||||
entity = new PjAuth();
|
||||
entity.setPj(pj);
|
||||
entity.setRes("");
|
||||
entity.setRw("");
|
||||
req.setAttribute("entity", entity);
|
||||
}
|
||||
if (StringUtils.isBlank(res)) {
|
||||
String path = req.getParameter("path");
|
||||
if (StringUtils.isNotBlank(path)) {
|
||||
res = this.projectAuthService.formatRes(pj, path);
|
||||
}
|
||||
} else {
|
||||
res = entity.getRes();
|
||||
}
|
||||
entity.setRes(res);
|
||||
List<PjAuth> list = projectAuthService.list(pj, res);
|
||||
req.setAttribute("list", list);
|
||||
req.setAttribute("pj", pj);
|
||||
req.setAttribute("pjreslist", projectAuthService.getResList(pj));
|
||||
req.setAttribute("pjgrlist",projectGroupService.getList(pj));
|
||||
req.setAttribute("usrList", usrService.getList());
|
||||
return pj;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class ProjectAuthService extends BaseService<PjAuth> {
|
|||
* @return 项目的资源列表
|
||||
*/
|
||||
public List<String> getResList(String pj) {
|
||||
Sql sql = Sqls.create("select distinct res from pj_gr_auth where pj=? UNION select distinct res from pj_usr_auth where pj=@pj order by res");
|
||||
Sql sql = Sqls.create("select distinct res from pj_gr_auth where pj=@pj UNION select distinct res from pj_usr_auth where pj=@pj order by res");
|
||||
sql.setCallback(Sqls.callback.strList());
|
||||
sql.setParam("pj", pj);
|
||||
dao().execute(sql);
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
package com.rekoe.service;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.sql.SqlCallback;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import com.rekoe.domain.PjGr;
|
||||
|
@ -31,4 +40,29 @@ public class ProjectGroupService extends BaseService<PjGr> {
|
|||
dao().update(getEntityClass(), Chain.make("des", pjGr.getDes()), Cnd.where("pj", "=", pjGr.getPj()).and("gr", "=", pjGr.getGr()));
|
||||
}
|
||||
}
|
||||
|
||||
public List<PjGr> getList(String pj) {
|
||||
Sql sql = Sqls.create("select pj,gr,des from pj_gr $condition");
|
||||
sql.setCondition(Cnd.where("pj", "=", pj).desc("pj,gr"));
|
||||
final List<PjGr> list = new ArrayList<PjGr>();
|
||||
sql.setCallback(new SqlCallback() {
|
||||
|
||||
@Override
|
||||
public Object invoke(Connection conn, ResultSet rs, Sql sql) throws SQLException {
|
||||
while (rs.next()) {
|
||||
list.add(readPjGr(rs));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
PjGr readPjGr(ResultSet rs) throws SQLException {
|
||||
PjGr result = new PjGr();
|
||||
result.setPj(rs.getString("pj"));
|
||||
result.setGr(rs.getString("gr"));
|
||||
result.setDes(rs.getString("des"));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,13 @@ public class UsrService extends BaseService<Usr> {
|
|||
super(dao);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 所有用户列表
|
||||
*/
|
||||
public List<Usr> getList() {
|
||||
return dao().query(getEntityClass(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pj
|
||||
* 项目
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
*/
|
||||
package com.rekoe.utils;
|
||||
|
||||
import org.nutz.mvc.Mvcs;
|
||||
|
||||
import com.rekoe.domain.Usr;
|
||||
|
||||
/**
|
||||
|
@ -17,7 +19,7 @@ public class UsrProvider {
|
|||
* @return 当前的用户
|
||||
*/
|
||||
public static Usr getCurrentUsr() {
|
||||
Usr usr = USR_THREAD_LOCAL.get();
|
||||
Usr usr = (Usr)Mvcs.getReq().getSession().getAttribute("usr");
|
||||
if (usr == null) {
|
||||
throw new RuntimeException("当前线程没有设置用户!");
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ function getTableForm() {
|
|||
<@p.column title="ID" align="center">${i+1}</@p.column><#t/>
|
||||
<@p.column title="姓名" align="center">${user.pj}</@p.column><#t/>
|
||||
<@p.column title="路径" align="center">${user.path}</@p.column><#t/>
|
||||
<@p.column title="URL" align="center">${user.url}</@p.column><#t/>
|
||||
<@p.column title="URL" align="center"><a href="rep?pj=${user.pj}">${user.url}</a></@p.column><#t/>
|
||||
<@p.column title="类型" align="center">${user.type}</@p.column><#t/>
|
||||
<@p.column title="描述" align="center">${user.des}</@p.column><#t/>
|
||||
<@p.column title="设置用户组" align="center">设置用户组</@p.column><#t/>
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
<html>
|
||||
<head>
|
||||
<script src="${base}/resources/jquery-1.7.min.js" type="text/javascript"></script>
|
||||
<script src="${base}/resources/sorttable.js"></script>
|
||||
<script src="${base}/resources/svnadmin.js"></script>
|
||||
<link rel="stylesheet" href="${base}/resources/svnadmin.css" />
|
||||
<script>
|
||||
$(function(){
|
||||
//移到用户组右边
|
||||
$('#group_add').click(function() {
|
||||
//获取选中的选项,删除并追加给对方
|
||||
$('#select3 option:selected').appendTo('#select4');
|
||||
});
|
||||
//移到用户组左边
|
||||
$('#group_del').click(function() {
|
||||
$('#select4 option:selected').appendTo('#select3');
|
||||
});
|
||||
//全部移到用户组右边
|
||||
$('#group_add_all').click(function() {
|
||||
//获取全部的选项,删除并追加给对方
|
||||
$('#select3 option').appendTo('#select4');
|
||||
});
|
||||
//全部移到用户组左边
|
||||
$('#group_del_all').click(function() {
|
||||
$('#select4 option').appendTo('#select3');
|
||||
});
|
||||
|
||||
//移到用户右边
|
||||
$('#user_add').click(function() {
|
||||
//获取选中的选项,删除并追加给对方
|
||||
$('#select1 option:selected').appendTo('#select2');
|
||||
});
|
||||
//移到用户左边
|
||||
$('#user_del').click(function() {
|
||||
$('#select2 option:selected').appendTo('#select1');
|
||||
});
|
||||
//全部移到用户右边
|
||||
$('#user_add_all').click(function() {
|
||||
//获取全部的选项,删除并追加给对方
|
||||
$('#select1 option').appendTo('#select2');
|
||||
});
|
||||
//全部移到用户左边
|
||||
$('#user_del_all').click(function() {
|
||||
$('#select2 option').appendTo('#select1');
|
||||
});
|
||||
|
||||
//双击选项
|
||||
$('#select1').dblclick(function(){ //绑定双击事件
|
||||
//获取全部的选项,删除并追加给对方
|
||||
$("option:selected",this).appendTo('#select2'); //追加给对方
|
||||
});
|
||||
//双击选项
|
||||
$('#select2').dblclick(function(){
|
||||
$("option:selected",this).appendTo('#select1');
|
||||
});
|
||||
//双击选项
|
||||
$('#select3').dblclick(function(){ //绑定双击事件
|
||||
//获取全部的选项,删除并追加给对方
|
||||
$("option:selected",this).appendTo('#select4'); //追加给对方
|
||||
});
|
||||
//双击选项
|
||||
$('#select4').dblclick(function(){
|
||||
$("option:selected",this).appendTo('#select3');
|
||||
});
|
||||
});
|
||||
|
||||
function checkForm(f){
|
||||
if(f.elements["pj"].value==""){
|
||||
alert("项目不可以为空");
|
||||
f.elements["pj"].focus();
|
||||
return false;
|
||||
}
|
||||
if(f.elements["res"].value==""){
|
||||
alert("资源不可以为空");
|
||||
f.elements["res"].focus();
|
||||
return false;
|
||||
}
|
||||
if(f.elements["grs"].value=="" && f.elements["usrs"].value==""){
|
||||
alert("请选择用户组或用户");
|
||||
f.elements["grs"].focus();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body style="margin: 0px;">
|
||||
<#assign errorMsg="">
|
||||
<#if errorMsg?exists>
|
||||
<div style="color:red;">错误 ${errorMsg}</div>
|
||||
</#if>
|
||||
<form name="pjauth" action="${base}/pjauth" method="post" onsubmit="return checkForm(this);">
|
||||
<input type="hidden" name="act" value="save">
|
||||
<input type="hidden" name="pj" value="${pj}">
|
||||
<table class="table table-striped table-bordered">
|
||||
<tr>
|
||||
<td class="lbl">资源</td>
|
||||
<td colspan="3">
|
||||
<input type="text" name="res" value="${entity.res!""}" style="width:400px;"><span style="color:red;">*</span>
|
||||
<select onchange="this.form.res.value=this.value">
|
||||
<option value="">选择资源</option>
|
||||
<#list pjreslist as pjre>
|
||||
<option value="${pjre}">${pjre}</option>
|
||||
</#list>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="lbl">用户组</td>
|
||||
<td valign="top">
|
||||
<table>
|
||||
<tr>
|
||||
<td style="border:0px;">
|
||||
<select id="select3" multiple="multiple" style="height: 150px;width: 150px;">
|
||||
<#list pjgrlist as pjGr>
|
||||
<option value="${pjGr.gr}">${pjGr.gr}</option>
|
||||
</#list>
|
||||
</select>
|
||||
</td>
|
||||
<td style="border:0px;">
|
||||
<input id="group_add" type="button" style="width:30px;" value=">"><br>
|
||||
<input id="group_add_all" type="button" style="width:30px;" value=">>"><br><br>
|
||||
<input id="group_del" type="button" style="width:30px;" value="<"><br>
|
||||
<input id="group_del_all" type="button" style="width:30px;" value="<<"><br><br>
|
||||
</td>
|
||||
<td style="border:0px;">
|
||||
<select id="select4" name="grs" multiple="multiple" style="height: 150px;width: 150px;">
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td class="lbl">用户</td>
|
||||
<td valign="top">
|
||||
<table>
|
||||
<tr>
|
||||
<td style="border:0px;">
|
||||
<select id="select1" multiple="multiple" style="height: 150px;width: 160px;">
|
||||
<#list usrList as usr>
|
||||
<option value="${usr.usr}">${usr.name!usr.usr}(${usr.usr})</option>
|
||||
</#list>
|
||||
</select>
|
||||
</td>
|
||||
<td style="border:0px;">
|
||||
<input id="user_add" type="button" style="width:30px;" value=">"><br>
|
||||
<input id="user_add_all" type="button" style="width:30px;" value=">>"><br><br>
|
||||
<input id="user_del" type="button" style="width:30px;" value="<"><br>
|
||||
<input id="user_del_all" type="button" style="width:30px;" value="<<"><br><br>
|
||||
</td>
|
||||
<td style="border:0px;">
|
||||
<select id="select2" name="usrs" multiple="multiple" style="height: 150px;width: 160px;">
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="lbl">权限</td>
|
||||
<td colspan="3">
|
||||
<select name="rw">
|
||||
<option value="rw" <#if entity.rw == "rw">selected='selected'</#if>>可读可写</option>
|
||||
<option value="" <#if entity.rw == "">selected='selected'</#if>>没有权限</option>
|
||||
<option value="r"<#if entity.rw == "r">selected='selected'</#if>>可读</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" align="center" style="text-align: center;">
|
||||
<input type="submit" class="btn btn-primary" value="保存">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<td>NO.</td>
|
||||
<td>项目</td>
|
||||
<td>资源</td>
|
||||
<td>用户组/用户</td>
|
||||
<td>权限</td>
|
||||
<td>删除</td>
|
||||
</thead>
|
||||
<#list list as pjAuth>
|
||||
<tr>
|
||||
<td>${pjAuth_index +1}</td>
|
||||
<td>${pjAuth.pj}</td>
|
||||
<td>${pjAuth.res}</td>
|
||||
<td>${pjAuth.gr!""}${pjAuth.usr!pjAuth.usrName}:(${pjAuth.usr})</td>
|
||||
<td>
|
||||
<#if "r"== pjAuth.rw>
|
||||
可读
|
||||
<#elseif "rw"== pjAuth.rw>
|
||||
可读可写
|
||||
<#else>
|
||||
没有权限
|
||||
</#if>
|
||||
</td>
|
||||
<td>
|
||||
<a href="javascript:if(confirm('确认删除?')){del('${base}/pjauth?pj=${pjAuth.pj}&res=${pjAuth.res}&gr=${pjAuth.gr}&usr=${pjAuth.usr}')}">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
</#list>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,85 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<title></title>
|
||||
<#include "/template/admin/head.ftl"/>
|
||||
<span style="color:green;font-weight:bold;"><a href="${base}/pj">项目管理(${pj})</a> | 权限管理</span><br><br>
|
||||
<script type="text/javascript" src="${base}/resources/treeview/treeview.js"></script>
|
||||
<link type="text/css" rel="stylesheet" href="${base}/resources/treeview/treeview.css"></link>
|
||||
<style>
|
||||
#svnroot li{
|
||||
line-height: 11px;
|
||||
}
|
||||
#svnroot span{
|
||||
line-height: 11px;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
AjaxTreeView.config.onclick=function(o,a){
|
||||
var p=o.getAttribute("param");
|
||||
if(p==null)p="";
|
||||
var url="pjauth";
|
||||
if(url!=""){
|
||||
if(p!=""){
|
||||
if(url.indexOf("?")>0){
|
||||
url=url+"&"+p;
|
||||
}else{
|
||||
url=url+"?"+p;
|
||||
}
|
||||
}
|
||||
//alert(url);
|
||||
go(url,"pjauthWindow");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
$(document).ready(function (){
|
||||
AjaxTreeView.open(document.getElementById("svnroot"));
|
||||
$('#path').bind('keyup', function(event){
|
||||
if (event.keyCode=="13"){
|
||||
freshTree();
|
||||
}
|
||||
});
|
||||
});
|
||||
function freshTree(){
|
||||
var $p = $("#path");
|
||||
var p = $p.val();
|
||||
if(p==""){
|
||||
p="/";
|
||||
$p.val(p);
|
||||
}else if(p.substring(0,1)!="/"){
|
||||
p = "/"+p;
|
||||
$p.val(p);
|
||||
}
|
||||
var $r = $("#svnroot");
|
||||
$r.children("ul").first().remove();
|
||||
$("#rootlink").text("${root}"+p);
|
||||
AjaxTreeView.close($r[0]);
|
||||
$r.attr("param","pj=${pj}&path="+p);
|
||||
$r[0].loading = false;
|
||||
$r[0].loaded = false;
|
||||
AjaxTreeView.open($r[0]);
|
||||
}
|
||||
</script>
|
||||
<table style="width:100%;height:80%;" class="table table-striped table-bordered">
|
||||
<tr>
|
||||
<td valign="top" style="width:300px;">
|
||||
<input type="text" style="width:210px;" id="path" value="${path}"> <input onclick="freshTree();" class="btn btn-primary" type="button" value="刷新">
|
||||
<div class="filetree treeview" style="width:300px;height:500px;overflow: auto;">
|
||||
<ul>
|
||||
<li id="svnroot" class="closed lastclosed" treeId="rep" param="pj=${pj}&path=${path}">
|
||||
<div class="hit closed-hit lastclosed-hit" onclick='$att(this);'></div>
|
||||
<span class="folder" onclick='$att(this);'>
|
||||
<a id="rootlink" href='javascript:void(0);' onclick='$atc(this)'>${root}${path}</a>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</td>
|
||||
<td valign="top" height="100%">
|
||||
<iframe height="100%" width="100%" style="border:0px;" frameBorder="0" name="pjauthWindow" src="pjauth?pj=${pj}"></iframe>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
After Width: | Height: | Size: 237 B |
|
@ -0,0 +1,520 @@
|
|||
/*
|
||||
SortTable
|
||||
version 2
|
||||
7th April 2007
|
||||
Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/
|
||||
|
||||
Instructions:
|
||||
Download this file
|
||||
Add <script src="sorttable.js"></script> to your HTML
|
||||
Add class="sortable" to any table you'd like to make sortable
|
||||
Click on the headers to sort
|
||||
|
||||
Thanks to many, many people for contributions and suggestions.
|
||||
Licenced as X11: http://www.kryogenix.org/code/browser/licence.html
|
||||
This basically means: do what you want with it.
|
||||
*/
|
||||
|
||||
|
||||
var stIsIE = /*@cc_on!@*/false;
|
||||
|
||||
sorttable = {
|
||||
init: function() {
|
||||
// quit if this function has already been called
|
||||
if (arguments.callee.done) return;
|
||||
// flag this function so we don't do the same thing twice
|
||||
arguments.callee.done = true;
|
||||
// kill the timer
|
||||
if (_timer) clearInterval(_timer);
|
||||
|
||||
if (!document.createElement || !document.getElementsByTagName) return;
|
||||
|
||||
sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/;
|
||||
|
||||
forEach(document.getElementsByTagName('table'), function(table) {
|
||||
if (table.className.search(/\bsortable\b/) != -1) {
|
||||
sorttable.makeSortable(table);
|
||||
sorttable.makeHightlightTable(table.tBodies[0]);//by Harvey 2011-09-03
|
||||
sorttable.addHeadTitle(table);//by Harvey 2011-09-17
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
//by Harvey 2011-09-03
|
||||
makeHightlightTable:function(tbody){
|
||||
for (var i=0; i<tbody.rows.length; i++) {
|
||||
tbody.rows[i]._sorttable_cls=tbody.rows[i].className=(i%2==0)?"even":"odd";
|
||||
dean_addEvent(tbody.rows[i],"mouseover", function(e) {
|
||||
this.className="over";
|
||||
});
|
||||
dean_addEvent(tbody.rows[i],"mouseout", function(e) {
|
||||
this.className=this._sorttable_cls;
|
||||
});
|
||||
}
|
||||
},
|
||||
addHeadTitle:function(table){
|
||||
// Safari doesn't support table.tHead, sigh
|
||||
if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0];
|
||||
if (table.tHead.rows.length != 1) return; // can't cope with two header rows
|
||||
headrow = table.tHead.rows[0].cells;
|
||||
for (var i=0; i<headrow.length; i++) {
|
||||
text = sorttable.getInnerText(headrow[i]);
|
||||
if(text == null){
|
||||
text = "";
|
||||
}
|
||||
headrow[i].title="Sort "+ text;
|
||||
}
|
||||
},
|
||||
//end by Harvey 2011-09-03
|
||||
makeSortable: function(table) {
|
||||
if (table.getElementsByTagName('thead').length == 0) {
|
||||
// table doesn't have a tHead. Since it should have, create one and
|
||||
// put the first table row in it.
|
||||
the = document.createElement('thead');
|
||||
the.appendChild(table.rows[0]);
|
||||
table.insertBefore(the,table.firstChild);
|
||||
}
|
||||
// Safari doesn't support table.tHead, sigh
|
||||
if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0];
|
||||
|
||||
if (table.tHead.rows.length != 1) return; // can't cope with two header rows
|
||||
|
||||
// Sorttable v1 put rows with a class of "sortbottom" at the bottom (as
|
||||
// "total" rows, for example). This is B&R, since what you're supposed
|
||||
// to do is put them in a tfoot. So, if there are sortbottom rows,
|
||||
// for backwards compatibility, move them to tfoot (creating it if needed).
|
||||
sortbottomrows = [];
|
||||
for (var i=0; i<table.rows.length; i++) {
|
||||
if (table.rows[i].className.search(/\bsortbottom\b/) != -1) {
|
||||
sortbottomrows[sortbottomrows.length] = table.rows[i];
|
||||
}
|
||||
}
|
||||
if (sortbottomrows) {
|
||||
if (table.tFoot == null) {
|
||||
// table doesn't have a tfoot. Create one.
|
||||
tfo = document.createElement('tfoot');
|
||||
table.appendChild(tfo);
|
||||
}
|
||||
for (var i=0; i<sortbottomrows.length; i++) {
|
||||
tfo.appendChild(sortbottomrows[i]);
|
||||
}
|
||||
delete sortbottomrows;
|
||||
}
|
||||
|
||||
// work through each column and calculate its type
|
||||
headrow = table.tHead.rows[0].cells;
|
||||
for (var i=0; i<headrow.length; i++) {
|
||||
// manually override the type with a sorttable_type attribute
|
||||
if (!headrow[i].className.match(/\bsorttable_nosort\b/)) { // skip this col
|
||||
mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/);
|
||||
if (mtch) { override = mtch[1]; }
|
||||
if (mtch && typeof sorttable["sort_"+override] == 'function') {
|
||||
headrow[i].sorttable_sortfunction = sorttable["sort_"+override];
|
||||
} else {
|
||||
headrow[i].sorttable_sortfunction = sorttable.guessType(table,i);
|
||||
}
|
||||
// make it clickable to sort
|
||||
headrow[i].sorttable_columnindex = i;
|
||||
headrow[i].sorttable_tbody = table.tBodies[0];
|
||||
dean_addEvent(headrow[i],"click", function(e) {
|
||||
|
||||
if (this.className.search(/\bsorttable_sorted\b/) != -1) {
|
||||
// if we're already sorted by this column, just
|
||||
// reverse the table, which is quicker
|
||||
sorttable.reverse(this.sorttable_tbody);
|
||||
this.className = this.className.replace('sorttable_sorted',
|
||||
'sorttable_sorted_reverse');
|
||||
this.removeChild(document.getElementById('sorttable_sortfwdind'));
|
||||
sortrevind = document.createElement('span');
|
||||
sortrevind.id = "sorttable_sortrevind";
|
||||
sortrevind.innerHTML = stIsIE ? ' <font face="webdings">5</font>' : ' ▴';
|
||||
this.appendChild(sortrevind);
|
||||
return;
|
||||
}
|
||||
if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) {
|
||||
// if we're already sorted by this column in reverse, just
|
||||
// re-reverse the table, which is quicker
|
||||
sorttable.reverse(this.sorttable_tbody);
|
||||
this.className = this.className.replace('sorttable_sorted_reverse',
|
||||
'sorttable_sorted');
|
||||
this.removeChild(document.getElementById('sorttable_sortrevind'));
|
||||
sortfwdind = document.createElement('span');
|
||||
sortfwdind.id = "sorttable_sortfwdind";
|
||||
sortfwdind.innerHTML = stIsIE ? ' <font face="webdings">6</font>' : ' ▾';
|
||||
this.appendChild(sortfwdind);
|
||||
return;
|
||||
}
|
||||
|
||||
// remove sorttable_sorted classes
|
||||
theadrow = this.parentNode;
|
||||
forEach(theadrow.childNodes, function(cell) {
|
||||
if (cell.nodeType == 1) { // an element
|
||||
cell.className = cell.className.replace('sorttable_sorted_reverse','');
|
||||
cell.className = cell.className.replace('sorttable_sorted','');
|
||||
}
|
||||
});
|
||||
sortfwdind = document.getElementById('sorttable_sortfwdind');
|
||||
if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); }
|
||||
sortrevind = document.getElementById('sorttable_sortrevind');
|
||||
if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); }
|
||||
|
||||
this.className += ' sorttable_sorted';
|
||||
sortfwdind = document.createElement('span');
|
||||
sortfwdind.id = "sorttable_sortfwdind";
|
||||
sortfwdind.innerHTML = stIsIE ? ' <font face="webdings">6</font>' : ' ▾';
|
||||
this.appendChild(sortfwdind);
|
||||
|
||||
// build an array to sort. This is a Schwartzian transform thing,
|
||||
// i.e., we "decorate" each row with the actual sort key,
|
||||
// sort based on the sort keys, and then put the rows back in order
|
||||
// which is a lot faster because you only do getInnerText once per row
|
||||
row_array = [];
|
||||
col = this.sorttable_columnindex;
|
||||
rows = this.sorttable_tbody.rows;
|
||||
for (var j=0; j<rows.length; j++) {
|
||||
row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j]];
|
||||
}
|
||||
/* If you want a stable sort, uncomment the following line */
|
||||
//sorttable.shaker_sort(row_array, this.sorttable_sortfunction);
|
||||
/* and comment out this one */
|
||||
row_array.sort(this.sorttable_sortfunction);
|
||||
|
||||
tb = this.sorttable_tbody;
|
||||
for (var j=0; j<row_array.length; j++) {
|
||||
tb.appendChild(row_array[j][1]);
|
||||
}
|
||||
|
||||
delete row_array;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
guessType: function(table, column) {
|
||||
// guess the type of a column based on its first non-blank row
|
||||
sortfn = sorttable.sort_alpha;
|
||||
for (var i=0; i<table.tBodies[0].rows.length; i++) {
|
||||
text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]);
|
||||
if (text != '') {
|
||||
if (text.match(/^-?[?<3F>]?[\d,.]+%?$/)) {
|
||||
return sorttable.sort_numeric;
|
||||
}
|
||||
// check for a date: dd/mm/yyyy or dd/mm/yy
|
||||
// can have / or . or - as separator
|
||||
// can be mm/dd as well
|
||||
possdate = text.match(sorttable.DATE_RE)
|
||||
if (possdate) {
|
||||
// looks like a date
|
||||
first = parseInt(possdate[1]);
|
||||
second = parseInt(possdate[2]);
|
||||
if (first > 12) {
|
||||
// definitely dd/mm
|
||||
return sorttable.sort_ddmm;
|
||||
} else if (second > 12) {
|
||||
return sorttable.sort_mmdd;
|
||||
} else {
|
||||
// looks like a date, but we can't tell which, so assume
|
||||
// that it's dd/mm (English imperialism!) and keep looking
|
||||
sortfn = sorttable.sort_ddmm;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return sortfn;
|
||||
},
|
||||
|
||||
getInnerText: function(node) {
|
||||
// gets the text we want to use for sorting for a cell.
|
||||
// strips leading and trailing whitespace.
|
||||
// this is *not* a generic getInnerText function; it's special to sorttable.
|
||||
// for example, you can override the cell text with a customkey attribute.
|
||||
// it also gets .value for <input> fields.
|
||||
|
||||
hasInputs = (typeof node.getElementsByTagName == 'function') &&
|
||||
node.getElementsByTagName('input').length;
|
||||
|
||||
if (node.getAttribute("sorttable_customkey") != null) {
|
||||
return node.getAttribute("sorttable_customkey");
|
||||
}
|
||||
else if (typeof node.textContent != 'undefined' && !hasInputs) {
|
||||
return node.textContent.replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
else if (typeof node.innerText != 'undefined' && !hasInputs) {
|
||||
return node.innerText.replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
else if (typeof node.text != 'undefined' && !hasInputs) {
|
||||
return node.text.replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
else {
|
||||
switch (node.nodeType) {
|
||||
case 3:
|
||||
if (node.nodeName.toLowerCase() == 'input') {
|
||||
return node.value.replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
case 4:
|
||||
return node.nodeValue.replace(/^\s+|\s+$/g, '');
|
||||
break;
|
||||
case 1:
|
||||
case 11:
|
||||
var innerText = '';
|
||||
for (var i = 0; i < node.childNodes.length; i++) {
|
||||
innerText += sorttable.getInnerText(node.childNodes[i]);
|
||||
}
|
||||
return innerText.replace(/^\s+|\s+$/g, '');
|
||||
break;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
reverse: function(tbody) {
|
||||
// reverse the rows in a tbody
|
||||
newrows = [];
|
||||
for (var i=0; i<tbody.rows.length; i++) {
|
||||
newrows[newrows.length] = tbody.rows[i];
|
||||
}
|
||||
for (var i=newrows.length-1; i>=0; i--) {
|
||||
tbody.appendChild(newrows[i]);
|
||||
}
|
||||
delete newrows;
|
||||
},
|
||||
|
||||
/* sort functions
|
||||
each sort function takes two parameters, a and b
|
||||
you are comparing a[0] and b[0] */
|
||||
sort_numeric: function(a,b) {
|
||||
aa = parseFloat(a[0].replace(/[^0-9.-]/g,''));
|
||||
if (isNaN(aa)) aa = 0;
|
||||
bb = parseFloat(b[0].replace(/[^0-9.-]/g,''));
|
||||
if (isNaN(bb)) bb = 0;
|
||||
return aa-bb;
|
||||
},
|
||||
sort_alpha: function(a,b) {
|
||||
if (a[0]==b[0]) return 0;
|
||||
if (a[0]<b[0]) return -1;
|
||||
return 1;
|
||||
},
|
||||
sort_ddmm: function(a,b) {
|
||||
mtch = a[0].match(sorttable.DATE_RE);
|
||||
y = mtch[3]; m = mtch[2]; d = mtch[1];
|
||||
if (m.length == 1) m = '0'+m;
|
||||
if (d.length == 1) d = '0'+d;
|
||||
dt1 = y+m+d;
|
||||
mtch = b[0].match(sorttable.DATE_RE);
|
||||
y = mtch[3]; m = mtch[2]; d = mtch[1];
|
||||
if (m.length == 1) m = '0'+m;
|
||||
if (d.length == 1) d = '0'+d;
|
||||
dt2 = y+m+d;
|
||||
if (dt1==dt2) return 0;
|
||||
if (dt1<dt2) return -1;
|
||||
return 1;
|
||||
},
|
||||
sort_mmdd: function(a,b) {
|
||||
mtch = a[0].match(sorttable.DATE_RE);
|
||||
y = mtch[3]; d = mtch[2]; m = mtch[1];
|
||||
if (m.length == 1) m = '0'+m;
|
||||
if (d.length == 1) d = '0'+d;
|
||||
dt1 = y+m+d;
|
||||
mtch = b[0].match(sorttable.DATE_RE);
|
||||
y = mtch[3]; d = mtch[2]; m = mtch[1];
|
||||
if (m.length == 1) m = '0'+m;
|
||||
if (d.length == 1) d = '0'+d;
|
||||
dt2 = y+m+d;
|
||||
if (dt1==dt2) return 0;
|
||||
if (dt1<dt2) return -1;
|
||||
return 1;
|
||||
},
|
||||
|
||||
shaker_sort: function(list, comp_func) {
|
||||
// A stable sort function to allow multi-level sorting of data
|
||||
// see: http://en.wikipedia.org/wiki/Cocktail_sort
|
||||
// thanks to Joseph Nahmias
|
||||
var b = 0;
|
||||
var t = list.length - 1;
|
||||
var swap = true;
|
||||
|
||||
while(swap) {
|
||||
swap = false;
|
||||
for(var i = b; i < t; ++i) {
|
||||
if ( comp_func(list[i], list[i+1]) > 0 ) {
|
||||
var q = list[i]; list[i] = list[i+1]; list[i+1] = q;
|
||||
swap = true;
|
||||
}
|
||||
} // for
|
||||
t--;
|
||||
|
||||
if (!swap) break;
|
||||
|
||||
for(var i = t; i > b; --i) {
|
||||
if ( comp_func(list[i], list[i-1]) < 0 ) {
|
||||
var q = list[i]; list[i] = list[i-1]; list[i-1] = q;
|
||||
swap = true;
|
||||
}
|
||||
} // for
|
||||
b++;
|
||||
|
||||
} // while(swap)
|
||||
}
|
||||
}
|
||||
|
||||
/* ******************************************************************
|
||||
Supporting functions: bundled here to avoid depending on a library
|
||||
****************************************************************** */
|
||||
|
||||
// Dean Edwards/Matthias Miller/John Resig
|
||||
|
||||
/* for Mozilla/Opera9 */
|
||||
if (document.addEventListener) {
|
||||
document.addEventListener("DOMContentLoaded", sorttable.init, false);
|
||||
}
|
||||
|
||||
/* for Internet Explorer */
|
||||
/*@cc_on @*/
|
||||
/*@if (@_win32)
|
||||
document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
|
||||
var script = document.getElementById("__ie_onload");
|
||||
script.onreadystatechange = function() {
|
||||
if (this.readyState == "complete") {
|
||||
sorttable.init(); // call the onload handler
|
||||
}
|
||||
};
|
||||
/*@end @*/
|
||||
|
||||
/* for Safari */
|
||||
if (/WebKit/i.test(navigator.userAgent)) { // sniff
|
||||
var _timer = setInterval(function() {
|
||||
if (/loaded|complete/.test(document.readyState)) {
|
||||
sorttable.init(); // call the onload handler
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
|
||||
/* for other browsers */
|
||||
window.onload = sorttable.init;
|
||||
|
||||
// written by Dean Edwards, 2005
|
||||
// with input from Tino Zijdel, Matthias Miller, Diego Perini
|
||||
|
||||
// http://dean.edwards.name/weblog/2005/10/add-event/
|
||||
|
||||
function dean_addEvent(element, type, handler) {
|
||||
if (element.addEventListener) {
|
||||
element.addEventListener(type, handler, false);
|
||||
} else {
|
||||
// assign each event handler a unique ID
|
||||
if (!handler.$$guid) handler.$$guid = dean_addEvent.guid++;
|
||||
// create a hash table of event types for the element
|
||||
if (!element.events) element.events = {};
|
||||
// create a hash table of event handlers for each element/event pair
|
||||
var handlers = element.events[type];
|
||||
if (!handlers) {
|
||||
handlers = element.events[type] = {};
|
||||
// store the existing event handler (if there is one)
|
||||
if (element["on" + type]) {
|
||||
handlers[0] = element["on" + type];
|
||||
}
|
||||
}
|
||||
// store the event handler in the hash table
|
||||
handlers[handler.$$guid] = handler;
|
||||
// assign a global event handler to do all the work
|
||||
element["on" + type] = handleEvent;
|
||||
}
|
||||
};
|
||||
// a counter used to create unique IDs
|
||||
dean_addEvent.guid = 1;
|
||||
|
||||
function removeEvent(element, type, handler) {
|
||||
if (element.removeEventListener) {
|
||||
element.removeEventListener(type, handler, false);
|
||||
} else {
|
||||
// delete the event handler from the hash table
|
||||
if (element.events && element.events[type]) {
|
||||
delete element.events[type][handler.$$guid];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function handleEvent(event) {
|
||||
var returnValue = true;
|
||||
// grab the event object (IE uses a global event object)
|
||||
event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
|
||||
// get a reference to the hash table of event handlers
|
||||
var handlers = this.events[event.type];
|
||||
// execute each event handler
|
||||
for (var i in handlers) {
|
||||
this.$$handleEvent = handlers[i];
|
||||
if (this.$$handleEvent(event) === false) {
|
||||
returnValue = false;
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
};
|
||||
|
||||
function fixEvent(event) {
|
||||
// add W3C standard event methods
|
||||
event.preventDefault = fixEvent.preventDefault;
|
||||
event.stopPropagation = fixEvent.stopPropagation;
|
||||
return event;
|
||||
};
|
||||
fixEvent.preventDefault = function() {
|
||||
this.returnValue = false;
|
||||
};
|
||||
fixEvent.stopPropagation = function() {
|
||||
this.cancelBubble = true;
|
||||
}
|
||||
|
||||
// Dean's forEach: http://dean.edwards.name/base/forEach.js
|
||||
/*
|
||||
forEach, version 1.0
|
||||
Copyright 2006, Dean Edwards
|
||||
License: http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
// array-like enumeration
|
||||
if (!Array.forEach) { // mozilla already supports this
|
||||
Array.forEach = function(array, block, context) {
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
block.call(context, array[i], i, array);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// generic enumeration
|
||||
Function.prototype.forEach = function(object, block, context) {
|
||||
for (var key in object) {
|
||||
if (typeof this.prototype[key] == "undefined") {
|
||||
block.call(context, object[key], key, object);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// character enumeration
|
||||
String.forEach = function(string, block, context) {
|
||||
Array.forEach(string.split(""), function(chr, index) {
|
||||
block.call(context, chr, index, string);
|
||||
});
|
||||
};
|
||||
|
||||
// globally resolve forEach enumeration
|
||||
var forEach = function(object, block, context) {
|
||||
if (object) {
|
||||
var resolve = Object; // default
|
||||
if (object instanceof Function) {
|
||||
// functions have a "length" property
|
||||
resolve = Function;
|
||||
} else if (object.forEach instanceof Function) {
|
||||
// the object implements a custom forEach method so use that
|
||||
object.forEach(block, context);
|
||||
return;
|
||||
} else if (typeof object == "string") {
|
||||
// the object is a string
|
||||
resolve = String;
|
||||
} else if (typeof object.length == "number") {
|
||||
// the object is array-like
|
||||
resolve = Array;
|
||||
}
|
||||
resolve.forEach(object, block, context);
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
table.thinborder {
|
||||
border-collapse:collapse;
|
||||
border:solid #999;
|
||||
border-width:1px 0 0 1px;
|
||||
}
|
||||
table.thinborder caption {font-size:14px;font-weight:bolder;}
|
||||
table.thinborder th,table.thinborder td {
|
||||
border:solid #999;
|
||||
border-width:0 1px 1px 0;
|
||||
padding:2px;
|
||||
word-break : keep-all;
|
||||
white-space:nowrap;
|
||||
}
|
||||
|
||||
table.sortablet foot td {text-align:center;background: #ECF20F;}
|
||||
table.sortable thead td {text-align:center;background: #ECF20F;}
|
||||
|
||||
table.sortable tr.odd{background: #ECFCCC;}
|
||||
table.sortable tr.even{background: #FFFFFF;}
|
||||
table.sortable tr.over{background: #ECF2AF;}
|
||||
|
||||
td.lbl{
|
||||
text-align: right;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
function del(act){
|
||||
var ind = act.indexOf("?");
|
||||
if(ind == -1){
|
||||
go(act+"?act=del");
|
||||
}else{
|
||||
go(act+"&act=del");
|
||||
}
|
||||
}
|
||||
function go(act,target){
|
||||
var fm =document.getElementById("goForm");
|
||||
//clear
|
||||
var eles = fm.elements;
|
||||
if(eles != null && eles.length > 0){
|
||||
for(var i=0;i<eles.length;i++){
|
||||
fm.removeChild(eles[i]);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
fm.target = "_self";
|
||||
//action?a=1&b=2
|
||||
var ind = act.indexOf("?");
|
||||
if(ind == -1){
|
||||
fm.action = act;
|
||||
}else{
|
||||
fm.action = act.substring(0,ind);
|
||||
var parms = act.substring(ind+1);
|
||||
if(parms !=null && parms.length > 0){
|
||||
var arr=parms.split("&");
|
||||
if(arr!=null && arr.length>0){
|
||||
for(var i=0;i<arr.length;i++){
|
||||
if(arr[i] == null || arr[i].length == 0){
|
||||
continue;
|
||||
}
|
||||
var pv = arr[i].split("=");
|
||||
if(pv == null || pv.length==0 || pv[0] == null){
|
||||
continue;
|
||||
}
|
||||
var inp = document.createElement("input");
|
||||
inp.setAttribute("type","hidden");
|
||||
inp.setAttribute("name",pv[0]);
|
||||
if(pv.length == 2){
|
||||
inp.setAttribute("value",pv[1]);
|
||||
}
|
||||
fm.appendChild(inp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//submit
|
||||
if(target){
|
||||
fm.target = target;
|
||||
}
|
||||
fm.submit();
|
||||
}
|
||||
|
||||
document.write("<form id='goForm' name='goForm' action='#' method='post'></form>");
|
After Width: | Height: | Size: 825 B |
After Width: | Height: | Size: 251 B |
After Width: | Height: | Size: 105 B |
After Width: | Height: | Size: 106 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1,71 @@
|
|||
.treeview {
|
||||
font-family: Verdana, helvetica, arial, sans-serif;
|
||||
font-size: 68.75%;
|
||||
background: #fff;
|
||||
color: #333;
|
||||
}
|
||||
.treeview, .treeview ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.treeview ul {
|
||||
background-color: white;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.treeview .closed ul {display:none;}
|
||||
.treeview .hit {
|
||||
background: url(images/treeview-default.gif) -64px -25px no-repeat;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin-left: -16px;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* fix for IE6 */
|
||||
* html .hit {
|
||||
display: inline;
|
||||
float:none;
|
||||
}
|
||||
|
||||
.treeview li {
|
||||
margin: 0;
|
||||
padding: 3px 0pt 3px 16px;
|
||||
}
|
||||
|
||||
.treeview a.selected {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
#treecontrol { margin: 1em 0; display: none; }
|
||||
|
||||
.treeview .hover { color: red; cursor: pointer; }
|
||||
.treeview a {background:none;text-decoration:none;color:#000;}
|
||||
.treeview a:visited {color:#000;}
|
||||
|
||||
.treeview li { background: url(images/treeview-default-line.gif) 0 0 no-repeat; }
|
||||
.treeview li.open, .treeview li.closed { background-position: 0 -176px; }
|
||||
|
||||
.treeview .closed-hit { background-position: -80px -3px; }
|
||||
|
||||
.treeview li.last { background-position: 0 -1766px }
|
||||
.treeview li.lastopen, .treeview li.lastclosed { background-image: url(images/treeview-default.gif); }
|
||||
.treeview li.lastopen { background-position: 0 -111px }
|
||||
.treeview li.lastclosed { background-position: -32px -67px }
|
||||
|
||||
.treeview div.lastopen-hit, .treeview div.lastclosed-hit { background-position: 0; }
|
||||
|
||||
.treeview span.loading {
|
||||
background: url(images/ajax-loader.gif) 0 0 no-repeat;
|
||||
display: block;
|
||||
cursor: wait;
|
||||
padding: 1px 0 1px 16px;
|
||||
}
|
||||
|
||||
.filetree li { padding: 3px 0 2px 16px; }
|
||||
.filetree span.folder, .filetree span.file {padding: 1px 0 1px 16px; display: block; }
|
||||
.filetree span.folder {cursor: pointer;background: url(images/folder.gif) 0 0 no-repeat; }
|
||||
.filetree li.closed span.folder { background: url(images/folder-closed.gif) 0 0 no-repeat; }
|
||||
.filetree span.file { background: url(images/file.gif) 0 0 no-repeat; }
|
|
@ -0,0 +1,120 @@
|
|||
var AjaxTreeView={
|
||||
config:{
|
||||
classLoading: "loading",//ajax loading css
|
||||
ontoggle : null,//function(o,b) when toggle folder.o:li,b:is open
|
||||
onclick : null,//function(o,a) when click text.o: li;a:a
|
||||
url:"ajaxTreeService.ajax",//ajax load url
|
||||
attrs:["treeId","treeParentId"]
|
||||
},
|
||||
|
||||
open:function(o){//li
|
||||
var $o=$(o),b=$o.hasClass("closed"),$div=$o.children("div").first();
|
||||
if(b){//open
|
||||
var isl=!o.loading && !o.loaded && ($o.attr("treeId")!=null||$o.attr("treeParentId")!=null);
|
||||
if(isl){
|
||||
o.loading=true;
|
||||
AjaxTreeView.load(o);
|
||||
}
|
||||
$div.removeClass("closed-hit");
|
||||
$o.removeClass("closed");
|
||||
|
||||
$div.addClass("open-hit");
|
||||
$o.addClass("open");
|
||||
//last?
|
||||
if($o.hasClass("lastclosed")){
|
||||
$o.removeClass("lastclosed");
|
||||
$o.addClass("lastopen");
|
||||
}
|
||||
if($div.hasClass("lastclosed-hit")){
|
||||
$div.removeClass("lastclosed-hit");
|
||||
$div.addClass("lastopen-hit");
|
||||
}
|
||||
}
|
||||
},
|
||||
close:function(o){//li
|
||||
var $o=$(o),b=$o.hasClass("open"),$div=$o.children("div").first();
|
||||
if(b){//close
|
||||
$div.removeClass("open-hit");
|
||||
$o.removeClass("open");
|
||||
|
||||
$div.addClass("closed-hit");
|
||||
$o.addClass("closed");
|
||||
//last?
|
||||
if($o.hasClass("lastopen")){
|
||||
$o.removeClass("lastopen");
|
||||
$o.addClass("lastclosed");
|
||||
}
|
||||
if($div.hasClass("lastopen-hit")){
|
||||
$div.removeClass("lastopen-hit");
|
||||
$div.addClass("lastclosed-hit");
|
||||
}
|
||||
}
|
||||
},
|
||||
toggle:function(o){//li
|
||||
var $o=$(o),c="closed",b=$o.hasClass(c);
|
||||
if(b){//open
|
||||
AjaxTreeView.open(o);
|
||||
}else{//close
|
||||
AjaxTreeView.close(o);
|
||||
}
|
||||
|
||||
if(typeof(AjaxTreeView.config.ontoggle)=="function"){//call ontoggle
|
||||
return AjaxTreeView.config.ontoggle(o,b);
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
},
|
||||
load:function(o,func){//li,func
|
||||
if(o.loaded){
|
||||
return;
|
||||
}
|
||||
var $o=$(o),$span = $o.children("span").first();
|
||||
$span.attr("class",AjaxTreeView.config.classLoading);
|
||||
|
||||
var pa=AjaxTreeView.getParams(o);
|
||||
$.post(AjaxTreeView.config.url,pa,
|
||||
function(d){
|
||||
if(d.length>0){
|
||||
//$(o.children[o.children.length-1]).after(d);//not good
|
||||
$o.append(d);
|
||||
}
|
||||
o.loaded=true;
|
||||
o.loading=false;
|
||||
$span.attr("class","folder");
|
||||
if(typeof(func)=="function"){
|
||||
func(o,d);
|
||||
}
|
||||
}
|
||||
,"html");
|
||||
},
|
||||
getParams:function(o){//eg. {suggest:txt}
|
||||
var n, v;
|
||||
var r={};
|
||||
for (var i = 0; i < AjaxTreeView.config.attrs.length; i++) {
|
||||
n = AjaxTreeView.config.attrs[i];
|
||||
v = o.getAttribute(n);
|
||||
if (v) {
|
||||
r[AjaxTreeView.config.attrs[i]]=v;
|
||||
}
|
||||
}
|
||||
var p=o.getAttribute("param");//eg a=1&b=2
|
||||
if(p!=null&&p!=""){
|
||||
var ar = p.split("&");
|
||||
for(var j=0;j<ar.length;j++){
|
||||
var nvr = ar[j].split("=");
|
||||
r[nvr[0]]=nvr[1];
|
||||
}
|
||||
}
|
||||
//console.log(r);
|
||||
return r;
|
||||
},
|
||||
click:function(a){
|
||||
if(typeof(AjaxTreeView.config.onclick)=="function"){//call onclick
|
||||
return AjaxTreeView.config.onclick(a.parentNode.parentNode,a);
|
||||
}
|
||||
},
|
||||
|
||||
end:""
|
||||
};
|
||||
var $att = function(o){AjaxTreeView.toggle(o.parentNode);};
|
||||
var $atc = AjaxTreeView.click;
|