implemented mention in comments almost complete
git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/user/news-feed@94652 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
parent
aedf4cb81c
commit
1728e6dfc3
|
@ -1,15 +1,12 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<classpath>
|
<classpath>
|
||||||
<classpathentry kind="src" path="src/main/webapp" />
|
<classpathentry excluding="js/jquery.autosize.js|js/jquery.min.js" kind="src" path="src/main/webapp"/>
|
||||||
<classpathentry kind="con"
|
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
|
||||||
path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER" />
|
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
|
||||||
<classpathentry kind="con"
|
<attributes>
|
||||||
path="org.eclipse.wst.jsdt.launching.WebProject">
|
<attribute name="hide" value="true"/>
|
||||||
<attributes>
|
</attributes>
|
||||||
<attribute name="hide" value="true" />
|
</classpathentry>
|
||||||
</attributes>
|
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
|
||||||
</classpathentry>
|
<classpathentry kind="output" path=""/>
|
||||||
<classpathentry kind="con"
|
|
||||||
path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary" />
|
|
||||||
<classpathentry kind="output" path="" />
|
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
|
<wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
|
||||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
|
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
|
||||||
<wb-resource deploy-path="/WEB-INF/classes" source-path="/target/generated-sources/gwt"/>
|
<wb-resource deploy-path="/WEB-INF/classes" source-path="/target/generated-sources/gwt"/>
|
||||||
|
<dependent-module archiveName="pickuser-widget-0.4.0-SNAPSHOT.jar" deploy-path="/WEB-INF/lib" handle="module:/resource/pickuser-widget/pickuser-widget">
|
||||||
|
<dependency-type>uses</dependency-type>
|
||||||
|
</dependent-module>
|
||||||
<property name="java-output-path" value="/${module}/target/www/WEB-INF/classes"/>
|
<property name="java-output-path" value="/${module}/target/www/WEB-INF/classes"/>
|
||||||
<property name="context-root" value="news-feed"/>
|
<property name="context-root" value="news-feed"/>
|
||||||
</wb-module>
|
</wb-module>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
org.eclipse.wst.jsdt.launching.baseBrowserLibrary
|
org.eclipse.wst.jsdt.launching.JRE_CONTAINER
|
|
@ -0,0 +1 @@
|
||||||
|
Global
|
5
pom.xml
5
pom.xml
|
@ -81,6 +81,11 @@
|
||||||
<artifactId>session-checker</artifactId>
|
<artifactId>session-checker</artifactId>
|
||||||
<version>[0.2.0-SNAPSHOT, 1.0.0-SNAPSHOT)</version>
|
<version>[0.2.0-SNAPSHOT, 1.0.0-SNAPSHOT)</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.gcube.portlets.widgets</groupId>
|
||||||
|
<artifactId>pickuser-widget</artifactId>
|
||||||
|
<version>[0.4.0-SNAPSHOT, 1.0.0-SNAPSHOT)</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.applicationsupportlayer</groupId>
|
<groupId>org.gcube.applicationsupportlayer</groupId>
|
||||||
<artifactId>aslsocial</artifactId>
|
<artifactId>aslsocial</artifactId>
|
||||||
|
|
|
@ -8,6 +8,7 @@ import org.gcube.portal.databook.shared.UserInfo;
|
||||||
import org.gcube.portlets.user.newsfeed.shared.EnhancedFeed;
|
import org.gcube.portlets.user.newsfeed.shared.EnhancedFeed;
|
||||||
import org.gcube.portlets.user.newsfeed.shared.MoreFeedsBean;
|
import org.gcube.portlets.user.newsfeed.shared.MoreFeedsBean;
|
||||||
import org.gcube.portlets.user.newsfeed.shared.UserSettings;
|
import org.gcube.portlets.user.newsfeed.shared.UserSettings;
|
||||||
|
import org.gcube.portlets.widgets.pickuser.shared.PickingUser;
|
||||||
|
|
||||||
import com.google.gwt.user.client.rpc.RemoteService;
|
import com.google.gwt.user.client.rpc.RemoteService;
|
||||||
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
|
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
|
||||||
|
@ -46,4 +47,6 @@ public interface NewsService extends RemoteService {
|
||||||
UserSettings getUserSettings();
|
UserSettings getUserSettings();
|
||||||
|
|
||||||
EnhancedFeed getSingleFeed(String feedKey);
|
EnhancedFeed getSingleFeed(String feedKey);
|
||||||
|
|
||||||
|
ArrayList<PickingUser> getOrganizationUsers(String currentScope);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.gcube.portal.databook.shared.Like;
|
||||||
import org.gcube.portlets.user.newsfeed.shared.EnhancedFeed;
|
import org.gcube.portlets.user.newsfeed.shared.EnhancedFeed;
|
||||||
import org.gcube.portlets.user.newsfeed.shared.MoreFeedsBean;
|
import org.gcube.portlets.user.newsfeed.shared.MoreFeedsBean;
|
||||||
import org.gcube.portlets.user.newsfeed.shared.UserSettings;
|
import org.gcube.portlets.user.newsfeed.shared.UserSettings;
|
||||||
|
import org.gcube.portlets.widgets.pickuser.shared.PickingUser;
|
||||||
|
|
||||||
import com.google.gwt.user.client.rpc.AsyncCallback;
|
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||||
|
|
||||||
|
@ -54,4 +55,7 @@ public interface NewsServiceAsync {
|
||||||
void unlike(String feedid, String feedText, String feedOwnerId,
|
void unlike(String feedid, String feedText, String feedOwnerId,
|
||||||
AsyncCallback<Boolean> callback);
|
AsyncCallback<Boolean> callback);
|
||||||
|
|
||||||
|
void getOrganizationUsers(String currentScope,
|
||||||
|
AsyncCallback<ArrayList<PickingUser>> callback);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,10 @@ import com.google.gwt.user.client.ui.Widget;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class NewsFeedPanel extends Composite {
|
public class NewsFeedPanel extends Composite {
|
||||||
|
/**
|
||||||
|
* the current scope on the client can be static
|
||||||
|
*/
|
||||||
|
private static String currentScope;
|
||||||
/**
|
/**
|
||||||
* Create a remote service proxy to talk to the server-side News service.
|
* Create a remote service proxy to talk to the server-side News service.
|
||||||
*/
|
*/
|
||||||
|
@ -107,7 +110,7 @@ public class NewsFeedPanel extends Composite {
|
||||||
public static final String MESSAGE_LABEL = "Message";
|
public static final String MESSAGE_LABEL = "Message";
|
||||||
|
|
||||||
private String vreLabel;
|
private String vreLabel;
|
||||||
private String currentScope;
|
|
||||||
private boolean showFeedTimelineSource = false;
|
private boolean showFeedTimelineSource = false;
|
||||||
private boolean isInfrastructure = false;
|
private boolean isInfrastructure = false;
|
||||||
|
|
||||||
|
@ -224,7 +227,6 @@ public class NewsFeedPanel extends Composite {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -937,5 +939,11 @@ public class NewsFeedPanel extends Composite {
|
||||||
public void setCurrentFilter(FilterType currentFilter) {
|
public void setCurrentFilter(FilterType currentFilter) {
|
||||||
this.currentFilter = currentFilter;
|
this.currentFilter = currentFilter;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return the current scope on the client
|
||||||
|
*/
|
||||||
|
public static String getCurrentScope() {
|
||||||
|
return currentScope;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,29 @@
|
||||||
package org.gcube.portlets.user.newsfeed.client.templates;
|
package org.gcube.portlets.user.newsfeed.client.templates;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.gcube.portal.databook.shared.Comment;
|
import org.gcube.portal.databook.shared.Comment;
|
||||||
import org.gcube.portal.databook.shared.UserInfo;
|
import org.gcube.portal.databook.shared.UserInfo;
|
||||||
|
import org.gcube.portlets.user.newsfeed.client.NewsService;
|
||||||
|
import org.gcube.portlets.user.newsfeed.client.NewsServiceAsync;
|
||||||
import org.gcube.portlets.user.newsfeed.client.event.AddCommentEvent;
|
import org.gcube.portlets.user.newsfeed.client.event.AddCommentEvent;
|
||||||
import org.gcube.portlets.user.newsfeed.client.event.EditCommentEvent;
|
import org.gcube.portlets.user.newsfeed.client.event.EditCommentEvent;
|
||||||
|
import org.gcube.portlets.user.newsfeed.client.panels.NewsFeedPanel;
|
||||||
|
import org.gcube.portlets.widgets.pickuser.client.dialog.PickUsersDialog;
|
||||||
|
import org.gcube.portlets.widgets.pickuser.shared.PickingUser;
|
||||||
|
|
||||||
import com.google.gwt.core.client.GWT;
|
import com.google.gwt.core.client.GWT;
|
||||||
import com.google.gwt.event.dom.client.ClickEvent;
|
import com.google.gwt.event.dom.client.ClickEvent;
|
||||||
import com.google.gwt.event.dom.client.KeyPressEvent;
|
import com.google.gwt.event.dom.client.KeyPressEvent;
|
||||||
|
import com.google.gwt.event.dom.client.KeyUpEvent;
|
||||||
|
import com.google.gwt.event.dom.client.KeyUpHandler;
|
||||||
import com.google.gwt.event.shared.HandlerManager;
|
import com.google.gwt.event.shared.HandlerManager;
|
||||||
import com.google.gwt.uibinder.client.UiBinder;
|
import com.google.gwt.uibinder.client.UiBinder;
|
||||||
import com.google.gwt.uibinder.client.UiField;
|
import com.google.gwt.uibinder.client.UiField;
|
||||||
import com.google.gwt.uibinder.client.UiHandler;
|
import com.google.gwt.uibinder.client.UiHandler;
|
||||||
import com.google.gwt.user.client.Event;
|
import com.google.gwt.user.client.Event;
|
||||||
import com.google.gwt.user.client.Window;
|
import com.google.gwt.user.client.Window;
|
||||||
|
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||||
import com.google.gwt.user.client.ui.Button;
|
import com.google.gwt.user.client.ui.Button;
|
||||||
import com.google.gwt.user.client.ui.Composite;
|
import com.google.gwt.user.client.ui.Composite;
|
||||||
import com.google.gwt.user.client.ui.HTML;
|
import com.google.gwt.user.client.ui.HTML;
|
||||||
|
@ -22,22 +32,34 @@ import com.google.gwt.user.client.ui.Image;
|
||||||
import com.google.gwt.user.client.ui.TextArea;
|
import com.google.gwt.user.client.ui.TextArea;
|
||||||
import com.google.gwt.user.client.ui.Widget;
|
import com.google.gwt.user.client.ui.Widget;
|
||||||
|
|
||||||
public class AddCommentTemplate extends Composite{
|
public class AddCommentTemplate extends Composite {
|
||||||
|
|
||||||
private static CommentTemplateUiBinder uiBinder = GWT
|
interface CommentTemplateUiBinder extends UiBinder<Widget, AddCommentTemplate> {
|
||||||
.create(CommentTemplateUiBinder.class);
|
}
|
||||||
|
|
||||||
private final static String COMMENT_TEXT = "Add a comment ...";
|
private static CommentTemplateUiBinder uiBinder = GWT.create(CommentTemplateUiBinder.class);
|
||||||
|
|
||||||
|
|
||||||
|
private final static String COMMENT_TEXT = "Add a comment ... use @ to mention someone";
|
||||||
private final static String ERROR_UPDATE_TEXT = "Looks like empty to me!";
|
private final static String ERROR_UPDATE_TEXT = "Looks like empty to me!";
|
||||||
public static final String avatar_default = GWT.getModuleBaseURL() + "../images/Avatar_default.png";
|
public static final String avatar_default = GWT.getModuleBaseURL() + "../images/Avatar_default.png";
|
||||||
|
|
||||||
|
private final static int TEXT_AREA_WIDTH = 450;
|
||||||
|
private final static int TEXT_AREA_HEIGHT = 40;
|
||||||
|
|
||||||
private TweetTemplate owner;
|
private TweetTemplate owner;
|
||||||
private HandlerManager eventBus;
|
private HandlerManager eventBus;
|
||||||
private boolean isEditing = false;
|
private boolean isEditing = false;
|
||||||
private HTMLPanel commentPanel;
|
private HTMLPanel commentPanel;
|
||||||
private Comment toEdit;
|
private Comment toEdit;
|
||||||
|
|
||||||
interface CommentTemplateUiBinder extends UiBinder<Widget, AddCommentTemplate> {
|
@UiField HTMLPanel mainPanel;
|
||||||
}
|
@UiField Image avatarImage;
|
||||||
|
@UiField SuperPosedTextArea commentTextArea;
|
||||||
|
@UiField Button submitButton;
|
||||||
|
@UiField Button cancelButton;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* called on add comment
|
* called on add comment
|
||||||
* @param caller
|
* @param caller
|
||||||
|
@ -50,7 +72,7 @@ public class AddCommentTemplate extends Composite{
|
||||||
owner = caller;
|
owner = caller;
|
||||||
avatarImage.setPixelSize(30, 30);
|
avatarImage.setPixelSize(30, 30);
|
||||||
avatarImage.setUrl(myUserInfo.getAvatarId());
|
avatarImage.setUrl(myUserInfo.getAvatarId());
|
||||||
commentTextArea.setPixelSize(450, 26);
|
//commentTextArea.setPixelSize(TEXT_AREA_WIDTH, TEXT_AREA_HEIGHT);
|
||||||
commentTextArea.setText(COMMENT_TEXT);
|
commentTextArea.setText(COMMENT_TEXT);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -67,38 +89,18 @@ public class AddCommentTemplate extends Composite{
|
||||||
owner = caller;
|
owner = caller;
|
||||||
avatarImage.setPixelSize(30, 30);
|
avatarImage.setPixelSize(30, 30);
|
||||||
avatarImage.setUrl(caller.getMyUserInfo().getAvatarId());
|
avatarImage.setUrl(caller.getMyUserInfo().getAvatarId());
|
||||||
commentTextArea.setPixelSize(450, 26);
|
//commentTextArea.setPixelSize(TEXT_AREA_WIDTH, TEXT_AREA_HEIGHT);
|
||||||
commentTextArea.setText(new HTML(toEdit.getText()).getText());
|
commentTextArea.setText(new HTML(toEdit.getText()).getText());
|
||||||
mainPanel.removeStyleName("comment-hidden");
|
mainPanel.removeStyleName("comment-hidden");
|
||||||
mainPanel.setStyleName("single-comment");
|
mainPanel.setStyleName("single-comment");
|
||||||
commentTextArea.addStyleName("dark-color");
|
commentTextArea.addStyleName("comment-dark-color");
|
||||||
}
|
}
|
||||||
|
|
||||||
@UiField HTMLPanel mainPanel;
|
|
||||||
@UiField Image avatarImage;
|
|
||||||
@UiField TextArea commentTextArea;
|
|
||||||
@UiField Button submitButton;
|
|
||||||
@UiField Button cancelButton;
|
|
||||||
|
|
||||||
public void setFocus() {
|
public void setFocus() {
|
||||||
commentTextArea.setFocus(true);
|
commentTextArea.setFocus(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* paste event overridden
|
|
||||||
*/
|
|
||||||
public void onBrowserEvent(Event event) {
|
|
||||||
super.onBrowserEvent(event);
|
|
||||||
switch (event.getTypeInt()) {
|
|
||||||
case Event.ONPASTE:
|
|
||||||
if (commentTextArea.getText().equals(COMMENT_TEXT) || commentTextArea.getText().equals(ERROR_UPDATE_TEXT) ) {
|
|
||||||
commentTextArea.setText("");
|
|
||||||
commentTextArea.addStyleName("dark-color");
|
|
||||||
commentTextArea.removeStyleName("error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@UiHandler("submitButton")
|
@UiHandler("submitButton")
|
||||||
void onSubmitClick(ClickEvent e) {
|
void onSubmitClick(ClickEvent e) {
|
||||||
String userComment = commentTextArea.getText().trim();
|
String userComment = commentTextArea.getText().trim();
|
||||||
|
@ -155,7 +157,7 @@ public class AddCommentTemplate extends Composite{
|
||||||
void onCommentClick(ClickEvent e) {
|
void onCommentClick(ClickEvent e) {
|
||||||
if (commentTextArea.getText().equals(COMMENT_TEXT) || commentTextArea.getText().equals(ERROR_UPDATE_TEXT) ) {
|
if (commentTextArea.getText().equals(COMMENT_TEXT) || commentTextArea.getText().equals(ERROR_UPDATE_TEXT) ) {
|
||||||
commentTextArea.setText("");
|
commentTextArea.setText("");
|
||||||
commentTextArea.addStyleName("dark-color");
|
commentTextArea.addStyleName("comment-dark-color");
|
||||||
commentTextArea.removeStyleName("error");
|
commentTextArea.removeStyleName("error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,7 +166,7 @@ public class AddCommentTemplate extends Composite{
|
||||||
void onCommentKeyPress(KeyPressEvent e) {
|
void onCommentKeyPress(KeyPressEvent e) {
|
||||||
if (commentTextArea.getText().equals(COMMENT_TEXT) || commentTextArea.getText().equals(ERROR_UPDATE_TEXT) ) {
|
if (commentTextArea.getText().equals(COMMENT_TEXT) || commentTextArea.getText().equals(ERROR_UPDATE_TEXT) ) {
|
||||||
commentTextArea.setText("");
|
commentTextArea.setText("");
|
||||||
commentTextArea.addStyleName("dark-color");
|
commentTextArea.addStyleName("comment-dark-color");
|
||||||
commentTextArea.removeStyleName("error");
|
commentTextArea.removeStyleName("error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
|
||||||
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
|
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
|
||||||
xmlns:g="urn:import:com.google.gwt.user.client.ui">
|
xmlns:g="urn:import:com.google.gwt.user.client.ui"
|
||||||
|
xmlns:m="urn:import:org.gcube.portlets.user.newsfeed.client.templates">
|
||||||
<ui:style>
|
<ui:style>
|
||||||
.important {
|
.important {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
</ui:style>
|
</ui:style>
|
||||||
<g:HTMLPanel styleName="comment-hidden" ui:field="mainPanel">
|
<g:HTMLPanel styleName="comment-hidden" ui:field="mainPanel">
|
||||||
<table class="">
|
<table class="">
|
||||||
<tr>
|
<tr>
|
||||||
<td width="30px;" align="middle">
|
<td width="30px;" align="middle">
|
||||||
|
@ -16,9 +17,18 @@
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<div class="commentContainer">
|
<div id="comment-supercontainer">
|
||||||
<g:TextArea styleName="post-comment" ui:field="commentTextArea" />
|
<div id="comment-highlighterContainer">
|
||||||
|
<div id="comment-highlighter">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="comment-inputContainer">
|
||||||
|
<m:SuperPosedTextArea styleName="post-comment" ui:field="commentTextArea" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- <div class="commentContainer"> -->
|
||||||
|
<!-- <g:TextArea styleName="post-comment" ui:field="commentTextArea" /> -->
|
||||||
|
<!-- </div> -->
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -0,0 +1,196 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.gcube.portlets.user.newsfeed.client.templates;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.gcube.portlets.user.newsfeed.client.NewsService;
|
||||||
|
import org.gcube.portlets.user.newsfeed.client.NewsServiceAsync;
|
||||||
|
import org.gcube.portlets.user.newsfeed.client.panels.NewsFeedPanel;
|
||||||
|
import org.gcube.portlets.widgets.pickuser.client.dialog.PickUsersDialog;
|
||||||
|
import org.gcube.portlets.widgets.pickuser.client.events.PickedUserEvent;
|
||||||
|
import org.gcube.portlets.widgets.pickuser.client.events.PickedUserEventHandler;
|
||||||
|
import org.gcube.portlets.widgets.pickuser.shared.PickingUser;
|
||||||
|
|
||||||
|
import com.google.gwt.core.client.GWT;
|
||||||
|
import com.google.gwt.dom.client.Element;
|
||||||
|
import com.google.gwt.event.dom.client.KeyCodes;
|
||||||
|
import com.google.gwt.event.shared.HandlerManager;
|
||||||
|
import com.google.gwt.user.client.DOM;
|
||||||
|
import com.google.gwt.user.client.Event;
|
||||||
|
import com.google.gwt.user.client.Timer;
|
||||||
|
import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||||
|
import com.google.gwt.user.client.ui.TextArea;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author massi
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SuperPosedTextArea extends TextArea {
|
||||||
|
|
||||||
|
private final NewsServiceAsync newsService = GWT.create(NewsService.class);
|
||||||
|
|
||||||
|
private final HandlerManager eventBus = new HandlerManager(null);
|
||||||
|
private final static String COMMENT_TEXT = "Add a comment ... use @ to mention someone";
|
||||||
|
private final static String ERROR_UPDATE_TEXT = "Looks like empty to me!";
|
||||||
|
|
||||||
|
PickUsersDialog pickUserDlg;
|
||||||
|
public final static int ARROW_UP = 38;
|
||||||
|
public final static int ARROW_DOWN = 40;
|
||||||
|
|
||||||
|
private ArrayList<String> mentionedUsers = new ArrayList<String>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public SuperPosedTextArea() {
|
||||||
|
sinkEvents(Event.ONPASTE);
|
||||||
|
sinkEvents(Event.ONKEYUP);
|
||||||
|
sinkEvents(Event.ONCONTEXTMENU);
|
||||||
|
sinkEvents(Event.ONKEYDOWN);
|
||||||
|
|
||||||
|
newsService.getOrganizationUsers(NewsFeedPanel.getCurrentScope(), new AsyncCallback<ArrayList<PickingUser>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(ArrayList<PickingUser> users) {
|
||||||
|
pickUserDlg = new PickUsersDialog(users, eventBus, 450);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable caught) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
DOM.setElementAttribute(getElement(), "id", "postTextArea");
|
||||||
|
bind();
|
||||||
|
Timer t = new Timer() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
myAutoSize();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
t.schedule(1000);
|
||||||
|
}
|
||||||
|
public static native void myAutoSize() /*-{
|
||||||
|
function autoSizeArea() {
|
||||||
|
$wnd.jQuery('#postTextArea').autosize();
|
||||||
|
}
|
||||||
|
autoSizeArea();
|
||||||
|
}-*/;
|
||||||
|
/**
|
||||||
|
* @param element
|
||||||
|
*/
|
||||||
|
public SuperPosedTextArea(Element element) {
|
||||||
|
super(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* paste event overridden
|
||||||
|
*/
|
||||||
|
public void onBrowserEvent(Event event) {
|
||||||
|
super.onBrowserEvent(event);
|
||||||
|
switch (event.getTypeInt()) {
|
||||||
|
case Event.ONPASTE: {
|
||||||
|
if (getText().equals(COMMENT_TEXT) || getText().equals(ERROR_UPDATE_TEXT) ) {
|
||||||
|
setText("");
|
||||||
|
addStyleName("dark-color");
|
||||||
|
removeStyleName("error");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Event.ONKEYUP: {
|
||||||
|
injectInDiv(getText());
|
||||||
|
pickUserDlg.onKeyUp(event.getKeyCode(), this.getAbsoluteLeft(), this.getAbsoluteTop()+45, getText());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Event.ONCONTEXTMENU: {
|
||||||
|
removeSampleText();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Event.ONKEYDOWN: {
|
||||||
|
if (pickUserDlg.isShowing()) {
|
||||||
|
//avoid the arrow up to move the cursor at the beginning of the textbox and the TAB to move around inputs and enter to go newline
|
||||||
|
if (event.getKeyCode() == ARROW_UP || event.getKeyCode() == KeyCodes.KEY_TAB || event.getKeyCode() == KeyCodes.KEY_ENTER) {
|
||||||
|
DOM.eventCancelBubble(event, true);
|
||||||
|
DOM.eventPreventDefault(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected void removeSampleText() {
|
||||||
|
if (getText().equals(COMMENT_TEXT) || getText().equals(ERROR_UPDATE_TEXT) ) {
|
||||||
|
setText("");
|
||||||
|
addStyleName("darker-color");
|
||||||
|
removeStyleName("error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected void cleanHighlighterDiv() {
|
||||||
|
DOM.getElementById("comment-highlighter").setInnerHTML("");
|
||||||
|
}
|
||||||
|
private void injectInDiv(String textAreaText) {
|
||||||
|
String text;
|
||||||
|
// parse the text:
|
||||||
|
// replace all the line braks by <br/>, and all the double spaces by the html version
|
||||||
|
text = textAreaText.replaceAll("(\r\n|\n)","<br />");
|
||||||
|
text = text.replaceAll("\\s\\s"," ");
|
||||||
|
|
||||||
|
for (String mentionedUser : mentionedUsers) {
|
||||||
|
text = text.replaceAll(mentionedUser,"<span class=\"highlightedUser\">"+mentionedUser+"</span>");
|
||||||
|
}
|
||||||
|
// re-inject the processed text into the div
|
||||||
|
DOM.getElementById("comment-highlighter").setInnerHTML(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* events binder
|
||||||
|
*/
|
||||||
|
private void bind() {
|
||||||
|
eventBus.addHandler(PickedUserEvent.TYPE, new PickedUserEventHandler() {
|
||||||
|
@Override
|
||||||
|
public void onSelectedUser(PickedUserEvent event) {
|
||||||
|
|
||||||
|
String toAdd = event.getSelectedUser().getFullName();
|
||||||
|
mentionedUsers.add(toAdd);
|
||||||
|
|
||||||
|
String[] toSplit = getText().split("@"); //get the preceeding part
|
||||||
|
|
||||||
|
setText(toSplit[0]+toAdd);
|
||||||
|
Element highDiv = DOM.getElementById("comment-highlighter");
|
||||||
|
|
||||||
|
String[] htmlToSplit = highDiv.getInnerHTML().split("@"); //get the preceeding part
|
||||||
|
String highLightedUser = "<span class=\"highlightedUser\">"+toAdd+"</span>";
|
||||||
|
highDiv.setInnerHTML(htmlToSplit[0]+highLightedUser);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<String> getMentionedUsers() {
|
||||||
|
ArrayList<String> toReturn = new ArrayList<String>();
|
||||||
|
for (String mentionedUser : mentionedUsers) {
|
||||||
|
if (getText().contains(mentionedUser))
|
||||||
|
toReturn.add(mentionedUser);
|
||||||
|
}
|
||||||
|
GWT.log(toReturn.toString());
|
||||||
|
return mentionedUsers;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* <script>
|
||||||
|
$(document).ready(function(){
|
||||||
|
setTimeout(function(){
|
||||||
|
$('.postTextArea').autosize();
|
||||||
|
}, 3000);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
|
@ -40,6 +40,7 @@ import org.gcube.portlets.user.newsfeed.shared.EnhancedFeed;
|
||||||
import org.gcube.portlets.user.newsfeed.shared.MoreFeedsBean;
|
import org.gcube.portlets.user.newsfeed.shared.MoreFeedsBean;
|
||||||
import org.gcube.portlets.user.newsfeed.shared.NewsConstants;
|
import org.gcube.portlets.user.newsfeed.shared.NewsConstants;
|
||||||
import org.gcube.portlets.user.newsfeed.shared.UserSettings;
|
import org.gcube.portlets.user.newsfeed.shared.UserSettings;
|
||||||
|
import org.gcube.portlets.widgets.pickuser.shared.PickingUser;
|
||||||
import org.gcube.vomanagement.usermanagement.GroupManager;
|
import org.gcube.vomanagement.usermanagement.GroupManager;
|
||||||
import org.gcube.vomanagement.usermanagement.impl.liferay.LiferayGroupManager;
|
import org.gcube.vomanagement.usermanagement.impl.liferay.LiferayGroupManager;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -111,7 +112,7 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
|
||||||
}
|
}
|
||||||
public String getDevelopmentUser() {
|
public String getDevelopmentUser() {
|
||||||
String user = "test.user";
|
String user = "test.user";
|
||||||
//user = "massimiliano.assante";
|
user = "massimiliano.assante";
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -680,6 +681,12 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public ArrayList<PickingUser> getOrganizationUsers(String currentScope) {
|
||||||
|
ArrayList<PickingUser> toReturn = UsersUtil.getOrganizationUsers(currentScope, getASLSession().getUsername(), withinPortal);
|
||||||
|
_log.trace("Returning " + toReturn.size() + " users for scope " + currentScope);
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
private UserSettings getUserSettingsFromSession() {
|
private UserSettings getUserSettingsFromSession() {
|
||||||
try {
|
try {
|
||||||
|
@ -861,4 +868,6 @@ public class NewsServiceImpl extends RemoteServiceServlet implements NewsService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
package org.gcube.portlets.user.newsfeed.server;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.gcube.common.scope.impl.ScopeBean;
|
||||||
|
import org.gcube.common.scope.impl.ScopeBean.Type;
|
||||||
|
import org.gcube.portal.custom.communitymanager.OrganizationsUtil;
|
||||||
|
import org.gcube.portlets.widgets.pickuser.shared.PickingUser;
|
||||||
|
import org.gcube.vomanagement.usermanagement.GroupManager;
|
||||||
|
import org.gcube.vomanagement.usermanagement.UserManager;
|
||||||
|
import org.gcube.vomanagement.usermanagement.impl.liferay.LiferayGroupManager;
|
||||||
|
import org.gcube.vomanagement.usermanagement.impl.liferay.LiferayUserManager;
|
||||||
|
import org.gcube.vomanagement.usermanagement.model.UserModel;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.liferay.portal.service.UserLocalServiceUtil;
|
||||||
|
|
||||||
|
public class UsersUtil {
|
||||||
|
private static final Logger _log = LoggerFactory.getLogger(UsersUtil.class);
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param session the Asl Session
|
||||||
|
* @param withinPortal true when is on Liferay portal
|
||||||
|
* @return the users belonging to the current organization (scope)
|
||||||
|
*/
|
||||||
|
public static ArrayList<PickingUser> getOrganizationUsers(String scope, String currUser, boolean withinPortal) {
|
||||||
|
ArrayList<PickingUser> portalUsers = new ArrayList<PickingUser>();
|
||||||
|
try {
|
||||||
|
if (withinPortal) {
|
||||||
|
UserManager um = new LiferayUserManager();
|
||||||
|
GroupManager gm = new LiferayGroupManager();
|
||||||
|
ScopeBean sb = new ScopeBean(scope);
|
||||||
|
List<UserModel> users = null;
|
||||||
|
|
||||||
|
if (sb.is(Type.INFRASTRUCTURE))
|
||||||
|
users = um.listUsersByGroup(gm.getRootVO().getGroupId());
|
||||||
|
else if (sb.is(Type.VRE)) { //must be in VRE
|
||||||
|
//get the name from the scope
|
||||||
|
String orgName = scope.substring(scope.lastIndexOf("/")+1, scope.length());
|
||||||
|
//ask the users
|
||||||
|
users = um.listUsersByGroup(gm.getGroupId(orgName));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_log.error("Error, you must be in SCOPE VRE OR INFRASTURCTURE, you are in VO SCOPE returning no users");
|
||||||
|
return portalUsers;
|
||||||
|
}
|
||||||
|
for (UserModel user : users) {
|
||||||
|
if (user.getScreenName().compareTo("test.user") != 0 && user.getScreenName().compareTo(currUser) != 0) { //skip test.user & current user
|
||||||
|
String thumbnailURL = "";
|
||||||
|
com.liferay.portal.model.UserModel lifeUser = UserLocalServiceUtil.getUserByScreenName(OrganizationsUtil.getCompany().getCompanyId(), user.getScreenName());
|
||||||
|
thumbnailURL = "/image/user_male_portrait?img_id="+lifeUser.getPortraitId();
|
||||||
|
portalUsers.add(new PickingUser(user.getUserId(), user.getScreenName(), user.getFullname(), thumbnailURL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { //test users
|
||||||
|
portalUsers.add(new PickingUser("12111", "massimiliano.assante", "Test User #1", ""));
|
||||||
|
portalUsers.add(new PickingUser("14111", "massimiliano.assante", "Test Second User #2", ""));
|
||||||
|
portalUsers.add(new PickingUser("11511", "massimiliano.assante", "Test Third User", ""));
|
||||||
|
portalUsers.add(new PickingUser("11611", "massimiliano.assante", "Test Fourth User", ""));
|
||||||
|
portalUsers.add(new PickingUser("11711", "massimiliano.assante", "Test Fifth User", ""));
|
||||||
|
portalUsers.add(new PickingUser("11811", "massimiliano.assante", "Test Sixth User", ""));
|
||||||
|
portalUsers.add(new PickingUser("15811", "massimiliano.assante", "Ninth Testing User", ""));
|
||||||
|
portalUsers.add(new PickingUser("15811", "massimiliano.assante", "Eighth Testing User", ""));
|
||||||
|
portalUsers.add(new PickingUser("11211", "giogio.giorgi", "Seventh Test User", ""));
|
||||||
|
portalUsers.add(new PickingUser("2222", "pino.pinetti", "Tenth Testing User", ""));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
_log.error("Error in server get all contacts ", e);
|
||||||
|
}
|
||||||
|
return portalUsers;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
<inherits name='com.google.gwt.user.User' />
|
<inherits name='com.google.gwt.user.User' />
|
||||||
|
|
||||||
<!-- To Comment out -->
|
<!-- To Comment out -->
|
||||||
<!-- <set-property name="user.agent" value="safari,gecko1_8,ie9" /> -->
|
<set-property name="user.agent" value="safari,gecko1_8,ie9" />
|
||||||
|
|
||||||
<!-- Other module inherits -->
|
<!-- Other module inherits -->
|
||||||
<inherits name="net.eliasbalasis.tibcopagebus4gwt.tibcopagebus4gwt" />
|
<inherits name="net.eliasbalasis.tibcopagebus4gwt.tibcopagebus4gwt" />
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
<inherits name='org.gcube.portlets.widgets.wsmail.WsMail_Widget' />
|
<inherits name='org.gcube.portlets.widgets.wsmail.WsMail_Widget' />
|
||||||
<inherits name='org.gcube.portlets.widgets.userselection.UserSelection' />
|
<inherits name='org.gcube.portlets.widgets.userselection.UserSelection' />
|
||||||
<inherits name='org.gcube.portlets.widgets.sessionchecker.SessionChecker' />
|
<inherits name='org.gcube.portlets.widgets.sessionchecker.SessionChecker' />
|
||||||
|
<inherits name='org.gcube.portlets.widgets.pickuser.PickUser' />
|
||||||
<inherits
|
<inherits
|
||||||
name='org.gcube.portlets.widgets.lighttree.WorkspacePortletLightTree' />
|
name='org.gcube.portlets.widgets.lighttree.WorkspacePortletLightTree' />
|
||||||
<inherits name='org.gcube.portal.databook.GCubeSocialNetworking' />
|
<inherits name='org.gcube.portal.databook.GCubeSocialNetworking' />
|
||||||
|
|
|
@ -5,6 +5,69 @@ table {
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Superpose TextArea and Highlight DIV trick starts here */
|
||||||
|
#comment-supercontainer {
|
||||||
|
position: relative;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
#comment-highlighterContainer {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
cursor: text;
|
||||||
|
width: 525px;
|
||||||
|
height: 54px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#comment-inputContainer {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#comment-highlighter {
|
||||||
|
padding: 4px 2px;
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #FFF;
|
||||||
|
margin-top: 0;
|
||||||
|
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
|
||||||
|
sans-serif;
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: normal;
|
||||||
|
line-height: normal;
|
||||||
|
|
||||||
|
border: 1px solid transparent;
|
||||||
|
|
||||||
|
width: 450px;
|
||||||
|
min-height: 40px;
|
||||||
|
|
||||||
|
word-wrap: break-word; /* this is very important when usere paste long links*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-comment {
|
||||||
|
padding: 4px 2px;
|
||||||
|
color: #999;
|
||||||
|
background-color: transparent;
|
||||||
|
|
||||||
|
margin-top: 0px;
|
||||||
|
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
|
||||||
|
sans-serif;
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: normal;
|
||||||
|
line-height: normal;
|
||||||
|
|
||||||
|
border: 1px solid #999;
|
||||||
|
|
||||||
|
width: 450px;
|
||||||
|
min-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlightedUser {
|
||||||
|
background-color: #D8DFEA !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DIV trick ends here */
|
||||||
|
|
||||||
.framed {
|
.framed {
|
||||||
margin: 0 0 10px;
|
margin: 0 0 10px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
@ -300,20 +363,6 @@ table {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-comment {
|
|
||||||
height: 30px;
|
|
||||||
width: 99%;
|
|
||||||
color: #999;
|
|
||||||
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
|
|
||||||
sans-serif;
|
|
||||||
font-size: 11px;
|
|
||||||
padding: 4px 2px;
|
|
||||||
border-color: #999;
|
|
||||||
border-width: 1px;
|
|
||||||
letter-spacing: normal;
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.seemore,a.seemore:visited {
|
a.seemore,a.seemore:visited {
|
||||||
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
|
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
|
@ -520,9 +569,9 @@ a.link:hover {
|
||||||
-webkit-transition: background .45s ease-in-out;
|
-webkit-transition: background .45s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-color {
|
.comment-dark-color {
|
||||||
color: #333;
|
color: #333;
|
||||||
background-color: #FFF;
|
background-color: transparent;
|
||||||
transition: background .25s ease-in-out;
|
transition: background .25s ease-in-out;
|
||||||
-moz-transition: background .25s ease-in-out;
|
-moz-transition: background .25s ease-in-out;
|
||||||
-webkit-transition: background .25s ease-in-out;
|
-webkit-transition: background .25s ease-in-out;
|
||||||
|
|
|
@ -17,6 +17,13 @@
|
||||||
<!-- Any title is fine -->
|
<!-- Any title is fine -->
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<title>News Feed</title>
|
<title>News Feed</title>
|
||||||
|
|
||||||
|
<script src='js/jquery.min.js'></script>
|
||||||
|
<script src='js/jquery.autosize.js'></script>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
<script src="js/pagebus.js"></script>
|
<script src="js/pagebus.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
if(window.parent.PageBus) {
|
if(window.parent.PageBus) {
|
||||||
|
|
|
@ -0,0 +1,187 @@
|
||||||
|
/*!
|
||||||
|
jQuery Autosize v1.16.12
|
||||||
|
(c) 2013 Jack Moore - jacklmoore.com
|
||||||
|
updated: 2013-05-31
|
||||||
|
license: http://www.opensource.org/licenses/mit-license.php
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function ($) {
|
||||||
|
var
|
||||||
|
defaults = {
|
||||||
|
className: 'autosizejs',
|
||||||
|
append: '',
|
||||||
|
callback: false
|
||||||
|
},
|
||||||
|
hidden = 'hidden',
|
||||||
|
borderBox = 'border-box',
|
||||||
|
lineHeight = 'lineHeight',
|
||||||
|
|
||||||
|
// border:0 is unnecessary, but avoids a bug in FireFox on OSX
|
||||||
|
copy = '<textarea tabindex="-1" style="position:absolute; top:-999px; left:0; right:auto; bottom:auto; border:0; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden;"/>',
|
||||||
|
|
||||||
|
// line-height is conditionally included because IE7/IE8/old Opera do not return the correct value.
|
||||||
|
copyStyle = [
|
||||||
|
'fontFamily',
|
||||||
|
'fontSize',
|
||||||
|
'fontWeight',
|
||||||
|
'fontStyle',
|
||||||
|
'letterSpacing',
|
||||||
|
'textTransform',
|
||||||
|
'wordSpacing',
|
||||||
|
'textIndent'
|
||||||
|
],
|
||||||
|
oninput = 'oninput',
|
||||||
|
onpropertychange = 'onpropertychange',
|
||||||
|
|
||||||
|
// to keep track which textarea is being mirrored when adjust() is called.
|
||||||
|
mirrored,
|
||||||
|
|
||||||
|
// the mirror element, which is used to calculate what size the mirrored element should be.
|
||||||
|
mirror = $(copy).data('autosize', true)[0];
|
||||||
|
|
||||||
|
// test that line-height can be accurately copied.
|
||||||
|
mirror.style.lineHeight = '99px';
|
||||||
|
if ($(mirror).css(lineHeight) === '99px') {
|
||||||
|
copyStyle.push(lineHeight);
|
||||||
|
}
|
||||||
|
mirror.style.lineHeight = '';
|
||||||
|
|
||||||
|
$.fn.autosize = function (options) {
|
||||||
|
options = $.extend({}, defaults, options || {});
|
||||||
|
|
||||||
|
if (mirror.parentNode !== document.body) {
|
||||||
|
$(document.body).append(mirror);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.each(function () {
|
||||||
|
var
|
||||||
|
ta = this,
|
||||||
|
$ta = $(ta),
|
||||||
|
minHeight,
|
||||||
|
maxHeight,
|
||||||
|
resize,
|
||||||
|
boxOffset = 0,
|
||||||
|
callback = $.isFunction(options.callback);
|
||||||
|
|
||||||
|
if ($ta.data('autosize')) {
|
||||||
|
// exit if autosize has already been applied, or if the textarea is the mirror element.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ta.css('box-sizing') === borderBox || $ta.css('-moz-box-sizing') === borderBox || $ta.css('-webkit-box-sizing') === borderBox){
|
||||||
|
boxOffset = $ta.outerHeight() - $ta.height();
|
||||||
|
}
|
||||||
|
|
||||||
|
// IE8 and lower return 'auto', which parses to NaN, if no min-height is set.
|
||||||
|
minHeight = Math.max(parseInt($ta.css('minHeight'), 10) - boxOffset || 0, $ta.height());
|
||||||
|
|
||||||
|
resize = ($ta.css('resize') === 'none' || $ta.css('resize') === 'vertical') ? 'none' : 'horizontal';
|
||||||
|
|
||||||
|
$ta.css({
|
||||||
|
overflow: hidden,
|
||||||
|
overflowY: hidden,
|
||||||
|
wordWrap: 'break-word',
|
||||||
|
resize: resize
|
||||||
|
}).data('autosize', true);
|
||||||
|
|
||||||
|
function initMirror() {
|
||||||
|
mirrored = ta;
|
||||||
|
mirror.className = options.className;
|
||||||
|
maxHeight = parseInt($ta.css('maxHeight'), 10);
|
||||||
|
|
||||||
|
// mirror is a duplicate textarea located off-screen that
|
||||||
|
// is automatically updated to contain the same text as the
|
||||||
|
// original textarea. mirror always has a height of 0.
|
||||||
|
// This gives a cross-browser supported way getting the actual
|
||||||
|
// height of the text, through the scrollTop property.
|
||||||
|
$.each(copyStyle, function(i, val){
|
||||||
|
mirror.style[val] = $ta.css(val);
|
||||||
|
});
|
||||||
|
|
||||||
|
// The textarea overflow is probably now hidden, but Chrome doesn't reflow the text to account for the
|
||||||
|
// new space made available by removing the scrollbars. This workaround causes Chrome to reflow the text.
|
||||||
|
if (oninput in ta) {
|
||||||
|
var value = ta.value;
|
||||||
|
ta.value = '';
|
||||||
|
ta.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using mainly bare JS in this function because it is going
|
||||||
|
// to fire very often while typing, and needs to very efficient.
|
||||||
|
function adjust() {
|
||||||
|
var height, overflow, original;
|
||||||
|
|
||||||
|
if (mirrored !== ta) {
|
||||||
|
initMirror();
|
||||||
|
}
|
||||||
|
|
||||||
|
mirror.value = ta.value + options.append;
|
||||||
|
mirror.style.overflowY = ta.style.overflowY;
|
||||||
|
original = parseInt(ta.style.height,10);
|
||||||
|
|
||||||
|
// Update the width in case the original textarea width has changed
|
||||||
|
// A floor of 0 is needed because IE8 returns a negative value for hidden textareas, raising an error.
|
||||||
|
mirror.style.width = Math.max($ta.width(), 0) + 'px';
|
||||||
|
|
||||||
|
// Needed for IE8 and lower to reliably return the correct scrollTop
|
||||||
|
mirror.scrollTop = 0;
|
||||||
|
|
||||||
|
mirror.scrollTop = 9e4;
|
||||||
|
|
||||||
|
// Using scrollTop rather than scrollHeight because scrollHeight is non-standard and includes padding.
|
||||||
|
height = mirror.scrollTop;
|
||||||
|
|
||||||
|
if (maxHeight && height > maxHeight) {
|
||||||
|
height = maxHeight;
|
||||||
|
overflow = 'scroll';
|
||||||
|
} else if (height < minHeight) {
|
||||||
|
height = minHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
height += boxOffset;
|
||||||
|
ta.style.overflowY = overflow || hidden;
|
||||||
|
|
||||||
|
if (original !== height) {
|
||||||
|
ta.style.height = height + 'px';
|
||||||
|
if (callback) {
|
||||||
|
options.callback.call(ta,ta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onpropertychange in ta) {
|
||||||
|
if (oninput in ta) {
|
||||||
|
// Detects IE9. IE9 does not fire onpropertychange or oninput for deletions,
|
||||||
|
// so binding to onkeyup to catch most of those occassions. There is no way that I
|
||||||
|
// know of to detect something like 'cut' in IE9.
|
||||||
|
ta[oninput] = ta.onkeyup = adjust;
|
||||||
|
} else {
|
||||||
|
// IE7 / IE8
|
||||||
|
ta[onpropertychange] = function(){
|
||||||
|
if(event.propertyName === 'value'){
|
||||||
|
adjust();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Modern Browsers
|
||||||
|
ta[oninput] = adjust;
|
||||||
|
}
|
||||||
|
|
||||||
|
$(window).on('resize', function(){
|
||||||
|
active = false;
|
||||||
|
adjust();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Allow for manual triggering if needed.
|
||||||
|
$ta.on('autosize', function(){
|
||||||
|
active = false;
|
||||||
|
adjust();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Call adjust in case the textarea already contains text.
|
||||||
|
adjust();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}(window.jQuery || window.Zepto));
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue