Skip to content

Commit 8b6a449

Browse files
committed
Initial commit
1 parent 7db8cc5 commit 8b6a449

File tree

5 files changed

+155
-0
lines changed

5 files changed

+155
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
elm-stuff/

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# elm-jsonp
2+
3+
Send HTTP requests to servers that implement strict CORS headers.
4+
5+
It emulates `elm-http`'s `Http.send` and `Http.get` API. POST requests have not
6+
been implemented yet.
7+
8+
## Usage
9+
10+
Because we aren't allowed to publish packages with Native JS code, you'll either
11+
have to clone this project into a `vendor/elm-jsonp` folder and add it to your
12+
`elm-package.json` source-directories and alter the Native module name.
13+
14+
Or, you can use [`elm_self_publish`](https://github.com/NoRedInk/elm-ops-tooling/blob/master/elm_self_publish.py)
15+
which will take care of changing the Native module to your project's user and name,
16+
compiling the package, and copying it to your project's `elm-stuff/packages`. I'd recommend
17+
using this script.
18+
19+
## Example
20+
21+
```elm
22+
import Http
23+
import Jsonp
24+
import Json.Decode as Json exposing ((:=))
25+
import Task exposing (Task)
26+
27+
type alias Info =
28+
{ identified : Bool }
29+
30+
31+
lookupInfo : Task Http.Error Info
32+
lookupInfo =
33+
Jsonp.get infoDecoder ("https://api.twitch.tv/kraken")
34+
35+
36+
infoDecoder : Json.Decoder Info
37+
infodecoder =
38+
Json.object1 Info
39+
("identified" := Json.bool)
40+
```

elm-package.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"version": "1.0.0",
3+
"summary": "A Native implementation for sending JSONP GET requests",
4+
"repository": "https://github.com/tolgap/elm-jsonp.git",
5+
"license": "BSD3",
6+
"native-modules": true,
7+
"source-directories": [
8+
"src"
9+
],
10+
"exposed-modules": [
11+
"Jsonp"
12+
],
13+
"dependencies": {
14+
"elm-lang/core": "4.0.5 <= v < 5.0.0",
15+
"evancz/elm-http": "3.0.1 <= v < 4.0.0"
16+
},
17+
"elm-version": "0.17.1 <= v < 0.18.0"
18+
}

src/Jsonp.elm

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
module Jsonp exposing (jsonp, get)
2+
3+
{-| # Fetch JSON
4+
5+
@docs get
6+
7+
# Arbitrary requests
8+
9+
@docs jsonp
10+
-}
11+
12+
import Http
13+
import Json.Decode as Json
14+
import Native.Jsonp
15+
import Random
16+
import Task exposing (Task)
17+
import Time
18+
19+
{-| Send a GET request to the given URL. The specified `Decoder` will be
20+
used to parse the result.
21+
22+
See [`Http.get`](http://package.elm-lang.org/packages/evancz/elm-http/3.0.1/Http#get)
23+
for same usage.
24+
-}
25+
get : Json.Decoder value -> String -> Task Http.Error value
26+
get decoder url =
27+
let
28+
decode s =
29+
Json.decodeString decoder s
30+
|> Task.fromResult
31+
|> Task.mapError Http.UnexpectedPayload
32+
in
33+
randomCallbackName
34+
`Task.andThen` jsonp url
35+
`Task.andThen` decode
36+
37+
{-| Send an arbitrary JSONP request. You will have to map the error for this `Task`
38+
yourself, as JSONP failures cannot be captured. You will most likely be using
39+
`Jsonp.get`. The first argument is the URL. The second argument is the callback name.
40+
`Jsonp.get` uses a random callback name generator under the hood.
41+
-}
42+
jsonp : String -> String -> Task x String
43+
jsonp =
44+
Native.Jsonp.jsonp
45+
46+
47+
randomCallbackName : Task x String
48+
randomCallbackName =
49+
let
50+
generator =
51+
Random.int 100 Random.maxInt
52+
in
53+
Time.now
54+
|> Task.map (round >> Random.initialSeed)
55+
|> Task.map (Random.step generator >> fst)
56+
|> Task.map (toString >> (++) "callback")

src/Native/Jsonp.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
var _tolgap$elm_jsonp$Native_Jsonp = function() {
2+
3+
function jsonp(url, callbackName)
4+
{
5+
return _elm_lang$core$Native_Scheduler.nativeBinding(function(callback) {
6+
window[callbackName] = function(content)
7+
{
8+
callback(_elm_lang$core$Native_Scheduler.succeed(JSON.stringify(content)));
9+
delete window[callbackName];
10+
};
11+
12+
var scriptTag = createScript(url, callbackName);
13+
document.head.appendChild(scriptTag);
14+
document.head.removeChild(scriptTag);
15+
});
16+
}
17+
18+
19+
function createScript(url, callbackName)
20+
{
21+
var s = document.createElement('script');
22+
s.type = 'text/javascript';
23+
24+
if (url.indexOf('?') >= 0)
25+
{
26+
s.src = url + '&callback=' + callbackName;
27+
}
28+
else {
29+
s.src = url + '?callback=' + callbackName;
30+
}
31+
32+
return s;
33+
}
34+
35+
36+
return {
37+
jsonp: F2(jsonp)
38+
};
39+
40+
}();

0 commit comments

Comments
 (0)