<commit_before>function puts(){
  console.log.apply(console, arguments);
}

// global namespace
var Jdbcwb = {};

(function(){

  "use strict";

  var _g = Jdbcwb; // global namespace alias

  var COL_CONTENT_LENGTH_MAX = 32;

  ////////////////////////////////

  function snipLongContent(str){
    if(str == null){
      return null;
    }
    if(str.length > COL_CONTENT_LENGTH_MAX){
      var snip = "...";
      var half = Math.floor((COL_CONTENT_LENGTH_MAX - snip.length) / 2);
      var head = str.substring(0, half);
      var tail = str.substring(str.length - half, str.length);
      str = head + '' + snip + '' + tail;
    }
    return str;
  }

  ////////////////////////////////
  // Table Utilities

  function makeHeaderRows(
    // colPNames,
    colDefs){
    var inner = "#	";
    _.each(colDefs, function(colDef){
      inner += '' + colDef.name + '	';
    });
    return '
' + inner + '
';
  }

  ////////////////////////////////

  var Database = {

    singleQuery: function(mode, schema, tablePName, sql, fnOk, fnNg){
      this.multiQuery(mode, schema, tablePName, [sql], function(results){
        fnOk(results[0]);
      }, fnNg);
    },

    multiQuery: function(mode, schema, tablePName, sqls, fnOk, fnNg){
      $.post("/api/query", {
        mode: mode,
        schema: schema,
        table: tablePName,
        sqls: JSON.stringify(sqls)
      }).done(function(data){
        _g.appM.set("ajaxResponse", JSON.stringify(data));

        if(data.status === 'OK'){
          fnOk(data.results);
        }else{
          console.error(data.ex); // TODO
          fnNg(data);
        }
      });
    },

    update: function(sql, fnOk, fnNg){
      $.post("/api/update", {
        sql: sql
      }, function(data){
        _g.appM.set("ajaxResponse", JSON.stringify(data));

        if(data.status === 'OK'){
          fnOk(data);
        }else{
          console.error(data.ex); // TODO
          fnNg(data);
        }
      });
    }
  };

  ////////////////////////////////

  _g.AppM = Backbone.Model.extend({
    defaults: {
      ajaxResponse: "",
      snipLongContent: true
    },

    toggleSnipLongContent: function(){
      this.set("snipLongContent", ! this.get("snipLongContent") );
    }
  });

  _g.AppV = Backbone.View.extend({

    el: "body",

    events: {
      "click .snip_long_content": function(){
        this.model.toggleSnipLongContent();
      }
    },

    initialize: function(){
      this.listenTo(this.model, "change", this.render);
    },

    render: function(){
      $("#ajax_response").val(this.model.get("ajaxResponse"));
      this.$(".snip_long_content")
          .prop("checked", this.model.get("snipLongContent"));
    },

    guard:   function(){ this.$("#guard_layer").show(); },
    unguard: function(){ this.$("#guard_layer").hide(); }
  });

  ////////////////////////////////

  _g.GenericOperationM = Backbone.Model.extend({

    doQuery: function(sql, viewFnOk, viewFnNg){
      var resboxM = _g.genericOperationResultBoxM;
      Database.singleQuery('generic', null, null, sql, function(result){
        resboxM.setResult(result);
        viewFnOk();
      }, function(data){
        viewFnNg();
      });
    }
  });

  _g.GenericOperationV = Backbone.View.extend({

    el: "#_generic_operation",

    events: {
      "click .btn_query": "doQuery",
      "click .btn_update": "doUpdate"
    },

    doQuery: function(){
      var resboxM = _g.genericOperationResultBoxM;

      _g.appV.guard();
      resboxM.reset();

      var sql = this.$("textarea").val();

      this.model.doQuery(sql, function(){
        _g.appV.unguard();
      }, function(){
        _g.appV.unguard();
      });
    },

    doUpdate: function(){
      var resboxM = _g.genericOperationResultBoxM;
      _g.appV.guard();

      var sql = this.$("textarea").val();

      Database.update(sql, function(data){
        resboxM.set("numRows", data.count);
        _g.appV.unguard();
      }, function(data){
        _g.appV.unguard();
      });
    }
  });

  ////////////////////////////////

  _g.TableEditM = Backbone.Model.extend({

    doQuery: function(schema, tablePName, viewFnOk, viewFnNg){
      var resboxM = _g.tableEditResultBoxM;
      var sql = this.makeSql(tablePName);

      Database.singleQuery('single_table', schema, tablePName, sql, function(result){
        // OK
        resboxM.setResult(result);
        viewFnOk();
      }, function(data){
        // NG
        viewFnNg();
      });
    },

    makeSql: function(tablePName){
      return [
        "SELECT *",
        "FROM " + tablePName
      ].join("\n");
    }
  });

  _g.TableEditV = Backbone.View.extend({

    el: "#_table_edit",

    events: {
      "click .btn_query": "doQuery"
    },

    doQuery: function(ev){
      ev.preventDefault();
      var resboxM = _g.tableEditResultBoxM;

      _g.appV.guard();
      // _g.appV.hideMsg(); // TODO
      resboxM.reset();
      this.colDefs = null;

      var schema = this.$("[name=schema]").val();
      var tablePName = this.$("[name=table_pname]").val();

      this.model.doQuery(schema, tablePName, function(){
        _g.appV.unguard();
      }, function(){
        _g.appV.unguard();
      });
    }
  });

  ////////////////////////////////

  _g.ResultBoxM = Backbone.Model.extend({
    defaults: {
      numRows: null,
      rows: [],
      colDefs: []
    },

    reset: function(){
      this.set("data", {
        colDefs: [],
        rows: [],
        numRows: "-",
        numRowsAll: "-"
      });
      this.set("colDefs", [], {silent: true});
      this.set("rows", [], {silent: true});
      this.set("numRows", "-", {silent: true});
      this.set("numRowsAll", "-", {silent: true});
      this.trigger("change");
    },

    setResult: function(result){
      this.set("numRows", result.numRows, {silent: true});
      this.set("colDefs", result.colDefs, {silent: true});
      this.set("rows", result.rows, {silent: true});
      this.trigger("change");
    }
  });

  _g.ResultBoxV = Backbone.View.extend({
    initialize: function(){
      this.listenTo(this.model, "change", this.render);
    },

    _renderNormalView: function(){
      // header
      this.$(".result thead").append(makeHeaderRows(
        // colPNames,
        this.model.get("colDefs")
      ));

      // rows
      var $tbody = this.$(".result tbody");
      _.each(this.model.get("rows"), function(row, ri){
        var rn = ri + 1;
        var $tr = $('
'+rn+'
');
        _.each(row, function(col){
          var content = col;
          if(_g.appM.get("snipLongContent")){
            content = snipLongContent(col);
          }
          $tr.append(''+ content +'	');
        });
        $tbody.append($tr);
      });
    },

    render: function(){
      // clear
      this.$(".result thead").empty();
      this.$(".result tbody").empty();

      var numRows = this.model.get("numRows");
      this.$(".num_rows").text(numRows != null ? numRows : "-");

      this._renderNormalView();
    }
  });

  ////////////////////////////////

  _g.start = function(){

    _g.genericOperationResultBoxM = new _g.ResultBoxM();
    _g.genericOperationResultBoxV = new _g.ResultBoxV({
      el: $("#_generic_operation ._result_box"),
      model: _g.genericOperationResultBoxM
    });

    _g.tableEditResultBoxM = new _g.ResultBoxM();
    _g.tableEditResultBoxV = new _g.ResultBoxV({
      el: $("#_table_edit ._result_box"),
      model: _g.tableEditResultBoxM
    });

    _g.genericOperationM = new _g.GenericOperationM();
    _g.genericOperationV = new _g.GenericOperationV({
      model: _g.genericOperationM
    });

    _g.tableEditM = new _g.TableEditM();
    _g.tableEditV = new _g.TableEditV({
      model: _g.tableEditM
    });

    _g.appM = new _g.AppM();
    _g.appV = new _g.AppV({
      model: _g.appM
    });
  };

})();

////////////////////////////////

$(Jdbcwb.start);
<commit_msg>refactor: extract makeDataRows<commit_after>function puts(){
  console.log.apply(console, arguments);
}

// global namespace
var Jdbcwb = {};

(function(){

  "use strict";

  var _g = Jdbcwb; // global namespace alias

  var COL_CONTENT_LENGTH_MAX = 32;

  ////////////////////////////////

  function snipLongContent(str){
    if(str == null){
      return null;
    }
    if(str.length > COL_CONTENT_LENGTH_MAX){
      var snip = "...";
      var half = Math.floor((COL_CONTENT_LENGTH_MAX - snip.length) / 2);
      var head = str.substring(0, half);
      var tail = str.substring(str.length - half, str.length);
      str = head + '' + snip + '' + tail;
    }
    return str;
  }

  ////////////////////////////////
  // Table Utilities

  function makeHeaderRows(
    // colPNames,
    colDefs){
    var inner = "#	";
    _.each(colDefs, function(colDef){
      inner += '' + colDef.name + '	';
    });
    return '
' + inner + '
';
  }

  function makeDataRows(row, ri){
    var inner = '' + (ri + 1) + '	';
    _.each(row, function(col){
      var content = col;
      if(_g.appM.get("snipLongContent")){
        content = snipLongContent(col);
      }
      inner += ''+ content +'	';
    });
    return '
' + inner + '
';
  }

  ////////////////////////////////

  var Database = {

    singleQuery: function(mode, schema, tablePName, sql, fnOk, fnNg){
      this.multiQuery(mode, schema, tablePName, [sql], function(results){
        fnOk(results[0]);
      }, fnNg);
    },

    multiQuery: function(mode, schema, tablePName, sqls, fnOk, fnNg){
      $.post("/api/query", {
        mode: mode,
        schema: schema,
        table: tablePName,
        sqls: JSON.stringify(sqls)
      }).done(function(data){
        _g.appM.set("ajaxResponse", JSON.stringify(data));

        if(data.status === 'OK'){
          fnOk(data.results);
        }else{
          console.error(data.ex); // TODO
          fnNg(data);
        }
      });
    },

    update: function(sql, fnOk, fnNg){
      $.post("/api/update", {
        sql: sql
      }, function(data){
        _g.appM.set("ajaxResponse", JSON.stringify(data));

        if(data.status === 'OK'){
          fnOk(data);
        }else{
          console.error(data.ex); // TODO
          fnNg(data);
        }
      });
    }
  };

  ////////////////////////////////

  _g.AppM = Backbone.Model.extend({
    defaults: {
      ajaxResponse: "",
      snipLongContent: true
    },

    toggleSnipLongContent: function(){
      this.set("snipLongContent", ! this.get("snipLongContent") );
    }
  });

  _g.AppV = Backbone.View.extend({

    el: "body",

    events: {
      "click .snip_long_content": function(){
        this.model.toggleSnipLongContent();
      }
    },

    initialize: function(){
      this.listenTo(this.model, "change", this.render);
    },

    render: function(){
      $("#ajax_response").val(this.model.get("ajaxResponse"));
      this.$(".snip_long_content")
          .prop("checked", this.model.get("snipLongContent"));
    },

    guard:   function(){ this.$("#guard_layer").show(); },
    unguard: function(){ this.$("#guard_layer").hide(); }
  });

  ////////////////////////////////

  _g.GenericOperationM = Backbone.Model.extend({

    doQuery: function(sql, viewFnOk, viewFnNg){
      var resboxM = _g.genericOperationResultBoxM;
      Database.singleQuery('generic', null, null, sql, function(result){
        resboxM.setResult(result);
        viewFnOk();
      }, function(data){
        viewFnNg();
      });
    }
  });

  _g.GenericOperationV = Backbone.View.extend({

    el: "#_generic_operation",

    events: {
      "click .btn_query": "doQuery",
      "click .btn_update": "doUpdate"
    },

    doQuery: function(){
      var resboxM = _g.genericOperationResultBoxM;

      _g.appV.guard();
      resboxM.reset();

      var sql = this.$("textarea").val();

      this.model.doQuery(sql, function(){
        _g.appV.unguard();
      }, function(){
        _g.appV.unguard();
      });
    },

    doUpdate: function(){
      var resboxM = _g.genericOperationResultBoxM;
      _g.appV.guard();

      var sql = this.$("textarea").val();

      Database.update(sql, function(data){
        resboxM.set("numRows", data.count);
        _g.appV.unguard();
      }, function(data){
        _g.appV.unguard();
      });
    }
  });

  ////////////////////////////////

  _g.TableEditM = Backbone.Model.extend({

    doQuery: function(schema, tablePName, viewFnOk, viewFnNg){
      var resboxM = _g.tableEditResultBoxM;
      var sql = this.makeSql(tablePName);

      Database.singleQuery('single_table', schema, tablePName, sql, function(result){
        // OK
        resboxM.setResult(result);
        viewFnOk();
      }, function(data){
        // NG
        viewFnNg();
      });
    },

    makeSql: function(tablePName){
      return [
        "SELECT *",
        "FROM " + tablePName
      ].join("\n");
    }
  });

  _g.TableEditV = Backbone.View.extend({

    el: "#_table_edit",

    events: {
      "click .btn_query": "doQuery"
    },

    doQuery: function(ev){
      ev.preventDefault();
      var resboxM = _g.tableEditResultBoxM;

      _g.appV.guard();
      // _g.appV.hideMsg(); // TODO
      resboxM.reset();
      this.colDefs = null;

      var schema = this.$("[name=schema]").val();
      var tablePName = this.$("[name=table_pname]").val();

      this.model.doQuery(schema, tablePName, function(){
        _g.appV.unguard();
      }, function(){
        _g.appV.unguard();
      });
    }
  });

  ////////////////////////////////

  _g.ResultBoxM = Backbone.Model.extend({
    defaults: {
      numRows: null,
      rows: [],
      colDefs: []
    },

    reset: function(){
      this.set("data", {
        colDefs: [],
        rows: [],
        numRows: "-",
        numRowsAll: "-"
      });
      this.set("colDefs", [], {silent: true});
      this.set("rows", [], {silent: true});
      this.set("numRows", "-", {silent: true});
      this.set("numRowsAll", "-", {silent: true});
      this.trigger("change");
    },

    setResult: function(result){
      this.set("numRows", result.numRows, {silent: true});
      this.set("colDefs", result.colDefs, {silent: true});
      this.set("rows", result.rows, {silent: true});
      this.trigger("change");
    }
  });

  _g.ResultBoxV = Backbone.View.extend({
    initialize: function(){
      this.listenTo(this.model, "change", this.render);
    },

    _renderNormalView: function(){
      // header
      this.$(".result thead").append(makeHeaderRows(
        // colPNames,
        this.model.get("colDefs")
      ));

      // rows
      var $tbody = this.$(".result tbody");
      _.each(this.model.get("rows"), function(row, ri){
        $tbody.append(makeDataRows(row, ri));
      });
    },

    render: function(){
      // clear
      this.$(".result thead").empty();
      this.$(".result tbody").empty();

      var numRows = this.model.get("numRows");
      this.$(".num_rows").text(numRows != null ? numRows : "-");

      this._renderNormalView();
    }
  });

  ////////////////////////////////

  _g.start = function(){

    _g.genericOperationResultBoxM = new _g.ResultBoxM();
    _g.genericOperationResultBoxV = new _g.ResultBoxV({
      el: $("#_generic_operation ._result_box"),
      model: _g.genericOperationResultBoxM
    });

    _g.tableEditResultBoxM = new _g.ResultBoxM();
    _g.tableEditResultBoxV = new _g.ResultBoxV({
      el: $("#_table_edit ._result_box"),
      model: _g.tableEditResultBoxM
    });

    _g.genericOperationM = new _g.GenericOperationM();
    _g.genericOperationV = new _g.GenericOperationV({
      model: _g.genericOperationM
    });

    _g.tableEditM = new _g.TableEditM();
    _g.tableEditV = new _g.TableEditV({
      model: _g.tableEditM
    });

    _g.appM = new _g.AppM();
    _g.appV = new _g.AppV({
      model: _g.appM
    });
  };

})();

////////////////////////////////

$(Jdbcwb.start);
<|endoftext|>


<commit_before>define(['jquery', 'webmaker-auth-client/webmaker-auth-client'], function ($, WebmakerAuthClient) {
  'use strict';

  var auth = new WebmakerAuthClient({
    csrfToken: $('meta[name="csrf-token"]').attr('content')
  });

  var loginEl = $('.webmaker-login');
  var logoutEl = $('.webmaker-logout');

  function toggleUserData(userData) {
    var placeHolder = $('#identity');
    var userElement = $('div.user-name');
    var lang = $('html').attr('lang') || 'en-US';

    if (userData) {
      placeHolder.html('' +
        '' + userData.username + "");
    } else {
      userElement.html('');
    }
  }

  function onLogin(user) {
    $('#webmaker-nav').addClass('loggedin');
    toggleUserData(user);
    loginEl.hide();
    logoutEl.show();
  }

  function onLogout() {
    $('#webmaker-nav').removeClass('loggedin');
    toggleUserData();
    loginEl.show();
    logoutEl.hide();
  }

  auth.on('login', onLogin);
  auth.on('logout', onLogout);

  auth.on('error', function (err) {
    window.console.log(err);
  });

  loginEl.click(auth.login);
  logoutEl.click(auth.logout);

  return auth;
});
<commit_msg>empty alt text<commit_after>define(['jquery', 'webmaker-auth-client/webmaker-auth-client'], function ($, WebmakerAuthClient) {
  'use strict';

  var auth = new WebmakerAuthClient({
    csrfToken: $('meta[name="csrf-token"]').attr('content')
  });

  var loginEl = $('.webmaker-login');
  var logoutEl = $('.webmaker-logout');

  function toggleUserData(userData) {
    var placeHolder = $('#identity');
    var userElement = $('div.user-name');
    var lang = $('html').attr('lang') || 'en-US';

    if (userData) {
      placeHolder.html('' +
        '' + userData.username + "");
    } else {
      userElement.html('');
    }
  }

  function onLogin(user) {
    $('#webmaker-nav').addClass('loggedin');
    toggleUserData(user);
    loginEl.hide();
    logoutEl.show();
  }

  function onLogout() {
    $('#webmaker-nav').removeClass('loggedin');
    toggleUserData();
    loginEl.show();
    logoutEl.hide();
  }

  auth.on('login', onLogin);
  auth.on('logout', onLogout);

  auth.on('error', function (err) {
    window.console.log(err);
  });

  loginEl.click(auth.login);
  logoutEl.click(auth.logout);

  return auth;
});
<|endoftext|>


<commit_before>$(document).ready(function(){

window.global_summary = {};

// Prepare basic skeletal structure of the questions sections
// from the schema
$(project_schema.questions).each(function(){
  var row = $('
').addClass('row');
  var h1 = $('
').html(this.title);
  var chart_container = $('
').addClass('geotagx_chart_container').attr('id', 'geotagx_chart_'+this.answer.saved_as);
  // row.append(h1)
  row.append(chart_container);
  $("#task_run_visualization").append(row);
  $("#task_run_visualization").append($('
'));

  global_summary[this.answer.saved_as] = {};
});

// Analyse data and init the graphs
var response;
$(project_task_runs).each(function(){
  var task_run = $(this).get(0);
    $(project_schema.questions).each(function(){
      // (this.answer.saved_as)
      response = task_run.info[this.answer.saved_as];
      if(response == undefined){
        // not answered this field
        // normalise this as NotAnswered
        response = "Not Answered";
      }else if(response.trim()==""){
        //normalise empty string results
        response = "Not Answered";
      }
      //Check if this answer has been initialized in the global summary
      if(global_summary[this.answer.saved_as][response] == undefined){
        global_summary[this.answer.saved_as][response] = 0;
      }
      global_summary[this.answer.saved_as][response] += 1;
    })
  });

//Render Graphs now in the respective containers
// Radialize the colors
Highcharts.getOptions().colors = Highcharts.map(Highcharts.getOptions().colors, function (color) {
    return {
        radialGradient: { cx: 0.5, cy: 0.3, r: 0.7 },
        stops: [
            [0, color],
            [1, Highcharts.Color(color).brighten(-0.3).get('rgb')] // darken
        ]
    };
});

function iterateSorted(dataObject, worker)
{
    var keys = [];
    for (var key in dataObject)
    {
        if (dataObject.hasOwnProperty(key))
            keys.push(key);
    }
    keys.sort();
    for (var i = 0; i < keys.length; i++)
    {
        worker(keys[i], dataObject[keys[i]]);
    }
}

$(project_schema.questions).each(function(){
  var question = this;
  if(question.type != "geotagging"){
    // Format Data for the chart
    var chart_data = [];
    var data_sum = 0;
    iterateSorted(global_summary[this.answer.saved_as], function(key, value){
      chart_data.push([key, value]);
      data_sum += value;
    });
    // Build the chart
    $('#geotagx_chart_'+this.answer.saved_as).highcharts({
        chart: {
            plotBackgroundColor: null,
            plotBorderWidth: null,
            plotShadow: true,
        },
        title: {
            text: this.title //Question text
        },
        tooltip: {
            pointFormat: '{point.percentage:.1f}%'
        },
        plotOptions: {
            pie: {
                allowPointSelect: true,
                cursor: 'pointer',
                dataLabels: {
                    enabled: true,
                    format: '{point.name}: {point.percentage:.1f} % ({point.y}/'+ data_sum +")",
                    style: {
                        color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
                    },
                    connectorColor: 'silver'
                },
                showInLegend: true
            }
        },
        series: [{
            type: 'pie',
            data: chart_data
        }],
        credits : {
          enabled : false
        }
    });
  }else{
    $('#geotagx_chart_'+this.answer.saved_as).html("TODO:- Add support for Geotagging responses");
  }

  $("#reference_image_padding").css("max-height",$(".partners").offset().top - $("#task_run_visualization_reference_image").height() - 400)
});

$(window).scroll(function(){
  var tOffSetOfImageTopPad = $("#reference_image_padding").offset().top;
  var tOffSetOfImage = $("#task_run_visualization_reference_image").offset().top;
  $("#reference_image_padding").stop().animate({height:$(window).scrollTop()-tOffSetOfImageTopPad + 130}, 500)
})

});

<commit_msg>Adds a try catch block for catching errors during rendering data in geotagx visualization<commit_after>$(document).ready(function(){

window.global_summary = {};

// Prepare basic skeletal structure of the questions sections
// from the schema
$(project_schema.questions).each(function(){
  var row = $('
').addClass('row');
  var h1 = $('
').html(this.title);
  var chart_container = $('
').addClass('geotagx_chart_container').attr('id', 'geotagx_chart_'+this.answer.saved_as);
  // row.append(h1)
  row.append(chart_container);
  $("#task_run_visualization").append(row);
  $("#task_run_visualization").append($('
'));

  global_summary[this.answer.saved_as] = {};
});

// Analyse data and init the graphs
var response;
$(project_task_runs).each(function(){
  var task_run = $(this).get(0);
  console.log(task_run);
    $(project_schema.questions).each(function(){
      // (this.answer.saved_as)
      try{
      response = task_run.info[this.answer.saved_as];
      if(response == undefined){
        // not answered this field
        // normalise this as NotAnswered
        response = "Not Answered";
      }else if(response.trim()==""){
        //normalise empty string results
        response = "Not Answered";
      }
      //Check if this answer has been initialized in the global summary
      if(global_summary[this.answer.saved_as][response] == undefined){
        global_summary[this.answer.saved_as][response] = 0;
      }
      global_summary[this.answer.saved_as][response] += 1;
     }catch(err){
		//pass silently in case of errors
     }
    })
  });

//Render Graphs now in the respective containers
// Radialize the colors
Highcharts.getOptions().colors = Highcharts.map(Highcharts.getOptions().colors, function (color) {
    return {
        radialGradient: { cx: 0.5, cy: 0.3, r: 0.7 },
        stops: [
            [0, color],
            [1, Highcharts.Color(color).brighten(-0.3).get('rgb')] // darken
        ]
    };
});

function iterateSorted(dataObject, worker)
{
    var keys = [];
    for (var key in dataObject)
    {
        if (dataObject.hasOwnProperty(key))
            keys.push(key);
    }
    keys.sort();
    for (var i = 0; i < keys.length; i++)
    {
        worker(keys[i], dataObject[keys[i]]);
    }
}

$(project_schema.questions).each(function(){
  var question = this;
  if(question.type != "geotagging"){
    // Format Data for the chart
    var chart_data = [];
    var data_sum = 0;
    iterateSorted(global_summary[this.answer.saved_as], function(key, value){
      chart_data.push([key, value]);
      data_sum += value;
    });
    // Build the chart
    $('#geotagx_chart_'+this.answer.saved_as).highcharts({
        chart: {
            plotBackgroundColor: null,
            plotBorderWidth: null,
            plotShadow: true,
        },
        title: {
            text: this.title //Question text
        },
        tooltip: {
            pointFormat: '{point.percentage:.1f}%'
        },
        plotOptions: {
            pie: {
                allowPointSelect: true,
                cursor: 'pointer',
                dataLabels: {
                    enabled: true,
                    format: '{point.name}: {point.percentage:.1f} % ({point.y}/'+ data_sum +")",
                    style: {
                        color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
                    },
                    connectorColor: 'silver'
                },
                showInLegend: true
            }
        },
        series: [{
            type: 'pie',
            data: chart_data
        }],
        credits : {
          enabled : false
        }
    });
  }else{
    $('#geotagx_chart_'+this.answer.saved_as).html("TODO:- Add support for Geotagging responses");
  }

  $("#reference_image_padding").css("max-height",$(".partners").offset().top - $("#task_run_visualization_reference_image").height() - 400)
});

$(window).scroll(function(){
  var tOffSetOfImageTopPad = $("#reference_image_padding").offset().top;
  var tOffSetOfImage = $("#task_run_visualization_reference_image").offset().top;
  $("#reference_image_padding").stop().animate({height:$(window).scrollTop()-tOffSetOfImageTopPad + 130}, 500)
})

});

<|endoftext|>


<commit_before>(function() {

d3.simplify = function() {
  var projection = d3.geo.albers(),
      triangulateLineString = triangulateLineStringSimple,
      heap,
      minArea = 3,
      topology = false,
      ringId,
      id,
      idByRings,
      ringByPoint,
      ringsByPoint,
      sharedPoints,
      graph;

  var projectCoordinates = {
    MultiPolygon: projectMultiPolygon,
    Polygon: projectPolygon,
    MultiLineString: projectPolygon,
    LineString: projectLineString
  };

  var triangulateCoordinates = {
    MultiPolygon: triangulateMultiPolygon,
    Polygon: triangulatePolygon,
    MultiLineString: triangulatePolygon,
    LineString: triangulateLineString
  };

  var simplifyCoordinates = {
    MultiPolygon: simplifyMultiPolygon,
    Polygon: simplifyPolygon,
    MultiLineString: simplifyPolygon,
    LineString: simplifyLineString
  };

  function simplify(object) {
    var type = object.type;
    if (type === "FeatureCollection") {
      object = copy(object);
      object.features = object.features.map(simplifyFeature).filter(nonemptyFeature);
      return object;
    }
    return (type === "Feature" ? simplifyFeature : simplifyGeometry)(object);
  }

  simplify.project = function(feature) {
    var maxArea = 0,
        maxAreas = {},
        triangle;

    heap = minHeap();

    if (topology) {
      id = 0;
      idByRings = {};
      ringsByPoint = {};
      ringByPoint = {};
      sharedPoints = {};
      graph = {};
      triangulateTopology(feature);
    } else {
      triangulateSimple(feature);
    }

    while (triangle = heap.pop()) {
      // If the area of the current point is less than that of the previous point
      // to be eliminated, use the latter’s area instead. This ensures that the
      // current point cannot be eliminated without eliminating previously-
      // eliminated points.
      if (triangle[1][2] < maxArea) triangle[1][2] = maxArea;
      else maxArea = triangle[1][2];

      if (triangle.previous) {
        triangle.previous.next = triangle.next;
        triangle.previous[2] = triangle[2];
        update(triangle.previous);
      } else if (topology) {
        maxAreas[triangle.ring] = triangle[1][2];
      } else {
        triangle[0][2] = triangle[1][2];
      }

      if (triangle.next) {
        triangle.next.previous = triangle.previous;
        triangle.next[0] = triangle[0];
        update(triangle.next);
      } else if (topology) {
        maxAreas[triangle.ring] = triangle[1][2];
      } else {
        triangle[2][2] = triangle[1][2];
      }
    }

    function update(triangle) {
      heap.remove(triangle);
      triangle[1][2] = area(triangle);
      heap.push(triangle);
    }

    if (topology) {
      var seen = {},
          max,
          m,
          c;
      for (var key in graph) {
        if (seen.hasOwnProperty(key)) continue;
        max = 0;
        for (var k in (c = components(graph, key))) if ((m = maxAreas[k]) > max) max = m;
        for (var k in c) maxAreas[k] = max, seen[k] = 1;
      }

      for (var key in sharedPoints) {
        maxArea = maxAreas[ringsByPoint[key][0]];
        sharedPoints[key].forEach(function(point) { point[2] = maxArea; });
      }
      ringByPoint = idByRings = ringsByPoint = sharedPoints = graph = null;
    }

    heap = null;
    return feature;
  };

  function components(graph, source) {
    var seen = {},
        nextLevel = {},
        thisLevel,
        empty;
    nextLevel[source] = 1;
    while (1) {
      empty = true;
      for (var k in nextLevel) empty = false;
      if (empty) break;
      thisLevel = nextLevel;
      nextLevel = {};
      for (var v in thisLevel) {
        if (seen.hasOwnProperty(v)) continue;
        seen[v] = 1;
        var neighbors = graph[v];
        for (var k in neighbors) nextLevel[k] = neighbors[k];
      }
    }
    return seen;
  }

  function projectFeature(feature) {
    projectGeometry(feature.geometry);
  }

  function projectGeometry(geometry) {
    var type = geometry.type;
    if (type === "GeometryCollection") geometry.geometries.forEach(projectGeometry);
    else geometry.coordinates = projectCoordinates[type](geometry.coordinates);
  }

  function projectMultiPolygon(multiPolygon) {
    return multiPolygon.map(projectPolygon);
  }

  function projectPolygon(polygon) {
    return polygon.map(projectLineString);
  }

  function projectLineString(lineString) {
    ++ringId;
    return lineString.map(projectPoint);
  }

  function projectPoint(point) {
    var pointKey = (point = projection(point))[0] + "," + point[1],
        key = (ringByPoint.hasOwnProperty(pointKey) ? ringByPoint[pointKey] + ":" : "") + ringId;
    ringByPoint[pointKey] = idByRings.hasOwnProperty(key)
        ? idByRings[key]
        : idByRings[key] = ++id;
    return point;
  }

  function triangulateLineStringTopology(lineString) {
    ++ringId;
    var n = lineString.length - 1,
        triangle0,
        triangle,
        a = lineString[0],
        b = lineString[1],
        c,
        idA = ringByPoint[a[0] + "," + a[1]],
        idB = ringByPoint[b[0] + "," + b[1]],
        idC;

    lineString[0][2] = lineString[n][2] = 0;
    if (n < 2) return lineString;

    graph[ringId] = {};

    addSharedPoint(a);
    for (var i = 2; i <= n; ++i, a = b, b = c, idA = idB, idB = idC) {
      c = lineString[i];
      idC = ringByPoint[c[0] + "," + c[1]];
      if (idA === idB && idB === idC) {
        triangle = [a, b, c];
        triangle.ring = ringId;
        b[2] = area(triangle);
        heap.push(triangle);
        if (triangle0) (triangle.previous = triangle0).next = triangle;
        triangle0 = triangle;
      } else {
        addSharedPoint(b);
        triangle0 = null;
      }
    }
    addSharedPoint(c);

    function addSharedPoint(point) {
      var key = point[0] + "," + point[1],
          rings = ringsByPoint.hasOwnProperty(key) ? ringsByPoint[key] : (ringsByPoint[key] = []);
      rings.forEach(function(ring) {
        graph[ring][ringId] = graph[ringId][ring] = 1;
      });
      rings.push(ringId);
      if (sharedPoints.hasOwnProperty(key)) sharedPoints[key].push(point);
      else sharedPoints[key] = [point];
    }

    return lineString;
  }

  // Project and triangulate.
  function triangulateLineStringSimple(lineString) {
    var points = lineString.map(projection),
        n = points.length - 1,
        triangle0,
        triangle,
        a = points[0],
        b = points[1],
        c;

    points[0][2] = points[n][2] = 0;

    for (var i = 2; i <= n; ++i) {
      triangle = [a, b, c = points[i]];
      b[2] = area(triangle);
      heap.push(triangle);
      if (triangle0) (triangle.previous = triangle0).next = triangle;
      triangle0 = triangle;
      a = b;
      b = c;
    }

    return points;
  }

  function triangulateSimple(object) {
    var type = object.type;
    if (type === "FeatureCollection") object.features.forEach(triangulateFeature);
    else (type === "Feature" ? triangulateFeature : triangulateGeometry)(object);
  }

  function triangulateTopology(object) {
    var type = object.type;
    ringId = 0;
    if (type === "FeatureCollection") {
      object.features.forEach(projectFeature);
      ringId = 0;
      object.features.forEach(triangulateFeature);
    } else if (type === "Feature") {
      projectFeature(object);
      ringId = 0;
      triangulateFeature(object);
    } else {
      projectGeometry(object);
      ringId = 0;
      triangulateGeometry(object);
    }
  }

  function triangulateFeature(feature) {
    triangulateGeometry(feature.geometry);
  }

  function triangulateGeometry(geometry) {
    var type = geometry.type;
    if (type === "GeometryCollection") geometry.geometries.forEach(triangulateGeometry);
    else geometry.coordinates = triangulateCoordinates[type](geometry.coordinates);
  }

  function triangulateMultiPolygon(multiPolygon) {
    return multiPolygon.map(triangulatePolygon);
  }

  function triangulatePolygon(polygon) {
    return polygon.map(triangulateLineString);
  }

  function simplifyFeature(feature) {
    feature = copy(feature);
    feature.geometry = simplifyGeometry(feature.geometry);
    return feature;
  }

  function simplifyGeometry(geometry) {
    var type = geometry.type;
    geometry = copy(geometry);
    if (type === "GeometryCollection") {
      geometry.geometries = geometry.geometries.map(simplifyGeometry).filter(nonemptyGeometry);
    } else {
      geometry.coordinates = simplifyCoordinates[type](geometry.coordinates);
    }
    return geometry;
  }

  function simplifyMultiPolygon(multiPolygon) {
    return multiPolygon.map(simplifyPolygon).filter(length);
  }

  function simplifyPolygon(polygon) {
    return polygon.map(simplifyLineString).filter(length);
  }

  function simplifyLineString(lineString) {
    return lineString.filter(filterLineString);
  }

  function filterLineString(point) {
    return point[2] >= minArea;
  }

  simplify.projection = function(_) {
    if (!arguments.length) return projection;
    projection = _;
    return simplify;
  };

  simplify.area = function(_) {
    if (!arguments.length) return minArea;
    minArea = +_;
    return simplify;
  };

  simplify.topology = function(_) {
    if (!arguments.length) return topology;
    triangulateCoordinates.LineString =
    triangulateLineString = (topology = !!_)
        ? triangulateLineStringTopology
        : triangulateLineStringSimple;
    return simplify;
  };

  return simplify;
};

function compare(a, b) {
  return a[1][2] - b[1][2] || a[1][1] - b[1][1] || a[1][0] - b[1][0];
}

function area(t) {
  return Math.abs((t[0][0] - t[2][0]) * (t[1][1] - t[0][1]) - (t[0][0] - t[1][0]) * (t[2][1] - t[0][1]));
}

function minHeap() {
  var heap = {},
      array = [];

  heap.push = function() {
    for (var i = 0, n = arguments.length; i < n; ++i) {
      var object = arguments[i];
      up(object.index = array.push(object) - 1);
    }
    return array.length;
  };

  heap.pop = function() {
    var removed = array[0],
        object = array.pop();
    if (array.length) {
      array[object.index = 0] = object;
      down(0);
    }
    return removed;
  };

  heap.remove = function(removed) {
    var i = removed.index,
        object = array.pop();
    if (i !== array.length) {
      array[object.index = i] = object;
      (compare(object, removed) < 0 ? up : down)(i);
    }
    return i;
  };

  function up(i) {
    var object = array[i];
    while (i > 0) {
      var up = ((i + 1) >> 1) - 1,
          parent = array[up];
      if (compare(object, parent) >= 0) break;
      array[parent.index = i] = parent;
      array[object.index = i = up] = object;
    }
  }

  function down(i) {
    var object = array[i];
    while (true) {
      var right = (i + 1) << 1,
          left = right - 1,
          down = i,
          child = array[down];
      if (left < array.length && compare(array[left], child) < 0) child = array[down = left];
      if (right < array.length && compare(array[right], child) < 0) child = array[down = right];
      if (down === i) break;
      array[child.index = i] = child;
      array[object.index = i = down] = object;
    }
  }

  return heap;
}

function nonemptyFeature(d) { return nonemptyGeometry(d.geometry); }

function nonemptyGeometry(d) {
  return length(d.type === "GeometryCollection"
      ? d.geometries : d.coordinates);
}

function length(d) { return d.length; }

function copy(object) {
  var o = {};
  for (var key in object) o[key] = object[key];
  return o;
}

})();
<commit_msg>d3.simplify: improve polygon handling.<commit_after>(function() {

d3.simplify = function() {
  var projection = d3.geo.albers(),
      triangulateLineString = triangulateLineStringSimple,
      heap,
      minArea = 3,
      topology = false,
      ringId,
      id,
      idByRings,
      ringByPoint,
      ringsByPoint,
      sharedPoints,
      graph;

  var projectCoordinates = {
    MultiPolygon: projectMultiPolygon,
    Polygon: projectPolygon,
    MultiLineString: projectPolygon,
    LineString: projectLineString
  };

  var triangulateCoordinates = {
    MultiPolygon: triangulateMultiPolygon,
    Polygon: triangulatePolygon,
    MultiLineString: triangulatePolygon,
    LineString: triangulateLineString
  };

  var simplifyCoordinates = {
    MultiPolygon: simplifyMultiPolygon,
    Polygon: simplifyPolygon,
    MultiLineString: simplifyPolygon,
    LineString: simplifyLineString
  };

  function simplify(object) {
    var type = object.type;
    if (type === "FeatureCollection") {
      object = copy(object);
      object.features = object.features.map(simplifyFeature).filter(nonemptyFeature);
      return object;
    }
    return (type === "Feature" ? simplifyFeature : simplifyGeometry)(object);
  }

  simplify.project = function(feature) {
    var maxArea = 0,
        maxAreas = {},
        triangle;

    heap = minHeap();

    if (topology) {
      id = 0;
      idByRings = {};
      ringsByPoint = {};
      ringByPoint = {};
      sharedPoints = {};
      graph = {};
      triangulateTopology(feature);
    } else {
      triangulateSimple(feature);
    }

    while (triangle = heap.pop()) {
      // If the area of the current point is less than that of the previous point
      // to be eliminated, use the latter’s area instead. This ensures that the
      // current point cannot be eliminated without eliminating previously-
      // eliminated points.
      if (triangle[1][2] < maxArea) triangle[1][2] = maxArea;
      else maxArea = triangle[1][2];

      if (triangle.previous) {
        triangle.previous.next = triangle.next;
        triangle.previous[2] = triangle[2];
        update(triangle.previous);
      } else if (topology) {
        maxAreas[triangle.ring] = triangle[1][2];
      } else {
        triangle[0][2] = triangle[1][2];
      }

      if (triangle.next) {
        triangle.next.previous = triangle.previous;
        triangle.next[0] = triangle[0];
        update(triangle.next);
      } else if (topology) {
        maxAreas[triangle.ring] = triangle[1][2];
      } else {
        triangle[2][2] = triangle[1][2];
      }
    }

    function update(triangle) {
      heap.remove(triangle);
      triangle[1][2] = area(triangle);
      heap.push(triangle);
    }

    if (topology) {
      var seen = {},
          max,
          m,
          c;
      for (var key in graph) {
        if (seen.hasOwnProperty(key)) continue;
        max = 0;
        for (var k in (c = components(graph, key))) if ((m = maxAreas[k]) > max) max = m;
        for (var k in c) maxAreas[k] = max, seen[k] = 1;
      }

      for (var key in sharedPoints) {
        maxArea = maxAreas[ringsByPoint[key][0]];
        sharedPoints[key].forEach(function(point) { point[2] = maxArea; });
      }
      ringByPoint = idByRings = ringsByPoint = sharedPoints = graph = null;
    }

    heap = null;
    return feature;
  };

  function components(graph, source) {
    var seen = {},
        nextLevel = {},
        thisLevel,
        empty;
    nextLevel[source] = 1;
    while (1) {
      empty = true;
      for (var k in nextLevel) empty = false;
      if (empty) break;
      thisLevel = nextLevel;
      nextLevel = {};
      for (var v in thisLevel) {
        if (seen.hasOwnProperty(v)) continue;
        seen[v] = 1;
        var neighbors = graph[v];
        for (var k in neighbors) nextLevel[k] = neighbors[k];
      }
    }
    return seen;
  }

  function projectFeature(feature) {
    projectGeometry(feature.geometry);
  }

  function projectGeometry(geometry) {
    var type = geometry.type;
    if (type === "GeometryCollection") geometry.geometries.forEach(projectGeometry);
    else geometry.coordinates = projectCoordinates[type](geometry.coordinates);
  }

  function projectMultiPolygon(multiPolygon) {
    return multiPolygon.map(projectPolygon);
  }

  function projectPolygon(polygon) {
    return polygon.map(projectLinearRing);
  }

  function projectLinearRing(linearRing) {
    ++ringId;
    var points = [],
        n = linearRing.length - 1;
    for (var i = 0; i < n; ++i) points.push(projectPoint(linearRing[i]));
    points.push(points[0].slice());
    return points;
  }

  function projectLineString(lineString) {
    ++ringId;
    return lineString.map(projectPoint);
  }

  function projectPoint(point) {
    var pointKey = (point = projection(point))[0] + "," + point[1],
        key = (ringByPoint.hasOwnProperty(pointKey) ? ringByPoint[pointKey] + ":" : "") + ringId;
    ringByPoint[pointKey] = idByRings.hasOwnProperty(key)
        ? idByRings[key]
        : idByRings[key] = ++id;
    return point;
  }

  function triangulateLineStringTopology(lineString) {
    ++ringId;
    var n = lineString.length - 1,
        triangle0,
        triangle,
        a = lineString[0],
        b = lineString[1],
        c,
        idA = ringByPoint[a[0] + "," + a[1]],
        idB = ringByPoint[b[0] + "," + b[1]],
        idC;

    lineString[0][2] = lineString[n][2] = 0;
    if (n < 2) return lineString;

    graph[ringId] = {};

    addSharedPoint(a);
    for (var i = 2; i <= n; ++i, a = b, b = c, idA = idB, idB = idC) {
      c = lineString[i];
      idC = ringByPoint[c[0] + "," + c[1]];
      if (idA === idB && idB === idC) {
        triangle = [a, b, c];
        triangle.ring = ringId;
        b[2] = area(triangle);
        heap.push(triangle);
        if (triangle0) (triangle.previous = triangle0).next = triangle;
        triangle0 = triangle;
      } else {
        addSharedPoint(b);
        triangle0 = null;
      }
    }
    addSharedPoint(c);

    function addSharedPoint(point) {
      var key = point[0] + "," + point[1],
          rings = ringsByPoint.hasOwnProperty(key) ? ringsByPoint[key] : (ringsByPoint[key] = []);
      rings.forEach(function(ring) {
        graph[ring][ringId] = graph[ringId][ring] = 1;
      });
      rings.push(ringId);
      if (sharedPoints.hasOwnProperty(key)) sharedPoints[key].push(point);
      else sharedPoints[key] = [point];
    }

    return lineString;
  }

  // Project and triangulate.
  function triangulateLineStringSimple(lineString) {
    var points = lineString.map(projection),
        n = points.length - 1,
        triangle0,
        triangle,
        a = points[0],
        b = points[1],
        c;

    points[0][2] = points[n][2] = 0;

    for (var i = 2; i <= n; ++i) {
      triangle = [a, b, c = points[i]];
      b[2] = area(triangle);
      heap.push(triangle);
      if (triangle0) (triangle.previous = triangle0).next = triangle;
      triangle0 = triangle;
      a = b;
      b = c;
    }

    return points;
  }

  function triangulateSimple(object) {
    var type = object.type;
    if (type === "FeatureCollection") object.features.forEach(triangulateFeature);
    else (type === "Feature" ? triangulateFeature : triangulateGeometry)(object);
  }

  function triangulateTopology(object) {
    var type = object.type;
    ringId = 0;
    if (type === "FeatureCollection") {
      object.features.forEach(projectFeature);
      ringId = 0;
      object.features.forEach(triangulateFeature);
    } else if (type === "Feature") {
      projectFeature(object);
      ringId = 0;
      triangulateFeature(object);
    } else {
      projectGeometry(object);
      ringId = 0;
      triangulateGeometry(object);
    }
  }

  function triangulateFeature(feature) {
    triangulateGeometry(feature.geometry);
  }

  function triangulateGeometry(geometry) {
    var type = geometry.type;
    if (type === "GeometryCollection") geometry.geometries.forEach(triangulateGeometry);
    else geometry.coordinates = triangulateCoordinates[type](geometry.coordinates);
  }

  function triangulateMultiPolygon(multiPolygon) {
    return multiPolygon.map(triangulatePolygon);
  }

  function triangulatePolygon(polygon) {
    return polygon.map(triangulateLineString);
  }

  function simplifyFeature(feature) {
    feature = copy(feature);
    feature.geometry = simplifyGeometry(feature.geometry);
    return feature;
  }

  function simplifyGeometry(geometry) {
    var type = geometry.type;
    geometry = copy(geometry);
    if (type === "GeometryCollection") {
      geometry.geometries = geometry.geometries.map(simplifyGeometry).filter(nonemptyGeometry);
    } else {
      geometry.coordinates = simplifyCoordinates[type](geometry.coordinates);
    }
    return geometry;
  }

  function simplifyMultiPolygon(multiPolygon) {
    return multiPolygon.map(simplifyPolygon).filter(length);
  }

  function simplifyPolygon(polygon) {
    return polygon.map(simplifyLineString).filter(length);
  }

  function simplifyLineString(lineString) {
    return lineString.filter(filterLineString);
  }

  function filterLineString(point) {
    return point[2] >= minArea;
  }

  simplify.projection = function(_) {
    if (!arguments.length) return projection;
    projection = _;
    return simplify;
  };

  simplify.area = function(_) {
    if (!arguments.length) return minArea;
    minArea = +_;
    return simplify;
  };

  simplify.topology = function(_) {
    if (!arguments.length) return topology;
    triangulateCoordinates.LineString =
    triangulateLineString = (topology = !!_)
        ? triangulateLineStringTopology
        : triangulateLineStringSimple;
    return simplify;
  };

  return simplify;
};

function compare(a, b) {
  return a[1][2] - b[1][2] || a[1][1] - b[1][1] || a[1][0] - b[1][0];
}

function area(t) {
  return Math.abs((t[0][0] - t[2][0]) * (t[1][1] - t[0][1]) - (t[0][0] - t[1][0]) * (t[2][1] - t[0][1]));
}

function minHeap() {
  var heap = {},
      array = [];

  heap.push = function() {
    for (var i = 0, n = arguments.length; i < n; ++i) {
      var object = arguments[i];
      up(object.index = array.push(object) - 1);
    }
    return array.length;
  };

  heap.pop = function() {
    var removed = array[0],
        object = array.pop();
    if (array.length) {
      array[object.index = 0] = object;
      down(0);
    }
    return removed;
  };

  heap.remove = function(removed) {
    var i = removed.index,
        object = array.pop();
    if (i !== array.length) {
      array[object.index = i] = object;
      (compare(object, removed) < 0 ? up : down)(i);
    }
    return i;
  };

  function up(i) {
    var object = array[i];
    while (i > 0) {
      var up = ((i + 1) >> 1) - 1,
          parent = array[up];
      if (compare(object, parent) >= 0) break;
      array[parent.index = i] = parent;
      array[object.index = i = up] = object;
    }
  }

  function down(i) {
    var object = array[i];
    while (true) {
      var right = (i + 1) << 1,
          left = right - 1,
          down = i,
          child = array[down];
      if (left < array.length && compare(array[left], child) < 0) child = array[down = left];
      if (right < array.length && compare(array[right], child) < 0) child = array[down = right];
      if (down === i) break;
      array[child.index = i] = child;
      array[object.index = i = down] = object;
    }
  }

  return heap;
}

function nonemptyFeature(d) { return nonemptyGeometry(d.geometry); }

function nonemptyGeometry(d) {
  return length(d.type === "GeometryCollection"
      ? d.geometries : d.coordinates);
}

function length(d) { return d.length; }

function copy(object) {
  var o = {};
  for (var key in object) o[key] = object[key];
  return o;
}

})();
<|endoftext|>


<commit_before>/* global config */
const config = require('collections-online/lib/config');
const helpers = require('collections-online/shared/helpers');

helpers.documentTitle = (metadata, fallback) => {
  let title = metadata.short_title || fallback || 'Billede uden titel';
  return helpers.capitalizeFirstLetter(title);
};

helpers.documentDescription = (metadata, fallback) => {
  let description = metadata.description || fallback || '';
  return helpers.capitalizeFirstLetter(description);
};

helpers.documentSecondaryDescription = (metadata, fallback) => {
  let description = metadata.secondary_description || fallback || '';
  return helpers.capitalizeFirstLetter(description);
};

helpers.documentLicense = (metadata) => {
  return metadata.license && metadata.license.displaystring;
};

// TODO: Delete this when metadata.catalog has transitioned to .collection
helpers.getDocumentURL = (metadata) => {
  let path = [metadata.collection || metadata.catalog];
  if(Object.keys(config.types).length > 1) {
    path.push(metadata.type);
  }
  path.push(metadata.id);
  return '/' + path.join('/');
};

helpers.determinePlayer = (metadata) => {
  return 'image';
};

helpers.generateSitemapElements = (metadata) => {
  throw new Exception('Not yet implemented');
};

function getFileDimensionsString(metadata, size) {
  let width = metadata.width_px;
  let height = metadata.height_px;
  if(typeof(size) === 'number') {
    let ratio = width / height;
    if(ratio > 1) {
      width = size;
      height = size / ratio;
    } else {
      width = size * ratio;
      height = size;
    }
  }
  return Math.round(width) + ' × ' + Math.round(height);
}

function generateSizeDownloadOption(optionKey, option) {
  return {
    label: metadata => {
      let dimensions = getFileDimensionsString(metadata, option.size);
      return option.labelPrefix + ' (' + dimensions + ') JPEG';
    },
    filter: (metadata, derived) => {
      return derived.maxSize >= option.size;
    },
    url: metadata => helpers.getDownloadURL(metadata, optionKey),
  };
}

if(config.downloadOptions) {
  // Loop though the download options defined in the configuration and make them
  // available as an iteratable array of 3-method objects
  const AVAILABLE_DOWNLOAD_OPTIONS = Object.keys(config.downloadOptions)
  .map(optionKey => {
    const option = config.downloadOptions[optionKey];
    if(option.size) {
      return generateSizeDownloadOption(optionKey, option);
    } else if(optionKey === 'original-jpeg') {
      return {
        label: metadata => {
          let label = option.labelPrefix;
          return label + ' (' + getFileDimensionsString(metadata) + ') JPEG';
        },
        filter: metadata => {
          return metadata.file_format !== 'JPEG Image';
        },
        url: metadata => helpers.getDownloadURL(metadata, optionKey),
      };
    } else if(optionKey === 'original') {
      return {
        label: metadata => {
          const type = metadata.file_format;
          // TODO: Consider translating the file_format
          const label = option.labelPrefix;
          return label + ' (' + getFileDimensionsString(metadata) + ') ' + type;
        },
        filter: metadata => {
          return true; // Let's always allow download of the original
        },
        url: metadata => helpers.getDownloadURL(metadata),
      };
    } else {
      throw new Error('Expected "orignal", "original-jpeg" or a size field');
    }
  });

  helpers.getDownloadOptions = (metadata) => {
    let derived = {
      maxSize: Math.max(metadata.width_px, metadata.height_px)
    };

    return AVAILABLE_DOWNLOAD_OPTIONS.filter(option => {
      return option.filter(metadata, derived);
    }).map(option => {
      return {
        label: option.label(metadata, derived),
        url: option.url(metadata, derived)
      };
    });
  };
}

helpers.isDownloadable = (metadata) => {
  return !metadata.license || metadata.license.id !== 7;
};

helpers.isWatermarkRequired = (metadata) => {
  if(metadata.license) {
    const licenseMapped = config.licenseMapping[metadata.license.id];
    return licenseMapped && licenseMapped.watermark;
  } else {
    return false;
  }
};

module.exports = helpers;
<commit_msg>Defined a cleanDocumentId helper, as collections-online was pulled from upstream<commit_after>/* global config */
const config = require('collections-online/lib/config');
const helpers = require('collections-online/shared/helpers');

helpers.documentTitle = (metadata, fallback) => {
  let title = metadata.short_title || fallback || 'Billede uden titel';
  return helpers.capitalizeFirstLetter(title);
};

helpers.documentDescription = (metadata, fallback) => {
  let description = metadata.description || fallback || '';
  return helpers.capitalizeFirstLetter(description);
};

helpers.documentSecondaryDescription = (metadata, fallback) => {
  let description = metadata.secondary_description || fallback || '';
  return helpers.capitalizeFirstLetter(description);
};

helpers.documentLicense = (metadata) => {
  return metadata.license && metadata.license.displaystring;
};

// TODO: Delete this when metadata.catalog has transitioned to .collection
helpers.getDocumentURL = (metadata) => {
  let path = [metadata.collection || metadata.catalog];
  if(Object.keys(config.types).length > 1) {
    path.push(metadata.type);
  }
  path.push(metadata.id);
  return '/' + path.join('/');
};

helpers.determinePlayer = (metadata) => {
  return 'image';
};

helpers.generateSitemapElements = (metadata) => {
  throw new Exception('Not yet implemented');
};

function getFileDimensionsString(metadata, size) {
  let width = metadata.width_px;
  let height = metadata.height_px;
  if(typeof(size) === 'number') {
    let ratio = width / height;
    if(ratio > 1) {
      width = size;
      height = size / ratio;
    } else {
      width = size * ratio;
      height = size;
    }
  }
  return Math.round(width) + ' × ' + Math.round(height);
}

function generateSizeDownloadOption(optionKey, option) {
  return {
    label: metadata => {
      let dimensions = getFileDimensionsString(metadata, option.size);
      return option.labelPrefix + ' (' + dimensions + ') JPEG';
    },
    filter: (metadata, derived) => {
      return derived.maxSize >= option.size;
    },
    url: metadata => helpers.getDownloadURL(metadata, optionKey),
  };
}

if(config.downloadOptions) {
  // Loop though the download options defined in the configuration and make them
  // available as an iteratable array of 3-method objects
  const AVAILABLE_DOWNLOAD_OPTIONS = Object.keys(config.downloadOptions)
  .map(optionKey => {
    const option = config.downloadOptions[optionKey];
    if(option.size) {
      return generateSizeDownloadOption(optionKey, option);
    } else if(optionKey === 'original-jpeg') {
      return {
        label: metadata => {
          let label = option.labelPrefix;
          return label + ' (' + getFileDimensionsString(metadata) + ') JPEG';
        },
        filter: metadata => {
          return metadata.file_format !== 'JPEG Image';
        },
        url: metadata => helpers.getDownloadURL(metadata, optionKey),
      };
    } else if(optionKey === 'original') {
      return {
        label: metadata => {
          const type = metadata.file_format;
          // TODO: Consider translating the file_format
          const label = option.labelPrefix;
          return label + ' (' + getFileDimensionsString(metadata) + ') ' + type;
        },
        filter: metadata => {
          return true; // Let's always allow download of the original
        },
        url: metadata => helpers.getDownloadURL(metadata),
      };
    } else {
      throw new Error('Expected "orignal", "original-jpeg" or a size field');
    }
  });

  helpers.getDownloadOptions = (metadata) => {
    let derived = {
      maxSize: Math.max(metadata.width_px, metadata.height_px)
    };

    return AVAILABLE_DOWNLOAD_OPTIONS.filter(option => {
      return option.filter(metadata, derived);
    }).map(option => {
      return {
        label: option.label(metadata, derived),
        url: option.url(metadata, derived)
      };
    });
  };
}

helpers.isDownloadable = (metadata) => {
  return !metadata.license || metadata.license.id !== 7;
};

helpers.isWatermarkRequired = (metadata) => {
  if(metadata.license) {
    const licenseMapped = config.licenseMapping[metadata.license.id];
    return licenseMapped && licenseMapped.watermark;
  } else {
    return false;
  }
};

helpers.cleanDocumentId = (id) => {
  // We simply return the id ..
  console.log('cleanDocumentId called with', id);
  return id;
};

module.exports = helpers;
<|endoftext|>


<commit_before>Qlb.globalEnvironment.merge({
  // general

  "رأس":    // head
  function(x) {
    return x[0];
  },

  "ذيل":    // tail
  function(x) {
    return x.slice(1);
  },

  "كينس":    // cons
  function(x, y) {
    return [x].concat(y)
  },

  "كينس":    // cons
  function(x, y) {
    return [x].concat(y)
  },

  "و":    // and
  function(x, y) {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      if(idx > 0) return prv && !!cur;
      else return !!cur;
    });
  },

  "أو":    // or
  function(x, y) {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      if(idx > 0) return prv || !!cur;
      else return !!cur;
    });
  },

  // input/output

  "قول":    // say
  function(str) {
    Qlb.console.log(str);
    return str;
  },

  "ضمن":    // require
  function(url) {
      jx.load("/lib/" + url.replace("\\", "/") + ".qlb", function(code) {
      return Qlb.execute(code);
    }, function(error) {
      Qlb.console.warn("خطأ: نص '" + url + "' غير موجود");
    }, false);
  },

  // comparison

  "أكبر؟":     // greater
  function(a, b) {
    return a > b;
  },

  "أكبر-أو-يساوي؟":     // greater or equal
  function(a, b) {
    return a >= b;
  },

  "أصغر؟":     // less
  function(a, b) {
    return a < b
  },

  "أصغر-أو-يساوي؟":     // less or equal
  function(a, b) {
    return a <= b;
  },

  // arithmetic

  "سقف":     // ceil
  function(x) {
    return Math.ceil(x)
  },

  "أرض":     // floor
  function(x) {
    return Math.floor(x)
  },

  "القيمة-المطلقة":     // abs
  function(x) {
    return Math.abs(x)
  },

  "الأكبر":     // max
  function() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      if(idx > 0) return cur > prv ? cur : prv
      else return cur
    });
  },

  "الأصغر":     // min
  function() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      if(idx > 0) return cur < prv ? cur : prv
      else return cur
    });
  },

  "جمع":     // add
  function() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      return prv + cur;
    });
  },

  "طرح":    // subtract
  function() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      return prv - cur;
    });
  },

  "ضرب":     // multiply
  function() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      return prv * cur;
    });
  },

  "ضرب":     // divide
  function() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      return prv / cur;
    });
  }
});<commit_msg>Add primitives to support Conway's Game of Life<commit_after>Qlb.globalEnvironment.merge({
  // general

  "رأس":          // head
  function(x) {
    return x[0];
  },

  "ذيل":    // tail
  function(x) {
    return x.slice(1);
  },

  "كونس":    // cons
  function(x, y) {
    return [x].concat(y)
  },

  "طول":    // cons
  function(lst) {
    return lst.length;
  },

  "حال":    // cond
  function() {
    for (var i = 0; i < arguments.length; i++) {
      var cond = Qlb.eval(arguments[i][0]),
          val = arguments[i][1];
    }
  },

  "عدم": // null
  function() {
    return [];
  },

  "عدم?": // null?
  function(lst) {
    return lst instanceof Array && lst.length == 0;
  },

  "لائحة؟": // list?
  function(lst) {
    return lst instanceof Array;
  },

  "و":    // and
  function() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      if(idx > 0) return prv && !!cur;
      else return !!cur;
    });
  },

  "أو":    // or
  function() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      if(idx > 0) return prv || !!cur;
      else return !!cur;
    });
  },

  "طبق":    // map
  function(fn, lst) {
    return lst.map(fn);
  },

  // input/output

  "قول":    // say
  function(str) {
    Qlb.console.log(str);
    return str;
  },

  "ضمن":    // require
  function(url) {
      jx.load("/lib/" + url.replace("\\", "/") + ".qlb", function(code) {
      return Qlb.execute(code);
    }, function(error) {
      Qlb.console.warn("خطأ: نص '" + url + "' غير موجود");
    }, false);
  },

  // comparison

  "يساوي؟":     // equals
  function(a, b) {
    return a == b;
  },

  "أكبر؟":     // greater
  function(a, b) {
    return a > b;
  },

  "أكبر-أو-يساوي؟":     // greater or equal
  function(a, b) {
    return a >= b;
  },

  "أصغر؟":     // less
  function(a, b) {
    return a < b
  },

  "أصغر-أو-يساوي؟":     // less or equal
  function(a, b) {
    return a <= b;
  },

  // arithmetic

  "سقف":     // ceil
  function(x) {
    return Math.ceil(x)
  },

  "أرض":     // floor
  function(x) {
    return Math.floor(x)
  },

  "القيمة-المطلقة":     // abs
  function(x) {
    return Math.abs(x)
  },

  "الأكبر":     // max
  function() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      if(idx > 0) return cur > prv ? cur : prv
      else return cur
    });
  },

  "الأصغر":     // min
  function() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      if(idx > 0) return cur < prv ? cur : prv
      else return cur
    });
  },

  "جمع":     // add
  function() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      return prv + cur;
    });
  },

  "طرح":    // subtract
  function() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      return prv - cur;
    });
  },

  "ضرب":     // multiply
  function() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      return prv * cur;
    });
  },

  "قسم":     // divide
  function() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(prv, cur, idx, ary) {
      return prv / cur;
    });
  }
});<|endoftext|>


<commit_before>
var   fs = require('graceful-fs')
    , path = require('path')
    , wrench = require('wrench')
    , fse = require('fs-extra')
    , bars = require('handlebars')
    , util = require('../../util/util')

var internal = {};

exports.run = function run(flow, files) {

        //copy local project + build files

    flow.log(2, 'files - copying project assets to %s', flow.project.paths.files);
    flow.log(3,'');

        var projectfiles = internal.copy_files(flow, files.project_files, flow.project.paths.files);

    flow.log(3,'');
    flow.log(2, 'files - copying build files to %s', flow.project.paths.build);
    flow.log(3,'');

        var buildfiles = internal.copy_files(flow, files.build_files, flow.project.paths.build);

        //clean up the list of files by their destination
    projectfiles.map(function(_path, i){
        _path = util.normalize(_path);
        projectfiles[i] = _path.replace(flow.project.paths.files,'');
    });

        //clean up the list of files by their destination
    buildfiles.map(function(_path, i){
        _path = util.normalize(_path);
        buildfiles[i] = _path.replace(flow.project.paths.build,'');
    });

        //store the lists
    flow.project.prepared.files.project_files_output = projectfiles;
    flow.project.prepared.files.build_files_output = buildfiles;

    flow.log(3,'');
    flow.log(3,'files - done');
    flow.log(3,'');

} //run

    //in this case, verify will return a list of files
    //as a flat array of { source : dest } from prepared
exports.verify = function verify(flow, done) {

    flow.log(3, 'files - verifying ... ');

    var final_project_files = [];
    var final_build_files = [];

    var warning = '';
    var err = null;

        //check if each source exists, otherwise
        //we throw an error because this is likely
        //unexpected. this can be configured from the
        //flow : { } object in the project
    for(index in flow.project.prepared.files.project_files) {

        var file = flow.project.prepared.files.project_files[index];

        flow.log(4, 'files - checking for project file `' + file.source +'`');
        if(!fs.existsSync(file.source)) {
            warning += '       > missing files source path ' + file.source + '\n';
        } else {
            final_project_files.push(file);
        }

    } //index in prepared files

    for(index in flow.project.prepared.files.build_files) {

        var file = flow.project.prepared.files.build_files[index];

        flow.log(4, 'files - checking for build file `' + file.source +'`');
        if(!fs.existsSync(file.source)) {
            warning += '       > missing files source path ' + file.source + '\n';
        } else {
            final_build_files.push(file);
        }

    } //index in prepared build files

    if(flow.config.build.files_error_on_missing) {
        if(warning) {
            err = warning;
            flow.project.failed = true;
        }
    } else {
        if(warning) {
            internal._missing_warning(flow, warning, 'Warning');
        }
    }

    done(err, { project_files:final_project_files, build_files:final_build_files });

} //verify

internal.copy_files = function(flow, files, output) {

    var copied_list = [];

    if(files.length > 0) {

                //first deal with the files in the project itself
            for(index in files) {

                var node = files[index];
                var dest = util.normalize(path.join(output, node.dest));

                if(node.template) {
                    flow.log(3, '   copying with template %s from %s to %s%s', node.template, node.source, output, node.dest);
                    if(!node.not_listed) {
                        copied_list = copied_list.concat( internal.template_path(flow, node, dest) );
                    }
                } else {
                    flow.log(3, '   copying %s to %s%s', node.source, output, node.dest);
                    if(!node.not_listed) {
                        copied_list = copied_list.concat( util.copy_path(flow, node.source, dest) );
                    }
                }

            } //each project file

    } //files.length > 0

    return copied_list;

} //copy_project_files

internal.template_path = function(flow, node, dest) {

    if(fs.statSync(node.source).isDirectory()) {
        return internal.template_folder_recursively(flow, node, dest);
    } else {
        internal.template_file(flow, node.template, node.source, dest);
        return [ dest ];
    }

} //template_path

internal.template_folder_recursively = function(flow, node, _dest, _overwrite) {

    var copied_list = [];

    if(_overwrite == undefined) _overwrite = true;

        //make sure the destination exists
        //before copying any files to the location
    wrench.mkdirSyncRecursive(_dest, 0755);

        //obtain a list of items from the source
    var _source_path = node.source;
        //if a relative path from our project, make it absolute
    if(!node.source_name) {
        _source_path = util.normalize(path.resolve(flow.run_path, node.source), true);
    }

    var _source_list = wrench.readdirSyncRecursive(_source_path);

        //for each source item, check if it's a directory
    var _source_file_list = [];

    for(var i = 0; i < _source_list.length; ++i) {
        var _is_dir = fs.statSync( path.join(node.source, _source_list[i]) ).isDirectory();
        if(!_is_dir) {
            var allow = _source_list[i].charAt(0) != '.' || !flow.config.build.files_ignore_dotfiles;
            if(allow) {
              _source_file_list.push(_source_list[i]);
            }
        }
    }

        //for each file only, copy it across
    for(var i = 0; i < _source_file_list.length; ++i) {

        var _dest_file = path.join( _dest, _source_file_list[i] );
        var source_path = path.join(node.source, _source_file_list[i]);

        flow.log(3,'        - copying with template %s %s to %s', node.template, source_path, _dest_file );

        // fse.copySync( source_path, _dest_file );
        internal.template_file(flow, node.template, source_path, _dest_file);
        copied_list.push(_dest_file);

    } //each source file

    return copied_list;

} //template_folder_recursively

internal.template_file = function(flow, _template, _source, _dest) {

    var templates = [];

        //we allow multiple context nodes via ['one','two']
    if(_template.constructor == Array) {
        templates = _template;
    } else if(_template.constructor == String) {
        templates.push(_template);
    } else {
        flow.log(1, '    Warning - template value on `files` currently supports Array or String only', _source, _template );
    }

        //we wrap the context against a root for clarity in the template files
        //as well as allowing multiple contexts side by side
    var real_context = {
        debug : flow.flags.debug || false,
        flow : { config : flow.config }
    };

    for(index in templates) {
        var templ = templates[index];
        var context = flow.project.prepared.source[templ];
        if(!context) {
            flow.log(1, '    Warning - template value missing! %s was not found in the project root', templ);
        } else {
            real_context[templ] = context;
        }
    } //each templates

    var raw_file = fs.readFileSync(_source, 'utf8');

    flow.log(6, 'context for file node : ', _source, real_context);

    var template = bars.compile(raw_file);
    var templated = template( real_context );

    fse.ensureFileSync(_dest);
    fs.writeFileSync(_dest, templated, 'utf8');

} //template_file

internal._missing_warning = function(flow, msg, type) {

    var level = 3;

    if(type == 'Error') {
        level = 1;
    }

    flow.log(level, '\n    %s', type);
    flow.log(level, '      failed to find some files list in project tree!\n');
    flow.log(level, '%s', msg);

} //_missing_warning

exports.error = function(flow, err) {

    internal._missing_warning(flow, err, 'Error');

} //error

<commit_msg>add flow files <target> command fixes, as well as fixing files not being copied if node.not_listed was set<commit_after>
var   fs = require('graceful-fs')
    , path = require('path')
    , wrench = require('wrench')
    , fse = require('fs-extra')
    , bars = require('handlebars')
    , util = require('../../util/util')

var internal = {};

exports.run = function run(flow, files) {

        //copy local project + build files

    flow.log(2, 'files - copying project assets to %s', flow.project.paths.files);
    flow.log(3,'');

        var projectfiles = internal.copy_files(flow, files.project_files, flow.project.paths.files);

    flow.log(3,'');
    flow.log(2, 'files - copying build files to %s', flow.project.paths.build);
    flow.log(3,'');

        var buildfiles = internal.copy_files(flow, files.build_files, flow.project.paths.build);

        //clean up the list of files by their destination
    projectfiles.map(function(_path, i){
        _path = util.normalize(_path);
        projectfiles[i] = _path.replace(flow.project.paths.files,'');
    });

        //clean up the list of files by their destination
    buildfiles.map(function(_path, i){
        _path = util.normalize(_path);
        buildfiles[i] = _path.replace(flow.project.paths.build,'');
    });

        //store the lists
    flow.project.prepared.files.project_files_output = projectfiles;
    flow.project.prepared.files.build_files_output = buildfiles;

    flow.log(3,'');
    flow.log(3,'files - done');
    flow.log(3,'');

} //run

    //in this case, verify will return a list of files
    //as a flat array of { source : dest } from prepared
exports.verify = function verify(flow, done) {

    flow.log(3, 'files - verifying ... ');

    flow.project.do_prepare(flow);

    var final_project_files = [];
    var final_build_files = [];

    var warning = '';
    var err = null;

        //check if each source exists, otherwise
        //we throw an error because this is likely
        //unexpected. this can be configured from the
        //flow : { } object in the project
    for(index in flow.project.prepared.files.project_files) {

        var file = flow.project.prepared.files.project_files[index];

        flow.log(4, 'files - checking for project file `' + file.source +'`');
        if(!fs.existsSync(file.source)) {
            warning += '       > missing files source path ' + file.source + '\n';
        } else {
            final_project_files.push(file);
        }

    } //index in prepared files

    for(index in flow.project.prepared.files.build_files) {

        var file = flow.project.prepared.files.build_files[index];

        flow.log(4, 'files - checking for build file `' + file.source +'`');
        if(!fs.existsSync(file.source)) {
            warning += '       > missing files source path ' + file.source + '\n';
        } else {
            final_build_files.push(file);
        }

    } //index in prepared build files

    if(flow.config.build.files_error_on_missing) {
        if(warning) {
            err = warning;
            flow.project.failed = true;
        }
    } else {
        if(warning) {
            internal._missing_warning(flow, warning, 'Warning');
        }
    }

    done(err, { project_files:final_project_files, build_files:final_build_files });

} //verify

internal.copy_files = function(flow, files, output) {

    var copied_list = [];

    if(files.length > 0) {

                //first deal with the files in the project itself
            for(index in files) {

                var node = files[index];
                var dest = util.normalize(path.join(output, node.dest));

                if(node.template) {

                    flow.log(3, '   copying with template %s from %s to %s%s', node.template, node.source, output, node.dest);

                    var res = internal.template_path(flow, node, dest);

                    if(!node.not_listed) {
                        copied_list = copied_list.concat( res );
                    }

                } else {

                    flow.log(3, '   copying %s to %s%s', node.source, output, node.dest);

                    var res = util.copy_path(flow, node.source, dest);

                    if(!node.not_listed) {
                        copied_list = copied_list.concat( res );
                    }
                }

            } //each project file

    } //files.length > 0

    return copied_list;

} //copy_project_files

internal.template_path = function(flow, node, dest) {

    if(fs.statSync(node.source).isDirectory()) {
        return internal.template_folder_recursively(flow, node, dest);
    } else {
        internal.template_file(flow, node.template, node.source, dest);
        return [ dest ];
    }

} //template_path

internal.template_folder_recursively = function(flow, node, _dest, _overwrite) {

    var copied_list = [];

    if(_overwrite == undefined) _overwrite = true;

        //make sure the destination exists
        //before copying any files to the location
    wrench.mkdirSyncRecursive(_dest, 0755);

        //obtain a list of items from the source
    var _source_path = node.source;
        //if a relative path from our project, make it absolute
    if(!node.source_name) {
        _source_path = util.normalize(path.resolve(flow.run_path, node.source), true);
    }

    var _source_list = wrench.readdirSyncRecursive(_source_path);

        //for each source item, check if it's a directory
    var _source_file_list = [];

    for(var i = 0; i < _source_list.length; ++i) {
        var _is_dir = fs.statSync( path.join(node.source, _source_list[i]) ).isDirectory();
        if(!_is_dir) {
            var allow = _source_list[i].charAt(0) != '.' || !flow.config.build.files_ignore_dotfiles;
            if(allow) {
              _source_file_list.push(_source_list[i]);
            }
        }
    }

        //for each file only, copy it across
    for(var i = 0; i < _source_file_list.length; ++i) {

        var _dest_file = path.join( _dest, _source_file_list[i] );
        var source_path = path.join(node.source, _source_file_list[i]);

        flow.log(3,'        - copying with template %s %s to %s', node.template, source_path, _dest_file );

        // fse.copySync( source_path, _dest_file );
        internal.template_file(flow, node.template, source_path, _dest_file);
        copied_list.push(_dest_file);

    } //each source file

    return copied_list;

} //template_folder_recursively

internal.template_file = function(flow, _template, _source, _dest) {

    var templates = [];

        //we allow multiple context nodes via ['one','two']
    if(_template.constructor == Array) {
        templates = _template;
    } else if(_template.constructor == String) {
        templates.push(_template);
    } else {
        flow.log(1, '    Warning - template value on `files` currently supports Array or String only', _source, _template );
    }

        //we wrap the context against a root for clarity in the template files
        //as well as allowing multiple contexts side by side
    var real_context = {
        debug : flow.flags.debug || false,
        flow : { config : flow.config }
    };

    for(index in templates) {
        var templ = templates[index];
        var context = flow.project.prepared.source[templ];
        if(!context) {
            flow.log(1, '    Warning - template value missing! %s was not found in the project root', templ);
        } else {
            real_context[templ] = context;
        }
    } //each templates

    var raw_file = fs.readFileSync(_source, 'utf8');

    flow.log(6, 'context for file node : ', _source, real_context);

    var template = bars.compile(raw_file);
    var templated = template( real_context );

    fse.ensureFileSync(_dest);
    fs.writeFileSync(_dest, templated, 'utf8');

} //template_file

internal._missing_warning = function(flow, msg, type) {

    var level = 3;

    if(type == 'Error') {
        level = 1;
    }

    flow.log(level, '\n    %s', type);
    flow.log(level, '      failed to find some files list in project tree!\n');
    flow.log(level, '%s', msg);

} //_missing_warning

exports.error = function(flow, err) {

    internal._missing_warning(flow, err, 'Error');

} //error

<|endoftext|>