<commit_before>/*
 *  $Id$
 *
 * The MIT License
 *
 * Copyright (c) 2007 Lim Chee Aun <cheeaun@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
 * MooEditable.js
 * MooEditable class for contentEditable-capable browsers
 *
 * @package     MooEditable
 * @subpackage  Core
 * @author      Lim Chee Aun <cheeaun@gmail.com>
 * @author      Marc Fowler <marc.fowler@defraction.net>
 * @author      Radovan Lozej <xrado@email.si>
 * @license     http://www.opensource.org/licenses/mit-license.php MIT License
 * @link        http://code.google.com/p/mooeditable/
 * @since       1.0
 * @version     $Revision: 8 $
 * @credits     Most code is based on Stefan's work "Safari Supports Content Editing!"
 *                  <http://www.xs4all.nl/~hhijdra/stefan/ContentEditable.html>
 *              Main reference from Peter-Paul Koch's "execCommand compatibility" research
 *                  <http://www.quirksmode.org/dom/execCommand.html>
 *              Some ideas inspired by TinyMCE <http://tinymce.moxiecode.com/>
 *              Some functions inspired by Inviz's "Most tiny wysiwyg you ever seen"
 *                  <http://forum.mootools.net/viewtopic.php?id=746>,
 *                  <http://forum.mootools.net/viewtopic.php?id=5740>
 *              Some regex from Cameron Adams's widgEditor
 *                  <http://themaninblue.com/experiment/widgEditor/>
 *              IE support referring Robert Bredlau's "Rich Text Editing" part 1 and 2 articles
 *                  <http://www.rbredlau.com/drupal/node/6>
 *              Tango icons from the Tango Desktop Project
 *                  <http://tango.freedesktop.org/>
 *              Additional tango icons from Tango OpenOffice set by Jimmacs
 *                  <http://www.gnome-look.org/content/show.php/Tango+OpenOffice?content=54799>
 */

var MooEditable = new Class({

	Implements: [Events, Options],

	options:{
		toolbar: true,
		buttons: 'bold,italic,strikethrough,separator,insertunorderedlist,insertorderedlist,indent,outdent,separator,undo,redo,separator,createlink,unlink,toggleview',
		text: {
			'bold': 'Bold',
			'italic': 'Italic',
			'strikethrough': 'Strikethrough',
			'insertunorderedlist': 'Unordered List',
			'insertorderedlist': 'Ordered List',
			'indent': 'Indent',
			'outdent': 'Outdent',
			'undo': 'Undo',
			'redo': 'Redo',
			'createlink': 'Add Hyperlink',
			'unlink': 'Remove Hyperlink',
			'separator': '|',
			'toggleview': 'Toggle View'
		}
	},

	initialize: function(el,options){
		this.setOptions(options);
		this.textarea = el;
		this.build();
	},

	build: function(){
		// Build the container
		this.container = new Element('div',{
			'id': (this.textarea.id) ? this.textarea.id+'-container' : null,
			'class': 'mooeditable-container',
			'styles': {
				'width': this.textarea.getOffsetSize().x,
				'margin': this.textarea.getStyle('margin')
			}
		});

		// Put textarea inside container
		this.container.wraps(this.textarea);

		this.textarea.setStyles({
			'margin': 0,
			'display': 'none',
			'resize': 'none', // disable resizable textareas in Safari
			'outline': 'none' // disable focus ring in Safari
		});

		// Fix IE bug, refer "IE/Win Inherited Margins on Form Elements" <http://positioniseverything.net/explorer/inherited_margin.html>
		if(Browser.Engine.trident) new Element('span').wraps(this.textarea);

		// Build the iframe
		var pads = this.textarea.getStyle('padding').split(' ');
		pads = pads.map(function(p){ return (p == 'auto') ? 0 : p.toInt(); });

		this.iframe = new IFrame({
			'class': 'mooeditable-iframe',
			'styles': {
				'width': this.textarea.getStyle('width').toInt() + pads[1] + pads[3],
				'height': this.textarea.getStyle('height').toInt() + pads[0] + pads[2],
				'border-color': this.textarea.getStyle('border-color'),
				'border-width': this.textarea.getStyle('border-width'),
				'border-style': this.textarea.getStyle('border-style')
			}
		});
		this.iframe.inject(this.container, 'top');

		// contentWindow and document references
		this.win = this.iframe.contentWindow;
		this.doc = this.win.document;

		// Build the content of iframe
		var documentTemplate = '\
			\
				'+
				this.cleanup(this.textarea.value) +
				'\
			\
		';
		this.doc.open();
		this.doc.write(documentTemplate);
		this.doc.close();

		// Turn on Design Mode
		this.doc.designMode = 'on';

		// In IE6, after designMode is on, it forgots what is this.doc. Weird.
		if(Browser.Engine.trident4) this.doc = this.win.document;

		// Assign view mode
		this.mode = 'iframe';

		// Update the event for textarea's corresponding labels
		if(this.textarea.id && $$('label[for="'+this.textarea.id+'"]')){
			$$('label[for="'+this.textarea.id+'"]').addEvent('click', function(e){
				if(this.mode == 'iframe'){
					e = new Event(e).stop();
					this.win.focus();
				}
			}.bind(this));
		}

		// Update & cleanup content befour submit
		this.form = this.textarea.getParent('form');
		if(this.form) this.form.addEvent('submit',function(){
			this.updateContent();
		}.bind(this));

		if(this.options.toolbar) this.buildToolbar();
	},

	updateContent: function(){
		if(this.mode=='iframe') this.textarea.value = this.cleanup(this.doc.getElementById('editable').innerHTML);
	},

	buildToolbar: function(){
		this.toolbar = new Element('div',{ 'class': 'mooeditable-toolbar' });
		this.toolbar.inject(this.iframe, 'before');

		var toolbarButtons = this.options.buttons.split(',');

		for (var i=0 ; i<toolbarButtons.length ; i++){
			var command = toolbarButtons[i];
			var b;
			if (command == 'separator'){
				b = new Element('span',{ 'class': 'toolbar-separator' });
			}
			else{
				b = new Element('button',{
					'class': command+'-button toolbar-button',
					'title': this.options.text[command]
				});
			}
			b.set('text', this.options.text[command]);
			b.inject(this.toolbar, 'bottom');
		}

		this.toolbar.getElements('.toolbar-button').each(function(item){
			item.addEvent('click', function(e){
				e = new Event(e).stop();
				if (!item.hasClass('disabled')){
					var command = item.className.split(' ')[0].split('-')[0];
					this.action(command);
				}
				this.win.focus();
			}.bind(this));

			// remove focus rings off the buttons in Firefox
			item.addEvent('mousedown', function(e){ new Event(e).stop(); });

			// add hover effect for IE6
			if(Browser.Engine.trident4) item.addEvents({
				'mouseenter': function(e){ this.addClass('hover'); },
				'mouseleave': function(e){ this.removeClass('hover'); }
			});
		}.bind(this));
	},

	action: function(command){
		var selection = '';
		switch(command){
			case 'createlink':
				if (this.doc.selection){
					selection = this.doc.selection.createRange().text;
					if (selection == ''){
						alert("Please select the text you wish to hyperlink.");
						break;
					}
				}
				else{
					selection = this.win.getSelection();
					if (selection == ''){
						alert("Please select the text you wish to hyperlink.");
						break;
					}
				}
				var url = prompt('Enter URL','http://');
				if (url) this.execute(command, false, url.trim());
				break;
			case 'toggleview':
				this.toggleView();
				break;
			default:
				if (!Browser.Engine.trident) this.execute('styleWithCSS', false, false);
				this.execute(command, false, '');
		}
	},

	execute: function(command, param1, param2){
	    if (!this.busy){
			this.busy = true;
			this.doc.execCommand(command, param1, param2);
			this.textarea.value = this.cleanup(this.doc.getElementById('editable').innerHTML);
			this.busy = false;
		}
		return false;
	},

	toggleView: function() {
		if (this.mode == 'textarea') {
			this.mode = 'iframe';
			this.iframe.setStyle('display', '');
			(function(){
				this.doc.getElementById('editable').innerHTML = this.textarea.value;
			}).bind(this).delay(1); // dealing with Adobe AIR's webkit bug
			this.toolbar.getElements('.toolbar-button').each(function(item){
				item.removeClass('disabled');
				item.set('opacity', 1);
			});
			this.textarea.setStyle('display', 'none');
		} else {
			this.mode = 'textarea';
			this.textarea.setStyle('display', '');
			this.textarea.value = this.cleanup(this.doc.getElementById('editable').innerHTML);
			this.toolbar.getElements('.toolbar-button').each(function(item){
				if (!item.hasClass('toggleview-button')) {
					item.addClass('disabled');
					item.set('opacity', 0.4);
				}
			});
			this.iframe.setStyle('display', 'none');
		}
	},

	cleanup: function(source){
		// Webkit cleanup
		source = source.replace(/
/gi, "
");
		source = source.replace(/(.*)<\/span>/gi, '$1');
		source = source.replace(/ class="Apple-style-span"/gi, '');
		source = source.replace(//gi, '');

		// Remove padded paragraphs
		source = source.replace(/
\s*
\s*<\/p>/gi, '
\u00a0
');
		source = source.replace(/
( |\s)*<\/p>/gi, '
\u00a0
');
		source = source.replace(/\s*
\s*<\/p>/gi, '
');

		// Replace improper BRs
		source = source.replace(/
/gi, "
");

		// Remove leading and trailing BRs
		source = source.replace(/
$/gi, '');
		source = source.replace(/^
/gi, '');

		// Remove useless BRs
		source = source.replace(/>
/gi, '>');

		// Remove BRs right before the end of blocks
		source = source.replace(/
\s*<\/(h1|h2|h3|h4|h5|h6|li|p)/gi, '</$1');

		// Remove empty tags
		source = source.replace(/(<[^\/]>|<[^\/][^>]*[^\/]>)\s*<\/[^>]*>/gi, '');

		// Semantic conversion
		source = source.replace(/(.*)<\/span>/gi, '$1');
		source = source.replace(/(.*)<\/span>/gi, '$1');
		source = source.replace(/)/g, "<strong$1");
		source = source.replace(/<\/b(\s+|>)/g, "</strong$1");
		source = source.replace(/)/g, "<em$1");
		source = source.replace(/<\/i(\s+|>)/g, "</em$1");

		// Replace uppercase element names with lowercase
		source = source.replace(/<[^> ]*/g, function(match){return match.toLowerCase();});

		// Replace uppercase attribute names with lowercase
		source = source.replace(/<[^>]*>/g, function(match){
			match = match.replace(/ [^=]+=/g, function(match2){return match2.toLowerCase();});
			return match;
		});

		// Put quotes around unquoted attributes
		source = source.replace(/<[^>]*>/g, function(match){
			match = match.replace(/( [^=]+=)([^"][^ >]*)/g, "$1\"$2\"");
			return match;
		});

		// Final trim
		source = source.trim();

		return source;
	}
});
<commit_msg>recover the lost code + fix<commit_after>/*
 *  $Id$
 *
 * The MIT License
 *
 * Copyright (c) 2007 Lim Chee Aun <cheeaun@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
 * MooEditable.js
 * MooEditable class for contentEditable-capable browsers
 *
 * @package     MooEditable
 * @subpackage  Core
 * @author      Lim Chee Aun <cheeaun@gmail.com>
 * @author      Marc Fowler <marc.fowler@defraction.net>
 * @author      Radovan Lozej <xrado@email.si>
 * @license     http://www.opensource.org/licenses/mit-license.php MIT License
 * @link        http://code.google.com/p/mooeditable/
 * @since       1.0
 * @version     $Revision: 8 $
 * @credits     Most code is based on Stefan's work "Safari Supports Content Editing!"
 *                  <http://www.xs4all.nl/~hhijdra/stefan/ContentEditable.html>
 *              Main reference from Peter-Paul Koch's "execCommand compatibility" research
 *                  <http://www.quirksmode.org/dom/execCommand.html>
 *              Some ideas inspired by TinyMCE <http://tinymce.moxiecode.com/>
 *              Some functions inspired by Inviz's "Most tiny wysiwyg you ever seen"
 *                  <http://forum.mootools.net/viewtopic.php?id=746>,
 *                  <http://forum.mootools.net/viewtopic.php?id=5740>
 *              Some regex from Cameron Adams's widgEditor
 *                  <http://themaninblue.com/experiment/widgEditor/>
 *              IE support referring Robert Bredlau's "Rich Text Editing" part 1 and 2 articles
 *                  <http://www.rbredlau.com/drupal/node/6>
 *              Tango icons from the Tango Desktop Project
 *                  <http://tango.freedesktop.org/>
 *              Additional tango icons from Tango OpenOffice set by Jimmacs
 *                  <http://www.gnome-look.org/content/show.php/Tango+OpenOffice?content=54799>
 */

var MooEditable = new Class({

	Implements: [Events, Options],

	options:{
		toolbar: true,
		buttons: 'bold,italic,underline,strikethrough,separator,insertunorderedlist,insertorderedlist,indent,outdent,separator,undo,redo,separator,\
					createlink,unlink,separator,urlimage,separator,toggleview',
		text: {
			'bold': 'Bold',
			'italic': 'Italic',
			'underline': 'Underline',
			'strikethrough': 'Strikethrough',
			'insertunorderedlist': 'Unordered List',
			'insertorderedlist': 'Ordered List',
			'indent': 'Indent',
			'outdent': 'Outdent',
			'undo': 'Undo',
			'redo': 'Redo',
			'createlink': 'Add Hyperlink',
			'unlink': 'Remove Hyperlink',
			'urlimage': 'Add image from URL',
			'separator': '|',
			'toggleview': 'Toggle View'
		}
	},

	initialize: function(el,options){
		this.setOptions(options);
		this.textarea = el;
		this.build();
	},

	build: function(){
		// Build the container
		this.container = new Element('div',{
			'id': (this.textarea.id) ? this.textarea.id+'-container' : null,
			'class': 'mooeditable-container',
			'styles': {
				'width': this.textarea.getOffsetSize().x,
				'margin': this.textarea.getStyle('margin')
			}
		});

		// Put textarea inside container
		this.container.wraps(this.textarea);

		this.textarea.setStyles({
			'margin': 0,
			'display': 'none',
			'resize': 'none', // disable resizable textareas in Safari
			'outline': 'none' // disable focus ring in Safari
		});

		// Fix IE bug, refer "IE/Win Inherited Margins on Form Elements" <http://positioniseverything.net/explorer/inherited_margin.html>
		if(Browser.Engine.trident) new Element('span').wraps(this.textarea);

		// Build the iframe
		var pads = this.textarea.getStyle('padding').split(' ');
		pads = pads.map(function(p){ return (p == 'auto') ? 0 : p.toInt(); });

		this.iframe = new IFrame({
			'class': 'mooeditable-iframe',
			'styles': {
				'width': this.textarea.getStyle('width').toInt() + pads[1] + pads[3],
				'height': this.textarea.getStyle('height').toInt() + pads[0] + pads[2],
				'border-color': this.textarea.getStyle('border-color'),
				'border-width': this.textarea.getStyle('border-width'),
				'border-style': this.textarea.getStyle('border-style')
			}
		});
		this.iframe.inject(this.container, 'top');

		// contentWindow and document references
		this.win = this.iframe.contentWindow;
		this.doc = this.win.document;

		// Build the content of iframe
		var documentTemplate = '\
			\
				'+
				this.cleanup(this.textarea.value) +
				'\
			\
		';
		this.doc.open();
		this.doc.write(documentTemplate);
		this.doc.close();

		// Turn on Design Mode
		this.doc.designMode = 'on';

		// In IE6, after designMode is on, it forgots what is this.doc. Weird.
		if(Browser.Engine.trident4) this.doc = this.win.document;

		// Assign view mode
		this.mode = 'iframe';

		// Update the event for textarea's corresponding labels
		if(this.textarea.id && $$('label[for="'+this.textarea.id+'"]')){
			$$('label[for="'+this.textarea.id+'"]').addEvent('click', function(e){
				if(this.mode == 'iframe'){
					e = new Event(e).stop();
					this.win.focus();
				}
			}.bind(this));
		}

		// Update & cleanup content befour submit
		this.form = this.textarea.getParent('form');
		if(this.form) this.form.addEvent('submit',function(){
			this.updateContent();
		}.bind(this));

		if(this.options.toolbar) this.buildToolbar();
	},

	updateContent: function(){
		if(this.mode=='iframe') this.textarea.value = this.cleanup(this.doc.getElementById('editable').innerHTML);
	},

	buildToolbar: function(){
		this.toolbar = new Element('div',{ 'class': 'mooeditable-toolbar' });
		this.toolbar.inject(this.iframe, 'before');

		var toolbarButtons = this.options.buttons.split(',');

		for (var i=0 ; i<toolbarButtons.length ; i++){
			var command = toolbarButtons[i];
			var b;
			if (command == 'separator'){
				b = new Element('span',{ 'class': 'toolbar-separator' });
			}
			else{
				b = new Element('button',{
					'class': command+'-button toolbar-button',
					'title': this.options.text[command]
				});
			}
			b.set('text', this.options.text[command]);
			b.inject(this.toolbar, 'bottom');
		}

		this.toolbar.getElements('.toolbar-button').each(function(item){
			item.addEvent('click', function(e){
				e = new Event(e).stop();
				if (!item.hasClass('disabled')){
					var command = item.className.split(' ')[0].split('-')[0];
					this.action(command);
				}
				this.win.focus();
			}.bind(this));

			// remove focus rings off the buttons in Firefox
			item.addEvent('mousedown', function(e){ new Event(e).stop(); });

			// add hover effect for IE6
			if(Browser.Engine.trident4) item.addEvents({
				'mouseenter': function(e){ this.addClass('hover'); },
				'mouseleave': function(e){ this.removeClass('hover'); }
			});
		}.bind(this));
	},

	action: function(command){
		var selection = '';
		switch(command){
			case 'createlink':
				if (this.doc.selection){
					selection = this.doc.selection.createRange().text;
					if (selection == ''){
						alert("Please select the text you wish to hyperlink.");
						break;
					}
				}
				else{
					selection = this.win.getSelection();
					if (selection == ''){
						alert("Please select the text you wish to hyperlink.");
						break;
					}
				}
				var url = prompt('Enter URL','http://');
				if (url) this.execute(command, false, url.trim());
				break;
			case 'urlimage':
				var url = prompt("Enter Image URL","http://");
				if (url) this.execute("insertImage", false, url.trim());
				break;
			case 'toggleview':
				this.toggleView();
				break;
			default:
				if (!Browser.Engine.trident) this.execute('styleWithCSS', false, false);
				this.execute(command, false, '');
		}
	},

	execute: function(command, param1, param2){
	    if (!this.busy){
			this.busy = true;
			this.doc.execCommand(command, param1, param2);
			this.textarea.value = this.cleanup(this.doc.getElementById('editable').innerHTML);
			this.busy = false;
		}
		return false;
	},

	toggleView: function() {
		if (this.mode == 'textarea') {
			this.mode = 'iframe';
			this.iframe.setStyle('display', '');
			(function(){
				this.doc.getElementById('editable').innerHTML = this.textarea.value;
			}).bind(this).delay(1); // dealing with Adobe AIR's webkit bug
			this.toolbar.getElements('.toolbar-button').each(function(item){
				item.removeClass('disabled');
				item.set('opacity', 1);
			});
			this.textarea.setStyle('display', 'none');
		} else {
			this.mode = 'textarea';
			this.textarea.setStyle('display', '');
			this.textarea.value = this.cleanup(this.doc.getElementById('editable').innerHTML);
			this.toolbar.getElements('.toolbar-button').each(function(item){
				if (!item.hasClass('toggleview-button')) {
					item.addClass('disabled');
					item.set('opacity', 0.4);
				}
			});
			this.iframe.setStyle('display', 'none');
		}
	},

	cleanup: function(source){
		// Webkit cleanup
		source = source.replace(/
/gi, "
");
		source = source.replace(/(.*)<\/span>/gi, '$1');
		source = source.replace(/ class="Apple-style-span"/gi, '');
		source = source.replace(//gi, '');

		// Remove padded paragraphs
		source = source.replace(/
\s*
\s*<\/p>/gi, '
\u00a0
');
		source = source.replace(/
( |\s)*<\/p>/gi, '
\u00a0
');
		source = source.replace(/\s*
\s*<\/p>/gi, '
');

		// Replace improper BRs
		source = source.replace(/
/gi, "
");

		// Remove leading and trailing BRs
		source = source.replace(/
$/gi, '');
		source = source.replace(/^
/gi, '');

		// Remove useless BRs
		source = source.replace(/>
/gi, '>');

		// Remove BRs right before the end of blocks
		source = source.replace(/
\s*<\/(h1|h2|h3|h4|h5|h6|li|p)/gi, '</$1');

		// Remove empty tags
		source = source.replace(/(<[^\/]>|<[^\/][^>]*[^\/]>)\s*<\/[^>]*>/gi, '');

		// Semantic conversion
		source = source.replace(/(.*)<\/span>/gi, '$1');
		source = source.replace(/(.*)<\/span>/gi, '$1');
		source = source.replace(/)/g, "<strong$1");
		source = source.replace(/<\/b(\s+|>)/g, "</strong$1");
		source = source.replace(/)/g, "<em$1");
		source = source.replace(/<\/i(\s+|>)/g, "</em$1");

		// Replace uppercase element names with lowercase
		source = source.replace(/<[^> ]*/g, function(match){return match.toLowerCase();});

		// Replace uppercase attribute names with lowercase
		source = source.replace(/<[^>]*>/g, function(match){
			match = match.replace(/ [^=]+=/g, function(match2){return match2.toLowerCase();});
			return match;
		});

		// Put quotes around unquoted attributes
		source = source.replace(/<[^>]*>/g, function(match){
			match = match.replace(/( [^=]+=)([^"][^ >]*)/g, "$1\"$2\"");
			return match;
		});

		// Final trim
		source = source.trim();

		return source;
	}
});
<|endoftext|>


<commit_before>var cdb = require('cartodb.js');
var Utils = require('cdb.Utils')

/**
 *  Limits reach content
 *
 */

module.exports = cdb.core.View.extend({

  events: {
    'click .js-toggler': '_onLumpSumClick'
  },

  initialize: function() {
    this.user = this.options.user;
    this.model = new cdb.core.Model({
      lumpSum: false
    });
    this.template = cdb.templates.getTemplate('common/dialogs/limits_reach/limits_reached_content');
    this._initBinds();
  },

  render: function() {
    var canUpgrade = cdb.config.get('upgrade_url') && !cdb.config.get('custom_com_hosted') && !this.user.isInsideOrg();
    var currentPlan = this.user.get("account_type");

    var availablePlans = _.compact(this.collection.map(function(plan, index) {
      var price = plan.get('price');
      var planName = plan.get('title');

      return {
        name: planName.toLowerCase(),
        price: Utils.formatNumber(price),
        isUserPlan: planName.search(currentPlan) !== -1,
        lumpSumPrice: price == "0" ? "0" : Utils.formatNumber(plan.get('lump_sum').price),
        quota: getQuotaSize(plan.get('bytes_quota')),
        layers: plan.get('max_layers'),
        privateMaps: plan.get('private_tables'),
        removableBrand: plan.get('removable_brand')
      }
    }));

    this.$el.html(
      this.template({
        lumpSum: this.model.get('lumpSum'),
        itemHighlighted: this._getHighlighted(availablePlans, this.user.get("account_type")),
        canUpgrade: canUpgrade,
        availablePlans: availablePlans,
        organizationAdmin: this.user.isOrgAdmin(),
        organizationUser: (this.user.isInsideOrg() && !this.user.isOrgAdmin()),
        customHosted: cdb.config.get('custom_com_hosted'),
        upgradeURL: cdb.config.get('upgrade_url'),
        canStartTrial: this.user.canStartTrial()
      })
    );

    return this;
  },

  _initBinds: function() {
    this.model.bind('change', this.render, this);
    this.collection.bind('reset', this.render, this);
    this.add_related_model(this.collection);
  },

  _getHighlighted: function(plans, currentPlan) {
    var item = 0;
    for (var i = 0, l = plans.length; i < l; i++) {
      if (plans[i].name.search(currentPlan) !== -1) {
        item = i;
      }
    }
    return item < 2 ? 2 : 3;
  },

  _onLumpSumClick: function() {
    this.model.set('lumpSum', !this.model.get('lumpSum'));
  }

  _getQuotaSize: function(bytes) {
    var s = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
    var e = Math.floor(Math.log(bytes)/Math.log(1024));
    return parseFloat((bytes/Math.pow(1024, Math.floor(e))).toFixed(2))+s[e];
  }

})
<commit_msg>Vector data size improvements fix<commit_after>var cdb = require('cartodb.js');
var Utils = require('cdb.Utils')

/**
 *  Limits reach content
 *
 */

module.exports = cdb.core.View.extend({

  events: {
    'click .js-toggler': '_onLumpSumClick'
  },

  initialize: function() {
    this.user = this.options.user;
    this.model = new cdb.core.Model({
      lumpSum: false
    });
    this.template = cdb.templates.getTemplate('common/dialogs/limits_reach/limits_reached_content');
    this._initBinds();
  },

  render: function() {
    var canUpgrade = cdb.config.get('upgrade_url') && !cdb.config.get('custom_com_hosted') && !this.user.isInsideOrg();
    var currentPlan = this.user.get("account_type");

    var availablePlans = _.compact(this.collection.map(function(plan, index) {
      var price = plan.get('price');
      var planName = plan.get('title');

      return {
        name: planName.toLowerCase(),
        price: Utils.formatNumber(price),
        isUserPlan: planName.search(currentPlan) !== -1,
        lumpSumPrice: price == "0" ? "0" : Utils.formatNumber(plan.get('lump_sum').price),
        quota: getQuotaSize(plan.get('bytes_quota')),
        layers: plan.get('max_layers'),
        privateMaps: plan.get('private_tables'),
        removableBrand: plan.get('removable_brand')
      }
    }));

    this.$el.html(
      this.template({
        lumpSum: this.model.get('lumpSum'),
        itemHighlighted: this._getHighlighted(availablePlans, this.user.get("account_type")),
        canUpgrade: canUpgrade,
        availablePlans: availablePlans,
        organizationAdmin: this.user.isOrgAdmin(),
        organizationUser: (this.user.isInsideOrg() && !this.user.isOrgAdmin()),
        customHosted: cdb.config.get('custom_com_hosted'),
        upgradeURL: cdb.config.get('upgrade_url'),
        canStartTrial: this.user.canStartTrial()
      })
    );

    return this;
  },

  _initBinds: function() {
    this.model.bind('change', this.render, this);
    this.collection.bind('reset', this.render, this);
    this.add_related_model(this.collection);
  },

  _getHighlighted: function(plans, currentPlan) {
    var item = 0;
    for (var i = 0, l = plans.length; i < l; i++) {
      if (plans[i].name.search(currentPlan) !== -1) {
        item = i;
      }
    }
    return item < 2 ? 2 : 3;
  },

  _onLumpSumClick: function() {
    this.model.set('lumpSum', !this.model.get('lumpSum'));
  },

  _getQuotaSize: function(bytes) {
    var s = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
    var e = Math.floor(Math.log(bytes)/Math.log(1024));
    return parseFloat((bytes/Math.pow(1024, Math.floor(e))).toFixed(2))+s[e];
  }

})
<|endoftext|>


<commit_before>export const root = typeof window === 'undefined' ? global : window;

const { Object, MutationObserver } = root;
const { getOwnPropertyNames, getOwnPropertySymbols } = Object;

export function dashCase (str) {
  return str.split(/([A-Z])/).reduce((one, two, idx) => {
    const dash = !one || idx % 2 === 0 ? '' : '-';
    return `${one}${dash}${two.toLowerCase()}`;
  });
}

export function debounce (cbFunc) {
  let scheduled = false;
  let i = 0;
  let cbArgs = [];
  const elem = document.createElement('span');
  const observer = new MutationObserver(() => {
    cbFunc(...cbArgs);
    scheduled = false;
    cbArgs = null;
  });

  observer.observe(elem, { childList: true });

  return (...args) => {
    cbArgs = args;
    if (!scheduled) {
      scheduled = true;
      elem.textContent = `${i}`;
      i += 1;
    }
  };
}

export function keys (obj = {}) {
  const names = getOwnPropertyNames(obj);
  return getOwnPropertySymbols ? names.concat(getOwnPropertySymbols(obj)) : names;
}

export function sym () {
  return typeof Symbol === 'function' ? Symbol() : uniqueId();
}

export function uniqueId () {
  return 'xxxxxxxx'.replace(/[xy]/g, (c) => {
    const r = Math.random() * 16 | 0;
    const v = c === 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
}
<commit_msg>chore: Add genera empty util.<commit_after>export const root = typeof window === 'undefined' ? global : window;

const { Object, MutationObserver } = root;
const { getOwnPropertyNames, getOwnPropertySymbols } = Object;

export function dashCase (str) {
  return str.split(/([A-Z])/).reduce((one, two, idx) => {
    const dash = !one || idx % 2 === 0 ? '' : '-';
    return `${one}${dash}${two.toLowerCase()}`;
  });
}

export function debounce (cbFunc) {
  let scheduled = false;
  let i = 0;
  let cbArgs = [];
  const elem = document.createElement('span');
  const observer = new MutationObserver(() => {
    cbFunc(...cbArgs);
    scheduled = false;
    cbArgs = null;
  });

  observer.observe(elem, { childList: true });

  return (...args) => {
    cbArgs = args;
    if (!scheduled) {
      scheduled = true;
      elem.textContent = `${i}`;
      i += 1;
    }
  };
}

export const empty = val => val == null;

export function keys (obj = {}) {
  const names = getOwnPropertyNames(obj);
  return getOwnPropertySymbols ? names.concat(getOwnPropertySymbols(obj)) : names;
}

export function sym () {
  return typeof Symbol === 'function' ? Symbol() : uniqueId();
}

export function uniqueId () {
  return 'xxxxxxxx'.replace(/[xy]/g, (c) => {
    const r = Math.random() * 16 | 0;
    const v = c === 'x' ? r : (r & 0x3 | 0x8);
    return v.toString(16);
  });
}
<|endoftext|>


<commit_before>//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Merge two objects to create a new one with the properties of both
//------------------------------------------------------------------------------
d3plus.util.merge = function(obj1, obj2) {
  var obj3 = {};
  function copy_object(obj,ret) {
    for (var a in obj) {
      if (typeof obj[a] != "undefined") {
        if (typeof obj[a] == "object" && !(obj[a] instanceof Array) && obj[a] !== null) {
          if (typeof ret[a] != "object") ret[a] = {}
          copy_object(obj[a],ret[a])
        }
        else if (obj[a] instanceof Array) {
          ret[a] = obj[a].slice(0)
        }
        else {
          ret[a] = obj[a]
        }
      }
    }
  }
  if (obj1) copy_object(obj1,obj3)
  if (obj2) copy_object(obj2,obj3)
  return obj3;
}
<commit_msg>code cleanup<commit_after>//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Merge two objects to create a new one with the properties of both
//------------------------------------------------------------------------------
d3plus.util.merge = function(obj1, obj2) {

  var obj3 = {};

  function copy_object(obj,ret) {

    for (var a in obj) {

      if (typeof obj[a] != "undefined") {

        if (typeof obj[a] == "object" && !(obj[a] instanceof Array) && obj[a] !== null) {

          if (typeof ret[a] != "object") ret[a] = {}
          copy_object(obj[a],ret[a])

        }
        else if (obj[a] instanceof Array) {

          ret[a] = obj[a].slice(0)

        }
        else {

          ret[a] = obj[a]

        }

      }

    }

  }

  if (obj1) copy_object(obj1,obj3)
  if (obj2) copy_object(obj2,obj3)

  return obj3;
}
<|endoftext|>


<commit_before>/**
 * Creates an instance of Admin.
 *
 * @constructor
 * @param {Object} options - instance options
 * @classdesc This class contains utility methods used by the admin
 * application.
 */
var Admin = function(options) {
    Listing.call(this, options);
};

Admin.prototype = {
    defaults: {
        deflocation: "list/",
        squery: null
    },

    initialize: function(options) {
        this.options = $.extend({}, this.defaults, options);
        this.options.defcallback = $.proxy(this.list_cb, this);
        Listing.prototype.initialize.call(this, this.options);
        this.listen();
    },

    /**
     * Callback used when the initial content of the listing is
     * received.
     *
     * @this Admin
     * @param {Object} data - response of the ajax call (JSON)
     */
    list_cb: function(data) {
        if (data.rows) {
            $("#objects_table tbody").html(data.rows);
        } else {
            $("#objects_table tbody").html("");
        }
        this.update_listing(data);
        if (data.length === 0) {
            this.get_load_page_args();
            this.end_of_list_reached();
        }
    },

    /**
     * Children must override this method.
     */
    listen: function() {
    },

    importform_cb: function() {
        $(".submit").one('click', function(e) {
            e.preventDefault();
            if ($("#id_sourcefile").val() === "") {
                return;
            }
            $("#import_status").css("display", "block");
            $("#import_result").html("").removeClass("alert alert-danger");
            $("#importform").submit();
        });
    },

    importdone: function(status, msg) {
        $("#import_status").css("display", "none");
        if (status == "ok") {
            $("#modalbox").modal('hide');
            this.reload_listing(msg);
        } else {
            $("#import_result").addClass("alert alert-danger");
            $("#import_result").html(msg);
            this.importform_cb();
        }
    },

    exportform_cb: function() {
        $(".submit").one('click', function(e) {
            e.preventDefault();
            $("#exportform").submit();
            $("#modalbox").modal('hide');
        });
    },

    reload_listing: function(data) {
        this.navobj.update(true);
        if (data) {
            $("body").notify("success", data, 2000);
        }
    }
};

Admin.prototype = $.extend({}, Listing.prototype, Admin.prototype);

/**
 * Creates an instance of Domains.
 *
 * @constructor
 * @param {Object} options - instance options
 * @classdesc This class extends the Admin one by adding methods
 * specific to domains management.
 */
var Domains = function(options) {
    Admin.call(this, options);
};

Domains.prototype = {
    initialize: function(options) {
        Admin.prototype.initialize.call(this, options);
        this.options.navigation_params.push("domfilter", "srvfilter");
        this.options.eor_message = gettext("No more domain to show");
        this.register_tag_handler("dom");
    },

    /**
     * Initialize the domain links embedded within a page.
     *
     * @param {Object} data - options
     */
    init_domain_links: function(data) {
        var deloptions = (data.handle_mailboxes) ?
            {keepdir: gettext("Do not delete domain directory")} : {};
        var warnmsg = (data.auto_account_removal && data.auto_account_removal == "yes")
            ? gettext("This operation will remove ALL data associated to this domain.")
            : gettext("This operation will remove all data associated to this domain, excepting accounts.");

        $("a[name=deldomain]").confirm({
            question: function() { return this.$element.attr('title'); },
            method: "POST",
            warning: warnmsg,
            checkboxes: deloptions,
            success_cb: $.proxy(this.reload_listing, this)
        });
        $(document).trigger('domain_listing_refresh');
    },

    /**
     * Navigation callback: default.
     *
     * @param {Object} data - response of the ajax call (JSON)
     */
    list_cb: function(data) {
        Admin.prototype.list_cb.call(this, data);
        this.init_domain_links(data);
    },

    /**
     * A new page has been received, inject it.
     *
     * @param {Object} data - page content
     * @param {string} direction -
     */
    add_new_page: function(data, direction) {
        Admin.prototype.add_new_page.call(this, data, direction);
        this.init_domain_links(data);
    },

    change_inputs_state: function(value) {
        $("#id_dom_admin_username").attr("disabled", value);
        $("input[name=create_aliases]").attr("disabled", value);
    },

    create_dom_admin_changed: function(e) {
        var $target = $(e.target);
        this.change_inputs_state(($target.val() == "yes") ? false : true);
    },

    /**
     * Initialize the main form contained in the domain edition modal.
     *
     * @this Domains
     */
    generalform_init: function() {
        $('input:text:visible:first').focus();
        $("#original_aliases").dynamic_input({
            input_added: function($row) {
                $row.find("label").html("");
            },
            input_removed: function($input) {
                $input.parents(".form-group").remove();
                return true;
            }
        });
    },

    optionsform_init: function() {
        $("input[name=create_dom_admin]").click($.proxy(this.create_dom_admin_changed, this));
        this.change_inputs_state(
            $("input[name=create_dom_admin]:checked").val() == "yes" ? false : true
        );
        this.optionsform_prefill();
    },

    optionsform_prefill: function() {
        var $span = $("#id_dom_admin_username").next("span");
        $span.html("@" + $("#id_name").val());
    },

    domadminsform_init: function() {
        $("a[name=removeperm]").click(function(e) {
            var $tr = $(this).parents('tr');
            simple_ajax_request.apply(this, [e, {
                ok_cb: function(resp) {
                    $tr.remove();
                    if (!$("#domadmins").find("tr").length) {
                        $("#admins").html('
'
                            + gettext("No domain administrator defined") + "
");
                    }
                }
            }]);
        });
    },

    newdomain_cb: function() {
        this.generalform_init();
        this.optionsform_init();
        $("#wizard").cwizard({
            formid: "domform",
            transition_callbacks: {
                1: this.optionsform_prefill
            },
            error_callbacks: {
                2: $.proxy(this.optionsform_init, this)
            },
            success_callback: $.proxy(this.reload_listing, this)
        });
    },

    domainform_cb: function() {
        this.generalform_init();
        this.domadminsform_init();
        $(".submit").one('click', $.proxy(function(e) {
            simple_ajax_form_post(e, {
                formid: "domform",
                error_cb: $.proxy(this.domainform_cb, this),
                reload_on_success: false,
                success_cb: $.proxy(this.reload_listing, this)
            });
        }, this));
        $(document).trigger('domform_init');
    }
};

Domains.prototype = $.extend({}, Admin.prototype, Domains.prototype);

/**
 * Creates an instance of Identities.
 *
 * @constructor
 * @param {Object} options - instance options
 * @classdesc This class extends the Admin one by adding methods
 * specific to identities management.
 */
var Identities = function(options) {
    Admin.call(this, options);
};

Identities.prototype = {
    initialize: function(options) {
        Admin.prototype.initialize.call(this, options);
        this.options.navigation_params.push("idtfilter", "grpfilter");
        this.options.eor_message = gettext("No more identity to show");
        this.domain_list = [];
        this.register_tag_handler("idt");
        this.register_tag_handler("grp", this.grp_tag_handler);
    },

    listen: function() {
        Admin.prototype.listen.call(this);
        $(document).on("click", "a.ajaxnav", $.proxy(this.page_loader, this));
        $(document).on("click", "a.ajaxcall", $.proxy(this.send_call, this));
    },

    page_loader: function(e) {
        var $link = get_target(e);
        e.preventDefault();
        if ($link.hasClass("navigation")) {
            $(".sidebar li.active").removeClass("active");
            $link.parent().addClass("active");
        }
        this.navobj.baseurl($link.attr("href")).update();
    },

    /**
     * Send an ajax call.
     */
    send_call: function(evt) {
        var $link = get_target(evt, "a");
        var $this = this;
        var method = $link.attr("data-call_method");

        if (method === undefined) {
            method = "GET";
        }
        evt.preventDefault();
        $.ajax({
            url: $link.attr("href"),
            type: method,
            dataType: "json"
        }).done(function(data) {
            $this.reload_listing(data.respmsg);
        });
    },

    /**
     * Initialize the links embedded within a page.
     *
     * @param {Object} data - options
     */
    init_identity_links: function(data) {
        var deloptions = {};

        if (data.handle_mailboxes == "yes") {
            deloptions = {keepdir: gettext("Do not delete mailbox directory")};
        }

        $("a[name=delaccount]").confirm({
            question: function() { return this.$element.attr('title'); },
            method: "POST",
            checkboxes: deloptions,
            success_cb: $.proxy(this.reload_listing, this)
        });
        $("a[name=delalias]").confirm({
            question: function() { return this.$element.attr('title'); },
            method: "DELETE",
            success_cb: $.proxy(this.reload_listing, this)
        });
    },

    /**
     * Add a type to let the server know what kind of object we expect.
     *
     * @this Listing
     */
    get_load_page_args: function() {
        var args = Admin.prototype.get_load_page_args.call(this);

        if (this.navobj.getbaseurl() == "list") {
            args.objtype = "identity";
            this.options.eor_message = gettext("No more identity to show");
        } else {
            args.objtype = "quota";
            this.options.eor_message = gettext("No more quota to show");
        }
        return args;
    },

    /**
     * A new page has been received, inject it.
     *
     * @param {Object} data - page content
     * @param {string} direction -
     */
    add_new_page: function(data, direction) {
        Admin.prototype.add_new_page.call(this, data, direction);
        this.init_identity_links(data);
    },

    /**
     * Navigation callback: default.
     *
     * @param {Object} data - response of the ajax call (JSON)
     */
    list_cb: function(data) {
        if ($(".sidebar li.active").length === 0) {
            var menu = this.navobj.getbaseurl();
            if (menu == "list") {
                menu = "identities";
            }
            $("a[name={0}]".format(menu)).parent().addClass("active");
        }
        $("#objects_table thead tr").html(data.headers);
        Admin.prototype.list_cb.call(this, data);
        this.init_identity_links(data);
    },

    grp_tag_handler: function(tag, $link) {
        if (this.navobj.getparam(tag + "filter") === undefined &&
            $link.hasClass(tag)) {
            var text = $link.attr("name");
            this.navobj
                .setparam("idtfilter", "account")
                .setparam(tag + "filter", text)
                .update();
            if ($("a[name=idt]").length === 0) {
                $("#taglist").append(this.make_tag("account", "idt"));
            }
            $("#taglist").append(this.make_tag(text, tag));
            return true;
        }
        return false;
    },

    /**
     * Retrieve a list of domain from the server.
     *
     * @this Identities
     * @return {Array} a list of domain names
     */
    get_domain_list: function() {
        if (!this.domain_list.length) {
            $.ajax({
                url: this.options.domain_list_url,
                dataType: "json",
                async: false
            }).done($.proxy(function(data) {
                this.domain_list = data;
            }, this));
        }
        return this.domain_list;
    },

    simpleuser_mode: function() {
        $("#id_username").autocompleter({
            from_character: "@",
            choices: $.proxy(this.get_domain_list, this)
        });
        $("#id_email").addClass("disabled")
            .attr("readonly", "")
            .autocompleter("unbind");
    },

    normal_mode: function() {
        $("#id_email").removeClass("disabled")
            .attr("readonly", null)
            .autocompleter("listen");
    },

    generalform_init: function(notrigger) {
        $("#id_role").change($.proxy(function(e) {
            var $this = $(e.target);
            var value = $this.val();

            if (value == "SimpleUsers" || value === "") {
                this.simpleuser_mode();
            } else {
                this.normal_mode();
            }
        }, this));
        if (notrigger !== undefined && notrigger) {
            return;
        }
        $("#id_role").trigger("change");
    },

    mailform_init: function() {
        $("#id_aliases").autocompleter({
            from_character: "@",
            choices: $.proxy(this.get_domain_list, this)
        });
        $("#original_aliases").dynamic_input({
            input_added: function($row) {
                $row.find("label").html("");
            },
            input_removed: function($input) {
                $input.parents(".form-group").remove();
                return true;
            }
        });
        $("#id_email").autocompleter({
            from_character: "@",
            choices: $.proxy(this.get_domain_list, this)
        });
        if ($("#id_role").length) {
            $("#id_role").trigger("change");
        } else {
            this.simpleuser_mode();
        }
        $("#id_domains").autocompleter({
            choices: $.proxy(this.get_domain_list, this)
        });
        $("#original_domains").dynamic_input({
            input_added: function($row) {
                $row.find("label").html("");
            },
            input_removed: function($input) {
                $input.parents(".form-group").remove();
                return true;
            }
        });
        activate_widget.call($("#id_quota_act"));
    },

    accountform_init: function() {
        this.generalform_init(true);
        this.mailform_init();
    },

    mailform_prefill: function() {
        var $role = $("#id_role");
        if (!$role.length || $role.val() === "" || $role.val() == "SimpleUsers") {
            $("#id_email").val($("#id_username").val());
        }
    },

    newaccount_cb: function() {
        this.accountform_init();
        $("#wizard").cwizard({
            formid: "newaccount_form",
            transition_callbacks: {
                1: this.mailform_prefill
            },
            success_callback: $.proxy(this.reload_listing, this)
        });
    },

    editaccount_cb: function() {
        this.accountform_init();
        $('.submit').on('click', $.proxy(function(e) {
            simple_ajax_form_post(e, {
                formid: "accountform",
                reload_on_success: false,
                success_cb: $.proxy(this.reload_listing, this)
            });
        }, this));
    },

    aliasform_cb: function() {
        $("#id_email").autocompleter({
            from_character: "@",
            choices: $.proxy(this.get_domain_list, this)
        });
        $("#original_recipients").dynamic_input({
            input_added: function($row) {
                $row.find("label").html("");
            },
            input_removed: function($input) {
                $input.parents(".form-group").remove();
                return true;
            }
        });
        $(".submit").on('click', $.proxy(function(e) {
            simple_ajax_form_post(e, {
                formid: "aliasform",
                reload_on_success: false,
                success_cb: $.proxy(this.reload_listing, this)
            });
        }, this));
    }

};

Identities.prototype = $.extend({}, Admin.prototype, Identities.prototype);
<commit_msg>Prevent a double loading.<commit_after>/**
 * Creates an instance of Admin.
 *
 * @constructor
 * @param {Object} options - instance options
 * @classdesc This class contains utility methods used by the admin
 * application.
 */
var Admin = function(options) {
    Listing.call(this, options);
};

Admin.prototype = {
    defaults: {
        deflocation: "list/",
        squery: null
    },

    initialize: function(options) {
        this.options = $.extend({}, this.defaults, options);
        this.options.defcallback = $.proxy(this.list_cb, this);
        Listing.prototype.initialize.call(this, this.options);
        this.listen();
    },

    /**
     * Callback used when the initial content of the listing is
     * received.
     *
     * @this Admin
     * @param {Object} data - response of the ajax call (JSON)
     */
    list_cb: function(data) {
        if (data.rows) {
            $("#objects_table tbody").html(data.rows);
        } else {
            $("#objects_table tbody").html("");
        }
        this.update_listing(data);
        if (data.length === 0) {
            this.get_load_page_args();
            this.end_of_list_reached();
        }
    },

    /**
     * Children must override this method.
     */
    listen: function() {
    },

    /**
     * Load a new page using an AJAX request.
     *
     * @this Admin
     * @param {Object} e - event object
     */
    page_loader: function(e) {
        var $link = get_target(e);
        e.preventDefault();
        if ($link.hasClass("navigation")) {
            $(".sidebar li.active").removeClass("active");
            $link.parent().addClass("active");
        }
        this.navobj.baseurl($link.attr("href")).update();
    },

    importform_cb: function() {
        $(".submit").one('click', function(e) {
            e.preventDefault();
            if ($("#id_sourcefile").val() === "") {
                return;
            }
            $("#import_status").css("display", "block");
            $("#import_result").html("").removeClass("alert alert-danger");
            $("#importform").submit();
        });
    },

    importdone: function(status, msg) {
        $("#import_status").css("display", "none");
        if (status == "ok") {
            $("#modalbox").modal('hide');
            this.reload_listing(msg);
        } else {
            $("#import_result").addClass("alert alert-danger");
            $("#import_result").html(msg);
            this.importform_cb();
        }
    },

    exportform_cb: function() {
        $(".submit").one('click', function(e) {
            e.preventDefault();
            $("#exportform").submit();
            $("#modalbox").modal('hide');
        });
    },

    reload_listing: function(data) {
        this.navobj.update(true);
        if (data) {
            $("body").notify("success", data, 2000);
        }
    }
};

Admin.prototype = $.extend({}, Listing.prototype, Admin.prototype);

/**
 * Creates an instance of Domains.
 *
 * @constructor
 * @param {Object} options - instance options
 * @classdesc This class extends the Admin one by adding methods
 * specific to domains management.
 */
var Domains = function(options) {
    Admin.call(this, options);
};

Domains.prototype = {
    initialize: function(options) {
        Admin.prototype.initialize.call(this, options);
        this.options.navigation_params.push("domfilter", "srvfilter");
        this.options.eor_message = gettext("No more domain to show");
        this.register_tag_handler("dom");
    },

    /**
     * Custom callbacks declaration.
     */
    listen: function() {
        Admin.prototype.listen.call(this);
        $(document).on("click", "a.ajaxnav", $.proxy(this.page_loader, this));
    },

    /**
     * Initialize the domain links embedded within a page.
     *
     * @param {Object} data - options
     */
    init_domain_links: function(data) {
        var deloptions = (data.handle_mailboxes) ?
            {keepdir: gettext("Do not delete domain directory")} : {};
        var warnmsg = (data.auto_account_removal && data.auto_account_removal == "yes")
            ? gettext("This operation will remove ALL data associated to this domain.")
            : gettext("This operation will remove all data associated to this domain, excepting accounts.");

        $("a[name=deldomain]").confirm({
            question: function() { return this.$element.attr('title'); },
            method: "POST",
            warning: warnmsg,
            checkboxes: deloptions,
            success_cb: $.proxy(this.reload_listing, this)
        });
        $(document).trigger('domain_listing_refresh');
    },

    /**
     * Navigation callback: default.
     *
     * @param {Object} data - response of the ajax call (JSON)
     */
    list_cb: function(data) {
        Admin.prototype.list_cb.call(this, data);
        this.init_domain_links(data);
    },

    /**
     * A new page has been received, inject it.
     *
     * @param {Object} data - page content
     * @param {string} direction -
     */
    add_new_page: function(data, direction) {
        Admin.prototype.add_new_page.call(this, data, direction);
        this.init_domain_links(data);
    },

    change_inputs_state: function(value) {
        $("#id_dom_admin_username").attr("disabled", value);
        $("input[name=create_aliases]").attr("disabled", value);
    },

    create_dom_admin_changed: function(e) {
        var $target = $(e.target);
        this.change_inputs_state(($target.val() == "yes") ? false : true);
    },

    /**
     * Initialize the main form contained in the domain edition modal.
     *
     * @this Domains
     */
    generalform_init: function() {
        $('input:text:visible:first').focus();
        $("#original_aliases").dynamic_input({
            input_added: function($row) {
                $row.find("label").html("");
            },
            input_removed: function($input) {
                $input.parents(".form-group").remove();
                return true;
            }
        });
    },

    optionsform_init: function() {
        $("input[name=create_dom_admin]").click($.proxy(this.create_dom_admin_changed, this));
        this.change_inputs_state(
            $("input[name=create_dom_admin]:checked").val() == "yes" ? false : true
        );
        this.optionsform_prefill();
    },

    optionsform_prefill: function() {
        var $span = $("#id_dom_admin_username").next("span");
        $span.html("@" + $("#id_name").val());
    },

    domadminsform_init: function() {
        $("a[name=removeperm]").click(function(e) {
            var $tr = $(this).parents('tr');
            simple_ajax_request.apply(this, [e, {
                ok_cb: function(resp) {
                    $tr.remove();
                    if (!$("#domadmins").find("tr").length) {
                        $("#admins").html('
'
                            + gettext("No domain administrator defined") + "
");
                    }
                }
            }]);
        });
    },

    newdomain_cb: function() {
        this.generalform_init();
        this.optionsform_init();
        $("#wizard").cwizard({
            formid: "domform",
            transition_callbacks: {
                1: this.optionsform_prefill
            },
            error_callbacks: {
                2: $.proxy(this.optionsform_init, this)
            },
            success_callback: $.proxy(this.reload_listing, this)
        });
    },

    domainform_cb: function() {
        this.generalform_init();
        this.domadminsform_init();
        $(".submit").one('click', $.proxy(function(e) {
            simple_ajax_form_post(e, {
                formid: "domform",
                error_cb: $.proxy(this.domainform_cb, this),
                reload_on_success: false,
                success_cb: $.proxy(this.reload_listing, this)
            });
        }, this));
        $(document).trigger('domform_init');
    }
};

Domains.prototype = $.extend({}, Admin.prototype, Domains.prototype);

/**
 * Creates an instance of Identities.
 *
 * @constructor
 * @param {Object} options - instance options
 * @classdesc This class extends the Admin one by adding methods
 * specific to identities management.
 */
var Identities = function(options) {
    Admin.call(this, options);
};

Identities.prototype = {
    initialize: function(options) {
        Admin.prototype.initialize.call(this, options);
        this.options.navigation_params.push("idtfilter", "grpfilter");
        this.options.eor_message = gettext("No more identity to show");
        this.domain_list = [];
        this.register_tag_handler("idt");
        this.register_tag_handler("grp", this.grp_tag_handler);
    },

    listen: function() {
        Admin.prototype.listen.call(this);
        $(document).on("click", "a.ajaxnav", $.proxy(this.page_loader, this));
        $(document).on("click", "a.ajaxcall", $.proxy(this.send_call, this));
    },

    /**
     * Send an ajax call.
     */
    send_call: function(evt) {
        var $link = get_target(evt, "a");
        var $this = this;
        var method = $link.attr("data-call_method");

        if (method === undefined) {
            method = "GET";
        }
        evt.preventDefault();
        $.ajax({
            url: $link.attr("href"),
            type: method,
            dataType: "json"
        }).done(function(data) {
            $this.reload_listing(data.respmsg);
        });
    },

    /**
     * Initialize the links embedded within a page.
     *
     * @param {Object} data - options
     */
    init_identity_links: function(data) {
        var deloptions = {};

        if (data.handle_mailboxes == "yes") {
            deloptions = {keepdir: gettext("Do not delete mailbox directory")};
        }

        $("a[name=delaccount]").confirm({
            question: function() { return this.$element.attr('title'); },
            method: "POST",
            checkboxes: deloptions,
            success_cb: $.proxy(this.reload_listing, this)
        });
        $("a[name=delalias]").confirm({
            question: function() { return this.$element.attr('title'); },
            method: "DELETE",
            success_cb: $.proxy(this.reload_listing, this)
        });
    },

    /**
     * Add a type to let the server know what kind of object we expect.
     *
     * @this Listing
     */
    get_load_page_args: function() {
        var args = Admin.prototype.get_load_page_args.call(this);

        if (this.navobj.getbaseurl() == "list") {
            args.objtype = "identity";
            this.options.eor_message = gettext("No more identity to show");
        } else {
            args.objtype = "quota";
            this.options.eor_message = gettext("No more quota to show");
        }
        return args;
    },

    /**
     * A new page has been received, inject it.
     *
     * @param {Object} data - page content
     * @param {string} direction -
     */
    add_new_page: function(data, direction) {
        Admin.prototype.add_new_page.call(this, data, direction);
        this.init_identity_links(data);
    },

    /**
     * Navigation callback: default.
     *
     * @param {Object} data - response of the ajax call (JSON)
     */
    list_cb: function(data) {
        if ($(".sidebar li.active").length === 0) {
            var menu = this.navobj.getbaseurl();
            if (menu == "list") {
                menu = "identities";
            }
            $("a[name={0}]".format(menu)).parent().addClass("active");
        }
        $("#objects_table thead tr").html(data.headers);
        Admin.prototype.list_cb.call(this, data);
        this.init_identity_links(data);
    },

    grp_tag_handler: function(tag, $link) {
        if (this.navobj.getparam(tag + "filter") === undefined &&
            $link.hasClass(tag)) {
            var text = $link.attr("name");
            this.navobj
                .setparam("idtfilter", "account")
                .setparam(tag + "filter", text)
                .update();
            if ($("a[name=idt]").length === 0) {
                $("#taglist").append(this.make_tag("account", "idt"));
            }
            $("#taglist").append(this.make_tag(text, tag));
            return true;
        }
        return false;
    },

    /**
     * Retrieve a list of domain from the server.
     *
     * @this Identities
     * @return {Array} a list of domain names
     */
    get_domain_list: function() {
        if (!this.domain_list.length) {
            $.ajax({
                url: this.options.domain_list_url,
                dataType: "json",
                async: false
            }).done($.proxy(function(data) {
                this.domain_list = data;
            }, this));
        }
        return this.domain_list;
    },

    simpleuser_mode: function() {
        $("#id_username").autocompleter({
            from_character: "@",
            choices: $.proxy(this.get_domain_list, this)
        });
        $("#id_email").addClass("disabled")
            .attr("readonly", "")
            .autocompleter("unbind");
    },

    normal_mode: function() {
        $("#id_email").removeClass("disabled")
            .attr("readonly", null)
            .autocompleter("listen");
    },

    generalform_init: function(notrigger) {
        $("#id_role").change($.proxy(function(e) {
            var $this = $(e.target);
            var value = $this.val();

            if (value == "SimpleUsers" || value === "") {
                this.simpleuser_mode();
            } else {
                this.normal_mode();
            }
        }, this));
        if (notrigger !== undefined && notrigger) {
            return;
        }
        $("#id_role").trigger("change");
    },

    mailform_init: function() {
        $("#id_aliases").autocompleter({
            from_character: "@",
            choices: $.proxy(this.get_domain_list, this)
        });
        $("#original_aliases").dynamic_input({
            input_added: function($row) {
                $row.find("label").html("");
            },
            input_removed: function($input) {
                $input.parents(".form-group").remove();
                return true;
            }
        });
        $("#id_email").autocompleter({
            from_character: "@",
            choices: $.proxy(this.get_domain_list, this)
        });
        if ($("#id_role").length) {
            $("#id_role").trigger("change");
        } else {
            this.simpleuser_mode();
        }
        $("#id_domains").autocompleter({
            choices: $.proxy(this.get_domain_list, this)
        });
        $("#original_domains").dynamic_input({
            input_added: function($row) {
                $row.find("label").html("");
            },
            input_removed: function($input) {
                $input.parents(".form-group").remove();
                return true;
            }
        });
        activate_widget.call($("#id_quota_act"));
    },

    accountform_init: function() {
        this.generalform_init(true);
        this.mailform_init();
    },

    mailform_prefill: function() {
        var $role = $("#id_role");
        if (!$role.length || $role.val() === "" || $role.val() == "SimpleUsers") {
            $("#id_email").val($("#id_username").val());
        }
    },

    newaccount_cb: function() {
        this.accountform_init();
        $("#wizard").cwizard({
            formid: "newaccount_form",
            transition_callbacks: {
                1: this.mailform_prefill
            },
            success_callback: $.proxy(this.reload_listing, this)
        });
    },

    editaccount_cb: function() {
        this.accountform_init();
        $('.submit').on('click', $.proxy(function(e) {
            simple_ajax_form_post(e, {
                formid: "accountform",
                reload_on_success: false,
                success_cb: $.proxy(this.reload_listing, this)
            });
        }, this));
    },

    aliasform_cb: function() {
        $("#id_email").autocompleter({
            from_character: "@",
            choices: $.proxy(this.get_domain_list, this)
        });
        $("#original_recipients").dynamic_input({
            input_added: function($row) {
                $row.find("label").html("");
            },
            input_removed: function($input) {
                $input.parents(".form-group").remove();
                return true;
            }
        });
        $(".submit").on('click', $.proxy(function(e) {
            simple_ajax_form_post(e, {
                formid: "aliasform",
                reload_on_success: false,
                success_cb: $.proxy(this.reload_listing, this)
            });
        }, this));
    }

};

Identities.prototype = $.extend({}, Admin.prototype, Identities.prototype);
<|endoftext|>


<commit_before>describe('user service', function() {
  /**
   * $httpBackend is used to fake backend for Angular tests. Define placeholder
   * services here (e.g. `user`) so you can reference them later in tests.
   */
  var $httpBackend;
  var user;

  // load necessary modules; typically will only be the one you're testing
  beforeEach(module('app.services.user'));

  /**
   * have Angular inject providers into your placeholder variables
   * it intelligently removes the _'s to reference the actual provider. This
   * is done so you can refer to the original name without any naming conflicts
   */
  beforeEach(inject(function(_$httpBackend_, _user_) {
    $httpBackend = _$httpBackend_;
    user = _user_;
  }));

  // basic questions, proof of concept that things are loading correctly
  describe('user', function() {
    it('should exist', function() {
      expect(user).to.be.a('object');
    });

    it('should have certain keys', function() {
      expect(user).to.have.keys(['getUser', 'loggedIn', 'registerCb']);
    });
  });

  describe('#activate', function() {

    it('should activate with a call to api', function() {
      /**
       * you tell `$httpBackend` to listen to certain requests and respond
       * with whatever you tell it. Look into $httpBackend docs for more info
       * on options available
       */
      $httpBackend
        .expectGET('/api/user')
        .respond(200, { username: 'AndrewSouthpaw' });

      // tell backend to process the requests that have been made
      $httpBackend.flush();

      // in this case, test that method called route and stored expected info
      expect(user.getUser()).to.eql({ username: 'AndrewSouthpaw' });
    });

  });

  describe('#loggedIn', function() {

    it('should return true when signed in', function() {
      $httpBackend
        .expectGET('/api/user')
        .respond(200, { username: 'AndrewSouthpaw' });
      $httpBackend.flush();
      expect(user.loggedIn()).to.equal(true);
    });

    it('should return false when not signed in', function() {
      $httpBackend
        .expectGET('/api/user')
        .respond(200, undefined);
      $httpBackend.flush();
      expect(user.loggedIn()).to.equal(false);
    });

  });

  describe('#registerCb', function() {

    it('should take callbacks', function() {
      var cb = function() { console.log('hello'); };
      expect(user.registerCb(cb)).to.equal(true);
    });

    it('should throw error on bad input', function() {
      var cb = 'hello';
      expect(user.registerCb.bind(cb)).to.throw(/only takes functions as callbacks/);
    });

    it('should execute callbacks after user is resolved', function() {
      $httpBackend
        .expectGET('/api/user')
        .respond(200, { username: 'Andrew' });

      // tracers for cb
      var success1 = false;
      var success2 = false;

      // set callbacks
      var cb1 = function() { success1 = true; };
      var cb2 = function() { success2 = true; };
      user.registerCb(cb1);
      user.registerCb(cb2);

      // resolve user
      $httpBackend.flush();
      expect(success1).to.equal(true);
      expect(success2).to.equal(true);
    });

    it('should immediately invoke registered callbacks after resolve', function() {
      $httpBackend
        .expectGET('/api/user')
        .respond(200, { username: 'Andrew' });

      $httpBackend.flush();
      var success = false;
      var cb = function() { success = true; };
      user.registerCb(cb);
      expect(success).to.equal(true);
    });

  });

});
<commit_msg>test user.service error handling<commit_after>describe('user service', function() {
  /**
   * $httpBackend is used to fake backend for Angular tests. Define placeholder
   * services here (e.g. `user`) so you can reference them later in tests.
   */
  var $httpBackend;
  var user;

  // load necessary modules; typically will only be the one you're testing
  beforeEach(module('app.services.user'));

  /**
   * have Angular inject providers into your placeholder variables
   * it intelligently removes the _'s to reference the actual provider. This
   * is done so you can refer to the original name without any naming conflicts
   */
  beforeEach(inject(function(_$httpBackend_, _user_) {
    $httpBackend = _$httpBackend_;
    user = _user_;
  }));

  // basic questions, proof of concept that things are loading correctly
  describe('user', function() {
    it('should exist', function() {
      expect(user).to.be.a('object');
    });

    it('should have certain keys', function() {
      expect(user).to.have.keys(['getUser', 'loggedIn', 'registerCb']);
    });
  });

  describe('#activate', function() {

    it('should activate with a call to api', function() {
      /**
       * you tell `$httpBackend` to listen to certain requests and respond
       * with whatever you tell it. Look into $httpBackend docs for more info
       * on options available
       */
      $httpBackend
        .expectGET('/api/user')
        .respond(200, { username: 'AndrewSouthpaw' });

      // tell backend to process the requests that have been made
      $httpBackend.flush();

      // in this case, test that method called route and stored expected info
      expect(user.getUser()).to.eql({ username: 'AndrewSouthpaw' });
    });

    it('should handle error', function() {
      $httpBackend
        .expectGET('/api/user')
        .respond(400);

      $httpBackend.flush();
    });

  });

  describe('#loggedIn', function() {

    it('should return true when signed in', function() {
      $httpBackend
        .expectGET('/api/user')
        .respond(200, { username: 'AndrewSouthpaw' });
      $httpBackend.flush();
      expect(user.loggedIn()).to.equal(true);
    });

    it('should return false when not signed in', function() {
      $httpBackend
        .expectGET('/api/user')
        .respond(200, undefined);
      $httpBackend.flush();
      expect(user.loggedIn()).to.equal(false);
    });

  });

  describe('#registerCb', function() {

    it('should take callbacks', function() {
      var cb = function() { console.log('hello'); };
      expect(user.registerCb(cb)).to.equal(true);
    });

    it('should throw error on bad input', function() {
      var cb = 'hello';
      expect(user.registerCb.bind(cb)).to.throw(/only takes functions as callbacks/);
    });

    it('should execute callbacks after user is resolved', function() {
      $httpBackend
        .expectGET('/api/user')
        .respond(200, { username: 'Andrew' });

      // tracers for cb
      var success1 = false;
      var success2 = false;

      // set callbacks
      var cb1 = function() { success1 = true; };
      var cb2 = function() { success2 = true; };
      user.registerCb(cb1);
      user.registerCb(cb2);

      // resolve user
      $httpBackend.flush();
      expect(success1).to.equal(true);
      expect(success2).to.equal(true);
    });

    it('should immediately invoke registered callbacks after resolve', function() {
      $httpBackend
        .expectGET('/api/user')
        .respond(200, { username: 'Andrew' });

      $httpBackend.flush();
      var success = false;
      var cb = function() { success = true; };
      user.registerCb(cb);
      expect(success).to.equal(true);
    });

  });

});
<|endoftext|>


<commit_before>var logger = require('winston');
var LoginForm = require('../login_form.js');
var SignupForm = require('../signup_form.js');

module.exports = ['$http', function($http) {
  session = this;

  var configureEndpoint = function () {
    api.setClient('angular', $http, {
      headers: {
        'X-Auth-Token': localStorage.token
      }
    });
  };

  configureEndpoint();

  this.load = function () {
    configureEndpoint();
    api.get('session').success(function(data) {
      session.user = data;
      try {
        localStorage.github = data.authorizations.github.token;
      } catch (e) {
        logger.warn("no github authorization");
        localStorage.removeItem('github');
      }
      session.loggedIn = true;
      session.getBoardList();
    }).error(function () {
      session.destroy();
    });
  };

  if (localStorage.token) {
    this.load();
  }

  this.destroy = function () {
    localStorage.clear();
    session.loggedIn = false;
    session.user = null;
  };

  this.getBoardList = app.updateBoardList = function () {
    api.get('boards').success(function(data) {
      session.boards = data.boards;
    })
  };

  app.loadLastBoard = function () {
    if (localStorage.lastBoardId) {
      app.loadBoardById(localStorage.lastBoardId);
    }
  };

  if (session.loggedIn) {
    app.loadLastBoard();
  } else {
    session.loginForm = new LoginForm(this);
    session.signupForm = new SignupForm(this);
  }
}];
<commit_msg>fix loadLastBoard<commit_after>var logger = require('winston');
var LoginForm = require('../login_form.js');
var SignupForm = require('../signup_form.js');

module.exports = ['$http', function($http) {
  session = this;
  session.loginForm = new LoginForm(this);
  session.signupForm = new SignupForm(this);

  var configureEndpoint = function () {
    api.setClient('angular', $http, {
      headers: {
        'X-Auth-Token': localStorage.token
      }
    });
  };

  configureEndpoint();

  this.load = function () {
    configureEndpoint();
    api.get('session').success(function(data) {
      session.user = data;
      try {
        localStorage.github = data.authorizations.github.token;
      } catch (e) {
        logger.warn("no github authorization");
        localStorage.removeItem('github');
      }
      session.loggedIn = true;
      session.getBoardList();
      app.loadLastBoard();
    }).error(function () {
      session.destroy();
    });
  };

  if (localStorage.token) {
    this.load();
  }

  this.destroy = function () {
    localStorage.clear();
    session.loggedIn = false;
    session.user = null;
  };

  this.getBoardList = app.updateBoardList = function () {
    api.get('boards').success(function(data) {
      session.boards = data.boards;
    })
  };

  app.loadLastBoard = function () {
    if (localStorage.lastBoardId) {
      app.loadBoardById(localStorage.lastBoardId);
    }
  };
}];
<|endoftext|>


<commit_before>'use strict';
var _ = require('underscore');

// Function for parsing ClinVar data for variant object creation
// Derived from:
// https://github.com/standard-analytics/pubmed-schema-org/blob/master/lib/pubmed.js
module.exports.parseClinvar = parseClinvar;
function parseClinvar(xml){
    var variant = {};
    var doc = new DOMParser().parseFromString(xml, 'text/xml');

    var $ClinVarResult = doc.getElementsByTagName('ClinVarResult-Set')[0];
    if ($ClinVarResult) {
        var $VariationReport = $ClinVarResult.getElementsByTagName('VariationReport')[0];
        if ($VariationReport) {
            // Get the ID (just in case) and Preferred Title
            variant.clinvarVariantId = $VariationReport.getAttribute('VariationID');
            variant.clinvarVariantTitle = $VariationReport.getAttribute('VariationName');
            var $Allele = $VariationReport.getElementsByTagName('Allele')[0];
            if ($Allele) {
                var $HGVSlist_raw = $Allele.getElementsByTagName('HGVSlist')[0];
                if ($HGVSlist_raw) {
                    variant.hgvsNames = {};
                    variant.hgvsNames.others = [];
                    // get the HGVS entries
                    var $HGVSlist = $HGVSlist_raw.getElementsByTagName('HGVS');
                    _.map($HGVSlist, $HGVS => {
                        let temp_hgvs = $HGVS.textContent;
                        let assembly = $HGVS.getAttribute('Assembly');
                        if (assembly) {
                            variant.hgvsNames[assembly] = temp_hgvs;
                        } else {
                            variant.hgvsNames.others.push(temp_hgvs);
                        }
                    });
                }
                variant.dbSNPIds = [];
                var $XRefList = $Allele.getElementsByTagName('XRefList')[0];
                var $XRef = $XRefList.getElementsByTagName('XRef');
                for(var i = 0; i < $XRef.length; i++) {
                    if ($XRef[i].getAttribute('DB') === 'dbSNP') {
                        variant.dbSNPIds.push($XRef[i].getAttribute('ID'));
                    }
                }
            }
        }
    }
    return variant;
}

// Function for parsing CAR data for variant object creation
module.exports.parseCAR = parseCAR;
function parseCAR(json) {
    var data = {};
    // set carId in payload, since we'll always have this from a CAR response
    data.carId = json['@id'].substring(json['@id'].indexOf('CA'));
    if (json.externalRecords) {
        // extract ClinVar data if available
        if (json.externalRecords.ClinVar && json.externalRecords.ClinVar.length > 0) {
            // we only need to look at the first entry since the variantionID and preferred name
            // should be the same for all of them
            data.clinvarVariantId = json.externalRecords.ClinVar[0].variationId;
            data.clinvarVariantTitle = json.externalRecords.ClinVar[0].preferredName;
        }
        // extract dbSNPId data if available
        if (json.externalRecords.dbSNP && json.externalRecords.dbSNP.length > 0) {
            data.dbSNPIds = [];
            json.externalRecords.dbSNP.map(function(dbSNPentry, i) {
                data.dbSNPIds.push(dbSNPentry.rs);
            });
        }
    }
    var temp_nc_hgvs = {};
    var temp_other_hgvs = [];
    if (json.genomicAlleles && json.genomicAlleles.length > 0) {
        json.genomicAlleles.map(function(genomicAllele, i) {
            if (genomicAllele.hgvs && genomicAllele.hgvs.length > 0) {
                // extract the genomicAlleles hgvs terms
                genomicAllele.hgvs.map(function(hgvs_temp, j) {
                    // skip the hgvs term if it starts with 'CM'
                    if (!hgvs_temp.startsWith('CM')) {
                        // FIXME/TODO: cannot easily get reference genome for NCs from CAR.
                        // Dump everything as 'other' hgvs term for now...
                        /*
                        if (hgvs_temp.startsWith('NC')) {
                            // special handling for 'NC' hgvs terms
                            temp_nc_hgvs[genomicAllele.referenceSequence] = hgvs_temp;
                        } else {
                            temp_other_hgvs.push(hgvs_temp);
                        }*/
                        temp_other_hgvs.push(hgvs_temp);
                    }
                });
            }
        });
    }
    // extract the aminoAcidAlleles hgvs terms
    if (json.aminoAcidAlleles && json.aminoAcidAlleles.length > 0) {
        json.aminoAcidAlleles.map(function(allele, i) {
            if (allele.hgvs && allele.hgvs.length > 0) {
                allele.hgvs.map(function(hgvs_temp, j) {
                    temp_other_hgvs.push(hgvs_temp);
                });
            }
        });
    }
    // extract the transcriptAlleles hgvs terms
    if (json.transcriptAlleles && json.transcriptAlleles.length > 0) {
        json.transcriptAlleles.map(function(allele, i) {
            if (allele.hgvs && allele.hgvs.length > 0) {
                allele.hgvs.map(function(hgvs_temp, j) {
                    temp_other_hgvs.push(hgvs_temp);
                });
            }
        });
    }

    // this bit will have to change once we actually get assembly info from the CAR
    // so that the proper key:value pairs are created for hgvs terms
    var temp_hgvs = {};
    if (temp_other_hgvs.length > 0) {
        temp_hgvs.others = temp_other_hgvs;
    }
    if (temp_hgvs != {}) {
        data.hgvsNames = temp_hgvs;
    }

    return data;
}
<commit_msg>add workaround for CAR NC assembly<commit_after>'use strict';
var _ = require('underscore');

// Function for parsing ClinVar data for variant object creation
// Derived from:
// https://github.com/standard-analytics/pubmed-schema-org/blob/master/lib/pubmed.js
module.exports.parseClinvar = parseClinvar;
function parseClinvar(xml){
    var variant = {};
    var doc = new DOMParser().parseFromString(xml, 'text/xml');

    var $ClinVarResult = doc.getElementsByTagName('ClinVarResult-Set')[0];
    if ($ClinVarResult) {
        var $VariationReport = $ClinVarResult.getElementsByTagName('VariationReport')[0];
        if ($VariationReport) {
            // Get the ID (just in case) and Preferred Title
            variant.clinvarVariantId = $VariationReport.getAttribute('VariationID');
            variant.clinvarVariantTitle = $VariationReport.getAttribute('VariationName');
            var $Allele = $VariationReport.getElementsByTagName('Allele')[0];
            if ($Allele) {
                var $HGVSlist_raw = $Allele.getElementsByTagName('HGVSlist')[0];
                if ($HGVSlist_raw) {
                    variant.hgvsNames = {};
                    variant.hgvsNames.others = [];
                    // get the HGVS entries
                    var $HGVSlist = $HGVSlist_raw.getElementsByTagName('HGVS');
                    _.map($HGVSlist, $HGVS => {
                        let temp_hgvs = $HGVS.textContent;
                        let assembly = $HGVS.getAttribute('Assembly');
                        if (assembly) {
                            variant.hgvsNames[assembly] = temp_hgvs;
                        } else {
                            variant.hgvsNames.others.push(temp_hgvs);
                        }
                    });
                }
                variant.dbSNPIds = [];
                var $XRefList = $Allele.getElementsByTagName('XRefList')[0];
                var $XRef = $XRefList.getElementsByTagName('XRef');
                for(var i = 0; i < $XRef.length; i++) {
                    if ($XRef[i].getAttribute('DB') === 'dbSNP') {
                        variant.dbSNPIds.push($XRef[i].getAttribute('ID'));
                    }
                }
            }
        }
    }
    return variant;
}

// Function for parsing CAR data for variant object creation
module.exports.parseCAR = parseCAR;
function parseCAR(json) {
    var data = {};
    // set carId in payload, since we'll always have this from a CAR response
    data.carId = json['@id'].substring(json['@id'].indexOf('CA'));
    if (json.externalRecords) {
        // extract ClinVar data if available
        if (json.externalRecords.ClinVar && json.externalRecords.ClinVar.length > 0) {
            // we only need to look at the first entry since the variantionID and preferred name
            // should be the same for all of them
            data.clinvarVariantId = json.externalRecords.ClinVar[0].variationId;
            data.clinvarVariantTitle = json.externalRecords.ClinVar[0].preferredName;
        }
        // extract dbSNPId data if available
        if (json.externalRecords.dbSNP && json.externalRecords.dbSNP.length > 0) {
            data.dbSNPIds = [];
            json.externalRecords.dbSNP.map(function(dbSNPentry, i) {
                data.dbSNPIds.push(dbSNPentry.rs);
            });
        }
    }
    data.hgvsNames = {};
    if (json.genomicAlleles && json.genomicAlleles.length > 0) {
        json.genomicAlleles.map(function(genomicAllele, i) {
            if (genomicAllele.hgvs && genomicAllele.hgvs.length > 0) {
                // extract the genomicAlleles hgvs terms
                genomicAllele.hgvs.map(function(hgvs_temp, j) {
                    // skip the hgvs term if it starts with 'CM'
                    if (!hgvs_temp.startsWith('CM')) {
                        // FIXME/TODO: cannot easily get reference genome for NCs from CAR.
                        // Base it off the RS###### for now...
                        if (hgvs_temp.startsWith('NC')) {
                            if (genomicAllele.referenceSequence.endsWith('RS000065')) {
                                data.hgvsNames.GRCh38 = hgvs_temp;
                            } else if (genomicAllele.referenceSequence.endsWith('RS000041')) {
                                data.hgvsNames.GRCh37 = hgvs_temp;
                            } else {
                                if (!data.hgvsNames.others) {
                                    data.hgvsNames.others = [];
                                }
                                data.hgvsNames.others.push(hgvs_temp);
                            }
                        } else {
                            if (!data.hgvsNames.others) {
                                data.hgvsNames.others = [];
                            }
                            data.hgvsNames.others.push(hgvs_temp);
                        }
                    }
                });
            }
        });
    }
    // TODO: these should really be cleaned up so it's not using the same code over and over again
    // extract the aminoAcidAlleles hgvs terms
    if (json.aminoAcidAlleles && json.aminoAcidAlleles.length > 0) {
        json.aminoAcidAlleles.map(function(allele, i) {
            if (allele.hgvs && allele.hgvs.length > 0) {
                allele.hgvs.map(function(hgvs_temp, j) {
                    if (!data.hgvsNames.others) {
                        data.hgvsNames.others = [];
                    }
                    data.hgvsNames.others.push(hgvs_temp);
                });
            }
        });
    }
    // extract the transcriptAlleles hgvs terms
    if (json.transcriptAlleles && json.transcriptAlleles.length > 0) {
        json.transcriptAlleles.map(function(allele, i) {
            if (allele.hgvs && allele.hgvs.length > 0) {
                allele.hgvs.map(function(hgvs_temp, j) {
                    if (!data.hgvsNames.others) {
                        data.hgvsNames.others = [];
                    }
                    data.hgvsNames.others.push(hgvs_temp);
                });
            }
        });
    }

    return data;
}
<|endoftext|>