<commit_before>/*
 * Copyright (c) $year, Den Norske Turistforening (DNT)
 *
 * https://github.com/Turistforeningen/turadmin
 */

define(function (require, exports, module) {
    "use strict";

    // Dependencies
    var $ = require('jquery'),
        _ = require('underscore'),
        Backbone = require('backbone'),
        NtbEditorView = require('views/ntb/editor'),
        MapWrapper = require('views/map/wrapper'),
        RouteModel = require('models/route'),
        RouteDrawView = require('views/routes/draw'),
        PictureCollection = require('collections/pictures'),
        PictureManager = require('views/pictures/manager'),
        PoiCollection = require('collections/pois'),
        PoiManager = require('views/pois/manager'),
        MarkingModel = require('models/marking'),
        MarkingEdit = require('views/marking/edit'),
        RouteDetailsView = require('views/routes/details');

    require('backbone-stickit');
    require('backbone-validation');
    require('bootstrap');
    require('jquery-ssr');

    // Module
    return NtbEditorView.extend({

        el: '[data-view="app"]',

        initialize: function (options) {

            // Create model
            this.model = new RouteModel(options.routeData);

            // Create collections
            this.pictures = new PictureCollection(options.picturesData);
            this.pois = new PoiCollection(options.poisData);

            this.relatedCollections = [
                {
                    field: 'bilder',
                    collection: this.pictures,
                    destroyRemoved: true
                },
                {
                    field: 'steder',
                    collection: this.pois,
                    destroyRemoved: true
                }
            ];

            if (this.model.get('rute')) {
                // Create models
                this.marking = new MarkingModel(options.routeData.rute);

                this.relatedModels = [
                    {
                        field: 'rute',
                        model: this.marking
                    }
                ];
            }

            // Set up views

            this.mapWrapper = new MapWrapper({
                el: '[data-view="route-map"]',
                route: this.model,
                pictures: this.pictures,
                pois: this.pois
            }).render();

            this.routeDrawView = new RouteDrawView({
                model: this.model,
                pictures: this.pictures,
                map: this.mapWrapper
            }).render();

            this.pictureManager = new PictureManager({
                el: '[data-view="route-pictures"]',
                pictures: this.pictures,
                map: this.mapWrapper,
                messages: {
                    empty: 'Husk å legge inn bilder fra turen din, slik at det blir synlig på forsiden av UT.no'
                }
            }).render();

            this.poiManager = new PoiManager({
                el: '[data-view="route-pois"]',
                pois: this.pois,
                pictures: this.pictures,
                map: this.mapWrapper
            }).render();

            this.routeDetailsView = new RouteDetailsView({
                el: '[data-view="route-details"]',
                route: this.model
            }).render();

            if (this.model.get('rute')) {
                this.markingEdit = new MarkingEdit({
                    el: '[data-view="route-marking"]',
                    model: this.marking
                }).render();
            }

            this.listenTo(this.model, 'change:status', $.proxy(this.updatePublishButtons, this));

            NtbEditorView.prototype.initialize.call(this, options);
        },

        render: function () {
            $('body').scrollspy({target: '.navbar-app'});

            this.updatePublishButtons();
        },

        publish: function() {

            var isValid = this.model.isValid(true);

            if (isValid === true) {

                this.pictures.setPublished();
                this.pois.setPublished();

                this.model.set('status', 'Offentlig', {silent: true});

                this.save();

            } else {

                var doHide = 0;
                var hideTooltip = function () {
                    // NOTE: The first click event on publish button is fired twice. Because of that,
                    // the document click listener that will hide the tooltip can not be applied directly
                    // after the tooltip is shown, as that will cause the tooltip to be hidden on the "second"
                    // which is supposedly happening instantnly. That is the reason for this quite dirrrty hack.
                    if (doHide === 3) {
                        $('[data-action="do-publish"]').tooltip('hide');
                        $('[data-action="do-publish"]').on('hidden.bs.tooltip', function () {
                            $(document).off('click.tooltip');
                        });
                    }
                    doHide++;
                };

                $('[data-action="do-publish"]').on('shown.bs.tooltip', function () {
                    $(document).on('click.tooltip', $.proxy(function (e) {
                        hideTooltip();
                    }, this));
                });

                $('[data-action="do-publish"]').tooltip({
                    title: 'Stedet kan ikke publiseres uten at alle de påkrevde feltene er fylt ut.',
                    placement: 'bottom',
                    trigger: 'manual'
                }).tooltip('show');

                var $firstError = $('.has-error').first();

                $('html, body').animate({
                    scrollTop: ($firstError.offset().top - 80)
                }, 1000);
            }

            this.updatePublishButtons();

        },

        unpublish: function() {
            this.model.set('status', 'Kladd', {silent: true});
            this.pictures.setUnpublished();
            this.pois.setUnpublished();
            this.updatePublishButtons();
            this.save();
        }

    });

});
<commit_msg>Missing spaces<commit_after>/*
 * Copyright (c) $year, Den Norske Turistforening (DNT)
 *
 * https://github.com/Turistforeningen/turadmin
 */

define(function (require, exports, module) {
    "use strict";

    // Dependencies
    var $ = require('jquery'),
        _ = require('underscore'),
        Backbone = require('backbone'),
        NtbEditorView = require('views/ntb/editor'),
        MapWrapper = require('views/map/wrapper'),
        RouteModel = require('models/route'),
        RouteDrawView = require('views/routes/draw'),
        PictureCollection = require('collections/pictures'),
        PictureManager = require('views/pictures/manager'),
        PoiCollection = require('collections/pois'),
        PoiManager = require('views/pois/manager'),
        MarkingModel = require('models/marking'),
        MarkingEdit = require('views/marking/edit'),
        RouteDetailsView = require('views/routes/details');

    require('backbone-stickit');
    require('backbone-validation');
    require('bootstrap');
    require('jquery-ssr');

    // Module
    return NtbEditorView.extend({

        el: '[data-view="app"]',

        initialize: function (options) {

            // Create model
            this.model = new RouteModel(options.routeData);

            // Create collections
            this.pictures = new PictureCollection(options.picturesData);
            this.pois = new PoiCollection(options.poisData);

            this.relatedCollections = [
                {
                    field: 'bilder',
                    collection: this.pictures,
                    destroyRemoved: true
                },
                {
                    field: 'steder',
                    collection: this.pois,
                    destroyRemoved: true
                }
            ];

            if (this.model.get('rute')) {
                // Create models
                this.marking = new MarkingModel(options.routeData.rute);

                this.relatedModels = [
                    {
                        field: 'rute',
                        model: this.marking
                    }
                ];
            }

            // Set up views

            this.mapWrapper = new MapWrapper({
                el: '[data-view="route-map"]',
                route: this.model,
                pictures: this.pictures,
                pois: this.pois
            }).render();

            this.routeDrawView = new RouteDrawView({
                model: this.model,
                pictures: this.pictures,
                map: this.mapWrapper
            }).render();

            this.pictureManager = new PictureManager({
                el: '[data-view="route-pictures"]',
                pictures: this.pictures,
                map: this.mapWrapper,
                messages: {
                    empty: 'Husk å legge inn bilder fra turen din, slik at det blir synlig på forsiden av UT.no'
                }
            }).render();

            this.poiManager = new PoiManager({
                el: '[data-view="route-pois"]',
                pois: this.pois,
                pictures: this.pictures,
                map: this.mapWrapper
            }).render();

            this.routeDetailsView = new RouteDetailsView({
                el: '[data-view="route-details"]',
                route: this.model
            }).render();

            if (this.model.get('rute')) {
                this.markingEdit = new MarkingEdit({
                    el: '[data-view="route-marking"]',
                    model: this.marking
                }).render();
            }

            this.listenTo(this.model, 'change:status', $.proxy(this.updatePublishButtons, this));

            NtbEditorView.prototype.initialize.call(this, options);
        },

        render: function () {
            $('body').scrollspy({target: '.navbar-app'});

            this.updatePublishButtons();
        },

        publish: function () {

            var isValid = this.model.isValid(true);

            if (isValid === true) {

                this.pictures.setPublished();
                this.pois.setPublished();

                this.model.set('status', 'Offentlig', {silent: true});

                this.save();

            } else {

                var doHide = 0;
                var hideTooltip = function () {
                    // NOTE: The first click event on publish button is fired twice. Because of that,
                    // the document click listener that will hide the tooltip can not be applied directly
                    // after the tooltip is shown, as that will cause the tooltip to be hidden on the "second"
                    // which is supposedly happening instantnly. That is the reason for this quite dirrrty hack.
                    if (doHide === 3) {
                        $('[data-action="do-publish"]').tooltip('hide');
                        $('[data-action="do-publish"]').on('hidden.bs.tooltip', function () {
                            $(document).off('click.tooltip');
                        });
                    }
                    doHide++;
                };

                $('[data-action="do-publish"]').on('shown.bs.tooltip', function () {
                    $(document).on('click.tooltip', $.proxy(function (e) {
                        hideTooltip();
                    }, this));
                });

                $('[data-action="do-publish"]').tooltip({
                    title: 'Stedet kan ikke publiseres uten at alle de påkrevde feltene er fylt ut.',
                    placement: 'bottom',
                    trigger: 'manual'
                }).tooltip('show');

                var $firstError = $('.has-error').first();

                $('html, body').animate({
                    scrollTop: ($firstError.offset().top - 80)
                }, 1000);
            }

            this.updatePublishButtons();

        },

        unpublish: function () {
            this.model.set('status', 'Kladd', {silent: true});
            this.pictures.setUnpublished();
            this.pois.setUnpublished();
            this.updatePublishButtons();
            this.save();
        }

    });

});
<|endoftext|>


<commit_before>/* global app:true, io:false */

var socket;
var myname;
var block_id;
var pattern_array = [];
var pattern_string;

(function() {
  'use strict';

  /*socket = io.connect();
  socket.on('connect', function(){
  	socket.emit('/replay/#join');
  });

  socket.on('message', function (message) {
      console.log(message);
  });

  socket.on('disconnect', function() {
      console.log('>>> DB disconnected');
  });*/

  app = app || {};

  app.Reset = Backbone.Model.extend({
    defaults: {
      success: false,
      errors: [],
      errfor: {},
      blockid: undefined,
      confitm: ''
    },
    url: function(){
      return '/account/pattern/' + this.get('block_id') +'/';
    }
  });

  app.PatternView = Backbone.View.extend({
    el: '#pattern_menu',
    template: _.template( $('#tmpl-pattern_menu').html() ),
    events: {
      'click .btn-check': 'reqCheck',
      'click .btn-edit': 'reqEdit',
      'click .btn-submit': 'reqSubmit'
    },
    initialize: function() {
      //this.model = new app.Blocks();
      //this.listenTo(this.model, 'sync', this.render);
      this.render();
    },
    render: function() {
      this.$el.html(this.template);
    },
    reqCheck: function() {
      document.getElementById("btn_check").disabled = true;
      document.getElementById("btn_submit").disabled = false;
      document.getElementById("btn_edit").disabled = false;
      document.getElementById("pattern_input").disabled = true;
      var input = document.getElementById("pattern_input").value.split(/\n/);
      input = cleanArray(input);

      input.forEach(function(line){
	    var res = line.split(",");
	    var pattern = new Object();
	    pattern.id = res[0];
	    pattern.msec = res[1];
	    pattern.led = res[2];
	    pattern_array.push(pattern);
      });
      console.log(pattern_array);

      pattern_string = input.join("&&");
      console.log(pattern_string);

      drawVis(pattern_array);
    },
    reqEdit: function() {
      document.getElementById("btn_check").disabled = false;
      document.getElementById("btn_submit").disabled = true;
      document.getElementById("btn_edit").disabled = true;
      document.getElementById("pattern_input").disabled = false;
    },
    reqSubmit: function() {
      document.getElementById("btn_check").disabled = true;
      document.getElementById("btn_submit").disabled = true;
      document.getElementById("btn_edit").disabled = true;
      console.log("Submit");
    }
  });

  app.Router = Backbone.Router.extend({
    routes: {
      'account/pattern/': 'default',
      'account/pattern/load/:block/': 'load'
    },
    default: function(){
      console.log(" >>default view, nothing loaded");
    },
    load: function(block) {
      console.log(">> loading block "+block);
      block_id = block;
      var info_div = document.getElementById("info_box");
      var info_text = document.createElement("h6");
      var block_node = document.createTextNode("Pattern for [ block # "+block_id+" ]");
      var pattern_node = document.createTextNode(" -  [ pattern # "+" ]");
	info_text.appendChild(block_node);
	info_text.appendChild(pattern_node);
	info_div.appendChild(info_text);
      document.getElementById("btn_submit").disabled = true;
      document.getElementById("btn_edit").disabled = true;
      //socket.emit('/replay/#callblock', { targetBlock: block});
      setupVis();
    }
  });

  $(document).ready(function() {
    app.patternView = new app.PatternView();
    app.router = new app.Router();
    Backbone.history.start({ pushState: true });
  });
}());

function cleanArray(actual){
  var newArray = new Array();
  for(var i = 0; i<actual.length; i++){
      if (actual[i].length > 0){
        newArray.push(actual[i]);
    }
  }
  return newArray;
}

/////////////////////////////
// Canvas setup functions
/////////////////////////////

var svg_vis;
var margin = {top: 20, right: 20, bottom: 30, left: 60},
	width = 500 - margin.left - margin.right,
	height = 3600 - margin.top - margin.bottom;

function setupVis(){
    d3.select("#pattern_vis").selectAll("svg")
	.remove();

    svg_vis = d3.select("#pattern_vis").append("svg")
	.attr("width", width + margin.left + margin.right)
	.attr("height", height + margin.top + margin.bottom)
     .append("g")
	.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
}

function drawVis(data){
    var format = d3.time.format("%M:%S");
    var y = d3.time.scale()
	.domain([d3.time.minute.offset(new Date(0), 5), new Date(0)])
	.range([height, 0]);

    var color = d3.scale.category10();

    var yAxis = d3.svg.axis()
	.scale(y)
	.orient("left")
	.ticks(d3.time.seconds, 5)
	.tickFormat(format);

    svg_vis.append("g")
      .attr("class", "y axis")
      .call(yAxis);

    var plot = svg_vis.selectAll('.plot')
	  .data(data)
      .enter().append('rect')
	  .attr('class', 'spot')
	  .attr('x', function(d){
	      //console.log(d.msec-Math.floor(d.msec/5000)*5000);
	      return (d.msec-Math.floor(d.msec/1000)*1000)/2
	  })
	  .attr('y', function(d){
	      //console.log(y(d3.time.second.offset(new Date(0), Math.floor(d.msec/1000))));
	      return  y(d3.time.second.offset(new Date(0), Math.floor(d.msec/1000)))+1
	  })
	  .attr('width', 10)
	  .attr('height', 10);
      plot.append('text')
	  .attr('class', 'arrow')
	  .attr('font-family', 'FontAwesome')
	      .style('font-size', '100%' )
	      .attr("x",0)
	      .attr("y",0)
	      .text(function(d) { return '\uf023' });
	      //.style("display", function(d) {
	          //return d.lock == true ? null : "none";
	      //});

    svg_vis.append("g")
        .attr("class", "grid")
        .attr("transform", "translate(1,0)")
        .call(make_y_axis()
            .tickSize(-width, 0, 0)
            .tickFormat("")
        )

    function make_y_axis() {
	return d3.svg.axis()
	    .scale(y)
	    .orient("left")
	    .ticks(250)
    }
}

 /*   var frame = svg_data_vis.selectAll(".frame")
	    .data(d3data)
    .enter().append("g")
	    .attr("class", "block")
	    .attr("transform", function (d,i)
	    {
		    var dx = (i+1)%100*datavis_x_gap;
		    var dy = 20 + Math.floor((i+1)/100)*datavis_y_gap;
		    return "translate(" + dx + ","+ dy + ")";
	    });
	    //.on('mouseover', tip.show)
	    //.on('mouseout', tip.hide);

    frame.append("rect")
	    .attr("class", function (d,i)
	    {
		    var class_name;
		    if(i==current_frame){
		      class_name="current-frame";
		    }
		    else{
		      if (d.ledarray.length>0){
			    class_name="frame-with-led";
		      }else{
			    class_name="frame-no-led";
		      }

		    }
		    return class_name;
	    })
	    .attr("width", 8)
	    .attr("height", 8);*/
	    /*.attr("led", function (d){
		    if (d.ledarray.length>0){
			    return true;
		    }else{
			    return false
		    }
	    });*/
	    //.on('mouseover', tip.show)
	    //.on('mouseout', tip.hide)
	    //.on('click', mouseclick);
    /*frame.append("line")
	    .attr("class", function (d,i)
	    {
		    var class_name = "stroke-led";
		    return class_name;
	    })
	    .attr("x1", 4)
	    .attr("y1", 4)
	    .attr("x2", function (d){
	      if (d.ledarray.length>0) {
		var x2=0;

		d.ledarray.forEach(function(ele){
		  x2 = x2 + parseFloat(ele.arrow[1])*8 - parseFloat(ele.arrow[3])*8;
		});

		return 4 + x2/(d.ledarray.length)
	      }else{
		return 4
	      }
	    })
	    .attr("y2",function (d){
	      if (d.ledarray.length>0) {
		var y2=0;

		d.ledarray.forEach(function(ele){
		  y2 = y2 + parseFloat(ele.arrow[0])*8 - parseFloat(ele.arrow[2])*8;
		});

		return 4 + y2/(d.ledarray.length)
	      }else{
		return 4
	      }

	      return 4
	    });
	    */<commit_msg>pattern vis grid<commit_after>/* global app:true, io:false */

var socket;
var myname;
var block_id;
var pattern_array = [];
var pattern_string;

(function() {
  'use strict';

  /*socket = io.connect();
  socket.on('connect', function(){
  	socket.emit('/replay/#join');
  });

  socket.on('message', function (message) {
      console.log(message);
  });

  socket.on('disconnect', function() {
      console.log('>>> DB disconnected');
  });*/

  app = app || {};

  app.Reset = Backbone.Model.extend({
    defaults: {
      success: false,
      errors: [],
      errfor: {},
      blockid: undefined,
      confitm: ''
    },
    url: function(){
      return '/account/pattern/' + this.get('block_id') +'/';
    }
  });

  app.PatternView = Backbone.View.extend({
    el: '#pattern_menu',
    template: _.template( $('#tmpl-pattern_menu').html() ),
    events: {
      'click .btn-check': 'reqCheck',
      'click .btn-edit': 'reqEdit',
      'click .btn-submit': 'reqSubmit'
    },
    initialize: function() {
      //this.model = new app.Blocks();
      //this.listenTo(this.model, 'sync', this.render);
      this.render();
    },
    render: function() {
      this.$el.html(this.template);
    },
    reqCheck: function() {
      document.getElementById("btn_check").disabled = true;
      document.getElementById("btn_submit").disabled = false;
      document.getElementById("btn_edit").disabled = false;
      document.getElementById("pattern_input").disabled = true;
      var input = document.getElementById("pattern_input").value.split(/\n/);
      input = cleanArray(input);

      input.forEach(function(line){
	    var res = line.split(",");
	    var pattern = new Object();
	    pattern.id = res[0];
	    pattern.msec = res[1];
	    pattern.led = res[2];
	    pattern_array.push(pattern);
      });
      console.log(pattern_array);

      pattern_string = input.join("&&");
      console.log(pattern_string);

      drawVis(pattern_array);
    },
    reqEdit: function() {
      document.getElementById("btn_check").disabled = false;
      document.getElementById("btn_submit").disabled = true;
      document.getElementById("btn_edit").disabled = true;
      document.getElementById("pattern_input").disabled = false;
    },
    reqSubmit: function() {
      document.getElementById("btn_check").disabled = true;
      document.getElementById("btn_submit").disabled = true;
      document.getElementById("btn_edit").disabled = true;
      console.log("Submit");
    }
  });

  app.Router = Backbone.Router.extend({
    routes: {
      'account/pattern/': 'default',
      'account/pattern/load/:block/': 'load'
    },
    default: function(){
      console.log(" >>default view, nothing loaded");
    },
    load: function(block) {
      console.log(">> loading block "+block);
      block_id = block;
      var info_div = document.getElementById("info_box");
      var info_text = document.createElement("h6");
      var block_node = document.createTextNode("Pattern for [ block # "+block_id+" ]");
      var pattern_node = document.createTextNode(" -  [ pattern # "+" ]");
	info_text.appendChild(block_node);
	info_text.appendChild(pattern_node);
	info_div.appendChild(info_text);
      document.getElementById("btn_submit").disabled = true;
      document.getElementById("btn_edit").disabled = true;
      //socket.emit('/replay/#callblock', { targetBlock: block});
      setupVis();
    }
  });

  $(document).ready(function() {
    app.patternView = new app.PatternView();
    app.router = new app.Router();
    Backbone.history.start({ pushState: true });
  });
}());

function cleanArray(actual){
  var newArray = new Array();
  for(var i = 0; i<actual.length; i++){
      if (actual[i].length > 0){
        newArray.push(actual[i]);
    }
  }
  return newArray;
}

/////////////////////////////
// Canvas setup functions
/////////////////////////////

var svg_vis;
var margin = {top: 20, right: 20, bottom: 30, left: 60},
	width = 600 - margin.left - margin.right,
	height = 3600 - margin.top - margin.bottom;

function setupVis(){
    d3.select("#pattern_vis").selectAll("svg")
	.remove();

    svg_vis = d3.select("#pattern_vis").append("svg")
	.attr("width", width + margin.left + margin.right)
	.attr("height", height + margin.top + margin.bottom)
     .append("g")
	.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
}

function drawVis(data){
    var format = d3.time.format("%M:%S");
    var y = d3.time.scale()
	.domain([d3.time.minute.offset(new Date(0), 5), new Date(0)])
	.range([height, 0]);

    var color = d3.scale.category10();

    var yAxis = d3.svg.axis()
	.scale(y)
	.orient("left")
	.ticks(d3.time.seconds, 5)
	.tickFormat(format);

    svg_vis.append("g")
      .attr("class", "y axis")
      .call(yAxis);

    var plot = svg_vis.selectAll('.plot')
	  .data(data)
      .enter().append('rect')
	  .attr('class', 'spot')
	  .attr('x', function(d){
	      //console.log(d.msec-Math.floor(d.msec/5000)*5000);
	      return (d.msec-Math.floor(d.msec/1000)*1000)/2
	  })
	  .attr('y', function(d){
	      //console.log(y(d3.time.second.offset(new Date(0), Math.floor(d.msec/1000))));
	      return  y(d3.time.second.offset(new Date(0), Math.floor(d.msec/1000)))+1
	  })
	  .attr('width', 10)
	  .attr('height', 10);
      plot.append('text')
	  .attr('class', 'arrow')
	  .attr('font-family', 'FontAwesome')
	      .style('font-size', '100%' )
	      .attr("x",0)
	      .attr("y",0)
	      .text(function(d) { return '\uf023' });
	      //.style("display", function(d) {
	          //return d.lock == true ? null : "none";
	      //});

    svg_vis.append("g")
        .attr("class", "grid")
        .attr("transform", "translate(1,0)")
        .call(make_y_axis()
            .tickSize(-width, 0, 0)
            .tickFormat("")
        )

    function make_y_axis() {
	return d3.svg.axis()
	    .scale(y)
	    .orient("left")
	    .ticks(250)
    }
}

 /*   var frame = svg_data_vis.selectAll(".frame")
	    .data(d3data)
    .enter().append("g")
	    .attr("class", "block")
	    .attr("transform", function (d,i)
	    {
		    var dx = (i+1)%100*datavis_x_gap;
		    var dy = 20 + Math.floor((i+1)/100)*datavis_y_gap;
		    return "translate(" + dx + ","+ dy + ")";
	    });
	    //.on('mouseover', tip.show)
	    //.on('mouseout', tip.hide);

    frame.append("rect")
	    .attr("class", function (d,i)
	    {
		    var class_name;
		    if(i==current_frame){
		      class_name="current-frame";
		    }
		    else{
		      if (d.ledarray.length>0){
			    class_name="frame-with-led";
		      }else{
			    class_name="frame-no-led";
		      }

		    }
		    return class_name;
	    })
	    .attr("width", 8)
	    .attr("height", 8);*/
	    /*.attr("led", function (d){
		    if (d.ledarray.length>0){
			    return true;
		    }else{
			    return false
		    }
	    });*/
	    //.on('mouseover', tip.show)
	    //.on('mouseout', tip.hide)
	    //.on('click', mouseclick);
    /*frame.append("line")
	    .attr("class", function (d,i)
	    {
		    var class_name = "stroke-led";
		    return class_name;
	    })
	    .attr("x1", 4)
	    .attr("y1", 4)
	    .attr("x2", function (d){
	      if (d.ledarray.length>0) {
		var x2=0;

		d.ledarray.forEach(function(ele){
		  x2 = x2 + parseFloat(ele.arrow[1])*8 - parseFloat(ele.arrow[3])*8;
		});

		return 4 + x2/(d.ledarray.length)
	      }else{
		return 4
	      }
	    })
	    .attr("y2",function (d){
	      if (d.ledarray.length>0) {
		var y2=0;

		d.ledarray.forEach(function(ele){
		  y2 = y2 + parseFloat(ele.arrow[0])*8 - parseFloat(ele.arrow[2])*8;
		});

		return 4 + y2/(d.ledarray.length)
	      }else{
		return 4
	      }

	      return 4
	    });
	    */<|endoftext|>


<commit_before>if (typeof Noonworks === 'undefined') {
    var Noonworks = {};
}
if (typeof Noonworks.MenuBuilder === 'undefined') {
    Noonworks.MenuBuilder = function() {
        var need_sep = false;
        this.menu = {};
        this.count = 0;
        this.addItem = function(name, item) {
            if (item === null) {
                return false;
            }
            if (this.need_sep) {
                this.addSep();
                this.need_sep = false;
            }
            var menu_name = name;
            var i = 2;
            while (menu_name in this.menu) {
                menu_name = name + ' (' + i + ')';
                i++;
            }
            this.menu[menu_name] = item;
            this.count++;
            return true;
        };
        this.addSep = function() {
            this.menu[Noonworks.MenuBuilder.randomSepString()] = 'sep';
        };
        this.minify = function(str, num) {
            return Noonworks.MenuBuilder.minifyString(str, num);
        };
    };
    Noonworks.MenuBuilder.minifyString = function(str, num) {
        if (str.length <= num) {
            return str;
        }
        if (num < 2) {
            return str.substring(0, num);
        }
        var len = num / 2;
        return str.substring(0, len) + ' … ' +
            str.substring(str.length - len, str.length);
    };
    Noonworks.MenuBuilder.randomSepString = function() {
        return '----' + (new Date()).getTime() +
            'abcdefghijklmnopqrstuvwxyz'.substring(Math.floor(Math.random() * 10), 26);
    };
}
<commit_msg>Add MenuBuilder::isGrown.<commit_after>if (typeof Noonworks === 'undefined') {
    var Noonworks = {};
}
if (typeof Noonworks.MenuBuilder === 'undefined') {
    Noonworks.MenuBuilder = function() {
        var need_sep = false;
        this.menu = {};
        this.count = 0;
        this._pre_count = 0;
        this.addItem = function(name, item) {
            if (item === null) {
                return false;
            }
            if (this.need_sep) {
                this.addSep();
                this.need_sep = false;
            }
            var menu_name = name;
            var i = 2;
            while (menu_name in this.menu) {
                menu_name = name + ' (' + i + ')';
                i++;
            }
            this.menu[menu_name] = item;
            this.count++;
            return true;
        };
        this.addSep = function() {
            this.menu[Noonworks.MenuBuilder.randomSepString()] = 'sep';
        };
        this.minify = function(str, num) {
            return Noonworks.MenuBuilder.minifyString(str, num);
        };
        this.isGrown = function() {
            var ret = (this._pre_count < this.count);
            this._pre_count = this.count;
            return ret;
        };
    };
    Noonworks.MenuBuilder.minifyString = function(str, num) {
        if (str.length <= num) {
            return str;
        }
        if (num < 2) {
            return str.substring(0, num);
        }
        var len = num / 2;
        return str.substring(0, len) + ' … ' +
            str.substring(str.length - len, str.length);
    };
    Noonworks.MenuBuilder.randomSepString = function() {
        return '----' + (new Date()).getTime() +
            'abcdefghijklmnopqrstuvwxyz'.substring(Math.floor(Math.random() * 10), 26);
    };
}
<|endoftext|>


<commit_before>import React from 'react';
import { List } from 'antd';
import './FinalesPendientes.css';

const FinalesPendientes = ({ materias, updateEstado }) => {

  const pendientesDeFinal = materias.filter(m => m.final === true && m.status === 3);

  return (

      <List
        itemLayout="horizontal"
        dataSource={pendientesDeFinal}
        renderItem={item => (
          <List.Item actions={[
             updateEstado({ id: item.id, status: '4' })}
              onKeyPress={() => {}}
            >
              Aprobada

          ]}
          >
            <List.Item.Meta title={{item.name}} />
          </List.Item>
         )}
      />

  );

}

export default FinalesPendientes;
<commit_msg>Materias pendientes de final: texto cuando no hay finales pendientes.<commit_after>import React from 'react';
import { List } from 'antd';
import './FinalesPendientes.css';

const FinalesPendientes = ({ materias, updateEstado }) => {

  const pendientesDeFinal = materias.filter(m => m.final === true && m.status === 3);

  if(pendientesDeFinal.length === 0)
	return (

		No existen materias pendientes de final.

	   No tenés materias pendientes de final. Una vez que termines la cursada de una materia y marques la misma como firmada la misma aparecera en este área.

	);

  return (

      <List
        itemLayout="horizontal"
        dataSource={pendientesDeFinal}
        renderItem={item => (
          <List.Item actions={[
             updateEstado({ id: item.id, status: '4' })}
              onKeyPress={() => {}}
            >
              Aprobada

          ]}
          >
            <List.Item.Meta title={{item.name}} />
          </List.Item>
         )}
      />

  );

}

export default FinalesPendientes;
<|endoftext|>


<commit_before><commit_msg>Fix dates on Dashboard chart.<commit_after><|endoftext|>


<commit_before>/*jslint indent: 2, nomen: true, maxlen: 120 */
/*global module, require, exports */

////////////////////////////////////////////////////////////////////////////////
/// @brief Foxx Request Context
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2013 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Lucas Dohmen
/// @author Copyright 2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

var RequestContext,
  extend = require("underscore").extend,
  internal = require("org/arangodb/foxx/internals");

////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_RequestContext_initializer
/// @brief Context of a Request Definition
///
/// Used for documenting and constraining the routes.
////////////////////////////////////////////////////////////////////////////////

RequestContext = function (route) {
  'use strict';
  this.route = route;
  this.typeToRegex = {
    "int": "/[0-9]+/",
    "string": "/.+/"
  };
  this.route.docs.nickname = internal.constructNickname(route.docs.httpMethod, route.url.match);
};

extend(RequestContext.prototype, {

////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_RequestContext_pathParam
/// @brief Describe a path parameter
///
/// meow
////////////////////////////////////////////////////////////////////////////////

  pathParam: function (paramName, attributes) {
    'use strict';
    var url = this.route.url,
      docs = this.route.docs,
      constraint = url.constraint || {};

    constraint[paramName] = this.typeToRegex[attributes.dataType];
    this.route.url = internal.constructUrlObject(url.match, constraint, url.methods[0]);
    this.route.docs.parameters.push(internal.constructPathParamDoc(
      paramName,
      attributes.description,
      attributes.dataType
    ));
    return this;
  },

////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_RequestContext_queryParam
/// @brief Describe a Query Parameter
///
/// @FUN{FoxxApplication::queryParam(@FA{id}, @FA{options})}
///
/// Describe a query parameter:
///
/// If you defined a route "/foxx", you can constrain which format a query
/// parameter (`/foxx?a=12`) can have by giving it a type.  We currently support
/// the following types:
///
/// * int
/// * string
///
/// You can also provide a description of this parameter, if it is required and
/// if you can provide the parameter multiple times.
///
/// @EXAMPLES
///
/// @code
///     app.get("/foxx", function {
///       // Do something
///     }).queryParam("id", {
///       description: "Id of the Foxx",
///       dataType: "int",
///       required: true,
///       allowMultiple: false
///     });
/// @endcode
////////////////////////////////////////////////////////////////////////////////

  queryParam: function (paramName, attributes) {
    'use strict';
    this.route.docs.parameters.push(internal.constructQueryParamDoc(
      paramName,
      attributes.description,
      attributes.dataType,
      attributes.required,
      attributes.allowMultiple
    ));
    return this;
  },

////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_RequestContext_summary
/// @brief Set the summary for this route in the documentation
///
/// @FUN{FoxxApplication::summary(@FA{description})}
///
/// Set the summary for this route in the documentation. Can't be longer than 60.
/// characters
////////////////////////////////////////////////////////////////////////////////

  summary: function (summary) {
    'use strict';
    if (summary.length > 60) {
      throw new Error("Summary can't be longer than 60 characters");
    }
    this.route.docs.summary = summary;
    return this;
  },

////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_RequestContext_notes
/// @brief Set the notes for this route in the documentation
///
/// @FUN{FoxxApplication::notes(@FA{description})}
///
/// Set the notes for this route in the documentation
////////////////////////////////////////////////////////////////////////////////

  notes: function (notes) {
    'use strict';
    this.route.docs.notes = notes;
    return this;
  },

////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_RequestContext_errorResponse
/// @brief Document an error response
///
/// @FUN{FoxxApplication::errorResponse(@FA{code}, @FA{description})}
///
/// Document the error response for a given error @FA{code} with a reason for
/// the occurrence.
////////////////////////////////////////////////////////////////////////////////

  errorResponse: function (code, reason) {
    'use strict';
    this.route.docs.errorResponses.push(internal.constructErrorResponseDoc(code, reason));
    return this;
  }
});

exports.RequestContext = RequestContext;

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

/// Local Variables:
/// mode: outline-minor
/// outline-regexp: "/// @brief\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\|/\\*jslint"
/// End:
<commit_msg>Foxx: Separated the idea of documentation and the concept of annotation<commit_after>/*jslint indent: 2, nomen: true, maxlen: 120 */
/*global module, require, exports */

////////////////////////////////////////////////////////////////////////////////
/// @brief Foxx Request Context
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2013 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Lucas Dohmen
/// @author Copyright 2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////

var RequestContext,
  SwaggerDocs,
  extend = require("underscore").extend,
  internal = require("org/arangodb/foxx/internals");

// Wraps the docs object of a route to add swagger compatible documentation
SwaggerDocs = function (docs) {
  this.docs = docs;
};

extend(SwaggerDocs.prototype, {
  addNickname: function (httpMethod, match) {
    this.docs.nickname = internal.constructNickname(httpMethod, match);
  },

  addPathParam: function (paramName, description, dataType) {
    this.docs.parameters.push(internal.constructPathParamDoc(paramName, description, dataType));
  },

  addQueryParam: function (paramName, description, dataType, required, allowMultiple) {
    this.docs.parameters.push(internal.constructQueryParamDoc(
      paramName,
      description,
      dataType,
      required,
      allowMultiple
    ));
  },

  addSummary: function (summary) {
    this.docs.summary = summary;
  },

  addNotes: function (notes) {
    this.docs.notes = notes;
  }
});

////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_RequestContext_initializer
/// @brief Context of a Request Definition
///
/// Used for documenting and constraining the routes.
////////////////////////////////////////////////////////////////////////////////

RequestContext = function (route) {
  'use strict';
  this.route = route;
  this.typeToRegex = {
    "int": "/[0-9]+/",
    "string": "/.+/"
  };
  this.docs = new SwaggerDocs(this.route.docs);
  this.docs.addNickname(route.docs.httpMethod, route.url.match);
};

extend(RequestContext.prototype, {

////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_RequestContext_pathParam
/// @brief Describe a path parameter
///
/// meow
////////////////////////////////////////////////////////////////////////////////

  pathParam: function (paramName, attributes) {
    'use strict';
    var url = this.route.url,
      docs = this.route.docs,
      constraint = url.constraint || {};

    constraint[paramName] = this.typeToRegex[attributes.dataType];
    this.route.url = internal.constructUrlObject(url.match, constraint, url.methods[0]);
    this.docs.addPathParam(paramName, attributes.description, attributes.dataType);
    return this;
  },

////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_RequestContext_queryParam
/// @brief Describe a Query Parameter
///
/// @FUN{FoxxApplication::queryParam(@FA{id}, @FA{options})}
///
/// Describe a query parameter:
///
/// If you defined a route "/foxx", you can constrain which format a query
/// parameter (`/foxx?a=12`) can have by giving it a type.  We currently support
/// the following types:
///
/// * int
/// * string
///
/// You can also provide a description of this parameter, if it is required and
/// if you can provide the parameter multiple times.
///
/// @EXAMPLES
///
/// @code
///     app.get("/foxx", function {
///       // Do something
///     }).queryParam("id", {
///       description: "Id of the Foxx",
///       dataType: "int",
///       required: true,
///       allowMultiple: false
///     });
/// @endcode
////////////////////////////////////////////////////////////////////////////////

  queryParam: function (paramName, attributes) {
    'use strict';
    this.docs.addQueryParam(
      paramName,
      attributes.description,
      attributes.dataType,
      attributes.required,
      attributes.allowMultiple
    );
    return this;
  },

////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_RequestContext_summary
/// @brief Set the summary for this route in the documentation
///
/// @FUN{FoxxApplication::summary(@FA{description})}
///
/// Set the summary for this route in the documentation. Can't be longer than 60.
/// characters
////////////////////////////////////////////////////////////////////////////////

  summary: function (summary) {
    'use strict';
    if (summary.length > 60) {
      throw new Error("Summary can't be longer than 60 characters");
    }
    this.docs.addSummary(summary);
    return this;
  },

////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_RequestContext_notes
/// @brief Set the notes for this route in the documentation
///
/// @FUN{FoxxApplication::notes(@FA{description})}
///
/// Set the notes for this route in the documentation
////////////////////////////////////////////////////////////////////////////////

  notes: function (notes) {
    'use strict';
    this.docs.addNotes(notes);
    return this;
  },

////////////////////////////////////////////////////////////////////////////////
/// @fn JSF_foxx_RequestContext_errorResponse
/// @brief Document an error response
///
/// @FUN{FoxxApplication::errorResponse(@FA{code}, @FA{description})}
///
/// Document the error response for a given error @FA{code} with a reason for
/// the occurrence.
////////////////////////////////////////////////////////////////////////////////

  errorResponse: function (code, reason) {
    'use strict';
    this.route.docs.errorResponses.push(internal.constructErrorResponseDoc(code, reason));
    return this;
  }
});

exports.RequestContext = RequestContext;

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

/// Local Variables:
/// mode: outline-minor
/// outline-regexp: "/// @brief\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}\\|/\\*jslint"
/// End:
<|endoftext|>


<commit_before>define([
      'jquery', 'underscore', 'backbone'
], function($, _, Backbone) {
  return Backbone.Model.extend({
    getValues: function(){
      return _.reduce(this.get("fields"), function(o, v, k){
        o[k]  = v["value"];
        return o;
      }, {});
    }
    , idFriendlyTitle: function(){
      return this.get("title").replace(/\W/g,'').toLowerCase();
    }
    , setField: function(name, value) {
      var fields = this.get("fields")
      fields[name]["value"] = value;
      this.set("fields", fields);
      debugger;
    }
  });
});
<commit_msg>grep -r --incude '*.js' debugger .<commit_after>define([
      'jquery', 'underscore', 'backbone'
], function($, _, Backbone) {
  return Backbone.Model.extend({
    getValues: function(){
      return _.reduce(this.get("fields"), function(o, v, k){
        o[k]  = v["value"];
        return o;
      }, {});
    }
    , idFriendlyTitle: function(){
      return this.get("title").replace(/\W/g,'').toLowerCase();
    }
    , setField: function(name, value) {
      var fields = this.get("fields")
      fields[name]["value"] = value;
      this.set("fields", fields);
    }
  });
});
<|endoftext|>


<commit_before>requirejs(['app', 'bridge', 'ace/ace'], function (app, Bridge, ace) {

    /**
     * HighlightEntity
     * This highlights SketchUp entities and points and colors when hovering the console.
     */

    // Add CSS rules
    var className = 'highlight_entity';
    ace.require('ace/lib/dom').importCssString("\
.highlight_entity {             \
    border: 1px solid #eeeeee;  \
    border-color: rgba(200, 200, 200, 0.3);\
    margin: -1px;               \
    display: inline-block;      \
}                               \
                                \
.highlight_entity:hover {       \
    color: Highlight;           \
    border-color: Highlight;    \
}                               \
");

    function stop () {
        Bridge.call('highlight_stop');
    }

    var regexpEntity       = /#(?:<|<|<)Sketchup\:\:(?:Face|Edge|Curve|ArcCurve|Image|Group|ComponentInstance|ComponentDefinition|Text|Drawingelement|ConstructionLine|ConstructionPoint|Vertex)\:([0-9abcdefx]+)(?:>|>|>)/,
        regexpBoundingBox  = /#(?:<|<|<)Geom\:\:BoundingBox\:([0-9abcdefx]+)(?:>|>|>)/,
        regexpPoint        = /Point3d\(([0-9\.\-eE]+),[\s\u00a0]*([0-9\.\-eE]+),[\s\u00a0]*([0-9\.\-eE]+)\)/,
        regexpPointString  = /(?!Point3d)\(([0-9\.\,\-eE]+)(?:m|\"|\'|cm|mm),[\s\u00a0]*([0-9\.\,\-eE]+)(?:m|\"|\'|cm|mm),[\s\u00a0]*([0-9\.\,\-eE]+)(m|\"|\'|cm|mm)\)/,
        regexpVector       = /Vector3d\(([0-9\.\-eE]+),[\s\u00a0]*([0-9\.\-eE]+),[\s\u00a0]*([0-9\.\-eE]+)\)/,
        regexpVectorString = /\(([0-9\.\-eE]+),[\s\u00a0]*([0-9\.\-eE]+),[\s\u00a0]*([0-9\.\-eE]+)\)/,
        regexpColor        = /Color\(([\s\u00a0]*[0-9\.]+,[\s\u00a0]*[0-9\.]+,[\s\u00a0]*[0-9\.]+)(,[\s\u00a0]*[0-9\.]+)?\)/,
        regexpColorInspect = /#(?:<|<|<)Sketchup\:\:Color\:([0-9abcdefx]+)(?:>|>|>)/;

    function detectVisualizableElements(htmlElement) {
        $(htmlElement).find('.ace_sketchup').each(function(index, element) {
            var $element = $(element);
            var text = $element.text();
            if (regexpEntity.test(text) || regexpBoundingBox.test(text)) {
                addEntityHighlight($element, RegExp);
            } else if (regexpPoint.test(text)) {
                addPointWithoutUnitsHighlight($element, RegExp);
            } else if (regexpPointString.test(text)) {
                addPointWithUnitsHighlight($element, RegExp);
            } else if (regexpVector.test(text) || regexpVectorString.test(text)) {
                addVectorHighlight($element, RegExp);
            } else if (regexpColor.test(text)) {
                addColorHighlight($element, RegExp);
            } else if (regexpColorInspect.test(text)) {
                addColorInspectHighlight($element, RegExp);
            }
        });
    }

    function addEntityHighlight($element, regExp) {
        // Add highlight feature to SketchUp entities and get their id.
        var idString = regExp.$1;
        $element.addClass(className)
        .data('type', 'entity')
        .data('identifier', idString)
        .on('mouseover', function() { // Note: This can trigger repeatedly!
            Bridge.get('highlight_entity', idString)['catch'](function () {
                // If the entity isn't valid (deleted or GC), remove the highlight feature.
                $element.removeClass(className);
                $element.off('mouseover');
                $element.off('mouseout');
            });
        })
        .on('mouseout', stop);
    }

    function addPointWithoutUnitsHighlight($element, regExp) {
        // Add highlight feature to Point3d (without units: units = 'inch')
        var coordinates = [parseFloat(regExp.$1), parseFloat(regExp.$2), parseFloat(regExp.$3)];
        $element.addClass(className)
        .data('type', 'point')
        .data('identifier', [coordinates, 'inch'])
        .on('mouseover', function() {
            Bridge.call('highlight_point', coordinates);
        })
        .on('mouseout', stop);
    }

    function addPointWithUnitsHighlight($element, regExp) {
        // Add highlight feature to Point3d string with units
        var coordinates = $([regExp.$1, regExp.$2, regExp.$3]).map(function(index, coordinate){
            return parseFloat(coordinate.replace(/\,(?=[\d])/, '.'));
        });
        var units = regExp.$4;
        // Replace unit names so they don't need escaping.
        switch (units) {
            case '"':
                units = 'inch';
                break;
            case "'":
                units = 'feet';
                break;
        }
        $element.addClass(className)
        .data('type', 'point')
        .data('identifier', [coordinates, units])
        .on('mouseover', function() {
            Bridge.call('highlight_point', coordinates, units);
        })
        .on('mouseout', stop);
    }

    function addVectorHighlight($element, regExp) {
        // Add highlight feature to Vector3d or Vector3d string
        var coordinates = [parseFloat(regExp.$1), parseFloat(regExp.$2), parseFloat(regExp.$3)];
        $element.addClass(className)
        .data('type', 'vector')
        .data('identifier', coordinates)
        .on('mouseover', function() {
            Bridge.call('highlight_vector', coordinates);
        })
        .on('mouseout', stop);
    }

    function addColorHighlight($element, regExp) {
        // Add highlight feature to Color (only HTML/JS)
        // when color has been printed as numerical color values.
        addColorHighlightToHTMLElement($element, 'rgb(' + regExp.$1 + ')');
    }

    function addColorInspectHighlight($element, regExp) {
        // Add highlight feature to Color (only HTML/JS)
        // when color has been printed as Ruby object with id.
        var idString = regExp.$1;
        Bridge.get('get_color', idString).then(function (colorArray) {
          addColorHighlightToHTMLElement($element, 'rgb(' + colorArray.slice(0, 3).join(',') + ')');
        }, function () {
            // If the entity isn't valid (deleted or GC), remove the highlight feature.
            $element.removeClass(className);
            $element.off('mouseover');
            $element.off('mouseout');
        });
    }

    function addColorHighlightToHTMLElement($element, colorString) {
        $element.addClass(className)
        .on('mouseover', function() {
            $(this).css('background-color', colorString);
        }).on('mouseout', function() {
            $(this).css('background-color', 'transparent');
        });
    }

    function detectContainerElements(htmlElement) {
        // Find arrays that contain only elements that can be visualized (SketchUp entities, points, vectors)
        // Begin of an array.
        var arrayStart = $(htmlElement).find('.ace_paren.ace_lparen'),
            arrayEnd,
            currentElement = arrayStart,
            nextElement,
            arrayElements = [],
            dataToHighlight = {
              entity: [],
              point: [],
              vector: []
            };
        while (true) {
            nextElement = currentElement.next(); // Or comma, but text nodes are ignored by jQuery.
            if (nextElement.length == 0) {
                // No element. Something is wrong, end the traversal.
                arrayElements.length = 0;
                break;
            } else if (nextElement.hasClass('highlight_entity')) { // or 'highlight_entity'
                // This is a visualizable element, add it.
                arrayElements.push(nextElement);
                dataToHighlight[nextElement.data('type')].push(nextElement.data('identifier'));
            } else if (nextElement.hasClass('ace_rparen')) {
                arrayEnd = nextElement;
                // End of the array.
                break;
            }
            currentElement = nextElement;
        }
        if (arrayElements.length != 0) {
            var container = $('').addClass(className);
            container.on('mouseenter', function () {
                Bridge.get('highlight_multiple', dataToHighlight)['catch'](function () {
                    // If one of the entities isn't valid (deleted or GC), remove the highlight feature.
                    container.removeClass(className);
                    container.off('mouseover');
                    container.off('mouseout');
                });
            }).on('mouseout', stop);
            var contents = arrayStart.parent().contents(); // Includes text nodes
            contents.slice(contents.index(arrayStart), contents.index(arrayEnd)+1).wrapAll(container);
        }
    }

    app.output.addListener('added', function (htmlElement, text, metadata) {
        if (metadata.type && /input|result|puts|print/.test(metadata.type) && !/javascript/.test(metadata.type)) {
            detectVisualizableElements(htmlElement);
            detectContainerElements(htmlElement);
        }
    });
});
<commit_msg>If not html (elements marked by tokenizer) but plain text, search highlighable elements with regexp.<commit_after>requirejs(['app', 'bridge', 'ace/ace'], function (app, Bridge, ace) {

    /**
     * HighlightEntity
     * This highlights SketchUp entities and points and colors when hovering the console.
     */

    // Add CSS rules
    var className = 'highlight_entity';
    ace.require('ace/lib/dom').importCssString("\
.highlight_entity {             \
    border: 1px solid #eeeeee;  \
    border-color: rgba(200, 200, 200, 0.3);\
    margin: -1px;               \
    display: inline-block;      \
}                               \
                                \
.highlight_entity:hover {       \
    color: Highlight;           \
    border-color: Highlight;    \
}                               \
");

    function stop () {
        Bridge.call('highlight_stop');
    }

    var regexpEntity       = /#(?:<|<|<)Sketchup\:\:(?:Face|Edge|Curve|ArcCurve|Image|Group|ComponentInstance|ComponentDefinition|Text|Drawingelement|ConstructionLine|ConstructionPoint|Vertex)\:([0-9abcdefx]+)(?:>|>|>)/,
        regexpBoundingBox  = /#(?:<|<|<)Geom\:\:BoundingBox\:([0-9abcdefx]+)(?:>|>|>)/,
        regexpPoint        = /Point3d\(([0-9\.\-eE]+),[\s\u00a0]*([0-9\.\-eE]+),[\s\u00a0]*([0-9\.\-eE]+)\)/,
        regexpPointString  = /(?!Point3d)\(([0-9\.\,\-eE]+)(?:m|\"|\'|cm|mm),[\s\u00a0]*([0-9\.\,\-eE]+)(?:m|\"|\'|cm|mm),[\s\u00a0]*([0-9\.\,\-eE]+)(m|\"|\'|cm|mm)\)/,
        regexpVector       = /Vector3d\(([0-9\.\-eE]+),[\s\u00a0]*([0-9\.\-eE]+),[\s\u00a0]*([0-9\.\-eE]+)\)/,
        regexpVectorString = /\(([0-9\.\-eE]+),[\s\u00a0]*([0-9\.\-eE]+),[\s\u00a0]*([0-9\.\-eE]+)\)/,
        regexpColor        = /Color\(([\s\u00a0]*[0-9\.]+,[\s\u00a0]*[0-9\.]+,[\s\u00a0]*[0-9\.]+)(,[\s\u00a0]*[0-9\.]+)?\)/,
        regexpColorInspect = /#(?:<|<|<)Sketchup\:\:Color\:([0-9abcdefx]+)(?:>|>|>)/;

    function detectVisualizableElements(htmlElement) {
        var sketchupTokens = $(htmlElement).find('.ace_sketchup');
        if (sketchupTokens.length == 0) {
            var regexps = [regexpEntity, regexpBoundingBox, regexpPoint, regexpPointString, regexpVector, regexpVectorString, regexpColor, regexpColorInspect];
            for (var i = 0; i < regexps.length; i++) {
                var oldHtml = $(htmlElement).html();
                var globalRegexp = new RegExp(regexps[i].source, 'g');
                var newHtml = oldHtml.replace(globalRegexp, function (match) { return '' + match + ''; });
                $(htmlElement).html(newHtml);
            }
            sketchupTokens = $(htmlElement).find('.ace_sketchup');
        }
        sketchupTokens.each(function (index, element) {
            var $element = $(element);
            var text = $element.text();
            if (regexpEntity.test(text) || regexpBoundingBox.test(text)) {
                addEntityHighlight($element, RegExp);
            } else if (regexpPoint.test(text)) {
                addPointWithoutUnitsHighlight($element, RegExp);
            } else if (regexpPointString.test(text)) {
                addPointWithUnitsHighlight($element, RegExp);
            } else if (regexpVector.test(text) || regexpVectorString.test(text)) {
                addVectorHighlight($element, RegExp);
            } else if (regexpColor.test(text)) {
                addColorHighlight($element, RegExp);
            } else if (regexpColorInspect.test(text)) {
                addColorInspectHighlight($element, RegExp);
            }
        });
    }

    function addEntityHighlight($element, regExp) {
        // Add highlight feature to SketchUp entities and get their id.
        var idString = regExp.$1;
        $element.addClass(className)
        .data('type', 'entity')
        .data('identifier', idString)
        .on('mouseover', function() { // Note: This can trigger repeatedly!
            Bridge.get('highlight_entity', idString)['catch'](function () {
                // If the entity isn't valid (deleted or GC), remove the highlight feature.
                $element.removeClass(className);
                $element.off('mouseover');
                $element.off('mouseout');
            });
        })
        .on('mouseout', stop);
    }

    function addPointWithoutUnitsHighlight($element, regExp) {
        // Add highlight feature to Point3d (without units: units = 'inch')
        var coordinates = [parseFloat(regExp.$1), parseFloat(regExp.$2), parseFloat(regExp.$3)];
        $element.addClass(className)
        .data('type', 'point')
        .data('identifier', [coordinates, 'inch'])
        .on('mouseover', function() {
            Bridge.call('highlight_point', coordinates);
        })
        .on('mouseout', stop);
    }

    function addPointWithUnitsHighlight($element, regExp) {
        // Add highlight feature to Point3d string with units
        var coordinates = $([regExp.$1, regExp.$2, regExp.$3]).map(function(index, coordinate){
            return parseFloat(coordinate.replace(/\,(?=[\d])/, '.'));
        });
        var units = regExp.$4;
        // Replace unit names so they don't need escaping.
        switch (units) {
            case '"':
                units = 'inch';
                break;
            case "'":
                units = 'feet';
                break;
        }
        $element.addClass(className)
        .data('type', 'point')
        .data('identifier', [coordinates, units])
        .on('mouseover', function() {
            Bridge.call('highlight_point', coordinates, units);
        })
        .on('mouseout', stop);
    }

    function addVectorHighlight($element, regExp) {
        // Add highlight feature to Vector3d or Vector3d string
        var coordinates = [parseFloat(regExp.$1), parseFloat(regExp.$2), parseFloat(regExp.$3)];
        $element.addClass(className)
        .data('type', 'vector')
        .data('identifier', coordinates)
        .on('mouseover', function() {
            Bridge.call('highlight_vector', coordinates);
        })
        .on('mouseout', stop);
    }

    function addColorHighlight($element, regExp) {
        // Add highlight feature to Color (only HTML/JS)
        // when color has been printed as numerical color values.
        addColorHighlightToHTMLElement($element, 'rgb(' + regExp.$1 + ')');
    }

    function addColorInspectHighlight($element, regExp) {
        // Add highlight feature to Color (only HTML/JS)
        // when color has been printed as Ruby object with id.
        var idString = regExp.$1;
        Bridge.get('get_color', idString).then(function (colorArray) {
          addColorHighlightToHTMLElement($element, 'rgb(' + colorArray.slice(0, 3).join(',') + ')');
        }, function () {
            // If the entity isn't valid (deleted or GC), remove the highlight feature.
            $element.removeClass(className);
            $element.off('mouseover');
            $element.off('mouseout');
        });
    }

    function addColorHighlightToHTMLElement($element, colorString) {
        $element.addClass(className)
        .on('mouseover', function() {
            $(this).css('background-color', colorString);
        }).on('mouseout', function() {
            $(this).css('background-color', 'transparent');
        });
    }

    function detectContainerElements(htmlElement) {
        // Find arrays that contain only elements that can be visualized (SketchUp entities, points, vectors)
        // Begin of an array.
        var arrayStart = $(htmlElement).find('.ace_paren.ace_lparen'),
            arrayEnd,
            currentElement = arrayStart,
            nextElement,
            arrayElements = [],
            dataToHighlight = {
              entity: [],
              point: [],
              vector: []
            };
        while (true) {
            nextElement = currentElement.next(); // Or comma, but text nodes are ignored by jQuery.
            if (nextElement.length == 0) {
                // No element. Something is wrong, end the traversal.
                arrayElements.length = 0;
                break;
            } else if (nextElement.hasClass('highlight_entity')) { // or 'highlight_entity'
                // This is a visualizable element, add it.
                arrayElements.push(nextElement);
                dataToHighlight[nextElement.data('type')].push(nextElement.data('identifier'));
            } else if (nextElement.hasClass('ace_rparen')) {
                arrayEnd = nextElement;
                // End of the array.
                break;
            }
            currentElement = nextElement;
        }
        if (arrayElements.length != 0) {
            var container = $('').addClass(className);
            container.on('mouseenter', function () {
                Bridge.get('highlight_multiple', dataToHighlight)['catch'](function () {
                    // If one of the entities isn't valid (deleted or GC), remove the highlight feature.
                    container.removeClass(className);
                    container.off('mouseover');
                    container.off('mouseout');
                });
            }).on('mouseout', stop);
            var contents = arrayStart.parent().contents(); // Includes text nodes
            contents.slice(contents.index(arrayStart), contents.index(arrayEnd)+1).wrapAll(container);
        }
    }

    app.output.addListener('added', function (htmlElement, text, metadata) {
        if (metadata.type && /input|result|puts|print/.test(metadata.type) && !/javascript/.test(metadata.type)) {
            detectVisualizableElements(htmlElement);
            detectContainerElements(htmlElement);
        }
    });
});
<|endoftext|>


<commit_before>/*
The MIT License (MIT)
Copyright (c) 2013 Kevin Conway

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

/*global require, define, module

*/
(function (factory) {
    "use strict";

    var env = factory.env,
        def = factory.def,
        deps = {
            amd: ['./node_modules/modelo/modelo.js', './node_modules/eventjs/event.js', './node_modules/deferjs/defer.js'],
            node: ['modelo', 'eventjs', 'deferjs'],
            browser: ['Modelo', 'Event', 'defer']
        };

    def.call(this, 'Deferred', deps[env], function (Modelo, Event, defer) {

        var Deferred,
            DeferredObject,
            PromiseObject,
            PromiseCollectionObject,
            callWithValue;

        // This specialized scope is used later on to allow function that are
        // executed asynchronously to be passed an input value.
        callWithValue = function (fn, value) {

            return function () {

                fn(value);

            };

        };

        // PromiseObjects in this context are specialized wrappers around
        // DeferredObjects that limit what actions can be performed on the
        // deferred. Basically the intent is to prevent the manipulation or
        // premature resolution/error of a deferred at runtime.
        //
        // Yes, I have read the proposed commonJS specification for promises.
        // I've purposefully chosen to break from the current proposals because
        // A) none of them are ratified yet and B) they all over complicate the
        // purpose of a promise.
        //
        // In this module, promises are simply limited interfaces to a deferred.
        // Promises do not expose a set of half-baked flow control functions.
        //
        // They simply allow interactions with a DeferredObject which is
        // documented below.
        PromiseObject = Modelo.define(function (options) {

            this.callback = function (fn) {
                options.deferred.callback(fn);
                return this;
            };
            this.done = this.callback;
            this.succeess = this.callback;

            this.errback = function (fn) {
                options.deferred.errback(fn);
                return this;
            };
            this.failure = this.errback;
            this.error = this.errback;

            this.resolved = function () {
                return options.deferred.resolved;
            };
            this.failed = function () {
                return options.deferred.failed;
            };
            this.completed = function () {
                return options.deferred.completed;
            };

            this.value = function () {
                return options.deferred.value;
            };

        });

        // Deferreds are another construct that tend to be over complicated.
        //
        // For example, in Twisted Python's implementation of a deferred
        // (http://twistedmatrix.com/documents/current/core/howto/defer.html#auto3)
        // the callbacks and errbacks registered with the deferred are called
        // in sequence and the choice of executing a callback or errback is
        // determined by the result of the previously executed callback or
        // errback. There may, indeed, be a million use cases for this type of
        // logic but they have mixed flow control with their deferred
        // implementation.
        //
        // In this module, deferreds do one thing only: represent a future
        // resource.
        //
        // When that resource is ready all callback functions are
        // executed asynchronously, in no given order, and with the resolved
        // value as a single input parameter.
        //
        // When that resource is failed to load all errback function are
        // executed asynchronously, in no given order, and with the error
        // that caused the failure as a single input parameter.
        DeferredObject = Event.extend(function (options) {

            this.callbacks = [];
            this.errbacks = [];
            this.resolved = false;
            this.failed = false;
            this.completed = false;

        });

        // This method, and its aliases `success` and `done`, can be used
        // to register a callbcak function with the deferred. All callbacks
        // registered using this method, or its aliases, are passed in a
        // single value as input. This input parameter is the resolved
        // value for the deferred.
        //
        // If the value of the deferred is unimportant to the callback
        // it can, alternatively, be bound to the `success` and `done`
        // events that are emitted.
        DeferredObject.prototype.callback = function (fn) {

            if (this.resolved === true) {
                defer(callWithValue(fn, this.value));
                return this;
            }

            if (typeof fn === "function") {
                this.callbacks.push(fn);
            }

            return this;

        };
        DeferredObject.prototype.succeess = DeferredObject.prototype.callback;
        DeferredObject.prototype.done = DeferredObject.prototype.callback;

        // This method, and its aliases `failure` and `error`, can be used
        // to register callbacks with the deferred that are executed when
        // an error is thrown. Callbacks registered using this method, and
        // its aliases, are passed a single input parameter that contains
        // the error that was thrown.
        //
        // If the value of the error is unimportant there is the option
        // of binding the callback to the `fail`, `failure`, and `error`
        // events that are triggered.
        DeferredObject.prototype.errback = function (fn) {

            if (this.failed === true) {
                defer(callWithValue(fn, this.value));
                return this;
            }

            if (typeof fn === "function") {
                this.errbacks.push(fn);
            }

            return this;

        };
        DeferredObject.prototype.failure = DeferredObject.prototype.errback;
        DeferredObject.prototype.error = DeferredObject.prototype.errback;

        // This method is used to mark the deferred as resolved and
        // to execute all the success callbacks registered. The value
        // passed to this method is the value that will be passed to
        // all callbacks.
        //
        // This method only triggers the callbacks once after which
        // neither it nor the `fail` method have any effect.
        DeferredObject.prototype.resolve = function (value) {

            var x;

            if (this.complete === true) {
                return this;
            }

            this.resolved = true;
            this.completed = true;
            this.value = value;

            for (x = 0; x < this.callbacks.length; x = x + 1) {

                defer(callWithValue(this.callbacks[x], value));

            }

            this.trigger('success').trigger('done');
            this.trigger('complete');

            return this;

        };

        // This method is used to mark the deferred as failed and
        // to execute all the failure errbacks registered. The error value
        // passed to this method is the value that will be passed to
        // all errbacks.
        //
        // This method only triggers the errbacks once after which
        // neither it nor the `resolve` method have any effect.
        DeferredObject.prototype.fail = function (value) {

            var x;

            if (this.complete === true) {
                return this;
            }

            this.failed = true;
            this.completed = true;
            this.value = value;

            for (x = 0; x < this.errbacks.length; x = x + 1) {

                defer(callWithValue(this.errbacks[x], value));

            }

            this.trigger('fail').trigger('failure').trigger('error');
            this.trigger('complete');

            return this;

        };

        // Deferreds should never be returned directly to avoid the potential
        // of runtime manipulation. Instead, return the value of this method
        // any time that you would normally want to return the deferred.
        DeferredObject.prototype.promise = function () {

            return new PromiseObject({"deferred": this});

        };

        // Admittedly, this construct borders on flow control. Promise
        // collections basically allow for the combination of multiple
        // promises into a single promise that resolved when all the contained
        // promises have been resolved. Likewise, the collection fails when
        // any of the contained promises fail.
        //
        // Unlike standard promises, the value passed to succes callbacks
        // are always object literals. These object literals contain key=>value
        // pairs of the values returned by the contained callbacks. The keys
        // are determined when the promises are given to the promise collection.
        //
        // For example, assume that p1, p2, and p3 are promises returned by
        // asynchronous functions that will be resolved to the values 1, 2, and
        // 3 respectively::
        //
        //      var collection = new PromiseCollectionObject({
        //          "p1": p1,
        //          "p2": p2,
        //          "p3": p3
        //      });
        //
        //      collection.callback(function (values) { console.log(values); });
        //
        //      // Some time later...
        //      // CONSOLE OUTPUT: {"p1": 1, "p2": 2, "p3": 3}
        PromiseCollectionObject = DeferredObject.extend(function (options) {

            this.promiseCollection = {};
            this.numberOfPromises = 0;
            this.numberOfResolvedPromises = 0;

            var x;

            for (x in options.promises) {

                if (options.promises.hasOwnProperty(x)) {

                    this.add(x, options.promises[x]);

                }

            }

        });

        // This method can be used to add promises to the collection after
        // the initial creation of the collection. As an important note,
        // it currently fails silently if you try to use it after the
        // the collection has already been resolved or failed.
        PromiseCollectionObject.prototype.add = function (key, promise) {

            this.promiseCollection[key] = promise;
            this.numberOfPromises = this.numberOfPromises + 1;

            var op = this;

            promise.callback(function (value) {

                var x,
                    finalValue = {};

                op.numberOfResolvedPromises = op.numberOfResolvedPromises + 1;

                if (op.numberOfResolvedPromises >= op.numberOfPromises) {

                    for (x in op.promiseCollection) {

                        if (op.promiseCollection.hasOwnProperty(x)) {

                            finalValue[x] = op.promiseCollection[x].value();

                        }

                    }

                    op.resolve(finalValue);

                }

            });

            promise.errback(function (err) {

                op.fail(err);

            });

            return this;

        };

        // This exposes an interface identical to a promise except
        // it adds the `add` method.
        PromiseCollectionObject.prototype.promise = function () {

            var promise = new PromiseObject({"deferred": this}),
                op = this;

            promise.add = function (key, value) {

                op.add(key, value);
                return this;

            };

            return promise;

        };

        // Similar to other modules in this package, the interface returned
        // by this module is a set of wrappers around the actual objects.
        //
        // In this case deferred objects can be created in any of the following
        // ways::
        //
        //      new Deferred();
        //      Deferred();
        //      new Deferred.Deferred();
        //      Deferred.Deferred();
        //
        // The choice comes down to style and preference.
        Deferred = function () {
            return new DeferredObject();
        };
        Deferred.Deferred = Deferred;

        // Deferred.Promise exposes a secondary interface for creating promises.
        // Using the `promise` method of a deferred and creating a new promise
        // object while passing in your deferred have the same effect.
        Deferred.Promise = function (d) {
            return new PromiseObject({"deferred": d});
        };

        // Expects a key=>value store of promises and outputs an extended
        // promise interface that contains the `add` method.
        Deferred.PromiseCollection = function (promises) {

            promises = promises || {};

            return new PromiseCollectionObject({"promises": promises}).promise();

        };

        return Deferred;

    });

}.call(this, (function () {
    "use strict";

    var currentEnvironment,
        generator;

    // Check the environment to determine the dependency management strategy.

    if (typeof define === "function" && !!define.amd) {

        currentEnvironment = 'amd';

    } else if (typeof require === "function" &&
                        module !== undefined && !!module.exports) {

        currentEnvironment = 'node';

    } else if (this.window !== undefined) {

        currentEnvironment = 'browser';

    }

    generator = (function () {
        switch (currentEnvironment) {

        case 'amd':

            // If RequireJS is used to load this module then return the global
            // define() function.
            return function (name, deps, mod) {
                define(deps, mod);
            };

        case 'node':

            // If this module is loaded in Node, require each of the
            // dependencies and pass them along.
            return function (name, deps, mod) {

                var x,
                    dep_list = [];

                for (x = 0; x < deps.length; x = x + 1) {

                    dep_list.push(require(deps[x]));

                }

                module.exports = mod.apply(this, dep_list);

            };

        case 'browser':

            // If this module is being used in a browser environment first
            // generate a list of dependencies, run the provided definition
            // function with the list of dependencies, and insert the returned
            // object into the global namespace using the provided module name.
            return function (name, deps, mod) {

                var namespaces = name.split('/'),
                    root = this,
                    dep_list = [],
                    current_scope,
                    current_dep,
                    i,
                    x;

                for (i = 0; i < deps.length; i = i + 1) {

                    current_scope = root;
                    current_dep = deps[i].split('/');

                    for (x = 0; x < current_dep.length; x = x + 1) {

                        current_scope = current_scope[current_dep[x]] || {};

                    }

                    dep_list.push(current_scope);

                }

                current_scope = root;
                for (i = 1; i < namespaces.length; i = i + 1) {

                    current_scope = current_scope[namespaces[i - 1]] || {};

                }

                current_scope[namespaces[i - 1]] = mod.apply(this, dep_list);

            };

        default:
            throw new Error("Unrecognized environment.");

        }

    }.call());

    return {
        env: currentEnvironment,
        def: generator
    };

}.call(this))));
<commit_msg>Fix: JSLint validation error in module wrapper<commit_after>/*
The MIT License (MIT)
Copyright (c) 2013 Kevin Conway

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

/*global require, define, module

*/
(function (ctx, factory) {
    "use strict";

    var env = factory.env,
        def = factory.def,
        deps = {
            amd: ['./node_modules/modelo/modelo.js', './node_modules/eventjs/event.js', './node_modules/deferjs/defer.js'],
            node: ['modelo', 'eventjs', 'deferjs'],
            browser: ['Modelo', 'Event', 'defer']
        };

    def.call(ctx, 'Deferred', deps[env], function (Modelo, Event, defer) {

        var Deferred,
            DeferredObject,
            PromiseObject,
            PromiseCollectionObject,
            callWithValue;

        // This specialized scope is used later on to allow function that are
        // executed asynchronously to be passed an input value.
        callWithValue = function (fn, value) {

            return function () {

                fn(value);

            };

        };

        // PromiseObjects in this context are specialized wrappers around
        // DeferredObjects that limit what actions can be performed on the
        // deferred. Basically the intent is to prevent the manipulation or
        // premature resolution/error of a deferred at runtime.
        //
        // Yes, I have read the proposed commonJS specification for promises.
        // I've purposefully chosen to break from the current proposals because
        // A) none of them are ratified yet and B) they all over complicate the
        // purpose of a promise.
        //
        // In this module, promises are simply limited interfaces to a deferred.
        // Promises do not expose a set of half-baked flow control functions.
        //
        // They simply allow interactions with a DeferredObject which is
        // documented below.
        PromiseObject = Modelo.define(function (options) {

            this.callback = function (fn) {
                options.deferred.callback(fn);
                return this;
            };
            this.done = this.callback;
            this.succeess = this.callback;

            this.errback = function (fn) {
                options.deferred.errback(fn);
                return this;
            };
            this.failure = this.errback;
            this.error = this.errback;

            this.resolved = function () {
                return options.deferred.resolved;
            };
            this.failed = function () {
                return options.deferred.failed;
            };
            this.completed = function () {
                return options.deferred.completed;
            };

            this.value = function () {
                return options.deferred.value;
            };

        });

        // Deferreds are another construct that tend to be over complicated.
        //
        // For example, in Twisted Python's implementation of a deferred
        // (http://twistedmatrix.com/documents/current/core/howto/defer.html#auto3)
        // the callbacks and errbacks registered with the deferred are called
        // in sequence and the choice of executing a callback or errback is
        // determined by the result of the previously executed callback or
        // errback. There may, indeed, be a million use cases for this type of
        // logic but they have mixed flow control with their deferred
        // implementation.
        //
        // In this module, deferreds do one thing only: represent a future
        // resource.
        //
        // When that resource is ready all callback functions are
        // executed asynchronously, in no given order, and with the resolved
        // value as a single input parameter.
        //
        // When that resource is failed to load all errback function are
        // executed asynchronously, in no given order, and with the error
        // that caused the failure as a single input parameter.
        DeferredObject = Event.extend(function (options) {

            this.callbacks = [];
            this.errbacks = [];
            this.resolved = false;
            this.failed = false;
            this.completed = false;

        });

        // This method, and its aliases `success` and `done`, can be used
        // to register a callbcak function with the deferred. All callbacks
        // registered using this method, or its aliases, are passed in a
        // single value as input. This input parameter is the resolved
        // value for the deferred.
        //
        // If the value of the deferred is unimportant to the callback
        // it can, alternatively, be bound to the `success` and `done`
        // events that are emitted.
        DeferredObject.prototype.callback = function (fn) {

            if (this.resolved === true) {
                defer(callWithValue(fn, this.value));
                return this;
            }

            if (typeof fn === "function") {
                this.callbacks.push(fn);
            }

            return this;

        };
        DeferredObject.prototype.succeess = DeferredObject.prototype.callback;
        DeferredObject.prototype.done = DeferredObject.prototype.callback;

        // This method, and its aliases `failure` and `error`, can be used
        // to register callbacks with the deferred that are executed when
        // an error is thrown. Callbacks registered using this method, and
        // its aliases, are passed a single input parameter that contains
        // the error that was thrown.
        //
        // If the value of the error is unimportant there is the option
        // of binding the callback to the `fail`, `failure`, and `error`
        // events that are triggered.
        DeferredObject.prototype.errback = function (fn) {

            if (this.failed === true) {
                defer(callWithValue(fn, this.value));
                return this;
            }

            if (typeof fn === "function") {
                this.errbacks.push(fn);
            }

            return this;

        };
        DeferredObject.prototype.failure = DeferredObject.prototype.errback;
        DeferredObject.prototype.error = DeferredObject.prototype.errback;

        // This method is used to mark the deferred as resolved and
        // to execute all the success callbacks registered. The value
        // passed to this method is the value that will be passed to
        // all callbacks.
        //
        // This method only triggers the callbacks once after which
        // neither it nor the `fail` method have any effect.
        DeferredObject.prototype.resolve = function (value) {

            var x;

            if (this.complete === true) {
                return this;
            }

            this.resolved = true;
            this.completed = true;
            this.value = value;

            for (x = 0; x < this.callbacks.length; x = x + 1) {

                defer(callWithValue(this.callbacks[x], value));

            }

            this.trigger('success').trigger('done');
            this.trigger('complete');

            return this;

        };

        // This method is used to mark the deferred as failed and
        // to execute all the failure errbacks registered. The error value
        // passed to this method is the value that will be passed to
        // all errbacks.
        //
        // This method only triggers the errbacks once after which
        // neither it nor the `resolve` method have any effect.
        DeferredObject.prototype.fail = function (value) {

            var x;

            if (this.complete === true) {
                return this;
            }

            this.failed = true;
            this.completed = true;
            this.value = value;

            for (x = 0; x < this.errbacks.length; x = x + 1) {

                defer(callWithValue(this.errbacks[x], value));

            }

            this.trigger('fail').trigger('failure').trigger('error');
            this.trigger('complete');

            return this;

        };

        // Deferreds should never be returned directly to avoid the potential
        // of runtime manipulation. Instead, return the value of this method
        // any time that you would normally want to return the deferred.
        DeferredObject.prototype.promise = function () {

            return new PromiseObject({"deferred": this});

        };

        // Admittedly, this construct borders on flow control. Promise
        // collections basically allow for the combination of multiple
        // promises into a single promise that resolved when all the contained
        // promises have been resolved. Likewise, the collection fails when
        // any of the contained promises fail.
        //
        // Unlike standard promises, the value passed to succes callbacks
        // are always object literals. These object literals contain key=>value
        // pairs of the values returned by the contained callbacks. The keys
        // are determined when the promises are given to the promise collection.
        //
        // For example, assume that p1, p2, and p3 are promises returned by
        // asynchronous functions that will be resolved to the values 1, 2, and
        // 3 respectively::
        //
        //      var collection = new PromiseCollectionObject({
        //          "p1": p1,
        //          "p2": p2,
        //          "p3": p3
        //      });
        //
        //      collection.callback(function (values) { console.log(values); });
        //
        //      // Some time later...
        //      // CONSOLE OUTPUT: {"p1": 1, "p2": 2, "p3": 3}
        PromiseCollectionObject = DeferredObject.extend(function (options) {

            this.promiseCollection = {};
            this.numberOfPromises = 0;
            this.numberOfResolvedPromises = 0;

            var x;

            for (x in options.promises) {

                if (options.promises.hasOwnProperty(x)) {

                    this.add(x, options.promises[x]);

                }

            }

        });

        // This method can be used to add promises to the collection after
        // the initial creation of the collection. As an important note,
        // it currently fails silently if you try to use it after the
        // the collection has already been resolved or failed.
        PromiseCollectionObject.prototype.add = function (key, promise) {

            this.promiseCollection[key] = promise;
            this.numberOfPromises = this.numberOfPromises + 1;

            var op = this;

            promise.callback(function (value) {

                var x,
                    finalValue = {};

                op.numberOfResolvedPromises = op.numberOfResolvedPromises + 1;

                if (op.numberOfResolvedPromises >= op.numberOfPromises) {

                    for (x in op.promiseCollection) {

                        if (op.promiseCollection.hasOwnProperty(x)) {

                            finalValue[x] = op.promiseCollection[x].value();

                        }

                    }

                    op.resolve(finalValue);

                }

            });

            promise.errback(function (err) {

                op.fail(err);

            });

            return this;

        };

        // This exposes an interface identical to a promise except
        // it adds the `add` method.
        PromiseCollectionObject.prototype.promise = function () {

            var promise = new PromiseObject({"deferred": this}),
                op = this;

            promise.add = function (key, value) {

                op.add(key, value);
                return this;

            };

            return promise;

        };

        // Similar to other modules in this package, the interface returned
        // by this module is a set of wrappers around the actual objects.
        //
        // In this case deferred objects can be created in any of the following
        // ways::
        //
        //      new Deferred();
        //      Deferred();
        //      new Deferred.Deferred();
        //      Deferred.Deferred();
        //
        // The choice comes down to style and preference.
        Deferred = function () {
            return new DeferredObject();
        };
        Deferred.Deferred = Deferred;

        // Deferred.Promise exposes a secondary interface for creating promises.
        // Using the `promise` method of a deferred and creating a new promise
        // object while passing in your deferred have the same effect.
        Deferred.Promise = function (d) {
            return new PromiseObject({"deferred": d});
        };

        // Expects a key=>value store of promises and outputs an extended
        // promise interface that contains the `add` method.
        Deferred.PromiseCollection = function (promises) {

            promises = promises || {};

            return new PromiseCollectionObject({"promises": promises}).promise();

        };

        return Deferred;

    });

}(this, (function (ctx) {
    "use strict";

    var currentEnvironment,
        generator;

    // Check the environment to determine the dependency management strategy.

    if (typeof define === "function" && !!define.amd) {

        currentEnvironment = 'amd';

    } else if (typeof require === "function" &&
                        module !== undefined && !!module.exports) {

        currentEnvironment = 'node';

    } else if (ctx.window !== undefined) {

        currentEnvironment = 'browser';

    }

    generator = (function () {
        switch (currentEnvironment) {

        case 'amd':

            // If RequireJS is used to load this module then return the global
            // define() function.
            return function (name, deps, mod) {
                define(deps, mod);
            };

        case 'node':

            // If this module is loaded in Node, require each of the
            // dependencies and pass them along.
            return function (name, deps, mod) {

                var x,
                    dep_list = [];

                for (x = 0; x < deps.length; x = x + 1) {

                    dep_list.push(require(deps[x]));

                }

                module.exports = mod.apply(ctx, dep_list);

            };

        case 'browser':

            // If this module is being used in a browser environment first
            // generate a list of dependencies, run the provided definition
            // function with the list of dependencies, and insert the returned
            // object into the global namespace using the provided module name.
            return function (name, deps, mod) {

                var namespaces = name.split('/'),
                    root = ctx,
                    dep_list = [],
                    current_scope,
                    current_dep,
                    i,
                    x;

                for (i = 0; i < deps.length; i = i + 1) {

                    current_scope = root;
                    current_dep = deps[i].split('/');

                    for (x = 0; x < current_dep.length; x = x + 1) {

                        current_scope = current_scope[current_dep[x]] || {};

                    }

                    dep_list.push(current_scope);

                }

                current_scope = root;
                for (i = 1; i < namespaces.length; i = i + 1) {

                    current_scope = current_scope[namespaces[i - 1]] =
                                    current_scope[namespaces[i - 1]] || {};

                }

                current_scope[namespaces[i - 1]] = mod.apply(ctx, dep_list);

            };

        default:
            throw new Error("Unrecognized environment.");

        }

    }());

    return {
        env: currentEnvironment,
        def: generator
    };

}(this))));
<|endoftext|>