summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Feuer <mfeuer@jaguarlandrover.com>2015-06-24 15:52:08 -0700
committerMagnus Feuer <mfeuer@jaguarlandrover.com>2015-06-24 15:52:08 -0700
commit6d08b7662a0508a1a56581ee8338cb1797493282 (patch)
tree9a75b3a388d9defe0223601043b137036c465b7f
parent87a10222cc8321e93dda041013a90d53943e833e (diff)
parentda3e1513bddf34dbd6cb9de1ac964c688dbff40a (diff)
downloadrvi_core-6d08b7662a0508a1a56581ee8338cb1797493282.tar.gz
Merge branch 'testing' into release-next
-rw-r--r--backend.config2
-rw-r--r--components/dlink_bt/src/bt_connection.erl25
-rw-r--r--components/dlink_bt/src/dlink_bt_rpc.erl24
-rw-r--r--components/dlink_tcp/src/connection.erl134
-rw-r--r--components/rvi_common/src/rvi_common.erl135
-rw-r--r--components/service_discovery/src/service_discovery_rpc.erl8
-rw-r--r--components/service_edge/src/service_edge.app.src3
-rw-r--r--components/service_edge/src/service_edge_rpc.erl161
-rw-r--r--components/service_edge/src/wse_server.erl (renamed from deps/wse/src/wse_server.erl)337
-rw-r--r--deps/bt/.gitignore1
-rw-r--r--deps/bt/c_src/bt_linux_drv.c152
-rw-r--r--deps/wse/LICENSE24
-rw-r--r--deps/wse/README.md88
-rw-r--r--deps/wse/priv/base64.js83
-rw-r--r--deps/wse/priv/bd.jpgbin22732 -> 0 bytes
-rw-r--r--deps/wse/priv/button_demo.html22
-rw-r--r--deps/wse/priv/document_demo.html21
-rw-r--r--deps/wse/priv/ej.js672
-rw-r--r--deps/wse/priv/fish.html19
-rw-r--r--deps/wse/priv/fish/fish0001.pngbin8525 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0002.pngbin9342 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0003.pngbin6937 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0004.pngbin7584 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0005.pngbin9756 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0006.pngbin6421 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0007.pngbin7065 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0008.pngbin6157 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0009.pngbin2412 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0010.pngbin6136 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0011.pngbin6575 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0012.pngbin6088 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0013.pngbin10450 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0014.pngbin8429 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0015.pngbin6744 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0016.pngbin9061 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0017.pngbin8073 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0018.pngbin4662 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0019.pngbin3822 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0020.pngbin2083 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0021.pngbin2120 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0022.pngbin4025 -> 0 bytes
-rw-r--r--deps/wse/priv/fish/fish0023.pngbin5189 -> 0 bytes
-rw-r--r--deps/wse/priv/frame1.html20
-rw-r--r--deps/wse/priv/frame2.html20
-rw-r--r--deps/wse/priv/frame_demo.html23
-rw-r--r--deps/wse/priv/location.html30
-rw-r--r--deps/wse/priv/locationX.html9
-rw-r--r--deps/wse/priv/page_a.html20
-rw-r--r--deps/wse/priv/page_b.html20
-rw-r--r--deps/wse/priv/raphael-min.js11
-rw-r--r--deps/wse/priv/raphael.html21
-rw-r--r--deps/wse/priv/table_demo.html21
-rw-r--r--deps/wse/priv/utf8.js73
-rw-r--r--deps/wse/priv/wse.js725
-rw-r--r--deps/wse/priv/wse_demo.html13
-rw-r--r--deps/wse/rebar.config2
-rw-r--r--deps/wse/src/raphael.erl106
-rw-r--r--deps/wse/src/wse.app.src7
-rw-r--r--deps/wse/src/wse.erl453
-rw-r--r--deps/wse/src/wse_button_demo.erl50
-rw-r--r--deps/wse/src/wse_demo.erl24
-rw-r--r--deps/wse/src/wse_document_demo.erl71
-rw-r--r--deps/wse/src/wse_fish_demo.erl54
-rw-r--r--deps/wse/src/wse_frame_demo.erl137
-rw-r--r--deps/wse/src/wse_location_demo.erl46
-rw-r--r--deps/wse/src/wse_raphael_demo.erl73
-rw-r--r--deps/wse/src/wse_table_demo.erl109
-rw-r--r--packaging/tizen.config1
-rw-r--r--rebar.config4
-rw-r--r--rvi_sample.config1
70 files changed, 478 insertions, 3577 deletions
diff --git a/backend.config b/backend.config
index cc5dc55..317d894 100644
--- a/backend.config
+++ b/backend.config
@@ -43,8 +43,8 @@
%%
rvi,
rvi_common,
- service_edge,
service_discovery,
+ service_edge,
authorize,
schedule,
dlink_tcp,
diff --git a/components/dlink_bt/src/bt_connection.erl b/components/dlink_bt/src/bt_connection.erl
index ab6d5da..a5fc3c5 100644
--- a/components/dlink_bt/src/bt_connection.erl
+++ b/components/dlink_bt/src/bt_connection.erl
@@ -41,6 +41,7 @@
remote_addr = "00:00:00:00:00:00",
channel = 0,
rfcomm_ref = undefined,
+ listen_ref = undefined,
mod = undefined,
func = undefined,
args = undefined
@@ -150,6 +151,7 @@ init({accept, Channel, ListenRef, Mod, Fun, Arg}) ->
{ok, #st{
channel = Channel,
rfcomm_ref = ARef,
+ listen_ref = ListenRef,
mod = Mod,
func = Fun,
args = Arg
@@ -221,7 +223,7 @@ handle_cast(connect, #st {
rfcomm_ref = ConnRef
}};
- { err, Error } ->
+ { error, Error } ->
?info("Failed to connect to ~p-~p", [ BTAddr, Channel]),
{ stop, { connect_failed, Error}, St }
end;
@@ -282,20 +284,31 @@ handle_info({rfcomm, _ConnRef, {data, Data}},
{noreply, State};
-handle_info({rfcomm_closed, ConnRef},
+handle_info({rfcomm, ConnRef, closed},
#st { remote_addr = BTAddr,
channel = Channel,
+ listen_ref = ListenRef,
mod = Mod,
func = Fun,
args = Arg } = State) ->
- ?debug("~p:handle_info(tcp_closed): BTAddr: ~p:~p ", [ ?MODULE, BTAddr, Channel]),
+ ?debug("~p:handle_info(bt_closed): BTAddr: ~p:~p ", [ ?MODULE, BTAddr, Channel]),
Mod:Fun(self(), BTAddr, Channel, closed, Arg),
bt_connection_manager:delete_connection_by_pid(self()),
- rfcomm_close:close(ConnRef),
+ rfcomm:close(ConnRef),
+
+ %% Fire up a new accept process to take care of the next incomign connectionX
+ gen_server:start_link(?MODULE, {accept,
+ Channel,
+ ListenRef,
+ Mod,
+ Fun,
+ Arg},[]),
+
+ %% Stop this process.
{stop, normal, State};
-handle_info({rfcomm_error, ConnRef},
+handle_info({rfcomm, ConnRef, error},
#st { remote_addr = BTAddr,
channel = Channel,
mod = Mod,
@@ -310,7 +323,7 @@ handle_info({rfcomm_error, ConnRef},
handle_info(_Info, State) ->
- ?warning("~p:handle_cast(): Unknown info: ~p", [ ?MODULE, _Info]),
+ ?warning("~p:handle_info(): Unknown info: ~p", [ ?MODULE, _Info]),
{noreply, State}.
%%--------------------------------------------------------------------
diff --git a/components/dlink_bt/src/dlink_bt_rpc.erl b/components/dlink_bt/src/dlink_bt_rpc.erl
index 3e16ab0..7edc948 100644
--- a/components/dlink_bt/src/dlink_bt_rpc.erl
+++ b/components/dlink_bt/src/dlink_bt_rpc.erl
@@ -31,7 +31,6 @@
disconnect_data_link/2,
send_data/5]).
-
-include_lib("lager/include/log.hrl").
-include_lib("rvi_common/include/rvi_common.hrl").
-include_lib("rvi_common/include/rvi_dlink.hrl").
@@ -264,8 +263,8 @@ announce_local_service_(CompSpec,
[
{ ?DLINK_ARG_CMD, ?DLINK_CMD_SERVICE_ANNOUNCE },
{ ?DLINK_ARG_TRANSACTION_ID, 3},
- { ?DLINK_ARG_STATUS, atom_to_list(Status) },
- { ?DLINK_ARG_STATUS, { array, [Service]} },
+ { ?DLINK_ARG_STATUS, Status },
+ { ?DLINK_ARG_SERVICES, { array, [Service]} },
{ ?DLINK_ARG_SIGNATURE, "" }
]
})),
@@ -300,7 +299,7 @@ process_announce(FromPid,
RemoteBTAddr,
RemoteChannel,
TransactionID,
- "available",
+ "av",
Services,
Signature, CompSpec) ->
?debug("dlink_bt:service_announce(available): Address: ~p-~p", [ RemoteBTAddr, RemoteChannel ]),
@@ -318,7 +317,7 @@ process_announce(FromPid,
RemoteBTAddr,
RemoteChannel,
TransactionID,
- "unavailable",
+ "un",
Services,
Signature ,
CompSpec) ->
@@ -474,23 +473,31 @@ handle_socket(FromPid, PeerBTAddr, PeerChannel, data,
handle_socket(FromPid, SetupBTAddr, SetupChannel, closed, CompSpec) ->
?info("dlink_bt:closed(): SetupAddress: {~p, ~p}", [ SetupBTAddr, SetupChannel ]),
- NetworkAddress = SetupBTAddr ++ "-" ++ integer_to_list(SetupChannel),
+ NetworkAddress = bt_address_to_string(SetupBTAddr) ++ "-" ++ integer_to_list(SetupChannel),
%% Get all service records associated with the given connection
LostSvcNameList = get_services_by_connection(FromPid),
+ ?info("Will delete services: ~p~n", [ LostSvcNameList]),
delete_connection(FromPid),
- %% Check if this was our last connection supchanneling each given service.
+ %% Check if this was our last connection for each given service.
lists:map(
fun(SvcName) ->
case get_connections_by_service(SvcName) of
[] ->
+ ?info("No connection"),
service_discovery_rpc:
unregister_services(CompSpec,
[SvcName],
?MODULE);
- _ -> ok
+ _ ->
+ ?info("connection"),
+ service_discovery_rpc:
+ unregister_services(CompSpec,
+ [SvcName],
+ ?MODULE)
+
end
end, LostSvcNameList),
@@ -510,6 +517,7 @@ handle_socket(FromPid, SetupBTAddr, SetupChannel, closed, CompSpec) ->
BTAddr, Channel, CompSpec);
false -> ok
end,
+
ok;
handle_socket(FromPid, SetupBTAddr, SetupChannel, connected, _ExtraArgs) ->
diff --git a/components/dlink_tcp/src/connection.erl b/components/dlink_tcp/src/connection.erl
index 06a648d..daa5835 100644
--- a/components/dlink_tcp/src/connection.erl
+++ b/components/dlink_tcp/src/connection.erl
@@ -19,6 +19,7 @@
-behaviour(gen_server).
-include_lib("lager/include/log.hrl").
+
%% API
%% gen_server callbacks
@@ -36,13 +37,6 @@
-define(SERVER, ?MODULE).
--record(pst, {
- buffer = [],
- balance = start,
- in_string = false,
- escaped = false
- }).
-
-record(st, {
ip = {0,0,0,0},
port = 0,
@@ -146,7 +140,7 @@ init({IP, Port, Sock, Mod, Fun, Arg}) ->
mod = Mod,
func = Fun,
args = Arg,
- pst = #pst{}
+ pst = undefined
}}.
@@ -236,7 +230,7 @@ handle_info({tcp, Sock, Data},
?debug("~p:handle_info(data): Data: ~p", [ ?MODULE, Data]),
?debug("~p:handle_info(data): From: ~p:~p ", [ ?MODULE, IP, Port]),
- case extract_json(Data, PST) of
+ case rvi_common:extract_json(Data, PST) of
{ [], NPST } ->
?debug("~p:handle_info(data incomplete)", [ ?MODULE]),
inet:setopts(Sock, [{active, once}]),
@@ -313,125 +307,3 @@ code_change(_OldVsn, State, _Extra) ->
%%%===================================================================
%%% Internal functions
%%%===================================================================
-
-
-count_brackets([],
- #pst {
- buffer = [],
- balance = start } = PSt) ->
- { incomplete, PSt#pst {}};
-
-count_brackets([],
- #pst {
- buffer = Buffer,
- balance = start } = PSt) ->
- count_brackets(Buffer,
- PSt#pst {
- buffer = [],
- balance = start } );
-count_brackets([${ | Rem],
- #pst {
- buffer = Buffer,
- balance = start } = PSt) ->
- count_brackets(Rem,
- PSt#pst{
- buffer = [ ${ | Buffer ],
- balance = 1});
-
-%% Drop any initial characters prior to opening bracket
-count_brackets([_ | Rem],
- #pst { balance = start } = PSt) ->
- count_brackets(Rem, PSt );
-
-%% If balance is back to zero, we have completed a JSON
-%% element.
-count_brackets(Rem,
- #pst {
- buffer = Buffer,
- balance = 0 } = PSt) ->
-
- { complete, lists:reverse(Buffer),
- PSt#pst {
- buffer = Rem,
- balance = start
- }
- };
-
-%% If we still have balance, but no more input
-%% we have an incomplete element.x
-count_brackets([], PSt) ->
- { incomplete, PSt };
-
-
-%% We have a string start or end, and we are not esacped
-%% Flip our in-string state
-count_brackets([$" | Rem],
- #pst {
- buffer = Buffer,
- in_string = InString,
- escaped = false} = PSt) ->
-
- count_brackets(Rem, PSt#pst {
- buffer = [ $" | Buffer ],
- in_string = not InString });
-
-
-%% We have an escape character, and we are in a string. Turn on our escape state
-count_brackets([$\\ | Rem],
- #pst {
- buffer = Buffer,
- in_string = true,
- escaped = false } = PSt) ->
-
- count_brackets(Rem, PSt#pst {
- buffer = [ $\\ | Buffer ],
- escaped = true});
-
-%% We have an opening bracket and we are not in a string
-count_brackets([${ | Rem],
- #pst {
- buffer = Buffer,
- balance = Balance,
- in_string = false } = PSt) ->
-
- count_brackets(Rem,
- PSt#pst {
- buffer = [ ${ | Buffer ],
- balance = Balance + 1});
-
-%% We have an closing bracket and we are not in a string
-count_brackets([$} | Rem],
- #pst {
- buffer = Buffer,
- balance = Balance,
- in_string = false } = PSt) ->
-
- count_brackets(Rem,
- PSt#pst {
- buffer = [ $} | Buffer ],
- balance = Balance - 1});
-
-%% We have just regular data to feed over.
-%% Make sure to clear the escape state.
-count_brackets([C | Rem],
- #pst { buffer = Buffer } = PSt) ->
-
- count_brackets(Rem, PSt#pst {
- buffer = [ C | Buffer ],
- escaped = false
- } ).
-
-extract_json(Buf, PST, Acc) ->
- case count_brackets(Buf, PST) of
- { complete, Processed, NPST} ->
- io:format("Trying again~n"),
- extract_json([], NPST, [ Processed | Acc]);
-
-
- { incomplete, NPST} ->
- io:format("Incomplete~n"),
- { Acc, NPST }
- end.
-
-extract_json(Buf, PST) ->
- extract_json(Buf, PST,[]).
diff --git a/components/rvi_common/src/rvi_common.erl b/components/rvi_common/src/rvi_common.erl
index 2c16b40..19055af 100644
--- a/components/rvi_common/src/rvi_common.erl
+++ b/components/rvi_common/src/rvi_common.erl
@@ -41,10 +41,18 @@
]).
-export([start_json_rpc_server/3]).
+-export([extract_json/2]).
-define(NODE_SERVICE_PREFIX, node_service_prefix).
-define(NODE_ADDRESS, node_address).
+-record(pst, {
+ buffer = [],
+ balance = start,
+ in_string = false,
+ escaped = false
+ }).
+
json_rpc_status(0) ->
ok;
@@ -137,7 +145,7 @@ get_request_result({error, Reason})->
{ error, Reason};
get_request_result(ok)->
- { ok, ok, "{}"};
+ { ok, ok};
get_request_result(Other)->
?error("get_request_result(): Unhandled result: ~p", [Other]),
@@ -652,3 +660,128 @@ start_json_rpc_server(Component, Module, Supervisor) ->
Err
end.
+
+
+
+
+count_brackets([],
+ #pst {
+ buffer = [],
+ balance = start } = PSt) ->
+ { incomplete, PSt#pst {}};
+
+count_brackets([],
+ #pst {
+ buffer = Buffer,
+ balance = start } = PSt) ->
+ count_brackets(Buffer,
+ PSt#pst {
+ buffer = [],
+ balance = start } );
+count_brackets([${ | Rem],
+ #pst {
+ buffer = Buffer,
+ balance = start } = PSt) ->
+ count_brackets(Rem,
+ PSt#pst{
+ buffer = [ ${ | Buffer ],
+ balance = 1});
+
+%% Drop any initial characters prior to opening bracket
+count_brackets([_ | Rem],
+ #pst { balance = start } = PSt) ->
+ count_brackets(Rem, PSt );
+
+%% If balance is back to zero, we have completed a JSON
+%% element.
+count_brackets(Rem,
+ #pst {
+ buffer = Buffer,
+ balance = 0 } = PSt) ->
+
+ { complete, lists:reverse(Buffer),
+ PSt#pst {
+ buffer = Rem,
+ balance = start
+ }
+ };
+
+%% If we still have balance, but no more input
+%% we have an incomplete element.x
+count_brackets([], PSt) ->
+ { incomplete, PSt };
+
+
+%% We have a string start or end, and we are not esacped
+%% Flip our in-string state
+count_brackets([$" | Rem],
+ #pst {
+ buffer = Buffer,
+ in_string = InString,
+ escaped = false} = PSt) ->
+
+ count_brackets(Rem, PSt#pst {
+ buffer = [ $" | Buffer ],
+ in_string = not InString });
+
+
+%% We have an escape character, and we are in a string. Turn on our escape state
+count_brackets([$\\ | Rem],
+ #pst {
+ buffer = Buffer,
+ in_string = true,
+ escaped = false } = PSt) ->
+
+ count_brackets(Rem, PSt#pst {
+ buffer = [ $\\ | Buffer ],
+ escaped = true});
+
+%% We have an opening bracket and we are not in a string
+count_brackets([${ | Rem],
+ #pst {
+ buffer = Buffer,
+ balance = Balance,
+ in_string = false } = PSt) ->
+
+ count_brackets(Rem,
+ PSt#pst {
+ buffer = [ ${ | Buffer ],
+ balance = Balance + 1});
+
+%% We have an closing bracket and we are not in a string
+count_brackets([$} | Rem],
+ #pst {
+ buffer = Buffer,
+ balance = Balance,
+ in_string = false } = PSt) ->
+
+ count_brackets(Rem,
+ PSt#pst {
+ buffer = [ $} | Buffer ],
+ balance = Balance - 1});
+
+%% We have just regular data to feed over.
+%% Make sure to clear the escape state.
+count_brackets([C | Rem],
+ #pst { buffer = Buffer } = PSt) ->
+
+ count_brackets(Rem, PSt#pst {
+ buffer = [ C | Buffer ],
+ escaped = false
+ } ).
+
+extract_json(Buf, PST, Acc) ->
+ case count_brackets(Buf, PST) of
+ { complete, Processed, NPST} ->
+ extract_json([], NPST, [ Processed | Acc]);
+
+
+ { incomplete, NPST} ->
+ { Acc, NPST }
+ end.
+
+extract_json(Buf, undefined) ->
+ extract_json(Buf, #pst {},[]);
+
+extract_json(Buf, PST) ->
+ extract_json(Buf, PST,[]).
diff --git a/components/service_discovery/src/service_discovery_rpc.erl b/components/service_discovery/src/service_discovery_rpc.erl
index b67a7a9..b3d2a4d 100644
--- a/components/service_discovery/src/service_discovery_rpc.erl
+++ b/components/service_discovery/src/service_discovery_rpc.erl
@@ -395,6 +395,14 @@ notify_subscribers(CompSpec, Available, Services, DataLinkModule) ->
unavailable -> service_unavailable
end,
+
+ ets:foldl(
+ %% Notify if this is not the originating service.
+ fun(#subscriber_entry { module = Module }, Acc) ->
+ ?debug(" notify_subscribers module: ~p ", [ Module]),
+ ok
+ end, ok, ?SUBSCRIBER_TABLE),
+
%% Initiate with the first module
notify_single_subscriber(CompSpec,
ets:first(?SUBSCRIBER_TABLE),
diff --git a/components/service_edge/src/service_edge.app.src b/components/service_edge/src/service_edge.app.src
index 47c967e..8e08926 100644
--- a/components/service_edge/src/service_edge.app.src
+++ b/components/service_edge/src/service_edge.app.src
@@ -16,8 +16,7 @@
{applications, [
kernel,
stdlib,
- rvi_common,
- wse
+ rvi_common
]},
{mod, { service_edge_app, []}},
diff --git a/components/service_edge/src/service_edge_rpc.erl b/components/service_edge/src/service_edge_rpc.erl
index cff7fad..ccac474 100644
--- a/components/service_edge/src/service_edge_rpc.erl
+++ b/components/service_edge/src/service_edge_rpc.erl
@@ -2,7 +2,7 @@
%% Copyright (C) 2014, Jaguar Land Rover
%%
%% This program is licensed under the terms and conditions of the
-%% Mozilla Public License, version 2.0. The full text of the
+% Mozilla Public License, version 2.0. The full text of the
%% Mozilla Public License is at https://www.mozilla.org/MPL/2.0/
%%
@@ -12,11 +12,8 @@
-export([handle_rpc/2]).
-export([handle_notification/2]).
--export([wse_register_service/2]).
--export([wse_unregister_service/2]).
--export([wse_get_available_services/1]).
--export([wse_message/5]).
--export([wse_message/4]).
+-export([handle_websocket/3]).
+
-export([start_link/0]).
@@ -39,6 +36,7 @@
service_unavailable/3]).
+
%%-include_lib("lhttpc/include/lhttpc.hrl").
-include_lib("lager/include/log.hrl").
@@ -120,16 +118,18 @@ start_websocket() ->
Port ->
%% FIXME: MONITOR AND RESTART
- wse_server:start(Port, proplists:delete(port, WSOpts)),
+ wse_server:start(Port,
+ ?MODULE, handle_websocket, undefined,
+ [{type, text} | proplists:delete(port, WSOpts)]),
ok
end
end.
+
%% Invoked by service_discovery to announce service availability
%% Must be handled either as a JSON-RPC call or a gen_server call.
-
service_available(CompSpec, SvcName, DataLinkModule) ->
rvi_common:notification(service_edge, ?MODULE,
service_available,
@@ -164,44 +164,63 @@ handle_local_timeout(CompSpec, SvcName, TransID) ->
+handle_websocket(WSock, Mesg, Arg) ->
+ { ok, Method } = rvi_common:get_json_element(["method"], Mesg),
+ { ok, Params } = rvi_common:get_json_element(["params"], Mesg),
+ { ok, ID } = rvi_common:get_json_element(["id"], Mesg),
-%% Websocket interface
-wse_register_service(Ws, SvcName ) ->
- ?debug("service_edge_rpc:wse_register_service(~p) service: ~p", [ Ws, SvcName ]),
- gen_server:call(?SERVER, { rvi, register_local_service, [ SvcName, "ws:" ++ pid_to_list(Ws)]}),
- { ok, [ { status, rvi_common:json_rpc_status(ok)} ]}.
+ ?debug("service_edge_rpc:handle_websocket(~p/~p) method: ~p", [ WSock, ID,Method ]),
-wse_unregister_service(Ws, SvcName ) ->
- ?debug("service_edge_rpc:wse_unregister_service(~p) service: ~p", [ Ws, SvcName ]),
- gen_server:call(?SERVER, { rvi, unregister_local_service, [ SvcName ]}),
- { ok, [ { status, rvi_common:json_rpc_status(ok)} ]}.
+ case handle_ws_json_rpc(WSock, Method, {array,Params}, Arg) of
+ ok -> ok;
+ {ok, Reply} ->
+ EncReply = binary_to_list(iolist_to_binary(exo_json:encode({struct, [ { id, ID} |Reply]}))),
+ ?debug("service_edge_rpc:handle_websocket(~p/~p) reply: ~s", [ WSock, ID, EncReply]),
+ wse_server:send(WSock, list_to_binary(EncReply))
+ end,
+ ok.
-wse_get_available_services(_Ws ) ->
- ?debug("service_edge_rpc:wse_get_available_services()"),
- [ Services ] = gen_server:call(?SERVER, { rvi, get_available_services, []}),
- { ok, [ { status, rvi_common:json_rpc_status(ok)},
- { services, Services}] }.
-
+%% Websocket interface
+handle_ws_json_rpc(WSock, "message", Params, _Arg ) ->
+ { ok, SvcName } = rvi_common:get_json_element(["service_name"], Params),
+ { ok, Timeout } = rvi_common:get_json_element(["timeout"], Params),
+ { ok, Parameters } = rvi_common:get_json_element(["parameters"], Params),
-wse_message(Ws, SvcName, Timeout, JSONParameters) ->
- %% Parameters are delivered as JSON. Decode into tuple
- { ok, Parameters } = exo_json:decode_string(JSONParameters),
- ?debug("service_edge_rpc:wse_message(~p) SvcName: ~p", [ Ws, SvcName ]),
- ?debug("service_edge_rpc:wse_message(~p) Timeout: ~p", [ Ws, Timeout]),
- ?debug("service_edge_rpc:wse_message(~p) Parameters: ~p", [ Ws, Parameters ]),
+ ?debug("service_edge_rpc:handle_websocket(~p) params!: ~p", [ WSock, Params ]),
+ ?debug("service_edge_rpc:handle_websocket(~p) service: ~p", [ WSock, SvcName ]),
+ ?debug("service_edge_rpc:handle_websocket(~p) parameters: ~p", [ WSock, Parameters ]),
[ Res, TID ] = gen_server:call(?SERVER, { rvi, handle_local_message,
- [ SvcName, Timeout, Parameters]}),
+ [ SvcName, Timeout, [{struct, Parameters}]]}),
- ?debug("service_edge_rpc:wse_message(~p) Res: ~p", [ Ws, Res ]),
+ ?debug("service_edge_rpc:wse_message(~p) Res: ~p", [ WSock, Res ]),
{ ok, [ { status, rvi_common:json_rpc_status(Res) },
- { transaction_id, TID} ] }.
+ { transaction_id, TID} ] };
-%% Deprecated
-wse_message(Ws, SvcName, Timeout, JSONParameters, _CallingService) ->
- wse_message(Ws, SvcName, Timeout, JSONParameters).
+handle_ws_json_rpc(WSock, "register_service", Params,_Arg ) ->
+ { ok, SvcName } = rvi_common:get_json_element(["service_name"], Params),
+ ?debug("service_edge_rpc:websocket_register(~p) service: ~p", [ WSock, SvcName ]),
+ [ok, FullSvcName ] = gen_server:call(?SERVER,
+ { rvi,
+ register_local_service,
+ [ SvcName,
+ "ws:" ++ pid_to_list(WSock)]}),
+
+ { ok, [ { status, rvi_common:json_rpc_status(ok)},
+ { service, FullSvcName }]};
+handle_ws_json_rpc(WSock, "unregister_service", Params, _Arg ) ->
+ { ok, SvcName } = rvi_common:get_json_element(["service_name"], Params),
+ ?debug("service_edge_rpc:websocket_unregister(~p) service: ~p", [ WSock, SvcName ]),
+ gen_server:call(?SERVER, { rvi, unregister_local_service, [ SvcName ]}),
+ { ok, [ { status, rvi_common:json_rpc_status(ok)} ]};
+
+handle_ws_json_rpc(_Ws , "get_available_services", _Params, _Arg ) ->
+ ?debug("service_edge_rpc:websocket_get_available()"),
+ [ Services ] = gen_server:call(?SERVER, { rvi, get_available_services, []}),
+ { ok, [ { status, rvi_common:json_rpc_status(ok)},
+ { services, Services}] }.
%% Invoked by locally connected services.
@@ -312,10 +331,11 @@ handle_notification(Other, _Args) ->
%% connected services that uses the same HTTP port to transmit their
%% register_service, and message calls.
handle_call({ rvi, register_local_service, [SvcName, URL] }, _From, St) ->
- ?debug("service_edge_rpc:register_local_service(): service: ~p ", [SvcName]),
- ?debug("service_edge_rpc:register_local_service(): address: ~p ", [URL]),
+ ?debug("service_edge_rpc:register_local_service(): service: ~p ", [SvcName]),
+ ?debug("service_edge_rpc:register_local_service(): address: ~p ", [URL]),
FullSvcName = rvi_common:local_service_to_string(SvcName),
+ ?debug("service_edge_rpc:register_local_service(): full name: ~p ", [FullSvcName]),
ets:insert(?SERVICE_TABLE, #service_entry {
service = FullSvcName,
@@ -348,6 +368,13 @@ handle_call({rvi, get_available_services, []}, _From, St) ->
?debug("service_edge_rpc:get_available_services()"),
{reply, service_discovery_rpc:get_all_services(St#st.cs), St};
+
+%%CRASH13:43:57.370 [debug] service_edge_rpc:local_msg: parameters: [{struct,"{"value":"3"}"}]
+
+%%13:43:57.370 [debug] service_edge_rpc:local_msg: parameters: [{struct,"{"value":"3"}"}]
+%% [{struct,[{"a","b"}]}]
+%% 13:48:12.943 [debug] service_edge_rpc:local_msg: parameters: [{struct,[{"a","b"}]}]
+
handle_call({ rvi, handle_local_message,
[SvcName, TimeoutArg, Parameters] }, _From, St) ->
?debug("service_edge_rpc:local_msg: service_name: ~p", [SvcName]),
@@ -418,11 +445,13 @@ handle_call(Other, _From, St) ->
handle_cast({rvi, service_available, [SvcName, _DataLinkModule] }, St) ->
+ ?debug("service_edge_rpc: Service available: ~p:", [ SvcName]),
announce_service_availability(available, SvcName),
{ noreply, St };
handle_cast({rvi, service_unavailable, [SvcName, _DataLinkModule] }, St) ->
+ ?debug("service_edge_rpc: Service unavailable: ~p:", [ SvcName]),
announce_service_availability(unavailable, SvcName),
{ noreply, St };
@@ -527,13 +556,23 @@ flatten_ws_args(Args) ->
flatten_ws_args(Args, []).
+json_rpc_notification(Method, Parameters) ->
+ iolist_to_binary(
+ exo_json:encode(
+ {struct,
+ [ { "json-rpc", "2.0"},
+ { "method", Method },
+ { "params", {struct, Parameters}}
+ ]})).
+
dispatch_to_local_service([ $w, $s, $: | WSPidStr], services_available,
{struct, [{ services, { array, Services}}]} ) ->
?info("service_edge:dispatch_to_local_service(service_available, websock, ~p): ~p",
[ WSPidStr, Services]),
- wse:call(list_to_pid(WSPidStr), wse:window(),
- "services_available",
- [ "services", Services ]),
+ wse_server:send(list_to_pid(WSPidStr),
+ json_rpc_notification("services_available",
+ [{"services", {array, Services}}])),
+ %% No reply
ok;
dispatch_to_local_service([ $w, $s, $: | WSPidStr], services_unavailable,
@@ -541,24 +580,39 @@ dispatch_to_local_service([ $w, $s, $: | WSPidStr], services_unavailable,
?info("service_edge:dispatch_to_local_service(service_unavailable, websock, ~p): ~p",
[ WSPidStr, Services]),
- wse:call(list_to_pid(WSPidStr), wse:window(),
- "services_unavailable",
- [ "services", Services ]),
+ wse_server:send(list_to_pid(WSPidStr),
+ json_rpc_notification("services_unavailable",
+ [{"services", {array, Services}}])),
ok;
dispatch_to_local_service([ $w, $s, $: | WSPidStr], message,
- {struct, [{ service_name, SvcName}, { parameters, Args}]} ) ->
+ {struct, [{ service_name, SvcName}, { parameters, [ { struct, Args} ]}]} ) ->
?info("service_edge:dispatch_to_local_service(message, websock): ~p", [Args]),
- wse:call(list_to_pid(WSPidStr), wse:window(),
- "message",
- [ "service_name", SvcName ] ++ flatten_ws_args(Args)),
- ?debug("service_edge:dispatch_to_local_service(message, websock): Done", []),
+ wse_server:send(list_to_pid(WSPidStr),
+ json_rpc_notification("message",
+ [{ "service_name", SvcName}, {parameters, { struct, Args}}])),
+ %% No response expected.
+ ?debug("service_edge:dispatch_to_local_service(message, websock): Done"),
+ ok;
+
+dispatch_to_local_service([ $w, $s, $: | WSPidStr], message,
+ {struct, [{ service_name, SvcName}, { parameters,{array,[{struct, Args}]}}]}) ->
+ ?info("service_edge:dispatch_to_local_service(message/alt, websock): ~p", [Args]),
+ wse_server:send(list_to_pid(WSPidStr),
+ json_rpc_notification("message",
+ [{ "service_name", SvcName}, {parameters, { struct, Args}}])),
+ %% No response expected.
+ ?debug("service_edge:dispatch_to_local_service(message, websock): Done"),
+ ok;
+
+dispatch_to_local_service([ $w, $s, $: | _WSPidStr], message, Other) ->
+ ?warning("service_edge:dispatch_to_local_service(message/alt, websock): UNKNOWN: ~p", [Other]),
ok;
%% Dispatch to regular JSON-RPC over HTTP.
dispatch_to_local_service(URL, Command, Args) ->
CmdStr = atom_to_list(Command),
- ?debug("dispatch_to_local_service(): Command: ~p",[ CmdStr]),
+ ?debug("dispatch_to_local_service(): Command: ~p",[ Command]),
?debug("dispatch_to_local_service(): Args: ~p",[ Args]),
?debug("dispatch_to_local_service(): URL: ~p",[ URL]),
Res = rvi_common:send_json_request(URL, CmdStr, Args),
@@ -626,15 +680,22 @@ announce_service_availability(Available, SvcName) ->
[ #service_entry { url = URL } ] -> [URL];
[] -> []
end,
-
+ ets:foldl(fun(Term, _Acc) ->
+ ?debug("~p: ~p~n", [ ?SERVICE_TABLE, Term]),
+ ok
+ end, ok, ?SERVICE_TABLE),
+ ?debug("announce: service: ~p", [ SvcName]),
+ ?debug("announce: Block: ~p", [ BlockURLs]),
ets:foldl(
%% Notify if this is not the originating service.
fun(#service_entry { url = URL }, Acc) ->
%% If the URL is not on the blackout
%% list, send a notification
+ ?debug(" URL: ~p - Acc : ~p ", [ URL, Acc]),
case lists:member(URL, Acc) of
false ->
+ ?debug("DISPATCH: ~p: ~p", [ URL, Cmd]),
dispatch_to_local_service(URL, Cmd,
{struct, [ { services,
{ array, [SvcName]}
diff --git a/deps/wse/src/wse_server.erl b/components/service_edge/src/wse_server.erl
index 1ea4c58..e9897a7 100644
--- a/deps/wse/src/wse_server.erl
+++ b/components/service_edge/src/wse_server.erl
@@ -22,9 +22,12 @@
%%% Created : 9 Feb 2014 by Tony Rogvall <tony@rogvall.se>
-module(wse_server).
+-include_lib("lager/include/log.hrl").
--export([start/0, start/1, start/2, stop/1]).
+-export([start/4, start/5, stop/1]).
-export([ws_loop/3]).
+-export([send/2]).
+-export([close/1]).
-compile(export_all).
@@ -35,15 +38,7 @@
-define(WS_OP_PING, 9).
-define(WS_OP_PONG, 10).
--define(WSE_DEFAULT_PORT, 1234).
-
--record(event,
- {
- iref, %% global integer reference
- from, %% [owner local reference | event owner pid]
- how=once, %% once | all | none
- data %% local data for events
- }).
+-define(WSE_DEFAULT_PORT, 8808).
-record(ws_header,
{
@@ -72,30 +67,21 @@
fs = [], %% fragments
wait = [], %% #event
header, %% ws_header
- gc_table %% ets table of objects
+ cb = {undefined, undefined, undefined }
}).
--define(log(F,W,As),
- io:format("~s:~w: " ++ (W)++" "++(F)++"\n", [?MODULE, ?LINE | (As)])).
-%%-define(debug(F,As), ?log(F,"debug",As)).
--define(debug(F,A), ok).
--define(info(F,As), ?log(F,"info", As)).
--define(warn(F,As), ?log(F,"warn", As)).
--define(error(F,As), ?log(F,"error", As)).
%% start()
%% This should be in another module for clarity
%% but is included here to make the example self-contained
-start() -> start_([]).
-start(Port) when is_integer(Port) ->
- start_([{port,Port}]);
-start([AtomPort]) when is_atom(AtomPort) ->
- start(list_to_integer(atom_to_list(AtomPort))).
+start(Port, M, F, A) when is_integer(Port) ->
+ start_([{cb, {M,F,A}}, {port,Port}]).
-start(Port,Opts) when is_integer(Port) -> start_([{port,Port}|Opts]).
+start(Port,M,F,A, Opts) when is_integer(Port) ->
+ start_([{port,Port}, {cb, {M,F,A}}] ++ Opts).
start_(Opts) -> spawn(fun() -> init(Opts) end).
@@ -118,6 +104,8 @@ init(Opts) ->
process_flag(trap_exit, true),
listen_loop(Listen,Opts).
+
+
listen_loop(Listen,Opts) ->
?debug("Listen loop ~p\n", [Listen]),
Parent = self(),
@@ -130,13 +118,13 @@ accept_loop(Listen,Opts,Pid) ->
{Pid,ok} ->
?MODULE:listen_loop(Listen,Opts);
{Pid,Error} ->
- ?warn("process ~p error: ~p\n", [Pid, Error]),
+ ?warning("process ~p error: ~p\n", [Pid, Error]),
?MODULE:listen_loop(Listen,Opts);
{'EXIT',Pid,Reason} ->
- ?warn("process ~p crashed: ~p\n", [Pid, Reason]),
+ ?warning("process ~p crashed: ~p\n", [Pid, Reason]),
?MODULE:listen_loop(Listen,Opts);
{'EXIT',OtherPid,Reason} ->
- ?warn("other process ~p crashed: ~p\n", [OtherPid, Reason]),
+ ?debug("other process ~p exited: ~p\n", [OtherPid, Reason]),
?MODULE:accept_loop(Listen, Opts, Pid);
stop ->
gen_tcp:close(Listen),
@@ -155,28 +143,40 @@ accept(Parent, Listen, Opts) ->
Error ->
Parent ! {self(), Error}
end.
-%%
-%% Simple BERT
-%%
-bert_encode(Term) ->
- term_to_binary(Term).
-bert_decode(Bin) ->
- binary_to_term(Bin).
+
+send(Pid, Data) ->
+ try
+ Pid ! { send, Data },
+ ok
+ catch
+ error:Reason ->
+ ?info("wse_server:send(~p) failed : ~s\n", [Pid, Reason]),
+ {error, Reason}
+ end.
+
+
+close(Pid) ->
+ try
+ Pid ! close,
+ ok
+ catch
+ _:_ -> %% Already closed
+ ok
+ end.
+
%%
ws_encode(Term,?WS_OP_BINARY) ->
- bert_encode(Term);
+ Term;
ws_encode(Term,?WS_OP_TEXT) ->
- base64:encode(bert_encode(Term)).
-
-ws_decode(Data,?WS_OP_BINARY) -> {mesg,bert_decode(Data)};
-ws_decode(Data,?WS_OP_TEXT) -> {mesg,bert_decode(base64:decode(Data))};
-ws_decode(Data, ?WS_OP_PING) -> {ping, Data};
-ws_decode(Data, ?WS_OP_PONG) -> {pong,Data};
-ws_decode(Data, ?WS_OP_CLOSE) -> {close,Data}.
-
+ Term.
+ws_decode(Data, ?WS_OP_BINARY) -> {mesg, Data};
+ws_decode(Data, ?WS_OP_TEXT) -> {mesg, Data};
+ws_decode(Data, ?WS_OP_PING) -> {ping, Data};
+ws_decode(Data, ?WS_OP_PONG) -> {pong, Data};
+ws_decode(Data, ?WS_OP_CLOSE) -> {close,Data}.
ws_handshake(Socket,Opts) ->
receive
@@ -184,11 +184,11 @@ ws_handshake(Socket,Opts) ->
?debug("got ws request ~p", [_Req]),
ws_handshake(Socket, Uri, Opts);
{http, _Socket, Req={http_request, _, _, _}} ->
- ?warn("reject ws request ~p", [Req]),
+ ?warning("reject ws request ~p", [Req]),
%% send error reply!
ws_error({error, bad_request});
Any ->
- ?warn("reject ws data ~p", [Any]),
+ ?warning("reject ws data ~p", [Any]),
ws_error({error, no_data})
end.
@@ -236,7 +236,7 @@ ws_handshake(Socket, _Uri, Opts) ->
pingInterval=PingInterval,
pongTimeout=PongTimeout,
header = F,
- gc_table = ets:new(gc_table, [])
+ cb = proplists:get_value(cb, Opts, {undefined, undefined, undefined})
},
S1 = start_ping_timer(S0),
ws_loop(<<>>, Socket, S1);
@@ -278,40 +278,17 @@ ws_recv_headers(S, F, Timeout) ->
{error, timeout}
end.
-%%
-%% Reply on event
-%% if reply returns true then the event should stay
-%% otherwise the event should be deleted
-%%
-reply(E, Reply) ->
- if E#event.how == none ->
- false;
- true ->
- [Ref|Pid] = E#event.from,
- Pid ! {reply,Ref,Reply},
- E#event.how == all
- end.
-next_ref(Ref) ->
- Ref1 = (Ref+1) band 16#ffffffff,
- if Ref1 == 0 ->
- 1;
- true ->
- Ref1
- end.
-
ws_loop(Buf, Socket, S) ->
receive
%% WebSocket stuff
{tcp, Socket, Data} ->
- %% ?debug("tcp ~w: ~p", [Socket, Data]),
+ ?debug("tcp ~w: ~p", [Socket, Data]),
ws_data(Buf, Data, Socket, S);
{tcp_closed, Socket} ->
?debug("tcp_closed ~w", [Socket]),
- %% reply to all remaining callers
- lists:foreach(fun(E) -> reply(E, {error,closed}) end, S#s.wait),
exit(closed);
{'EXIT',Pid,Reason} ->
@@ -323,24 +300,9 @@ ws_loop(Buf, Socket, S) ->
?debug("exit from ~w reason=~p\n", [Pid, Reason]),
ws_loop(Buf, Socket, S)
end;
-
- {collect,ID} ->
- case ets:update_counter(S#s.gc_table, ID, -1) of
- 0 ->
- ?debug("garbage collect: delete ~w\n", [ID]),
- IRef = S#s.iref,
- Data = ws_encode({async,IRef,{delete,ID}},S#s.type),
- gen_tcp:send(Socket, ws_make_server_frame(Data,S#s.type)),
- S1 = S#s { iref=next_ref(IRef) },
- ets:delete(S#s.gc_table, ID),
- ws_loop(Buf, Socket, S1);
- _I ->
- ?debug("garbage collect: ~w ref=~w\n", [ID,_I]),
- ws_loop(Buf, Socket, S)
- end;
Message ->
- ?debug("handle_local: ~p", [Message]),
+ ?debug("handle_local: ~p - ~p", [Message, S]),
case handle_local(Message, Socket, S) of
{noreply,S1} ->
ws_loop(Buf, Socket, S1);
@@ -351,21 +313,23 @@ ws_loop(Buf, Socket, S) ->
end
end.
+
+
ws_data(Buf, Data, Socket, S) ->
case <<Buf/binary, Data/binary>> of
%% masked data
<<Fin:1,_Rsv:3,Op:4,1:1,126:7,L:16,M:4/binary,Frag:L/binary,Buf1/binary>> ->
- %% ?debug("unmask fragment: mask=~p, frag=~p", [M, Frag]),
+ ?debug("unmask fragment: mask=~p, frag=~p", [M, Frag]),
Frag1 = ws_mask(M, Frag),
S1 = ws_fragment(Socket, Fin, Op, Frag1, S),
ws_data(Buf1, <<>>, Socket, S1);
<<Fin:1,_Rsv:3,Op:4,1:1,127:7,L:64,M:4/binary,Frag:L/binary,Buf1/binary>> ->
- %% ?debug("unmask fragment: mask=~p, frag=~p", [M, Frag]),
+ ?debug("unmask fragment: mask=~p, frag=~p", [M, Frag]),
Frag1 = ws_mask(M, Frag),
S1 = ws_fragment(Socket,Fin, Op, Frag1, S),
ws_data(Buf1, <<>>, Socket, S1);
<<Fin:1,_Rsv:3,Op:4,1:1,L:7,M:4/binary,Frag:L/binary,Buf1/binary>> ->
- %% ?debug("unmask fragment: mask=~p, frag=~p", [M, Frag]),
+ ?debug("unmask fragment: mask=~p, frag=~p", [M, Frag]),
Frag1 = ws_mask(M, Frag),
S1 = ws_fragment(Socket,Fin, Op, Frag1, S),
ws_data(Buf1, <<>>, Socket, S1);
@@ -400,10 +364,11 @@ ws_mask(<<M:32>>, Frag) ->
ws_fragment(Socket,1, Op, Frag, S) ->
Payload = iolist_to_binary(lists:reverse([Frag|S#s.fs])),
- %% ?debug("op=~w, unmasked payload = ~p", [ws_opcode(Op),Payload]),
+ ?debug("op=~w, unmasked payload = ~p", [ws_opcode(Op),Payload]),
Message = ws_decode(Payload,Op),
?debug("handle_remote: ~p", [Message]),
handle_remote(Message, Socket, S#s { fs=[] });
+
ws_fragment(_Socket, 0, _Op, Frag, S) ->
%% ?debug("collect fragment: Op=~w, Frag=~p", [_Op,Frag]),
S#s { fs = [Frag|S#s.fs ]}.
@@ -441,62 +406,15 @@ ws_make_frame(Fin, Op, Mask, Data) ->
end.
-handle_local({rsync,From,Request},Socket,S0) ->
- IRef = S0#s.iref,
- Data = ws_encode({rsync,IRef,Request},S0#s.type),
- gen_tcp:send(Socket, ws_make_server_frame(Data,S0#s.type)),
- Event = #event{iref=IRef,from=From},
- Wait1 = [Event|S0#s.wait],
- {noreply,S0#s { iref=next_ref(IRef), wait=Wait1 }};
-handle_local({nsync,From,Request},Socket,S0) ->
- IRef = S0#s.iref,
- Data = ws_encode({nsync,IRef,Request},S0#s.type),
- gen_tcp:send(Socket, ws_make_server_frame(Data,S0#s.type)),
- Event = #event{iref=IRef,from=From,how=none},
- Wait1 = [Event|S0#s.wait],
- {noreply,S0#s { iref=next_ref(IRef), wait=Wait1 }};
-handle_local({async,_From,Request},Socket,S0) ->
- IRef = S0#s.iref,
- Data = ws_encode({async,IRef,Request},S0#s.type),
- gen_tcp:send(Socket, ws_make_server_frame(Data,S0#s.type)),
- {noreply,S0#s { iref=next_ref(IRef) }};
-handle_local({dsync,From,Request},Socket,S0) ->
- IRef = S0#s.iref,
- Data = ws_encode({dsync,IRef,Request},S0#s.type),
- gen_tcp:send(Socket, ws_make_server_frame(Data,S0#s.type)),
- Event = #event{iref=IRef,from=From},
- Wait1 = [Event|S0#s.wait],
- {noreply,S0#s { iref=next_ref(IRef), wait=Wait1 }};
-handle_local({close,From,Reason},Socket,S0) ->
- reply(#event { from=From} , ok),
- lists:foreach(fun(E) -> reply(E, {error, closed}) end, S0#s.wait),
- CloseData = if is_atom(Reason) -> atom_to_binary(Reason, latin1);
- true -> <<"unknown">>
- end,
- gen_tcp:send(Socket, ws_make_server_frame(CloseData,?WS_OP_CLOSE)),
- {noreply,S0#s { closing=server }};
-
-handle_local({create_event,From,How,Data},_Socket,S0) ->
- IRef = S0#s.iref,
- Event = #event { iref=IRef, from=From, how=How, data=Data},
- Wait1 = [Event|S0#s.wait],
- reply(Event, {ok, IRef}),
- {noreply,S0#s { iref=next_ref(IRef), wait=Wait1 }};
-
-handle_local({header, From},_Socket,S0=#s{header = Header}) ->
- ?debug("header: all\n", []),
- reply(#event {from=From}, {ok, Header#ws_header.hs}),
- {noreply,S0};
-
-handle_local({header, ItemName, From},_Socket,S0=#s{header = Header}) ->
- ?debug("header: ~p\n", [ItemName]),
- case lists:keyfind(ItemName, 1, Header#ws_header.hs) of
- {ItemName, ItemValue} ->
- reply(#event {from=From}, {ok, ItemValue});
- false ->
- reply(#event {from=From}, {error, unknown_header_item})
- end,
- {noreply,S0};
+handle_local({ send,Data},Socket,S0) ->
+ ?debug("wse_server:send(): ~p", [ Data]),
+ gen_tcp:send(Socket, ws_make_server_frame(Data, S0#s.type)),
+ { noreply,S0 };
+
+handle_local(close,Socket,S0) ->
+ ?debug("wse_server:close()"),
+ gen_tcp:send(Socket, ws_make_server_frame(<<"unknown">>,?WS_OP_CLOSE)),
+ {noreply, S0#s { closing=server }};
handle_local({timeout,Ref,ping},Socket,S0) when S0#s.ping_ref =:= Ref ->
%% ping the browser!
@@ -512,7 +430,7 @@ handle_local({timeout,Ref,pong},_Socket,S0) when S0#s.pong_tmr =:= Ref ->
{stop, not_responding};
handle_local(Other,_Socket,S0) ->
- ?warn("handle_local: got ~p~n",[Other]),
+ ?warning("handle_local: got ~p~n",[Other]),
{noreply,S0}.
%%
@@ -522,6 +440,7 @@ handle_remote({ping,Data}, Socket, S0) ->
%% ?debug("got ping ~p, sending pong ~p", [Data]),
gen_tcp:send(Socket, ws_make_server_frame(Data,?WS_OP_PONG)),
S0;
+
handle_remote({pong,Data}, _Socket, S0) ->
if Data =:= S0#s.ping_data ->
%% ?debug("got pong reply: ~p", [Data]),
@@ -531,6 +450,7 @@ handle_remote({pong,Data}, _Socket, S0) ->
?debug("got heartbeat pong: ~p", [Data]),
S0
end;
+
handle_remote({close,Data}, Socket, S0) ->
if S0#s.closing =:= server ->
?debug("got close ~p, both sides closed", [Data]),
@@ -541,128 +461,15 @@ handle_remote({close,Data}, Socket, S0) ->
gen_tcp:send(Socket, ws_make_server_frame(Data,?WS_OP_CLOSE)),
S0#s { closing = client }
end;
-handle_remote({mesg, Mesg0}, Socket, S0) ->
- Mesg = install_resource_objects(Mesg0, S0#s.gc_table),
- handle_mesg(Mesg, Socket, S0).
-
-
-handle_mesg({reply,IRef,Reply}, _Socket, S0) ->
- case lists:keytake(IRef, #event.iref, S0#s.wait) of
- false ->
- ?debug("got reply ~w = ~w (ignored)\n", [IRef,Reply]),
- S0;
- {value,Event,Wait1} ->
- ?debug("got reply ~w = ~w (~w)\n", [IRef,Reply,Event]),
- reply(Event, Reply),
- S0#s { wait=Wait1}
- end;
-handle_mesg({noreply,IRef},_Socket,S0) ->
- case lists:keytake(IRef, #event.iref, S0#s.wait) of
- false ->
- S0;
- {value,_Event,Wait1} ->
- S0#s { wait=Wait1}
- end;
-handle_mesg({notify,IRef,RemoteData},_Socket,S0) ->
- ?info("notify: ~w ~p\n", [IRef,RemoteData]),
- case lists:keytake(IRef,#event.iref, S0#s.wait) of
- false ->
- S0;
- {value,E,Wait1} ->
- [_Ref|Pid] = E#event.from,
- Pid ! {notify,IRef,E#event.data,RemoteData},
- if E#event.how == all ->
- S0;
- true ->
- S0#s { wait=Wait1}
- end
- end;
-handle_mesg({info,_Data},_Socket,S0) ->
- ?debug("info: ~p\n", [_Data]),
- S0;
-handle_mesg({start,M,F,As},_Socket,S0) ->
- _Pid = spawn_link(M,F,[self()|As]),
- ?debug("wse process ~w:~w/~w, started, pid=~p\n", [M,F,length(As),_Pid]),
- S0;
-handle_mesg({register,Name},_Socket,S0) ->
- ?debug("register ~p\n", [Name]),
- try register(Name,self()) of
- true -> S0
- catch
- error:Reason ->
- ?info("register of ~p failed : ~s\n", [Name, Reason]),
- S0
- end;
-handle_mesg({unregister}, _Socket, S0) ->
- case process_info(self(), registered_name) of
- [] -> S0;
- {registered_name,Name} ->
- ?debug("unregister ~p\n", [Name]),
- catch (unregister(Name)),
- S0
- end;
-handle_mesg({call,IRef,M,F,As},Socket,S0) ->
- %% maybe direct this to gen_server call on spawned processes?
- try apply(M,F,As) of
- Value ->
- Data = ws_encode({reply,IRef,{ok,Value}},S0#s.type),
- gen_tcp:send(Socket, ws_make_server_frame(Data,S0#s.type)),
- S0
- catch
- error:Reason ->
- Data = ws_encode({reply,IRef,{error,Reason}},S0#s.type),
- gen_tcp:send(Socket, ws_make_server_frame(Data,S0#s.type)),
- S0
- end;
-handle_mesg({cast,_IRef,M,F,As},_Socket,S0) ->
- %% maybe direct this to gen_server cast on spawned processes?
- catch (apply(M,F,As)),
- S0;
+
+handle_remote({mesg, Mesg}, _Socket, #s { cb = {M,F,A} } = S) ->
+ %% Parameters are delivered as JSON. Decode into tuple
+ _Pid = spawn_link(M,F,[self(), Mesg, A ]),
+ S.
handle_mesg(_Other, _Socket, S0) ->
?debug("unknown mesg ~p\n", [_Other]),
S0.
-%%
-%% Transform a message sent from java script so that
-%% {object,N} => {objec,N,resource()}
-%% {function,N} => {function,N,resource()}
-%%
-install_resource_objects(Message, GcTable) ->
- install_(Message, GcTable).
-
-install_(X, _GcTable) when is_number(X) -> X;
-install_(X, _GcTable) when is_atom(X) -> X;
-install_(X, _GcTable) when is_binary(X) -> X;
-install_(X, GcTable) when is_list(X) ->
- try erlang:io_list_size(X) of
- _ -> X
- catch
- error:_ -> install_list_(X, [], GcTable)
- end;
-install_({object,ID}, GcTable) when is_integer(ID) ->
- ets:insert_new(GcTable, {ID,0}),
- ets:update_counter(GcTable,ID,1),
- %% _RID is not relly needed so we use ID instead! (still unique)
- {resource,_RID,Ref} = resource:notify_when_destroyed(self(),
- {collect,ID}),
- {object,ID,Ref};
-install_(X={object,_}, _GcTable) -> X;
-
-install_(X, GcTable) when is_tuple(X) ->
- install_tuple_(size(X), X, [], GcTable).
-
-install_tuple_(0, _X, Acc, _GcTable) ->
- list_to_tuple(Acc);
-install_tuple_(I, X, Acc, GcTable) ->
- Y = install_(element(I,X), GcTable),
- install_tuple_(I-1, X, [Y|Acc], GcTable).
-
-install_list_([], Acc, _GcTable) ->
- lists:reverse(Acc);
-install_list_([H|T], Acc, GcTable) ->
- Y = install_(H, GcTable),
- install_list_(T, [Y|Acc], GcTable).
-
start_ping_timer(S0) ->
if is_integer(S0#s.pingInterval),S0#s.pingInterval>0 ->
diff --git a/deps/bt/.gitignore b/deps/bt/.gitignore
deleted file mode 100644
index b25c15b..0000000
--- a/deps/bt/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*~
diff --git a/deps/bt/c_src/bt_linux_drv.c b/deps/bt/c_src/bt_linux_drv.c
index 9dc54b9..d4fff55 100644
--- a/deps/bt/c_src/bt_linux_drv.c
+++ b/deps/bt/c_src/bt_linux_drv.c
@@ -58,6 +58,11 @@ int set_nonblock(int fd)
#define ERR_SHORT 1
#define ERR_LONG 2
+typedef struct {
+ bt_ctx_t* ctx; // access to subscription list
+ int pending_accepts;
+ subscription_list_t acceptors;
+} linux_listen_queue_t;
static int mgmt_open(void)
@@ -283,10 +288,10 @@ static void ddata_put_io_error(ddata_t* data, int errnum, int type)
static void cleanup(subscription_t* s)
{
DEBUGF("cleanup: %s", format_subscription(s));
- drv_data_t* lctx = (drv_data_t*) s->handle;
-
+
switch(s->type) {
case INQUIRY: {
+ drv_data_t* lctx = (drv_data_t*) s->handle;
bt_poll_del(lctx->inquiry_fd);
close(lctx->inquiry_fd);
@@ -302,7 +307,9 @@ static void cleanup(subscription_t* s)
case SDP_QUERY: break;
case SDP: break;
case RFCOMM: {
+ DEBUGF("cleanup: Disabling and closing descriptor %d", PTR2INT(s->handle));
bt_poll_del(PTR2INT(s->handle));
+ shutdown(PTR2INT(s->handle), 2); // Very likely not necessary at all
close(PTR2INT(s->handle));
break;
}
@@ -379,6 +386,8 @@ static void rfcomm_running(struct pollfd* pfd, void* arg)
if (pfd->revents & POLLIN) { // input ready
DEBUGF("rfcomm_running: %d has input", PTR2INT(s->handle));
+ DEBUGF("rfcomm_running: sub %p", s);
+ DEBUGF("rfcomm_running: id %d", s->id);
bt_data_len = read(pfd->fd, bt_data, sizeof(bt_data));
@@ -404,17 +413,18 @@ static void rfcomm_running(struct pollfd* pfd, void* arg)
ddata_send(&data, 1);
ddata_final(&data);
- release_subscription(s);
bt_poll_del(pfd->fd);
shutdown(pfd->fd, 2);
close(pfd->fd);
}
+
if (pfd->revents & POLLOUT) { // output ready
DEBUGF("rfcomm_running: %d may output", PTR2INT(s->handle));
// FIXME: Send additional pending data.
}
}
+
// CALLBACK
static void rfcomm_connected(struct pollfd* pfd, void* arg)
{
@@ -430,24 +440,61 @@ static void rfcomm_connected(struct pollfd* pfd, void* arg)
-// CALLBACK
static void rfcomm_accept(struct pollfd* pfd, void* arg)
{
- subscription_t *accept_s = (subscription_t*) arg;
-
// We have a pending client connection
+ subscription_t *listen_s = (subscription_t*) arg;
+ linux_listen_queue_t* lq = (linux_listen_queue_t*) listen_s->opaque;
struct sockaddr_rc rem_addr = { 0 };
- int client;
+ struct sockaddr_rc loc_addr = { 0 };
+ int client_des = 0;
socklen_t alen = sizeof(rem_addr);
uint8_t buf[64];
ddata_t data;
+ subscription_link_t* link = 0;
+ subscription_t* accept_s = 0;
- client = accept(pfd->fd, (struct sockaddr *)&rem_addr, &alen);
+ if (listen_s->type != RFCOMM_LISTEN) {
+ DEBUGF("RFCOMM: not a listen subscription: %d", listen_s->type);
+ exit(0);
+ }
- /* send EVENT id {accept,Address,Channel} */
-
- bt_poll_add(client, POLLIN | POLLHUP, rfcomm_running, accept_s);
- accept_s->handle = INT2PTR(client);
+ //
+ // Find a waiting process that is currently accepting traffic
+ //
+ if (!(link = lq->acceptors.first)) {
+ DEBUGF("RFCOMM: no accepting processes. Should not happen");
+ exit(0);
+ }
+
+ //
+ // Is this the last accepting subscription?
+ // If so. Remove the listen descriptor from the bt_poll
+ // subsystem until we have another acceptor
+ //
+ if (lq->acceptors.length == 1) {
+ DEBUGF("RFCOMM: This is the last accepting process. Will disable listen");
+ bt_poll_del(pfd->fd);
+ }
+ // Retrieve the accepting subscriber process
+ accept_s = link->s;
+
+ // Remove from acceptors waiting for an accept on this socket.
+ unlink_subscription(link);
+
+ client_des = accept(pfd->fd, (struct sockaddr *)&rem_addr, &alen);
+
+ bt_poll_add(client_des, POLLIN | POLLHUP, rfcomm_running, accept_s);
+
+ accept_s->handle = INT2PTR(client_des);
+ accept_s->accept = 0; // We are now a regular RFCOMM connection.
+
+ getsockname(client_des, (struct sockaddr *)&loc_addr, &alen);
+
+ DEBUGF("RFCOMM: accept on %X", &loc_addr.rc_channel);
+ DEBUGF("RFCOMM: desc %d", client_des);
+ DEBUGF("RFCOMM: ptr %p", accept_s);
+ DEBUGF("RFCOMM: id %p", accept_s->id);
ddata_init(&data, buf, sizeof(buf), 0);
ddata_put_UINT32(&data, 0);
@@ -456,7 +503,7 @@ static void rfcomm_accept(struct pollfd* pfd, void* arg)
ddata_put_tag(&data, TUPLE);
ddata_put_atom(&data, "accept");
ddata_put_addr(&data, &rem_addr.rc_bdaddr);
- ddata_put_uint8(&data, PTR2INT(accept_s->handle));
+ ddata_put_uint8(&data, loc_addr.rc_channel);
ddata_put_tag(&data, TUPLE_END);
ddata_send(&data, 1);
ddata_final(&data);
@@ -621,7 +668,7 @@ void bt_command(bt_ctx_t* ctx, const uint8_t* src, uint32_t src_len)
uint32_t sid = 0;
uint8_t channel = 0;
subscription_t* listen_sub = 0;
-// listen_queue_t* lq = 0;
+ linux_listen_queue_t* lq = 0;
int listen_desc = 0;
struct sockaddr_rc loc_addr = { 0 };
int dev_id;
@@ -651,6 +698,11 @@ void bt_command(bt_ctx_t* ctx, const uint8_t* src, uint32_t src_len)
cleanup)) == NULL)
goto mem_error;
+ if ((lq = alloc_type(linux_listen_queue_t)) == NULL) {
+ release_subscription(listen_sub);
+ goto mem_error;
+ }
+
dev_id = hci_get_route(NULL);
hci_devinfo(dev_id, &dev_info);
ba2str( &dev_info.bdaddr, buf );
@@ -680,9 +732,13 @@ void bt_command(bt_ctx_t* ctx, const uint8_t* src, uint32_t src_len)
}
listen_sub->handle = INT2PTR(listen_desc);
- listen_sub->opaque = INT2PTR(channel);
+ listen_sub->opaque = (void* ) lq;
insert_last(&ctx->list, listen_sub);
+ // We will not add the listen descriptor to
+ // the bt_poll subsystem until we have t least
+ // one acceptor.
+
ddata_put_tag(&data_out, REPLY_OK);
ddata_put_UINT32(&data_out, cmdid);
goto reply;
@@ -692,8 +748,8 @@ void bt_command(bt_ctx_t* ctx, const uint8_t* src, uint32_t src_len)
case CMD_RFCOMM_ACCEPT: { /* id:32 listen_id:32 */
uint32_t sid = 0;
uint32_t listen_id = 0;
-// listen_queue_t* lq = 0;
- subscription_t* listen = 0;
+ linux_listen_queue_t* lq = 0;
+ subscription_t* listen_s = 0;
subscription_t* s = 0;
DEBUGF("CMD_RFCOMM_ACCEPT cmdid=%d", cmdid);
@@ -713,7 +769,7 @@ void bt_command(bt_ctx_t* ctx, const uint8_t* src, uint32_t src_len)
goto badarg;
}
- if ((listen = find_subscription(&ctx->list,
+ if ((listen_s = find_subscription(&ctx->list,
RFCOMM_LISTEN,listen_id))==NULL) {
DEBUGF("listen subscription %d does not exists", listen_id);
goto badarg;
@@ -722,15 +778,26 @@ void bt_command(bt_ctx_t* ctx, const uint8_t* src, uint32_t src_len)
if ((s = new_subscription(RFCOMM,sid,cmdid,NULL,cleanup)) == NULL)
goto mem_error;
- // s->accept = listen; // mark that we are accepting
+ s->accept = listen_s; // mark that we are accepting
- bt_poll_add(PTR2INT(listen->handle), POLLIN, rfcomm_accept, s);
- s->handle = listen->opaque;
+ // Are we the first acceptor added to the listen
+ // descriptor? If so, enable it.
+ lq = (linux_listen_queue_t*) listen_s->opaque;
+ if (lq->acceptors.length == 0) {
+ DEBUGF("First acceptor for listen descriptor %d. Add to poll", listen_id);
+ // Call rfcomm_accept with listen subscriber
+ // when someone connects to us.
+ bt_poll_add(PTR2INT(listen_s->handle), POLLIN, rfcomm_accept, listen_s);
+ }
+
+
+ insert_last(&lq->acceptors, s);
insert_last(&ctx->list, s);
ddata_put_tag(&data_out, REPLY_OK);
ddata_put_UINT32(&data_out, cmdid);
ddata_send(&data_out, 1);
+
goto done;
}
@@ -748,34 +815,36 @@ void bt_command(bt_ctx_t* ctx, const uint8_t* src, uint32_t src_len)
if ((link = find_subscription_link(&ctx->list,RFCOMM,sid)) != NULL) {
subscription_t* s = link->s;
int sock;
+ DEBUGF("CMD_RFCOMM_CLOSE found RFCOMM link", cmdid);
s->cmdid = cmdid;
sock = PTR2INT(s->handle);
if (sock >= 0) {
DEBUGF("RFCOMM_CLOSE: channel=%d", sock);
- bt_poll_del(sock);
- close(sock);
- unlink_subscription(link);
- goto done;
+ unlink_subscription(link); // Will close and unlink s->handle
+ goto ok;
}
- /* else if (s->accept != NULL) { */
- /* listen_queue_t* lq = (listen_queue_t*)((s->accept)->opaque); */
- /* remove_subscription(&lq->wait,RFCOMM,sid); */
- /* unlink_subscription(link); */
- /* goto ok; */
- /* } */
+ else if (s->accept != NULL) {
+ DEBUGF("RFCOMM_CLOSE: This is an acceptor with no session");
+ linux_listen_queue_t* lq = (linux_listen_queue_t*)((s->accept)->opaque);
+ remove_subscription(&lq->acceptors,RFCOMM,sid);
+ unlink_subscription(link);
+ goto ok;
+ }
}
else if ((link = find_subscription_link(&ctx->list,RFCOMM_LISTEN,sid)) != NULL) {
- /* subscription_t* listen = link->s; */
- /* listen_queue_t* lq = (listen_queue_t*)listen->opaque; */
- /* subscription_link_t* link1; */
- /* /\* remove all waiters *\/ */
- /* while((link1=lq->wait.first) != NULL) { */
- /* send_event(link1->s->id, "closed"); */
- /* unlink_subscription(link1); */
- /* } */
- /* unlink_subscription(link); */
+ subscription_t* listen = link->s;
+ linux_listen_queue_t* lq = (linux_listen_queue_t*)listen->opaque;
+ subscription_link_t* link1;
+ DEBUGF("RFCOMM_CLOSE: This is a listen subscriuber");
+ /* remove all waiters */
+ while((link1=lq->acceptors.first) != NULL) {
+ send_event(link1->s->id, "closed");
+ unlink_subscription(link1);
+ }
+ unlink_subscription(link);
goto ok;
}
+ DEBUGF("RFCOMM_CLOSE: Shit");
goto error;
}
@@ -980,7 +1049,8 @@ void read_callback(struct pollfd* pfd, void* data)
int fd = pfd->fd;
int n;
- DEBUGF("read_callback: %d", pfd->fd);
+ DEBUGF("read_callback: %d:%X", pfd->fd, pfd->revents);
+
if (pfd->revents & POLLHUP) {
DEBUGF("hangup");
goto closed;
diff --git a/deps/wse/LICENSE b/deps/wse/LICENSE
deleted file mode 100644
index b9134e4..0000000
--- a/deps/wse/LICENSE
+++ /dev/null
@@ -1,24 +0,0 @@
-Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-Except as contained in this notice, the name(s) of the above copyright holders
-shall not be used in advertising or otherwise to promote the sale, use or other
-dealings in this Software without prior written authorization.
-
diff --git a/deps/wse/README.md b/deps/wse/README.md
deleted file mode 100644
index a9443f3..0000000
--- a/deps/wse/README.md
+++ /dev/null
@@ -1,88 +0,0 @@
-wse - Websockets for Erlang
-===========================
-
-WSE is a simple, standalone, websocket server which execute
-request in the browser instead of in the web server. There is a bit
-of boot strapping that may need help from a web server. But a simple
-web page and a browser is all that it takes to get running.
-
-To get control of part of a web page (or all of it) use the following
-HTML snippet. Also make sure you have ej.js and wse.js in the same directory.
-
- <html><head>
- <title>wse demo page</title>
- <script src='ej.js'></script>
- <script src='wse.js'></script>
- <script>
- window.onload = function() {
- if (Wse.open("ws://localhost:1234/websession"))
- Wse.start('wse_demo', 'run', ["myid"]);
- };
- </script></head>
- <body>
- <div id="myid"></div>
- </body></html>
-
-Next thing is to start erlang wse server (default to port 1234):
-
- $ erl
- > wse_server:start().
-
-Then have the erlang module wse_demo in the path somewhere:
-
- -module(wse_demo).
- -export([run/2]).
-
- run(Ws, Where) ->
- ElemNode = wse:createElement(Ws, "p"),
- TextNode = wse:createTextNode(Ws, "Hello world"),
- wse:appendChild(Ws, ElemNode, TextNode),
- wse:appendChild(Ws, wse:id(Where), ElemNode).
-
-The browser will call wse_demo:run (via the websocket) with the web socket proxy process as a the first argument and the "myid" as the second argument. From thereon the web page can be manipulated at will.
-
-# register pages
-
-One nice trick to interact with pages from command line is to
-register the page it self
-
- <html><head>
- <title>Page A</title>
- <script src='ej.js'></script>
- <script src='wse.js'></script>
- <script>
- window.onload = function() {
- if (Wse.open("ws://localhost:1234/websession")) {
- Wse.register('page_a');
- };
- </script>
- </head><body>
- <p id="x">Hello A World</p>
- </body></html>
-
-Now this page should be registered in erlang and can be tested. Start with
-changing the text in the paragraf on the page.
-
- > {ok,X} = wse:getElementById(page_a, "x").
- > {ok,Text} = wse:firstChild(page_a, X).
- > wse:set(page_a, Text, "nodeValue", "Hej A").
-
-Or we could send some ehtml (erlang style html) defining a button to it
-
- > wse:send(page_a, "x", {button,[{id,"y"}],["Press Me"]}).
-
-Or why not send a whole table to it
-
- > wse:send(page_a, "x", {table,[],[{tr,[],[{td,[],["A"]},{td,[],["B"]}]},{tr,[],[{td,[],["C"]},{td,[],["D"]}]}]}).
-
-To have events sent to us when pressing a button, using send, we can do
-
- > {ok,E} = wse:create_event(page_a).
- > wse:send(page_a, "x", {button,[{id,"y"},{onclick,"Wse.notify("++integer_to_list(E)++",'click');"}],["Press Me"]}).
-
-Click on the button on page A a couple of times
-
- > flush().
- Shell got {notify,2,[],"click"}
- Shell got {notify,2,[],"click"}
- Shell got {notify,2,[],"click"}
diff --git a/deps/wse/priv/base64.js b/deps/wse/priv/base64.js
deleted file mode 100644
index 56c7efe..0000000
--- a/deps/wse/priv/base64.js
+++ /dev/null
@@ -1,83 +0,0 @@
-//---- BEGIN COPYRIGHT -------------------------------------------------------
-//
-// Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-//
-// This software is licensed as described in the file COPYRIGHT, which
-// you should have received as part of this distribution. The terms
-// are also available at http://www.rogvall.se/docs/copyright.txt.
-//
-// You may opt to use, copy, modify, merge, publish, distribute and/or sell
-// copies of the Software, and permit persons to whom the Software is
-// furnished to do so, under the terms of the COPYRIGHT file.
-//
-// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-// KIND, either express or implied.
-//
-//---- END COPYRIGHT ---------------------------------------------------------
-//
-// Base64 encoder/decoder (on strings)
-//
-function Base64Class() {
- this._keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-};
-
-// Base64 encoder
-Base64Class.prototype.encode = function (input) {
- var output = "";
- var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
- var i = 0;
-
- while (i < input.length) {
- chr1 = input.charCodeAt(i++);
- chr2 = input.charCodeAt(i++);
- chr3 = input.charCodeAt(i++);
-
- enc1 = chr1 >> 2;
- enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
- enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
- enc4 = chr3 & 63;
-
- if (isNaN(chr2)) {
- enc3 = enc4 = 64;
- } else if (isNaN(chr3)) {
- enc4 = 64;
- }
- output = output +
- this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
- this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
- }
- return output;
-};
-
-// Base64 decoder
-Base64Class.prototype.decode = function (input) {
- var output = "";
- var chr1, chr2, chr3;
- var enc1, enc2, enc3, enc4;
- var i = 0;
-
- input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
-
- while (i < input.length) {
- enc1 = this._keyStr.indexOf(input.charAt(i++));
- enc2 = this._keyStr.indexOf(input.charAt(i++));
- enc3 = this._keyStr.indexOf(input.charAt(i++));
- enc4 = this._keyStr.indexOf(input.charAt(i++));
-
- chr1 = (enc1 << 2) | (enc2 >> 4);
- chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
- chr3 = ((enc3 & 3) << 6) | enc4;
-
- output = output + String.fromCharCode(chr1);
-
- if (enc3 != 64) {
- output = output + String.fromCharCode(chr2);
- }
- if (enc4 != 64) {
- output = output + String.fromCharCode(chr3);
- }
- }
- return output;
-};
-
-var Base64 = new Base64Class();
diff --git a/deps/wse/priv/bd.jpg b/deps/wse/priv/bd.jpg
deleted file mode 100644
index 6e2c45d..0000000
--- a/deps/wse/priv/bd.jpg
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/button_demo.html b/deps/wse/priv/button_demo.html
deleted file mode 100644
index d397f83..0000000
--- a/deps/wse/priv/button_demo.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<html>
-<head>
-<title>Button demo page</title>
-<script src='ej.js'></script>
-<script src='wse.js'></script>
-<script>
-
-window.onload = function() {
- if (Wse.open("ws://"+(location.hostname||"localhost")+":1234/websession")) {
- // Wse.enable_console_output(true);
- Wse.start('wse_button_demo', 'run', ["myid"]);
- }
- else
- alert("WebSockets not supported");
-};
-
-</script>
-</head>
-<body>
-<div id="myid"></div>
-</body>
-</html>
diff --git a/deps/wse/priv/document_demo.html b/deps/wse/priv/document_demo.html
deleted file mode 100644
index 87e3a49..0000000
--- a/deps/wse/priv/document_demo.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html>
-<head>
-<title>Document demo page</title>
-<script src='ej.js'></script>
-<script src='wse.js'></script>
-<script>
-
-window.onload = function() {
- if (Wse.open("ws://"+(location.hostname||"localhost")+":1234/websession")) {
- Wse.start('wse_document_demo', 'run', ["i1"]);
- }
- else
- alert("WebSockets not supported");
-};
-
-</script>
-</head>
-<body>
-<div id="i1" width=640 height=480></div>
-</body>
-</html>
diff --git a/deps/wse/priv/ej.js b/deps/wse/priv/ej.js
deleted file mode 100644
index af3b1f2..0000000
--- a/deps/wse/priv/ej.js
+++ /dev/null
@@ -1,672 +0,0 @@
-//---- BEGIN COPYRIGHT -------------------------------------------------------
-//
-// Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-//
-// This software is licensed as described in the file COPYRIGHT, which
-// you should have received as part of this distribution. The terms
-// are also available at http://www.rogvall.se/docs/copyright.txt.
-//
-// You may opt to use, copy, modify, merge, publish, distribute and/or sell
-// copies of the Software, and permit persons to whom the Software is
-// furnished to do so, under the terms of the COPYRIGHT file.
-//
-// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-// KIND, either express or implied.
-//
-//---- END COPYRIGHT ---------------------------------------------------------
-//
-// Erlang term encode/decode using TypeArray interface
-//
-
-function EiClass() {
- this.MAGIC = 131;
- this.SMALL_ATOM = 115;
- this.ATOM = 100;
- this.BINARY = 109;
- this.SMALL_INTEGER = 97;
- this.INTEGER = 98;
- this.SMALL_BIG = 110;
- this.LARGE_BIG = 111;
- this.FLOAT = 99;
- this.NEW_FLOAT = 70;
- this.STRING = 107;
- this.LIST = 108;
- this.SMALL_TUPLE = 104;
- this.LARGE_TUPLE = 105;
- this.NIL = 106;
- this.MAP = 116;
-
- this.use_map = false; // use map when available
- this.use_small_atom = true; // use small atom when available
-
- if (this.use_small_atom) {
- this.true_atom_size = 1+4;
- this.false_atom_size = 1+5;
- }
- else {
- this.true_atom_size = 2+4;
- this.false_atom_size = 2+5;
- }
-};
-
-//
-// [] can be encoded as:
-// <<MAGIC, NIL>>
-// <<MAGIC, STRING, 0:16>>
-// <<MAGIC, LIST, 0:32, NIL>>
-//
-function EiAtom(Obj) {
- this.type = "Atom";
- this.value = Obj;
- this.toString = function () {
- return Obj;
- };
-};
-
-// Obj is typed array or string
-function EiBinary(Obj) {
- this.type = "Binary";
- this.value = Obj;
- this.toString = function () {
- return "<<\"" + Obj + "\">>";
- };
-};
-
-function EiTuple(Arr) {
- var i;
- this.type = "Tuple";
- this.length = Arr.length;
- this.value = Arr;
- this.toString = function () {
- var i, s = "";
- for (i = 0; i < this.value.length; i++) {
- if (s !== "") {
- s += ", ";
- }
- s += this.value[i].toString();
- }
- return "{" + s + "}";
- };
-};
-
-// - INTERFACE -
-
-EiClass.prototype.isAtom = function (Obj) {
- return (Obj.type === "Atom");
-};
-
-EiClass.prototype.eqAtom = function (Obj, name) {
- return (Obj.type === "Atom") && (Obj.value === name);
-};
-
-EiClass.prototype.isArray = function(Obj) {
- return (typeof(Obj) == "object") &&
- (Obj.constructor.toString().indexOf("Array") !== -1);
-};
-
-EiClass.prototype.isTuple = function(Obj) {
- return (typeof(Obj) == "object") && (Obj.type == "Tuple");
-};
-
-EiClass.prototype.isTupleSize = function(Obj,n) {
- return (typeof(Obj) == "object") && (Obj.type == "Tuple") &&
- (Obj.length == n);
-};
-
-EiClass.prototype.isBinary = function (Obj) {
- return (Obj.type === "Binary");
-};
-
-EiClass.prototype.binary_size = function (Obj) {
- if (Obj.type === "Binary") return Obj.value.byteLength;
- return 0;
-};
-
-
-EiClass.prototype.atom = function (Obj) {
- return new EiAtom(Obj);
-};
-
-EiClass.prototype.binary = function (Obj) {
- return new EiBinary(Obj);
-};
-
-EiClass.prototype.tuple = function () {
- return new EiTuple([].splice.call(arguments,0));
-};
-
-// byte_size_xxx
-// calculate the size need to encode the Term
-// (use byte_size_term to avoid extra magic byte)
-//
-EiClass.prototype.byte_size = function (Obj) {
- return 1+this.byte_size_term(Obj);
-};
-
-EiClass.prototype.byte_size_term = function (Obj) {
- var len, Size;
- switch(typeof(Obj)) {
- case 'string':
- len = Obj.length;
- if (len <= 65535)
- Size = 2+len; // STRING encoded
- else
- Size = 4+2*len+1; // LIST encoded (with terminating nil)!
- break;
- case 'boolean':
- Size = Obj ? this.true_atom_size : this.false_atom_size;
- break;
- case 'number':
- if (Obj % 1 === 0) { // then integer
- if ((Obj >= 0) && (Obj < 256))
- Size = 1; // small_integer (uint8)
- else if ((Obj >= -134217728) && (Obj <= 134217727))
- Size = 4; // integer (int32)
- else // bignum (32 bit only, can not really be used here
- Size = 1+1+4; // size,sign,byte*4
- }
- else {
- Size = 8; // NEW_FLOAT
- }
- break;
- case 'object':
- switch (Obj.type) {
- case 'Atom':
- Size = this.atom_size(Obj.value);
- break;
- case 'Binary':
- Size = 4 + Obj.value.byteLength;
- break;
- case 'Tuple':
- Size = this.byte_size_tuple(Obj);
- break;
- default:
- if (Obj.constructor.toString().indexOf("Array") !== -1)
- Size = this.byte_size_array(Obj);
- else
- Size = this.byte_size_associative_array(Obj);
- break;
- }
- break;
- default:
- throw ("bad object: " + Obj);
- }
- return 1+Size;
-}
-
-EiClass.prototype.atom_size = function (Name) {
- if ((Name.length < 256) && this.use_small_atom)
- return 1+Name.length;
- else
- return 2+Name.length;
-}
-
-EiClass.prototype.byte_size_tuple = function (Obj) {
- var i;
- var Size = (Obj.length < 256) ? 1 : 4;
- for (i = 0; i < Obj.length; i++)
- Size += this.byte_size_term(Obj.value[i]);
- return Size;
-}
-
-EiClass.prototype.byte_size_array = function (Obj) {
- var len = Obj.length;
- if (len == 0)
- return 1; // nil only
- else {
- var i;
- var Size = 4; // length-bytes
- for (i = 0; i < len; i++)
- Size += this.byte_size_term(Obj[i]);
- Size +=1; // nil byte
- return Size;
- }
-}
-
-EiClass.prototype.byte_size_associative_array = function (Obj) {
- var key, Size = 0, N = 0;
-
- for (key in Obj) {
- if (Obj.hasOwnProperty(key)) {
- var len = key.length;
- klen = (len < 256) ? 1+len : 2+len;
- Size += 1+klen; // (small)atom
- Size += this.byte_size_term(Obj[key]);
- N++;
- }
- }
- if (N == 0) {
- if (!this.use_map)
- Size = 4; // map size
- else
- Size = 0 // nil
- }
- else {
- if (!this.use_map)
- Size += N*2; // add N small tuples
- Size += 4; // list or map size
- }
- return Size;
-}
-
-// encode_xxx
-// encode the term into Array Buffer
-
-EiClass.prototype.encode = function (Obj) {
- var sz = this.byte_size(Obj);
- var ab = new ArrayBuffer(sz);
- var dv = new DataView(ab);
- dv.setUint8(0, this.MAGIC);
- this.encode_term(Obj, dv, 1);
- return ab;
-};
-
-EiClass.prototype.encode_term = function (Obj,dv,pos) {
- switch(typeof(Obj)) {
- case 'string':
- if (Obj.length <= 65535) {
- dv.setUint8(pos++, this.STRING);
- dv.setUint16(pos, Obj.length);
- pos += 2;
- pos = this.string_to_bytes(Obj,dv,pos,Obj.length);
- }
- else {
- dv.setUint8(pos++, this.LIST);
- dv.setUint32(pos, Obj.length);
- pos += 4;
- for (i = 0; i < Obj.length; i++) {
- dv.setUint8(pos++, this.SMALL_INTEGER);
- dv.setUint8(pos++, Obj.charCodeAt(i));
- }
- dv.setUint8(pos++, this.NIL);
- }
- break;
-
- case 'boolean':
- if (Obj)
- pos = this.encode_atom_string("true",dv,pos);
- else
- pos = this.encode_atom_string("false",dv,pos);
- break;
-
- case 'number':
- if ((Obj % 1 === 0)) { // integer
- if ((Obj >= 0) && (Obj < 256)) {
- dv.setUint8(pos, this.SMALL_INTEGER);
- dv.setUint8(pos+1, Obj);
- pos += 2;
- }
- else if ((Obj >= -134217728) && (Obj <= 134217727)) {
- dv.setUint8(pos, this.INTEGER);
- dv.setInt32(pos+1, Obj);
- pos += 5;
- }
- else if (Obj < 0) {
- dv.setUint8(pos, this.SMALL_BIG);
- dv.setUint8(pos+1, 4);
- dv.setUint8(pos+2, 0); // negative
- // little endian encoded digits!
- dv.setUint32(pos+3, -Obj, true);
- pos += 7;
- }
- else {
- dv.setUint8(pos, this.SMALL_BIG);
- dv.setUint8(pos+1, 4);
- dv.setUint8(pos+2, 1);
- // little endian encoded digits!
- dv.setUint32(pos+3, Obj, true);
- pos += 7;
- }
- }
- else {
- dv.setUint8(pos, this.NEW_FLOAT);
- dv.setFloat64(pos+1, Obj, false); // store float as big endian 64
- pos += 9;
- }
- break;
-
- case 'object':
- switch(Obj.type) {
- case 'Atom':
- pos = this.encode_atom_string(Obj.value,dv,pos);
- break;
-
- case 'Binary': { // Obj.value MUST be an Uint8Array!
- var i, len = Obj.value.byteLength;
- dv.setUint8(pos, this.BINARY);
- dv.setUint32(pos+1, len, false);
- pos += 5;
- for (i = 0; i < len; i++, pos++)
- dv.setUint8(pos, Obj.value[i]);
- break;
- }
-
- case 'Tuple':
- pos = this.encode_tuple(Obj,dv,pos);
- break;
- default:
- if (Obj.constructor.toString().indexOf("Array") !== -1)
- pos = this.encode_array(Obj,dv,pos);
- else
- pos = this.encode_associative_array(Obj,dv,pos);
- }
- break;
-
- default:
- throw ("bad object: " + Obj);
- }
- return pos;
-};
-
-EiClass.prototype.encode_atom_string = function (Name,dv,pos) {
- var len = Name.length;
- var i;
- if ((len < 256) && this.use_small_atom) {
- dv.setUint8(pos, this.SMALL_ATOM);
- dv.setUint8(pos+1, len);
- pos += 2;
- }
- else if (len < 65536) {
- dv.setUint8(pos, this.ATOM);
- dv.setUint16(pos+1, len, false);
- pos += 3;
- }
- else
- throw("bad atom: too big");
- return this.string_to_bytes(Name,dv,pos,len);
-}
-
-
-EiClass.prototype.encode_tuple = function (Obj,dv,pos) {
- var i;
- var N = Obj.length;
- if (N < 256) {
- dv.setUint8(pos, this.SMALL_TUPLE);
- dv.setUint8(pos+1, N);
- pos += 2;
- } else {
- dv.setUint8(pos, this.LARGE_TUPLE);
- dv.setUint32(pos+1, N, false);
- pos += 5;
- }
- for (i = 0; i < N; i++)
- pos = this.encode_term(Obj.value[i],dv,pos);
- return pos;
-};
-
-EiClass.prototype.encode_array = function (Obj,dv,pos) {
- var N = Obj.length;
- if (N > 0) {
- dv.setUint8(pos, this.LIST);
- dv.setUint32(pos+1, N, false);
- pos += 5;
- for (var i = 0; i < N; i++)
- pos = this.encode_term(Obj[i],dv,pos);
- }
- dv.setUint8(pos,this.NIL);
- return pos+1;
-};
-
-// count number of keys
-EiClass.prototype.assoc_num_keys = function (Obj) {
- if (!Object.keys) {
- var N = 0;
- var key;
- for (key in Obj) {
- if (Obj.hasOwnProperty(key))
- N++;
- }
- return N;
- }
- return Object.keys(Obj).length;
-};
-
-
-EiClass.prototype.encode_associative_array = function (Obj,dv,pos) {
- var N = this.assoc_num_keys(Obj);
- if (N > 0) {
- var key;
- dv.setUint8(pos, this.use_map ? this.MAP : this.LIST);
- dv.setUint32(pos+1,N,false);
- pos += 5
- for (key in Obj) {
- if (Obj.hasOwnProperty(key)) {
- if (!this.use_map) {
- dv.setUint8(pos++, this.SMALL_TUPLE);
- dv.setUint8(pos++, 2);
- }
- pos = this.encode_atom_string(key,dv,pos);
- pos = this.encode_term(Obj[key],dv,pos);
- }
- }
- }
- if (!this.use_map)
- dv.setUint8(pos++,this.NIL);
- else if (this.use_map && (N == 0)) { // special case for empty map
- dv.setUint8(pos, this.MAP);
- dv.setUint32(pos+1,0,false);
- pos += 5;
- }
- return pos;
-};
-
-//
-// decode_size_xxx
-//
-// Calculate the size of an external encoded term
-// in the buffer
-//
-
-EiClass.prototype.decode_size = function (ab, pos) {
- var dv = new DataView(ab);
- if (dv.getUint8(pos) !== this.MAGIC) {
- throw ("badmagic");
- }
- return 1+this.decode_size_term(dv, pos+1);
-};
-
-EiClass.prototype.decode_size_term = function (dv,pos) {
- var Tag = dv.getUint8(pos++);
- var L = 0;
-
- switch (Tag) {
- case this.NIL: break;
- case this.SMALL_ATOM: L = 1+dv.getUint8(pos); break;
- case this.ATOM: L = 2+dv.getUint16(pos,false); break;
- case this.BINARY: L = 4+dv.getUint32(pos,false); break;
- case this.SMALL_INTEGER: L = 1; break;
- case this.INTEGER: L = 4; break;
- case this.SMALL_BIG: L = 1+dv.getUint8(pos); break;
- case this.LARGE_BIG: L = 4+dv.getUint32(pos,false); break;
- case this.FLOAT: L = 31; break;
- case this.NEW_FLOAT: L = 8; break;
- case this.STRING: L = 2+dv.getUint16(pos,false); break;
- case this.LIST:
- L = this.decode_size_seq(dv,pos+4,dv.getUint32(pos,false)+1,4);
- break;
- case this.SMALL_TUPLE:
- L = this.decode_size_seq(dv,pos+1,dv.getUint8(pos),1);
- break;
- case this.LARGE_TUPLE:
- L = this.decode_size_seq(dv,pos+4,dv.getUint32(pos,false),4);
- break;
- case this.MAP:
- L = this.decode_size_seq(dv,pos+4,2*dv.getUint32(pos,false),4);
- break;
- default: throw ("bad tag: " + Tag);
- }
- return L+1;
-};
-
-EiClass.prototype.decode_size_seq = function (dv,pos,len,Size) {
- var i;
- for (i = 0; i < len; i++) {
- var k = this.decode_size_term(dv,pos);
- pos += k;
- Size += k;
- }
- return Size;
-}
-
-//
-// Decode the Array Buffer
-//
-
-EiClass.prototype.decode = function (ab, pos) {
- var dv = new DataView(ab);
- if (dv.getUint8(pos) !== this.MAGIC) {
- throw ("badmagic");
- }
- return this.decode_term(dv, pos+1);
-};
-
-EiClass.prototype.decode_term = function (dv,pos) {
- var R,Tag = dv.getUint8(pos++);
-
- switch (Tag) {
- case this.NIL:
- R = []; break;
- case this.SMALL_ATOM:
- R = this.decode_atom_bytes(dv,pos+1,dv.getUint8(pos)); break;
- case this.ATOM:
- R = this.decode_atom_bytes(dv,pos+2,dv.getUint16(pos,false)); break;
- case this.BINARY:
- R = this.decode_binary(dv,pos); break;
- case this.SMALL_INTEGER:
- R = dv.getUint8(pos); break;
- case this.INTEGER:
- R = dv.getInt32(pos,false); break;
- case this.SMALL_BIG:
- R = this.decode_big_bytes(dv,pos+1,dv.getUint8(pos)); break;
- case this.LARGE_BIG:
- R = this.decode_big_bytes(dv,pos+4,dv.getUint32(pos,false)); break;
- case this.FLOAT:
- R = parseFloat(this.bytes_to_string(dv,pos,31)); break;
- case this.NEW_FLOAT:
- R = dv.getFloat64(pos, false); break;
- case this.STRING:
- R = this.bytes_to_string(dv,pos+2,dv.getUint16(pos,false)); break;
- case this.LIST:
- R = this.decode_list(dv,pos); break;
- case this.SMALL_TUPLE:
- R = this.decode_tuple(dv,pos+1,dv.getUint8(pos)); break;
- case this.LARGE_TUPLE:
- R = this.decode_tuple(dv,pos+4,dv.getUint32(pos,false)); break;
- case this.MAP:
- R = this.decode_map(dv,pos+4,dv.getUint32(pos,false)); break;
- default:
- throw ("badtag: " + Tag);
- }
- // console.debug("decode_term = " + R);
- return R;
-};
-
-EiClass.prototype.decode_atom_bytes = function (dv,pos,len) {
- var S = this.bytes_to_string(dv,pos,len);
- if (S === "true")
- return true;
- else if (S === "false")
- return false;
- return new this.atom(S);
-};
-
-EiClass.prototype.decode_binary = function (dv,pos) {
- var Size = dv.getUint32(pos, false);
- var Bin = new Uint8Array(dv.buffer, pos+4, Size);
- return this.binary(Bin);
-};
-
-EiClass.prototype.decode_big_bytes = function (dv,pos,len) {
- var Sign = dv.getUint8(pos++);
- if (len == 4) {
- var Num = dv.getUint32(pos,false);
- if (Sign) return -Num;
- return Num;
- }
- throw ("bad number");
-};
-
-//
-// Special hack for argument lists ['array',64,65,66,67]
-// to separate this in the erlang term_to_binary from a string!
-// also make sure [array|T] is encoded as [array,array|T]
-//
-EiClass.prototype.decode_list = function (dv,pos) {
- var len, i, Arr = [];
-
- len = dv.getUint32(pos, false);
- pos += 4;
- // console.debug("decode_list len=" + len);
- for (i = 0; i < len; i++) {
- var Term = this.decode_term(dv,pos);
- var k = this.decode_size_term(dv,pos);
- //console.debug("term (tag="+dv.getUint8(pos)+"["+ Term+ "] size = "+k);
- pos += k;
- if (!((i==0) && this.eqAtom(Term, "array")))
- Arr.push(Term);
- }
- // console.debug("decode_list end");
- if (dv.getUint8(pos) != this.NIL) { // improper list not allowed
- throw ("List does not end with NIL! [tag="+dv.getUint8(pos)+"]");
- }
- return Arr;
-};
-
-EiClass.prototype.decode_tuple = function (dv,pos,len) {
- var i, Arr = [];
- for (i = 0; i < len; i++) {
- var Term = this.decode_term(dv,pos);
- pos += this.decode_size_term(dv,pos);
- Arr.push(Term);
- }
- return new EiTuple(Arr);
-};
-
-
-EiClass.prototype.decode_map = function (dv,pos,len) {
- var key, value, i, Obj = new Object();
- for (i = 0; i < len; i++) {
- key = this.decode_term(dv,pos);
- pos += this.decode_size_term(dv,pos);
- value = this.decode_term(dv,pos);
- pos += this.decode_size_term(dv,pos);
- Obj[key.value] = value; // key must be EiAtom! fixme test!
- }
- return Obj;
-};
-
-
-// Convert an array of bytes into a string.
-EiClass.prototype.bytes_to_string = function (dv,pos,count) {
- var i, s = "";
- for (i = 0; i < count; i++,pos++)
- s += String.fromCharCode(dv.getUint8(pos));
- return s;
-};
-
-// Convert an array of bytes into a string.
-EiClass.prototype.string_to_bytes = function (Obj,dv,pos,count) {
- var i;
- for (i = 0; i < count; i++, pos++)
- dv.setUint8(pos, Obj.charCodeAt(i));
- return pos;
-};
-
-// Pretty Print a byte-string in Erlang binary form.
-EiClass.prototype.pp_bytes = function (Bin) {
- var i, s = "";
- for (i = 0; i < Bin.length; i++) {
- if (s !== "") {
- s += ",";
- }
- s += "" + Bin[i];
- }
- return "<<" + s + ">>";
-};
-
-// Pretty Print a JS object in Erlang term form.
-EiClass.prototype.pp = function (Obj) {
- return Obj.toString();
-};
-
-var Ei = new EiClass();
diff --git a/deps/wse/priv/fish.html b/deps/wse/priv/fish.html
deleted file mode 100644
index 2ea0e0b..0000000
--- a/deps/wse/priv/fish.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<html>
-<head>
-<title>Animated fish demo</title>
-<script src='ej.js'></script>
-<script src='wse.js'></script>
-<script>
-
-window.onload = function() {
- if (Wse.open("ws://"+(location.hostname||"localhost")+":1234/websession")) {
- // Wse.enable_console_output(true);
- Wse.start('wse_fish_demo', 'run', ["myid"]);
- }
-}
-</script>
-</head>
-<body>
-<div id="myid"></div>
-</body>
-</html>
diff --git a/deps/wse/priv/fish/fish0001.png b/deps/wse/priv/fish/fish0001.png
deleted file mode 100644
index 42b403a..0000000
--- a/deps/wse/priv/fish/fish0001.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0002.png b/deps/wse/priv/fish/fish0002.png
deleted file mode 100644
index c526314..0000000
--- a/deps/wse/priv/fish/fish0002.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0003.png b/deps/wse/priv/fish/fish0003.png
deleted file mode 100644
index 89c5dcd..0000000
--- a/deps/wse/priv/fish/fish0003.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0004.png b/deps/wse/priv/fish/fish0004.png
deleted file mode 100644
index 01ffb4c..0000000
--- a/deps/wse/priv/fish/fish0004.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0005.png b/deps/wse/priv/fish/fish0005.png
deleted file mode 100644
index e8d5674..0000000
--- a/deps/wse/priv/fish/fish0005.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0006.png b/deps/wse/priv/fish/fish0006.png
deleted file mode 100644
index c811c6b..0000000
--- a/deps/wse/priv/fish/fish0006.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0007.png b/deps/wse/priv/fish/fish0007.png
deleted file mode 100644
index de0ee78..0000000
--- a/deps/wse/priv/fish/fish0007.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0008.png b/deps/wse/priv/fish/fish0008.png
deleted file mode 100644
index 77794a8..0000000
--- a/deps/wse/priv/fish/fish0008.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0009.png b/deps/wse/priv/fish/fish0009.png
deleted file mode 100644
index 7cbfc30..0000000
--- a/deps/wse/priv/fish/fish0009.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0010.png b/deps/wse/priv/fish/fish0010.png
deleted file mode 100644
index 81db776..0000000
--- a/deps/wse/priv/fish/fish0010.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0011.png b/deps/wse/priv/fish/fish0011.png
deleted file mode 100644
index be3df4e..0000000
--- a/deps/wse/priv/fish/fish0011.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0012.png b/deps/wse/priv/fish/fish0012.png
deleted file mode 100644
index 7dad219..0000000
--- a/deps/wse/priv/fish/fish0012.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0013.png b/deps/wse/priv/fish/fish0013.png
deleted file mode 100644
index b8b899c..0000000
--- a/deps/wse/priv/fish/fish0013.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0014.png b/deps/wse/priv/fish/fish0014.png
deleted file mode 100644
index 30ca6db..0000000
--- a/deps/wse/priv/fish/fish0014.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0015.png b/deps/wse/priv/fish/fish0015.png
deleted file mode 100644
index ab1d4b6..0000000
--- a/deps/wse/priv/fish/fish0015.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0016.png b/deps/wse/priv/fish/fish0016.png
deleted file mode 100644
index 67567b4..0000000
--- a/deps/wse/priv/fish/fish0016.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0017.png b/deps/wse/priv/fish/fish0017.png
deleted file mode 100644
index a615fd2..0000000
--- a/deps/wse/priv/fish/fish0017.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0018.png b/deps/wse/priv/fish/fish0018.png
deleted file mode 100644
index 06940cc..0000000
--- a/deps/wse/priv/fish/fish0018.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0019.png b/deps/wse/priv/fish/fish0019.png
deleted file mode 100644
index c13a0c7..0000000
--- a/deps/wse/priv/fish/fish0019.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0020.png b/deps/wse/priv/fish/fish0020.png
deleted file mode 100644
index 8610f32..0000000
--- a/deps/wse/priv/fish/fish0020.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0021.png b/deps/wse/priv/fish/fish0021.png
deleted file mode 100644
index c3893be..0000000
--- a/deps/wse/priv/fish/fish0021.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0022.png b/deps/wse/priv/fish/fish0022.png
deleted file mode 100644
index 8c30ed4..0000000
--- a/deps/wse/priv/fish/fish0022.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/fish/fish0023.png b/deps/wse/priv/fish/fish0023.png
deleted file mode 100644
index 725b3fd..0000000
--- a/deps/wse/priv/fish/fish0023.png
+++ /dev/null
Binary files differ
diff --git a/deps/wse/priv/frame1.html b/deps/wse/priv/frame1.html
deleted file mode 100644
index 56c09c1..0000000
--- a/deps/wse/priv/frame1.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<html>
-<head>
-<title>Frame</title>
-<script src='ej.js'></script>
-<script src='wse.js'></script>
-<script>
-
-window.onload = function() {
- if (Wse.open("ws://"+(location.hostname||"localhost")+":1234/websession")) {
- Wse.id = 'w1';
- Wse.start('wse_frame_demo', 'run', ["i1"]);
- }
-}
-</script>
-</head>
-<body>
-<h2>Frame1</h2>
-<div id="i1" width=620 height=170></div>
-</body>
-</html>
diff --git a/deps/wse/priv/frame2.html b/deps/wse/priv/frame2.html
deleted file mode 100644
index fdece19..0000000
--- a/deps/wse/priv/frame2.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<html>
-<head>
-<title>Frame</title>
-<script src='ej.js'></script>
-<script src='wse.js'></script>
-<script>
-
-window.onload = function() {
- if (Wse.open("ws://"+(location.hostname||"localhost")+":1235/websession")) {
- Wse.id = 'w2';
- Wse.start('wse_frame_demo', 'run', ["i2"]);
- }
-}
-</script>
-</head>
-<body>
-<h2>Frame2</h2>
-<div id="i2" width=620 height=170></div>
-</body>
-</html>
diff --git a/deps/wse/priv/frame_demo.html b/deps/wse/priv/frame_demo.html
deleted file mode 100644
index 3519ba8..0000000
--- a/deps/wse/priv/frame_demo.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<html>
-<head>
-<title>Frame demo page</title>
-
-<script src='ej.js'></script>
-<script src='wse.js'></script>
-<script>
-<!-- port numbers used main=1233, frame1=1234, frame2=1235 -->
-window.onload = function() {
- if (Wse.open("ws://"+(location.hostname||"localhost")+":1233/websession")) {
- Wse.id = 'w0';
- Wse.start('wse_frame_demo', 'run', ["i0"]);
- }
-}
-</script>
-</head>
-
-<body>
-<iframe id="f1" src="frame1.html" width=640 height=180></iframe>
-<iframe id="f2" src="frame2.html" width=640 height=180></iframe>
-<div id="i0"></div>
-</body>
-</html>
diff --git a/deps/wse/priv/location.html b/deps/wse/priv/location.html
deleted file mode 100644
index b8eb3df..0000000
--- a/deps/wse/priv/location.html
+++ /dev/null
@@ -1,30 +0,0 @@
-<html>
-<head>
-<title>Location demo page</title>
-<script src='ej.js'></script>
-<script src='wse.js'></script>
-<script>
-
-window.onload = function() {
- if (Wse.open("ws://"+(location.hostname||"localhost")+":1234/websession")) {
- Wse.start('wse_location_demo', 'run', ["location"]);
- }
- else
- alert("WebSockets not supported");
-};
-
-</script>
-</head>
-<body style="background: #333">
- <input name="webpage" placeholder="webpage" type="text" id="webpage"/>
- <button onclick="goto()">Goto</button>
-<script>
- function goto() {
- var location = document.getElementById("webpage").value;
- window.console.debug("Goto " +location);
- Wse.call('wse_location_demo', 'goto', [location]);
-}
-</script>
-
-</body>
-</html>
diff --git a/deps/wse/priv/locationX.html b/deps/wse/priv/locationX.html
deleted file mode 100644
index 5fb4645..0000000
--- a/deps/wse/priv/locationX.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<html>
-<head>
-<title>Location X demo page</title>
-</head>
-<body style="background: #333">
- <p> Location X </p>
-
-</body>
-</html>
diff --git a/deps/wse/priv/page_a.html b/deps/wse/priv/page_a.html
deleted file mode 100644
index 25fa08e..0000000
--- a/deps/wse/priv/page_a.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<html>
-<head>
-<title>Page A</title>
-<script src='ej.js'></script>
-<script src='wse.js'></script>
-<script>
-
-window.onload = function() {
- if (Wse.open("ws://"+(location.hostname||"localhost")+":1234/websession")) {
- // Wse.enable_console_output(true);
- Wse.register('page_a');
- }
-};
-
-</script>
-</head>
-<body>
-<p id="x">Hello A world</p>
-</body>
-</html>
diff --git a/deps/wse/priv/page_b.html b/deps/wse/priv/page_b.html
deleted file mode 100644
index 589da7e..0000000
--- a/deps/wse/priv/page_b.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<html>
-<head>
-<title>Page B</title>
-<script src='ej.js'></script>
-<script src='wse.js'></script>
-<script>
-
-window.onload = function() {
- if (Wse.open("ws://"+(location.hostname||"localhost")+":1234/websession")) {
- // Wse.enable_console_output(true);
- Wse.register('page_b');
- }
-};
-
-</script>
-</head>
-<body>
-<p id="x">Hello B World</p>
-</body>
-</html>
diff --git a/deps/wse/priv/raphael-min.js b/deps/wse/priv/raphael-min.js
deleted file mode 100644
index 404f8b2..0000000
--- a/deps/wse/priv/raphael-min.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// ┌────────────────────────────────────────────────────────────────────┐ \\
-// │ Raphaël 2.1.2 - JavaScript Vector Library │ \\
-// ├────────────────────────────────────────────────────────────────────┤ \\
-// │ Copyright © 2008-2012 Dmitry Baranovskiy (http://raphaeljs.com) │ \\
-// │ Copyright © 2008-2012 Sencha Labs (http://sencha.com) │ \\
-// ├────────────────────────────────────────────────────────────────────┤ \\
-// │ Licensed under the MIT (http://raphaeljs.com/license.html) license.│ \\
-// └────────────────────────────────────────────────────────────────────┘ \\
-!function(a){var b,c,d="0.4.2",e="hasOwnProperty",f=/[\.\/]/,g="*",h=function(){},i=function(a,b){return a-b},j={n:{}},k=function(a,d){a=String(a);var e,f=c,g=Array.prototype.slice.call(arguments,2),h=k.listeners(a),j=0,l=[],m={},n=[],o=b;b=a,c=0;for(var p=0,q=h.length;q>p;p++)"zIndex"in h[p]&&(l.push(h[p].zIndex),h[p].zIndex<0&&(m[h[p].zIndex]=h[p]));for(l.sort(i);l[j]<0;)if(e=m[l[j++]],n.push(e.apply(d,g)),c)return c=f,n;for(p=0;q>p;p++)if(e=h[p],"zIndex"in e)if(e.zIndex==l[j]){if(n.push(e.apply(d,g)),c)break;do if(j++,e=m[l[j]],e&&n.push(e.apply(d,g)),c)break;while(e)}else m[e.zIndex]=e;else if(n.push(e.apply(d,g)),c)break;return c=f,b=o,n.length?n:null};k._events=j,k.listeners=function(a){var b,c,d,e,h,i,k,l,m=a.split(f),n=j,o=[n],p=[];for(e=0,h=m.length;h>e;e++){for(l=[],i=0,k=o.length;k>i;i++)for(n=o[i].n,c=[n[m[e]],n[g]],d=2;d--;)b=c[d],b&&(l.push(b),p=p.concat(b.f||[]));o=l}return p},k.on=function(a,b){if(a=String(a),"function"!=typeof b)return function(){};for(var c=a.split(f),d=j,e=0,g=c.length;g>e;e++)d=d.n,d=d.hasOwnProperty(c[e])&&d[c[e]]||(d[c[e]]={n:{}});for(d.f=d.f||[],e=0,g=d.f.length;g>e;e++)if(d.f[e]==b)return h;return d.f.push(b),function(a){+a==+a&&(b.zIndex=+a)}},k.f=function(a){var b=[].slice.call(arguments,1);return function(){k.apply(null,[a,null].concat(b).concat([].slice.call(arguments,0)))}},k.stop=function(){c=1},k.nt=function(a){return a?new RegExp("(?:\\.|\\/|^)"+a+"(?:\\.|\\/|$)").test(b):b},k.nts=function(){return b.split(f)},k.off=k.unbind=function(a,b){if(!a)return k._events=j={n:{}},void 0;var c,d,h,i,l,m,n,o=a.split(f),p=[j];for(i=0,l=o.length;l>i;i++)for(m=0;m<p.length;m+=h.length-2){if(h=[m,1],c=p[m].n,o[i]!=g)c[o[i]]&&h.push(c[o[i]]);else for(d in c)c[e](d)&&h.push(c[d]);p.splice.apply(p,h)}for(i=0,l=p.length;l>i;i++)for(c=p[i];c.n;){if(b){if(c.f){for(m=0,n=c.f.length;n>m;m++)if(c.f[m]==b){c.f.splice(m,1);break}!c.f.length&&delete c.f}for(d in c.n)if(c.n[e](d)&&c.n[d].f){var q=c.n[d].f;for(m=0,n=q.length;n>m;m++)if(q[m]==b){q.splice(m,1);break}!q.length&&delete c.n[d].f}}else{delete c.f;for(d in c.n)c.n[e](d)&&c.n[d].f&&delete c.n[d].f}c=c.n}},k.once=function(a,b){var c=function(){return k.unbind(a,c),b.apply(this,arguments)};return k.on(a,c)},k.version=d,k.toString=function(){return"You are running Eve "+d},"undefined"!=typeof module&&module.exports?module.exports=k:"undefined"!=typeof define?define("eve",[],function(){return k}):a.eve=k}(this),function(a,b){"function"==typeof define&&define.amd?define(["eve"],function(c){return b(a,c)}):b(a,a.eve)}(this,function(a,b){function c(a){if(c.is(a,"function"))return u?a():b.on("raphael.DOMload",a);if(c.is(a,V))return c._engine.create[D](c,a.splice(0,3+c.is(a[0],T))).add(a);var d=Array.prototype.slice.call(arguments,0);if(c.is(d[d.length-1],"function")){var e=d.pop();return u?e.call(c._engine.create[D](c,d)):b.on("raphael.DOMload",function(){e.call(c._engine.create[D](c,d))})}return c._engine.create[D](c,arguments)}function d(a){if("function"==typeof a||Object(a)!==a)return a;var b=new a.constructor;for(var c in a)a[z](c)&&(b[c]=d(a[c]));return b}function e(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return a.push(a.splice(c,1)[0])}function f(a,b,c){function d(){var f=Array.prototype.slice.call(arguments,0),g=f.join("␀"),h=d.cache=d.cache||{},i=d.count=d.count||[];return h[z](g)?(e(i,g),c?c(h[g]):h[g]):(i.length>=1e3&&delete h[i.shift()],i.push(g),h[g]=a[D](b,f),c?c(h[g]):h[g])}return d}function g(){return this.hex}function h(a,b){for(var c=[],d=0,e=a.length;e-2*!b>d;d+=2){var f=[{x:+a[d-2],y:+a[d-1]},{x:+a[d],y:+a[d+1]},{x:+a[d+2],y:+a[d+3]},{x:+a[d+4],y:+a[d+5]}];b?d?e-4==d?f[3]={x:+a[0],y:+a[1]}:e-2==d&&(f[2]={x:+a[0],y:+a[1]},f[3]={x:+a[2],y:+a[3]}):f[0]={x:+a[e-2],y:+a[e-1]}:e-4==d?f[3]=f[2]:d||(f[0]={x:+a[d],y:+a[d+1]}),c.push(["C",(-f[0].x+6*f[1].x+f[2].x)/6,(-f[0].y+6*f[1].y+f[2].y)/6,(f[1].x+6*f[2].x-f[3].x)/6,(f[1].y+6*f[2].y-f[3].y)/6,f[2].x,f[2].y])}return c}function i(a,b,c,d,e){var f=-3*b+9*c-9*d+3*e,g=a*f+6*b-12*c+6*d;return a*g-3*b+3*c}function j(a,b,c,d,e,f,g,h,j){null==j&&(j=1),j=j>1?1:0>j?0:j;for(var k=j/2,l=12,m=[-.1252,.1252,-.3678,.3678,-.5873,.5873,-.7699,.7699,-.9041,.9041,-.9816,.9816],n=[.2491,.2491,.2335,.2335,.2032,.2032,.1601,.1601,.1069,.1069,.0472,.0472],o=0,p=0;l>p;p++){var q=k*m[p]+k,r=i(q,a,c,e,g),s=i(q,b,d,f,h),t=r*r+s*s;o+=n[p]*N.sqrt(t)}return k*o}function k(a,b,c,d,e,f,g,h,i){if(!(0>i||j(a,b,c,d,e,f,g,h)<i)){var k,l=1,m=l/2,n=l-m,o=.01;for(k=j(a,b,c,d,e,f,g,h,n);Q(k-i)>o;)m/=2,n+=(i>k?1:-1)*m,k=j(a,b,c,d,e,f,g,h,n);return n}}function l(a,b,c,d,e,f,g,h){if(!(O(a,c)<P(e,g)||P(a,c)>O(e,g)||O(b,d)<P(f,h)||P(b,d)>O(f,h))){var i=(a*d-b*c)*(e-g)-(a-c)*(e*h-f*g),j=(a*d-b*c)*(f-h)-(b-d)*(e*h-f*g),k=(a-c)*(f-h)-(b-d)*(e-g);if(k){var l=i/k,m=j/k,n=+l.toFixed(2),o=+m.toFixed(2);if(!(n<+P(a,c).toFixed(2)||n>+O(a,c).toFixed(2)||n<+P(e,g).toFixed(2)||n>+O(e,g).toFixed(2)||o<+P(b,d).toFixed(2)||o>+O(b,d).toFixed(2)||o<+P(f,h).toFixed(2)||o>+O(f,h).toFixed(2)))return{x:l,y:m}}}}function m(a,b,d){var e=c.bezierBBox(a),f=c.bezierBBox(b);if(!c.isBBoxIntersect(e,f))return d?0:[];for(var g=j.apply(0,a),h=j.apply(0,b),i=O(~~(g/5),1),k=O(~~(h/5),1),m=[],n=[],o={},p=d?0:[],q=0;i+1>q;q++){var r=c.findDotsAtSegment.apply(c,a.concat(q/i));m.push({x:r.x,y:r.y,t:q/i})}for(q=0;k+1>q;q++)r=c.findDotsAtSegment.apply(c,b.concat(q/k)),n.push({x:r.x,y:r.y,t:q/k});for(q=0;i>q;q++)for(var s=0;k>s;s++){var t=m[q],u=m[q+1],v=n[s],w=n[s+1],x=Q(u.x-t.x)<.001?"y":"x",y=Q(w.x-v.x)<.001?"y":"x",z=l(t.x,t.y,u.x,u.y,v.x,v.y,w.x,w.y);if(z){if(o[z.x.toFixed(4)]==z.y.toFixed(4))continue;o[z.x.toFixed(4)]=z.y.toFixed(4);var A=t.t+Q((z[x]-t[x])/(u[x]-t[x]))*(u.t-t.t),B=v.t+Q((z[y]-v[y])/(w[y]-v[y]))*(w.t-v.t);A>=0&&1.001>=A&&B>=0&&1.001>=B&&(d?p++:p.push({x:z.x,y:z.y,t1:P(A,1),t2:P(B,1)}))}}return p}function n(a,b,d){a=c._path2curve(a),b=c._path2curve(b);for(var e,f,g,h,i,j,k,l,n,o,p=d?0:[],q=0,r=a.length;r>q;q++){var s=a[q];if("M"==s[0])e=i=s[1],f=j=s[2];else{"C"==s[0]?(n=[e,f].concat(s.slice(1)),e=n[6],f=n[7]):(n=[e,f,e,f,i,j,i,j],e=i,f=j);for(var t=0,u=b.length;u>t;t++){var v=b[t];if("M"==v[0])g=k=v[1],h=l=v[2];else{"C"==v[0]?(o=[g,h].concat(v.slice(1)),g=o[6],h=o[7]):(o=[g,h,g,h,k,l,k,l],g=k,h=l);var w=m(n,o,d);if(d)p+=w;else{for(var x=0,y=w.length;y>x;x++)w[x].segment1=q,w[x].segment2=t,w[x].bez1=n,w[x].bez2=o;p=p.concat(w)}}}}}return p}function o(a,b,c,d,e,f){null!=a?(this.a=+a,this.b=+b,this.c=+c,this.d=+d,this.e=+e,this.f=+f):(this.a=1,this.b=0,this.c=0,this.d=1,this.e=0,this.f=0)}function p(){return this.x+H+this.y+H+this.width+" × "+this.height}function q(a,b,c,d,e,f){function g(a){return((l*a+k)*a+j)*a}function h(a,b){var c=i(a,b);return((o*c+n)*c+m)*c}function i(a,b){var c,d,e,f,h,i;for(e=a,i=0;8>i;i++){if(f=g(e)-a,Q(f)<b)return e;if(h=(3*l*e+2*k)*e+j,Q(h)<1e-6)break;e-=f/h}if(c=0,d=1,e=a,c>e)return c;if(e>d)return d;for(;d>c;){if(f=g(e),Q(f-a)<b)return e;a>f?c=e:d=e,e=(d-c)/2+c}return e}var j=3*b,k=3*(d-b)-j,l=1-j-k,m=3*c,n=3*(e-c)-m,o=1-m-n;return h(a,1/(200*f))}function r(a,b){var c=[],d={};if(this.ms=b,this.times=1,a){for(var e in a)a[z](e)&&(d[_(e)]=a[e],c.push(_(e)));c.sort(lb)}this.anim=d,this.top=c[c.length-1],this.percents=c}function s(a,d,e,f,g,h){e=_(e);var i,j,k,l,m,n,p=a.ms,r={},s={},t={};if(f)for(v=0,x=ic.length;x>v;v++){var u=ic[v];if(u.el.id==d.id&&u.anim==a){u.percent!=e?(ic.splice(v,1),k=1):j=u,d.attr(u.totalOrigin);break}}else f=+s;for(var v=0,x=a.percents.length;x>v;v++){if(a.percents[v]==e||a.percents[v]>f*a.top){e=a.percents[v],m=a.percents[v-1]||0,p=p/a.top*(e-m),l=a.percents[v+1],i=a.anim[e];break}f&&d.attr(a.anim[a.percents[v]])}if(i){if(j)j.initstatus=f,j.start=new Date-j.ms*f;else{for(var y in i)if(i[z](y)&&(db[z](y)||d.paper.customAttributes[z](y)))switch(r[y]=d.attr(y),null==r[y]&&(r[y]=cb[y]),s[y]=i[y],db[y]){case T:t[y]=(s[y]-r[y])/p;break;case"colour":r[y]=c.getRGB(r[y]);var A=c.getRGB(s[y]);t[y]={r:(A.r-r[y].r)/p,g:(A.g-r[y].g)/p,b:(A.b-r[y].b)/p};break;case"path":var B=Kb(r[y],s[y]),C=B[1];for(r[y]=B[0],t[y]=[],v=0,x=r[y].length;x>v;v++){t[y][v]=[0];for(var D=1,F=r[y][v].length;F>D;D++)t[y][v][D]=(C[v][D]-r[y][v][D])/p}break;case"transform":var G=d._,H=Pb(G[y],s[y]);if(H)for(r[y]=H.from,s[y]=H.to,t[y]=[],t[y].real=!0,v=0,x=r[y].length;x>v;v++)for(t[y][v]=[r[y][v][0]],D=1,F=r[y][v].length;F>D;D++)t[y][v][D]=(s[y][v][D]-r[y][v][D])/p;else{var K=d.matrix||new o,L={_:{transform:G.transform},getBBox:function(){return d.getBBox(1)}};r[y]=[K.a,K.b,K.c,K.d,K.e,K.f],Nb(L,s[y]),s[y]=L._.transform,t[y]=[(L.matrix.a-K.a)/p,(L.matrix.b-K.b)/p,(L.matrix.c-K.c)/p,(L.matrix.d-K.d)/p,(L.matrix.e-K.e)/p,(L.matrix.f-K.f)/p]}break;case"csv":var M=I(i[y])[J](w),N=I(r[y])[J](w);if("clip-rect"==y)for(r[y]=N,t[y]=[],v=N.length;v--;)t[y][v]=(M[v]-r[y][v])/p;s[y]=M;break;default:for(M=[][E](i[y]),N=[][E](r[y]),t[y]=[],v=d.paper.customAttributes[y].length;v--;)t[y][v]=((M[v]||0)-(N[v]||0))/p}var O=i.easing,P=c.easing_formulas[O];if(!P)if(P=I(O).match(Z),P&&5==P.length){var Q=P;P=function(a){return q(a,+Q[1],+Q[2],+Q[3],+Q[4],p)}}else P=nb;if(n=i.start||a.start||+new Date,u={anim:a,percent:e,timestamp:n,start:n+(a.del||0),status:0,initstatus:f||0,stop:!1,ms:p,easing:P,from:r,diff:t,to:s,el:d,callback:i.callback,prev:m,next:l,repeat:h||a.times,origin:d.attr(),totalOrigin:g},ic.push(u),f&&!j&&!k&&(u.stop=!0,u.start=new Date-p*f,1==ic.length))return kc();k&&(u.start=new Date-u.ms*f),1==ic.length&&jc(kc)}b("raphael.anim.start."+d.id,d,a)}}function t(a){for(var b=0;b<ic.length;b++)ic[b].el.paper==a&&ic.splice(b--,1)}c.version="2.1.2",c.eve=b;var u,v,w=/[, ]+/,x={circle:1,rect:1,path:1,ellipse:1,text:1,image:1},y=/\{(\d+)\}/g,z="hasOwnProperty",A={doc:document,win:a},B={was:Object.prototype[z].call(A.win,"Raphael"),is:A.win.Raphael},C=function(){this.ca=this.customAttributes={}},D="apply",E="concat",F="ontouchstart"in A.win||A.win.DocumentTouch&&A.doc instanceof DocumentTouch,G="",H=" ",I=String,J="split",K="click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[J](H),L={mousedown:"touchstart",mousemove:"touchmove",mouseup:"touchend"},M=I.prototype.toLowerCase,N=Math,O=N.max,P=N.min,Q=N.abs,R=N.pow,S=N.PI,T="number",U="string",V="array",W=Object.prototype.toString,X=(c._ISURL=/^url\(['"]?([^\)]+?)['"]?\)$/i,/^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i),Y={NaN:1,Infinity:1,"-Infinity":1},Z=/^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,$=N.round,_=parseFloat,ab=parseInt,bb=I.prototype.toUpperCase,cb=c._availableAttrs={"arrow-end":"none","arrow-start":"none",blur:0,"clip-rect":"0 0 1e9 1e9",cursor:"default",cx:0,cy:0,fill:"#fff","fill-opacity":1,font:'10px "Arial"',"font-family":'"Arial"',"font-size":"10","font-style":"normal","font-weight":400,gradient:0,height:0,href:"http://raphaeljs.com/","letter-spacing":0,opacity:1,path:"M0,0",r:0,rx:0,ry:0,src:"",stroke:"#000","stroke-dasharray":"","stroke-linecap":"butt","stroke-linejoin":"butt","stroke-miterlimit":0,"stroke-opacity":1,"stroke-width":1,target:"_blank","text-anchor":"middle",title:"Raphael",transform:"",width:0,x:0,y:0},db=c._availableAnimAttrs={blur:T,"clip-rect":"csv",cx:T,cy:T,fill:"colour","fill-opacity":T,"font-size":T,height:T,opacity:T,path:"path",r:T,rx:T,ry:T,stroke:"colour","stroke-opacity":T,"stroke-width":T,transform:"transform",width:T,x:T,y:T},eb=/[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/,fb={hs:1,rg:1},gb=/,?([achlmqrstvxz]),?/gi,hb=/([achlmrqstvz])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/gi,ib=/([rstm])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/gi,jb=/(-?\d*\.?\d*(?:e[\-+]?\d+)?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/gi,kb=(c._radial_gradient=/^r(?:\(([^,]+?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*([^\)]+?)\))?/,{}),lb=function(a,b){return _(a)-_(b)},mb=function(){},nb=function(a){return a},ob=c._rectPath=function(a,b,c,d,e){return e?[["M",a+e,b],["l",c-2*e,0],["a",e,e,0,0,1,e,e],["l",0,d-2*e],["a",e,e,0,0,1,-e,e],["l",2*e-c,0],["a",e,e,0,0,1,-e,-e],["l",0,2*e-d],["a",e,e,0,0,1,e,-e],["z"]]:[["M",a,b],["l",c,0],["l",0,d],["l",-c,0],["z"]]},pb=function(a,b,c,d){return null==d&&(d=c),[["M",a,b],["m",0,-d],["a",c,d,0,1,1,0,2*d],["a",c,d,0,1,1,0,-2*d],["z"]]},qb=c._getPath={path:function(a){return a.attr("path")},circle:function(a){var b=a.attrs;return pb(b.cx,b.cy,b.r)},ellipse:function(a){var b=a.attrs;return pb(b.cx,b.cy,b.rx,b.ry)},rect:function(a){var b=a.attrs;return ob(b.x,b.y,b.width,b.height,b.r)},image:function(a){var b=a.attrs;return ob(b.x,b.y,b.width,b.height)},text:function(a){var b=a._getBBox();return ob(b.x,b.y,b.width,b.height)},set:function(a){var b=a._getBBox();return ob(b.x,b.y,b.width,b.height)}},rb=c.mapPath=function(a,b){if(!b)return a;var c,d,e,f,g,h,i;for(a=Kb(a),e=0,g=a.length;g>e;e++)for(i=a[e],f=1,h=i.length;h>f;f+=2)c=b.x(i[f],i[f+1]),d=b.y(i[f],i[f+1]),i[f]=c,i[f+1]=d;return a};if(c._g=A,c.type=A.win.SVGAngle||A.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")?"SVG":"VML","VML"==c.type){var sb,tb=A.doc.createElement("div");if(tb.innerHTML='<v:shape adj="1"/>',sb=tb.firstChild,sb.style.behavior="url(#default#VML)",!sb||"object"!=typeof sb.adj)return c.type=G;tb=null}c.svg=!(c.vml="VML"==c.type),c._Paper=C,c.fn=v=C.prototype=c.prototype,c._id=0,c._oid=0,c.is=function(a,b){return b=M.call(b),"finite"==b?!Y[z](+a):"array"==b?a instanceof Array:"null"==b&&null===a||b==typeof a&&null!==a||"object"==b&&a===Object(a)||"array"==b&&Array.isArray&&Array.isArray(a)||W.call(a).slice(8,-1).toLowerCase()==b},c.angle=function(a,b,d,e,f,g){if(null==f){var h=a-d,i=b-e;return h||i?(180+180*N.atan2(-i,-h)/S+360)%360:0}return c.angle(a,b,f,g)-c.angle(d,e,f,g)},c.rad=function(a){return a%360*S/180},c.deg=function(a){return 180*a/S%360},c.snapTo=function(a,b,d){if(d=c.is(d,"finite")?d:10,c.is(a,V)){for(var e=a.length;e--;)if(Q(a[e]-b)<=d)return a[e]}else{a=+a;var f=b%a;if(d>f)return b-f;if(f>a-d)return b-f+a}return b},c.createUUID=function(a,b){return function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(a,b).toUpperCase()}}(/[xy]/g,function(a){var b=0|16*N.random(),c="x"==a?b:8|3&b;return c.toString(16)}),c.setWindow=function(a){b("raphael.setWindow",c,A.win,a),A.win=a,A.doc=A.win.document,c._engine.initWin&&c._engine.initWin(A.win)};var ub=function(a){if(c.vml){var b,d=/^\s+|\s+$/g;try{var e=new ActiveXObject("htmlfile");e.write("<body>"),e.close(),b=e.body}catch(g){b=createPopup().document.body}var h=b.createTextRange();ub=f(function(a){try{b.style.color=I(a).replace(d,G);var c=h.queryCommandValue("ForeColor");return c=(255&c)<<16|65280&c|(16711680&c)>>>16,"#"+("000000"+c.toString(16)).slice(-6)}catch(e){return"none"}})}else{var i=A.doc.createElement("i");i.title="Raphaël Colour Picker",i.style.display="none",A.doc.body.appendChild(i),ub=f(function(a){return i.style.color=a,A.doc.defaultView.getComputedStyle(i,G).getPropertyValue("color")})}return ub(a)},vb=function(){return"hsb("+[this.h,this.s,this.b]+")"},wb=function(){return"hsl("+[this.h,this.s,this.l]+")"},xb=function(){return this.hex},yb=function(a,b,d){if(null==b&&c.is(a,"object")&&"r"in a&&"g"in a&&"b"in a&&(d=a.b,b=a.g,a=a.r),null==b&&c.is(a,U)){var e=c.getRGB(a);a=e.r,b=e.g,d=e.b}return(a>1||b>1||d>1)&&(a/=255,b/=255,d/=255),[a,b,d]},zb=function(a,b,d,e){a*=255,b*=255,d*=255;var f={r:a,g:b,b:d,hex:c.rgb(a,b,d),toString:xb};return c.is(e,"finite")&&(f.opacity=e),f};c.color=function(a){var b;return c.is(a,"object")&&"h"in a&&"s"in a&&"b"in a?(b=c.hsb2rgb(a),a.r=b.r,a.g=b.g,a.b=b.b,a.hex=b.hex):c.is(a,"object")&&"h"in a&&"s"in a&&"l"in a?(b=c.hsl2rgb(a),a.r=b.r,a.g=b.g,a.b=b.b,a.hex=b.hex):(c.is(a,"string")&&(a=c.getRGB(a)),c.is(a,"object")&&"r"in a&&"g"in a&&"b"in a?(b=c.rgb2hsl(a),a.h=b.h,a.s=b.s,a.l=b.l,b=c.rgb2hsb(a),a.v=b.b):(a={hex:"none"},a.r=a.g=a.b=a.h=a.s=a.v=a.l=-1)),a.toString=xb,a},c.hsb2rgb=function(a,b,c,d){this.is(a,"object")&&"h"in a&&"s"in a&&"b"in a&&(c=a.b,b=a.s,a=a.h,d=a.o),a*=360;var e,f,g,h,i;return a=a%360/60,i=c*b,h=i*(1-Q(a%2-1)),e=f=g=c-i,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a],zb(e,f,g,d)},c.hsl2rgb=function(a,b,c,d){this.is(a,"object")&&"h"in a&&"s"in a&&"l"in a&&(c=a.l,b=a.s,a=a.h),(a>1||b>1||c>1)&&(a/=360,b/=100,c/=100),a*=360;var e,f,g,h,i;return a=a%360/60,i=2*b*(.5>c?c:1-c),h=i*(1-Q(a%2-1)),e=f=g=c-i/2,a=~~a,e+=[i,h,0,0,h,i][a],f+=[h,i,i,h,0,0][a],g+=[0,0,h,i,i,h][a],zb(e,f,g,d)},c.rgb2hsb=function(a,b,c){c=yb(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g;return f=O(a,b,c),g=f-P(a,b,c),d=0==g?null:f==a?(b-c)/g:f==b?(c-a)/g+2:(a-b)/g+4,d=60*((d+360)%6)/360,e=0==g?0:g/f,{h:d,s:e,b:f,toString:vb}},c.rgb2hsl=function(a,b,c){c=yb(a,b,c),a=c[0],b=c[1],c=c[2];var d,e,f,g,h,i;return g=O(a,b,c),h=P(a,b,c),i=g-h,d=0==i?null:g==a?(b-c)/i:g==b?(c-a)/i+2:(a-b)/i+4,d=60*((d+360)%6)/360,f=(g+h)/2,e=0==i?0:.5>f?i/(2*f):i/(2-2*f),{h:d,s:e,l:f,toString:wb}},c._path2string=function(){return this.join(",").replace(gb,"$1")},c._preload=function(a,b){var c=A.doc.createElement("img");c.style.cssText="position:absolute;left:-9999em;top:-9999em",c.onload=function(){b.call(this),this.onload=null,A.doc.body.removeChild(this)},c.onerror=function(){A.doc.body.removeChild(this)},A.doc.body.appendChild(c),c.src=a},c.getRGB=f(function(a){if(!a||(a=I(a)).indexOf("-")+1)return{r:-1,g:-1,b:-1,hex:"none",error:1,toString:g};if("none"==a)return{r:-1,g:-1,b:-1,hex:"none",toString:g};!(fb[z](a.toLowerCase().substring(0,2))||"#"==a.charAt())&&(a=ub(a));var b,d,e,f,h,i,j=a.match(X);return j?(j[2]&&(e=ab(j[2].substring(5),16),d=ab(j[2].substring(3,5),16),b=ab(j[2].substring(1,3),16)),j[3]&&(e=ab((h=j[3].charAt(3))+h,16),d=ab((h=j[3].charAt(2))+h,16),b=ab((h=j[3].charAt(1))+h,16)),j[4]&&(i=j[4][J](eb),b=_(i[0]),"%"==i[0].slice(-1)&&(b*=2.55),d=_(i[1]),"%"==i[1].slice(-1)&&(d*=2.55),e=_(i[2]),"%"==i[2].slice(-1)&&(e*=2.55),"rgba"==j[1].toLowerCase().slice(0,4)&&(f=_(i[3])),i[3]&&"%"==i[3].slice(-1)&&(f/=100)),j[5]?(i=j[5][J](eb),b=_(i[0]),"%"==i[0].slice(-1)&&(b*=2.55),d=_(i[1]),"%"==i[1].slice(-1)&&(d*=2.55),e=_(i[2]),"%"==i[2].slice(-1)&&(e*=2.55),("deg"==i[0].slice(-3)||"°"==i[0].slice(-1))&&(b/=360),"hsba"==j[1].toLowerCase().slice(0,4)&&(f=_(i[3])),i[3]&&"%"==i[3].slice(-1)&&(f/=100),c.hsb2rgb(b,d,e,f)):j[6]?(i=j[6][J](eb),b=_(i[0]),"%"==i[0].slice(-1)&&(b*=2.55),d=_(i[1]),"%"==i[1].slice(-1)&&(d*=2.55),e=_(i[2]),"%"==i[2].slice(-1)&&(e*=2.55),("deg"==i[0].slice(-3)||"°"==i[0].slice(-1))&&(b/=360),"hsla"==j[1].toLowerCase().slice(0,4)&&(f=_(i[3])),i[3]&&"%"==i[3].slice(-1)&&(f/=100),c.hsl2rgb(b,d,e,f)):(j={r:b,g:d,b:e,toString:g},j.hex="#"+(16777216|e|d<<8|b<<16).toString(16).slice(1),c.is(f,"finite")&&(j.opacity=f),j)):{r:-1,g:-1,b:-1,hex:"none",error:1,toString:g}},c),c.hsb=f(function(a,b,d){return c.hsb2rgb(a,b,d).hex}),c.hsl=f(function(a,b,d){return c.hsl2rgb(a,b,d).hex}),c.rgb=f(function(a,b,c){return"#"+(16777216|c|b<<8|a<<16).toString(16).slice(1)}),c.getColor=function(a){var b=this.getColor.start=this.getColor.start||{h:0,s:1,b:a||.75},c=this.hsb2rgb(b.h,b.s,b.b);return b.h+=.075,b.h>1&&(b.h=0,b.s-=.2,b.s<=0&&(this.getColor.start={h:0,s:1,b:b.b})),c.hex},c.getColor.reset=function(){delete this.start},c.parsePathString=function(a){if(!a)return null;var b=Ab(a);if(b.arr)return Cb(b.arr);var d={a:7,c:6,h:1,l:2,m:2,r:4,q:4,s:4,t:2,v:1,z:0},e=[];return c.is(a,V)&&c.is(a[0],V)&&(e=Cb(a)),e.length||I(a).replace(hb,function(a,b,c){var f=[],g=b.toLowerCase();if(c.replace(jb,function(a,b){b&&f.push(+b)}),"m"==g&&f.length>2&&(e.push([b][E](f.splice(0,2))),g="l",b="m"==b?"l":"L"),"r"==g)e.push([b][E](f));else for(;f.length>=d[g]&&(e.push([b][E](f.splice(0,d[g]))),d[g]););}),e.toString=c._path2string,b.arr=Cb(e),e},c.parseTransformString=f(function(a){if(!a)return null;var b=[];return c.is(a,V)&&c.is(a[0],V)&&(b=Cb(a)),b.length||I(a).replace(ib,function(a,c,d){var e=[];M.call(c),d.replace(jb,function(a,b){b&&e.push(+b)}),b.push([c][E](e))}),b.toString=c._path2string,b});var Ab=function(a){var b=Ab.ps=Ab.ps||{};return b[a]?b[a].sleep=100:b[a]={sleep:100},setTimeout(function(){for(var c in b)b[z](c)&&c!=a&&(b[c].sleep--,!b[c].sleep&&delete b[c])}),b[a]};c.findDotsAtSegment=function(a,b,c,d,e,f,g,h,i){var j=1-i,k=R(j,3),l=R(j,2),m=i*i,n=m*i,o=k*a+3*l*i*c+3*j*i*i*e+n*g,p=k*b+3*l*i*d+3*j*i*i*f+n*h,q=a+2*i*(c-a)+m*(e-2*c+a),r=b+2*i*(d-b)+m*(f-2*d+b),s=c+2*i*(e-c)+m*(g-2*e+c),t=d+2*i*(f-d)+m*(h-2*f+d),u=j*a+i*c,v=j*b+i*d,w=j*e+i*g,x=j*f+i*h,y=90-180*N.atan2(q-s,r-t)/S;return(q>s||t>r)&&(y+=180),{x:o,y:p,m:{x:q,y:r},n:{x:s,y:t},start:{x:u,y:v},end:{x:w,y:x},alpha:y}},c.bezierBBox=function(a,b,d,e,f,g,h,i){c.is(a,"array")||(a=[a,b,d,e,f,g,h,i]);var j=Jb.apply(null,a);return{x:j.min.x,y:j.min.y,x2:j.max.x,y2:j.max.y,width:j.max.x-j.min.x,height:j.max.y-j.min.y}},c.isPointInsideBBox=function(a,b,c){return b>=a.x&&b<=a.x2&&c>=a.y&&c<=a.y2},c.isBBoxIntersect=function(a,b){var d=c.isPointInsideBBox;return d(b,a.x,a.y)||d(b,a.x2,a.y)||d(b,a.x,a.y2)||d(b,a.x2,a.y2)||d(a,b.x,b.y)||d(a,b.x2,b.y)||d(a,b.x,b.y2)||d(a,b.x2,b.y2)||(a.x<b.x2&&a.x>b.x||b.x<a.x2&&b.x>a.x)&&(a.y<b.y2&&a.y>b.y||b.y<a.y2&&b.y>a.y)},c.pathIntersection=function(a,b){return n(a,b)},c.pathIntersectionNumber=function(a,b){return n(a,b,1)},c.isPointInsidePath=function(a,b,d){var e=c.pathBBox(a);return c.isPointInsideBBox(e,b,d)&&1==n(a,[["M",b,d],["H",e.x2+10]],1)%2},c._removedFactory=function(a){return function(){b("raphael.log",null,"Raphaël: you are calling to method “"+a+"” of removed object",a)}};var Bb=c.pathBBox=function(a){var b=Ab(a);if(b.bbox)return d(b.bbox);if(!a)return{x:0,y:0,width:0,height:0,x2:0,y2:0};a=Kb(a);for(var c,e=0,f=0,g=[],h=[],i=0,j=a.length;j>i;i++)if(c=a[i],"M"==c[0])e=c[1],f=c[2],g.push(e),h.push(f);else{var k=Jb(e,f,c[1],c[2],c[3],c[4],c[5],c[6]);g=g[E](k.min.x,k.max.x),h=h[E](k.min.y,k.max.y),e=c[5],f=c[6]}var l=P[D](0,g),m=P[D](0,h),n=O[D](0,g),o=O[D](0,h),p=n-l,q=o-m,r={x:l,y:m,x2:n,y2:o,width:p,height:q,cx:l+p/2,cy:m+q/2};return b.bbox=d(r),r},Cb=function(a){var b=d(a);return b.toString=c._path2string,b},Db=c._pathToRelative=function(a){var b=Ab(a);if(b.rel)return Cb(b.rel);c.is(a,V)&&c.is(a&&a[0],V)||(a=c.parsePathString(a));var d=[],e=0,f=0,g=0,h=0,i=0;"M"==a[0][0]&&(e=a[0][1],f=a[0][2],g=e,h=f,i++,d.push(["M",e,f]));for(var j=i,k=a.length;k>j;j++){var l=d[j]=[],m=a[j];if(m[0]!=M.call(m[0]))switch(l[0]=M.call(m[0]),l[0]){case"a":l[1]=m[1],l[2]=m[2],l[3]=m[3],l[4]=m[4],l[5]=m[5],l[6]=+(m[6]-e).toFixed(3),l[7]=+(m[7]-f).toFixed(3);break;case"v":l[1]=+(m[1]-f).toFixed(3);break;case"m":g=m[1],h=m[2];default:for(var n=1,o=m.length;o>n;n++)l[n]=+(m[n]-(n%2?e:f)).toFixed(3)}else{l=d[j]=[],"m"==m[0]&&(g=m[1]+e,h=m[2]+f);for(var p=0,q=m.length;q>p;p++)d[j][p]=m[p]}var r=d[j].length;switch(d[j][0]){case"z":e=g,f=h;break;case"h":e+=+d[j][r-1];break;case"v":f+=+d[j][r-1];break;default:e+=+d[j][r-2],f+=+d[j][r-1]}}return d.toString=c._path2string,b.rel=Cb(d),d},Eb=c._pathToAbsolute=function(a){var b=Ab(a);if(b.abs)return Cb(b.abs);if(c.is(a,V)&&c.is(a&&a[0],V)||(a=c.parsePathString(a)),!a||!a.length)return[["M",0,0]];var d=[],e=0,f=0,g=0,i=0,j=0;"M"==a[0][0]&&(e=+a[0][1],f=+a[0][2],g=e,i=f,j++,d[0]=["M",e,f]);for(var k,l,m=3==a.length&&"M"==a[0][0]&&"R"==a[1][0].toUpperCase()&&"Z"==a[2][0].toUpperCase(),n=j,o=a.length;o>n;n++){if(d.push(k=[]),l=a[n],l[0]!=bb.call(l[0]))switch(k[0]=bb.call(l[0]),k[0]){case"A":k[1]=l[1],k[2]=l[2],k[3]=l[3],k[4]=l[4],k[5]=l[5],k[6]=+(l[6]+e),k[7]=+(l[7]+f);break;case"V":k[1]=+l[1]+f;break;case"H":k[1]=+l[1]+e;break;case"R":for(var p=[e,f][E](l.slice(1)),q=2,r=p.length;r>q;q++)p[q]=+p[q]+e,p[++q]=+p[q]+f;d.pop(),d=d[E](h(p,m));break;case"M":g=+l[1]+e,i=+l[2]+f;default:for(q=1,r=l.length;r>q;q++)k[q]=+l[q]+(q%2?e:f)}else if("R"==l[0])p=[e,f][E](l.slice(1)),d.pop(),d=d[E](h(p,m)),k=["R"][E](l.slice(-2));else for(var s=0,t=l.length;t>s;s++)k[s]=l[s];switch(k[0]){case"Z":e=g,f=i;break;case"H":e=k[1];break;case"V":f=k[1];break;case"M":g=k[k.length-2],i=k[k.length-1];default:e=k[k.length-2],f=k[k.length-1]}}return d.toString=c._path2string,b.abs=Cb(d),d},Fb=function(a,b,c,d){return[a,b,c,d,c,d]},Gb=function(a,b,c,d,e,f){var g=1/3,h=2/3;return[g*a+h*c,g*b+h*d,g*e+h*c,g*f+h*d,e,f]},Hb=function(a,b,c,d,e,g,h,i,j,k){var l,m=120*S/180,n=S/180*(+e||0),o=[],p=f(function(a,b,c){var d=a*N.cos(c)-b*N.sin(c),e=a*N.sin(c)+b*N.cos(c);return{x:d,y:e}});if(k)y=k[0],z=k[1],w=k[2],x=k[3];else{l=p(a,b,-n),a=l.x,b=l.y,l=p(i,j,-n),i=l.x,j=l.y;var q=(N.cos(S/180*e),N.sin(S/180*e),(a-i)/2),r=(b-j)/2,s=q*q/(c*c)+r*r/(d*d);s>1&&(s=N.sqrt(s),c=s*c,d=s*d);var t=c*c,u=d*d,v=(g==h?-1:1)*N.sqrt(Q((t*u-t*r*r-u*q*q)/(t*r*r+u*q*q))),w=v*c*r/d+(a+i)/2,x=v*-d*q/c+(b+j)/2,y=N.asin(((b-x)/d).toFixed(9)),z=N.asin(((j-x)/d).toFixed(9));y=w>a?S-y:y,z=w>i?S-z:z,0>y&&(y=2*S+y),0>z&&(z=2*S+z),h&&y>z&&(y-=2*S),!h&&z>y&&(z-=2*S)}var A=z-y;if(Q(A)>m){var B=z,C=i,D=j;z=y+m*(h&&z>y?1:-1),i=w+c*N.cos(z),j=x+d*N.sin(z),o=Hb(i,j,c,d,e,0,h,C,D,[z,B,w,x])}A=z-y;var F=N.cos(y),G=N.sin(y),H=N.cos(z),I=N.sin(z),K=N.tan(A/4),L=4/3*c*K,M=4/3*d*K,O=[a,b],P=[a+L*G,b-M*F],R=[i+L*I,j-M*H],T=[i,j];if(P[0]=2*O[0]-P[0],P[1]=2*O[1]-P[1],k)return[P,R,T][E](o);o=[P,R,T][E](o).join()[J](",");for(var U=[],V=0,W=o.length;W>V;V++)U[V]=V%2?p(o[V-1],o[V],n).y:p(o[V],o[V+1],n).x;return U},Ib=function(a,b,c,d,e,f,g,h,i){var j=1-i;return{x:R(j,3)*a+3*R(j,2)*i*c+3*j*i*i*e+R(i,3)*g,y:R(j,3)*b+3*R(j,2)*i*d+3*j*i*i*f+R(i,3)*h}},Jb=f(function(a,b,c,d,e,f,g,h){var i,j=e-2*c+a-(g-2*e+c),k=2*(c-a)-2*(e-c),l=a-c,m=(-k+N.sqrt(k*k-4*j*l))/2/j,n=(-k-N.sqrt(k*k-4*j*l))/2/j,o=[b,h],p=[a,g];return Q(m)>"1e12"&&(m=.5),Q(n)>"1e12"&&(n=.5),m>0&&1>m&&(i=Ib(a,b,c,d,e,f,g,h,m),p.push(i.x),o.push(i.y)),n>0&&1>n&&(i=Ib(a,b,c,d,e,f,g,h,n),p.push(i.x),o.push(i.y)),j=f-2*d+b-(h-2*f+d),k=2*(d-b)-2*(f-d),l=b-d,m=(-k+N.sqrt(k*k-4*j*l))/2/j,n=(-k-N.sqrt(k*k-4*j*l))/2/j,Q(m)>"1e12"&&(m=.5),Q(n)>"1e12"&&(n=.5),m>0&&1>m&&(i=Ib(a,b,c,d,e,f,g,h,m),p.push(i.x),o.push(i.y)),n>0&&1>n&&(i=Ib(a,b,c,d,e,f,g,h,n),p.push(i.x),o.push(i.y)),{min:{x:P[D](0,p),y:P[D](0,o)},max:{x:O[D](0,p),y:O[D](0,o)}}}),Kb=c._path2curve=f(function(a,b){var c=!b&&Ab(a);if(!b&&c.curve)return Cb(c.curve);for(var d=Eb(a),e=b&&Eb(b),f={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},g={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},h=(function(a,b,c){var d,e;if(!a)return["C",b.x,b.y,b.x,b.y,b.x,b.y];switch(!(a[0]in{T:1,Q:1})&&(b.qx=b.qy=null),a[0]){case"M":b.X=a[1],b.Y=a[2];break;case"A":a=["C"][E](Hb[D](0,[b.x,b.y][E](a.slice(1))));break;case"S":"C"==c||"S"==c?(d=2*b.x-b.bx,e=2*b.y-b.by):(d=b.x,e=b.y),a=["C",d,e][E](a.slice(1));break;case"T":"Q"==c||"T"==c?(b.qx=2*b.x-b.qx,b.qy=2*b.y-b.qy):(b.qx=b.x,b.qy=b.y),a=["C"][E](Gb(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case"Q":b.qx=a[1],b.qy=a[2],a=["C"][E](Gb(b.x,b.y,a[1],a[2],a[3],a[4]));break;case"L":a=["C"][E](Fb(b.x,b.y,a[1],a[2]));break;case"H":a=["C"][E](Fb(b.x,b.y,a[1],b.y));break;case"V":a=["C"][E](Fb(b.x,b.y,b.x,a[1]));break;case"Z":a=["C"][E](Fb(b.x,b.y,b.X,b.Y))}return a}),i=function(a,b){if(a[b].length>7){a[b].shift();for(var c=a[b];c.length;)a.splice(b++,0,["C"][E](c.splice(0,6)));a.splice(b,1),l=O(d.length,e&&e.length||0)}},j=function(a,b,c,f,g){a&&b&&"M"==a[g][0]&&"M"!=b[g][0]&&(b.splice(g,0,["M",f.x,f.y]),c.bx=0,c.by=0,c.x=a[g][1],c.y=a[g][2],l=O(d.length,e&&e.length||0))},k=0,l=O(d.length,e&&e.length||0);l>k;k++){d[k]=h(d[k],f),i(d,k),e&&(e[k]=h(e[k],g)),e&&i(e,k),j(d,e,f,g,k),j(e,d,g,f,k);var m=d[k],n=e&&e[k],o=m.length,p=e&&n.length;f.x=m[o-2],f.y=m[o-1],f.bx=_(m[o-4])||f.x,f.by=_(m[o-3])||f.y,g.bx=e&&(_(n[p-4])||g.x),g.by=e&&(_(n[p-3])||g.y),g.x=e&&n[p-2],g.y=e&&n[p-1]}return e||(c.curve=Cb(d)),e?[d,e]:d},null,Cb),Lb=(c._parseDots=f(function(a){for(var b=[],d=0,e=a.length;e>d;d++){var f={},g=a[d].match(/^([^:]*):?([\d\.]*)/);if(f.color=c.getRGB(g[1]),f.color.error)return null;f.color=f.color.hex,g[2]&&(f.offset=g[2]+"%"),b.push(f)}for(d=1,e=b.length-1;e>d;d++)if(!b[d].offset){for(var h=_(b[d-1].offset||0),i=0,j=d+1;e>j;j++)if(b[j].offset){i=b[j].offset;break}i||(i=100,j=e),i=_(i);for(var k=(i-h)/(j-d+1);j>d;d++)h+=k,b[d].offset=h+"%"}return b}),c._tear=function(a,b){a==b.top&&(b.top=a.prev),a==b.bottom&&(b.bottom=a.next),a.next&&(a.next.prev=a.prev),a.prev&&(a.prev.next=a.next)}),Mb=(c._tofront=function(a,b){b.top!==a&&(Lb(a,b),a.next=null,a.prev=b.top,b.top.next=a,b.top=a)},c._toback=function(a,b){b.bottom!==a&&(Lb(a,b),a.next=b.bottom,a.prev=null,b.bottom.prev=a,b.bottom=a)},c._insertafter=function(a,b,c){Lb(a,c),b==c.top&&(c.top=a),b.next&&(b.next.prev=a),a.next=b.next,a.prev=b,b.next=a},c._insertbefore=function(a,b,c){Lb(a,c),b==c.bottom&&(c.bottom=a),b.prev&&(b.prev.next=a),a.prev=b.prev,b.prev=a,a.next=b},c.toMatrix=function(a,b){var c=Bb(a),d={_:{transform:G},getBBox:function(){return c}};return Nb(d,b),d.matrix}),Nb=(c.transformPath=function(a,b){return rb(a,Mb(a,b))},c._extractTransform=function(a,b){if(null==b)return a._.transform;b=I(b).replace(/\.{3}|\u2026/g,a._.transform||G);var d=c.parseTransformString(b),e=0,f=0,g=0,h=1,i=1,j=a._,k=new o;if(j.transform=d||[],d)for(var l=0,m=d.length;m>l;l++){var n,p,q,r,s,t=d[l],u=t.length,v=I(t[0]).toLowerCase(),w=t[0]!=v,x=w?k.invert():0;"t"==v&&3==u?w?(n=x.x(0,0),p=x.y(0,0),q=x.x(t[1],t[2]),r=x.y(t[1],t[2]),k.translate(q-n,r-p)):k.translate(t[1],t[2]):"r"==v?2==u?(s=s||a.getBBox(1),k.rotate(t[1],s.x+s.width/2,s.y+s.height/2),e+=t[1]):4==u&&(w?(q=x.x(t[2],t[3]),r=x.y(t[2],t[3]),k.rotate(t[1],q,r)):k.rotate(t[1],t[2],t[3]),e+=t[1]):"s"==v?2==u||3==u?(s=s||a.getBBox(1),k.scale(t[1],t[u-1],s.x+s.width/2,s.y+s.height/2),h*=t[1],i*=t[u-1]):5==u&&(w?(q=x.x(t[3],t[4]),r=x.y(t[3],t[4]),k.scale(t[1],t[2],q,r)):k.scale(t[1],t[2],t[3],t[4]),h*=t[1],i*=t[2]):"m"==v&&7==u&&k.add(t[1],t[2],t[3],t[4],t[5],t[6]),j.dirtyT=1,a.matrix=k}a.matrix=k,j.sx=h,j.sy=i,j.deg=e,j.dx=f=k.e,j.dy=g=k.f,1==h&&1==i&&!e&&j.bbox?(j.bbox.x+=+f,j.bbox.y+=+g):j.dirtyT=1}),Ob=function(a){var b=a[0];switch(b.toLowerCase()){case"t":return[b,0,0];case"m":return[b,1,0,0,1,0,0];case"r":return 4==a.length?[b,0,a[2],a[3]]:[b,0];case"s":return 5==a.length?[b,1,1,a[3],a[4]]:3==a.length?[b,1,1]:[b,1]}},Pb=c._equaliseTransform=function(a,b){b=I(b).replace(/\.{3}|\u2026/g,a),a=c.parseTransformString(a)||[],b=c.parseTransformString(b)||[];for(var d,e,f,g,h=O(a.length,b.length),i=[],j=[],k=0;h>k;k++){if(f=a[k]||Ob(b[k]),g=b[k]||Ob(f),f[0]!=g[0]||"r"==f[0].toLowerCase()&&(f[2]!=g[2]||f[3]!=g[3])||"s"==f[0].toLowerCase()&&(f[3]!=g[3]||f[4]!=g[4]))return;for(i[k]=[],j[k]=[],d=0,e=O(f.length,g.length);e>d;d++)d in f&&(i[k][d]=f[d]),d in g&&(j[k][d]=g[d])
-}return{from:i,to:j}};c._getContainer=function(a,b,d,e){var f;return f=null!=e||c.is(a,"object")?a:A.doc.getElementById(a),null!=f?f.tagName?null==b?{container:f,width:f.style.pixelWidth||f.offsetWidth,height:f.style.pixelHeight||f.offsetHeight}:{container:f,width:b,height:d}:{container:1,x:a,y:b,width:d,height:e}:void 0},c.pathToRelative=Db,c._engine={},c.path2curve=Kb,c.matrix=function(a,b,c,d,e,f){return new o(a,b,c,d,e,f)},function(a){function b(a){return a[0]*a[0]+a[1]*a[1]}function d(a){var c=N.sqrt(b(a));a[0]&&(a[0]/=c),a[1]&&(a[1]/=c)}a.add=function(a,b,c,d,e,f){var g,h,i,j,k=[[],[],[]],l=[[this.a,this.c,this.e],[this.b,this.d,this.f],[0,0,1]],m=[[a,c,e],[b,d,f],[0,0,1]];for(a&&a instanceof o&&(m=[[a.a,a.c,a.e],[a.b,a.d,a.f],[0,0,1]]),g=0;3>g;g++)for(h=0;3>h;h++){for(j=0,i=0;3>i;i++)j+=l[g][i]*m[i][h];k[g][h]=j}this.a=k[0][0],this.b=k[1][0],this.c=k[0][1],this.d=k[1][1],this.e=k[0][2],this.f=k[1][2]},a.invert=function(){var a=this,b=a.a*a.d-a.b*a.c;return new o(a.d/b,-a.b/b,-a.c/b,a.a/b,(a.c*a.f-a.d*a.e)/b,(a.b*a.e-a.a*a.f)/b)},a.clone=function(){return new o(this.a,this.b,this.c,this.d,this.e,this.f)},a.translate=function(a,b){this.add(1,0,0,1,a,b)},a.scale=function(a,b,c,d){null==b&&(b=a),(c||d)&&this.add(1,0,0,1,c,d),this.add(a,0,0,b,0,0),(c||d)&&this.add(1,0,0,1,-c,-d)},a.rotate=function(a,b,d){a=c.rad(a),b=b||0,d=d||0;var e=+N.cos(a).toFixed(9),f=+N.sin(a).toFixed(9);this.add(e,f,-f,e,b,d),this.add(1,0,0,1,-b,-d)},a.x=function(a,b){return a*this.a+b*this.c+this.e},a.y=function(a,b){return a*this.b+b*this.d+this.f},a.get=function(a){return+this[I.fromCharCode(97+a)].toFixed(4)},a.toString=function(){return c.svg?"matrix("+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)].join()+")":[this.get(0),this.get(2),this.get(1),this.get(3),0,0].join()},a.toFilter=function(){return"progid:DXImageTransform.Microsoft.Matrix(M11="+this.get(0)+", M12="+this.get(2)+", M21="+this.get(1)+", M22="+this.get(3)+", Dx="+this.get(4)+", Dy="+this.get(5)+", sizingmethod='auto expand')"},a.offset=function(){return[this.e.toFixed(4),this.f.toFixed(4)]},a.split=function(){var a={};a.dx=this.e,a.dy=this.f;var e=[[this.a,this.c],[this.b,this.d]];a.scalex=N.sqrt(b(e[0])),d(e[0]),a.shear=e[0][0]*e[1][0]+e[0][1]*e[1][1],e[1]=[e[1][0]-e[0][0]*a.shear,e[1][1]-e[0][1]*a.shear],a.scaley=N.sqrt(b(e[1])),d(e[1]),a.shear/=a.scaley;var f=-e[0][1],g=e[1][1];return 0>g?(a.rotate=c.deg(N.acos(g)),0>f&&(a.rotate=360-a.rotate)):a.rotate=c.deg(N.asin(f)),a.isSimple=!(+a.shear.toFixed(9)||a.scalex.toFixed(9)!=a.scaley.toFixed(9)&&a.rotate),a.isSuperSimple=!+a.shear.toFixed(9)&&a.scalex.toFixed(9)==a.scaley.toFixed(9)&&!a.rotate,a.noRotation=!+a.shear.toFixed(9)&&!a.rotate,a},a.toTransformString=function(a){var b=a||this[J]();return b.isSimple?(b.scalex=+b.scalex.toFixed(4),b.scaley=+b.scaley.toFixed(4),b.rotate=+b.rotate.toFixed(4),(b.dx||b.dy?"t"+[b.dx,b.dy]:G)+(1!=b.scalex||1!=b.scaley?"s"+[b.scalex,b.scaley,0,0]:G)+(b.rotate?"r"+[b.rotate,0,0]:G)):"m"+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)]}}(o.prototype);var Qb=navigator.userAgent.match(/Version\/(.*?)\s/)||navigator.userAgent.match(/Chrome\/(\d+)/);v.safari="Apple Computer, Inc."==navigator.vendor&&(Qb&&Qb[1]<4||"iP"==navigator.platform.slice(0,2))||"Google Inc."==navigator.vendor&&Qb&&Qb[1]<8?function(){var a=this.rect(-99,-99,this.width+99,this.height+99).attr({stroke:"none"});setTimeout(function(){a.remove()})}:mb;for(var Rb=function(){this.returnValue=!1},Sb=function(){return this.originalEvent.preventDefault()},Tb=function(){this.cancelBubble=!0},Ub=function(){return this.originalEvent.stopPropagation()},Vb=function(a){var b=A.doc.documentElement.scrollTop||A.doc.body.scrollTop,c=A.doc.documentElement.scrollLeft||A.doc.body.scrollLeft;return{x:a.clientX+c,y:a.clientY+b}},Wb=function(){return A.doc.addEventListener?function(a,b,c,d){var e=function(a){var b=Vb(a);return c.call(d,a,b.x,b.y)};if(a.addEventListener(b,e,!1),F&&L[b]){var f=function(b){for(var e=Vb(b),f=b,g=0,h=b.targetTouches&&b.targetTouches.length;h>g;g++)if(b.targetTouches[g].target==a){b=b.targetTouches[g],b.originalEvent=f,b.preventDefault=Sb,b.stopPropagation=Ub;break}return c.call(d,b,e.x,e.y)};a.addEventListener(L[b],f,!1)}return function(){return a.removeEventListener(b,e,!1),F&&L[b]&&a.removeEventListener(L[b],e,!1),!0}}:A.doc.attachEvent?function(a,b,c,d){var e=function(a){a=a||A.win.event;var b=A.doc.documentElement.scrollTop||A.doc.body.scrollTop,e=A.doc.documentElement.scrollLeft||A.doc.body.scrollLeft,f=a.clientX+e,g=a.clientY+b;return a.preventDefault=a.preventDefault||Rb,a.stopPropagation=a.stopPropagation||Tb,c.call(d,a,f,g)};a.attachEvent("on"+b,e);var f=function(){return a.detachEvent("on"+b,e),!0};return f}:void 0}(),Xb=[],Yb=function(a){for(var c,d=a.clientX,e=a.clientY,f=A.doc.documentElement.scrollTop||A.doc.body.scrollTop,g=A.doc.documentElement.scrollLeft||A.doc.body.scrollLeft,h=Xb.length;h--;){if(c=Xb[h],F&&a.touches){for(var i,j=a.touches.length;j--;)if(i=a.touches[j],i.identifier==c.el._drag.id){d=i.clientX,e=i.clientY,(a.originalEvent?a.originalEvent:a).preventDefault();break}}else a.preventDefault();var k,l=c.el.node,m=l.nextSibling,n=l.parentNode,o=l.style.display;A.win.opera&&n.removeChild(l),l.style.display="none",k=c.el.paper.getElementByPoint(d,e),l.style.display=o,A.win.opera&&(m?n.insertBefore(l,m):n.appendChild(l)),k&&b("raphael.drag.over."+c.el.id,c.el,k),d+=g,e+=f,b("raphael.drag.move."+c.el.id,c.move_scope||c.el,d-c.el._drag.x,e-c.el._drag.y,d,e,a)}},Zb=function(a){c.unmousemove(Yb).unmouseup(Zb);for(var d,e=Xb.length;e--;)d=Xb[e],d.el._drag={},b("raphael.drag.end."+d.el.id,d.end_scope||d.start_scope||d.move_scope||d.el,a);Xb=[]},$b=c.el={},_b=K.length;_b--;)!function(a){c[a]=$b[a]=function(b,d){return c.is(b,"function")&&(this.events=this.events||[],this.events.push({name:a,f:b,unbind:Wb(this.shape||this.node||A.doc,a,b,d||this)})),this},c["un"+a]=$b["un"+a]=function(b){for(var d=this.events||[],e=d.length;e--;)d[e].name!=a||!c.is(b,"undefined")&&d[e].f!=b||(d[e].unbind(),d.splice(e,1),!d.length&&delete this.events);return this}}(K[_b]);$b.data=function(a,d){var e=kb[this.id]=kb[this.id]||{};if(0==arguments.length)return e;if(1==arguments.length){if(c.is(a,"object")){for(var f in a)a[z](f)&&this.data(f,a[f]);return this}return b("raphael.data.get."+this.id,this,e[a],a),e[a]}return e[a]=d,b("raphael.data.set."+this.id,this,d,a),this},$b.removeData=function(a){return null==a?kb[this.id]={}:kb[this.id]&&delete kb[this.id][a],this},$b.getData=function(){return d(kb[this.id]||{})},$b.hover=function(a,b,c,d){return this.mouseover(a,c).mouseout(b,d||c)},$b.unhover=function(a,b){return this.unmouseover(a).unmouseout(b)};var ac=[];$b.drag=function(a,d,e,f,g,h){function i(i){(i.originalEvent||i).preventDefault();var j=i.clientX,k=i.clientY,l=A.doc.documentElement.scrollTop||A.doc.body.scrollTop,m=A.doc.documentElement.scrollLeft||A.doc.body.scrollLeft;if(this._drag.id=i.identifier,F&&i.touches)for(var n,o=i.touches.length;o--;)if(n=i.touches[o],this._drag.id=n.identifier,n.identifier==this._drag.id){j=n.clientX,k=n.clientY;break}this._drag.x=j+m,this._drag.y=k+l,!Xb.length&&c.mousemove(Yb).mouseup(Zb),Xb.push({el:this,move_scope:f,start_scope:g,end_scope:h}),d&&b.on("raphael.drag.start."+this.id,d),a&&b.on("raphael.drag.move."+this.id,a),e&&b.on("raphael.drag.end."+this.id,e),b("raphael.drag.start."+this.id,g||f||this,i.clientX+m,i.clientY+l,i)}return this._drag={},ac.push({el:this,start:i}),this.mousedown(i),this},$b.onDragOver=function(a){a?b.on("raphael.drag.over."+this.id,a):b.unbind("raphael.drag.over."+this.id)},$b.undrag=function(){for(var a=ac.length;a--;)ac[a].el==this&&(this.unmousedown(ac[a].start),ac.splice(a,1),b.unbind("raphael.drag.*."+this.id));!ac.length&&c.unmousemove(Yb).unmouseup(Zb),Xb=[]},v.circle=function(a,b,d){var e=c._engine.circle(this,a||0,b||0,d||0);return this.__set__&&this.__set__.push(e),e},v.rect=function(a,b,d,e,f){var g=c._engine.rect(this,a||0,b||0,d||0,e||0,f||0);return this.__set__&&this.__set__.push(g),g},v.ellipse=function(a,b,d,e){var f=c._engine.ellipse(this,a||0,b||0,d||0,e||0);return this.__set__&&this.__set__.push(f),f},v.path=function(a){a&&!c.is(a,U)&&!c.is(a[0],V)&&(a+=G);var b=c._engine.path(c.format[D](c,arguments),this);return this.__set__&&this.__set__.push(b),b},v.image=function(a,b,d,e,f){var g=c._engine.image(this,a||"about:blank",b||0,d||0,e||0,f||0);return this.__set__&&this.__set__.push(g),g},v.text=function(a,b,d){var e=c._engine.text(this,a||0,b||0,I(d));return this.__set__&&this.__set__.push(e),e},v.set=function(a){!c.is(a,"array")&&(a=Array.prototype.splice.call(arguments,0,arguments.length));var b=new mc(a);return this.__set__&&this.__set__.push(b),b.paper=this,b.type="set",b},v.setStart=function(a){this.__set__=a||this.set()},v.setFinish=function(){var a=this.__set__;return delete this.__set__,a},v.setSize=function(a,b){return c._engine.setSize.call(this,a,b)},v.setViewBox=function(a,b,d,e,f){return c._engine.setViewBox.call(this,a,b,d,e,f)},v.top=v.bottom=null,v.raphael=c;var bc=function(a){var b=a.getBoundingClientRect(),c=a.ownerDocument,d=c.body,e=c.documentElement,f=e.clientTop||d.clientTop||0,g=e.clientLeft||d.clientLeft||0,h=b.top+(A.win.pageYOffset||e.scrollTop||d.scrollTop)-f,i=b.left+(A.win.pageXOffset||e.scrollLeft||d.scrollLeft)-g;return{y:h,x:i}};v.getElementByPoint=function(a,b){var c=this,d=c.canvas,e=A.doc.elementFromPoint(a,b);if(A.win.opera&&"svg"==e.tagName){var f=bc(d),g=d.createSVGRect();g.x=a-f.x,g.y=b-f.y,g.width=g.height=1;var h=d.getIntersectionList(g,null);h.length&&(e=h[h.length-1])}if(!e)return null;for(;e.parentNode&&e!=d.parentNode&&!e.raphael;)e=e.parentNode;return e==c.canvas.parentNode&&(e=d),e=e&&e.raphael?c.getById(e.raphaelid):null},v.getElementsByBBox=function(a){var b=this.set();return this.forEach(function(d){c.isBBoxIntersect(d.getBBox(),a)&&b.push(d)}),b},v.getById=function(a){for(var b=this.bottom;b;){if(b.id==a)return b;b=b.next}return null},v.forEach=function(a,b){for(var c=this.bottom;c;){if(a.call(b,c)===!1)return this;c=c.next}return this},v.getElementsByPoint=function(a,b){var c=this.set();return this.forEach(function(d){d.isPointInside(a,b)&&c.push(d)}),c},$b.isPointInside=function(a,b){var d=this.realPath=qb[this.type](this);return this.attr("transform")&&this.attr("transform").length&&(d=c.transformPath(d,this.attr("transform"))),c.isPointInsidePath(d,a,b)},$b.getBBox=function(a){if(this.removed)return{};var b=this._;return a?((b.dirty||!b.bboxwt)&&(this.realPath=qb[this.type](this),b.bboxwt=Bb(this.realPath),b.bboxwt.toString=p,b.dirty=0),b.bboxwt):((b.dirty||b.dirtyT||!b.bbox)&&((b.dirty||!this.realPath)&&(b.bboxwt=0,this.realPath=qb[this.type](this)),b.bbox=Bb(rb(this.realPath,this.matrix)),b.bbox.toString=p,b.dirty=b.dirtyT=0),b.bbox)},$b.clone=function(){if(this.removed)return null;var a=this.paper[this.type]().attr(this.attr());return this.__set__&&this.__set__.push(a),a},$b.glow=function(a){if("text"==this.type)return null;a=a||{};var b={width:(a.width||10)+(+this.attr("stroke-width")||1),fill:a.fill||!1,opacity:a.opacity||.5,offsetx:a.offsetx||0,offsety:a.offsety||0,color:a.color||"#000"},c=b.width/2,d=this.paper,e=d.set(),f=this.realPath||qb[this.type](this);f=this.matrix?rb(f,this.matrix):f;for(var g=1;c+1>g;g++)e.push(d.path(f).attr({stroke:b.color,fill:b.fill?b.color:"none","stroke-linejoin":"round","stroke-linecap":"round","stroke-width":+(b.width/c*g).toFixed(3),opacity:+(b.opacity/c).toFixed(3)}));return e.insertBefore(this).translate(b.offsetx,b.offsety)};var cc=function(a,b,d,e,f,g,h,i,l){return null==l?j(a,b,d,e,f,g,h,i):c.findDotsAtSegment(a,b,d,e,f,g,h,i,k(a,b,d,e,f,g,h,i,l))},dc=function(a,b){return function(d,e,f){d=Kb(d);for(var g,h,i,j,k,l="",m={},n=0,o=0,p=d.length;p>o;o++){if(i=d[o],"M"==i[0])g=+i[1],h=+i[2];else{if(j=cc(g,h,i[1],i[2],i[3],i[4],i[5],i[6]),n+j>e){if(b&&!m.start){if(k=cc(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n),l+=["C"+k.start.x,k.start.y,k.m.x,k.m.y,k.x,k.y],f)return l;m.start=l,l=["M"+k.x,k.y+"C"+k.n.x,k.n.y,k.end.x,k.end.y,i[5],i[6]].join(),n+=j,g=+i[5],h=+i[6];continue}if(!a&&!b)return k=cc(g,h,i[1],i[2],i[3],i[4],i[5],i[6],e-n),{x:k.x,y:k.y,alpha:k.alpha}}n+=j,g=+i[5],h=+i[6]}l+=i.shift()+i}return m.end=l,k=a?n:b?m:c.findDotsAtSegment(g,h,i[0],i[1],i[2],i[3],i[4],i[5],1),k.alpha&&(k={x:k.x,y:k.y,alpha:k.alpha}),k}},ec=dc(1),fc=dc(),gc=dc(0,1);c.getTotalLength=ec,c.getPointAtLength=fc,c.getSubpath=function(a,b,c){if(this.getTotalLength(a)-c<1e-6)return gc(a,b).end;var d=gc(a,c,1);return b?gc(d,b).end:d},$b.getTotalLength=function(){var a=this.getPath();if(a)return this.node.getTotalLength?this.node.getTotalLength():ec(a)},$b.getPointAtLength=function(a){var b=this.getPath();if(b)return fc(b,a)},$b.getPath=function(){var a,b=c._getPath[this.type];if("text"!=this.type&&"set"!=this.type)return b&&(a=b(this)),a},$b.getSubpath=function(a,b){var d=this.getPath();if(d)return c.getSubpath(d,a,b)};var hc=c.easing_formulas={linear:function(a){return a},"<":function(a){return R(a,1.7)},">":function(a){return R(a,.48)},"<>":function(a){var b=.48-a/1.04,c=N.sqrt(.1734+b*b),d=c-b,e=R(Q(d),1/3)*(0>d?-1:1),f=-c-b,g=R(Q(f),1/3)*(0>f?-1:1),h=e+g+.5;return 3*(1-h)*h*h+h*h*h},backIn:function(a){var b=1.70158;return a*a*((b+1)*a-b)},backOut:function(a){a-=1;var b=1.70158;return a*a*((b+1)*a+b)+1},elastic:function(a){return a==!!a?a:R(2,-10*a)*N.sin((a-.075)*2*S/.3)+1},bounce:function(a){var b,c=7.5625,d=2.75;return 1/d>a?b=c*a*a:2/d>a?(a-=1.5/d,b=c*a*a+.75):2.5/d>a?(a-=2.25/d,b=c*a*a+.9375):(a-=2.625/d,b=c*a*a+.984375),b}};hc.easeIn=hc["ease-in"]=hc["<"],hc.easeOut=hc["ease-out"]=hc[">"],hc.easeInOut=hc["ease-in-out"]=hc["<>"],hc["back-in"]=hc.backIn,hc["back-out"]=hc.backOut;var ic=[],jc=a.requestAnimationFrame||a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame||a.msRequestAnimationFrame||function(a){setTimeout(a,16)},kc=function(){for(var a=+new Date,d=0;d<ic.length;d++){var e=ic[d];if(!e.el.removed&&!e.paused){var f,g,h=a-e.start,i=e.ms,j=e.easing,k=e.from,l=e.diff,m=e.to,n=(e.t,e.el),o={},p={};if(e.initstatus?(h=(e.initstatus*e.anim.top-e.prev)/(e.percent-e.prev)*i,e.status=e.initstatus,delete e.initstatus,e.stop&&ic.splice(d--,1)):e.status=(e.prev+(e.percent-e.prev)*(h/i))/e.anim.top,!(0>h))if(i>h){var q=j(h/i);for(var r in k)if(k[z](r)){switch(db[r]){case T:f=+k[r]+q*i*l[r];break;case"colour":f="rgb("+[lc($(k[r].r+q*i*l[r].r)),lc($(k[r].g+q*i*l[r].g)),lc($(k[r].b+q*i*l[r].b))].join(",")+")";break;case"path":f=[];for(var t=0,u=k[r].length;u>t;t++){f[t]=[k[r][t][0]];for(var v=1,w=k[r][t].length;w>v;v++)f[t][v]=+k[r][t][v]+q*i*l[r][t][v];f[t]=f[t].join(H)}f=f.join(H);break;case"transform":if(l[r].real)for(f=[],t=0,u=k[r].length;u>t;t++)for(f[t]=[k[r][t][0]],v=1,w=k[r][t].length;w>v;v++)f[t][v]=k[r][t][v]+q*i*l[r][t][v];else{var x=function(a){return+k[r][a]+q*i*l[r][a]};f=[["m",x(0),x(1),x(2),x(3),x(4),x(5)]]}break;case"csv":if("clip-rect"==r)for(f=[],t=4;t--;)f[t]=+k[r][t]+q*i*l[r][t];break;default:var y=[][E](k[r]);for(f=[],t=n.paper.customAttributes[r].length;t--;)f[t]=+y[t]+q*i*l[r][t]}o[r]=f}n.attr(o),function(a,c,d){setTimeout(function(){b("raphael.anim.frame."+a,c,d)})}(n.id,n,e.anim)}else{if(function(a,d,e){setTimeout(function(){b("raphael.anim.frame."+d.id,d,e),b("raphael.anim.finish."+d.id,d,e),c.is(a,"function")&&a.call(d)})}(e.callback,n,e.anim),n.attr(m),ic.splice(d--,1),e.repeat>1&&!e.next){for(g in m)m[z](g)&&(p[g]=e.totalOrigin[g]);e.el.attr(p),s(e.anim,e.el,e.anim.percents[0],null,e.totalOrigin,e.repeat-1)}e.next&&!e.stop&&s(e.anim,e.el,e.next,null,e.totalOrigin,e.repeat)}}}c.svg&&n&&n.paper&&n.paper.safari(),ic.length&&jc(kc)},lc=function(a){return a>255?255:0>a?0:a};$b.animateWith=function(a,b,d,e,f,g){var h=this;if(h.removed)return g&&g.call(h),h;var i=d instanceof r?d:c.animation(d,e,f,g);s(i,h,i.percents[0],null,h.attr());for(var j=0,k=ic.length;k>j;j++)if(ic[j].anim==b&&ic[j].el==a){ic[k-1].start=ic[j].start;break}return h},$b.onAnimation=function(a){return a?b.on("raphael.anim.frame."+this.id,a):b.unbind("raphael.anim.frame."+this.id),this},r.prototype.delay=function(a){var b=new r(this.anim,this.ms);return b.times=this.times,b.del=+a||0,b},r.prototype.repeat=function(a){var b=new r(this.anim,this.ms);return b.del=this.del,b.times=N.floor(O(a,0))||1,b},c.animation=function(a,b,d,e){if(a instanceof r)return a;(c.is(d,"function")||!d)&&(e=e||d||null,d=null),a=Object(a),b=+b||0;var f,g,h={};for(g in a)a[z](g)&&_(g)!=g&&_(g)+"%"!=g&&(f=!0,h[g]=a[g]);return f?(d&&(h.easing=d),e&&(h.callback=e),new r({100:h},b)):new r(a,b)},$b.animate=function(a,b,d,e){var f=this;if(f.removed)return e&&e.call(f),f;var g=a instanceof r?a:c.animation(a,b,d,e);return s(g,f,g.percents[0],null,f.attr()),f},$b.setTime=function(a,b){return a&&null!=b&&this.status(a,P(b,a.ms)/a.ms),this},$b.status=function(a,b){var c,d,e=[],f=0;if(null!=b)return s(a,this,-1,P(b,1)),this;for(c=ic.length;c>f;f++)if(d=ic[f],d.el.id==this.id&&(!a||d.anim==a)){if(a)return d.status;e.push({anim:d.anim,status:d.status})}return a?0:e},$b.pause=function(a){for(var c=0;c<ic.length;c++)ic[c].el.id!=this.id||a&&ic[c].anim!=a||b("raphael.anim.pause."+this.id,this,ic[c].anim)!==!1&&(ic[c].paused=!0);return this},$b.resume=function(a){for(var c=0;c<ic.length;c++)if(ic[c].el.id==this.id&&(!a||ic[c].anim==a)){var d=ic[c];b("raphael.anim.resume."+this.id,this,d.anim)!==!1&&(delete d.paused,this.status(d.anim,d.status))}return this},$b.stop=function(a){for(var c=0;c<ic.length;c++)ic[c].el.id!=this.id||a&&ic[c].anim!=a||b("raphael.anim.stop."+this.id,this,ic[c].anim)!==!1&&ic.splice(c--,1);return this},b.on("raphael.remove",t),b.on("raphael.clear",t),$b.toString=function(){return"Raphaël’s object"};var mc=function(a){if(this.items=[],this.length=0,this.type="set",a)for(var b=0,c=a.length;c>b;b++)!a[b]||a[b].constructor!=$b.constructor&&a[b].constructor!=mc||(this[this.items.length]=this.items[this.items.length]=a[b],this.length++)},nc=mc.prototype;nc.push=function(){for(var a,b,c=0,d=arguments.length;d>c;c++)a=arguments[c],!a||a.constructor!=$b.constructor&&a.constructor!=mc||(b=this.items.length,this[b]=this.items[b]=a,this.length++);return this},nc.pop=function(){return this.length&&delete this[this.length--],this.items.pop()},nc.forEach=function(a,b){for(var c=0,d=this.items.length;d>c;c++)if(a.call(b,this.items[c],c)===!1)return this;return this};for(var oc in $b)$b[z](oc)&&(nc[oc]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a][D](c,b)})}}(oc));return nc.attr=function(a,b){if(a&&c.is(a,V)&&c.is(a[0],"object"))for(var d=0,e=a.length;e>d;d++)this.items[d].attr(a[d]);else for(var f=0,g=this.items.length;g>f;f++)this.items[f].attr(a,b);return this},nc.clear=function(){for(;this.length;)this.pop()},nc.splice=function(a,b){a=0>a?O(this.length+a,0):a,b=O(0,P(this.length-a,b));var c,d=[],e=[],f=[];for(c=2;c<arguments.length;c++)f.push(arguments[c]);for(c=0;b>c;c++)e.push(this[a+c]);for(;c<this.length-a;c++)d.push(this[a+c]);var g=f.length;for(c=0;c<g+d.length;c++)this.items[a+c]=this[a+c]=g>c?f[c]:d[c-g];for(c=this.items.length=this.length-=b-g;this[c];)delete this[c++];return new mc(e)},nc.exclude=function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]==a)return this.splice(b,1),!0},nc.animate=function(a,b,d,e){(c.is(d,"function")||!d)&&(e=d||null);var f,g,h=this.items.length,i=h,j=this;if(!h)return this;e&&(g=function(){!--h&&e.call(j)}),d=c.is(d,U)?d:g;var k=c.animation(a,b,d,g);for(f=this.items[--i].animate(k);i--;)this.items[i]&&!this.items[i].removed&&this.items[i].animateWith(f,k,k),this.items[i]&&!this.items[i].removed||h--;return this},nc.insertAfter=function(a){for(var b=this.items.length;b--;)this.items[b].insertAfter(a);return this},nc.getBBox=function(){for(var a=[],b=[],c=[],d=[],e=this.items.length;e--;)if(!this.items[e].removed){var f=this.items[e].getBBox();a.push(f.x),b.push(f.y),c.push(f.x+f.width),d.push(f.y+f.height)}return a=P[D](0,a),b=P[D](0,b),c=O[D](0,c),d=O[D](0,d),{x:a,y:b,x2:c,y2:d,width:c-a,height:d-b}},nc.clone=function(a){a=this.paper.set();for(var b=0,c=this.items.length;c>b;b++)a.push(this.items[b].clone());return a},nc.toString=function(){return"Raphaël‘s set"},nc.glow=function(a){var b=this.paper.set();return this.forEach(function(c){var d=c.glow(a);null!=d&&d.forEach(function(a){b.push(a)})}),b},nc.isPointInside=function(a,b){var c=!1;return this.forEach(function(d){return d.isPointInside(a,b)?(console.log("runned"),c=!0,!1):void 0}),c},c.registerFont=function(a){if(!a.face)return a;this.fonts=this.fonts||{};var b={w:a.w,face:{},glyphs:{}},c=a.face["font-family"];for(var d in a.face)a.face[z](d)&&(b.face[d]=a.face[d]);if(this.fonts[c]?this.fonts[c].push(b):this.fonts[c]=[b],!a.svg){b.face["units-per-em"]=ab(a.face["units-per-em"],10);for(var e in a.glyphs)if(a.glyphs[z](e)){var f=a.glyphs[e];if(b.glyphs[e]={w:f.w,k:{},d:f.d&&"M"+f.d.replace(/[mlcxtrv]/g,function(a){return{l:"L",c:"C",x:"z",t:"m",r:"l",v:"c"}[a]||"M"})+"z"},f.k)for(var g in f.k)f[z](g)&&(b.glyphs[e].k[g]=f.k[g])}}return a},v.getFont=function(a,b,d,e){if(e=e||"normal",d=d||"normal",b=+b||{normal:400,bold:700,lighter:300,bolder:800}[b]||400,c.fonts){var f=c.fonts[a];if(!f){var g=new RegExp("(^|\\s)"+a.replace(/[^\w\d\s+!~.:_-]/g,G)+"(\\s|$)","i");for(var h in c.fonts)if(c.fonts[z](h)&&g.test(h)){f=c.fonts[h];break}}var i;if(f)for(var j=0,k=f.length;k>j&&(i=f[j],i.face["font-weight"]!=b||i.face["font-style"]!=d&&i.face["font-style"]||i.face["font-stretch"]!=e);j++);return i}},v.print=function(a,b,d,e,f,g,h,i){g=g||"middle",h=O(P(h||0,1),-1),i=O(P(i||1,3),1);var j,k=I(d)[J](G),l=0,m=0,n=G;if(c.is(e,"string")&&(e=this.getFont(e)),e){j=(f||16)/e.face["units-per-em"];for(var o=e.face.bbox[J](w),p=+o[0],q=o[3]-o[1],r=0,s=+o[1]+("baseline"==g?q+ +e.face.descent:q/2),t=0,u=k.length;u>t;t++){if("\n"==k[t])l=0,x=0,m=0,r+=q*i;else{var v=m&&e.glyphs[k[t-1]]||{},x=e.glyphs[k[t]];l+=m?(v.w||e.w)+(v.k&&v.k[k[t]]||0)+e.w*h:0,m=1}x&&x.d&&(n+=c.transformPath(x.d,["t",l*j,r*j,"s",j,j,p,s,"t",(a-p)/j,(b-s)/j]))}}return this.path(n).attr({fill:"#000",stroke:"none"})},v.add=function(a){if(c.is(a,"array"))for(var b,d=this.set(),e=0,f=a.length;f>e;e++)b=a[e]||{},x[z](b.type)&&d.push(this[b.type]().attr(b));return d},c.format=function(a,b){var d=c.is(b,V)?[0][E](b):arguments;return a&&c.is(a,U)&&d.length-1&&(a=a.replace(y,function(a,b){return null==d[++b]?G:d[b]})),a||G},c.fullfill=function(){var a=/\{([^\}]+)\}/g,b=/(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g,c=function(a,c,d){var e=d;return c.replace(b,function(a,b,c,d,f){b=b||d,e&&(b in e&&(e=e[b]),"function"==typeof e&&f&&(e=e()))}),e=(null==e||e==d?a:e)+""};return function(b,d){return String(b).replace(a,function(a,b){return c(a,b,d)})}}(),c.ninja=function(){return B.was?A.win.Raphael=B.is:delete Raphael,c},c.st=nc,function(a,b,d){function e(){/in/.test(a.readyState)?setTimeout(e,9):c.eve("raphael.DOMload")}null==a.readyState&&a.addEventListener&&(a.addEventListener(b,d=function(){a.removeEventListener(b,d,!1),a.readyState="complete"},!1),a.readyState="loading"),e()}(document,"DOMContentLoaded"),b.on("raphael.DOMload",function(){u=!0}),function(){if(c.svg){var a="hasOwnProperty",b=String,d=parseFloat,e=parseInt,f=Math,g=f.max,h=f.abs,i=f.pow,j=/[, ]+/,k=c.eve,l="",m=" ",n="http://www.w3.org/1999/xlink",o={block:"M5,0 0,2.5 5,5z",classic:"M5,0 0,2.5 5,5 3.5,3 3.5,2z",diamond:"M2.5,0 5,2.5 2.5,5 0,2.5z",open:"M6,1 1,3.5 6,6",oval:"M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"},p={};c.toString=function(){return"Your browser supports SVG.\nYou are running Raphaël "+this.version};var q=function(d,e){if(e){"string"==typeof d&&(d=q(d));for(var f in e)e[a](f)&&("xlink:"==f.substring(0,6)?d.setAttributeNS(n,f.substring(6),b(e[f])):d.setAttribute(f,b(e[f])))}else d=c._g.doc.createElementNS("http://www.w3.org/2000/svg",d),d.style&&(d.style.webkitTapHighlightColor="rgba(0,0,0,0)");return d},r=function(a,e){var j="linear",k=a.id+e,m=.5,n=.5,o=a.node,p=a.paper,r=o.style,s=c._g.doc.getElementById(k);if(!s){if(e=b(e).replace(c._radial_gradient,function(a,b,c){if(j="radial",b&&c){m=d(b),n=d(c);var e=2*(n>.5)-1;i(m-.5,2)+i(n-.5,2)>.25&&(n=f.sqrt(.25-i(m-.5,2))*e+.5)&&.5!=n&&(n=n.toFixed(5)-1e-5*e)}return l}),e=e.split(/\s*\-\s*/),"linear"==j){var t=e.shift();if(t=-d(t),isNaN(t))return null;var u=[0,0,f.cos(c.rad(t)),f.sin(c.rad(t))],v=1/(g(h(u[2]),h(u[3]))||1);u[2]*=v,u[3]*=v,u[2]<0&&(u[0]=-u[2],u[2]=0),u[3]<0&&(u[1]=-u[3],u[3]=0)}var w=c._parseDots(e);if(!w)return null;if(k=k.replace(/[\(\)\s,\xb0#]/g,"_"),a.gradient&&k!=a.gradient.id&&(p.defs.removeChild(a.gradient),delete a.gradient),!a.gradient){s=q(j+"Gradient",{id:k}),a.gradient=s,q(s,"radial"==j?{fx:m,fy:n}:{x1:u[0],y1:u[1],x2:u[2],y2:u[3],gradientTransform:a.matrix.invert()}),p.defs.appendChild(s);for(var x=0,y=w.length;y>x;x++)s.appendChild(q("stop",{offset:w[x].offset?w[x].offset:x?"100%":"0%","stop-color":w[x].color||"#fff"}))}}return q(o,{fill:"url(#"+k+")",opacity:1,"fill-opacity":1}),r.fill=l,r.opacity=1,r.fillOpacity=1,1},s=function(a){var b=a.getBBox(1);q(a.pattern,{patternTransform:a.matrix.invert()+" translate("+b.x+","+b.y+")"})},t=function(d,e,f){if("path"==d.type){for(var g,h,i,j,k,m=b(e).toLowerCase().split("-"),n=d.paper,r=f?"end":"start",s=d.node,t=d.attrs,u=t["stroke-width"],v=m.length,w="classic",x=3,y=3,z=5;v--;)switch(m[v]){case"block":case"classic":case"oval":case"diamond":case"open":case"none":w=m[v];break;case"wide":y=5;break;case"narrow":y=2;break;case"long":x=5;break;case"short":x=2}if("open"==w?(x+=2,y+=2,z+=2,i=1,j=f?4:1,k={fill:"none",stroke:t.stroke}):(j=i=x/2,k={fill:t.stroke,stroke:"none"}),d._.arrows?f?(d._.arrows.endPath&&p[d._.arrows.endPath]--,d._.arrows.endMarker&&p[d._.arrows.endMarker]--):(d._.arrows.startPath&&p[d._.arrows.startPath]--,d._.arrows.startMarker&&p[d._.arrows.startMarker]--):d._.arrows={},"none"!=w){var A="raphael-marker-"+w,B="raphael-marker-"+r+w+x+y;c._g.doc.getElementById(A)?p[A]++:(n.defs.appendChild(q(q("path"),{"stroke-linecap":"round",d:o[w],id:A})),p[A]=1);var C,D=c._g.doc.getElementById(B);D?(p[B]++,C=D.getElementsByTagName("use")[0]):(D=q(q("marker"),{id:B,markerHeight:y,markerWidth:x,orient:"auto",refX:j,refY:y/2}),C=q(q("use"),{"xlink:href":"#"+A,transform:(f?"rotate(180 "+x/2+" "+y/2+") ":l)+"scale("+x/z+","+y/z+")","stroke-width":(1/((x/z+y/z)/2)).toFixed(4)}),D.appendChild(C),n.defs.appendChild(D),p[B]=1),q(C,k);var E=i*("diamond"!=w&&"oval"!=w);f?(g=d._.arrows.startdx*u||0,h=c.getTotalLength(t.path)-E*u):(g=E*u,h=c.getTotalLength(t.path)-(d._.arrows.enddx*u||0)),k={},k["marker-"+r]="url(#"+B+")",(h||g)&&(k.d=c.getSubpath(t.path,g,h)),q(s,k),d._.arrows[r+"Path"]=A,d._.arrows[r+"Marker"]=B,d._.arrows[r+"dx"]=E,d._.arrows[r+"Type"]=w,d._.arrows[r+"String"]=e}else f?(g=d._.arrows.startdx*u||0,h=c.getTotalLength(t.path)-g):(g=0,h=c.getTotalLength(t.path)-(d._.arrows.enddx*u||0)),d._.arrows[r+"Path"]&&q(s,{d:c.getSubpath(t.path,g,h)}),delete d._.arrows[r+"Path"],delete d._.arrows[r+"Marker"],delete d._.arrows[r+"dx"],delete d._.arrows[r+"Type"],delete d._.arrows[r+"String"];for(k in p)if(p[a](k)&&!p[k]){var F=c._g.doc.getElementById(k);F&&F.parentNode.removeChild(F)}}},u={"":[0],none:[0],"-":[3,1],".":[1,1],"-.":[3,1,1,1],"-..":[3,1,1,1,1,1],". ":[1,3],"- ":[4,3],"--":[8,3],"- .":[4,3,1,3],"--.":[8,3,1,3],"--..":[8,3,1,3,1,3]},v=function(a,c,d){if(c=u[b(c).toLowerCase()]){for(var e=a.attrs["stroke-width"]||"1",f={round:e,square:e,butt:0}[a.attrs["stroke-linecap"]||d["stroke-linecap"]]||0,g=[],h=c.length;h--;)g[h]=c[h]*e+(h%2?1:-1)*f;q(a.node,{"stroke-dasharray":g.join(",")})}},w=function(d,f){var i=d.node,k=d.attrs,m=i.style.visibility;i.style.visibility="hidden";for(var o in f)if(f[a](o)){if(!c._availableAttrs[a](o))continue;var p=f[o];switch(k[o]=p,o){case"blur":d.blur(p);break;case"href":case"title":var u=q("title"),w=c._g.doc.createTextNode(p);u.appendChild(w),i.appendChild(u);break;case"target":var x=i.parentNode;if("a"!=x.tagName.toLowerCase()){var u=q("a");x.insertBefore(u,i),u.appendChild(i),x=u}"target"==o?x.setAttributeNS(n,"show","blank"==p?"new":p):x.setAttributeNS(n,o,p);break;case"cursor":i.style.cursor=p;break;case"transform":d.transform(p);break;case"arrow-start":t(d,p);break;case"arrow-end":t(d,p,1);break;case"clip-rect":var z=b(p).split(j);if(4==z.length){d.clip&&d.clip.parentNode.parentNode.removeChild(d.clip.parentNode);var A=q("clipPath"),B=q("rect");A.id=c.createUUID(),q(B,{x:z[0],y:z[1],width:z[2],height:z[3]}),A.appendChild(B),d.paper.defs.appendChild(A),q(i,{"clip-path":"url(#"+A.id+")"}),d.clip=B}if(!p){var C=i.getAttribute("clip-path");if(C){var D=c._g.doc.getElementById(C.replace(/(^url\(#|\)$)/g,l));D&&D.parentNode.removeChild(D),q(i,{"clip-path":l}),delete d.clip}}break;case"path":"path"==d.type&&(q(i,{d:p?k.path=c._pathToAbsolute(p):"M0,0"}),d._.dirty=1,d._.arrows&&("startString"in d._.arrows&&t(d,d._.arrows.startString),"endString"in d._.arrows&&t(d,d._.arrows.endString,1)));break;case"width":if(i.setAttribute(o,p),d._.dirty=1,!k.fx)break;o="x",p=k.x;case"x":k.fx&&(p=-k.x-(k.width||0));case"rx":if("rx"==o&&"rect"==d.type)break;case"cx":i.setAttribute(o,p),d.pattern&&s(d),d._.dirty=1;break;case"height":if(i.setAttribute(o,p),d._.dirty=1,!k.fy)break;o="y",p=k.y;case"y":k.fy&&(p=-k.y-(k.height||0));case"ry":if("ry"==o&&"rect"==d.type)break;case"cy":i.setAttribute(o,p),d.pattern&&s(d),d._.dirty=1;break;case"r":"rect"==d.type?q(i,{rx:p,ry:p}):i.setAttribute(o,p),d._.dirty=1;break;case"src":"image"==d.type&&i.setAttributeNS(n,"href",p);break;case"stroke-width":(1!=d._.sx||1!=d._.sy)&&(p/=g(h(d._.sx),h(d._.sy))||1),d.paper._vbSize&&(p*=d.paper._vbSize),i.setAttribute(o,p),k["stroke-dasharray"]&&v(d,k["stroke-dasharray"],f),d._.arrows&&("startString"in d._.arrows&&t(d,d._.arrows.startString),"endString"in d._.arrows&&t(d,d._.arrows.endString,1));break;case"stroke-dasharray":v(d,p,f);break;case"fill":var E=b(p).match(c._ISURL);if(E){A=q("pattern");var F=q("image");A.id=c.createUUID(),q(A,{x:0,y:0,patternUnits:"userSpaceOnUse",height:1,width:1}),q(F,{x:0,y:0,"xlink:href":E[1]}),A.appendChild(F),function(a){c._preload(E[1],function(){var b=this.offsetWidth,c=this.offsetHeight;q(a,{width:b,height:c}),q(F,{width:b,height:c}),d.paper.safari()})}(A),d.paper.defs.appendChild(A),q(i,{fill:"url(#"+A.id+")"}),d.pattern=A,d.pattern&&s(d);break}var G=c.getRGB(p);if(G.error){if(("circle"==d.type||"ellipse"==d.type||"r"!=b(p).charAt())&&r(d,p)){if("opacity"in k||"fill-opacity"in k){var H=c._g.doc.getElementById(i.getAttribute("fill").replace(/^url\(#|\)$/g,l));if(H){var I=H.getElementsByTagName("stop");q(I[I.length-1],{"stop-opacity":("opacity"in k?k.opacity:1)*("fill-opacity"in k?k["fill-opacity"]:1)})}}k.gradient=p,k.fill="none";break}}else delete f.gradient,delete k.gradient,!c.is(k.opacity,"undefined")&&c.is(f.opacity,"undefined")&&q(i,{opacity:k.opacity}),!c.is(k["fill-opacity"],"undefined")&&c.is(f["fill-opacity"],"undefined")&&q(i,{"fill-opacity":k["fill-opacity"]});G[a]("opacity")&&q(i,{"fill-opacity":G.opacity>1?G.opacity/100:G.opacity});case"stroke":G=c.getRGB(p),i.setAttribute(o,G.hex),"stroke"==o&&G[a]("opacity")&&q(i,{"stroke-opacity":G.opacity>1?G.opacity/100:G.opacity}),"stroke"==o&&d._.arrows&&("startString"in d._.arrows&&t(d,d._.arrows.startString),"endString"in d._.arrows&&t(d,d._.arrows.endString,1));break;case"gradient":("circle"==d.type||"ellipse"==d.type||"r"!=b(p).charAt())&&r(d,p);break;case"opacity":k.gradient&&!k[a]("stroke-opacity")&&q(i,{"stroke-opacity":p>1?p/100:p});case"fill-opacity":if(k.gradient){H=c._g.doc.getElementById(i.getAttribute("fill").replace(/^url\(#|\)$/g,l)),H&&(I=H.getElementsByTagName("stop"),q(I[I.length-1],{"stop-opacity":p}));break}default:"font-size"==o&&(p=e(p,10)+"px");var J=o.replace(/(\-.)/g,function(a){return a.substring(1).toUpperCase()});i.style[J]=p,d._.dirty=1,i.setAttribute(o,p)}}y(d,f),i.style.visibility=m},x=1.2,y=function(d,f){if("text"==d.type&&(f[a]("text")||f[a]("font")||f[a]("font-size")||f[a]("x")||f[a]("y"))){var g=d.attrs,h=d.node,i=h.firstChild?e(c._g.doc.defaultView.getComputedStyle(h.firstChild,l).getPropertyValue("font-size"),10):10;
-if(f[a]("text")){for(g.text=f.text;h.firstChild;)h.removeChild(h.firstChild);for(var j,k=b(f.text).split("\n"),m=[],n=0,o=k.length;o>n;n++)j=q("tspan"),n&&q(j,{dy:i*x,x:g.x}),j.appendChild(c._g.doc.createTextNode(k[n])),h.appendChild(j),m[n]=j}else for(m=h.getElementsByTagName("tspan"),n=0,o=m.length;o>n;n++)n?q(m[n],{dy:i*x,x:g.x}):q(m[0],{dy:0});q(h,{x:g.x,y:g.y}),d._.dirty=1;var p=d._getBBox(),r=g.y-(p.y+p.height/2);r&&c.is(r,"finite")&&q(m[0],{dy:r})}},z=function(a,b){this[0]=this.node=a,a.raphael=!0,this.id=c._oid++,a.raphaelid=this.id,this.matrix=c.matrix(),this.realPath=null,this.paper=b,this.attrs=this.attrs||{},this._={transform:[],sx:1,sy:1,deg:0,dx:0,dy:0,dirty:1},!b.bottom&&(b.bottom=this),this.prev=b.top,b.top&&(b.top.next=this),b.top=this,this.next=null},A=c.el;z.prototype=A,A.constructor=z,c._engine.path=function(a,b){var c=q("path");b.canvas&&b.canvas.appendChild(c);var d=new z(c,b);return d.type="path",w(d,{fill:"none",stroke:"#000",path:a}),d},A.rotate=function(a,c,e){if(this.removed)return this;if(a=b(a).split(j),a.length-1&&(c=d(a[1]),e=d(a[2])),a=d(a[0]),null==e&&(c=e),null==c||null==e){var f=this.getBBox(1);c=f.x+f.width/2,e=f.y+f.height/2}return this.transform(this._.transform.concat([["r",a,c,e]])),this},A.scale=function(a,c,e,f){if(this.removed)return this;if(a=b(a).split(j),a.length-1&&(c=d(a[1]),e=d(a[2]),f=d(a[3])),a=d(a[0]),null==c&&(c=a),null==f&&(e=f),null==e||null==f)var g=this.getBBox(1);return e=null==e?g.x+g.width/2:e,f=null==f?g.y+g.height/2:f,this.transform(this._.transform.concat([["s",a,c,e,f]])),this},A.translate=function(a,c){return this.removed?this:(a=b(a).split(j),a.length-1&&(c=d(a[1])),a=d(a[0])||0,c=+c||0,this.transform(this._.transform.concat([["t",a,c]])),this)},A.transform=function(b){var d=this._;if(null==b)return d.transform;if(c._extractTransform(this,b),this.clip&&q(this.clip,{transform:this.matrix.invert()}),this.pattern&&s(this),this.node&&q(this.node,{transform:this.matrix}),1!=d.sx||1!=d.sy){var e=this.attrs[a]("stroke-width")?this.attrs["stroke-width"]:1;this.attr({"stroke-width":e})}return this},A.hide=function(){return!this.removed&&this.paper.safari(this.node.style.display="none"),this},A.show=function(){return!this.removed&&this.paper.safari(this.node.style.display=""),this},A.remove=function(){if(!this.removed&&this.node.parentNode){var a=this.paper;a.__set__&&a.__set__.exclude(this),k.unbind("raphael.*.*."+this.id),this.gradient&&a.defs.removeChild(this.gradient),c._tear(this,a),"a"==this.node.parentNode.tagName.toLowerCase()?this.node.parentNode.parentNode.removeChild(this.node.parentNode):this.node.parentNode.removeChild(this.node);for(var b in this)this[b]="function"==typeof this[b]?c._removedFactory(b):null;this.removed=!0}},A._getBBox=function(){if("none"==this.node.style.display){this.show();var a=!0}var b={};try{b=this.node.getBBox()}catch(c){}finally{b=b||{}}return a&&this.hide(),b},A.attr=function(b,d){if(this.removed)return this;if(null==b){var e={};for(var f in this.attrs)this.attrs[a](f)&&(e[f]=this.attrs[f]);return e.gradient&&"none"==e.fill&&(e.fill=e.gradient)&&delete e.gradient,e.transform=this._.transform,e}if(null==d&&c.is(b,"string")){if("fill"==b&&"none"==this.attrs.fill&&this.attrs.gradient)return this.attrs.gradient;if("transform"==b)return this._.transform;for(var g=b.split(j),h={},i=0,l=g.length;l>i;i++)b=g[i],h[b]=b in this.attrs?this.attrs[b]:c.is(this.paper.customAttributes[b],"function")?this.paper.customAttributes[b].def:c._availableAttrs[b];return l-1?h:h[g[0]]}if(null==d&&c.is(b,"array")){for(h={},i=0,l=b.length;l>i;i++)h[b[i]]=this.attr(b[i]);return h}if(null!=d){var m={};m[b]=d}else null!=b&&c.is(b,"object")&&(m=b);for(var n in m)k("raphael.attr."+n+"."+this.id,this,m[n]);for(n in this.paper.customAttributes)if(this.paper.customAttributes[a](n)&&m[a](n)&&c.is(this.paper.customAttributes[n],"function")){var o=this.paper.customAttributes[n].apply(this,[].concat(m[n]));this.attrs[n]=m[n];for(var p in o)o[a](p)&&(m[p]=o[p])}return w(this,m),this},A.toFront=function(){if(this.removed)return this;"a"==this.node.parentNode.tagName.toLowerCase()?this.node.parentNode.parentNode.appendChild(this.node.parentNode):this.node.parentNode.appendChild(this.node);var a=this.paper;return a.top!=this&&c._tofront(this,a),this},A.toBack=function(){if(this.removed)return this;var a=this.node.parentNode;return"a"==a.tagName.toLowerCase()?a.parentNode.insertBefore(this.node.parentNode,this.node.parentNode.parentNode.firstChild):a.firstChild!=this.node&&a.insertBefore(this.node,this.node.parentNode.firstChild),c._toback(this,this.paper),this.paper,this},A.insertAfter=function(a){if(this.removed)return this;var b=a.node||a[a.length-1].node;return b.nextSibling?b.parentNode.insertBefore(this.node,b.nextSibling):b.parentNode.appendChild(this.node),c._insertafter(this,a,this.paper),this},A.insertBefore=function(a){if(this.removed)return this;var b=a.node||a[0].node;return b.parentNode.insertBefore(this.node,b),c._insertbefore(this,a,this.paper),this},A.blur=function(a){var b=this;if(0!==+a){var d=q("filter"),e=q("feGaussianBlur");b.attrs.blur=a,d.id=c.createUUID(),q(e,{stdDeviation:+a||1.5}),d.appendChild(e),b.paper.defs.appendChild(d),b._blur=d,q(b.node,{filter:"url(#"+d.id+")"})}else b._blur&&(b._blur.parentNode.removeChild(b._blur),delete b._blur,delete b.attrs.blur),b.node.removeAttribute("filter");return b},c._engine.circle=function(a,b,c,d){var e=q("circle");a.canvas&&a.canvas.appendChild(e);var f=new z(e,a);return f.attrs={cx:b,cy:c,r:d,fill:"none",stroke:"#000"},f.type="circle",q(e,f.attrs),f},c._engine.rect=function(a,b,c,d,e,f){var g=q("rect");a.canvas&&a.canvas.appendChild(g);var h=new z(g,a);return h.attrs={x:b,y:c,width:d,height:e,r:f||0,rx:f||0,ry:f||0,fill:"none",stroke:"#000"},h.type="rect",q(g,h.attrs),h},c._engine.ellipse=function(a,b,c,d,e){var f=q("ellipse");a.canvas&&a.canvas.appendChild(f);var g=new z(f,a);return g.attrs={cx:b,cy:c,rx:d,ry:e,fill:"none",stroke:"#000"},g.type="ellipse",q(f,g.attrs),g},c._engine.image=function(a,b,c,d,e,f){var g=q("image");q(g,{x:c,y:d,width:e,height:f,preserveAspectRatio:"none"}),g.setAttributeNS(n,"href",b),a.canvas&&a.canvas.appendChild(g);var h=new z(g,a);return h.attrs={x:c,y:d,width:e,height:f,src:b},h.type="image",h},c._engine.text=function(a,b,d,e){var f=q("text");a.canvas&&a.canvas.appendChild(f);var g=new z(f,a);return g.attrs={x:b,y:d,"text-anchor":"middle",text:e,font:c._availableAttrs.font,stroke:"none",fill:"#000"},g.type="text",w(g,g.attrs),g},c._engine.setSize=function(a,b){return this.width=a||this.width,this.height=b||this.height,this.canvas.setAttribute("width",this.width),this.canvas.setAttribute("height",this.height),this._viewBox&&this.setViewBox.apply(this,this._viewBox),this},c._engine.create=function(){var a=c._getContainer.apply(0,arguments),b=a&&a.container,d=a.x,e=a.y,f=a.width,g=a.height;if(!b)throw new Error("SVG container not found.");var h,i=q("svg"),j="overflow:hidden;";return d=d||0,e=e||0,f=f||512,g=g||342,q(i,{height:g,version:1.1,width:f,xmlns:"http://www.w3.org/2000/svg"}),1==b?(i.style.cssText=j+"position:absolute;left:"+d+"px;top:"+e+"px",c._g.doc.body.appendChild(i),h=1):(i.style.cssText=j+"position:relative",b.firstChild?b.insertBefore(i,b.firstChild):b.appendChild(i)),b=new c._Paper,b.width=f,b.height=g,b.canvas=i,b.clear(),b._left=b._top=0,h&&(b.renderfix=function(){}),b.renderfix(),b},c._engine.setViewBox=function(a,b,c,d,e){k("raphael.setViewBox",this,this._viewBox,[a,b,c,d,e]);var f,h,i=g(c/this.width,d/this.height),j=this.top,l=e?"meet":"xMinYMin";for(null==a?(this._vbSize&&(i=1),delete this._vbSize,f="0 0 "+this.width+m+this.height):(this._vbSize=i,f=a+m+b+m+c+m+d),q(this.canvas,{viewBox:f,preserveAspectRatio:l});i&&j;)h="stroke-width"in j.attrs?j.attrs["stroke-width"]:1,j.attr({"stroke-width":h}),j._.dirty=1,j._.dirtyT=1,j=j.prev;return this._viewBox=[a,b,c,d,!!e],this},c.prototype.renderfix=function(){var a,b=this.canvas,c=b.style;try{a=b.getScreenCTM()||b.createSVGMatrix()}catch(d){a=b.createSVGMatrix()}var e=-a.e%1,f=-a.f%1;(e||f)&&(e&&(this._left=(this._left+e)%1,c.left=this._left+"px"),f&&(this._top=(this._top+f)%1,c.top=this._top+"px"))},c.prototype.clear=function(){c.eve("raphael.clear",this);for(var a=this.canvas;a.firstChild;)a.removeChild(a.firstChild);this.bottom=this.top=null,(this.desc=q("desc")).appendChild(c._g.doc.createTextNode("Created with Raphaël "+c.version)),a.appendChild(this.desc),a.appendChild(this.defs=q("defs"))},c.prototype.remove=function(){k("raphael.remove",this),this.canvas.parentNode&&this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]="function"==typeof this[a]?c._removedFactory(a):null};var B=c.st;for(var C in A)A[a](C)&&!B[a](C)&&(B[C]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a].apply(c,b)})}}(C))}}(),function(){if(c.vml){var a="hasOwnProperty",b=String,d=parseFloat,e=Math,f=e.round,g=e.max,h=e.min,i=e.abs,j="fill",k=/[, ]+/,l=c.eve,m=" progid:DXImageTransform.Microsoft",n=" ",o="",p={M:"m",L:"l",C:"c",Z:"x",m:"t",l:"r",c:"v",z:"x"},q=/([clmz]),?([^clmz]*)/gi,r=/ progid:\S+Blur\([^\)]+\)/g,s=/-?[^,\s-]+/g,t="position:absolute;left:0;top:0;width:1px;height:1px",u=21600,v={path:1,rect:1,image:1},w={circle:1,ellipse:1},x=function(a){var d=/[ahqstv]/gi,e=c._pathToAbsolute;if(b(a).match(d)&&(e=c._path2curve),d=/[clmz]/g,e==c._pathToAbsolute&&!b(a).match(d)){var g=b(a).replace(q,function(a,b,c){var d=[],e="m"==b.toLowerCase(),g=p[b];return c.replace(s,function(a){e&&2==d.length&&(g+=d+p["m"==b?"l":"L"],d=[]),d.push(f(a*u))}),g+d});return g}var h,i,j=e(a);g=[];for(var k=0,l=j.length;l>k;k++){h=j[k],i=j[k][0].toLowerCase(),"z"==i&&(i="x");for(var m=1,r=h.length;r>m;m++)i+=f(h[m]*u)+(m!=r-1?",":o);g.push(i)}return g.join(n)},y=function(a,b,d){var e=c.matrix();return e.rotate(-a,.5,.5),{dx:e.x(b,d),dy:e.y(b,d)}},z=function(a,b,c,d,e,f){var g=a._,h=a.matrix,k=g.fillpos,l=a.node,m=l.style,o=1,p="",q=u/b,r=u/c;if(m.visibility="hidden",b&&c){if(l.coordsize=i(q)+n+i(r),m.rotation=f*(0>b*c?-1:1),f){var s=y(f,d,e);d=s.dx,e=s.dy}if(0>b&&(p+="x"),0>c&&(p+=" y")&&(o=-1),m.flip=p,l.coordorigin=d*-q+n+e*-r,k||g.fillsize){var t=l.getElementsByTagName(j);t=t&&t[0],l.removeChild(t),k&&(s=y(f,h.x(k[0],k[1]),h.y(k[0],k[1])),t.position=s.dx*o+n+s.dy*o),g.fillsize&&(t.size=g.fillsize[0]*i(b)+n+g.fillsize[1]*i(c)),l.appendChild(t)}m.visibility="visible"}};c.toString=function(){return"Your browser doesn’t support SVG. Falling down to VML.\nYou are running Raphaël "+this.version};var A=function(a,c,d){for(var e=b(c).toLowerCase().split("-"),f=d?"end":"start",g=e.length,h="classic",i="medium",j="medium";g--;)switch(e[g]){case"block":case"classic":case"oval":case"diamond":case"open":case"none":h=e[g];break;case"wide":case"narrow":j=e[g];break;case"long":case"short":i=e[g]}var k=a.node.getElementsByTagName("stroke")[0];k[f+"arrow"]=h,k[f+"arrowlength"]=i,k[f+"arrowwidth"]=j},B=function(e,i){e.attrs=e.attrs||{};var l=e.node,m=e.attrs,p=l.style,q=v[e.type]&&(i.x!=m.x||i.y!=m.y||i.width!=m.width||i.height!=m.height||i.cx!=m.cx||i.cy!=m.cy||i.rx!=m.rx||i.ry!=m.ry||i.r!=m.r),r=w[e.type]&&(m.cx!=i.cx||m.cy!=i.cy||m.r!=i.r||m.rx!=i.rx||m.ry!=i.ry),s=e;for(var t in i)i[a](t)&&(m[t]=i[t]);if(q&&(m.path=c._getPath[e.type](e),e._.dirty=1),i.href&&(l.href=i.href),i.title&&(l.title=i.title),i.target&&(l.target=i.target),i.cursor&&(p.cursor=i.cursor),"blur"in i&&e.blur(i.blur),(i.path&&"path"==e.type||q)&&(l.path=x(~b(m.path).toLowerCase().indexOf("r")?c._pathToAbsolute(m.path):m.path),"image"==e.type&&(e._.fillpos=[m.x,m.y],e._.fillsize=[m.width,m.height],z(e,1,1,0,0,0))),"transform"in i&&e.transform(i.transform),r){var y=+m.cx,B=+m.cy,D=+m.rx||+m.r||0,E=+m.ry||+m.r||0;l.path=c.format("ar{0},{1},{2},{3},{4},{1},{4},{1}x",f((y-D)*u),f((B-E)*u),f((y+D)*u),f((B+E)*u),f(y*u)),e._.dirty=1}if("clip-rect"in i){var G=b(i["clip-rect"]).split(k);if(4==G.length){G[2]=+G[2]+ +G[0],G[3]=+G[3]+ +G[1];var H=l.clipRect||c._g.doc.createElement("div"),I=H.style;I.clip=c.format("rect({1}px {2}px {3}px {0}px)",G),l.clipRect||(I.position="absolute",I.top=0,I.left=0,I.width=e.paper.width+"px",I.height=e.paper.height+"px",l.parentNode.insertBefore(H,l),H.appendChild(l),l.clipRect=H)}i["clip-rect"]||l.clipRect&&(l.clipRect.style.clip="auto")}if(e.textpath){var J=e.textpath.style;i.font&&(J.font=i.font),i["font-family"]&&(J.fontFamily='"'+i["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g,o)+'"'),i["font-size"]&&(J.fontSize=i["font-size"]),i["font-weight"]&&(J.fontWeight=i["font-weight"]),i["font-style"]&&(J.fontStyle=i["font-style"])}if("arrow-start"in i&&A(s,i["arrow-start"]),"arrow-end"in i&&A(s,i["arrow-end"],1),null!=i.opacity||null!=i["stroke-width"]||null!=i.fill||null!=i.src||null!=i.stroke||null!=i["stroke-width"]||null!=i["stroke-opacity"]||null!=i["fill-opacity"]||null!=i["stroke-dasharray"]||null!=i["stroke-miterlimit"]||null!=i["stroke-linejoin"]||null!=i["stroke-linecap"]){var K=l.getElementsByTagName(j),L=!1;if(K=K&&K[0],!K&&(L=K=F(j)),"image"==e.type&&i.src&&(K.src=i.src),i.fill&&(K.on=!0),(null==K.on||"none"==i.fill||null===i.fill)&&(K.on=!1),K.on&&i.fill){var M=b(i.fill).match(c._ISURL);if(M){K.parentNode==l&&l.removeChild(K),K.rotate=!0,K.src=M[1],K.type="tile";var N=e.getBBox(1);K.position=N.x+n+N.y,e._.fillpos=[N.x,N.y],c._preload(M[1],function(){e._.fillsize=[this.offsetWidth,this.offsetHeight]})}else K.color=c.getRGB(i.fill).hex,K.src=o,K.type="solid",c.getRGB(i.fill).error&&(s.type in{circle:1,ellipse:1}||"r"!=b(i.fill).charAt())&&C(s,i.fill,K)&&(m.fill="none",m.gradient=i.fill,K.rotate=!1)}if("fill-opacity"in i||"opacity"in i){var O=((+m["fill-opacity"]+1||2)-1)*((+m.opacity+1||2)-1)*((+c.getRGB(i.fill).o+1||2)-1);O=h(g(O,0),1),K.opacity=O,K.src&&(K.color="none")}l.appendChild(K);var P=l.getElementsByTagName("stroke")&&l.getElementsByTagName("stroke")[0],Q=!1;!P&&(Q=P=F("stroke")),(i.stroke&&"none"!=i.stroke||i["stroke-width"]||null!=i["stroke-opacity"]||i["stroke-dasharray"]||i["stroke-miterlimit"]||i["stroke-linejoin"]||i["stroke-linecap"])&&(P.on=!0),("none"==i.stroke||null===i.stroke||null==P.on||0==i.stroke||0==i["stroke-width"])&&(P.on=!1);var R=c.getRGB(i.stroke);P.on&&i.stroke&&(P.color=R.hex),O=((+m["stroke-opacity"]+1||2)-1)*((+m.opacity+1||2)-1)*((+R.o+1||2)-1);var S=.75*(d(i["stroke-width"])||1);if(O=h(g(O,0),1),null==i["stroke-width"]&&(S=m["stroke-width"]),i["stroke-width"]&&(P.weight=S),S&&1>S&&(O*=S)&&(P.weight=1),P.opacity=O,i["stroke-linejoin"]&&(P.joinstyle=i["stroke-linejoin"]||"miter"),P.miterlimit=i["stroke-miterlimit"]||8,i["stroke-linecap"]&&(P.endcap="butt"==i["stroke-linecap"]?"flat":"square"==i["stroke-linecap"]?"square":"round"),i["stroke-dasharray"]){var T={"-":"shortdash",".":"shortdot","-.":"shortdashdot","-..":"shortdashdotdot",". ":"dot","- ":"dash","--":"longdash","- .":"dashdot","--.":"longdashdot","--..":"longdashdotdot"};P.dashstyle=T[a](i["stroke-dasharray"])?T[i["stroke-dasharray"]]:o}Q&&l.appendChild(P)}if("text"==s.type){s.paper.canvas.style.display=o;var U=s.paper.span,V=100,W=m.font&&m.font.match(/\d+(?:\.\d*)?(?=px)/);p=U.style,m.font&&(p.font=m.font),m["font-family"]&&(p.fontFamily=m["font-family"]),m["font-weight"]&&(p.fontWeight=m["font-weight"]),m["font-style"]&&(p.fontStyle=m["font-style"]),W=d(m["font-size"]||W&&W[0])||10,p.fontSize=W*V+"px",s.textpath.string&&(U.innerHTML=b(s.textpath.string).replace(/</g,"&#60;").replace(/&/g,"&#38;").replace(/\n/g,"<br>"));var X=U.getBoundingClientRect();s.W=m.w=(X.right-X.left)/V,s.H=m.h=(X.bottom-X.top)/V,s.X=m.x,s.Y=m.y+s.H/2,("x"in i||"y"in i)&&(s.path.v=c.format("m{0},{1}l{2},{1}",f(m.x*u),f(m.y*u),f(m.x*u)+1));for(var Y=["x","y","text","font","font-family","font-weight","font-style","font-size"],Z=0,$=Y.length;$>Z;Z++)if(Y[Z]in i){s._.dirty=1;break}switch(m["text-anchor"]){case"start":s.textpath.style["v-text-align"]="left",s.bbx=s.W/2;break;case"end":s.textpath.style["v-text-align"]="right",s.bbx=-s.W/2;break;default:s.textpath.style["v-text-align"]="center",s.bbx=0}s.textpath.style["v-text-kern"]=!0}},C=function(a,f,g){a.attrs=a.attrs||{};var h=(a.attrs,Math.pow),i="linear",j=".5 .5";if(a.attrs.gradient=f,f=b(f).replace(c._radial_gradient,function(a,b,c){return i="radial",b&&c&&(b=d(b),c=d(c),h(b-.5,2)+h(c-.5,2)>.25&&(c=e.sqrt(.25-h(b-.5,2))*(2*(c>.5)-1)+.5),j=b+n+c),o}),f=f.split(/\s*\-\s*/),"linear"==i){var k=f.shift();if(k=-d(k),isNaN(k))return null}var l=c._parseDots(f);if(!l)return null;if(a=a.shape||a.node,l.length){a.removeChild(g),g.on=!0,g.method="none",g.color=l[0].color,g.color2=l[l.length-1].color;for(var m=[],p=0,q=l.length;q>p;p++)l[p].offset&&m.push(l[p].offset+n+l[p].color);g.colors=m.length?m.join():"0% "+g.color,"radial"==i?(g.type="gradientTitle",g.focus="100%",g.focussize="0 0",g.focusposition=j,g.angle=0):(g.type="gradient",g.angle=(270-k)%360),a.appendChild(g)}return 1},D=function(a,b){this[0]=this.node=a,a.raphael=!0,this.id=c._oid++,a.raphaelid=this.id,this.X=0,this.Y=0,this.attrs={},this.paper=b,this.matrix=c.matrix(),this._={transform:[],sx:1,sy:1,dx:0,dy:0,deg:0,dirty:1,dirtyT:1},!b.bottom&&(b.bottom=this),this.prev=b.top,b.top&&(b.top.next=this),b.top=this,this.next=null},E=c.el;D.prototype=E,E.constructor=D,E.transform=function(a){if(null==a)return this._.transform;var d,e=this.paper._viewBoxShift,f=e?"s"+[e.scale,e.scale]+"-1-1t"+[e.dx,e.dy]:o;e&&(d=a=b(a).replace(/\.{3}|\u2026/g,this._.transform||o)),c._extractTransform(this,f+a);var g,h=this.matrix.clone(),i=this.skew,j=this.node,k=~b(this.attrs.fill).indexOf("-"),l=!b(this.attrs.fill).indexOf("url(");if(h.translate(1,1),l||k||"image"==this.type)if(i.matrix="1 0 0 1",i.offset="0 0",g=h.split(),k&&g.noRotation||!g.isSimple){j.style.filter=h.toFilter();var m=this.getBBox(),p=this.getBBox(1),q=m.x-p.x,r=m.y-p.y;j.coordorigin=q*-u+n+r*-u,z(this,1,1,q,r,0)}else j.style.filter=o,z(this,g.scalex,g.scaley,g.dx,g.dy,g.rotate);else j.style.filter=o,i.matrix=b(h),i.offset=h.offset();return d&&(this._.transform=d),this},E.rotate=function(a,c,e){if(this.removed)return this;if(null!=a){if(a=b(a).split(k),a.length-1&&(c=d(a[1]),e=d(a[2])),a=d(a[0]),null==e&&(c=e),null==c||null==e){var f=this.getBBox(1);c=f.x+f.width/2,e=f.y+f.height/2}return this._.dirtyT=1,this.transform(this._.transform.concat([["r",a,c,e]])),this}},E.translate=function(a,c){return this.removed?this:(a=b(a).split(k),a.length-1&&(c=d(a[1])),a=d(a[0])||0,c=+c||0,this._.bbox&&(this._.bbox.x+=a,this._.bbox.y+=c),this.transform(this._.transform.concat([["t",a,c]])),this)},E.scale=function(a,c,e,f){if(this.removed)return this;if(a=b(a).split(k),a.length-1&&(c=d(a[1]),e=d(a[2]),f=d(a[3]),isNaN(e)&&(e=null),isNaN(f)&&(f=null)),a=d(a[0]),null==c&&(c=a),null==f&&(e=f),null==e||null==f)var g=this.getBBox(1);return e=null==e?g.x+g.width/2:e,f=null==f?g.y+g.height/2:f,this.transform(this._.transform.concat([["s",a,c,e,f]])),this._.dirtyT=1,this},E.hide=function(){return!this.removed&&(this.node.style.display="none"),this},E.show=function(){return!this.removed&&(this.node.style.display=o),this},E._getBBox=function(){return this.removed?{}:{x:this.X+(this.bbx||0)-this.W/2,y:this.Y-this.H,width:this.W,height:this.H}},E.remove=function(){if(!this.removed&&this.node.parentNode){this.paper.__set__&&this.paper.__set__.exclude(this),c.eve.unbind("raphael.*.*."+this.id),c._tear(this,this.paper),this.node.parentNode.removeChild(this.node),this.shape&&this.shape.parentNode.removeChild(this.shape);for(var a in this)this[a]="function"==typeof this[a]?c._removedFactory(a):null;this.removed=!0}},E.attr=function(b,d){if(this.removed)return this;if(null==b){var e={};for(var f in this.attrs)this.attrs[a](f)&&(e[f]=this.attrs[f]);return e.gradient&&"none"==e.fill&&(e.fill=e.gradient)&&delete e.gradient,e.transform=this._.transform,e}if(null==d&&c.is(b,"string")){if(b==j&&"none"==this.attrs.fill&&this.attrs.gradient)return this.attrs.gradient;for(var g=b.split(k),h={},i=0,m=g.length;m>i;i++)b=g[i],h[b]=b in this.attrs?this.attrs[b]:c.is(this.paper.customAttributes[b],"function")?this.paper.customAttributes[b].def:c._availableAttrs[b];return m-1?h:h[g[0]]}if(this.attrs&&null==d&&c.is(b,"array")){for(h={},i=0,m=b.length;m>i;i++)h[b[i]]=this.attr(b[i]);return h}var n;null!=d&&(n={},n[b]=d),null==d&&c.is(b,"object")&&(n=b);for(var o in n)l("raphael.attr."+o+"."+this.id,this,n[o]);if(n){for(o in this.paper.customAttributes)if(this.paper.customAttributes[a](o)&&n[a](o)&&c.is(this.paper.customAttributes[o],"function")){var p=this.paper.customAttributes[o].apply(this,[].concat(n[o]));this.attrs[o]=n[o];for(var q in p)p[a](q)&&(n[q]=p[q])}n.text&&"text"==this.type&&(this.textpath.string=n.text),B(this,n)}return this},E.toFront=function(){return!this.removed&&this.node.parentNode.appendChild(this.node),this.paper&&this.paper.top!=this&&c._tofront(this,this.paper),this},E.toBack=function(){return this.removed?this:(this.node.parentNode.firstChild!=this.node&&(this.node.parentNode.insertBefore(this.node,this.node.parentNode.firstChild),c._toback(this,this.paper)),this)},E.insertAfter=function(a){return this.removed?this:(a.constructor==c.st.constructor&&(a=a[a.length-1]),a.node.nextSibling?a.node.parentNode.insertBefore(this.node,a.node.nextSibling):a.node.parentNode.appendChild(this.node),c._insertafter(this,a,this.paper),this)},E.insertBefore=function(a){return this.removed?this:(a.constructor==c.st.constructor&&(a=a[0]),a.node.parentNode.insertBefore(this.node,a.node),c._insertbefore(this,a,this.paper),this)},E.blur=function(a){var b=this.node.runtimeStyle,d=b.filter;return d=d.replace(r,o),0!==+a?(this.attrs.blur=a,b.filter=d+n+m+".Blur(pixelradius="+(+a||1.5)+")",b.margin=c.format("-{0}px 0 0 -{0}px",f(+a||1.5))):(b.filter=d,b.margin=0,delete this.attrs.blur),this},c._engine.path=function(a,b){var c=F("shape");c.style.cssText=t,c.coordsize=u+n+u,c.coordorigin=b.coordorigin;var d=new D(c,b),e={fill:"none",stroke:"#000"};a&&(e.path=a),d.type="path",d.path=[],d.Path=o,B(d,e),b.canvas.appendChild(c);var f=F("skew");return f.on=!0,c.appendChild(f),d.skew=f,d.transform(o),d},c._engine.rect=function(a,b,d,e,f,g){var h=c._rectPath(b,d,e,f,g),i=a.path(h),j=i.attrs;return i.X=j.x=b,i.Y=j.y=d,i.W=j.width=e,i.H=j.height=f,j.r=g,j.path=h,i.type="rect",i},c._engine.ellipse=function(a,b,c,d,e){var f=a.path();return f.attrs,f.X=b-d,f.Y=c-e,f.W=2*d,f.H=2*e,f.type="ellipse",B(f,{cx:b,cy:c,rx:d,ry:e}),f},c._engine.circle=function(a,b,c,d){var e=a.path();return e.attrs,e.X=b-d,e.Y=c-d,e.W=e.H=2*d,e.type="circle",B(e,{cx:b,cy:c,r:d}),e},c._engine.image=function(a,b,d,e,f,g){var h=c._rectPath(d,e,f,g),i=a.path(h).attr({stroke:"none"}),k=i.attrs,l=i.node,m=l.getElementsByTagName(j)[0];return k.src=b,i.X=k.x=d,i.Y=k.y=e,i.W=k.width=f,i.H=k.height=g,k.path=h,i.type="image",m.parentNode==l&&l.removeChild(m),m.rotate=!0,m.src=b,m.type="tile",i._.fillpos=[d,e],i._.fillsize=[f,g],l.appendChild(m),z(i,1,1,0,0,0),i},c._engine.text=function(a,d,e,g){var h=F("shape"),i=F("path"),j=F("textpath");d=d||0,e=e||0,g=g||"",i.v=c.format("m{0},{1}l{2},{1}",f(d*u),f(e*u),f(d*u)+1),i.textpathok=!0,j.string=b(g),j.on=!0,h.style.cssText=t,h.coordsize=u+n+u,h.coordorigin="0 0";var k=new D(h,a),l={fill:"#000",stroke:"none",font:c._availableAttrs.font,text:g};k.shape=h,k.path=i,k.textpath=j,k.type="text",k.attrs.text=b(g),k.attrs.x=d,k.attrs.y=e,k.attrs.w=1,k.attrs.h=1,B(k,l),h.appendChild(j),h.appendChild(i),a.canvas.appendChild(h);var m=F("skew");return m.on=!0,h.appendChild(m),k.skew=m,k.transform(o),k},c._engine.setSize=function(a,b){var d=this.canvas.style;return this.width=a,this.height=b,a==+a&&(a+="px"),b==+b&&(b+="px"),d.width=a,d.height=b,d.clip="rect(0 "+a+" "+b+" 0)",this._viewBox&&c._engine.setViewBox.apply(this,this._viewBox),this},c._engine.setViewBox=function(a,b,d,e,f){c.eve("raphael.setViewBox",this,this._viewBox,[a,b,d,e,f]);var h,i,j=this.width,k=this.height,l=1/g(d/j,e/k);return f&&(h=k/e,i=j/d,j>d*h&&(a-=(j-d*h)/2/h),k>e*i&&(b-=(k-e*i)/2/i)),this._viewBox=[a,b,d,e,!!f],this._viewBoxShift={dx:-a,dy:-b,scale:l},this.forEach(function(a){a.transform("...")}),this};var F;c._engine.initWin=function(a){var b=a.document;b.createStyleSheet().addRule(".rvml","behavior:url(#default#VML)");try{!b.namespaces.rvml&&b.namespaces.add("rvml","urn:schemas-microsoft-com:vml"),F=function(a){return b.createElement("<rvml:"+a+' class="rvml">')}}catch(c){F=function(a){return b.createElement("<"+a+' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')}}},c._engine.initWin(c._g.win),c._engine.create=function(){var a=c._getContainer.apply(0,arguments),b=a.container,d=a.height,e=a.width,f=a.x,g=a.y;if(!b)throw new Error("VML container not found.");var h=new c._Paper,i=h.canvas=c._g.doc.createElement("div"),j=i.style;return f=f||0,g=g||0,e=e||512,d=d||342,h.width=e,h.height=d,e==+e&&(e+="px"),d==+d&&(d+="px"),h.coordsize=1e3*u+n+1e3*u,h.coordorigin="0 0",h.span=c._g.doc.createElement("span"),h.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;",i.appendChild(h.span),j.cssText=c.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden",e,d),1==b?(c._g.doc.body.appendChild(i),j.left=f+"px",j.top=g+"px",j.position="absolute"):b.firstChild?b.insertBefore(i,b.firstChild):b.appendChild(i),h.renderfix=function(){},h},c.prototype.clear=function(){c.eve("raphael.clear",this),this.canvas.innerHTML=o,this.span=c._g.doc.createElement("span"),this.span.style.cssText="position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;",this.canvas.appendChild(this.span),this.bottom=this.top=null},c.prototype.remove=function(){c.eve("raphael.remove",this),this.canvas.parentNode.removeChild(this.canvas);for(var a in this)this[a]="function"==typeof this[a]?c._removedFactory(a):null;return!0};var G=c.st;for(var H in E)E[a](H)&&!G[a](H)&&(G[H]=function(a){return function(){var b=arguments;return this.forEach(function(c){c[a].apply(c,b)})}}(H))}}(),B.was?A.win.Raphael=c:Raphael=c,c}); \ No newline at end of file
diff --git a/deps/wse/priv/raphael.html b/deps/wse/priv/raphael.html
deleted file mode 100644
index ee18237..0000000
--- a/deps/wse/priv/raphael.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html>
-<head>
-<title>Raphael demo page</title>
-<script src='ej.js'></script>
-<script src='wse.js'></script>
-<script>
-
-window.onload = function() {
- if (Wse.open("ws://"+(location.hostname||"localhost")+":1234/websession")) {
- Wse.start('wse_raphael_demo', 'run', ["i1"]);
- }
- else
- alert("WebSockets not supported");
-};
-
-</script>
-</head>
-<body style="background: #333">
-<div id="i1" width=640 height=480></div>
-</body>
-</html>
diff --git a/deps/wse/priv/table_demo.html b/deps/wse/priv/table_demo.html
deleted file mode 100644
index c0e93f6..0000000
--- a/deps/wse/priv/table_demo.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html>
-<head>
-<title>Table demo page</title>
-<script src='ej.js'></script>
-<script src='wse.js'></script>
-<script>
-
-window.onload = function() {
- if (Wse.open("ws://"+(location.hostname||"localhost")+":1234/websession")) {
- Wse.start('wse_table_demo', 'run', ["t1"]);
- }
- else
- alert("WebSockets not supported");
-};
-
-</script>
-</head>
-<body>
-<div id="t1" width=640 height=480></div>
-</body>
-</html>
diff --git a/deps/wse/priv/utf8.js b/deps/wse/priv/utf8.js
deleted file mode 100644
index db7b033..0000000
--- a/deps/wse/priv/utf8.js
+++ /dev/null
@@ -1,73 +0,0 @@
-//---- BEGIN COPYRIGHT -------------------------------------------------------
-//
-// Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-//
-// This software is licensed as described in the file COPYRIGHT, which
-// you should have received as part of this distribution. The terms
-// are also available at http://www.rogvall.se/docs/copyright.txt.
-//
-// You may opt to use, copy, modify, merge, publish, distribute and/or sell
-// copies of the Software, and permit persons to whom the Software is
-// furnished to do so, under the terms of the COPYRIGHT file.
-//
-// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-// KIND, either express or implied.
-//
-//---- END COPYRIGHT ---------------------------------------------------------
-//
-// UTF8 encoder/decoder
-//
-function UTF8Class() {
-};
-
-// method for UTF-8 encoding
-UTF8Class.prototype.encode = function (string) {
- string = string.replace(/\r\n/g,"\n");
- var utftext = "";
-
- for (var n = 0; n < string.length; n++) {
- var c = string.charCodeAt(n);
- if (c < 128) {
- utftext += String.fromCharCode(c);
- }
- else if((c > 127) && (c < 2048)) {
- utftext += String.fromCharCode((c >> 6) | 192);
- utftext += String.fromCharCode((c & 63) | 128);
- }
- else {
- utftext += String.fromCharCode((c >> 12) | 224);
- utftext += String.fromCharCode(((c >> 6) & 63) | 128);
- utftext += String.fromCharCode((c & 63) | 128);
- }
- }
- return utftext;
-};
-
-// method for UTF-8 decoding
-UTF8Class.prototype.decode = function(utftext) {
- var string = "";
- var i = 0;
- var c = c1 = c2 = 0;
-
- while (i < utftext.length) {
- c = utftext.charCodeAt(i);
- if (c < 128) {
- string += String.fromCharCode(c);
- i++;
- }
- else if((c > 191) && (c < 224)) {
- c2 = utftext.charCodeAt(i+1);
- string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
- i += 2;
- }
- else {
- c2 = utftext.charCodeAt(i+1);
- c3 = utftext.charCodeAt(i+2);
- string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
- i += 3;
- }
- }
- return string;
-};
-
-var UTF8 = new UTF8Class();
diff --git a/deps/wse/priv/wse.js b/deps/wse/priv/wse.js
deleted file mode 100644
index 602cde2..0000000
--- a/deps/wse/priv/wse.js
+++ /dev/null
@@ -1,725 +0,0 @@
-//---- BEGIN COPYRIGHT -------------------------------------------------------
-//
-// Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-//
-// This software is licensed as described in the file COPYRIGHT, which
-// you should have received as part of this distribution. The terms
-// are also available at http://www.rogvall.se/docs/copyright.txt.
-//
-// You may opt to use, copy, modify, merge, publish, distribute and/or sell
-// copies of the Software, and permit persons to whom the Software is
-// furnished to do so, under the terms of the COPYRIGHT file.
-//
-// This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-// KIND, either express or implied.
-//
-//---- END COPYRIGHT ---------------------------------------------------------
-//
-// WebSocket/Erlang interface
-//
-//
-
-// operations:
-// {rsync,IRef,Request} -> {reply,IRef,Reply}
-// {nsync,IRef,Request} -> {noreply,IRef}
-// {async,IRef,Request} -> void
-// {dsync,IRef,Request} -> void ... {reply,IRef,Reply}
-//
-// request:
-// {new, Class, Arguments}
-// -> {object,ID}
-//
-// {newf, ParamNames, Body}
-// -> {function,ID}
-//
-// {delete, ID}
-// -> ok | {error,Reason}
-//
-// {call, Object, method, This, Arguments}
-// -> {ok,Value} | {error,Reason}
-//
-// {call, Function, This, Arguments}
-// -> {ok,Value} | {error,Reason}
-//
-// {get, Object, AttrIndex}
-// -> {ok,Value} | {error,Reason}
-// {set, Object, AttrIndex, Value}
-// -> {ok,Value} | {error,Reason}
-//
-// Reverse operations:
-// {start, Mod, Fun, Args}
-// {call, Mod, Fun, Args} -> Value
-// {cast, Mod, Fun, Args}
-// {register, Name}
-// {unregister}
-//
-// {notify, ID, Data}
-// {info, String}
-//
-// Values:
-// number => integer|float
-// string => list of chars
-// atom => string
-// boolean => true|false
-// array => list of values
-// function => {function, ID}
-// object => {object,ID}
-//
-(function() {
- id_counter = 1;
- Object.defineProperty(Object.prototype, "__uniqueId", {
- writable: true
- });
- Object.defineProperty(Object.prototype, "uniqueId", {
- get: function() {
- if (this.__uniqueId == undefined)
- this.__uniqueId = id_counter++;
- return this.__uniqueId;
- }
- });
-}());
-
-var wse_console_debug = true;
-//
-// window.onerror = function(message, url, line)
-// console.low("window error was invoked with message = " +
-// message + ", url = " + url + ", line = " + line);
-// }
-//
-
-function WseClass(enable_console) {
- this.win = window;
- this.ws = undefined;
- this.state = "closed";
-
- this.objects = {}; // object of objects
-
- this.iref = 1;
- this.requests = new Array();
- this.reply_fun = {};
- this.reply_obj = {};
- this.reply_ref = {};
-
- this.OkTag = Ei.atom("ok");
- this.ErrorTag = Ei.atom("error");
- this.ExceptionTag = Ei.atom("exception");
- this.ObjectTag = Ei.atom("object");
- this.FunctionTag = Ei.atom("function");
- this.ReplyTag = Ei.atom("reply");
- this.NoReplyTag = Ei.atom("noreply");
-
- this.dummyConsole = {
- assert : function(){},
- log : function(){},
- warn : function(){},
- error : function(){},
- debug : function(){},
- dir : function(){},
- info : function(){}
- };
- if (enable_console && (window.console !== undefined))
- this.console = window.console;
- else
- this.console = this.dummyConsole;
-};
-
-WseClass.prototype.enable_console_output = function(enable) {
- if (enable && (window.console !== undefined))
- this.console = window.console;
- else
- this.console = this.dummyConsole;
-}
-
-WseClass.prototype.getWse = function(id) {
- var i;
- for (i = 0; i < this.win.frames.length; i++) {
- if (('Wse' in this.win.frames[i]) &&
- (this.win.frames[i].Wse.id == id))
- return this.win.frames[i].Wse;
- }
- return null;
-}
-
-// Fixme: check binaryType for the wanted encoding ?!
-WseClass.prototype.encode = function(Obj) {
-// return Base64.encode(Ei.encode(Obj));
- return Ei.encode(Obj);
-};
-
-// Fixme: handle base64 string & Blob and ArrayBuffer!
-WseClass.prototype.decode = function(Data) {
-// return Ei.decode(Base64.decode(Data));
- return Ei.decode(Data, 0);
-};
-
-// Decide an Erlang term that represent a json object into a
-// native json object i.e {struct,[{a,1},{b,2}]} => { a:1, b:2 }
-WseClass.prototype.decode_js = function(Data) {
- switch(typeof(Data)) {
- case "string": return Data;
- case "number": return Data;
- case "object":
- if (Ei.eqAtom(Data, "true")) return true;
- else if (Ei.eqAtom(Data, "false")) return false;
- else if (Ei.eqAtom(Data, "null")) return null;
- else if (Ei.isTupleSize(Data,2)) {
- var elem = Data.value;
- if (Ei.eqAtom(elem[0], "array") && Ei.isArray(elem[1])) {
- var iArr = elem[1];
- var arr = new Array();
- var len, i;
- for (i = 0; i < iArr.length; i++)
- arr[i] = this.decode_js(iArr[i]);
- return arr;
- }
- else if (Ei.eqAtom(elem[0],"struct") && Ei.isArray(elem[1])) {
- var iArr = elem[1];
- var obj = new Object();
- var len, i;
- for (i = 0; i < iArr.length; i++) {
- if (Ei.isTupleSize(iArr[i],2)) {
- var pair = iArr[i].value;
- if (typeof(pair[0]) == "string")
- obj[pair[0]] = this.decode_js(pair[1]);
- }
- }
- return obj;
- }
- else {
- this.console.debug("unable to decode pair " + Data);
- return null;
- }
- }
- else if (Ei.isArray(Data)) {
- var arr = new Array();
- var len, i;
- for (i = 0; i < Data.length; i++)
- arr[i] = this.decode_js(Data[i]);
- return arr
- }
- else {
- this.console.debug("unable to decode object " + Data);
- return null;
- }
- break;
- default:
- this.console.debug("unable to decode data " + Data);
- return null;
- }
-};
-
-WseClass.prototype.open = function(url) {
- var wse = this; // save WebSocket closure
-
- if ("WebSocket" in window) {
- this.state = "connecting";
- this.ws = new WebSocket(url);
- this.ws.binaryType = "arraybuffer";
-
-
- this.ws.onopen = function() {
- var info = Ei.tuple(Ei.atom("info"),"connected");
- wse.state = "open";
- this.send(wse.encode(info));
- for (ref in wse.requests) {
- var cmd = wse.requests[ref];
- if (cmd !== undefined)
- this.send(wse.encode(cmd));
- }
- // overwrite the old request array with a new and let
- // the old array be garbage collected. The new array is
- // not used right now, so we could set it to null, but keep
- // it for future ideas.
- wse.requests = new Array();
- };
-
- this.ws.onmessage = function(evt) {
- var Request = wse.decode(evt.data);
- var val = wse.dispatch(Request);
- if (val != undefined)
- this.send(wse.encode(val));
- };
-
- this.ws.onclose = function() {
- wse.state = "closed";
- wse.ws = undefined;
- };
- return true;
- }
- return false;
-};
-
-//
-// Remove all children (DOM util)
-//
-WseClass.prototype.remove_children = function(Cell) {
- if (Cell.hasChildNodes()) {
- while(Cell.childNodes.length >= 1)
- Cell.removeChild(Cell.firstChild);
- }
-}
-
-WseClass.prototype.lookup_object = function(index) {
- var obj = this.objects[index];
- this.console.debug("lookup object "+index+" = "+obj);
- return obj;
-}
-
-WseClass.prototype.insert_object = function(index,obj) {
- this.console.debug("insert object "+index+" = "+obj);
- this.objects[index] = obj;
-}
-
-WseClass.prototype.delete_object = function(index) {
- this.console.debug("deleting object "+index);
- delete this.objects[index];
-}
-
-//
-// Decode javascript object into BERT rpc values
-//
-WseClass.prototype.encode_value = function(Obj) {
- switch(typeof(Obj)) {
- case "number": return Obj;
- case "string": return Obj;
- case "boolean": return Obj ? Ei.atom("true") : Ei.atom("false");
- case "object":
- // {object, window} - the current window object
- // {object, document} - the current document object
- // {object, id} - DOM object with id field
- // {object, num} - Stored in objects object!
- if (Obj == window.self)
- return Ei.tuple(this.ObjectTag,Ei.atom("window"));
- else if (Obj == window.document)
- return Ei.tuple(this.ObjectTag,Ei.atom("document"));
- else if (Obj == screen)
- return Ei.tuple(this.ObjectTag,Ei.atom("screen"));
- else if (Obj == navigator)
- return Ei.tuple(this.ObjectTag,Ei.atom("navigator"));
- else if (('id' in Obj) && Obj.id) {
- if (Obj == document.getElementById(Obj.id))
- return Ei.tuple(this.ObjectTag,Obj.id);
- }
- this.insert_object(Obj.uniqueId, Obj);
- return Ei.tuple(this.ObjectTag,Obj.uniqueId);
- case "function":
- this.insert_object(Obj.uniqueId, Obj);
- return Ei.tuple(this.FunctionTag,Obj.uniqueId);
- case "undefined":
- return Ei.atom("undefined");
- }
-};
-
-//
-// Decode BERT rpc values into javascript objects
-// {object, window} => window.self
-// {object, document} => window.document
-// {object, screen} => screen
-// {object, navigator} => navigator
-// {object, id} => window.document.getElelementById(id)
-// {object, num} => objects[num]
-// {function,num} => objects[num]
-// [H1,H2...Hn] => Array
-//
-
-WseClass.prototype.decode_value = function(Obj) {
- switch(typeof(Obj)) {
- case "number": return Obj;
- case "string": return Obj;
- case "boolean": return Obj;
- case "object":
- if (Ei.isAtom(Obj))
- return Obj.value;
- else if (Ei.isTuple(Obj)) {
- var elem = Obj.value;
- if ((elem.length==2) && Ei.eqAtom(elem[0],"object")) {
- if (Ei.eqAtom(elem[1], "window"))
- return window.self;
- else if (Ei.eqAtom(elem[1],"document"))
- return window.document;
- else if (Ei.eqAtom(elem[1], "screen"))
- return screen;
- else if (Ei.eqAtom(elem[1], "navigator"))
- return navigator;
- else if (typeof(elem[1]) == "number")
- return this.lookup_object(elem[1]);
- else if (typeof(elem[1]) == "string")
- return window.document.getElementById(elem[1]);
- }
- // this is a garbage collected version {object,num,res-bin}
- if ((elem.length==3) && Ei.eqAtom(elem[0],"object")) {
- if ((typeof(elem[1]) == "number") && Ei.isBinary(elem[2])) {
- return this.lookup_object(elem[1]);
- }
- return undefined;
- }
- if ((elem.length==2) && Ei.eqAtom(elem[0],"function")) {
- if (typeof(elem[1]) == "number")
- return this.lookup_object(elem[1]);
- return undefined;
- }
- // this is a garbage collected version {function,num,res-bin}
- if ((elem.length==3) && Ei.eqAtom(elem[0],"function")) {
- if ((typeof(elem[1]) == "number") && Ei.isBinary(elem[2])) {
- return this.lookup_object(elem[1]);
- }
- return undefined;
- }
- }
- else if (Ei.isArray(Obj)) {
- var i;
- var arr = new Array();
- for (i = 0; i < Obj.length; i++)
- arr[i] = this.decode_value(Obj[i]);
- return arr;
- }
- return undefined;
- default:
- this.console.debug("unhandled object "+ Obj);
- return Obj;
- }
-};
-//
-// Decode ehtml to DOM
-// Elem = {Tag,Attributes,Children}
-// | {Tag,Attributes}
-// Tag is EiAtom
-// Attributes is Array of Tuple(Atom,Value) or Atom
-// optional Children is Array of Elem
-// Return top level DOM element
-//
-WseClass.prototype.decode_ehtml = function (Obj) {
- var element = undefined;
-
- if (typeof(Obj) == "string") {
- element = document.createTextNode(Obj);
- }
- else if (typeof(Obj) == "number") {
- element = document.createTextNode(Obj.toString());
- }
- else if (Ei.isArray(Obj)) {
- element = document.createDocumentFragment();
- for (i = 0; i < Obj.length; i++) {
- var child = this.decode_ehtml(Obj[i]);
- if (child != undefined)
- element.appendChild(child);
- }
- }
- else if (Ei.isTuple(Obj)) {
- var argv = Obj.value;
-
- if ((argv.length == 0) || !Ei.isAtom(argv[0]))
- return undefined;
-
- element = document.createElement(argv[0].value);
-
- if ((argv.length > 1) && Ei.isArray(argv[1])) {
- var attrs = argv[1];
- var i;
- for (i = 0; i < attrs.length; i++) {
- if (Ei.isTuple(attrs[i])) {
- var key = this.decode_value(attrs[i].value[0]);
- var value;
- if (attrs[0].length > 1)
- value = this.decode_value(attrs[i].value[1]);
- else
- value = true;
- element.setAttribute(key, value);
- }
- }
- if ((argv.length > 2) && Ei.isArray(argv[2])) {
- var children = argv[2];
- for (i = 0; i < children.length; i++) {
- var child = this.decode_ehtml(children[i]);
- if (child != undefined)
- element.appendChild(child);
- }
- }
- }
- }
- return element;
-};
-
-//
-// Dispatch remote operations
-//
-WseClass.prototype.dispatch = function (Request) {
- var iref, aref;
- var value, rvalue;
- var r, t;
- var is_dsync = false;
-
- if (Ei.isTupleSize(Request, 3)) {
- var argv = Request.value;
- aref = argv[1];
- if (Ei.eqAtom(argv[0], "rsync"))
- iref = aref;
- else if (Ei.eqAtom(argv[0], "nsync"))
- iref = -aref;
- else if (Ei.eqAtom(argv[0], "async"))
- iref = 0;
- else if (Ei.eqAtom(argv[0], "dsync")) {
- is_dsync = true;
- iref = 0;
- }
- else if (Ei.eqAtom(argv[0], "reply")) {
- var fn,obj,ref;
- iref = aref;
- value = argv[2];
- fn = this.reply_fun[iref];
- obj = this.reply_obj[iref];
- ref = this.reply_ref[iref];
- this.console.debug("got reply "+iref+","+value+" fn="+fn+" obj="+obj+" ref="+ref);
- if (fn != undefined) {
- delete this.reply_fun[iref];
- delete this.reply_obj[iref];
- delete this.reply_ref[iref];
- try {
- fn(obj,ref,value);
- }
- catch (err) {
- this.console.info("reply function crashed "+err.message);
- }
- }
- return undefined;
- }
- else
- return undefined; // signal protocol error
- r = argv[2];
- }
- else
- return undefined;
-
- if (Ei.isTuple(r)) {
- var argv = r.value;
- if ((argv.length == 3) && Ei.eqAtom(argv[0],"send")) {
- var Cell = document.getElementById(argv[1]);
-
- try {
- if (typeof(argv[2]) == "string") {
- Cell.innerHTML = Ei.pp(argv[2]);
- }
- else if (Ei.isTuple(argv[2]) || Ei.isArray(argv[2])) {
- var elem = this.decode_ehtml(argv[2]);
- this.remove_children(Cell);
- Cell.appendChild(elem);
- }
- value = this.OkTag;
- }
- catch(err) {
- value = Ei.tuple(this.ExceptionTag, err.message);
- }
- }
- else if ((argv.length == 3) && Ei.eqAtom(argv[0],"new")) {
- var obj = new Object();
- var fn = window[this.decode_value(argv[1])];
-
- try {
- fn.apply(obj, this.decode_value(argv[2]));
- obj.__proto__ = fn.prototype;
- rvalue = this.encode_value(obj);
- value = rvalue;
- }
- catch(err) {
- value = Ei.tuple(this.ExceptionTag, err.message);
- }
- }
- else if ((argv.length == 3) && Ei.eqAtom(argv[0],"newf")) {
- this.console.debug("new Function("+argv[1]+","+argv[2]+")");
- try {
- var fn = new Function(argv[1],argv[2]);
- this.console.debug("function = "+fn);
- rvalue = this.encode_value(fn);
- value = rvalue;
- }
- catch(err) {
- value = Ei.tuple(this.ExceptionTag, err.message);
- }
- }
- else if ((argv.length == 4) && Ei.eqAtom(argv[0],"call")) {
- var fn = this.decode_value(argv[1]);
- var objb = this.decode_value(argv[2]);
- var args = this.decode_value(argv[3]);
- var val;
-
- try {
- val = window[fn].apply(objb, args);
- rvalue = this.encode_value(val);
- this.console.debug("call/3=" + Ei.pp(argv[1]) + "," + Ei.pp(argv[2]) + "," + Ei.pp(argv[3]));
- if (is_dsync && (fn === "call") && (val % 1 === 0)) {
- // val is a reference in this case
- this.console.debug("set reply_obj["+val+"] = "+objb);
- objb.reply_obj[val] = this; // patch object
- objb.reply_ref[val] = aref; // original ref
- }
- value = Ei.tuple(this.OkTag, rvalue);
- }
- catch(err) {
- value = Ei.tuple(this.ErrorTag, err.message);
- }
- }
- else if ((argv.length == 5) && Ei.eqAtom(argv[0],"call")) {
- var obja = this.decode_value(argv[1]);
- var meth = this.decode_value(argv[2]);
- var objb = this.decode_value(argv[3]);
- var args = this.decode_value(argv[4]);
- var val;
-
- try {
- val = (obja[meth]).apply(objb, args);
- rvalue = this.encode_value(val);
- this.console.debug("call/4=" + Ei.pp(argv[1]) + "," + Ei.pp(argv[2]) + "," + Ei.pp(argv[3]) + "," + Ei.pp(argv[4]));
- if (is_dsync && (meth === "call") && (val % 1 === 0)) {
- // val is a reference in this case
- this.console.debug("set obja.reply_obj["+val+"] = "+this);
- obja.reply_obj[val] = this; // patch object
- obja.reply_ref[val] = aref; // original ref
- }
- value = Ei.tuple(this.OkTag, rvalue);
- }
- catch(err) {
- value = Ei.tuple(this.ErrorTag, err.message);
- }
- }
- else if ((argv.length == 3) && Ei.eqAtom(argv[0],"get")) {
- var obj = this.decode_value(argv[1]);
- var attr = this.decode_value(argv[2]);
- try {
- rvalue = obj[attr]; // both array and object attribute!
- this.console.debug(argv[1]+".get: "+attr+"="+rvalue);
- value = Ei.tuple(this.OkTag, this.encode_value(rvalue));
- }
- catch (err) {
- value = Ei.tuple(this.ErrorTag, err.message);
- }
- }
- else if ((argv.length == 4) && Ei.eqAtom(argv[0],"set")) {
- var obj = this.decode_value(argv[1]);
- var attr = this.decode_value(argv[2]);
- rvalue = this.decode_value(argv[3]);
- this.console.debug(argv[1]+".set: "+attr+"="+argv[3]+"("+rvalue+")");
- try {
- obj[attr] = rvalue; // both array and object attribute!
- value = this.OkTag;
- }
- catch (err) {
- value = Ei.tuple(this.ErrorTag, err.message);
- }
- }
- else if ((argv.length === 2) && Ei.eqAtom(argv[0],"delete")) {
- // argv[1] must be the uniqID integer
- this.delete_object(argv[1]);
- rvalue = null;
- value = this.OkTag;
- }
- }
- if (iref == 0) {
- // this.console.debug("ival=0");
- return undefined;
- }
- else if (iref > 0) {
- if (value == undefined) {
- value = Ei.tuple(this.ErrorTag, Ei.atom("badarg"));
- }
- t = Ei.tuple(this.ReplyTag,iref,value);
- }
- else {
- t = Ei.tuple(this.NoReplyTag,-iref);
- }
- // this.console.debug("t = " + Ei.pp(t));
- return t;
-};
-
-WseClass.prototype.send_request = function (ref, request)
-{
- if (this.state === "open") {
- this.ws.send(this.encode(request));
- }
- else {
- // safe until channel is open
- this.requests[ref] = request;
- }
-}
-
-//
-// Start remote controller "program"
-//
-WseClass.prototype.start = function (mod,fun,args) {
- var ref = this.iref++;
- var cmd = Ei.tuple(Ei.atom("start"),Ei.atom(mod),Ei.atom(fun),args);
-
- this.send_request(ref, cmd);
- return ref;
-};
-
-//
-// Call remote function mod:fun(Args)
-// execute onreply when reply is returned
-//
-WseClass.prototype.call = function (mod,fun,args,onreply) {
- var ref = this.iref++;
- var cmd = Ei.tuple(Ei.atom("call"),ref,Ei.atom(mod),Ei.atom(fun),args);
-
- this.console.debug("call mod="+mod+", fun="+fun+", args="+args);
- this.reply_fun[ref] = onreply;
- this.reply_obj[ref] = this;
- this.reply_ref[ref] = ref;
- this.console.debug("set reply_fun["+ref+"] = "+onreply);
- this.send_request(ref, cmd);
- return ref;
-};
-
-// Used for handle return relay
-WseClass.prototype.reply = function (iref,value) {
- var reply = Ei.tuple(this.ReplyTag,iref,value);
- this.console.debug("sending reply "+reply+"id="+this.id);
- if (this.state == "open") {
- this.ws.send(this.encode(reply));
- return true;
- }
- return false;
-};
-//
-// Execute remote function mod:fun(Args)
-//
-WseClass.prototype.cast = function (mod,fun,args) {
- var ref = this.iref++;
- var cmd = Ei.tuple(Ei.atom("cast"),ref,Ei.atom(mod),Ei.atom(fun),args);
- this.console.debug("cast mod="+mod+", fun="+fun+", args="+args);
- this.send_request(ref, cmd);
- return true;
-};
-
-//
-// Send notification
-//
-WseClass.prototype.notify = function (ref,data) {
- var cmd = Ei.tuple(Ei.atom("notify"),ref,data);
- this.console.debug("notify "+ ref + ", data="+data);
- this.send_request(ref, cmd);
- return true;
-};
-
-//
-// Register a websocket (on the erlang node side)
-// could nearly call erlang:register through the call
-// but only nearly
-//
-WseClass.prototype.register = function (name) {
- var ref = this.iref++;
- var cmd = Ei.tuple(Ei.atom("register"),Ei.atom(name));
- this.console.debug("register "+ name);
- this.send_request(ref, cmd);
- return true;
-}
-
-// Unregister a websocket (on the erlang node side)
-WseClass.prototype.unregister = function () {
- var ref = this.iref++;
- var cmd = Ei.tuple(Ei.atom("unregister"));
- this.console.debug("unregister");
- this.send_request(ref, cmd);
- return true;
-}
-
-var Wse = new WseClass(wse_console_debug);
diff --git a/deps/wse/priv/wse_demo.html b/deps/wse/priv/wse_demo.html
deleted file mode 100644
index 610d03f..0000000
--- a/deps/wse/priv/wse_demo.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<html><head>
-<title>wse demo page</title>
-<script src='ej.js'></script>
-<script src='wse.js'></script>
-<script>
- window.onload = function() {
- if (Wse.open("ws://"+(location.hostname||"localhost")+":1234/websession"))
- Wse.start('wse_demo', 'run', ["myid"]);
- };
-</script></head>
-<body>
- <div id="myid"></div>
-</body></html>
diff --git a/deps/wse/rebar.config b/deps/wse/rebar.config
deleted file mode 100644
index 2df9f72..0000000
--- a/deps/wse/rebar.config
+++ /dev/null
@@ -1,2 +0,0 @@
-{deps, [ {resource, ".*", {git, "git@github.com:tonyrog/resource.git"}}]}.
-{edoc_opts, [{doclet, edown_doclet}]}.
diff --git a/deps/wse/src/raphael.erl b/deps/wse/src/raphael.erl
deleted file mode 100644
index fb7a1fb..0000000
--- a/deps/wse/src/raphael.erl
+++ /dev/null
@@ -1,106 +0,0 @@
-%%%---- BEGIN COPYRIGHT -------------------------------------------------------
-%%%
-%%% Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-%%%
-%%% This software is licensed as described in the file COPYRIGHT, which
-%%% you should have received as part of this distribution. The terms
-%%% are also available at http://www.rogvall.se/docs/copyright.txt.
-%%%
-%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
-%%% copies of the Software, and permit persons to whom the Software is
-%%% furnished to do so, under the terms of the COPYRIGHT file.
-%%%
-%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-%%% KIND, either express or implied.
-%%%
-%%%---- END COPYRIGHT ---------------------------------------------------------
-%%% File : raphael.erl
-%%% Author : Tony Rogvall <tony@rogvall.se>
-%%% Description : Raphael interface towards browser
-%%% Created : 21 Dec 2009 by Tony Rogvall <tony@rogvall.se>
-
--module(raphael).
-
--compile(export_all).
-
-%% New returns a reference to the canvase object
-new(Ws, Array) ->
- wse:call(Ws, wse:window(), "Raphael", [Array]).
-
-new(Ws, Object, W, H) ->
- wse:call(Ws, wse:window(), "Raphael", [Object,W,H]).
-
-new(Ws, X, Y, W, H) ->
- wse:call(Ws, wse:window(), "Raphael", [X,Y,W,H]).
-
-setSize(Ws,Paper,W,H) ->
- wse:call(Ws, Paper, setSize, [W, H]).
-
-close(Ws,Paper) ->
- wse:call(Ws, Paper, clone, []).
-
-%% get attribute value
-attr(Ws,Object,Name) ->
- wse:call(Ws,Object,attr,[Name]).
-
-%% set attribute value
-attr(Ws,Object,Name,Value) ->
- wse:call(Ws,Object,attr,[Name,Value]).
-
-
-circle(Ws,Paper, X, Y, R) ->
- wse:call(Ws, Paper, circle, [X, Y, R]).
-
-rect(Ws,Paper, X, Y, W, H) ->
- wse:call(Ws, Paper, rect, [X, Y, W, H]).
-
-rect(Ws,Paper, X, Y, W, H, R) ->
- wse:call(Ws, Paper, rect, [X, Y, W, H, R]).
-
-ellipse(Ws,Paper,X,Y,Rx,Ry) ->
- wse:call(Ws,Paper,ellipse,[X,Y,Rx,Ry]).
-
-image(Ws,Paper,Src,X,Y,Width,Height) ->
- wse:call(Ws,Paper,image,[Src,X,Y,Width,Height]).
-
-set(Ws,Paper) ->
- wse:call(Ws,Paper,set,[]).
-
-push(Ws,Set,Objects) when is_list(Objects) ->
- wse:call(Ws,Set,push,Objects);
-push(Ws, Set, Object) ->
- wse:call(Ws,Set,push,[Object]).
-
-%% FIXME: utf8!
-text(Ws,Paper,X,Y,Text) ->
- wse:call(Ws,Paper,text,[X,Y,Text]).
-
-%% return a font object
-getFont(Ws,Paper,Family) ->
- wse:call(Ws,Paper,getFont,[Family]).
-
-print(Ws,Paper,X,Y,Text,Font,FontSize) ->
- wse:call(Ws,Paper,print,[X,Y,Text,Font,FontSize]).
-
-path(Ws,Paper,SVG) ->
- wse:call(Ws,Paper,path,[SVG]).
-
-path(Ws,Paper) ->
- wse:call(Ws,Paper,path,[]).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/deps/wse/src/wse.app.src b/deps/wse/src/wse.app.src
deleted file mode 100644
index cba9091..0000000
--- a/deps/wse/src/wse.app.src
+++ /dev/null
@@ -1,7 +0,0 @@
-{application, wse,
- [{description, "Erlang web socket server"},
- {vsn, git},
- {registered, []},
- {env, []},
- {applications,[kernel,stdlib]}
- ]}.
diff --git a/deps/wse/src/wse.erl b/deps/wse/src/wse.erl
deleted file mode 100644
index 21e2ef0..0000000
--- a/deps/wse/src/wse.erl
+++ /dev/null
@@ -1,453 +0,0 @@
-%%%---- BEGIN COPYRIGHT -------------------------------------------------------
-%%%
-%%% Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-%%%
-%%% This software is licensed as described in the file COPYRIGHT, which
-%%% you should have received as part of this distribution. The terms
-%%% are also available at http://www.rogvall.se/docs/copyright.txt.
-%%%
-%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
-%%% copies of the Software, and permit persons to whom the Software is
-%%% furnished to do so, under the terms of the COPYRIGHT file.
-%%%
-%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-%%% KIND, either express or implied.
-%%%
-%%%---- END COPYRIGHT ---------------------------------------------------------
-%%% File : wse.erl
-%%% Author : Tony Rogvall <tony@rogvall.se>
-%%% Description : WebSocket Erlang interface
-%%% Created : 21 Dec 2009 by Tony Rogvall <tony@rogvall.se>
-
--module(wse).
-
--export([call/4, call/5]).
--export([rcall/4, rcall/5]).
--export([get/3, set/4]).
--export([cast/4, cast/5]).
--export([send/3]).
--export([new/3]).
--export([delete/2]).
--export([close/1, close/2]).
-%% standard objects
--export([document/0, window/0, screen/0, navigator/0]).
-%% object wrapper when passing string based id
--export([id/1]).
--export([array/1]).
--export([create_event/1, create_event/3]).
--export([wait_event/2]).
--export([createElement/2]).
--export([createTextNode/2]).
--export([getElementsByTagName/2]).
--export([getElementById/2]).
--export([appendChild/3]).
--export([load_image/2, load/2]).
-%% header items
--export([header/1]).
--export([header/2]).
--export([session_header/0]).
--export([session_header/1]).
-
--compile(export_all).
-
--type void() :: ok.
--type wse_object() :: {object, atom()|string()|integer()}.
--type wse_event() :: integer().
--type wse() :: pid().
--type url() :: string().
-
--type dom_id() :: atom()|string().
--type html_tag() :: atom().
--type attr_name() :: atom().
--type attr_value() :: atom()|string()|integer().
--type html_attr() :: {attr_name(),attr_value()}.
--type ehtml() :: atom() | string() | integer() |
- {Tag::html_tag(),[html_attr()]} |
- {Tag::html_tag(),[html_attr()],[ehtml()]}.
-
-id(ID) when is_atom(ID) ->
- {object, ID};
-id(ID) when is_list(ID) ->
- {object, ID}.
-
--spec document() -> wse_object().
-document() -> id(document).
-
--spec window() -> wse_object().
-window() -> id(window).
-
--spec screen() -> wse_object().
-screen() -> id(screen).
-
--spec navigator() -> wse_object().
-navigator() -> id(navigator).
-
-%% @doc
-%% Send (e)HTML to a DOM element sowmehere in the document.
-%% @end
--spec send(Ws::wse(), Tag::dom_id(), Data::ehtml()) -> void().
-
-send(Ws, Tag, Data) ->
- nsync(Ws, {send,Tag,Data}).
-
-%% @doc
-%% Call a Javascript method
-%% @end
--spec call(Ws::wse(), Object::wse_object(), Method::atom(), Args::[term()]) ->
- {ok, Value::term()}.
-call(Ws, Object, Method, Args) ->
- call(Ws, Object, Method, Object, Args).
-
-%% @doc
-%% Call a Javascript method setting this
-%% @end
--spec call(Ws::wse(), Object::wse_object(),
- This::wse_object(), Method::atom(), Args::[term()]) ->
- {ok, Value::term()}.
-call(Ws, Object, Method, This, Args) when is_list(Args) ->
- rsync(Ws, {call, Object, Method, This, array(Args)}).
-
-%% @doc
-%% Remote call
-%% @end
-
--spec rcall(Ws::wse(), Object::wse_object(), Method::atom(), Args::[term()]) ->
- {ok, Value::term()}.
-rcall(Ws, Object, Method, Args) ->
- rcall(Ws, Object, Method, Object, Args).
-
--spec rcall(Ws::wse(), Object::wse_object(),
- This::wse_object(), Method::atom(), Args::[term()]) ->
- {ok, Value::term()}.
-rcall(Ws, Object, Method, This, Args) when is_list(Args) ->
- dsync(Ws, {call, Object, Method, This, array(Args)}).
-
-%% @doc
-%% Get attribute or value at index
-%% @end
-
--spec get(Ws::wse(), Object::wse_object(),
- Attribute::integer()|atom()|string()|list())
- -> {ok,Value::term()} | {error,Reason::term()}.
-
-get(Ws, Object, [LeafAttribute]) when is_list(LeafAttribute) ->
- get(Ws, Object, LeafAttribute);
-get(Ws, Object, [Attribute | SubAttributes]) when is_list(Attribute) ->
- {ok, AttributeObject} = get(Ws, Object, Attribute),
- get(Ws, AttributeObject, SubAttributes);
-get(Ws, Object, Attribute) ->
- rsync(Ws, {get, Object, Attribute}).
-
-%% @doc
-%% Set attibute or array at index
-%% @end
--spec set(Ws::wse(), Object::wse_object(),
- Attribute::integer()|atom()|string()|list(),
- Value::term()) -> ok | {error,Reason::term()}.
-
-set(Ws, Object, [LeafAttribute], Value) when is_list(LeafAttribute) ->
- rsync(Ws, {set, Object, LeafAttribute, Value});
-set(Ws, Object, [Attribute | SubAttributes], Value) when is_list(Attribute) ->
- {ok, AttributeObject} = get(Ws, Object, Attribute),
- set(Ws, AttributeObject, SubAttributes, Value);
-set(Ws, Object, Attribute, Value) ->
- rsync(Ws, {set, Object, Attribute, Value}).
-
-%% @doc
-%% Cast like call, but with no return value
-%% @end
--spec cast(Ws::wse(), Object::wse_object(), Method::atom(), Args::[term()]) ->
- ok.
-cast(Ws, Object, Method, Args) ->
- cast(Ws, Object, Method, Object, Args).
-
--spec cast(Ws::wse(), Object::wse_object(), Method::atom(),
- Thus::wse_object(), Args::[term()]) ->
- ok.
-cast(Ws, Object, Method, This, Args) when is_list(Args) ->
- async(Ws, {call, Object, Method, This, array(Args)}).
-
-%% @doc
-%% Create a new Java script object
-%% @end
-new(Ws, Class, Args) when is_list(Args) ->
- rsync(Ws, {new,Class,array(Args)}).
-
-%% @doc
-%% Create a new function.
-%% <pre>
-%% newf(Ws, "e,f", "'e.pageX'").
-%% </pre>
-%% @end
--spec newf(Wse::wse(), Agrs::string(), Body::string()) ->
- wse_object().
-
-newf(Ws, Args, Body) when is_list(Args), is_list(Body) ->
- rsync(Ws, {newf,Args,Body}).
-
-%% @doc
-%% Release an object from the encoding object array.
-%% use with care
-%% @end
-
--spec delete(Ws::wse(), Object::wse_object()) ->
- void().
-
-delete(Ws, {object,ID,_Ref}) ->
- rsync(Ws, {delete,ID});
-delete(_Ws, _) ->
- ok.
-
-close(Ws) ->
- close(Ws, normal).
-
-close(Ws,Reason) ->
- Ref = make_ref(),
- Ws ! {close,[Ref|self()],Reason},
- receive
- {reply, Ref, Reply} ->
- Reply
- end.
-
-%% @doc
-%% Force list to be encoded as a list (instead of a string)
-%% when using term_to_binary, this is handled in the wse decoder
-%% @end
-
--spec array([term()]) -> list().
-
-array(Elements) when is_list(Elements) ->
- ['array'|Elements].
-
-%% @doc
-%% Create event listener that can be used to wait
-%% for events from java script.
-%% Same as create_event(Ws, all, []).
-%% @end
-
--spec create_event(Ws::wse()) ->
- {ok, wse_event()}.
-create_event(Ws) ->
- create_event(Ws,all,[]).
-
-%% @doc
-%% Create event listener with two flavours
-%% @end
--spec create_event(Ws::wse(), How::once|all, Data::term()) ->
- {ok, wse_event()}.
-
-create_event(Ws,How,Data) ->
- Ref = make_ref(),
- Ws ! {create_event,[Ref|self()],How,Data},
- receive
- {reply, Ref, Reply} ->
- Reply
- end.
-
-%% @doc
-%% Wait for an event sent from java script.
-%% Reply will contain both the local data installed with the
-%% event it self, and the data sent by java script, as a pair.
-%% @end
--spec wait_event(ID::wse_event(), Timeout::timeout()) ->
- {ok,{Local::term(), Remote::term()}}.
-
-wait_event(ID,Timeout) ->
- receive
- {notify,ID,Local,Remote} ->
- {ok,{Local,Remote}}
- after Timeout ->
- {error,timeout}
- end.
-
-%% Short cuts to DOM access
-
-%% @doc
-%% Short cut for
-%% <pre>
-%% {ok,E} = call(Ws, document(), createElement, [Name]), E
-%% </pre>
-%% @end
--spec createElement(Ws::wse(), Name::string()) -> wse_object().
-createElement(Ws, Name) ->
- %% io:format("createElement: ~p\n", [Name]),
- {ok,E} = call(Ws, document(), createElement, [Name]),
- E.
-
-%% @doc
-%% Short cut for
-%% <pre>
-%% {ok,E} = call(Ws, document(), createTextNode, [Text]), E
-%% </pre>
-%% @end
--spec createTextNode(Ws::wse(), Text::string()) -> wse_object().
-createTextNode(Ws, Text) ->
- {ok,E} = call(Ws, document(), createTextNode, [Text]),
- E.
-
-%% @doc
-%% Short cut for
-%% <pre>
-%% {ok,_} = call(Ws, Element, appendChild, [Child]), ok
-%% </pre>
-%% @end
--spec appendChild(Ws::wse(), Element::wse_object(), Child::wse_object()) ->
- ok.
-appendChild(Ws, Element, Child) ->
- {ok,_} = call(Ws, Element, appendChild, [Child]),
- ok.
-
-%% @doc
-%% Retrive an array of DOM objects by tag name
-%% Short cut for
-%% <ptr>
-%% call(Ws, document(), getElementsByTagName, [Name])
-%% </ptr>
-%% @end
-%%
--spec getElementsByTagName(Ws::wse(), Name::string()) ->
- {ok,Array::wse_object()} |
- {error,Reason::string()}.
-getElementsByTagName(Ws, Name) ->
- call(Ws, document(), getElementsByTagName, [Name]).
-
-
-%% @doc
-%% Retrive a DOM object by its id
-%% Short cut for
-%% <ptr>
-%% call(Ws, document(), getElementById, [ID]).
-%% </ptr>
-%% @end
-%%
--spec getElementById(Ws::wse(), ID::string()) ->
- {ok,Elem::wse_object()} |
- {error,Reason::string()}.
-getElementById(Ws, ID) ->
- call(Ws, document(), getElementById, [ID]).
-
-
-%% @doc
-%% Get first child
-%% @end
-firstChild(Ws, Object) ->
- get(Ws, Object, firstChild).
-
-%% @doc
-%% Get last child
-%% @end
-lastChild(Ws, Object) ->
- get(Ws, Object, lastChild).
-
-%% @doc
-%% Get next sibling
-%% @end
-nextSibling(Ws, Object) ->
- get(Ws, Object, nextSibling).
-
-%% @doc
-%% Load an image into the document and return
-%% image the object.
-%% @end
--spec load_image(Ws::wse(), Src::url()) ->
- {ok,Image::wse_object()}.
-
-load_image(Ws, Src) ->
- Image = createElement(Ws, "img"),
- set(Ws, Image, "src", Src),
- {ok,Style} = wse:get(Ws, Image, "style"),
- set(Ws, Style, "display", "none"),
- %% set(Ws, Image, "type", "image/jpeg");
- {ok,Array} = getElementsByTagName(Ws, "head"),
- {ok,Elem} = get(Ws, Array, 0),
- appendChild(Ws, Elem, Image),
- %% wait for image to load?
- {ok,Image}.
-
-%% @doc
-%% Load a java script library, and wait for it to load.
-%% @end
--spec load(Ws::wse(), Library::url()) -> ok.
-
-%% Short cut to dynamically load java script library
-load(Ws, Library) ->
- Script1 = createElement(Ws, "script"),
- set(Ws, Script1, "type", "text/javascript"),
- set(Ws, Script1, "src", Library),
-
- {ok,ID} = create_event(Ws),
- Script2 = createElement(Ws, "script"),
- Text=createTextNode(Ws, "Wse.notify("++integer_to_list(ID)++",'loaded');"),
- appendChild(Ws, Script2, Text),
-
- %% Append script's in head element
- {ok,Head} = call(Ws, document(), getElementsByTagName, ["head"]),
- {ok,Elem} = get(Ws, Head, 0),
- appendChild(Ws, Elem, Script1),
- appendChild(Ws, Elem, Script2),
- _Result = wait_event(ID, 5000),
- %% io:format("wait event = ~p\n", [_Result]),
- ok.
-
-header(Ws) when is_pid(Ws) ->
- Ref = make_ref(),
- Ws ! {header,[Ref|self()]},
- receive
- {reply, Ref, Reply} ->
- Reply
- after 5000 ->
- {error,timeout}
- end.
-
-header(Ws, ItemName) when is_pid(Ws) ->
- Ref = make_ref(),
- Ws ! {header,ItemName, [Ref|self()]},
- receive
- {reply, Ref, Reply} ->
- Reply
- after 5000 ->
- {error,timeout}
- end.
-
-session_header() ->
- %% Header stored in process dictionary
- get(header).
-
-session_header(ItemName) ->
- case get(header) of
- undefined ->
- %% or crash??
- {error, no_header};
- Header ->
- case lists:keyfind(ItemName, 1, Header) of
- {ItemName, ItemValue} ->
- {ok, ItemValue};
- false ->
- {error, unknown_header_item}
- end
- end.
-
-%% Sync and Async primitives
-rsync(Ws, Command) ->
- Ref = make_ref(),
- Ws ! {rsync,[Ref|self()],Command},
- receive
- {reply, Ref, Reply} ->
- Reply
- end.
-
-dsync(Ws, Command) ->
- Ref = make_ref(),
- Ws ! {dsync,[Ref|self()],Command},
- receive
- {reply, Ref, Reply} ->
- Reply
- end.
-
-nsync(Ws, Command) ->
- Ref = make_ref(),
- Ws ! {nsync,[Ref|self()],Command}.
-
-async(Ws, Command) ->
- Ref = make_ref(),
- Ws ! {async,[Ref|self()],Command}.
diff --git a/deps/wse/src/wse_button_demo.erl b/deps/wse/src/wse_button_demo.erl
deleted file mode 100644
index bfcde03..0000000
--- a/deps/wse/src/wse_button_demo.erl
+++ /dev/null
@@ -1,50 +0,0 @@
-%%%---- BEGIN COPYRIGHT -------------------------------------------------------
-%%%
-%%% Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-%%%
-%%% This software is licensed as described in the file COPYRIGHT, which
-%%% you should have received as part of this distribution. The terms
-%%% are also available at http://www.rogvall.se/docs/copyright.txt.
-%%%
-%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
-%%% copies of the Software, and permit persons to whom the Software is
-%%% furnished to do so, under the terms of the COPYRIGHT file.
-%%%
-%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-%%% KIND, either express or implied.
-%%%
-%%%---- END COPYRIGHT ---------------------------------------------------------
-%%% @author Tony Rogvall <tony@rogvall.se>
-%%% @copyright (C) 2014, Tony Rogvall
-%%% @doc
-%%% Demo a button with notification callback
-%%% @end
-%%% Created : 16 Jun 2014 by Tony Rogvall <tony@rogvall.se>
-
--module(wse_button_demo).
-
--export([run/2]).
-
-%% Button demo
-run(Ws, Where) ->
- io:format("button_demo: called\n"),
- Button = wse:createElement(Ws, "button"),
- io:format("button=~w\n", [Button]),
- Text = wse:createTextNode(Ws, "Press me"),
- io:format("text=~w\n", [Text]),
- wse:appendChild(Ws, Button, Text),
- wse:appendChild(Ws, wse:id(Where), Button),
- {ok,ID} = wse:create_event(Ws),
- io:format("ID=~w\n", [ID]),
- Func = wse:newf(Ws, "",
- "{ Wse.notify("++integer_to_list(ID)++",'click'); }"),
- wse:set(Ws,Button,"onclick",Func),
- run_loop(Ws, Text, ID).
-
-run_loop(Ws, Text, ID) ->
- receive
- {notify,ID,_Local,Data} ->
- io:format("~p\n", [Data]),
- wse:set(Ws, Text, "nodeValue", "Again"),
- run_loop(Ws, Text, ID)
- end.
diff --git a/deps/wse/src/wse_demo.erl b/deps/wse/src/wse_demo.erl
deleted file mode 100644
index 3f0c40b..0000000
--- a/deps/wse/src/wse_demo.erl
+++ /dev/null
@@ -1,24 +0,0 @@
-%%%---- BEGIN COPYRIGHT -------------------------------------------------------
-%%%
-%%% Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-%%%
-%%% This software is licensed as described in the file COPYRIGHT, which
-%%% you should have received as part of this distribution. The terms
-%%% are also available at http://www.rogvall.se/docs/copyright.txt.
-%%%
-%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
-%%% copies of the Software, and permit persons to whom the Software is
-%%% furnished to do so, under the terms of the COPYRIGHT file.
-%%%
-%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-%%% KIND, either express or implied.
-%%%
-%%%---- END COPYRIGHT ---------------------------------------------------------
--module(wse_demo).
--export([run/2]).
-
-run(Ws, Where) ->
- ElemNode = wse:createElement(Ws, "p"),
- TextNode = wse:createTextNode(Ws, "Hello world"),
- wse:appendChild(Ws, ElemNode, TextNode),
- wse:appendChild(Ws, wse:id(Where), ElemNode).
diff --git a/deps/wse/src/wse_document_demo.erl b/deps/wse/src/wse_document_demo.erl
deleted file mode 100644
index 8b6aae6..0000000
--- a/deps/wse/src/wse_document_demo.erl
+++ /dev/null
@@ -1,71 +0,0 @@
-%%%---- BEGIN COPYRIGHT -------------------------------------------------------
-%%%
-%%% Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-%%%
-%%% This software is licensed as described in the file COPYRIGHT, which
-%%% you should have received as part of this distribution. The terms
-%%% are also available at http://www.rogvall.se/docs/copyright.txt.
-%%%
-%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
-%%% copies of the Software, and permit persons to whom the Software is
-%%% furnished to do so, under the terms of the COPYRIGHT file.
-%%%
-%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-%%% KIND, either express or implied.
-%%%
-%%%---- END COPYRIGHT ---------------------------------------------------------
-%%% @author Tony Rogvall <tony@rogvall.se>
-%%% @copyright (C) 2014, Tony Rogvall
-%%% @doc
-%%% This demo is called directly from web page
-%%% @end
-%%% Created : 24 Apr 2014 by Tony Rogvall <tony@rogvall.se>
-
--module(wse_document_demo).
--export([run/2]).
-
--compile(export_all).
-
-run(Ws, Where) ->
- io:format("document_demo: called\n"),
-
- screen_info(Ws, wse:id(Where),
- [availHeight, availWidth,colorDepth,
- height, pixelDepth, width ]),
-
- window_info(Ws, wse:id(Where),
- [closed, innerHeight,innerWidth,length,name,
- outerHeight,outerWidth]),
-
- navigator_info(Ws, wse:id(Where),
- [appCodeName,appName,appVersion,cookieEnabled,
- language,onLine,platform,product,userAgent]),
-
- document_info(Ws, wse:id(Where),
- [cookie,docType,inputEncoding,lastModified,
- referrer,domain,baseURI,title,'URL']),
- %% wse:close(Ws, done),
- ok.
-
-screen_info(Ws, Parent, As=[A|_]) when is_atom(A) ->
- [ info(Ws, wse:screen(), "screen", What, Parent) || What <- As ].
-
-window_info(Ws, Parent, As=[A|_]) when is_atom(A) ->
- [ info(Ws, wse:window(), "window", What, Parent) || What <- As ].
-
-navigator_info(Ws, Parent, As=[A|_]) when is_atom(A) ->
- [ info(Ws, wse:navigator(), "navigator", What, Parent) || What <- As ].
-
-document_info(Ws, Parent, As=[A|_]) when is_atom(A) ->
- [ info(Ws, wse:document(), "document", What, Parent) || What <- As ].
-
-info(Ws, Object, ObjName, What, Parent) ->
- {ok,Value} = wse:get(Ws, Object, What),
- Text = ObjName++"."++to_text(What)++"="++to_text(Value),
- ElemNode = wse:createElement(Ws, "p"),
- TextNode = wse:createTextNode(Ws, Text),
- wse:appendChild(Ws, ElemNode, TextNode),
- wse:appendChild(Ws, Parent, ElemNode).
-
-to_text(X) ->
- lists:flatten(io_lib:format("~p", [X])).
diff --git a/deps/wse/src/wse_fish_demo.erl b/deps/wse/src/wse_fish_demo.erl
deleted file mode 100644
index e486b6e..0000000
--- a/deps/wse/src/wse_fish_demo.erl
+++ /dev/null
@@ -1,54 +0,0 @@
-%%%---- BEGIN COPYRIGHT -------------------------------------------------------
-%%%
-%%% Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-%%%
-%%% This software is licensed as described in the file COPYRIGHT, which
-%%% you should have received as part of this distribution. The terms
-%%% are also available at http://www.rogvall.se/docs/copyright.txt.
-%%%
-%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
-%%% copies of the Software, and permit persons to whom the Software is
-%%% furnished to do so, under the terms of the COPYRIGHT file.
-%%%
-%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-%%% KIND, either express or implied.
-%%%
-%%%---- END COPYRIGHT ---------------------------------------------------------
-%%% @author Tony Rogvall <tony@rogvall.se>
-%%% @copyright (C) 2014, Tony Rogvall
-%%% @doc
-%%% Show how to do remote animation with png
-%%% Fishes from: http://www.squaregoldfish.co.uk
-%%% @end
-%%% Created : 24 Apr 2014 by Tony Rogvall <tony@rogvall.se>
-
--module(wse_fish_demo).
--export([run/2]).
-
--compile(export_all).
-
-run(Ws, Where) ->
- io:format("fish_demo: called\n"),
- %% "preload" fish images
- Fishes =
- [ begin
- FNo = tl(integer_to_list(10000+I)),
- File = "fish/fish"++FNo++".png",
- {ok,Image} = wse:load_image(Ws, File),
- %% io:format("loaded: ~s\n", [File]),
- Image
- end || I <- lists:seq(1,23)],
- Image = wse:createElement(Ws, "img"),
- Parent = wse:id(Where),
- wse:appendChild(Ws, Parent, Image),
- update_loop(Ws, Image, Fishes, Fishes).
-
-update_loop(Ws, Image, [F|Fs], Fishes) ->
- {ok,Src} = wse:get(Ws, F, "src"),
- %% io:format("Src=~p\n", [Src]),
- wse:set(Ws, Image, "src", Src),
- timer:sleep(100),
- update_loop(Ws, Image, Fs, Fishes);
-update_loop(Ws, Image, [], Fishes) ->
- update_loop(Ws, Image, Fishes, Fishes).
-
diff --git a/deps/wse/src/wse_frame_demo.erl b/deps/wse/src/wse_frame_demo.erl
deleted file mode 100644
index 279b5b3..0000000
--- a/deps/wse/src/wse_frame_demo.erl
+++ /dev/null
@@ -1,137 +0,0 @@
-%%%---- BEGIN COPYRIGHT -------------------------------------------------------
-%%%
-%%% Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-%%%
-%%% This software is licensed as described in the file COPYRIGHT, which
-%%% you should have received as part of this distribution. The terms
-%%% are also available at http://www.rogvall.se/docs/copyright.txt.
-%%%
-%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
-%%% copies of the Software, and permit persons to whom the Software is
-%%% furnished to do so, under the terms of the COPYRIGHT file.
-%%%
-%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-%%% KIND, either express or implied.
-%%%
-%%%---- END COPYRIGHT ---------------------------------------------------------
-%%% @author Tony Rogvall <tony@rogvall.se>
-%%% @copyright (C) 2014, Tony Rogvall
-%%% @doc
-%%% This demo is called directly from web page
-%%% @end
-%%% Created : 24 Apr 2014 by Tony Rogvall <tony@rogvall.se>
-
--module(wse_frame_demo).
--export([run/2]).
-
--compile(export_all).
-
-run(Ws, Where) ->
- io:format("frame_demo where=~s: called\n", [Where]),
-
- case Where of
- "i0" ->
- window_info(Ws, wse:id(Where), [frames]),
- {ok,Frames} = wse:get(Ws, wse:window(), frames),
- io:format("Frames object=~p\n", [Frames]),
- {ok,Length} = wse:get(Ws, Frames, length),
- io:format("#Frames=~p\n", [Length]),
- lists:foreach(
- fun(I) ->
- %% Access frames and ping the wse in each
- {ok,F} = wse:get(Ws, Frames, I),
- io:format("Frame ~w: ~p\n", [I,F]),
- {ok,D} = wse:get(Ws, F, document),
- io:format("Frame Document: ~p\n", [D]),
- {ok,Wse} = wse:get(Ws, F, 'Wse'),
- io:format("Frame Wse: ~p\n", [Wse]),
- {ok,ID} = wse:get(Ws, Wse, id),
- io:format("Frame Wse: Wse.id=~p\n", [ID]),
- %% wse:cast(Ws, Wse, notify, [120+I, hello_world]),
- ok
- end, lists:seq(0, Length-1)),
- ok;
- _ ->
- window_info(Ws, wse:id(Where), [name,innerHeight,innerWidth]),
-
- %% sleep short time ?
- timer:sleep(500),
- Target = case Where of
- "i1" -> "w2";
- "i2" -> "w1"
- end,
- io:format("target = ~p\n", [Target]),
- {ok,Wse} = get_wse_frame(Ws, Target),
- %% try send message across to other frames wse endpoint
- case Wse of
- undefined ->
- ok;
- _ ->
- io:format("~s: get info of other system ~p\n",
- [Where,Target]),
- Func = wse:newf(Ws, "wse,iref,value",
- "{ console.debug('frame_demo.reply_fun'); wse.reply(iref,value); }"),
- Call = [lists,reverse,[[1,2,3]],Func],
- io:format("rcall ~p\n", [Call]),
- Ret=wse:rcall(Ws, Wse, call, Call),
- io:format("rcall return = ~p\n", [Ret]),
- %% wse:cast(Ws, Wse, notify, [111, [inter_frame,Where]]),
- ok
- end,
- %% wse:close(Ws, done),
- ok
- end.
-
-get_wse_frame(Ws, Wid) ->
- {ok,P} = wse:get(Ws, wse:window(), parent), %% p = window.parent,
- io:format("window.parent = ~p\n", [P]),
- {ok,Wse} = wse:get(Ws, P, 'Wse'),
- io:format("window.parent.Wse = ~p\n", [Wse]),
- {ok,WseID} = wse:get(Ws, Wse, id),
- io:format("window.parent.Wse.id = ~p\n", [WseID]),
- {ok,Wse1} = wse:call(Ws, Wse, getWse, [Wid]),
- io:format("Wse1 = ~p\n", [Wse1]),
- {ok,Wse1}.
-
-
-all_info(Ws, Where) ->
- screen_info(Ws, wse:id(Where),
- [availHeight, availWidth,colorDepth,
- height, pixelDepth, width ]),
- window_info(Ws, wse:id(Where),
- [closed, innerHeight,innerWidth,length,name,
- outerHeight,outerWidth]),
- navigator_info(Ws, wse:id(Where),
- [appCodeName,appName,appVersion,cookieEnabled,
- language,onLine,platform,product,userAgent]),
- document_info(Ws, wse:id(Where),
- [cookie,docType,inputEncoding,lastModified,
- referrer,domain,baseURI,title,'URL']),
- ok.
-
-screen_info(Ws, Parent, As=[A|_]) when is_atom(A) ->
- [ info(Ws, wse:screen(), "screen", What, Parent) || What <- As ].
-
-window_info(Ws, Parent, As=[A|_]) when is_atom(A) ->
- [ info(Ws, wse:window(), "window", What, Parent) || What <- As ].
-
-navigator_info(Ws, Parent, As=[A|_]) when is_atom(A) ->
- [ info(Ws, wse:navigator(), "navigator", What, Parent) || What <- As ].
-
-document_info(Ws, Parent, As=[A|_]) when is_atom(A) ->
- [ info(Ws, wse:document(), "document", What, Parent) || What <- As ].
-
-info(Ws, Object, ObjName, What, Parent) ->
- {ok,Value} = wse:get(Ws, Object, What),
- Text = ObjName++"."++to_text(What)++"="++to_text(Value),
- ElemNode = wse:createElement(Ws, "p"),
- TextNode = wse:createTextNode(Ws, Text),
- wse:appendChild(Ws, ElemNode, TextNode),
- wse:appendChild(Ws, Parent, ElemNode).
-
-to_text(X) ->
- lists:flatten(io_lib:format("~p", [X])).
-
-
-
-
diff --git a/deps/wse/src/wse_location_demo.erl b/deps/wse/src/wse_location_demo.erl
deleted file mode 100644
index 65d3c56..0000000
--- a/deps/wse/src/wse_location_demo.erl
+++ /dev/null
@@ -1,46 +0,0 @@
-%%%---- BEGIN COPYRIGHT -------------------------------------------------------
-%%%
-%%% Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-%%%
-%%% This software is licensed as described in the file COPYRIGHT, which
-%%% you should have received as part of this distribution. The terms
-%%% are also available at http://www.rogvall.se/docs/copyright.txt.
-%%%
-%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
-%%% copies of the Software, and permit persons to whom the Software is
-%%% furnished to do so, under the terms of the COPYRIGHT file.
-%%%
-%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-%%% KIND, either express or implied.
-%%%
-%%%---- END COPYRIGHT ---------------------------------------------------------
-%%% @author Tony Rogvall <tony@rogvall.se>
-%%% @copyright (C) 2014, Tony Rogvall
-%%% @doc
-%%% This demo is called directly from web page
-%%% @end
-%%% Created : 24 Apr 2014 by Tony Rogvall <tony@rogvall.se>
-
--module(wse_location_demo).
--export([run/2,
- goto/1]).
-
--compile(export_all).
-
-run(Ws,_Id) ->
- io:format("location_demo: called\n"),
- register(wse_location_demo, self()),
- listen_loop(Ws).
-
-goto(Location) ->
- wse_location_demo ! {goto, Location}.
-
-listen_loop(Ws) ->
- receive
- {goto, Location} ->
- io:format("goto: ~p~n", [Location]),
- ok = wse:set(Ws, wse:window(), ["location", "href"], Location);
- {'DOWN',_Mon,process,_Pid,Reason} ->
- io:format("process crashed: ~p~n", [Reason])
- end,
- listen_loop(Ws).
diff --git a/deps/wse/src/wse_raphael_demo.erl b/deps/wse/src/wse_raphael_demo.erl
deleted file mode 100644
index a73b322..0000000
--- a/deps/wse/src/wse_raphael_demo.erl
+++ /dev/null
@@ -1,73 +0,0 @@
-%%%---- BEGIN COPYRIGHT -------------------------------------------------------
-%%%
-%%% Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-%%%
-%%% This software is licensed as described in the file COPYRIGHT, which
-%%% you should have received as part of this distribution. The terms
-%%% are also available at http://www.rogvall.se/docs/copyright.txt.
-%%%
-%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
-%%% copies of the Software, and permit persons to whom the Software is
-%%% furnished to do so, under the terms of the COPYRIGHT file.
-%%%
-%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-%%% KIND, either express or implied.
-%%%
-%%%---- END COPYRIGHT ---------------------------------------------------------
-%%% @author Tony Rogvall <tony@rogvall.se>
-%%% @copyright (C) 2014, Tony Rogvall
-%%% @doc
-%%% This demo is called directly from web page
-%%% @end
-%%% Created : 9 Feb 2014 by Tony Rogvall <tony@rogvall.se>
-
--module(wse_raphael_demo).
-
--export([run/2]).
-
-%%
-%% Small demo
-%%
-run(Ws, Where) ->
- io:format("raphael_demo: called\n"),
- ok = wse:load(Ws, "raphael-min.js"),
- {ok,Paper} = raphael:new(Ws, Where, 640, 540),
-
- %% must create the image element here!
- {ok,Image} = wse:load_image(Ws, "bd.jpg"),
- {ok,Src} = wse:get(Ws, Image, "src"),
- {ok,_I1} = raphael:image(Ws, Paper, Src, 140, 140, 320, 240),
- {ok,I2} = raphael:image(Ws, Paper, Src, 140, 380, 320, 240),
- raphael:attr(Ws, I2, "transform", "s1-1"),
- raphael:attr(Ws, I2, "opacity", "0.5"),
- {ok,R6} = raphael:rect(Ws, Paper, 0, 380, 600, 160),
- raphael:attr(Ws, R6, "fill", "90-#333-#333"),
- raphael:attr(Ws, R6, "stroke", "none"),
- raphael:attr(Ws, R6, "opacity", "0.5"),
-
-
- {ok,C1} = raphael:circle(Ws, Paper, 10, 10, 10),
- raphael:attr(Ws, C1, "fill", "#FF0000"),
- {ok,C2} = raphael:circle(Ws, Paper, 40, 10, 10),
- raphael:attr(Ws, C2, "fill", "#00FF00"),
- {ok,C3} = raphael:circle(Ws, Paper, 70, 10, 10),
- raphael:attr(Ws, C3, "fill", "#0000FF"),
- {ok,C4} = raphael:circle(Ws, Paper, 100, 10, 10),
- raphael:attr(Ws, C4, "fill", "90-#fff-#000"),
-
- {ok,R1} = raphael:rect(Ws, Paper, 10, 30, 10, 10),
- raphael:attr(Ws, R1, "fill", "#FF0000"),
- {ok,R2} = raphael:rect(Ws, Paper, 40, 30, 10, 10),
- raphael:attr(Ws, R2, "fill", "#00FF00"),
-
- {ok,R3} = raphael:rect(Ws, Paper, 70, 30, 10, 10),
- raphael:attr(Ws, R3, "fill", "#0000FF"),
- {ok,R4} = raphael:rect(Ws, Paper, 100, 30, 10, 10),
- raphael:attr(Ws, R4, "fill", "90-#fff-#000"),
-
-
- ok.
-
-
-
-
diff --git a/deps/wse/src/wse_table_demo.erl b/deps/wse/src/wse_table_demo.erl
deleted file mode 100644
index b1c547f..0000000
--- a/deps/wse/src/wse_table_demo.erl
+++ /dev/null
@@ -1,109 +0,0 @@
-%%%---- BEGIN COPYRIGHT -------------------------------------------------------
-%%%
-%%% Copyright (C) 2007 - 2014, Rogvall Invest AB, <tony@rogvall.se>
-%%%
-%%% This software is licensed as described in the file COPYRIGHT, which
-%%% you should have received as part of this distribution. The terms
-%%% are also available at http://www.rogvall.se/docs/copyright.txt.
-%%%
-%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
-%%% copies of the Software, and permit persons to whom the Software is
-%%% furnished to do so, under the terms of the COPYRIGHT file.
-%%%
-%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-%%% KIND, either express or implied.
-%%%
-%%%---- END COPYRIGHT ---------------------------------------------------------
-%%% @author Tony Rogvall <tony@rogvall.se>
-%%% @copyright (C) 2014, Tony Rogvall
-%%% @doc
-%%% This demo is called directly from web page
-%%% @end
-%%% Created : 24 Apr 2014 by Tony Rogvall <tony@rogvall.se>
-
--module(wse_table_demo).
--export([run/2]).
-
--compile(export_all).
-
-table_data() ->
- [ ["1111", on, 1],
- ["1112", off, 2],
- ["1113", off, 3],
- ["1114", off, 4],
- ["1115", off, 5]
- ].
-
-run(Ws, Where) ->
- io:format("table_demo: called\n"),
-
- Parent = wse:id(Where),
- {Table,TableElems} = make_table(Ws, table_data()),
- wse:set(Ws, Table, "border", "2"),
- wse:appendChild(Ws, Parent, Table),
- update_loop(Ws, TableElems, 1).
-
-update_loop(Ws, Rs, I) ->
- update_rows(Ws, Rs, 0, I),
- timer:sleep(1000),
- update_loop(Ws, Rs, I+1).
-
-update_rows(Ws, [{Tr,Tds}|Rs], Ri, I) ->
- {ok,Style} = wse:get(Ws, Tr, "style"),
- case Ri rem 2 of
- 0 -> wse:set(Ws, Style, "backgroundColor", "rgb(0,255,0)");
- 1 -> wse:set(Ws, Style, "backgroundColor", "rgb(255,0,0)")
- end,
- I1 = update_row(Ws, Tds, I),
- update_rows(Ws, Rs, Ri+1, I1);
-update_rows(_Ws, [], _Ri, _I) ->
- ok.
-
-update_row(Ws, [{_Td,Txt}|Tds], I) ->
- wse:set(Ws, Txt, "nodeValue", integer_to_list(I)),
- update_row(Ws, Tds, I+1);
-update_row(_Ws, [], I) ->
- I.
-
-
-%%
-%% return:
-%% {Table,[{Tr1,[Td11,Td12,..Td1m1]},
-%% {Tr2,[Td21,Td22,..Td2m1]}
-%% {Trn,[Tdn1,Tn22,..Tdnmn]}]}
-%%
-make_table(Ws, TableData) ->
- %% create a table from table data
- Table = wse:createElement(Ws, "table"),
- TBody = wse:createElement(Ws, "tbody"),
- TableElems =
- [ begin
- Tr = wse:createElement(Ws, "tr"),
- R = {Tr, [begin Td = wse:createElement(Ws, "td"),
- Text = lists:flatten(io_lib:format("~p", [Col])),
- TextNode = wse:createTextNode(Ws, Text),
- wse:appendChild(Ws, Td, TextNode),
- wse:appendChild(Ws, Tr, Td),
- {Td,TextNode}
- end || Col <- Row ]},
- wse:appendChild(Ws, TBody, Tr),
- R
- end || Row <- TableData ],
- wse:appendChild(Ws, Table, TBody),
- {Table, TableElems}.
-
-
-info(Ws, Object, ObjName, What, Parent) ->
- {ok,Value} = wse:get(Ws, Object, What),
- Text = ObjName++"."++to_text(What)++"="++to_text(Value),
- ElemNode = wse:createElement(Ws, "p"),
- TextNode = wse:createTextNode(Ws, Text),
- wse:appendChild(Ws, ElemNode, TextNode),
- wse:appendChild(Ws, Parent, ElemNode).
-
-to_text(X) ->
- lists:flatten(io_lib:format("~p", [X])).
-
-
-
-
diff --git a/packaging/tizen.config b/packaging/tizen.config
index 6bdc2db..8fd7198 100644
--- a/packaging/tizen.config
+++ b/packaging/tizen.config
@@ -28,7 +28,6 @@
compiler,
ssl,
asn1,
- wse,
%% RVI-specific apps.
%% Do not touch unless you are replacing apps with your own
diff --git a/rebar.config b/rebar.config
index 96de275..21d3bb8 100644
--- a/rebar.config
+++ b/rebar.config
@@ -30,6 +30,6 @@
{bt, ".*", {git, "git://github.com/magnusfeuer/bt.git", "HEAD"}},
{dthread, ".*", {git, "git://github.com/tonyrog/dthread.git", "HEAD"}},
{uart, ".*", {git, "git://github.com/tonyrog/uart.git", "HEAD"}},
- {gsms, ".*", {git, "git://github.com/tonyrog/gsms.git", "HEAD"}},
- {wse, ".*", {git, "git://github.com/tonyrog/wse.git", "HEAD"}}
+ {gsms, ".*", {git, "git://github.com/tonyrog/gsms.git", "HEAD"}}
+%% {wse, ".*", {git, "git://github.com/tonyrog/wse.git", "HEAD"}}
]}.
diff --git a/rvi_sample.config b/rvi_sample.config
index 81abb9a..3cfc286 100644
--- a/rvi_sample.config
+++ b/rvi_sample.config
@@ -28,7 +28,6 @@
compiler,
ssl,
asn1,
- wse,
%% RVI-specific apps.
%% Do not touch unless you are replacing apps with your own