package jj.engine;
import jj.http.server.websocket.CurrentWebSocketConnection;
import jj.jjmessage.EventNameHelper;
import jj.jjmessage.JJMessage;
import jj.script.CurrentScriptEnvironment;
import org.jsoup.nodes.Element;
import org.mozilla.javascript.Callable;
/**
* Pretty much every operation in here fires out on the wire.
* @author jason
*
*/
public class EventSelection implements Selection {
private final String selector;
private final CurrentWebSocketConnection connection;
private final CurrentScriptEnvironment env;
public EventSelection(final String selector, final CurrentWebSocketConnection connection, final CurrentScriptEnvironment env) {
this.selector = selector;
this.connection = connection;
this.env = env;
}
private void verifyContext(final String actionDescription) {
if (connection.current() == null) {
throw new IllegalStateException("cannot " + actionDescription + " from this context");
}
}
@Override
public String selector() {
return selector;
}
@Override
public Selection hide() {
verifyContext("hide a selection");
connection.current().send(JJMessage.makeSet(this.selector, "hide", null));
return this;
}
@Override
public Selection hide(final String duration) {
verifyContext("hide a selection");
connection.current().send(JJMessage.makeSet(this.selector, "hide", duration));
return this;
}
@Override
public Selection show() {
verifyContext("show a selection");
connection.current().send(JJMessage.makeSet(this.selector, "show", null));
return this;
}
@Override
public Selection show(final String duration) {
verifyContext("show a selection");
connection.current().send(JJMessage.makeSet(this.selector, "show", duration));
return this;
}
@Override
public Selection on(String type, Callable function) {
return on(type, "", function);
}
@Override
public Selection on(String type, String selector, Callable function) {
verifyContext("bind an event");
connection.current().send(JJMessage.makeBind(this.selector, selector, type));
connection.current().addFunction(EventNameHelper.makeEventName(this.selector, selector, type), function);
return this;
}
public Selection off(String type) {
return off(type, "");
}
public Selection off(String type, String selector) {
verifyContext("unbind an event");
if (connection.current().removeFunction(EventNameHelper.makeEventName(this.selector, selector, type))) {
connection.current().send(JJMessage.makeUnbind(this.selector, selector, type));
}
return this;
}
public Selection off(String type, Callable function) {
return off(type, "", function);
}
public Selection off(String type, String selector, Callable function) {
verifyContext("unbind an event");
if (connection.current().removeFunction(EventNameHelper.makeEventName(this.selector, selector, type), function)) {
connection.current().send(JJMessage.makeUnbind(this.selector, selector, type));
}
return this;
}
@Override
public Selection bind(String type, boolean cancel) {
throw new UnsupportedOperationException("bind with autocancel is not yet implemented");
}
@Override
public Selection bind(String type, Callable function) {
return on(type, function);
}
@Override
public Selection bind(String type, Object data, boolean cancel) {
throw new UnsupportedOperationException("bind with autocancel is not yet implemented");
}
@Override
public Selection bind(String type, Object data, Callable function) {
return on(type, function);
}
@Override
public Selection click(Callable function) {
return on("click", function);
}
@Override
public Selection enter(Callable function) {
return on("enter", function);
}
public String data(String key) {
verifyContext("get data");
throw env.preparedContinuation(JJMessage.makeGet(selector, "data", key));
}
@Override
public Selection data(String key, String value) {
verifyContext("set data");
connection.current().send(JJMessage.makeSet(selector, "data", key, value));
return this;
}
@Override
public Selection text(String text) {
verifyContext("retrieve text");
connection.current().send(JJMessage.makeSet(selector, "text", text));
return this;
}
@Override
public Selection append(Selection selection) {
verifyContext("append");
connection.current().send(JJMessage.makeAppend(selector, selection.selector()));
return this;
}
@Override
public String attr(String attributeKey) {
verifyContext("get an attribute value");
throw env.preparedContinuation(JJMessage.makeGet(selector, "attr", attributeKey));
}
public String prop(String propKey) {
verifyContext("get an property value");
throw env.preparedContinuation(JJMessage.makeGet(selector, "prop", propKey));
}
@Override
public boolean hasAttr(String attributeKey) {
verifyContext("check for an attribute");
throw env.preparedContinuation(JJMessage.makeGet(selector, "hasAttr", attributeKey));
}
@Override
public Selection attr(String attributeKey, String attributeValue) {
verifyContext("set an attribute");
connection.current().send(JJMessage.makeSet(selector, "attr", attributeKey, attributeValue));
return this;
}
public Selection prop(String propKey, String propValue) {
verifyContext("set an property");
connection.current().send(JJMessage.makeSet(selector, "prop", propKey, propValue));
return this;
}
@Override
public Selection removeAttr(String attributeKey) {
verifyContext("remove an attribute");
connection.current().send(JJMessage.makeSet(selector, "removeAttr", attributeKey));
return this;
}
@Override
public Selection addClass(String className) {
verifyContext("add a class");
connection.current().send(JJMessage.makeSet(selector, "addClass", className));
return this;
}
@Override
public Selection removeClass(String className) {
verifyContext("remove a class");
connection.current().send(JJMessage.makeSet(selector, "removeClass", className));
return this;
}
@Override
public Selection toggleClass(String className) {
verifyContext("toggle a class");
connection.current().send(JJMessage.makeSet(selector, "toggleClass", className));
return this;
}
@Override
public boolean hasClass(String className) {
verifyContext("check for a class");
throw env.preparedContinuation(JJMessage.makeGet(selector, "hasClass", className));
}
@Override
public String val() {
verifyContext("retrieve a value");
throw env.preparedContinuation(JJMessage.makeGet(selector, "val"));
}
@Override
public Selection val(String value) {
verifyContext("set a value");
connection.current().send(JJMessage.makeSet(selector, "val", value));
return this;
}
@Override
public String text() {
verifyContext("retrieve text");
throw env.preparedContinuation(JJMessage.makeGet(selector, "text"));
}
@Override
public String html() {
verifyContext("retrieve html");
throw env.preparedContinuation(JJMessage.makeGet(selector, "html"));
}
@Override
public Selection html(String html) {
verifyContext("set html");
connection.current().send(JJMessage.makeSet(selector, "html", html));
return this;
}
@Override
public Selection prepend(String html) {
verifyContext("prepend html");
connection.current().send(JJMessage.makeSet(selector, "prepend", html));
return this;
}
@Override
public Selection append(String html) {
verifyContext("append html");
connection.current().send(JJMessage.makeSet(selector, "append", html));
return this;
}
@Override
public Selection before(String html) {
verifyContext("set html before");
connection.current().send(JJMessage.makeSet(selector, "before", html));
return this;
}
@Override
public Selection after(String html) {
verifyContext("set html after");
connection.current().send(JJMessage.makeSet(selector, "after", html));
return this;
}
@Override
public Selection wrap(String html) {
verifyContext("wrap elements with html");
connection.current().send(JJMessage.makeSet(selector, "wrap", html));
return this;
}
@Override
public Selection unwrap() {
verifyContext("unwrap elements");
connection.current().send(JJMessage.makeSet(selector, "unwrap", ""));
return this;
}
@Override
public Selection empty() {
verifyContext("empty an element set");
connection.current().send(JJMessage.makeSet(selector, "empty", ""));
return this;
}
@Override
public Selection remove() {
verifyContext("remove elements");
connection.current().send(JJMessage.makeSet(selector, "remove", ""));
return this;
}
@Override
public Selection select(String query) {
// this i believe is exactly what jquery does!
return new EventSelection(selector + " " + query, connection, env);
}
@Override
public Selection not(String query) {
throw new UnsupportedOperationException("not is not yet implemented");
}
@Override
public Selection eq(int index) {
throw new UnsupportedOperationException("eq is not yet implemented");
}
@Override
public boolean is(String query) {
throw new UnsupportedOperationException("is is not yet implemented (and may never be!)");
}
@Override
public Selection parents() {
throw new UnsupportedOperationException("parents is not yet implemented");
}
@Override
public Element first() {
throw new UnsupportedOperationException("first is not yet implemented and probably will never be");
}
@Override
public Element last() {
throw new UnsupportedOperationException("first is not yet implemented and probably will never be");
}
@Override
public Selection clone() {
return new EventSelection(selector, connection, env);
}
@Override
public String toString() {
return EventSelection.class.getSimpleName() + ": " + selector;
}
}