Manage desktop scripts in a simple way in Adaptive.js
Descript allows you to manage scripts captured from the desktop site's HTML from within your Adaptive.js views. It provides some simple features, such as:
- loading all desktop scripts into a default container, preserving source order
- allowing the developer to create containers of scripts for different use cases (i.e. urgent scripts that need to be executed in the document head)
- allowing for unneeded scripts to be removed
- adding the ability to inject a script to execute at a specific location within a script container.
Install descript
using bower:
bower install descript --save
Initialize it in your view:
descript.init();
If you need to preserve scripts in the DOM in a certain position (i.e. you want descript to leave certain scripts alone), you can specify a preserve
option when initializing:
descript.init({
preserve: {
src: 'leaveThisScript.js',
contains: ['leave', 'these', 'too']
}
});
The init
method creates a singleton instance, so subsequent calls will simply return the same instance. This is particularly useful if you need to manipulate scripts in a specific view in addition to the base view.
After initializing you can then use descript to add scripts to different containers, using patterns that match either src
attributes (or x-src
in the case of a captured document) for external scripts, or string patterns for inline scripts:
descript
.add('urgent', {
src: ['script1.js', 'script2.js'],
contains: 'somescript.init'
})
.add('defer', {
src: ['script4.js']
});
You can also remove scripts entirely:
descript.remove({
src: ['jquery']
});
To get scripts within a specific container, use the get
function, which returns a wrapped set of scripts:
var $urgentScripts = descript.get('urgent');
or you can get all the scripts:
var $allScripts = descript.getAll();
which will return an object of key/value pairs containing the containers, by name, and the wrapped set of scripts for each container.
If you need to insert a script at a specific location, to proxy or override a function for example, you can do this using the insertScript
function. The second parameter to insertScript
can be either a string
representing the src
attribute of an external script, or a function
representing the contents of an inline script.
// inserts an external script
descript.insertScript({src: 'script4.js'}, 'someExternal.js');
or
// inserts an inline script
descript.insertScript({src: 'script4.js'}, function() {
// do some overrides in here
);
This will inject an inline script immediately after the script defined in the script attribute. So, in the above case, the function passed in will be injected immediately following the script that has a src
attribute containing script4.js
.
At times it may be necessary to test for the existence of certain scripts. To do this you can use the exists
function.
if (!descript.exists({src: 'someScript'})) {
descript.insertScript({src: 'script1'}, 'someScript.js');
}
Search types are supplied via an object, where the key is the search type and the value is the pattern. The pattern can be either a string or regex.
In the example below, we're using the src
search type, and the pattern is jquery.ui
.
{ src: 'jquery-ui' }
This will match the following:
<script type="text/javascript" x-src="/assets/js/jquery-ui-1.11.4.js"></script>
Patterns can be either:
- A single string or regex pattern, i.e.
'script1'
or/script1/
or/script\d/
- A string of comma separated patterns, i.e.
'script1, script2'
- An array of string or regex patterns, i.e.
['script1', 'script2']
or[/script1/, /script2/]
Internally descript will normalize these values into an array of patterns.
There are a two different ways to search for scripts.
Specifying the src
search type will search the script element's x-src
attribute to see whether it matches the search pattern. If using strings, internally it's using Zepto's contains attribute selector ([x-src*=]). If using regex, it matches the pattern.
descript
.add('urgent', {
src: ['script1.js', 'script2.js']
});
Use the contains
search type if searching for content in an inline script. If using strings, it's using a simple contains using indexOf. If using regex, it matches the pattern.
descript
.add('urgent', {
contains: 'somescript.init'
});
In addition to searching by the source filename (src
) and contents of the
script (contains
), you can define a custom function to filter scripts by.
Parameter name | Description |
---|---|
searcher name | The name of the searcher |
filter function | A function that should return true or false. |
Parameter name | Description |
---|---|
$script (argument 1) | The current script to be evaluated |
query (argument 2) | The searching criteria |
Add a new searcher example:
descript
.addSearcher(
'selector',
function ($script, query) {
return !!$script.filter(query).length;
}
)
Above searcher will allow script search based on query selectors.
Example usage:
descript
.add('templates', {
selector: '.template'
});
// Above will capture any scripts with the following html markup
<script class="template">...</script>
Once you've added, removed, and inserted to your heart's content, you will want to output the manipulated scripts in your dust template. To do so, you'll want to retreive all the script containers and attach them to your context.
var descript;
return {
template: template,
includes: {
header: header,
footer: footer
},
preProcess: function() {
descript = Descript.init();
descript
.add('seusses', {
src: ['one-script', 'two-script'],
contains: ['red script', 'blue script']
})
.remove({ src: 'this-script, that-script' });
},
context: {
scripts: descript.getAll(), // attach to context property
...
}
};
And ultimately use in your dust template:
{scripts.seusses}
...
{scripts.default}
Adds a script to a custom container.
Parameter name | Description |
---|---|
container | The container to add the script to |
searchType | An object containing one or more search types and one or more script patterns for each type |
descript
.add('urgent', {
src: ['script1.js', 'script2.js'],
contains: 'somescript.init'
})
.add('defer', {
src: ['script4.js']
});
Removes a script from the default container.
Parameter name | Description |
---|---|
searchType | An object containing one or more search types and one or more script patterns for each type |
descript.remove({ src: 'jquery' });
Inserts a script after the script specified by searchType
Parameter name | Description |
---|---|
searchType | An object containing one search type and one script pattern |
scriptToInsert | A string (representing an src attribute path) or a function (representing the contents of an inline script) |
// inserts an external script
descript.insertScript({src: 'script4.js'}, 'someExternal.js');
or
// inserts an inline script
descript.insertScript({src: 'script4.js'}, function() {
// do some overrides in here
);
Replaces the contents of an inline script specified by searchType
Parameter name | Description |
---|---|
searchType | An object containing one search type and one script pattern |
pattern | A string (representing the pattern to find) or an object (representing a has of pattern/replacement pairs) |
replacement | If pattern is a string, this represents the replacement string |
descript.replace({contains: 'google'}, 'alert', 'console.log');
or
descript.replace({contains: 'google'}, [
{
pattern: 'alert',
replacement: 'console.log'
},
{
pattern: 'hi',
replacement: 'bye'
}
]);
Determines the existence of the script specified by searchType
Parameter name | Description |
---|---|
searchType | An object containing one search type and one script pattern |
// returns true if the script exists
descript.exists({src: 'script4.js'});
grunt
orgrunt build
- builds a distributable releasegrunt test
- runs the test suitegrunt test:browser
- runs a server that allows you to run the test suite in your browser