mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
First pass of Ajax object picker framework and JSF UI component wrappers. Ajax folder picker implementation.
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@7429 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
131
source/java/org/alfresco/web/bean/ajax/JSONWriter.java
Normal file
131
source/java/org/alfresco/web/bean/ajax/JSONWriter.java
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing
|
||||||
|
*/
|
||||||
|
package org.alfresco.web.bean.ajax;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Very simple JSON writer. Wraps a Writer to output a JSON stream.
|
||||||
|
*
|
||||||
|
* @author Kevin Roast
|
||||||
|
*/
|
||||||
|
public class JSONWriter
|
||||||
|
{
|
||||||
|
private Writer out;
|
||||||
|
private Stack<Boolean> stack = new Stack<Boolean>();
|
||||||
|
|
||||||
|
public JSONWriter(Writer out)
|
||||||
|
{
|
||||||
|
this.out = out;
|
||||||
|
stack.push(Boolean.FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startArray() throws IOException
|
||||||
|
{
|
||||||
|
if (stack.peek() == true) out.write(", ");
|
||||||
|
out.write("[");
|
||||||
|
stack.pop();
|
||||||
|
stack.push(Boolean.TRUE);
|
||||||
|
stack.push(Boolean.FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endArray() throws IOException
|
||||||
|
{
|
||||||
|
out.write("]");
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startObject() throws IOException
|
||||||
|
{
|
||||||
|
if (stack.peek() == true) out.write(", ");
|
||||||
|
out.write("{");
|
||||||
|
stack.pop();
|
||||||
|
stack.push(Boolean.TRUE);
|
||||||
|
stack.push(Boolean.FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endObject() throws IOException
|
||||||
|
{
|
||||||
|
out.write("}");
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startValue(String name) throws IOException
|
||||||
|
{
|
||||||
|
if (stack.peek() == true) out.write(", ");
|
||||||
|
out.write(name);
|
||||||
|
out.write(": ");
|
||||||
|
stack.pop();
|
||||||
|
stack.push(Boolean.TRUE);
|
||||||
|
stack.push(Boolean.FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endValue()
|
||||||
|
{
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeValue(String name, String value) throws IOException
|
||||||
|
{
|
||||||
|
if (stack.peek() == true) out.write(", ");
|
||||||
|
out.write(name);
|
||||||
|
out.write(": \"");
|
||||||
|
out.write(value);
|
||||||
|
out.write('"');
|
||||||
|
stack.pop();
|
||||||
|
stack.push(Boolean.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeValue(String name, int value) throws IOException
|
||||||
|
{
|
||||||
|
if (stack.peek() == true) out.write(", ");
|
||||||
|
out.write(name);
|
||||||
|
out.write(": ");
|
||||||
|
out.write(Integer.toString(value));
|
||||||
|
stack.pop();
|
||||||
|
stack.push(Boolean.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeValue(String name, boolean value) throws IOException
|
||||||
|
{
|
||||||
|
if (stack.peek() == true) out.write(", ");
|
||||||
|
out.write(name);
|
||||||
|
out.write(": ");
|
||||||
|
out.write(Boolean.toString(value));
|
||||||
|
stack.pop();
|
||||||
|
stack.push(Boolean.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeNullValue(String name) throws IOException
|
||||||
|
{
|
||||||
|
if (stack.peek() == true) out.write(", ");
|
||||||
|
out.write(name);
|
||||||
|
out.write(": null");
|
||||||
|
stack.pop();
|
||||||
|
stack.push(Boolean.TRUE);
|
||||||
|
}
|
||||||
|
}
|
237
source/java/org/alfresco/web/bean/ajax/PickerBean.java
Normal file
237
source/java/org/alfresco/web/bean/ajax/PickerBean.java
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing
|
||||||
|
*/
|
||||||
|
package org.alfresco.web.bean.ajax;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.faces.context.FacesContext;
|
||||||
|
import javax.transaction.UserTransaction;
|
||||||
|
|
||||||
|
import org.alfresco.model.ApplicationModel;
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.content.MimetypeMap;
|
||||||
|
import org.alfresco.service.cmr.model.FileFolderService;
|
||||||
|
import org.alfresco.service.cmr.model.FileInfo;
|
||||||
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.search.CategoryService;
|
||||||
|
import org.alfresco.web.app.Application;
|
||||||
|
import org.alfresco.web.app.servlet.ajax.InvokeCommand;
|
||||||
|
import org.alfresco.web.bean.BrowseBean;
|
||||||
|
import org.alfresco.web.bean.repository.Repository;
|
||||||
|
import org.alfresco.web.ui.common.Utils;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bean backing the ajax requests for the ajax based picker components.
|
||||||
|
*
|
||||||
|
* @author Kevin Roast
|
||||||
|
*/
|
||||||
|
public class PickerBean
|
||||||
|
{
|
||||||
|
private static Log logger = LogFactory.getLog(PickerBean.class);
|
||||||
|
|
||||||
|
private CategoryService categoryService;
|
||||||
|
private NodeService nodeService;
|
||||||
|
private NodeService internalNodeService;
|
||||||
|
private FileFolderService fileFolderService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param categoryService The categoryService to set
|
||||||
|
*/
|
||||||
|
public void setCategoryService(CategoryService categoryService)
|
||||||
|
{
|
||||||
|
this.categoryService = categoryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nodeService The nodeService to set
|
||||||
|
*/
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param internalNodeService The internalNodeService to set.
|
||||||
|
*/
|
||||||
|
public void setInternalNodeService(NodeService internalNodeService)
|
||||||
|
{
|
||||||
|
this.internalNodeService = internalNodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param fileFolderService the FileFolderService to set
|
||||||
|
*/
|
||||||
|
public void setFileFolderService(FileFolderService fileFolderService)
|
||||||
|
{
|
||||||
|
this.fileFolderService = fileFolderService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
|
||||||
|
public void getCategoryNodes() throws Exception
|
||||||
|
{
|
||||||
|
FacesContext fc = FacesContext.getCurrentInstance();
|
||||||
|
|
||||||
|
UserTransaction tx = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tx = Repository.getUserTransaction(FacesContext.getCurrentInstance(), true);
|
||||||
|
tx.begin();
|
||||||
|
|
||||||
|
Collection<ChildAssociationRef> childRefs;
|
||||||
|
NodeRef parentRef = null;
|
||||||
|
Map params = fc.getExternalContext().getRequestParameterMap();
|
||||||
|
String strParentRef = (String)params.get("parent");
|
||||||
|
if (strParentRef == null || strParentRef.length() == 0)
|
||||||
|
{
|
||||||
|
childRefs = this.categoryService.getRootCategories(
|
||||||
|
Repository.getStoreRef(),
|
||||||
|
ContentModel.ASPECT_GEN_CLASSIFIABLE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parentRef = new NodeRef(strParentRef);
|
||||||
|
childRefs = this.categoryService.getChildren(
|
||||||
|
parentRef,
|
||||||
|
CategoryService.Mode.SUB_CATEGORIES,
|
||||||
|
CategoryService.Depth.IMMEDIATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONWriter out = new JSONWriter(fc.getResponseWriter());
|
||||||
|
out.startObject();
|
||||||
|
out.startValue("parent");
|
||||||
|
out.startObject();
|
||||||
|
if (parentRef == null)
|
||||||
|
{
|
||||||
|
out.writeNullValue("id");
|
||||||
|
out.writeValue("name", "Categories");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.writeValue("id", strParentRef);
|
||||||
|
out.writeValue("name", Repository.getNameForNode(this.internalNodeService, parentRef));
|
||||||
|
}
|
||||||
|
out.endObject();
|
||||||
|
out.endValue();
|
||||||
|
out.startValue("children");
|
||||||
|
out.startArray();
|
||||||
|
for (ChildAssociationRef ref : childRefs)
|
||||||
|
{
|
||||||
|
NodeRef nodeRef = ref.getChildRef();
|
||||||
|
out.startObject();
|
||||||
|
out.writeValue("id", nodeRef.toString());
|
||||||
|
out.writeValue("name", Repository.getNameForNode(this.internalNodeService, nodeRef));
|
||||||
|
out.endObject();
|
||||||
|
}
|
||||||
|
out.endArray();
|
||||||
|
out.endValue();
|
||||||
|
out.endObject();
|
||||||
|
|
||||||
|
tx.commit();
|
||||||
|
}
|
||||||
|
catch (Throwable err)
|
||||||
|
{
|
||||||
|
Utils.addErrorMessage("PickerBean exception in getCategoryRootNodes()", err);
|
||||||
|
fc.getResponseWriter().write("ERROR: " + err.getMessage());
|
||||||
|
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@InvokeCommand.ResponseMimetype(value=MimetypeMap.MIMETYPE_HTML)
|
||||||
|
public void getFolderNodes() throws Exception
|
||||||
|
{
|
||||||
|
FacesContext fc = FacesContext.getCurrentInstance();
|
||||||
|
|
||||||
|
UserTransaction tx = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tx = Repository.getUserTransaction(FacesContext.getCurrentInstance(), true);
|
||||||
|
tx.begin();
|
||||||
|
|
||||||
|
List<ChildAssociationRef> childRefs;
|
||||||
|
NodeRef parentRef = null;
|
||||||
|
Map params = fc.getExternalContext().getRequestParameterMap();
|
||||||
|
String strParentRef = (String)params.get("parent");
|
||||||
|
if (strParentRef == null || strParentRef.length() == 0)
|
||||||
|
{
|
||||||
|
parentRef = new NodeRef(Repository.getStoreRef(), Application.getCompanyRootId(fc));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parentRef = new NodeRef(strParentRef);
|
||||||
|
}
|
||||||
|
List<FileInfo> folders = this.fileFolderService.listFolders(parentRef);
|
||||||
|
|
||||||
|
JSONWriter out = new JSONWriter(fc.getResponseWriter());
|
||||||
|
out.startObject();
|
||||||
|
out.startValue("parent");
|
||||||
|
out.startObject();
|
||||||
|
if (strParentRef == null || strParentRef.length() == 0)
|
||||||
|
{
|
||||||
|
out.writeNullValue("id");
|
||||||
|
out.writeValue("name", Repository.getNameForNode(this.internalNodeService, parentRef));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.writeValue("id", strParentRef);
|
||||||
|
out.writeValue("name", Repository.getNameForNode(this.internalNodeService, parentRef));
|
||||||
|
}
|
||||||
|
out.endObject();
|
||||||
|
out.endValue();
|
||||||
|
out.startValue("children");
|
||||||
|
out.startArray();
|
||||||
|
|
||||||
|
// filter out those children that are not spaces
|
||||||
|
for (FileInfo folder : folders)
|
||||||
|
{
|
||||||
|
out.startObject();
|
||||||
|
out.writeValue("id", folder.getNodeRef().toString());
|
||||||
|
out.writeValue("name", (String)folder.getProperties().get(ContentModel.PROP_NAME));
|
||||||
|
String icon = (String)folder.getProperties().get(ApplicationModel.PROP_ICON);
|
||||||
|
out.writeValue("icon", (icon != null ? icon + "-16.gif" : BrowseBean.SPACE_SMALL_DEFAULT + ".gif"));
|
||||||
|
out.endObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
out.endArray();
|
||||||
|
out.endValue();
|
||||||
|
out.endObject();
|
||||||
|
|
||||||
|
tx.commit();
|
||||||
|
}
|
||||||
|
catch (Throwable err)
|
||||||
|
{
|
||||||
|
Utils.addErrorMessage("PickerBean exception in getFolderNodes()", err);
|
||||||
|
fc.getResponseWriter().write("ERROR: " + err.getMessage());
|
||||||
|
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -81,7 +81,7 @@ public class UIMenu extends SelfRenderingComponent
|
|||||||
// output image
|
// output image
|
||||||
if (getAttributes().get("image") != null)
|
if (getAttributes().get("image") != null)
|
||||||
{
|
{
|
||||||
out.write(Utils.buildImageTag(context, (String)getAttributes().get("image"), null, "middle"));
|
out.write(Utils.buildImageTag(context, (String)getAttributes().get("image"), null, "-4px"));
|
||||||
}
|
}
|
||||||
|
|
||||||
out.write("</a>");
|
out.write("</a>");
|
||||||
|
@@ -142,7 +142,7 @@ public class ActionLinkRenderer extends BaseRenderer
|
|||||||
renderActionLinkAnchor(context, out, link);
|
renderActionLinkAnchor(context, out, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
out.write(Utils.buildImageTag(context, image, (String)link.getValue(), "middle"));
|
out.write(Utils.buildImageTag(context, image, (String)link.getValue(), "-4px"));
|
||||||
|
|
||||||
if (link.getShowLink() == false)
|
if (link.getShowLink() == false)
|
||||||
{
|
{
|
||||||
|
@@ -214,7 +214,7 @@ public class ModeListRenderer extends BaseRenderer
|
|||||||
// output image
|
// output image
|
||||||
if (list.getMenuImage() != null)
|
if (list.getMenuImage() != null)
|
||||||
{
|
{
|
||||||
out.write(Utils.buildImageTag(context, list.getMenuImage(), null, "middle"));
|
out.write(Utils.buildImageTag(context, list.getMenuImage(), null, "-4px"));
|
||||||
}
|
}
|
||||||
|
|
||||||
out.write("</a></td></tr></table>");
|
out.write("</a></td></tr></table>");
|
||||||
|
@@ -0,0 +1,328 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing
|
||||||
|
*/
|
||||||
|
package org.alfresco.web.ui.repo.component;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
import javax.faces.component.UIInput;
|
||||||
|
import javax.faces.context.FacesContext;
|
||||||
|
import javax.faces.context.ResponseWriter;
|
||||||
|
import javax.faces.el.ValueBinding;
|
||||||
|
import javax.faces.event.AbortProcessingException;
|
||||||
|
import javax.faces.event.FacesEvent;
|
||||||
|
|
||||||
|
import org.alfresco.web.app.Application;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Kevin Roast
|
||||||
|
*/
|
||||||
|
public abstract class BaseAjaxItemPicker extends UIInput
|
||||||
|
{
|
||||||
|
private static final String MSG_GO_UP = "go_up";
|
||||||
|
private static final String MSG_OK = "ok";
|
||||||
|
private static final String MSG_CANCEL = "cancel";
|
||||||
|
|
||||||
|
/** label to be displayed before an item is selected */
|
||||||
|
protected String label = null;
|
||||||
|
|
||||||
|
/** id of the initially selected item, if value is not set */
|
||||||
|
protected String initialSelectionId = null;
|
||||||
|
|
||||||
|
/** flag to show whether the component is disabled */
|
||||||
|
protected Boolean disabled;
|
||||||
|
|
||||||
|
/** True for single select mode, false for multi-select mode */
|
||||||
|
protected Boolean singleSelect;
|
||||||
|
|
||||||
|
protected static int ACTION_DONE = 0;
|
||||||
|
protected static int ACTION_CANCEL = 1;
|
||||||
|
|
||||||
|
|
||||||
|
public BaseAjaxItemPicker()
|
||||||
|
{
|
||||||
|
setRendererType(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see javax.faces.component.UIComponent#getFamily()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public abstract String getFamily();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext, java.lang.Object)
|
||||||
|
*/
|
||||||
|
public void restoreState(FacesContext context, Object state)
|
||||||
|
{
|
||||||
|
Object values[] = (Object[])state;
|
||||||
|
// standard component attributes are restored by the super class
|
||||||
|
super.restoreState(context, values[0]);
|
||||||
|
this.label = (String)values[1];
|
||||||
|
this.singleSelect = (Boolean)values[2];
|
||||||
|
this.initialSelectionId = (String)values[3];
|
||||||
|
this.disabled = (Boolean)values[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see javax.faces.component.StateHolder#saveState(javax.faces.context.FacesContext)
|
||||||
|
*/
|
||||||
|
public Object saveState(FacesContext context)
|
||||||
|
{
|
||||||
|
Object values[] = new Object[] {
|
||||||
|
// standard component attributes are saved by the super class
|
||||||
|
super.saveState(context),
|
||||||
|
this.label,
|
||||||
|
this.singleSelect,
|
||||||
|
this.initialSelectionId,
|
||||||
|
this.disabled};
|
||||||
|
return (values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see javax.faces.component.UIComponentBase#decode(javax.faces.context.FacesContext)
|
||||||
|
*/
|
||||||
|
public void decode(FacesContext context)
|
||||||
|
{
|
||||||
|
Map requestMap = context.getExternalContext().getRequestParameterMap();
|
||||||
|
String fieldId = getHiddenFieldName();
|
||||||
|
String value = (String)requestMap.get(fieldId);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see javax.faces.component.UIInput#broadcast(javax.faces.event.FacesEvent)
|
||||||
|
*/
|
||||||
|
public void broadcast(FacesEvent event) throws AbortProcessingException
|
||||||
|
{
|
||||||
|
super.broadcast(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see javax.faces.component.UIComponentBase#encodeBegin(javax.faces.context.FacesContext)
|
||||||
|
*/
|
||||||
|
public void encodeBegin(FacesContext fc) throws IOException
|
||||||
|
{
|
||||||
|
if (isRendered() == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResponseWriter out = fc.getResponseWriter();
|
||||||
|
|
||||||
|
ResourceBundle msg = Application.getBundle(fc);
|
||||||
|
|
||||||
|
// TODO: from submitted value or 'none'
|
||||||
|
String selection = "none";
|
||||||
|
|
||||||
|
// TODO: output images with context correctly
|
||||||
|
|
||||||
|
String divId = getId();
|
||||||
|
String objId = divId + "Obj";
|
||||||
|
String contextPath = fc.getExternalContext().getRequestContextPath();
|
||||||
|
out.write("<script type='text/javascript'>");
|
||||||
|
out.write("function init" + divId + "() {");
|
||||||
|
out.write(" window." + objId + " = new AlfPicker('" + divId + "','" + objId + "','" + getServiceCall() + "'," + getSingleSelect() + ");");
|
||||||
|
if (getInitialSelection() != null)
|
||||||
|
{
|
||||||
|
out.write(" window." + objId + ".setStartId('" + getInitialSelection() + "');");
|
||||||
|
}
|
||||||
|
out.write("}");
|
||||||
|
out.write(" window.addEvent('domready', init" + divId + ");");
|
||||||
|
out.write("</script>");
|
||||||
|
|
||||||
|
out.write("<div id='" + divId + "' class='picker'>") ;
|
||||||
|
out.write(" <input id='" + divId + "-value' name='" + divId + "-value' type='hidden'>");
|
||||||
|
out.write(" <div id='" + divId + "-noitems' class='pickerNoSelectedItems'>");
|
||||||
|
out.write(" <span><" + selection + "></span>");
|
||||||
|
out.write(" <span class='pickerActionButton'><a href='#' onclick='" + objId + ".showSelector();'>");
|
||||||
|
out.write(msg.getString(getLabel()));
|
||||||
|
out.write("</a></span>");
|
||||||
|
out.write(" </div>");
|
||||||
|
// container for item navigation
|
||||||
|
out.write(" <div id='" + divId + "-selector' class='pickerSelector'>");
|
||||||
|
out.write(" <div class='pickerResults'>");
|
||||||
|
out.write(" <div class='pickerResultsHeader'>");
|
||||||
|
out.write(" <div class='pickerNavControls'>");
|
||||||
|
out.write(" <span class='pickerNavUp'>");
|
||||||
|
out.write(" <a id='" + divId + "-nav-up' href='#'><img src='");
|
||||||
|
out.write(contextPath);
|
||||||
|
out.write("/images/icons/arrow_up.gif' border='0' alt='");
|
||||||
|
out.write(msg.getString(MSG_GO_UP));
|
||||||
|
out.write("' title='");
|
||||||
|
out.write(msg.getString(MSG_GO_UP));
|
||||||
|
out.write("'></a>");
|
||||||
|
out.write(" </span>");
|
||||||
|
out.write(" <span class='pickerNavBreadcrumb'>");
|
||||||
|
out.write(" <div id='" + divId + "-nav-bread' class='pickerNavBreadcrumbPanel'></div>");
|
||||||
|
out.write(" <a href='#' onclick='" + objId + ".breadcrumbToggle();'><span id='" + divId + "-nav-txt'></span><img border='0' src='");
|
||||||
|
out.write(contextPath);
|
||||||
|
out.write("/images/icons/arrow_open.gif'></a>");
|
||||||
|
out.write(" </span>");
|
||||||
|
out.write(" </div>");
|
||||||
|
out.write(" </div>");
|
||||||
|
// container for item selection
|
||||||
|
out.write(" <div>");
|
||||||
|
out.write(" <div id='" + divId + "-ajax-wait' class='pickerAjaxWait'></div>");
|
||||||
|
out.write(" <div id='" + divId + "-results-list' class='pickerResultsList'></div>");
|
||||||
|
out.write(" </div>");
|
||||||
|
out.write(" </div>");
|
||||||
|
out.write(" <div id='" + divId + "-finish' class='pickerFinishControls'>");
|
||||||
|
out.write(" <div class='pickerDoneButton'><a href='#' onclick='" + objId + ".doneClicked();'>");
|
||||||
|
out.write(msg.getString(MSG_OK));
|
||||||
|
out.write("</a></div>");
|
||||||
|
// TODO: Cancel button
|
||||||
|
out.write(" </div>");
|
||||||
|
out.write(" </div>");
|
||||||
|
// container for selected items
|
||||||
|
out.write(" <div id='" + divId + "-selected' class='pickerSelectedItems'></div>");
|
||||||
|
out.write("</div>");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the ajax service bean call, for instance 'PickerBean.getFolderNodes'
|
||||||
|
*/
|
||||||
|
protected abstract String getServiceCall();
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// Strongly typed component property accessors
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the label.
|
||||||
|
*/
|
||||||
|
public String getLabel()
|
||||||
|
{
|
||||||
|
ValueBinding vb = getValueBinding("label");
|
||||||
|
if (vb != null)
|
||||||
|
{
|
||||||
|
this.label = (String)vb.getValue(getFacesContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param label The label to set.
|
||||||
|
*/
|
||||||
|
public void setLabel(String label)
|
||||||
|
{
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the initial selecttion.
|
||||||
|
*/
|
||||||
|
public String getInitialSelection()
|
||||||
|
{
|
||||||
|
ValueBinding vb = getValueBinding("initialSelection");
|
||||||
|
if (vb != null)
|
||||||
|
{
|
||||||
|
this.initialSelectionId = (String)vb.getValue(getFacesContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.initialSelectionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param initialSelection The initial selection to set.
|
||||||
|
*/
|
||||||
|
public void setInitialSelection(String initialSelection)
|
||||||
|
{
|
||||||
|
this.initialSelectionId = initialSelection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the component should be rendered in a disabled state
|
||||||
|
*
|
||||||
|
* @return Returns whether the component is disabled
|
||||||
|
*/
|
||||||
|
public boolean isDisabled()
|
||||||
|
{
|
||||||
|
if (this.disabled == null)
|
||||||
|
{
|
||||||
|
ValueBinding vb = getValueBinding("disabled");
|
||||||
|
if (vb != null)
|
||||||
|
{
|
||||||
|
this.disabled = (Boolean)vb.getValue(getFacesContext());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.disabled == null ? Boolean.FALSE : this.disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the component should be rendered in a disabled state
|
||||||
|
*
|
||||||
|
* @param disabled true to disable the component
|
||||||
|
*/
|
||||||
|
public void setDisabled(boolean disabled)
|
||||||
|
{
|
||||||
|
this.disabled = disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true is single select mode, false for multi-select
|
||||||
|
*/
|
||||||
|
public Boolean getSingleSelect()
|
||||||
|
{
|
||||||
|
if (this.singleSelect == null)
|
||||||
|
{
|
||||||
|
ValueBinding vb = getValueBinding("singleSelect");
|
||||||
|
if (vb != null)
|
||||||
|
{
|
||||||
|
this.singleSelect = (Boolean)vb.getValue(getFacesContext());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.singleSelect == null ? Boolean.TRUE : this.singleSelect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param singleSelect true for single select mode, false for multi-select
|
||||||
|
*/
|
||||||
|
public void setSingleSelect(Boolean singleSelect)
|
||||||
|
{
|
||||||
|
this.singleSelect = singleSelect;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------
|
||||||
|
// Protected helpers
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We use a unique hidden field name based on our client Id.
|
||||||
|
* This is on the assumption that there won't be many selectors on screen at once!
|
||||||
|
* Also means we have less values to decode on submit.
|
||||||
|
*
|
||||||
|
* @return hidden field name
|
||||||
|
*/
|
||||||
|
protected String getHiddenFieldName()
|
||||||
|
{
|
||||||
|
return this.getClientId(getFacesContext());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing
|
||||||
|
*/
|
||||||
|
package org.alfresco.web.ui.repo.component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Kevin Roast
|
||||||
|
*/
|
||||||
|
public class UIAjaxFolderPicker extends BaseAjaxItemPicker
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public String getFamily()
|
||||||
|
{
|
||||||
|
return "org.alfresco.faces.AjaxFolderPicker";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getServiceCall()
|
||||||
|
{
|
||||||
|
return "PickerBean.getFolderNodes";
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Created on 25-May-2005
|
||||||
|
*/
|
||||||
|
package org.alfresco.web.ui.repo.tag;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Kevin Roast
|
||||||
|
*/
|
||||||
|
public class AjaxFolderSelectorTag extends AjaxItemSelectorTag
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @see javax.faces.webapp.UIComponentTag#getComponentType()
|
||||||
|
*/
|
||||||
|
public String getComponentType()
|
||||||
|
{
|
||||||
|
return "org.alfresco.faces.AjaxFolderPicker";
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Created on 25-May-2005
|
||||||
|
*/
|
||||||
|
package org.alfresco.web.ui.repo.tag;
|
||||||
|
|
||||||
|
import javax.faces.component.UIComponent;
|
||||||
|
|
||||||
|
import org.alfresco.web.ui.common.tag.BaseComponentTag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for the item selector tag
|
||||||
|
*
|
||||||
|
* @author Kevin Roast
|
||||||
|
*/
|
||||||
|
public abstract class AjaxItemSelectorTag extends BaseComponentTag
|
||||||
|
{
|
||||||
|
/** the value */
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
/** the label */
|
||||||
|
private String label;
|
||||||
|
|
||||||
|
/** the id of initial selection */
|
||||||
|
private String initialSelection;
|
||||||
|
|
||||||
|
/** Whether the component is single or multi-select */
|
||||||
|
private String singleSelect;
|
||||||
|
|
||||||
|
/** Whether the component is disabled */
|
||||||
|
private String disabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see javax.faces.webapp.UIComponentTag#getComponentType()
|
||||||
|
*/
|
||||||
|
public abstract String getComponentType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see javax.faces.webapp.UIComponentTag#getRendererType()
|
||||||
|
*/
|
||||||
|
public String getRendererType()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see javax.faces.webapp.UIComponentTag#setProperties(javax.faces.component.UIComponent)
|
||||||
|
*/
|
||||||
|
protected void setProperties(UIComponent component)
|
||||||
|
{
|
||||||
|
super.setProperties(component);
|
||||||
|
|
||||||
|
setStringBindingProperty(component, "value", this.value);
|
||||||
|
setStringBindingProperty(component, "initialSelection", this.initialSelection);
|
||||||
|
setStringProperty(component, "label", this.label);
|
||||||
|
setBooleanProperty(component, "singleSelect", this.singleSelect);
|
||||||
|
setBooleanProperty(component, "disabled", this.disabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.alfresco.web.ui.common.tag.HtmlComponentTag#release()
|
||||||
|
*/
|
||||||
|
public void release()
|
||||||
|
{
|
||||||
|
super.release();
|
||||||
|
|
||||||
|
this.value = null;
|
||||||
|
this.label = null;
|
||||||
|
this.singleSelect = null;
|
||||||
|
this.initialSelection = null;
|
||||||
|
this.disabled = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value
|
||||||
|
*
|
||||||
|
* @param value the value
|
||||||
|
*/
|
||||||
|
public void setValue(String value)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the label
|
||||||
|
*
|
||||||
|
* @param label the label
|
||||||
|
*/
|
||||||
|
public void setLabel(String label)
|
||||||
|
{
|
||||||
|
this.label = label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the singleSelect
|
||||||
|
*
|
||||||
|
* @param singleSelect the singleSelect
|
||||||
|
*/
|
||||||
|
public void setSingleSelect(String singleSelect)
|
||||||
|
{
|
||||||
|
this.singleSelect = singleSelect;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id of the item to be initially selected, this is overridden
|
||||||
|
* however if a value is supplied
|
||||||
|
*
|
||||||
|
* @param initialSelection The id of the initial selected item
|
||||||
|
*/
|
||||||
|
public void setInitialSelection(String initialSelection)
|
||||||
|
{
|
||||||
|
this.initialSelection = initialSelection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the component should be rendered in a disabled state
|
||||||
|
*
|
||||||
|
* @param disabled true to render the component in a disabled state
|
||||||
|
*/
|
||||||
|
public void setDisabled(String disabled)
|
||||||
|
{
|
||||||
|
this.disabled = disabled;
|
||||||
|
}
|
||||||
|
}
|
@@ -47,7 +47,7 @@ public class PageTag extends TagSupport
|
|||||||
private final static String SCRIPTS_START = "<script type=\"text/javascript\" src=\"";
|
private final static String SCRIPTS_START = "<script type=\"text/javascript\" src=\"";
|
||||||
private final static String SCRIPTS_END = "\"></script>\n";
|
private final static String SCRIPTS_END = "\"></script>\n";
|
||||||
private final static String STYLES_START = "<link rel=\"stylesheet\" href=\"";
|
private final static String STYLES_START = "<link rel=\"stylesheet\" href=\"";
|
||||||
private final static String STYLES_MAIN = "/css/main.css\" type=\"text/css\">\n";
|
private final static String STYLES_MAIN = "\" type=\"text/css\">\n";
|
||||||
|
|
||||||
private final static String[] SCRIPTS =
|
private final static String[] SCRIPTS =
|
||||||
{
|
{
|
||||||
@@ -66,7 +66,15 @@ public class PageTag extends TagSupport
|
|||||||
// common Alfresco util methods
|
// common Alfresco util methods
|
||||||
"/scripts/ajax/common.js",
|
"/scripts/ajax/common.js",
|
||||||
// pop-up panel helper objects
|
// pop-up panel helper objects
|
||||||
"/scripts/ajax/summary-info.js"
|
"/scripts/ajax/summary-info.js",
|
||||||
|
// ajax pickers
|
||||||
|
"/scripts/ajax/picker.js"
|
||||||
|
};
|
||||||
|
|
||||||
|
private final static String[] CSS =
|
||||||
|
{
|
||||||
|
"/css/main.css",
|
||||||
|
"/css/picker.css"
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -219,10 +227,15 @@ public class PageTag extends TagSupport
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CSS style includes
|
// CSS style includes
|
||||||
|
for (final String css : PageTag.CSS)
|
||||||
|
{
|
||||||
out.write(STYLES_START);
|
out.write(STYLES_START);
|
||||||
out.write(reqPath);
|
out.write(reqPath);
|
||||||
|
out.write(css);
|
||||||
out.write(STYLES_MAIN);
|
out.write(STYLES_MAIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// JavaScript includes
|
||||||
for (final String s : PageTag.SCRIPTS)
|
for (final String s : PageTag.SCRIPTS)
|
||||||
{
|
{
|
||||||
out.write(SCRIPTS_START);
|
out.write(SCRIPTS_START);
|
||||||
|
@@ -4197,6 +4197,31 @@
|
|||||||
<managed-bean-scope>request</managed-bean-scope>
|
<managed-bean-scope>request</managed-bean-scope>
|
||||||
</managed-bean>
|
</managed-bean>
|
||||||
|
|
||||||
|
<managed-bean>
|
||||||
|
<description>
|
||||||
|
Bean backing the ajax requests for the ajax based picker components
|
||||||
|
</description>
|
||||||
|
<managed-bean-name>PickerBean</managed-bean-name>
|
||||||
|
<managed-bean-class>org.alfresco.web.bean.ajax.PickerBean</managed-bean-class>
|
||||||
|
<managed-bean-scope>request</managed-bean-scope>
|
||||||
|
<managed-property>
|
||||||
|
<property-name>categoryService</property-name>
|
||||||
|
<value>#{CategoryService}</value>
|
||||||
|
</managed-property>
|
||||||
|
<managed-property>
|
||||||
|
<property-name>nodeService</property-name>
|
||||||
|
<value>#{NodeService}</value>
|
||||||
|
</managed-property>
|
||||||
|
<managed-property>
|
||||||
|
<property-name>internalNodeService</property-name>
|
||||||
|
<value>#{nodeService}</value>
|
||||||
|
</managed-property>
|
||||||
|
<managed-property>
|
||||||
|
<property-name>fileFolderService</property-name>
|
||||||
|
<value>#{FileFolderService}</value>
|
||||||
|
</managed-property>
|
||||||
|
</managed-bean>
|
||||||
|
|
||||||
<managed-bean>
|
<managed-bean>
|
||||||
<description>
|
<description>
|
||||||
Bean that returns manages the tree data for the navigator component
|
Bean that returns manages the tree data for the navigator component
|
||||||
|
@@ -209,6 +209,11 @@
|
|||||||
<component-class>org.alfresco.web.ui.repo.component.UICategoryBrowser</component-class>
|
<component-class>org.alfresco.web.ui.repo.component.UICategoryBrowser</component-class>
|
||||||
</component>
|
</component>
|
||||||
|
|
||||||
|
<component>
|
||||||
|
<component-type>org.alfresco.faces.AjaxFolderPicker</component-type>
|
||||||
|
<component-class>org.alfresco.web.ui.repo.component.UIAjaxFolderPicker</component-class>
|
||||||
|
</component>
|
||||||
|
|
||||||
|
|
||||||
<!-- ==================== CONVERTERS ==================== -->
|
<!-- ==================== CONVERTERS ==================== -->
|
||||||
<component>
|
<component>
|
||||||
|
@@ -2204,4 +2204,58 @@
|
|||||||
</attribute>
|
</attribute>
|
||||||
</tag>
|
</tag>
|
||||||
|
|
||||||
|
<tag>
|
||||||
|
<name>ajaxFolderSelector</name>
|
||||||
|
<tag-class>org.alfresco.web.ui.repo.tag.AjaxFolderSelectorTag</tag-class>
|
||||||
|
<body-content>JSP</body-content>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>id</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
</attribute>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>binding</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
</attribute>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>rendered</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
</attribute>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>value</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
</attribute>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>label</name>
|
||||||
|
<required>true</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
</attribute>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>initialSelection</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
</attribute>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>singleSelect</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
</attribute>
|
||||||
|
|
||||||
|
<attribute>
|
||||||
|
<name>disabled</name>
|
||||||
|
<required>false</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
</attribute>
|
||||||
|
</tag>
|
||||||
|
|
||||||
</taglib>
|
</taglib>
|
||||||
|
199
source/web/css/picker.css
Normal file
199
source/web/css/picker.css
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
.pickerNoSelectedItems
|
||||||
|
{
|
||||||
|
margin-top: 2px
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickerSelectedItems
|
||||||
|
{
|
||||||
|
padding-left: 6px;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickerSelectedItemsFocus
|
||||||
|
{
|
||||||
|
background-color: #faf7ce;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickerSelectedItemsActions div
|
||||||
|
{
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickerSelectedItemsActions div img
|
||||||
|
{
|
||||||
|
vertical-align: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.pickerSelectedItem
|
||||||
|
{
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 2px 2px;
|
||||||
|
margin: 2px;
|
||||||
|
padding: 2px;
|
||||||
|
border: 1px dashed #e7e7e7;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.pickerSelectedItemText
|
||||||
|
{
|
||||||
|
float: left;
|
||||||
|
margin-left: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.pickerSelectedItemAction
|
||||||
|
{
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.pickerSelectedIcon
|
||||||
|
{
|
||||||
|
margin-left: 4px;
|
||||||
|
vertical-align: -4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.pickerSelector
|
||||||
|
{
|
||||||
|
width: 300px;
|
||||||
|
border: 1px solid #e7e7e7;
|
||||||
|
background-color: #DFE6ED;
|
||||||
|
padding: 4px;
|
||||||
|
margin-top: 5px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.pickerResultsList
|
||||||
|
{
|
||||||
|
*width: 300px;
|
||||||
|
height: 120px;
|
||||||
|
overflow: auto;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.pickerResults
|
||||||
|
{
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid #e7e7e7;
|
||||||
|
padding: 3px 3px 5px 3px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
-moz-border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.pickerResultsHeader
|
||||||
|
{
|
||||||
|
margin-bottom: 2px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.pickerAjaxWait
|
||||||
|
{
|
||||||
|
background-image: url(../images/icons/ajax_anim.gif);
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 50% 65%;
|
||||||
|
width: 292px;
|
||||||
|
height: 120px;
|
||||||
|
overflow: hidden;
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickerNavControls
|
||||||
|
{
|
||||||
|
float: left;
|
||||||
|
border-bottom: 1px solid #b2b2b2;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.pickerActionButton
|
||||||
|
{
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.pickerResultsRow
|
||||||
|
{
|
||||||
|
padding: 4px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickerResultsOddRow
|
||||||
|
{
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickerResultsEvenRow
|
||||||
|
{
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickerResultIcon
|
||||||
|
{
|
||||||
|
float: left;
|
||||||
|
margin-top: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickerResultName
|
||||||
|
{
|
||||||
|
margin-left: 6px;
|
||||||
|
padding-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickerResultActions
|
||||||
|
{
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.pickerDoneButton
|
||||||
|
{
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 50px;
|
||||||
|
padding: 3px;
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.pickerFinishControls
|
||||||
|
{
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickerNavBreadcrumb
|
||||||
|
{
|
||||||
|
float: left;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickerNavBreadcrumb img
|
||||||
|
{
|
||||||
|
vertical-align: -7px;
|
||||||
|
padding-left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.pickerNavBreadcrumbPanel
|
||||||
|
{
|
||||||
|
position: absolute;
|
||||||
|
max-width: 250px;
|
||||||
|
padding: 2px;
|
||||||
|
margin-top: 20px;
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
border: 1px solid #cccccc;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.pickerNavBreadcrumbItem
|
||||||
|
{
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickerNavUp
|
||||||
|
{
|
||||||
|
float: right;
|
||||||
|
margin-top: 2px;
|
||||||
|
margin-right: 15px;
|
||||||
|
text-align: right:
|
||||||
|
}
|
||||||
|
|
||||||
|
.pickerNavUp img
|
||||||
|
{
|
||||||
|
vertical-align: -4px;
|
||||||
|
}
|
407
source/web/scripts/ajax/picker.js
Normal file
407
source/web/scripts/ajax/picker.js
Normal file
@@ -0,0 +1,407 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prerequisites: common.js
|
||||||
|
* mootools.v1.11.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Picker class definition
|
||||||
|
var AlfPicker = new Class(
|
||||||
|
{
|
||||||
|
/* id of the picker */
|
||||||
|
id: null,
|
||||||
|
|
||||||
|
/* variable name being used */
|
||||||
|
varName: null,
|
||||||
|
|
||||||
|
/* the item the picker will start with */
|
||||||
|
startId: null,
|
||||||
|
|
||||||
|
/* list of items currently selected */
|
||||||
|
selected: null,
|
||||||
|
|
||||||
|
/* the current parent being shown */
|
||||||
|
parent: null,
|
||||||
|
|
||||||
|
/* the list of items currently displayed */
|
||||||
|
items: [],
|
||||||
|
|
||||||
|
/* parent stack for the Navigate Up action*/
|
||||||
|
stack: [],
|
||||||
|
|
||||||
|
/* row type toggle */
|
||||||
|
oddRow: true,
|
||||||
|
|
||||||
|
/* ajax service call to retrieve data */
|
||||||
|
service: null,
|
||||||
|
|
||||||
|
/* default icon to use if not provided by the associated service */
|
||||||
|
defaultIcon: null,
|
||||||
|
|
||||||
|
/* single selection mode flag */
|
||||||
|
singleSelect: false,
|
||||||
|
|
||||||
|
initialize: function(id, varName, service, singleSelect)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
this.varName = varName;
|
||||||
|
this.parent = this.startId;
|
||||||
|
this.selected = [];
|
||||||
|
this.service = service;
|
||||||
|
if (singleSelect != undefined)
|
||||||
|
{
|
||||||
|
this.singleSelect = singleSelect;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setDefaultIcon: function(icon)
|
||||||
|
{
|
||||||
|
this.defaultIcon = icon;
|
||||||
|
},
|
||||||
|
|
||||||
|
setStartId: function(id)
|
||||||
|
{
|
||||||
|
this.startId = id;
|
||||||
|
},
|
||||||
|
|
||||||
|
showSelector: function()
|
||||||
|
{
|
||||||
|
$(this.id + "-selector").setStyle("display", "block");
|
||||||
|
$(this.id + "-selected").setStyle("display", "block");
|
||||||
|
$(this.id + "-noitems").setStyle("display", "none");
|
||||||
|
if (this.singleSelect)
|
||||||
|
{
|
||||||
|
$(this.id + "-finish").setStyle("display", "none");
|
||||||
|
}
|
||||||
|
|
||||||
|
// simulate an ajax request for children of start item
|
||||||
|
this.getChildData(this.startId, this.populateChildren);
|
||||||
|
},
|
||||||
|
|
||||||
|
childClicked: function(index)
|
||||||
|
{
|
||||||
|
this.hidePanels();
|
||||||
|
var item = this.items[index];
|
||||||
|
// add an extra property to record the scroll position for this item
|
||||||
|
item.scrollpos = $(this.id + "-results-list").scrollTop;
|
||||||
|
this.stack.push(item); // ready for the breadcrumb redraw after the child data request
|
||||||
|
this.getChildData(item.id, this.populateChildren)
|
||||||
|
},
|
||||||
|
|
||||||
|
upClicked: function()
|
||||||
|
{
|
||||||
|
this.hidePanels();
|
||||||
|
// pop the parent off - peek for the grandparent
|
||||||
|
var parent = this.stack.pop();
|
||||||
|
var grandParent = this.stack[this.stack.length-1];
|
||||||
|
this.getChildData(grandParent != null ? grandParent.id : null, this.populateChildren, parent.scrollpos);
|
||||||
|
},
|
||||||
|
|
||||||
|
addItem: function(index)
|
||||||
|
{
|
||||||
|
var item = this.items[index];
|
||||||
|
|
||||||
|
// add item to list of selected items
|
||||||
|
this.selected.push(item);
|
||||||
|
|
||||||
|
if (this.singleSelect)
|
||||||
|
{
|
||||||
|
this.doneClicked();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// add the item to list above the selector
|
||||||
|
var itemId = this.id + "-sel-" + item.id;
|
||||||
|
var itemDiv = new Element("div", {"id": itemId, "class": "pickerSelectedItem"});
|
||||||
|
|
||||||
|
var itemSpan = new Element("span", {"class": "pickerSelectedItemText"});
|
||||||
|
itemSpan.appendText(item.name);
|
||||||
|
itemSpan.injectInside(itemDiv);
|
||||||
|
|
||||||
|
var actionSpan = new Element("span", {"class": "pickerSelectedItemAction"});
|
||||||
|
var actionScript = "javascript:" + this.varName + ".delItem('" + item.id + "');";
|
||||||
|
var actionLink = new Element("a", {"href": actionScript});
|
||||||
|
var deleteIcon = new Element("img", {"src": getContextPath() + "/images/icons/minus.gif", "class": "pickerSelectedIcon",
|
||||||
|
"border": 0, "title": "Remove", "alt": "Remove"});
|
||||||
|
deleteIcon.injectInside(actionLink);
|
||||||
|
actionLink.injectInside(actionSpan);
|
||||||
|
actionSpan.injectInside(itemDiv);
|
||||||
|
|
||||||
|
// add mouse enter/leave enter to toggle delete icon (and toggle margin on outer div)
|
||||||
|
itemDiv.addEvent('mouseenter', function(e) {
|
||||||
|
$E('.pickerSelectedIcon', itemDiv).setStyle("opacity", 1);
|
||||||
|
});
|
||||||
|
itemDiv.addEvent('mouseleave', function(e) {
|
||||||
|
$E('.pickerSelectedIcon', itemDiv).setStyle("opacity", 0);
|
||||||
|
});
|
||||||
|
// add the item to the main selected item div
|
||||||
|
itemDiv.injectInside($(this.id + "-selected"));
|
||||||
|
|
||||||
|
// set the background image now the itemdiv has been added to the DOM (for IE)
|
||||||
|
itemDiv.setStyle("background-image", "url(" + getContextPath() + "/images/icons/" + item.icon + ")");
|
||||||
|
|
||||||
|
// set opacity the style now the item has been added to the DOM (for IE)
|
||||||
|
$E('.pickerSelectedIcon', itemDiv).setStyle("opacity", 0);
|
||||||
|
|
||||||
|
// apply the effect
|
||||||
|
var fx = new Fx.Styles(itemDiv, {duration: 1000, wait: false, transition: Fx.Transitions.Quad.easeOut});
|
||||||
|
fx.start({'background-color': ['#faf7ce', '#ffffff']});
|
||||||
|
|
||||||
|
// hide the Add button as this item is now added
|
||||||
|
$(this.id + "-add-" + item.id).setStyle("display", "none");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
delItem: function(itemId)
|
||||||
|
{
|
||||||
|
// remove item from the selected items list
|
||||||
|
for (i=0; i<this.selected.length; i++)
|
||||||
|
{
|
||||||
|
if (this.selected[i].id == itemId)
|
||||||
|
{
|
||||||
|
this.selected.splice(i, 1); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the div representing the selected item
|
||||||
|
$(this.id + "-sel-" + itemId).remove();
|
||||||
|
|
||||||
|
// unhide the Add button if visible
|
||||||
|
var addBtn = $(this.id + "-add-" + itemId);
|
||||||
|
if (addBtn != null)
|
||||||
|
{
|
||||||
|
addBtn.setStyle("display", "block");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
populateBreadcrumb: function()
|
||||||
|
{
|
||||||
|
var bcpanel = $(this.id + "-nav-bread");
|
||||||
|
bcpanel.empty();
|
||||||
|
|
||||||
|
// add each item from the navigation stack to the breadcrumb
|
||||||
|
for (var i=0; i<this.stack.length; i++)
|
||||||
|
{
|
||||||
|
var div = new Element("div", {"class": "pickerNavBreadcrumbItem"});
|
||||||
|
|
||||||
|
var actionScript = "javascript:" + this.varName + ".clickBreadcumb(" + i + ");";
|
||||||
|
var actionLink = new Element("a", {"href": actionScript});
|
||||||
|
actionLink.setText(this.stack[i].name);
|
||||||
|
actionLink.injectInside(div);
|
||||||
|
|
||||||
|
div.injectInside(bcpanel);
|
||||||
|
|
||||||
|
// override left padding to indent the items appropriately
|
||||||
|
div.setStyle("padding-left", (i<<3)+2);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
clickBreadcumb: function(index)
|
||||||
|
{
|
||||||
|
this.hidePanels();
|
||||||
|
var item = this.stack[index];
|
||||||
|
// remove all items under this one from the navigation stack
|
||||||
|
var removeCount = (this.stack.length - index - 1);
|
||||||
|
if (removeCount != 0)
|
||||||
|
{
|
||||||
|
this.stack.splice(index + 1, removeCount);
|
||||||
|
}
|
||||||
|
this.getChildData(item.id, this.populateChildren);
|
||||||
|
},
|
||||||
|
|
||||||
|
breadcrumbToggle: function()
|
||||||
|
{
|
||||||
|
var bcpanel = $(this.id + "-nav-bread");
|
||||||
|
if (bcpanel.getChildren().length != 0)
|
||||||
|
{
|
||||||
|
if (bcpanel.getStyle("display") == "none")
|
||||||
|
{
|
||||||
|
bcpanel.setStyle("opacity", 0);
|
||||||
|
bcpanel.setStyle("display", "block");
|
||||||
|
var fx = new Fx.Styles(bcpanel, {duration: 200, wait: false, transition: Fx.Transitions.Quad.easeOut});
|
||||||
|
fx.start({'opacity': [0, 1]});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var fx = new Fx.Styles(bcpanel, {duration: 200, wait: false, transition: Fx.Transitions.Quad.easeOut,
|
||||||
|
onComplete: function() {bcpanel.setStyle("display", "none");}});
|
||||||
|
fx.start({'opacity': [1, 0]});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
hidePanels: function()
|
||||||
|
{
|
||||||
|
$(this.id + "-nav-bread").setStyle("display", "none");
|
||||||
|
},
|
||||||
|
|
||||||
|
doneClicked: function()
|
||||||
|
{
|
||||||
|
$(this.id + "-selector").setStyle("display", "none");
|
||||||
|
$(this.id + "-value").setProperty("value", this.selected);
|
||||||
|
|
||||||
|
alert("The following items have been selected: " + $(this.id + "-value").value);
|
||||||
|
},
|
||||||
|
|
||||||
|
populateChildren: function(response, picker, scrollpos)
|
||||||
|
{
|
||||||
|
// clear any current results
|
||||||
|
var results = $(picker.id + "-results-list");
|
||||||
|
results.empty();
|
||||||
|
|
||||||
|
// set the new parent
|
||||||
|
picker.parent = response.parent.id;
|
||||||
|
|
||||||
|
// if nav stack is empty - add an item to represent the parent as the first entry
|
||||||
|
if (picker.stack.length == 0)
|
||||||
|
{
|
||||||
|
picker.stack.push({id: response.parent.id, name: response.parent.name});
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the parent is null we're at the root so hide the up link
|
||||||
|
// otherwise we need to render it with the correct details
|
||||||
|
var upLink = $(picker.id + "-nav-up");
|
||||||
|
if (picker.parent == null)
|
||||||
|
{
|
||||||
|
upLink.setStyle("display", "none");
|
||||||
|
upLink.setProperty("href", "#");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
upLink.setStyle("display", "block");
|
||||||
|
upLink.setProperty("href", "javascript:" + picker.varName + ".upClicked('" + picker.parent + "');");
|
||||||
|
}
|
||||||
|
|
||||||
|
// show what the parent next to the breadcrumb drop-down
|
||||||
|
$(picker.id + "-nav-txt").setText(response.parent.name);
|
||||||
|
|
||||||
|
// iterate through the children and render a row for each one
|
||||||
|
picker.items = [];
|
||||||
|
for (var i=0; i<response.children.length; i++)
|
||||||
|
{
|
||||||
|
var item = response.children[i];
|
||||||
|
if (item.icon == undefined)
|
||||||
|
{
|
||||||
|
item.icon = picker.defaultIcon;
|
||||||
|
}
|
||||||
|
picker.items.push(item);
|
||||||
|
picker.renderResultItem(item, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// scroll back to last position if required
|
||||||
|
results.scrollTop = (scrollpos == undefined ? 0 : scrollpos);
|
||||||
|
|
||||||
|
picker.oddRow = true;
|
||||||
|
|
||||||
|
picker.populateBreadcrumb();
|
||||||
|
},
|
||||||
|
|
||||||
|
renderResultItem: function(item, index)
|
||||||
|
{
|
||||||
|
var divClass = "pickerResultsRow " + (this.oddRow ? "pickerResultsOddRow" : "pickerResultsEvenRow");
|
||||||
|
|
||||||
|
this.oddRow = !this.oddRow;
|
||||||
|
|
||||||
|
var div = new Element("div", {"class": divClass});
|
||||||
|
|
||||||
|
// render icon
|
||||||
|
var iconSpan = new Element("span", {"class": "pickerResultIcon"});
|
||||||
|
var iconImg = new Element("img", {"src": getContextPath() + "/images/icons/" + item.icon});
|
||||||
|
iconImg.injectInside(iconSpan);
|
||||||
|
iconSpan.injectInside(div);
|
||||||
|
|
||||||
|
// render actions
|
||||||
|
var actionsSpan = new Element("span", {"class": "pickerResultActions"});
|
||||||
|
|
||||||
|
// see if the item exists in the selected items array - don't display Add button if it does
|
||||||
|
var found = false;
|
||||||
|
for (i=0; i<this.selected.length; i++)
|
||||||
|
{
|
||||||
|
if (this.selected[i].id == item.id)
|
||||||
|
{
|
||||||
|
found = true; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var actionId = this.id + "-add-" + item.id;
|
||||||
|
var actionScript = "javascript:" + this.varName + ".addItem(" + index + ");";
|
||||||
|
var actionLink = new Element("a", {"href": actionScript});
|
||||||
|
var actionImg = new Element("img", {"id": actionId, "src": getContextPath() + "/images/icons/plus.gif", "class": "pickerActionButton",
|
||||||
|
"border": 0, "title": "Add", "alt": "Add"});
|
||||||
|
actionImg.injectInside(actionLink);
|
||||||
|
actionLink.injectInside(actionsSpan);
|
||||||
|
actionsSpan.injectInside(div);
|
||||||
|
|
||||||
|
// render name
|
||||||
|
var nameSpan = new Element("span", {"class": "pickerResultName"});
|
||||||
|
|
||||||
|
var link = "javascript:" + this.varName + ".childClicked(" + index + ");";
|
||||||
|
|
||||||
|
var nameLink = new Element("a", {"href": link});
|
||||||
|
nameLink.appendText(item.name);
|
||||||
|
nameLink.injectInside(nameSpan);
|
||||||
|
nameSpan.injectInside(div);
|
||||||
|
|
||||||
|
// add results
|
||||||
|
div.injectInside($(this.id + "-results-list"));
|
||||||
|
|
||||||
|
// hide the Add button (now this item is in the DOM) if in the selected list
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
actionImg.setStyle("display", "none");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getChildData: function(parent, callback, scrollpos)
|
||||||
|
{
|
||||||
|
// show ajax wait panel
|
||||||
|
$(this.id + '-ajax-wait').setStyle('display', 'block');
|
||||||
|
$(this.id + '-results-list').setStyle('visibility', 'hidden');
|
||||||
|
|
||||||
|
var picker = this;
|
||||||
|
|
||||||
|
// execute ajax service call to retrieve list of child nodes as JSON response
|
||||||
|
new Ajax(getContextPath() + "/ajax/invoke/" + this.service + "?parent=" + (parent!=null ? parent : ""),
|
||||||
|
{
|
||||||
|
method: 'get',
|
||||||
|
async: false,
|
||||||
|
onComplete: function(r)
|
||||||
|
{
|
||||||
|
if (r.startsWith("ERROR:") == false)
|
||||||
|
{
|
||||||
|
result = Json.evaluate(r);
|
||||||
|
result.children.sort(picker.sortByName);
|
||||||
|
|
||||||
|
callback(result, picker, scrollpos);
|
||||||
|
|
||||||
|
// display results list again and hide ajax wait panel
|
||||||
|
$(picker.id + '-results-list').setStyle('visibility', 'visible');
|
||||||
|
$(picker.id + '-ajax-wait').setStyle('display', 'none');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onFailure: function (r)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}).request();
|
||||||
|
},
|
||||||
|
|
||||||
|
sortByName: function(a, b)
|
||||||
|
{
|
||||||
|
return ((a.name < b.name) ? -1 : ((a.name > b.name) ? 1 : 0));
|
||||||
|
}
|
||||||
|
});
|
Reference in New Issue
Block a user