<commit_before>/**
 * Construct the module list from source.
 * The module list is located in the source
 * because it must also work with noscript.
 */
function reapModuleList() {
	var modules = new Array();

	$('#module-list-source').find('li > a').each(function() {
		modules.push($(this).text());
	});

	return modules;
}

/**
 * Build a table representing the module hierarchy of the project
 * given a linear list of modules.
 */
function buildModuleTree(modlist) {
	var root = {'members': {}};

	for (var i = 0; i < modlist.length; i++) {
		var qualifiedName = modlist[i];
		var parts = qualifiedName.split('.');

		var parent = root;
		for(var partIndex = 0; partIndex < parts.length; partIndex++) {
			var name = parts[partIndex];
			var node;

			if(partIndex == parts.length - 1) {
				node = {'type': 'module', 'qualifiedName': qualifiedName};
				parent.members[name] = node;
			} else {
				node = parent.members[name];
				if(typeof node == "undefined") {
					node = {'type': 'package', 'members': {}};
					parent.members[name] = node;
				}
			}

			parent = node;
		}
	}

	return root;
}

/**
 * Build a path to the appropriate resource for a fully qualified module name,
 * respecting the global PackageSeparator variable.
 */
function qualifiedModuleNameToUrl(modName) {
	if(PackageSeparator == '.') {
		return modName + '.html';
	} else {
		return modName.replace(/\./g, PackageSeparator) + '.html';
	}
}

/**
 * Create the module list in the sidebar.
 */
function populateModuleList(modTree) {
	function treePackageNode(name) {
		return '
' +
			   ' ' + name + '' +
			   '

';
	}

	function treeModuleNode(name, url) {
		return '
' +
			   ' ' + name + '' +
			   '
';
	}

	var $listHeader = $('#module-list');

	function traverser(node, $parentList) {
		for(var name in node.members) {
			var member = node.members[name];

			if(member.type == 'package') {
				var $elem = $(treePackageNode(name));
				$parentList.append($elem);

				var $ul = $elem.find('ul');
				if($parentList != $listHeader) {
					$ul.hide();
				}

				traverser(member, $ul);

			} else if(member.type == 'module') {
				var url = qualifiedModuleNameToUrl(member.qualifiedName);
				var $elem = $(treeModuleNode(name, url));
				$parentList.append($elem);

				if(member.qualifiedName == Title) { // Current module.
					$elem.find('a').append(' ');

					var $up = $parentList;
					while(!$up.is($listHeader)) {
						$up.show();
						$up = $up.parent();
					}
				}
			}
		}
	}

	traverser(modTree, $listHeader);
}

/**
 * Build a relative path for the given module name.
 */
function moduleNameToPath(modName) {
	return modName.replace(/\./g, '/') + '.d';
}

/**
 * Configure the breadcrumb component at the top of the page
 * with the current module.
 */
function updateBreadcrumb(qualifiedName, sourceRepoUrl) {
	var $breadcrumb = $('#module-breadcrumb');

	var parts = qualifiedName.split('.');
	for(var i = 0; i < parts.length; i++) {
		var part = parts[i];

		if(i == parts.length - 1) {
			var sourceUrl = sourceRepoUrl + '/' + moduleNameToPath(qualifiedName);
			$breadcrumb.append('

' + part + ' view source

');
		} else {
			$breadcrumb.append('

' + part + '/

');
		}
	}
}

var enumRegex = /^enum /;
var structRegex = /^struct /;
var classRegex = /^class /;
var templateRegex = /^template /;
var functionRegex = /\);\s*$/m;
var propertyRegex = /@property/m;
var specialMemberRegex = /^([^(]+)/;

/**
 * Build a table out of all symbols declared in the current module.
 */
function buildSymbolTree() {
	function fillTree(parentNode, $parent) {
		$parent.children('.declaration').each(function() {
			var $decl = $(this);
			var text = $decl.text();

			var $symbolLink = $decl.find('.symbol-link');
			var symbol;
			if($symbolLink.length == 0) { // Special member (e.g. constructor).
				symbol = text.match(specialMemberRegex)[0];
			} else {
				symbol = $symbolLink.html();
			}

			function fillSubTree(type) {
				var subTree = {
					'name': symbol,
					'type': type,
					'members': new Array(),
					'decl': $decl,
					'symbolLinkNode': $symbolLink,
				};

				parentNode.push(subTree);
				fillTree(subTree.members, $decl.next('.declaration-content').children('.member-list'));
			}

			function addLeaf(type) {
				var leaf = {
					'name': symbol,
					'type': type,
					'decl': $decl,
					'symbolLinkNode': $symbolLink,
				};

				parentNode.push(leaf);
			}

			if(enumRegex.test(text)) {
				fillSubTree('enum');
			} else if(structRegex.test(text)) {
				fillSubTree('struct');
			} else if(classRegex.test(text)) {
				fillSubTree('class');
			} else if(templateRegex.test(text)) {
				fillSubTree('template');
			} else if(functionRegex.test(text)) {
				if(propertyRegex.test(text)) {
					addLeaf('property');
				} else {
					addLeaf('function');
				}
			} else {
				addLeaf('variable');
			}
		});
	}

	var $declRoot = $('#declaration-list');
	var tree = new Array();

	fillTree(tree, $declRoot);

	return tree;
}

/**
 * Create the symbol list in the sidebar.
 * Returns an array of the anchor names for the symbols in the list.
 */
function populateSymbolList(tree) {
	function expandableNode(name, anchor, type) {
		return '
' +
		       '' + name + '' +
		       '

';
	}

	function leafNode(name, anchor, type) {
		return '
' + name + '
';
	}

	var anchorNames = new Array();

	function traverser(parent, $parent, anchorTail) {
		for(var i = 0; i < parent.length; i++) {
			var node = parent[i];
			var isTree = typeof node.members !== 'undefined';
			var anchorName = anchorTail + node.name;
			anchorNames.push(anchorName);

			node.symbolLinkNode.attr('id', anchorName);
			node.symbolLinkNode.attr('href', '#' + anchorName);

			if(isTree) {
				var $node = $(expandableNode(node.name, anchorName, node.type));
				$parent.append($node);

				if(node.members.length > 0) {
					var $caret = $('');
					$node.find('span').append($caret);
				}

				var $list = $node.find('ul');
				$list.attr('id', anchorName + '_member-list');
				$list.hide(); // Default to closed.
				traverser(node.members, $list, anchorName + '.');
			} else {
				var $node = $(leafNode(node.name, anchorName, node.type));
				$parent.append($node);
			}
		}
	}

	var $symbolHeader = $('#symbol-list');
	$symbolHeader.removeClass('hidden');

	traverser(tree, $symbolHeader.parent(), '');

	return anchorNames;
}

/**
 * Set the current symbol to highlight.
 */
function highlightSymbol(targetId) {
	function escapeId(id) {
		return id.replace(/\./g, '\\.');
	}

	var $target = $(escapeId(targetId)).parent();

	if(window.currentlyHighlightedSymbol) {
		window.currentlyHighlightedSymbol.removeClass('highlighted-symbol');
	}

	$target.addClass('highlighted-symbol');

	window.currentlyHighlightedSymbol = $target;

	// Open symbol list down to highlighted symbol.
	function eatHead(name) {
		var i = name.lastIndexOf('.');
		if(i != -1) {
			return name.slice(0, i);
		}
	}

	var nodeName = eatHead(targetId);
	while(typeof nodeName !== 'undefined') {
		$(escapeId(nodeName) + '_member-list').show();
		nodeName = eatHead(nodeName);
	}
}

/**
 * Configure the goto-symbol search form in the titlebar.
 */
function setupGotoSymbolForm(typeaheadData) {
	var $form = $('#gotosymbol');
	var $input = $form.children('input');

	function go(target) {
		window.location.hash = target;
		highlightSymbol('#' + target);
		$input.blur();
	}

	$form.submit(function(event) {
		event.preventDefault();

		go($input.val());

		$input.val('');
	});

	$input.typeahead({
		'source': typeaheadData,
		'updater': function(item) {
			go(item);
			return '';
		}
	});

	$form.removeClass('hidden');
}

// 'Title' and 'SourceRepository' are created inline in the DDoc generated HTML page.
$(document).ready(function() {
	// Setup page title.
	updateBreadcrumb(Title, SourceRepository);

	// Construct module list.
	populateModuleList(buildModuleTree(reapModuleList()));

	// Construct symbol list and setup goto-symbol form.
	var symbolTree = buildSymbolTree();
	if(symbolTree.length > 0) {
		var symbolAnchors = populateSymbolList(symbolTree);
		setupGotoSymbolForm(symbolAnchors);
	}

	// Setup symbol anchor highlighting.
	$('.symbol-link').click(function() {
		var targetId = $(this).attr('href');
		highlightSymbol(targetId);
	});

	if(document.location.hash.length > 0) {
		highlightSymbol(document.location.hash);
	}

	// Setup collapsable tree nodes.
	function treeNodeClick() {
		$(this).parent().children('ul').toggle();
	}

	function standaloneNodeClick() {
		$(this).parent().parent().children('ul').toggle();
	}

	var $treeNodes = $('.tree-node');
	var $standaloneTreeNodes = $('.tree-node-standalone');

	$treeNodes.click(treeNodeClick);
	$standaloneTreeNodes.click(standaloneNodeClick);
});
<commit_msg>Remove white space at end of lines in bootdoc.js<commit_after>/**
 * Construct the module list from source.
 * The module list is located in the source
 * because it must also work with noscript.
 */
function reapModuleList() {
	var modules = new Array();

	$('#module-list-source').find('li > a').each(function() {
		modules.push($(this).text());
	});

	return modules;
}

/**
 * Build a table representing the module hierarchy of the project
 * given a linear list of modules.
 */
function buildModuleTree(modlist) {
	var root = {'members': {}};

	for (var i = 0; i < modlist.length; i++) {
		var qualifiedName = modlist[i];
		var parts = qualifiedName.split('.');

		var parent = root;
		for(var partIndex = 0; partIndex < parts.length; partIndex++) {
			var name = parts[partIndex];
			var node;

			if(partIndex == parts.length - 1) {
				node = {'type': 'module', 'qualifiedName': qualifiedName};
				parent.members[name] = node;
			} else {
				node = parent.members[name];
				if(typeof node == "undefined") {
					node = {'type': 'package', 'members': {}};
					parent.members[name] = node;
				}
			}

			parent = node;
		}
	}

	return root;
}

/**
 * Build a path to the appropriate resource for a fully qualified module name,
 * respecting the global PackageSeparator variable.
 */
function qualifiedModuleNameToUrl(modName) {
	if(PackageSeparator == '.') {
		return modName + '.html';
	} else {
		return modName.replace(/\./g, PackageSeparator) + '.html';
	}
}

/**
 * Create the module list in the sidebar.
 */
function populateModuleList(modTree) {
	function treePackageNode(name) {
		return '
' +
			   ' ' + name + '' +
			   '

';
	}

	function treeModuleNode(name, url) {
		return '
' +
			   ' ' + name + '' +
			   '
';
	}

	var $listHeader = $('#module-list');

	function traverser(node, $parentList) {
		for(var name in node.members) {
			var member = node.members[name];

			if(member.type == 'package') {
				var $elem = $(treePackageNode(name));
				$parentList.append($elem);

				var $ul = $elem.find('ul');
				if($parentList != $listHeader) {
					$ul.hide();
				}

				traverser(member, $ul);

			} else if(member.type == 'module') {
				var url = qualifiedModuleNameToUrl(member.qualifiedName);
				var $elem = $(treeModuleNode(name, url));
				$parentList.append($elem);

				if(member.qualifiedName == Title) { // Current module.
					$elem.find('a').append(' ');

					var $up = $parentList;
					while(!$up.is($listHeader)) {
						$up.show();
						$up = $up.parent();
					}
				}
			}
		}
	}

	traverser(modTree, $listHeader);
}

/**
 * Build a relative path for the given module name.
 */
function moduleNameToPath(modName) {
	return modName.replace(/\./g, '/') + '.d';
}

/**
 * Configure the breadcrumb component at the top of the page
 * with the current module.
 */
function updateBreadcrumb(qualifiedName, sourceRepoUrl) {
	var $breadcrumb = $('#module-breadcrumb');

	var parts = qualifiedName.split('.');
	for(var i = 0; i < parts.length; i++) {
		var part = parts[i];

		if(i == parts.length - 1) {
			var sourceUrl = sourceRepoUrl + '/' + moduleNameToPath(qualifiedName);
			$breadcrumb.append('

' + part + ' view source

');
		} else {
			$breadcrumb.append('

' + part + '/

');
		}
	}
}

var enumRegex = /^enum /;
var structRegex = /^struct /;
var classRegex = /^class /;
var templateRegex = /^template /;
var functionRegex = /\);\s*$/m;
var propertyRegex = /@property/m;
var specialMemberRegex = /^([^(]+)/;

/**
 * Build a table out of all symbols declared in the current module.
 */
function buildSymbolTree() {
	function fillTree(parentNode, $parent) {
		$parent.children('.declaration').each(function() {
			var $decl = $(this);
			var text = $decl.text();

			var $symbolLink = $decl.find('.symbol-link');
			var symbol;
			if($symbolLink.length == 0) { // Special member (e.g. constructor).
				symbol = text.match(specialMemberRegex)[0];
			} else {
				symbol = $symbolLink.html();
			}

			function fillSubTree(type) {
				var subTree = {
					'name': symbol,
					'type': type,
					'members': new Array(),
					'decl': $decl,
					'symbolLinkNode': $symbolLink,
				};

				parentNode.push(subTree);
				fillTree(subTree.members, $decl.next('.declaration-content').children('.member-list'));
			}

			function addLeaf(type) {
				var leaf = {
					'name': symbol,
					'type': type,
					'decl': $decl,
					'symbolLinkNode': $symbolLink,
				};

				parentNode.push(leaf);
			}

			if(enumRegex.test(text)) {
				fillSubTree('enum');
			} else if(structRegex.test(text)) {
				fillSubTree('struct');
			} else if(classRegex.test(text)) {
				fillSubTree('class');
			} else if(templateRegex.test(text)) {
				fillSubTree('template');
			} else if(functionRegex.test(text)) {
				if(propertyRegex.test(text)) {
					addLeaf('property');
				} else {
					addLeaf('function');
				}
			} else {
				addLeaf('variable');
			}
		});
	}

	var $declRoot = $('#declaration-list');
	var tree = new Array();

	fillTree(tree, $declRoot);

	return tree;
}

/**
 * Create the symbol list in the sidebar.
 * Returns an array of the anchor names for the symbols in the list.
 */
function populateSymbolList(tree) {
	function expandableNode(name, anchor, type) {
		return '
' +
		       '' + name + '' +
		       '

';
	}

	function leafNode(name, anchor, type) {
		return '
' + name + '
';
	}

	var anchorNames = new Array();

	function traverser(parent, $parent, anchorTail) {
		for(var i = 0; i < parent.length; i++) {
			var node = parent[i];
			var isTree = typeof node.members !== 'undefined';
			var anchorName = anchorTail + node.name;
			anchorNames.push(anchorName);

			node.symbolLinkNode.attr('id', anchorName);
			node.symbolLinkNode.attr('href', '#' + anchorName);

			if(isTree) {
				var $node = $(expandableNode(node.name, anchorName, node.type));
				$parent.append($node);

				if(node.members.length > 0) {
					var $caret = $('');
					$node.find('span').append($caret);
				}

				var $list = $node.find('ul');
				$list.attr('id', anchorName + '_member-list');
				$list.hide(); // Default to closed.
				traverser(node.members, $list, anchorName + '.');
			} else {
				var $node = $(leafNode(node.name, anchorName, node.type));
				$parent.append($node);
			}
		}
	}

	var $symbolHeader = $('#symbol-list');
	$symbolHeader.removeClass('hidden');

	traverser(tree, $symbolHeader.parent(), '');

	return anchorNames;
}

/**
 * Set the current symbol to highlight.
 */
function highlightSymbol(targetId) {
	function escapeId(id) {
		return id.replace(/\./g, '\\.');
	}

	var $target = $(escapeId(targetId)).parent();

	if(window.currentlyHighlightedSymbol) {
		window.currentlyHighlightedSymbol.removeClass('highlighted-symbol');
	}

	$target.addClass('highlighted-symbol');

	window.currentlyHighlightedSymbol = $target;

	// Open symbol list down to highlighted symbol.
	function eatHead(name) {
		var i = name.lastIndexOf('.');
		if(i != -1) {
			return name.slice(0, i);
		}
	}

	var nodeName = eatHead(targetId);
	while(typeof nodeName !== 'undefined') {
		$(escapeId(nodeName) + '_member-list').show();
		nodeName = eatHead(nodeName);
	}
}

/**
 * Configure the goto-symbol search form in the titlebar.
 */
function setupGotoSymbolForm(typeaheadData) {
	var $form = $('#gotosymbol');
	var $input = $form.children('input');

	function go(target) {
		window.location.hash = target;
		highlightSymbol('#' + target);
		$input.blur();
	}

	$form.submit(function(event) {
		event.preventDefault();

		go($input.val());

		$input.val('');
	});

	$input.typeahead({
		'source': typeaheadData,
		'updater': function(item) {
			go(item);
			return '';
		}
	});

	$form.removeClass('hidden');
}

// 'Title' and 'SourceRepository' are created inline in the DDoc generated HTML page.
$(document).ready(function() {
	// Setup page title.
	updateBreadcrumb(Title, SourceRepository);

	// Construct module list.
	populateModuleList(buildModuleTree(reapModuleList()));

	// Construct symbol list and setup goto-symbol form.
	var symbolTree = buildSymbolTree();
	if(symbolTree.length > 0) {
		var symbolAnchors = populateSymbolList(symbolTree);
		setupGotoSymbolForm(symbolAnchors);
	}

	// Setup symbol anchor highlighting.
	$('.symbol-link').click(function() {
		var targetId = $(this).attr('href');
		highlightSymbol(targetId);
	});

	if(document.location.hash.length > 0) {
		highlightSymbol(document.location.hash);
	}

	// Setup collapsable tree nodes.
	function treeNodeClick() {
		$(this).parent().children('ul').toggle();
	}

	function standaloneNodeClick() {
		$(this).parent().parent().children('ul').toggle();
	}

	var $treeNodes = $('.tree-node');
	var $standaloneTreeNodes = $('.tree-node-standalone');

	$treeNodes.click(treeNodeClick);
	$standaloneTreeNodes.click(standaloneNodeClick);
});
<|endoftext|>


<commit_before>window.DOMTokenList
<commit_msg>Add basic DOMTokenList detection<commit_after>this.DOMTokenList
<|endoftext|>


<commit_before>class Confirm extends React.Component {
    constructor(props) {
        super(props)

        this.handleCancel = this.handleCancel.bind(this)
        this.handleConfirm = this.handleConfirm.bind(this)
    }

    handleCancel() {
        if (this.props.onCancel) {
            this.props.onCancel.call(null)
        }
    }

    handleConfirm() {
        if (this.props.onConfirm) {
            this.props.onConfirm.call(null)
        }
    }

    render() {
        let message = "Are you sure you want to continue?"
        if (this.props.message) {
            message = this.props.message
        }

        return (

{message}

                        <button className="button button-outline" onClick={this.handleCancel}>No</button>
                        <button className="button-primary float-right" onClick={this.handleConfirm}>Yes</button>

        )
    }
}<commit_msg>Clicking outside confirm dialogue now cancels<commit_after>class Confirm extends React.Component {
    constructor(props) {
        super(props)

        this.handleCancel = this.handleCancel.bind(this)
        this.handleConfirm = this.handleConfirm.bind(this)
    }

    handleCancel() {
        if (this.props.onCancel) {
            this.props.onCancel.call(null)
        }
    }

    handleConfirm() {
        if (this.props.onConfirm) {
            this.props.onConfirm.call(null)
        }
    }

    render() {
        let message = "Are you sure you want to continue?"
        if (this.props.message) {
            message = this.props.message
        }

        return (

{message}

                        <button className="button button-outline" onClick={this.handleCancel}>No</button>
                        <button className="button-primary float-right" onClick={this.handleConfirm}>Yes</button>

        )
    }
}<|endoftext|>


<commit_before>'use babel'
import {CompositeDisposable} from 'atom'
let views = require('../util/views')
let {span, div} = views.tags

export default class ResultView {
  constructor (model, opts = {}) {
    this.model = model
    this.disposables = new CompositeDisposable()
    this.completeView(opts)

    this.model.onDidRemove(() => this.destroy())
    this.model.onDidUpdate(() => this.modelUpdated = true)
    this.model.onDidInvalidate(() => this.view.classList.add('invalid'))
    this.model.onDidValidate(() => this.view.classList.remove('invalid'))
    this.model.onDidAttach(() => this.overlayElement = this.complete.parentElement)

    this.lastEdWidth = -1

    // HACK: compatibility to proto-repl:
    this.classList = {add() {}}

    return this
  }

  getView () {
    return this.model.type == 'inline' ? this.complete : this.view
  }

  getContent () {
    return this.view
  }

  getRawContent () {
    return this.rawContent
  }

  completeView (opts) {
    this.complete = document.createElement('div')
    this.complete.classList.add('ink-result-container')
    if (!opts.noTB && opts.type === 'inline') {
      this.toolbarView = this.toolbar(opts.buttons, opts.customButtons)
      this.complete.appendChild(this.toolbarView)
    }

    this.complete.appendChild(this.content(opts))

    this.disposables.add(atom.config.observe('editor.lineHeight', (h) => {
      this.complete.style.top = -h + 'em'
      this.complete.style.minHeight = h + 'em'
    }))
  }

  content (opts) {
    let {content, fade, loading, type} = opts
    this.view = document.createElement('div')
    this.view.setAttribute('tabindex', '-1')
    this.view.classList.add('ink', 'result', opts.scope)
    if (type === 'inline') {
      this.view.classList.add('inline')
    } else if (type === 'block') {
      this.view.classList.add('under')
    }

    this.view.addEventListener('mousewheel', (e) => {
      if ((this.view.offsetHeight < this.view.scrollHeight ||
           this.view.offsetWidth  < this.view.scrollWidth) &&
          ((e.deltaY > 0 && this.view.scrollHeight - this.view.scrollTop > this.view.clientHeight) ||
           (e.deltaY < 0 && this.view.scrollTop > 0) ||
           (e.deltaX > 0 && this.view.scrollWidth - this.view.scrollLeft > this.view.clientWidth) ||
           (e.deltaX < 0 && this.view.scrollLeft > 0))) {
        e.stopPropagation()
      }
    })

    this.view.addEventListener('click', () => {
      if (!(this.overlayElement && this.overlayElement.parentNode)) return
      this.overlayElement.parentNode.appendChild(this.overlayElement)
    })

    if (fade) this.fadeIn()
    if (content != null) this.setContent(content, opts)
    if (loading) this.setContent(views.render(span('loading icon icon-gear')), opts)

    return this.view
  }

  fadeIn () {
    this.view.classList.add('ink-hide')
    setTimeout(() => this.view.classList.remove('ink-hide'), 20)
  }

  setContent (view, {error = false, loading = false}) {
    this.rawContent  = [view, {error, loading}]
    while (this.view.firstChild != null) {
      this.view.removeChild(this.view.firstChild)
    }
    error ? this.view.classList.add('error') : this.view.classList.remove('error')
    loading ? this.view.classList.add('loading') : this.view.classList.remove('loading')
    this.view.appendChild(view)

    // HACK: don't display toolbar for "small" results
    if (this.model.type === 'inline' && this.toolbarView && view.innerHTML.length < 100 ) {
      this.toolbarView.classList.add('hide')
    } else {
      this.toolbarView.classList.remove('hide')
    }
  }

  toolbar (buttons, customButtons) {
    let tb = views.render(div('btn-group'))
    let addButtons = (buttons) => {
      for (let b of buttons(this.model)) {
        let v = document.createElement('button')
        v.classList.add('btn', b.icon)
        v.addEventListener('click', b.onclick)
        tb.appendChild(v)
      }
    }
    if (customButtons) addButtons(customButtons)
    addButtons(buttons)
    return views.render(div('ink-result-toolbar', tb))
  }

  // only read from the DOM
  decideUpdateWidth (edRect) {
    this.isVisible = false
    this.left = 0
    this.newEdWidth = false
    if (this.overlayElement) {
      let rect = this.view.getBoundingClientRect()
      this.isVisible = rect.top < edRect.bottom && rect.bottom > edRect.top
      this.left = parseInt(this.getView().parentElement.style.left)
      this.newEdWidth = edRect.width !== this.lastEdWidth
    }
  }

  // only write to the DOM
  updateWidth (edRect) {
    if ((this.isVisible && this.newEdWidth) || this.modelUpdated) {
      let w = edRect.width + edRect.left - 40 - this.left
      if (w < 100) w = 100
      this.getView().style.maxWidth = w + 'px'
      this.lastEdWidth = edRect.width
      this.modelUpdated = false
    }
  }

  destroy () {
    this.view.classList.add('ink-hide')
    this.disposables.dispose()
  }
}
<commit_msg>fix block result toolbar fixes #138<commit_after>'use babel'
import {CompositeDisposable} from 'atom'
let views = require('../util/views')
let {span, div} = views.tags

export default class ResultView {
  constructor (model, opts = {}) {
    this.model = model
    this.disposables = new CompositeDisposable()
    this.completeView(opts)

    this.model.onDidRemove(() => this.destroy())
    this.model.onDidUpdate(() => this.modelUpdated = true)
    this.model.onDidInvalidate(() => this.view.classList.add('invalid'))
    this.model.onDidValidate(() => this.view.classList.remove('invalid'))
    this.model.onDidAttach(() => this.overlayElement = this.complete.parentElement)

    this.lastEdWidth = -1

    // HACK: compatibility to proto-repl:
    this.classList = {add() {}}

    return this
  }

  getView () {
    return this.model.type == 'inline' ? this.complete : this.view
  }

  getContent () {
    return this.view
  }

  getRawContent () {
    return this.rawContent
  }

  completeView (opts) {
    this.complete = document.createElement('div')
    this.complete.classList.add('ink-result-container')
    if (!opts.noTB && opts.type === 'inline') {
      this.toolbarView = this.toolbar(opts.buttons, opts.customButtons)
      this.complete.appendChild(this.toolbarView)
    }

    this.complete.appendChild(this.content(opts))

    this.disposables.add(atom.config.observe('editor.lineHeight', (h) => {
      this.complete.style.top = -h + 'em'
      this.complete.style.minHeight = h + 'em'
    }))
  }

  content (opts) {
    let {content, fade, loading, type} = opts
    this.view = document.createElement('div')
    this.view.setAttribute('tabindex', '-1')
    this.view.classList.add('ink', 'result', opts.scope)
    if (type === 'inline') {
      this.view.classList.add('inline')
    } else if (type === 'block') {
      this.view.classList.add('under')
    }

    this.view.addEventListener('mousewheel', (e) => {
      if ((this.view.offsetHeight < this.view.scrollHeight ||
           this.view.offsetWidth  < this.view.scrollWidth) &&
          ((e.deltaY > 0 && this.view.scrollHeight - this.view.scrollTop > this.view.clientHeight) ||
           (e.deltaY < 0 && this.view.scrollTop > 0) ||
           (e.deltaX > 0 && this.view.scrollWidth - this.view.scrollLeft > this.view.clientWidth) ||
           (e.deltaX < 0 && this.view.scrollLeft > 0))) {
        e.stopPropagation()
      }
    })

    this.view.addEventListener('click', () => {
      if (!(this.overlayElement && this.overlayElement.parentNode)) return
      this.overlayElement.parentNode.appendChild(this.overlayElement)
    })

    if (fade) this.fadeIn()
    if (content != null) this.setContent(content, opts)
    if (loading) this.setContent(views.render(span('loading icon icon-gear')), opts)

    return this.view
  }

  fadeIn () {
    this.view.classList.add('ink-hide')
    setTimeout(() => this.view.classList.remove('ink-hide'), 20)
  }

  setContent (view, {error = false, loading = false}) {
    this.rawContent  = [view, {error, loading}]
    while (this.view.firstChild != null) {
      this.view.removeChild(this.view.firstChild)
    }
    error ? this.view.classList.add('error') : this.view.classList.remove('error')
    loading ? this.view.classList.add('loading') : this.view.classList.remove('loading')
    this.view.appendChild(view)

    // HACK: don't display toolbar for "small" results
    if (this.toolbarView) {
      if (this.model.type === 'inline' && view.innerHTML.length < 100 ) {
        this.toolbarView.classList.add('hide')
      } else {
        this.toolbarView.classList.remove('hide')
      }
    }
  }

  toolbar (buttons, customButtons) {
    let tb = views.render(div('btn-group'))
    let addButtons = (buttons) => {
      for (let b of buttons(this.model)) {
        let v = document.createElement('button')
        v.classList.add('btn', b.icon)
        v.addEventListener('click', b.onclick)
        tb.appendChild(v)
      }
    }
    if (customButtons) addButtons(customButtons)
    addButtons(buttons)
    return views.render(div('ink-result-toolbar', tb))
  }

  // only read from the DOM
  decideUpdateWidth (edRect) {
    this.isVisible = false
    this.left = 0
    this.newEdWidth = false
    if (this.overlayElement) {
      let rect = this.view.getBoundingClientRect()
      this.isVisible = rect.top < edRect.bottom && rect.bottom > edRect.top
      this.left = parseInt(this.getView().parentElement.style.left)
      this.newEdWidth = edRect.width !== this.lastEdWidth
    }
  }

  // only write to the DOM
  updateWidth (edRect) {
    if ((this.isVisible && this.newEdWidth) || this.modelUpdated) {
      let w = edRect.width + edRect.left - 40 - this.left
      if (w < 100) w = 100
      this.getView().style.maxWidth = w + 'px'
      this.lastEdWidth = edRect.width
      this.modelUpdated = false
    }
  }

  destroy () {
    this.view.classList.add('ink-hide')
    this.disposables.dispose()
  }
}
<|endoftext|>


<commit_before>$(document).ready(function () {
    var f = $(".timecode-widget");
    f.attr("placeholder", "hh:mm:ss:ff");
    f.keypress(function (event) {
        var key = event.which;
        var valueLength = $(this).val().length;

        if (valueLength >= 11) {
            event.preventDefault();
            return;
        }

        if ($(this).caret() == valueLength) {
            // we are entering at the end of the string
            if (valueLength % 3 == 2) {
                $(this).val($(this).val() + ":");
            }
        }
    });
});<commit_msg>Modified widget js behaviour<commit_after>function isDigit(asciiCode) {
    return asciiCode >= 48 && asciiCode < 58;
}

function isDivider(asciiCode) {
    return asciiCode == 58 || asciiCode == 46;
}

$(document).ready(function () {
    var f = $(".timecode-widget");
    f.attr("placeholder", "hh:mm:ss:ff");
    f.keypress(function (event) {
        var key = event.which;
        var valueLength = $(this).val().length;

        if (valueLength >= 11) {
            event.preventDefault();
            return;
        }

        if (!isDigit(key)) {
            event.preventDefault();
        }

        if ($(this).caret() == valueLength) {
            // we are entering at the end of the string
            if (valueLength % 3 == 2) {
                if (isDivider(key)) {
                    event.preventDefault();
                }

                $(this).val($(this).val() + ":");
            }
        }
    });
});<|endoftext|>


<commit_before>if (webkitAudioContext) {

    enchant.Game._loadFuncs['mp3'] =
    enchant.Game._loadFuncs['aac'] =
    enchant.Game._loadFuncs['m4a'] =
    enchant.Game._loadFuncs['wav'] =
    enchant.Game._loadFuncs['ogg'] = function(src, callback, ext) {
        this.assets[src] = enchant.NeoSound.load(src, 'audio/' + ext, callback);
    };

    enchant.NeoSound = enchant.Class.create(enchant.EventTarget, {
        initialize: function() {
            enchant.EventTarget.call(this);
            this.src = null;
            this.buffer = null;
        },
        load: function(src, callback) {
        },
        play: function() {
            var actx = enchant.NeoSound.audioContext;
            this.src = actx.createBufferSource();
            this.src.buffer = this.buffer;
            this.src.noteOn(0);
            this.src.connect(actx.destination);
        },
        pause: function() {
        },
        stop: function() {
        },
        clone: function() {
            // iranaikamo
        }
    });
    enchant.NeoSound.load = function(src, type, callback) {
        var actx = enchant.NeoSound.audioContext;
        var xhr = new XMLHttpRequest();
        var sound = new enchant.NeoSound();
        xhr.responseType = 'arraybuffer';
        xhr.open('GET', src, true);
        xhr.onload = function() {
            actx.decodeAudioData(
                xhr.response,
                function(buffer) {
                    sound.buffer = buffer;
                    callback();
                },
                function(error) {
                    console.log(error);
                    callback();
                }
            );
        };
        xhr.send(null);
        return sound;
    };

    enchant.NeoSound.audioContext = new webkitAudioContext();

}
<commit_msg>update NeoSound<commit_after>if (webkitAudioContext) {

    enchant.Game._loadFuncs['mp3'] =
    enchant.Game._loadFuncs['aac'] =
    enchant.Game._loadFuncs['m4a'] =
    enchant.Game._loadFuncs['wav'] =
    enchant.Game._loadFuncs['ogg'] = function(src, callback, ext) {
        this.assets[src] = enchant.NeoSound.load(src, 'audio/' + ext, callback);
    };

    enchant.NeoSound = enchant.Class.create(enchant.EventTarget, {
        initialize: function() {
            var actx = enchant.NeoSound.audioContext;
            enchant.EventTarget.call(this);
            this.src = actx.createBufferSource();
            this.buffer = null;
            this._volume = 1;
            this._currentTime = 0;
            this._state = 0;
        },
        play: function() {
            var actx = enchant.NeoSound.audioContext;
            if (this._state == 2) {
                this.src.connect(actx.destination);
            } else {
                if (this._state == 1) {
                    this.src.disconnect(actx.destination);
                }
                this.src = actx.createBufferSource();
                this.src.buffer = this.buffer;
                this.src.gain.value = this._volume;
                this.src.connect(actx.destination);
                this.src.noteOn(0);
            }
            this._state = 1;
        },
        pause: function() {
            var actx = enchant.NeoSound.audioContext;
            this.src.disconnect(actx.destination);
            this._state = 2;
        },
        stop: function() {
            this.src.noteOff(0);
            this._state = 0;
        },
        clone: function() {
            var sound = new enchant.NeoSound();
            sound.buffer = this.buffer;
            return sound;
        },
        dulation: {
            get: function() {
                if (this.buffer) {
                    return this.buffer.dulation;
                } else {
                    return 0;
                }
            }
        },
        volume: {
            get: function() {
                return this._volume;
            },
            set: function(volume) {
                volume = Math.max(0, Math.min(1, volume));
                this._volume = volume;
                if (this.src) {
                    this.src.gain.value = volume;
                }
            }
        },
        currentTime: {
            get: function() {
                window.console.log('currentTime is not allowed');
                return this._currentTime;
            },
            set: function(time) {
                window.console.log('currentTime is not allowed');
                this._currentTime = time;
            }
        }
    });

    enchant.NeoSound.load = function(src, type, callback) {
        var actx = enchant.NeoSound.audioContext;
        var xhr = new XMLHttpRequest();
        var sound = new enchant.NeoSound();
        var mimeType = 'audio/' + enchant.Game.findExt(src);
        // TODO check Audio.canPlayType(mimeType)
        xhr.responseType = 'arraybuffer';
        xhr.open('GET', src, true);
        xhr.onload = function() {
            actx.decodeAudioData(
                xhr.response,
                function(buffer) {
                    sound.buffer = buffer;
                    callback();
                },
                function(error) {
                    // TODO change to enchant Error
                    window.console.log(error);
                }
            );
        };
        xhr.send(null);
        return sound;
    };

    enchant.NeoSound.audioContext = new webkitAudioContext();

}
<|endoftext|>


<commit_before>(function (window) {
  'use strict';

  function MultiMap(){
    var map = {
      arrayMap: [],
      weakMap: new WeakMap()
    };

    this.get = function (key) {
      if (canBeAnArrayMapKey(key)){
        return map.arrayMap[key];
      } else if (canBeAWeakMapKey(key)){
        return map.weakMap.get(key);
      }
    };

    this.set = function (key, value) {
      if (canBeAnArrayMapKey(key)){
        map.arrayMap[key] = value;
      } else if (canBeAWeakMapKey(key)){
        map.weakMap.set(key, value);
      } else {
        throw new Error('Invalid key type');
      }

    };

    this.delete = function (key) {
      if (canBeAnArrayMapKey(key)){
        delete map.arrayMap[key];
      } else if (canBeAWeakMapKey(key)){
        map.weakMap.delete(key);
      }
    };

    function canBeAnArrayMapKey(obj){
      return obj !== null && !isNaNSymbol(obj) && (typeof obj == 'string' || typeof obj == 'number');
    }

    function canBeAWeakMapKey(obj){
      return obj !== null && (typeof obj == 'object' || typeof obj == 'function');
    }

    function isNaNSymbol(obj){
      return obj !== obj; // NaN === NaN is always false
    }

  }

  if (!window.MultiMap){
    window.MultiMap = MultiMap;
  }

})(window);<commit_msg>Fixed MultiMap implementation, to work with IE8<commit_after>(function (window) {
  'use strict';

  function MultiMap() {
    var map = {
      arrayMap: [],
      weakMap: new WeakMap()
    };

    return {
      'get': function (key) {
        if (canBeAnArrayMapKey(key)) {
          return map.arrayMap[key];
        } else if (canBeAWeakMapKey(key)) {
          return map.weakMap.get(key);
        }
      },

      'set': function (key, value) {
        if (canBeAnArrayMapKey(key)) {
          map.arrayMap[key] = value;
        } else if (canBeAWeakMapKey(key)) {
          map.weakMap.set(key, value);
        } else {
          throw new Error('Invalid key type');
        }

      },

      'delete': function (key) {
        if (canBeAnArrayMapKey(key)) {
          delete map.arrayMap[key];
        } else if (canBeAWeakMapKey(key)) {
          map.weakMap['delete'](key);  //Delete must be called using square bracket notation, because IE8 does not handle using `delete` with dot notation
        }
      }
    };

    function canBeAnArrayMapKey(obj){
      return obj !== null && !isNaNSymbol(obj) && (typeof obj == 'string' || typeof obj == 'number');
    }

    function canBeAWeakMapKey(obj){
      return obj !== null && (typeof obj == 'object' || typeof obj == 'function');
    }

    function isNaNSymbol(obj){
      return obj !== obj; // NaN === NaN is always false
    }

  }

  if (!window.MultiMap){
    window.MultiMap = MultiMap;
  }

})(window);<|endoftext|>


<commit_before>require([
    "datum/Datums",
    "datum/Datum"
], function(Datums,Datum) {

		describe("Test Datums", function() {
			it("should print collection", function(){
				var dc = new Datums();
				dc.add([{utterance: "tusunayawanmi"},{utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				//console.log(JSON.stringify(dc));
				expect(JSON.stringify(dc)).toEqual('[{"utterance":"tusunayawanmi","morphemes":"tusa-naya-wa-n","gloss":"dance-IMP-1OM-3SG","translation":"I feel like dancing.","grammaticalTags":"impulsative","sessionID":0,"status":{"statuses":[{"id":1,"label":"Checked"},{"id":2,"label":"To be checked","selected":true},{"id":3,"label":"Deleted"}],"active":0,"defaultStatus":0},"datumMenu":{},"datumField":{"script":"","context":"","semanticDenotation":"","ipa":"","segmentation":"tusu-naya-wa-n","other":""},"datumTag":{}},{"utterance":"purunaywanmi","morphemes":"tusa-naya-wa-n","gloss":"dance-IMP-1OM-3SG","translation":"I feel like dancing.","grammaticalTags":"impulsative","sessionID":0,"status":{"statuses":[{"id":1,"label":"Checked"},{"id":2,"label":"To be checked","selected":true},{"id":3,"label":"Deleted"}],"active":0,"defaultStatus":0},"datumMenu":{},"datumField":{"script":"","context":"","semanticDenotation":"","ipa":"","segmentation":"tusu-naya-wa-n","other":""},"datumTag":{}},{"utterance":"allillanchu","morphemes":"tusa-naya-wa-n","gloss":"dance-IMP-1OM-3SG","translation":"I feel like dancing.","grammaticalTags":"impulsative","sessionID":0,"status":{"statuses":[{"id":1,"label":"Checked"},{"id":2,"label":"To be checked","selected":true},{"id":3,"label":"Deleted"}],"active":0,"defaultStatus":0},"datumMenu":{},"datumField":{"script":"","context":"","semanticDenotation":"","ipa":"","segmentation":"tusu-naya-wa-n","other":""},"datumTag":{}}]');
			});

			it("should filter collection", function(){
				var dc = new Datums();
				dc.add([{utterance: "tusunayawanmi"},{utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var fildc = dc.where({utterance: "macaroni"});
				//console.log(JSON.stringify(fildc));
				expect(fildc).toEqual([]);
			});

			it("should remove a datum from collection", function(){
				var dc = new Datums();
				dc.add([{utterance: "tusunayawanmi"},{utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var remdc = dc.remove([{utterance: "tusunayawanmi"}]);
				//It doesn't actually appear to remove anything....
				console.log(JSON.stringify(remdc));
				expect(remdc.length).toEqual(3);
			});

			it("should get a datum from a collection", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var d = dc.get(77);
				//id's need to be assigned, they are not automatically generated.
				//console.log(d);
				expect(d.get("utterance")).toEqual("purunaywanmi");
			});
			it("should get a datum by client ID", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var d = dc.get(77);
				//cid ARE automatically generated.
				//console.log(d.cid);
				//expect(d.cid).toEqual("c16");
			});
			it("should get a datum from a collected at an index", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var d = dc.at(2);
				//console.log(d);
				expect(d.get("utterance")).toEqual("allillanchu");
			});
			it("should add a datum to the end of the collection", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				dc.push({utterance: "qaparinayawan"});
				var d = dc.at(3);
				console.log(d);
				expect(d.get("utterance")).toEqual("qaparinayawan");
			});
			it("should pop the last datum", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var d = dc.pop();
				console.log(d);
				expect(d.get("utterance")).toEqual("allillanchu");

			});
			it("should add a datum to the beginning of the collection", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				dc.unshift({utterance: "qaparinayawan"});
				var d = dc.at(0);
				console.log(d);
				expect(d.get("utterance")).toEqual("qaparinayawan");
			});
			it("should pop the first datum", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var d = dc.shift();
				console.log(d);
				expect(d.get("utterance")).toEqual("tusunayawanmi");

			});
			it("count the data in the collection", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var d = dc.length;
				console.log(d);
				expect(d).toEqual(3);

			});
			it("should pluck the data in the collection", function(){
				var dc = new Datums();
				dc.add([
				        {id: 99, utterance: "tusunayawanmi"},
				        {id: 77, utterance: "purunaywanmi"},
				        {utterance:"allillanchu"}
				        ]);

				var utterances = dc.pluck("utterance")

				expect(JSON.stringify(utterances)).toEqual('["tusunayawanmi","purunaywanmi","allillanchu"]');

			});
//			it("should fetch the data in the collection", function(){
//				var dc = new Datums();
//				dc.add([
//				        {id: 99, utterance: "tusunayawanmi"},
//				        {id: 77, utterance: "purunaywanmi"},
//				        {utterance:"allillanchu"}
//				        ]);
//
//				var d = dc.create({
//					utterance: "+Hall-pa-nay-wa-n "
//				});
//				expect().toFail.
//			});

	});

});
<commit_msg>fixing build<commit_after>require([
    "datum/Datums",
    "datum/Datum"
], function(Datums,Datum) {

		describe("Test Datums", function() {
			it("should print collection", function(){
				var dc = new Datums();
				dc.add([{utterance: "tusunayawanmi"},{utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				//console.log(JSON.stringify(dc));
				expect(JSON.stringify(dc)).toEqual('[{"utterance":"tusunayawanmi","morphemes":"tusa-naya-wa-n","gloss":"dance-IMP-1OM-3SG","translation":"I feel like dancing.","grammaticalTags":"impulsative","sessionID":0,"status":{"statuses":[{"id":1,"label":"Checked"},{"id":2,"label":"To be checked","selected":true},{"id":3,"label":"Deleted"}],"active":0,"defaultStatus":0},"datumField":{"script":"","context":"","semanticDenotation":"","ipa":"","segmentation":"tusu-naya-wa-n","other":""},"datumTag":{}},{"utterance":"purunaywanmi","morphemes":"tusa-naya-wa-n","gloss":"dance-IMP-1OM-3SG","translation":"I feel like dancing.","grammaticalTags":"impulsative","sessionID":0,"status":{"statuses":[{"id":1,"label":"Checked"},{"id":2,"label":"To be checked","selected":true},{"id":3,"label":"Deleted"}],"active":0,"defaultStatus":0},"datumField":{"script":"","context":"","semanticDenotation":"","ipa":"","segmentation":"tusu-naya-wa-n","other":""},"datumTag":{}},{"utterance":"allillanchu","morphemes":"tusa-naya-wa-n","gloss":"dance-IMP-1OM-3SG","translation":"I feel like dancing.","grammaticalTags":"impulsative","sessionID":0,"status":{"statuses":[{"id":1,"label":"Checked"},{"id":2,"label":"To be checked","selected":true},{"id":3,"label":"Deleted"}],"active":0,"defaultStatus":0},"datumField":{"script":"","context":"","semanticDenotation":"","ipa":"","segmentation":"tusu-naya-wa-n","other":""},"datumTag":{}}]');
			});

			it("should filter collection", function(){
				var dc = new Datums();
				dc.add([{utterance: "tusunayawanmi"},{utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var fildc = dc.where({utterance: "macaroni"});
				//console.log(JSON.stringify(fildc));
				expect(fildc).toEqual([]);
			});

			it("should remove a datum from collection", function(){
				var dc = new Datums();
				dc.add([{utterance: "tusunayawanmi"},{utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var remdc = dc.remove([{utterance: "tusunayawanmi"}]);
				//It doesn't actually appear to remove anything....
				console.log(JSON.stringify(remdc));
				expect(remdc.length).toEqual(3);
			});

			it("should get a datum from a collection", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var d = dc.get(77);
				//id's need to be assigned, they are not automatically generated.
				//console.log(d);
				expect(d.get("utterance")).toEqual("purunaywanmi");
			});
			it("should get a datum by client ID", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var d = dc.get(77);
				//cid ARE automatically generated.
				//console.log(d.cid);
				//expect(d.cid).toEqual("c16");
			});
			it("should get a datum from a collected at an index", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var d = dc.at(2);
				//console.log(d);
				expect(d.get("utterance")).toEqual("allillanchu");
			});
			it("should add a datum to the end of the collection", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				dc.push({utterance: "qaparinayawan"});
				var d = dc.at(3);
				console.log(d);
				expect(d.get("utterance")).toEqual("qaparinayawan");
			});
			it("should pop the last datum", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var d = dc.pop();
				console.log(d);
				expect(d.get("utterance")).toEqual("allillanchu");

			});
			it("should add a datum to the beginning of the collection", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				dc.unshift({utterance: "qaparinayawan"});
				var d = dc.at(0);
				console.log(d);
				expect(d.get("utterance")).toEqual("qaparinayawan");
			});
			it("should pop the first datum", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var d = dc.shift();
				console.log(d);
				expect(d.get("utterance")).toEqual("tusunayawanmi");

			});
			it("count the data in the collection", function(){
				var dc = new Datums();
				dc.add([{id: 99, utterance: "tusunayawanmi"},{id: 77, utterance: "purunaywanmi"},{utterance:"allillanchu"}]);
				var d = dc.length;
				console.log(d);
				expect(d).toEqual(3);

			});
			it("should pluck the data in the collection", function(){
				var dc = new Datums();
				dc.add([
				        {id: 99, utterance: "tusunayawanmi"},
				        {id: 77, utterance: "purunaywanmi"},
				        {utterance:"allillanchu"}
				        ]);

				var utterances = dc.pluck("utterance")

				expect(JSON.stringify(utterances)).toEqual('["tusunayawanmi","purunaywanmi","allillanchu"]');

			});
//			it("should fetch the data in the collection", function(){
//				var dc = new Datums();
//				dc.add([
//				        {id: 99, utterance: "tusunayawanmi"},
//				        {id: 77, utterance: "purunaywanmi"},
//				        {utterance:"allillanchu"}
//				        ]);
//
//				var d = dc.create({
//					utterance: "+Hall-pa-nay-wa-n "
//				});
//				expect().toFail.
//			});

	});

});
<|endoftext|>


<commit_before>/**
 * 节点测试
 */
var NodeTestLayer = TestBaseLayer.extend({
	w2: 0,
	h2: 0,
	ctor: function(){
		this._super();
		this.w2 = this.size.width / 2;
		this.h2 = this.size.height / 2;
		var node = new cc.Sprite(res.node152_png);
		this.addChild(node);
		node.setPosition(this.w2 - node.getContentSize().width * 1.3, this.h2);

		var node1 = new cc.Sprite(res.node152_png);
		this.addChild(node1);
		node1.setPosition(this.w2 + node1.getContentSize().width * 1.3,  this.h2);

		// 配置一些信息
		node.name = "node";
		node1.name = "node1";
		this.name = "MainLayer";
		this.setName("MainLayer");

		/// 基础属性
		// 1.1,位置测试
//		this.test_1_1(node, node1);
		// 1.2,大小测试
//		this.test_1_2(node, node1);
		// 1.3,锚点测试
//		this.test_1_3(node, node1);
		// 1.4,层级测试
//		this.test_1_4(node, node1);
		// 1.5,数据和标签测试
//		this.test_1_5(node, node1);

		/// 图形属性
		// 2.1 旋转
		this.test_2_1(node, node1);
		// 2.2 缩放
		// 2.3 倾斜
		// 2.4 可见
		// 2.5 透明
		// 2.6 颜色
		// 2.7 渲染

		/// 其他属性
		// 3.1 父/子相关
		// 3.2定时器
		// 3.3 运行状态
		// 3.4 动作管理
		// 3.5 到达顺序

		/// 功能函数
		// 4.1 属性配置
		// 4.2 图形操作
		// 4.3 节点操作
		// 4.4 事件回调
		// 4.5 动作模块
		// 4.6内存管理
		// 4.7计时器
		// 4.8坐标转换
		// 4.9边框区域

	},
	/**
	 * 1.1,位置测试
	 */
	test_1_1: function(node, node1){
		cc.log("===============[位置 Began]===============");
		// 针对【父节点】设置/获取坐标点
		node.setPosition(this.w2, this.h2);
		var position = node.getPosition();
		cc.log("position X: ", position.x, "position Y: ",position.y);

		node.setPositionX(100);
		node.setPositionY(200);
		var posX = node.getPositionX();
		var posY = node.getPositionY();
		cc.log("position X: ", posX, "position Y: ",posY);
		// 规格化设置坐标
		// node.setNormalizedPosition(0.5, 0.5);

		cc.log("-------------------------------------------");

		node1.x = this.w2;
		node1.y = this.h2;
		var position = cc.p(node1.x, node1.y);
		cc.log("position X: ", position.x, "position Y: ",position.y);

		node1.x = 555;
		node1.y = 444;
		var posX = node1.x;
		var posY = node1.y;
		cc.log("position X: ", posX, "position Y: ",posY);

		cc.log("===============[位置 End]=================");
	},
	/**
	 * 1.2,大小测试
	 */
	test_1_2: function(node, node1){
		cc.log("===============[大小 Began]===============");
		var width = node.getContentSize().width;
		var height = node.getContentSize().height;
		cc.log("width : ",width, " , height : ", height);
		// 1. 所有的节点都有大小。 Layer和Scene默认拥有跟【屏幕】一样的大小
		// 2. 设置节点内容的大小, 会影响坐标【位置】。其他举例：LayerColor, 事件
		// 3. 不管节点【缩放或者旋转】等，节点的contentSize是【不会】发生变化的
		node.setContentSize(width/2, height/2);
		cc.log("width2 : ",width, " , height2 : ", height);
		node.setContentSize(cc.size(width/4, height/4));
		cc.log("width4 : ",width, " , height4 : ", height);

		cc.log("-------------------------------------------");

		var width = node1.width;
		var height = node1.height;
		cc.log("width : ",width, " , height : ", height);

		node1.width = width/2;
		node1.height = height/4;
		cc.log("width : ",width, " , height : ", height);

		cc.log("===============[大小 End]=================");
	},
	/**
	 * 1.3,锚点测试
	 */
	test_1_3: function(node, node1){
		cc.log("===============[Block Began]===============");

		// cc.p(0, 0)
		// 1. 是一个【点】，【取值范围】是[0-1]
		// 2. 【决定】了你节点上的【哪个点】定位在你指定的【坐标】上
		// 3. 一些【动作】和【属性】饶这个锚点运作
		// 4. cc.Node 【默认】为 (0, 0), cc.Scene、cc.Layer、cc.Sprite 为(0.5, 0.5)
		var anchor = node.getAnchorPoint();
		cc.log("anchor:", anchor);

		node.setAnchorPoint(0.1, 0.5);
		var anchor = node.getAnchorPoint();
		cc.log("anchor : ", anchor);

		// 【锚点】在当前节点上的【绝对位置】
		cc.log("node.getAnchorPointInPoints() : ", node.getAnchorPointInPoints());

		/// 忽略锚点
		var ignoreAnchor = node.isIgnoreAnchorPointForPosition();
		cc.log("ignoreAnchor", ignoreAnchor);

		node.ignoreAnchorPointForPosition(!ignoreAnchor);
		var ignoreAnchor = node.isIgnoreAnchorPointForPosition();
		cc.log("ignoreAnchor", ignoreAnchor);

		cc.log("-------------------------------------------");

		var anchor = cc.p(node1.anchorX, node1.anchorY);
		cc.log("anchor : ", anchor);

		node1.anchorX = 1;
		node1.anchorY = 1;
		var anchor = cc.p(node1.anchorX, node1.anchorY);
        cc.log("anchor : ", anchor);

        var ignoreAnchor = node1.ignoreAnchor;
        cc.log("ignoreAnchor", ignoreAnchor);

        node1.ignoreAnchor = !ignoreAnchor;
        var ignoreAnchor = node1.ignoreAnchor;
        cc.log("ignoreAnchor", ignoreAnchor);

        // ignoreAnchor
        var node = new cc.Node();

        // cc.Node、 cc.Sprite 为 【false】
        // cc.Layer、cc.Scene  为 【true】
        var scene = new cc.Scene();
        var layer = new cc.Layer();
        var sprite = new cc.Sprite();
        cc.log("node", node.ignoreAnchor);
        cc.log("scene", scene.ignoreAnchor);
        cc.log("layer", layer.ignoreAnchor);
        cc.log("sprite", sprite.ignoreAnchor);

        cc.log("===============[Block End]=================");
	},
	/**
	 * 1.4,层级测试
	 */
	test_1_4: function(node, node1){
		node.setPosition(this.w2, this.h2);
        node1.setVisible(false);

        cc.log("===============[Block Began]===============");

        var tmpNode = new cc.Sprite(res.node152_png);
        tmpNode.setPosition(node.getPositionX() + 50, node.getPositionY() + 50);
        this.addChild(tmpNode);

        // 层级设置
        tmpNode.setLocalZOrder(-1);
        cc.log(" tmpNode.getLocalZOrder() : ", tmpNode.getLocalZOrder());
        cc.log(" tmpNode.getGlobalZOrder() : ", tmpNode.getGlobalZOrder());

        cc.log("-------------------------------------------");

        // tmpNode.zIndex = -1;
        cc.log(" tmpNode.zIndex : ", tmpNode.zIndex);

        cc.log("===============[Block End]=================");
	},
	/**
	 * 1.5,数据和标签测试
	 */
	test_1_5: function(node, node1){
		cc.log("===============[Block Began]===============");
        var OUT_MAN = 1;

        // tag 为【number】类型。
        node.setTag(OUT_MAN);
        cc.log("node.getTag() : ", node.getTag());

        // name 为【string】类型
        node.setName("out man");  // 奥特曼
        cc.log("node.getName() : ", node.getName());

        var userData = {
            name : "out man",
            age : 18
        }

        // 【随意】设置， 一个【数据块】, 【结构体】或者一个【对象】
        node.setUserData(userData);
        cc.log("node.getUserData() :", node.getUserData());

        var tmpNode = new cc.Node();
        tmpNode.setTag(998);

        // 设置一个用户指定的【cocos2d对象】
        node.setUserObject(tmpNode);
        cc.log("node.getObject() : ", node.getUserObject());

        cc.log("-------------------------------------------");

        var OUT_MAN = 1;
        node1.tag = OUT_MAN;
        cc.log("node1.tag : ", node1.tag);

        node1.name = "out man";
        cc.log("node1.name : ", node1.name);

        var userData = {
            name : "out man",
            age : 18
        }
        node1.userData = userData;
        cc.log("node1.userData :", node1.userData);

        var tmpNode = new cc.Node();
        tmpNode.tag = 998 ;
        node1.userObject = tmpNode;
        cc.log("node1.userObject : ", node1.userObject.tag);

        cc.log("===============[Block End]=================");
	},
	/**
	 * 2.1 旋转
	 */
	test_2_1: function(node, node1){
		cc.log("===============[Block Began]===============");

//		1. 默认为0度
		node.setRotation(45);
//		node.setRotationX(45);
//		node.setRotationY(45);
		cc.log("node.getRotation() : ", node.getRotation());
		cc.log("node.getRotationX() : ", node.getRotationX());
		cc.log("node.getRotationY() : ", node.getRotationY());

		cc.log("-------------------------------------------");

		node1.rotation = 90;
//			node1.rotationX = 45;
//			node1.rotationY = 45;
		cc.log("node1.rotation : ", node1.rotation);
		cc.log("node1.rotationX : ", node1.rotationX);
		cc.log("node1.rotationY : ", node1.rotationY);

		cc.log("===============[Block End]=================");
	}
});

var NodeTestScene = cc.Scene.extend({
	onEnter: function(){
		this._super();

		if(true){
			var layer = new NodeTestLayer();
			this.addChild(layer);
		}
	}
})<commit_msg>2.2缩放<commit_after>/**
 * 节点测试
 */
var NodeTestLayer = TestBaseLayer.extend({
	w2: 0,
	h2: 0,
	ctor: function(){
		this._super();
		this.w2 = this.size.width / 2;
		this.h2 = this.size.height / 2;
		var node = new cc.Sprite(res.node152_png);
		this.addChild(node);
		node.setPosition(this.w2 - node.getContentSize().width * 1.3, this.h2);

		var node1 = new cc.Sprite(res.node152_png);
		this.addChild(node1);
		node1.setPosition(this.w2 + node1.getContentSize().width * 1.3,  this.h2);

		// 配置一些信息
		node.name = "node";
		node1.name = "node1";
		this.name = "MainLayer";
		this.setName("MainLayer");

		/// 基础属性
		// 1.1,位置测试
//		this.test_1_1(node, node1);
		// 1.2,大小测试
//		this.test_1_2(node, node1);
		// 1.3,锚点测试
//		this.test_1_3(node, node1);
		// 1.4,层级测试
//		this.test_1_4(node, node1);
		// 1.5,数据和标签测试
//		this.test_1_5(node, node1);

		/// 图形属性
		// 2.1 旋转
//		this.test_2_1(node, node1);
		// 2.2 缩放
		this.test_2_2(node, node1);
		// 2.3 倾斜
		// 2.4 可见
		// 2.5 透明
		// 2.6 颜色
		// 2.7 渲染

		/// 其他属性
		// 3.1 父/子相关
		// 3.2定时器
		// 3.3 运行状态
		// 3.4 动作管理
		// 3.5 到达顺序

		/// 功能函数
		// 4.1 属性配置
		// 4.2 图形操作
		// 4.3 节点操作
		// 4.4 事件回调
		// 4.5 动作模块
		// 4.6内存管理
		// 4.7计时器
		// 4.8坐标转换
		// 4.9边框区域

	},
	/**
	 * 1.1,位置测试
	 */
	test_1_1: function(node, node1){
		cc.log("===============[位置 Began]===============");
		// 针对【父节点】设置/获取坐标点
		node.setPosition(this.w2, this.h2);
		var position = node.getPosition();
		cc.log("position X: ", position.x, "position Y: ",position.y);

		node.setPositionX(100);
		node.setPositionY(200);
		var posX = node.getPositionX();
		var posY = node.getPositionY();
		cc.log("position X: ", posX, "position Y: ",posY);
		// 规格化设置坐标
		// node.setNormalizedPosition(0.5, 0.5);

		cc.log("-------------------------------------------");

		node1.x = this.w2;
		node1.y = this.h2;
		var position = cc.p(node1.x, node1.y);
		cc.log("position X: ", position.x, "position Y: ",position.y);

		node1.x = 555;
		node1.y = 444;
		var posX = node1.x;
		var posY = node1.y;
		cc.log("position X: ", posX, "position Y: ",posY);

		cc.log("===============[位置 End]=================");
	},
	/**
	 * 1.2,大小测试
	 */
	test_1_2: function(node, node1){
		cc.log("===============[大小 Began]===============");
		var width = node.getContentSize().width;
		var height = node.getContentSize().height;
		cc.log("width : ",width, " , height : ", height);
		// 1. 所有的节点都有大小。 Layer和Scene默认拥有跟【屏幕】一样的大小
		// 2. 设置节点内容的大小, 会影响坐标【位置】。其他举例：LayerColor, 事件
		// 3. 不管节点【缩放或者旋转】等，节点的contentSize是【不会】发生变化的
		node.setContentSize(width/2, height/2);
		cc.log("width2 : ",width, " , height2 : ", height);
		node.setContentSize(cc.size(width/4, height/4));
		cc.log("width4 : ",width, " , height4 : ", height);

		cc.log("-------------------------------------------");

		var width = node1.width;
		var height = node1.height;
		cc.log("width : ",width, " , height : ", height);

		node1.width = width/2;
		node1.height = height/4;
		cc.log("width : ",width, " , height : ", height);

		cc.log("===============[大小 End]=================");
	},
	/**
	 * 1.3,锚点测试
	 */
	test_1_3: function(node, node1){
		cc.log("===============[Block Began]===============");

		// cc.p(0, 0)
		// 1. 是一个【点】，【取值范围】是[0-1]
		// 2. 【决定】了你节点上的【哪个点】定位在你指定的【坐标】上
		// 3. 一些【动作】和【属性】饶这个锚点运作
		// 4. cc.Node 【默认】为 (0, 0), cc.Scene、cc.Layer、cc.Sprite 为(0.5, 0.5)
		var anchor = node.getAnchorPoint();
		cc.log("anchor:", anchor);

		node.setAnchorPoint(0.1, 0.5);
		var anchor = node.getAnchorPoint();
		cc.log("anchor : ", anchor);

		// 【锚点】在当前节点上的【绝对位置】
		cc.log("node.getAnchorPointInPoints() : ", node.getAnchorPointInPoints());

		/// 忽略锚点
		var ignoreAnchor = node.isIgnoreAnchorPointForPosition();
		cc.log("ignoreAnchor", ignoreAnchor);

		node.ignoreAnchorPointForPosition(!ignoreAnchor);
		var ignoreAnchor = node.isIgnoreAnchorPointForPosition();
		cc.log("ignoreAnchor", ignoreAnchor);

		cc.log("-------------------------------------------");

		var anchor = cc.p(node1.anchorX, node1.anchorY);
		cc.log("anchor : ", anchor);

		node1.anchorX = 1;
		node1.anchorY = 1;
		var anchor = cc.p(node1.anchorX, node1.anchorY);
        cc.log("anchor : ", anchor);

        var ignoreAnchor = node1.ignoreAnchor;
        cc.log("ignoreAnchor", ignoreAnchor);

        node1.ignoreAnchor = !ignoreAnchor;
        var ignoreAnchor = node1.ignoreAnchor;
        cc.log("ignoreAnchor", ignoreAnchor);

        // ignoreAnchor
        var node = new cc.Node();

        // cc.Node、 cc.Sprite 为 【false】
        // cc.Layer、cc.Scene  为 【true】
        var scene = new cc.Scene();
        var layer = new cc.Layer();
        var sprite = new cc.Sprite();
        cc.log("node", node.ignoreAnchor);
        cc.log("scene", scene.ignoreAnchor);
        cc.log("layer", layer.ignoreAnchor);
        cc.log("sprite", sprite.ignoreAnchor);

        cc.log("===============[Block End]=================");
	},
	/**
	 * 1.4,层级测试
	 */
	test_1_4: function(node, node1){
		node.setPosition(this.w2, this.h2);
        node1.setVisible(false);

        cc.log("===============[Block Began]===============");

        var tmpNode = new cc.Sprite(res.node152_png);
        tmpNode.setPosition(node.getPositionX() + 50, node.getPositionY() + 50);
        this.addChild(tmpNode);

        // 层级设置
        tmpNode.setLocalZOrder(-1);
        cc.log(" tmpNode.getLocalZOrder() : ", tmpNode.getLocalZOrder());
        cc.log(" tmpNode.getGlobalZOrder() : ", tmpNode.getGlobalZOrder());

        cc.log("-------------------------------------------");

        // tmpNode.zIndex = -1;
        cc.log(" tmpNode.zIndex : ", tmpNode.zIndex);

        cc.log("===============[Block End]=================");
	},
	/**
	 * 1.5,数据和标签测试
	 */
	test_1_5: function(node, node1){
		cc.log("===============[Block Began]===============");
        var OUT_MAN = 1;

        // tag 为【number】类型。
        node.setTag(OUT_MAN);
        cc.log("node.getTag() : ", node.getTag());

        // name 为【string】类型
        node.setName("out man");  // 奥特曼
        cc.log("node.getName() : ", node.getName());

        var userData = {
            name : "out man",
            age : 18
        }

        // 【随意】设置， 一个【数据块】, 【结构体】或者一个【对象】
        node.setUserData(userData);
        cc.log("node.getUserData() :", node.getUserData());

        var tmpNode = new cc.Node();
        tmpNode.setTag(998);

        // 设置一个用户指定的【cocos2d对象】
        node.setUserObject(tmpNode);
        cc.log("node.getObject() : ", node.getUserObject());

        cc.log("-------------------------------------------");

        var OUT_MAN = 1;
        node1.tag = OUT_MAN;
        cc.log("node1.tag : ", node1.tag);

        node1.name = "out man";
        cc.log("node1.name : ", node1.name);

        var userData = {
            name : "out man",
            age : 18
        }
        node1.userData = userData;
        cc.log("node1.userData :", node1.userData);

        var tmpNode = new cc.Node();
        tmpNode.tag = 998 ;
        node1.userObject = tmpNode;
        cc.log("node1.userObject : ", node1.userObject.tag);

        cc.log("===============[Block End]=================");
	},
	/**
	 * 2.1 旋转
	 */
	test_2_1: function(node, node1){
		cc.log("===============[Block Began]===============");

//		1. 默认为0度
		node.setRotation(45);
//		node.setRotationX(45);
//		node.setRotationY(45);
		cc.log("node.getRotation() : ", node.getRotation());
		cc.log("node.getRotationX() : ", node.getRotationX());
		cc.log("node.getRotationY() : ", node.getRotationY());

		cc.log("-------------------------------------------");

		node1.rotation = 90;
//		node1.rotationX = 45;
//		node1.rotationY = 45;
		cc.log("node1.rotation : ", node1.rotation);
		cc.log("node1.rotationX : ", node1.rotationX);
		cc.log("node1.rotationY : ", node1.rotationY);

		cc.log("===============[Block End]=================");
	},
	/**
	 * 2.2 缩放
	 */
	test_2_2: function(node, node1){
		cc.log("===============[Block Began]===============");

//       1. 默认为 1
		cc.log("node.getScale() : ", node.getScale());
         node.setScale(2);
//       node.setScaleX(2);
//       node.setScaleY(2);

         cc.log("node.getScale() : ", node.getScale());
         cc.log("node.getScaleX() : ", node.getScaleX());
         cc.log("node.getScaleY() : ", node.getScaleY());

         cc.log("-------------------------------------------");

//       node1.scale = 1;
         node1.scaleX = 1.5;
         node1.scaleY = 2;

         cc.log("node1.getScale() : ", node1.getScale());
         cc.log("node1.getScaleX() : ", node1.getScaleX());
         cc.log("node1.getScaleY() : ", node1.getScaleY());

         cc.log("===============[Block End]=================");
	}
});

var NodeTestScene = cc.Scene.extend({
	onEnter: function(){
		this._super();

		if(true){
			var layer = new NodeTestLayer();
			this.addChild(layer);
		}
	}
})<|endoftext|>


<commit_before>goog.provide('my.LineRing');

goog.require('og.scene.RenderNode');
goog.require('og.inheritance');

goog.require('og.EntityCollection');
goog.require('og.Entity');
goog.require('og.Label');

function getIntersection(start1, end1, start2, end2) {
    if (!start1.equal(start2)) {
        var dir = end2.sub(start2);
        var perp = new og.math.Vector2(-dir.y, dir.x);
        var d2 = perp.dot(start2);
        var seg = perp.dot(start1) - d2;
        var u = seg / (seg - perp.dot(end1) + d2);
        return start1.add(end1.sub(start1).scale(u));
    }
    return start1;
}

function test0(order) {
    thickness = 20;
    current = og.math.vector2(100, 300), prev = og.math.vector2(700, 300), next = og.math.vector2(700, 300);
    dirNext = next.sub(current).normalize(), dirPrev = next.sub(current).normalize();
    normalNext = og.math.vector2(-dirNext.y, dirNext.x).normalize();
    normalPrev = og.math.vector2(dirPrev.y, -dirPrev.x).normalize();
    d = thickness * Math.sign(order);
    //vec2 m = getIntersection( current + normalPrev * d, prev + normalPrev * d,
    //    current + normalNext * d, next + normalNext * d );
    m = getIntersection(current.add(normalPrev.scaleTo(d)), prev.add(normalPrev.scaleTo(d)),
        current.add(normalNext.scaleTo(d)), next.add(normalNext.scaleTo(d)));

    ccw = Math.sign(dirNext.x * dirPrev.y - dirNext.y * dirPrev.x);
    if (ccw == 0.0) ccw = 1.0;
}

my.LineRing = function(name) {
    og.inheritance.base(this, name);
    this.thickness = 55;
};

og.inheritance.extend(my.LineRing, og.scene.RenderNode);

my.LineRing.prototype.initialization = function() {
    this.renderer.events.on("charkeypress", og.input.KEY_X, function() {
        if (this._drawType == this.renderer.handler.gl.LINE_STRIP) {
            this._drawType = this.renderer.handler.gl.TRIANGLE_STRIP;
        } else {
            this._drawType = this.renderer.handler.gl.LINE_STRIP;
        }
    }, this);

    this._drawType = this.renderer.handler.gl.TRIANGLE_STRIP;

    this.renderer.handler.addShaderProgram(new og.shaderProgram.ShaderProgram("lineRing", {
        uniforms: {
            'viewport': {
                type: og.shaderProgram.types.VEC2
            },
            'thickness': {
                type: og.shaderProgram.types.FLOAT
            },
            'alpha': {
                type: og.shaderProgram.types.FLOAT
            },
            'color': {
                type: og.shaderProgram.types.VEC4
            },

        },
        attributes: {
            'prev': {
                type: og.shaderProgram.types.VEC2
            },
            'current': {
                type: og.shaderProgram.types.VEC2
            },
            'next': {
                type: og.shaderProgram.types.VEC2
            },
            'order': {
                type: og.shaderProgram.types.FLOAT
            }
        },
        vertexShader: 'attribute vec2 prev;\
                attribute vec2 current;\
                attribute vec2 next;\
                attribute float order;\
                uniform float thickness;\
                uniform vec2 viewport;\
                \
                vec2 getIntersection(vec2 start1, vec2 end1, vec2 start2, vec2 end2){\
                    /*if(start1 != start2) {*/\
                        vec2 dir = end2 - start2;\
                        vec2 perp = vec2(-dir.y, dir.x);\
                        float d2 = dot(perp, start2);\
                        float seg = dot(perp, start1) - d2;\
                        float u = seg / (seg - dot(perp, end1) + d2);\
                        return start1 + u * (end1 - start1);\
                    /*}\
                    return start1;*/\
                }\
                void main(){\
                    vec2 dirNext = normalize(next - current);\
                    vec2 dirPrev = normalize(prev - current);\
                    vec2 normalNext = normalize(vec2(-dirNext.y, dirNext.x));\
                    vec2 normalPrev = normalize(vec2(dirPrev.y, -dirPrev.x));\
                    float d = thickness * sign(order);\
                    \
                    vec2 m;\
                    float dotNP = dot(dirNext, dirPrev);\
                    if(abs(dotNP) != 1.0){\
                        m = getIntersection( current + normalPrev * d, prev + normalPrev * d,\
                            current + normalNext * d, next + normalNext * d );\
                    }else{\
                        m = current + normalPrev * d;\
                    }\
                    \
                    if( dotNP > 0.5 && dot(dirNext + dirPrev, m - current) < 0.0 ){\
                        float ccw = sign(dirNext.x * dirPrev.y - dirNext.y * dirPrev.x);\
                        float occw = order * ccw;\
                        if(occw == -1.0){\
                            m = current + normalPrev * d;\
                        }else if(occw == 1.0){\
                            m = current + normalNext * d;\
                        }else if(occw == -2.0){\
                            m = current + normalNext * d;\
                        }else if(occw == 2.0){\
                            m = current + normalPrev * d;\
                        }\
                    }else{\
                        float maxDist = max(distance(current, next), distance(current, prev));\
                        if(distance(current, m) > maxDist){\
                            m = current + maxDist * normalize(m - current);\
                        }\
                    }\
                    m /= viewport;\
                    gl_Position = vec4(-1.0 + m.x, 1.0 - m.y, 0.0, 1.0);\
                }',
        fragmentShader: 'precision highp float;\
                uniform float alpha;\
                uniform vec4 color;\
                void main() {\
                    gl_FragColor = vec4(color.rgb, alpha * color.a);\
                }'
    }));

    var path = [
        [100, 100],
        [400, 100],
        [400, 110],
        [100, 120]
    ];

    this._mainData = [];
    this._orderData = [];
    this._indexData = [];

    var last = path[path.length - 1];
    var prev = last;
    this._mainData.push(last[0], last[1], last[0], last[1], last[0], last[1], last[0], last[1]);
    this._orderData.push(1, -1, 2, -2);
    var k = 0;
    for (var i = 0; i < path.length; i++) {
        var cur = path[i];
        if (cur[0] != prev[0] || cur[1] != prev[1]) {
            this._mainData.push(cur[0], cur[1], cur[0], cur[1], cur[0], cur[1], cur[0], cur[1]);
            this._orderData.push(1, -1, 2, -2);
            this._indexData.push(k++, k++, k++, k++);
        }
        prev = cur;
    }
    var first = path[0];
    this._mainData.push(first[0], first[1], first[0], first[1], first[0], first[1], first[0], first[1]);
    this._orderData.push(1, -1, 2, -2);
    this._indexData.push(0, 1);

    var h = this.renderer.handler;
    this._orderBuffer = h.createArrayBuffer(new Float32Array(this._orderData), 1, (this._orderData.length / 2));
    this._mainBuffer = h.createArrayBuffer(new Float32Array(this._mainData), 2, (this._mainData.length) / 4);
    this._indexBuffer = h.createElementArrayBuffer(new Uint16Array(this._indexData), 1, this._indexData.length);
};

my.LineRing.prototype.frame = function() {

    var rn = this;
    var r = rn.renderer;
    var sh = r.handler.shaderPrograms.lineRing;
    var p = sh._program;
    var gl = r.handler.gl,
        sha = p.attributes,
        shu = p.uniforms;

    sh.activate();

    gl.enable(gl.BLEND);
    gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
    gl.blendFuncSeparate(
        gl.SRC_ALPHA,
        gl.ONE_MINUS_SRC_ALPHA,
        gl.ONE,
        gl.ONE_MINUS_SRC_ALPHA
    );
    gl.disable(gl.DEPTH_TEST);

    gl.disable(gl.CULL_FACE);
    gl.uniform2fv(shu.viewport._pName, [r.handler.canvas.width, r.handler.canvas.height]);
    gl.uniform1f(shu.thickness._pName, (this.thickness + 2) * 0.5);
    gl.uniform1f(shu.alpha._pName, 0.54);
    gl.uniform4fv(shu.color._pName, [1.0, 0.0, 0.0, 0.5]);

    var mb = this._mainBuffer;
    gl.bindBuffer(gl.ARRAY_BUFFER, mb);
    gl.vertexAttribPointer(sha.prev._pName, mb.itemSize, gl.FLOAT, false, 0, 0);
    gl.vertexAttribPointer(sha.current._pName, mb.itemSize, gl.FLOAT, false, 0, 32);
    gl.vertexAttribPointer(sha.next._pName, mb.itemSize, gl.FLOAT, false, 0, 64);
    gl.bindBuffer(gl.ARRAY_BUFFER, this._orderBuffer);
    gl.vertexAttribPointer(sha.order._pName, this._orderBuffer.itemSize, gl.FLOAT, false, 4, 0);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
    gl.drawElements(this._drawType, this._indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

    gl.uniform1f(shu.thickness._pName, this.thickness * 0.5);
    gl.uniform1f(shu.alpha._pName, 1.0);
    gl.drawElements(this._drawType, this._indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

    gl.enable(gl.CULL_FACE);
    gl.disable(gl.BLEND);
};

// struct Line {\
//     float A, B, C;\
// };\
// \
// Line getLine(vec2 p0, vec2 p1) {\
//     return Line(p1.y - p0.y, p0.x - p1.x, p1.x * p0.y - p0.x * p1.y);\
// }\
// \
// Line getParallel(Line l, vec2 p){\
//     return Line(l.A, l.B, -l.A * p.x - l.B * p.y);\
// }\
// \
// vec2 getIntersection(Line L0, Line L1, vec2 p) {\
//     if(/*L0.A / L1.A != L0.B / L1.B*/true){\
//         float x = (L1.B * L0.C - L0.B * L1.C) / (L0.B * L1.A - L1.B * L0.A);\
//         float y = -(L0.C + L0.A * x) / L0.B;\
//         return vec2(x, y);\
//     }\
//     return vec2(p);\
// }\
<commit_msg>Equal prev current and next coordinates right way processing.<commit_after>goog.provide('my.LineRing');

goog.require('og.scene.RenderNode');
goog.require('og.inheritance');

goog.require('og.EntityCollection');
goog.require('og.Entity');
goog.require('og.Label');

function getIntersection(start1, end1, start2, end2) {
    if (!start1.equal(start2)) {
        var dir = end2.sub(start2);
        var perp = new og.math.Vector2(-dir.y, dir.x);
        var d2 = perp.dot(start2);
        var seg = perp.dot(start1) - d2;
        var u = seg / (seg - perp.dot(end1) + d2);
        return start1.add(end1.sub(start1).scale(u));
    }
    return start1;
}

function test0(order) {
    thickness = 20;
    current = og.math.vector2(100, 300), prev = og.math.vector2(700, 300), next = og.math.vector2(700, 300);
    dirNext = next.sub(current).normalize(), dirPrev = next.sub(current).normalize();
    normalNext = og.math.vector2(-dirNext.y, dirNext.x).normalize();
    normalPrev = og.math.vector2(dirPrev.y, -dirPrev.x).normalize();
    d = thickness * Math.sign(order);
    //vec2 m = getIntersection( current + normalPrev * d, prev + normalPrev * d,
    //    current + normalNext * d, next + normalNext * d );
    m = getIntersection(current.add(normalPrev.scaleTo(d)), prev.add(normalPrev.scaleTo(d)),
        current.add(normalNext.scaleTo(d)), next.add(normalNext.scaleTo(d)));

    ccw = Math.sign(dirNext.x * dirPrev.y - dirNext.y * dirPrev.x);
    if (ccw == 0.0) ccw = 1.0;
}

my.LineRing = function(name) {
    og.inheritance.base(this, name);
    this.thickness = 10;
};

og.inheritance.extend(my.LineRing, og.scene.RenderNode);

my.LineRing.prototype.initialization = function() {
    this.renderer.events.on("charkeypress", og.input.KEY_X, function() {
        if (this._drawType == this.renderer.handler.gl.LINE_STRIP) {
            this._drawType = this.renderer.handler.gl.TRIANGLE_STRIP;
        } else {
            this._drawType = this.renderer.handler.gl.LINE_STRIP;
        }
    }, this);

    this._drawType = this.renderer.handler.gl.TRIANGLE_STRIP;

    this.renderer.handler.addShaderProgram(new og.shaderProgram.ShaderProgram("lineRing", {
        uniforms: {
            'viewport': {
                type: og.shaderProgram.types.VEC2
            },
            'thickness': {
                type: og.shaderProgram.types.FLOAT
            },
            'alpha': {
                type: og.shaderProgram.types.FLOAT
            },
            'color': {
                type: og.shaderProgram.types.VEC4
            },

        },
        attributes: {
            'prev': {
                type: og.shaderProgram.types.VEC2
            },
            'current': {
                type: og.shaderProgram.types.VEC2
            },
            'next': {
                type: og.shaderProgram.types.VEC2
            },
            'order': {
                type: og.shaderProgram.types.FLOAT
            }
        },
        vertexShader: 'attribute vec2 prev;\
                attribute vec2 current;\
                attribute vec2 next;\
                attribute float order;\
                uniform float thickness;\
                uniform vec2 viewport;\
                \
                vec2 getIntersection(vec2 start1, vec2 end1, vec2 start2, vec2 end2){\
                    vec2 dir = end2 - start2;\
                    vec2 perp = vec2(-dir.y, dir.x);\
                    float d2 = dot(perp, start2);\
                    float seg = dot(perp, start1) - d2;\
                    float u = seg / (seg - dot(perp, end1) + d2);\
                    return start1 + u * (end1 - start1);\
                }\
                void main(){\
                    vec2 _next = next;\
                    vec2 _prev = prev;\
                    if(prev == current){\
                        if(next == current){\
                            _next = current + vec2(1.0, 0.0);\
                            _prev = current - next;\
                        }else{\
                            _prev = current + normalize(current - next);\
                        }\
                    }\
                    if(next == current){\
                        _next = current + normalize(current - _prev);\
                    }\
                    vec2 sNext = _next / viewport,\
                         sCurrent = current / viewport,\
                         sPrev = _prev / viewport;\
                    vec2 dirNext = normalize(sNext - sCurrent);\
                    vec2 dirPrev = normalize(sPrev - sCurrent);\
                    vec2 normalNext = normalize(vec2(-dirNext.y, dirNext.x));\
                    vec2 normalPrev = normalize(vec2(dirPrev.y, -dirPrev.x));\
                    vec2 d = thickness * sign(order) / viewport;\
                    \
                    vec2 m;\
                    float dotNP = dot(dirNext, dirPrev);\
                    if(abs(dotNP) != 1.0){\
                        m = getIntersection( sCurrent + normalPrev * d, sPrev + normalPrev * d,\
                            sCurrent + normalNext * d, sNext + normalNext * d );\
                    }else{\
                        m = sCurrent + normalPrev * d;\
                    }\
                    \
                    if( dotNP > 0.5 && dot(dirNext + dirPrev, m - sCurrent) < 0.0 ){\
                        float ccw = sign(dirNext.x * dirPrev.y - dirNext.y * dirPrev.x);\
                        float occw = order * ccw;\
                        if(occw == -1.0){\
                            m = sCurrent + normalPrev * d;\
                        }else if(occw == 1.0){\
                            m = sCurrent + normalNext * d;\
                        }else if(occw == -2.0){\
                            m = sCurrent + normalNext * d;\
                        }else if(occw == 2.0){\
                            m = sCurrent + normalPrev * d;\
                        }\
                    }else{\
                        float maxDist = max(distance(sCurrent, sNext), distance(sCurrent, sPrev));\
                        if(distance(sCurrent, m) > maxDist){\
                            m = sCurrent + maxDist * normalize(m - sCurrent);\
                        }\
                    }\
                    gl_Position = vec4(-1.0 + m.x, 1.0 - m.y, 0.0, 1.0);\
                }',
        fragmentShader: 'precision highp float;\
                uniform float alpha;\
                uniform vec4 color;\
                void main() {\
                    gl_FragColor = vec4(color.rgb, alpha * color.a);\
                }'
    }));

    var path = [
        [100, 100],
        [200, 100],
        [200, 450]
    ];

    this._mainData = [];
    this._orderData = [];
    this._indexData = [];

    var last = path[path.length - 1];
    var prev = last;
    this._mainData.push(last[0], last[1], last[0], last[1], last[0], last[1], last[0], last[1]);
    this._orderData.push(1, -1, 2, -2);
    var k = 0;
    for (var i = 0; i < path.length; i++) {
        var cur = path[i];
        //if (cur[0] != prev[0] || cur[1] != prev[1]) {
            this._mainData.push(cur[0], cur[1], cur[0], cur[1], cur[0], cur[1], cur[0], cur[1]);
            this._orderData.push(1, -1, 2, -2);
            this._indexData.push(k++, k++, k++, k++);
        //}
        //prev = cur;
    }
    var first = path[0];
    this._mainData.push(first[0], first[1], first[0], first[1], first[0], first[1], first[0], first[1]);
    this._orderData.push(1, -1, 2, -2);
    this._indexData.push(0, 1);

    var h = this.renderer.handler;
    this._orderBuffer = h.createArrayBuffer(new Float32Array(this._orderData), 1, (this._orderData.length / 2));
    this._mainBuffer = h.createArrayBuffer(new Float32Array(this._mainData), 2, (this._mainData.length) / 4);
    this._indexBuffer = h.createElementArrayBuffer(new Uint16Array(this._indexData), 1, this._indexData.length);
};

my.LineRing.prototype.frame = function() {

    var rn = this;
    var r = rn.renderer;
    var sh = r.handler.shaderPrograms.lineRing;
    var p = sh._program;
    var gl = r.handler.gl,
        sha = p.attributes,
        shu = p.uniforms;

    sh.activate();

    gl.enable(gl.BLEND);
    gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
    gl.blendFuncSeparate(
        gl.SRC_ALPHA,
        gl.ONE_MINUS_SRC_ALPHA,
        gl.ONE,
        gl.ONE_MINUS_SRC_ALPHA
    );
    gl.disable(gl.DEPTH_TEST);

    gl.disable(gl.CULL_FACE);
    gl.uniform2fv(shu.viewport._pName, [512, 512]);
    gl.uniform1f(shu.thickness._pName, (this.thickness + 2) * 0.5);
    gl.uniform1f(shu.alpha._pName, 0.54);
    gl.uniform4fv(shu.color._pName, [1.0, 0.0, 0.0, 1]);

    var mb = this._mainBuffer;
    gl.bindBuffer(gl.ARRAY_BUFFER, mb);
    gl.vertexAttribPointer(sha.prev._pName, mb.itemSize, gl.FLOAT, false, 0, 0);
    gl.vertexAttribPointer(sha.current._pName, mb.itemSize, gl.FLOAT, false, 0, 32);
    gl.vertexAttribPointer(sha.next._pName, mb.itemSize, gl.FLOAT, false, 0, 64);
    gl.bindBuffer(gl.ARRAY_BUFFER, this._orderBuffer);
    gl.vertexAttribPointer(sha.order._pName, this._orderBuffer.itemSize, gl.FLOAT, false, 4, 0);

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._indexBuffer);
    gl.drawElements(this._drawType, this._indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

    gl.uniform1f(shu.thickness._pName, this.thickness * 0.5);
    gl.uniform1f(shu.alpha._pName, 1.0);
    gl.drawElements(this._drawType, this._indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

    gl.enable(gl.CULL_FACE);
    gl.disable(gl.BLEND);
};

// struct Line {\
//     float A, B, C;\
// };\
// \
// Line getLine(vec2 p0, vec2 p1) {\
//     return Line(p1.y - p0.y, p0.x - p1.x, p1.x * p0.y - p0.x * p1.y);\
// }\
// \
// Line getParallel(Line l, vec2 p){\
//     return Line(l.A, l.B, -l.A * p.x - l.B * p.y);\
// }\
// \
// vec2 getIntersection(Line L0, Line L1, vec2 p) {\
//     if(/*L0.A / L1.A != L0.B / L1.B*/true){\
//         float x = (L1.B * L0.C - L0.B * L1.C) / (L0.B * L1.A - L1.B * L0.A);\
//         float y = -(L0.C + L0.A * x) / L0.B;\
//         return vec2(x, y);\
//     }\
//     return vec2(p);\
// }\
<|endoftext|>


<commit_before>import { detectFont, supportedFonts, removeQuotes } from '../src/detect-font';

describe('DetectFont:', () => {

    describe('Font Detection:', () => {

        const node = document.createElement('div');

        it('Should yield the first supported font;', () => {
            node.style.fontFamily = 'Arial, Tahoma, Helvetica';
            expect(detectFont(node)).toEqual('Arial');
            node.style.fontFamily = `UnknownFont, 'Tahoma', Helvetica`;
            expect(detectFont(node)).toEqual('Tahoma');
        });

        it('Should yield the only font if supported;', () => {
            node.style.fontFamily = 'Helvetica';
            expect(detectFont(node)).toEqual('Helvetica');
        });

        it('Should yield font which includes spaces;', () => {
            node.style.fontFamily = 'GoodnessKnows, "Times New Roman"';
            expect(detectFont(node)).toEqual('Times New Roman');
        });

        it('Should yield base font when discovered;', () => {
            node.style.fontFamily = 'Nothingness, monospace, "Times New Roman", sans-serif';
            expect(detectFont(node)).toEqual('monospace');
        });

        it('Should yield base font when reached end;', () => {
            node.style.fontFamily = 'Nothingness, GoodnessKnows, AbsolutelyNothing, "sans-serif"';
            expect(detectFont(node)).toEqual('sans-serif');
        });

        it('Should yield browser default when no font specified;', () => {
            const node = document.createElement('section');
            node.style.fontFamily = '';
            expect(detectFont(node)).toEqual('serif');
        });

        it('Should yield browser default when font cannot be recognised;', () => {
            const node = document.createElement('section');
            node.style.fontFamily = 'Nothingness, GoodnessKnows, AbsolutelyNothing';
            expect(detectFont(node)).toEqual(false);
        });

        it('Should return an array of supported fonts;', () => {
            node.style.fontFamily = 'GoodnessKnows, "Times New Roman", Arial, Nothingness, monospace, Tahoma';
            expect(supportedFonts(node)).toEqual(['Times New Roman', 'Arial', 'monospace', 'Tahoma']);
        });

        it('Should be case-insensitive;', () => {
            node.style.fontFamily = 'ARIAL, TAHOMA, HELVETICA';
            expect(detectFont(node)).toEqual('ARIAL');
            node.style.fontFamily = 'MONOSPACE, ARIAL, SANS-SERIF';
            expect(detectFont(node)).toEqual('monospace');
        });

        it('Should be able to change the font size', () => {
            node.style.fontFamily = '"Goodness Knows", Arial';
            expect(detectFont(node, { fontSize: 1 })).toEqual('Arial');
        });

    });

    describe('Error Handling:', () => {

        it('Should raise an exception when passed a non-element;', () => {
            expect(() => detectFont(1)).toThrow(new Error('DetectFont: Cannot detect font on a non-element.'));
        });

        it('Should raise an exception when font size is set to 0;', () => {
            const node = document.createElement('span');
            node.fontFamily = 'GoodnessKnows, Arial, Tahoma, Helvetica';
            expect(() => detectFont(node, { fontSize: 0 })).toThrow(new Error('DetectFont: Setting font size to zero will always yield false positives.'));
        });

        it('Should raise an exception if non-text has been passed into `options`', () => {
            const node = document.createElement('span');
            node.fontFamily = 'GoodnessKnows, Arial, Tahoma, Helvetica';
            expect(() => detectFont(node, { text: '' })).toThrow(new Error('DetectFont: Setting text to an empty string will always yield false positives.'));
        });

    });

    describe('Remove Quotes:', () => {

        it('Should remove optional quoting from the string;', () => {
            expect(removeQuotes(`Times New Roman`)).toEqual('Times New Roman');
            expect(removeQuotes(`'Times New Roman'`)).toEqual('Times New Roman');
            expect(removeQuotes(`"Times New Roman"`)).toEqual('Times New Roman');
        });

    });

});
<commit_msg>added should return an empty array<commit_after>import { detectFont, supportedFonts, removeQuotes } from '../src/detect-font';

describe('DetectFont:', () => {

    describe('Font Detection:', () => {

        const node = document.createElement('div');

        it('Should yield the first supported font;', () => {
            node.style.fontFamily = 'Arial, Tahoma, Helvetica';
            expect(detectFont(node)).toEqual('Arial');
            node.style.fontFamily = `UnknownFont, 'Tahoma', Helvetica`;
            expect(detectFont(node)).toEqual('Tahoma');
        });

        it('Should yield the only font if supported;', () => {
            node.style.fontFamily = 'Helvetica';
            expect(detectFont(node)).toEqual('Helvetica');
        });

        it('Should yield font which includes spaces;', () => {
            node.style.fontFamily = 'GoodnessKnows, "Times New Roman"';
            expect(detectFont(node)).toEqual('Times New Roman');
        });

        it('Should yield base font when discovered;', () => {
            node.style.fontFamily = 'Nothingness, monospace, "Times New Roman", sans-serif';
            expect(detectFont(node)).toEqual('monospace');
        });

        it('Should yield base font when reached end;', () => {
            node.style.fontFamily = 'Nothingness, GoodnessKnows, AbsolutelyNothing, "sans-serif"';
            expect(detectFont(node)).toEqual('sans-serif');
        });

        it('Should yield browser default when no font specified;', () => {
            const node = document.createElement('section');
            node.style.fontFamily = '';
            expect(detectFont(node)).toEqual('serif');
        });

        it('Should yield browser default when font cannot be recognised;', () => {
            const node = document.createElement('section');
            node.style.fontFamily = 'Nothingness, GoodnessKnows, AbsolutelyNothing';
            expect(detectFont(node)).toEqual(false);
        });

        it('Should return an array of supported fonts;', () => {
            node.style.fontFamily = 'GoodnessKnows, "Times New Roman", Arial, Nothingness, monospace, Tahoma';
            expect(supportedFonts(node)).toEqual(['Times New Roman', 'Arial', 'monospace', 'Tahoma']);
        });

        it('Should return an empty array', () => {
            node.style.fontFamily = '"test fontName"';
            expect(supportedFonts(node)).toEqual([]);
        });

        it('Should be case-insensitive;', () => {
            node.style.fontFamily = 'ARIAL, TAHOMA, HELVETICA';
            expect(detectFont(node)).toEqual('ARIAL');
            node.style.fontFamily = 'MONOSPACE, ARIAL, SANS-SERIF';
            expect(detectFont(node)).toEqual('monospace');
        });

        it('Should be able to change the font size', () => {
            node.style.fontFamily = '"Goodness Knows", Arial';
            expect(detectFont(node, { fontSize: 1 })).toEqual('Arial');
        });

    });

    describe('Error Handling:', () => {

        it('Should raise an exception when passed a non-element;', () => {
            expect(() => detectFont(1)).toThrow(new Error('DetectFont: Cannot detect font on a non-element.'));
        });

        it('Should raise an exception when font size is set to 0;', () => {
            const node = document.createElement('span');
            node.fontFamily = 'GoodnessKnows, Arial, Tahoma, Helvetica';
            expect(() => detectFont(node, { fontSize: 0 })).toThrow(new Error('DetectFont: Setting font size to zero will always yield false positives.'));
        });

        it('Should raise an exception if non-text has been passed into `options`', () => {
            const node = document.createElement('span');
            node.fontFamily = 'GoodnessKnows, Arial, Tahoma, Helvetica';
            expect(() => detectFont(node, { text: '' })).toThrow(new Error('DetectFont: Setting text to an empty string will always yield false positives.'));
        });

    });

    describe('Remove Quotes:', () => {

        it('Should remove optional quoting from the string;', () => {
            expect(removeQuotes(`Times New Roman`)).toEqual('Times New Roman');
            expect(removeQuotes(`'Times New Roman'`)).toEqual('Times New Roman');
            expect(removeQuotes(`"Times New Roman"`)).toEqual('Times New Roman');
        });

    });

});
<|endoftext|>


<commit_before>function(doc) {
    if (!doc.type || doc.type != 'CSV') {
        return;
    }

    emit([doc.campagne+'', doc.cvi+'', doc._id], 1);
}<commit_msg>On ignore les cvi ne commencant pas par 6<commit_after>function(doc) {
    if (!doc.type || doc.type != 'CSV') {
        return;
    }

    if(!doc.cvi.match(/^(67|68)/)) {
		return;
	}

    emit([doc.campagne+'', doc.cvi+'', doc._id], 1);
}<|endoftext|>