Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
components
build
node_modules
23 changes: 22 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,36 @@ $ npm install load-script
```

## API
`load-script` appends a `script` node to the `<head>` element in the dom.

`require('load-script')` returns a function of the following interface: `function(url[, opts][, cb]) {}`

### url
Any url that you would like to load. May be absolute or relative.

### [, opts]
A map of options. Here are the currently supported options:

* `async` - A boolean value used for `script.async`. By default this is `true`.
* `attrs` - A map of attributes to set on the `script` node before appending it to the DOM. By default this is empty.
* `charset` - A string value used for `script.charset`. By default this is `utf8`.
* `text` - A string of text to append to the `script` node before it is appended to the DOM. By default this is empty.
* `type` - A string used for `script.type`. By default this is `text/javascript`.

### [, cb]
A callback function of the following interface: `function(err, script) {}` where `err` is an error if any occurred and `script` is the `script` node that was appended to the DOM.

## Example Usage

```javascript
var load = require('load-script')

load('foo.js', function (err) {
load('foo.js', function (err, script) {
if (err) {
// print useful message
}
else {
console.log(script.src);// Prints 'foo'.js'
// use script
// note that in IE8 and below loading error wouldn't be reported
}
Expand Down
36 changes: 28 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@

module.exports = function load (src, cb) {
module.exports = function load (src, opts, cb) {
var head = document.head || document.getElementsByTagName('head')[0]
var script = document.createElement('script')

cb = cb || function() {};
if (typeof opts === 'function') {
cb = opts
opts = {}
}

opts = opts || {}
cb = cb || function() {}

script.type = 'text/javascript'
script.charset = 'utf8'
script.async = true
script.type = opts.type || 'text/javascript'
script.charset = opts.charset || 'utf8';
script.async = 'async' in opts ? !!opts.async : true
script.src = src

if (opts.attrs) {
setAttributes(script, opts.attrs)
}

if (opts.text) {
script.appendChild(document.createTextNode(opts.text))
}

var onend = 'onload' in script ? stdOnEnd : ieOnEnd
onend(script, cb)

Expand All @@ -23,23 +37,29 @@ module.exports = function load (src, cb) {
head.appendChild(script)
}

function setAttributes(script, attrs) {
for (var attr in attrs) {
script.setAttribute(attr, attrs[attr]);
}
}

function stdOnEnd (script, cb) {
script.onload = function () {
this.onerror = this.onload = null
cb()
cb(null, script)
}
script.onerror = function () {
// this.onload = null here is necessary
// because even IE9 works not like others
this.onerror = this.onload = null
cb(new Error('Failed to load ' + this.src))
cb(new Error('Failed to load ' + this.src), script)
}
}

function ieOnEnd (script, cb) {
script.onreadystatechange = function () {
if (this.readyState != 'complete' && this.readyState != 'loaded') return
this.onreadystatechange = null
cb(null, true) // there is no way to catch loading errors in IE8
cb(null, script) // there is no way to catch loading errors in IE8
}
}
41 changes: 41 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,47 @@ test('success', function(done) {
})
});

test('opts.async', function(done) {
load('test/hello.js', {async: false}, function(err, script) {
assert.ifError(err);
assert.equal(script.async, false);
done();
})
});

test('opts.attrs', function(done) {
load('test/hello.js', {attrs: {foo: 'boo'}}, function(err, script) {
assert.ifError(err);
assert.equal(script.getAttribute('foo'), 'boo');
done();
})
});

test('opts.charset', function(done) {
load('test/hello.js', {charset: 'iso-8859-1'}, function(err, script) {
assert.ifError(err);
assert.equal(script.charset, 'iso-8859-1');
done();
})
});

test('opts.text', function(done) {
load('test/hello.js', {text: 'foo'}, function(err, script) {
assert.ifError(err);
assert.equal(script.childNodes.length, 1);
assert.equal(script.childNodes[0].nodeValue, 'foo');
done();
})
});

test('opts.type', function(done) {
load('test/hello.js', {type: 'text/ecmascript'}, function(err, script) {
assert.ifError(err);
assert.equal(script.type, 'text/ecmascript');
done();
})
});

test('no exist', function(done) {
load('unexistent.js', function (err, legacy) {
if (!legacy) {
Expand Down