Translate annotation-sync.coffee to JavaScript

annotation-sync.js is the unmodified output of
`coffee -bc src/annotator/annotation-sync.coffee`.
parent 6ba26182
# AnnotationSync listens for messages from the sidebar app indicating that
# annotations have been added or removed and relays them to Annotator.
#
# It also listens for events from Annotator when new annotations are created or
# annotations successfully anchor and relays these to the sidebar app.
module.exports = class AnnotationSync
# Cache of annotations which have crossed the bridge for fast, encapsulated
# association of annotations received in arguments to window-local copies.
cache: null
constructor: (@bridge, options) ->
if !options.on
throw new Error('options.on unspecified for AnnotationSync.')
if !options.emit
throw new Error('options.emit unspecified for AnnotationSync.')
@cache = {}
@_on = options.on
@_emit = options.emit
# Listen locally for interesting events
for event, handler of @_eventListeners
this._on(event, handler.bind(this))
# Register remotely invokable methods
for method, func of @_channelListeners
@bridge.on(method, func.bind(this))
sync: (annotations) ->
annotations = (this._format a for a in annotations)
@bridge.call 'sync', annotations, (err, annotations = []) =>
for a in annotations
this._parse(a)
this
# Handlers for messages arriving through a channel
_channelListeners:
'deleteAnnotation': (body, cb) ->
annotation = this._parse(body)
delete @cache[annotation.$tag]
@_emit('annotationDeleted', annotation)
cb(null, this._format(annotation))
'loadAnnotations': (bodies, cb) ->
annotations = (this._parse(a) for a in bodies)
@_emit('annotationsLoaded', annotations)
cb(null, annotations)
# Handlers for events coming from this frame, to send them across the channel
_eventListeners:
'beforeAnnotationCreated': (annotation) ->
return if annotation.$tag?
this._mkCallRemotelyAndParseResults('beforeCreateAnnotation')(annotation)
_mkCallRemotelyAndParseResults: (method, callBack) ->
(annotation) =>
# Wrap the callback function to first parse returned items
wrappedCallback = (failure, results) =>
unless failure?
this._parseResults results
callBack? failure, results
# Call the remote method
@bridge.call(method, this._format(annotation), wrappedCallback)
# Parse returned message bodies to update cache with any changes made remotely
_parseResults: (results) ->
for bodies in results
bodies = [].concat(bodies) # Ensure always an array.
this._parse(body) for body in bodies when body != null
return
# Assign a non-enumerable tag to objects which cross the bridge.
# This tag is used to identify the objects between message.
_tag: (ann, tag) ->
return ann if ann.$tag
tag = tag or window.btoa(Math.random())
Object.defineProperty(ann, '$tag', value: tag)
@cache[tag] = ann
ann
# Parse a message body from a RPC call with the provided parser.
_parse: (body) ->
local = @cache[body.tag]
remote = body.msg
merged = Object.assign(local || {}, remote)
this._tag(merged, body.tag)
# Format an annotation into an RPC message body with the provided formatter.
_format: (ann) ->
this._tag(ann)
{
tag: ann.$tag
msg: ann
}
// Generated by CoffeeScript 1.10.0
var AnnotationSync;
module.exports = AnnotationSync = (function() {
AnnotationSync.prototype.cache = null;
function AnnotationSync(bridge, options) {
var event, func, handler, method, ref, ref1;
this.bridge = bridge;
if (!options.on) {
throw new Error('options.on unspecified for AnnotationSync.');
}
if (!options.emit) {
throw new Error('options.emit unspecified for AnnotationSync.');
}
this.cache = {};
this._on = options.on;
this._emit = options.emit;
ref = this._eventListeners;
for (event in ref) {
handler = ref[event];
this._on(event, handler.bind(this));
}
ref1 = this._channelListeners;
for (method in ref1) {
func = ref1[method];
this.bridge.on(method, func.bind(this));
}
}
AnnotationSync.prototype.sync = function(annotations) {
var a;
annotations = (function() {
var i, len, results1;
results1 = [];
for (i = 0, len = annotations.length; i < len; i++) {
a = annotations[i];
results1.push(this._format(a));
}
return results1;
}).call(this);
this.bridge.call('sync', annotations, (function(_this) {
return function(err, annotations) {
var i, len, results1;
if (annotations == null) {
annotations = [];
}
results1 = [];
for (i = 0, len = annotations.length; i < len; i++) {
a = annotations[i];
results1.push(_this._parse(a));
}
return results1;
};
})(this));
return this;
};
AnnotationSync.prototype._channelListeners = {
'deleteAnnotation': function(body, cb) {
var annotation;
annotation = this._parse(body);
delete this.cache[annotation.$tag];
this._emit('annotationDeleted', annotation);
return cb(null, this._format(annotation));
},
'loadAnnotations': function(bodies, cb) {
var a, annotations;
annotations = (function() {
var i, len, results1;
results1 = [];
for (i = 0, len = bodies.length; i < len; i++) {
a = bodies[i];
results1.push(this._parse(a));
}
return results1;
}).call(this);
this._emit('annotationsLoaded', annotations);
return cb(null, annotations);
}
};
AnnotationSync.prototype._eventListeners = {
'beforeAnnotationCreated': function(annotation) {
if (annotation.$tag != null) {
return;
}
return this._mkCallRemotelyAndParseResults('beforeCreateAnnotation')(annotation);
}
};
AnnotationSync.prototype._mkCallRemotelyAndParseResults = function(method, callBack) {
return (function(_this) {
return function(annotation) {
var wrappedCallback;
wrappedCallback = function(failure, results) {
if (failure == null) {
_this._parseResults(results);
}
return typeof callBack === "function" ? callBack(failure, results) : void 0;
};
return _this.bridge.call(method, _this._format(annotation), wrappedCallback);
};
})(this);
};
AnnotationSync.prototype._parseResults = function(results) {
var bodies, body, i, j, len, len1;
for (i = 0, len = results.length; i < len; i++) {
bodies = results[i];
bodies = [].concat(bodies);
for (j = 0, len1 = bodies.length; j < len1; j++) {
body = bodies[j];
if (body !== null) {
this._parse(body);
}
}
}
};
AnnotationSync.prototype._tag = function(ann, tag) {
if (ann.$tag) {
return ann;
}
tag = tag || window.btoa(Math.random());
Object.defineProperty(ann, '$tag', {
value: tag
});
this.cache[tag] = ann;
return ann;
};
AnnotationSync.prototype._parse = function(body) {
var local, merged, remote;
local = this.cache[body.tag];
remote = body.msg;
merged = Object.assign(local || {}, remote);
return this._tag(merged, body.tag);
};
AnnotationSync.prototype._format = function(ann) {
this._tag(ann);
return {
tag: ann.$tag,
msg: ann
};
};
return AnnotationSync;
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment