-
-
Notifications
You must be signed in to change notification settings - Fork 35
Visual Editor
This is the most basic javascript needed to use the Visual Editor.
require.config({
baseUrl: "..", // should be the path to cslEditorLib/
urlArgs : "bust=$GIT_COMMIT"
});
requirejs(['src/config'], function (config) {
require(['src/VisualEditor'], function (CSLEDIT_VisualEditor) {
var cslEditor = new CSLEDIT_VisualEditor('#visualEditorContainer', { /* options go here */ });
});
});
Most of this is boilerplate needed for RequireJS, the interesting line is this:
var cslEditor = new CSLEDIT_VisualEditor('#visualEditorContainer', { /* options go here */ });
This sets up the Visual Editor within the #visualEditorContainer
div. See the 'Full configuration options' example below to see all possible options.
The Visual Editor uses persistent storage in the browser to retain state, see Storage.
A very basic example of it's use is the bare-bones example Visual Editor page.
See the relevant files in the reference implementation for a more complete example:
Here's an example containing the complete list of options for the Visual Editor.
var cslEditor = new CSLEDIT.VisualEditor("#visualEditorContainer", {
// The name and function of the load style menu item
loadCSLName : "Load Style from Ref Manager",
loadCSLFunc : function () {
alert("Loading a blank CSL style");
cslEditor.setCslCode("<style><info /><citation><layout /></citation><bibliography><layout /></bibliography></style>");
},
// The name and function of the save/export style menu item
saveCSLName : "Save Style to Ref Manager",
saveCSLFunc : function (cslCode) {
alert("Save function not implemented");
},
// Name and function of the load from URL menu item
loadStyleFromUrlName : "Load Style From URL",
loadStyleFromUrlFunc : function () {
alert("Load from URL not implemented");
},
// this is called after every style edit
onChange : function () {
// you can access the current style contents using:
var code = cslEditor.getCslCode();
},
// override the default initial style of APA with this:
initialCslCode : "<style>this style is not valid!</style>",
// each example reference follows the csl-data.json schema, but doesn't require the 'id' propery
// (see https://github.com/citation-style-language/schema/blob/master/csl-data.json)
exampleReferences : [
{type:"article", title:"Article Title", author:"An Author", date:"2010"},
{type:"book", title:"Book Title", author:"Another Author", date:"2000"}
],
// a list of the references to appear in each citation
exampleCitations : [[0,1], [1]],
onLoaded : function () {
// do stuff after the UI has finished initializing
}
});
Tip: after instanciating a CSLEDIT_VisualEditor
, wait until the UI is loaded before doing anything, you can tell this by adding an onLoaded
callback in the constructor options
There is only a small set of helper functions exposed by instances of CSLEDIT_VisualEditor
. I'd encourage you to look at the src/visualEditor.js
code to see the documentation for these functions. It's worth looking at the function implementions too as they are quite simple and will help introduce you to other important modules like CSLEDIT_data
and CSLEDIT_controller
.
function setCslCode(cslCode)
function getCslCode()
function getStyleName()
function getStyleId()
function setStyleId(styleId)
function conformStyleToRepoConventions()
Tip: all code snippets below should work if you load the Visual Editor page and paste into the Chrome's Developer Tools console.
The Visual Editor uses the CSLEDIT.data
key in CSLEDIT_storage
(see Storage) to store a JSON representation of the current CSL style.
All interaction with the CSL style by the rest of the code happens in one of two ways:
-
Reading is done by interacting with the
CSLEDIT_data
(src/dataInstance.js
). -
Writing is done by issuing commands to the
CSLEDIT_controller
(src/controller.js
).
CSL styles are converted from XML form to a more convenient JSON representation by CSLEDIT_cslParser
(src/cslParser.js
). The XML and equivalent JSON representation of the new style template are shown here for example:
<?xml version="1.0" encoding="utf-8"?>
<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="never">
<info>
<title>No Title</title>
<id>Enter unique style id here</id>
<updated>2012-09-21T17:06:54+00:00</updated>
</info>
<citation>
<layout/>
</citation>
<bibliography>
<layout/>
</bibliography>
</style>
{
"name": "style",
"attributes": [
{
"key": "xmlns",
"value": "http://purl.org/net/xbiblio/csl",
"enabled": true
},
{
"key": "class",
"value": "in-text",
"enabled": true
},
{
"key": "version",
"value": "1.0",
"enabled": true
},
{
"key": "demote-non-dropping-particle",
"value": "never",
"enabled": true
}
],
"cslId": 0,
"children": [
{
"name": "info",
"attributes": [],
"cslId": 1,
"children": [
{
"name": "title",
"attributes": [],
"cslId": 2,
"children": [],
"textValue": "No Title"
},
{
"name": "id",
"attributes": [],
"cslId": 3,
"children": [],
"textValue": "Enter unique style id here"
},
{
"name": "updated",
"attributes": [],
"cslId": 4,
"children": [],
"textValue": "2012-09-21T17:06:57+00:00"
}
]
},
{
"name": "citation",
"attributes": [],
"cslId": 5,
"children": [
{
"name": "layout",
"attributes": [],
"cslId": 6,
"children": []
}
]
},
{
"name": "bibliography",
"attributes": [],
"cslId": 7,
"children": [
{
"name": "layout",
"attributes": [],
"cslId": 8,
"children": []
}
]
}
]
}
Note the cslId values in the above, these are often used to refer to a specific CSL node.
Use CSLEDIT_data.getCslCode()
to get an XML string, the usual representation of CSL:
require(['src/dataInstance'], function (CSLEDIT_data) {
var cslCode = CSLEDIT_data.getCslCode();
console.log("This is the entire CSL style in XML form:");
console.log(cslCode);
});
Use CSLEDIT_data.get()
to get a more useful JSON representation of the root style
node (i.e. the entire CSL style):
require(['src/dataInstance'], function (CSLEDIT_data) {
var cslData = CSLEDIT_data.get();
console.log("This is the entire CSL style in a JSON representation:");
console.log(JSON.stringify(cslData, null, 4));
});
Use CSLEDIT_data.getNode()
to get a specific CSL node by it's cslId:
require(['src/dataInstance'], function (CSLEDIT_data) {
// cslId 0 will always by the 'style' node
// let's see what the first child of 'style' is,
// which will have cslId 1 and typically be the 'style/info' node
var cslNode1 = CSLEDIT_data.getNode(1);
console.log("This is the CSL node with cslId === 1");
console.log(JSON.stringify(cslNode1, null, 4));
});
Use CSLEDIT_data.getNodesFromPath()
to get a list of CSL nodes with the given path:
// note: src/dataInstance -> CSLEDIT_data is the only exception to
// the convention that the variable name always matches the
// module source code name, mainly because src/Data.js and
// src/data.js are the same file on windows
require(['src/dataInstance'], function (CSLEDIT_data) {
// display the list of style authors and contrubutors
var styleInfoAuthors = CSLEDIT_data.getNodesFromPath('style/info/author');
$.each(styleInfoAuthors, function (i, authorNode) {
// the style/author node contains child nodes with textValues
$.each(authorNode.children, function (i, authorChildNode) {
// authorChildNode.name can be one of
// - name
// - email
// - uri
console.log("author " + authorChildNode.name + ": " + authorChildNode.textValue);
});
});
// get all text nodes within the root of a macro node
var textNodesInMacro = CSLEDIT_data.getNodesFromPath("style/macro/text");
$.each(textNodesInMacro, function (i, node) {
console.log("text node " + i + " has cslId: " + node.cslId);
});
});
All the public functions of CSLEDIT_data
are documented in src/Data.js
so please check there for more info.
To write to the current style you must use CSLEDIT_controller.exec()
function.
The arguments of CSLEDIT_controller.exec(command, args, silent)
are:
-
command
- the name of the function inCSLEDIT_data
, seesrc/Data.js
for the definitionsaddNode
deleteNode
moveNode
amendNode
setCslCode
-
args
- the list of arguments to pass to the function specified incommand
-
silent
(optional) - if true, this will not display an error message in case of error
Here is an example of each of the 5 possible commands:
Add a contributor to the 'style/info' node:
require(['src/controller'], function (CSLEDIT_controller) {
var styleInfoNode = CSLEDIT_data.getNodesFromPath('style/info')[0];
CSLEDIT_controller.exec('addNode', [styleInfoNode.cslId, "last", {
name : "contributor",
attributes : [],
children : [
{
name : "name",
textValue : name,
attributes : [],
children : []
},
{
name : "uri",
textValue : "<?php echo $_SESSION['profile_url'];?>",
attributes : [],
children : []
}
]
}
]);
});
Delete the node with cslId 8:
require(['src/controller'], function (CSLEDIT_controller) {
CSLEDIT_controller.exec('deleteNode', [8]);
});
Move node with cslId 7 to after cslId 3:
require(['src/controller'], function (CSLEDIT_controller) {
CSLEDIT_controller.exec('moveNode', [7, 3, "after"]);
});
Move node with cslId 7 to the last child within cslId 3:
require(['src/controller'], function (CSLEDIT_controller) {
CSLEDIT_controller.exec('moveNode', [7, 3, "last"]);
});
Specify new properties for node 7:
(Note: ammendNode will ignore child elements, use addNode if you need to add a sub-tree recursively)
require(['src/controller'], function (CSLEDIT_controller) {
CSLEDIT_controller.exec('amendNode', [7, {
name : text,
attributes : [
{
key: "macro",
value: "author-short"
]
}]);
});
Completely change the CSL style using a string containing XML:
require(['src/controller'], function (CSLEDIT_controller) {
// This command won't complete, and will display an error because the style is not valid
CSLEDIT_controller.exec('setCslCode', ["<style>Invalid style!!</style>"]);
});
CSLEDIT_controller
allows undo and redo of all the above commands.
To undo the last command:
require(['src/controller'], function (CSLEDIT_controller) {
// check commandHistory first
if (CSLEDIT_controller.commandHistory.length > 0) {
CSLEDIT_controller.undo();
}
});
To redo a command that you just undid:
require(['src/controller'], function (CSLEDIT_controller) {
// check undoCommandHistory first
if (CSLEDIT_controller.undoCommandHistory.length > 0) {
CSLEDIT_controller.redo();
}
});
The example citations metadata are also stored in CSLEDIT_storage
(src/storage.js
) but don't have a separate model and controller with undo functionality. Any module is free to read and write to them using the CSLEDIT_exampleCitations
(src/exampleCitations.js
) module.
Here's some code demonstrating how to alter the example inline citations.
require(['src/exampleCitations'], function (CSLEDIT_exampleCitations) {
// let's see the JSON data for first reference in example citation 0
var referenceIndexes = CSLEDIT_exampleCitations.getReferenceIndexesForCitation(0);
console.log("Citation 0 contains the following references:");
$.each(referenceIndexes, function (i, referenceIndex) {
var referenceData = CSLEDIT_exampleCitations.getReferences()[referenceIndexes[0]];
console.log("reference " + i + " is " + JSON.stringify(referenceData));
});
// this resets the exampleCitations to the default ones
// (either the ones in src/exampleData, or the ones specified in the CSLEDIT_VisualEditor options)
CSLEDIT_exampleCitations.resetToDefault();
// takes same input as the exampleReferences constructor option
CSLEDIT_exampleCitations.setReferences([
{
title : "reference 1"
},
{
title : "reference 2"
}
]);
// Let's make citation 0 contain reference 0 only
CSLEDIT_exampleCitations.setReferenceIndexesForCitation(0, [0]);
// Let's make citation 1 contain references 0 and 1
CSLEDIT_exampleCitations.setReferenceIndexesForCitation(1, [0, 1]);
// Add a new reference to citation 2 (the 3rd one)
CSLEDIT_exampleCitations.addReference(
// argument 1 is a csl-data.json object
// (see https://github.com/citation-style-language/schema/blob/master/csl-data.json)
{
title : "New reference",
type: "article-journal"
},
// argument 2 (optional) is the index of the citation you want to add to
2
);
});
Please browse the source code to learn more, there are plenty of comments to help you there.