Skip to content
This repository has been archived by the owner on Jun 2, 2020. It is now read-only.

Commit

Permalink
Add DOM Storage setters
Browse files Browse the repository at this point in the history
  • Loading branch information
Félix Saparelli committed Nov 8, 2011
1 parent d475ca7 commit f213484
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 39 deletions.
13 changes: 8 additions & 5 deletions README.markdown
Expand Up @@ -11,7 +11,7 @@ extra file you will ever have to load is `dynworker.js`.

DynWorker contains a few utilities to augment your worker. You can easily inject
functions into the worker, run arbitrary code, pass messages containing mixed
data (everything is JSON-encoded), and access DOM storage.
data (everything is JSON-encoded), and access DOM storage (setters only atm).

Future developments may include being able to clone workers, access the DOM asynchronously,
make full XHR requests (including XML parsing), access the indexedDB directly from
Expand Down Expand Up @@ -46,9 +46,10 @@ worker.inject("funcName", function(arg1, arg2) {
return result;
});

// The callback gets back the raw event
worker.receive(function(e) {
e.data; // Display and strike awe
// The callback gets back the raw event and the
// parsed data
worker.receive(function(e, data) {
data; // Display and strike awe
});


Expand All @@ -73,7 +74,9 @@ Inside the worker:

```javascript
DynWorker.localStorage.setItem("key", "data");
var data = DynWorker.localStorage.getItem("key");
DynWorker.localStorage.getItem("key", function(data) {
// Getters are not implemented yet
});
```


Expand Down
104 changes: 90 additions & 14 deletions dynworker.coffee
@@ -1,26 +1,33 @@
###
DynWorker is Copyright Félix "passcod" Saparelli
DynWorker is copyright Félix "passcod" Saparelli
and licensed under MIT: http://mit.passcod.net
###

"use strict";

DynWorker = (path = DynWorker.libpath) ->
# The internal worker
worker = new Worker(path)

# Adds a listener to the "onmessage" event. The `e` object
# cannot be touched, so we also pass a second parameter that
# contains the unserialized data.
receive = (func) ->
callback = (e) ->
e.data = JSON.parse e.data
func e
func e, JSON.parse e.data
worker.addEventListener "message", callback, false

# A helper method for devs!
log = ->
receive (e) ->
console.log e.data
receive (e, data) ->
console.log data

# Send a message to the worker. The message is JSON-ified, so
# you can pass in whatever will get properly serialized.
send = (msg) ->
worker.postMessage(JSON.strinigfy msg)
worker.postMessage(JSON.stringify msg)

# Send a command to the worker. Args optional
cmd = (action, args...) ->
msg = {DynWorkerAction: action, args: 0}
objAdd = (arg) ->
Expand All @@ -29,20 +36,54 @@ DynWorker = (path = DynWorker.libpath) ->
objAdd arg for arg in args
send msg


# Eval code in the worker
weval = (code) ->
cmd 'eval', code

# Inject a function in the worker. The function can be anonymous or
# named, but the name will get stripped anyway, so you have to be
# careful when writing recursive functions to use the internal name.
inject = (name, func) ->
# There's two kinds of functions: named and anonymous. We want them
# all to be anonymous, so we can easily store them.
sfunc = func.toString()
unless /^function \(/.test(sfunc)
sfunc.replace(/^function [^\(]+\(/, 'function (')

# Namespace the function inside the worker
weval "DynWorker.ns['#{name}']=#{sfunc};"

# Run a function in the worker and pass it args
run = (name, args...) ->
# Send up what the function returns
weval "DynWorker.send(DynWorker.ns['#{name}'].apply(null, #{JSON.stringify args}));"

# Use DOM Storage
store = (type, action, key, data) ->
switch action
when 'set'
if type is 'local'
window.localStorage.setItem key, data
else
window.sessionStorage.setItem key, data

when 'remove'
if type is 'local'
window.localStorage.removeItem key
else
window.sessionStorage.removeItem key

when 'clear'
if type is 'local'
window.localStorage.clear()
else
window.sessionStorage.clear()

# Respond to commands from worker
receive (e, data) ->
switch data['DynWorkerAction']
when 'domstorage' then store data.arg1, data.arg2, data.arg3, data.arg4

return {
receive: receive
log: log
Expand All @@ -53,21 +94,31 @@ DynWorker = (path = DynWorker.libpath) ->
run: run
}

DynWorker.ns = {}

# Default path and method to set it differently
DynWorker.libpath = "dynworker.js"
DynWorker.path = (path) ->
if path then DynWorker.libpath = path


# The following functions make up the in-worker API. They probably shouldn't
# be defined here, but rather added when needed. For now it's OK, though.

# Namespace for injected functions
DynWorker.ns = {}

# Receive a message from the parent (main) thread
DynWorker.receive = (func) ->
callback = (e) ->
e.data = JSON.parse e.data
func e
# Can't touch `e`, so use a second parameter
func e, JSON.parse e.data
self.addEventListener "message", callback, false

# Send a message "up" (to the parent/main thread)
DynWorker.send = (msg) ->
self.postMessage(JSON.stringify msg)

# Send a command to the parent (main) thread. This works
# the same as worker.cmd does in the main thread.
DynWorker.cmd = (action, args...) ->
msg = {DynWorkerAction: action, args: 0}
objAdd = (arg) ->
Expand All @@ -76,12 +127,37 @@ DynWorker.cmd = (action, args...) ->
objAdd arg for arg in args
DynWorker.send msg

# Use DOM Storage from the worker. Everything is async,
# and the getters take a callback method instead of returning.
DynWorker.localStorage = {
setItem: (key, data) ->
DynWorker.cmd 'domstorage', 'local', 'set', key, data

removeItem: (key) ->
DynWorker.cmd 'domstorage', 'local', 'remove', key

clear: ->
DynWorker.cmd 'domstorage', 'local', 'clear'
}
DynWorker.sessionStorage = {
setItem: (key, data) ->
DynWorker.cmd 'domstorage', 'session', 'set', key, data

removeItem: (key) ->
DynWorker.cmd 'domstorage', 'session', 'remove', key

clear: ->
DynWorker.cmd 'domstorage', 'session', 'clear'
}


if typeof window == "undefined"
# This is a worker
self.DynWorker = DynWorker

DynWorker.receive (e) ->
switch e.data['DynWorkerAction']
when 'eval' then eval e.data['arg1']
DynWorker.receive (e, data) ->
switch data['DynWorkerAction']
when 'eval' then eval data['arg1']
else
# This is the main thread
window.DynWorker = DynWorker
133 changes: 114 additions & 19 deletions dynworker.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion index.html
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<title>DynWorker - Dynamic Web Worker</title>
<link rel="stylesheet" href="style.css" />
<script src="http://localhost:8080/dynworker.js"></script>
<script src="/dynworker.js"></script>
</head>
<body>
<script>
Expand Down

0 comments on commit f213484

Please sign in to comment.