From 250997dccffc7d46a0a91ad2dda240a7335574e5 Mon Sep 17 00:00:00 2001 From: Alex Heeton Date: Mon, 11 Nov 2013 17:36:37 +0000 Subject: [PATCH] wip --- app/assets/javascripts/emberfire.js | 140 +++++++++++++++++ app/assets/javascripts/firebase.js | 145 ++++++++++++++++++ app/assets/javascripts/live_reader.js.coffee | 3 +- .../routes/documents.js.coffee.erb | 20 +-- app/assets/javascripts/write_room.js.coffee | 33 +++- .../writeroom/documents_controller.rb | 5 +- app/models/document.rb | 8 - app/views/writeroom/documents/edit.html.haml | 2 +- 8 files changed, 318 insertions(+), 38 deletions(-) create mode 100644 app/assets/javascripts/emberfire.js create mode 100644 app/assets/javascripts/firebase.js diff --git a/app/assets/javascripts/emberfire.js b/app/assets/javascripts/emberfire.js new file mode 100644 index 0000000..26e071f --- /dev/null +++ b/app/assets/javascripts/emberfire.js @@ -0,0 +1,140 @@ +"use strict"; + +var EmberFire = Ember.Namespace.create(); + +EmberFire._checkType = function(snapshot, cb, binding) { + var obj = snapshot.val(); + var type = obj._type; + + switch (type) { + case "object": + cb.call(binding, EmberFire.Object.create({ ref: snapshot.ref() })); + break; + case "array": + cb.call(binding, EmberFire.Array.create({ ref: snapshot.ref() })); + break; + default: + cb.call(binding, obj); + } +}; + +EmberFire.Object = Ember.ObjectProxy.extend({ + init: function() { + var object = {}; + this.set("content", object); + + function applyChange(snapshot) { + var key = snapshot.name(); + /*jshint validthis:true */ + EmberFire._checkType(snapshot, function(val) { + Ember.set(object, key, val); + }, this); + } + + this.ref.child("_type").set("object"); + + this.ref.on("child_added", applyChange, this); + + this.ref.on("child_changed", applyChange, this); + + this.ref.on("child_removed", function(snapshot) { + this.set(snapshot.name(), null); + }, this); + + this._super(); + }, + + willDestroy: function() { + this.ref.off(); + }, + + toJSON: function() { + var json = {}, + object = this.get("content"); + + for (var key in object) { + json[key] = Ember.get(object, key); + } + + json._type = "object"; + return json; + }, + + setUnknownProperty: function(key, value) { + if (value instanceof EmberFire.Object || value instanceof EmberFire.Array) { + value.ref = this.ref.child(key); + value.ref.set(value.toJSON()); + } else { + this.ref.child(key).set(value); + return this._super(key, value); + } + }, + + ref: null +}); + +EmberFire.Array = Ember.ArrayProxy.extend({ + init: function() { + var array = Ember.A([]); + this._index = Ember.A([]); + + this.set("content", array); + + this.ref.child("_type").set("array"); + + this.ref.on("child_added", function(snapshot) { + if (snapshot.name() == "_type") { + return; + } + EmberFire._checkType(snapshot, function(val) { + this._index.pushObject(snapshot.name()); + array.pushObject(val); + }, this); + }, this); + + this.ref.on("child_removed", function(snapshot) { + if (snapshot.name() == "_type") { + return; + } + var idx = this._index.indexOf(snapshot.name()); + this._index.removeAt(idx); + array.removeAt(idx); + }, this); + + this.ref.on("child_changed", function(snapshot) { + if (snapshot.name() == "_type") { + return; + } + var idx = this._index.indexOf(snapshot.name()); + array.replace(idx, 1, [snapshot.val()]); + }, this); + + this._super(); + }, + + replaceContent: function(idx, amt, objects) { + for (var i = 0; i < amt; i++) { + var key = this._index[idx+i]; + this.ref.child(key).remove(); + } + objects.forEach(function(object) { + var val = object; + if (object.toJSON) { + val = object.toJSON(); + } + return this.ref.push(val).name(); + }, this); + }, + + toJSON: function() { + var json = {}, + values = this.get("content"); + + for (var i = 0; i < this._index.length; i++) { + json[this._index[i]] = values[i]; + } + + json._type = "array"; + return json; + } +}); diff --git a/app/assets/javascripts/firebase.js b/app/assets/javascripts/firebase.js new file mode 100644 index 0000000..f1940ad --- /dev/null +++ b/app/assets/javascripts/firebase.js @@ -0,0 +1,145 @@ +(function() {function g(a){throw a;}var j=void 0,k=!0,l=null,o=!1;function aa(a){return function(){return this[a]}}function r(a){return function(){return a}}var s,ba=this;function ca(){}function da(a){a.mb=function(){return a.bd?a.bd:a.bd=new a}} +function ea(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 u(a){return a!==j}function fa(a){var b=ea(a);return"array"==b||"object"==b&&"number"==typeof a.length}function v(a){return"string"==typeof a}function ga(a){return"number"==typeof a}function ha(a){var b=typeof a;return"object"==b&&a!=l||"function"==b}Math.floor(2147483648*Math.random()).toString(36);function ia(a,b,c){return a.call.apply(a.bind,arguments)} +function ja(a,b,c){a||g(Error());if(2b?e+="000":256>b?e+="00":4096>b&&(e+="0");return pa[a]=e+b.toString(16)}),'"')};function y(a){if("undefined"!==typeof JSON&&u(JSON.stringify))a=JSON.stringify(a);else{var b=[];na(new ma,a,b);a=b.join("")}return a};function ra(a){for(var b=[],c=0,d=0;d=e&&(e-=55296,d++,z(de?b[c++]=e:(2048>e?b[c++]=e>>6|192:(65536>e?b[c++]=e>>12|224:(b[c++]=e>>18|240,b[c++]=e>>12&63|128),b[c++]=e>>6&63|128),b[c++]=e&63|128)}return b};function A(a,b,c,d){var e;dc&&(e=0===c?"none":"no more than "+c);e&&g(Error(a+" failed: Was called with "+d+(1===d?" argument.":" arguments.")+" Expects "+e+"."))}function B(a,b,c){var d="";switch(b){case 1:d=c?"first":"First";break;case 2:d=c?"second":"Second";break;case 3:d=c?"third":"Third";break;case 4:d=c?"fourth":"Fourth";break;default:sa.assert(o,"errorPrefix_ called with argumentNumber > 4. Need to update it?")}return a+" failed: "+(d+" argument ")} +function C(a,b,c,d){(!d||u(c))&&"function"!=ea(c)&&g(Error(B(a,b,d)+"must be a valid function."))}function ta(a,b,c){u(c)&&(!ha(c)||c===l)&&g(Error(B(a,b,k)+"must be a valid context object."))};function D(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function ua(a,b){if(Object.prototype.hasOwnProperty.call(a,b))return a[b]};var sa={},va=/[\[\].#$\/]/,wa=/[\[\].#$]/;function xa(a){return v(a)&&0!==a.length&&!va.test(a)}function ya(a,b,c){(!c||u(b))&&za(B(a,1,c),b)} +function za(a,b,c,d){c||(c=0);d||(d=[]);u(b)||g(Error(a+"contains undefined"+Aa(d)));"function"==ea(b)&&g(Error(a+"contains a function"+Aa(d)+" with contents: "+b.toString()));Ba(b)&&g(Error(a+"contains "+b.toString()+Aa(d)));1E310485760/3&&10485760=a)&&g("Query.limit: First argument must be a positive integer.");return new H(this.n,this.path,a,this.ca,this.ua,this.za,this.Sa)};H.prototype.limit=H.prototype.Bd;H.prototype.Rd=function(a,b){A("Query.startAt",0,2,arguments.length);Da("Query.startAt",1,a,k);Fa("Query.startAt",b);u(a)||(b=a=l);return new H(this.n,this.path,this.Ba,a,b,this.za,this.Sa)};H.prototype.startAt=H.prototype.Rd; +H.prototype.wd=function(a,b){A("Query.endAt",0,2,arguments.length);Da("Query.endAt",1,a,k);Fa("Query.endAt",b);return new H(this.n,this.path,this.Ba,this.ca,this.ua,a,b)};H.prototype.endAt=H.prototype.wd;function Ia(a){var b={};u(a.ca)&&(b.sp=a.ca);u(a.ua)&&(b.sn=a.ua);u(a.za)&&(b.ep=a.za);u(a.Sa)&&(b.en=a.Sa);u(a.Ba)&&(b.l=a.Ba);u(a.ca)&&(u(a.ua)&&a.ca===l&&a.ua===l)&&(b.vf="l");return b}H.prototype.La=function(){var a=Ja(Ia(this));return"{}"===a?"default":a}; +function Ha(a,b,c){var d={};b&&c?(d.cancel=b,C(a,3,d.cancel,k),d.T=c,ta(a,4,d.T)):b&&("object"===typeof b&&b!==l?d.T=b:"function"===typeof b?d.cancel=b:g(Error(B(a,3,k)+"must either be a cancel callback or a context object.")));return d};function K(a){if(a instanceof K)return a;if(1==arguments.length){this.m=a.split("/");for(var b=0,c=0;c=a.m.length?l:a.m[a.Z]}function Ka(a){var b=a.Z;b=this.m.length)return l;for(var a=[],b=this.Z;b=this.m.length}; +function La(a,b){var c=F(a);if(c===l)return b;if(c===F(b))return La(Ka(a),Ka(b));g("INTERNAL ERROR: innerPath ("+b+") is not within outerPath ("+a+")")}s.contains=function(a){var b=0;if(this.m.length>a.m.length)return o;for(;bb?1:0}s=Ra.prototype;s.na=function(a,b){return new Ra(this.Pa,this.ba.na(a,b,this.Pa).copy(l,l,o,l,l))};s.remove=function(a){return new Ra(this.Pa,this.ba.remove(a,this.Pa).copy(l,l,o,l,l))};s.get=function(a){for(var b,c=this.ba;!c.f();){b=this.Pa(a,c.key);if(0===b)return c.value;0>b?c=c.left:0c?d=d.left:0d?e.copy(l,l,l,e.left.na(a,b,c),l):0===d?e.copy(l,b,l,l,l):e.copy(l,l,l,l,e.right.na(a,b,c));return Za(e)};function bb(a){if(a.left.f())return Ta;!a.left.O()&&!a.left.left.O()&&(a=cb(a));a=a.copy(l,l,l,bb(a.left),l);return Za(a)} +s.remove=function(a,b){var c,d;c=this;if(0>b(a,c.key))!c.left.f()&&(!c.left.O()&&!c.left.left.O())&&(c=cb(c)),c=c.copy(l,l,l,c.left.remove(a,b),l);else{c.left.O()&&(c=db(c));!c.right.f()&&(!c.right.O()&&!c.right.left.O())&&(c=eb(c),c.left.left.O()&&(c=db(c),c=eb(c)));if(0===b(a,c.key)){if(c.right.f())return Ta;d=Ya(c.right);c=c.copy(d.key,d.value,l,l,bb(c.right))}c=c.copy(l,l,l,l,c.right.remove(a,b))}return Za(c)};s.O=aa("color"); +function Za(a){a.right.O()&&!a.left.O()&&(a=fb(a));a.left.O()&&a.left.left.O()&&(a=db(a));a.left.O()&&a.right.O()&&(a=eb(a));return a}function cb(a){a=eb(a);a.right.left.O()&&(a=a.copy(l,l,l,l,db(a.right)),a=fb(a),a=eb(a));return a}function fb(a){var b;b=a.copy(l,l,k,l,a.right.left);return a.right.copy(l,l,a.color,b,l)}function db(a){var b;b=a.copy(l,l,k,a.left.right,l);return a.left.copy(l,l,a.color,l,b)} +function eb(a){var b,c;b=a.left.copy(l,l,!a.left.color,l,l);c=a.right.copy(l,l,!a.right.color,l,l);return a.copy(l,l,!a.color,b,c)}function gb(){}s=gb.prototype;s.copy=function(){return this};s.na=function(a,b){return new Xa(a,b,j,j,j)};s.remove=function(){return this};s.count=r(0);s.f=r(k);s.Aa=r(o);s.Ma=r(o);s.tb=r(l);s.Wa=r(l);s.O=r(o);var Ta=new gb;var hb=Array.prototype,ib=hb.forEach?function(a,b,c){hb.forEach.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=v(a)?a.split(""):a,f=0;fa;++a)this.Xb[a]=0;this.reset()}ka(lb,kb);lb.prototype.reset=function(){this.B[0]=1732584193;this.B[1]=4023233417;this.B[2]=2562383102;this.B[3]=271733878;this.B[4]=3285377520;this.Sc=this.ob=0}; +function mb(a,b){var c;c||(c=0);for(var d=a.rd,e=c;ee;e++){var f=d[e-3]^d[e-8]^d[e-14]^d[e-16];d[e]=(f<<1|f>>>31)&4294967295}c=a.B[0];for(var h=a.B[1],i=a.B[2],m=a.B[3],n=a.B[4],p,e=0;80>e;e++)40>e?20>e?(f=m^h&(i^m),p=1518500249):(f=h^i^m,p=1859775393):60>e?(f=h&i|m&(h|i),p=2400959708):(f=h^i^m,p=3395469782),f=(c<<5|c>>>27)+f+n+p+d[e]&4294967295,n=m,m=i,i=(h<<30|h>>>2)&4294967295,h=c,c=f;a.B[0]=a.B[0]+c&4294967295;a.B[1]=a.B[1]+h& +4294967295;a.B[2]=a.B[2]+i&4294967295;a.B[3]=a.B[3]+m&4294967295;a.B[4]=a.B[4]+n&4294967295}lb.prototype.update=function(a,b){u(b)||(b=a.length);var c=this.oc,d=this.ob,e=0;if(v(a))for(;ec;c++)Eb[c]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(c),Fb[c]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.".charAt(c)}for(var c=b?Fb:Eb,d=[],e=0;e>2,f=(f&3)<<4|i>>4,i=(i&15)<<2|n>>6,n=n&63;m||(n=64,h||(i=64));d.push(c[p],c[f],c[i],c[n])}return d.join("")} +;var Hb,Ib=1;Hb=function(){return Ib++};function z(a,b){a||g(Error("Firebase INTERNAL ASSERT FAILED:"+b))}function Jb(a){var b=ra(a),a=new lb;a.update(b);var b=[],c=8*a.Sc;56>a.ob?a.update(a.Xb,56-a.ob):a.update(a.Xb,64-(a.ob-56));for(var d=63;56<=d;d--)a.oc[d]=c&255,c/=256;mb(a,a.oc);for(d=c=0;5>d;d++)for(var e=24;0<=e;e-=8)b[c++]=a.B[d]>>e&255;return Gb(b)} +function Kb(){for(var a="",b=0;bb?1:-1:0}function Sb(a,b){if(a===b)return 0;var c=Tb(a),d=Tb(b);return c!==l?d!==l?c-d:-1:d!==l?1:aa?c.push(a.substring(d,a.length)):c.push(a.substring(d,d+b));return c}function Wb(a,b){if("array"==ea(a))for(var c=0;ca,a=Math.abs(a),a>=Math.pow(2,-1022)?(d=Math.min(Math.floor(Math.log(a)/Math.LN2),1023),c=d+1023,d=Math.round(a*Math.pow(2,52-d)-Math.pow(2,52))):(c=0,d=Math.round(a/Math.pow(2,-1074))));e=[];for(a=52;a;a-=1)e.push(d%2?1:0),d=Math.floor(d/2);for(a=11;a;a-=1)e.push(c%2?1:0),c=Math.floor(c/2);e.push(b?1:0);e.reverse();b=e.join("");c="";for(a=0;64>a;a+=8)d=parseInt(b.substr(a,8),2).toString(16),1===d.length&&(d="0"+d),c+=d; +return c.toLowerCase()}var Zb=/^-?\d{1,10}$/;function Tb(a){return Zb.test(a)&&(a=Number(a),-2147483648<=a&&2147483647>=a)?a:l}function $b(a){try{a()}catch(b){setTimeout(function(){g(b)})}};function ac(a,b){this.D=a;z(this.D!==l,"LeafNode shouldn't be created with null value.");this.Za="undefined"!==typeof b?b:l}s=ac.prototype;s.N=r(k);s.j=aa("Za");s.Ea=function(a){return new ac(this.D,a)};s.M=function(){return Q};s.Q=function(a){return F(a)===l?this:Q};s.da=r(l);s.G=function(a,b){return(new R).G(a,b).Ea(this.Za)};s.xa=function(a,b){var c=F(a);return c===l?b:this.G(c,Q.xa(Ka(a),b))};s.f=r(o);s.Sb=r(0);s.V=function(a){return a&&this.j()!==l?{".value":this.k(),".priority":this.j()}:this.k()}; +s.hash=function(){var a="";this.j()!==l&&(a+="priority:"+bc(this.j())+":");var b=typeof this.D,a=a+(b+":"),a="number"===b?a+Yb(this.D):a+this.D;return Jb(a)};s.k=aa("D");s.toString=function(){return"string"===typeof this.D?'"'+this.D+'"':this.D};function cc(a,b){return Rb(a.ha,b.ha)||Sb(a.name,b.name)}function dc(a,b){return Sb(a.name,b.name)}function ec(a,b){return Sb(a,b)};function R(a,b){this.o=a||new Ra(ec);this.Za="undefined"!==typeof b?b:l}s=R.prototype;s.N=r(o);s.j=aa("Za");s.Ea=function(a){return new R(this.o,a)};s.G=function(a,b){var c=this.o.remove(a);b&&b.f()&&(b=l);b!==l&&(c=c.na(a,b));return b&&b.j()!==l?new fc(c,l,this.Za):new R(c,this.Za)};s.xa=function(a,b){var c=F(a);if(c===l)return b;var d=this.M(c).xa(Ka(a),b);return this.G(c,d)};s.f=function(){return this.o.f()};s.Sb=function(){return this.o.count()};var gc=/^\d+$/;s=R.prototype; +s.V=function(a){if(this.f())return l;var b={},c=0,d=0,e=k;this.w(function(f,h){b[f]=h.V(a);c++;e&&gc.test(f)?d=Math.max(d,Number(f)):e=o});if(!a&&e&&d<2*c){var f=[],h;for(h in b)f[h]=b[h];return f}a&&this.j()!==l&&(b[".priority"]=this.j());return b};s.hash=function(){var a="";this.j()!==l&&(a+="priority:"+bc(this.j())+":");this.w(function(b,c){var d=c.hash();""!==d&&(a+=":"+b+":"+d)});return""===a?"":Jb(a)};s.M=function(a){a=this.o.get(a);return a===l?Q:a}; +s.Q=function(a){var b=F(a);return b===l?this:this.M(b).Q(Ka(a))};s.da=function(a){return Ua(this.o,a)};s.$c=function(){return this.o.tb()};s.ad=function(){return this.o.Wa()};s.w=function(a){return this.o.Aa(a)};s.vc=function(a){return this.o.Ma(a)};s.Va=function(){return this.o.Va()};s.toString=function(){var a="{",b=k;this.w(function(c,d){b?b=o:a+=", ";a+='"'+c+'" : '+d.toString()});return a+="}"};var Q=new R;function fc(a,b,c){R.call(this,a,c);b===l&&(b=new Ra(cc),a.Aa(function(a,c){b=b.na({name:a,ha:c.j()},c)}));this.ta=b}ka(fc,R);s=fc.prototype;s.G=function(a,b){var c=this.M(a),d=this.o,e=this.ta;c!==l&&(d=d.remove(a),e=e.remove({name:a,ha:c.j()}));b&&b.f()&&(b=l);b!==l&&(d=d.na(a,b),e=e.na({name:a,ha:b.j()},b));return new fc(d,e,this.j())};s.da=function(a,b){var c=Ua(this.ta,{name:a,ha:b.j()});return c?c.name:l};s.w=function(a){return this.ta.Aa(function(b,c){return a(b.name,c)})}; +s.vc=function(a){return this.ta.Ma(function(b,c){return a(b.name,c)})};s.Va=function(){return this.ta.Va(function(a,b){return{key:a.name,value:b}})};s.$c=function(){return this.ta.f()?l:this.ta.tb().name};s.ad=function(){return this.ta.f()?l:this.ta.Wa().name};function S(a,b){if(a===l)return Q;var c=l;"object"===typeof a&&".priority"in a?c=a[".priority"]:"undefined"!==typeof b&&(c=b);z(c===l||"string"===typeof c||"number"===typeof c||"object"===typeof c&&".sv"in c);"object"===typeof a&&(".value"in a&&a[".value"]!==l)&&(a=a[".value"]);if("object"!==typeof a||".sv"in a)return new ac(a,c);if(a instanceof Array){var d=Q;Xb(a,function(b,c){if(D(a,c)&&"."!==c.substring(0,1)){var e=S(b);if(e.N()||!e.f())d=d.G(c,e)}});return d.Ea(c)}var e=[],f={},h=o;Wb(a,function(b, +c){if("string"!==typeof c||"."!==c.substring(0,1)){var d=S(a[c]);d.f()||(h=h||d.j()!==l,e.push({name:c,ha:d.j()}),f[c]=d)}});var i=hc(e,f,o);if(h){var m=hc(e,f,k);return new fc(i,m,c)}return new R(i,c)}var ic=Math.log(2);function jc(a){this.count=parseInt(Math.log(a+1)/ic);this.Xc=this.count-1;this.td=a+1&parseInt(Array(this.count+1).join("1"),2)} +function hc(a,b,c){function d(d,f){var h=n-d,p=n;n-=d;var q=a[h].name,h=new Xa(c?a[h]:q,b[q],f,l,e(h+1,p));i?i.left=h:m=h;i=h}function e(d,f){var h=f-d;if(0==h)return l;if(1==h){var h=a[d].name,i=c?a[d]:h;return new Xa(i,b[h],o,l,l)}var i=parseInt(h/2)+d,m=e(d,i),n=e(i+1,f),h=a[i].name,i=c?a[i]:h;return new Xa(i,b[h],o,m,n)}var f=c?cc:dc;a.sort(f);var h,f=new jc(a.length),i=l,m=l,n=a.length;for(h=0;hd?l:v(c)?c.charAt(d):c[d],"Unknown event: "+b)};function nc(){kc.call(this,["visible"]);var a,b;"undefined"!==typeof document&&"undefined"!==typeof document.addEventListener&&("undefined"!==typeof document.hidden?(b="visibilitychange",a="hidden"):"undefined"!==typeof document.mozHidden?(b="mozvisibilitychange",a="mozHidden"):"undefined"!==typeof document.msHidden?(b="msvisibilitychange",a="msHidden"):"undefined"!==typeof document.webkitHidden&&(b="webkitvisibilitychange",a="webkitHidden"));this.hb=k;if(b){var c=this;document.addEventListener(b, +function(){var b=!document[a];if(b!==c.hb){c.hb=b;c.Uc("visible",b)}},o)}}ka(nc,kc);da(nc);nc.prototype.xc=function(a){z("visible"===a);return[this.hb]};function oc(a){this.Gc=a;this.Zb=[];this.Ra=0;this.qc=-1;this.Ja=l};function Xb(a,b){for(var c in a)b.call(j,a[c],c,a)}function pc(a){var b={},c;for(c in a)b[c]=a[c];return b};function qc(){this.jb={}}function rc(a,b,c){u(c)||(c=1);D(a.jb,b)||(a.jb[b]=0);a.jb[b]+=c}qc.prototype.get=function(){return pc(this.jb)};function sc(a){this.ud=a;this.Qb=l}sc.prototype.get=function(){var a=this.ud.get(),b=pc(a);if(this.Qb)for(var c in this.Qb)b[c]-=this.Qb[c];this.Qb=a;return b};function tc(a,b){this.Pc={};this.hc=new sc(a);this.u=b;setTimeout(w(this.gd,this),10+6E4*Math.random())}tc.prototype.gd=function(){var a=this.hc.get(),b={},c=o,d;for(d in a)0=a.length){var b=Number(a);if(!isNaN(b)){c.Rc= +b;c.frames=[];a=l;break a}}c.Rc=1;c.frames=[]}a!==l&&Bc(c,a)}};this.Y.onerror=function(a){c.e("WebSocket error. Closing connection.");a.data&&c.e(a.data);c.Ka()}};yc.prototype.start=function(){};yc.isAvailable=function(){return!("undefined"!==typeof navigator&&"Opera"===navigator.appName)&&xc!==l&&!zc};function Bc(a,b){a.frames.push(b);if(a.frames.length==a.Rc){var c=a.frames.join("");a.frames=l;c="undefined"!==typeof JSON&&u(JSON.parse)?JSON.parse(c):la(c);a.Fd(c)}} +yc.prototype.send=function(a){Ac(this);a=y(a);rc(this.$,"bytes_sent",a.length);a=Vb(a,16384);1document.domain="'+document.domain+'";<\/script>');a=""+a+"";try{this.X.ya.open(),this.X.ya.write(a),this.X.ya.close()}catch(f){N("frame writing exception"),f.stack&&N(f.stack),N(f)}} +Jc.prototype.close=function(){this.mc=o;if(this.X){this.X.ya.body.innerHTML="";var a=this;setTimeout(function(){a.X!==l&&(document.body.removeChild(a.X),a.X=l)},0)}var b=this.ga;b&&(this.ga=l,b())}; +function Lc(a){if(a.mc&&a.fc&&a.Ic.count()<(0=a.Db[0].Yc.length+30+c.length){var e=a.Db.shift(),c=c+"&seg"+d+"="+e.Nd+"&ts"+d+"="+e.Sd+"&d"+d+"="+e.Yc;d++}else break;var b=b+c,f=a.sc;a.Ic.add(f);var h=function(){a.Ic.remove(f);Lc(a)},i=setTimeout(h,25E3);Kc(a,b,function(){clearTimeout(i);h()});return k}return o} +function Kc(a,b,c){setTimeout(function(){try{if(a.fc){var d=a.X.ya.createElement("script");d.type="text/javascript";d.async=k;d.src=b;d.onload=d.onreadystatechange=function(){var a=d.readyState;if(!a||"loaded"===a||"complete"===a)d.onload=d.onreadystatechange=l,d.parentNode&&d.parentNode.removeChild(d),c()};d.onerror=function(){N("Long-poll script failed to load: "+b);a.fc=o;a.close()};a.X.ya.body.appendChild(d)}}catch(e){}},1)};function Mc(){var a=[];Wb(Nc,function(b,c){c&&c.isAvailable()&&a.push(c)});this.ic=a}var Nc=[Gc,{isAvailable:r(o)},yc];function Oc(a,b,c,d,e,f){this.id=a;this.e=Ob("c:"+this.id+":");this.Gc=c;this.yb=d;this.R=e;this.Fc=f;this.K=b;this.Yb=[];this.Vc=0;this.Tc=new Mc;this.va=0;this.e("Connection created");Pc(this)}function Pc(a){var b;var c=a.Tc;0c)f=ua(q,I.key),u(f)?(n.push({wc:I,Qc:i[f]}),i[f]=l):(t[I.key]=m.length,m.push(I)),f=k,I=Wa(x);else{if(0c||0===c&&0>=Sb(a,d.Sa)}):c.push(function(a,b){return 0>=Rb(b,d.za)}));var e=l,f=l;if(u(this.J.Ba))if(u(this.J.ca)){if(e=Id(a,c,this.J.Ba,o)){var h=a.M(e).j();c.push(function(a,b){var c=Rb(b,h);return 0>c||0===c&&0>=Sb(a,e)})}}else if(f= +Id(a,c,this.J.Ba,k)){var i=a.M(f).j();c.push(function(a,b){var c=Rb(b,i);return 0d;d++)ne[d]=Math.floor(64*Math.random());for(d=0;12>d;d++)a+="-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".charAt(ne[d]);z(20===a.length,"NextPushId: Length should be 20.");return a};function J(){var a,b,c;if(arguments[0]instanceof Xd)c=arguments[0],a=arguments[1];else{A("new Firebase",1,2,arguments.length);var d=arguments[0];b=a="";var e=k,f="";if(v(d)){var h=d.indexOf("//");if(0<=h)var i=d.substring(0,h-1),d=d.substring(h+2);h=d.indexOf("/");-1===h&&(h=d.length);a=d.substring(0,h);var d=d.substring(h+1),m=a.split(".");if(3==m.length){h=m[2].indexOf(":");e=0<=h?"https"===i:k;if("firebase"===m[1])Qb(a+" is no longer supported. Please use .firebaseio.com instead"); +else{b=m[0];f="";d=("/"+d).split("/");for(i=0;i - this.store.findAll('document') - activate: -> - # Setup Pusher - pusher = new Pusher('8146487894a3cc81758c') - @set('pusher', pusher) - channel = pusher.subscribe('<%= Rails.env %>_main_channel') - channel.bind 'update', (payload) => - # TODO: Clean up this big ugly chunk of procedural code - payload.updated_at = new Date(payload.updated_at) - doc = @model().find((item) => item.get('id') == payload.id) - # debugger - if doc - doc.setProperties - title: payload.title - body: payload.body - updated_at: payload.updated_at - else - doc = LiveReader.Document.createRecord(payload) + EmberFire.Array.create + ref: new Firebase("https://lws.firebaseio.com") diff --git a/app/assets/javascripts/write_room.js.coffee b/app/assets/javascripts/write_room.js.coffee index f5dd32e..1061749 100644 --- a/app/assets/javascripts/write_room.js.coffee +++ b/app/assets/javascripts/write_room.js.coffee @@ -4,6 +4,11 @@ #= require bootstrap #= require_self #= require redactor +#= require handlebars +#= require ember +#= require ember-data +#= require firebase +#= require emberfire class Editor dirty: false @@ -11,15 +16,33 @@ class Editor body: false title: false - constructor: -> + constructor: (documentId) -> console.log("Initialising editor") + @documentId = documentId @takeSnapshot() + @setupFirebase() takeSnapshot: -> console.log("Taking snapshot of current text") @snapshot.body = @currentBody() @snapshot.title = @currentTitle() + setupFirebase: (documentId) -> + @db = new Firebase("https://lws.firebaseio.com") + @db.once 'value', (snapshot) => + snapshot.forEach (child) => + @doc = child.ref() if child.val().id == @documentId + unless @doc + @doc = @db.push + id: @documentId + isVisible: true + body: @currentBody() + title: @currentTitle() + $(".redactor_editor").on "keyup", (element) => + @doc.child('body').set @currentBody() + @doc.child('title').set @currentTitle() + console.log @currentBody() + currentBody: -> $('#redactor').getCode() @@ -74,15 +97,13 @@ WriteRoom.register = (label, callback) -> WriteRoom.require = (label, data) -> WriteRoom.fragments[label].call(window,data) -WriteRoom.register 'documents/edit', (data) -> +WriteRoom.register 'documents/edit', (documentId) -> console.log("Attaching redactor to view") $('#redactor').redactor() console.log("Initialising Editor instance") - - editor = new Editor - + editor = new Editor(documentId) editor.updateConnectionStatus("Ready!", "info") setInterval -> editor.update() - , 500 + , 5000 diff --git a/app/controllers/writeroom/documents_controller.rb b/app/controllers/writeroom/documents_controller.rb index 4261a79..52e4f3f 100644 --- a/app/controllers/writeroom/documents_controller.rb +++ b/app/controllers/writeroom/documents_controller.rb @@ -34,10 +34,7 @@ def create def update @document = Document.find(params[:id]) - - if @document.update(document_params) - Pusher.trigger(pusher_channel, 'update', @document.to_pusher) - end + @document.update(document_params) respond_with @document end diff --git a/app/models/document.rb b/app/models/document.rb index baeea40..ecb2c36 100644 --- a/app/models/document.rb +++ b/app/models/document.rb @@ -10,13 +10,5 @@ def word_count def notify_requester DocumentNotifier.writing_started_on(self).deliver unless self.requester.blank? end - def to_pusher - { - id: self.id.to_s, - title: self.title, - body: self.body, - updated_at: self.updated_at - } - end end diff --git a/app/views/writeroom/documents/edit.html.haml b/app/views/writeroom/documents/edit.html.haml index 986b6d0..4ef7632 100644 --- a/app/views/writeroom/documents/edit.html.haml +++ b/app/views/writeroom/documents/edit.html.haml @@ -2,4 +2,4 @@ - content_for :javascript do :javascript - WriteRoom.require('documents/edit', {}); + WriteRoom.require('documents/edit', #{@document.id});