From 0e76a0347c53476bd959f0ebaeef76a697f511bc Mon Sep 17 00:00:00 2001 From: gered Date: Sat, 7 May 2016 16:20:54 -0400 Subject: [PATCH] fix chat-demo - dependencies updated - removed old netty adapter code - generally converted it into something more resembling a modern clojure web app --- chat-demo/Procfile | 2 +- chat-demo/cljs/bc/core.cljs | 52 --- chat-demo/cljs/bc/dom-helpers.cljs | 141 ------- chat-demo/project.clj | 51 ++- chat-demo/resources/dev/index-dev.html | 37 -- chat-demo/resources/dev/js/compile_target_dir | 0 .../resources/{public => html}/index.html | 10 +- chat-demo/resources/public/cljs/app.js | 357 ++++++++++++++++++ .../resources/public/{css => }/default.css | 0 .../resources/public/js/compile_target_dir | 0 chat-demo/src/chat_demo/client.cljs | 62 +++ chat-demo/src/chat_demo/core.clj | 75 ---- chat-demo/src/chat_demo/server.clj | 61 +++ chat-demo/src/tasks/browser_repl.clj | 6 - chat-demo/src/tasks/build_advanced_js.clj | 6 - chat-demo/src/tasks/build_dev_js.clj | 38 -- 16 files changed, 529 insertions(+), 369 deletions(-) delete mode 100644 chat-demo/cljs/bc/core.cljs delete mode 100644 chat-demo/cljs/bc/dom-helpers.cljs delete mode 100644 chat-demo/resources/dev/index-dev.html delete mode 100644 chat-demo/resources/dev/js/compile_target_dir rename chat-demo/resources/{public => html}/index.html (70%) create mode 100644 chat-demo/resources/public/cljs/app.js rename chat-demo/resources/public/{css => }/default.css (100%) delete mode 100644 chat-demo/resources/public/js/compile_target_dir create mode 100644 chat-demo/src/chat_demo/client.cljs delete mode 100644 chat-demo/src/chat_demo/core.clj create mode 100644 chat-demo/src/chat_demo/server.clj delete mode 100644 chat-demo/src/tasks/browser_repl.clj delete mode 100644 chat-demo/src/tasks/build_advanced_js.clj delete mode 100644 chat-demo/src/tasks/build_dev_js.clj diff --git a/chat-demo/Procfile b/chat-demo/Procfile index e754de0..076f0d4 100644 --- a/chat-demo/Procfile +++ b/chat-demo/Procfile @@ -1 +1 @@ -web: lein trampoline run -m chat-demo.core +web: lein trampoline run -m chat-demo.server diff --git a/chat-demo/cljs/bc/core.cljs b/chat-demo/cljs/bc/core.cljs deleted file mode 100644 index f7159f9..0000000 --- a/chat-demo/cljs/bc/core.cljs +++ /dev/null @@ -1,52 +0,0 @@ -(ns bc.core - (:require - [bc.dom-helpers :as dom] - [goog.net.BrowserChannel :as goog-browserchannel] - [goog.events :as events] - [goog.events.KeyCodes :as key-codes] - [goog.events.KeyHandler :as key-handler])) - -(defn handler [] - (let [h (goog.net.BrowserChannel.Handler.)] - (set! (.-channelOpened h) - (fn [channel] - (enable-chat))) - (set! (.-channelHandleArray h) - (fn [x data] - (let [msg (aget data "msg")] - (dom/append (dom/get-element "room") (dom/element :div (str "MSG::" msg)))))) - h)) - -(defn say [text] - (.sendMap channel (doto (js-obj) - (aset "msg" text)) )) - -(defn enable-chat [] - (let [msg-input (dom/get-element "msg-input") - send-button (dom/get-element "send-button") - handler (fn [e] - (say (dom/value msg-input)) - (dom/set-value msg-input ""))] - (dom/set-disabled msg-input false) - (dom/set-disabled send-button false) - (events/listen (goog.events.KeyHandler. msg-input) - "key" - (fn [e] - (when (= (.-keyCode e) key-codes/ENTER) - (handler e)))) - (events/listen send-button - "click" - handler))) - -(def channel (goog.net.BrowserChannel.)) - -(defn ^:export run [] - (events/listen js/window "unload" #(do - (.disconnect channel ()) - (events/removeAll))) - (doto (.. channel getChannelDebug getLogger) - (.setLevel goog.debug.Logger.Level.OFF)) - (doto channel - (.setHandler (handler)) - (.connect "/channel/test" "/channel/bind") - )) diff --git a/chat-demo/cljs/bc/dom-helpers.cljs b/chat-demo/cljs/bc/dom-helpers.cljs deleted file mode 100644 index a65b80e..0000000 --- a/chat-demo/cljs/bc/dom-helpers.cljs +++ /dev/null @@ -1,141 +0,0 @@ -; Copyright (c) Rich Hickey. All rights reserved. -; The use and distribution terms for this software are covered by the -; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) -; which can be found in the file epl-v10.html at the root of this distribution. -; By using this software in any fashion, you are agreeing to be bound by -; the terms of this license. -; You must not remove this notice, or any other, from this software. - -(ns bc.dom-helpers - (:require [clojure.string :as string] - [goog.style :as style] - [goog.dom :as dom] - [goog.dom.classes :as classes] - [goog.dom.forms :as forms] - [goog.fx :as fx] - [goog.fx.dom :as fx-dom] - [goog.Timer :as timer] - )) - -(defn get-element - "Return the element with the passed id." - [id] - (dom/getElement (name id))) - -(defn show-element [e b] - (style/showElement e b)) - -(defn add-remove-class [e add-classes remove-classes] - (classes/addRemove e remove-classes add-classes)) - -(defn get-radio-value [form-name name] - (forms/getValueByName (get-element form-name) name)) - -(defn value [element] - (forms/getValue element)) - -(defn set-value [element] - (forms/setValue element)) - -(defn set-disabled [element disabled] - (forms/setDisabled element disabled)) - -(defn append - "Append all children to parent." - [parent & children] - (do (doseq [child children] - (dom/appendChild parent child)) - parent)) - -(defn set-text - "Set the text content for the passed element returning the - element. If a keyword is passed in the place of e, the element with - that id will be used and returned." - [e s] - (let [e (if (or (keyword? e) (string? e)) (get-element e) e)] - (doto e - (dom/setTextContent s)))) - -(defn normalize-args [tag args] - (let [parts (string/split tag #"(\.|#)") - [tag attrs] [(first parts) - (apply hash-map (map #(cond (= % ".") :class - (= % "#") :id - :else %) - (rest parts)))]] - (if (map? (first args)) - [tag (merge attrs (first args)) (rest args)] - [tag attrs args]))) - -;; TODO: replace call to .strobj with whatever we come up with for -;; creating js objects from Clojure maps. - -(defn element - "Create a dom element using a keyword for the element name and a map - for the attributes. Append all children to parent. If the first - child is a string then the string will be set as the text content of - the parent and all remaining children will be appended." - [tag & args] - (let [[tag attrs children] (normalize-args tag args) - ;; keyword/string mangling screws up (name tag) - parent (dom/createDom (subs tag 1) - (. (reduce (fn [m [k v]] - (assoc m k v)) - {} - (map #(vector (name %1) %2) - (keys attrs) - (vals attrs))) -strobj)) - [parent children] (if (string? (first children)) - [(set-text (element tag attrs) (first children)) - (rest children)] - [parent children])] - (apply append parent children))) - -(defn remove-children - "Remove all children from the element with the passed id." - [parent-el] - (dom/removeChildren parent-el)) - -(defn html - "Create a dom element from an html string." - [s] - (dom/htmlToDocumentFragment s)) - -(defn- element-arg? [x] - (or (keyword? x) - (map? x) - (string? x))) - -(defn build - "Build up a dom element from nested vectors." - [x] - (if (vector? x) - (let [[parent children] (if (keyword? (first x)) - [(apply element (take-while element-arg? x)) - (drop-while element-arg? x)] - [(first x) (rest x)]) - children (map build children)] - (apply append parent children)) - x)) - -(defn insert-at - "Insert a child element at a specific location." - [parent child index] - (dom/insertChildAt parent child index)) - -(defn set-timeout [func ttime] - (timer/callOnce func ttime)) - -(defn set-position [e x y] - (style/setPosition e x y)) - -(defn get-position [e] - (style/getPosition e)) - -(defn toggle-class [el classname] - (classes/toggle el classname)) - -(defn add-class [el classname] - (classes/add el classname)) -(defn remove-class [el classname] - (classes/remove el classname)) diff --git a/chat-demo/project.clj b/chat-demo/project.clj index 02a33c0..740d9de 100644 --- a/chat-demo/project.clj +++ b/chat-demo/project.clj @@ -1,11 +1,44 @@ (defproject chat-demo "0.0.1" - :description "Example for using BrowserChannel and a client side with ClojureScript" - :dependencies [[org.clojure/clojure "1.3.0"] - [ring/ring-core "1.1.0-SNAPSHOT" :exclusions [javax.servlet/servlet-api]] - [org.clojure/clojurescript "0.0-1011" :exclusions [org.clojure/google-closure-library]] - [net.thegeez/google-closure-library "0.0-1698"] - [net.thegeez/clj-browserchannel-server "0.0.4"] - [net.thegeez/clj-browserchannel-jetty-adapter "0.0.1"] - #_[net.thegeez/clj-browserchannel-netty-adapter "0.0.1"] - ] + :description "Example for using BrowserChannel and a client side with ClojureScript" + + :main chat-demo.server + + :dependencies [[org.clojure/clojure "1.8.0"] + [org.clojure/clojurescript "1.8.51"] + [ring/ring-defaults "0.2.0" :exclusions [javax.servlet/servlet-api]] + [ring/ring-devel "1.4.0"] + [compojure "1.4.0"] + [clj-pebble "0.2.0"] + [prismatic/dommy "1.1.0"] + [net.thegeez/clj-browserchannel-server "0.2.1"] + [net.thegeez/clj-browserchannel-jetty-adapter "0.0.8"] + [environ "1.0.3"]] + + :plugins [[lein-cljsbuild "1.1.3"] + [lein-environ "1.0.3"]] + + :clean-targets ^{:protect false} [:target-path + [:cljsbuild :builds :main :compiler :output-dir] + [:cljsbuild :builds :main :compiler :output-to]] + :cljsbuild {:builds {:main + {:source-paths ["src"] + :compiler {:output-to "resources/public/cljs/app.js" + :output-dir "resources/public/cljs/target" + :source-map true + :optimizations :none + :pretty-print true}}}} + + :profiles {:dev {:env {:dev "true"}} + + :uberjar {:env {} + :aot :all + :hooks [leiningen.cljsbuild] + :cljsbuild {:jar true + :builds {:main + {:compiler ^:replace {:output-to "resources/public/cljs/app.js" + :optimizations :advanced + :pretty-print false}}}}}} + + :aliases {"uberjar" ["do" ["clean"] ["uberjar"]]} + ) diff --git a/chat-demo/resources/dev/index-dev.html b/chat-demo/resources/dev/index-dev.html deleted file mode 100644 index 47cdc1a..0000000 --- a/chat-demo/resources/dev/index-dev.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - BrowserChannel - - - - - -
-
-
- - -
-
clj-browserchannel-demo
-
- Written by: Gijs Stuurman - / @thegeez - / Blog / GitHub
- - - - - - diff --git a/chat-demo/resources/dev/js/compile_target_dir b/chat-demo/resources/dev/js/compile_target_dir deleted file mode 100644 index e69de29..0000000 diff --git a/chat-demo/resources/public/index.html b/chat-demo/resources/html/index.html similarity index 70% rename from chat-demo/resources/public/index.html rename to chat-demo/resources/html/index.html index 5eda764..9b4011e 100644 --- a/chat-demo/resources/public/index.html +++ b/chat-demo/resources/html/index.html @@ -8,7 +8,7 @@ - +
@@ -17,14 +17,16 @@
-
clj-browserchannel-demo
+
clj-browserchannel-demo
Written by: Gijs Stuurman / @thegeez / Blog / GitHub
- + {% if dev %}{% endif %} + + {% if dev %}{% endif %} diff --git a/chat-demo/resources/public/cljs/app.js b/chat-demo/resources/public/cljs/app.js new file mode 100644 index 0000000..fd793a1 --- /dev/null +++ b/chat-demo/resources/public/cljs/app.js @@ -0,0 +1,357 @@ +if(typeof Math.imul == "undefined" || (Math.imul(0xffffffff,5) == 0)) { + Math.imul = function (a, b) { + var ah = (a >>> 16) & 0xffff; + var al = a & 0xffff; + var bh = (b >>> 16) & 0xffff; + var bl = b & 0xffff; + // the shift by 0 fixes the sign on the high part + // the final |0 converts the unsigned value into a signed value + return ((al * bl) + (((ah * bl + al * bh) << 16) >>> 0)|0); + } +} + + +;(function(){ +var f,aa=aa||{},r=this;function ba(){} +function v(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null"; +else if("function"==b&&"undefined"==typeof a.call)return"object";return b}function ca(a){return"array"==v(a)}function da(a){var b=v(a);return"array"==b||"object"==b&&"number"==typeof a.length}function fa(a){return"string"==typeof a}function ga(a){return"number"==typeof a}function ia(a){return"function"==v(a)}var ka="closure_uid_"+(1E9*Math.random()>>>0),na=0;function oa(a,b,c){return a.call.apply(a.bind,arguments)} +function pa(a,b,c){if(!a)throw Error();if(2/g,Aa=/"/g,Ba=/'/g,Da=/\x00/g,Ea=/[\x00&<>"']/,Fa={"\x00":"\\0","\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r","\t":"\\t","\x0B":"\\x0B",'"':'\\"',"\\":"\\\\","\x3c":"\x3c"},Ga={"'":"\\'"}; +function Ha(a,b){return ab?1:0};function Ja(a,b,c){for(var d in a)b.call(c,a[d],d,a)}function Ka(a,b){for(var c in a)if(b.call(void 0,a[c],c,a))return!0;return!1}function La(a){var b=[],c=0,d;for(d in a)b[c++]=a[d];return b}function Ma(a){var b=[],c=0,d;for(d in a)b[c++]=d;return b}function Na(a){return null!==a&&"withCredentials"in a}var Oa="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "); +function Pa(a,b){for(var c,d,e=1;ec?Math.max(0,a.length+c):c;if(fa(a))return fa(b)&&1==b.length?a.indexOf(b,c):-1;for(;cb?null:fa(a)?a.charAt(b):a[b]}function ab(a){return Va.concat.apply(Va,arguments)}function bb(a){var b=a.length;if(0>>16&65535)*d+c*(b>>>16&65535)<<16>>>0)|0};function qc(a){a=pc(a|0,-862048943);return pc(a<<15|a>>>-15,461845907)}function rc(a,b){var c=(a|0)^(b|0);return pc(c<<13|c>>>-13,5)+-430675100|0} +function sc(a,b){var c=(a|0)^b,c=pc(c^c>>>16,-2048144789),c=pc(c^c>>>13,-1028477387);return c^c>>>16}function tc(a){var b;a:{b=1;for(var c=0;;)if(b>2)} +function Ac(a,b,c,d,e){this.Fc=a;this.name=b;this.Ib=c;this.Yb=d;this.ma=e;this.i=2154168321;this.D=4096}f=Ac.prototype;f.toString=function(){return this.Ib};f.equiv=function(a){return this.u(null,a)};f.u=function(a,b){return b instanceof Ac?this.Ib===b.Ib:!1}; +f.call=function(){function a(a,b,c){return L.g?L.g(b,this,c):L.call(null,b,this,c)}function b(a,b){return L.a?L.a(b,this):L.call(null,b,this)}var c=null,c=function(c,e,g){switch(arguments.length){case 2:return b.call(this,0,e);case 3:return a.call(this,0,e,g)}throw Error("Invalid arity: "+arguments.length);};c.a=b;c.g=a;return c}();f.apply=function(a,b){return this.call.apply(this,[this].concat(tb(b)))};f.b=function(a){return L.a?L.a(a,this):L.call(null,a,this)}; +f.a=function(a,b){return L.g?L.g(a,this,b):L.call(null,a,this,b)};f.O=function(){return this.ma};f.P=function(a,b){return new Ac(this.Fc,this.name,this.Ib,this.Yb,b)};f.N=function(){var a=this.Yb;return null!=a?a:this.Yb=a=zc(tc(this.name),xc(this.Fc))};f.U=function(a,b){return K(b,this.Ib)}; +function M(a){if(null==a)return null;if(null!=a&&(a.i&8388608||a.af))return a.Z(null);if(pb(a)||"string"===typeof a)return 0===a.length?null:new N(a,0,null);if(B(Zb,a))return $b(a);throw Error([E(a),E(" is not ISeqable")].join(""));}function O(a){if(null==a)return null;if(null!=a&&(a.i&64||a.bc))return a.ja(null);a=M(a);return null==a?null:G(a)}function Bc(a){return null!=a?null!=a&&(a.i&64||a.bc)?a.va(null):(a=M(a))?H(a):P:P} +function Q(a){return null==a?null:null!=a&&(a.i&128||a.Oc)?a.qa(null):M(Bc(a))}var Cc=function Cc(b){for(var c=[],d=arguments.length,e=0;;)if(e=d)return-1;!(0c&&(c+=d,c=0>c?0:c);for(;;)if(cc?d+c:c;for(;;)if(0<=c){if(Cc.a(Rc?Rc(a,c):Sc.call(null,a,c),b))return c;--c}else return-1}function Tc(a,b){this.c=a;this.l=b}Tc.prototype.ra=function(){return this.la?0:a};f.N=function(){return Gc(this)};f.u=function(a,b){return Uc.a?Uc.a(this,b):Uc.call(null,this,b)};f.ea=function(){return P};f.ha=function(a,b){return Oc(this.c,b,this.c[this.l],this.l+1)};f.ia=function(a,b,c){return Oc(this.c,b,c,this.l)};f.ja=function(){return this.c[this.l]};f.va=function(){return this.l+1>1&1431655765;a=(a&858993459)+(a>>2&858993459);return 16843009*(a+(a>>4)&252645135)>>24} +var E=function E(b){for(var c=[],d=arguments.length,e=0;;)if(ea?0:a-1>>>5<<5}function ge(a,b,c){for(;;){if(0===b)return c;var d=ee(a);d.c[0]=c;c=d;b-=5}}var he=function he(b,c,d,e){var g=new de(d.F,tb(d.c)),h=b.j-1>>>c&31;5===c?g.c[h]=e:(d=d.c[h],b=null!=d?he(b,c-5,d,e):ge(null,c-5,e),g.c[h]=b);return g}; +function ie(a,b){throw Error([E("No item "),E(a),E(" in vector of length "),E(b)].join(""));}function je(a,b){if(b>=fe(a))return a.fa;for(var c=a.root,d=a.shift;;)if(0>>d&31],d=e;else return c.c}function ke(a,b){return 0<=b&&b>>c&31;b=le(b,c-5,d.c[k],e,g);h.c[k]=b}return h};function me(a,b,c,d,e,g){this.l=a;this.Lc=b;this.c=c;this.Va=d;this.start=e;this.end=g} +me.prototype.ra=function(){return this.l=this.j)return new N(this.fa,0,null);var a;a:{a=this.root;for(var b=this.shift;;)if(0this.j-fe(this)){for(var c=this.fa.length,d=Array(c+1),e=0;;)if(e>>5>1<b)a=new Vd(null,b,5,Wd,a,null);else for(var c=32,d=(new Vd(null,32,5,Wd,a.slice(0,32),null)).ac(null);;)if(cb||this.end<=this.start+b?ie(b,this.end-this.start):F.a(this.Va,this.start+b)}; +f.ya=function(a,b,c){return 0>b||this.end<=this.start+b?c:F.g(this.Va,this.start+b,c)};f.Ad=function(a,b,c){var d=this.start+b;a=this.o;c=bd.g(this.Va,d,c);b=this.start;var e=this.end,d=d+1,d=e>d?e:d;return ye.pa?ye.pa(a,c,b,d,null):ye.call(null,a,c,b,d,null)};f.O=function(){return this.o};f.da=function(){return this.end-this.start};f.N=function(){var a=this.s;return null!=a?a:this.s=a=Gc(this)};f.u=function(a,b){return Uc(this,b)};f.ea=function(){return fd(Yc,this.o)}; +f.ha=function(a,b){return Kc(this,b)};f.ia=function(a,b,c){return Lc(this,b,c)};f.qc=function(a,b,c){if("number"===typeof b)return Rb(this,b,c);throw Error("Subvec's key for assoc must be a number.");};f.Z=function(){var a=this;return function(b){return function d(e){return e===a.end?null:V(F.a(a.Va,e),new Fd(null,function(){return function(){return d(e+1)}}(b),null,null))}}(this)(a.start)}; +f.P=function(a,b){return ye.pa?ye.pa(b,this.Va,this.start,this.end,this.s):ye.call(null,b,this.Va,this.start,this.end,this.s)};f.Y=function(a,b){var c=this.o,d=Rb(this.Va,this.end,b),e=this.start,g=this.end+1;return ye.pa?ye.pa(c,d,e,g,null):ye.call(null,c,d,e,g,null)}; +f.call=function(){var a=null,a=function(a,c,d){switch(arguments.length){case 2:return this.T(null,c);case 3:return this.ya(null,c,d)}throw Error("Invalid arity: "+arguments.length);};a.a=function(a,c){return this.T(null,c)};a.g=function(a,c,d){return this.ya(null,c,d)};return a}();f.apply=function(a,b){return this.call.apply(this,[this].concat(tb(b)))};f.b=function(a){return this.T(null,a)};f.a=function(a,b){return this.ya(null,a,b)};xe.prototype[rb]=function(){return Ec(this)}; +function ye(a,b,c,d,e){for(;;)if(b instanceof xe)c=b.start+c,d=b.start+d,b=b.Va;else{var g=T(b);if(0>c||0>d||c>g||d>g)throw Error("Index out of bounds");return new xe(a,b,c,d,e)}}function ve(a){for(var b=[],c=arguments.length,d=0;;)if(d>>c&31;if(5===c)b=e;else{var h=d.c[g];b=null!=h?Ae(b,c-5,h,e):ge(b.root.F,c-5,e)}d.c[g]=b;return d}; +function ne(a,b,c,d){this.j=a;this.shift=b;this.root=c;this.fa=d;this.D=88;this.i=275}f=ne.prototype; +f.sc=function(a,b){if(this.root.F){if(32>this.j-fe(this))this.fa[this.j&31]=b;else{var c=new de(this.root.F,this.fa),d=[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null];d[0]=b;this.fa=d;if(this.j>>>5>1<>>a&31,m=g(a-5,l.c[n]);l.c[n]=m}return l}}(this).call(null,d.shift,d.root),d.root=a),this;if(b===d.j)return ec(this,c);throw Error([E("Index "),E(b),E(" out of bounds for TransientVector of length"),E(d.j)].join(""));}throw Error("assoc! after persistent!");}; +f.da=function(){if(this.root.F)return this.j;throw Error("count after persistent!");};f.T=function(a,b){if(this.root.F)return ke(this,b)[b&31];throw Error("nth after persistent!");};f.ya=function(a,b,c){return 0<=b&&bb?4:2*(b+1));od(this.c,0,c,0,2*b);return new We(a,this.S,c)}; +f.Bc=function(){return Xe?Xe(this.c):Ze.call(null,this.c)};f.Bb=function(a,b,c,d){var e=1<<(b>>>a&31);if(0===(this.S&e))return d;var g=xd(this.S&e-1),e=this.c[2*g],g=this.c[2*g+1];return null==e?g.Bb(a+5,b,c,d):Se(c,e)?g:d}; +f.Ma=function(a,b,c,d,e,g){var h=1<<(c>>>b&31),k=xd(this.S&h-1);if(0===(this.S&h)){var l=xd(this.S);if(2*l>>b&31]=$e.Ma(a,b+5,c,d,e,g);for(e=d=0;;)if(32>d)0!== +(this.S>>>d&1)&&(k[d]=null!=this.c[e]?$e.Ma(a,b+5,yc(this.c[e]),this.c[e],this.c[e+1],g):this.c[e+1],e+=2),d+=1;else break;return new af(a,l+1,k)}b=Array(2*(l+4));od(this.c,0,b,0,2*k);b[2*k]=d;b[2*k+1]=e;od(this.c,2*k,b,2*(k+1),2*(l-k));g.Wa=!0;a=this.Nb(a);a.c=b;a.S|=h;return a}l=this.c[2*k];h=this.c[2*k+1];if(null==l)return l=h.Ma(a,b+5,c,d,e,g),l===h?this:Ue(this,a,2*k+1,l);if(Se(d,l))return e===h?this:Ue(this,a,2*k+1,e);g.Wa=!0;g=b+5;d=bf?bf(a,g,l,h,c,d,e):cf.call(null,a,g,l,h,c,d,e);e=2*k;k= +2*k+1;a=this.Nb(a);a.c[e]=null;a.c[k]=d;return a}; +f.La=function(a,b,c,d,e){var g=1<<(b>>>a&31),h=xd(this.S&g-1);if(0===(this.S&g)){var k=xd(this.S);if(16<=k){h=[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null];h[b>>>a&31]=$e.La(a+5,b,c,d,e);for(d=c=0;;)if(32>c)0!==(this.S>>>c&1)&&(h[c]=null!=this.c[d]?$e.La(a+5,yc(this.c[d]),this.c[d],this.c[d+1],e):this.c[d+1],d+=2),c+=1;else break;return new af(null,k+1,h)}a=Array(2*(k+1));od(this.c, +0,a,0,2*h);a[2*h]=c;a[2*h+1]=d;od(this.c,2*h,a,2*(h+1),2*(k-h));e.Wa=!0;return new We(null,this.S|g,a)}var l=this.c[2*h],g=this.c[2*h+1];if(null==l)return k=g.La(a+5,b,c,d,e),k===g?this:new We(null,this.S,Te(this.c,2*h+1,k));if(Se(c,l))return d===g?this:new We(null,this.S,Te(this.c,2*h+1,d));e.Wa=!0;e=this.S;k=this.c;a+=5;a=df?df(a,l,g,b,c,d):cf.call(null,a,l,g,b,c,d);c=2*h;h=2*h+1;d=tb(k);d[c]=null;d[h]=a;return new We(null,e,d)};f.nb=function(){return new Ve(this.c,0,null,null)}; +var $e=new We(null,0,[]);function ef(a,b,c){this.c=a;this.l=b;this.Na=c}ef.prototype.ra=function(){for(var a=this.c.length;;){if(null!=this.Na&&this.Na.ra())return!0;if(this.l>>a&31];return null!=e?e.Bb(a+5,b,c,d):d};f.Ma=function(a,b,c,d,e,g){var h=c>>>b&31,k=this.c[h];if(null==k)return a=Ue(this,a,h,$e.Ma(a,b+5,c,d,e,g)),a.j+=1,a;b=k.Ma(a,b+5,c,d,e,g);return b===k?this:Ue(this,a,h,b)}; +f.La=function(a,b,c,d,e){var g=b>>>a&31,h=this.c[g];if(null==h)return new af(null,this.j+1,Te(this.c,g,$e.La(a+5,b,c,d,e)));a=h.La(a+5,b,c,d,e);return a===h?this:new af(null,this.j,Te(this.c,g,a))};f.nb=function(){return new ef(this.c,0,null)};function hf(a,b,c){b*=2;for(var d=0;;)if(da?d:Se(c,this.c[a])?this.c[a+1]:d}; +f.Ma=function(a,b,c,d,e,g){if(c===this.xb){b=hf(this.c,this.j,d);if(-1===b){if(this.c.length>2*this.j)return b=2*this.j,c=2*this.j+1,a=this.Nb(a),a.c[b]=d,a.c[c]=e,g.Wa=!0,a.j+=1,a;c=this.c.length;b=Array(c+2);od(this.c,0,b,0,c);b[c]=d;b[c+1]=e;g.Wa=!0;d=this.j+1;a===this.F?(this.c=b,this.j=d,a=this):a=new jf(this.F,this.xb,d,b);return a}return this.c[b+1]===e?this:Ue(this,a,b+1,e)}return(new We(a,1<<(this.xb>>>b&31),[null,this,null,null])).Ma(a,b,c,d,e,g)}; +f.La=function(a,b,c,d,e){return b===this.xb?(a=hf(this.c,this.j,c),-1===a?(a=2*this.j,b=Array(a+2),od(this.c,0,b,0,a),b[a]=c,b[a+1]=d,e.Wa=!0,new jf(null,this.xb,this.j+1,b)):Cc.a(this.c[a],d)?this:new jf(null,this.xb,this.j,Te(this.c,a+1,d))):(new We(null,1<<(this.xb>>>a&31),[null,this])).La(a,b,c,d,e)};f.nb=function(){return new Ve(this.c,0,null,null)}; +function cf(a){for(var b=[],c=arguments.length,d=0;;)if(dgb)return K(a,"#");K(a,c);if(0===ob.b(g))M(h)&&K(a,function(){var a=Cf.b(g);return x(a)?a:"..."}());else{if(M(h)){var l=O(h);b.g?b.g(l,a,g):b.call(null,l,a,g)}for(var n=Q(h),m=ob.b(g)-1;;)if(!n||null!=m&&0===m){M(n)&&0===m&&(K(a,d),K(a,function(){var a=Cf.b(g);return x(a)?a:"..."}()));break}else{K(a,d);var p=O(n);c=a;h=g;b.g?b.g(p,c,h):b.call(null,p,c,h);var q=Q(n);c=m-1;n=q;m=c}}return K(a,e)}finally{gb=k}} +function Df(a,b){for(var c=M(b),d=null,e=0,g=0;;)if(g2*this.aa&&Wf(this),!0):!1};function Wf(a){if(a.aa!=a.L.length){for(var b=0,c=0;bb)throw Error("Bad port number "+b);a.Tb=b}else a.Tb=null}function eg(a,b,c){bg(a);a.oa=c?gg(b,!0):b}function fg(a,b,c){bg(a);b instanceof hg?(a.Pa=b,a.Pa.Od(a.Ha)):(c||(b=ig(b,ng)),a.Pa=new hg(b,0,a.Ha))}function og(a,b,c){bg(a);a.Pa.set(b,c)}function pg(a,b,c){bg(a);ca(c)||(c=[String(c)]);qg(a.Pa,b,c)} +function rg(a){bg(a);og(a,"zx",Math.floor(2147483648*Math.random()).toString(36)+Math.abs(Math.floor(2147483648*Math.random())^ra()).toString(36));return a}function bg(a){if(a.kf)throw Error("Tried to modify a read-only Uri");}$f.prototype.Od=function(a){this.Ha=a;this.Pa&&this.Pa.Od(a);return this};function sg(a){return a instanceof $f?a.clone():new $f(a,void 0)}function tg(a,b,c,d){var e=new $f(null,void 0);a&&ag(e,a);b&&cg(e,b);c&&dg(e,c);d&&eg(e,d);return e} +function gg(a,b){return a?b?decodeURI(a.replace(/%25/g,"%2525")):decodeURIComponent(a):""}function ig(a,b,c){return fa(a)?(a=encodeURI(a).replace(b,ug),c&&(a=a.replace(/%25([0-9a-fA-F]{2})/g,"%$1")),a):null}function ug(a){a=a.charCodeAt(0);return"%"+(a>>4&15).toString(16)+(a&15).toString(16)}var jg=/[#\/\?@]/g,lg=/[\#\?:]/g,kg=/[\#\?]/g,ng=/[\#\?@]/g,mg=/#/g;function hg(a,b,c){this.aa=this.K=null;this.Aa=a||null;this.Ha=!!c} +function vg(a){a.K||(a.K=new Vf,a.aa=0,a.Aa&&Zf(a.Aa,function(b,c){a.add(decodeURIComponent(b.replace(/\+/g," ")),c)}))}f=hg.prototype;f.add=function(a,b){vg(this);this.Aa=null;a=wg(this,a);var c=this.K.get(a);c||this.K.set(a,c=[]);c.push(b);this.aa++;return this};f.remove=function(a){vg(this);a=wg(this,a);return this.K.uc(a)?(this.Aa=null,this.aa-=this.K.get(a).length,this.K.remove(a)):!1};f.clear=function(){this.K=this.Aa=null;this.aa=0};f.uc=function(a){vg(this);a=wg(this,a);return this.K.uc(a)}; +f.qb=function(){vg(this);for(var a=this.K.Ka(),b=this.K.qb(),c=[],d=0;dparseFloat(a))?String(b):a}(),Sg={}; +function Tg(a){var b;if(!(b=Sg[a])){b=0;for(var c=va(String(Rg)).split("."),d=va(String(a)).split("."),e=Math.max(c.length,d.length),g=0;0==b&&g=fh(this).value)for(ia(b)&&(b=b()),a=new Wg(a,String(b),this.qe),c&&(a.fe=c),c="log:"+a.nf,r.console&&(r.console.timeStamp?r.console.timeStamp(c):r.console.markTimeline&&r.console.markTimeline(c)),r.msWriteProfilerMark&&r.msWriteProfilerMark(c),c=this;c;){b=c;var d=a;if(b.ie)for(var e=0,g=void 0;g=b.ie[e];e++)g(d);c=c.getParent()}}; +f.Qa=function(a,b){this.log(ah,a,b)};f.Xb=function(a,b){this.log(bh,a,b)};f.info=function(a,b){this.log(ch,a,b)};var gh={},hh=null;function ih(a){hh||(hh=new Yg(""),gh[""]=hh,hh.Pd(dh));var b;if(!(b=gh[a])){b=new Yg(a);var c=a.lastIndexOf("."),d=a.substr(c+1),c=ih(a.substr(0,c));c.td||(c.td={});c.td[d]=b;b.ad=c;gh[a]=b}return b};function jh(){this.xe=ra()}new jh;jh.prototype.set=function(a){this.xe=a};jh.prototype.reset=function(){this.set(ra())};jh.prototype.get=function(){return this.xe};function kh(){0!=lh&&(mh[this[ka]||(this[ka]=++na)]=this);this.wc=this.wc;this.Zc=this.Zc}var lh=0,mh={};kh.prototype.wc=!1;kh.prototype.Dd=function(){if(!this.wc&&(this.wc=!0,this.za(),0!=lh)){var a=this[ka]||(this[ka]=++na);delete mh[a]}};kh.prototype.za=function(){if(this.Zc)for(;this.Zc.length;)this.Zc.shift()()};function nh(a,b){this.type=a;this.currentTarget=this.target=b;this.defaultPrevented=this.Ub=!1;this.ze=!0}nh.prototype.stopPropagation=function(){this.Ub=!0};nh.prototype.preventDefault=function(){this.defaultPrevented=!0;this.ze=!1};var oh=!Jg||9<=Vg,ph=Jg&&!Tg("9");!Mg||Tg("528");Lg&&Tg("1.9b")||Jg&&Tg("8")||Ig&&Tg("9.5")||Mg&&Tg("528");Lg&&!Tg("8")||Jg&&Tg("9");function qh(a){qh[" "](a);return a}qh[" "]=ba;function rh(a,b){nh.call(this,a?a.type:"");this.relatedTarget=this.currentTarget=this.target=null;this.charCode=this.keyCode=this.button=this.screenY=this.screenX=this.clientY=this.clientX=this.offsetY=this.offsetX=0;this.metaKey=this.shiftKey=this.altKey=this.ctrlKey=!1;this.dc=this.state=null;if(a){var c=this.type=a.type,d=a.changedTouches?a.changedTouches[0]:null;this.target=a.target||a.srcElement;this.currentTarget=b;var e=a.relatedTarget;if(e){if(Lg){var g;a:{try{qh(e.nodeName);g=!0;break a}catch(h){}g= +!1}g||(e=null)}}else"mouseover"==c?e=a.fromElement:"mouseout"==c&&(e=a.toElement);this.relatedTarget=e;null===d?(this.offsetX=Mg||void 0!==a.offsetX?a.offsetX:a.layerX,this.offsetY=Mg||void 0!==a.offsetY?a.offsetY:a.layerY,this.clientX=void 0!==a.clientX?a.clientX:a.pageX,this.clientY=void 0!==a.clientY?a.clientY:a.pageY,this.screenX=a.screenX||0,this.screenY=a.screenY||0):(this.clientX=void 0!==d.clientX?d.clientX:d.pageX,this.clientY=void 0!==d.clientY?d.clientY:d.pageY,this.screenX=d.screenX|| +0,this.screenY=d.screenY||0);this.button=a.button;this.keyCode=a.keyCode||0;this.charCode=a.charCode||("keypress"==c?a.keyCode:0);this.ctrlKey=a.ctrlKey;this.altKey=a.altKey;this.shiftKey=a.shiftKey;this.metaKey=a.metaKey;this.state=a.state;this.dc=a;a.defaultPrevented&&this.preventDefault()}}sa(rh,nh);rh.prototype.stopPropagation=function(){rh.Jb.stopPropagation.call(this);this.dc.stopPropagation?this.dc.stopPropagation():this.dc.cancelBubble=!0}; +rh.prototype.preventDefault=function(){rh.Jb.preventDefault.call(this);var a=this.dc;if(a.preventDefault)a.preventDefault();else if(a.returnValue=!1,ph)try{if(a.ctrlKey||112<=a.keyCode&&123>=a.keyCode)a.keyCode=-1}catch(b){}};var sh="closure_listenable_"+(1E6*Math.random()|0),th=0;function uh(a,b,c,d,e){this.listener=a;this.cd=null;this.src=b;this.type=c;this.pc=!!d;this.Sc=e;this.key=++th;this.ic=this.Mc=!1}function vh(a){a.ic=!0;a.listener=null;a.cd=null;a.src=null;a.Sc=null};function wh(a){this.src=a;this.na={};this.Jc=0}f=wh.prototype;f.add=function(a,b,c,d,e){var g=a.toString();a=this.na[g];a||(a=this.na[g]=[],this.Jc++);var h=xh(a,b,d,e);-1e.keyCode||void 0!=e.returnValue)){a:{var g=!1;if(0==e.keyCode)try{e.keyCode=-1;break a}catch(l){g=!0}if(g||void 0==e.returnValue)e.returnValue=!0}e=[];for(g=c.currentTarget;g;g=g.parentNode)e.push(g);for(var g=a.type,h=e.length-1;!c.Ub&&0<=h;h--){c.currentTarget=e[h];var k=Kh(e[h],g,!0,c),d=d&&k}for(h=0;!c.Ub&&h< +e.length;h++)c.currentTarget=e[h],k=Kh(e[h],g,!1,c),d=d&&k}return d}return Lh(a,new rh(b,this))}function Eh(a){a=a[zh];return a instanceof wh?a:null}var Mh="__closure_events_fn_"+(1E9*Math.random()>>>0);function Dh(a){if(ia(a))return a;a[Mh]||(a[Mh]=function(b){return a.handleEvent(b)});return a[Mh]};function Nh(){kh.call(this);this.pb=new wh(this);this.Je=this;this.Ld=null}sa(Nh,kh);Nh.prototype[sh]=!0;f=Nh.prototype;f.addEventListener=function(a,b,c,d){Ch(this,a,b,c,d)};f.removeEventListener=function(a,b,c,d){Ih(this,a,b,c,d)}; +f.dispatchEvent=function(a){var b,c=this.Ld;if(c)for(b=[];c;c=c.Ld)b.push(c);var c=this.Je,d=a.type||a;if(fa(a))a=new nh(a,c);else if(a instanceof nh)a.target=a.target||c;else{var e=a;a=new nh(d,c);Pa(a,e)}var e=!0,g;if(b)for(var h=b.length-1;!a.Ub&&0<=h;h--)g=a.currentTarget=b[h],e=Oh(g,d,!0,a)&&e;a.Ub||(g=a.currentTarget=c,e=Oh(g,d,!0,a)&&e,a.Ub||(e=Oh(g,d,!1,a)&&e));if(b)for(h=0;!a.Ub&&hb)break a}else if(3>b||3==b&&!Ig&&!yi(this.X))break a;this.Lb||4!=b||7==c||(8==c||0>=d?this.B.Oa(zi):this.B.Oa(Ai));Bi(this);var e=xi(this.X);this.M=e;var g=yi(this.X);g||this.h.debug("No response text for uri "+this.Ea+" status "+e);this.Ia=200==e;this.h.info("XMLHTTP RESP ("+this.Ga+") [ attempt "+this.Hc+"]: "+this.mc+"\n"+this.Ea+"\n"+b+" "+e);this.Ia?(4==b&&Ci(this),this.ee? +(Di(this,b,g),Ig&&this.Ia&&3==b&&(this.Fd.Yc(this.bd,$h,this.yf),this.bd.start())):(Ei(this.h,this.Ga,g,null),Fi(this,g)),this.Ia&&!this.Lb&&(4==b?this.B.$c(this):(this.Ia=!1,ui(this)))):(400==e&&0b.length)return qi;var e=b.substr(d,c);a.Kc=d+c;return e} +function Oi(a,b){a.Gc=ra();ui(a);var c=b?window.location.hostname:"";a.Ea=a.wb.clone();og(a.Ea,"DOMAIN",c);og(a.Ea,"t",a.Hc);try{a.Ra=new ActiveXObject("htmlfile")}catch(n){a.h.Qa("ActiveX blocked");Ci(a);a.ka=7;Z(Pi);Ii(a);return}var d="\x3chtml\x3e\x3cbody\x3e";if(b){for(var e="",g=0;gl)k=h;else{if(256>l){if(k="\\x", +16>l||256l&&(k+="0");k+=l.toString(16).toUpperCase()}h=Ga[h]=k}e+=h}}d+='\x3cscript\x3edocument.domain\x3d"'+e+'"\x3c/script\x3e'}c=(new Ag).le(d+"\x3c/body\x3e\x3c/html\x3e");a.Ra.open();a.Ra.write(Cg(c));a.Ra.close();a.Ra.parentWindow.m=w(a.wf,a);a.Ra.parentWindow.d=w(a.we,a,!0);a.Ra.parentWindow.rpcClose=w(a.we,a,!1);c=a.Ra.createElement("DIV");a.Ra.parentWindow.document.body.appendChild(c);d=a.Ea.toString();d instanceof xg||(d=d.ke?d.Fb:String(d),zg.test(d)||(d="about:invalid#zClosurez"), +g=new xg,g.Fb=d,d=g);d instanceof xg&&d.constructor===xg&&d.Ie===yg?d=d.Fb:(Ua("expected object of type SafeUrl, got '"+d+"'"),d="type_error:SafeUrl");Ea.test(d)&&(-1!=d.indexOf("\x26")&&(d=d.replace(wa,"\x26amp;")),-1!=d.indexOf("\x3c")&&(d=d.replace(xa,"\x26lt;")),-1!=d.indexOf("\x3e")&&(d=d.replace(za,"\x26gt;")),-1!=d.indexOf('"')&&(d=d.replace(Aa,"\x26quot;")),-1!=d.indexOf("'")&&(d=d.replace(Ba,"\x26#39;")),-1!=d.indexOf("\x00")&&(d=d.replace(Da,"\x26#0;")));c.innerHTML=Cg((new Ag).le('\x3ciframe src\x3d"'+ +d+'"\x3e\x3c/iframe\x3e'));a.h.info("TRIDENT REQ ("+a.Ga+") [ attempt "+a.Hc+"]: GET\n"+a.Ea);a.B.Oa(vi)}f.wf=function(a){Qi(w(this.vf,this,a),0)};f.vf=function(a){if(!this.Lb){var b=this.h;b.info("TRIDENT TEXT ("+this.Ga+"): "+Ri(b,a));Bi(this);Fi(this,a);ui(this)}};f.we=function(a){Qi(w(this.uf,this,a),0)};f.uf=function(a){this.Lb||(this.h.info("TRIDENT TEXT ("+this.Ga+"): "+a?"success":"failure"),Ci(this),this.Ia=a,this.B.$c(this),this.B.Oa(Si))};f.cancel=function(){this.Lb=!0;Ci(this)}; +function ui(a){a.Td=ra()+a.jc;Ti(a,a.jc)}function Ti(a,b){if(null!=a.nc)throw Error("WatchDog timer not null");a.nc=Qi(w(a.xf,a),b)}function Bi(a){a.nc&&(r.clearTimeout(a.nc),a.nc=null)}f.xf=function(){this.nc=null;var a=ra();0<=a-this.Td?(this.Ia&&this.h.Qa("Received watchdog timeout even though request loaded successfully"),this.h.info("TIMEOUT: "+this.Ea),2!=this.lc&&this.B.Oa(zi),Ci(this),this.ka=2,Z(Ui),Ii(this)):(this.h.Xb("WatchDog timer called too early"),Ti(this,this.Td-a))}; +function Ii(a){a.B.me()||a.Lb||a.B.$c(a)}function Ci(a){Bi(a);var b=a.dd;b&&"function"==typeof b.Dd&&b.Dd();a.dd=null;a.bd.stop();a.Fd.fd();a.X&&(b=a.X,a.X=null,b.abort(),b.Dd());a.Ra&&(a.Ra=null)}f.he=function(){return this.ka};function Fi(a,b){try{a.B.te(a,b),a.B.Oa(Si)}catch(c){Ji(a.h,c,"Error in httprequest callback")}};function Vi(){this.la=ih("goog.net.BrowserChannel")}function Ei(a,b,c,d){a.info("XMLHTTP TEXT ("+b+"): "+Ri(a,c)+(d?" "+d:""))}Vi.prototype.debug=function(a){this.info(a)};function Ji(a,b,c){a.Qa((c||"Exception")+b)}Vi.prototype.info=function(a){var b=this.la;b&&b.info(a,void 0)};Vi.prototype.Xb=function(a){var b=this.la;b&&b.Xb(a,void 0)};Vi.prototype.Qa=function(a){var b=this.la;b&&b.Qa(a,void 0)}; +function Ri(a,b){if(!b||b==Wi)return b;try{var c=Qh(b);if(c)for(var d=0;de.length)){var g=e[1];if(ca(g)&&!(1>g.length)){var h=g[0];if("noop"!=h&&"stop"!=h)for(var k=1;kc)this.M=200,this.Fa.cancel(),this.h.debug("Test connection succeeded; using streaming connection"), +Z(lj),kj(this.B,this,!0)}else Z(qj),this.Qc=this.Jd=ra(),this.ed=!1}; +f.$c=function(){this.M=this.Fa.M;if(!this.Fa.Ia)this.h.debug("TestConnection: request failed, in state "+this.C),0==this.C?Z(rj):2==this.C&&Z(sj),nj(this.B,this);else if(0==this.C)this.h.debug("TestConnection: request complete for initial check"),this.oc?(this.C=1,dj(this)):(this.C=2,ej(this));else if(2==this.C){this.h.debug("TestConnection: request complete for stage 2");var a=!1;(a=!Jg||10<=Vg?this.ed:200>this.Jd-this.Qc?!1:!0)?(this.h.debug("Test connection succeeded; using streaming connection"), +Z(lj),kj(this.B,this,!0)):(this.h.debug("Test connection failed; not using streaming"),Z(jj),kj(this.B,this,!1))}};f.jd=function(){return this.B.jd()};f.fc=function(){return this.B.fc()};f.Oa=function(a){this.B.Oa(a)};function tj(a){Nh.call(this);this.headers=new Vf;this.nd=a||null;this.vb=!1;this.md=this.v=null;this.ne=this.Xc="";this.gc=0;this.ka="";this.Qb=this.Gd=this.Tc=this.Ed=!1;this.Ic=0;this.kd=null;this.ye=uj;this.ld=this.zf=this.Fe=!1}sa(tj,Nh);var uj="";tj.prototype.la=ih("goog.net.XhrIo");var vj=/^https?$/i,wj=["POST","PUT"];f=tj.prototype; +f.send=function(a,b,c,d){if(this.v)throw Error("[goog.net.XhrIo] Object is active with another request\x3d"+this.Xc+"; newUri\x3d"+a);b=b?b.toUpperCase():"GET";this.Xc=a;this.ka="";this.gc=0;this.ne=b;this.Ed=!1;this.vb=!0;this.v=this.nd?ki(this.nd):ki(ii);this.md=this.nd?gi(this.nd):gi(ii);this.v.onreadystatechange=w(this.se,this);this.zf&&"onprogress"in this.v&&(this.v.onprogress=w(function(a){this.re(a,!0)},this),this.v.upload&&(this.v.upload.onprogress=w(this.re,this)));try{Yh(this.la,xj(this, +"Opening Xhr")),this.Gd=!0,this.v.open(b,String(a),!0),this.Gd=!1}catch(g){Yh(this.la,xj(this,"Error opening Xhr: "+g.message));yj(this,g);return}a=c||"";var e=this.headers.clone();d&&Uf(d,function(a,b){e.set(b,a)});d=Za(e.qb());c=r.FormData&&a instanceof r.FormData;!(0<=Wa(wj,b))||d||c||e.set("Content-Type","application/x-www-form-urlencoded;charset\x3dutf-8");e.forEach(function(a,b){this.v.setRequestHeader(b,a)},this);this.ye&&(this.v.responseType=this.ye);Na(this.v)&&(this.v.withCredentials=this.Fe); +try{zj(this),0=a.$b?e:g-d;try{Uf(h,function(a,b){c.push("req"+g+"_"+b+"\x3d"+encodeURIComponent(a))})}catch(k){c.push("req"+g+"_type\x3d"+encodeURIComponent("_badmap"))}}a.sb=a.sb.concat(a.wa.splice(0,b));return c.join("\x26")}function Wj(a){a.R||a.Xa||(a.Ud=1,a.Xa=Qi(w(a.ue,a),0),a.Zb=0)} +function Xj(a){if(a.R||a.Xa)return a.h.Qa("Request already in progress"),!1;if(3<=a.Zb)return!1;a.h.debug("Going to retry GET");a.Ud++;a.Xa=Qi(w(a.ue,a),Yj(a,a.Zb));a.Zb++;return!0} +f.ue=function(){this.Xa=null;this.h.debug("Creating new HttpRequest");this.R=new li(this,this.h,this.Vb,"rpc",this.Ud);this.R.Hb(this.Ba);this.R.De(this.hc);var a=this.Vd.clone();og(a,"RID","rpc");og(a,"SID",this.Vb);og(a,"CI",this.Sd?"0":"1");og(a,"AID",this.Wc);Nj(this,a);if(!Jg||10<=Vg)og(a,"TYPE","xmlhttp"),ti(this.R,a,!0,this.Sa,!1);else{og(a,"TYPE","html");var b=this.R,c=!!this.Sa;b.lc=3;b.wb=rg(a.clone());Oi(b,c)}this.h.debug("New Request created")}; +function kj(a,b,c){a.h.debug("Test Connection Finished");a.Sd=a.Ke&&c;a.M=b.M;a.h.debug("connectChannel_()");a.cf(Gj,0);a.Rc=bj(a,a.oa);Tj(a)}function nj(a,b){a.h.debug("Test Connection Failed");a.M=b.M;hj(a,2)} +f.te=function(a,b){if(0!=this.C&&(this.R==a||this.Ca==a))if(this.M=a.M,this.Ca==a&&3==this.C)if(7d&&this.Sd&&0==this.Zb&&!this.Mb&&(this.Mb=Qi(w(this.rf,this),6E3)))}else this.h.debug("Bad POST response data returned"),hj(this,11)}else b!=Wi&&(this.h.debug("Bad data returned - missing/invald magic cookie"),hj(this,11));else if(this.R==a&&Pj(this),!/^[\s\xa0]*$/.test(b)){c=this.rb.parse(b);for(var d=this.ba&&this.ba.sd?[]:null,e=0;e=(this.df?0:this.gf)?d=!1:(this.h.debug("Going to retry POST"),this.zb=Qi(w(this.ve,this,a),Yj(this,this.zc)),this.zc++,d=!0);if(d||2==b&&Xj(this))return;this.h.debug("Exceeded max number of retries")}this.h.debug("Error: HTTP request failed");switch(c){case 1:hj(this,5);break;case 4:hj(this,10);break;case 3:hj(this,6);break;case 7:hj(this,12);break;default:hj(this,2)}}}; +function Yj(a,b){var c=a.Me+Math.floor(Math.random()*a.Bf);a.fc()||(a.h.debug("Inactive channel"),c*=2);return c*b}f.cf=function(a){if(!(0<=Wa(arguments,this.C)))throw Error("Unexpected channel state: "+this.C);};function hj(a,b){a.h.info("Error code "+b);if(2==b||9==b){var c=null;a.ba&&(c=null);var d=w(a.Ff,a);c||(c=new $f("//www.google.com/images/cleardot.gif"),rg(c));Yi(c.toString(),1E4,d)}else Z(2);Zj(a,b)} +f.Ff=function(a){a?(this.h.info("Successfully pinged google.com"),Z(2)):(this.h.info("Failed to ping google.com"),Z(1),Zj(this,8))};function Zj(a,b){a.h.debug("HttpChannel: error - "+b);a.C=0;Oj(a);Mj(a)}function Oj(a){a.C=0;a.M=-1;!a.ba||0==a.sb.length&&0==a.wa.length||(a.h.debug("Number of undelivered maps, pending: "+a.sb.length+", outgoing: "+a.wa.length),bb(a.sb),bb(a.wa),a.sb.length=0,a.wa.length=0)}function bj(a,b){var c=fj(a,null,b);a.h.debug("GetForwardChannelUri: "+c);return c} +function mj(a,b,c){b=fj(a,a.jd()?b:null,c);a.h.debug("GetBackChannelUri: "+b);return b}function fj(a,b,c){var d=sg(c);if(""!=d.ob)b&&cg(d,b+"."+d.ob),dg(d,d.Tb);else var e=window.location,d=tg(e.protocol,b?b+"."+e.hostname:e.hostname,e.port,c);a.yc&&Ja(a.yc,function(a,b){og(d,b,a)});og(d,"VER",a.$b);Nj(a,d);return d}f.Cd=function(a){if(a&&!this.Qd)throw Error("Can't create secondary domain capable XhrIo object.");a=new tj;a.Fe=this.Qd;return a};f.fc=function(){return!!this.ba&&this.ba.fc(this)}; +function Qi(a,b){if(!ia(a))throw Error("Fn must not be null and must be a function");return r.setTimeout(function(){a()},b)}f.Oa=function(){Ij.dispatchEvent(new Lj(Ij))};function Z(a){Ij.dispatchEvent(new Jj(Ij,a))}f.jd=function(){return this.Qd||!(!Jg||10<=Vg)};function ak(){}f=ak.prototype;f.sd=null;f.Yd=function(){};f.Xd=function(){};f.fc=function(){return!0};f.vc=function(a){return a};function bk(a,b,c,d,e){if(!(Jg||Kg||Mg&&Tg("525")))return!0;if(Ng&&e)return ck(a);if(e&&!d)return!1;ga(b)&&(b=dk(b));if(!c&&(17==b||18==b||Ng&&91==b))return!1;if((Mg||Kg)&&d&&c)switch(a){case 220:case 219:case 221:case 192:case 186:case 189:case 187:case 188:case 190:case 191:case 192:case 222:return!1}if(Jg&&d&&b==a)return!1;switch(a){case 13:return!0;case 27:return!(Mg||Kg)}return ck(a)} +function ck(a){if(48<=a&&57>=a||96<=a&&106>=a||65<=a&&90>=a||(Mg||Kg)&&0==a)return!0;switch(a){case 32:case 43:case 63:case 64:case 107:case 109:case 110:case 111:case 186:case 59:case 189:case 187:case 61:case 188:case 190:case 191:case 192:case 222:case 219:case 220:case 221:return!0;default:return!1}}function dk(a){if(Lg)a=ek(a);else if(Ng&&Mg)a:switch(a){case 93:a=91;break a}return a} +function ek(a){switch(a){case 61:return 187;case 59:return 186;case 173:return 189;case 224:return 91;case 0:return 224;default:return a}};function fk(a,b){Nh.call(this);a&&(this.Vc&&this.detach(),this.xc=a,this.Uc=Ch(this.xc,"keypress",this,b),this.Id=Ch(this.xc,"keydown",this.hf,b,this),this.Vc=Ch(this.xc,"keyup",this.jf,b,this))}sa(fk,Nh);f=fk.prototype;f.xc=null;f.Uc=null;f.Id=null;f.Vc=null;f.Da=-1;f.Cb=-1;f.od=!1; +var gk={3:13,12:144,63232:38,63233:40,63234:37,63235:39,63236:112,63237:113,63238:114,63239:115,63240:116,63241:117,63242:118,63243:119,63244:120,63245:121,63246:122,63247:123,63248:44,63272:46,63273:36,63275:35,63276:33,63277:34,63289:144,63302:45},hk={Up:38,Down:40,Left:37,Right:39,Enter:13,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,"U+007F":46,Home:36,End:35,PageUp:33,PageDown:34,Insert:45},ik=Jg||Kg||Mg&&Tg("525"),jk=Ng&&Lg;f=fk.prototype; +f.hf=function(a){if(Mg||Kg)if(17==this.Da&&!a.ctrlKey||18==this.Da&&!a.altKey||Ng&&91==this.Da&&!a.metaKey)this.Cb=this.Da=-1;-1==this.Da&&(a.ctrlKey&&17!=a.keyCode?this.Da=17:a.altKey&&18!=a.keyCode?this.Da=18:a.metaKey&&91!=a.keyCode&&(this.Da=91));ik&&!bk(a.keyCode,this.Da,a.shiftKey,a.ctrlKey,a.altKey)?this.handleEvent(a):(this.Cb=dk(a.keyCode),jk&&(this.od=a.altKey))};f.jf=function(a){this.Cb=this.Da=-1;this.od=a.altKey}; +f.handleEvent=function(a){var b=a.dc,c,d,e=b.altKey;Jg&&"keypress"==a.type?(c=this.Cb,d=13!=c&&27!=c?b.keyCode:0):(Mg||Kg)&&"keypress"==a.type?(c=this.Cb,d=0<=b.charCode&&63232>b.charCode&&ck(c)?b.charCode:0):Ig&&!Mg?(c=this.Cb,d=ck(c)?b.keyCode:0):(c=b.keyCode||this.Cb,d=b.charCode||0,jk&&(e=this.od),Ng&&63==d&&224==c&&(c=191));var g=c=dk(c),h=b.keyIdentifier;c?63232<=c&&c in gk?g=gk[c]:25==c&&a.shiftKey&&(g=9):h&&h in hk&&(g=hk[h]);a=g==this.Da;this.Da=g;b=new kk(g,d,a,b);b.altKey=e;this.dispatchEvent(b)}; +f.detach=function(){this.Uc&&(Jh(this.Uc),Jh(this.Id),Jh(this.Vc),this.Vc=this.Id=this.Uc=null);this.xc=null;this.Cb=this.Da=-1};f.za=function(){fk.Jb.za.call(this);this.detach()};function kk(a,b,c,d){rh.call(this,d);this.type="key";this.keyCode=a;this.charCode=b;this.repeat=c}sa(kk,rh);var $d=new Ac(null,"meta15224","meta15224",-154517792,null),mb=new W(null,"meta","meta",1499536964),nb=new W(null,"dup","dup",556298533),lk=new W(null,"disabled","disabled",-1529784218),mk=new W(null,"msg","msg",-1386103444),Kf=new W(null,"fallback-impl","fallback-impl",-1501286995),kb=new W(null,"flush-on-newline","flush-on-newline",-151457939),lb=new W(null,"readably","readably",1129599760),Cf=new W(null,"more-marker","more-marker",-14717935),ob=new W(null,"print-length","print-length",1931866356), +Zd=new Ac(null,"quote","quote",1377916282,null),Yd=new W(null,"arglists","arglists",1661989754),Xd=new Ac(null,"nil-iter","nil-iter",1101030523,null),Jf=new W(null,"alt-impl","alt-impl",670969595),Sf=new W(null,"keywordize-keys","keywordize-keys",1310784252);function nk(a){return a instanceof W?[E(function(){var b=Cd(a);return null==b?null:[E(b),E("/")].join("")}()),E(Ed(a))].join(""):a};ce(ae,X.a(function(a){var b=ad(a,0,null),c=ad(a,1,null);return new Vd(null,2,5,Wd,[b,Ne([c,function(a,b,c){return function(h){return function(){return function(a){var b=a.relatedTarget,c;c=a.Rf;c=x(c)?c:a.currentTarget;b=x(b)?x(c.contains)?c.contains(b):x(c.compareDocumentPosition)?0!=(c.compareDocumentPosition(b)&16):null:b;return x(b)?null:h.b?h.b(a):h.call(null,a)}}(a,b,c)}}(a,b,c)])],null)},new jb(null,2,[new W(null,"mouseenter","mouseenter",-1792413560),new W(null,"mouseover","mouseover",-484272303), +new W(null,"mouseleave","mouseleave",531566580),new W(null,"mouseout","mouseout",2049446890)],null)));if("undefined"===typeof Rj)var Rj=new Fj;function ok(a){if(x(x(lk)?a.getAttribute(nk(lk)):null)){var b=nk(lk);x((new xf(null,new jb(null,2,["class",null,"classes",null],null),null)).call(null,b))?a.className="":a.removeAttribute(b)}else{var b=nk(lk),c=nk(lk);if(x(b)){var d=ia(b);(d?d:null!=b?b.Pe||(b.Bd?0:B(xb,b)):B(xb,b))?a[c]=b:a.setAttribute(c,b)}}} +function pk(){var a=document.getElementById("msg-input"),b=document.getElementById("send-button"),c=function(a){return function(){var b=Rj,c=Of(new jb(null,1,[mk,a.value],null));if(0==b.C)throw Error("Invalid operation: sending map when state is closed");1E3==b.wa.length&&b.h.Qa("Already have 1000 queued maps upon queueing "+Sh(new Rh(void 0),c));b.wa.push(new Hj(b.pf++,c));2!=b.C&&3!=b.C||Tj(b);a.value="";return a}}(a,b);ok(a);ok(b);var d=new fk(a);Ch(d,"key",function(a,b,c,d,l){return function(a){return Cc.a(a.keyCode, +13)?l(a):null}}(d,"key",a,b,c));return Ch(b,"click",c)}function Sj(){var a=new ak;a.Yd=function(){return function(){return pk()}}(a);a.Xd=function(){return function(a,c){var d=Rf(c),e=L.a(d,"msg"),d=document.getElementById("room"),g=document.createElement(nk("div")),e=[E("MSG::"),E(e)].join("");void 0!==g.textContent?g.textContent=e:g.innerText=e;d.appendChild(g);return d}}(a);return a} +function qk(){var a=window;Ch(a,"unload",function(){return function(){Rj.disconnect();return 0}}(a,"unload"));Rj.h.la.Pd($g);Qj();Rj.connect("/channel/test","/channel/bind");return Rj}var rk=["chat_demo","client","run"],sk=r;rk[0]in sk||!sk.execScript||sk.execScript("var "+rk[0]);for(var tk;rk.length&&(tk=rk.shift());)rk.length||void 0===qk?sk=sk[tk]?sk[tk]:sk[tk]={}:sk[tk]=qk; +})(); diff --git a/chat-demo/resources/public/css/default.css b/chat-demo/resources/public/default.css similarity index 100% rename from chat-demo/resources/public/css/default.css rename to chat-demo/resources/public/default.css diff --git a/chat-demo/resources/public/js/compile_target_dir b/chat-demo/resources/public/js/compile_target_dir deleted file mode 100644 index e69de29..0000000 diff --git a/chat-demo/src/chat_demo/client.cljs b/chat-demo/src/chat_demo/client.cljs new file mode 100644 index 0000000..b1b30b4 --- /dev/null +++ b/chat-demo/src/chat_demo/client.cljs @@ -0,0 +1,62 @@ +(ns chat-demo.client + (:require + [dommy.core :as dom :refer-macros [by-id]] + goog.net.BrowserChannel + goog.events.KeyHandler + [goog.events.KeyCodes :as key-codes] + [goog.events :as events])) + +(defonce channel (goog.net.BrowserChannel.)) + +(defn say [text] + (.sendMap channel (clj->js {:msg text}))) + +(defn toggle-element [elem] + (if (dom/attr elem :disabled) + (dom/remove-attr! elem :disabled) + (dom/set-attr! elem :disabled))) + +(defn enable-chat [] + (let [msg-input (by-id "msg-input") + send-button (by-id "send-button") + send-message (fn [e] + (say (dom/value msg-input)) + (dom/set-value! msg-input ""))] + (toggle-element msg-input) + (toggle-element send-button) + (events/listen + (goog.events.KeyHandler. msg-input) + "key" + (fn [e] + (when (= (.-keyCode e) key-codes/ENTER) + (send-message e)))) + (events/listen + send-button + "click" + send-message))) + +(defn handler [] + (let [h (goog.net.BrowserChannel.Handler.)] + (set! (.-channelOpened h) + (fn [channel] + (enable-chat))) + (set! (.-channelHandleArray h) + (fn [channel data] + (let [data (js->clj data) + msg (get data "msg")] + (dom/append! (by-id "room") + (-> (dom/create-element "div") + (dom/set-text! (str "MSG::" msg))))))) + h)) + +(defn ^:export run [] + (events/listen + js/window "unload" + (fn [] + (.disconnect channel) + (events/removeAll))) + (doto (.. channel getChannelDebug getLogger) + (.setLevel goog.debug.Logger.Level.OFF)) + (doto channel + (.setHandler (handler)) + (.connect "/channel/test" "/channel/bind"))) \ No newline at end of file diff --git a/chat-demo/src/chat_demo/core.clj b/chat-demo/src/chat_demo/core.clj deleted file mode 100644 index 314059f..0000000 --- a/chat-demo/src/chat_demo/core.clj +++ /dev/null @@ -1,75 +0,0 @@ -(ns chat-demo.core - (:require [net.thegeez.browserchannel :as browserchannel] - [net.thegeez.jetty-async-adapter :as jetty] - #_[net.thegeez.netty-adapter :as netty] - [ring.middleware.resource :as resource] - [ring.middleware.file-info :as file])) - -(defn handler [req] - {:status 200 - :headers {"Content-Type" "text/plain"} - :body "Hello World"}) - -(def clients (atom #{})) - -(def dev-app - (-> handler - (resource/wrap-resource "dev") - (resource/wrap-resource "public") - file/wrap-file-info - (browserchannel/wrap-browserchannel {:base "/channel" - :on-session - (fn [session-id req] - (println "session " session-id "connected") - - (browserchannel/add-listener - session-id - :close - (fn [reason] - (println "session " session-id " disconnected: " reason) - (swap! clients disj session-id) - (doseq [client-id @clients] - (browserchannel/send-map client-id {"msg" (str "client " session-id " disconnected " reason)})))) - (browserchannel/add-listener - session-id - :map - (fn [map] - (println "session " session-id " sent " map) - (doseq [client-id @clients] - (browserchannel/send-map client-id map)))) - (swap! clients conj session-id) - (doseq [client-id @clients] - (browserchannel/send-map client-id {"msg" (str "client " session-id " connected")})))}))) - -(defn -main [& args] - (println "Using Jetty adapter") - (jetty/run-jetty-async #'dev-app {:port (Integer. - (or - (System/getenv "PORT") - 8080)) :join? false})) - -#_(defn -main [& args] - (println "Using Netty adapter") - (netty/run-netty #'dev-app {:port (Integer. - (or - (System/getenv "PORT") - 8080)) :join? false})) - - -(comment - (def jetty-async-server (-main)) - (.stop jetty-async-server) - (do - (.stop jetty-async-server) - (def jetty-async-server (-main)) - ) - ) - -(comment - (def netty-async-server (-main)) - (netty-async-server) - (do - (netty-async-server) - (def netty-async-server (-main)) - ) - ) diff --git a/chat-demo/src/chat_demo/server.clj b/chat-demo/src/chat_demo/server.clj new file mode 100644 index 0000000..b36a133 --- /dev/null +++ b/chat-demo/src/chat_demo/server.clj @@ -0,0 +1,61 @@ +(ns chat-demo.server + (:gen-class) + (:require + [compojure.core :refer [routes GET]] + [compojure.route :as route] + [ring.middleware.defaults :refer [wrap-defaults site-defaults]] + [ring.util.response :refer [response]] + [clj-pebble.core :as pebble] + [net.thegeez.browserchannel :as browserchannel] + [net.thegeez.jetty-async-adapter :as jetty] + [environ.core :refer [env]])) + +(defonce clients (atom #{})) + +(defn on-browserchannel-session + [session-id request] + (println "session " session-id "connected") + + (browserchannel/add-listener + session-id + :close + (fn [request reason] + (println "session " session-id " disconnected: " reason) + (swap! clients disj session-id) + (doseq [client-id @clients] + (browserchannel/send-map client-id {"msg" (str "client " session-id " disconnected " reason)})))) + + (browserchannel/add-listener + session-id + :map + (fn [request map] + (println "session " session-id " sent " map) + (doseq [client-id @clients] + (browserchannel/send-map client-id map)))) + + (swap! clients conj session-id) + (doseq [client-id @clients] + (browserchannel/send-map client-id {"msg" (str "client " session-id " connected")}))) + +(def app-routes + (routes + (GET "/" [] (pebble/render-resource "html/index.html" {:dev (boolean (env :dev))})) + (route/resources "/") + (route/not-found "not found"))) + +(def handler + (-> app-routes + (browserchannel/wrap-browserchannel {:base "/channel" :on-session on-browserchannel-session}) + (wrap-defaults (assoc-in site-defaults [:security :anti-forgery] false)))) + +(defn run-jetty [] + (println "Using Jetty adapter") + (jetty/run-jetty-async + #'handler + {:join? false + :port 8080})) + +(defn -main [& args] + (if (env :dev) (pebble/set-options! :cache false)) + + (run-jetty)) diff --git a/chat-demo/src/tasks/browser_repl.clj b/chat-demo/src/tasks/browser_repl.clj deleted file mode 100644 index 89950d2..0000000 --- a/chat-demo/src/tasks/browser_repl.clj +++ /dev/null @@ -1,6 +0,0 @@ -(ns tasks.browser-repl - (require [cljs.repl :as repl]) - (require [cljs.repl.browser :as browser])) - -(defn -main [] - (repl/repl (browser/repl-env))) diff --git a/chat-demo/src/tasks/build_advanced_js.clj b/chat-demo/src/tasks/build_advanced_js.clj deleted file mode 100644 index 3862810..0000000 --- a/chat-demo/src/tasks/build_advanced_js.clj +++ /dev/null @@ -1,6 +0,0 @@ -(ns tasks.build-advanced-js - (:require [cljs.closure :as cljs])) - -(defn -main [& args] - (cljs/build "cljs" {:optimizations :advanced - :output-to "resources/public/js/bc.js"})) diff --git a/chat-demo/src/tasks/build_dev_js.clj b/chat-demo/src/tasks/build_dev_js.clj deleted file mode 100644 index 5cffa31..0000000 --- a/chat-demo/src/tasks/build_dev_js.clj +++ /dev/null @@ -1,38 +0,0 @@ -(ns tasks.build-dev-js - (:require [cljs.closure :as cljs]) - (:import [java.io File])) - -(def config {:sources-path "cljs" - ;; whitespace makes it a single file - :optimizations :whitespace - :output-to "resources/dev/js/bc-dev.js"}) - -(defn print-title [msg] - (println (str "\033]0;" msg "\007")) - (println msg)) - -(defn build [] - (print-title "CLJSB - building") - (cljs/build (:sources-path config) (dissoc config :sources-path)) - (print-title "cljsb - done")) - -(defn -main [& [cmd]] - (print-title "cljsb") - (if-not (= cmd "auto") - (build) - (loop [old-entries {}] - (let [entries (into {} (for [file-dir (tree-seq #(.isDirectory %) - #(.listFiles %) - (File. (:sources-path config))) - :let [name (.getName file-dir)] - :when (and - (not (.contains name "#")) - (.endsWith name ".cljs"))] - [(.getPath file-dir) (.lastModified file-dir)]))] - (when (some (fn [[entry-path entry-stamp]] - (let [old-entry-stamp (old-entries entry-path)] - (or (nil? old-entry-stamp) - (> entry-stamp old-entry-stamp)))) entries) - (build)) - (Thread/sleep 700) - (recur entries)))))