Skip to content
waveform80 edited this page Jan 15, 2013 · 16 revisions

How to use

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.

Bare-bones example

A very basic example of it's use is the bare-bones example Visual Editor page.

Reference implementation

See the relevant files in the reference implementation for a more complete example:

Full configuration options 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
		}
	});

Visual Editor member functions

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()

Interacting with the CSL style (MVC architecture)

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:

  1. Reading is done by interacting with the CSLEDIT_data (src/dataInstance.js).

  2. Writing is done by issuing commands to the CSLEDIT_controller (src/controller.js).

CSL style representation

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 representation

	<?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>

JSON representation

	{
		"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.

Reading

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.

Writing

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 in CSLEDIT_data, see src/Data.js for the definitions

    • addNode
    • deleteNode
    • moveNode
    • amendNode
    • setCslCode
  • args - the list of arguments to pass to the function specified in command

  • 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:

addNode

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 : []
			}
		]
		}
	]);
});

deleteNode

Delete the node with cslId 8:

require(['src/controller'], function (CSLEDIT_controller) {
	CSLEDIT_controller.exec('deleteNode', [8]);
});

moveNode

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"]);
});

amendNode

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"
		]
	}]);
});

setCslCode

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>"]);
});

Undo and Redo

CSLEDIT_controller allows undo and redo of all the above commands.

undo

To undo the last command:

require(['src/controller'], function (CSLEDIT_controller) {
	// check commandHistory first
	if (CSLEDIT_controller.commandHistory.length > 0) {
		CSLEDIT_controller.undo();
	}
});

redo

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();
	}
});

Changing the example citations

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
	);
});

More help

Please browse the source code to learn more, there are plenty of comments to help you there.