Skip to content

Instantly share code, notes, and snippets.

@rhumlover
Created June 17, 2015 22:03
Show Gist options
  • Save rhumlover/f016bb010afa375df239 to your computer and use it in GitHub Desktop.
Save rhumlover/f016bb010afa375df239 to your computer and use it in GitHub Desktop.
Fancy ScopedFrame
Worker = require 'models/worker'
class ScopedFrame
# Private
_uniqueId = (prefix) ->
return prefix + Math.random().toString(36).slice(2)
_messageReceivedByParent = (message) ->
{origin, data} = message
return if origin isnt location.origin
return if (not data.sid) or data.sid isnt @sid
@worker.trigger data.transactionId, data.data
false
_messageReceivedByIframe = (message) ->
{data} = message
if data.sid and data.sid is @sid
message.reply = _reply.bind @, message
@worker.trigger data.action, data.data, message
false
_reply = (firstMessage, data) ->
{sid, transactionId, action} = firstMessage.data
message = {
sid
transactionId
action
data
}
window.postMessage message, firstMessage.origin
# Exposed
constructor: (options) ->
{@content, @style, @onLoad} = options
@sid = _uniqueId 'sid-'
@rendered = no
@worker = new Worker()
render: ->
return if @rendered
el = document.createElement 'iframe'
if @style?
Object.keys(@style).forEach(
(key) -> el.style[key] = @[key]
@style
)
document.body.appendChild el
ifWindow = el.contentWindow
ifDocument = ifWindow.document
ifDocument.open()
ifDocument.write @content
ifDocument.close()
window.addEventListener 'message', _messageReceivedByParent.bind(@), false
ifWindow.addEventListener 'message', _messageReceivedByIframe.bind(@), false
ifDocument.onreadystatechange = =>
if ifDocument.readyState is 'interactive' then @onLoad?()
@rendered = yes
@el = el
getWindow: ->
@el.contentWindow
listen: (action) ->
unless @rendered
console.warn 'ScopedFrame: trying to listen for a message in an unrendered document. Render your ScopedFrame first.'
return
@worker.listen action, @el.contentWindow
send: (action, data) ->
unless @rendered
console.warn 'ScopedFrame: trying to send a message to an unrendered document. Render your ScopedFrame first.'
return
message = {
transactionId: _uniqueId 'tid-'
@sid
action
data
}
@el.contentWindow.postMessage message, location.origin
eventStream = @worker.listen message.transactionId
eventStream.onReply = eventStream.then
eventStream
module.exports = ScopedFrame
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment