<commit_before>$(function () {
    $('.button-checkbox').each(function () {

        // Settings
        var $widget = $(this),
            $button = $widget.find('button'),
            $checkbox = $widget.find('input:checkbox'),
            color = $button.data('color'),
            settings = {
                on: {
                    icon: 'glyphicon glyphicon-check'
                },
                off: {
                    icon: 'glyphicon glyphicon-unchecked'
                }
            };

        // Event Handlers
        $button.on('click', function () {
            $checkbox.prop('checked', !$checkbox.is(':checked'));
            $checkbox.triggerHandler('change');
            updateDisplay();
        });
        $checkbox.on('change', function () {
            updateDisplay();
        });

        // Actions
        function updateDisplay() {
            var isChecked = $checkbox.is(':checked');

            // Set the button's state
            $button.data('state', (isChecked) ? "on" : "off");

            // Set the button's icon
            $button.find('.state-icon')
                .removeClass()
                .addClass('state-icon ' + settings[$button.data('state')].icon);

            // Update the button's color
            if (isChecked) {
                $button
                    .removeClass('btn-default')
                    .addClass('btn-' + color + ' active');
            }
            else {
                $button
                    .removeClass('btn-' + color + ' active')
                    .addClass('btn-default');
            }
        }

        // Initialization
        function init() {

            updateDisplay();

            // Inject the icon if applicable
            if ($button.find('.state-icon').length == 0) {
                $button.prepend(' ');
            }
        }
        init();
    });
});

$(function () {
    $('.list-group.checked-list-box .list-group-item').each(function () {

        // Settings
        var $widget = $(this),
            $checkbox = $('<input type="checkbox" class="hidden" />'),
            color = ($widget.data('color') ? $widget.data('color') : "primary"),
            style = ($widget.data('style') == "button" ? "btn-" : "list-group-item-"),
            settings = {
                on: {
                    icon: 'glyphicon glyphicon-check'
                },
                off: {
                    icon: 'glyphicon glyphicon-unchecked'
                }
            };

        $widget.css('cursor', 'pointer')
        $widget.append($checkbox);

        // Event Handlers
        $widget.on('click', function () {
            $checkbox.prop('checked', !$checkbox.is(':checked'));
            $checkbox.triggerHandler('change');
            updateDisplay();
        });
        $checkbox.on('change', function () {
            updateDisplay();
        });

        // Actions
        function updateDisplay() {
            var isChecked = $checkbox.is(':checked');

            // Set the button's state
            $widget.data('state', (isChecked) ? "on" : "off");

            // Set the button's icon
            $widget.find('.state-icon')
                .removeClass()
                .addClass('state-icon ' + settings[$widget.data('state')].icon);

            // Update the button's color
            if (isChecked) {
                $widget.addClass(style + color + ' active');
            } else {
                $widget.removeClass(style + color + ' active');
            }
        }

        // Initialization
        function init() {

            if ($widget.data('checked') == true) {
                $checkbox.prop('checked', !$checkbox.is(':checked'));
            }

            updateDisplay();

            // Inject the icon if applicable
            if ($widget.find('.state-icon').length == 0) {
                $widget.prepend(' ');
            }
        }
        init();
    });
});

$(document).ready(function() {
    $('#coypright #author-name').each(function () {
        if ($(this).text() != 'Florian Gareis') {
            $(this).css('color', 'red');
        }
    });

    $('.btn').tooltip({container: 'body'});

    $('#group_colour_component').on('changeColor', function (ev) {
        $('input[name=group_colour]').val(ev.color.toHex().replace('#', ''));
    });

    $("select").addClass("selectpicker");
    $(".selectpicker").attr({"data-width": "auto"});
    $(".selectpicker").selectpicker();

    $('.top, .to-top, .top2').click(function(event){
        event.preventDefault();
        $('html,body').animate({scrollTop:$(this.hash).offset().top}, 800);
    });

    $('#site-logo img').attr('class','img-responsive center-block');

    $('.progress .progress-bar').progressbar({
        percent_format: function(percent) { return percent; }
    });

    $('.pagination-line a:not(.btn)').attr('class','btn btn-default btn-xs');
    $('.topic-pagination a:not(.btn), .forum-pagination a:not(.btn)').attr('class','btn btn-default btn-sm');
    if (!($('.topic-pagination a, .forum-pagination a').hasClass('no-btn'))){
        $('.topic-pagination strong, .forum-pagination strong').attr('class','btn btn-primary btn-sm disabled');
    };
    $('.page-sep').remove();

    $('.pm-to a:not(.btn)').attr('class','btn btn-default btn-sm');

    $('.btn-fix a').attr('class','btn btn-primary btn-sm');

    $('.btn-radio-group .btn-radio').click(function() {
        $(this).parents('.btn-radio-group').find('.btn-radio.active').removeClass('active');
        $(this).addClass('active');
        return true;
    });

    $('.btn-radio-group .btn-radio input:checked').each(function() {
        $(this).parents('.btn-radio-group').find('.btn-radio.active').removeClass('active');
        $(this).parent().addClass('active');
    });

    $(window).scroll(function () {
        if ($(this).scrollTop() > 100) {
            $('#back-to-top').fadeIn();
        } else {
            $('#back-to-top').fadeOut();
        }
    });
    // scroll body to 0px on click
    $('#back-to-top').click(function () {
        $('#back-to-top').tooltip('hide');
        $('body,html').animate({
            scrollTop: 0
        }, 800);
        return false;
    });
    $('#back-to-top').hover(function () {
        $('#back-to-top').tooltip('show');
    });

    var $this = $('.content img');
    var src = $this.attr('src');
    $this.attr('data-lightbox', src);

    if ($('#footer-nav .nav.fix-right-nav').length = 0){
        $('#footer-nav ul.navbar-nav').after('

Design: ComBoot by Florian Gareis

');
    }

    var dangercolor = $('.alert-danger').css('color');
    $('#alert-area').css('border-color', dangercolor);

    $('.colour-picker').colorpicker({
        format: 'hex'
    });
});

$(document).on('click', '.panel-heading span.clickable', function(e){
    var $this = $(this);
    if(!$this.hasClass('panel-collapsed')) {
        $this.parents('.panel-collapsible').find('.panel-body, .panel-footer').slideUp();
        $this.addClass('panel-collapsed');
        $this.find('i').removeClass('fa-chevron-up').addClass('fa-chevron-down');
    } else {
        $this.parents('.panel-collapsible').find('.panel-body, .panel-footer').slideDown();
        $this.removeClass('panel-collapsed');
        $this.find('i').removeClass('fa-chevron-down').addClass('fa-chevron-up');
    }
});
function isImageFile(fname) {
    return fname.match(/\.(jpg|gif|bmp|jpeg|png)$/);
}<commit_msg>Little jQuery fix<commit_after>$(function () {
    $('.button-checkbox').each(function () {

        // Settings
        var $widget = $(this),
            $button = $widget.find('button'),
            $checkbox = $widget.find('input:checkbox'),
            color = $button.data('color'),
            settings = {
                on: {
                    icon: 'glyphicon glyphicon-check'
                },
                off: {
                    icon: 'glyphicon glyphicon-unchecked'
                }
            };

        // Event Handlers
        $button.on('click', function () {
            $checkbox.prop('checked', !$checkbox.is(':checked'));
            $checkbox.triggerHandler('change');
            updateDisplay();
        });
        $checkbox.on('change', function () {
            updateDisplay();
        });

        // Actions
        function updateDisplay() {
            var isChecked = $checkbox.is(':checked');

            // Set the button's state
            $button.data('state', (isChecked) ? "on" : "off");

            // Set the button's icon
            $button.find('.state-icon')
                .removeClass()
                .addClass('state-icon ' + settings[$button.data('state')].icon);

            // Update the button's color
            if (isChecked) {
                $button
                    .removeClass('btn-default')
                    .addClass('btn-' + color + ' active');
            }
            else {
                $button
                    .removeClass('btn-' + color + ' active')
                    .addClass('btn-default');
            }
        }

        // Initialization
        function init() {

            updateDisplay();

            // Inject the icon if applicable
            if ($button.find('.state-icon').length == 0) {
                $button.prepend(' ');
            }
        }
        init();
    });
});

$(function () {
    $('.list-group.checked-list-box .list-group-item').each(function () {

        // Settings
        var $widget = $(this),
            $checkbox = $('<input type="checkbox" class="hidden" />'),
            color = ($widget.data('color') ? $widget.data('color') : "primary"),
            style = ($widget.data('style') == "button" ? "btn-" : "list-group-item-"),
            settings = {
                on: {
                    icon: 'glyphicon glyphicon-check'
                },
                off: {
                    icon: 'glyphicon glyphicon-unchecked'
                }
            };

        $widget.css('cursor', 'pointer')
        $widget.append($checkbox);

        // Event Handlers
        $widget.on('click', function () {
            $checkbox.prop('checked', !$checkbox.is(':checked'));
            $checkbox.triggerHandler('change');
            updateDisplay();
        });
        $checkbox.on('change', function () {
            updateDisplay();
        });

        // Actions
        function updateDisplay() {
            var isChecked = $checkbox.is(':checked');

            // Set the button's state
            $widget.data('state', (isChecked) ? "on" : "off");

            // Set the button's icon
            $widget.find('.state-icon')
                .removeClass()
                .addClass('state-icon ' + settings[$widget.data('state')].icon);

            // Update the button's color
            if (isChecked) {
                $widget.addClass(style + color + ' active');
            } else {
                $widget.removeClass(style + color + ' active');
            }
        }

        // Initialization
        function init() {

            if ($widget.data('checked') == true) {
                $checkbox.prop('checked', !$checkbox.is(':checked'));
            }

            updateDisplay();

            // Inject the icon if applicable
            if ($widget.find('.state-icon').length == 0) {
                $widget.prepend(' ');
            }
        }
        init();
    });
});

$(document).ready(function() {
    $('#coypright #author-name').each(function () {
        if ($(this).text() != 'Florian Gareis') {
            $(this).css('color', 'red');
        }
    });

    $('.btn').tooltip({container: 'body'});

    $('#group_colour_component').on('changeColor', function (ev) {
        $('input[name=group_colour]').val(ev.color.toHex().replace('#', ''));
    });

    $("select").addClass("selectpicker");
    $(".selectpicker").attr({"data-width": "auto"});
    $(".selectpicker").selectpicker();

    $('.top, .to-top, .top2').click(function(event){
        event.preventDefault();
        $('html,body').animate({scrollTop:$(this.hash).offset().top}, 800);
    });

    $('#site-logo img').attr('class','img-responsive center-block');

    $('.progress .progress-bar').progressbar({
        percent_format: function(percent) { return percent; }
    });

    $('.pagination-line a:not(.btn)').attr('class','btn btn-default btn-xs');
    $('.topic-pagination a:not(.btn), .forum-pagination a:not(.btn)').attr('class','btn btn-default btn-sm');
    if (!($('.topic-pagination a, .forum-pagination a').hasClass('no-btn'))){
        $('.topic-pagination strong, .forum-pagination strong').attr('class','btn btn-primary btn-sm disabled');
    };
    $('.page-sep').remove();

    $('.pm-to a:not(.btn)').attr('class','btn btn-default btn-sm');

    $('.btn-fix a').addClass('btn btn-primary btn-sm');

    $('.btn-radio-group .btn-radio').click(function() {
        $(this).parents('.btn-radio-group').find('.btn-radio.active').removeClass('active');
        $(this).addClass('active');
        return true;
    });

    $('.btn-radio-group .btn-radio input:checked').each(function() {
        $(this).parents('.btn-radio-group').find('.btn-radio.active').removeClass('active');
        $(this).parent().addClass('active');
    });

    $(window).scroll(function () {
        if ($(this).scrollTop() > 100) {
            $('#back-to-top').fadeIn();
        } else {
            $('#back-to-top').fadeOut();
        }
    });
    // scroll body to 0px on click
    $('#back-to-top').click(function () {
        $('#back-to-top').tooltip('hide');
        $('body,html').animate({
            scrollTop: 0
        }, 800);
        return false;
    });
    $('#back-to-top').hover(function () {
        $('#back-to-top').tooltip('show');
    });

    var $this = $('.content img');
    var src = $this.attr('src');
    $this.attr('data-lightbox', src);

    if ($('#footer-nav .nav.fix-right-nav').length = 0){
        $('#footer-nav ul.navbar-nav').after('

Design: ComBoot by Florian Gareis

');
    }

    var dangercolor = $('.alert-danger').css('color');
    $('#alert-area').css('border-color', dangercolor);

    $('.colour-picker').colorpicker({
        format: 'hex'
    });
});

$(document).on('click', '.panel-heading span.clickable', function(e){
    var $this = $(this);
    if(!$this.hasClass('panel-collapsed')) {
        $this.parents('.panel-collapsible').find('.panel-body, .panel-footer').slideUp();
        $this.addClass('panel-collapsed');
        $this.find('i').removeClass('fa-chevron-up').addClass('fa-chevron-down');
    } else {
        $this.parents('.panel-collapsible').find('.panel-body, .panel-footer').slideDown();
        $this.removeClass('panel-collapsed');
        $this.find('i').removeClass('fa-chevron-down').addClass('fa-chevron-up');
    }
});
function isImageFile(fname) {
    return fname.match(/\.(jpg|gif|bmp|jpeg|png)$/);
}<|endoftext|>


<commit_before>define( ['dojo/_base/array',
         'JBrowse/Util',
         './Util',
         'JBrowse/Model/SimpleFeature'
        ],
        function( array, Util, BAMUtil, SimpleFeature ) {

var SEQRET_DECODER = ['=', 'A', 'C', 'x', 'G', 'x', 'x', 'x', 'T', 'x', 'x', 'x', 'x', 'x', 'x', 'N'];
var CIGAR_DECODER  = ['M', 'I', 'D', 'N', 'S', 'H', 'P', '=', 'X', '?', '?', '?', '?', '?', '?', '?'];

var readInt   = BAMUtil.readInt;
var readShort = BAMUtil.readShort;
var readFloat = BAMUtil.readFloat;

var Feature = Util.fastDeclare(
{
    constructor: function( args ) {
        this.store = args.store;
        this.file  = args.file;
        this.data  = {
            type: 'match',
            source: args.store.source
        };
        this.bytes = {
            start: args.bytes.start,
            end: args.bytes.end,
            byteArray: args.bytes.byteArray
        };

        this._coreParse();
    },

    get: function( field) {
        return this._get( field.toLowerCase() );
    },

    // same as get(), except requires lower-case arguments.  used
    // internally to save lots of calls to field.toLowerCase()
    _get: function( field ) {
        return field in this.data ? this.data[field] : // have we already parsed it out?
            function() {
                var v = this.data[field] =
                    this[field]            ? this[field]()            : // maybe we have a special parser for it
                    this._flagMasks[field] ? this._parseFlag( field ) : // or is it a flag?
                                             this._parseTag( field );   // otherwise, look for it in the tags
                return v;
            }.call(this);
    },

    tags: function() {
        return this._get('_tags');
    },

    _tags: function() {
        this._parseAllTags();

        var tags = [ 'seq', 'seq_reverse_complemented', 'unmapped' ];
        if( ! this._get('unmapped') )
            tags.push( 'start', 'end', 'strand', 'score', 'qual', 'MQ', 'CIGAR', 'length_on_ref' );
        if( this._get('multi_segment_template') ) {
            tags.push( 'multi_segment_all_aligned',
                       'multi_segment_next_segment_unmapped',
                       'multi_segment_next_segment_reversed',
                       'multi_segment_first',
                       'multi_segment_last',
                       'secondary_alignment',
                       'qc_failed',
                       'duplicate',
                       'next_segment_position'
                     );
        }
        tags = tags.concat( this._tagList || [] );

        var d = this.data;
        for( var k in d ) {
            if( d.hasOwnProperty( k ) && k[0] != '_' )
                tags.push( k );
        }

        var seen = {};
        tags = array.filter( tags, function(t) {
            if( t in this.data && this.data[t] === undefined )
                return false;

            var lt = t.toLowerCase();
            var s = seen[lt];
            seen[lt] = true;
            return ! s;
        },this);

        return tags;
    },

    parent: function() {
        return undefined;
    },

    children: function() {
        return this._get('subfeatures');
    },

    id: function() {
        return this._get('name')+'/'+this._get('md')+'/'+this._get('cigar')+'/'+this._get('start');
    },

    // special parsers
    /**
     * Mapping quality score.
     */
    mq: function() {
        var mq = (this._get('_bin_mq_nl') & 0xff00) >> 8;
        return mq == 255 ? undefined : mq;
    },
    score: function() {
        return this._get('mq');
    },
    qual: function() {
        if( this._get('unmapped') )
            return undefined;

        var qseq = [];
        var byteArray = this.bytes.byteArray;
        var p = this.bytes.start + 36 + this._get('_l_read_name') + this._get('_n_cigar_op')*4 + this._get('_seq_bytes');
        var lseq = this._get('seq_length');
        for (var j = 0; j < lseq; ++j) {
            qseq.push( byteArray[p + j] );
        }
        return qseq.join(' ');
    },
    strand: function() {
        var xs = this._get('xs');
        return xs ? ( xs == '-' ? -1 : 1 ) :
               this._get('seq_reverse_complemented') ? -1 :  1;
    },
    /**
     * Length in characters of the read name.
     */
    _l_read_name: function() {
        return this._get('_bin_mq_nl') & 0xff;
    },
    /**
     * number of bytes in the sequence field
     */
    _seq_bytes: function() {
        return (this._get('seq_length') + 1) >> 1;
    },
    seq: function() {
        var seq = '';
        var byteArray = this.bytes.byteArray;
        var p = this.bytes.start + 36 + this._get('_l_read_name') + this._get('_n_cigar_op')*4;
        var seqBytes = this._get('_seq_bytes');
        for (var j = 0; j < seqBytes; ++j) {
            var sb = byteArray[p + j];
            seq += SEQRET_DECODER[(sb & 0xf0) >> 4];
            seq += SEQRET_DECODER[(sb & 0x0f)];
        }
        return seq;
    },
    name: function() {
        return this._get('_read_name');
    },
    _read_name: function() {
        var byteArray = this.bytes.byteArray;
        var readName = '';
        var nl = this._get('_l_read_name');
        var p = this.bytes.start + 36;
        for (var j = 0; j < nl-1; ++j) {
            readName += String.fromCharCode(byteArray[p+j]);
        }
        return readName;
    },
    _n_cigar_op: function() {
        return this._get('_flag_nc') & 0xffff;
    },
    cigar: function() {
        if( this._get('unmapped') )
            return undefined;

        var byteArray   = this.bytes.byteArray;
        var numCigarOps = this._get('_n_cigar_op');
        var p = this.bytes.start + 36 + this._get('_l_read_name');
        var cigar = '';
        var lref = 0;
        for (var c = 0; c < numCigarOps; ++c) {
            var cigop = readInt(byteArray, p);
            var lop = cigop >> 4;
            var op = CIGAR_DECODER[cigop & 0xf];
            cigar = cigar + lop + op;
            lref += lop;
            p += 4;
        }
        this.data.length_on_ref = lref;
        return cigar;
    },
    next_segment_position: function() {
        var nextRefID = this._get('_next_refid');
        var nextSegment = this.file.indexToChr[nextRefID];
        if( nextSegment )
            return nextSegment.name+':'+this._get('_next_pos');
        else
            return undefined;
    },
    subfeatures: function() {
        if( ! this.store.createSubfeatures )
            return undefined;

        var cigar = this._get('cigar');
        if( cigar )
            return this._cigarToSubfeats( cigar );

        return undefined;
    },
    length_on_ref: function() {
        var c = this._get('cigar'); // the length_on_ref is set as a
                                   // side effect of the CIGAR parsing
        return this.data.length_on_ref;
    },
    _flags: function() {
        return (this.data._flag_nc & 0xffff0000) >> 16;
    },
    end: function() {
        return this._get('start') + ( this._get('length_on_ref') || this._get('seq_length') || undefined );
    },

    seq_id: function() {
        if( this._get('unmapped') )
            return undefined;

        return ( this.file.indexToChr[ this._refID ] || {} ).name;
    },

    /**
     * parse the core data: start, end, strand, etc
     */
    _coreParse: function() {
        var byteArray = this.bytes.byteArray;
        var dataStart = this.bytes.start+4;

        var tempBytes = new Uint8Array( 32 );
        for( var i = 0; i<32; i++ ) {
            tempBytes[i] = byteArray[i+dataStart];
        }
        var ints = new Int32Array( tempBytes.buffer );

        var d = this.data;
        this._refID        = ints[0];
        d.start            = ints[1];
        d._bin_mq_nl       = ints[2];
        d._flag_nc         = ints[3];
        d.seq_length       = ints[4];
        d._next_refid      = ints[5];
        d._next_pos        = ints[6];
        d.template_length  = ints[7];
    },

    /**
     * Get the value of a tag, parsing the tags as far as necessary.
     * Only called if we have not already parsed that field.
     */
    _parseTag: function( tagName ) {
        // if all of the tags have been parsed and we're still being
        // called, we already know that we have no such tag, because
        // it would already have been cached.
        if( this._allTagsParsed )
            return undefined;

        this._tagList = this._tagList || [];
        var byteArray = this.bytes.byteArray;
        var p = this._tagOffset || this.bytes.start + 36 + this._get('_l_read_name') + this._get('_n_cigar_op')*4 + this._get('_seq_bytes') + this._get('seq_length');

        var blockEnd = this.bytes.end;
        while( p < blockEnd && lcTag != tagName ) {
            var tag      = String.fromCharCode( byteArray[p], byteArray[ p+1 ] );
            var lcTag    = tag.toLowerCase();
            var type = String.fromCharCode( byteArray[ p+2 ] );
            p += 3;

            var value;
            switch( type.toLowerCase() ) {
            case 'a':
                value = String.fromCharCode( byteArray[p] );
                p += 1;
                break;
            case 'i':
                value = readInt(byteArray, p );
                p += 4;
                break;
            case 'c':
                value = byteArray[p];
                p += 1;
                break;
            case 's':
                value = readShort(byteArray, p);
                p += 2;
                break;
            case 'f':
                value = readFloat( byteArray, p );
                p += 4;
                break;
            case 'z':
            case 'h':
                value = '';
                while( p <= blockEnd ) {
                    var cc = byteArray[p++];
                    if( cc == 0 ) {
                        break;
                    }
                    else {
                        value += String.fromCharCode(cc);
                    }
                }
                break;
            default:
                console.warn( "Unknown BAM tag type '"+type
                              +"', tags may be incomplete"
                            );
                value = undefined;
                p = blockEnd; // stop parsing tags
            }

            this._tagOffset = p;

            this._tagList.push( tag );
            if( lcTag == tagName )
                return value;
            else {
                this.data[ lcTag ] = value;
            }
        }
        this._allTagsParsed = true;
        return undefined;
    },
    _parseAllTags: function() {
        this._parseTag(); // calling _parseTag with no arg just parses
        // all the tags and returns the last one
    },

    _flagMasks: {
        multi_segment_template:              0x1,
        multi_segment_all_aligned:           0x2,
        unmapped:                            0x4,
        multi_segment_next_segment_unmapped: 0x8,
        seq_reverse_complemented:            0x10,
        multi_segment_next_segment_reversed: 0x20,
        multi_segment_first:                 0x40,
        multi_segment_last:                  0x80,
        secondary_alignment:                 0x100,
        qc_failed:                           0x200,
        duplicate:                           0x400
    },

    _parseFlag: function( flagName ) {
        return !!( this._get('_flags') & this._flagMasks[flagName] );
    },

    _parseCigar: function( cigar ) {
        return array.map( cigar.match(/\d+\D/g), function( op ) {
           return [ op.match(/\D/)[0].toUpperCase(), parseInt( op ) ];
        });
    },

    /**
     *  take a cigar string, and initial position, return an array of subfeatures
     */
    _cigarToSubfeats: function(cigar)    {
        var subfeats = [];
        var min = this._get('start');
        var max;
        var ops = this._parseCigar( cigar );
        for (var i = 0; i < ops.length; i++)  {
            var lop = ops[i][1];
            var op = ops[i][0];  // operation type
            // converting "=" to "E" to avoid possible problems later with non-alphanumeric type name
            if (op === "=")  { op = "E"; }

            switch (op) {
            case 'M':
            case 'D':
            case 'N':
            case 'E':
            case 'X':
                max = min + lop;
                break;
            case 'I':
                max = min;
                break;
            case 'P':  // not showing padding deletions (possibly change this later -- could treat same as 'I' ?? )
            case 'H':  // not showing hard clipping (since it's unaligned, and offset arg meant to be beginning of aligned part)
            case 'S':  // not showing soft clipping (since it's unaligned, and offset arg meant to be beginning of aligned part)
                break;
                // other possible cases
            }
            if( op !== 'N' ) {
                var subfeat = new SimpleFeature({
                    data: {
                    type: op,
                        start: min,
                        end: max,
                        strand: this._get('strand'),
                        cigar_op: lop+op
                    },
                    parent: this
                });
                subfeats.push(subfeat);
            }
            min = max;
        }
        return subfeats;
    }

});

return Feature;
});<commit_msg>small performance optimization to BAM features<commit_after>define( ['dojo/_base/array',
         'JBrowse/Util',
         './Util',
         'JBrowse/Model/SimpleFeature'
        ],
        function( array, Util, BAMUtil, SimpleFeature ) {

var SEQRET_DECODER = ['=', 'A', 'C', 'x', 'G', 'x', 'x', 'x', 'T', 'x', 'x', 'x', 'x', 'x', 'x', 'N'];
var CIGAR_DECODER  = ['M', 'I', 'D', 'N', 'S', 'H', 'P', '=', 'X', '?', '?', '?', '?', '?', '?', '?'];

var readInt   = BAMUtil.readInt;
var readShort = BAMUtil.readShort;
var readFloat = BAMUtil.readFloat;

var Feature = Util.fastDeclare(
{
    constructor: function( args ) {
        this.store = args.store;
        this.file  = args.file;
        this.data  = {
            type: 'match',
            source: args.store.source
        };
        this.bytes = {
            start: args.bytes.start,
            end: args.bytes.end,
            byteArray: args.bytes.byteArray
        };

        this._coreParse();
    },

    get: function( field) {
        return this._get( field.toLowerCase() );
    },

    // same as get(), except requires lower-case arguments.  used
    // internally to save lots of calls to field.toLowerCase()
    _get: function( field ) {
        return field in this.data ? this.data[field] : // have we already parsed it out?
            function(field) {
                var v = this.data[field] =
                    this[field]            ? this[field]()            : // maybe we have a special parser for it
                    this._flagMasks[field] ? this._parseFlag( field ) : // or is it a flag?
                                             this._parseTag( field );   // otherwise, look for it in the tags
                return v;
            }.call(this,field);
    },

    tags: function() {
        return this._get('_tags');
    },

    _tags: function() {
        this._parseAllTags();

        var tags = [ 'seq', 'seq_reverse_complemented', 'unmapped' ];
        if( ! this._get('unmapped') )
            tags.push( 'start', 'end', 'strand', 'score', 'qual', 'MQ', 'CIGAR', 'length_on_ref' );
        if( this._get('multi_segment_template') ) {
            tags.push( 'multi_segment_all_aligned',
                       'multi_segment_next_segment_unmapped',
                       'multi_segment_next_segment_reversed',
                       'multi_segment_first',
                       'multi_segment_last',
                       'secondary_alignment',
                       'qc_failed',
                       'duplicate',
                       'next_segment_position'
                     );
        }
        tags = tags.concat( this._tagList || [] );

        var d = this.data;
        for( var k in d ) {
            if( d.hasOwnProperty( k ) && k[0] != '_' )
                tags.push( k );
        }

        var seen = {};
        tags = array.filter( tags, function(t) {
            if( t in this.data && this.data[t] === undefined )
                return false;

            var lt = t.toLowerCase();
            var s = seen[lt];
            seen[lt] = true;
            return ! s;
        },this);

        return tags;
    },

    parent: function() {
        return undefined;
    },

    children: function() {
        return this._get('subfeatures');
    },

    id: function() {
        return this._get('name')+'/'+this._get('md')+'/'+this._get('cigar')+'/'+this._get('start');
    },

    // special parsers
    /**
     * Mapping quality score.
     */
    mq: function() {
        var mq = (this._get('_bin_mq_nl') & 0xff00) >> 8;
        return mq == 255 ? undefined : mq;
    },
    score: function() {
        return this._get('mq');
    },
    qual: function() {
        if( this._get('unmapped') )
            return undefined;

        var qseq = [];
        var byteArray = this.bytes.byteArray;
        var p = this.bytes.start + 36 + this._get('_l_read_name') + this._get('_n_cigar_op')*4 + this._get('_seq_bytes');
        var lseq = this._get('seq_length');
        for (var j = 0; j < lseq; ++j) {
            qseq.push( byteArray[p + j] );
        }
        return qseq.join(' ');
    },
    strand: function() {
        var xs = this._get('xs');
        return xs ? ( xs == '-' ? -1 : 1 ) :
               this._get('seq_reverse_complemented') ? -1 :  1;
    },
    /**
     * Length in characters of the read name.
     */
    _l_read_name: function() {
        return this._get('_bin_mq_nl') & 0xff;
    },
    /**
     * number of bytes in the sequence field
     */
    _seq_bytes: function() {
        return (this._get('seq_length') + 1) >> 1;
    },
    seq: function() {
        var seq = '';
        var byteArray = this.bytes.byteArray;
        var p = this.bytes.start + 36 + this._get('_l_read_name') + this._get('_n_cigar_op')*4;
        var seqBytes = this._get('_seq_bytes');
        for (var j = 0; j < seqBytes; ++j) {
            var sb = byteArray[p + j];
            seq += SEQRET_DECODER[(sb & 0xf0) >> 4];
            seq += SEQRET_DECODER[(sb & 0x0f)];
        }
        return seq;
    },
    name: function() {
        return this._get('_read_name');
    },
    _read_name: function() {
        var byteArray = this.bytes.byteArray;
        var readName = '';
        var nl = this._get('_l_read_name');
        var p = this.bytes.start + 36;
        for (var j = 0; j < nl-1; ++j) {
            readName += String.fromCharCode(byteArray[p+j]);
        }
        return readName;
    },
    _n_cigar_op: function() {
        return this._get('_flag_nc') & 0xffff;
    },
    cigar: function() {
        if( this._get('unmapped') )
            return undefined;

        var byteArray   = this.bytes.byteArray;
        var numCigarOps = this._get('_n_cigar_op');
        var p = this.bytes.start + 36 + this._get('_l_read_name');
        var cigar = '';
        var lref = 0;
        for (var c = 0; c < numCigarOps; ++c) {
            var cigop = readInt(byteArray, p);
            var lop = cigop >> 4;
            var op = CIGAR_DECODER[cigop & 0xf];
            cigar = cigar + lop + op;
            lref += lop;
            p += 4;
        }
        this.data.length_on_ref = lref;
        return cigar;
    },
    next_segment_position: function() {
        var nextRefID = this._get('_next_refid');
        var nextSegment = this.file.indexToChr[nextRefID];
        if( nextSegment )
            return nextSegment.name+':'+this._get('_next_pos');
        else
            return undefined;
    },
    subfeatures: function() {
        if( ! this.store.createSubfeatures )
            return undefined;

        var cigar = this._get('cigar');
        if( cigar )
            return this._cigarToSubfeats( cigar );

        return undefined;
    },
    length_on_ref: function() {
        var c = this._get('cigar'); // the length_on_ref is set as a
                                   // side effect of the CIGAR parsing
        return this.data.length_on_ref;
    },
    _flags: function() {
        return (this.data._flag_nc & 0xffff0000) >> 16;
    },
    end: function() {
        return this._get('start') + ( this._get('length_on_ref') || this._get('seq_length') || undefined );
    },

    seq_id: function() {
        if( this._get('unmapped') )
            return undefined;

        return ( this.file.indexToChr[ this._refID ] || {} ).name;
    },

    /**
     * parse the core data: start, end, strand, etc
     */
    _coreParse: function() {
        var byteArray = this.bytes.byteArray;
        var dataStart = this.bytes.start+4;

        var tempBytes = new Uint8Array( 32 );
        for( var i = 0; i<32; i++ ) {
            tempBytes[i] = byteArray[i+dataStart];
        }
        var ints = new Int32Array( tempBytes.buffer );

        var d = this.data;
        this._refID        = ints[0];
        d.start            = ints[1];
        d._bin_mq_nl       = ints[2];
        d._flag_nc         = ints[3];
        d.seq_length       = ints[4];
        d._next_refid      = ints[5];
        d._next_pos        = ints[6];
        d.template_length  = ints[7];
    },

    /**
     * Get the value of a tag, parsing the tags as far as necessary.
     * Only called if we have not already parsed that field.
     */
    _parseTag: function( tagName ) {
        // if all of the tags have been parsed and we're still being
        // called, we already know that we have no such tag, because
        // it would already have been cached.
        if( this._allTagsParsed )
            return undefined;

        this._tagList = this._tagList || [];
        var byteArray = this.bytes.byteArray;
        var p = this._tagOffset || this.bytes.start + 36 + this._get('_l_read_name') + this._get('_n_cigar_op')*4 + this._get('_seq_bytes') + this._get('seq_length');

        var blockEnd = this.bytes.end;
        while( p < blockEnd && lcTag != tagName ) {
            var tag      = String.fromCharCode( byteArray[p], byteArray[ p+1 ] );
            var lcTag    = tag.toLowerCase();
            var type = String.fromCharCode( byteArray[ p+2 ] );
            p += 3;

            var value;
            switch( type.toLowerCase() ) {
            case 'a':
                value = String.fromCharCode( byteArray[p] );
                p += 1;
                break;
            case 'i':
                value = readInt(byteArray, p );
                p += 4;
                break;
            case 'c':
                value = byteArray[p];
                p += 1;
                break;
            case 's':
                value = readShort(byteArray, p);
                p += 2;
                break;
            case 'f':
                value = readFloat( byteArray, p );
                p += 4;
                break;
            case 'z':
            case 'h':
                value = '';
                while( p <= blockEnd ) {
                    var cc = byteArray[p++];
                    if( cc == 0 ) {
                        break;
                    }
                    else {
                        value += String.fromCharCode(cc);
                    }
                }
                break;
            default:
                console.warn( "Unknown BAM tag type '"+type
                              +"', tags may be incomplete"
                            );
                value = undefined;
                p = blockEnd; // stop parsing tags
            }

            this._tagOffset = p;

            this._tagList.push( tag );
            if( lcTag == tagName )
                return value;
            else {
                this.data[ lcTag ] = value;
            }
        }
        this._allTagsParsed = true;
        return undefined;
    },
    _parseAllTags: function() {
        this._parseTag(); // calling _parseTag with no arg just parses
        // all the tags and returns the last one
    },

    _flagMasks: {
        multi_segment_template:              0x1,
        multi_segment_all_aligned:           0x2,
        unmapped:                            0x4,
        multi_segment_next_segment_unmapped: 0x8,
        seq_reverse_complemented:            0x10,
        multi_segment_next_segment_reversed: 0x20,
        multi_segment_first:                 0x40,
        multi_segment_last:                  0x80,
        secondary_alignment:                 0x100,
        qc_failed:                           0x200,
        duplicate:                           0x400
    },

    _parseFlag: function( flagName ) {
        return !!( this._get('_flags') & this._flagMasks[flagName] );
    },

    _parseCigar: function( cigar ) {
        return array.map( cigar.match(/\d+\D/g), function( op ) {
           return [ op.match(/\D/)[0].toUpperCase(), parseInt( op ) ];
        });
    },

    /**
     *  take a cigar string, and initial position, return an array of subfeatures
     */
    _cigarToSubfeats: function(cigar)    {
        var subfeats = [];
        var min = this._get('start');
        var max;
        var ops = this._parseCigar( cigar );
        for (var i = 0; i < ops.length; i++)  {
            var lop = ops[i][1];
            var op = ops[i][0];  // operation type
            // converting "=" to "E" to avoid possible problems later with non-alphanumeric type name
            if (op === "=")  { op = "E"; }

            switch (op) {
            case 'M':
            case 'D':
            case 'N':
            case 'E':
            case 'X':
                max = min + lop;
                break;
            case 'I':
                max = min;
                break;
            case 'P':  // not showing padding deletions (possibly change this later -- could treat same as 'I' ?? )
            case 'H':  // not showing hard clipping (since it's unaligned, and offset arg meant to be beginning of aligned part)
            case 'S':  // not showing soft clipping (since it's unaligned, and offset arg meant to be beginning of aligned part)
                break;
                // other possible cases
            }
            if( op !== 'N' ) {
                var subfeat = new SimpleFeature({
                    data: {
                    type: op,
                        start: min,
                        end: max,
                        strand: this._get('strand'),
                        cigar_op: lop+op
                    },
                    parent: this
                });
                subfeats.push(subfeat);
            }
            min = max;
        }
        return subfeats;
    }

});

return Feature;
});<|endoftext|>


<commit_before>/**
 * @author windy
 * @version 2.0
 * Created by windy on 2021/5/18
 */
BI.SelectPatchEditor = BI.inherit(BI.Widget, {

    props: {
        baseCls: "bi-patch-select-editor",
        height: 24,
    },

    render: function () {
        var self = this, o = this.options;

        var debounceInputChange = BI.debounce(BI.bind(this._dealChange, this), 300);

        return BI.extend({
            type: "bi.state_editor",
            ref: function (_ref) {
                self.editor = _ref;
            },
            hgap: o.hgap,
            vgap: o.vgap,
            lgap: o.lgap,
            rgap: o.rgap,
            tgap: o.tgap,
            bgap: o.bgap,
            height: o.height,
            watermark: o.watermark,
            allowBlank: true,
            value: o.value,
            defaultText: o.text,
            text: o.text,
            tipType: o.tipType,
            warningTitle: o.warningTitle,
            el: {
                type: 'bi.textarea_editor',
                scrolly: false,
                validationChecker: function () {
                    return true;
                },
                throttle: true,
            },
            listeners: [{
                eventName: BI.Controller.EVENT_CHANGE,
                action: function (type, v) {
                    if (BI.contains(v, "\n")) {
                        self._dealChange(type, v);
                    } else {
                        debounceInputChange(type, v);
                    }
                },
            }, {
                eventName: BI.Editor.EVENT_FOCUS,
                action: function () {
                    self.fireEvent(BI.SelectPatchEditor.EVENT_FOCUS, arguments);
                },
            }, {
                eventName: BI.Editor.EVENT_BLUR,
                action: function () {
                    self.fireEvent(BI.SelectPatchEditor.EVENT_BLUR, arguments);
                },
            }],
        }, o.el);
    },

    _dealChange: function (type, v) {
        var value = "";
        if (BI.isKey(v)) {
            value = this._formatText(v);
        }
        if (type === BI.Events.CHANGE) {
            this._setValue(value);
            if (this._trimValue(value) !== "") {
                if (!this._start || !BI.isKey(this._lastValue) || (this._pause === true && !/\u200b\s\u200b$/.test(this.getValue()))) {
                    this._start = true;
                    this._pause = false;
                    this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.STARTEDIT, this.getValue(), this);
                }
            }
            if (this._trimValue(this._lastValue) !== this._trimValue(value)) {
                this.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
            }
            if (BI.endWith(value, BI.BlankSplitChar)) {
                this._pause = true;
                this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.PAUSE, "", this);
            }
        }
        if (type === BI.Events.EMPTY || type === BI.Events.STOPEDIT) {
            this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EMPTY);
        }
        this._lastValue = value;
    },

    _trimValue: function (v) {
        return BI.trim(BI.replaceAll(v || "", BI.BlankSplitChar, ""));
    },

    _formatText: function (v) {
        return BI.replaceAll(v || "", "\n", BI.BlankSplitChar);
    },

    setWaterMark: function (v) {
        this.editor.setWaterMark(v);
    },

    doRedMark: function () {
        this.editor.doRedMark.apply(this.editor, arguments);
    },

    unRedMark: function () {
        this.editor.unRedMark.apply(this.editor, arguments);
    },

    doHighLight: function () {
        this.editor.doHighLight.apply(this.editor, arguments);
    },

    unHighLight: function () {
        this.text.unHighLight.apply(this.text, arguments);
    },

    focus: function () {
        this.editor.focus();
    },

    blur: function () {
        this.editor.blur();
    },

    _setValue: function (v) {
        this.editor.setValue(this._formatText(v));
    },

    _showInput: function () {
        this.editor.visible();
        this.text.invisible();
    },

    _showHint: function () {
        this.editor.invisible();
        this.text.visible();
    },

    isValid: function () {
        return this.editor.isValid();
    },

    setErrorText: function (text) {
        this.editor.setErrorText(text);
    },

    getErrorText: function () {
        return this.editor.getErrorText();
    },

    isEditing: function () {
        return this.editor.isEditing();
    },

    getLastValidValue: function () {
        return this.editor.getLastValidValue();
    },

    getLastChangedValue: function () {
        return this.editor.getLastChangedValue();
    },

    setValue: function (v) {
        this._setValue(v);
        this._lastValue = this._trimValue(v);
    },

    getValue: function () {
        return BI.trim(this.editor.getValue());
    },

    getState: function () {
        return this.editor.getState();
    },

    setState: function (v) {
        this.editor.setState(v);
    },

    setTipType: function (v) {
        this.editor.setTipType(v);
    },

    getText: function () {
        return this.editor.getText();
    },
});
BI.SelectPatchEditor.EVENT_CHANGE = "EVENT_CHANGE";
BI.SelectPatchEditor.EVENT_FOCUS = "EVENT_FOCUS";
BI.SelectPatchEditor.EVENT_BLUR = "EVENT_BLUR";

BI.shortcut("bi.select_patch_editor", BI.SelectPatchEditor);<commit_msg>Pull request #1938: 无JIRA任务 测试下fineui同步dec-fineui<commit_after>/**
 * @author windy
 * @version 2.0
 * Created by windy on 2021/5/18
 */
BI.SelectPatchEditor = BI.inherit(BI.Widget, {

    props: {
        baseCls: "bi-patch-select-editor",
        height: 24,
    },

    render: function () {
        var self = this, o = this.options;

        var debounceInputChange = BI.debounce(BI.bind(this._dealChange, this), 300);

        return BI.extend({
            type: "bi.state_editor",
            ref: function (_ref) {
                self.editor = _ref;
            },
            hgap: o.hgap,
            vgap: o.vgap,
            lgap: o.lgap,
            rgap: o.rgap,
            tgap: o.tgap,
            bgap: o.bgap,
            height: o.height,
            watermark: o.watermark,
            allowBlank: true,
            value: o.value,
            defaultText: o.text,
            text: o.text,
            tipType: o.tipType,
            warningTitle: o.warningTitle,
            el: {
                type: 'bi.textarea_editor',
                scrolly: false,
                validationChecker: function () {
                    return true;
                },
                throttle: true,
            },
            listeners: [{
                eventName: BI.Controller.EVENT_CHANGE,
                action: function (type, v) {
                    if (BI.contains(v, "\n")) {
                        self._dealChange(type, v);
                    } else {
                        debounceInputChange(type, v);
                    }
                },
            }, {
                eventName: BI.Editor.EVENT_FOCUS,
                action: function () {
                    self.fireEvent(BI.SelectPatchEditor.EVENT_FOCUS, arguments);
                },
            }, {
                eventName: BI.Editor.EVENT_BLUR,
                action: function () {
                    self.fireEvent(BI.SelectPatchEditor.EVENT_BLUR, arguments);
                },
            }],
        }, o.el);
    },

    _dealChange: function (type, v) {
        var value = "";
        if (v !== this.editor.getValue()) {
            return;
        }
        if (BI.isKey(v)) {
            value = this._formatText(v);
        }
        if (type === BI.Events.CHANGE) {
            this._setValue(value);
            if (this._trimValue(value) !== "") {
                if (!this._start || !BI.isKey(this._lastValue) || (this._pause === true && this._trimValue(this._lastValue) !== this._trimValue(value))) {
                    this._start = true;
                    this._pause = false;
                    this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.STARTEDIT, this.getValue(), this);
                }
            }
            if (this._trimValue(this._lastValue) !== this._trimValue(value)) {
                this.fireEvent(BI.Controller.EVENT_CHANGE, arguments);
            }
            if (BI.endWith(value, BI.BlankSplitChar)) {
                this._pause = true;
                this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.PAUSE, "", this);
            }
        }
        if (type === BI.Events.EMPTY || type === BI.Events.STOPEDIT) {
            this.fireEvent(BI.Controller.EVENT_CHANGE, BI.Events.EMPTY);
        }
        this._lastValue = value;
    },

    _trimValue: function (v) {
        return BI.trim(BI.replaceAll(v || "", BI.BlankSplitChar, ""));
    },

    _formatText: function (v) {
        return BI.replaceAll(v || "", "\n", BI.BlankSplitChar);
    },

    setWaterMark: function (v) {
        this.editor.setWaterMark(v);
    },

    doRedMark: function () {
        this.editor.doRedMark.apply(this.editor, arguments);
    },

    unRedMark: function () {
        this.editor.unRedMark.apply(this.editor, arguments);
    },

    doHighLight: function () {
        this.editor.doHighLight.apply(this.editor, arguments);
    },

    unHighLight: function () {
        this.text.unHighLight.apply(this.text, arguments);
    },

    focus: function () {
        this.editor.focus();
    },

    blur: function () {
        this.editor.blur();
    },

    _setValue: function (v) {
        this.editor.setValue(this._formatText(v));
    },

    _showInput: function () {
        this.editor.visible();
        this.text.invisible();
    },

    _showHint: function () {
        this.editor.invisible();
        this.text.visible();
    },

    isValid: function () {
        return this.editor.isValid();
    },

    setErrorText: function (text) {
        this.editor.setErrorText(text);
    },

    getErrorText: function () {
        return this.editor.getErrorText();
    },

    isEditing: function () {
        return this.editor.isEditing();
    },

    getLastValidValue: function () {
        return this.editor.getLastValidValue();
    },

    getLastChangedValue: function () {
        return this.editor.getLastChangedValue();
    },

    setValue: function (v) {
        this._setValue(v);
        this._lastValue = this._trimValue(v);
    },

    getValue: function () {
        return BI.trim(this.editor.getValue());
    },

    getState: function () {
        return this.editor.getState();
    },

    setState: function (v) {
        this.editor.setState(v);
    },

    setTipType: function (v) {
        this.editor.setTipType(v);
    },

    getText: function () {
        return this.editor.getText();
    },
});
BI.SelectPatchEditor.EVENT_CHANGE = "EVENT_CHANGE";
BI.SelectPatchEditor.EVENT_FOCUS = "EVENT_FOCUS";
BI.SelectPatchEditor.EVENT_BLUR = "EVENT_BLUR";

BI.shortcut("bi.select_patch_editor", BI.SelectPatchEditor);<|endoftext|>


<commit_before>angular.module('Ladder').factory('LadderSvc', LadderSvc);

LadderSvc.$inject = ['$http', '$q'];
function LadderSvc($http, $q) {
    var factory = {};
    var url = window.location.hostname + ':4007/ladder';

    factory.top = function(game) {
        var deferred = $q.defer();

        $http.get(url + '/' + game).then(function(results) {
            deferred.resolve(results);
        });

        return deferred.promise;
    };

    return factory;
}
<commit_msg>adding protocol, otherwise call fails due to different port<commit_after>angular.module('Ladder').factory('LadderSvc', LadderSvc);

LadderSvc.$inject = ['$http', '$q'];
function LadderSvc($http, $q) {
    var factory = {};
    var url = window.location.protocol +'//'+ window.location.hostname + ':4007/ladder';

    factory.top = function(game) {
        var deferred = $q.defer();

        $http.get(url + '/' + game).then(function(results) {
            deferred.resolve(results.data);
        });

        return deferred.promise;
    };

    return factory;
}
<|endoftext|>


<commit_before>function Clipboard(base_url, tree_url, clipboard_id) {
    this.base_url = base_url;
    this.contentElement = getElement(clipboard_id);
    this.tree = new Tree(tree_url, clipboard_id);
    connect(this.tree, 'treeChangeEvent', this, 'handleTreeChange');
    this.connectDNDHandlers();
    var dnd = this;
    this.dragging = false;
    MochiKit.Position.includeScrollOffsets = true;

    // Adding
    connect('clip-add-folder-link', 'onclick', this, 'showAddBox');
    connect('clip-add-folder-submit', 'onclick', this, 'addClip');
    connect('clip-add-folder-cancel', 'onclick', this, 'hideAddBox');
    connect('clipboardcontents', 'onclick', this, 'removeClip');
}

Clipboard.prototype = {

    connectDNDHandlers: function() {
        var elements = this.contentElement.getElementsByTagName('li');
        var dnd = this;
        forEach(elements, function(node) {
            new Droppable(node, {
                hoverclass: 'TreeHover',
                ondrop: function(element, last_active_element, event) {
                        dnd.handleDrop(node.getAttribute('uniqueid'), element);
                    },
            });
            if (node.getAttribute('uniqueid')) {
                new Draggable(node, {
                    starteffect: null,
                    endeffect: null});
            }
        });

        forEach(this.contentElement.getElementsByTagName('a'), function(node) {
                connect(node, 'onclick', function(event) {
                    if (dnd.dragging == true) {
                        event.stop();
                    }
                });
            });
    },

    handleDrop: function(dropped_on, element) {
        this.dragging = true;
        var url;
        var unique_id;
        var dnd = this;
        var options = {'add_to': dropped_on};

        var dragged_element = element.dragged_element;
        if (dragged_element == undefined) return;

        if (dragged_element.nodeName == 'LI') {
            url = '/@@moveContent';
            options['object_path'] = dragged_element.getAttribute('uniqueid');
        } else {
            url = '/@@addContent';
            options['unique_id'] = element.uniqueId;
        }

            if (!options) return;

            var d = doSimpleXMLHttpRequest(this.base_url + url, options);
            d.addCallbacks(
                function(result) {
                    dnd.dragging = false;
                    dnd.tree.replaceTree(result.responseText);
            },
            alert
        );
    },

    handleTreeChange: function(event) {
        this.connectDNDHandlers();
    },

    // Adding

    showAddBox: function(event) {
        hideElement('clip-add-folder-link');
        showElement('clip-add-folder-box');
    },

    hideAddBox: function(event) {
        hideElement('clip-add-folder-box');
        showElement('clip-add-folder-link');
    },

    addClip: function(event) {
        var dnd = this;
        var title = getElement('clip-add-folder-title').value;
        if (!title.match(/\w.+/))
            return

        var d = doSimpleXMLHttpRequest(
            this.base_url + '/@@addContainer', {
                'title': title});
        d.addCallbacks(
            function(result) {
                dnd.tree.replaceTree(result.responseText);
                clipboarddnd.hideAddBox();
            },
            alert
        );
        event.stop();
    },

    removeClip: function(event) {
        var element = event.target();
        if (element == undefined) return;

        var css_class = element.getAttribute('class');
        if (css_class == 'DeleteLink') {
            var url = element.getAttribute('href')
            var d = doSimpleXMLHttpRequest(url);
            d.addCallbacks(
                function(result) {
                    clipboarddnd.tree.replaceTree(result.responseText);
                });
        }

        if (element.nodeName == 'A' && !(css_class == 'DeleteLink')) return;

        event.stop();
    },
}

<commit_msg>fixed dragging items from the breadcrumbs to the clipboard<commit_after>function Clipboard(base_url, tree_url, clipboard_id) {
    this.base_url = base_url;
    this.contentElement = getElement(clipboard_id);
    this.tree = new Tree(tree_url, clipboard_id);
    connect(this.tree, 'treeChangeEvent', this, 'handleTreeChange');
    this.connectDNDHandlers();
    var dnd = this;
    this.dragging = false;
    MochiKit.Position.includeScrollOffsets = true;

    // Adding
    connect('clip-add-folder-link', 'onclick', this, 'showAddBox');
    connect('clip-add-folder-submit', 'onclick', this, 'addClip');
    connect('clip-add-folder-cancel', 'onclick', this, 'hideAddBox');
    connect('clipboardcontents', 'onclick', this, 'removeClip');
}

Clipboard.prototype = {

    connectDNDHandlers: function() {
        var elements = this.contentElement.getElementsByTagName('li');
        var dnd = this;
        forEach(elements, function(node) {
            new Droppable(node, {
                hoverclass: 'TreeHover',
                ondrop: function(element, last_active_element, event) {
                        dnd.handleDrop(node.getAttribute('uniqueid'), element);
                    },
            });
            if (node.getAttribute('uniqueid')) {
                new Draggable(node, {
                    starteffect: null,
                    endeffect: null});
            }
        });

        forEach(this.contentElement.getElementsByTagName('a'), function(node) {
                connect(node, 'onclick', function(event) {
                    if (dnd.dragging == true) {
                        event.stop();
                    }
                });
            });
    },

    handleDrop: function(dropped_on, element) {
        this.dragging = true;
        var url;
        var dnd = this;
        var options = {'add_to': dropped_on};

        var dragged_element = element.dragged_element;
        if (dragged_element == undefined) return;

        var panel = null;
        try {
            panel = getFirstParentByTagAndClassName(
                dragged_element, 'div', 'panel');
        } catch(e) {
            // bug in mochikit? getFirstParentByTagAndClassName raises
            // exception when there is no such parent.
        }
        if (panel != null && panel.id == 'ClipboardPanel') {
            url = '/@@moveContent';
            options['object_path'] = dragged_element.getAttribute('uniqueid');
        } else {
            url = '/@@addContent';
            options['unique_id'] = element.uniqueId;
        }

            if (!options) return;

            var d = doSimpleXMLHttpRequest(this.base_url + url, options);
            d.addCallbacks(
                function(result) {
                    dnd.dragging = false;
                    dnd.tree.replaceTree(result.responseText);
            },
            alert
        );
    },

    handleTreeChange: function(event) {
        this.connectDNDHandlers();
    },

    // Adding

    showAddBox: function(event) {
        hideElement('clip-add-folder-link');
        showElement('clip-add-folder-box');
    },

    hideAddBox: function(event) {
        hideElement('clip-add-folder-box');
        showElement('clip-add-folder-link');
    },

    addClip: function(event) {
        var dnd = this;
        var title = getElement('clip-add-folder-title').value;
        if (!title.match(/\w.+/))
            return

        var d = doSimpleXMLHttpRequest(
            this.base_url + '/@@addContainer', {
                'title': title});
        d.addCallbacks(
            function(result) {
                dnd.tree.replaceTree(result.responseText);
                clipboarddnd.hideAddBox();
            },
            alert
        );
        event.stop();
    },

    removeClip: function(event) {
        var element = event.target();
        if (element == undefined) return;

        var css_class = element.getAttribute('class');
        if (css_class == 'DeleteLink') {
            var url = element.getAttribute('href')
            var d = doSimpleXMLHttpRequest(url);
            d.addCallbacks(
                function(result) {
                    clipboarddnd.tree.replaceTree(result.responseText);
                });
        }

        if (element.nodeName == 'A' && !(css_class == 'DeleteLink')) return;

        event.stop();
    },
}

<|endoftext|>


<commit_before>if (typeof dreamer === 'undefined') {
    var dreamer = {};
}
var level = {}

dreamer.SuperfluidityController = (function(global) {
    'use strict';

    var DEBUG = true;

    SuperfluidityController.prototype.constructor = SuperfluidityController;

    /**
     * Constructor
     */
    function SuperfluidityController() {
         SuperfluidityController.etsiController = new dreamer.EtsiController();

    }

    SuperfluidityController.prototype.addVnf = function(self, node, success, error) {
        SuperfluidityController.etsiController.addVnf(self, node, success, error);
    };

    SuperfluidityController.prototype.addVnfVdu = function(self, node, success, error) {
        SuperfluidityController.etsiController.addVnfVdu(self, node, success, error);
    }

    SuperfluidityController.prototype.addVnfVduCp = function(self, node, success, error) {
         var vnf_id = node.info.group[0];
        var vnf_vdus = $.grep(self.d3_graph.nodes, function(e) {
            return (e.info.group.indexOf(vnf_id) >= 0 && (e.info.type == 'vnf_vdu' || e.info.type == 'vnf_click_vdu'));
        });
        if (success)
            success();
        if (typeof vnf_vdus == 'undefined' || vnf_vdus.length <= 0) {
            alert('You should add a VDU')
        } else {
            console.log(vnf_vdus)
            showChooserModal('Select the VDU to link', vnf_vdus, function(choice) {
                var target = choice;
                choice = $.grep(vnf_vdus, function(e){ return e.id == choice; });
                console.log(choice)
                choice = vnf_vdus[0].info.type == 'vnf_vdu' ? choice : vnf_vdus[0].vduId;

                new dreamer.GraphRequests().addNode(node, choice, function() {
                    var link = {
                        source: node.id,
                        target: target,
                        view: self.filter_parameters.link.view[0],
                        group: [node.info.group[0]],
                    };

                    self.parent.addLink.call(self, link);

                    $('#modal_create_link_chooser').modal('hide');
                });
            });
        }
    }

    SuperfluidityController.prototype.nsCpExclusiveConnection = function(self, link, success, error) {
        SuperfluidityController.etsiController.nsCpExclusiveConnection(self, link, success, error);
    }

    SuperfluidityController.prototype.linkVnftoNsVl = function(self, link, success, error) {
        SuperfluidityController.etsiController.linkVnftoNsVl(self, link, success, error);
    }

    SuperfluidityController.prototype.linkVnftoNsCp = function(self, link, success, error) {
        SuperfluidityController.etsiController.linkVnftoNsCp(self, link, success, error);
    }

    SuperfluidityController.prototype.linkVltoVduCp = function(self, link, success, error) {
        SuperfluidityController.etsiController.linkVltoVduCp(self, link, success, error);
    }

   SuperfluidityController.prototype.linkVnfVltoExpCp = function(self, link, success, error) {
        SuperfluidityController.etsiController.linkVnfVltoExpCp(self, link, success, error);
   }

   SuperfluidityController.prototype.removeVnfVdu = function(self, node, success, error) {
        SuperfluidityController.etsiController.removeVnfVdu(self, node, success, error);
   }

    SuperfluidityController.prototype.removeVnfVduCp = function(self, node, success, error) {
        var vdu_links = $.grep(self.d3_graph.links, function(e) {
            return (e.source.id == node.id || e.target.id == node.id) && (e.source.info.type == 'vnf_vdu' || e.target.info.type == 'vnf_vdu'
            || e.source.info.type == 'vnf_click_vdu' || e.target.info.type == 'vnf_click_vdu')
        });
        var vdu_id;
        if(vdu_links[0].source.info.type == 'vnf_vdu'){
            vdu_id = vdu_links[0].source.id;
        }else if(vdu_links[0].target.info.type == 'vnf_vdu' ){
            vdu_id = vdu_links[0].target.id;
        }else if(vdu_links[0].source.info.type == 'vnf_click_vdu' ){
            vdu_id = vdu_links[0].source.vduId;
        }else{
            vdu_id = vdu_links[0].target.vduId;
        }
        console.log(vdu_id)
        new dreamer.GraphRequests().removeNode(node, vdu_id, function() {
            if (success) {
                success();
            }
        });
    }

    SuperfluidityController.prototype.addNode = function(self, node, success, error) {
        if(self.getCurrentView()!= 'click'){
            SuperfluidityController.etsiController.addNode(self, node, success, error);
        }
    };

    SuperfluidityController.prototype.addToCurrentVNFFG = function(self, args, error) {
        if(self.getCurrentView()!= 'click'){
            SuperfluidityController.etsiController.addToCurrentVNFFG(self, args, error);
        }
    }

    SuperfluidityController.prototype.removeNode = function(self, node, success, error) {
        if(self.getCurrentView()!= 'click'){
            new dreamer.GraphRequests().removeNode(node, null, function() {
                if (success) {
                    success();
                }
            });
         }
    };

    SuperfluidityController.prototype.removeLink = function(self, link, success, error) {
        if(self.getCurrentView()!= 'click'){
            new dreamer.GraphRequests().removeLink(link, success,error);
        }
    };

    return SuperfluidityController;

}(this));

if (typeof module === 'object') {
    module.exports = dreamer.SuperfluidityController;
}<commit_msg>fix problem link vdu to vdu_cp<commit_after>if (typeof dreamer === 'undefined') {
    var dreamer = {};
}
var level = {}

dreamer.SuperfluidityController = (function(global) {
    'use strict';

    var DEBUG = true;

    SuperfluidityController.prototype.constructor = SuperfluidityController;

    /**
     * Constructor
     */
    function SuperfluidityController() {
         SuperfluidityController.etsiController = new dreamer.EtsiController();

    }

    SuperfluidityController.prototype.addVnf = function(self, node, success, error) {
        SuperfluidityController.etsiController.addVnf(self, node, success, error);
    };

    SuperfluidityController.prototype.addVnfVdu = function(self, node, success, error) {
        SuperfluidityController.etsiController.addVnfVdu(self, node, success, error);
    }

    SuperfluidityController.prototype.addVnfVduCp = function(self, node, success, error) {
         var vnf_id = node.info.group[0];
        var vnf_vdus = $.grep(self.d3_graph.nodes, function(e) {
            return (e.info.group.indexOf(vnf_id) >= 0 && (e.info.type == 'vnf_vdu' || e.info.type == 'vnf_click_vdu'));
        });
        if (success)
            success();
        if (typeof vnf_vdus == 'undefined' || vnf_vdus.length <= 0) {
            alert('You should add a VDU')
        } else {
            console.log(vnf_vdus)
            showChooserModal('Select the VDU to link', vnf_vdus, function(choice) {
                var target = choice;
                choice = $.grep(vnf_vdus, function(e){ return e.id == choice; });
                console.log(choice)
                choice = vnf_vdus[0].info.type == 'vnf_vdu' ? choice : vnf_vdus[0].vduId;

                new dreamer.GraphRequests().addNode(node, choice, function() {
                    var link = {
                        source: node.id,
                        target: target,
                        view: self.filter_parameters.link.view[0],
                        group: [node.info.group[0]],
                    };

                    self.parent.addLink.call(self, link);

                    $('#modal_create_link_chooser').modal('hide');
                });
            });
        }
    }

    SuperfluidityController.prototype.nsCpExclusiveConnection = function(self, link, success, error) {
        SuperfluidityController.etsiController.nsCpExclusiveConnection(self, link, success, error);
    }

    SuperfluidityController.prototype.linkVnftoNsVl = function(self, link, success, error) {
        SuperfluidityController.etsiController.linkVnftoNsVl(self, link, success, error);
    }

    SuperfluidityController.prototype.linkVnftoNsCp = function(self, link, success, error) {
        SuperfluidityController.etsiController.linkVnftoNsCp(self, link, success, error);
    }

    SuperfluidityController.prototype.linkVltoVduCp = function(self, link, success, error) {
        var s = link.source;
        var d = link.target;
        var source_id = s.id;
        var target_id = d.id;
        var source_type = s.info.type;
        var destination_type = d.info.type;
        var vnf_vdu_cp_id = source_type == 'vnf_vdu_cp' ? source_id : target_id;
        var vdu_links = $.grep(self.d3_graph.links, function(e) {
            return (e.source.id == vnf_vdu_cp_id || e.target.id == vnf_vdu_cp_id) && (e.source.info.type == 'vnf_vdu' || e.target.info.type == 'vnf_vdu'
            || e.source.info.type == 'vnf_click_vdu' || e.target.info.type == 'vnf_click_vdu')
        });
        var vdu_id = vdu_links[0].source.info.type == 'vnf_vdu' ? vdu_links[0].source.id : vdu_links[0].target.id;
        if(vdu_links[0].source.info.type == 'vnf_vdu'){
            vdu_id = vdu_links[0].source.id;
        }else if (vdu_links[0].target.info.type == 'vnf_vdu'){
            vdu_id = vdu_links[0].target.id;
        } else if(vdu_links[0].source.info.type == 'vnf_click_vdu'){
          var vnf_vdus = $.grep(self.d3_graph.nodes, function(e) {
            return (e.id == vdu_links[0].source.id) && (e.info.type == 'vnf_click_vdu')
          });
          vdu_id = vnf_vdus[0].vduId;
        }else{
            var vnf_vdus = $.grep(self.d3_graph.nodes, function(e) {
            return (e.id == vdu_links[0].target.id) && (e.info.type == 'vnf_click_vdu')
          });
          vdu_id = vnf_vdus[0].vduId;
        }
        var old_link = $.grep(self.d3_graph.links, function(e) {
            return (e.source.id == vnf_vdu_cp_id || e.target.id == vnf_vdu_cp_id) && (e.source.info.type == 'vnf_vl' || e.target.info.type == 'vnf_vl')
        });
        new dreamer.GraphRequests().addLink(link,  vdu_id, function() {
            self._deselectAllNodes();
            if (typeof old_link !== 'undefined' && old_link.length > 0 && old_link[0].index !== 'undefined') {
                self.parent.removeLink.call(self, old_link[0].index);
            }
            if (success) {
                success();
            }
        });
    }

   SuperfluidityController.prototype.linkVnfVltoExpCp = function(self, link, success, error) {
        SuperfluidityController.etsiController.linkVnfVltoExpCp(self, link, success, error);
   }

   SuperfluidityController.prototype.removeVnfVdu = function(self, node, success, error) {
        SuperfluidityController.etsiController.removeVnfVdu(self, node, success, error);
   }

    SuperfluidityController.prototype.removeVnfVduCp = function(self, node, success, error) {
        var vdu_links = $.grep(self.d3_graph.links, function(e) {
            return (e.source.id == node.id || e.target.id == node.id) && (e.source.info.type == 'vnf_vdu' || e.target.info.type == 'vnf_vdu'
            || e.source.info.type == 'vnf_click_vdu' || e.target.info.type == 'vnf_click_vdu')
        });
        var vdu_id;
        if(vdu_links[0].source.info.type == 'vnf_vdu'){
            vdu_id = vdu_links[0].source.id;
        }else if(vdu_links[0].target.info.type == 'vnf_vdu' ){
            vdu_id = vdu_links[0].target.id;
        }else if(vdu_links[0].source.info.type == 'vnf_click_vdu' ){
            vdu_id = vdu_links[0].source.vduId;
        }else{
            vdu_id = vdu_links[0].target.vduId;
        }
        console.log(vdu_id)
        new dreamer.GraphRequests().removeNode(node, vdu_id, function() {
            if (success) {
                success();
            }
        });
    }

    SuperfluidityController.prototype.addNode = function(self, node, success, error) {
        if(self.getCurrentView()!= 'click'){
            SuperfluidityController.etsiController.addNode(self, node, success, error);
        }
    };

    SuperfluidityController.prototype.addToCurrentVNFFG = function(self, args, error) {
        if(self.getCurrentView()!= 'click'){
            SuperfluidityController.etsiController.addToCurrentVNFFG(self, args, error);
        }
    }

    SuperfluidityController.prototype.removeNode = function(self, node, success, error) {
        if(self.getCurrentView()!= 'click'){
            new dreamer.GraphRequests().removeNode(node, null, function() {
                if (success) {
                    success();
                }
            });
         }
    };

    SuperfluidityController.prototype.removeLink = function(self, link, success, error) {
        if(self.getCurrentView()!= 'click'){
            new dreamer.GraphRequests().removeLink(link, success,error);
        }
    };

    return SuperfluidityController;

}(this));

if (typeof module === 'object') {
    module.exports = dreamer.SuperfluidityController;
}<|endoftext|>


<commit_before>// +++ under development
// The Crazyflie Nano Quadcopter -- http://www.bitcraze.se/crazyflie/

exports.start = function() {};
if (true) return;

var aerogel     = require('aerogel')
  , underscore  = require('underscore')
  , util        = require('util')
  , devices     = require('./../../core/device')
  , steward     = require('./../../core/steward')
  , utility     = require('./../../core/utility')
  , broker      = utility.broker
  , motive      = require('./../device-motive')
  ;

// var logger   = motive.logger;
var logger2  = utility.logger('discovery');

var driver;

var QuadCopter = exports.device = function(deviceID, deviceUID, info) {
  var self;

  self = this;

  self.whatami = info.deviceType;
  self.deviceID = deviceID.toString();
  self.deviceUID = deviceUID;
  self.name = info.device.name;
  self.getName();

  self.thrust = { min: 10001, max: 60000 };

  self.info = { thrust: 0 };

  self.status = 'waiting';
  self.changed();

  self.copter = new aerogel.Copter(driver);
  self.copter.on('stabilizer', function(data) {
    var stabilizer, thrust, updateP;

    updateP = false;
    thrust = devices.scaledLevel(Math.abs(data.thrust), self.thrust.min, self.thrust.max);
    if (self.info.thrust !== thrust) {
      self.info.thrust = thrust;
      updateP = true;
    }

    delete(data.thrust);
    stabilizer = f2(data);
    if (!underscore.isEqual(self.info.stabilizer, stabilizer)) {
      self.info.stabilizer = stabilizer;
      updateP = true;
    }

    if (updateP) self.changed();
  }).on('accelerometer', function(data) {
    var accelerometer = f2(data);

    if (!underscore.isEqual(self.info.acceleration, accelerometer)) {
      self.info.acceleration = accelerometer;
      self.changed();
    }
  }).on('gyroscope', function(data) {
    var gyroscope = f2(data);

    if (!underscore.isEqual(self.info.orientation, gyroscope)) {
      self.info.orientation = gyroscope;
      self.changed();
    }
  });
  self.copter.connect(info.url).then(function() { self.status = 'ready'; self.changed(); }).done();

  broker.subscribe('actors', function(request, eventID, actor, observe, parameter) {
    if (actor !== ('device/' + self.deviceID)) return;

    if (request === 'observe') {
      if ((observe === 'cliff') || (observe === 'obstacle') || (observe === 'wall')) {
        self.events[eventID] = { observe: observe };
      }
      return;
    }
    if (request === 'perform') return self.perform(self, eventID, observe, parameter);
  });
};
util.inherits(QuadCopter, motive.Device);

var f2 = function(data) {
  var prop, props;

  props = {};
  for (prop in data) if (data.hasOwnProperty(prop)) props[prop] = data[prop].toFixed(2);

  return props;
};

QuadCopter.prototype.perform = function(self, taskID, perform, parameter) {
  var f, g, params;

  try { params = JSON.parse(parameter); } catch(ex) { params = {}; }

  g = function(dof) {
        var degrees, duration;

        degrees = parseFloat(params.degrees);
        if (isNaN(degrees) || (degrees < -180) || (degrees > 180)) return false;
        duration = parseInt(params.duration, 10);
        if (isNaN(duration) || (duration < 0) || (duration > 1000)) duration = 250;

        self.copter[dof](degrees);
        self.status = 'busy';
        setTimeout(function() { self.copter[dof](0); self.status = 'ready'; }, duration);

        return true;
      };

  f = { set     : function() {
                    return self.setName(params.name);
                  }

      , takeoff : function() {
                    self.copter.takeoff().then(function() {
                      self.copter.hover();
                      self.copter.setPitch(0);
                      self.copter.setRoll(0);
                      self.info.thrust = 40;
                      self.copter.setThrust(devices.scaledPercentage(self.info.thrust, self.thrust.min, self.thrust.max));

                      self.status = 'hovering';
                      self.changed();
                    });

                    self.changed();
                    return true;
                  }

      , hover   : function() {
                    self.copter.hover();

                    self.status = 'hovering';
                    self.changed();
                    return true;
                  }

      , land    : function() {
                    self.copter.land().then(function() {
                      self.status = 'ready';
                      self.changed();
                    });

                    self.status = 'landing';
                    self.changed();
                    return true;
                  }

      , halt    : function() {
                    self.copter.land().then(function() {
                      self.copter.shutdown();

                      self.status = 'down';
                      self.changed();
                    });

                    self.status = 'landing';
                    self.changed();
                    return true;
                  }

      , pitch   : function() {
                    return g('setPitch');
                  }

      , roll    : function() {
                    return g('setRoll');
                  }

      , yaw     : function() {
                    return g('setYaw');
                  }

      , thrust  : function() {
                    var thrust;

                    if (!params.value) return false;
                    thrust = parseInt(params.value, 10);
                    if ((thrust < 1) || (thrust > 100)) return false;

                    self.info.thrust = thrust;
                    self.copter.setThrust(devices.scaledPercentage(self.info.thrust, self.thrust.min, self.thrust.max));
                    self.changed();
                  }
     }[perform];
  if (!f) return false;

  return (f() && steward.performed(taskID));
};

exports.validThurst  = function(thrust)  { return ((0 <= thrust) && (thrust <= 100)); };

var validate_perform = function(perform, parameter) {
  var params = {}
    , result = { invalid: [], requires: [] }
    ;

  if (!!parameter) try { params = JSON.parse(parameter); } catch(ex) { result.invalid.push('parameter'); }

  var g = function(dof) {
            var degrees;

            if (!!params.degrees) {
              degrees = parseFloat(params.degrees);
              if (isNaN(degrees) || (degrees < -180) || (degrees > 180)) result.invalid.push(dof + '.degrees');
            } else result.requires.push(dof + '.degrees');

          };

  var f = { set     : function() { if (!params.name) result.requires('name'); }

          , takeoff : function() { }
          , hover   : function() { }
          , land    : function() { }
          , halt    : function() { }

          , pitch   : function() { g('pitch'); }
          , roll    : function() { g('roll'); }
          , yaw     : function() { g('yaw'); }

          , thrust  : function() {
                        var thrust;

                        if (!!params.value) {
                          thrust = parseInt(params.value, 10);
                          if ((thrust < 1) || (thrust > 100)) result.invalid.push('thrust.value');
                        } else result.requires.push('thrust.value');
                      }
         }[perform];
  if (f) f(); else result.invalid.push('perform');

  return result;
};

var uris = {};

var scan = function() {
  driver.findCopters().then(function(copters) {
    var i, info, uri;

    for (i = 0; i < copters.length; i++) {
      uri = copters[i];
      if (!!uris[uri]) continue;
      uris[uri] = true;

      info = { source: 'aerogel' };
      info.device = { url          : null
                    , name         : ''
                    , manufacturer : 'Bitcraze'
                    , model        : { name        : 'Crazyflie'
                                     , description : 'Nano Quadcopter'
                                     , number      : ''
                                     }
                    , unit         : { serialNo    : uri
                                     , udn         : 'crazyradio:' + uri
                                     }
                    };
      info.url = info.device.url;
      info.deviceType = '/device/motive/crazyflie/3d';
      info.id = info.device.unit.udn;

      if (!!devices.devices[info.id]) return;

      logger2.info('crazyflie-3d', { url: info.url });
      devices.discover(info);
    }

    setTimeout(scan, 30 * 1000);
  }).done();
};

exports.start = function() {
  steward.actors.device.motive.crazyflie = steward.actors.device.motive.crazyflie ||
      { $info     : { type: '/device/motive/crazyflie' } };

  steward.actors.device.motive.crazyflie['3d'] =
      { $info     : { type       : '/device/motive/crazyflie/3d'
                    , observe    : [ ]
                    , perform    : [ 'takeoff'
                                   , 'hover'
                                   , 'land'
                                   , 'halt'
                                   , 'pitch'      // degrees: -180(down)..+180(up)           duration: milli-seconds
                                   , 'roll'       // degrees: +180(left)..-180(right)        duration: milli-seconds
                                   , 'yaw'        // degrees/second: +180(left)..-180(right) duration: milli-seconds
                                   , 'thrust'     // value: 0..100
                                   ]
                    , properties : { name          : true
                                   , status        : [ 'waiting', 'busy', 'ready', 'hovering', 'landing', 'down' ]
                                   , stabilizer    : { roll: 'degrees',      pitch: 'degrees',     yaw: 'degrees/second' }
                                   , acceleration  : { x: 'meters/second^2', y: 'meters/second^2', z: 'meters/second^2'  }
                                   , orientation   : { x: 'degrees/second',  y: 'degrees/second',  z: 'degrees/second'   }
                                   , thrust        : 'percentage'
                                   , batteryLevel  : 'percentage'
                                  }
                    }
      , $validate : { perform: validate_perform }
      };
  devices.makers['/device/motive/crazyflie/3d'] = QuadCopter;

  driver = new aerogel.CrazyDriver();
  scan();
};
<commit_msg>rename radio property<commit_after>// +++ under development
// The Crazyflie Nano Quadcopter -- http://www.bitcraze.se/crazyflie/

exports.start = function() {};
if (true) return;

var aerogel     = require('aerogel')
  , underscore  = require('underscore')
  , util        = require('util')
  , devices     = require('./../../core/device')
  , steward     = require('./../../core/steward')
  , utility     = require('./../../core/utility')
  , broker      = utility.broker
  , motive      = require('./../device-motive')
  ;

// var logger   = motive.logger;
var logger2  = utility.logger('discovery');

var driver;

var QuadCopter = exports.device = function(deviceID, deviceUID, info) {
  var self;

  self = this;

  self.whatami = info.deviceType;
  self.deviceID = deviceID.toString();
  self.deviceUID = deviceUID;
  self.name = info.device.name;
  self.getName();

  self.thrust = { min: 10001, max: 60000 };

  self.info = { thrust: 0 };

  self.status = 'waiting';
  self.changed();

  self.copter = new aerogel.Copter(driver);
  self.copter.on('stabilizer', function(data) {
    var stabilizer, thrust, updateP;

    updateP = false;
    thrust = devices.scaledLevel(Math.abs(data.thrust), self.thrust.min, self.thrust.max);
    if (self.info.thrust !== thrust) {
      self.info.thrust = thrust;
      updateP = true;
    }

    delete(data.thrust);
    stabilizer = f2(data);
    if (!underscore.isEqual(self.info.stabilizer, stabilizer)) {
      self.info.stabilizer = stabilizer;
      updateP = true;
    }

    if (updateP) self.changed();
  }).on('accelerometer', function(data) {
    var accelerometer = f2(data);

    if (!underscore.isEqual(self.info.acceleration, accelerometer)) {
      self.info.acceleration = accelerometer;
      self.changed();
    }
  }).on('gyroscope', function(data) {
    var gyroscope = f2(data);

    if (!underscore.isEqual(self.info.orientation, gyroscope)) {
      self.info.orientation = gyroscope;
      self.changed();
    }
  });
  self.copter.connect(info.radio).then(function() { self.status = 'ready'; self.changed(); }).done();

  broker.subscribe('actors', function(request, eventID, actor, observe, parameter) {
    if (actor !== ('device/' + self.deviceID)) return;

    if (request === 'observe') {
      if ((observe === 'cliff') || (observe === 'obstacle') || (observe === 'wall')) {
        self.events[eventID] = { observe: observe };
      }
      return;
    }
    if (request === 'perform') return self.perform(self, eventID, observe, parameter);
  });
};
util.inherits(QuadCopter, motive.Device);

var f2 = function(data) {
  var prop, props;

  props = {};
  for (prop in data) if (data.hasOwnProperty(prop)) props[prop] = data[prop].toFixed(2);

  return props;
};

QuadCopter.prototype.perform = function(self, taskID, perform, parameter) {
  var f, g, params;

  try { params = JSON.parse(parameter); } catch(ex) { params = {}; }

  g = function(dof) {
        var degrees, duration;

        degrees = parseFloat(params.degrees);
        if (isNaN(degrees) || (degrees < -180) || (degrees > 180)) return false;
        duration = parseInt(params.duration, 10);
        if (isNaN(duration) || (duration < 0) || (duration > 1000)) duration = 250;

        self.copter[dof](degrees);
        self.status = 'busy';
        setTimeout(function() { self.copter[dof](0); self.status = 'ready'; }, duration);

        return true;
      };

  f = { set     : function() {
                    return self.setName(params.name);
                  }

      , takeoff : function() {
                    self.copter.takeoff().then(function() {
                      self.copter.hover();
                      self.copter.setPitch(0);
                      self.copter.setRoll(0);
                      self.info.thrust = 40;
                      self.copter.setThrust(devices.scaledPercentage(self.info.thrust, self.thrust.min, self.thrust.max));

                      self.status = 'hovering';
                      self.changed();
                    });

                    self.changed();
                    return true;
                  }

      , hover   : function() {
                    self.copter.hover();

                    self.status = 'hovering';
                    self.changed();
                    return true;
                  }

      , land    : function() {
                    self.copter.land().then(function() {
                      self.status = 'ready';
                      self.changed();
                    });

                    self.status = 'landing';
                    self.changed();
                    return true;
                  }

      , halt    : function() {
                    self.copter.land().then(function() {
                      self.copter.shutdown();

                      self.status = 'down';
                      self.changed();
                    });

                    self.status = 'landing';
                    self.changed();
                    return true;
                  }

      , pitch   : function() {
                    return g('setPitch');
                  }

      , roll    : function() {
                    return g('setRoll');
                  }

      , yaw     : function() {
                    return g('setYaw');
                  }

      , thrust  : function() {
                    var thrust;

                    if (!params.value) return false;
                    thrust = parseInt(params.value, 10);
                    if ((thrust < 1) || (thrust > 100)) return false;

                    self.info.thrust = thrust;
                    self.copter.setThrust(devices.scaledPercentage(self.info.thrust, self.thrust.min, self.thrust.max));
                    self.changed();
                  }
     }[perform];
  if (!f) return false;

  return (f() && steward.performed(taskID));
};

exports.validThurst  = function(thrust)  { return ((0 <= thrust) && (thrust <= 100)); };

var validate_perform = function(perform, parameter) {
  var params = {}
    , result = { invalid: [], requires: [] }
    ;

  if (!!parameter) try { params = JSON.parse(parameter); } catch(ex) { result.invalid.push('parameter'); }

  var g = function(dof) {
            var degrees;

            if (!!params.degrees) {
              degrees = parseFloat(params.degrees);
              if (isNaN(degrees) || (degrees < -180) || (degrees > 180)) result.invalid.push(dof + '.degrees');
            } else result.requires.push(dof + '.degrees');

          };

  var f = { set     : function() { if (!params.name) result.requires('name'); }

          , takeoff : function() { }
          , hover   : function() { }
          , land    : function() { }
          , halt    : function() { }

          , pitch   : function() { g('pitch'); }
          , roll    : function() { g('roll'); }
          , yaw     : function() { g('yaw'); }

          , thrust  : function() {
                        var thrust;

                        if (!!params.value) {
                          thrust = parseInt(params.value, 10);
                          if ((thrust < 1) || (thrust > 100)) result.invalid.push('thrust.value');
                        } else result.requires.push('thrust.value');
                      }
         }[perform];
  if (f) f(); else result.invalid.push('perform');

  return result;
};

var uris = {};

var scan = function() {
  driver.findCopters().then(function(copters) {
    var i, info, uri;

    for (i = 0; i < copters.length; i++) {
      uri = copters[i];
      if (!!uris[uri]) continue;
      uris[uri] = true;

      info = { source: 'aerogel', radio: uri };
      info.device = { url          : null
                    , name         : ''
                    , manufacturer : 'Bitcraze'
                    , model        : { name        : 'Crazyflie'
                                     , description : 'Nano Quadcopter'
                                     , number      : ''
                                     }
                    , unit         : { serialNo    : uri
                                     , udn         : 'crazyradio:' + uri
                                     }
                    };
      info.url = info.device.url;
      info.deviceType = '/device/motive/crazyflie/3d';
      info.id = info.device.unit.udn;

      if (!!devices.devices[info.id]) return;

      logger2.info('crazyflie-3d', { url: info.url });
      devices.discover(info);
    }

    setTimeout(scan, 30 * 1000);
  }).done();
};

exports.start = function() {
  steward.actors.device.motive.crazyflie = steward.actors.device.motive.crazyflie ||
      { $info     : { type: '/device/motive/crazyflie' } };

  steward.actors.device.motive.crazyflie['3d'] =
      { $info     : { type       : '/device/motive/crazyflie/3d'
                    , observe    : [ ]
                    , perform    : [ 'takeoff'
                                   , 'hover'
                                   , 'land'
                                   , 'halt'
                                   , 'pitch'      // degrees: -180(down)..+180(up)           duration: milli-seconds
                                   , 'roll'       // degrees: +180(left)..-180(right)        duration: milli-seconds
                                   , 'yaw'        // degrees/second: +180(left)..-180(right) duration: milli-seconds
                                   , 'thrust'     // value: 0..100
                                   ]
                    , properties : { name          : true
                                   , status        : [ 'waiting', 'busy', 'ready', 'hovering', 'landing', 'down' ]
                                   , stabilizer    : { roll: 'degrees',      pitch: 'degrees',     yaw: 'degrees/second' }
                                   , acceleration  : { x: 'meters/second^2', y: 'meters/second^2', z: 'meters/second^2'  }
                                   , orientation   : { x: 'degrees/second',  y: 'degrees/second',  z: 'degrees/second'   }
                                   , thrust        : 'percentage'
                                   , batteryLevel  : 'percentage'
                                  }
                    }
      , $validate : { perform: validate_perform }
      };
  devices.makers['/device/motive/crazyflie/3d'] = QuadCopter;

  driver = new aerogel.CrazyDriver();
  scan();
};
<|endoftext|>